Skip to content

Commit 76682d7

Browse files
committed
Fix mobile UI issues: UserMenu overlap, emotion quiz, streak, chat mic, feed redesign
- Add backdrop overlay to UserMenu dropdown for mobile visual separation - Replace card-flip Emotion Match with scenario-based Emotion Quiz (20 scenarios, adaptive difficulty, saves activity + streak) - Fix childId mismatch causing streak to not update (fallback "" → "default") - Fix SpeechRecognition cleanup/reuse in chat, reorder input bar (mic primary) - Add viewport meta to prevent mobile zoom on input focus - Redesign community feed: posts first, collapsible compose form, per-user reaction tracking (toggle on/off), floating action button - Add feedReactions IndexedDB table (schema v5) for spam prevention
1 parent a861ee0 commit 76682d7

11 files changed

Lines changed: 667 additions & 559 deletions

File tree

SETUP_GUIDE.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,41 @@ APP_ACCESS_KEY_ID, APP_SECRET_ACCESS_KEY, APP_REGION
204204

205205
## Changelog
206206

207+
### 2026-03-06 — Mobile UI Fixes, Emotion Quiz, Feed Redesign
208+
209+
**Issues fixed (8 items from mobile testing):**
210+
211+
1. **UserMenu dropdown overlap** — Added semi-transparent backdrop overlay behind dropdown for visual separation on mobile. Clicking backdrop closes menu.
212+
- `app/components/UserMenu.tsx`
213+
214+
2. **Emotion Match → Emotion Quiz** — Replaced card-flip matching game (identical to Memory game) with scenario-based Emotion Quiz. 20 scenarios, 5 emotion choices, adaptive difficulty, sound feedback. Now correctly saves game activity + updates streak.
215+
- `app/games/emotion-match/page.tsx` (full rewrite)
216+
- `app/kid-dashboard/games/page.tsx` (updated description)
217+
- `app/kid-dashboard/page.tsx` (updated card emoji/title)
218+
219+
3. **Streak not updating** — Fixed childId mismatch: dashboard used `""` fallback but games used `"default"`. Changed dashboard fallback to `"default"`.
220+
- `app/kid-dashboard/page.tsx`
221+
222+
4. **Chat mic + viewport + input reorder**:
223+
- Added `viewport` export in layout.tsx to prevent mobile zoom on input focus
224+
- Fixed SpeechRecognition: cleanup old instance before new one, 120ms delay for mic release, nullify ref on callbacks, cleanup on unmount
225+
- Reordered input bar: mic button first (64px, primary green), text input secondary
226+
- `app/kid-dashboard/chat/page.tsx`, `app/layout.tsx`
227+
228+
5. **Progress page** — Verified childId already uses `"default"` fallback; no change needed.
229+
230+
6. **BottomNav/navbar overlap** — Resolved by Fix 1 (backdrop overlay).
231+
232+
7. **Community Feed redesign**:
233+
- Posts displayed first, compose form behind "New Post" button + floating action button
234+
- Per-user reaction tracking via new `feedReactions` IndexedDB table (schema v5)
235+
- Reactions toggle on/off per user (filled/unfilled state)
236+
- Delete own posts with reaction cleanup
237+
- Cleaner card layout, category pills, empty state
238+
- `app/feed/page.tsx` (full rewrite), `app/lib/db/feed.repository.ts`, `app/lib/db/schema.ts`, `app/types/feedPost.ts`
239+
240+
**Files modified:** 10 files across components, games, pages, DB layer, and types.
241+
207242
### 2026-03-06 — Fix Google sign-in loop
208243

209244
**Root causes found:**

app/components/UserMenu.tsx

Lines changed: 69 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -72,75 +72,81 @@ export default function UserMenu() {
7272
</button>
7373

7474
{open && (
75-
<div
76-
style={{
77-
position: "absolute",
78-
top: "calc(100% + 6px)",
79-
right: 0,
80-
minWidth: 180,
81-
background: "var(--card)",
82-
border: "1px solid var(--border)",
83-
borderRadius: "var(--r-lg, 16px)",
84-
boxShadow: "0 8px 24px rgba(0,0,0,0.12)",
85-
zIndex: 200,
86-
overflow: "hidden",
87-
}}
88-
>
89-
<div style={{ padding: "12px 16px", borderBottom: "1px solid var(--border)" }}>
90-
<div
75+
<>
76+
<div
77+
onClick={() => setOpen(false)}
78+
style={{ position: "fixed", inset: 0, background: "rgba(0,0,0,0.18)", zIndex: 199 }}
79+
/>
80+
<div
81+
style={{
82+
position: "absolute",
83+
top: "calc(100% + 6px)",
84+
right: 0,
85+
minWidth: 180,
86+
background: "var(--card)",
87+
border: "1px solid var(--border)",
88+
borderRadius: "var(--r-lg, 16px)",
89+
boxShadow: "0 8px 24px rgba(0,0,0,0.12)",
90+
zIndex: 200,
91+
overflow: "hidden",
92+
}}
93+
>
94+
<div style={{ padding: "12px 16px", borderBottom: "1px solid var(--border)" }}>
95+
<div
96+
style={{
97+
fontWeight: 600,
98+
fontSize: "0.88rem",
99+
color: "var(--text-primary)",
100+
whiteSpace: "nowrap",
101+
overflow: "hidden",
102+
textOverflow: "ellipsis",
103+
}}
104+
>
105+
{user.name}
106+
</div>
107+
<div
108+
style={{
109+
fontSize: "0.75rem",
110+
color: "var(--text-muted)",
111+
whiteSpace: "nowrap",
112+
overflow: "hidden",
113+
textOverflow: "ellipsis",
114+
}}
115+
>
116+
{user.email}
117+
</div>
118+
</div>
119+
<button
120+
onClick={() => {
121+
setOpen(false);
122+
logout();
123+
}}
91124
style={{
92-
fontWeight: 600,
125+
display: "flex",
126+
alignItems: "center",
127+
gap: 8,
128+
width: "100%",
129+
padding: "12px 16px",
130+
border: "none",
131+
background: "transparent",
132+
cursor: "pointer",
93133
fontSize: "0.88rem",
94-
color: "var(--text-primary)",
95-
whiteSpace: "nowrap",
96-
overflow: "hidden",
97-
textOverflow: "ellipsis",
134+
fontWeight: 600,
135+
color: "#e74c3c",
136+
fontFamily: "inherit",
137+
textAlign: "left",
98138
}}
99-
>
100-
{user.name}
101-
</div>
102-
<div
103-
style={{
104-
fontSize: "0.75rem",
105-
color: "var(--text-muted)",
106-
whiteSpace: "nowrap",
107-
overflow: "hidden",
108-
textOverflow: "ellipsis",
139+
onMouseEnter={(e) => {
140+
(e.currentTarget as HTMLElement).style.background = "var(--sage-50, #f5f5f5)";
141+
}}
142+
onMouseLeave={(e) => {
143+
(e.currentTarget as HTMLElement).style.background = "transparent";
109144
}}
110145
>
111-
{user.email}
112-
</div>
146+
Sign Out
147+
</button>
113148
</div>
114-
<button
115-
onClick={() => {
116-
setOpen(false);
117-
logout();
118-
}}
119-
style={{
120-
display: "flex",
121-
alignItems: "center",
122-
gap: 8,
123-
width: "100%",
124-
padding: "12px 16px",
125-
border: "none",
126-
background: "transparent",
127-
cursor: "pointer",
128-
fontSize: "0.88rem",
129-
fontWeight: 600,
130-
color: "#e74c3c",
131-
fontFamily: "inherit",
132-
textAlign: "left",
133-
}}
134-
onMouseEnter={(e) => {
135-
(e.currentTarget as HTMLElement).style.background = "var(--sage-50, #f5f5f5)";
136-
}}
137-
onMouseLeave={(e) => {
138-
(e.currentTarget as HTMLElement).style.background = "transparent";
139-
}}
140-
>
141-
Sign Out
142-
</button>
143-
</div>
149+
</>
144150
)}
145151
</div>
146152
);

0 commit comments

Comments
 (0)