diff --git a/src/app/page.tsx b/src/app/page.tsx index d063951..93bfed3 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -21,6 +21,14 @@ import { EventsList } from "@/components/events-list"; import { EventDialog } from "@/components/event-dialog"; import { DragDropContainer } from "@/components/drag-drop-container"; +const fileToBase64 = (file: File): Promise => + new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.onload = () => resolve(reader.result as string); + reader.onerror = () => reject(new Error("Failed to read file")); + reader.readAsDataURL(file); + }); + export default function HomePage() { const [events, setEvents] = useState([]); const [dialogOpen, setDialogOpen] = useState(false); @@ -45,6 +53,10 @@ export default function HomePage() { const [summary, setSummary] = useState(null); const [summaryUpdated, setSummaryUpdated] = useState(null); + // Image + const [imageBase64, setImageBase64] = useState(null); + const [imagePreview, setImagePreview] = useState(null); + useEffect(() => { (async () => { const stored = await getAllEvents(); @@ -66,6 +78,20 @@ export default function HomePage() { setRecurrenceRule(undefined); }; + const handleImageSelect = async (file: File) => { + const base64 = await fileToBase64(file); + setImageBase64(base64); + setImagePreview(URL.createObjectURL(file)); + }; + + const handleImageClear = () => { + if (imagePreview) { + URL.revokeObjectURL(imagePreview); + } + setImageBase64(null); + setImagePreview(null); + }; + const handleSave = async () => { const eventData: CalendarEvent = { id: editingId || nanoid(), @@ -130,7 +156,7 @@ export default function HomePage() { // AI Create Event const handleAiCreate = async () => { - if (!aiPrompt.trim()) return; + if (!aiPrompt.trim() && !imageBase64) return; setAiLoading(true); const promise = (): Promise<{ message: string }> => @@ -139,7 +165,10 @@ export default function HomePage() { const res = await fetch("/api/ai-event", { method: "POST", headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ prompt: aiPrompt }), + body: JSON.stringify({ + prompt: aiPrompt, + imageBase64: imageBase64 || undefined, + }), }); if (res.status === 401) { @@ -154,7 +183,6 @@ export default function HomePage() { if (Array.isArray(data) && data.length > 0) { if (data.length === 1) { - // Prefill dialog directly (same as before) const ev = data[0]; setTitle(ev.title || ""); setDescription(ev.description || ""); @@ -167,11 +195,11 @@ export default function HomePage() { setAiPrompt(""); setDialogOpen(true); setRecurrenceRule(ev.recurrenceRule || undefined); + handleImageClear(); resolve({ message: "Event has been created!", }); } else { - // Save them all directly to DB for (const ev of data) { const newEvent = { id: nanoid(), @@ -186,8 +214,9 @@ export default function HomePage() { setAiPrompt(""); setSummary(`Added ${data.length} AI-generated events.`); setSummaryUpdated(new Date().toLocaleString()); + handleImageClear(); resolve({ - message: "Event has been created!", + message: "Events have been created!", }); } } else { @@ -264,6 +293,7 @@ export default function HomePage() { isDragOver={isDragOver} setIsDragOver={setIsDragOver} onImport={handleImport} + onImageDrop={handleImageSelect} >