From c1057830b17cd227bb0e8fba42f7d404fa81a172 Mon Sep 17 00:00:00 2001 From: Mannu Date: Sun, 10 May 2026 12:34:41 +0530 Subject: [PATCH] Improve AI card - chat popup, saved chats, quick questions below --- src/app/page.tsx | 126 ++++++++++++++++++++++++++++++----------------- 1 file changed, 81 insertions(+), 45 deletions(-) diff --git a/src/app/page.tsx b/src/app/page.tsx index 2bd4c00..71a0926 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -4,19 +4,19 @@ import { useState, useEffect } from "react"; import Link from "next/link"; const OFFLINE_QUEUE_KEY = "tia_offline_queue"; +const AI_CHAT_KEY = "tia_ai_chats"; export interface OfflineEntry { id: string; type: "feed" | "diaper" | "sleep"; - data: { - type: "feed" | "diaper" | "sleep"; - childId: string; - subType: string; - amountMl?: number; - notes?: string; - startedAt?: string; - endedAt?: string; - }; + data: any; + timestamp: number; +} + +export interface AIChat { + id: string; + role: "user" | "assistant"; + content: string; timestamp: number; } @@ -25,9 +25,7 @@ export function getOfflineQueue(): OfflineEntry[] { try { const data = localStorage.getItem(OFFLINE_QUEUE_KEY); return data ? JSON.parse(data) : []; - } catch { - return []; - } + } catch { return []; } } export function addToOfflineQueue(entry: Omit) { @@ -48,6 +46,18 @@ export async function processOfflineQueue() { localStorage.setItem(OFFLINE_QUEUE_KEY, JSON.stringify(failed)); } +function getAIChats(): AIChat[] { + if (typeof window === "undefined") return []; + try { + const data = localStorage.getItem(AI_CHAT_KEY); + return data ? JSON.parse(data) : []; + } catch { return []; } +} + +function saveAIChats(chats: AIChat[]) { + localStorage.setItem(AI_CHAT_KEY, JSON.stringify(chats)); +} + interface LogModalProps { type: "feed" | "diaper" | "sleep" | null; childId: string; @@ -77,9 +87,7 @@ function LogModal({ type, childId, onClose }: LogModalProps) {

- {type === "feed" && "Log Feed"} - {type === "diaper" && "Log Diaper"} - {type === "sleep" && "Log Sleep"} + {type === "feed" && "Log Feed"}{type === "diaper" && "Log Diaper"}{type === "sleep" && "Log Sleep"}

{type === "feed" && ( <> @@ -128,13 +136,12 @@ function getGreeting() { return "Good evening"; } -// Quick questions for mama const QUICK_QUESTIONS = [ "How much should my baby eat?", "When should baby sleep?", "Is fever normal?", "How to increase milk supply?", - "Baby won't sleep 😴", + "Baby won't sleep", "Starting solids?", ]; @@ -142,7 +149,7 @@ export default function HomePage() { const [modalType, setModalType] = useState<"feed" | "diaper" | "sleep" | null>(null); const [aiOpen, setAiOpen] = useState(false); const [aiInput, setAiInput] = useState(""); - const [aiReply, setAiReply] = useState(""); + const [aiChats, setAiChats] = useState([]); const [aiLoading, setAiLoading] = useState(false); const [childId] = useState("5ad3b16a-1e0d-45ab-bc91-038397d75d0a"); const [pendingCount, setPendingCount] = useState(0); @@ -156,13 +163,9 @@ export default function HomePage() { if (saved === "dark") { setDarkMode(true); document.documentElement.classList.add("dark"); } }, []); - const toggleDarkMode = () => { - const next = !darkMode; - setDarkMode(next); - localStorage.setItem("tia_theme", next ? "dark" : "light"); - if (next) { document.documentElement.classList.add("dark"); } - else { document.documentElement.classList.remove("dark"); } - }; + useEffect(() => { + setAiChats(getAIChats()); + }, []); useEffect(() => { const queue = getOfflineQueue(); @@ -183,17 +186,37 @@ export default function HomePage() { }).catch(() => {}); }, [childId]); + const toggleDarkMode = () => { + const next = !darkMode; + setDarkMode(next); + localStorage.setItem("tia_theme", next ? "dark" : "light"); + if (next) { document.documentElement.classList.add("dark"); } + else { document.documentElement.classList.remove("dark"); } + }; + const handleAiChat = async (question?: string) => { const q = question || aiInput; if (!q.trim() || aiLoading) return; setAiLoading(true); + setAiOpen(true); + + const newChats: AIChat[] = [...aiChats, { id: crypto.randomUUID(), role: "user", content: q, timestamp: Date.now() }]; + setAiChats(newChats); + setAiInput(""); + try { const res = await fetch("/api/ai", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ messages: [{ role: "user", content: q }] }) }); const data = await res.json(); - setAiReply(data.reply || "Sorry, I couldn't help with that."); - } catch { setAiReply("Something went wrong. Try again."); } + const reply = data.reply || "Sorry, I couldn't help with that."; + const updatedChats: AIChat[] = [...newChats, { id: crypto.randomUUID(), role: "assistant", content: reply, timestamp: Date.now() }]; + setAiChats(updatedChats); + saveAIChats(updatedChats); + } catch { + const errorChats: AIChat[] = [...newChats, { id: crypto.randomUUID(), role: "assistant", content: "Something went wrong. Try again.", timestamp: Date.now() }]; + setAiChats(errorChats); + saveAIChats(errorChats); + } setAiLoading(false); - if (!question) setAiInput(""); }; return ( @@ -217,7 +240,6 @@ export default function HomePage() { {pendingCount > 0 &&
{pendingCount} pending log{pendingCount > 1 ? "s" : ""}
} - {/* Quick Log - Keep as is */}

Quick Log

@@ -238,24 +260,23 @@ export default function HomePage() { {/* AI Chat Card */}
-

🤖 Ask Tia AI

+
+

Ask AI

+ View all chats → +
-

Quick questions:

-
- {QUICK_QUESTIONS.map((q, i) => ( - - ))} -
-
+
setAiInput(e.target.value)} onKeyDown={(e) => e.key === "Enter" && handleAiChat()} placeholder="Ask anything..." className="flex-1 p-2 border rounded-xl text-sm" disabled={aiLoading} /> - + +
+
+ {QUICK_QUESTIONS.map((q, i) => ( + + ))}
- {/* Recent Activity */}

Recent Activity

@@ -273,11 +294,26 @@ export default function HomePage() { setModalType(null)} /> - {aiOpen && aiReply && ( + {/* AI Chat Popup */} + {aiOpen && (
setAiOpen(false)}> -
e.stopPropagation()}> -

🤖 Tia says:

-
{aiReply}
+
e.stopPropagation()}> +
+

Ask AI

+ +
+
+ {aiChats.length === 0 ?

Ask a question to start chatting

: aiChats.map((chat) => ( +
+ {chat.content} +
+ ))} + {aiLoading &&
Thinking...
} +
+
+ setAiInput(e.target.value)} onKeyDown={(e) => e.key === "Enter" && handleAiChat()} placeholder="Ask a question..." className="flex-1 p-2 border rounded-xl text-sm" disabled={aiLoading} /> + +
)}