Files
WealthySmart/frontend/src/components/MeterLabelsDialog.tsx
Carlos Escalante fe62e50a85 Cosmetics: shared PeriodNavigator, breadcrumb, meter labels
One chevron component now drives year/month stepping in Budget and
Proyecciones (UX-03). Jumping from Proyecciones to a Budget month shows
a back affordance (UX-22). Water meters can be named (Casa, Cochera…)
via a settings-persisted dialog; the chart legend uses the names
(UX-24).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 15:27:06 -06:00

88 lines
2.5 KiB
TypeScript

import { useState } from 'react';
import { useQueryClient } from '@tanstack/react-query';
import { toast } from 'sonner';
import api, { type UserSettingsData } from '@/lib/api';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import {
Dialog,
DialogContent,
DialogFooter,
DialogHeader,
DialogTitle,
} from '@/components/ui/dialog';
interface Props {
meterIds: string[];
current: Record<string, string>;
settingsData: UserSettingsData;
onClose: () => void;
}
/** Human names for water meters, persisted in UserSettings (review UX-24). */
export default function MeterLabelsDialog({
meterIds,
current,
settingsData,
onClose,
}: Props) {
const queryClient = useQueryClient();
const [labels, setLabels] = useState<Record<string, string>>(() => ({
...current,
}));
const [saving, setSaving] = useState(false);
const handleSave = async () => {
setSaving(true);
try {
const cleaned = Object.fromEntries(
Object.entries(labels).filter(([, v]) => v.trim() !== ''),
);
await api.patch('/settings/', {
data: { ...settingsData, meter_labels: cleaned },
});
toast.success('Etiquetas guardadas');
queryClient.invalidateQueries({ queryKey: ['settings'] });
onClose();
} catch {
toast.error('No se pudieron guardar las etiquetas');
} finally {
setSaving(false);
}
};
return (
<Dialog open onOpenChange={(open) => { if (!open) onClose(); }}>
<DialogContent className="sm:max-w-sm">
<DialogHeader>
<DialogTitle>Etiquetas de medidores</DialogTitle>
</DialogHeader>
<div className="space-y-3">
{meterIds.map((id) => (
<div key={id} className="space-y-1">
<Label className="text-xs font-mono">Medidor {id}</Label>
<Input
value={labels[id] ?? ''}
placeholder="p. ej. Casa, Cochera…"
onChange={(e) =>
setLabels((prev) => ({ ...prev, [id]: e.target.value }))
}
/>
</div>
))}
</div>
<DialogFooter>
<Button variant="outline" onClick={onClose}>
Cancelar
</Button>
<Button onClick={handleSave} disabled={saving}>
{saving ? 'Guardando...' : 'Guardar'}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}