From 7286c9a33582cea0d310953f1a8bf9096b7a0ec0 Mon Sep 17 00:00:00 2001 From: Dmytro Stanchiev Date: Fri, 15 Aug 2025 00:13:38 -0400 Subject: [PATCH] richer editing --- src/app/page.tsx | 140 ++++++++++++++++++++++++++++++++++++----------- src/lib/ical.ts | 77 ++++++++++++++++++++++---- src/lib/types.ts | 11 +++- 3 files changed, 182 insertions(+), 46 deletions(-) diff --git a/src/app/page.tsx b/src/app/page.tsx index 72a3f99..1b46c4b 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -5,20 +5,26 @@ import { nanoid } from 'nanoid' import { Button } from '@/components/ui/button' import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog' import { Input } from '@/components/ui/input' -import { type CalendarEvent } from '@/lib/types' import { addEvent, deleteEvent, getAllEvents, clearEvents, getDB } from '@/lib/db' import { parseICS, generateICS } from '@/lib/ical' +import type { CalendarEvent } from '@/lib/types' export default function HomePage() { const [events, setEvents] = useState([]) const [dialogOpen, setDialogOpen] = useState(false) - const [title, setTitle] = useState('') - const [start, setStart] = useState('') const [editingId, setEditingId] = useState(null) const [isDragOver, setIsDragOver] = useState(false) - // Load events only in the browser + // Form fields + const [title, setTitle] = useState('') + const [description, setDescription] = useState('') + const [location, setLocation] = useState('') + const [url, setUrl] = useState('') + const [start, setStart] = useState('') + const [end, setEnd] = useState('') + const [allDay, setAllDay] = useState(false) + useEffect(() => { (async () => { const stored = await getAllEvents() @@ -28,24 +34,40 @@ export default function HomePage() { const resetForm = () => { setTitle('') + setDescription('') + setLocation('') + setUrl('') setStart('') + setEnd('') + setAllDay(false) setEditingId(null) } const handleSave = async () => { + const eventData: CalendarEvent = { + id: editingId || nanoid(), + title, + description, + location, + url, + start, + end: end || undefined, + allDay, + createdAt: editingId + ? events.find(e => e.id === editingId)?.createdAt + : new Date().toISOString(), + lastModified: new Date().toISOString(), + } + if (editingId) { - // EDIT EXISTING - const updatedEvent = { id: editingId, title, start } const db = await getDB() if (db) { - await db.put('events', updatedEvent) - setEvents(prev => prev.map(e => (e.id === editingId ? updatedEvent : e))) + await db.put('events', eventData) + setEvents(prev => prev.map(e => (e.id === editingId ? eventData : e))) } } else { - // ADD NEW - const newEvent = { id: nanoid(), title, start } - await addEvent(newEvent) - setEvents(prev => [...prev, newEvent]) + await addEvent(eventData) + setEvents(prev => [...prev, eventData]) } resetForm() setDialogOpen(false) @@ -61,11 +83,9 @@ export default function HomePage() { setEvents([]) } - // --- IMPORT --- const handleImport = async (file: File) => { const text = await file.text() const parsed = parseICS(text) - for (const ev of parsed) { await addEvent(ev) } @@ -73,7 +93,6 @@ export default function HomePage() { setEvents(stored) } - // --- EXPORT --- const handleExport = () => { const icsData = generateICS(events) const blob = new Blob([icsData], { type: 'text/calendar' }) @@ -87,17 +106,15 @@ export default function HomePage() { URL.revokeObjectURL(url) } - // --- DRAG & DROP --- + // Drag & drop const handleDragOver = (e: React.DragEvent) => { e.preventDefault() setIsDragOver(true) } - const handleDragLeave = (e: React.DragEvent) => { e.preventDefault() setIsDragOver(false) } - const handleDrop = (e: React.DragEvent) => { e.preventDefault() setIsDragOver(false) @@ -123,8 +140,12 @@ export default function HomePage() { {events.length > 0 && ( <> - - + + )}