Skip to content

Commit 7a72051

Browse files
committed
Restructure kid dashboard: remove Talking, add Detection + Nearby Help
- Remove Talking page (duplicates AI Chat) - Fix AI Chat: turn cap 7→15, personality-aware fallbacks - Create standalone Detection page with YOLO body+face inference - Create Nearby Help page merging Doctor Connect + Map with Leaflet - Add lat/lng coordinates to all 22 doctor records - Update quick links: Talking→Detection, Doctor→Nearby - Update BottomNav: Map→Help - Add permanent redirects for removed pages - 36/36 tests pass
1 parent b3ba3fe commit 7a72051

12 files changed

Lines changed: 1321 additions & 917 deletions

File tree

app/api/chat/conversation/route.ts

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -111,37 +111,47 @@ For action: when domain is "motor" and turnType is "instruction", include one of
111111
/* Fallback conversation */
112112
/* ------------------------------------------------------------------ */
113113

114+
const PERSONALITY_PREFIX: Record<string, string> = {
115+
dog: "Woof! ",
116+
cat: "Purrr... ",
117+
rabbit: "Oh! ",
118+
parrot: "Squawk! ",
119+
};
120+
114121
function buildFallbackTurn(
115122
childName: string,
116123
turnNumber: number,
124+
animalPersonality?: string,
117125
): ConversationResponse {
126+
const prefix = (animalPersonality && PERSONALITY_PREFIX[animalPersonality]) || "";
127+
118128
const fallback: Array<Omit<ConversationResponse, "fallback">> = [
119129
{
120-
text: `Hi ${childName}! I'm so happy to talk with you today! Are you ready to play a fun game with me?`,
130+
text: `${prefix}Hi ${childName}! I'm so happy to talk with you today! Are you ready to play a fun game with me?`,
121131
metadata: { turnType: "greeting", expectsResponse: true, responseRelevance: 0.5, shouldEnd: false, domain: "social" },
122132
},
123133
{
124-
text: `Awesome! Let's start with something fun. Can you wave hello to me?`,
134+
text: `${prefix}Awesome! Let's start with something fun. Can you wave hello to me?`,
125135
metadata: { turnType: "instruction", expectsResponse: true, responseRelevance: 0.5, shouldEnd: false, domain: "motor", action: "wave" },
126136
},
127137
{
128-
text: `Great job! Now tell me, what color is the sky?`,
138+
text: `${prefix}Great job! Now tell me, what color is the sky?`,
129139
metadata: { turnType: "question", expectsResponse: true, responseRelevance: 0.5, shouldEnd: false, domain: "cognitive" },
130140
},
131141
{
132-
text: `You're doing so well! Can you say the word banana for me?`,
142+
text: `${prefix}You're doing so well! Can you say the word banana for me?`,
133143
metadata: { turnType: "question", expectsResponse: true, responseRelevance: 0.5, shouldEnd: false, domain: "language" },
134144
},
135145
{
136-
text: `That's wonderful! Now let's try something silly. Can you touch your nose?`,
146+
text: `${prefix}That's wonderful! Now let's try something silly. Can you touch your nose?`,
137147
metadata: { turnType: "instruction", expectsResponse: true, responseRelevance: 0.5, shouldEnd: false, domain: "motor", action: "touch_nose" },
138148
},
139149
{
140-
text: `You're a superstar! What's your favorite animal?`,
150+
text: `${prefix}You're a superstar! What's your favorite animal?`,
141151
metadata: { turnType: "question", expectsResponse: true, responseRelevance: 0.5, shouldEnd: false, domain: "social" },
142152
},
143153
{
144-
text: `You did such an amazing job, ${childName}! Thank you so much for talking with me today! You're wonderful!`,
154+
text: `${prefix}You did such an amazing job, ${childName}! Thank you so much for talking with me today! You're wonderful!`,
145155
metadata: { turnType: "farewell", expectsResponse: false, responseRelevance: 0.5, shouldEnd: true, domain: "general" },
146156
},
147157
];
@@ -222,10 +232,10 @@ export async function POST(req: NextRequest) {
222232

223233
const { messages, childName, ageMonths, turnNumber, animalPersonality } = body;
224234

225-
// Hard cap — force farewell after 8 turns
226-
if (turnNumber >= 7) {
235+
// Hard cap — force farewell after 15 turns
236+
if (turnNumber >= 15) {
227237
return NextResponse.json(
228-
buildFallbackTurn(childName, 6), // farewell
238+
buildFallbackTurn(childName, 6, animalPersonality), // farewell
229239
);
230240
}
231241

@@ -285,18 +295,18 @@ export async function POST(req: NextRequest) {
285295

286296
if (!rawText) {
287297
console.warn("[Chat] Empty response from Bedrock, using fallback");
288-
return NextResponse.json(buildFallbackTurn(childName, turnNumber));
298+
return NextResponse.json(buildFallbackTurn(childName, turnNumber, animalPersonality));
289299
}
290300

291301
const parsed = parseAgentResponse(rawText);
292302
if (!parsed) {
293303
console.warn("[Chat] Failed to parse LLM JSON, using fallback. Raw:", rawText);
294-
return NextResponse.json(buildFallbackTurn(childName, turnNumber));
304+
return NextResponse.json(buildFallbackTurn(childName, turnNumber, animalPersonality));
295305
}
296306

297307
return NextResponse.json({ ...parsed, fallback: false } satisfies ConversationResponse);
298308
} catch (err) {
299309
console.error("[Chat] Bedrock invocation failed:", err);
300-
return NextResponse.json(buildFallbackTurn(childName, turnNumber));
310+
return NextResponse.json(buildFallbackTurn(childName, turnNumber, animalPersonality));
301311
}
302312
}

app/components/BottomNav.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const tabs = [
88
{ href: "/kid-dashboard/games", label: "Games", icon: "🎮" },
99
{ href: "/kid-dashboard/chat", label: "Chat", icon: "💬" },
1010
{ href: "/kid-dashboard/progress", label: "Progress", icon: "📊" },
11-
{ href: "/kid-dashboard/map", label: "Map", icon: "🗺️" },
11+
{ href: "/kid-dashboard/nearby-help", label: "Help", icon: "🏥" },
1212
];
1313

1414
export default function BottomNav() {

app/kid-dashboard/chat/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ export default function ChatPage() {
136136
setMessages(allMsgs); setTurnNumber(nextTurn + 1); setIsLoading(false);
137137
setAvatarState("talking");
138138
await playTTS(aiText);
139-
if (shouldEnd || nextTurn + 1 >= 7) { setAvatarState("happy"); endConversation(allMsgs); return; }
139+
if (shouldEnd || nextTurn + 1 >= 15) { setAvatarState("happy"); endConversation(allMsgs); return; }
140140
setAvatarState("idle");
141141
};
142142

0 commit comments

Comments
 (0)