import { useState } from 'react'; import { useSitesStore } from '@/store/sites.ts'; import { useToastStore } from '@/components/ui/Toast.tsx'; import Button from '@/components/ui/Button.tsx'; interface BatchEditProps { onBatchApplied?: (affectedIds: string[]) => void; } const QUICK_FREQS = [800, 1800, 1900, 2100, 2600]; export default function BatchEdit({ onBatchApplied }: BatchEditProps) { const selectedSiteIds = useSitesStore((s) => s.selectedSiteIds); const batchUpdateHeight = useSitesStore((s) => s.batchUpdateHeight); const batchSetHeight = useSitesStore((s) => s.batchSetHeight); const batchAdjustAzimuth = useSitesStore((s) => s.batchAdjustAzimuth); const batchSetAzimuth = useSitesStore((s) => s.batchSetAzimuth); const batchAdjustPower = useSitesStore((s) => s.batchAdjustPower); const batchSetPower = useSitesStore((s) => s.batchSetPower); const batchAdjustTilt = useSitesStore((s) => s.batchAdjustTilt); const batchSetTilt = useSitesStore((s) => s.batchSetTilt); const batchSetFrequency = useSitesStore((s) => s.batchSetFrequency); const clearSelection = useSitesStore((s) => s.clearSelection); const addToast = useToastStore((s) => s.addToast); const [customHeight, setCustomHeight] = useState(''); const [customAzimuth, setCustomAzimuth] = useState(''); const [customPower, setCustomPower] = useState(''); const [customTilt, setCustomTilt] = useState(''); const [customFrequency, setCustomFrequency] = useState(''); if (selectedSiteIds.length === 0) return null; const notifyBatch = (ids: string[]) => { onBatchApplied?.(ids); }; // ── Height ── const handleAdjustHeight = async (delta: number) => { const ids = [...selectedSiteIds]; await batchUpdateHeight(delta); notifyBatch(ids); addToast( `Updated ${ids.length} site(s) height by ${delta > 0 ? '+' : ''}${delta}m`, 'success' ); }; const handleSetHeight = async () => { const height = parseInt(customHeight, 10); if (isNaN(height) || height < 1 || height > 100) { addToast('Height must be between 1-100m', 'error'); return; } const ids = [...selectedSiteIds]; await batchSetHeight(height); notifyBatch(ids); addToast(`Set ${ids.length} site(s) to ${height}m`, 'success'); setCustomHeight(''); }; // ── Azimuth ── const handleAdjustAzimuth = async (delta: number) => { const ids = [...selectedSiteIds]; await batchAdjustAzimuth(delta); notifyBatch(ids); addToast( `Rotated ${ids.length} site(s) by ${delta > 0 ? '+' : ''}${delta}\u00B0`, 'success' ); }; const handleSetAzimuth = async () => { const az = parseInt(customAzimuth, 10); if (isNaN(az) || az < 0 || az > 359) { addToast('Azimuth must be between 0-359\u00B0', 'error'); return; } const ids = [...selectedSiteIds]; await batchSetAzimuth(az); notifyBatch(ids); addToast(`Set ${ids.length} site(s) azimuth to ${az}\u00B0`, 'success'); setCustomAzimuth(''); }; // ── Power ── const handleAdjustPower = async (delta: number) => { const ids = [...selectedSiteIds]; await batchAdjustPower(delta); notifyBatch(ids); addToast( `Adjusted ${ids.length} site(s) power by ${delta > 0 ? '+' : ''}${delta} dB`, 'success' ); }; const handleSetPower = async () => { const power = parseInt(customPower, 10); if (isNaN(power) || power < 10 || power > 50) { addToast('Power must be between 10-50 dBm', 'error'); return; } const ids = [...selectedSiteIds]; await batchSetPower(power); notifyBatch(ids); addToast(`Set ${ids.length} site(s) power to ${power} dBm`, 'success'); setCustomPower(''); }; // ── Tilt ── const handleAdjustTilt = async (delta: number) => { const ids = [...selectedSiteIds]; await batchAdjustTilt(delta); notifyBatch(ids); addToast( `Adjusted ${ids.length} site(s) tilt by ${delta > 0 ? '+' : ''}${delta}\u00B0`, 'success' ); }; const handleSetTilt = async () => { const tilt = parseInt(customTilt, 10); if (isNaN(tilt) || tilt < -90 || tilt > 90) { addToast('Tilt must be between -90\u00B0 and +90\u00B0', 'error'); return; } const ids = [...selectedSiteIds]; await batchSetTilt(tilt); notifyBatch(ids); addToast(`Set ${ids.length} site(s) tilt to ${tilt}\u00B0`, 'success'); setCustomTilt(''); }; // ── Frequency ── const handleSetFrequencyQuick = async (freq: number) => { const ids = [...selectedSiteIds]; await batchSetFrequency(freq); notifyBatch(ids); addToast(`Set ${ids.length} site(s) to ${freq} MHz`, 'success'); }; const handleSetFrequencyCustom = async () => { const freq = parseInt(customFrequency, 10); if (isNaN(freq) || freq < 100 || freq > 6000) { addToast('Frequency must be between 100-6000 MHz', 'error'); return; } const ids = [...selectedSiteIds]; await batchSetFrequency(freq); notifyBatch(ids); addToast(`Set ${ids.length} site(s) to ${freq} MHz`, 'success'); setCustomFrequency(''); }; const inputClass = 'flex-1 px-3 py-1.5 border border-gray-300 dark:border-dark-border dark:bg-dark-bg dark:text-dark-text rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500'; return (

Batch Edit ({selectedSiteIds.length} selected)

{/* ── Height ── */}
setCustomHeight(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && handleSetHeight()} placeholder="meters" className={inputClass} />
{/* ── Azimuth ── */}
setCustomAzimuth(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && handleSetAzimuth()} placeholder="0-359\u00B0" className={inputClass} />
{/* ── Power ── */}
setCustomPower(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && handleSetPower()} placeholder="dBm" className={inputClass} />
{/* ── Tilt ── */}
setCustomTilt(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && handleSetTilt()} placeholder="degrees" className={inputClass} />
{/* ── Frequency ── */}
{QUICK_FREQS.map((freq) => ( ))} MHz
setCustomFrequency(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && handleSetFrequencyCustom()} placeholder="MHz" className={inputClass} />
); }