mirror of
https://github.com/escalante29/WealthySmart.git
synced 2026-07-17 10:28:47 +02:00
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>
88 lines
2.5 KiB
TypeScript
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>
|
|
);
|
|
}
|