@mytec: iter5 ready for test
This commit is contained in:
@@ -3,7 +3,11 @@ import { useSitesStore } from '@/store/sites.ts';
|
||||
import { useToastStore } from '@/components/ui/Toast.tsx';
|
||||
import Button from '@/components/ui/Button.tsx';
|
||||
|
||||
export default function BatchEdit() {
|
||||
interface BatchEditProps {
|
||||
onBatchApplied?: (affectedIds: string[]) => void;
|
||||
}
|
||||
|
||||
export default function BatchEdit({ onBatchApplied }: BatchEditProps) {
|
||||
const selectedSiteIds = useSitesStore((s) => s.selectedSiteIds);
|
||||
const batchUpdateHeight = useSitesStore((s) => s.batchUpdateHeight);
|
||||
const batchSetHeight = useSitesStore((s) => s.batchSetHeight);
|
||||
@@ -15,9 +19,11 @@ export default function BatchEdit() {
|
||||
if (selectedSiteIds.length === 0) return null;
|
||||
|
||||
const handleAdjustHeight = async (delta: number) => {
|
||||
const ids = [...selectedSiteIds];
|
||||
await batchUpdateHeight(delta);
|
||||
onBatchApplied?.(ids);
|
||||
addToast(
|
||||
`Adjusted ${selectedSiteIds.length} site(s) by ${delta > 0 ? '+' : ''}${delta}m`,
|
||||
`Updated ${ids.length} site(s) by ${delta > 0 ? '+' : ''}${delta}m`,
|
||||
'success'
|
||||
);
|
||||
};
|
||||
@@ -28,8 +34,10 @@ export default function BatchEdit() {
|
||||
addToast('Height must be between 1-100m', 'error');
|
||||
return;
|
||||
}
|
||||
const ids = [...selectedSiteIds];
|
||||
await batchSetHeight(height);
|
||||
addToast(`Set ${selectedSiteIds.length} site(s) to ${height}m`, 'success');
|
||||
onBatchApplied?.(ids);
|
||||
addToast(`Set ${ids.length} site(s) to ${height}m`, 'success');
|
||||
setCustomHeight('');
|
||||
};
|
||||
|
||||
|
||||
@@ -77,6 +77,24 @@ export default function SiteForm({
|
||||
}
|
||||
}, [pendingLocation]);
|
||||
|
||||
// Live-sync: update form when the edited site changes externally
|
||||
// (e.g., batch height adjustment, drag on map)
|
||||
useEffect(() => {
|
||||
if (editSite) {
|
||||
setHeight(editSite.height);
|
||||
setPower(editSite.power);
|
||||
setGain(editSite.gain);
|
||||
setName(editSite.name);
|
||||
setLat(editSite.lat);
|
||||
setLon(editSite.lon);
|
||||
setFrequency(editSite.frequency);
|
||||
setAntennaType(editSite.antennaType);
|
||||
setAzimuth(editSite.azimuth ?? 0);
|
||||
setBeamwidth(editSite.beamwidth ?? 65);
|
||||
setNotes(editSite.notes ?? '');
|
||||
}
|
||||
}, [editSite]);
|
||||
|
||||
const applyTemplate = (key: keyof typeof TEMPLATES) => {
|
||||
const t = TEMPLATES[key];
|
||||
setName(t.name);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
import type { Site } from '@/types/index.ts';
|
||||
import { useSitesStore } from '@/store/sites.ts';
|
||||
import { useToastStore } from '@/components/ui/Toast.tsx';
|
||||
@@ -22,6 +23,15 @@ export default function SiteList({ onEditSite, onAddSite }: SiteListProps) {
|
||||
const clearSelection = useSitesStore((s) => s.clearSelection);
|
||||
const addToast = useToastStore((s) => s.addToast);
|
||||
|
||||
// Track recently batch-updated site IDs for flash animation
|
||||
const [flashIds, setFlashIds] = useState<Set<string>>(new Set());
|
||||
|
||||
const triggerFlash = useCallback((ids: string[]) => {
|
||||
setFlashIds(new Set(ids));
|
||||
// Clear after animation completes
|
||||
setTimeout(() => setFlashIds(new Set()), 700);
|
||||
}, []);
|
||||
|
||||
const handleDelete = async (id: string, name: string) => {
|
||||
await deleteSite(id);
|
||||
addToast(`"${name}" deleted`, 'info');
|
||||
@@ -73,7 +83,7 @@ export default function SiteList({ onEditSite, onAddSite }: SiteListProps) {
|
||||
{/* Batch edit panel (appears when sites are selected) */}
|
||||
{selectedSiteIds.length > 0 && (
|
||||
<div className="px-3 pt-3">
|
||||
<BatchEdit />
|
||||
<BatchEdit onBatchApplied={triggerFlash} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -86,6 +96,7 @@ export default function SiteList({ onEditSite, onAddSite }: SiteListProps) {
|
||||
<div className="divide-y divide-gray-100 dark:divide-dark-border max-h-60 overflow-y-auto">
|
||||
{sites.map((site) => {
|
||||
const isBatchSelected = selectedSiteIds.includes(site.id);
|
||||
const isFlashing = flashIds.has(site.id);
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -93,7 +104,8 @@ export default function SiteList({ onEditSite, onAddSite }: SiteListProps) {
|
||||
className={`px-4 py-2.5 flex items-center gap-2.5 cursor-pointer
|
||||
hover:bg-gray-50 dark:hover:bg-dark-border/50 transition-colors
|
||||
${selectedSiteId === site.id ? 'bg-blue-50 dark:bg-blue-900/20' : ''}
|
||||
${isBatchSelected && selectedSiteId !== site.id ? 'bg-blue-50/50 dark:bg-blue-900/10' : ''}`}
|
||||
${isBatchSelected && selectedSiteId !== site.id ? 'bg-blue-50/50 dark:bg-blue-900/10' : ''}
|
||||
${isFlashing ? 'flash-update' : ''}`}
|
||||
onClick={() => selectSite(site.id)}
|
||||
>
|
||||
{/* Batch checkbox */}
|
||||
|
||||
Reference in New Issue
Block a user