// UUID v4 generator (browser safe, duplicate of datastore.js for local use) function generateUUID() { if (window.crypto && window.crypto.randomUUID) return window.crypto.randomUUID(); return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { const r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); }); } import React, { useState, useEffect } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; import { motion } from 'framer-motion'; import { ArrowLeft, Save } from 'lucide-react'; import { Button } from '../components/ui/button'; import { Input } from '../components/ui/input'; import { Label } from '../components/ui/label'; import { useToast } from '../components/ui/use-toast'; import ColorPicker from '../components/ColorPicker'; import { getHabits, saveHabit, updateHabit } from '../lib/datastore'; // Local helper to get habit by id from localStorage function getHabit(id) { const habits = JSON.parse(localStorage.getItem('habitgrid_data') || '[]'); return habits.find(h => h.id === id); } const AddEditHabitPage = () => { const { id } = useParams(); const navigate = useNavigate(); const { toast } = useToast(); const isEdit = !!id; const [name, setName] = useState(''); const [color, setColor] = useState('#22c55e'); const [category, setCategory] = useState(''); useEffect(() => { if (isEdit) { const habit = getHabit(id); if (habit) { setName(habit.name); setColor(habit.color); if (habit.category) setCategory(habit.category); } else { toast({ title: "Habit not found", description: "This habit doesn't exist or was deleted.", variant: "destructive", }); navigate('/'); } } }, [id, isEdit, navigate, toast]); const handleSubmit = async (e) => { e.preventDefault(); if (!name.trim()) { toast({ title: "Name required", description: "Please enter a habit name.", variant: "destructive", }); return; } // Optimistic local update if (isEdit) { // Update localStorage directly for instant UI const habits = JSON.parse(localStorage.getItem('habitgrid_data') || '[]'); const idx = habits.findIndex(h => h.id === id); if (idx !== -1) { habits[idx] = { ...habits[idx], name: name.trim(), color, category: category.trim() }; localStorage.setItem('habitgrid_data', JSON.stringify(habits)); } updateHabit(id, { name: name.trim(), color, category: category.trim() }); // background sync toast({ title: "✅ Habit updated", description: "Your habit has been updated successfully.", }); } else { // Single source of truth: delegate to datastore; it will handle local or remote as needed const newHabit = { id: generateUUID(), name: name.trim(), color, category: category.trim(), completions: [], currentStreak: 0, longestStreak: 0, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), }; await saveHabit(newHabit); toast({ title: "✅ Habit created", description: "Your new habit is ready to track!", }); } navigate('/'); }; return (
{isEdit ? 'Update your habit details' : 'Start building a new habit'}
{name.length}/50 characters