'use client'; import { useState, useEffect } from 'react'; import { Button } from '@/components/ui/button'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@/components/ui/dialog'; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from '@/components/ui/alert-dialog'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Textarea } from '@/components/ui/textarea'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select'; import { Switch } from '@/components/ui/switch'; import { toast } from 'sonner'; interface Habit { id: string; name: string; description: string | null; domainId: string; frequency: 'daily' | 'weekly' | 'custom'; difficulty: 'easy' | 'medium' | 'hard'; goalPerPeriod: number; unit: string | null; active: boolean; moodTracking: boolean; tags: { id: string; name: string; color: string | null }[]; } interface HabitEditDialogProps { open: boolean; onOpenChange: (open: boolean) => void; habit: Habit; domainId: string; onUpdated: () => void; } export function HabitEditDialog({ open, onOpenChange, habit, domainId, onUpdated, }: HabitEditDialogProps) { const [name, setName] = useState(''); const [description, setDescription] = useState(''); const [frequency, setFrequency] = useState<'daily' | 'weekly' | 'custom'>('daily'); const [difficulty, setDifficulty] = useState<'easy' | 'medium' | 'hard'>('medium'); const [goalPerPeriod, setGoalPerPeriod] = useState('1'); const [unit, setUnit] = useState(''); const [reminderTime, setReminderTime] = useState(''); const [moodTracking, setMoodTracking] = useState(false); const [active, setActive] = useState(true); const [submitting, setSubmitting] = useState(false); const [error, setError] = useState(''); const [deleteOpen, setDeleteOpen] = useState(false); const [deleting, setDeleting] = useState(false); const [availableTags, setAvailableTags] = useState<{ id: string; name: string; color: string | null }[]>([]); const [selectedTagIds, setSelectedTagIds] = useState([]); useEffect(() => { if (open && habit) { setName(habit.name); setDescription(habit.description || ''); setFrequency(habit.frequency); setDifficulty(habit.difficulty); setGoalPerPeriod(String(habit.goalPerPeriod)); setUnit(habit.unit || ''); setReminderTime(''); setMoodTracking(habit.moodTracking); setActive(habit.active); setSelectedTagIds(habit.tags.map(t => t.id)); setError(''); fetch(`/api/domains/${domainId}/tags`) .then(res => res.json()) .then(data => setAvailableTags(data.items || [])) .catch(() => {}); } }, [open, habit, domainId]); function toggleTag(tagId: string) { setSelectedTagIds(prev => prev.includes(tagId) ? prev.filter(id => id !== tagId) : [...prev, tagId] ); } async function handleSubmit(event: React.FormEvent) { event.preventDefault(); if (!domainId) { setError('No domain selected'); return; } setSubmitting(true); setError(''); const body: Record = { name, frequency, difficulty, goalPerPeriod: parseInt(goalPerPeriod, 10) || 1, moodTracking, active, }; if (description) body.description = description; if (unit) body.unit = unit; if (reminderTime) body.reminderTime = reminderTime; try { const response = await fetch(`/api/domains/${domainId}/habits/${habit.id}`, { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body), }); if (!response.ok) { const err = await response.json(); throw new Error(err.error?.message || 'Unable to update habit'); } // Sync tags const currentTagIds = habit.tags.map(t => t.id); const toRemove = currentTagIds.filter(id => !selectedTagIds.includes(id)); const toAdd = selectedTagIds.filter(id => !currentTagIds.includes(id)); await Promise.all([ ...toRemove.map(tagId => fetch(`/api/domains/${domainId}/habits/${habit.id}/tags`, { method: 'DELETE', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ tagId }), }) ), ...toAdd.map(tagId => fetch(`/api/domains/${domainId}/habits/${habit.id}/tags`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ tagId }), }) ), ]); toast.success('Habit updated'); onOpenChange(false); onUpdated(); } catch (err) { setError(err instanceof Error ? err.message : 'Unable to update habit'); } finally { setSubmitting(false); } } async function handleDelete() { setDeleting(true); try { const response = await fetch(`/api/domains/${domainId}/habits/${habit.id}`, { method: 'DELETE', }); if (!response.ok) { const err = await response.json(); throw new Error(err.error?.message || 'Unable to delete habit'); } toast.success('Habit deleted'); setDeleteOpen(false); onOpenChange(false); onUpdated(); } catch (err) { toast.error(err instanceof Error ? err.message : 'Unable to delete habit'); } finally { setDeleting(false); } } return ( <> Edit Habit Update your habit details.
setName(e.target.value)} placeholder="e.g. Morning meditation" autoFocus required />