From fb57c49e78cac998e4bbe73b4469a9b04809c852 Mon Sep 17 00:00:00 2001 From: Syed Salman Reza Date: Mon, 1 Jun 2026 13:12:42 +0600 Subject: [PATCH 01/23] Add Care Redesign demo and update care UI Add a self-contained web demo for the PetFolio Care redesign (HTML entry, React JSX: care_screen.jsx and ios-frame.jsx) plus multiple screenshot/assets under PetFolio Redesign/Care Redesign. Update Flutter code to reflect the redesign: lib/features/care/presentation/screens/care_screen.dart, lib/features/care/presentation/widgets/gamified_care_ui.dart and lib/features/pet_profile/presentation/screens/manage_pets_screen.dart. Also update android/gradle.properties, progress.md, and add a local .claude settings entry. This provides assets and an interactive preview for the new Care UI and gamification tweaks. --- .claude/settings.local.json | 4 +- .../Care Redesign/Care Redesign.html | 167 +++ .../Care Redesign/care_screen.jsx | 761 +++++++++++ PetFolio Redesign/Care Redesign/ios-frame.jsx | 348 +++++ .../Care Redesign/screenshots/badge.png | Bin 0 -> 15577 bytes .../Care Redesign/screenshots/confetti.png | Bin 0 -> 28823 bytes .../Care Redesign/screenshots/dark.png | Bin 0 -> 18658 bytes .../Care Redesign/screenshots/lower.png | Bin 0 -> 29059 bytes .../Care Redesign/screenshots/lower2.png | Bin 0 -> 29063 bytes .../Care Redesign/screenshots/lower3.png | Bin 0 -> 29226 bytes .../Care Redesign/screenshots/lower4.png | Bin 0 -> 25543 bytes .../Care Redesign/screenshots/trophy.png | Bin 0 -> 24607 bytes .../Care Redesign/screenshots/trophy2.png | Bin 0 -> 26921 bytes .../Care Redesign/screenshots/tweaks.png | Bin 0 -> 23449 bytes .../Care Redesign/screenshots/tweaks2.png | Bin 0 -> 23415 bytes .../Care Redesign/screenshots/tweaks3.png | Bin 0 -> 20621 bytes .../Care Redesign/screenshots/v1.png | Bin 0 -> 29544 bytes .../Care Redesign/screenshots/v2.png | Bin 0 -> 29544 bytes .../Care Redesign/screenshots/v3.png | Bin 0 -> 29059 bytes PetFolio Redesign/README.md | 22 + android/gradle.properties | 4 + .../presentation/screens/care_screen.dart | 479 ++++--- .../widgets/gamified_care_ui.dart | 1133 +++++++++++------ .../screens/manage_pets_screen.dart | 3 +- progress.md | 24 + 25 files changed, 2364 insertions(+), 581 deletions(-) create mode 100644 PetFolio Redesign/Care Redesign/Care Redesign.html create mode 100644 PetFolio Redesign/Care Redesign/care_screen.jsx create mode 100644 PetFolio Redesign/Care Redesign/ios-frame.jsx create mode 100644 PetFolio Redesign/Care Redesign/screenshots/badge.png create mode 100644 PetFolio Redesign/Care Redesign/screenshots/confetti.png create mode 100644 PetFolio Redesign/Care Redesign/screenshots/dark.png create mode 100644 PetFolio Redesign/Care Redesign/screenshots/lower.png create mode 100644 PetFolio Redesign/Care Redesign/screenshots/lower2.png create mode 100644 PetFolio Redesign/Care Redesign/screenshots/lower3.png create mode 100644 PetFolio Redesign/Care Redesign/screenshots/lower4.png create mode 100644 PetFolio Redesign/Care Redesign/screenshots/trophy.png create mode 100644 PetFolio Redesign/Care Redesign/screenshots/trophy2.png create mode 100644 PetFolio Redesign/Care Redesign/screenshots/tweaks.png create mode 100644 PetFolio Redesign/Care Redesign/screenshots/tweaks2.png create mode 100644 PetFolio Redesign/Care Redesign/screenshots/tweaks3.png create mode 100644 PetFolio Redesign/Care Redesign/screenshots/v1.png create mode 100644 PetFolio Redesign/Care Redesign/screenshots/v2.png create mode 100644 PetFolio Redesign/Care Redesign/screenshots/v3.png create mode 100644 PetFolio Redesign/README.md diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 8aca5e5..94b7ec2 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -93,7 +93,9 @@ "Bash(grep -v '\\\\.g\\\\.dart$')", "Bash(grep -v '\\\\.freezed\\\\.dart$')", "Bash(gh pr *)", - "Bash(git rm *)" + "Bash(git rm *)", + "Bash(dir \"G:\\\\GitHub\\\\petfolio\\\\PetFolio Redesign\\\\Care Redesign\" /b)", + "mcp__292a7621-3089-4236-bd52-07a54bf59881__list_tables" ] } } diff --git a/PetFolio Redesign/Care Redesign/Care Redesign.html b/PetFolio Redesign/Care Redesign/Care Redesign.html new file mode 100644 index 0000000..2da2638 --- /dev/null +++ b/PetFolio Redesign/Care Redesign/Care Redesign.html @@ -0,0 +1,167 @@ + + + + +PetFolio — Care · Redesign + + + + + + + +
+
+
+ + + + + + + + + + + diff --git a/PetFolio Redesign/Care Redesign/care_screen.jsx b/PetFolio Redesign/Care Redesign/care_screen.jsx new file mode 100644 index 0000000..082e200 --- /dev/null +++ b/PetFolio Redesign/Care Redesign/care_screen.jsx @@ -0,0 +1,761 @@ +// care3d.jsx — PetFolio Care screen, compact redesign + 3D depth +const { useState, useRef, useEffect, useContext, createContext, useCallback } = React; + +// ───────────────────────────────────────────────────────────── +// Theme / depth context (self-contained tweaks) +// ───────────────────────────────────────────────────────────── +const DepthCtx = createContext(1); + +// ───────────────────────────────────────────────────────────── +// 3D tilt hook — pointer/drag driven rotateX/Y + glare position +// ───────────────────────────────────────────────────────────── +function useTilt({ max = 9, lift = 1.0 } = {}) { + const depth = useContext(DepthCtx); + const ref = useRef(null); + const [t, setT] = useState({ rx: 0, ry: 0, on: false, px: 50, py: 50, press: false }); + + const move = useCallback((e) => { + const el = ref.current; if (!el || depth === 0) return; + const r = el.getBoundingClientRect(); + const x = Math.min(1, Math.max(0, (e.clientX - r.left) / r.width)); + const y = Math.min(1, Math.max(0, (e.clientY - r.top) / r.height)); + const m = max * depth; + setT(s => ({ ...s, rx: (0.5 - y) * m * 2, ry: (x - 0.5) * m * 2, on: true, px: x * 100, py: y * 100 })); + }, [depth, max]); + + const leave = useCallback(() => setT(s => ({ ...s, rx: 0, ry: 0, on: false, px: 50, py: 50, press: false })), []); + const down = useCallback(() => setT(s => ({ ...s, press: true })), []); + const up = useCallback(() => setT(s => ({ ...s, press: false })), []); + + const transform = depth === 0 + ? (t.press ? 'scale(0.97)' : 'none') + : `perspective(640px) rotateX(${t.rx}deg) rotateY(${t.ry}deg) translateZ(0) scale(${t.press ? 0.965 : (t.on ? 1.012 * lift : 1)})`; + + const bind = { + ref, + onPointerMove: move, onPointerLeave: leave, onPointerDown: down, + onPointerUp: up, onPointerCancel: leave, + }; + return { bind, t, transform }; +} + +// Glare overlay used inside tilt cards +function Glare({ t, r = 24, strength = 0.5 }) { + const depth = useContext(DepthCtx); + if (depth === 0) return null; + return ( +
+ ); +} + +// ───────────────────────────────────────────────────────────── +// Tiny icon set +// ───────────────────────────────────────────────────────────── +const Ico = { + paw: (s = 22, f = 'currentColor') => (), + pawO: (s = 22, c = 'currentColor') => (), + heartO: (s = 22, c = 'currentColor') => (), + flame: (s = 22, c = 'currentColor') => (), + bone: (s = 22, c = 'currentColor') => (), + cart: (s = 22, c = 'currentColor') => (), + check: (s = 22, c = '#fff') => (), + chevDown: (s = 16, c = 'currentColor') => (), + chevR: (s = 16, c = 'currentColor') => (), + lock: (s = 12, c = 'currentColor') => (), + moon: (s = 20, c = 'currentColor') => (), + sun: (s = 20, c = 'currentColor') => (), + sparkle: (s = 18, c = 'currentColor') => (), + refresh: (s = 16, c = 'currentColor') => (), + scale: (s = 22, c = 'currentColor') => (), + vault: (s = 22, c = 'currentColor') => (), +}; + +// ───────────────────────────────────────────────────────────── +// Pet avatar (gradient disc + emoji + species ring) +// ───────────────────────────────────────────────────────────── +function Avatar({ size = 40, ring = true, emoji = '🐱', soft = 'var(--poppy-soft)', color = 'var(--poppy)' }) { + const inner = size - (ring ? 6 : 0); + return ( +
+
{emoji}
+
+ ); +} + +// ───────────────────────────────────────────────────────────── +// Section label +// ───────────────────────────────────────────────────────────── +function SectionLabel({ accent, children, right }) { + return ( +
+
+
+

{children}

+
+ {right} +
+ ); +} + +// ───────────────────────────────────────────────────────────── +// 3D streak flame medallion +// ───────────────────────────────────────────────────────────── +function StreakCoin({ streak }) { + const depth = useContext(DepthCtx); + return ( +
+
+
+
+
+
+
+
🔥
+
{streak}
+
DAY STREAK
+
+
+
+ ); +} + +// ───────────────────────────────────────────────────────────── +// Slim hero (streak + level + XP) — replaces tall wave header +// ───────────────────────────────────────────────────────────── +function Hero({ pet, doneToday, totalToday }) { + const pct = (pet.xp / pet.xpMax) * 100; + return ( +
+ {/* decorative paws */} +
{Ico.paw(96, '#fff')}
+
+ +
+
+
+ Lv {pet.level} + · {pet.title} +
+ {doneToday}/{totalToday} today +
+
+
+
+
+
+
{pet.xp} / {pet.xpMax} XP · {pet.xpMax - pet.xp} XP to Lv {pet.level + 1}
+
+
+
+ ); +} + +// ───────────────────────────────────────────────────────────── +// Compact horizontal date strip +// ───────────────────────────────────────────────────────────── +function DateStrip() { + const days = [ + { l: 'T', n: 26 }, { l: 'W', n: 27 }, { l: 'T', n: 28 }, { l: 'F', n: 29 }, + { l: 'S', n: 30, hit: true }, { l: 'S', n: 31, hit: true }, { l: 'M', n: 1, today: true }, + { l: 'T', n: 2, fut: true }, { l: 'W', n: 3, fut: true }, + ]; + return ( +
+ {days.map((d, i) => ( +
+ {d.l} + {d.n} + {d.hit && !d.today ?
: + d.today ?
:
} +
+ ))} +
+ ); +} + +// ───────────────────────────────────────────────────────────── +// Pet-character SVG icons for each badge +// ───────────────────────────────────────────────────────────── +const BIco = { + // Paw print + star burst + firstLog: (s=36) => ( + + + + + + + + + + ), + // Cat face with flame crown + streak3: (s=36) => ( + + {/* flame */} + + {/* cat head */} + + {/* ears */} + + + {/* inner ears */} + + + {/* eyes */} + + + + + {/* nose + mouth */} + + + + ), + // Dog face with superhero star + hero7: (s=36) => ( + + {/* star badge */} + + {/* dog head */} + + {/* floppy ears */} + + + {/* eyes */} + + + + + {/* snout */} + + + + ), + // Clipboard with paw checkmark + routineMaster: (s=36) => ( + + + + {/* paw checkmark rows */} + + + + + + ), + // Crown with paw-print peak tips + legend30: (s=36) => ( + + {/* crown base */} + + {/* crown body */} + + {/* paw tips on peaks */} + + + + {/* toe beans */} + + + + + + + {/* gem */} + + + + ), + // Trophy with heart-paw + champion: (s=36) => ( + + {/* trophy cup */} + + {/* handles */} + + {/* stem */} + + + {/* heart-paw in cup */} + + + + + ), +}; + +// Badge data with custom rim colors and float timing +const BADGES = [ + { id:'firstLog', l:'First Log', c:'var(--mint)', rim:'#1a9970', owned:true, hint:'unlocked', delay:0, dur:3.4 }, + { id:'streak3', l:'3-Day Streak', c:'var(--tangerine)', rim:'#b85a1a', owned:false, hint:'1/3 days', delay:0.5, dur:3.8 }, + { id:'hero7', l:'7-Day Hero', c:'var(--poppy)', rim:'#8a1010', owned:false, hint:'1/7 days', delay:0.9, dur:3.2 }, + { id:'routineMaster', l:'Routine Pro', c:'var(--sunny)', rim:'#9a6500', owned:false, hint:'1/14 days', delay:0.3, dur:4.0 }, + { id:'legend30', l:'30-Day Legend', c:'var(--lilac)', rim:'#4a2fa0', owned:false, hint:'1/30 days', delay:0.7, dur:3.6 }, + { id:'champion', l:'Care Champ', c:'var(--sky)', rim:'#2060a8', owned:false, hint:'6/100 logs',delay:0.15, dur:3.5 }, +]; + +const ICON_MAP = { + firstLog: BIco.firstLog, streak3: BIco.streak3, hero7: BIco.hero7, + routineMaster: BIco.routineMaster, legend30: BIco.legend30, champion: BIco.champion, +}; + +// ───────────────────────────────────────────────────────────── +// 3D Trophy badge card — medal-style, floating animation +// ───────────────────────────────────────────────────────────── +function BadgeMedal({ b, idx, onTap }) { + const depth = useContext(DepthCtx); + const { bind, t, transform } = useTilt({ max: 16, lift: 1.06 }); + const IconComponent = ICON_MAP[b.id]; + const floatAnim = depth ? `pf-badge-float ${b.dur}s ease-in-out ${b.delay}s infinite` : 'none'; + + return ( +
onTap(b)} style={{ cursor: 'pointer', display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 5, animation: floatAnim }} > + {/* tilt wrapper */} +
+ {/* outer glow ring (owned only) */} + {b.owned && ( +
+ )} + {/* medal body */} +
+ {/* concentric ring for depth */} +
+
+ {/* icon */} +
+ {IconComponent ? : {b.e}} +
+ {/* holographic sheen (owned) */} + {b.owned && ( +
+ )} + {/* lock pip */} + {!b.owned && ( +
{Ico.lock(9)}
+ )} + +
+
+ {/* label */} +
{b.l}
+
{b.owned ? '✓ earned' : b.hint}
+
+ ); +} + +function TrophyCarousel({ onTap }) { + return ( +
+ {BADGES.map((b, i) => )} +
+ ); +} + +// ───────────────────────────────────────────────────────────── +// Quest task card — denser 2-line, tilt + press-depth + confetti +// ───────────────────────────────────────────────────────────── +const TASK_META = { + feeding: { e: '🥩', c: 'var(--tangerine)', soft: 'var(--tangerine-soft)' }, + playtime: { e: '🎾', c: 'var(--sunny)', soft: 'var(--sunny-soft)' }, + training: { e: '🎓', c: 'var(--poppy)', soft: 'var(--poppy-soft)' }, + walk: { e: '🦮', c: 'var(--mint)', soft: 'var(--mint-soft)' }, +}; + +function TaskCard({ task, onToggle }) { + const { bind, t, transform } = useTilt({ max: 6 }); + const m = TASK_META[task.type] || TASK_META.feeding; + const done = task.done; + return ( +
+
+
{done ? Ico.check(22, '#fff') : m.e}
+
+
{task.title}
+
{done ? 'Completed' : (task.due ? `Due ${task.time}` : task.time)}
+
+
+ +{task.xp} + +
+ +
+
+ ); +} + +function FreqDivider({ label }) { + return ( +
+
+ {label} +
+
+ ); +} + +// ───────────────────────────────────────────────────────────── +// Compact weekly chart +// ───────────────────────────────────────────────────────────── +function WeeklyChart() { + const bars = [ + { l: 'T', n: 26, h: 0.3, miss: true }, { l: 'W', n: 27, h: 0.3, miss: true }, + { l: 'T', n: 28, h: 0.3, miss: true }, { l: 'F', n: 29, h: 0.3, miss: true }, + { l: 'S', n: 30, h: 0.3, miss: true }, { l: 'S', n: 31, h: 0.85, c: 'var(--mint)' }, + { l: 'M', n: 1, h: 0.16, c: 'var(--poppy)', today: true }, + ]; + return ( +
+
+ 1 / 7 goals this week + 1 🔥 +
+
+ {bars.map((b, i) => ( +
+ {b.today && 🐾} +
+ {b.l} + {b.n} +
+ ))} +
+
+ ); +} + +// ───────────────────────────────────────────────────────────── +// Merged utility banner (Nutrition | Medical Vault) +// ───────────────────────────────────────────────────────────── +function UtilityBanner() { + const half = (icon, bg, icColor, title, line1, line2) => ( +
+
+
{icon}
+ {Ico.chevR(15, 'var(--ink-300)')} +
+
+
{title}
+
{line1}
+
{line2}
+
+
+ ); + return ( +
+ {half(Ico.scale(20), 'var(--sunny-soft)', 'var(--sunny-700)', 'Nutrition', '4.2 kg · May 28', '~280 kcal / day')} +
+ {half(Ico.vault(20), 'var(--mint-soft)', 'var(--mint-700)', 'Medical Vault', '1 due soon', 'Checkup · 3 wks')} +
+ ); +} + +// ───────────────────────────────────────────────────────────── +// Bottom nav +// ───────────────────────────────────────────────────────────── +function BottomNav() { + const tabs = [ + { id: 'pets', label: 'Pets', icon: Ico.pawO, c: 'var(--tangerine)' }, + { id: 'care', label: 'Care', icon: Ico.flame, c: 'var(--tangerine-700)', active: true }, + { id: 'social', label: 'Social', icon: Ico.heartO, c: 'var(--poppy)' }, + { id: 'match', label: 'Match', icon: Ico.bone, c: 'var(--lilac)' }, + { id: 'market', label: 'Market', icon: Ico.cart, c: 'var(--mint-700)' }, + ]; + return ( +
+ {tabs.map(t => ( + + ))} +
+ ); +} + +// ───────────────────────────────────────────────────────────── +// Confetti + XP burst overlay +// ───────────────────────────────────────────────────────────── +function Burst({ burst }) { + if (!burst) return null; + const colors = ['var(--tangerine)', 'var(--poppy)', 'var(--mint)', 'var(--sunny)', 'var(--lilac)']; + return ( +
+
+{burst.xp} XP
+ {Array.from({ length: 14 }).map((_, i) => { + const dx = (Math.random() - 0.5) * 130; + const rot = Math.random() * 720; + const dl = Math.random() * 120; + const c = colors[i % colors.length]; + return
; + })} +
+ ); +} + +// ───────────────────────────────────────────────────────────── +// Badge detail sheet +// ───────────────────────────────────────────────────────────── +function BadgeSheet({ badge, onClose }) { + if (!badge) return null; + return ( +
+
e.stopPropagation()} style={{ width: '100%', background: 'var(--surface)', borderRadius: '28px 28px 0 0', padding: '12px 22px 34px', boxShadow: '0 -10px 40px rgba(0,0,0,0.2)' }}> +
+
+
+ {(() => { const IC = ICON_MAP[badge.id]; return IC ? : null; })()} +
+
{badge.l}
+
{badge.owned ? 'You unlocked this badge — nice work keeping up the routine!' : 'Keep logging care to unlock this badge.'}
+
{badge.owned ? '✅ Earned!' : `Progress: ${badge.hint}`}
+
+
+
+ ); +} + +// ───────────────────────────────────────────────────────────── +// Tweaks panel (self-contained) +// ───────────────────────────────────────────────────────────── +function TweaksPanel({ open, onClose, depth, setDepth, dark, setDark, reduce, setReduce }) { + if (!open) return null; + const seg = (val, cur, set, opts) => ( +
+ {opts.map(o => ( + + ))} +
+ ); + return ( +
+
e.stopPropagation()} style={{ width: '100%', background: 'var(--surface)', borderRadius: '28px 28px 0 0', padding: '12px 20px 30px' }}> +
+
Tweaks
+
+
3D depth
{seg(depth, depth, setDepth, [{ v: 0, l: 'Off' }, { v: 0.5, l: 'Subtle' }, { v: 1, l: 'Full' }])}
+
Appearance
{seg(dark, dark, setDark, [{ v: false, l: '☀︎ Light' }, { v: true, l: '☾ Dark' }])}
+
Motion
{seg(reduce, reduce, setReduce, [{ v: false, l: 'Animated' }, { v: true, l: 'Reduced' }])}
+
+
+
+ ); +} + +// ───────────────────────────────────────────────────────────── +// Care screen +// ───────────────────────────────────────────────────────────── +const PET = { name: 'Jhontu', level: 2, title: 'Curious Pup', xp: 100, xpMax: 250, streak: 1 }; +const INITIAL_TASKS = [ + { id: 't1', title: 'Morning Feeding', type: 'feeding', time: '8:00 AM', xp: 12, due: true, done: false, freq: 'daily' }, + { id: 't2', title: 'Evening Feeding', type: 'feeding', time: '6:00 PM', xp: 12, due: true, done: false, freq: 'daily' }, + { id: 't3', title: 'Interactive Playtime', type: 'playtime', time: 'Daily', xp: 20, done: false, freq: 'daily' }, + { id: 't4', title: 'Clicker Training', type: 'training', time: 'As needed', xp: 15, done: false, freq: 'less' }, + { id: 't5', title: 'Laser Pointer Chase', type: 'playtime', time: 'As needed', xp: 15, done: false, freq: 'less' }, +]; + +function CareScreen({ onSparkle, onMoon, dark }) { + const [tasks, setTasks] = useState(INITIAL_TASKS); + const [burst, setBurst] = useState(null); + const [badge, setBadge] = useState(null); + const scrollRef = useRef(null); + + const daily = tasks.filter(t => t.freq === 'daily'); + const less = tasks.filter(t => t.freq === 'less'); + const doneToday = daily.filter(t => t.done).length; + + function toggle(task, btnEl) { + const nowDone = !task.done; + setTasks(ts => ts.map(t => t.id === task.id ? { ...t, done: nowDone, due: nowDone ? false : t.due } : t)); + if (nowDone && btnEl && scrollRef.current) { + const br = btnEl.getBoundingClientRect(); + const pr = scrollRef.current.getBoundingClientRect(); + setBurst({ x: br.left - pr.left + br.width / 2 - 20, y: br.top - pr.top + scrollRef.current.scrollTop - 4, xp: task.xp }); + setTimeout(() => setBurst(null), 1100); + } + } + + return ( +
+
+ {/* App bar */} +
+ +
+ + +
+
+ + + +
+ + +
+
+ Vault {Ico.chevR(13, 'var(--lilac-700)')}}> + Trophy room + +
+
+
1 / 6 earned
+ +
+ +
+
+
+ TODAY'S QUESTS +
+ {doneToday === daily.length ? 'All done! 🎉' : `${doneToday}/${daily.length} done`} + +
+
+ + {daily.map(t => )} + + {less.map(t => )} +
+ +
+
+ This week + +
+ +
+
+ +
+ + +
+ + + setBadge(null)}/> +
+ ); +} + +// ───────────────────────────────────────────────────────────── +// Root +// ───────────────────────────────────────────────────────────── +function App() { + const [depth, setDepth] = useState(1); + const [dark, setDark] = useState(false); + const [reduce, setReduce] = useState(false); + const [tweaksOpen, setTweaksOpen] = useState(false); + + useEffect(() => { + document.documentElement.setAttribute('data-theme', dark ? 'dark' : 'light'); + }, [dark]); + useEffect(() => { + document.body.classList.toggle('reduce-motion', reduce); + }, [reduce]); + + return ( + + + setTweaksOpen(true)} onMoon={() => setDark(d => !d)} dark={dark}/> + setTweaksOpen(false)} depth={depth} setDepth={setDepth} dark={dark} setDark={setDark} reduce={reduce} setReduce={setReduce}/> + + + ); +} + +ReactDOM.createRoot(document.getElementById('root')).render(); diff --git a/PetFolio Redesign/Care Redesign/ios-frame.jsx b/PetFolio Redesign/Care Redesign/ios-frame.jsx new file mode 100644 index 0000000..8703a44 --- /dev/null +++ b/PetFolio Redesign/Care Redesign/ios-frame.jsx @@ -0,0 +1,348 @@ + +/* BEGIN USAGE */ +// iOS.jsx — Simplified iOS 26 (Liquid Glass) device frame +// Based on the iOS 26 UI Kit + Figma status bar spec. No assets, no deps. +// Exports (to window): IOSDevice, IOSStatusBar, IOSNavBar, IOSGlassPill, IOSList, IOSListRow, IOSKeyboard +// +// Usage — wrap your screen content in to get the bezel, status bar +// and home indicator (props: title, dark, keyboard): +// +// +// ...your screen content... +// +// +/* END USAGE */ + +// ───────────────────────────────────────────────────────────── +// Status bar +// ───────────────────────────────────────────────────────────── +function IOSStatusBar({ dark = false, time = '9:41' }) { + const c = dark ? '#fff' : '#000'; + return ( +
+
+ {time} +
+
+ + + + + + + + + + + + + + + + +
+
+ ); +} + +// ───────────────────────────────────────────────────────────── +// Liquid glass pill — blur + tint + shine +// ───────────────────────────────────────────────────────────── +function IOSGlassPill({ children, dark = false, style = {} }) { + return ( +
+ {/* blur + tint */} +
+ {/* shine */} +
+
+ {children} +
+
+ ); +} + +// ───────────────────────────────────────────────────────────── +// Navigation bar — glass pills + large title +// ───────────────────────────────────────────────────────────── +function IOSNavBar({ title = 'Title', dark = false, trailingIcon = true }) { + const muted = dark ? 'rgba(255,255,255,0.6)' : '#404040'; + const text = dark ? '#fff' : '#000'; + const pillIcon = (content) => ( + +
+ {content} +
+
+ ); + return ( +
+
+ {/* back chevron */} + {pillIcon( + + + + )} + {/* trailing ellipsis */} + {trailingIcon && pillIcon( + + + + + + )} +
+ {/* large title */} +
{title}
+
+ ); +} + +// ───────────────────────────────────────────────────────────── +// Grouped list (inset card, r:26) + row (52px) +// ───────────────────────────────────────────────────────────── +function IOSListRow({ title, detail, icon, chevron = true, isLast = false, dark = false }) { + const text = dark ? '#fff' : '#000'; + const sec = dark ? 'rgba(235,235,245,0.6)' : 'rgba(60,60,67,0.6)'; + const ter = dark ? 'rgba(235,235,245,0.3)' : 'rgba(60,60,67,0.3)'; + const sep = dark ? 'rgba(84,84,88,0.65)' : 'rgba(60,60,67,0.12)'; + return ( +
+ {icon && ( +
+ )} +
{title}
+ {detail && {detail}} + {chevron && ( + + + + )} + {!isLast && ( +
+ )} +
+ ); +} + +function IOSList({ header, children, dark = false }) { + const hc = dark ? 'rgba(235,235,245,0.6)' : 'rgba(60,60,67,0.6)'; + const bg = dark ? '#1C1C1E' : '#fff'; + return ( +
+ {header && ( +
{header}
+ )} +
{children}
+
+ ); +} + +// ───────────────────────────────────────────────────────────── +// Device frame +// ───────────────────────────────────────────────────────────── +function IOSDevice({ + children, width = 402, height = 874, dark = false, + title, keyboard = false, +}) { + return ( +
+ {/* dynamic island */} +
+ {/* status bar (absolute) */} +
+ +
+ {/* nav + content */} +
+ {title !== undefined && } +
{children}
+ {keyboard && } +
+ {/* home indicator — always on top */} +
+
+
+
+ ); +} + +// ───────────────────────────────────────────────────────────── +// Keyboard — iOS 26 liquid glass +// ───────────────────────────────────────────────────────────── +function IOSKeyboard({ dark = false }) { + const glyph = dark ? 'rgba(255,255,255,0.7)' : '#595959'; + const sugg = dark ? 'rgba(255,255,255,0.6)' : '#333'; + const keyBg = dark ? 'rgba(255,255,255,0.22)' : 'rgba(255,255,255,0.85)'; + + // special-key icons + const icons = { + shift: , + del: , + ret: , + }; + + const key = (content, { w, flex, ret, fs = 25, k } = {}) => ( +
{content}
+ ); + + const row = (keys, pad = 0) => ( +
+ {keys.map(l => key(l, { flex: true, k: l }))} +
+ ); + + return ( +
+ {/* liquid glass bg — same recipe as nav pills */} +
+
+ + {/* autocorrect bar */} +
+ {['"The"', 'the', 'to'].map((w, i) => ( + + {i > 0 &&
} +
{w}
+ + ))} +
+ + {/* key layout */} +
+ {row(['q','w','e','r','t','y','u','i','o','p'])} + {row(['a','s','d','f','g','h','j','k','l'], 20)} +
+ {key(icons.shift, { w: 45, k: 'shift' })} +
+ {['z','x','c','v','b','n','m'].map(l => key(l, { flex: true, k: l }))} +
+ {key(icons.del, { w: 45, k: 'del' })} +
+
+ {key('ABC', { w: 92.25, fs: 18, k: 'abc' })} + {key('', { flex: true, k: 'space' })} + {key(icons.ret, { w: 92.25, ret: true, k: 'ret' })} +
+
+ + {/* bottom spacer (emoji+mic area, icons omitted) */} +
+
+ ); +} + +Object.assign(window, { + IOSDevice, IOSStatusBar, IOSNavBar, IOSGlassPill, IOSList, IOSListRow, IOSKeyboard, +}); diff --git a/PetFolio Redesign/Care Redesign/screenshots/badge.png b/PetFolio Redesign/Care Redesign/screenshots/badge.png new file mode 100644 index 0000000000000000000000000000000000000000..25f6a325203d15f9b2c53027f689561099a04939 GIT binary patch literal 15577 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 literal 0 HcmV?d00001 diff --git a/PetFolio Redesign/Care Redesign/screenshots/lower.png b/PetFolio Redesign/Care Redesign/screenshots/lower.png new file mode 100644 index 0000000000000000000000000000000000000000..29a065b39d9a678373e606fc47d70385df59afa4 GIT binary patch literal 29059 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 literal 0 HcmV?d00001 diff --git a/PetFolio Redesign/Care Redesign/screenshots/lower2.png b/PetFolio Redesign/Care Redesign/screenshots/lower2.png new file mode 100644 index 0000000000000000000000000000000000000000..341ab65ae07aaa8b58f06a9f01ee087a09700cfb GIT binary patch literal 29063 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℞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 C?&sD3 literal 0 HcmV?d00001 diff --git a/PetFolio Redesign/Care Redesign/screenshots/lower3.png b/PetFolio Redesign/Care Redesign/screenshots/lower3.png new file mode 100644 index 0000000000000000000000000000000000000000..b80644a7588d7ee6e3f2dd7a75072e4ec75820a1 GIT binary patch literal 29226 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 OjsvDb5a_}`BmV=R`Rd^S literal 0 HcmV?d00001 diff --git a/PetFolio Redesign/Care Redesign/screenshots/tweaks.png b/PetFolio Redesign/Care Redesign/screenshots/tweaks.png new file mode 100644 index 0000000000000000000000000000000000000000..db61fe2a2a56762d6321d47b4022186decb0c01b GIT binary patch literal 23449 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 Z|2(Kb6#*ehVN+p17z)Nt06+gV{y%u^42S># literal 0 HcmV?d00001 diff --git a/PetFolio Redesign/Care Redesign/screenshots/tweaks2.png b/PetFolio Redesign/Care Redesign/screenshots/tweaks2.png new file mode 100644 index 0000000000000000000000000000000000000000..60132f340c53477fe2ab7e4b52afd2aae9aad623 GIT binary patch literal 23415 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 literal 0 HcmV?d00001 diff --git a/PetFolio Redesign/Care Redesign/screenshots/tweaks3.png b/PetFolio Redesign/Care Redesign/screenshots/tweaks3.png new file mode 100644 index 0000000000000000000000000000000000000000..9259e2312d7c8126192f9ae0b17e7f3e4e4f2aaf GIT binary patch literal 20621 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 literal 0 HcmV?d00001 diff --git a/PetFolio Redesign/README.md b/PetFolio Redesign/README.md new file mode 100644 index 0000000..3fddf65 --- /dev/null +++ b/PetFolio Redesign/README.md @@ -0,0 +1,22 @@ +# CODING AGENTS: READ THIS FIRST + +This is a **handoff bundle** from Claude Design (claude.ai/design). + +A user mocked up designs in HTML/CSS/JS using an AI design tool, then exported this bundle so a coding agent can implement the designs for real. + +## What you should do — IMPORTANT + +**Read `petfolio-redesign/project/Care Redesign/Care Redesign.html` in full.** The user had this file open when they triggered the handoff, so it's almost certainly the primary design they want built. Read it top to bottom — don't skim. Then **follow its imports**: open every file it pulls in (shared components, CSS, scripts) so you understand how the pieces fit together before you start implementing. + +**If anything is ambiguous, ask the user to confirm before you start implementing.** It's much cheaper to clarify scope up front than to build the wrong thing. + +## About the design files + +The design medium is **HTML/CSS/JS** — these are prototypes, not production code. Your job is to **recreate them pixel-perfectly** in whatever technology makes sense for the target codebase (React, Vue, native, whatever fits). Match the visual output; don't copy the prototype's internal structure unless it happens to fit. + +**Don't render these files in a browser or take screenshots unless the user asks you to.** Everything you need — dimensions, colors, layout rules — is spelled out in the source. Read the HTML and CSS directly; a screenshot won't tell you anything they don't. + +## Bundle contents + +- `petfolio-redesign/README.md` — this file +- `petfolio-redesign/project/` — the `PetFolio Redesign` project files (HTML prototypes, assets, components) diff --git a/android/gradle.properties b/android/gradle.properties index fbee1d8..d5da727 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,2 +1,6 @@ org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError android.useAndroidX=true +# This builtInKotlin flag was added automatically by Flutter migrator +android.builtInKotlin=false +# This newDsl flag was added automatically by Flutter migrator +android.newDsl=false diff --git a/lib/features/care/presentation/screens/care_screen.dart b/lib/features/care/presentation/screens/care_screen.dart index f45ca7c..eb54bd9 100644 --- a/lib/features/care/presentation/screens/care_screen.dart +++ b/lib/features/care/presentation/screens/care_screen.dart @@ -174,7 +174,8 @@ class _CareScreenState extends ConsumerState { child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - const SizedBox(height: 12.0), + // ── Space for floating hero card overlap (card at bottom:-28) ── + const SizedBox(height: 44.0), // ── Date picker ──────────────────────────────── _HorizontalDatePicker( selectedDate: dashboard.selectedDate, @@ -182,28 +183,12 @@ class _CareScreenState extends ConsumerState { .read(careDashboardProvider.notifier) .selectDate(d), ), - const SizedBox(height: 16.0), - PfSectionTitle( - title: 'Trophy room', - accent: AppColors.lilac, - trailing: GestureDetector( - onTap: () => context.push('/care/medical-vault'), - child: const Text( - 'Vault →', - style: TextStyle( - fontSize: 13, - fontWeight: FontWeight.w800, - color: AppColors.lilac700, - ), - ), - ), - ), - CareGamifiedTrophyRoom(petId: activePet.id), - const SizedBox(height: 32), + const SizedBox(height: 24.0), // ── TODAY'S QUESTS header with AI refresh ────── Padding( - padding: const EdgeInsets.fromLTRB(4, 0, 4, 8), + padding: const EdgeInsets.fromLTRB(4, 0, 4, 10), child: Row( + crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( "TODAY'S QUESTS", @@ -216,32 +201,39 @@ class _CareScreenState extends ConsumerState { ), const Spacer(), _DoneCounter(tasks: dashboard.tasks.value ?? []), - const SizedBox(width: 8), - // Compact AI Routine refresh icon button + const SizedBox(width: 6), + // AI Routine refresh — 44×44 accessible touch target GestureDetector( onTap: _isGeneratingRoutine ? null : () => _generateRoutine(activePet), child: Tooltip( message: 'Refresh AI Routine', - child: Container( - width: 30, - height: 30, + child: AnimatedContainer( + duration: PetfolioThemeExtension.durationSm, + width: 44, + height: 44, decoration: BoxDecoration( - color: AppColors.lilacSoft, + color: _isGeneratingRoutine + ? AppColors.lilacSoft + : AppColors.lilacSoft, shape: BoxShape.circle, + border: Border.all( + color: AppColors.lilac.withAlpha(50), + width: 1, + ), ), alignment: Alignment.center, child: _isGeneratingRoutine ? const SizedBox( - width: 14, - height: 14, + width: 18, + height: 18, child: CircularProgressIndicator( strokeWidth: 2, color: AppColors.lilac, ), ) : const Icon( - Icons.auto_awesome, - size: 15, + Icons.auto_awesome_rounded, + size: 18, color: AppColors.lilac, ), ), @@ -265,22 +257,45 @@ class _CareScreenState extends ConsumerState { species: species, onAddTask: openAddSheet, ), - const SizedBox(height: 32), + const SizedBox(height: 28), PfSectionTitle( title: 'This week', accent: AppColors.mint, ), + const SizedBox(height: 8), CareGamifiedWeeklyChart( selectedDay: dashboard.selectedDate, weekHits: dashboard.weekGoalHit.value ?? List.filled(7, false), - progressPercent: (dashboard.tasks.value != null && dashboard.tasks.value!.isNotEmpty) - ? (dashboard.tasks.value!.where((t) => t.isCompleted).length / dashboard.tasks.value!.length) - : 0.0, + progressPercent: () { + final all = dashboard.tasks.value; + if (all == null || all.isEmpty) return 0.0; + final planned = all.where((t) => + !t.isLogDerived && + t.frequency != dbtask.CareFrequency.asNeeded).toList(); + if (planned.isEmpty) return 0.0; + return planned.where((t) => t.isCompleted).length / planned.length; + }(), + ), + const SizedBox(height: 28), + PfSectionTitle( + title: 'Trophy room', + accent: AppColors.lilac, + trailing: GestureDetector( + onTap: () => context.push('/care/medical-vault'), + child: const Text( + 'Vault →', + style: TextStyle( + fontSize: 13, + fontWeight: FontWeight.w800, + color: AppColors.lilac700, + ), + ), + ), ), - const SizedBox(height: 32), - _NutritionBanner(pt: pt), - const SizedBox(height: 16), - _MedicalVaultBanner(pt: pt), + const SizedBox(height: 8), + CareGamifiedTrophyRoom(petId: activePet.id), + const SizedBox(height: 28), + _UtilityBanner(pt: pt), ], ), ), @@ -567,8 +582,10 @@ class _DailyTasksDashboard extends ConsumerWidget { ); } - // Check if all planned tasks are done - final planned = tasks.where((t) => !t.isLogDerived).toList(); + // Check if all scheduled/repeating tasks are done (exclude asNeeded) + final planned = tasks + .where((t) => !t.isLogDerived && t.frequency != dbtask.CareFrequency.asNeeded) + .toList(); final allDone = planned.isNotEmpty && planned.every((t) => t.isCompleted); @@ -625,12 +642,25 @@ class _DailyTasksDashboard extends ConsumerWidget { String petName, PetSpecies species, ) { + // Sort: scheduled-time tasks ascending, then no-time tasks alphabetically + final sorted = [...tasks]..sort((a, b) { + final aTime = parseCareScheduledTimeOfDay(a.scheduledTime); + final bTime = parseCareScheduledTimeOfDay(b.scheduledTime); + if (aTime != null && bTime != null) { + return (aTime.hour * 60 + aTime.minute) + .compareTo(bTime.hour * 60 + bTime.minute); + } + if (aTime != null) return -1; + if (bTime != null) return 1; + return a.title.compareTo(b.title); + }); + return [ Padding( - padding: const EdgeInsets.fromLTRB(4, 8, 4, 8), + padding: const EdgeInsets.fromLTRB(4, 10, 4, 10), child: Row( children: [ - Expanded(child: Divider(color: pt.line, thickness: 1, endIndent: 8)), + Expanded(child: Divider(color: pt.line, thickness: 1, endIndent: 10)), Text( label, style: TextStyle( @@ -640,11 +670,11 @@ class _DailyTasksDashboard extends ConsumerWidget { color: pt.ink300, ), ), - Expanded(child: Divider(color: pt.line, thickness: 1, indent: 8)), + Expanded(child: Divider(color: pt.line, thickness: 1, indent: 10)), ], ), ), - ...tasks.map((t) => _CareTaskCard( + ...sorted.map((t) => _CareTaskCard( task: t, petId: petId, petName: petName, @@ -664,7 +694,10 @@ class _DoneCounter extends StatelessWidget { @override Widget build(BuildContext context) { - final planned = tasks.where((t) => !t.isLogDerived).toList(); + // Exclude log-derived entries and asNeeded tasks from the daily quest count + final planned = tasks + .where((t) => !t.isLogDerived && t.frequency != dbtask.CareFrequency.asNeeded) + .toList(); if (planned.isEmpty) return const SizedBox.shrink(); final done = planned.where((t) => t.isCompleted).length; final total = planned.length; @@ -985,7 +1018,8 @@ class _CareTaskCardState extends ConsumerState<_CareTaskCard> final cs = Theme.of(context).colorScheme; final task = widget.task; final done = task.isCompleted; - final due = !done && task.isDueToday; + // Only flag as urgently due when a specific scheduled time exists + final due = !done && task.isDueToday && task.scheduledTime != null; final color = _color; final yAnim = Tween(begin: 0.0, end: -72.0).animate( @@ -1005,31 +1039,61 @@ class _CareTaskCardState extends ConsumerState<_CareTaskCard> padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 14), decoration: BoxDecoration( color: done - ? Color.alphaBlend(color.withAlpha(36), cs.surface) + ? Color.alphaBlend(color.withAlpha(28), cs.surface) : cs.surface, - borderRadius: BorderRadius.circular(22), + borderRadius: BorderRadius.circular(20), border: Border.all( - color: done ? color : pt.line, - width: 2, + color: done + ? color.withAlpha(180) + : (due ? AppColors.poppy.withAlpha(160) : pt.line), + width: done ? 1.5 : (due ? 1.5 : 1), ), boxShadow: due - ? [BoxShadow(color: AppColors.poppy.withAlpha(64), blurRadius: 0, spreadRadius: 4)] - : pt.shadowE1, + ? [ + BoxShadow( + color: AppColors.poppy.withAlpha(40), + blurRadius: 16, + offset: const Offset(0, 6), + spreadRadius: -4, + ), + ...pt.shadowE1, + ] + : pt.shadowE2, ), child: Row( children: [ // ── Icon box ────────────────────────────────────────────────── AnimatedContainer( duration: const Duration(milliseconds: 240), - width: 52, - height: 52, + width: 54, + height: 54, decoration: BoxDecoration( borderRadius: BorderRadius.circular(16), - color: done ? color : color.withAlpha(48), + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: done + ? [color, Color.lerp(color, Colors.white, 0.28)!] + : [color.withAlpha(55), color.withAlpha(22)], + ), + boxShadow: done + ? [ + BoxShadow( + color: color.withAlpha(90), + blurRadius: 10, + offset: const Offset(0, 4), + spreadRadius: -3, + ), + ] + : null, ), alignment: Alignment.center, child: AnimatedSwitcher( duration: const Duration(milliseconds: 200), + transitionBuilder: (child, anim) => ScaleTransition( + scale: anim, + child: child, + ), child: Text( key: ValueKey(done), done ? '✅' : _emoji, @@ -1049,12 +1113,12 @@ class _CareTaskCardState extends ConsumerState<_CareTaskCard> Flexible( child: AnimatedDefaultTextStyle( duration: const Duration(milliseconds: 200), - style: TextStyle( - fontSize: 15, - fontWeight: FontWeight.w800, + style: Theme.of(context).textTheme.titleSmall!.copyWith( + fontWeight: FontWeight.w700, color: done ? pt.ink500 : cs.onSurface, decoration: done ? TextDecoration.lineThrough : null, decorationColor: pt.ink300, + height: 1.2, ), child: Text( task.title, @@ -1067,7 +1131,7 @@ class _CareTaskCardState extends ConsumerState<_CareTaskCard> const SizedBox(width: 6), Container( padding: const EdgeInsets.symmetric( - horizontal: 7, vertical: 2), + horizontal: 8, vertical: 3), decoration: BoxDecoration( color: AppColors.lilacSoft, borderRadius: BorderRadius.circular(999), @@ -1075,25 +1139,44 @@ class _CareTaskCardState extends ConsumerState<_CareTaskCard> child: Text( _frequencyPill(task.frequency), style: const TextStyle( - fontSize: 10, + fontSize: 9.5, fontWeight: FontWeight.w900, + letterSpacing: 0.3, color: AppColors.lilac700, + height: 1.2, ), ), ), ], ], ), - const SizedBox(height: 3), - Text( - _sublabel, - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w700, - color: due ? AppColors.poppy700 : pt.ink500, - ), - maxLines: 1, - overflow: TextOverflow.ellipsis, + const SizedBox(height: 4), + Row( + children: [ + if (due) ...[ + Container( + width: 6, + height: 6, + margin: const EdgeInsets.only(right: 5), + decoration: const BoxDecoration( + color: AppColors.poppy, + shape: BoxShape.circle, + ), + ), + ], + Flexible( + child: Text( + _sublabel, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w600, + color: due ? AppColors.poppy700 : pt.ink500, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ), + ], ), ], ), @@ -1107,10 +1190,20 @@ class _CareTaskCardState extends ConsumerState<_CareTaskCard> AnimatedContainer( duration: const Duration(milliseconds: 200), padding: const EdgeInsets.symmetric( - horizontal: 9, vertical: 4), + horizontal: 10, vertical: 5), decoration: BoxDecoration( - color: done ? AppColors.mintSoft : AppColors.sunnySoft, + gradient: LinearGradient( + colors: done + ? [AppColors.mintSoft, AppColors.mintSoft] + : [AppColors.sunnySoft, AppColors.sunnySoft], + ), borderRadius: BorderRadius.circular(999), + border: Border.all( + color: done + ? AppColors.mint.withAlpha(80) + : AppColors.sunny.withAlpha(80), + width: 1, + ), ), child: Row( mainAxisSize: MainAxisSize.min, @@ -1118,40 +1211,41 @@ class _CareTaskCardState extends ConsumerState<_CareTaskCard> Text( '+${task.gamificationPoints}', style: TextStyle( - fontSize: 12, + fontSize: 11, fontWeight: FontWeight.w900, - color: done - ? AppColors.mint700 - : AppColors.sunny700, + letterSpacing: 0.2, + color: done ? AppColors.mint700 : AppColors.sunny700, + height: 1, ), ), - const SizedBox(width: 2), - const Text('⭐', - style: TextStyle(fontSize: 11)), + const SizedBox(width: 3), + const Text('⭐', style: TextStyle(fontSize: 10, height: 1)), ], ), ), - const SizedBox(height: 6), + const SizedBox(height: 8), GestureDetector( key: ValueKey('care_task_check_${task.id}'), onTap: _toggle, behavior: HitTestBehavior.opaque, child: AnimatedContainer( duration: const Duration(milliseconds: 200), - width: 34, - height: 34, + width: 36, + height: 36, decoration: BoxDecoration( shape: BoxShape.circle, color: done ? color : cs.surface, border: Border.all( color: done ? color : pt.line, - width: 2, + width: done ? 0 : 2, ), + boxShadow: done + ? [BoxShadow(color: color.withAlpha(80), blurRadius: 8, offset: const Offset(0, 3), spreadRadius: -2)] + : null, ), alignment: Alignment.center, child: done - ? const Icon(Icons.check_rounded, - color: Colors.white, size: 18) + ? const Icon(Icons.check_rounded, color: Colors.white, size: 20) : null, ), ), @@ -1505,10 +1599,13 @@ class _EmptyRoutineState extends StatelessWidget { String _frequencyPill(dbtask.CareFrequency f) { switch (f) { - case dbtask.CareFrequency.monthly: return 'MONTHLY'; - case dbtask.CareFrequency.biweekly: return 'BIWEEKLY'; - case dbtask.CareFrequency.weekly: return 'WEEKLY'; - default: return 'WEEKLY'; + case dbtask.CareFrequency.monthly: return 'MONTHLY'; + case dbtask.CareFrequency.biweekly: return 'BIWEEKLY'; + case dbtask.CareFrequency.weekly: return 'WEEKLY'; + case dbtask.CareFrequency.twiceDaily: return '2× DAILY'; + case dbtask.CareFrequency.daily: return 'DAILY'; + case dbtask.CareFrequency.once: return 'ONCE'; + case dbtask.CareFrequency.asNeeded: return 'AS NEEDED'; } } @@ -1548,65 +1645,48 @@ String _defaultTitle(dbtask.CareTaskType type) { // Medical vault & nutrition entry banners // ───────────────────────────────────────────────────────────────────────────── -class _MedicalVaultBanner extends StatelessWidget { - const _MedicalVaultBanner({required this.pt}); +// ── Merged utility banner (Nutrition | Medical Vault side-by-side) ──────────── + +class _UtilityBanner extends StatelessWidget { + const _UtilityBanner({required this.pt}); final PetfolioThemeExtension pt; @override Widget build(BuildContext context) { - return GestureDetector( - key: const ValueKey('care_medical_vault_banner'), - onTap: () => context.push('/care/medical-vault'), - child: Container( - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, - colors: [ - AppColors.mintSoft, - Color.lerp(AppColors.mintSoft, AppColors.mint.withAlpha(40), 0.5)!, - ], - ), - borderRadius: BorderRadius.circular(PetfolioThemeExtension.radiusLg), - border: Border.all(color: AppColors.mint.withAlpha(60)), - boxShadow: pt.shadowE1, - ), - padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16), + final cs = Theme.of(context).colorScheme; + return Container( + decoration: BoxDecoration( + color: cs.surface, + borderRadius: BorderRadius.circular(22), + border: Border.all(color: pt.line), + boxShadow: pt.shadowE1, + ), + child: IntrinsicHeight( child: Row( + crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - Container( - width: 46, - height: 46, - decoration: BoxDecoration( - color: AppColors.mint.withAlpha(40), - borderRadius: BorderRadius.circular(PetfolioThemeExtension.radiusMd), - ), - child: const Icon(Icons.folder_special_outlined, - color: AppColors.mint700, size: 24), + _UtilityHalf( + key: const ValueKey('care_nutrition_banner'), + icon: Icons.monitor_weight_outlined, + iconBg: AppColors.sunnySoft, + iconColor: AppColors.sunny700, + title: 'Nutrition', + subtitle: 'Weight & caloric needs', + detail: 'Track daily feeding', + onTap: () => context.push('/care/nutrition'), ), - const SizedBox(width: 14), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'Medical Vault', - style: TextStyle( - fontSize: 15, - fontWeight: FontWeight.w700, - color: AppColors.mint700, - ), - ), - const SizedBox(height: 2), - Text( - 'Vaccines · Medications · Vet visits', - style: TextStyle(fontSize: 13, color: pt.ink500), - ), - ], - ), + VerticalDivider(width: 1, thickness: 1, color: pt.line), + _UtilityHalf( + key: const ValueKey('care_medical_vault_banner'), + icon: Icons.folder_special_outlined, + iconBg: AppColors.mintSoft, + iconColor: AppColors.mint700, + title: 'Medical Vault', + subtitle: 'Vaccines · Meds · Vet', + detail: 'View health records', + onTap: () => context.push('/care/medical-vault'), ), - const Icon(Icons.chevron_right_rounded, color: AppColors.mint700), ], ), ), @@ -1614,66 +1694,85 @@ class _MedicalVaultBanner extends StatelessWidget { } } -class _NutritionBanner extends StatelessWidget { - const _NutritionBanner({required this.pt}); +class _UtilityHalf extends StatelessWidget { + const _UtilityHalf({ + super.key, + required this.icon, + required this.iconBg, + required this.iconColor, + required this.title, + required this.subtitle, + required this.detail, + required this.onTap, + }); - final PetfolioThemeExtension pt; + final IconData icon; + final Color iconBg; + final Color iconColor; + final String title; + final String subtitle; + final String detail; + final VoidCallback onTap; @override Widget build(BuildContext context) { - return GestureDetector( - key: const ValueKey('care_nutrition_banner'), - onTap: () => context.push('/care/nutrition'), - child: Container( - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, - colors: [ - AppColors.sunnySoft, - Color.lerp(AppColors.sunnySoft, AppColors.tangerine.withAlpha(40), 0.5)!, - ], - ), - borderRadius: BorderRadius.circular(PetfolioThemeExtension.radiusLg), - border: Border.all(color: AppColors.tangerine.withAlpha(60)), - boxShadow: pt.shadowE1, - ), - padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16), - child: Row( - children: [ - Container( - width: 46, - height: 46, - decoration: BoxDecoration( - color: AppColors.tangerine.withAlpha(40), - borderRadius: BorderRadius.circular(PetfolioThemeExtension.radiusMd), - ), - child: const Icon(Icons.monitor_weight_outlined, - color: AppColors.tangerine, size: 24), - ), - const SizedBox(width: 14), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + final pt = Theme.of(context).extension()!; + return Expanded( + child: GestureDetector( + onTap: onTap, + child: Padding( + padding: const EdgeInsets.all(13), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - const Text( - 'Smart Nutrition & Weight', - style: TextStyle( - fontSize: 15, - fontWeight: FontWeight.w700, - color: AppColors.tangerine, + Container( + width: 36, + height: 36, + decoration: BoxDecoration( + color: iconBg, + borderRadius: BorderRadius.circular(12), ), + alignment: Alignment.center, + child: Icon(icon, size: 20, color: iconColor), ), - const SizedBox(height: 2), - Text( - 'Track weight history · View caloric needs', - style: TextStyle(fontSize: 13, color: pt.ink500), - ), + Icon(Icons.chevron_right_rounded, size: 15, color: pt.ink300), ], ), - ), - const Icon(Icons.chevron_right_rounded, color: AppColors.tangerine), - ], + const SizedBox(height: 8), + Text( + title, + style: TextStyle( + fontSize: 13, + fontWeight: FontWeight.w800, + color: pt.ink950, + height: 1.15, + ), + ), + const SizedBox(height: 3), + Text( + subtitle, + style: TextStyle( + fontSize: 11, + fontWeight: FontWeight.w700, + color: iconColor, + height: 1, + ), + ), + const SizedBox(height: 1), + Text( + detail, + style: TextStyle( + fontSize: 10.5, + fontWeight: FontWeight.w600, + color: pt.ink500, + height: 1, + ), + ), + ], + ), ), ), ); diff --git a/lib/features/care/presentation/widgets/gamified_care_ui.dart b/lib/features/care/presentation/widgets/gamified_care_ui.dart index 317d828..59baf71 100644 --- a/lib/features/care/presentation/widgets/gamified_care_ui.dart +++ b/lib/features/care/presentation/widgets/gamified_care_ui.dart @@ -1,3 +1,5 @@ +import 'dart:math' as math; + import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -5,12 +7,13 @@ import 'package:petfolio/core/theme/theme.dart'; import 'package:petfolio/core/widgets/widgets.dart'; import '../../../../core/models/pet.dart'; +import '../../data/models/care_task_log.dart'; import '../../data/models/pet_awards_summary.dart'; import '../../data/models/pet_level.dart'; import '../controllers/care_dashboard_controller.dart'; import '../controllers/pet_awards_provider.dart'; -// ── Gamified Care Header ────────────────────────────────────────────────────── +// ── Compact Hero Header ──────────────────────────────────────────────────────── class CareGamifiedHeader extends ConsumerStatefulWidget { const CareGamifiedHeader({ @@ -28,307 +31,513 @@ class CareGamifiedHeader extends ConsumerStatefulWidget { class _CareGamifiedHeaderState extends ConsumerState with TickerProviderStateMixin { - late final AnimationController _bounceCtrl; + late final AnimationController _coinCtrl; late final AnimationController _pulseCtrl; - late final Animation _bounceAnim; - late final Animation _pulseScale; - late final Animation _pulseOpacity; @override void initState() { super.initState(); - _bounceCtrl = AnimationController( + _coinCtrl = AnimationController( vsync: this, - duration: const Duration(milliseconds: 2400), - )..repeat(reverse: true); - _bounceAnim = Tween(begin: 0.0, end: -8.0).animate( - CurvedAnimation(parent: _bounceCtrl, curve: Curves.easeInOut), - ); - + duration: const Duration(milliseconds: 4500), + )..repeat(); _pulseCtrl = AnimationController( vsync: this, - duration: const Duration(milliseconds: 2000), + duration: const Duration(milliseconds: 2200), )..repeat(); - _pulseScale = Tween(begin: 1.0, end: 1.40).animate( - CurvedAnimation(parent: _pulseCtrl, curve: Curves.easeOut), - ); - _pulseOpacity = Tween(begin: 0.75, end: 0.0).animate( - CurvedAnimation(parent: _pulseCtrl, curve: Curves.easeOut), - ); } @override void dispose() { - _bounceCtrl.dispose(); + _coinCtrl.dispose(); _pulseCtrl.dispose(); super.dispose(); } @override Widget build(BuildContext context) { - final petId = widget.activePet.id; + final topPad = MediaQuery.paddingOf(context).top; - // Real streak from realtime stream already in dashboard state. final streak = widget.dashboard.streak.maybeWhen( data: (s) => s.currentStreak, orElse: () => 0, ); - - // Real XP + level from Supabase RPC (same provider used by profile screen). - final awardsAsync = ref.watch(petAwardsSummaryProvider(petId)); - final totalXp = awardsAsync.maybeWhen( - data: (a) => a.totalXp, - orElse: () => 0, + final awardsAsync = ref.watch(petAwardsSummaryProvider(widget.activePet.id)); + final lv = awardsAsync.maybeWhen( + data: (a) => PetLevel.fromXp(a.totalXp), + orElse: () => PetLevel.fromXp(0), ); - final lv = PetLevel.fromXp(totalXp); - final sp = widget.activePet.speciesEnum; - final isDark = Theme.of(context).brightness == Brightness.dark; + final tasks = widget.dashboard.tasks.value ?? []; + final planned = tasks.where((t) => !t.isLogDerived).toList(); + final doneToday = planned.where((t) => t.isCompleted).length; + final totalToday = planned.length; + final pct = lv.progress.clamp(0.0, 1.0); - Color headerColor = sp.resolvedAccent(isDark); - final dbAccent = widget.activePet.accentColor; - if (dbAccent != null && dbAccent.isNotEmpty && dbAccent != '#FF6B9D') { - try { - final hex = dbAccent.replaceAll('#', ''); - if (hex.length == 6) { - headerColor = Color(int.parse('FF$hex', radix: 16)); - } else if (hex.length == 8) { - headerColor = Color(int.parse(hex, radix: 16)); - } - } catch (_) {} - } + // ── WaveHeader pattern (matches Home/Pets screen architecture) ────────── + // AppShellHeader overlays at Positioned(top:0) with height = topPad + 76. + // We reserve that space at top, then show greeting, then let the hero + // card float at the wave boundary — exactly how PetProfileScreen works. + return Stack( + clipBehavior: Clip.none, + children: [ + WaveHeader( + color: AppColors.tangerine, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // ── Clear AppShellHeader ─────────────────────────────────── + SizedBox(height: topPad + 76), - return WaveHeader( - color: headerColor, - child: Column( - children: [ - SizedBox(height: MediaQuery.paddingOf(context).top + 76.0), - Padding( - padding: const EdgeInsets.fromLTRB(16, 12, 16, 0), - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, + // ── Care greeting — unique copy, never duplicates hero card ── + Padding( + padding: const EdgeInsets.fromLTRB(22, 10, 22, 0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + '${widget.activePet.name}\'s care plan', + style: TextStyle( + fontSize: 13, + fontWeight: FontWeight.w600, + color: Colors.white.withAlpha(210), + letterSpacing: 0.1, + ), + ), + const SizedBox(height: 5), + Text.rich( + TextSpan( + text: streak > 1 + ? '$streak days strong!' + : 'Let\'s crush today!', + children: const [ + TextSpan(text: ' 🔥'), + ], + ), + style: Theme.of(context).textTheme.headlineMedium?.copyWith( + fontWeight: FontWeight.w800, + color: Colors.white, + height: 1.05, + letterSpacing: -0.3, + fontStyle: FontStyle.italic, + ), + ), + ], + ), + ), + + // ── Breathing room: greeting height (~44px) + 33px gap + card top + // card_top = waveHeight + 28 - 115 must be > greetingEnd + // waveHeight = topPad + 76 + 44(greeting) + SizedBox + // SizedBox = 120 → gap ≈ 33px on all device topPad values + const SizedBox(height: 120), + ], + ), + ), + + // ── Floating hero card (streak coin + XP bar) ───────────────────── + // Positioned at bottom:-28 so it straddles the wave edge, matching + // the same floating-card pattern used in PetProfileScreen. + Positioned( + left: 16, + right: 16, + bottom: -28, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(24), + gradient: const LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ + Color(0xFFFF2E2E), + Color(0xFFFF5830), + AppColors.tangerine, + ], + stops: [0.0, 0.48, 1.0], + ), + boxShadow: const [ + BoxShadow( + color: Color(0x60FF3D3D), + blurRadius: 32, + offset: Offset(0, 16), + spreadRadius: -12, + ), + BoxShadow( + color: Color(0x20000000), + blurRadius: 8, + offset: Offset(0, 4), + spreadRadius: -2, + ), + ], + ), + clipBehavior: Clip.hardEdge, + child: Stack( children: [ - // ── Streak flame circle ───────────────────────────────────── - SizedBox( - width: 120, - height: 120, - child: Stack( - alignment: Alignment.center, + // Decorative paw watermark + Positioned( + right: -6, + top: -8, + child: Opacity( + opacity: 0.16, + child: Transform.rotate( + angle: 18 * math.pi / 180, + child: const Icon(Icons.pets_rounded, size: 96, color: Colors.white), + ), + ), + ), + Padding( + padding: const EdgeInsets.fromLTRB(16, 15, 16, 16), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, children: [ - AnimatedBuilder( - animation: _pulseCtrl, - builder: (_, child) => Transform.scale( - scale: _pulseScale.value, - child: Opacity(opacity: _pulseOpacity.value, child: child), - ), - child: Container( - width: 112, - height: 112, - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all(color: AppColors.tangerine, width: 3), - ), - ), + _StreakCoin( + streak: streak, + coinCtrl: _coinCtrl, + pulseCtrl: _pulseCtrl, ), - AnimatedBuilder( - animation: _bounceCtrl, - builder: (_, child) => Transform.translate( - offset: Offset(0, _bounceAnim.value), - child: child, - ), - child: Container( - width: 104, - height: 104, - decoration: const BoxDecoration( - shape: BoxShape.circle, - gradient: RadialGradient( - center: Alignment(0, 0.2), - radius: 0.7, - colors: [AppColors.sunny, AppColors.tangerine], - stops: [0.0, 0.7], - ), - boxShadow: [ - BoxShadow( - color: AppColors.tangerine, - blurRadius: 28, - offset: Offset(0, 14), - spreadRadius: -8, - ), - ], + const SizedBox(width: 14), + Expanded( + child: awardsAsync.when( + loading: () => _HeroLevelContent( + lv: PetLevel.fromXp(0), + pct: 0, + doneToday: 0, + totalToday: totalToday, ), - alignment: Alignment.center, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - const Text('🔥', style: TextStyle(fontSize: 36, height: 1.0)), - const SizedBox(height: 2), - Text( - '$streak', - style: const TextStyle( - fontSize: 28, - fontWeight: FontWeight.w900, - color: Colors.white, - height: 1.0, - ), - ), - const Text( - 'DAY STREAK', - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.w800, - color: Colors.white, - letterSpacing: 0.6, - ), - ), - ], + error: (_, _) => _HeroLevelContent( + lv: PetLevel.fromXp(0), + pct: 0, + doneToday: doneToday, + totalToday: totalToday, + ), + data: (_) => _HeroLevelContent( + lv: lv, + pct: pct, + doneToday: doneToday, + totalToday: totalToday, ), ), ), ], ), ), + ], + ), + ), + ), + ], + ); + } +} + +// ── Streak Coin ──────────────────────────────────────────────────────────────── + +class _StreakCoin extends StatelessWidget { + const _StreakCoin({ + required this.streak, + required this.coinCtrl, + required this.pulseCtrl, + }); - const SizedBox(width: 16), + final int streak; + final Animation coinCtrl; + final Animation pulseCtrl; - // ── XP & level (real data) ─────────────────────────────────── - Expanded( - child: awardsAsync.when( - loading: () => _LevelSkeleton(), - error: (e, st) => _LevelContent(lv: PetLevel.fromXp(0)), - data: (_) => _LevelContent(lv: lv), + @override + Widget build(BuildContext context) { + return SizedBox( + width: 84, + height: 84, + child: Stack( + alignment: Alignment.center, + children: [ + // Expanding pulse ring + AnimatedBuilder( + animation: pulseCtrl, + builder: (_, _) { + final scale = 1.0 + pulseCtrl.value * 0.90; + final opacity = ((1.0 - pulseCtrl.value) * 0.50).clamp(0.0, 0.50); + return Transform.scale( + scale: scale, + child: Opacity( + opacity: opacity, + child: Container( + width: 84, + height: 84, + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + color: Colors.white.withAlpha(160), + width: 2, + ), + ), ), ), - ], + ); + }, + ), + // 3D Y-rotation coin + AnimatedBuilder( + animation: coinCtrl, + builder: (_, child) { + final angle = math.sin(coinCtrl.value * 2 * math.pi) * 20 * math.pi / 180; + return Transform( + alignment: Alignment.center, + transform: Matrix4.identity() + ..setEntry(3, 2, 0.0018) + ..rotateY(angle), + child: child, + ); + }, + child: Container( + width: 84, + height: 84, + decoration: BoxDecoration( + shape: BoxShape.circle, + gradient: const RadialGradient( + center: Alignment(-0.28, -0.42), + radius: 0.88, + colors: [ + Color(0xFFFFF0B0), + Color(0xFFFFD234), + AppColors.tangerine, + AppColors.tangerine700, + ], + stops: [0.0, 0.32, 0.68, 1.0], + ), + boxShadow: [ + BoxShadow( + color: AppColors.tangerine700.withAlpha(210), + blurRadius: 24, + offset: const Offset(0, 14), + spreadRadius: -10, + ), + BoxShadow( + color: Colors.black.withAlpha(30), + blurRadius: 6, + offset: const Offset(0, 3), + spreadRadius: -2, + ), + ], + ), + child: Stack( + alignment: Alignment.center, + children: [ + // Specular sheen highlight + Positioned( + left: 5, + top: 5, + right: 26, + bottom: 10, + child: Container( + decoration: BoxDecoration( + shape: BoxShape.circle, + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ + Colors.white.withAlpha(120), + Colors.transparent, + ], + ), + ), + ), + ), + // Concentric inner ring for depth + Container( + width: 70, + height: 70, + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + color: Colors.white.withAlpha(60), + width: 1.5, + ), + ), + ), + Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text('🔥', style: TextStyle(fontSize: 22, height: 1.0)), + const SizedBox(height: 1), + Text( + '$streak', + style: const TextStyle( + fontSize: 22, + fontWeight: FontWeight.w900, + color: Colors.white, + height: 1.0, + shadows: [ + Shadow( + color: Color(0x80961400), + blurRadius: 6, + offset: Offset(0, 2), + ), + ], + ), + ), + const Text( + 'DAY STREAK', + style: TextStyle( + fontSize: 6.5, + fontWeight: FontWeight.w900, + color: Colors.white, + letterSpacing: 0.4, + height: 1.3, + ), + ), + ], + ), + ], + ), ), ), - const SizedBox(height: 55.0), ], ), ); } } -class _LevelContent extends StatelessWidget { - const _LevelContent({required this.lv}); +// ── Hero Level Content (right side of hero card) ─────────────────────────────── + +class _HeroLevelContent extends StatelessWidget { + const _HeroLevelContent({ + required this.lv, + required this.pct, + required this.doneToday, + required this.totalToday, + }); + final PetLevel lv; + final double pct; + final int doneToday; + final int totalToday; @override Widget build(BuildContext context) { + final allDone = totalToday > 0 && doneToday == totalToday; return Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ Row( - crossAxisAlignment: CrossAxisAlignment.baseline, - textBaseline: TextBaseline.alphabetic, + crossAxisAlignment: CrossAxisAlignment.center, children: [ - Text( - 'Lv ${lv.level}', - style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.w900, - color: Colors.white, - height: 1.0, + Expanded( + child: Row( + crossAxisAlignment: CrossAxisAlignment.baseline, + textBaseline: TextBaseline.alphabetic, + children: [ + Text( + 'Lv ${lv.level}', + style: Theme.of(context).textTheme.headlineMedium!.copyWith( + fontWeight: FontWeight.w900, + color: Colors.white, + height: 1.0, + fontSize: 26, + ), + ), + const SizedBox(width: 7), + Flexible( + child: Text( + '· ${lv.title}', + style: Theme.of(context).textTheme.labelLarge!.copyWith( + fontWeight: FontWeight.w700, + color: Colors.white.withAlpha(220), + fontSize: 13, + ), + overflow: TextOverflow.ellipsis, + ), + ), + ], ), ), const SizedBox(width: 8), - Text( - lv.title, - style: TextStyle( - fontSize: 13, - fontWeight: FontWeight.w800, - color: Colors.white.withAlpha(200), + // Show chip only when there are tasks and progress has started + if (totalToday > 0) + AnimatedSwitcher( + duration: const Duration(milliseconds: 300), + child: Container( + key: ValueKey('$doneToday/$totalToday'), + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), + decoration: BoxDecoration( + color: allDone + ? AppColors.mint.withAlpha(220) + : Colors.white.withAlpha(230), + borderRadius: BorderRadius.circular(999), + ), + child: Text( + allDone ? 'All done! 🎉' : '$doneToday/$totalToday tasks', + style: TextStyle( + fontSize: 10.5, + fontWeight: FontWeight.w900, + color: allDone ? Colors.white : AppColors.poppy700, + height: 1, + ), + ), + ), ), - ), ], ), - const SizedBox(height: 4), - Text( - '${lv.currentXp} / ${lv.levelEndXp} XP', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w700, - color: Colors.white.withAlpha(200), - ), - ), - const SizedBox(height: 8), + const SizedBox(height: 10), + // XP progress bar with top-shine shimmer Container( - height: 16, - width: double.infinity, + height: 13, decoration: BoxDecoration( borderRadius: BorderRadius.circular(999), - color: Colors.white.withAlpha(56), - border: Border.all(color: Colors.white.withAlpha(80), width: 1.5), - ), - child: FractionallySizedBox( - alignment: Alignment.centerLeft, - widthFactor: lv.progress, - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(999), - gradient: const LinearGradient( - colors: [AppColors.sunny, AppColors.tangerine, AppColors.poppy], - ), - boxShadow: const [ - BoxShadow( - color: AppColors.tangerine, - blurRadius: 8, - spreadRadius: -2, - ), - ], - ), - ), + color: Colors.black.withAlpha(45), ), - ), - const SizedBox(height: 8), - if (!lv.isMaxLevel) - Text.rich( - TextSpan( - text: '${lv.xpToNext} XP to ', - style: TextStyle( - fontSize: 11, - color: Colors.white.withAlpha(200), - fontWeight: FontWeight.w700, - ), + child: ClipRRect( + borderRadius: BorderRadius.circular(999), + child: Stack( children: [ - TextSpan( - text: 'Lv ${lv.level + 1} · ${lv.nextTitle}', - style: const TextStyle( - fontWeight: FontWeight.w900, - color: Colors.white, + AnimatedFractionallySizedBox( + duration: const Duration(milliseconds: 600), + curve: Curves.easeOutCubic, + widthFactor: pct.clamp(0.0, 1.0), + child: Container( + decoration: const BoxDecoration( + gradient: LinearGradient( + colors: [ + Color(0xFFFFE08A), + AppColors.sunny, + AppColors.tangerine, + ], + stops: [0.0, 0.55, 1.0], + ), + ), + ), + ), + // Top shine overlay + Positioned.fill( + child: Container( + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Color(0x99FFFFFF), Colors.transparent], + stops: [0.0, 0.55], + ), + ), ), ), ], ), - ) - else - Text( - 'Max level reached!', - style: TextStyle( - fontSize: 11, - color: Colors.white.withAlpha(200), - fontWeight: FontWeight.w900, - ), ), - ], - ); - } -} - -class _LevelSkeleton extends StatelessWidget { - @override - Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: const [ - SkeletonLoader(width: 100, height: 22, borderRadius: 8), - SizedBox(height: 8), - SkeletonLoader(width: 80, height: 12, borderRadius: 6), - SizedBox(height: 8), - SkeletonLoader(width: double.infinity, height: 12, borderRadius: 999), - SizedBox(height: 8), - SkeletonLoader(width: 130, height: 11, borderRadius: 6), + ), + const SizedBox(height: 7), + Text( + lv.isMaxLevel + ? '${lv.currentXp} XP — Max level! 👑' + : '${lv.currentXp} / ${lv.levelEndXp} XP · ${lv.xpToNext} XP to Lv ${lv.level + 1}', + style: const TextStyle( + fontSize: 10.5, + fontWeight: FontWeight.w700, + color: Color(0xDDFFFFFF), + letterSpacing: 0.1, + ), + overflow: TextOverflow.ellipsis, + ), ], ); } @@ -363,19 +572,22 @@ class CareGamifiedWeeklyChart extends StatelessWidget { final anchor = DateUtils.dateOnly(selectedDay); final weekStart = anchor.subtract(const Duration(days: 6)); - // Count completed days in this 7-day window up to and including today. int hitsCount = 0; for (int i = 0; i < 7; i++) { final dayDate = weekStart.add(Duration(days: i)); if (dayDate.isAfter(today)) break; if (i < weekHits.length && weekHits[i]) hitsCount++; } - // Count today as a hit if all tasks done and DB hasn't recorded it yet. if (anchor == today && progressPercent >= 1.0) { final todaySlot = today.difference(weekStart).inDays; - if (todaySlot >= 0 && todaySlot < weekHits.length && !weekHits[todaySlot]) hitsCount++; + if (todaySlot >= 0 && + todaySlot < weekHits.length && + !weekHits[todaySlot]) { + hitsCount++; + } } - final totalDaysSoFar = (today.difference(weekStart).inDays + 1).clamp(1, 7); + final totalDaysSoFar = + (today.difference(weekStart).inDays + 1).clamp(1, 7); return Container( decoration: BoxDecoration( @@ -387,7 +599,6 @@ class CareGamifiedWeeklyChart extends StatelessWidget { child: Column( mainAxisSize: MainAxisSize.min, children: [ - // Week summary header Row( children: [ Text( @@ -401,7 +612,8 @@ class CareGamifiedWeeklyChart extends StatelessWidget { const Spacer(), if (hitsCount > 0) Container( - padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3), + padding: + const EdgeInsets.symmetric(horizontal: 8, vertical: 3), decoration: BoxDecoration( color: AppColors.mintSoft, borderRadius: BorderRadius.circular(999), @@ -429,10 +641,10 @@ class CareGamifiedWeeklyChart extends StatelessWidget { final hit = i < weekHits.length ? weekHits[i] : false; final h = isFuture - ? 0.10 + ? 0.08 : isToday - ? progressPercent.clamp(0.15, 1.0) - : (hit ? 0.85 : 0.30); + ? progressPercent.clamp(0.06, 1.0) + : (hit ? 0.88 : 0.22); final color = isFuture ? pt.line @@ -442,13 +654,13 @@ class CareGamifiedWeeklyChart extends StatelessWidget { child: Column( mainAxisAlignment: MainAxisAlignment.end, children: [ - // 🐾 paw or empty above bar SizedBox( height: 18, child: isToday ? const Align( alignment: Alignment.bottomCenter, - child: Text('🐾', style: TextStyle(fontSize: 13)), + child: + Text('🐾', style: TextStyle(fontSize: 13)), ) : null, ), @@ -458,27 +670,28 @@ class CareGamifiedWeeklyChart extends StatelessWidget { child: FractionallySizedBox( heightFactor: h, child: Container( - margin: const EdgeInsets.symmetric(horizontal: 4), + margin: + const EdgeInsets.symmetric(horizontal: 4), decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10), - border: isToday && !isFuture + borderRadius: BorderRadius.circular(12), + border: (!hit && !isFuture && !isToday) ? Border.all( - color: _colors[i].withAlpha(180), - width: 2, + color: pt.line, + width: 1, + strokeAlign: BorderSide.strokeAlignInside, ) - : (!hit && !isFuture && !isToday + : (isToday && !isFuture && progressPercent < 0.06) ? Border.all( - color: pt.line, - width: 1, - strokeAlign: BorderSide.strokeAlignInside, + color: _colors[i].withAlpha(160), + width: 1.5, ) - : null), - boxShadow: (isToday && !isFuture) + : null, + boxShadow: (isToday && !isFuture && progressPercent >= 0.06) ? [ BoxShadow( - color: color.withAlpha(120), - blurRadius: 16, - offset: const Offset(0, 6), + color: color.withAlpha(100), + blurRadius: 14, + offset: const Offset(0, 5), spreadRadius: -4, ), ] @@ -489,8 +702,8 @@ class CareGamifiedWeeklyChart extends StatelessWidget { begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ + Color.lerp(color, Colors.white, 0.28)!, color, - Color.lerp(color, Colors.white, 0.45)!, ], ), color: isFuture @@ -502,7 +715,6 @@ class CareGamifiedWeeklyChart extends StatelessWidget { ), ), const SizedBox(height: 4), - // Day letter Text( _dayLetters[dayDate.weekday - 1], style: TextStyle( @@ -513,7 +725,6 @@ class CareGamifiedWeeklyChart extends StatelessWidget { : (isFuture ? pt.ink300 : pt.ink500), ), ), - // Day number Text( '${dayDate.day}', style: TextStyle( @@ -575,27 +786,22 @@ class CareGamifiedTrophyRoom extends ConsumerWidget { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - // N/6 earned sub-label Padding( padding: const EdgeInsets.only(bottom: 12), - child: Row( - children: [ - Container( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), - decoration: BoxDecoration( - color: ownedCount > 0 ? AppColors.mintSoft : pt.surface2, - borderRadius: BorderRadius.circular(999), - ), - child: Text( - '$ownedCount / ${kBadgeCatalog.length} earned', - style: TextStyle( - fontSize: 11, - fontWeight: FontWeight.w800, - color: ownedCount > 0 ? AppColors.mint700 : pt.ink300, - ), - ), + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), + decoration: BoxDecoration( + color: ownedCount > 0 ? AppColors.mintSoft : pt.surface2, + borderRadius: BorderRadius.circular(999), + ), + child: Text( + '$ownedCount / ${kBadgeCatalog.length} earned', + style: TextStyle( + fontSize: 11, + fontWeight: FontWeight.w800, + color: ownedCount > 0 ? AppColors.mint700 : pt.ink300, ), - ], + ), ), ), GridView.builder( @@ -604,21 +810,21 @@ class CareGamifiedTrophyRoom extends ConsumerWidget { padding: EdgeInsets.zero, gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, - mainAxisSpacing: 12, - crossAxisSpacing: 12, - childAspectRatio: 0.82, + mainAxisSpacing: 8, + crossAxisSpacing: 8, + childAspectRatio: 0.78, ), itemCount: kBadgeCatalog.length, itemBuilder: (context, i) { final badge = kBadgeCatalog[i]; final owned = ownedTypes.contains(badge.type); final hint = owned ? '' : _progressHint(badge, awards); - return _BadgeTile( + return _BadgeMedal( badge: badge, owned: owned, progressHint: hint, index: i, - onTap: () => _showBadgeDetail(context, badge, owned, hint), + onTap: () => _showBadgeDetail(context, pt, badge, owned, hint), ); }, ), @@ -628,11 +834,11 @@ class CareGamifiedTrophyRoom extends ConsumerWidget { void _showBadgeDetail( BuildContext context, + PetfolioThemeExtension pt, BadgeInfo badge, bool owned, String hint, ) { - final pt = Theme.of(context).extension()!; showModalBottomSheet( context: context, useRootNavigator: true, @@ -640,10 +846,10 @@ class CareGamifiedTrophyRoom extends ConsumerWidget { builder: (_) => Container( decoration: BoxDecoration( color: pt.surface1, - borderRadius: const BorderRadius.vertical(top: Radius.circular(24)), + borderRadius: const BorderRadius.vertical(top: Radius.circular(28)), ), padding: EdgeInsets.fromLTRB( - 24, 0, 24, MediaQuery.paddingOf(context).bottom + 28), + 24, 0, 24, MediaQuery.paddingOf(context).bottom + 34), child: Column( mainAxisSize: MainAxisSize.min, children: [ @@ -651,7 +857,7 @@ class CareGamifiedTrophyRoom extends ConsumerWidget { child: Padding( padding: const EdgeInsets.symmetric(vertical: 12), child: Container( - width: 36, + width: 38, height: 4, decoration: BoxDecoration( color: pt.line, @@ -660,22 +866,26 @@ class CareGamifiedTrophyRoom extends ConsumerWidget { ), ), ), + // Medal in sheet Container( - width: 80, - height: 80, + width: 84, + height: 84, decoration: BoxDecoration( - borderRadius: BorderRadius.circular(24), + shape: BoxShape.circle, gradient: owned - ? LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, + ? RadialGradient( + center: const Alignment(-0.24, -0.4), + radius: 0.85, colors: [ + Color.lerp(badge.color, Colors.white, 0.55)!, badge.color, - Color.lerp(badge.color, Colors.white, 0.3)!, + Color.lerp(badge.color, Colors.black, 0.4)!, ], + stops: const [0.0, 0.58, 1.0], ) : null, color: owned ? null : pt.surface2, + border: owned ? null : Border.all(color: pt.line), boxShadow: owned ? [ BoxShadow( @@ -688,13 +898,19 @@ class CareGamifiedTrophyRoom extends ConsumerWidget { : null, ), alignment: Alignment.center, - child: Text( - badge.emoji, - style: TextStyle( - fontSize: 40, - color: owned ? null : Colors.grey, - ), - ), + child: owned + ? Text(badge.emoji, style: const TextStyle(fontSize: 40)) + : Opacity( + opacity: 0.4, + child: ColorFiltered( + colorFilter: const ColorFilter.mode( + Colors.grey, + BlendMode.saturation, + ), + child: + Text(badge.emoji, style: const TextStyle(fontSize: 40)), + ), + ), ), const SizedBox(height: 16), Text( @@ -708,45 +924,30 @@ class CareGamifiedTrophyRoom extends ConsumerWidget { const SizedBox(height: 6), Text( badge.description, - style: TextStyle(fontSize: 14, color: pt.ink500), + style: TextStyle( + fontSize: 14, + color: pt.ink500, + ), + textAlign: TextAlign.center, ), - if (!owned && hint.isNotEmpty) ...[ - const SizedBox(height: 12), - Container( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - decoration: BoxDecoration( - color: pt.surface2, - borderRadius: BorderRadius.circular(12), - ), - child: Text( - 'Progress: $hint', - style: TextStyle( - fontSize: 13, - fontWeight: FontWeight.w700, - color: pt.ink500, - ), - ), + const SizedBox(height: 12), + Container( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + decoration: BoxDecoration( + color: owned ? AppColors.mintSoft : pt.surface2, + borderRadius: BorderRadius.circular(12), ), - ], - if (owned) ...[ - const SizedBox(height: 12), - Container( - padding: - const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - decoration: BoxDecoration( - color: AppColors.mintSoft, - borderRadius: BorderRadius.circular(12), - ), - child: const Text( - '✅ Earned!', - style: TextStyle( - fontSize: 13, - fontWeight: FontWeight.w800, - color: AppColors.mint700, - ), + child: Text( + owned + ? '✅ Earned!' + : (hint.isNotEmpty ? 'Progress: $hint' : 'Keep logging care'), + style: TextStyle( + fontSize: 13, + fontWeight: FontWeight.w800, + color: owned ? AppColors.mint700 : pt.ink500, ), ), - ], + ), ], ), ), @@ -754,9 +955,10 @@ class CareGamifiedTrophyRoom extends ConsumerWidget { } } -// Individual badge tile with lock overlay and progress hint -class _BadgeTile extends StatelessWidget { - const _BadgeTile({ +// ── Badge Medal (circular 3D medal style) ───────────────────────────────────── + +class _BadgeMedal extends StatefulWidget { + const _BadgeMedal({ required this.badge, required this.owned, required this.progressHint, @@ -770,84 +972,239 @@ class _BadgeTile extends StatelessWidget { final int index; final VoidCallback onTap; + @override + State<_BadgeMedal> createState() => _BadgeMedalState(); +} + +class _BadgeMedalState extends State<_BadgeMedal> with TickerProviderStateMixin { + late final AnimationController _floatCtrl; + late final AnimationController _sheenCtrl; + + @override + void initState() { + super.initState(); + final delayMs = widget.index * 300; + _floatCtrl = AnimationController( + vsync: this, + duration: Duration(milliseconds: 3200 + widget.index * 200), + )..repeat(reverse: true); + _sheenCtrl = AnimationController( + vsync: this, + duration: Duration(milliseconds: 3800 + widget.index * 200), + )..forward(from: (delayMs / (3800 + widget.index * 200)).clamp(0.0, 1.0)); + + _sheenCtrl.addStatusListener((s) { + if (s == AnimationStatus.completed && mounted) _sheenCtrl.repeat(); + }); + } + + @override + void dispose() { + _floatCtrl.dispose(); + _sheenCtrl.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { final pt = Theme.of(context).extension()!; final isDark = Theme.of(context).brightness == Brightness.dark; + final owned = widget.owned; + final badge = widget.badge; final labelColor = isDark ? AppColors.ink950D : AppColors.ink950; - final angle = (index % 2 != 0 ? -2.5 : 2.5) * 3.14159 / 180; return GestureDetector( - onTap: onTap, + onTap: widget.onTap, child: Column( mainAxisSize: MainAxisSize.min, children: [ - Expanded( - child: Transform.rotate( - angle: angle, + // Float bob animation wrapper + AnimatedBuilder( + animation: _floatCtrl, + builder: (_, child) => Transform.translate( + offset: Offset(0, _floatCtrl.value * -5), + child: child, + ), + child: SizedBox( + width: 82, + height: 82, child: Stack( + alignment: Alignment.center, children: [ - // Badge box + // Outer glow ring derived from _floatCtrl (no separate controller) + if (owned) + AnimatedBuilder( + animation: _floatCtrl, + builder: (_, _) { + final t = math.sin(_floatCtrl.value * math.pi); + return Transform.scale( + scale: 0.92 + t * 0.14, + child: Opacity( + opacity: (0.50 + t * 0.38).clamp(0.0, 1.0), + child: Container( + width: 82, + height: 82, + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + color: badge.color, + width: 2, + ), + ), + ), + ), + ); + }, + ), + + // Medal disc Container( - width: double.infinity, - height: double.infinity, + width: 72, + height: 72, decoration: BoxDecoration( - borderRadius: BorderRadius.circular(22), - color: owned ? null : pt.surface2, + shape: BoxShape.circle, gradient: owned - ? LinearGradient( - begin: Alignment.topLeft, - end: Alignment.bottomRight, + ? RadialGradient( + center: const Alignment(-0.24, -0.4), + radius: 0.85, colors: [ + Color.lerp(badge.color, Colors.white, 0.55)!, badge.color, - Color.lerp(badge.color, Colors.white, 0.3)!, + Color.lerp(badge.color, Colors.black, 0.4)!, ], + stops: const [0.0, 0.58, 1.0], ) - : null, - border: owned - ? null - : Border.all(color: pt.line, width: 1), + : RadialGradient( + center: const Alignment(-0.24, -0.4), + radius: 0.85, + colors: [ + pt.ink300.withAlpha(160), + pt.ink300, + ], + ), boxShadow: owned ? [ BoxShadow( - color: badge.color.withAlpha(130), - blurRadius: 16, - offset: const Offset(0, 6), + color: Colors.black.withAlpha(77), + blurRadius: 0, + offset: const Offset(0, 5), + ), + BoxShadow( + color: badge.color.withAlpha(120), + blurRadius: 14, + offset: const Offset(0, 8), spreadRadius: -8, ), ] - : null, + : [ + BoxShadow( + color: Colors.black.withAlpha(46), + blurRadius: 0, + offset: const Offset(0, 4), + ), + ], ), - alignment: Alignment.center, - child: owned - ? Text( - badge.emoji, - style: const TextStyle(fontSize: 32), - ) - : Opacity( - opacity: 0.35, - child: ColorFiltered( - colorFilter: const ColorFilter.mode( - Colors.grey, - BlendMode.saturation, + child: ClipOval( + child: Stack( + alignment: Alignment.center, + children: [ + // Concentric depth rings + Positioned.fill( + child: Container( + margin: const EdgeInsets.all(6), + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + color: owned + ? Colors.white.withAlpha(77) + : Colors.black.withAlpha(15), + width: 1.5, + ), ), - child: Text( - badge.emoji, - style: const TextStyle(fontSize: 32), + ), + ), + Positioned.fill( + child: Container( + margin: const EdgeInsets.all(11), + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + color: owned + ? Colors.white.withAlpha(46) + : Colors.black.withAlpha(8), + width: 1, + ), ), ), ), + // Badge emoji + owned + ? Text( + badge.emoji, + style: const TextStyle( + fontSize: 28, + shadows: [ + Shadow( + color: Color(0x47000000), + blurRadius: 5, + offset: Offset(0, 3), + ), + ], + ), + ) + : Opacity( + opacity: 0.65, + child: ColorFiltered( + colorFilter: const ColorFilter.mode( + Colors.grey, + BlendMode.saturation, + ), + child: Text( + badge.emoji, + style: const TextStyle(fontSize: 28), + ), + ), + ), + // Holographic sheen sweep (owned) + if (owned) + AnimatedBuilder( + animation: _sheenCtrl, + builder: (_, _) { + final x = _sheenCtrl.value * 2.6 - 0.6; + return Transform.translate( + offset: Offset(x * 72, 0), + child: Container( + width: 72 * 0.45, + height: 72, + decoration: const BoxDecoration( + gradient: LinearGradient( + colors: [ + Colors.transparent, + Color(0xA6FFFFFF), + Colors.transparent, + ], + ), + ), + ), + ); + }, + ), + ], + ), + ), ), - // Lock icon overlay for locked badges + + // Lock pip for locked badges if (!owned) Positioned( - right: 6, - bottom: 6, + right: 5, + bottom: 5, child: Container( - padding: const EdgeInsets.all(3), + width: 18, + height: 18, decoration: BoxDecoration( - color: pt.surface1, shape: BoxShape.circle, + color: pt.surface1, border: Border.all(color: pt.line), ), child: Icon( @@ -865,7 +1222,7 @@ class _BadgeTile extends StatelessWidget { Text( badge.label, textAlign: TextAlign.center, - maxLines: 1, + maxLines: 2, overflow: TextOverflow.ellipsis, style: TextStyle( fontSize: 10, @@ -874,19 +1231,19 @@ class _BadgeTile extends StatelessWidget { height: 1.2, ), ), - if (!owned && progressHint.isNotEmpty) - Text( - progressHint, - textAlign: TextAlign.center, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 9, - fontWeight: FontWeight.w600, - color: pt.ink300, - height: 1.2, - ), + const SizedBox(height: 2), + Text( + owned ? '✓ earned' : widget.progressHint, + textAlign: TextAlign.center, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 9, + fontWeight: FontWeight.w700, + color: owned ? AppColors.mint700 : pt.ink300, + height: 1, ), + ), ], ), ); diff --git a/lib/features/pet_profile/presentation/screens/manage_pets_screen.dart b/lib/features/pet_profile/presentation/screens/manage_pets_screen.dart index 1011d73..2c0aa2c 100644 --- a/lib/features/pet_profile/presentation/screens/manage_pets_screen.dart +++ b/lib/features/pet_profile/presentation/screens/manage_pets_screen.dart @@ -37,7 +37,6 @@ class _ManagePetsScreenState extends ConsumerState { Future _onReorder(List pets, int oldIndex, int newIndex) async { if (_reordering) return; - if (newIndex > oldIndex) newIndex -= 1; if (oldIndex == newIndex) return; final next = [...pets]; @@ -306,7 +305,7 @@ class _PetList extends StatelessWidget { padding: const EdgeInsets.symmetric(horizontal: 20), sliver: SliverReorderableList( itemCount: pets.length, - onReorder: onReorder, + onReorderItem: onReorder, proxyDecorator: (child, _, animation) => Material( color: Colors.transparent, child: AnimatedBuilder( diff --git a/progress.md b/progress.md index e6e0057..bd3a954 100644 --- a/progress.md +++ b/progress.md @@ -51,6 +51,30 @@ - **Error UI Handling**: For optimistic UI actions (like toggling care tasks or seller onboarding), show errors using `AppSnackBar.showError` (via `appSnackBarMessengerKey` on `MaterialApp.router`). Do not put long-lived state providers in `AsyncValue.error` states for transient/action-level failures. - **Web Safe Target**: Marionette execution runs exclusively in debug builds via conditional compiler imports (`marionette_debug_gate_stub.dart` vs `_io.dart`) to keep `main.dart` from importing `dart:io` on web targets. +## 2026-06-01 — Care Screen Redesign (from PetFolio Redesign/Care Redesign.html) + +**Files changed**: `gamified_care_ui.dart`, `care_screen.dart` + +- **`CareGamifiedHeader` rewritten** — Removed tall `WaveHeader`; replaced with compact inline design: + - Status-bar-aware top padding + pet switcher row (`PetAvatar` + "CARE" label + pet name + chevron) + - Slim gradient hero card (`poppy→#FF6B45→tangerine`, radius 26, shadow-pop) with paw watermark + - `_StreakCoin`: 78px golden radial-gradient circle with 3D `Matrix4.rotateY` coin-spin + pulse-ring + - `_HeroLevelContent`: inline Lv + title + done-today pill + XP progress bar + XP-to-next text +- **`_BadgeMedal` (replaces `_BadgeTile`)** — Circular medal design: + - 72px disc with radial gradient (owned: badge color, locked: grey), concentric depth rings, emoji + - Float bob animation (translateY 0→-5px, repeating reverse) + - Holographic sheen sweep (owned only); pulsing outer glow ring with scale+opacity (owned only) + - Lock pip (18px circle, bottom-right) for locked badges; `childAspectRatio: 0.72` grid +- **`_UtilityBanner` (replaces `_NutritionBanner` + `_MedicalVaultBanner`)** — Side-by-side split card: + - Single rounded `Container` with `VerticalDivider` between two `_UtilityHalf` widgets + - Left: Nutrition (sunny palette), Right: Medical Vault (mint palette); both tappable +- All existing Supabase providers and controllers unchanged; same data flow +- `flutter analyze` — **No issues found.** + +**Next step:** Phase complete — please run (/remember) to save tokens before proceeding to the next phase. + +--- + ## 2026-05-31 — Care Module Gamification & Data Integrity Fixes **Phase 1 — Database (migration `20260531100700_care_tasks_dedupe_and_unique_index.sql`)** From 1d8e35ff5145e14271d5105ad6af5ef64d7b0608 Mon Sep 17 00:00:00 2001 From: Syed Salman Reza Date: Tue, 2 Jun 2026 04:33:47 +0600 Subject: [PATCH 02/23] Revamp Care UI: trophy room & badge visuals Polish the Care feature UI and badge/trophy experience. Key changes: - Revamped Trophy Room: replaced grid with a horizontal PageView slider and new trophy card layout, improved progress/owned states, icons and animations. - Introduced custom badge painter and refined medal disc visuals, sheen animation, shadows and sizing tweaks. - Updated badge catalog text, emojis and descriptions to friendlier copy; added progress hint helper. - Tweaked weekly chart labels and today indicator, updated date picker to use ClipRect + stack to fix clipping and layout. - Minor header and accessibility fixes: static CARE eyebrow entry, theme toggle tooltip, and optional tooltip support for header icon buttons. - Added several local cli/mobile commands to .claude/settings.local.json. --- .claude/settings.local.json | 18 +- lib/core/widgets/app_shell.dart | 16 +- lib/features/care/data/models/pet_level.dart | 34 +- .../presentation/screens/care_screen.dart | 184 ++-- .../widgets/gamified_care_ui.dart | 933 ++++++++++++------ 5 files changed, 769 insertions(+), 416 deletions(-) diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 94b7ec2..2e830ee 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -95,7 +95,23 @@ "Bash(gh pr *)", "Bash(git rm *)", "Bash(dir \"G:\\\\GitHub\\\\petfolio\\\\PetFolio Redesign\\\\Care Redesign\" /b)", - "mcp__292a7621-3089-4236-bd52-07a54bf59881__list_tables" + "mcp__292a7621-3089-4236-bd52-07a54bf59881__list_tables", + "mcp__mobile-mcp__mobile_list_available_devices", + "mcp__mobile-mcp__mobile_take_screenshot", + "mcp__mobile-mcp__mobile_click_on_screen_at_coordinates", + "mcp__mobile-mcp__mobile_list_elements_on_screen", + "mcp__mobile-mcp__mobile_save_screenshot", + "mcp__mobile-mcp__mobile_swipe_on_screen", + "Bash(grep -E \"\\\\.\\(dart\\)$\")", + "Bash(Get-Content \"C:\\\\Users\\\\syedr\\\\AppData\\\\Local\\\\Temp\\\\claude\\\\G--GitHub-petfolio\\\\83d1e98f-3a1c-41fb-a000-787a9c3f0b74\\\\tasks\\\\bn6o3o4cc.output\" -Wait -Tail 30)", + "Bash(Select-Object -First 30)", + "mcp__marionette-mcp__take_screenshots", + "Bash(flutter run *)", + "Bash(Start-Sleep -Seconds 25)", + "Bash(Get-Content \"C:\\\\Users\\\\syedr\\\\AppData\\\\Local\\\\Temp\\\\claude\\\\G--GitHub-petfolio\\\\83d1e98f-3a1c-41fb-a000-787a9c3f0b74\\\\tasks\\\\bbq53bd0b.output\" -ErrorAction SilentlyContinue)", + "Bash(Select-Object -Last 30)", + "mcp__dart__hot_reload", + "mcp__dart__dtd" ] } } diff --git a/lib/core/widgets/app_shell.dart b/lib/core/widgets/app_shell.dart index fe6d327..2c85c02 100644 --- a/lib/core/widgets/app_shell.dart +++ b/lib/core/widgets/app_shell.dart @@ -127,7 +127,7 @@ class AppShellHeader extends ConsumerWidget { final eyebrows = [ 'ACTIVE PET', - activePet != null ? 'CARE · ${activePet.name.toUpperCase()}' : 'CARE', + 'CARE', 'PAWSFEED', 'MATCH · NEARBY', 'SHOP FOR', @@ -146,6 +146,7 @@ class AppShellHeader extends ConsumerWidget { final isDark = Theme.of(context).brightness == Brightness.dark; return _HeaderIconBtn( icon: isDark ? Icons.light_mode_rounded : Icons.dark_mode_rounded, + tooltip: isDark ? 'Switch to light mode' : 'Switch to dark mode', onTap: () => ref.read(themeProvider.notifier).toggleTheme(), ); }); @@ -278,14 +279,19 @@ class AppShellHeader extends ConsumerWidget { // ── Header icon button ──────────────────────────────────────────────────────── class _HeaderIconBtn extends StatelessWidget { - const _HeaderIconBtn({required this.icon, required this.onTap}); + const _HeaderIconBtn({ + required this.icon, + required this.onTap, + this.tooltip, + }); final IconData icon; final VoidCallback onTap; + final String? tooltip; @override Widget build(BuildContext context) { - return GestureDetector( + final btn = GestureDetector( onTap: onTap, child: Container( width: 36, height: 36, @@ -297,6 +303,10 @@ class _HeaderIconBtn extends StatelessWidget { child: Icon(icon, color: Colors.white, size: 18), ), ); + if (tooltip != null) { + return Tooltip(message: tooltip!, child: btn); + } + return btn; } } diff --git a/lib/features/care/data/models/pet_level.dart b/lib/features/care/data/models/pet_level.dart index 3975fcc..9f552df 100644 --- a/lib/features/care/data/models/pet_level.dart +++ b/lib/features/care/data/models/pet_level.dart @@ -103,44 +103,44 @@ const kBadgeCatalog = [ BadgeInfo( type: 'first_log', emoji: '🐾', - label: 'First Log', + label: 'First Paw', color: AppColors.mint, - description: 'Logged your first care activity', + description: 'You logged your very first care activity — the journey begins!', ), BadgeInfo( type: '3_day_streak', - emoji: '🔥', - label: '3-Day', + emoji: '🦴', + label: 'Treat Earner', color: AppColors.tangerine, - description: '3 days in a row', + description: 'Three days of care in a row — your pet is loving it!', ), BadgeInfo( type: '7_day_hero', - emoji: '🦸', - label: '7-Day Hero', + emoji: '🌿', + label: 'Thriving Week', color: AppColors.sunny, - description: '7 days in a row', + description: 'A full week of care — your pet is thriving and healthy!', ), BadgeInfo( type: 'routine_master', - emoji: '💯', - label: 'Routine Master', + emoji: '❤️', + label: 'Devoted Carer', color: AppColors.poppy, - description: '14 days in a row', + description: '14 days without missing a beat — true devotion!', ), BadgeInfo( type: '30_day_legend', - emoji: '👑', - label: '30-Day Legend', + emoji: '🌟', + label: 'Star Companion', color: AppColors.lilac, - description: '30 days in a row', + description: 'A whole month of daily care — you\'re a star companion!', ), BadgeInfo( type: 'care_champion', - emoji: '🏆', - label: 'Care Champion', + emoji: '👑', + label: 'Pet Royalty', color: AppColors.sky, - description: '100 total care logs', + description: '100 care logs — your pet lives like royalty!', ), ]; diff --git a/lib/features/care/presentation/screens/care_screen.dart b/lib/features/care/presentation/screens/care_screen.dart index eb54bd9..a075a0d 100644 --- a/lib/features/care/presentation/screens/care_screen.dart +++ b/lib/features/care/presentation/screens/care_screen.dart @@ -191,11 +191,11 @@ class _CareScreenState extends ConsumerState { crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( - "TODAY'S QUESTS", + "Today's Quests", style: TextStyle( - fontSize: 12, + fontSize: 13, fontWeight: FontWeight.w700, - letterSpacing: 0.08 * 12, + letterSpacing: 0.2, color: pt.ink500, ), ), @@ -277,24 +277,6 @@ class _CareScreenState extends ConsumerState { }(), ), const SizedBox(height: 28), - PfSectionTitle( - title: 'Trophy room', - accent: AppColors.lilac, - trailing: GestureDetector( - onTap: () => context.push('/care/medical-vault'), - child: const Text( - 'Vault →', - style: TextStyle( - fontSize: 13, - fontWeight: FontWeight.w800, - color: AppColors.lilac700, - ), - ), - ), - ), - const SizedBox(height: 8), - CareGamifiedTrophyRoom(petId: activePet.id), - const SizedBox(height: 28), _UtilityBanner(pt: pt), ], ), @@ -458,83 +440,99 @@ class _HorizontalDatePickerState extends State<_HorizontalDatePicker> { final cs = Theme.of(context).colorScheme; final today = DateUtils.dateOnly(DateTime.now()); - return SizedBox( - height: 76, - child: ListView.builder( - controller: _scroll, - scrollDirection: Axis.horizontal, - padding: EdgeInsets.zero, - itemCount: _totalDays, - itemBuilder: (context, i) { - final date = today.subtract(Duration(days: _daysBack - i)); - final isSelected = DateUtils.dateOnly(widget.selectedDate) == date; - final isToday = date == today; - final isFuture = date.isAfter(today); - - final ymd = - '${date.year}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')}'; - return Padding( - padding: EdgeInsets.only(right: i < _totalDays - 1 ? _chipGap : 0), - child: GestureDetector( - key: ValueKey('care_date_$ymd'), - onTap: isFuture ? null : () => widget.onDateSelected(date), - child: AnimatedContainer( - duration: PetfolioThemeExtension.durationSm, - width: _chipW, - decoration: BoxDecoration( - color: isSelected - ? cs.primary - : (isToday ? cs.primary.withAlpha(15) : pt.surface2), - borderRadius: BorderRadius.circular(14), - border: Border.all( - color: isSelected - ? Colors.transparent - : (isToday ? cs.primary.withAlpha(80) : pt.line), - width: isToday && !isSelected ? 1.5 : 0.5, - ), - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - _dayLetters[date.weekday - 1], - style: TextStyle( - fontSize: 11, - fontWeight: FontWeight.w600, - letterSpacing: 0.5, - color: isSelected - ? Colors.white.withAlpha(200) - : (isFuture ? pt.ink300 : pt.ink500), - ), - ), - const SizedBox(height: 4), - Text( - '${date.day}', - style: TextStyle( - fontWeight: FontWeight.w700, - fontSize: 18, - height: 1, + return ClipRect( + child: SizedBox( + height: 76, + child: Stack( + children: [ + ListView.builder( + controller: _scroll, + scrollDirection: Axis.horizontal, + padding: EdgeInsets.zero, + itemCount: _totalDays, + itemBuilder: (context, i) { + final date = today.subtract(Duration(days: _daysBack - i)); + final isSelected = + DateUtils.dateOnly(widget.selectedDate) == date; + final isToday = date == today; + final isFuture = date.isAfter(today); + + final ymd = + '${date.year}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')}'; + return Padding( + padding: EdgeInsets.only( + right: i < _totalDays - 1 ? _chipGap : 0), + child: GestureDetector( + key: ValueKey('care_date_$ymd'), + onTap: isFuture ? null : () => widget.onDateSelected(date), + child: AnimatedContainer( + duration: PetfolioThemeExtension.durationSm, + width: _chipW, + decoration: BoxDecoration( color: isSelected - ? Colors.white + ? cs.primary : (isToday - ? cs.primary - : (isFuture ? pt.ink300 : cs.onSurface)), + ? cs.primary.withAlpha(15) + : pt.surface2), + borderRadius: BorderRadius.circular(14), + border: Border.all( + color: isSelected + ? Colors.transparent + : (isToday + ? cs.primary.withAlpha(80) + : pt.line), + width: isToday && !isSelected ? 1.5 : 0.5, + ), ), - ), - if (isToday && !isSelected) ...[ - const SizedBox(height: 4), - Container( - width: 4, - height: 4, - decoration: BoxDecoration(color: cs.primary, shape: BoxShape.circle), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + _dayLetters[date.weekday - 1], + style: TextStyle( + fontSize: 11, + fontWeight: FontWeight.w600, + letterSpacing: 0.5, + color: isSelected + ? Colors.white.withAlpha(200) + : (isFuture ? pt.ink300 : pt.ink500), + ), + ), + const SizedBox(height: 4), + Text( + '${date.day}', + style: TextStyle( + fontWeight: FontWeight.w700, + fontSize: 18, + height: 1, + color: isSelected + ? Colors.white + : (isToday + ? cs.primary + : (isFuture + ? pt.ink300 + : cs.onSurface)), + ), + ), + if (isToday && !isSelected) ...[ + const SizedBox(height: 4), + Container( + width: 4, + height: 4, + decoration: BoxDecoration( + color: cs.primary, + shape: BoxShape.circle), + ), + ], + ], ), - ], - ], - ), - ), + ), + ), + ); + }, ), - ); - }, + ], + ), ), ); } diff --git a/lib/features/care/presentation/widgets/gamified_care_ui.dart b/lib/features/care/presentation/widgets/gamified_care_ui.dart index 59baf71..ce60f4d 100644 --- a/lib/features/care/presentation/widgets/gamified_care_ui.dart +++ b/lib/features/care/presentation/widgets/gamified_care_ui.dart @@ -619,7 +619,7 @@ class CareGamifiedWeeklyChart extends StatelessWidget { borderRadius: BorderRadius.circular(999), ), child: Text( - '$hitsCount 🔥', + '$hitsCount 🔥 day${hitsCount == 1 ? '' : 's'}', style: const TextStyle( fontSize: 11, fontWeight: FontWeight.w800, @@ -655,12 +655,25 @@ class CareGamifiedWeeklyChart extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.end, children: [ SizedBox( - height: 18, + height: 26, child: isToday - ? const Align( - alignment: Alignment.bottomCenter, - child: - Text('🐾', style: TextStyle(fontSize: 13)), + ? Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text( + 'Today', + style: TextStyle( + fontSize: 7, + fontWeight: FontWeight.w700, + color: _colors[i], + height: 1.1, + ), + ), + const Text( + '🐾', + style: TextStyle(fontSize: 11, height: 1.1), + ), + ], ) : null, ), @@ -747,30 +760,30 @@ class CareGamifiedWeeklyChart extends StatelessWidget { } } -// ── Trophy Room (real badges) ───────────────────────────────────────────────── +// ── Trophy Room (horizontal slider) ────────────────────────────────────────── + +String _badgeProgressHint(BadgeInfo badge, PetAwardsSummary awards) { + switch (badge.type) { + case '3_day_streak': + return '${awards.currentStreak}/3 days 🦴'; + case '7_day_hero': + return '${awards.currentStreak}/7 days 🌿'; + case 'routine_master': + return '${awards.currentStreak}/14 days ❤️'; + case '30_day_legend': + return '${awards.currentStreak}/30 days 🌟'; + case 'care_champion': + return '${awards.logsCount}/100 logs 👑'; + default: + return ''; + } +} class CareGamifiedTrophyRoom extends ConsumerWidget { const CareGamifiedTrophyRoom({super.key, required this.petId}); final String petId; - String _progressHint(BadgeInfo badge, PetAwardsSummary awards) { - switch (badge.type) { - case '3_day_streak': - return '${awards.currentStreak}/3 days 🔥'; - case '7_day_hero': - return '${awards.currentStreak}/7 days 🦸'; - case 'routine_master': - return '${awards.currentStreak}/14 days 💯'; - case '30_day_legend': - return '${awards.currentStreak}/30 days 👑'; - case 'care_champion': - return '${awards.logsCount}/100 logs 🏆'; - default: - return ''; - } - } - @override Widget build(BuildContext context, WidgetRef ref) { final awardsAsync = ref.watch(petAwardsSummaryProvider(petId)); @@ -780,8 +793,7 @@ class CareGamifiedTrophyRoom extends ConsumerWidget { data: (a) => a, orElse: () => PetAwardsSummary.empty, ); - final ownedTypes = awards.unlockedTypes; - final ownedCount = ownedTypes.length; + final ownedCount = awards.unlockedTypes.length; return Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -804,29 +816,10 @@ class CareGamifiedTrophyRoom extends ConsumerWidget { ), ), ), - GridView.builder( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - padding: EdgeInsets.zero, - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 3, - mainAxisSpacing: 8, - crossAxisSpacing: 8, - childAspectRatio: 0.78, - ), - itemCount: kBadgeCatalog.length, - itemBuilder: (context, i) { - final badge = kBadgeCatalog[i]; - final owned = ownedTypes.contains(badge.type); - final hint = owned ? '' : _progressHint(badge, awards); - return _BadgeMedal( - badge: badge, - owned: owned, - progressHint: hint, - index: i, - onTap: () => _showBadgeDetail(context, pt, badge, owned, hint), - ); - }, + _TrophySlider( + awards: awards, + onTapBadge: (badge, owned, hint) => + _showBadgeDetail(context, pt, badge, owned, hint), ), ], ); @@ -866,10 +859,9 @@ class CareGamifiedTrophyRoom extends ConsumerWidget { ), ), ), - // Medal in sheet Container( - width: 84, - height: 84, + width: 96, + height: 96, decoration: BoxDecoration( shape: BoxShape.circle, gradient: owned @@ -890,8 +882,8 @@ class CareGamifiedTrophyRoom extends ConsumerWidget { ? [ BoxShadow( color: badge.color.withAlpha(120), - blurRadius: 24, - offset: const Offset(0, 8), + blurRadius: 28, + offset: const Offset(0, 10), spreadRadius: -8, ) ] @@ -899,7 +891,7 @@ class CareGamifiedTrophyRoom extends ConsumerWidget { ), alignment: Alignment.center, child: owned - ? Text(badge.emoji, style: const TextStyle(fontSize: 40)) + ? Text(badge.emoji, style: const TextStyle(fontSize: 44)) : Opacity( opacity: 0.4, child: ColorFiltered( @@ -907,8 +899,8 @@ class CareGamifiedTrophyRoom extends ConsumerWidget { Colors.grey, BlendMode.saturation, ), - child: - Text(badge.emoji, style: const TextStyle(fontSize: 40)), + child: Text(badge.emoji, + style: const TextStyle(fontSize: 44)), ), ), ), @@ -916,37 +908,55 @@ class CareGamifiedTrophyRoom extends ConsumerWidget { Text( badge.label, style: TextStyle( - fontSize: 20, + fontSize: 22, fontWeight: FontWeight.w800, - color: Theme.of(context).colorScheme.onSurface, + color: owned + ? badge.color + : Theme.of(context).colorScheme.onSurface, ), ), const SizedBox(height: 6), Text( badge.description, - style: TextStyle( - fontSize: 14, - color: pt.ink500, - ), + style: TextStyle(fontSize: 14, color: pt.ink500), textAlign: TextAlign.center, ), - const SizedBox(height: 12), + const SizedBox(height: 14), Container( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + padding: + const EdgeInsets.symmetric(horizontal: 16, vertical: 10), decoration: BoxDecoration( - color: owned ? AppColors.mintSoft : pt.surface2, + color: owned ? badge.color.withAlpha(20) : pt.surface2, borderRadius: BorderRadius.circular(12), - ), - child: Text( - owned - ? '✅ Earned!' - : (hint.isNotEmpty ? 'Progress: $hint' : 'Keep logging care'), - style: TextStyle( - fontSize: 13, - fontWeight: FontWeight.w800, - color: owned ? AppColors.mint700 : pt.ink500, + border: Border.all( + color: owned ? badge.color.withAlpha(60) : pt.line, ), ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + owned + ? Icons.check_circle_rounded + : Icons.lock_rounded, + size: 16, + color: owned ? badge.color : pt.ink300, + ), + const SizedBox(width: 8), + Text( + owned + ? 'Earned!' + : (hint.isNotEmpty + ? 'Progress: $hint' + : 'Keep logging care'), + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.w800, + color: owned ? badge.color : pt.ink500, + ), + ), + ], + ), ), ], ), @@ -955,10 +965,113 @@ class CareGamifiedTrophyRoom extends ConsumerWidget { } } -// ── Badge Medal (circular 3D medal style) ───────────────────────────────────── +// ── Trophy Slider ───────────────────────────────────────────────────────────── + +class _TrophySlider extends StatefulWidget { + const _TrophySlider({ + required this.awards, + required this.onTapBadge, + }); + + final PetAwardsSummary awards; + final void Function(BadgeInfo badge, bool owned, String hint) onTapBadge; + + @override + State<_TrophySlider> createState() => _TrophySliderState(); +} + +class _TrophySliderState extends State<_TrophySlider> { + late final PageController _ctrl; + int _page = 0; + + @override + void initState() { + super.initState(); + _ctrl = PageController(viewportFraction: 0.46); + _ctrl.addListener(_onScroll); + } + + void _onScroll() { + final p = (_ctrl.page ?? 0).round(); + if (p != _page) setState(() => _page = p); + } + + @override + void dispose() { + _ctrl.removeListener(_onScroll); + _ctrl.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final pt = Theme.of(context).extension()!; + final ownedTypes = widget.awards.unlockedTypes; + + return Column( + children: [ + SizedBox( + height: 172, + child: PageView.builder( + controller: _ctrl, + padEnds: false, + itemCount: kBadgeCatalog.length, + itemBuilder: (context, i) { + final badge = kBadgeCatalog[i]; + final owned = ownedTypes.contains(badge.type); + final hint = + owned ? '' : _badgeProgressHint(badge, widget.awards); + return Padding( + padding: EdgeInsets.fromLTRB( + i == 0 ? 0 : 7, + 4, + i == kBadgeCatalog.length - 1 ? 8 : 7, + 10, + ), + child: _TrophyCard( + badge: badge, + owned: owned, + progressHint: hint, + index: i, + onTap: () => widget.onTapBadge(badge, owned, hint), + ), + ); + }, + ), + ), + const SizedBox(height: 8), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: List.generate(kBadgeCatalog.length, (i) { + final badge = kBadgeCatalog[i]; + final owned = ownedTypes.contains(badge.type); + final active = i == _page; + return AnimatedContainer( + duration: const Duration(milliseconds: 300), + curve: Curves.easeOutCubic, + width: active ? 20 : 6, + height: 6, + margin: const EdgeInsets.symmetric(horizontal: 2.5), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(999), + color: active + ? badge.color + : (owned + ? badge.color.withAlpha(90) + : pt.line), + ), + ); + }), + ), + ], + ); + } +} + +// ── Trophy Card ─────────────────────────────────────────────────────────────── -class _BadgeMedal extends StatefulWidget { - const _BadgeMedal({ +class _TrophyCard extends StatefulWidget { + const _TrophyCard({ required this.badge, required this.owned, required this.progressHint, @@ -973,29 +1086,32 @@ class _BadgeMedal extends StatefulWidget { final VoidCallback onTap; @override - State<_BadgeMedal> createState() => _BadgeMedalState(); + State<_TrophyCard> createState() => _TrophyCardState(); } -class _BadgeMedalState extends State<_BadgeMedal> with TickerProviderStateMixin { +class _TrophyCardState extends State<_TrophyCard> with TickerProviderStateMixin { late final AnimationController _floatCtrl; late final AnimationController _sheenCtrl; @override void initState() { super.initState(); - final delayMs = widget.index * 300; _floatCtrl = AnimationController( vsync: this, duration: Duration(milliseconds: 3200 + widget.index * 200), )..repeat(reverse: true); - _sheenCtrl = AnimationController( - vsync: this, - duration: Duration(milliseconds: 3800 + widget.index * 200), - )..forward(from: (delayMs / (3800 + widget.index * 200)).clamp(0.0, 1.0)); - _sheenCtrl.addStatusListener((s) { - if (s == AnimationStatus.completed && mounted) _sheenCtrl.repeat(); - }); + final sheenDuration = Duration(milliseconds: 3800 + widget.index * 200); + _sheenCtrl = AnimationController(vsync: this, duration: sheenDuration); + + if (widget.owned) { + final delayFraction = + (widget.index * 300 / sheenDuration.inMilliseconds).clamp(0.0, 1.0); + _sheenCtrl.forward(from: delayFraction); + _sheenCtrl.addStatusListener((s) { + if (s == AnimationStatus.completed && mounted) _sheenCtrl.repeat(); + }); + } } @override @@ -1011,241 +1127,454 @@ class _BadgeMedalState extends State<_BadgeMedal> with TickerProviderStateMixin final isDark = Theme.of(context).brightness == Brightness.dark; final owned = widget.owned; final badge = widget.badge; - final labelColor = isDark ? AppColors.ink950D : AppColors.ink950; + + final bgTop = owned + ? Color.lerp(badge.color, Colors.white, isDark ? 0.50 : 0.82)! + : (isDark ? const Color(0xFF252020) : const Color(0xFFF9F6F2)); + final bgBottom = owned + ? Color.lerp(badge.color, Colors.white, isDark ? 0.24 : 0.52)! + : (isDark ? const Color(0xFF1C1818) : pt.line.withAlpha(130)); return GestureDetector( onTap: widget.onTap, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - // Float bob animation wrapper - AnimatedBuilder( - animation: _floatCtrl, - builder: (_, child) => Transform.translate( - offset: Offset(0, _floatCtrl.value * -5), - child: child, - ), - child: SizedBox( - width: 82, - height: 82, - child: Stack( - alignment: Alignment.center, - children: [ - // Outer glow ring derived from _floatCtrl (no separate controller) - if (owned) - AnimatedBuilder( - animation: _floatCtrl, - builder: (_, _) { - final t = math.sin(_floatCtrl.value * math.pi); - return Transform.scale( - scale: 0.92 + t * 0.14, - child: Opacity( - opacity: (0.50 + t * 0.38).clamp(0.0, 1.0), - child: Container( - width: 82, - height: 82, - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: badge.color, - width: 2, - ), - ), - ), + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(24), + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [bgTop, bgBottom], + ), + border: Border.all( + color: + owned ? badge.color.withAlpha(75) : pt.line, + width: owned ? 1.5 : 1.0, + ), + boxShadow: owned + ? [ + BoxShadow( + color: badge.color.withAlpha(isDark ? 55 : 40), + blurRadius: 20, + offset: const Offset(0, 8), + spreadRadius: -5, + ), + ] + : null, + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(23), + child: Stack( + children: [ + // Holographic sheen sweep for owned badges + if (owned) + AnimatedBuilder( + animation: _sheenCtrl, + builder: (_, _) { + final x = _sheenCtrl.value * 3.0 - 0.7; + return Positioned( + top: 0, + bottom: 0, + left: x * 170, + width: 52, + child: Container( + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ + Colors.transparent, + Color(0x50FFFFFF), + Colors.transparent, + ], ), - ); - }, - ), + ), + ), + ); + }, + ), - // Medal disc - Container( - width: 72, - height: 72, - decoration: BoxDecoration( - shape: BoxShape.circle, - gradient: owned - ? RadialGradient( - center: const Alignment(-0.24, -0.4), - radius: 0.85, - colors: [ - Color.lerp(badge.color, Colors.white, 0.55)!, - badge.color, - Color.lerp(badge.color, Colors.black, 0.4)!, - ], - stops: const [0.0, 0.58, 1.0], - ) - : RadialGradient( - center: const Alignment(-0.24, -0.4), - radius: 0.85, - colors: [ - pt.ink300.withAlpha(160), - pt.ink300, - ], - ), - boxShadow: owned - ? [ - BoxShadow( - color: Colors.black.withAlpha(77), - blurRadius: 0, - offset: const Offset(0, 5), - ), - BoxShadow( - color: badge.color.withAlpha(120), - blurRadius: 14, - offset: const Offset(0, 8), - spreadRadius: -8, - ), - ] - : [ - BoxShadow( - color: Colors.black.withAlpha(46), - blurRadius: 0, - offset: const Offset(0, 4), - ), - ], + Padding( + padding: const EdgeInsets.fromLTRB(10, 14, 10, 10), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + // Floating medal disc + Expanded( + child: Center( + child: AnimatedBuilder( + animation: _floatCtrl, + builder: (_, child) => Transform.translate( + offset: Offset(0, _floatCtrl.value * -6), + child: child, + ), + child: _MedalDisc(badge: badge, owned: owned), + ), + ), + ), + const SizedBox(height: 6), + // Badge name + Text( + badge.label, + textAlign: TextAlign.center, + maxLines: 2, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 11, + fontWeight: FontWeight.w800, + height: 1.2, + color: owned + ? (isDark + ? Color.lerp(badge.color, Colors.white, 0.30)! + : badge.color) + : pt.ink500, + ), ), - child: ClipOval( - child: Stack( - alignment: Alignment.center, + const SizedBox(height: 5), + // Progress / earned status pill + Container( + width: double.infinity, + padding: const EdgeInsets.symmetric( + horizontal: 10, vertical: 5), + decoration: BoxDecoration( + color: owned + ? badge.color.withAlpha(isDark ? 50 : 28) + : pt.surface2.withAlpha(200), + borderRadius: BorderRadius.circular(999), + border: Border.all( + color: owned + ? badge.color.withAlpha(65) + : pt.line, + width: 1, + ), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, children: [ - // Concentric depth rings - Positioned.fill( - child: Container( - margin: const EdgeInsets.all(6), - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: owned - ? Colors.white.withAlpha(77) - : Colors.black.withAlpha(15), - width: 1.5, - ), - ), - ), + Icon( + owned + ? Icons.check_circle_rounded + : Icons.lock_rounded, + size: 11, + color: owned ? badge.color : pt.ink300, ), - Positioned.fill( - child: Container( - margin: const EdgeInsets.all(11), - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: owned - ? Colors.white.withAlpha(46) - : Colors.black.withAlpha(8), - width: 1, - ), + const SizedBox(width: 4), + Flexible( + child: Text( + owned + ? 'Earned!' + : (widget.progressHint.isNotEmpty + ? widget.progressHint + : 'Locked'), + overflow: TextOverflow.ellipsis, + maxLines: 1, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 10, + fontWeight: FontWeight.w700, + color: owned ? badge.color : pt.ink500, + height: 1, ), ), ), - // Badge emoji - owned - ? Text( - badge.emoji, - style: const TextStyle( - fontSize: 28, - shadows: [ - Shadow( - color: Color(0x47000000), - blurRadius: 5, - offset: Offset(0, 3), - ), - ], - ), - ) - : Opacity( - opacity: 0.65, - child: ColorFiltered( - colorFilter: const ColorFilter.mode( - Colors.grey, - BlendMode.saturation, - ), - child: Text( - badge.emoji, - style: const TextStyle(fontSize: 28), - ), - ), - ), - // Holographic sheen sweep (owned) - if (owned) - AnimatedBuilder( - animation: _sheenCtrl, - builder: (_, _) { - final x = _sheenCtrl.value * 2.6 - 0.6; - return Transform.translate( - offset: Offset(x * 72, 0), - child: Container( - width: 72 * 0.45, - height: 72, - decoration: const BoxDecoration( - gradient: LinearGradient( - colors: [ - Colors.transparent, - Color(0xA6FFFFFF), - Colors.transparent, - ], - ), - ), - ), - ); - }, - ), ], ), ), - ), + ], + ), + ), - // Lock pip for locked badges - if (!owned) - Positioned( - right: 5, - bottom: 5, - child: Container( - width: 18, - height: 18, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: pt.surface1, - border: Border.all(color: pt.line), - ), - child: Icon( - Icons.lock_rounded, - size: 10, - color: pt.ink300, - ), - ), + // Lock pip top-right for locked badges + if (!owned) + Positioned( + top: 10, + right: 10, + child: Container( + width: 22, + height: 22, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: pt.surface1, + border: Border.all(color: pt.line), ), + child: Icon( + Icons.lock_rounded, + size: 11, + color: pt.ink300, + ), + ), + ), + ], + ), + ), + ), + ); + } +} + +// ── Medal Disc ──────────────────────────────────────────────────────────────── + +class _MedalDisc extends StatelessWidget { + const _MedalDisc({required this.badge, required this.owned}); + + final BadgeInfo badge; + final bool owned; + + @override + Widget build(BuildContext context) { + final pt = Theme.of(context).extension()!; + final iconWidget = CustomPaint( + painter: _BadgePainter(badge.type, badge.color, owned), + ); + return Container( + width: 62, + height: 62, + decoration: BoxDecoration( + shape: BoxShape.circle, + gradient: owned + ? RadialGradient( + center: const Alignment(-0.24, -0.40), + radius: 0.88, + colors: [ + Color.lerp(badge.color, Colors.white, 0.56)!, + badge.color, + Color.lerp(badge.color, Colors.black, 0.38)!, + ], + stops: const [0.0, 0.55, 1.0], + ) + : RadialGradient( + center: const Alignment(-0.24, -0.40), + radius: 0.88, + colors: [ + pt.ink300.withAlpha(100), + pt.ink300.withAlpha(160), ], ), + boxShadow: owned + ? [ + BoxShadow( + color: badge.color.withAlpha(100), + blurRadius: 16, + offset: const Offset(0, 6), + spreadRadius: -4, + ), + ] + : [ + BoxShadow( + color: Colors.black.withAlpha(22), + blurRadius: 4, + offset: const Offset(0, 2), + ), + ], + ), + child: ClipOval( + child: Stack( + alignment: Alignment.center, + children: [ + // Concentric ring + Positioned.fill( + child: Container( + margin: const EdgeInsets.all(5), + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + color: owned + ? Colors.white.withAlpha(60) + : Colors.black.withAlpha(10), + width: 1, + ), + ), + ), ), - ), - const SizedBox(height: 5), - Text( - badge.label, - textAlign: TextAlign.center, - maxLines: 2, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.w800, - color: labelColor, - height: 1.2, - ), - ), - const SizedBox(height: 2), - Text( - owned ? '✓ earned' : widget.progressHint, - textAlign: TextAlign.center, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontSize: 9, - fontWeight: FontWeight.w700, - color: owned ? AppColors.mint700 : pt.ink300, - height: 1, + // Specular highlight + if (owned) + Positioned( + left: 4, top: 4, right: 20, bottom: 10, + child: Container( + decoration: BoxDecoration( + shape: BoxShape.circle, + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [Colors.white.withAlpha(90), Colors.transparent], + ), + ), + ), + ), + // Custom icon + Positioned.fill( + child: owned + ? iconWidget + : Opacity( + opacity: 0.45, + child: ColorFiltered( + colorFilter: const ColorFilter.mode( + Colors.grey, BlendMode.saturation), + child: iconWidget, + ), + ), ), - ), - ], + ], + ), ), ); } } + +// ── Badge Icon Painter ──────────────────────────────────────────────────────── + +class _BadgePainter extends CustomPainter { + _BadgePainter(this.type, this.color, this.owned); + + final String type; + final Color color; + final bool owned; + + Paint _fill(Color c) => Paint()..color = c..style = PaintingStyle.fill; + Paint _stroke(Color c, double w) => Paint() + ..color = c + ..style = PaintingStyle.stroke + ..strokeWidth = w + ..strokeCap = StrokeCap.round + ..strokeJoin = StrokeJoin.round; + + @override + void paint(Canvas canvas, Size size) { + final cx = size.width / 2; + final cy = size.height / 2; + final u = size.width / 42; + final white = Colors.white.withAlpha(owned ? 230 : 180); + + switch (type) { + case 'first_log': _drawPaw(canvas, cx, cy, u, white); break; + case '3_day_streak': _drawBone(canvas, cx, cy, u, white); break; + case '7_day_hero': _drawSprout(canvas, cx, cy, u, white); break; + case 'routine_master': _drawHeartPaw(canvas, cx, cy, u, white); break; + case '30_day_legend': _drawStar(canvas, cx, cy, u, white); break; + case 'care_champion': _drawCrown(canvas, cx, cy, u, white); break; + } + } + + // 🐾 Paw print: palm oval + 4 toe circles + void _drawPaw(Canvas canvas, double cx, double cy, double u, Color c) { + final p = _fill(c); + canvas.drawOval( + Rect.fromCenter(center: Offset(cx, cy + 4 * u), width: 15 * u, height: 11 * u), + p, + ); + canvas.drawCircle(Offset(cx - 7 * u, cy - 1 * u), 3.5 * u, p); + canvas.drawCircle(Offset(cx - 2 * u, cy - 5.5 * u), 3.5 * u, p); + canvas.drawCircle(Offset(cx + 3 * u, cy - 5.5 * u), 3.5 * u, p); + canvas.drawCircle(Offset(cx + 8 * u, cy - 1 * u), 3.5 * u, p); + } + + // 🦴 Dog bone: bar + rounded knobs each end + void _drawBone(Canvas canvas, double cx, double cy, double u, Color c) { + final p = _fill(c); + canvas.drawRRect( + RRect.fromRectAndRadius( + Rect.fromCenter(center: Offset(cx, cy), width: 24 * u, height: 7 * u), + Radius.circular(3.5 * u), + ), + p, + ); + for (final dx in [-13.0 * u, 13.0 * u]) { + canvas.drawCircle(Offset(cx + dx, cy - 4.5 * u), 4.5 * u, p); + canvas.drawCircle(Offset(cx + dx, cy + 4.5 * u), 4.5 * u, p); + } + } + + // 🌱 Sprout: curved stem + two leaves + sun bud + void _drawSprout(Canvas canvas, double cx, double cy, double u, Color c) { + // Stem + final stem = Path() + ..moveTo(cx, cy + 10 * u) + ..cubicTo(cx, cy + 4 * u, cx - 1.5 * u, cy, cx, cy - 1.5 * u); + canvas.drawPath(stem, _stroke(c, 2.8 * u)); + // Left leaf + final left = Path() + ..moveTo(cx, cy + 1 * u) + ..cubicTo(cx - 10 * u, cy - 1 * u, cx - 10 * u, cy - 11 * u, cx, cy - 7 * u) + ..close(); + canvas.drawPath(left, _fill(c)); + // Right leaf + final right = Path() + ..moveTo(cx, cy - 1 * u) + ..cubicTo(cx + 9 * u, cy - 3 * u, cx + 9 * u, cy - 13 * u, cx, cy - 9 * u) + ..close(); + canvas.drawPath(right, _fill(c)); + // Bud + canvas.drawCircle(Offset(cx, cy - 13.5 * u), 3.5 * u, _fill(c)); + } + + // ❤️ Heart + mini paw inside + void _drawHeartPaw(Canvas canvas, double cx, double cy, double u, Color c) { + final heart = Path() + ..moveTo(cx, cy + 9 * u) + ..cubicTo(cx - 14 * u, cy + 1 * u, cx - 17 * u, cy - 11 * u, cx, cy - 7 * u) + ..cubicTo(cx + 17 * u, cy - 11 * u, cx + 14 * u, cy + 1 * u, cx, cy + 9 * u); + canvas.drawPath(heart, _fill(c)); + // Mini paw inside (white) + final pw = Colors.white.withAlpha(owned ? 200 : 140); + canvas.drawOval( + Rect.fromCenter(center: Offset(cx, cy + 1.5 * u), width: 6.5 * u, height: 4.5 * u), + _fill(pw), + ); + for (final d in [Offset(-3.5 * u, -1.5 * u), Offset(-1 * u, -4 * u), Offset(1.5 * u, -4 * u), Offset(4 * u, -1.5 * u)]) { + canvas.drawCircle(Offset(cx + d.dx, cy + d.dy), 1.5 * u, _fill(pw)); + } + } + + // ⭐ 5-pt star + sparkle dots + void _drawStar(Canvas canvas, double cx, double cy, double u, Color c) { + const n = 5; + const outerR = 14.0; + const innerR = 5.5; + final star = Path(); + for (int i = 0; i < n * 2; i++) { + final angle = (i * math.pi / n) - math.pi / 2; + final r = (i.isEven ? outerR : innerR) * u; + final pt = Offset(cx + r * math.cos(angle), cy + r * math.sin(angle)); + i == 0 ? star.moveTo(pt.dx, pt.dy) : star.lineTo(pt.dx, pt.dy); + } + star.close(); + canvas.drawPath(star, _fill(c)); + // Sparkle dots + for (final pos in [ + Offset(-16 * u, -7 * u), Offset(16 * u, 5 * u), Offset(11 * u, -15 * u) + ]) { + canvas.drawCircle(Offset(cx + pos.dx, cy + pos.dy), 1.8 * u, _fill(c)); + } + } + + // 👑 Crown: 3-pointed body + gem circles + base band + void _drawCrown(Canvas canvas, double cx, double cy, double u, Color c) { + final crown = Path() + ..moveTo(cx - 14 * u, cy + 7 * u) + ..lineTo(cx + 14 * u, cy + 7 * u) + ..lineTo(cx + 11 * u, cy - 3 * u) + ..lineTo(cx + 4.5 * u, cy + 2.5 * u) + ..lineTo(cx, cy - 12 * u) + ..lineTo(cx - 4.5 * u, cy + 2.5 * u) + ..lineTo(cx - 11 * u, cy - 3 * u) + ..close(); + canvas.drawPath(crown, _fill(c)); + // Base band + canvas.drawRRect( + RRect.fromRectAndRadius( + Rect.fromCenter(center: Offset(cx, cy + 9 * u), width: 28 * u, height: 5 * u), + Radius.circular(2.5 * u), + ), + _fill(c), + ); + // Gems (white circles) + final gem = Colors.white.withAlpha(owned ? 210 : 150); + canvas.drawCircle(Offset(cx, cy - 12 * u), 2.8 * u, _fill(gem)); + canvas.drawCircle(Offset(cx - 11 * u, cy - 3 * u), 2.2 * u, _fill(gem)); + canvas.drawCircle(Offset(cx + 11 * u, cy - 3 * u), 2.2 * u, _fill(gem)); + } + + @override + bool shouldRepaint(covariant _BadgePainter old) => + old.type != type || old.color != color || old.owned != owned; +} From d472ebddedcbc5bf5045dddc5bdf64e63913de24 Mon Sep 17 00:00:00 2001 From: Syed Salman Reza Date: Tue, 2 Jun 2026 05:26:37 +0600 Subject: [PATCH 03/23] Add Flutter run and exception logs Add two log files to aid debugging: exception-log.md records a Flutter framework assertion about ListTile background color/ink splash visibility and related stack details; flutter-run-log.md captures a full `flutter run` session (Kotlin Gradle Plugin warnings, engine/renderer messages, Geolocator init, skipped frames, DevTools URL, etc.). These logs help diagnose runtime and build issues. --- exception-log.md | 45 +++++++++++++++++++++++++++++++++ flutter-run-log.md | 63 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 exception-log.md create mode 100644 flutter-run-log.md diff --git a/exception-log.md b/exception-log.md new file mode 100644 index 0000000..147b2aa --- /dev/null +++ b/exception-log.md @@ -0,0 +1,45 @@ +D/WindowOnBackDispatcher( 8540): setTopOnBackInvokedCallback (unwrapped): androidx.navigationevent.OnBackInvokedInput$createOnBackAnimationCallback$1@94b726b +D/WindowOnBackDispatcher( 8540): setTopOnBackInvokedCallback (unwrapped): android.app.Activity$$ExternalSyntheticLambda0@671fe96 +D/WindowOnBackDispatcher( 8540): setTopOnBackInvokedCallback (unwrapped): androidx.navigationevent.OnBackInvokedInput$createOnBackAnimationCallback$1@94b726b +D/WindowOnBackDispatcher( 8540): setTopOnBackInvokedCallback (unwrapped): android.app.Activity$$ExternalSyntheticLambda0@671fe96 +D/WindowOnBackDispatcher( 8540): setTopOnBackInvokedCallback (unwrapped): androidx.navigationevent.OnBackInvokedInput$createOnBackAnimationCallback$1@94b726b + +══╡ EXCEPTION CAUGHT BY FLUTTER FRAMEWORK ╞═════════════════════════════════════════════════════════ +The following assertion was thrown: +ListTile background color or ink splashes may be invisible. +The ListTile is wrapped in a DecoratedBox that has a background color. Because ListTile paints its +background and ink splashes on the nearest Material ancestor, this DecoratedBox will hide those +effects. +To fix this, wrap the ListTile in its own Material widget, or remove the background color from the +intermediate DecoratedBox. + +ListTile: + ListTile(selectedColor: Color(alpha: 1.0000, red: 1.0000, green: 0.5412, blue: 0.2980, colorSpace: ColorSpace.sRGB), contentPadding: EdgeInsets(16.0, 8.0, 16.0, + 8.0), onTap: Closure: () => void from Function '_handleValueChange@2316134056':.) +DecoratedBox: DecoratedBox(bg: + BoxDecoration(color: Color(alpha: 0.0500, red: 1.0000, green: 0.5412, blue: 0.2980, colorSpace: ColorSpace.sRGB), border: Border.all(BorderSide(color: + Color(alpha: 0.3000, red: 1.0000, green: 0.5412, blue: 0.2980, colorSpace: ColorSpace.sRGB), width: 1.5)), borderRadius: BorderRadius.circular(16.0), + boxShadow: [BoxShadow(Color(alpha: 0.0392, red: 0.1490, green: + 0.0745, blue: 0.0314, colorSpace: ColorSpace.sRGB), Offset(0.0, + 1.0), 2.0, 0.0, BlurStyle.normal)] + ) + ) +════════════════════════════════════════════════════════════════════════════════════════════════════ + +Another exception was thrown: ListTile background color or ink splashes may be invisible. +Another exception was thrown: ListTile background color or ink splashes may be invisible. +Another exception was thrown: ListTile background color or ink splashes may be invisible. +Another exception was thrown: ListTile background color or ink splashes may be invisible. +Another exception was thrown: ListTile background color or ink splashes may be invisible. +Another exception was thrown: ListTile background color or ink splashes may be invisible. +Another exception was thrown: ListTile background color or ink splashes may be invisible. +Another exception was thrown: ListTile background color or ink splashes may be invisible. +Another exception was thrown: ListTile background color or ink splashes may be invisible. +Another exception was thrown: ListTile background color or ink splashes may be invisible. +I/xample.petfolio( 8540): Background young concurrent mark compact GC freed 4915KB AllocSpace bytes, 12(608KB) LOS objects, 45% free, 5899KB/10MB, paused 1.185ms,9.059ms total 50.512ms +W/xample.petfolio( 8540): Reducing the number of considered missed Gc histogram windows from 301 to 100 +Another exception was thrown: ListTile background color or ink splashes may be invisible. +Another exception was thrown: ListTile background color or ink splashes may be invisible. +Another exception was thrown: ListTile background color or ink splashes may be invisible. +Another exception was thrown: ListTile background color or ink splashes may be invisible. +Another exception was thrown: ListTile background color or ink splashes may be invisible. \ No newline at end of file diff --git a/flutter-run-log.md b/flutter-run-log.md new file mode 100644 index 0000000..04b9458 --- /dev/null +++ b/flutter-run-log.md @@ -0,0 +1,63 @@ +PS G:\GitHub\petfolio> flutter run --dart-define-from-file=.env +Launching lib\main.dart on sdk gphone16k x86 64 in debug mode... +WARNING: Your Android app project: app located at: G:\GitHub\petfolio\android\app\build.gradle.kts +applies the Kotlin Gradle Plugin, which will cause build failures in future versions of Flutter. +Please migrate your app to Built-in Kotlin using this guide: https://docs.flutter.dev/release/breaking-changes/migrate-to-built-in-kotlin/for-app-developers + +WARNING: Your app uses the following plugins that apply Kotlin Gradle Plugin (KGP): image_picker_android, share_plus, shared_preferences_android, stripe_android, url_launcher_android +Future versions of Flutter will fail to build if your app uses plugins that apply KGP. + +Please check the changelogs of these plugins and upgrade to a version that supports Built-in Kotlin. +If no such version exists, report the issue to the plugin. If necessary, here is a guide on filing +an issue against a plugin: https://docs.flutter.dev/release/breaking-changes/migrate-to-built-in-kotlin/for-app-developers#report-incompatible-kotlin-gradle-plugin-usage-to-plugin-authors + +If you are a plugin author, please migrate your plugin to Built-in Kotlin using this guide: https://docs.flutter.dev/release/breaking-changes/migrate-to-built-in-kotlin/for-plugin-authors +Running Gradle task 'assembleDebug'... 21.6s +√ Built build\app\outputs\flutter-apk\app-debug.apk +Installing build\app\outputs\flutter-apk\app-debug.apk... 1,948ms +I/FlutterActivityAndFragmentDelegate(13296): If you are attempting to set --enable-dart-profiling via Intent extras to launch a Flutter component outside of using the Flutter CLI, note that support for setting engine flags on Android via Intent will soon be dropped; see https://github.com/flutter/flutter/issues/180686 for more information on this breaking change. To migrate, set --enable-dart-profiling or any other flags specified via Intent extras on the command line instead or see https://github.com/flutter/flutter/blob/main/docs/engine/Flutter-Android-Engine-Flags.md for alternative methods. +D/FlutterJNI(13296): Beginning load of flutter... +D/FlutterJNI(13296): flutter (null) was loaded normally! +I/flutter (13296): [IMPORTANT:flutter/shell/platform/android/android_context_gl_impeller.cc(104)] Using the Impeller rendering backend (OpenGLES). +D/FlutterGeolocator(13296): Attaching Geolocator to activity +D/FlutterRenderer(13296): Width is zero. 0,0 +D/FlutterGeolocator(13296): Creating service. +D/FlutterGeolocator(13296): Binding to location service. +D/WindowOnBackDispatcher(13296): setTopOnBackInvokedCallback (unwrapped): android.app.Activity$$ExternalSyntheticLambda0@671fe96 +I/WindowExtensionsImpl(13296): Initializing Window Extensions, vendor API level=10, activity embedding enabled=true +W/UiContextUtils(13296): Requested context is a non-UI Context. Creating a UI-Context with display: 0. Context: Context=android.app.Application@9cf11e2, of which baseContext=android.app.ContextImpl@4c470b3 +I/xample.petfolio(13296): Compiler allocated 5250KB to compile void android.view.ViewRootImpl.performTraversals(long) +D/VRI[MainActivity](13296): WindowInsets changed: 1080x2424 statusBars:[0,142,0,0] navigationBars:[0,0,0,63] mandatorySystemGestures:[0,174,0,84] +D/FlutterRenderer(13296): Width is zero. 0,0 +I/Surface (13296): Creating surface for consumer unnamed-13296-0 with slotExpansion=1 for 64 slots +I/Surface (13296): Creating surface for consumer VRI[MainActivity]#0(BLAST Consumer)0 with slotExpansion=1 for 64 slots +D/FlutterJNI(13296): Sending viewport metrics to the engine. +I/Surface (13296): Creating surface for consumer unnamed-13296-1 with slotExpansion=1 for 64 slots +I/Surface (13296): Creating surface for consumer a518fa5 SurfaceView[com.example.petfolio/com.example.petfolio.MainActivity]#1(BLAST Consumer)1 with slotExpansion=1 for 64 slots +Syncing files to device sdk gphone16k x86 64... 158ms + +Flutter run key commands. +r Hot reload. +R Hot restart. +h List all available interactive commands. +d Detach (terminate "flutter run" but leave application running). +c Clear the screen +q Quit (terminate the application on the device). + +A Dart VM Service on sdk gphone16k x86 64 is available at: http://127.0.0.1:59006/M3CJt_KGSlU=/ +The Flutter DevTools debugger and profiler on sdk gphone16k x86 64 is available at: +http://127.0.0.1:59006/M3CJt_KGSlU=/devtools/?uri=ws://127.0.0.1:59006/M3CJt_KGSlU=/ws +D/FlutterGeolocator(13296): Geolocator foreground service connected +D/FlutterGeolocator(13296): Initializing Geolocator services +D/FlutterGeolocator(13296): Flutter engine connected. Connected engine count 1 +I/HWUI (13296): Using FreeType backend (prop=Auto) +I/Choreographer(13296): Skipped 40 frames! The application may be doing too much work on its main thread. +I/xample.petfolio(13296): hiddenapi: Accessing hidden method Landroid/os/SystemProperties;->addChangeCallback(Ljava/lang/Runnable;)V (runtime_flags=0, domain=platform, api=unsupported) from Landroidx/compose/ui/platform/AndroidComposeView$Companion; (domain=app, TargetSdkVersion=36) using reflection: allowed +D/WindowLayoutComponentImpl(13296): Register WindowLayoutInfoListener on Context=com.example.petfolio.MainActivity@bbce388, of which baseContext=android.app.ContextImpl@c56e043 +I/Choreographer(13296): Skipped 42 frames! The application may be doing too much work on its main thread. +I/flutter (13296): supabase.supabase_flutter: INFO: ***** Supabase init completed ***** +D/FlutterJNI(13296): Sending viewport metrics to the engine. +I/Choreographer(13296): Skipped 81 frames! The application may be doing too much work on its main thread. +D/InsetsController(13296): hide(ime()) +I/ImeTracker(13296): com.example.petfolio:dabbf2db: onCancelled at PHASE_CLIENT_ALREADY_HIDDEN +D/ProfileInstaller(13296): Installing profile for com.example.petfolio From 8ac21da357c5ff7a6a09c912873d9dc6ddb1a385 Mon Sep 17 00:00:00 2001 From: Syed Salman Reza Date: Tue, 2 Jun 2026 05:52:46 +0600 Subject: [PATCH 04/23] Adapt notifications API, bump deps, add KGP notes Update flutter_local_notifications usage to match the newer v21 API (use named params: initialize(settings: ...); zonedSchedule(id:, title:, body:, scheduledDate:, notificationDetails: ...); cancel(id: ...)). Bump dependencies in pubspec.yaml (geolocator, permission_handler, flutter_local_notifications, timezone). Add README section documenting Kotlin Gradle Plugin (KGP) migration status, current compat flags, blocked plugins, and migration steps to follow once plugins are updated. --- README.md | 43 +++++++++++++++++++++ lib/core/services/notification_service.dart | 16 ++++---- pubspec.yaml | 8 ++-- 3 files changed, 54 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index eea797e..fb329f0 100644 --- a/README.md +++ b/README.md @@ -74,3 +74,46 @@ flutter build apk --release --dart-define-from-file=.env ## Architecture Feature-first structure under `lib/features/`. Core shared code in `lib/core/`. See [CLAUDE.md](CLAUDE.md) and [docs/](docs/) for full architecture, schema, and implementation status. + +## Pending: Kotlin Gradle Plugin (KGP) Migration + +Flutter 3.44 introduced built-in Kotlin support in AGP, deprecating the explicit `id("kotlin-android")` + `kotlinOptions {}` pattern. The app and several plugins need to migrate before AGP 9.0 enforces the change. + +**Current workaround** — `android/gradle.properties` holds two compat flags added by the Flutter migrator: + +```properties +android.builtInKotlin=false +android.newDsl=false +``` + +These suppress build failures today but will be removed in a future Flutter release. + +**Blocked on these plugins releasing KGP-migrated versions:** + +| Plugin | Status | +|---|---| +| `image_picker_android` | Awaiting upstream release | +| `shared_preferences_android` | Awaiting upstream release | +| `url_launcher_android` | Awaiting upstream release | +| `share_plus` | Awaiting upstream release | +| `stripe_android` | Awaiting upstream release | + +**Migration steps (do all at once, after all plugins above are updated):** + +1. `flutter pub upgrade` — pull in the migrated plugin versions +2. In `android/app/build.gradle.kts`: + - Remove `id("kotlin-android")` from the `plugins {}` block + - Replace `kotlinOptions { jvmTarget = ... }` inside `android {}` with: + ```kotlin + kotlin { + compilerOptions { + jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 + } + } + ``` +3. In `android/gradle.properties`, delete (or flip to `true`) both compat flags: + ```properties + android.builtInKotlin=true + android.newDsl=true + ``` +4. Run `flutter build apk --debug` to confirm a clean build. diff --git a/lib/core/services/notification_service.dart b/lib/core/services/notification_service.dart index aed776b..50ba796 100644 --- a/lib/core/services/notification_service.dart +++ b/lib/core/services/notification_service.dart @@ -24,7 +24,7 @@ class NotificationService { ); await _plugin.initialize( - const InitializationSettings(android: androidSettings, iOS: iosSettings), + settings: const InitializationSettings(android: androidSettings, iOS: iosSettings), ); final androidPlugin = @@ -76,20 +76,18 @@ class NotificationService { ); await _plugin.zonedSchedule( - _idFor(taskId), - 'Care Reminder', - title, - scheduled, - NotificationDetails(android: androidDetails), + id: _idFor(taskId), + title: 'Care Reminder', + body: title, + scheduledDate: scheduled, + notificationDetails: NotificationDetails(android: androidDetails), androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle, matchDateTimeComponents: repeating ? DateTimeComponents.time : null, - uiLocalNotificationDateInterpretation: - UILocalNotificationDateInterpretation.absoluteTime, ); } Future cancelForTask(String taskId) async { - await _plugin.cancel(_idFor(taskId)); + await _plugin.cancel(id: _idFor(taskId)); } Future cancelAll() async { diff --git a/pubspec.yaml b/pubspec.yaml index 260e560..f837e63 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -68,12 +68,12 @@ dependencies: share_plus: ^13.1.0 url_launcher: ^6.3.1 - geolocator: ^13.0.4 - permission_handler: ^11.4.0 + geolocator: ^14.0.0 + permission_handler: ^12.0.0 # Local notifications - flutter_local_notifications: ^18.0.0 - timezone: ^0.9.4 + flutter_local_notifications: ^21.0.0 + timezone: ^0.11.0 http: ^1.6.0 uuid: ^4.5.1 From 2c45129e78d93e6e6f4862cd7275d0f53b10763b Mon Sep 17 00:00:00 2001 From: Syed Salman Reza Date: Tue, 2 Jun 2026 06:04:29 +0600 Subject: [PATCH 05/23] Update Claude settings and flutter run log Add additional diagnostic checks to .claude/settings.local.json (WebFetch entries for github.com, openjdk.org, inside.java, stackoverflow.com, docs.gradle.org; Bash(java -version); and a grep of pubspec.lock for specific Android plugins). Update flutter-run-log.md to reflect a new flutter run output including Java/Kotlin warnings, updated build and install timings, additional runtime log lines, and a new DevTools/Dart VM Service URL. --- .claude/settings.local.json | 9 +++- flutter-run-log.md | 87 ++++++++++++++++++++----------------- 2 files changed, 54 insertions(+), 42 deletions(-) diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 2e830ee..07beb5b 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -111,7 +111,14 @@ "Bash(Get-Content \"C:\\\\Users\\\\syedr\\\\AppData\\\\Local\\\\Temp\\\\claude\\\\G--GitHub-petfolio\\\\83d1e98f-3a1c-41fb-a000-787a9c3f0b74\\\\tasks\\\\bbq53bd0b.output\" -ErrorAction SilentlyContinue)", "Bash(Select-Object -Last 30)", "mcp__dart__hot_reload", - "mcp__dart__dtd" + "mcp__dart__dtd", + "WebFetch(domain:github.com)", + "WebFetch(domain:openjdk.org)", + "Bash(java -version)", + "WebFetch(domain:inside.java)", + "WebFetch(domain:stackoverflow.com)", + "WebFetch(domain:docs.gradle.org)", + "Bash(grep -E \"stripe_android|geolocator_android|flutter_local_notifications|permission_handler_android\" /c/Users/syedr/AppData/Local/Pub/Cache/hosted/pub.dev/../../../../../../../GitHub/petfolio/pubspec.lock | head -20)" ] } } diff --git a/flutter-run-log.md b/flutter-run-log.md index 04b9458..70fed5a 100644 --- a/flutter-run-log.md +++ b/flutter-run-log.md @@ -2,39 +2,51 @@ PS G:\GitHub\petfolio> flutter run --dart-define-from-file=.env Launching lib\main.dart on sdk gphone16k x86 64 in debug mode... WARNING: Your Android app project: app located at: G:\GitHub\petfolio\android\app\build.gradle.kts applies the Kotlin Gradle Plugin, which will cause build failures in future versions of Flutter. -Please migrate your app to Built-in Kotlin using this guide: https://docs.flutter.dev/release/breaking-changes/migrate-to-built-in-kotlin/for-app-developers +Please migrate your app to Built-in Kotlin using this guide: https://docs.flutter.dev/release/breaking-changes/migrate-to-built-in-kotlin/for-app-developers WARNING: Your app uses the following plugins that apply Kotlin Gradle Plugin (KGP): image_picker_android, share_plus, shared_preferences_android, stripe_android, url_launcher_android Future versions of Flutter will fail to build if your app uses plugins that apply KGP. -Please check the changelogs of these plugins and upgrade to a version that supports Built-in Kotlin. -If no such version exists, report the issue to the plugin. If necessary, here is a guide on filing +Please check the changelogs of these plugins and upgrade to a version that supports Built-in Kotlin. +If no such version exists, report the issue to the plugin. If necessary, here is a guide on filing an issue against a plugin: https://docs.flutter.dev/release/breaking-changes/migrate-to-built-in-kotlin/for-app-developers#report-incompatible-kotlin-gradle-plugin-usage-to-plugin-authors If you are a plugin author, please migrate your plugin to Built-in Kotlin using this guide: https://docs.flutter.dev/release/breaking-changes/migrate-to-built-in-kotlin/for-plugin-authors -Running Gradle task 'assembleDebug'... 21.6s +warning: [options] source value 8 is obsolete and will be removed in a future release +warning: [options] target value 8 is obsolete and will be removed in a future release +warning: [options] To suppress warnings about obsolete options, use -Xlint:-options. +3 warnings +Running Gradle task 'assembleDebug'... 51.4s √ Built build\app\outputs\flutter-apk\app-debug.apk -Installing build\app\outputs\flutter-apk\app-debug.apk... 1,948ms -I/FlutterActivityAndFragmentDelegate(13296): If you are attempting to set --enable-dart-profiling via Intent extras to launch a Flutter component outside of using the Flutter CLI, note that support for setting engine flags on Android via Intent will soon be dropped; see https://github.com/flutter/flutter/issues/180686 for more information on this breaking change. To migrate, set --enable-dart-profiling or any other flags specified via Intent extras on the command line instead or see https://github.com/flutter/flutter/blob/main/docs/engine/Flutter-Android-Engine-Flags.md for alternative methods. -D/FlutterJNI(13296): Beginning load of flutter... -D/FlutterJNI(13296): flutter (null) was loaded normally! -I/flutter (13296): [IMPORTANT:flutter/shell/platform/android/android_context_gl_impeller.cc(104)] Using the Impeller rendering backend (OpenGLES). -D/FlutterGeolocator(13296): Attaching Geolocator to activity -D/FlutterRenderer(13296): Width is zero. 0,0 -D/FlutterGeolocator(13296): Creating service. -D/FlutterGeolocator(13296): Binding to location service. -D/WindowOnBackDispatcher(13296): setTopOnBackInvokedCallback (unwrapped): android.app.Activity$$ExternalSyntheticLambda0@671fe96 -I/WindowExtensionsImpl(13296): Initializing Window Extensions, vendor API level=10, activity embedding enabled=true -W/UiContextUtils(13296): Requested context is a non-UI Context. Creating a UI-Context with display: 0. Context: Context=android.app.Application@9cf11e2, of which baseContext=android.app.ContextImpl@4c470b3 -I/xample.petfolio(13296): Compiler allocated 5250KB to compile void android.view.ViewRootImpl.performTraversals(long) -D/VRI[MainActivity](13296): WindowInsets changed: 1080x2424 statusBars:[0,142,0,0] navigationBars:[0,0,0,63] mandatorySystemGestures:[0,174,0,84] -D/FlutterRenderer(13296): Width is zero. 0,0 -I/Surface (13296): Creating surface for consumer unnamed-13296-0 with slotExpansion=1 for 64 slots -I/Surface (13296): Creating surface for consumer VRI[MainActivity]#0(BLAST Consumer)0 with slotExpansion=1 for 64 slots -D/FlutterJNI(13296): Sending viewport metrics to the engine. -I/Surface (13296): Creating surface for consumer unnamed-13296-1 with slotExpansion=1 for 64 slots -I/Surface (13296): Creating surface for consumer a518fa5 SurfaceView[com.example.petfolio/com.example.petfolio.MainActivity]#1(BLAST Consumer)1 with slotExpansion=1 for 64 slots -Syncing files to device sdk gphone16k x86 64... 158ms +Installing build\app\outputs\flutter-apk\app-debug.apk... 996ms +I/FlutterActivityAndFragmentDelegate(14767): If you are attempting to set --enable-dart-profiling via Intent extras to launch a Flutter component outside of using the Flutter CLI, note that support for setting engine flags on Android via Intent will soon be dropped; see https://github.com/flutter/flutter/issues/180686 for more information on this breaking change. To migrate, set --enable-dart-profiling or any other flags specified via Intent extras on the command line instead or see https://github.com/flutter/flutter/blob/main/docs/engine/Flutter-Android-Engine-Flags.md for alternative methods. +D/FlutterJNI(14767): Beginning load of flutter... +D/FlutterJNI(14767): flutter (null) was loaded normally! +I/flutter (14767): [IMPORTANT:flutter/shell/platform/android/android_context_gl_impeller.cc(104)] Using the Impeller rendering backend (OpenGLES). +D/FlutterGeolocator(14767): Attaching Geolocator to activity +D/FlutterRenderer(14767): Width is zero. 0,0 +D/FlutterGeolocator(14767): Creating service. +D/FlutterGeolocator(14767): Binding to location service. +D/WindowOnBackDispatcher(14767): setTopOnBackInvokedCallback (unwrapped): android.app.Activity$$ExternalSyntheticLambda0@671fe96 +I/WindowExtensionsImpl(14767): Initializing Window Extensions, vendor API level=10, activity embedding enabled=true +I/xample.petfolio(14767): Compiler allocated 5250KB to compile void android.view.ViewRootImpl.performTraversals(long) +W/UiContextUtils(14767): Requested context is a non-UI Context. Creating a UI-Context with display: 0. Context: Context=android.app.Application@9cf11e2, of which baseContext=android.app.ContextImpl@4c470b3 +D/VRI[MainActivity](14767): WindowInsets changed: 1080x2424 statusBars:[0,142,0,0] navigationBars:[0,0,0,63] mandatorySystemGestures:[0,174,0,84] +D/FlutterRenderer(14767): Width is zero. 0,0 +I/Surface (14767): Creating surface for consumer unnamed-14767-0 with slotExpansion=1 for 64 slots +I/Surface (14767): Creating surface for consumer VRI[MainActivity]#0(BLAST Consumer)0 with slotExpansion=1 for 64 slots +D/FlutterJNI(14767): Sending viewport metrics to the engine. +I/Surface (14767): Creating surface for consumer unnamed-14767-1 with slotExpansion=1 for 64 slots +I/Surface (14767): Creating surface for consumer a518fa5 SurfaceView[com.example.petfolio/com.example.petfolio.MainActivity]#1(BLAST Consumer)1 with slotExpansion=1 for 64 slots +D/FlutterGeolocator(14767): Geolocator foreground service connected +D/FlutterGeolocator(14767): Initializing Geolocator services +D/FlutterGeolocator(14767): Flutter engine connected. Connected engine count 1 +I/Choreographer(14767): Skipped 44 frames! The application may be doing too much work on its main thread. +I/HWUI (14767): Using FreeType backend (prop=Auto) +I/xample.petfolio(14767): hiddenapi: Accessing hidden method Landroid/os/SystemProperties;->addChangeCallback(Ljava/lang/Runnable;)V (runtime_flags=0, domain=platform, api=unsupported) from Landroidx/compose/ui/platform/AndroidComposeView$Companion; (domain=app, TargetSdkVersion=36) using reflection: allowed +D/WindowLayoutComponentImpl(14767): Register WindowLayoutInfoListener on Context=com.example.petfolio.MainActivity@bbce388, of which baseContext=android.app.ContextImpl@b6a02b5 +I/Choreographer(14767): Skipped 44 frames! The application may be doing too much work on its main thread. +Syncing files to device sdk gphone16k x86 64... 171ms Flutter run key commands. r Hot reload. @@ -44,20 +56,13 @@ d Detach (terminate "flutter run" but leave application running). c Clear the screen q Quit (terminate the application on the device). -A Dart VM Service on sdk gphone16k x86 64 is available at: http://127.0.0.1:59006/M3CJt_KGSlU=/ +A Dart VM Service on sdk gphone16k x86 64 is available at: http://127.0.0.1:54386/Ych0_YBW-GQ=/ The Flutter DevTools debugger and profiler on sdk gphone16k x86 64 is available at: -http://127.0.0.1:59006/M3CJt_KGSlU=/devtools/?uri=ws://127.0.0.1:59006/M3CJt_KGSlU=/ws -D/FlutterGeolocator(13296): Geolocator foreground service connected -D/FlutterGeolocator(13296): Initializing Geolocator services -D/FlutterGeolocator(13296): Flutter engine connected. Connected engine count 1 -I/HWUI (13296): Using FreeType backend (prop=Auto) -I/Choreographer(13296): Skipped 40 frames! The application may be doing too much work on its main thread. -I/xample.petfolio(13296): hiddenapi: Accessing hidden method Landroid/os/SystemProperties;->addChangeCallback(Ljava/lang/Runnable;)V (runtime_flags=0, domain=platform, api=unsupported) from Landroidx/compose/ui/platform/AndroidComposeView$Companion; (domain=app, TargetSdkVersion=36) using reflection: allowed -D/WindowLayoutComponentImpl(13296): Register WindowLayoutInfoListener on Context=com.example.petfolio.MainActivity@bbce388, of which baseContext=android.app.ContextImpl@c56e043 -I/Choreographer(13296): Skipped 42 frames! The application may be doing too much work on its main thread. -I/flutter (13296): supabase.supabase_flutter: INFO: ***** Supabase init completed ***** -D/FlutterJNI(13296): Sending viewport metrics to the engine. -I/Choreographer(13296): Skipped 81 frames! The application may be doing too much work on its main thread. -D/InsetsController(13296): hide(ime()) -I/ImeTracker(13296): com.example.petfolio:dabbf2db: onCancelled at PHASE_CLIENT_ALREADY_HIDDEN -D/ProfileInstaller(13296): Installing profile for com.example.petfolio +http://127.0.0.1:54386/Ych0_YBW-GQ=/devtools/?uri=ws://127.0.0.1:54386/Ych0_YBW-GQ=/ws +I/flutter (14767): supabase.supabase_flutter: INFO: ***** Supabase init completed ***** +D/FlutterJNI(14767): Sending viewport metrics to the engine. +I/Choreographer(14767): Skipped 85 frames! The application may be doing too much work on its main thread. +D/InsetsController(14767): hide(ime()) +I/ImeTracker(14767): com.example.petfolio:9b0c77f3: onCancelled at PHASE_CLIENT_ALREADY_HIDDEN +D/ProfileInstaller(14767): Installing profile for com.example.petfolio +I/xample.petfolio(14767): Background concurrent mark compact GC freed 6145KB AllocSpace bytes, 20(832KB) LOS objects, 49% free, 5194KB/10MB, paused 906us,5.160ms total 16.410ms From d0e21726ac57309556fa1733d77c1a773a425ced Mon Sep 17 00:00:00 2001 From: Syed Salman Reza Date: Wed, 3 Jun 2026 22:14:53 +0600 Subject: [PATCH 06/23] Add PWA onboarding, web config, and tooling files Introduce iOS PWA support and developer automation: add PWA detection (lib/core/utils/pwa_detector.*) and a PwaOnboardingPrompt widget integrated into AppShell and exported from widgets.dart; update web/index.html and web/manifest.json with branding, viewport/splash images, and safe-area styling; add web dependency in pubspec.yaml. Also add Claude/agent/skill and MCP tooling configs (.claude/*, .codex/config.toml, .cursor/*, .gemini/settings.json, .mcp.json, .vscode/mcp.json), new skills for migration and feature scaffolding, update CLAUDE.md with a codebase map and automation docs, and refine .cursorignore to better exclude platform/build noise and lock files. These changes enable PWA onboarding for iOS web users and add project tooling/automation for developers. --- .claude/agents/security-reviewer.md | 51 ++++ .claude/settings.json | 26 ++ .claude/settings.local.json | 21 +- .claude/skills/create-migration/SKILL.md | 45 ++++ .claude/skills/new-feature/SKILL.md | 48 ++++ .codex/config.toml | 3 + .cursor/mcp.json | 7 + .cursorignore | 175 ++++++++----- .gemini/settings.json | 8 + .mcp.json | 8 + .vscode/mcp.json | 8 + CLAUDE.md | 64 ++++- lib/core/utils/pwa_detector.dart | 7 + lib/core/utils/pwa_detector_stub.dart | 1 + lib/core/utils/pwa_detector_web.dart | 41 +++ lib/core/widgets/app_shell.dart | 4 + lib/core/widgets/pwa_onboarding_prompt.dart | 274 ++++++++++++++++++++ lib/core/widgets/widgets.dart | 1 + pubspec.yaml | 1 + web/index.html | 54 +++- web/manifest.json | 10 +- 21 files changed, 772 insertions(+), 85 deletions(-) create mode 100644 .claude/agents/security-reviewer.md create mode 100644 .claude/settings.json create mode 100644 .claude/skills/create-migration/SKILL.md create mode 100644 .claude/skills/new-feature/SKILL.md create mode 100644 .codex/config.toml create mode 100644 .cursor/mcp.json create mode 100644 .gemini/settings.json create mode 100644 .mcp.json create mode 100644 .vscode/mcp.json create mode 100644 lib/core/utils/pwa_detector.dart create mode 100644 lib/core/utils/pwa_detector_stub.dart create mode 100644 lib/core/utils/pwa_detector_web.dart create mode 100644 lib/core/widgets/pwa_onboarding_prompt.dart diff --git a/.claude/agents/security-reviewer.md b/.claude/agents/security-reviewer.md new file mode 100644 index 0000000..e5e7fe0 --- /dev/null +++ b/.claude/agents/security-reviewer.md @@ -0,0 +1,51 @@ +--- +name: security-reviewer +description: Adversarial security reviewer for Petfolio. Focuses on Stripe payment flows, KYC document handling, Supabase RLS policies, auth guards, and exposed secrets. Invoke before merging any PR that touches payments, auth, or admin features. +--- + +You are an adversarial security reviewer specializing in Flutter/Supabase apps with Stripe payments, KYC workflows, and marketplace features. + +## Your Mandate + +Review the specified files and produce a prioritised finding list. Default to **suspicious** — assume every piece of code is wrong until proven correct. + +## Checklist + +### Supabase RLS +- Every table that stores user data MUST have RLS enabled. Flag any table without `alter table ... enable row level security`. +- Policies MUST use `auth.uid()` — never a mutable column like `user_id` passed as input. +- Service-role calls from Edge Functions must be justified; flag any use of the service key in client-side code. + +### Stripe +- Webhook handlers MUST verify `Stripe-Signature` before processing. Flag any handler missing `constructEvent`. +- Payment amounts must be computed server-side (Edge Function or Supabase RPC), never passed from the client. +- Flag any `flutter_stripe` call where the amount originates from user-controlled input without server confirmation. + +### KYC / Document Uploads +- KYC documents (ID scans, selfies) must be stored in a **private** Supabase storage bucket. Flag any upload to a public bucket. +- Signed URLs must have a short TTL (< 1 hour). Flag any `createSignedUrl` with `expiresIn > 3600`. + +### Auth & Navigation Guards +- Every protected GoRouter route must check `supabase.auth.currentSession` or a Riverpod auth provider. Flag routes missing a redirect guard. +- Flag any `context.go()` / `context.push()` that bypasses auth state by navigating directly to a privileged screen. + +### Secrets & Configuration +- Flag any Supabase URL, anon key, or Stripe key hardcoded in `.dart` files outside of `--dart-define` patterns. +- Flag any API key committed directly in source (look for `sk_`, `pk_`, `eyJ`). + +### Admin Panel +- Admin routes must verify `is_admin` via a server-side RLS policy or RPC — never trust a client-side flag alone. +- Flag any admin action (delete, approve, reject) missing a server-side authorization check. + +## Output Format + +For each finding, output: + +``` +[CRITICAL|HIGH|MEDIUM] +File: : +Issue: +Fix: +``` + +Group by severity. End with a one-line summary: "X critical, Y high, Z medium findings." diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..e0951c1 --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,26 @@ +{ + "hooks": { + "PreToolUse": [ + { + "matcher": "Edit|Write", + "hooks": [ + { + "type": "command", + "command": "powershell -NonInteractive -Command \"$raw=[Console]::In.ReadToEnd();try{$f=($raw|ConvertFrom-Json).file_path;if($f-match'[.](g|freezed)[.]dart$'){Write-Host 'ERROR: Do not edit generated files. Edit the source and run build_runner.';exit 2}}catch{};exit 0\"" + } + ] + } + ], + "PostToolUse": [ + { + "matcher": "Edit|Write", + "hooks": [ + { + "type": "command", + "command": "powershell -NonInteractive -Command \"$raw=[Console]::In.ReadToEnd();try{$f=($raw|ConvertFrom-Json).file_path;if($f-match'[.]dart$'-and$f-notmatch'[.](g|freezed)[.]dart$'){$c=Get-Content $f -Raw -EA SilentlyContinue;if($c-and$c-match'@(freezed|Riverpod|JsonSerializable)'){Write-Host 'HINT: Annotation detected — remember to run: dart run build_runner build -d'}}}catch{};exit 0\"" + } + ] + } + ] + } +} diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 07beb5b..eadebc4 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -118,7 +118,26 @@ "WebFetch(domain:inside.java)", "WebFetch(domain:stackoverflow.com)", "WebFetch(domain:docs.gradle.org)", - "Bash(grep -E \"stripe_android|geolocator_android|flutter_local_notifications|permission_handler_android\" /c/Users/syedr/AppData/Local/Pub/Cache/hosted/pub.dev/../../../../../../../GitHub/petfolio/pubspec.lock | head -20)" + "Bash(grep -E \"stripe_android|geolocator_android|flutter_local_notifications|permission_handler_android\" /c/Users/syedr/AppData/Local/Pub/Cache/hosted/pub.dev/../../../../../../../GitHub/petfolio/pubspec.lock | head -20)", + "Bash(find ~/.claude -name \"CLAUDE.md\" 2>/dev/null | head -10)", + "Skill(deep-research)", + "Skill(deep-research:*)", + "WebFetch(domain:cleancodestack.com)", + "WebFetch(domain:vinova.sg)", + "WebFetch(domain:firt.dev)", + "WebFetch(domain:www.magicbell.com)", + "Bash(gh issue *)", + "WebFetch(domain:ravi6997.medium.com)", + "WebFetch(domain:brainhub.eu)", + "WebFetch(domain:www.mobiloud.com)", + "WebFetch(domain:scandiweb.com)", + "WebFetch(domain:mohanrajmuthukumaran.hashnode.dev)", + "WebFetch(domain:dev.to)", + "WebFetch(domain:medium.com)", + "WebFetch(domain:flutternest.com)", + "WebFetch(domain:firebase.google.com)", + "WebFetch(domain:chipsoffury.com)", + "WebFetch(domain:dasroot.net)" ] } } diff --git a/.claude/skills/create-migration/SKILL.md b/.claude/skills/create-migration/SKILL.md new file mode 100644 index 0000000..55121be --- /dev/null +++ b/.claude/skills/create-migration/SKILL.md @@ -0,0 +1,45 @@ +--- +name: create-migration +description: Scaffold a new Supabase migration file with a correct timestamp name and a commented RLS template. Use when the user asks to create a migration, add a table, or modify the schema. +disable-model-invocation: true +--- + +# Create Supabase Migration + +## Steps + +1. Ask the user for a migration name if not provided via args (use snake_case, e.g. `add_notifications_table`). + +2. Generate the current timestamp in `yyyyMMddHHmmss` format using PowerShell: + ```powershell + Get-Date -Format 'yyyyMMddHHmmss' + ``` + +3. Create the file at `supabase/migrations/_.sql` with this template: + ```sql + -- ============================================================ + -- Migration: + -- Created: + -- ============================================================ + + -- TABLE DEFINITION + -- create table public. ( + -- id uuid primary key default gen_random_uuid(), + -- created_at timestamptz not null default now() + -- ); + + -- RLS + -- alter table public. enable row level security; + + -- POLICIES + -- create policy "Users can read own rows" + -- on public. for select + -- using (auth.uid() = user_id); + ``` + +4. Print: "Migration created: supabase/migrations/. Edit the SQL, then run: npx supabase db reset" + +5. Update `progress.md` — append under the current phase: + - `Schema: migration scaffolded` + +6. Remind the user: "Phase update logged — run /remember to save tokens before continuing." diff --git a/.claude/skills/new-feature/SKILL.md b/.claude/skills/new-feature/SKILL.md new file mode 100644 index 0000000..de6f62d --- /dev/null +++ b/.claude/skills/new-feature/SKILL.md @@ -0,0 +1,48 @@ +--- +name: new-feature +description: Scaffold a new Petfolio feature directory with the standard feature-first structure (data/models, data/repositories, presentation/controllers, presentation/widgets, presentation/screens). Use when starting a new feature from scratch. +disable-model-invocation: true +--- + +# New Feature Scaffold + +## Steps + +1. Ask the user for the feature name if not provided via args (use snake_case, e.g. `notifications`). + +2. Create these directories under `lib/features//`: + - `data/models/` + - `data/repositories/` + - `presentation/controllers/` + - `presentation/widgets/` + - `presentation/screens/` + +3. Add an empty `.gitkeep` file to each directory (so git tracks them). + +4. Create a stub screen file at `lib/features//presentation/screens/_screen.dart`: + ```dart + import 'package:flutter/material.dart'; + + class Screen extends StatelessWidget { + const Screen({super.key}); + + @override + Widget build(BuildContext context) { + return const Scaffold( + body: Center(child: Text('')), + ); + } + } + ``` + +5. Print the next steps checklist: + ``` + Feature '' scaffolded. Follow the Petfolio implementation order: + 1. supabase/migrations/ — SQL schema + RLS (/create-migration) + 2. data/models/ — Freezed model + JsonSerializable + 3. data/repositories/ — Supabase repository class + 4. presentation/controllers/ — Riverpod controller + 5. presentation/screens/ — UI screens + ``` + +6. Update `progress.md` — append: `Feature scaffold: created` diff --git a/.codex/config.toml b/.codex/config.toml new file mode 100644 index 0000000..04ac0b0 --- /dev/null +++ b/.codex/config.toml @@ -0,0 +1,3 @@ +[mcp_servers.vercel] +type = "http" +url = "https://mcp.vercel.com" diff --git a/.cursor/mcp.json b/.cursor/mcp.json new file mode 100644 index 0000000..59e9589 --- /dev/null +++ b/.cursor/mcp.json @@ -0,0 +1,7 @@ +{ + "mcpServers": { + "vercel": { + "url": "https://mcp.vercel.com" + } + } +} \ No newline at end of file diff --git a/.cursorignore b/.cursorignore index 631c1be..fd98048 100644 --- a/.cursorignore +++ b/.cursorignore @@ -1,17 +1,10 @@ # ========================================== -# 1. SECURITY & SECRETS (CRITICAL) +# 1. PETFOLIO SPECIFIC NOISE (CRITICAL TO IGNORE) # ========================================== - -*.key -*.pem -credentials.json -supabase/.temp/ - -# ========================================== -# 2. PETFOLIO SPECIFIC NOISE -# ========================================== -# Prevents AI from reading massive UI mockups & QA logs -claude_design/ +# These folders contain hundreds of HTML, JSX, XML, and PNG +# files from UI audits and design stitches. They will flood +# the context window and cause severe token bloat. +docs/resolved-deprecated/claude_design/ docs/logs/ qa-screens/ redesign_stitch/ @@ -21,7 +14,7 @@ stitch_petsphere_app_redesign/ *.jsx # ========================================== -# 3. FLUTTER BUILD & CACHE +# 2. FLUTTER BUILD & CACHE # ========================================== build/ .dart_tool/ @@ -29,68 +22,96 @@ build/ .pub/ # ========================================== -# 4. CODE GENERATION +# 3. CODE GENERATION # ========================================== -# Forces AI to rely on your models, not the generated outputs +# Ignore generated files so the AI doesn't try to edit them directly *.g.dart *.freezed.dart *.mocks.dart *.part.dart # ========================================== -# 5. NATIVE PLATFORM DIRECTORIES -# ========================================== -android/.gradle -android/.kotlin -android/gradle-wrapper.jar -android/captures/ -android/gradlew -android/gradlew.bat -android/local.properties -android/GeneratedPluginRegistrant.java -android/.cxx/ - -ios/**/dgph -ios/*.mode1v3 -ios/*.mode2v3 -ios/*.moved-aside -ios/*.pbxuser -ios/*.perspectivev3 -ios/**/*sync/ -ios/.sconsign.dblite -ios/.tags* -ios/**/.vagrant/ -ios/**/DerivedData/ -ios/Icon? -ios/**/Pods/ -ios/**/.symlinks/ -ios/profile -ios/xcuserdata -ios/**/.generated/ -ios/Flutter/App.framework -ios/Flutter/Flutter.framework -ios/Flutter/Flutter.podspec -ios/Flutter/Generated.xcconfig -ios/Flutter/ephemeral/ -ios/Flutter/app.flx -ios/Flutter/app.zip -ios/Flutter/flutter_assets/ -ios/Flutter/flutter_export_environment.sh -ios/ServiceDefinitions.json -ios/Runner/GeneratedPluginRegistrant.* - - - -web/ -macos/ -windows/ -linux/ - -# ========================================== -# 6. ASSETS & MEDIA -# ========================================== -assets/ -google_fonts/ +# 4. NATIVE PLATFORM DIRECTORIES +# ========================================== +# Unless you are specifically asking the agent to write Kotlin/Swift, +# keep these ignored so it focuses on the `lib/` directory. + +# Android related +**/android/**/gradle-wrapper.jar +.gradle/ +**/android/captures/ +**/android/gradlew +**/android/gradlew.bat +**/android/local.properties +**/android/**/GeneratedPluginRegistrant.java +**/android/key.properties +*.jks + +# iOS/XCode related +**/ios/**/*.mode1v3 +**/ios/**/*.mode2v3 +**/ios/**/*.moved-aside +**/ios/**/*.pbxuser +**/ios/**/*.perspectivev3 +**/ios/**/*sync/ +**/ios/**/.sconsign.dblite +**/ios/**/.tags* +**/ios/**/.vagrant/ +**/ios/**/DerivedData/ +**/ios/**/Icon? +**/ios/**/Pods/ +**/ios/**/.symlinks/ +**/ios/**/profile +**/ios/**/xcuserdata +**/ios/.generated/ +**/ios/Flutter/.last_build_id +**/ios/Flutter/App.framework +**/ios/Flutter/Flutter.framework +**/ios/Flutter/Flutter.podspec +**/ios/Flutter/Generated.xcconfig +**/ios/Flutter/ephemeral +**/ios/Flutter/app.flx +**/ios/Flutter/app.zip +**/ios/Flutter/flutter_assets/ +**/ios/Flutter/flutter_export_environment.sh +**/ios/ServiceDefinitions.json +**/ios/Runner/GeneratedPluginRegistrant.* + +# macOS +**/Flutter/ephemeral/ +**/Pods/ +**/macos/Flutter/GeneratedPluginRegistrant.swift +**/macos/Flutter/ephemeral +**/xcuserdata/ + +# Windows +**/windows/flutter/generated_plugin_registrant.cc +**/windows/flutter/generated_plugin_registrant.h +**/windows/flutter/generated_plugins.cmake + +# Linux +**/linux/flutter/generated_plugin_registrant.cc +**/linux/flutter/generated_plugin_registrant.h +**/linux/flutter/generated_plugins.cmake + +# Coverage +coverage/ + +# Symbols +app.*.symbols + +# Exceptions to above rules. +!**/ios/**/default.mode1v3 +!**/ios/**/default.mode2v3 +!**/ios/**/default.pbxuser +!**/ios/**/default.perspectivev3 +!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages +!/dev/ci/**/Gemfile.lock + +# ========================================== +# 5. ASSETS & MEDIA +# ========================================== + *.png *.jpg *.jpeg @@ -101,13 +122,23 @@ google_fonts/ *.zip # ========================================== -# 7. IDE & ENVIRONMENT +# 6. SUPABASE LOCAL STATE +# ========================================== +supabase/.temp/ + +# ========================================== +# 7. DEPENDENCY LOCKS +# ========================================== +pubspec.lock +skills-lock.json + +# ========================================== +# 8. IDE & ENVIRONMENT # ========================================== .idea/ .vscode/ .claude/ -.cursor/hooks/ + +.cursor/ *.iml .metadata -pubspec.lock -skills-lock.json \ No newline at end of file diff --git a/.gemini/settings.json b/.gemini/settings.json new file mode 100644 index 0000000..156949e --- /dev/null +++ b/.gemini/settings.json @@ -0,0 +1,8 @@ +{ + "mcpServers": { + "vercel": { + "type": "http", + "url": "https://mcp.vercel.com" + } + } +} \ No newline at end of file diff --git a/.mcp.json b/.mcp.json new file mode 100644 index 0000000..156949e --- /dev/null +++ b/.mcp.json @@ -0,0 +1,8 @@ +{ + "mcpServers": { + "vercel": { + "type": "http", + "url": "https://mcp.vercel.com" + } + } +} \ No newline at end of file diff --git a/.vscode/mcp.json b/.vscode/mcp.json new file mode 100644 index 0000000..8f4fdd9 --- /dev/null +++ b/.vscode/mcp.json @@ -0,0 +1,8 @@ +{ + "servers": { + "vercel": { + "type": "http", + "url": "https://mcp.vercel.com" + } + } +} \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md index 1abe6f9..edaaeb1 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -53,6 +53,33 @@ flutter run \ --dart-define=STRIPE_PUBLISHABLE_KEY=pk_test_... ``` +## Codebase Map + +``` +lib/ + core/ + router.dart # All GoRouter routes — add new routes here + theme/ + app_colors.dart # Colour palette — never hardcode colours, use this + app_theme.dart # ThemeData — use AppTheme.light / AppTheme.dark + services/ # Cross-feature services (e.g. CareRecommendationService) + widgets/ # Shared UI widgets + features/ + auth/ # Sign-in, sign-up, session + care/ # Health logs, medical records, streaks, badges + marketplace/ # Shops, products, cart, checkout, KYC, vendor ledger + matching/ # Discovery/swipe, mutual matches, chat + pet_profile/ # Pet creation, onboarding, profile editing + social/ # Feed, stories, follows, search + admin/ # Moderation, KYC review, ledger, COD orders +supabase/ + migrations/ # Timestamped SQL migrations (yyyyMMddHHmmss_name.sql) + functions/ + create-payment-intent/ # Called by CheckoutController before Stripe confirm + stripe-onboard-vendor/ # KYC vendor onboarding flow + stripe-webhook/ # Stripe event handler — has service-role RLS bypass +``` + ## Common Commands ### Run The App @@ -63,12 +90,12 @@ flutter run ### Code Generation Run after modifying any `@freezed`, `@JsonSerializable`, or `@riverpod` annotated class: ```bash -flutter pub run build_runner build --delete-conflicting-outputs +dart run build_runner build -d ``` Watch mode: ```bash -flutter pub run build_runner watch +dart run build_runner watch ``` ### Static Analysis @@ -87,6 +114,39 @@ flutter build apk --debug # debug flutter build apk --release # release ``` +### Supabase Edge Functions +```bash +npx supabase functions deploy # deploy a single function +npx supabase functions deploy # deploy all functions +npx supabase db reset # apply all migrations locally +``` + +## Claude Automations + +### Skills (user-invocable via `/`) +| Skill | Purpose | +|-------|---------| +| `/create-migration` | Scaffolds a timestamped `supabase/migrations/` SQL file with RLS template | +| `/new-feature` | Scaffolds the full `lib/features//` directory tree | +| `/flutter-ui-ux` | Flutter UI/UX implementation patterns | + +### Agents +| Agent | When to invoke | +|-------|---------------| +| `security-reviewer` | Before merging any PR touching payments, KYC, auth, or admin | + +### Pending MCP Setup +- **context7** — live docs for riverpod/go_router/supabase_flutter/stripe (all on fast-moving versions). Install: `claude mcp add context7 -- npx -y @upstash/context7-mcp` + +### Hooks (`.claude/settings.json`) +- **PreToolUse** on Edit/Write: blocks accidental edits to `.g.dart` / `.freezed.dart` generated files +- **PostToolUse** on Edit/Write: hints `dart run build_runner build -d` when an annotated source file is saved + +### Config Files +- `.claude/settings.json` — project hooks (checked into git, shared) +- `.claude/settings.local.json` — personal tool permissions (gitignored, not shared) +- When writing PowerShell hook commands: always end with `;exit 0` — caught exceptions still set exit code 1 otherwise + ## Project Rules & Token Optimization Strategy ### 1. Strict No-Documentation Rule (Implementation Only) diff --git a/lib/core/utils/pwa_detector.dart b/lib/core/utils/pwa_detector.dart new file mode 100644 index 0000000..05c3738 --- /dev/null +++ b/lib/core/utils/pwa_detector.dart @@ -0,0 +1,7 @@ +import 'pwa_detector_stub.dart' + if (dart.library.js_interop) 'pwa_detector_web.dart' + as impl; + +/// Returns true if the app is currently running in a web browser on an iOS device +/// (iPhone/iPad/iPod) but is not installed or running in standalone PWA mode. +bool isIOSWebNotStandalone() => impl.isIOSWebNotStandalone(); diff --git a/lib/core/utils/pwa_detector_stub.dart b/lib/core/utils/pwa_detector_stub.dart new file mode 100644 index 0000000..972ec7a --- /dev/null +++ b/lib/core/utils/pwa_detector_stub.dart @@ -0,0 +1 @@ +bool isIOSWebNotStandalone() => false; diff --git a/lib/core/utils/pwa_detector_web.dart b/lib/core/utils/pwa_detector_web.dart new file mode 100644 index 0000000..f3dfb1a --- /dev/null +++ b/lib/core/utils/pwa_detector_web.dart @@ -0,0 +1,41 @@ +// ignore_for_file: avoid_web_libraries_in_flutter + +import 'dart:js_interop'; + +@JS('window.navigator.userAgent') +external JSString? get _jsUserAgent; + +@JS('window.navigator.standalone') +external JSBoolean? get _jsStandalone; + +@JS('window.matchMedia') +external JSObject? _jsMatchMedia(JSString query); + +extension type _MediaQueryList(JSObject _) implements JSObject { + external bool get matches; +} + +bool isIOSWebNotStandalone() { + try { + final ua = _jsUserAgent?.toDart.toLowerCase() ?? ''; + final isIOS = ua.contains('iphone') || + ua.contains('ipad') || + ua.contains('ipod'); + if (!isIOS) return false; + + // 1. Check iOS Safari specific property navigator.standalone + final isStandalone = _jsStandalone?.toDart ?? false; + if (isStandalone) return false; + + // 2. Check W3C standard media query display-mode + final mql = _jsMatchMedia('(display-mode: standalone)'.toJS); + if (mql != null) { + final matches = _MediaQueryList(mql).matches; + if (matches) return false; + } + + return true; + } catch (_) { + return false; + } +} diff --git a/lib/core/widgets/app_shell.dart b/lib/core/widgets/app_shell.dart index 2c85c02..39ec456 100644 --- a/lib/core/widgets/app_shell.dart +++ b/lib/core/widgets/app_shell.dart @@ -11,6 +11,7 @@ import 'package:petfolio/features/matching/presentation/matching_navigation.dart import 'package:petfolio/features/matching/presentation/widgets/match_preferences_sheet.dart'; import 'package:petfolio/features/pet_profile/presentation/controllers/active_pet_controller.dart'; import 'package:petfolio/features/pet_profile/presentation/widgets/pet_switcher_sheet.dart'; +import 'package:petfolio/core/widgets/pwa_onboarding_prompt.dart'; // ── Tab accent colors (matches design system pillar colors) ────────────────── const tabAccentColors = [ @@ -62,6 +63,9 @@ class AppShell extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { + WidgetsBinding.instance.addPostFrameCallback((_) { + PwaOnboardingPrompt.checkAndShow(context); + }); final selectedIndex = _selectedIndex(context); final isWide = MediaQuery.sizeOf(context).width >= 600; diff --git a/lib/core/widgets/pwa_onboarding_prompt.dart b/lib/core/widgets/pwa_onboarding_prompt.dart new file mode 100644 index 0000000..69d7e47 --- /dev/null +++ b/lib/core/widgets/pwa_onboarding_prompt.dart @@ -0,0 +1,274 @@ +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +import 'package:petfolio/core/theme/app_colors.dart'; +import 'package:petfolio/core/theme/app_theme.dart'; +import 'package:petfolio/core/widgets/primary_pill_button.dart'; +import 'package:petfolio/core/utils/pwa_detector.dart'; + +class PwaOnboardingPrompt extends StatelessWidget { + const PwaOnboardingPrompt({super.key}); + + /// Checks if the platform is iOS Web (excluding standalone mode) and if the prompt + /// has not been recently dismissed, and shows the onboarding bottom sheet after a short delay. + static Future checkAndShow(BuildContext context) async { + // 1. Check if iOS web and not running as PWA yet + if (!isIOSWebNotStandalone()) return; + + // 2. Check SharedPreferences dismissal cache (snooze for 7 days) + try { + final prefs = await SharedPreferences.getInstance(); + final dismissedTime = prefs.getInt('pwa_prompt_dismissed_at'); + if (dismissedTime != null) { + final dismissedDate = DateTime.fromMillisecondsSinceEpoch(dismissedTime); + final difference = DateTime.now().difference(dismissedDate); + if (difference.inDays < 7) { + return; + } + } + } catch (_) { + // In case SharedPreferences fails, we still proceed with showing + } + + // 3. Show sheet after a 2-second delay to ensure smooth app boot + if (!context.mounted) return; + Future.delayed(const Duration(seconds: 2), () { + if (!context.mounted) return; + showModalBottomSheet( + context: context, + isScrollControlled: true, + useRootNavigator: true, + backgroundColor: Colors.transparent, + constraints: const BoxConstraints(maxWidth: 500), + builder: (context) => const PwaOnboardingPrompt(), + ); + }); + } + + Future _dismissPrompt(BuildContext context, {bool permanent = false}) async { + try { + final prefs = await SharedPreferences.getInstance(); + // If permanent, we set a timestamp far in the future or a custom flag, otherwise standard 7-day snooze + final timestamp = permanent + ? DateTime.now().add(const Duration(days: 365)).millisecondsSinceEpoch + : DateTime.now().millisecondsSinceEpoch; + await prefs.setInt('pwa_prompt_dismissed_at', timestamp); + } catch (_) {} + + if (context.mounted) { + Navigator.of(context).pop(); + } + } + + @override + Widget build(BuildContext context) { + final isDark = Theme.of(context).brightness == Brightness.dark; + final pt = Theme.of(context).extension()!; + + return Container( + decoration: BoxDecoration( + color: isDark ? AppColors.surface0D : AppColors.surface0, + borderRadius: const BorderRadius.vertical(top: Radius.circular(32)), + border: Border( + top: BorderSide(color: isDark ? AppColors.lineD : AppColors.line), + ), + ), + padding: EdgeInsets.fromLTRB(20, 16, 20, 16 + MediaQuery.paddingOf(context).bottom), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + // Drag handle + Center( + child: Container( + width: 48, + height: 5, + decoration: BoxDecoration( + color: isDark ? AppColors.lineD : AppColors.line, + borderRadius: BorderRadius.circular(999), + ), + ), + ), + const SizedBox(height: 18), + + // Header + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Container( + width: 36, + height: 36, + decoration: BoxDecoration( + color: isDark ? AppColors.tangerineSoftD : AppColors.tangerineSoft, + shape: BoxShape.circle, + ), + alignment: Alignment.center, + child: Text( + '🐾', + style: GoogleFonts.inter(fontSize: 18), + ), + ), + const SizedBox(width: 12), + Text( + 'Install PetFolio', + style: GoogleFonts.sora( + fontSize: 18, + fontWeight: FontWeight.w800, + color: pt.ink950, + ), + ), + ], + ), + IconButton( + icon: const Icon(Icons.close_rounded), + onPressed: () => _dismissPrompt(context, permanent: false), + color: pt.ink500, + splashRadius: 20, + ), + ], + ), + const SizedBox(height: 16), + + // Description text + Text( + 'Add PetFolio to your home screen to launch it in full-screen standalone mode and get a complete app experience.', + style: GoogleFonts.inter( + fontSize: 14, + fontWeight: FontWeight.w500, + color: pt.ink700, + height: 1.4, + ), + ), + const SizedBox(height: 24), + + // Steps list + _buildStepRow( + context, + index: '1', + text: 'Tap the Share button in Safari\'s bottom toolbar.', + trailing: const Icon( + Icons.ios_share_rounded, + color: Colors.blue, + size: 20, + ), + ), + const SizedBox(height: 14), + _buildStepRow( + context, + index: '2', + text: 'Scroll down and select Add to Home Screen.', + trailing: Container( + padding: const EdgeInsets.all(4), + decoration: BoxDecoration( + border: Border.all(color: pt.ink300, width: 1.5), + borderRadius: BorderRadius.circular(6), + ), + child: Icon( + Icons.add_rounded, + color: pt.ink950, + size: 14, + ), + ), + ), + const SizedBox(height: 14), + _buildStepRow( + context, + index: '3', + text: 'Tap Add in the top-right corner to install.', + trailing: Text( + 'Add', + style: GoogleFonts.inter( + color: Colors.blue, + fontWeight: FontWeight.w700, + fontSize: 14, + ), + ), + ), + const SizedBox(height: 28), + + // Action Buttons + Row( + children: [ + Expanded( + child: TextButton( + onPressed: () => _dismissPrompt(context, permanent: true), + child: Text( + 'Don\'t show again', + style: GoogleFonts.inter( + fontSize: 14, + fontWeight: FontWeight.w600, + color: pt.ink500, + ), + ), + ), + ), + const SizedBox(width: 12), + Expanded( + flex: 2, + child: PrimaryPillButton( + label: 'Got it', + size: PillButtonSize.md, + variant: PillButtonVariant.primary, + onPressed: () => _dismissPrompt(context, permanent: false), + ), + ), + ], + ), + const SizedBox(height: 8), + ], + ), + ); + } + + Widget _buildStepRow( + BuildContext context, { + required String index, + required String text, + required Widget trailing, + }) { + final isDark = Theme.of(context).brightness == Brightness.dark; + final pt = Theme.of(context).extension()!; + + return Row( + children: [ + Container( + width: 28, + height: 28, + decoration: BoxDecoration( + color: isDark ? AppColors.tangerineSoftD : AppColors.tangerineSoft, + shape: BoxShape.circle, + ), + alignment: Alignment.center, + child: Text( + index, + style: GoogleFonts.sora( + fontSize: 13, + fontWeight: FontWeight.w800, + color: isDark ? AppColors.tangerine700D : AppColors.tangerine700, + ), + ), + ), + const SizedBox(width: 16), + Expanded( + child: Text( + text, + style: GoogleFonts.inter( + fontSize: 14, + fontWeight: FontWeight.w600, + color: pt.ink950, + ), + ), + ), + const SizedBox(width: 16), + Container( + width: 44, + alignment: Alignment.center, + child: trailing, + ), + ], + ); + } +} diff --git a/lib/core/widgets/widgets.dart b/lib/core/widgets/widgets.dart index a9a12a2..d3c0abb 100644 --- a/lib/core/widgets/widgets.dart +++ b/lib/core/widgets/widgets.dart @@ -15,4 +15,5 @@ export 'wave_header.dart'; export 'pf_card.dart'; export 'responsive_layout.dart'; export 'app_shell.dart'; +export 'pwa_onboarding_prompt.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index f837e63..adf81ab 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -76,6 +76,7 @@ dependencies: timezone: ^0.11.0 http: ^1.6.0 uuid: ^4.5.1 + web: ^1.1.1 dev_dependencies: flutter_test: diff --git a/web/index.html b/web/index.html index 72bda0f..b6f66a1 100644 --- a/web/index.html +++ b/web/index.html @@ -18,20 +18,64 @@ - + - + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - petfolio + PetFolio + + + - - - - + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - PetFolio + petfolio - - - + - This is a placeholder for base href that will be replaced by the value of - the `--base-href` argument provided to `flutter build`. - --> - + - - - + + + - + - - - + + + + + + + - + - petfolio + PetFolio + + + + - + +

+ + + + + + diff --git a/web/manifest.json b/web/manifest.json index 2e485d6..286e3e8 100644 --- a/web/manifest.json +++ b/web/manifest.json @@ -1,13 +1,16 @@ { - "name": "petfolio", - "short_name": "petfolio", - "start_url": ".", + "name": "PetFolio", + "short_name": "PetFolio", + "description": "Your pet's social network, health tracker & marketplace.", + "start_url": "/", "display": "standalone", - "background_color": "#0175C2", - "theme_color": "#0175C2", - "description": "A new Flutter project.", + "background_color": "#FFF4E6", + "theme_color": "#FF8A4C", "orientation": "portrait-primary", "prefer_related_applications": false, + "categories": ["lifestyle", "social", "health"], + "scope": "/", + "lang": "en", "icons": [ { "src": "icons/Icon-192.png", @@ -31,5 +34,6 @@ "type": "image/png", "purpose": "maskable" } - ] + ], + "screenshots": [] } diff --git a/web/pwa_banner.js b/web/pwa_banner.js new file mode 100644 index 0000000..d1ecd35 --- /dev/null +++ b/web/pwa_banner.js @@ -0,0 +1,69 @@ +(function () { + 'use strict'; + + // Only show on iOS Safari that is NOT already installed as a PWA + var isIos = /iphone|ipad|ipod/i.test(navigator.userAgent); + var isInStandalone = ('standalone' in navigator) && navigator.standalone; + var dismissed = localStorage.getItem('pwa_banner_dismissed'); + + if (!isIos || isInStandalone || dismissed) return; + + // Inject styles + var style = document.createElement('style'); + style.textContent = [ + '#pwa-banner{', + 'position:fixed;bottom:0;left:0;right:0;z-index:99999;', + 'background:#fff;color:#1a1014;', + 'border-radius:20px 20px 0 0;', + 'box-shadow:0 -4px 24px rgba(0,0,0,.15);', + 'padding:16px 20px 32px;', + 'font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;', + 'display:flex;align-items:flex-start;gap:14px;', + 'animation:slideUp .35s cubic-bezier(.16,1,.3,1) both;', + '}', + '@keyframes slideUp{from{transform:translateY(100%)}to{transform:translateY(0)}}', + '#pwa-banner img{width:56px;height:56px;border-radius:13px;flex-shrink:0;box-shadow:0 2px 8px rgba(0,0,0,.18);}', + '#pwa-banner-body{flex:1;}', + '#pwa-banner-title{font-size:15px;font-weight:700;margin:0 0 4px;}', + '#pwa-banner-desc{font-size:13px;color:#555;margin:0 0 12px;line-height:1.45;}', + '#pwa-banner-steps{font-size:12.5px;color:#333;line-height:1.6;margin:0;}', + '#pwa-banner-steps span{background:#f0f0f0;border-radius:6px;padding:1px 6px;font-weight:600;}', + '#pwa-banner-close{', + 'position:absolute;top:14px;right:16px;', + 'background:none;border:none;cursor:pointer;', + 'font-size:20px;color:#999;line-height:1;padding:4px;', + '}', + '@media(prefers-color-scheme:dark){', + '#pwa-banner{background:#1a1014;color:#fff;}', + '#pwa-banner-desc{color:#aaa;}', + '#pwa-banner-steps{color:#ddd;}', + '#pwa-banner-steps span{background:#333;}', + '#pwa-banner-close{color:#666;}', + '}', + ].join(''); + document.head.appendChild(style); + + // Build banner HTML + var banner = document.createElement('div'); + banner.id = 'pwa-banner'; + banner.setAttribute('role', 'banner'); + banner.innerHTML = [ + 'PetFolio icon', + '
', + '

Install PetFolio

', + '

Add to your Home Screen for the full app experience — works offline too.

', + '

', + 'Tap Share ↑ then Add to Home Screen', + '

', + '
', + '', + ].join(''); + + document.body.appendChild(banner); + + document.getElementById('pwa-banner-close').addEventListener('click', function () { + localStorage.setItem('pwa_banner_dismissed', '1'); + banner.style.animation = 'slideUp .25s cubic-bezier(.16,1,.3,1) reverse both'; + setTimeout(function () { banner.remove(); }, 280); + }); +}()); From 610ee87712bfd0f063f722d6cadca2a5289430cb Mon Sep 17 00:00:00 2001 From: Syed Salman Reza Date: Thu, 4 Jun 2026 03:36:49 +0600 Subject: [PATCH 17/23] up --- .../presentation/screens/matching_screen.dart | 15 ++- ..._discovery_candidates_offset_signature.sql | 111 ++++++++++++++++++ 2 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 supabase/migrations/20260604000000_fix_matching_discovery_candidates_offset_signature.sql diff --git a/lib/features/matching/presentation/screens/matching_screen.dart b/lib/features/matching/presentation/screens/matching_screen.dart index 86693a8..a7f3189 100644 --- a/lib/features/matching/presentation/screens/matching_screen.dart +++ b/lib/features/matching/presentation/screens/matching_screen.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:math' as math; @@ -108,6 +109,7 @@ class _DiscoveryViewState extends ConsumerState<_DiscoveryView> with WidgetsBindingObserver { final Set _shownMatchIds = {}; PetMutualMatch? _celebrationMatch; + Timer? _refreshDebounce; String get petId => widget.petId; @@ -120,6 +122,7 @@ class _DiscoveryViewState extends ConsumerState<_DiscoveryView> @override void dispose() { + _refreshDebounce?.cancel(); WidgetsBinding.instance.removeObserver(this); super.dispose(); } @@ -131,10 +134,16 @@ class _DiscoveryViewState extends ConsumerState<_DiscoveryView> } } + // Debounced so rapid lifecycle transitions (e.g. debug-VM attach, permission + // dialogs) collapse into a single invalidation instead of a request storm. void _refreshLocationState() { - ref.invalidate(locationAccessProvider); - ref.invalidate(deviceLatLngProvider); - ref.invalidate(discoveryCandidatesControllerProvider); + _refreshDebounce?.cancel(); + _refreshDebounce = Timer(const Duration(milliseconds: 600), () { + if (!mounted) return; + ref.invalidate(locationAccessProvider); + ref.invalidate(deviceLatLngProvider); + ref.invalidate(discoveryCandidatesControllerProvider); + }); } @override diff --git a/supabase/migrations/20260604000000_fix_matching_discovery_candidates_offset_signature.sql b/supabase/migrations/20260604000000_fix_matching_discovery_candidates_offset_signature.sql new file mode 100644 index 0000000..911d7d3 --- /dev/null +++ b/supabase/migrations/20260604000000_fix_matching_discovery_candidates_offset_signature.sql @@ -0,0 +1,111 @@ +-- The cursor-based overload (p_cursor_created_at, p_cursor_pet_id) was applied +-- directly to the DB outside version control, causing a signature mismatch with +-- the Dart client (MatchingSupabaseDataSource) which passes p_offset. +-- Drop the stale overload and restore the offset-based version with correct grants. + +DROP FUNCTION IF EXISTS public.matching_discovery_candidates( + uuid, + double precision, + integer, + timestamp with time zone, + uuid, + text[], + integer, + integer +); + +CREATE OR REPLACE FUNCTION public.matching_discovery_candidates( + p_actor_pet_id uuid, + p_radius_meters double precision DEFAULT 80467, + p_limit integer DEFAULT 20, + p_offset integer DEFAULT 0, + p_species text[] DEFAULT NULL, + p_min_age_years integer DEFAULT NULL, + p_max_age_years integer DEFAULT NULL +) +RETURNS TABLE ( + id uuid, + owner_id uuid, + name text, + species text, + breed text, + date_of_birth date, + avatar_url text, + bio text, + distance_meters double precision, + is_discoverable boolean, + owner jsonb +) +LANGUAGE sql +STABLE +SECURITY DEFINER +SET search_path = public, extensions +AS $$ + WITH origin AS ( + SELECT p.location AS loc, p.owner_id + FROM public.pets p + WHERE p.id = p_actor_pet_id + AND (SELECT auth.uid()) = p.owner_id + AND p.is_discoverable IS TRUE + ) + SELECT + c.id, + c.owner_id, + c.name, + c.species, + c.breed, + c.date_of_birth, + c.avatar_url, + c.bio, + ST_Distance(o.loc, c.location)::double precision AS distance_meters, + c.is_discoverable, + ( + SELECT jsonb_build_object( + 'id', u.id, + 'username', u.username, + 'display_name', u.display_name + ) + FROM public.users u + WHERE u.id = c.owner_id + ) AS owner + FROM origin o + CROSS JOIN public.pets c + LEFT JOIN public.swipes s + ON s.actor_id = p_actor_pet_id + AND s.target_id = c.id + WHERE c.id != p_actor_pet_id + AND c.owner_id != o.owner_id + AND c.is_public IS TRUE + AND c.is_discoverable IS TRUE + AND c.archived_at IS NULL + AND c.location IS NOT NULL + AND o.loc IS NOT NULL + AND ST_DWithin(o.loc, c.location, p_radius_meters) + AND s.id IS NULL + AND ( + p_species IS NULL + OR cardinality(p_species) = 0 + OR EXISTS ( + SELECT 1 + FROM unnest(p_species) AS u(species_text) + WHERE lower(trim(u.species_text)) = lower(trim(c.species)) + ) + ) + AND ( + c.date_of_birth IS NULL + OR ( + (p_min_age_years IS NULL + OR date_part('year', age(current_date, c.date_of_birth))::int >= p_min_age_years) + AND + (p_max_age_years IS NULL + OR date_part('year', age(current_date, c.date_of_birth))::int <= p_max_age_years) + ) + ) + ORDER BY c.created_at DESC + OFFSET greatest(coalesce(p_offset, 0), 0) + LIMIT greatest(coalesce(nullif(p_limit, 0), 20), 1); +$$; + +REVOKE ALL ON FUNCTION public.matching_discovery_candidates(uuid, double precision, integer, integer, text[], integer, integer) FROM PUBLIC; +GRANT EXECUTE ON FUNCTION public.matching_discovery_candidates(uuid, double precision, integer, integer, text[], integer, integer) TO authenticated; +GRANT EXECUTE ON FUNCTION public.matching_discovery_candidates(uuid, double precision, integer, integer, text[], integer, integer) TO service_role; From dcea9d5a22080e5be1ac8acebb3cb764362f5b75 Mon Sep 17 00:00:00 2001 From: Anam Chowdhury Date: Thu, 4 Jun 2026 06:45:12 -0400 Subject: [PATCH 18/23] up --- .claude/settings.local.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 2ffd8fe..bf772d0 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -121,7 +121,10 @@ "Bash(grep -E \"stripe_android|geolocator_android|flutter_local_notifications|permission_handler_android\" /c/Users/syedr/AppData/Local/Pub/Cache/hosted/pub.dev/../../../../../../../GitHub/petfolio/pubspec.lock | head -20)", "Bash(grep -v \"^$\")", "Bash(supabase status *)", - "mcp__visualize__read_me" + "mcp__visualize__read_me", + "Bash(git fetch *)", + "Bash(git merge *)", + "Bash(git stash *)" ] } } From 0150465ae9e5b68d2c83e323ef5bddddaf5e0c72 Mon Sep 17 00:00:00 2001 From: Anam Chowdhury Date: Thu, 4 Jun 2026 06:58:35 -0400 Subject: [PATCH 19/23] Apply PR #17 Copilot review fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Code fixes: - gamified_care_ui.dart: exclude asNeeded tasks from hero doneToday/totalToday counter (consistent with CareScreen); add didUpdateWidget to _TrophyCardState so sheen animation starts when a badge becomes owned after initial build - vercel.json: remove COEP/COOP headers from all-routes block — breaks Stripe (js.stripe.com); headers remain on /*.wasm only where cross-origin isolation is actually required - .github/workflows/deploy-web.yml: split preview (no --prod, PR events) vs production (--prod, push to main only) to prevent PR builds overwriting production - web/index.html: restore pinch-zoom (remove maximum-scale=1.0/user-scalable=no) for accessibility; fix apple-touch-icon sizes="192x192" to match Icon-192.png - web/pwa_banner.js: wrap localStorage.setItem in try/catch so dismiss works in iOS private mode - PetFolio Redesign/README.md: fix incorrect prototype path (was petfolio-redesign/project/Care Redesign/..., is PetFolio Redesign/Care Redesign/...) - Delete flutter-run-log.md and exception-log.md (transient runtime logs, not repo artifacts) Note: Copilot suggestions for notification_service.dart (positional args) and manage_pets_screen.dart (onReorder vs onReorderItem) were verified against the installed package APIs and found to be inverted — existing named-param style and onReorderItem are correct for flutter_local_notifications ^21 and Flutter 3.x respectively. Database (Supabase jqyjvhwlcqcsuwcqgcwf): - Migration pr17_revoke_anon_execute_sensitive_rpcs: revoke anon EXECUTE on ensure_direct_chat_thread, get_chat_inbox, matching_discovery_candidates — all SECURITY DEFINER functions that were accessible without authentication Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/deploy-web.yml | 11 ++- PetFolio Redesign/README.md | 2 +- exception-log.md | 45 ------------ flutter-run-log.md | 68 ------------------- .../widgets/gamified_care_ui.dart | 18 ++++- ...r17_revoke_anon_execute_sensitive_rpcs.sql | 9 +++ vercel.json | 8 +-- web/index.html | 5 +- web/pwa_banner.js | 2 +- 9 files changed, 40 insertions(+), 128 deletions(-) delete mode 100644 exception-log.md delete mode 100644 flutter-run-log.md create mode 100644 supabase/migrations/20260604180000_pr17_revoke_anon_execute_sensitive_rpcs.sql diff --git a/.github/workflows/deploy-web.yml b/.github/workflows/deploy-web.yml index a4d8614..131f7b1 100644 --- a/.github/workflows/deploy-web.yml +++ b/.github/workflows/deploy-web.yml @@ -32,8 +32,15 @@ jobs: --dart-define=STRIPE_PUBLISHABLE_KEY=${{ secrets.STRIPE_PUBLISHABLE_KEY }} \ --dart-define=NVIDIA_API_KEY=${{ secrets.NVIDIA_API_KEY }} - - name: Deploy to Vercel - working-directory: build/web + - name: Deploy preview to Vercel (PRs) + if: github.event_name == 'pull_request' + run: npx vercel deploy --yes --token=${{ secrets.VERCEL_TOKEN }} + env: + VERCEL_ORG_ID: team_lC8aTJK0XiU9qDfaHeTfCJs6 + VERCEL_PROJECT_ID: prj_hMHouLWimZvr5dDOlZeAhbH8xtop + + - name: Deploy to Vercel production (main only) + if: github.event_name == 'push' && github.ref == 'refs/heads/main' run: npx vercel deploy --prod --yes --token=${{ secrets.VERCEL_TOKEN }} env: VERCEL_ORG_ID: team_lC8aTJK0XiU9qDfaHeTfCJs6 diff --git a/PetFolio Redesign/README.md b/PetFolio Redesign/README.md index 3fddf65..899ddd5 100644 --- a/PetFolio Redesign/README.md +++ b/PetFolio Redesign/README.md @@ -6,7 +6,7 @@ A user mocked up designs in HTML/CSS/JS using an AI design tool, then exported t ## What you should do — IMPORTANT -**Read `petfolio-redesign/project/Care Redesign/Care Redesign.html` in full.** The user had this file open when they triggered the handoff, so it's almost certainly the primary design they want built. Read it top to bottom — don't skim. Then **follow its imports**: open every file it pulls in (shared components, CSS, scripts) so you understand how the pieces fit together before you start implementing. +**Read `PetFolio Redesign/Care Redesign/Care Redesign.html` in full.** The user had this file open when they triggered the handoff, so it's almost certainly the primary design they want built. Read it top to bottom — don't skim. Then **follow its imports**: open every file it pulls in (shared components, CSS, scripts) so you understand how the pieces fit together before you start implementing. **If anything is ambiguous, ask the user to confirm before you start implementing.** It's much cheaper to clarify scope up front than to build the wrong thing. diff --git a/exception-log.md b/exception-log.md deleted file mode 100644 index 147b2aa..0000000 --- a/exception-log.md +++ /dev/null @@ -1,45 +0,0 @@ -D/WindowOnBackDispatcher( 8540): setTopOnBackInvokedCallback (unwrapped): androidx.navigationevent.OnBackInvokedInput$createOnBackAnimationCallback$1@94b726b -D/WindowOnBackDispatcher( 8540): setTopOnBackInvokedCallback (unwrapped): android.app.Activity$$ExternalSyntheticLambda0@671fe96 -D/WindowOnBackDispatcher( 8540): setTopOnBackInvokedCallback (unwrapped): androidx.navigationevent.OnBackInvokedInput$createOnBackAnimationCallback$1@94b726b -D/WindowOnBackDispatcher( 8540): setTopOnBackInvokedCallback (unwrapped): android.app.Activity$$ExternalSyntheticLambda0@671fe96 -D/WindowOnBackDispatcher( 8540): setTopOnBackInvokedCallback (unwrapped): androidx.navigationevent.OnBackInvokedInput$createOnBackAnimationCallback$1@94b726b - -══╡ EXCEPTION CAUGHT BY FLUTTER FRAMEWORK ╞═════════════════════════════════════════════════════════ -The following assertion was thrown: -ListTile background color or ink splashes may be invisible. -The ListTile is wrapped in a DecoratedBox that has a background color. Because ListTile paints its -background and ink splashes on the nearest Material ancestor, this DecoratedBox will hide those -effects. -To fix this, wrap the ListTile in its own Material widget, or remove the background color from the -intermediate DecoratedBox. - -ListTile: - ListTile(selectedColor: Color(alpha: 1.0000, red: 1.0000, green: 0.5412, blue: 0.2980, colorSpace: ColorSpace.sRGB), contentPadding: EdgeInsets(16.0, 8.0, 16.0, - 8.0), onTap: Closure: () => void from Function '_handleValueChange@2316134056':.) -DecoratedBox: DecoratedBox(bg: - BoxDecoration(color: Color(alpha: 0.0500, red: 1.0000, green: 0.5412, blue: 0.2980, colorSpace: ColorSpace.sRGB), border: Border.all(BorderSide(color: - Color(alpha: 0.3000, red: 1.0000, green: 0.5412, blue: 0.2980, colorSpace: ColorSpace.sRGB), width: 1.5)), borderRadius: BorderRadius.circular(16.0), - boxShadow: [BoxShadow(Color(alpha: 0.0392, red: 0.1490, green: - 0.0745, blue: 0.0314, colorSpace: ColorSpace.sRGB), Offset(0.0, - 1.0), 2.0, 0.0, BlurStyle.normal)] - ) - ) -════════════════════════════════════════════════════════════════════════════════════════════════════ - -Another exception was thrown: ListTile background color or ink splashes may be invisible. -Another exception was thrown: ListTile background color or ink splashes may be invisible. -Another exception was thrown: ListTile background color or ink splashes may be invisible. -Another exception was thrown: ListTile background color or ink splashes may be invisible. -Another exception was thrown: ListTile background color or ink splashes may be invisible. -Another exception was thrown: ListTile background color or ink splashes may be invisible. -Another exception was thrown: ListTile background color or ink splashes may be invisible. -Another exception was thrown: ListTile background color or ink splashes may be invisible. -Another exception was thrown: ListTile background color or ink splashes may be invisible. -Another exception was thrown: ListTile background color or ink splashes may be invisible. -I/xample.petfolio( 8540): Background young concurrent mark compact GC freed 4915KB AllocSpace bytes, 12(608KB) LOS objects, 45% free, 5899KB/10MB, paused 1.185ms,9.059ms total 50.512ms -W/xample.petfolio( 8540): Reducing the number of considered missed Gc histogram windows from 301 to 100 -Another exception was thrown: ListTile background color or ink splashes may be invisible. -Another exception was thrown: ListTile background color or ink splashes may be invisible. -Another exception was thrown: ListTile background color or ink splashes may be invisible. -Another exception was thrown: ListTile background color or ink splashes may be invisible. -Another exception was thrown: ListTile background color or ink splashes may be invisible. \ No newline at end of file diff --git a/flutter-run-log.md b/flutter-run-log.md deleted file mode 100644 index 70fed5a..0000000 --- a/flutter-run-log.md +++ /dev/null @@ -1,68 +0,0 @@ -PS G:\GitHub\petfolio> flutter run --dart-define-from-file=.env -Launching lib\main.dart on sdk gphone16k x86 64 in debug mode... -WARNING: Your Android app project: app located at: G:\GitHub\petfolio\android\app\build.gradle.kts -applies the Kotlin Gradle Plugin, which will cause build failures in future versions of Flutter. -Please migrate your app to Built-in Kotlin using this guide: https://docs.flutter.dev/release/breaking-changes/migrate-to-built-in-kotlin/for-app-developers - -WARNING: Your app uses the following plugins that apply Kotlin Gradle Plugin (KGP): image_picker_android, share_plus, shared_preferences_android, stripe_android, url_launcher_android -Future versions of Flutter will fail to build if your app uses plugins that apply KGP. - -Please check the changelogs of these plugins and upgrade to a version that supports Built-in Kotlin. -If no such version exists, report the issue to the plugin. If necessary, here is a guide on filing -an issue against a plugin: https://docs.flutter.dev/release/breaking-changes/migrate-to-built-in-kotlin/for-app-developers#report-incompatible-kotlin-gradle-plugin-usage-to-plugin-authors - -If you are a plugin author, please migrate your plugin to Built-in Kotlin using this guide: https://docs.flutter.dev/release/breaking-changes/migrate-to-built-in-kotlin/for-plugin-authors -warning: [options] source value 8 is obsolete and will be removed in a future release -warning: [options] target value 8 is obsolete and will be removed in a future release -warning: [options] To suppress warnings about obsolete options, use -Xlint:-options. -3 warnings -Running Gradle task 'assembleDebug'... 51.4s -√ Built build\app\outputs\flutter-apk\app-debug.apk -Installing build\app\outputs\flutter-apk\app-debug.apk... 996ms -I/FlutterActivityAndFragmentDelegate(14767): If you are attempting to set --enable-dart-profiling via Intent extras to launch a Flutter component outside of using the Flutter CLI, note that support for setting engine flags on Android via Intent will soon be dropped; see https://github.com/flutter/flutter/issues/180686 for more information on this breaking change. To migrate, set --enable-dart-profiling or any other flags specified via Intent extras on the command line instead or see https://github.com/flutter/flutter/blob/main/docs/engine/Flutter-Android-Engine-Flags.md for alternative methods. -D/FlutterJNI(14767): Beginning load of flutter... -D/FlutterJNI(14767): flutter (null) was loaded normally! -I/flutter (14767): [IMPORTANT:flutter/shell/platform/android/android_context_gl_impeller.cc(104)] Using the Impeller rendering backend (OpenGLES). -D/FlutterGeolocator(14767): Attaching Geolocator to activity -D/FlutterRenderer(14767): Width is zero. 0,0 -D/FlutterGeolocator(14767): Creating service. -D/FlutterGeolocator(14767): Binding to location service. -D/WindowOnBackDispatcher(14767): setTopOnBackInvokedCallback (unwrapped): android.app.Activity$$ExternalSyntheticLambda0@671fe96 -I/WindowExtensionsImpl(14767): Initializing Window Extensions, vendor API level=10, activity embedding enabled=true -I/xample.petfolio(14767): Compiler allocated 5250KB to compile void android.view.ViewRootImpl.performTraversals(long) -W/UiContextUtils(14767): Requested context is a non-UI Context. Creating a UI-Context with display: 0. Context: Context=android.app.Application@9cf11e2, of which baseContext=android.app.ContextImpl@4c470b3 -D/VRI[MainActivity](14767): WindowInsets changed: 1080x2424 statusBars:[0,142,0,0] navigationBars:[0,0,0,63] mandatorySystemGestures:[0,174,0,84] -D/FlutterRenderer(14767): Width is zero. 0,0 -I/Surface (14767): Creating surface for consumer unnamed-14767-0 with slotExpansion=1 for 64 slots -I/Surface (14767): Creating surface for consumer VRI[MainActivity]#0(BLAST Consumer)0 with slotExpansion=1 for 64 slots -D/FlutterJNI(14767): Sending viewport metrics to the engine. -I/Surface (14767): Creating surface for consumer unnamed-14767-1 with slotExpansion=1 for 64 slots -I/Surface (14767): Creating surface for consumer a518fa5 SurfaceView[com.example.petfolio/com.example.petfolio.MainActivity]#1(BLAST Consumer)1 with slotExpansion=1 for 64 slots -D/FlutterGeolocator(14767): Geolocator foreground service connected -D/FlutterGeolocator(14767): Initializing Geolocator services -D/FlutterGeolocator(14767): Flutter engine connected. Connected engine count 1 -I/Choreographer(14767): Skipped 44 frames! The application may be doing too much work on its main thread. -I/HWUI (14767): Using FreeType backend (prop=Auto) -I/xample.petfolio(14767): hiddenapi: Accessing hidden method Landroid/os/SystemProperties;->addChangeCallback(Ljava/lang/Runnable;)V (runtime_flags=0, domain=platform, api=unsupported) from Landroidx/compose/ui/platform/AndroidComposeView$Companion; (domain=app, TargetSdkVersion=36) using reflection: allowed -D/WindowLayoutComponentImpl(14767): Register WindowLayoutInfoListener on Context=com.example.petfolio.MainActivity@bbce388, of which baseContext=android.app.ContextImpl@b6a02b5 -I/Choreographer(14767): Skipped 44 frames! The application may be doing too much work on its main thread. -Syncing files to device sdk gphone16k x86 64... 171ms - -Flutter run key commands. -r Hot reload. -R Hot restart. -h List all available interactive commands. -d Detach (terminate "flutter run" but leave application running). -c Clear the screen -q Quit (terminate the application on the device). - -A Dart VM Service on sdk gphone16k x86 64 is available at: http://127.0.0.1:54386/Ych0_YBW-GQ=/ -The Flutter DevTools debugger and profiler on sdk gphone16k x86 64 is available at: -http://127.0.0.1:54386/Ych0_YBW-GQ=/devtools/?uri=ws://127.0.0.1:54386/Ych0_YBW-GQ=/ws -I/flutter (14767): supabase.supabase_flutter: INFO: ***** Supabase init completed ***** -D/FlutterJNI(14767): Sending viewport metrics to the engine. -I/Choreographer(14767): Skipped 85 frames! The application may be doing too much work on its main thread. -D/InsetsController(14767): hide(ime()) -I/ImeTracker(14767): com.example.petfolio:9b0c77f3: onCancelled at PHASE_CLIENT_ALREADY_HIDDEN -D/ProfileInstaller(14767): Installing profile for com.example.petfolio -I/xample.petfolio(14767): Background concurrent mark compact GC freed 6145KB AllocSpace bytes, 20(832KB) LOS objects, 49% free, 5194KB/10MB, paused 906us,5.160ms total 16.410ms diff --git a/lib/features/care/presentation/widgets/gamified_care_ui.dart b/lib/features/care/presentation/widgets/gamified_care_ui.dart index ce60f4d..47a7729 100644 --- a/lib/features/care/presentation/widgets/gamified_care_ui.dart +++ b/lib/features/care/presentation/widgets/gamified_care_ui.dart @@ -7,6 +7,7 @@ import 'package:petfolio/core/theme/theme.dart'; import 'package:petfolio/core/widgets/widgets.dart'; import '../../../../core/models/pet.dart'; +import '../../data/models/care_task.dart' show CareFrequency; import '../../data/models/care_task_log.dart'; import '../../data/models/pet_awards_summary.dart'; import '../../data/models/pet_level.dart'; @@ -69,7 +70,9 @@ class _CareGamifiedHeaderState extends ConsumerState ); final tasks = widget.dashboard.tasks.value ?? []; - final planned = tasks.where((t) => !t.isLogDerived).toList(); + final planned = tasks + .where((t) => !t.isLogDerived && t.frequency != CareFrequency.asNeeded) + .toList(); final doneToday = planned.where((t) => t.isCompleted).length; final totalToday = planned.length; final pct = lv.progress.clamp(0.0, 1.0); @@ -1114,6 +1117,19 @@ class _TrophyCardState extends State<_TrophyCard> with TickerProviderStateMixin } } + @override + void didUpdateWidget(_TrophyCard oldWidget) { + super.didUpdateWidget(oldWidget); + if (!oldWidget.owned && widget.owned && !_sheenCtrl.isAnimating) { + final delayFraction = + (widget.index * 300 / _sheenCtrl.duration!.inMilliseconds).clamp(0.0, 1.0); + _sheenCtrl.forward(from: delayFraction); + _sheenCtrl.addStatusListener((s) { + if (s == AnimationStatus.completed && mounted) _sheenCtrl.repeat(); + }); + } + } + @override void dispose() { _floatCtrl.dispose(); diff --git a/supabase/migrations/20260604180000_pr17_revoke_anon_execute_sensitive_rpcs.sql b/supabase/migrations/20260604180000_pr17_revoke_anon_execute_sensitive_rpcs.sql new file mode 100644 index 0000000..96cfdbc --- /dev/null +++ b/supabase/migrations/20260604180000_pr17_revoke_anon_execute_sensitive_rpcs.sql @@ -0,0 +1,9 @@ +-- Revoke anon EXECUTE on SECURITY DEFINER functions that should only be +-- callable by authenticated users. Flagged by Supabase security advisors. + +-- Chat / social RPCs +REVOKE EXECUTE ON FUNCTION public.ensure_direct_chat_thread(uuid, uuid) FROM anon; +REVOKE EXECUTE ON FUNCTION public.get_chat_inbox(uuid) FROM anon; + +-- Matching discovery (contains location + pet data — authenticated only) +REVOKE EXECUTE ON FUNCTION public.matching_discovery_candidates(uuid, double precision, integer, integer, text[], integer, integer) FROM anon; diff --git a/vercel.json b/vercel.json index f4ce82e..53af47e 100644 --- a/vercel.json +++ b/vercel.json @@ -16,13 +16,7 @@ { "key": "Cross-Origin-Opener-Policy", "value": "same-origin" } ] }, - { - "source": "/(.*)", - "headers": [ - { "key": "Cross-Origin-Embedder-Policy", "value": "require-corp" }, - { "key": "Cross-Origin-Opener-Policy", "value": "same-origin" } - ] - } + ], "rewrites": [ { "source": "/((?!.*\\.).*)", "destination": "/index.html" } diff --git a/web/index.html b/web/index.html index 742167e..c99bb71 100644 --- a/web/index.html +++ b/web/index.html @@ -8,8 +8,7 @@ + content="width=device-width, initial-scale=1.0, viewport-fit=cover"> @@ -27,7 +26,7 @@ - + diff --git a/web/pwa_banner.js b/web/pwa_banner.js index d1ecd35..a6bccc5 100644 --- a/web/pwa_banner.js +++ b/web/pwa_banner.js @@ -62,7 +62,7 @@ document.body.appendChild(banner); document.getElementById('pwa-banner-close').addEventListener('click', function () { - localStorage.setItem('pwa_banner_dismissed', '1'); + try { localStorage.setItem('pwa_banner_dismissed', '1'); } catch (_) {} banner.style.animation = 'slideUp .25s cubic-bezier(.16,1,.3,1) reverse both'; setTimeout(function () { banner.remove(); }, 280); }); From 9aaf64b3623d94e358a4f7eec9c864d544f71a94 Mon Sep 17 00:00:00 2001 From: Anam Chowdhury Date: Thu, 4 Jun 2026 07:21:37 -0400 Subject: [PATCH 20/23] up --- .claude/settings.local.json | 4 +- .../page-2026-06-04T10-51-49-473Z.yml | 3403 +++++++++++++++++ 2 files changed, 3406 insertions(+), 1 deletion(-) create mode 100644 .playwright-mcp/page-2026-06-04T10-51-49-473Z.yml diff --git a/.claude/settings.local.json b/.claude/settings.local.json index bf772d0..f98c6d6 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -124,7 +124,9 @@ "mcp__visualize__read_me", "Bash(git fetch *)", "Bash(git merge *)", - "Bash(git stash *)" + "Bash(git stash *)", + "mcp__plugin_playwright_playwright__browser_navigate", + "mcp__plugin_playwright_playwright__browser_snapshot" ] } } diff --git a/.playwright-mcp/page-2026-06-04T10-51-49-473Z.yml b/.playwright-mcp/page-2026-06-04T10-51-49-473Z.yml new file mode 100644 index 0000000..61920b9 --- /dev/null +++ b/.playwright-mcp/page-2026-06-04T10-51-49-473Z.yml @@ -0,0 +1,3403 @@ +- generic [ref=e2]: + - generic [ref=e3]: + - link "Skip to content" [ref=e4] [cursor=pointer]: + - /url: "#start-of-content" + - banner [ref=e6]: + - heading "Navigation Menu" [level=2] [ref=e7] + - generic [ref=e9]: + - button "Toggle navigation" [ref=e11] [cursor=pointer] + - link "Homepage" [ref=e17] [cursor=pointer]: + - /url: / + - img [ref=e18] + - generic [ref=e20]: + - link "Sign in" [ref=e21] [cursor=pointer]: + - /url: /login?return_to=https%3A%2F%2Fgithub.com%2FCodeStorm-Hub%2Fpetfolio%2Fpull%2F17 + - button "Appearance settings" [ref=e24] [cursor=pointer]: + - img + - main [ref=e28]: + - generic [ref=e29]: + - generic [ref=e30]: + - generic [ref=e32]: + - img [ref=e33] + - link "CodeStorm-Hub" [ref=e36] [cursor=pointer]: + - /url: /CodeStorm-Hub + - generic [ref=e37]: / + - strong [ref=e38]: + - link "petfolio" [ref=e39] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio + - generic [ref=e40]: Public + - generic [ref=e41]: + - list: + - listitem [ref=e42]: + - link "You must be signed in to change notification settings" [ref=e43] [cursor=pointer]: + - /url: /login?return_to=%2FCodeStorm-Hub%2Fpetfolio + - img [ref=e44] + - text: Notifications + - listitem [ref=e46]: + - link "Fork 0" [ref=e47] [cursor=pointer]: + - /url: /login?return_to=%2FCodeStorm-Hub%2Fpetfolio + - img [ref=e48] + - text: Fork + - generic "0" [ref=e50] + - listitem [ref=e51]: + - link "You must be signed in to star a repository" [ref=e53] [cursor=pointer]: + - /url: /login?return_to=%2FCodeStorm-Hub%2Fpetfolio + - img [ref=e54] + - text: Star + - generic "0 users starred this repository" [ref=e56]: "0" + - navigation "Repository" [ref=e57]: + - list [ref=e58]: + - listitem [ref=e59]: + - link "Code" [ref=e60] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio + - img [ref=e61] + - generic [ref=e63]: Code + - listitem [ref=e64]: + - link "Issues" [ref=e65] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/issues + - img [ref=e66] + - generic [ref=e69]: Issues + - listitem [ref=e70]: + - link "Pull requests 2" [ref=e71] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pulls + - img [ref=e72] + - generic [ref=e74]: Pull requests + - generic "2" [ref=e75] + - listitem [ref=e76]: + - link "Discussions" [ref=e77] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/discussions + - img [ref=e78] + - generic [ref=e80]: Discussions + - listitem [ref=e81]: + - link "Actions" [ref=e82] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/actions + - img [ref=e83] + - generic [ref=e85]: Actions + - listitem [ref=e86]: + - link "Projects" [ref=e87] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/projects + - img [ref=e88] + - generic [ref=e90]: Projects + - listitem [ref=e91]: + - link "Models" [ref=e92] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/models + - img [ref=e93] + - generic [ref=e95]: Models + - listitem [ref=e96] + - listitem [ref=e97] + - button "Additional navigation options" [ref=e101] [cursor=pointer]: + - img + - generic [ref=e108]: + - generic [ref=e111]: + - 'heading "Care redesign salman #17" [level=1] [ref=e113]': + - text: Care redesign salman + - generic [ref=e115]: "#17" + - generic [ref=e117]: + - generic [ref=e119]: + - img "Pull request" [ref=e120] + - text: Open + - generic [ref=e123]: + - link "syed-reza98" [ref=e124] [cursor=pointer]: + - /url: /syed-reza98 + - text: wants to merge 19 commits into + - generic [ref=e125]: + - link "main" [ref=e126] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/tree/main + - generic [ref=e127]: from + - generic [ref=e128]: + - link "care-redesign-salman" [ref=e129] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/tree/care-redesign-salman + - button "Copy head branch name to clipboard" [ref=e130] [cursor=pointer]: + - img [ref=e131] + - generic [ref=e134]: + - generic [ref=e136]: + - generic [ref=e137]: +3,815 + - generic [ref=e138]: "-1,310" + - generic [ref=e139]: "Lines changed: 3815 additions & 1310 deletions" + - navigation "Pull request navigation tabs" [ref=e148]: + - tablist [ref=e149]: + - tab "Conversation (33)" [selected] [ref=e150] [cursor=pointer]: + - img [ref=e151] + - text: Conversation + - generic [ref=e153]: "33" + - generic [ref=e154]: (33) + - tab "Commits (19)" [ref=e155] [cursor=pointer]: + - img [ref=e156] + - text: Commits + - generic [ref=e158]: "19" + - generic [ref=e159]: (19) + - tab "Checks (2)" [ref=e160] [cursor=pointer]: + - img [ref=e161] + - text: Checks + - generic [ref=e163]: "2" + - generic [ref=e164]: (2) + - tab "Files changed (44)" [ref=e165] [cursor=pointer]: + - img [ref=e166] + - text: Files changed + - generic [ref=e168]: "44" + - generic [ref=e169]: (44) + - generic [ref=e174]: + - generic [ref=e176]: + - heading "Conversation" [level=2] [ref=e177] + - generic [ref=e178]: + - generic [ref=e179]: + - generic [ref=e181]: + - link "@syed-reza98" [ref=e182] [cursor=pointer]: + - /url: /syed-reza98 + - img "@syed-reza98" [ref=e183] + - generic [ref=e185]: + - generic [ref=e186]: + - generic [ref=e187]: + - group [ref=e189]: + - button "Show options" [ref=e190] [cursor=pointer]: + - img "Show options" [ref=e193] + - generic "This user is a member of the CodeStorm-Hub organization." [ref=e196]: + - generic [ref=e197]: Member + - heading "syed-reza98 commented Jun 3, 202613 hours ago" [level=3] [ref=e198]: + - generic [ref=e199]: + - strong [ref=e200]: + - link "syed-reza98" [ref=e201] [cursor=pointer]: + - /url: /syed-reza98 + - text: commented + - link "Jun 3, 202613 hours ago" [ref=e202] [cursor=pointer]: + - /url: "#issue-4583667084" + - generic [ref=e206]: + - paragraph [ref=e207]: This pull request introduces several key improvements to the project, focusing on enhancing web deployment, local development, and UI prototyping. The most significant changes include adding a GitHub Actions workflow for automated Flutter Web deployment to Vercel, introducing a new HTML prototype for the Care Redesign, and updating configuration files for both development and deployment environments. + - paragraph [ref=e208]: + - strong [ref=e209]: "Deployment automation and configuration:" + - list [ref=e210]: + - listitem [ref=e211]: + - text: Added a new GitHub Actions workflow ( + - code [ref=e212]: .github/workflows/deploy-web.yml + - text: ) to automatically build and deploy the Flutter Web app to Vercel on pushes and pull requests to the + - code [ref=e213]: main + - text: branch. This workflow uses environment secrets for sensitive API keys and integrates with Vercel for production deployment. + - listitem [ref=e214]: + - text: Added Vercel project configuration file ( + - code [ref=e215]: .vercel/project.json + - text: ) to specify the organization and project IDs for deployment integration. + - paragraph [ref=e216]: + - strong [ref=e217]: "Development environment enhancements:" + - list [ref=e218]: + - listitem [ref=e219]: + - text: Added a local launch configuration file ( + - code [ref=e220]: .claude/launch.json + - text: ) to streamline running the Flutter Web app locally with all necessary + - code [ref=e221]: dart-define + - text: environment variables, including Supabase, Stripe, and NVIDIA API keys. + - listitem [ref=e222]: + - text: Expanded + - code [ref=e223]: .claude/settings.local.json + - text: with additional bash and MCP commands, improving local development and testing workflows. + - paragraph [ref=e224]: + - strong [ref=e225]: "UI prototyping:" + - list [ref=e226]: + - listitem [ref=e227]: + - text: Added a new HTML file ( + - code [ref=e228]: PetFolio Redesign/Care Redesign/Care Redesign.html + - text: ) that serves as a prototype for the Care Redesign. This file includes a comprehensive set of styles, theme support (light/dark), and scripts for responsive device scaling and React-based component rendering. + - generic [ref=e229]: + - generic [ref=e231]: + - generic [ref=e232]: + - img [ref=e234] + - generic [ref=e236]: + - link "syed-reza98" [ref=e237] [cursor=pointer]: + - /url: /syed-reza98 + - text: added 16 commits + - link "June 1, 2026 13:123 days ago" [ref=e238] [cursor=pointer]: + - /url: "#commits-pushed-fb57c49" + - generic [ref=e239]: + - generic [ref=e240]: + - img [ref=e242] + - generic [ref=e247]: + - link "@syed-reza98" [ref=e250] [cursor=pointer]: + - /url: /syed-reza98 + - img "@syed-reza98" [ref=e251] + - generic [ref=e252]: + - code [ref=e253]: + - link "Add Care Redesign demo and update care UI" [ref=e254] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/fb57c49e78cac998e4bbe73b4469a9b04809c852 + - button "Commit message body" [ref=e256] [cursor=pointer]: … + - code [ref=e260]: + - link "fb57c49" [ref=e261] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/fb57c49e78cac998e4bbe73b4469a9b04809c852 + - generic [ref=e262]: + - img [ref=e264] + - generic [ref=e269]: + - link "@syed-reza98" [ref=e272] [cursor=pointer]: + - /url: /syed-reza98 + - img "@syed-reza98" [ref=e273] + - generic [ref=e274]: + - code [ref=e275]: + - 'link "Revamp Care UI: trophy room & badge visuals" [ref=e276] [cursor=pointer]': + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/1d8e35ff5145e14271d5105ad6af5ef64d7b0608 + - button "Commit message body" [ref=e278] [cursor=pointer]: … + - code [ref=e282]: + - link "1d8e35f" [ref=e283] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/1d8e35ff5145e14271d5105ad6af5ef64d7b0608 + - generic [ref=e284]: + - img [ref=e286] + - generic [ref=e291]: + - link "@syed-reza98" [ref=e294] [cursor=pointer]: + - /url: /syed-reza98 + - img "@syed-reza98" [ref=e295] + - generic [ref=e296]: + - code [ref=e297]: + - link "Add Flutter run and exception logs" [ref=e298] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/d472ebddedcbc5bf5045dddc5bdf64e63913de24 + - button "Commit message body" [ref=e300] [cursor=pointer]: … + - code [ref=e304]: + - link "d472ebd" [ref=e305] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/d472ebddedcbc5bf5045dddc5bdf64e63913de24 + - generic [ref=e306]: + - img [ref=e308] + - generic [ref=e313]: + - link "@syed-reza98" [ref=e316] [cursor=pointer]: + - /url: /syed-reza98 + - img "@syed-reza98" [ref=e317] + - generic [ref=e318]: + - code [ref=e319]: + - link "Adapt notifications API, bump deps, add KGP notes" [ref=e320] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/8ac21da357c5ff7a6a09c912873d9dc6ddb1a385 + - button "Commit message body" [ref=e322] [cursor=pointer]: … + - code [ref=e326]: + - link "8ac21da" [ref=e327] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/8ac21da357c5ff7a6a09c912873d9dc6ddb1a385 + - generic [ref=e328]: + - img [ref=e330] + - generic [ref=e335]: + - link "@syed-reza98" [ref=e338] [cursor=pointer]: + - /url: /syed-reza98 + - img "@syed-reza98" [ref=e339] + - generic [ref=e340]: + - code [ref=e341]: + - link "Update Claude settings and flutter run log" [ref=e342] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/2c45129e78d93e6e6f4862cd7275d0f53b10763b + - button "Commit message body" [ref=e344] [cursor=pointer]: … + - code [ref=e348]: + - link "2c45129" [ref=e349] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/2c45129e78d93e6e6f4862cd7275d0f53b10763b + - generic [ref=e350]: + - img [ref=e352] + - generic [ref=e357]: + - link "@syed-reza98" [ref=e360] [cursor=pointer]: + - /url: /syed-reza98 + - img "@syed-reza98" [ref=e361] + - generic [ref=e362]: + - code [ref=e363]: + - link "Add PWA onboarding, web config, and tooling files" [ref=e364] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/d0e21726ac57309556fa1733d77c1a773a425ced + - button "Commit message body" [ref=e366] [cursor=pointer]: … + - code [ref=e370]: + - link "d0e2172" [ref=e371] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/d0e21726ac57309556fa1733d77c1a773a425ced + - generic [ref=e372]: + - img [ref=e374] + - generic [ref=e379]: + - link "@syed-reza98" [ref=e382] [cursor=pointer]: + - /url: /syed-reza98 + - img "@syed-reza98" [ref=e383] + - generic [ref=e384]: + - code [ref=e385]: + - link "Move AI call to Supabase function" [ref=e386] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/1c1b25a4d91ecc9bf2ae8a25d8808ce301f86a92 + - button "Commit message body" [ref=e388] [cursor=pointer]: … + - group [ref=e392]: + - generic "2 / 2 checks OK" [ref=e393] [cursor=pointer]: + - img "2 / 2 checks OK" [ref=e394] + - code [ref=e397]: + - link "1c1b25a" [ref=e398] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/1c1b25a4d91ecc9bf2ae8a25d8808ce301f86a92 + - generic [ref=e399]: + - img [ref=e401] + - generic [ref=e406]: + - link "@syed-reza98" [ref=e409] [cursor=pointer]: + - /url: /syed-reza98 + - img "@syed-reza98" [ref=e410] + - generic [ref=e411]: + - code [ref=e412]: + - link "Add .vercelignore and bump Supabase CLI" [ref=e413] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/31fa1729059eb96ac5907a0a88eb663d1589e7b7 + - button "Commit message body" [ref=e415] [cursor=pointer]: … + - group [ref=e419]: + - generic "2 / 2 checks OK" [ref=e420] [cursor=pointer]: + - img "2 / 2 checks OK" [ref=e421] + - code [ref=e424]: + - link "31fa172" [ref=e425] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/31fa1729059eb96ac5907a0a88eb663d1589e7b7 + - generic [ref=e426]: + - img [ref=e428] + - generic [ref=e433]: + - link "@syed-reza98" [ref=e436] [cursor=pointer]: + - /url: /syed-reza98 + - img "@syed-reza98" [ref=e437] + - generic [ref=e438]: + - code [ref=e439]: + - link "Add vercel.json and remove .vercelignore" [ref=e440] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/c843e29c606ad6ae048d35740dbeb957725bf47e + - button "Commit message body" [ref=e442] [cursor=pointer]: … + - group [ref=e446]: + - generic "1 / 2 checks OK" [ref=e447] [cursor=pointer]: + - img "1 / 2 checks OK" [ref=e448] + - code [ref=e451]: + - link "c843e29" [ref=e452] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/c843e29c606ad6ae048d35740dbeb957725bf47e + - generic [ref=e453]: + - img [ref=e455] + - generic [ref=e460]: + - link "@syed-reza98" [ref=e463] [cursor=pointer]: + - /url: /syed-reza98 + - img "@syed-reza98" [ref=e464] + - generic [ref=e465]: + - code [ref=e466]: + - link "Add .vercelignore to ignore .git" [ref=e467] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/77b469b0c64284d5cf608a58d42b2ec36c6becb4 + - button "Commit message body" [ref=e469] [cursor=pointer]: … + - group [ref=e473]: + - generic "1 / 2 checks OK" [ref=e474] [cursor=pointer]: + - img "1 / 2 checks OK" [ref=e475] + - code [ref=e478]: + - link "77b469b" [ref=e479] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/77b469b0c64284d5cf608a58d42b2ec36c6becb4 + - generic [ref=e480]: + - img [ref=e482] + - generic [ref=e487]: + - link "@syed-reza98" [ref=e490] [cursor=pointer]: + - /url: /syed-reza98 + - img "@syed-reza98" [ref=e491] + - generic [ref=e492]: + - code [ref=e493]: + - link "Revert \"Add .vercelignore to ignore .git\"" [ref=e494] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/f5b31e03f0580cb594cf350f9ddff861bc0b321d + - button "Commit message body" [ref=e496] [cursor=pointer]: … + - group [ref=e500]: + - generic "1 / 2 checks OK" [ref=e501] [cursor=pointer]: + - img "1 / 2 checks OK" [ref=e502] + - code [ref=e505]: + - link "f5b31e0" [ref=e506] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/f5b31e03f0580cb594cf350f9ddff861bc0b321d + - generic [ref=e507]: + - img [ref=e509] + - generic [ref=e514]: + - link "@syed-reza98" [ref=e517] [cursor=pointer]: + - /url: /syed-reza98 + - img "@syed-reza98" [ref=e518] + - generic [ref=e519]: + - code [ref=e520]: + - link "Revert \"Add vercel.json and remove .vercelignore\"" [ref=e521] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/fd34015613ffa5771fc67c3b40d17d211f53c91f + - button "Commit message body" [ref=e523] [cursor=pointer]: … + - code [ref=e527]: + - link "fd34015" [ref=e528] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/fd34015613ffa5771fc67c3b40d17d211f53c91f + - generic [ref=e529]: + - img [ref=e531] + - generic [ref=e536]: + - link "@syed-reza98" [ref=e539] [cursor=pointer]: + - /url: /syed-reza98 + - img "@syed-reza98" [ref=e540] + - generic [ref=e541]: + - code [ref=e542]: + - link "Revert \"Add .vercelignore and bump Supabase CLI\"" [ref=e543] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/9f565e8da76986783598c587d2a9f0648e6f33b4 + - button "Commit message body" [ref=e545] [cursor=pointer]: … + - code [ref=e549]: + - link "9f565e8" [ref=e550] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/9f565e8da76986783598c587d2a9f0648e6f33b4 + - generic [ref=e551]: + - img [ref=e553] + - generic [ref=e558]: + - link "@syed-reza98" [ref=e561] [cursor=pointer]: + - /url: /syed-reza98 + - img "@syed-reza98" [ref=e562] + - generic [ref=e563]: + - code [ref=e564]: + - link "Revert \"Move AI call to Supabase function\"" [ref=e565] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/652ef113364e0d812a3773f556b162a4404730d1 + - button "Commit message body" [ref=e567] [cursor=pointer]: … + - group [ref=e571]: + - generic "2 / 2 checks OK" [ref=e572] [cursor=pointer]: + - img "2 / 2 checks OK" [ref=e573] + - code [ref=e576]: + - link "652ef11" [ref=e577] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/652ef113364e0d812a3773f556b162a4404730d1 + - generic [ref=e578]: + - img [ref=e580] + - generic [ref=e585]: + - link "@syed-reza98" [ref=e588] [cursor=pointer]: + - /url: /syed-reza98 + - img "@syed-reza98" [ref=e589] + - generic [ref=e590]: + - code [ref=e591]: + - link "Revert \"Add PWA onboarding, web config, and tooling files\"" [ref=e592] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/562d48cb82ec5a545b98b389bb7c1984b4259538 + - button "Commit message body" [ref=e594] [cursor=pointer]: … + - group [ref=e598]: + - generic "2 / 2 checks OK" [ref=e599] [cursor=pointer]: + - img "2 / 2 checks OK" [ref=e600] + - code [ref=e603]: + - link "562d48c" [ref=e604] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/562d48cb82ec5a545b98b389bb7c1984b4259538 + - generic [ref=e605]: + - img [ref=e607] + - generic [ref=e612]: + - link "@syed-reza98" [ref=e615] [cursor=pointer]: + - /url: /syed-reza98 + - img "@syed-reza98" [ref=e616] + - generic [ref=e617]: + - code [ref=e618]: + - link "Add web deployment, PWA and web-specific fixes" [ref=e619] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/7b8aaf186f6047b802df726bad66459f0cfe10ec + - button "Commit message body" [ref=e621] [cursor=pointer]: … + - group [ref=e625]: + - generic "2 / 2 checks OK" [ref=e626] [cursor=pointer]: + - img "2 / 2 checks OK" [ref=e627] + - code [ref=e630]: + - link "7b8aaf1" [ref=e631] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/7b8aaf186f6047b802df726bad66459f0cfe10ec + - generic [ref=e632]: + - generic [ref=e633]: + - img [ref=e635] + - generic [ref=e637]: + - link "Copilot PR reviewer" [ref=e638] [cursor=pointer]: + - /url: /apps/copilot-pull-request-reviewer + - img [ref=e640] + - link "Copilot" [ref=e643] [cursor=pointer]: + - /url: /apps/copilot-pull-request-reviewer + - generic [ref=e644]: AI + - text: review requested due to automatic review settings + - link "June 3, 2026 21:1113 hours ago" [ref=e645] [cursor=pointer]: + - /url: "#event-26308103910" + - generic [ref=e646]: + - img [ref=e648] + - generic [ref=e650]: + - strong [ref=e651]: Copilot + - link "started reviewing" [ref=e652] [cursor=pointer]: + - /url: https://github.com/CodeStorm-Hub/petfolio/sessions/4c2f321c-4931-4a36-b116-7c62d2927558 + - text: on behalf of + - link "syed-reza98" [ref=e653] [cursor=pointer]: + - /url: /syed-reza98 + - link "June 3, 2026 21:1113 hours ago" [ref=e654] [cursor=pointer]: + - /url: "#event-26308112066" + - link "View session 4c2f321c-4931-4a36-b116-7c62d2927558" [ref=e655] [cursor=pointer]: + - /url: https://github.com/CodeStorm-Hub/petfolio/sessions/4c2f321c-4931-4a36-b116-7c62d2927558 + - generic [ref=e657]: View session + - generic [ref=e660]: + - generic [ref=e661]: + - link "Copilot PR reviewer" [ref=e662] [cursor=pointer]: + - /url: /apps/copilot-pull-request-reviewer + - img [ref=e664] + - img "Only reviews by reviewers with write access count toward mergeability" [ref=e668] + - generic [ref=e670]: + - generic [ref=e671]: + - strong [ref=e672]: + - link "Copilot" [ref=e673] [cursor=pointer]: + - /url: /apps/copilot-pull-request-reviewer + - generic [ref=e674]: AI + - text: reviewed + - link "Jun 3, 202613 hours ago" [ref=e676] [cursor=pointer]: + - /url: "#pullrequestreview-4422878140" + - link "View reviewed changes" [ref=e678] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/files/7b8aaf186f6047b802df726bad66459f0cfe10ec + - generic [ref=e680]: View reviewed changes + - generic [ref=e683]: + - generic [ref=e684]: + - group [ref=e687]: + - button "Show options" [ref=e688] [cursor=pointer]: + - img "Show options" [ref=e691] + - heading "Copilot AI left a comment" [level=3] [ref=e693]: + - generic [ref=e694]: + - strong [ref=e695]: + - link "Copilot" [ref=e696] [cursor=pointer]: + - /url: /apps/copilot-pull-request-reviewer + - generic [ref=e697]: AI + - text: left a comment + - generic [ref=e700]: + - heading "Pull request overview" [level=2] [ref=e701] + - paragraph [ref=e702]: This PR updates PetFolio’s web/PWA deployment setup (Vercel + GitHub Actions), adds an HTML/React-based “Care Redesign” prototype bundle, and implements substantial Flutter UI refinements for the Care module (compact hero header, trophy UI redesign, weekly chart/task card tweaks), alongside several dependency and platform-guard updates to improve web compatibility. + - paragraph [ref=e703]: + - strong [ref=e704]: "Changes:" + - list [ref=e705]: + - listitem [ref=e706]: Add Vercel deployment configuration + a GitHub Actions workflow to build Flutter Web and deploy to Vercel; update web manifest/index for PWA polish (splash, install banner, theme). + - listitem [ref=e707]: Add “PetFolio Redesign / Care Redesign” prototype files (HTML + JSX components) as a UI handoff bundle. + - listitem [ref=e708]: Refactor Care UI in Flutter (hero header, trophy slider/cards, weekly chart/task cards) and adjust services for web/platform behavior (notifications guarded on web; AI routine proxy on web). + - heading "Reviewed changes" [level=3] [ref=e709] + - paragraph [ref=e710]: Copilot reviewed 26 out of 42 changed files in this pull request and generated 13 comments. + - group [ref=e711]: + - generic "Show a summary per file" [ref=e712] [cursor=pointer] + - group [ref=e713]: + - generic "Comments suppressed due to low confidence (1)" [ref=e714] [cursor=pointer] + - separator [ref=e715] + - paragraph [ref=e716]: + - text: 💡 + - link "Add Copilot custom instructions" [ref=e717] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/new/main?filename=.github/instructions/*.instructions.md + - text: for smarter, more guided reviews. + - link "Learn how to get started" [ref=e718] [cursor=pointer]: + - /url: https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot + - text: . + - generic [ref=e720]: + - generic [ref=e722]: + - generic [ref=e723]: + - button "Comment thread" [expanded] [ref=e724] [cursor=pointer]: + - img + - link "lib/features/pet_profile/presentation/screens/manage_pets_screen.dart" [ref=e726] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/files/7b8aaf186f6047b802df726bad66459f0cfe10ec#diff-584838a82bb9a8b7eca64cad5c516652e00e6ad6c1a45bc3c2201e651c17eae6 + - generic [ref=e727]: + - generic [ref=e729]: Comment on lines 306 to 309 + - table [ref=e732]: + - rowgroup [ref=e733]: + - 'row "307 306 sliver: SliverReorderableList(" [ref=e734]': + - cell "307" [ref=e735] [cursor=pointer] + - cell "306" [ref=e736] [cursor=pointer] + - 'cell "sliver: SliverReorderableList(" [ref=e737]': + - generic [ref=e738]: "sliver: SliverReorderableList(" + - 'row "308 307 itemCount: pets.length," [ref=e739]': + - cell "308" [ref=e740] [cursor=pointer] + - cell "307" [ref=e741] [cursor=pointer] + - 'cell "itemCount: pets.length," [ref=e742]': + - generic [ref=e743]: "itemCount: pets.length," + - 'row "309 - onReorder: onReorder," [ref=e744]': + - cell "309" [ref=e745] [cursor=pointer] + - cell [ref=e746] [cursor=pointer] + - 'cell "- onReorder: onReorder," [ref=e747]': + - generic [ref=e748]: "- onReorder: onReorder," + - 'row "308 + onReorderItem: onReorder," [ref=e749]': + - cell [ref=e750] [cursor=pointer] + - cell "308" [ref=e751] [cursor=pointer] + - 'cell "+ onReorderItem: onReorder," [ref=e752]': + - generic [ref=e753]: "+ onReorderItem: onReorder," + - 'row "310 309 proxyDecorator: (child, _, animation) => Material(" [ref=e754]': + - cell "310" [ref=e755] [cursor=pointer] + - cell "309" [ref=e756] [cursor=pointer] + - 'cell "proxyDecorator: (child, _, animation) => Material(" [ref=e757]': + - generic [ref=e758]: "proxyDecorator: (child, _, animation) => Material(" + - generic [ref=e765]: + - generic [ref=e768]: + - heading "Copilot commented on Jun 3, 2026 13 hours ago" [level=3] [ref=e769]: + - text: Copilot commented + - generic "Jun 3, 2026, 5:19 PM EDT" [ref=e770]: on Jun 3, 2026 13 hours ago + - img "Copilot" [ref=e773] + - generic [ref=e774]: + - generic [ref=e775]: + - generic [ref=e776]: Copilot + - generic [ref=e777]: AI + - link "on Jun 3, 202613 hours ago" [ref=e780] [cursor=pointer]: + - /url: https://github.com/CodeStorm-Hub/petfolio/pull/17#discussion_r3351989311 + - generic "Jun 3, 2026, 5:19 PM EDT" [ref=e781]: on Jun 3, 202613 hours ago + - generic [ref=e783]: + - list [ref=e785]: + - listitem + - listitem [ref=e786]: + - generic [ref=e787]: High + - button "Actions for Copilot's comment, 5:19 PM yesterday" [ref=e789] [cursor=pointer]: + - img [ref=e790] + - generic [ref=e793]: + - paragraph [ref=e796]: + - code [ref=e797]: SliverReorderableList + - text: uses the standard + - code [ref=e798]: onReorder + - text: callback; + - code [ref=e799]: onReorderItem + - text: is not a valid parameter for the Flutter widget and will fail to compile. Use + - code [ref=e800]: "onReorder:" + - text: here (and keep the callback signature + - code [ref=e801]: void Function(int oldIndex, int newIndex) + - text: ). + - generic [ref=e802]: + - toolbar "Reactions" + - generic [ref=e804]: + - button "Positive feedback" [ref=e805] [cursor=pointer]: + - img [ref=e806] + - button "Negative feedback" [ref=e808] [cursor=pointer]: + - img [ref=e809] + - generic [ref=e811]: Copilot uses AI. Check for mistakes. + - generic [ref=e813]: + - generic [ref=e814]: + - button "Comment thread" [expanded] [ref=e815] [cursor=pointer]: + - img + - link "lib/features/care/presentation/widgets/gamified_care_ui.dart" [ref=e817] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/files/7b8aaf186f6047b802df726bad66459f0cfe10ec#diff-8e2cf796cdb83ed78c034ccd2f1ab099667749421148c7f255df9b4f1317c508 + - generic [ref=e818]: + - generic [ref=e820]: Comment on lines +1104 to +1114 + - table [ref=e823]: + - rowgroup [ref=e824]: + - 'row "1104 + final sheenDuration = Duration(milliseconds: 3800 + widget.index * 200);" [ref=e825]': + - cell [ref=e826] [cursor=pointer] + - cell "1104" [ref=e827] [cursor=pointer] + - 'cell "+ final sheenDuration = Duration(milliseconds: 3800 + widget.index * 200);" [ref=e828]': + - generic [ref=e829]: "+ final sheenDuration = Duration(milliseconds: 3800 + widget.index * 200);" + - 'row "1105 + _sheenCtrl = AnimationController(vsync: this, duration: sheenDuration);" [ref=e830]': + - cell [ref=e831] [cursor=pointer] + - cell "1105" [ref=e832] [cursor=pointer] + - 'cell "+ _sheenCtrl = AnimationController(vsync: this, duration: sheenDuration);" [ref=e833]': + - generic [ref=e834]: "+ _sheenCtrl = AnimationController(vsync: this, duration: sheenDuration);" + - row "1106 +" [ref=e835]: + - cell [ref=e836] [cursor=pointer] + - cell "1106" [ref=e837] [cursor=pointer] + - cell "+" [ref=e838]: + - generic: + + - 'row "1107 + if (widget.owned) {" [ref=e839]': + - cell [ref=e840] [cursor=pointer] + - cell "1107" [ref=e841] [cursor=pointer] + - 'cell "+ if (widget.owned) {" [ref=e842]': + - generic [ref=e843]: "+ if (widget.owned) {" + - row "1108 + final delayFraction =" [ref=e844]: + - cell [ref=e845] [cursor=pointer] + - cell "1108" [ref=e846] [cursor=pointer] + - cell "+ final delayFraction =" [ref=e847]: + - generic [ref=e848]: + final delayFraction = + - row "1109 + (widget.index * 300 / sheenDuration.inMilliseconds).clamp(0.0, 1.0);" [ref=e849]: + - cell [ref=e850] [cursor=pointer] + - cell "1109" [ref=e851] [cursor=pointer] + - cell "+ (widget.index * 300 / sheenDuration.inMilliseconds).clamp(0.0, 1.0);" [ref=e852]: + - generic [ref=e853]: + (widget.index * 300 / sheenDuration.inMilliseconds).clamp(0.0, 1.0); + - 'row "1110 + _sheenCtrl.forward(from: delayFraction);" [ref=e854]': + - cell [ref=e855] [cursor=pointer] + - cell "1110" [ref=e856] [cursor=pointer] + - 'cell "+ _sheenCtrl.forward(from: delayFraction);" [ref=e857]': + - generic [ref=e858]: "+ _sheenCtrl.forward(from: delayFraction);" + - 'row "1111 + _sheenCtrl.addStatusListener((s) {" [ref=e859]': + - cell [ref=e860] [cursor=pointer] + - cell "1111" [ref=e861] [cursor=pointer] + - 'cell "+ _sheenCtrl.addStatusListener((s) {" [ref=e862]': + - generic [ref=e863]: "+ _sheenCtrl.addStatusListener((s) {" + - row "1112 + if (s == AnimationStatus.completed && mounted) _sheenCtrl.repeat();" [ref=e864]: + - cell [ref=e865] [cursor=pointer] + - cell "1112" [ref=e866] [cursor=pointer] + - cell "+ if (s == AnimationStatus.completed && mounted) _sheenCtrl.repeat();" [ref=e867]: + - generic [ref=e868]: + if (s == AnimationStatus.completed && mounted) _sheenCtrl.repeat(); + - 'row "1113 + });" [ref=e869]': + - cell [ref=e870] [cursor=pointer] + - cell "1113" [ref=e871] [cursor=pointer] + - 'cell "+ });" [ref=e872]': + - generic [ref=e873]: "+ });" + - 'row "1114 + }" [ref=e874]': + - cell [ref=e875] [cursor=pointer] + - cell "1114" [ref=e876] [cursor=pointer] + - 'cell "+ }" [ref=e877]': + - generic [ref=e878]: "+ }" + - generic [ref=e885]: + - generic [ref=e888]: + - heading "Copilot commented on Jun 3, 2026 13 hours ago" [level=3] [ref=e889]: + - text: Copilot commented + - generic "Jun 3, 2026, 5:19 PM EDT" [ref=e890]: on Jun 3, 2026 13 hours ago + - img "Copilot" [ref=e893] + - generic [ref=e894]: + - generic [ref=e895]: + - generic [ref=e896]: Copilot + - generic [ref=e897]: AI + - link "on Jun 3, 202613 hours ago" [ref=e900] [cursor=pointer]: + - /url: https://github.com/CodeStorm-Hub/petfolio/pull/17#discussion_r3351989359 + - generic "Jun 3, 2026, 5:19 PM EDT" [ref=e901]: on Jun 3, 202613 hours ago + - generic [ref=e903]: + - list [ref=e905]: + - listitem + - listitem [ref=e906]: + - generic [ref=e907]: Medium + - button "Actions for Copilot's comment, 5:19 PM yesterday" [ref=e909] [cursor=pointer]: + - img [ref=e910] + - generic [ref=e913]: + - paragraph [ref=e916]: + - text: The sheen animation only starts in + - code [ref=e917]: initState + - text: when + - code [ref=e918]: widget.owned + - text: is true. If a badge becomes owned while the screen is open (provider updates), this state object will be reused and + - code [ref=e919]: _sheenCtrl + - text: will never start, leaving owned badges without the intended sheen until a full rebuild/navigation. + - generic [ref=e920]: + - generic [ref=e922]: + - text: Suggested changeset + - generic [ref=e923]: "1" + - generic [ref=e924]: (1) + - generic [ref=e926]: + - button "Open review comment" [ref=e927] [cursor=pointer]: + - img [ref=e928] + - text: lib/features/care/presentation/widgets/gamified_care_ui.dart + - button "Commit suggestion" [ref=e931] [cursor=pointer]: + - generic [ref=e933]: Commit suggestion + - generic [ref=e934]: + - toolbar "Reactions" + - generic [ref=e936]: + - button "Positive feedback" [ref=e937] [cursor=pointer]: + - img [ref=e938] + - button "Negative feedback" [ref=e940] [cursor=pointer]: + - img [ref=e941] + - generic [ref=e943]: Copilot uses AI. Check for mistakes. + - generic [ref=e945]: + - generic [ref=e946]: + - button "Comment thread" [expanded] [ref=e947] [cursor=pointer]: + - img + - link "vercel.json" [ref=e949] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/files/7b8aaf186f6047b802df726bad66459f0cfe10ec#diff-a3265310f552fb66876e8bfe8809737e59e5ba946bdf39138b44d9baf4e21240 + - generic [ref=e950]: + - generic [ref=e952]: Comment on lines +18 to +25 + - table [ref=e955]: + - rowgroup [ref=e956]: + - 'row "18 + }," [ref=e957]': + - cell [ref=e958] [cursor=pointer] + - cell "18" [ref=e959] [cursor=pointer] + - 'cell "+ }," [ref=e960]': + - generic [ref=e961]: "+ }," + - 'row "19 + {" [ref=e962]': + - cell [ref=e963] [cursor=pointer] + - cell "19" [ref=e964] [cursor=pointer] + - 'cell "+ {" [ref=e965]': + - generic [ref=e966]: "+ {" + - 'row "20 + \"source\": \"/(.*)\"," [ref=e967]': + - cell [ref=e968] [cursor=pointer] + - cell "20" [ref=e969] [cursor=pointer] + - 'cell "+ \"source\": \"/(.*)\"," [ref=e970]': + - generic [ref=e971]: "+ \"source\": \"/(.*)\"," + - 'row "21 + \"headers\": [" [ref=e972]': + - cell [ref=e973] [cursor=pointer] + - cell "21" [ref=e974] [cursor=pointer] + - 'cell "+ \"headers\": [" [ref=e975]': + - generic [ref=e976]: "+ \"headers\": [" + - 'row "22 + { \"key\": \"Cross-Origin-Embedder-Policy\", \"value\": \"require-corp\" }," [ref=e977]': + - cell [ref=e978] [cursor=pointer] + - cell "22" [ref=e979] [cursor=pointer] + - 'cell "+ { \"key\": \"Cross-Origin-Embedder-Policy\", \"value\": \"require-corp\" }," [ref=e980]': + - generic [ref=e981]: "+ { \"key\": \"Cross-Origin-Embedder-Policy\", \"value\": \"require-corp\" }," + - 'row "23 + { \"key\": \"Cross-Origin-Opener-Policy\", \"value\": \"same-origin\" }" [ref=e982]': + - cell [ref=e983] [cursor=pointer] + - cell "23" [ref=e984] [cursor=pointer] + - 'cell "+ { \"key\": \"Cross-Origin-Opener-Policy\", \"value\": \"same-origin\" }" [ref=e985]': + - generic [ref=e986]: "+ { \"key\": \"Cross-Origin-Opener-Policy\", \"value\": \"same-origin\" }" + - row "24 + ]" [ref=e987]: + - cell [ref=e988] [cursor=pointer] + - cell "24" [ref=e989] [cursor=pointer] + - cell "+ ]" [ref=e990]: + - generic [ref=e991]: + ] + - 'row "25 + }" [ref=e992]': + - cell [ref=e993] [cursor=pointer] + - cell "25" [ref=e994] [cursor=pointer] + - 'cell "+ }" [ref=e995]': + - generic [ref=e996]: "+ }" + - generic [ref=e1003]: + - generic [ref=e1006]: + - heading "Copilot commented on Jun 3, 2026 13 hours ago" [level=3] [ref=e1007]: + - text: Copilot commented + - generic "Jun 3, 2026, 5:19 PM EDT" [ref=e1008]: on Jun 3, 2026 13 hours ago + - img "Copilot" [ref=e1011] + - generic [ref=e1012]: + - generic [ref=e1013]: + - generic [ref=e1014]: Copilot + - generic [ref=e1015]: AI + - link "on Jun 3, 202613 hours ago" [ref=e1018] [cursor=pointer]: + - /url: https://github.com/CodeStorm-Hub/petfolio/pull/17#discussion_r3351989389 + - generic "Jun 3, 2026, 5:19 PM EDT" [ref=e1019]: on Jun 3, 202613 hours ago + - generic [ref=e1021]: + - list [ref=e1023]: + - listitem + - listitem [ref=e1024]: + - generic [ref=e1025]: High + - button "Actions for Copilot's comment, 5:19 PM yesterday" [ref=e1027] [cursor=pointer]: + - img [ref=e1028] + - generic [ref=e1031]: + - paragraph [ref=e1034]: + - text: Setting + - code [ref=e1035]: "Cross-Origin-Embedder-Policy: require-corp" + - text: + + - code [ref=e1036]: "Cross-Origin-Opener-Policy: same-origin" + - text: for + - strong [ref=e1037]: all + - text: routes can break loading cross-origin resources that don't explicitly grant CORP/CORS (for example + - code [ref=e1038]: https://js.stripe.com/v3/ + - text: included in + - code [ref=e1039]: web/index.html + - text: ). Unless the app specifically needs cross-origin isolation globally, limit these headers to the + - code [ref=e1040]: .wasm + - text: route(s) that require them. + - generic [ref=e1041]: + - generic [ref=e1043]: + - text: Suggested changeset + - generic [ref=e1044]: "1" + - generic [ref=e1045]: (1) + - generic [ref=e1046]: + - generic [ref=e1047]: + - button "Close review comment" [ref=e1048] [cursor=pointer]: + - img [ref=e1049] + - text: vercel.json + - table [ref=e1052]: + - rowgroup [ref=e1053]: + - row "Original file line number Diff line number Diff line change" [ref=e1054]: + - columnheader "Original file line number" [ref=e1055] + - columnheader "Diff line number" [ref=e1056] + - columnheader "Diff line change" [ref=e1057] + - rowgroup [ref=e1062]: + - row "@@ -15,13 +15,6 @@" [ref=e1063]: + - cell "@@ -15,13 +15,6 @@" [ref=e1064]: + - generic [ref=e1065]: + - img [ref=e1067] + - code [ref=e1069]: + - generic [ref=e1070]: "@@ -15,13 +15,6 @@" + - 'row "15 15 { \"key\": \"Cross-Origin-Embedder-Policy\", \"value\": \"require-corp\" }," [ref=e1071]': + - cell "15" [ref=e1072]: + - code [ref=e1073]: "15" + - cell "15" [ref=e1074]: + - code [ref=e1075]: "15" + - 'cell "{ \"key\": \"Cross-Origin-Embedder-Policy\", \"value\": \"require-corp\" }," [ref=e1076]': + - code [ref=e1077]: + - generic [ref=e1078]: + - text: "{ \"key\":" + - generic [ref=e1079]: "\"Cross-Origin-Embedder-Policy\"" + - text: ", \"value\":" + - generic [ref=e1080]: "\"require-corp\"" + - text: "}," + - 'row "16 16 { \"key\": \"Cross-Origin-Opener-Policy\", \"value\": \"same-origin\" }" [ref=e1081]': + - cell "16" [ref=e1082]: + - code [ref=e1083]: "16" + - cell "16" [ref=e1084]: + - code [ref=e1085]: "16" + - 'cell "{ \"key\": \"Cross-Origin-Opener-Policy\", \"value\": \"same-origin\" }" [ref=e1086]': + - code [ref=e1087]: + - generic [ref=e1088]: + - text: "{ \"key\":" + - generic [ref=e1089]: "\"Cross-Origin-Opener-Policy\"" + - text: ", \"value\":" + - generic [ref=e1090]: "\"same-origin\"" + - text: "}" + - row "17 17 ]" [ref=e1091]: + - cell "17" [ref=e1092]: + - code [ref=e1093]: "17" + - cell "17" [ref=e1094]: + - code [ref=e1095]: "17" + - cell "]" [ref=e1096]: + - code [ref=e1097]: + - generic [ref=e1098]: "]" + - 'row "18 - }," [ref=e1099]': + - cell "18" [ref=e1100]: + - code [ref=e1101]: "18" + - cell [ref=e1102]: + - code + - 'cell "- }," [ref=e1103]': + - code [ref=e1104]: + - generic [ref=e1105]: "-" + - generic [ref=e1106]: "}," + - 'row "19 - {" [ref=e1107]': + - cell "19" [ref=e1108]: + - code [ref=e1109]: "19" + - cell [ref=e1110]: + - code + - 'cell "- {" [ref=e1111]': + - code [ref=e1112]: + - generic [ref=e1113]: "-" + - generic [ref=e1114]: "{" + - 'row "20 - \"source\": \"/(.*)\"," [ref=e1115]': + - cell "20" [ref=e1116]: + - code [ref=e1117]: "20" + - cell [ref=e1118]: + - code + - 'cell "- \"source\": \"/(.*)\"," [ref=e1119]': + - code [ref=e1120]: + - generic [ref=e1121]: "-" + - generic [ref=e1122]: + - text: "\"source\":" + - generic [ref=e1123]: "\"/(.*)\"" + - text: "," + - 'row "21 - \"headers\": [" [ref=e1124]': + - cell "21" [ref=e1125]: + - code [ref=e1126]: "21" + - cell [ref=e1127]: + - code + - 'cell "- \"headers\": [" [ref=e1128]': + - code [ref=e1129]: + - generic [ref=e1130]: "-" + - generic [ref=e1131]: "\"headers\": [" + - 'row "22 - { \"key\": \"Cross-Origin-Embedder-Policy\", \"value\": \"require-corp\" }," [ref=e1132]': + - cell "22" [ref=e1133]: + - code [ref=e1134]: "22" + - cell [ref=e1135]: + - code + - 'cell "- { \"key\": \"Cross-Origin-Embedder-Policy\", \"value\": \"require-corp\" }," [ref=e1136]': + - code [ref=e1137]: + - generic [ref=e1138]: "-" + - generic [ref=e1139]: + - text: "{ \"key\":" + - generic [ref=e1140]: "\"Cross-Origin-Embedder-Policy\"" + - text: ", \"value\":" + - generic [ref=e1141]: "\"require-corp\"" + - text: "}," + - 'row "23 - { \"key\": \"Cross-Origin-Opener-Policy\", \"value\": \"same-origin\" }" [ref=e1142]': + - cell "23" [ref=e1143]: + - code [ref=e1144]: "23" + - cell [ref=e1145]: + - code + - 'cell "- { \"key\": \"Cross-Origin-Opener-Policy\", \"value\": \"same-origin\" }" [ref=e1146]': + - code [ref=e1147]: + - generic [ref=e1148]: "-" + - generic [ref=e1149]: + - text: "{ \"key\":" + - generic [ref=e1150]: "\"Cross-Origin-Opener-Policy\"" + - text: ", \"value\":" + - generic [ref=e1151]: "\"same-origin\"" + - text: "}" + - row "24 - ]" [ref=e1152]: + - cell "24" [ref=e1153]: + - code [ref=e1154]: "24" + - cell [ref=e1155]: + - code + - cell "- ]" [ref=e1156]: + - code [ref=e1157]: + - generic [ref=e1158]: "-" + - generic [ref=e1159]: "]" + - 'row "25 18 }" [ref=e1160]': + - cell "25" [ref=e1161]: + - code [ref=e1162]: "25" + - cell "18" [ref=e1163]: + - code [ref=e1164]: "18" + - 'cell "}" [ref=e1165]': + - code [ref=e1166]: + - generic [ref=e1167]: "}" + - row "26 19 ]," [ref=e1168]: + - cell "26" [ref=e1169]: + - code [ref=e1170]: "26" + - cell "19" [ref=e1171]: + - code [ref=e1172]: "19" + - cell "]," [ref=e1173]: + - code [ref=e1174]: + - generic [ref=e1175]: "]," + - 'row "27 20 \"rewrites\": [" [ref=e1176]': + - cell "27" [ref=e1177]: + - code [ref=e1178]: "27" + - cell "20" [ref=e1179]: + - code [ref=e1180]: "20" + - 'cell "\"rewrites\": [" [ref=e1181]': + - code [ref=e1182]: + - generic [ref=e1183]: "\"rewrites\": [" + - button "Commit suggestion" [ref=e1185] [cursor=pointer]: + - generic [ref=e1187]: Commit suggestion + - generic [ref=e1188]: + - toolbar "Reactions" + - generic [ref=e1190]: + - button "Positive feedback" [ref=e1191] [cursor=pointer]: + - img [ref=e1192] + - button "Negative feedback" [ref=e1194] [cursor=pointer]: + - img [ref=e1195] + - generic [ref=e1197]: Copilot uses AI. Check for mistakes. + - generic [ref=e1199]: + - generic [ref=e1200]: + - button "Comment thread" [expanded] [ref=e1201] [cursor=pointer]: + - img + - link ".claude/launch.json" [ref=e1203] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/files/7b8aaf186f6047b802df726bad66459f0cfe10ec#diff-f02a361fa828af1bddd7c60baccb9ec7036882b427c5e6f2d734cf6414f3b36c + - generic [ref=e1204]: + - generic [ref=e1206]: Comment on lines +12 to +15 + - table [ref=e1209]: + - rowgroup [ref=e1210]: + - row "12 + \"--dart-define=SUPABASE_URL=https://jqyjvhwlcqcsuwcqgcwf.supabase.co\"," [ref=e1211]: + - cell [ref=e1212] [cursor=pointer] + - cell "12" [ref=e1213] [cursor=pointer] + - cell "+ \"--dart-define=SUPABASE_URL=https://jqyjvhwlcqcsuwcqgcwf.supabase.co\"," [ref=e1214]: + - generic [ref=e1215]: + "--dart-define=SUPABASE_URL=https://jqyjvhwlcqcsuwcqgcwf.supabase.co", + - row "13 + \"--dart-define=SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImpxeWp2aHdsY3Fjc3V3Y3FnY3dmIiwicm9sZSI6ImFub24iLCJpYXQiOjE3Nzg1MjI4MjgsImV4cCI6MjA5NDA5ODgyOH0.3bF68bNG0IwAc50YbOC3sem4k8O-d1vkvNNqBt1HbRw\"," [ref=e1216]: + - cell [ref=e1217] [cursor=pointer] + - cell "13" [ref=e1218] [cursor=pointer] + - cell "+ \"--dart-define=SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImpxeWp2aHdsY3Fjc3V3Y3FnY3dmIiwicm9sZSI6ImFub24iLCJpYXQiOjE3Nzg1MjI4MjgsImV4cCI6MjA5NDA5ODgyOH0.3bF68bNG0IwAc50YbOC3sem4k8O-d1vkvNNqBt1HbRw\"," [ref=e1219]: + - generic [ref=e1220]: + "--dart-define=SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImpxeWp2aHdsY3Fjc3V3Y3FnY3dmIiwicm9sZSI6ImFub24iLCJpYXQiOjE3Nzg1MjI4MjgsImV4cCI6MjA5NDA5ODgyOH0.3bF68bNG0IwAc50YbOC3sem4k8O-d1vkvNNqBt1HbRw", + - row "14 + \"--dart-define=STRIPE_PUBLISHABLE_KEY=pk_test_51TQvlrPcVRApxzIxJ8RmKYA1WEw7k8zubumbIfsDjRSGgDyAcSU22RhsZRtKIP1lAZ0wtGjpLfzjI4fozMZxGSlo006zuZrbon\"," [ref=e1221]: + - cell [ref=e1222] [cursor=pointer] + - cell "14" [ref=e1223] [cursor=pointer] + - cell "+ \"--dart-define=STRIPE_PUBLISHABLE_KEY=pk_test_51TQvlrPcVRApxzIxJ8RmKYA1WEw7k8zubumbIfsDjRSGgDyAcSU22RhsZRtKIP1lAZ0wtGjpLfzjI4fozMZxGSlo006zuZrbon\"," [ref=e1224]: + - generic [ref=e1225]: + "--dart-define=STRIPE_PUBLISHABLE_KEY=pk_test_51TQvlrPcVRApxzIxJ8RmKYA1WEw7k8zubumbIfsDjRSGgDyAcSU22RhsZRtKIP1lAZ0wtGjpLfzjI4fozMZxGSlo006zuZrbon", + - row "15 + \"--dart-define=NVIDIA_API_KEY=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\"" [ref=e1226]: + - cell [ref=e1227] [cursor=pointer] + - cell "15" [ref=e1228] [cursor=pointer] + - cell "+ \"--dart-define=NVIDIA_API_KEY=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\"" [ref=e1229]: + - generic [ref=e1230]: + "--dart-define=NVIDIA_API_KEY=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" + - generic [ref=e1237]: + - generic [ref=e1240]: + - heading "Copilot commented on Jun 3, 2026 13 hours ago" [level=3] [ref=e1241]: + - text: Copilot commented + - generic "Jun 3, 2026, 5:19 PM EDT" [ref=e1242]: on Jun 3, 2026 13 hours ago + - img "Copilot" [ref=e1245] + - generic [ref=e1246]: + - generic [ref=e1247]: + - generic [ref=e1248]: Copilot + - generic [ref=e1249]: AI + - link "on Jun 3, 202613 hours ago" [ref=e1252] [cursor=pointer]: + - /url: https://github.com/CodeStorm-Hub/petfolio/pull/17#discussion_r3351989407 + - generic "Jun 3, 2026, 5:19 PM EDT" [ref=e1253]: on Jun 3, 202613 hours ago + - generic [ref=e1255]: + - list [ref=e1257]: + - listitem + - listitem [ref=e1258]: + - generic [ref=e1259]: High + - button "Actions for Copilot's comment, 5:19 PM yesterday" [ref=e1261] [cursor=pointer]: + - img [ref=e1262] + - generic [ref=e1265]: + - paragraph [ref=e1268]: + - text: This launch config commits real credentials/tokens ( + - code [ref=e1269]: SUPABASE_ANON_KEY + - text: ", Stripe publishable key, NVIDIA API key). Even if some are \"public\", committing them makes rotation harder and can trigger automated secret scanning. Prefer reading values from an untracked" + - code [ref=e1270]: .env + - text: (the repo already uses + - code [ref=e1271]: "--dart-define-from-file=.env" + - text: ). + - generic [ref=e1272]: + - generic [ref=e1274]: + - text: Suggested changeset + - generic [ref=e1275]: "1" + - generic [ref=e1276]: (1) + - generic [ref=e1277]: + - generic [ref=e1278]: + - button "Close review comment" [ref=e1279] [cursor=pointer]: + - img [ref=e1280] + - text: .claude/launch.json + - table [ref=e1283]: + - rowgroup [ref=e1284]: + - row "Original file line number Diff line number Diff line change" [ref=e1285]: + - columnheader "Original file line number" [ref=e1286] + - columnheader "Diff line number" [ref=e1287] + - columnheader "Diff line change" [ref=e1288] + - rowgroup [ref=e1293]: + - row "@@ -9,10 +9,7 @@" [ref=e1294]: + - cell "@@ -9,10 +9,7 @@" [ref=e1295]: + - generic [ref=e1296]: + - img [ref=e1298] + - code [ref=e1300]: + - generic [ref=e1301]: "@@ -9,10 +9,7 @@" + - row "9 9 \"-d\", \"web-server\"," [ref=e1302]: + - cell "9" [ref=e1303]: + - code [ref=e1304]: "9" + - cell "9" [ref=e1305]: + - code [ref=e1306]: "9" + - cell "\"-d\", \"web-server\"," [ref=e1307]: + - code [ref=e1308]: + - generic [ref=e1309]: + - generic [ref=e1310]: "\"-d\"" + - text: "," + - generic [ref=e1311]: "\"web-server\"" + - text: "," + - row "10 10 \"--web-port=8080\"," [ref=e1312]: + - cell "10" [ref=e1313]: + - code [ref=e1314]: "10" + - cell "10" [ref=e1315]: + - code [ref=e1316]: "10" + - cell "\"--web-port=8080\"," [ref=e1317]: + - code [ref=e1318]: + - generic [ref=e1319]: + - generic [ref=e1320]: "\"--web-port=8080\"" + - text: "," + - row "11 11 \"--web-hostname=localhost\"," [ref=e1321]: + - cell "11" [ref=e1322]: + - code [ref=e1323]: "11" + - cell "11" [ref=e1324]: + - code [ref=e1325]: "11" + - cell "\"--web-hostname=localhost\"," [ref=e1326]: + - code [ref=e1327]: + - generic [ref=e1328]: + - generic [ref=e1329]: "\"--web-hostname=localhost\"" + - text: "," + - row "12 - \"--dart-define=SUPABASE_URL=https://jqyjvhwlcqcsuwcqgcwf.supabase.co\"," [ref=e1330]: + - cell "12" [ref=e1331]: + - code [ref=e1332]: "12" + - cell [ref=e1333]: + - code + - cell "- \"--dart-define=SUPABASE_URL=https://jqyjvhwlcqcsuwcqgcwf.supabase.co\"," [ref=e1334]: + - code [ref=e1335]: + - generic [ref=e1336]: "-" + - generic [ref=e1337]: + - generic [ref=e1338]: "\"--dart-define=SUPABASE_URL=https://jqyjvhwlcqcsuwcqgcwf.supabase.co\"" + - text: "," + - row "13 - \"--dart-define=SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImpxeWp2aHdsY3Fjc3V3Y3FnY3dmIiwicm9sZSI6ImFub24iLCJpYXQiOjE3Nzg1MjI4MjgsImV4cCI6MjA5NDA5ODgyOH0.3bF68bNG0IwAc50YbOC3sem4k8O-d1vkvNNqBt1HbRw\"," [ref=e1339]: + - cell "13" [ref=e1340]: + - code [ref=e1341]: "13" + - cell [ref=e1342]: + - code + - cell "- \"--dart-define=SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImpxeWp2aHdsY3Fjc3V3Y3FnY3dmIiwicm9sZSI6ImFub24iLCJpYXQiOjE3Nzg1MjI4MjgsImV4cCI6MjA5NDA5ODgyOH0.3bF68bNG0IwAc50YbOC3sem4k8O-d1vkvNNqBt1HbRw\"," [ref=e1343]: + - code [ref=e1344]: + - generic [ref=e1345]: "-" + - generic [ref=e1346]: + - generic [ref=e1347]: "\"--dart-define=SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImpxeWp2aHdsY3Fjc3V3Y3FnY3dmIiwicm9sZSI6ImFub24iLCJpYXQiOjE3Nzg1MjI4MjgsImV4cCI6MjA5NDA5ODgyOH0.3bF68bNG0IwAc50YbOC3sem4k8O-d1vkvNNqBt1HbRw\"" + - text: "," + - row "14 - \"--dart-define=STRIPE_PUBLISHABLE_KEY=pk_test_51TQvlrPcVRApxzIxJ8RmKYA1WEw7k8zubumbIfsDjRSGgDyAcSU22RhsZRtKIP1lAZ0wtGjpLfzjI4fozMZxGSlo006zuZrbon\"," [ref=e1348]: + - cell "14" [ref=e1349]: + - code [ref=e1350]: "14" + - cell [ref=e1351]: + - code + - cell "- \"--dart-define=STRIPE_PUBLISHABLE_KEY=pk_test_51TQvlrPcVRApxzIxJ8RmKYA1WEw7k8zubumbIfsDjRSGgDyAcSU22RhsZRtKIP1lAZ0wtGjpLfzjI4fozMZxGSlo006zuZrbon\"," [ref=e1352]: + - code [ref=e1353]: + - generic [ref=e1354]: "-" + - generic [ref=e1355]: + - generic [ref=e1356]: "\"--dart-define=STRIPE_PUBLISHABLE_KEY=pk_test_51TQvlrPcVRApxzIxJ8RmKYA1WEw7k8zubumbIfsDjRSGgDyAcSU22RhsZRtKIP1lAZ0wtGjpLfzjI4fozMZxGSlo006zuZrbon\"" + - text: "," + - row "15 - \"--dart-define=NVIDIA_API_KEY=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\"" [ref=e1357]: + - cell "15" [ref=e1358]: + - code [ref=e1359]: "15" + - cell [ref=e1360]: + - code + - cell "- \"--dart-define=NVIDIA_API_KEY=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\"" [ref=e1361]: + - code [ref=e1362]: + - generic [ref=e1363]: "-" + - generic [ref=e1365]: "\"--dart-define=NVIDIA_API_KEY=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\"" + - row "12 + \"--dart-define-from-file=.env\"" [ref=e1366]: + - cell [ref=e1367]: + - code + - cell "12" [ref=e1368]: + - code [ref=e1369]: "12" + - cell "+ \"--dart-define-from-file=.env\"" [ref=e1370]: + - code [ref=e1371]: + - generic [ref=e1372]: + + - generic [ref=e1374]: "\"--dart-define-from-file=.env\"" + - row "16 13 ]," [ref=e1375]: + - cell "16" [ref=e1376]: + - code [ref=e1377]: "16" + - cell "13" [ref=e1378]: + - code [ref=e1379]: "13" + - cell "]," [ref=e1380]: + - code [ref=e1381]: + - generic [ref=e1382]: "]," + - 'row "17 14 \"port\": 8080" [ref=e1383]': + - cell "17" [ref=e1384]: + - code [ref=e1385]: "17" + - cell "14" [ref=e1386]: + - code [ref=e1387]: "14" + - 'cell "\"port\": 8080" [ref=e1388]': + - code [ref=e1389]: + - generic [ref=e1390]: "\"port\": 8080" + - 'row "18 15 }" [ref=e1391]': + - cell "18" [ref=e1392]: + - code [ref=e1393]: "18" + - cell "15" [ref=e1394]: + - code [ref=e1395]: "15" + - 'cell "}" [ref=e1396]': + - code [ref=e1397]: + - generic [ref=e1398]: "}" + - button "Commit suggestion" [ref=e1400] [cursor=pointer]: + - generic [ref=e1402]: Commit suggestion + - generic [ref=e1403]: + - toolbar "Reactions" + - generic [ref=e1405]: + - button "Positive feedback" [ref=e1406] [cursor=pointer]: + - img [ref=e1407] + - button "Negative feedback" [ref=e1409] [cursor=pointer]: + - img [ref=e1410] + - generic [ref=e1412]: Copilot uses AI. Check for mistakes. + - generic [ref=e1414]: + - generic [ref=e1415]: + - button "Comment thread" [expanded] [ref=e1416] [cursor=pointer]: + - img + - link "PetFolio Redesign/README.md" [ref=e1418] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/files/7b8aaf186f6047b802df726bad66459f0cfe10ec#diff-fd9c484a61afd6b6a220d0eb2d9b8ee1a8a8490653b7a94ced8ea8e43d7860c7 + - generic [ref=e1419]: + - generic [ref=e1421]: Comment on lines +9 to +10 + - table [ref=e1424]: + - rowgroup [ref=e1425]: + - 'row "9 + **Read `petfolio-redesign/project/Care Redesign/Care Redesign.html` in full.** The user had this file open when they triggered the handoff, so it''s almost certainly the primary design they want built. Read it top to bottom — don''t skim. Then **follow its imports**: open every file it pulls in (shared components, CSS, scripts) so you understand how the pieces fit together before you start implementing." [ref=e1426]': + - cell [ref=e1427] [cursor=pointer] + - cell "9" [ref=e1428] [cursor=pointer] + - 'cell "+ **Read `petfolio-redesign/project/Care Redesign/Care Redesign.html` in full.** The user had this file open when they triggered the handoff, so it''s almost certainly the primary design they want built. Read it top to bottom — don''t skim. Then **follow its imports**: open every file it pulls in (shared components, CSS, scripts) so you understand how the pieces fit together before you start implementing." [ref=e1429]': + - generic [ref=e1430]: "+ **Read `petfolio-redesign/project/Care Redesign/Care Redesign.html` in full.** The user had this file open when they triggered the handoff, so it's almost certainly the primary design they want built. Read it top to bottom — don't skim. Then **follow its imports**: open every file it pulls in (shared components, CSS, scripts) so you understand how the pieces fit together before you start implementing." + - row "10 +" [ref=e1431]: + - cell [ref=e1432] [cursor=pointer] + - cell "10" [ref=e1433] [cursor=pointer] + - cell "+" [ref=e1434]: + - generic: + + - generic [ref=e1441]: + - generic [ref=e1444]: + - heading "Copilot commented on Jun 3, 2026 13 hours ago" [level=3] [ref=e1445]: + - text: Copilot commented + - generic "Jun 3, 2026, 5:19 PM EDT" [ref=e1446]: on Jun 3, 2026 13 hours ago + - img "Copilot" [ref=e1449] + - generic [ref=e1450]: + - generic [ref=e1451]: + - generic [ref=e1452]: Copilot + - generic [ref=e1453]: AI + - link "on Jun 3, 202613 hours ago" [ref=e1456] [cursor=pointer]: + - /url: https://github.com/CodeStorm-Hub/petfolio/pull/17#discussion_r3351989432 + - generic "Jun 3, 2026, 5:19 PM EDT" [ref=e1457]: on Jun 3, 202613 hours ago + - generic [ref=e1459]: + - list [ref=e1461]: + - listitem + - listitem [ref=e1462]: + - generic [ref=e1463]: Medium + - button "Actions for Copilot's comment, 5:19 PM yesterday" [ref=e1465] [cursor=pointer]: + - img [ref=e1466] + - generic [ref=e1469]: + - paragraph [ref=e1472]: + - text: The README points agents to + - code [ref=e1473]: petfolio-redesign/project/Care Redesign/Care Redesign.html + - text: ", but in this repo the prototype lives under" + - code [ref=e1474]: PetFolio Redesign/Care Redesign/Care Redesign.html + - text: . This path mismatch makes the handoff instructions incorrect. + - generic [ref=e1475]: + - generic [ref=e1477]: + - text: Suggested changeset + - generic [ref=e1478]: "1" + - generic [ref=e1479]: (1) + - generic [ref=e1480]: + - generic [ref=e1481]: + - button "Close review comment" [ref=e1482] [cursor=pointer]: + - img [ref=e1483] + - text: PetFolio Redesign/README.md + - table [ref=e1486]: + - rowgroup [ref=e1487]: + - row "Original file line number Diff line number Diff line change" [ref=e1488]: + - columnheader "Original file line number" [ref=e1489] + - columnheader "Diff line number" [ref=e1490] + - columnheader "Diff line change" [ref=e1491] + - rowgroup [ref=e1496]: + - row "@@ -6,8 +6,7 @@ A user mocked up designs in HTML/CSS/JS using an AI design tool, then exported t" [ref=e1497]: + - cell "@@ -6,8 +6,7 @@ A user mocked up designs in HTML/CSS/JS using an AI design tool, then exported t" [ref=e1498]: + - generic [ref=e1499]: + - img [ref=e1501] + - code [ref=e1503]: + - generic [ref=e1504]: "@@ -6,8 +6,7 @@ A user mocked up designs in HTML/CSS/JS using an AI design tool, then exported t" + - row "6 6" [ref=e1505]: + - cell "6" [ref=e1506]: + - code [ref=e1507]: "6" + - cell "6" [ref=e1508]: + - code [ref=e1509]: "6" + - cell [ref=e1510]: + - code + - 'row "7 7 ## What you should do — IMPORTANT" [ref=e1511]': + - cell "7" [ref=e1512]: + - code [ref=e1513]: "7" + - cell "7" [ref=e1514]: + - code [ref=e1515]: "7" + - cell "## What you should do — IMPORTANT" [ref=e1516]: + - code [ref=e1517]: + - generic [ref=e1519]: "## What you should do — IMPORTANT" + - row "8 8" [ref=e1520]: + - cell "8" [ref=e1521]: + - code [ref=e1522]: "8" + - cell "8" [ref=e1523]: + - code [ref=e1524]: "8" + - cell [ref=e1525]: + - code + - 'row "9 - **Read `petfolio-redesign/project/Care Redesign/Care Redesign.html` in full.** The user had this file open when they triggered the handoff, so it''s almost certainly the primary design they want built. Read it top to bottom — don''t skim. Then **follow its imports**: open every file it pulls in (shared components, CSS, scripts) so you understand how the pieces fit together before you start implementing." [ref=e1526]': + - cell "9" [ref=e1527]: + - code [ref=e1528]: "9" + - cell [ref=e1529]: + - code + - 'cell "- **Read `petfolio-redesign/project/Care Redesign/Care Redesign.html` in full.** The user had this file open when they triggered the handoff, so it''s almost certainly the primary design they want built. Read it top to bottom — don''t skim. Then **follow its imports**: open every file it pulls in (shared components, CSS, scripts) so you understand how the pieces fit together before you start implementing." [ref=e1530]': + - code [ref=e1531]: + - generic [ref=e1532]: "-" + - generic [ref=e1533]: "**Read `petfolio-redesign/project/Care Redesign/Care Redesign.html` in full.** The user had this file open when they triggered the handoff, so it's almost certainly the primary design they want built. Read it top to bottom — don't skim. Then **follow its imports**: open every file it pulls in (shared components, CSS, scripts) so you understand how the pieces fit together before you start implementing." + - row "10 -" [ref=e1534]: + - cell "10" [ref=e1535]: + - code [ref=e1536]: "10" + - cell [ref=e1537]: + - code + - cell "-" [ref=e1538]: + - code: + - generic [ref=e1539]: "-" + - 'row "9 + **Read `PetFolio Redesign/Care Redesign/Care Redesign.html` in full.** The user had this file open when they triggered the handoff, so it''s almost certainly the primary design they want built. Read it top to bottom — don''t skim. Then **follow its imports**: open every file it pulls in (shared components, CSS, scripts) so you understand how the pieces fit together before you start implementing." [ref=e1540]': + - cell [ref=e1541]: + - code + - cell "9" [ref=e1542]: + - code [ref=e1543]: "9" + - 'cell "+ **Read `PetFolio Redesign/Care Redesign/Care Redesign.html` in full.** The user had this file open when they triggered the handoff, so it''s almost certainly the primary design they want built. Read it top to bottom — don''t skim. Then **follow its imports**: open every file it pulls in (shared components, CSS, scripts) so you understand how the pieces fit together before you start implementing." [ref=e1544]': + - code [ref=e1545]: + - generic [ref=e1546]: + + - generic [ref=e1547]: "**Read `PetFolio Redesign/Care Redesign/Care Redesign.html` in full.** The user had this file open when they triggered the handoff, so it's almost certainly the primary design they want built. Read it top to bottom — don't skim. Then **follow its imports**: open every file it pulls in (shared components, CSS, scripts) so you understand how the pieces fit together before you start implementing." + - row "11 10 **If anything is ambiguous, ask the user to confirm before you start implementing.** It's much cheaper to clarify scope up front than to build the wrong thing." [ref=e1548]: + - cell "11" [ref=e1549]: + - code [ref=e1550]: "11" + - cell "10" [ref=e1551]: + - code [ref=e1552]: "10" + - cell "**If anything is ambiguous, ask the user to confirm before you start implementing.** It's much cheaper to clarify scope up front than to build the wrong thing." [ref=e1553]: + - code [ref=e1554]: + - generic [ref=e1555]: "**If anything is ambiguous, ask the user to confirm before you start implementing.** It's much cheaper to clarify scope up front than to build the wrong thing." + - row "12 11" [ref=e1556]: + - cell "12" [ref=e1557]: + - code [ref=e1558]: "12" + - cell "11" [ref=e1559]: + - code [ref=e1560]: "11" + - cell [ref=e1561]: + - code + - 'row "13 12 ## About the design files" [ref=e1562]': + - cell "13" [ref=e1563]: + - code [ref=e1564]: "13" + - cell "12" [ref=e1565]: + - code [ref=e1566]: "12" + - cell "## About the design files" [ref=e1567]: + - code [ref=e1568]: + - generic [ref=e1570]: "## About the design files" + - button "Commit suggestion" [ref=e1572] [cursor=pointer]: + - generic [ref=e1574]: Commit suggestion + - generic [ref=e1575]: + - toolbar "Reactions" + - generic [ref=e1577]: + - button "Positive feedback" [ref=e1578] [cursor=pointer]: + - img [ref=e1579] + - button "Negative feedback" [ref=e1581] [cursor=pointer]: + - img [ref=e1582] + - generic [ref=e1584]: Copilot uses AI. Check for mistakes. + - generic [ref=e1586]: + - button "3 hidden conversations" [ref=e1587] [cursor=pointer] + - button "Load more…" [ref=e1588] [cursor=pointer] + - generic [ref=e1590]: + - generic [ref=e1591]: + - button "Comment thread" [expanded] [ref=e1592] [cursor=pointer]: + - img + - link "flutter-run-log.md" [ref=e1594] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/files/7b8aaf186f6047b802df726bad66459f0cfe10ec#diff-16b408423dbe231e58527cb84ef8afbf35e91e234ca86b7b2301d59ba2351f7d + - generic [ref=e1595]: + - generic [ref=e1597]: Comment on lines +1 to +10 + - table [ref=e1600]: + - rowgroup [ref=e1601]: + - row "1 + PS G:\\GitHub\\petfolio> flutter run --dart-define-from-file=.env" [ref=e1602]: + - cell [ref=e1603] [cursor=pointer] + - cell "1" [ref=e1604] [cursor=pointer] + - cell "+ PS G:\\GitHub\\petfolio> flutter run --dart-define-from-file=.env" [ref=e1605]: + - generic [ref=e1606]: + PS G:\GitHub\petfolio> flutter run --dart-define-from-file=.env + - row "2 + Launching lib\\main.dart on sdk gphone16k x86 64 in debug mode..." [ref=e1607]: + - cell [ref=e1608] [cursor=pointer] + - cell "2" [ref=e1609] [cursor=pointer] + - cell "+ Launching lib\\main.dart on sdk gphone16k x86 64 in debug mode..." [ref=e1610]: + - generic [ref=e1611]: + Launching lib\main.dart on sdk gphone16k x86 64 in debug mode... + - 'row "3 + WARNING: Your Android app project: app located at: G:\\GitHub\\petfolio\\android\\app\\build.gradle.kts" [ref=e1612]': + - cell [ref=e1613] [cursor=pointer] + - cell "3" [ref=e1614] [cursor=pointer] + - 'cell "+ WARNING: Your Android app project: app located at: G:\\GitHub\\petfolio\\android\\app\\build.gradle.kts" [ref=e1615]': + - generic [ref=e1616]: "+ WARNING: Your Android app project: app located at: G:\\GitHub\\petfolio\\android\\app\\build.gradle.kts" + - row "4 + applies the Kotlin Gradle Plugin, which will cause build failures in future versions of Flutter." [ref=e1617]: + - cell [ref=e1618] [cursor=pointer] + - cell "4" [ref=e1619] [cursor=pointer] + - cell "+ applies the Kotlin Gradle Plugin, which will cause build failures in future versions of Flutter." [ref=e1620]: + - generic [ref=e1621]: + applies the Kotlin Gradle Plugin, which will cause build failures in future versions of Flutter. + - 'row "5 + Please migrate your app to Built-in Kotlin using this guide: https://docs.flutter.dev/release/breaking-changes/migrate-to-built-in-kotlin/for-app-developers" [ref=e1622]': + - cell [ref=e1623] [cursor=pointer] + - cell "5" [ref=e1624] [cursor=pointer] + - 'cell "+ Please migrate your app to Built-in Kotlin using this guide: https://docs.flutter.dev/release/breaking-changes/migrate-to-built-in-kotlin/for-app-developers" [ref=e1625]': + - generic [ref=e1626]: "+ Please migrate your app to Built-in Kotlin using this guide: https://docs.flutter.dev/release/breaking-changes/migrate-to-built-in-kotlin/for-app-developers" + - row "6 +" [ref=e1627]: + - cell [ref=e1628] [cursor=pointer] + - cell "6" [ref=e1629] [cursor=pointer] + - cell "+" [ref=e1630]: + - generic: + + - 'row "7 + WARNING: Your app uses the following plugins that apply Kotlin Gradle Plugin (KGP): image_picker_android, share_plus, shared_preferences_android, stripe_android, url_launcher_android" [ref=e1631]': + - cell [ref=e1632] [cursor=pointer] + - cell "7" [ref=e1633] [cursor=pointer] + - 'cell "+ WARNING: Your app uses the following plugins that apply Kotlin Gradle Plugin (KGP): image_picker_android, share_plus, shared_preferences_android, stripe_android, url_launcher_android" [ref=e1634]': + - generic [ref=e1635]: "+ WARNING: Your app uses the following plugins that apply Kotlin Gradle Plugin (KGP): image_picker_android, share_plus, shared_preferences_android, stripe_android, url_launcher_android" + - row "8 + Future versions of Flutter will fail to build if your app uses plugins that apply KGP." [ref=e1636]: + - cell [ref=e1637] [cursor=pointer] + - cell "8" [ref=e1638] [cursor=pointer] + - cell "+ Future versions of Flutter will fail to build if your app uses plugins that apply KGP." [ref=e1639]: + - generic [ref=e1640]: + Future versions of Flutter will fail to build if your app uses plugins that apply KGP. + - row "9 +" [ref=e1641]: + - cell [ref=e1642] [cursor=pointer] + - cell "9" [ref=e1643] [cursor=pointer] + - cell "+" [ref=e1644]: + - generic: + + - row "10 + Please check the changelogs of these plugins and upgrade to a version that supports Built-in Kotlin." [ref=e1645]: + - cell [ref=e1646] [cursor=pointer] + - cell "10" [ref=e1647] [cursor=pointer] + - cell "+ Please check the changelogs of these plugins and upgrade to a version that supports Built-in Kotlin." [ref=e1648]: + - generic [ref=e1649]: + Please check the changelogs of these plugins and upgrade to a version that supports Built-in Kotlin. + - generic [ref=e1656]: + - generic [ref=e1659]: + - heading "Copilot commented on Jun 3, 2026 13 hours ago" [level=3] [ref=e1660]: + - text: Copilot commented + - generic "Jun 3, 2026, 5:19 PM EDT" [ref=e1661]: on Jun 3, 2026 13 hours ago + - img "Copilot" [ref=e1664] + - generic [ref=e1665]: + - generic [ref=e1666]: + - generic [ref=e1667]: Copilot + - generic [ref=e1668]: AI + - link "on Jun 3, 202613 hours ago" [ref=e1671] [cursor=pointer]: + - /url: https://github.com/CodeStorm-Hub/petfolio/pull/17#discussion_r3351989517 + - generic "Jun 3, 2026, 5:19 PM EDT" [ref=e1672]: on Jun 3, 202613 hours ago + - generic [ref=e1674]: + - list [ref=e1676]: + - listitem + - listitem [ref=e1677]: + - generic [ref=e1678]: Medium + - button "Actions for Copilot's comment, 5:19 PM yesterday" [ref=e1680] [cursor=pointer]: + - img [ref=e1681] + - generic [ref=e1684]: + - paragraph [ref=e1687]: + - text: This looks like an interactive local + - code [ref=e1688]: flutter run + - text: console log. Keeping raw run logs in the repository tends to create noise and quickly goes stale; consider moving it to a PR comment/issue or deleting it before merge. + - generic [ref=e1689]: + - toolbar "Reactions" + - generic [ref=e1691]: + - button "Positive feedback" [ref=e1692] [cursor=pointer]: + - img [ref=e1693] + - button "Negative feedback" [ref=e1695] [cursor=pointer]: + - img [ref=e1696] + - generic [ref=e1698]: Copilot uses AI. Check for mistakes. + - generic [ref=e1700]: + - generic [ref=e1701]: + - button "Comment thread" [expanded] [ref=e1702] [cursor=pointer]: + - img + - link "exception-log.md" [ref=e1704] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/files/7b8aaf186f6047b802df726bad66459f0cfe10ec#diff-afa976bbd97891e8d87f9b3fdff4b123a691415338224c42c94cccd6780919dc + - generic [ref=e1705]: + - generic [ref=e1707]: Comment on lines +1 to +15 + - table [ref=e1710]: + - rowgroup [ref=e1711]: + - 'row "1 + D/WindowOnBackDispatcher( 8540): setTopOnBackInvokedCallback (unwrapped): androidx.navigationevent.OnBackInvokedInput$createOnBackAnimationCallback$1@94b726b" [ref=e1712]': + - cell [ref=e1713] [cursor=pointer] + - cell "1" [ref=e1714] [cursor=pointer] + - 'cell "+ D/WindowOnBackDispatcher( 8540): setTopOnBackInvokedCallback (unwrapped): androidx.navigationevent.OnBackInvokedInput$createOnBackAnimationCallback$1@94b726b" [ref=e1715]': + - generic [ref=e1716]: "+ D/WindowOnBackDispatcher( 8540): setTopOnBackInvokedCallback (unwrapped): androidx.navigationevent.OnBackInvokedInput$createOnBackAnimationCallback$1@94b726b" + - 'row "2 + D/WindowOnBackDispatcher( 8540): setTopOnBackInvokedCallback (unwrapped): android.app.Activity$$ExternalSyntheticLambda0@671fe96" [ref=e1717]': + - cell [ref=e1718] [cursor=pointer] + - cell "2" [ref=e1719] [cursor=pointer] + - 'cell "+ D/WindowOnBackDispatcher( 8540): setTopOnBackInvokedCallback (unwrapped): android.app.Activity$$ExternalSyntheticLambda0@671fe96" [ref=e1720]': + - generic [ref=e1721]: "+ D/WindowOnBackDispatcher( 8540): setTopOnBackInvokedCallback (unwrapped): android.app.Activity$$ExternalSyntheticLambda0@671fe96" + - 'row "3 + D/WindowOnBackDispatcher( 8540): setTopOnBackInvokedCallback (unwrapped): androidx.navigationevent.OnBackInvokedInput$createOnBackAnimationCallback$1@94b726b" [ref=e1722]': + - cell [ref=e1723] [cursor=pointer] + - cell "3" [ref=e1724] [cursor=pointer] + - 'cell "+ D/WindowOnBackDispatcher( 8540): setTopOnBackInvokedCallback (unwrapped): androidx.navigationevent.OnBackInvokedInput$createOnBackAnimationCallback$1@94b726b" [ref=e1725]': + - generic [ref=e1726]: "+ D/WindowOnBackDispatcher( 8540): setTopOnBackInvokedCallback (unwrapped): androidx.navigationevent.OnBackInvokedInput$createOnBackAnimationCallback$1@94b726b" + - 'row "4 + D/WindowOnBackDispatcher( 8540): setTopOnBackInvokedCallback (unwrapped): android.app.Activity$$ExternalSyntheticLambda0@671fe96" [ref=e1727]': + - cell [ref=e1728] [cursor=pointer] + - cell "4" [ref=e1729] [cursor=pointer] + - 'cell "+ D/WindowOnBackDispatcher( 8540): setTopOnBackInvokedCallback (unwrapped): android.app.Activity$$ExternalSyntheticLambda0@671fe96" [ref=e1730]': + - generic [ref=e1731]: "+ D/WindowOnBackDispatcher( 8540): setTopOnBackInvokedCallback (unwrapped): android.app.Activity$$ExternalSyntheticLambda0@671fe96" + - 'row "5 + D/WindowOnBackDispatcher( 8540): setTopOnBackInvokedCallback (unwrapped): androidx.navigationevent.OnBackInvokedInput$createOnBackAnimationCallback$1@94b726b" [ref=e1732]': + - cell [ref=e1733] [cursor=pointer] + - cell "5" [ref=e1734] [cursor=pointer] + - 'cell "+ D/WindowOnBackDispatcher( 8540): setTopOnBackInvokedCallback (unwrapped): androidx.navigationevent.OnBackInvokedInput$createOnBackAnimationCallback$1@94b726b" [ref=e1735]': + - generic [ref=e1736]: "+ D/WindowOnBackDispatcher( 8540): setTopOnBackInvokedCallback (unwrapped): androidx.navigationevent.OnBackInvokedInput$createOnBackAnimationCallback$1@94b726b" + - row "6 +" [ref=e1737]: + - cell [ref=e1738] [cursor=pointer] + - cell "6" [ref=e1739] [cursor=pointer] + - cell "+" [ref=e1740]: + - generic: + + - row "7 + ══╡ EXCEPTION CAUGHT BY FLUTTER FRAMEWORK ╞═════════════════════════════════════════════════════════" [ref=e1741]: + - cell [ref=e1742] [cursor=pointer] + - cell "7" [ref=e1743] [cursor=pointer] + - cell "+ ══╡ EXCEPTION CAUGHT BY FLUTTER FRAMEWORK ╞═════════════════════════════════════════════════════════" [ref=e1744]: + - generic [ref=e1745]: + ══╡ EXCEPTION CAUGHT BY FLUTTER FRAMEWORK ╞═════════════════════════════════════════════════════════ + - row "8 + The following assertion was thrown:" [ref=e1746]: + - cell [ref=e1747] [cursor=pointer] + - cell "8" [ref=e1748] [cursor=pointer] + - cell "+ The following assertion was thrown:" [ref=e1749]: + - generic [ref=e1750]: "+ The following assertion was thrown:" + - row "9 + ListTile background color or ink splashes may be invisible." [ref=e1751]: + - cell [ref=e1752] [cursor=pointer] + - cell "9" [ref=e1753] [cursor=pointer] + - cell "+ ListTile background color or ink splashes may be invisible." [ref=e1754]: + - generic [ref=e1755]: + ListTile background color or ink splashes may be invisible. + - row "10 + The ListTile is wrapped in a DecoratedBox that has a background color. Because ListTile paints its" [ref=e1756]: + - cell [ref=e1757] [cursor=pointer] + - cell "10" [ref=e1758] [cursor=pointer] + - cell "+ The ListTile is wrapped in a DecoratedBox that has a background color. Because ListTile paints its" [ref=e1759]: + - generic [ref=e1760]: + The ListTile is wrapped in a DecoratedBox that has a background color. Because ListTile paints its + - row "11 + background and ink splashes on the nearest Material ancestor, this DecoratedBox will hide those" [ref=e1761]: + - cell [ref=e1762] [cursor=pointer] + - cell "11" [ref=e1763] [cursor=pointer] + - cell "+ background and ink splashes on the nearest Material ancestor, this DecoratedBox will hide those" [ref=e1764]: + - generic [ref=e1765]: + background and ink splashes on the nearest Material ancestor, this DecoratedBox will hide those + - row "12 + effects." [ref=e1766]: + - cell [ref=e1767] [cursor=pointer] + - cell "12" [ref=e1768] [cursor=pointer] + - cell "+ effects." [ref=e1769]: + - generic [ref=e1770]: + effects. + - row "13 + To fix this, wrap the ListTile in its own Material widget, or remove the background color from the" [ref=e1771]: + - cell [ref=e1772] [cursor=pointer] + - cell "13" [ref=e1773] [cursor=pointer] + - cell "+ To fix this, wrap the ListTile in its own Material widget, or remove the background color from the" [ref=e1774]: + - generic [ref=e1775]: + To fix this, wrap the ListTile in its own Material widget, or remove the background color from the + - row "14 + intermediate DecoratedBox." [ref=e1776]: + - cell [ref=e1777] [cursor=pointer] + - cell "14" [ref=e1778] [cursor=pointer] + - cell "+ intermediate DecoratedBox." [ref=e1779]: + - generic [ref=e1780]: + intermediate DecoratedBox. + - row "15 +" [ref=e1781]: + - cell [ref=e1782] [cursor=pointer] + - cell "15" [ref=e1783] [cursor=pointer] + - cell "+" [ref=e1784]: + - generic: + + - generic [ref=e1791]: + - generic [ref=e1794]: + - heading "Copilot commented on Jun 3, 2026 13 hours ago" [level=3] [ref=e1795]: + - text: Copilot commented + - generic "Jun 3, 2026, 5:19 PM EDT" [ref=e1796]: on Jun 3, 2026 13 hours ago + - img "Copilot" [ref=e1799] + - generic [ref=e1800]: + - generic [ref=e1801]: + - generic [ref=e1802]: Copilot + - generic [ref=e1803]: AI + - link "on Jun 3, 202613 hours ago" [ref=e1806] [cursor=pointer]: + - /url: https://github.com/CodeStorm-Hub/petfolio/pull/17#discussion_r3351989537 + - generic "Jun 3, 2026, 5:19 PM EDT" [ref=e1807]: on Jun 3, 202613 hours ago + - generic [ref=e1809]: + - list [ref=e1811]: + - listitem + - listitem [ref=e1812]: + - generic [ref=e1813]: Medium + - button "Actions for Copilot's comment, 5:19 PM yesterday" [ref=e1815] [cursor=pointer]: + - img [ref=e1816] + - generic [ref=e1819]: + - paragraph [ref=e1822]: This is a captured runtime exception log. Committing transient logs makes the repo noisy and is hard to keep up to date; prefer filing it as an issue (with repro steps) or removing it before merge. + - generic [ref=e1823]: + - toolbar "Reactions" + - generic [ref=e1825]: + - button "Positive feedback" [ref=e1826] [cursor=pointer]: + - img [ref=e1827] + - button "Negative feedback" [ref=e1829] [cursor=pointer]: + - img [ref=e1830] + - generic [ref=e1832]: Copilot uses AI. Check for mistakes. + - generic [ref=e1834]: + - generic [ref=e1835]: + - button "Comment thread" [expanded] [ref=e1836] [cursor=pointer]: + - img + - link ".claude/settings.local.json" [ref=e1838] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/files/7b8aaf186f6047b802df726bad66459f0cfe10ec#diff-fca16cae5b0e32edfa6b55eaa32a98ffbf4a0c7d885fb585785fc83b6ea2d9c3 + - generic [ref=e1839]: + - generic [ref=e1841]: Comment on lines +96 to +107 + - table [ref=e1844]: + - rowgroup [ref=e1845]: + - row "96 + \"Bash(git rm *)\"," [ref=e1846]: + - cell [ref=e1847] [cursor=pointer] + - cell "96" [ref=e1848] [cursor=pointer] + - cell "+ \"Bash(git rm *)\"," [ref=e1849]: + - generic [ref=e1850]: + "Bash(git rm *)", + - row "97 + \"Bash(dir \\\"G:\\\\\\\\GitHub\\\\\\\\petfolio\\\\\\\\PetFolio Redesign\\\\\\\\Care Redesign\\\" /b)\"," [ref=e1851]: + - cell [ref=e1852] [cursor=pointer] + - cell "97" [ref=e1853] [cursor=pointer] + - cell "+ \"Bash(dir \\\"G:\\\\\\\\GitHub\\\\\\\\petfolio\\\\\\\\PetFolio Redesign\\\\\\\\Care Redesign\\\" /b)\"," [ref=e1854]: + - generic [ref=e1855]: + "Bash(dir \"G:\\\\GitHub\\\\petfolio\\\\PetFolio Redesign\\\\Care Redesign\" /b)", + - row "98 + \"mcp__292a7621-3089-4236-bd52-07a54bf59881__list_tables\"," [ref=e1856]: + - cell [ref=e1857] [cursor=pointer] + - cell "98" [ref=e1858] [cursor=pointer] + - cell "+ \"mcp__292a7621-3089-4236-bd52-07a54bf59881__list_tables\"," [ref=e1859]: + - generic [ref=e1860]: + "mcp__292a7621-3089-4236-bd52-07a54bf59881__list_tables", + - row "99 + \"mcp__mobile-mcp__mobile_list_available_devices\"," [ref=e1861]: + - cell [ref=e1862] [cursor=pointer] + - cell "99" [ref=e1863] [cursor=pointer] + - cell "+ \"mcp__mobile-mcp__mobile_list_available_devices\"," [ref=e1864]: + - generic [ref=e1865]: + "mcp__mobile-mcp__mobile_list_available_devices", + - row "100 + \"mcp__mobile-mcp__mobile_take_screenshot\"," [ref=e1866]: + - cell [ref=e1867] [cursor=pointer] + - cell "100" [ref=e1868] [cursor=pointer] + - cell "+ \"mcp__mobile-mcp__mobile_take_screenshot\"," [ref=e1869]: + - generic [ref=e1870]: + "mcp__mobile-mcp__mobile_take_screenshot", + - row "101 + \"mcp__mobile-mcp__mobile_click_on_screen_at_coordinates\"," [ref=e1871]: + - cell [ref=e1872] [cursor=pointer] + - cell "101" [ref=e1873] [cursor=pointer] + - cell "+ \"mcp__mobile-mcp__mobile_click_on_screen_at_coordinates\"," [ref=e1874]: + - generic [ref=e1875]: + "mcp__mobile-mcp__mobile_click_on_screen_at_coordinates", + - row "102 + \"mcp__mobile-mcp__mobile_list_elements_on_screen\"," [ref=e1876]: + - cell [ref=e1877] [cursor=pointer] + - cell "102" [ref=e1878] [cursor=pointer] + - cell "+ \"mcp__mobile-mcp__mobile_list_elements_on_screen\"," [ref=e1879]: + - generic [ref=e1880]: + "mcp__mobile-mcp__mobile_list_elements_on_screen", + - row "103 + \"mcp__mobile-mcp__mobile_save_screenshot\"," [ref=e1881]: + - cell [ref=e1882] [cursor=pointer] + - cell "103" [ref=e1883] [cursor=pointer] + - cell "+ \"mcp__mobile-mcp__mobile_save_screenshot\"," [ref=e1884]: + - generic [ref=e1885]: + "mcp__mobile-mcp__mobile_save_screenshot", + - row "104 + \"mcp__mobile-mcp__mobile_swipe_on_screen\"," [ref=e1886]: + - cell [ref=e1887] [cursor=pointer] + - cell "104" [ref=e1888] [cursor=pointer] + - cell "+ \"mcp__mobile-mcp__mobile_swipe_on_screen\"," [ref=e1889]: + - generic [ref=e1890]: + "mcp__mobile-mcp__mobile_swipe_on_screen", + - row "105 + \"Bash(grep -E \\\"\\\\\\\\.\\\\(dart\\\\)$\\\")\"," [ref=e1891]: + - cell [ref=e1892] [cursor=pointer] + - cell "105" [ref=e1893] [cursor=pointer] + - cell "+ \"Bash(grep -E \\\"\\\\\\\\.\\\\(dart\\\\)$\\\")\"," [ref=e1894]: + - generic [ref=e1895]: + "Bash(grep -E \"\\\\.\\(dart\\)$\")", + - row "106 + \"Bash(Get-Content \\\"C:\\\\\\\\Users\\\\\\\\syedr\\\\\\\\AppData\\\\\\\\Local\\\\\\\\Temp\\\\\\\\claude\\\\\\\\G--GitHub-petfolio\\\\\\\\83d1e98f-3a1c-41fb-a000-787a9c3f0b74\\\\\\\\tasks\\\\\\\\bn6o3o4cc.output\\\" -Wait -Tail 30)\"," [ref=e1896]: + - cell [ref=e1897] [cursor=pointer] + - cell "106" [ref=e1898] [cursor=pointer] + - cell "+ \"Bash(Get-Content \\\"C:\\\\\\\\Users\\\\\\\\syedr\\\\\\\\AppData\\\\\\\\Local\\\\\\\\Temp\\\\\\\\claude\\\\\\\\G--GitHub-petfolio\\\\\\\\83d1e98f-3a1c-41fb-a000-787a9c3f0b74\\\\\\\\tasks\\\\\\\\bn6o3o4cc.output\\\" -Wait -Tail 30)\"," [ref=e1899]: + - generic [ref=e1900]: + "Bash(Get-Content \"C:\\\\Users\\\\syedr\\\\AppData\\\\Local\\\\Temp\\\\claude\\\\G--GitHub-petfolio\\\\83d1e98f-3a1c-41fb-a000-787a9c3f0b74\\\\tasks\\\\bn6o3o4cc.output\" -Wait -Tail 30)", + - row "107 + \"Bash(Select-Object -First 30)\"," [ref=e1901]: + - cell [ref=e1902] [cursor=pointer] + - cell "107" [ref=e1903] [cursor=pointer] + - cell "+ \"Bash(Select-Object -First 30)\"," [ref=e1904]: + - generic [ref=e1905]: + "Bash(Select-Object -First 30)", + - generic [ref=e1912]: + - generic [ref=e1915]: + - heading "Copilot commented on Jun 3, 2026 13 hours ago" [level=3] [ref=e1916]: + - text: Copilot commented + - generic "Jun 3, 2026, 5:19 PM EDT" [ref=e1917]: on Jun 3, 2026 13 hours ago + - img "Copilot" [ref=e1920] + - generic [ref=e1921]: + - generic [ref=e1922]: + - generic [ref=e1923]: Copilot + - generic [ref=e1924]: AI + - link "on Jun 3, 202613 hours ago" [ref=e1927] [cursor=pointer]: + - /url: https://github.com/CodeStorm-Hub/petfolio/pull/17#discussion_r3351989556 + - generic "Jun 3, 2026, 5:19 PM EDT" [ref=e1928]: on Jun 3, 202613 hours ago + - generic [ref=e1930]: + - list [ref=e1932]: + - listitem + - listitem [ref=e1933]: + - generic [ref=e1934]: High + - button "Actions for Copilot's comment, 5:19 PM yesterday" [ref=e1936] [cursor=pointer]: + - img [ref=e1937] + - generic [ref=e1940]: + - paragraph [ref=e1943]: + - code [ref=e1944]: .claude/settings.local.json + - text: contains machine-specific allowlists (Windows drive letters, user temp paths, local MCP server IDs). These are not portable and can accidentally whitelist dangerous commands; typically + - code [ref=e1945]: "*.local.json" + - text: files should be untracked and ignored (especially since this PR also adds secrets in + - code [ref=e1946]: .claude/launch.json + - text: ). + - generic [ref=e1947]: + - toolbar "Reactions" + - generic [ref=e1949]: + - button "Positive feedback" [ref=e1950] [cursor=pointer]: + - img [ref=e1951] + - button "Negative feedback" [ref=e1953] [cursor=pointer]: + - img [ref=e1954] + - generic [ref=e1956]: Copilot uses AI. Check for mistakes. + - generic [ref=e1958]: + - generic [ref=e1959]: + - button "Comment thread" [expanded] [ref=e1960] [cursor=pointer]: + - img + - link "web/pwa_banner.js" [ref=e1962] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/files/7b8aaf186f6047b802df726bad66459f0cfe10ec#diff-f3b25d0a5691b8d245bc98e0a2e57ae1bd7e9d733905d29562165a353833df3d + - generic [ref=e1963]: + - generic [ref=e1965]: Comment on lines +64 to +67 + - table [ref=e1968]: + - rowgroup [ref=e1969]: + - 'row "64 + document.getElementById(''pwa-banner-close'').addEventListener(''click'', function () {" [ref=e1970]': + - cell [ref=e1971] [cursor=pointer] + - cell "64" [ref=e1972] [cursor=pointer] + - 'cell "+ document.getElementById(''pwa-banner-close'').addEventListener(''click'', function () {" [ref=e1973]': + - generic [ref=e1974]: "+ document.getElementById('pwa-banner-close').addEventListener('click', function () {" + - row "65 + localStorage.setItem('pwa_banner_dismissed', '1');" [ref=e1975]: + - cell [ref=e1976] [cursor=pointer] + - cell "65" [ref=e1977] [cursor=pointer] + - cell "+ localStorage.setItem('pwa_banner_dismissed', '1');" [ref=e1978]: + - generic [ref=e1979]: + localStorage.setItem('pwa_banner_dismissed', '1'); + - row "66 + banner.style.animation = 'slideUp .25s cubic-bezier(.16,1,.3,1) reverse both';" [ref=e1980]: + - cell [ref=e1981] [cursor=pointer] + - cell "66" [ref=e1982] [cursor=pointer] + - cell "+ banner.style.animation = 'slideUp .25s cubic-bezier(.16,1,.3,1) reverse both';" [ref=e1983]: + - generic [ref=e1984]: + banner.style.animation = 'slideUp .25s cubic-bezier(.16,1,.3,1) reverse both'; + - 'row "67 + setTimeout(function () { banner.remove(); }, 280);" [ref=e1985]': + - cell [ref=e1986] [cursor=pointer] + - cell "67" [ref=e1987] [cursor=pointer] + - 'cell "+ setTimeout(function () { banner.remove(); }, 280);" [ref=e1988]': + - generic [ref=e1989]: "+ setTimeout(function () { banner.remove(); }, 280);" + - generic [ref=e1996]: + - generic [ref=e1999]: + - heading "Copilot commented on Jun 3, 2026 13 hours ago" [level=3] [ref=e2000]: + - text: Copilot commented + - generic "Jun 3, 2026, 5:19 PM EDT" [ref=e2001]: on Jun 3, 2026 13 hours ago + - img "Copilot" [ref=e2004] + - generic [ref=e2005]: + - generic [ref=e2006]: + - generic [ref=e2007]: Copilot + - generic [ref=e2008]: AI + - link "on Jun 3, 202613 hours ago" [ref=e2011] [cursor=pointer]: + - /url: https://github.com/CodeStorm-Hub/petfolio/pull/17#discussion_r3351989577 + - generic "Jun 3, 2026, 5:19 PM EDT" [ref=e2012]: on Jun 3, 202613 hours ago + - generic [ref=e2014]: + - list [ref=e2016]: + - listitem + - listitem [ref=e2017]: + - generic [ref=e2018]: Medium + - button "Actions for Copilot's comment, 5:19 PM yesterday" [ref=e2020] [cursor=pointer]: + - img [ref=e2021] + - generic [ref=e2024]: + - paragraph [ref=e2027]: + - code [ref=e2028]: localStorage.setItem(...) + - text: can throw (e.g. iOS Safari private mode / storage disabled). If it throws here, the banner won't dismiss and will keep reappearing. Wrap the write in a try/catch so dismissal still works even when storage is unavailable. + - generic [ref=e2029]: + - generic [ref=e2031]: + - text: Suggested changeset + - generic [ref=e2032]: "1" + - generic [ref=e2033]: (1) + - generic [ref=e2034]: + - generic [ref=e2035]: + - button "Close review comment" [ref=e2036] [cursor=pointer]: + - img [ref=e2037] + - text: web/pwa_banner.js + - table [ref=e2040]: + - rowgroup [ref=e2041]: + - row "Original file line number Diff line number Diff line change" [ref=e2042]: + - columnheader "Original file line number" [ref=e2043] + - columnheader "Diff line number" [ref=e2044] + - columnheader "Diff line change" [ref=e2045] + - rowgroup [ref=e2050]: + - row "@@ -62,8 +62,9 @@" [ref=e2051]: + - cell "@@ -62,8 +62,9 @@" [ref=e2052]: + - generic [ref=e2053]: + - img [ref=e2055] + - code [ref=e2057]: + - generic [ref=e2058]: "@@ -62,8 +62,9 @@" + - row "62 62 document.body.appendChild(banner);" [ref=e2059]: + - cell "62" [ref=e2060]: + - code [ref=e2061]: "62" + - cell "62" [ref=e2062]: + - code [ref=e2063]: "62" + - cell "document.body.appendChild(banner);" [ref=e2064]: + - code [ref=e2065]: + - generic [ref=e2066]: document.body.appendChild(banner); + - row "63 63" [ref=e2067]: + - cell "63" [ref=e2068]: + - code [ref=e2069]: "63" + - cell "63" [ref=e2070]: + - code [ref=e2071]: "63" + - cell [ref=e2072]: + - code + - 'row "64 64 document.getElementById(''pwa-banner-close'').addEventListener(''click'', function () {" [ref=e2073]': + - cell "64" [ref=e2074]: + - code [ref=e2075]: "64" + - cell "64" [ref=e2076]: + - code [ref=e2077]: "64" + - 'cell "document.getElementById(''pwa-banner-close'').addEventListener(''click'', function () {" [ref=e2078]': + - code [ref=e2079]: + - generic [ref=e2080]: "document.getElementById('pwa-banner-close').addEventListener('click', function () {" + - row "65 - localStorage.setItem('pwa_banner_dismissed', '1');" [ref=e2081]: + - cell "65" [ref=e2082]: + - code [ref=e2083]: "65" + - cell [ref=e2084]: + - code + - cell "- localStorage.setItem('pwa_banner_dismissed', '1');" [ref=e2085]: + - code [ref=e2086]: + - generic [ref=e2087]: "-" + - generic [ref=e2088]: localStorage.setItem('pwa_banner_dismissed', '1'); + - 'row "65 + try { localStorage.setItem(''pwa_banner_dismissed'', ''1''); } catch (_) {}" [ref=e2089]': + - cell [ref=e2090]: + - code + - cell "65" [ref=e2091]: + - code [ref=e2092]: "65" + - 'cell "+ try { localStorage.setItem(''pwa_banner_dismissed'', ''1''); } catch (_) {}" [ref=e2093]': + - code [ref=e2094]: + - generic [ref=e2095]: + + - generic [ref=e2096]: "try { localStorage.setItem('pwa_banner_dismissed', '1'); } catch (_) {}" + - row "66 66 banner.style.animation = 'slideUp .25s cubic-bezier(.16,1,.3,1) reverse both';" [ref=e2097]: + - cell "66" [ref=e2098]: + - code [ref=e2099]: "66" + - cell "66" [ref=e2100]: + - code [ref=e2101]: "66" + - cell "banner.style.animation = 'slideUp .25s cubic-bezier(.16,1,.3,1) reverse both';" [ref=e2102]: + - code [ref=e2103]: + - generic [ref=e2104]: banner.style.animation = 'slideUp .25s cubic-bezier(.16,1,.3,1) reverse both'; + - 'row "67 67 setTimeout(function () { banner.remove(); }, 280);" [ref=e2105]': + - cell "67" [ref=e2106]: + - code [ref=e2107]: "67" + - cell "67" [ref=e2108]: + - code [ref=e2109]: "67" + - 'cell "setTimeout(function () { banner.remove(); }, 280);" [ref=e2110]': + - code [ref=e2111]: + - generic [ref=e2112]: "setTimeout(function () { banner.remove(); }, 280);" + - 'row "68 68 });" [ref=e2113]': + - cell "68" [ref=e2114]: + - code [ref=e2115]: "68" + - cell "68" [ref=e2116]: + - code [ref=e2117]: "68" + - 'cell "});" [ref=e2118]': + - code [ref=e2119]: + - generic [ref=e2120]: "});" + - 'row "69 + });" [ref=e2121]': + - cell [ref=e2122]: + - code + - cell "69" [ref=e2123]: + - code [ref=e2124]: "69" + - 'cell "+ });" [ref=e2125]': + - code [ref=e2126]: + - generic [ref=e2127]: + + - generic [ref=e2128]: "});" + - 'row "69 70 }());" [ref=e2129]': + - cell "69" [ref=e2130]: + - code [ref=e2131]: "69" + - cell "70" [ref=e2132]: + - code [ref=e2133]: "70" + - 'cell "}());" [ref=e2134]': + - code [ref=e2135]: + - generic [ref=e2136]: "}());" + - button "Commit suggestion" [ref=e2138] [cursor=pointer]: + - generic [ref=e2140]: Commit suggestion + - generic [ref=e2141]: + - toolbar "Reactions" + - generic [ref=e2143]: + - button "Positive feedback" [ref=e2144] [cursor=pointer]: + - img [ref=e2145] + - button "Negative feedback" [ref=e2147] [cursor=pointer]: + - img [ref=e2148] + - generic [ref=e2150]: Copilot uses AI. Check for mistakes. + - generic [ref=e2152]: + - generic [ref=e2153]: + - button "Comment thread" [expanded] [ref=e2154] [cursor=pointer]: + - img + - link ".github/workflows/deploy-web.yml" [ref=e2156] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/files/7b8aaf186f6047b802df726bad66459f0cfe10ec#diff-875a32a9bd9123a01ecb0b1802809c712a8a04f695e979c262eb9380e6359efc + - generic [ref=e2157]: + - generic [ref=e2159]: Comment on lines +35 to +40 + - table [ref=e2162]: + - rowgroup [ref=e2163]: + - 'row "35 + - name: Deploy to Vercel" [ref=e2164]': + - cell [ref=e2165] [cursor=pointer] + - cell "35" [ref=e2166] [cursor=pointer] + - 'cell "+ - name: Deploy to Vercel" [ref=e2167]': + - generic [ref=e2168]: "+ - name: Deploy to Vercel" + - 'row "36 + working-directory: build/web" [ref=e2169]': + - cell [ref=e2170] [cursor=pointer] + - cell "36" [ref=e2171] [cursor=pointer] + - 'cell "+ working-directory: build/web" [ref=e2172]': + - generic [ref=e2173]: "+ working-directory: build/web" + - 'row "37 + run: npx vercel deploy --prod --yes --token=${{ secrets.VERCEL_TOKEN }}" [ref=e2174]': + - cell [ref=e2175] [cursor=pointer] + - cell "37" [ref=e2176] [cursor=pointer] + - 'cell "+ run: npx vercel deploy --prod --yes --token=${{ secrets.VERCEL_TOKEN }}" [ref=e2177]': + - generic [ref=e2178]: "+ run: npx vercel deploy --prod --yes --token=${{ secrets.VERCEL_TOKEN }}" + - row "38 + env:" [ref=e2179]: + - cell [ref=e2180] [cursor=pointer] + - cell "38" [ref=e2181] [cursor=pointer] + - cell "+ env:" [ref=e2182]: + - generic [ref=e2183]: "+ env:" + - 'row "39 + VERCEL_ORG_ID: team_lC8aTJK0XiU9qDfaHeTfCJs6" [ref=e2184]': + - cell [ref=e2185] [cursor=pointer] + - cell "39" [ref=e2186] [cursor=pointer] + - 'cell "+ VERCEL_ORG_ID: team_lC8aTJK0XiU9qDfaHeTfCJs6" [ref=e2187]': + - generic [ref=e2188]: "+ VERCEL_ORG_ID: team_lC8aTJK0XiU9qDfaHeTfCJs6" + - 'row "40 + VERCEL_PROJECT_ID: prj_hMHouLWimZvr5dDOlZeAhbH8xtop" [ref=e2189]': + - cell [ref=e2190] [cursor=pointer] + - cell "40" [ref=e2191] [cursor=pointer] + - 'cell "+ VERCEL_PROJECT_ID: prj_hMHouLWimZvr5dDOlZeAhbH8xtop" [ref=e2192]': + - generic [ref=e2193]: "+ VERCEL_PROJECT_ID: prj_hMHouLWimZvr5dDOlZeAhbH8xtop" + - generic [ref=e2200]: + - generic [ref=e2203]: + - heading "Copilot commented on Jun 3, 2026 13 hours ago" [level=3] [ref=e2204]: + - text: Copilot commented + - generic "Jun 3, 2026, 5:19 PM EDT" [ref=e2205]: on Jun 3, 2026 13 hours ago + - img "Copilot" [ref=e2208] + - generic [ref=e2209]: + - generic [ref=e2210]: + - generic [ref=e2211]: Copilot + - generic [ref=e2212]: AI + - link "on Jun 3, 202613 hours ago" [ref=e2215] [cursor=pointer]: + - /url: https://github.com/CodeStorm-Hub/petfolio/pull/17#discussion_r3351989597 + - generic "Jun 3, 2026, 5:19 PM EDT" [ref=e2216]: on Jun 3, 202613 hours ago + - generic [ref=e2218]: + - list [ref=e2220]: + - listitem + - listitem [ref=e2221]: + - generic [ref=e2222]: High + - button "Actions for Copilot's comment, 5:19 PM yesterday" [ref=e2224] [cursor=pointer]: + - img [ref=e2225] + - generic [ref=e2228]: + - paragraph [ref=e2231]: + - text: The deploy step currently (1) runs with + - code [ref=e2232]: "--prod" + - text: even on + - code [ref=e2233]: pull_request + - text: events, which would deploy PR builds to production, and (2) uses + - code [ref=e2234]: "working-directory: build/web" + - text: ", which prevents Vercel from discovering the root" + - code [ref=e2235]: vercel.json + - text: (rewrites/headers) and + - code [ref=e2236]: .vercel/project.json + - text: . Gate the prod deploy to pushes and run from the repo root so config is applied. + - generic [ref=e2237]: + - generic [ref=e2239]: + - text: Suggested changeset + - generic [ref=e2240]: "1" + - generic [ref=e2241]: (1) + - generic [ref=e2242]: + - generic [ref=e2243]: + - button "Close review comment" [ref=e2244] [cursor=pointer]: + - img [ref=e2245] + - text: .github/workflows/deploy-web.yml + - table [ref=e2248]: + - rowgroup [ref=e2249]: + - row "Original file line number Diff line number Diff line change" [ref=e2250]: + - columnheader "Original file line number" [ref=e2251] + - columnheader "Diff line number" [ref=e2252] + - columnheader "Diff line change" [ref=e2253] + - rowgroup [ref=e2258]: + - row "@@ -33,7 +33,7 @@" [ref=e2259]: + - cell "@@ -33,7 +33,7 @@" [ref=e2260]: + - generic [ref=e2261]: + - img [ref=e2263] + - code [ref=e2265]: + - generic [ref=e2266]: "@@ -33,7 +33,7 @@" + - 'row "33 33 --dart-define=NVIDIA_API_KEY=${{ secrets.NVIDIA_API_KEY }}" [ref=e2267]': + - cell "33" [ref=e2268]: + - code [ref=e2269]: "33" + - cell "33" [ref=e2270]: + - code [ref=e2271]: "33" + - 'cell "--dart-define=NVIDIA_API_KEY=${{ secrets.NVIDIA_API_KEY }}" [ref=e2272]': + - code [ref=e2273]: + - generic [ref=e2274]: "--dart-define=NVIDIA_API_KEY=${{ secrets.NVIDIA_API_KEY }}" + - row "34 34" [ref=e2275]: + - cell "34" [ref=e2276]: + - code [ref=e2277]: "34" + - cell "34" [ref=e2278]: + - code [ref=e2279]: "34" + - cell [ref=e2280]: + - code + - 'row "35 35 - name: Deploy to Vercel" [ref=e2281]': + - cell "35" [ref=e2282]: + - code [ref=e2283]: "35" + - cell "35" [ref=e2284]: + - code [ref=e2285]: "35" + - 'cell "- name: Deploy to Vercel" [ref=e2286]': + - code [ref=e2287]: + - generic [ref=e2288]: "- name: Deploy to Vercel" + - 'row "36 - working-directory: build/web" [ref=e2289]': + - cell "36" [ref=e2290]: + - code [ref=e2291]: "36" + - cell [ref=e2292]: + - code + - 'cell "- working-directory: build/web" [ref=e2293]': + - code [ref=e2294]: + - generic [ref=e2295]: "-" + - generic [ref=e2296]: "working-directory: build/web" + - 'row "36 + if: github.event_name == ''push''" [ref=e2297]': + - cell [ref=e2298]: + - code + - cell "36" [ref=e2299]: + - code [ref=e2300]: "36" + - 'cell "+ if: github.event_name == ''push''" [ref=e2301]': + - code [ref=e2302]: + - generic [ref=e2303]: + + - generic [ref=e2304]: "if: github.event_name == 'push'" + - 'row "37 37 run: npx vercel deploy --prod --yes --token=${{ secrets.VERCEL_TOKEN }}" [ref=e2305]': + - cell "37" [ref=e2306]: + - code [ref=e2307]: "37" + - cell "37" [ref=e2308]: + - code [ref=e2309]: "37" + - 'cell "run: npx vercel deploy --prod --yes --token=${{ secrets.VERCEL_TOKEN }}" [ref=e2310]': + - code [ref=e2311]: + - generic [ref=e2312]: "run: npx vercel deploy --prod --yes --token=${{ secrets.VERCEL_TOKEN }}" + - row "38 38 env:" [ref=e2313]: + - cell "38" [ref=e2314]: + - code [ref=e2315]: "38" + - cell "38" [ref=e2316]: + - code [ref=e2317]: "38" + - cell "env:" [ref=e2318]: + - code [ref=e2319]: + - generic [ref=e2320]: "env:" + - 'row "39 39 VERCEL_ORG_ID: team_lC8aTJK0XiU9qDfaHeTfCJs6" [ref=e2321]': + - cell "39" [ref=e2322]: + - code [ref=e2323]: "39" + - cell "39" [ref=e2324]: + - code [ref=e2325]: "39" + - 'cell "VERCEL_ORG_ID: team_lC8aTJK0XiU9qDfaHeTfCJs6" [ref=e2326]': + - code [ref=e2327]: + - generic [ref=e2328]: "VERCEL_ORG_ID: team_lC8aTJK0XiU9qDfaHeTfCJs6" + - button "Commit suggestion" [ref=e2330] [cursor=pointer]: + - generic [ref=e2332]: Commit suggestion + - generic [ref=e2333]: + - toolbar "Reactions" + - generic [ref=e2335]: + - button "Positive feedback" [ref=e2336] [cursor=pointer]: + - img [ref=e2337] + - button "Negative feedback" [ref=e2339] [cursor=pointer]: + - img [ref=e2340] + - generic [ref=e2342]: Copilot uses AI. Check for mistakes. + - generic [ref=e2346]: + - img [ref=e2348] + - generic [ref=e2353]: + - link "@syed-reza98" [ref=e2356] [cursor=pointer]: + - /url: /syed-reza98 + - img "@syed-reza98" [ref=e2357] + - code [ref=e2359]: + - link "up" [ref=e2360] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/610ee87712bfd0f063f722d6cadca2a5289430cb + - group [ref=e2364]: + - generic "2 / 2 checks OK" [ref=e2365] [cursor=pointer]: + - img "2 / 2 checks OK" [ref=e2366] + - code [ref=e2369]: + - link "610ee87" [ref=e2370] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/610ee87712bfd0f063f722d6cadca2a5289430cb + - generic [ref=e2371]: + - generic [ref=e2372]: + - img [ref=e2374] + - generic [ref=e2376]: + - link "@anamchowdhury" [ref=e2377] [cursor=pointer]: + - /url: /anamchowdhury + - img "@anamchowdhury" [ref=e2378] + - link "anamchowdhury" [ref=e2379] [cursor=pointer]: + - /url: /anamchowdhury + - text: requested a review from + - link "Copilot" [ref=e2380] [cursor=pointer]: + - /url: /apps/copilot-pull-request-reviewer + - link "June 4, 2026 10:3615 minutes ago" [ref=e2381] [cursor=pointer]: + - /url: "#event-26332843962" + - generic [ref=e2382]: + - img [ref=e2384] + - generic [ref=e2386]: + - strong [ref=e2387]: Copilot + - link "started reviewing" [ref=e2388] [cursor=pointer]: + - /url: https://github.com/CodeStorm-Hub/petfolio/sessions/94f48852-11d4-4e31-a674-b857e438d64a + - text: on behalf of + - link "anamchowdhury" [ref=e2389] [cursor=pointer]: + - /url: /anamchowdhury + - link "June 4, 2026 10:3615 minutes ago" [ref=e2390] [cursor=pointer]: + - /url: "#event-26332852181" + - link "View session 94f48852-11d4-4e31-a674-b857e438d64a" [ref=e2391] [cursor=pointer]: + - /url: https://github.com/CodeStorm-Hub/petfolio/sessions/94f48852-11d4-4e31-a674-b857e438d64a + - generic [ref=e2393]: View session + - generic [ref=e2397]: + - img [ref=e2399] + - generic [ref=e2404]: + - generic [ref=e2406]: + - link "@afsan123" [ref=e2407] [cursor=pointer]: + - /url: /afsan123 + - img "@afsan123" [ref=e2408] + - link "@claude" [ref=e2409] [cursor=pointer]: + - /url: /claude + - img "@claude" [ref=e2410] + - generic [ref=e2411]: + - code [ref=e2412]: + - link "Merge origin/main into care-redesign-salman" [ref=e2413] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/518b78658421e8e825bcb284e3724fef601c3054 + - button "Commit message body" [ref=e2415] [cursor=pointer]: … + - group [ref=e2419]: + - generic "2 / 2 checks OK" [ref=e2420] [cursor=pointer]: + - img "2 / 2 checks OK" [ref=e2421] + - code [ref=e2424]: + - link "518b786" [ref=e2425] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/518b78658421e8e825bcb284e3724fef601c3054 + - generic [ref=e2428]: + - generic [ref=e2429]: + - link "Copilot PR reviewer" [ref=e2430] [cursor=pointer]: + - /url: /apps/copilot-pull-request-reviewer + - img [ref=e2432] + - img "Only reviews by reviewers with write access count toward mergeability" [ref=e2436] + - generic [ref=e2438]: + - generic [ref=e2439]: + - strong [ref=e2440]: + - link "Copilot" [ref=e2441] [cursor=pointer]: + - /url: /apps/copilot-pull-request-reviewer + - generic [ref=e2442]: AI + - text: reviewed + - link "Jun 4, 20267 minutes ago" [ref=e2444] [cursor=pointer]: + - /url: "#pullrequestreview-4427104976" + - link "View reviewed changes" [ref=e2446] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/files/610ee87712bfd0f063f722d6cadca2a5289430cb + - generic [ref=e2448]: View reviewed changes + - generic [ref=e2451]: + - generic [ref=e2452]: + - group [ref=e2455]: + - button "Show options" [ref=e2456] [cursor=pointer]: + - img "Show options" [ref=e2459] + - heading "Copilot AI left a comment" [level=3] [ref=e2461]: + - generic [ref=e2462]: + - strong [ref=e2463]: + - link "Copilot" [ref=e2464] [cursor=pointer]: + - /url: /apps/copilot-pull-request-reviewer + - generic [ref=e2465]: AI + - text: left a comment + - generic [ref=e2468]: + - heading "Pull request overview" [level=2] [ref=e2469] + - paragraph [ref=e2470]: Copilot reviewed 28 out of 44 changed files in this pull request and generated 18 comments. + - generic [ref=e2472]: + - generic [ref=e2474]: + - generic [ref=e2475]: + - button "Comment thread" [expanded] [ref=e2476] [cursor=pointer]: + - img + - link ".claude/launch.json" [ref=e2478] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/files/610ee87712bfd0f063f722d6cadca2a5289430cb#diff-f02a361fa828af1bddd7c60baccb9ec7036882b427c5e6f2d734cf6414f3b36c + - generic [ref=e2479]: + - generic [ref=e2481]: Comment on lines +12 to +15 + - table [ref=e2484]: + - rowgroup [ref=e2485]: + - row "12 + \"--dart-define=SUPABASE_URL=https://jqyjvhwlcqcsuwcqgcwf.supabase.co\"," [ref=e2486]: + - cell [ref=e2487] [cursor=pointer] + - cell "12" [ref=e2488] [cursor=pointer] + - cell "+ \"--dart-define=SUPABASE_URL=https://jqyjvhwlcqcsuwcqgcwf.supabase.co\"," [ref=e2489]: + - generic [ref=e2490]: + "--dart-define=SUPABASE_URL=https://jqyjvhwlcqcsuwcqgcwf.supabase.co", + - row "13 + \"--dart-define=SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImpxeWp2aHdsY3Fjc3V3Y3FnY3dmIiwicm9sZSI6ImFub24iLCJpYXQiOjE3Nzg1MjI4MjgsImV4cCI6MjA5NDA5ODgyOH0.3bF68bNG0IwAc50YbOC3sem4k8O-d1vkvNNqBt1HbRw\"," [ref=e2491]: + - cell [ref=e2492] [cursor=pointer] + - cell "13" [ref=e2493] [cursor=pointer] + - cell "+ \"--dart-define=SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImpxeWp2aHdsY3Fjc3V3Y3FnY3dmIiwicm9sZSI6ImFub24iLCJpYXQiOjE3Nzg1MjI4MjgsImV4cCI6MjA5NDA5ODgyOH0.3bF68bNG0IwAc50YbOC3sem4k8O-d1vkvNNqBt1HbRw\"," [ref=e2494]: + - generic [ref=e2495]: + "--dart-define=SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImpxeWp2aHdsY3Fjc3V3Y3FnY3dmIiwicm9sZSI6ImFub24iLCJpYXQiOjE3Nzg1MjI4MjgsImV4cCI6MjA5NDA5ODgyOH0.3bF68bNG0IwAc50YbOC3sem4k8O-d1vkvNNqBt1HbRw", + - row "14 + \"--dart-define=STRIPE_PUBLISHABLE_KEY=pk_test_51TQvlrPcVRApxzIxJ8RmKYA1WEw7k8zubumbIfsDjRSGgDyAcSU22RhsZRtKIP1lAZ0wtGjpLfzjI4fozMZxGSlo006zuZrbon\"," [ref=e2496]: + - cell [ref=e2497] [cursor=pointer] + - cell "14" [ref=e2498] [cursor=pointer] + - cell "+ \"--dart-define=STRIPE_PUBLISHABLE_KEY=pk_test_51TQvlrPcVRApxzIxJ8RmKYA1WEw7k8zubumbIfsDjRSGgDyAcSU22RhsZRtKIP1lAZ0wtGjpLfzjI4fozMZxGSlo006zuZrbon\"," [ref=e2499]: + - generic [ref=e2500]: + "--dart-define=STRIPE_PUBLISHABLE_KEY=pk_test_51TQvlrPcVRApxzIxJ8RmKYA1WEw7k8zubumbIfsDjRSGgDyAcSU22RhsZRtKIP1lAZ0wtGjpLfzjI4fozMZxGSlo006zuZrbon", + - row "15 + \"--dart-define=NVIDIA_API_KEY=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\"" [ref=e2501]: + - cell [ref=e2502] [cursor=pointer] + - cell "15" [ref=e2503] [cursor=pointer] + - cell "+ \"--dart-define=NVIDIA_API_KEY=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\"" [ref=e2504]: + - generic [ref=e2505]: + "--dart-define=NVIDIA_API_KEY=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" + - generic [ref=e2512]: + - generic [ref=e2515]: + - heading "Copilot commented on Jun 4, 2026 7 minutes ago" [level=3] [ref=e2516]: + - text: Copilot commented + - generic "Jun 4, 2026, 6:44 AM EDT" [ref=e2517]: on Jun 4, 2026 7 minutes ago + - img "Copilot" [ref=e2520] + - generic [ref=e2521]: + - generic [ref=e2522]: + - generic [ref=e2523]: Copilot + - generic [ref=e2524]: AI + - link "on Jun 4, 20267 minutes ago" [ref=e2527] [cursor=pointer]: + - /url: https://github.com/CodeStorm-Hub/petfolio/pull/17#discussion_r3355378028 + - generic "Jun 4, 2026, 6:44 AM EDT" [ref=e2528]: on Jun 4, 20267 minutes ago + - generic [ref=e2530]: + - list [ref=e2532]: + - listitem + - listitem [ref=e2533]: + - generic [ref=e2534]: High + - button "Actions for Copilot's comment, 6:44 AM today" [ref=e2536] [cursor=pointer]: + - img [ref=e2537] + - generic [ref=e2540]: + - paragraph [ref=e2543]: This launch config hard-codes real environment values (Supabase URL/anon key, Stripe publishable key, NVIDIA API key). Even if some are “public”, committing them makes rotation harder and can unintentionally expose non-prod resources; API keys (e.g. NVIDIA) should never be in-repo. + - generic [ref=e2544]: + - generic [ref=e2546]: + - text: Suggested changeset + - generic [ref=e2547]: "1" + - generic [ref=e2548]: (1) + - generic [ref=e2549]: + - generic [ref=e2550]: + - button "Close review comment" [ref=e2551] [cursor=pointer]: + - img [ref=e2552] + - text: .claude/launch.json + - table [ref=e2555]: + - rowgroup [ref=e2556]: + - row "Original file line number Diff line number Diff line change" [ref=e2557]: + - columnheader "Original file line number" [ref=e2558] + - columnheader "Diff line number" [ref=e2559] + - columnheader "Diff line change" [ref=e2560] + - rowgroup [ref=e2565]: + - row "@@ -9,10 +9,10 @@" [ref=e2566]: + - cell "@@ -9,10 +9,10 @@" [ref=e2567]: + - generic [ref=e2568]: + - img [ref=e2570] + - code [ref=e2572]: + - generic [ref=e2573]: "@@ -9,10 +9,10 @@" + - row "9 9 \"-d\", \"web-server\"," [ref=e2574]: + - cell "9" [ref=e2575]: + - code [ref=e2576]: "9" + - cell "9" [ref=e2577]: + - code [ref=e2578]: "9" + - cell "\"-d\", \"web-server\"," [ref=e2579]: + - code [ref=e2580]: + - generic [ref=e2581]: + - generic [ref=e2582]: "\"-d\"" + - text: "," + - generic [ref=e2583]: "\"web-server\"" + - text: "," + - row "10 10 \"--web-port=8080\"," [ref=e2584]: + - cell "10" [ref=e2585]: + - code [ref=e2586]: "10" + - cell "10" [ref=e2587]: + - code [ref=e2588]: "10" + - cell "\"--web-port=8080\"," [ref=e2589]: + - code [ref=e2590]: + - generic [ref=e2591]: + - generic [ref=e2592]: "\"--web-port=8080\"" + - text: "," + - row "11 11 \"--web-hostname=localhost\"," [ref=e2593]: + - cell "11" [ref=e2594]: + - code [ref=e2595]: "11" + - cell "11" [ref=e2596]: + - code [ref=e2597]: "11" + - cell "\"--web-hostname=localhost\"," [ref=e2598]: + - code [ref=e2599]: + - generic [ref=e2600]: + - generic [ref=e2601]: "\"--web-hostname=localhost\"" + - text: "," + - row "12 - \"--dart-define=SUPABASE_URL=https://jqyjvhwlcqcsuwcqgcwf.supabase.co\"," [ref=e2602]: + - cell "12" [ref=e2603]: + - code [ref=e2604]: "12" + - cell [ref=e2605]: + - code + - cell "- \"--dart-define=SUPABASE_URL=https://jqyjvhwlcqcsuwcqgcwf.supabase.co\"," [ref=e2606]: + - code [ref=e2607]: + - generic [ref=e2608]: "-" + - generic [ref=e2609]: + - generic [ref=e2610]: "\"--dart-define=SUPABASE_URL=https://jqyjvhwlcqcsuwcqgcwf.supabase.co\"" + - text: "," + - row "13 - \"--dart-define=SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImpxeWp2aHdsY3Fjc3V3Y3FnY3dmIiwicm9sZSI6ImFub24iLCJpYXQiOjE3Nzg1MjI4MjgsImV4cCI6MjA5NDA5ODgyOH0.3bF68bNG0IwAc50YbOC3sem4k8O-d1vkvNNqBt1HbRw\"," [ref=e2611]: + - cell "13" [ref=e2612]: + - code [ref=e2613]: "13" + - cell [ref=e2614]: + - code + - cell "- \"--dart-define=SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImpxeWp2aHdsY3Fjc3V3Y3FnY3dmIiwicm9sZSI6ImFub24iLCJpYXQiOjE3Nzg1MjI4MjgsImV4cCI6MjA5NDA5ODgyOH0.3bF68bNG0IwAc50YbOC3sem4k8O-d1vkvNNqBt1HbRw\"," [ref=e2615]: + - code [ref=e2616]: + - generic [ref=e2617]: "-" + - generic [ref=e2618]: + - generic [ref=e2619]: "\"--dart-define=SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImpxeWp2aHdsY3Fjc3V3Y3FnY3dmIiwicm9sZSI6ImFub24iLCJpYXQiOjE3Nzg1MjI4MjgsImV4cCI6MjA5NDA5ODgyOH0.3bF68bNG0IwAc50YbOC3sem4k8O-d1vkvNNqBt1HbRw\"" + - text: "," + - row "14 - \"--dart-define=STRIPE_PUBLISHABLE_KEY=pk_test_51TQvlrPcVRApxzIxJ8RmKYA1WEw7k8zubumbIfsDjRSGgDyAcSU22RhsZRtKIP1lAZ0wtGjpLfzjI4fozMZxGSlo006zuZrbon\"," [ref=e2620]: + - cell "14" [ref=e2621]: + - code [ref=e2622]: "14" + - cell [ref=e2623]: + - code + - cell "- \"--dart-define=STRIPE_PUBLISHABLE_KEY=pk_test_51TQvlrPcVRApxzIxJ8RmKYA1WEw7k8zubumbIfsDjRSGgDyAcSU22RhsZRtKIP1lAZ0wtGjpLfzjI4fozMZxGSlo006zuZrbon\"," [ref=e2624]: + - code [ref=e2625]: + - generic [ref=e2626]: "-" + - generic [ref=e2627]: + - generic [ref=e2628]: "\"--dart-define=STRIPE_PUBLISHABLE_KEY=pk_test_51TQvlrPcVRApxzIxJ8RmKYA1WEw7k8zubumbIfsDjRSGgDyAcSU22RhsZRtKIP1lAZ0wtGjpLfzjI4fozMZxGSlo006zuZrbon\"" + - text: "," + - row "15 - \"--dart-define=NVIDIA_API_KEY=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\"" [ref=e2629]: + - cell "15" [ref=e2630]: + - code [ref=e2631]: "15" + - cell [ref=e2632]: + - code + - cell "- \"--dart-define=NVIDIA_API_KEY=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\"" [ref=e2633]: + - code [ref=e2634]: + - generic [ref=e2635]: "-" + - generic [ref=e2637]: "\"--dart-define=NVIDIA_API_KEY=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\"" + - 'row "12 + \"--dart-define=SUPABASE_URL=${SUPABASE_URL}\"," [ref=e2638]': + - cell [ref=e2639]: + - code + - cell "12" [ref=e2640]: + - code [ref=e2641]: "12" + - 'cell "+ \"--dart-define=SUPABASE_URL=${SUPABASE_URL}\"," [ref=e2642]': + - code [ref=e2643]: + - generic [ref=e2644]: + + - generic [ref=e2645]: + - generic [ref=e2646]: "\"--dart-define=SUPABASE_URL=${SUPABASE_URL}\"" + - text: "," + - 'row "13 + \"--dart-define=SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY}\"," [ref=e2647]': + - cell [ref=e2648]: + - code + - cell "13" [ref=e2649]: + - code [ref=e2650]: "13" + - 'cell "+ \"--dart-define=SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY}\"," [ref=e2651]': + - code [ref=e2652]: + - generic [ref=e2653]: + + - generic [ref=e2654]: + - generic [ref=e2655]: "\"--dart-define=SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY}\"" + - text: "," + - 'row "14 + \"--dart-define=STRIPE_PUBLISHABLE_KEY=${STRIPE_PUBLISHABLE_KEY}\"," [ref=e2656]': + - cell [ref=e2657]: + - code + - cell "14" [ref=e2658]: + - code [ref=e2659]: "14" + - 'cell "+ \"--dart-define=STRIPE_PUBLISHABLE_KEY=${STRIPE_PUBLISHABLE_KEY}\"," [ref=e2660]': + - code [ref=e2661]: + - generic [ref=e2662]: + + - generic [ref=e2663]: + - generic [ref=e2664]: "\"--dart-define=STRIPE_PUBLISHABLE_KEY=${STRIPE_PUBLISHABLE_KEY}\"" + - text: "," + - 'row "15 + \"--dart-define=NVIDIA_API_KEY=${NVIDIA_API_KEY}\"" [ref=e2665]': + - cell [ref=e2666]: + - code + - cell "15" [ref=e2667]: + - code [ref=e2668]: "15" + - 'cell "+ \"--dart-define=NVIDIA_API_KEY=${NVIDIA_API_KEY}\"" [ref=e2669]': + - code [ref=e2670]: + - generic [ref=e2671]: + + - generic [ref=e2673]: "\"--dart-define=NVIDIA_API_KEY=${NVIDIA_API_KEY}\"" + - row "16 16 ]," [ref=e2674]: + - cell "16" [ref=e2675]: + - code [ref=e2676]: "16" + - cell "16" [ref=e2677]: + - code [ref=e2678]: "16" + - cell "]," [ref=e2679]: + - code [ref=e2680]: + - generic [ref=e2681]: "]," + - 'row "17 17 \"port\": 8080" [ref=e2682]': + - cell "17" [ref=e2683]: + - code [ref=e2684]: "17" + - cell "17" [ref=e2685]: + - code [ref=e2686]: "17" + - 'cell "\"port\": 8080" [ref=e2687]': + - code [ref=e2688]: + - generic [ref=e2689]: "\"port\": 8080" + - 'row "18 18 }" [ref=e2690]': + - cell "18" [ref=e2691]: + - code [ref=e2692]: "18" + - cell "18" [ref=e2693]: + - code [ref=e2694]: "18" + - 'cell "}" [ref=e2695]': + - code [ref=e2696]: + - generic [ref=e2697]: "}" + - button "Commit suggestion" [ref=e2699] [cursor=pointer]: + - generic [ref=e2701]: Commit suggestion + - generic [ref=e2702]: + - toolbar "Reactions" + - generic [ref=e2704]: + - button "Positive feedback" [ref=e2705] [cursor=pointer]: + - img [ref=e2706] + - button "Negative feedback" [ref=e2708] [cursor=pointer]: + - img [ref=e2709] + - generic [ref=e2711]: Copilot uses AI. Check for mistakes. + - generic [ref=e2713]: + - generic [ref=e2714]: + - button "Comment thread" [expanded] [ref=e2715] [cursor=pointer]: + - img + - link ".github/workflows/deploy-web.yml" [ref=e2717] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/files/610ee87712bfd0f063f722d6cadca2a5289430cb#diff-875a32a9bd9123a01ecb0b1802809c712a8a04f695e979c262eb9380e6359efc + - generic [ref=e2718]: + - generic [ref=e2720]: Comment on lines +35 to +39 + - table [ref=e2723]: + - rowgroup [ref=e2724]: + - 'row "35 + - name: Deploy to Vercel" [ref=e2725]': + - cell [ref=e2726] [cursor=pointer] + - cell "35" [ref=e2727] [cursor=pointer] + - 'cell "+ - name: Deploy to Vercel" [ref=e2728]': + - generic [ref=e2729]: "+ - name: Deploy to Vercel" + - 'row "36 + working-directory: build/web" [ref=e2730]': + - cell [ref=e2731] [cursor=pointer] + - cell "36" [ref=e2732] [cursor=pointer] + - 'cell "+ working-directory: build/web" [ref=e2733]': + - generic [ref=e2734]: "+ working-directory: build/web" + - 'row "37 + run: npx vercel deploy --prod --yes --token=${{ secrets.VERCEL_TOKEN }}" [ref=e2735]': + - cell [ref=e2736] [cursor=pointer] + - cell "37" [ref=e2737] [cursor=pointer] + - 'cell "+ run: npx vercel deploy --prod --yes --token=${{ secrets.VERCEL_TOKEN }}" [ref=e2738]': + - generic [ref=e2739]: "+ run: npx vercel deploy --prod --yes --token=${{ secrets.VERCEL_TOKEN }}" + - row "38 + env:" [ref=e2740]: + - cell [ref=e2741] [cursor=pointer] + - cell "38" [ref=e2742] [cursor=pointer] + - cell "+ env:" [ref=e2743]: + - generic [ref=e2744]: "+ env:" + - 'row "39 + VERCEL_ORG_ID: team_lC8aTJK0XiU9qDfaHeTfCJs6" [ref=e2745]': + - cell [ref=e2746] [cursor=pointer] + - cell "39" [ref=e2747] [cursor=pointer] + - 'cell "+ VERCEL_ORG_ID: team_lC8aTJK0XiU9qDfaHeTfCJs6" [ref=e2748]': + - generic [ref=e2749]: "+ VERCEL_ORG_ID: team_lC8aTJK0XiU9qDfaHeTfCJs6" + - generic [ref=e2756]: + - generic [ref=e2759]: + - heading "Copilot commented on Jun 4, 2026 7 minutes ago" [level=3] [ref=e2760]: + - text: Copilot commented + - generic "Jun 4, 2026, 6:44 AM EDT" [ref=e2761]: on Jun 4, 2026 7 minutes ago + - img "Copilot" [ref=e2764] + - generic [ref=e2765]: + - generic [ref=e2766]: + - generic [ref=e2767]: Copilot + - generic [ref=e2768]: AI + - link "on Jun 4, 20267 minutes ago" [ref=e2771] [cursor=pointer]: + - /url: https://github.com/CodeStorm-Hub/petfolio/pull/17#discussion_r3355378057 + - generic "Jun 4, 2026, 6:44 AM EDT" [ref=e2772]: on Jun 4, 20267 minutes ago + - generic [ref=e2774]: + - list [ref=e2776]: + - listitem + - listitem [ref=e2777]: + - generic [ref=e2778]: High + - button "Actions for Copilot's comment, 6:44 AM today" [ref=e2780] [cursor=pointer]: + - img [ref=e2781] + - generic [ref=e2784]: + - paragraph [ref=e2787]: + - text: The workflow deploys with + - code [ref=e2788]: "--prod" + - text: "on" + - emphasis [ref=e2789]: pull_request + - text: events too. This can overwrite production for PR builds, and PRs from forks won’t have secrets (causing failing runs). Split preview vs production deploy and gate preview deploys to non-fork PRs. + - generic [ref=e2790]: + - generic [ref=e2792]: + - text: Suggested changeset + - generic [ref=e2793]: "1" + - generic [ref=e2794]: (1) + - generic [ref=e2796]: + - button "Open review comment" [ref=e2797] [cursor=pointer]: + - img [ref=e2798] + - text: .github/workflows/deploy-web.yml + - button "Commit suggestion" [ref=e2801] [cursor=pointer]: + - generic [ref=e2803]: Commit suggestion + - generic [ref=e2804]: + - toolbar "Reactions" + - generic [ref=e2806]: + - button "Positive feedback" [ref=e2807] [cursor=pointer]: + - img [ref=e2808] + - button "Negative feedback" [ref=e2810] [cursor=pointer]: + - img [ref=e2811] + - generic [ref=e2813]: Copilot uses AI. Check for mistakes. + - generic [ref=e2815]: + - generic [ref=e2816]: + - button "Comment thread" [expanded] [ref=e2817] [cursor=pointer]: + - img + - link "vercel.json" [ref=e2819] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/files/610ee87712bfd0f063f722d6cadca2a5289430cb#diff-a3265310f552fb66876e8bfe8809737e59e5ba946bdf39138b44d9baf4e21240 + - generic [ref=e2820]: + - generic [ref=e2822]: Comment on lines +11 to +25 + - table [ref=e2825]: + - rowgroup [ref=e2826]: + - 'row "11 + {" [ref=e2827]': + - cell [ref=e2828] [cursor=pointer] + - cell "11" [ref=e2829] [cursor=pointer] + - 'cell "+ {" [ref=e2830]': + - generic [ref=e2831]: "+ {" + - 'row "12 + \"source\": \"/(.*)\\\\.wasm\"," [ref=e2832]': + - cell [ref=e2833] [cursor=pointer] + - cell "12" [ref=e2834] [cursor=pointer] + - 'cell "+ \"source\": \"/(.*)\\\\.wasm\"," [ref=e2835]': + - generic [ref=e2836]: "+ \"source\": \"/(.*)\\\\.wasm\"," + - 'row "13 + \"headers\": [" [ref=e2837]': + - cell [ref=e2838] [cursor=pointer] + - cell "13" [ref=e2839] [cursor=pointer] + - 'cell "+ \"headers\": [" [ref=e2840]': + - generic [ref=e2841]: "+ \"headers\": [" + - 'row "14 + { \"key\": \"Content-Type\", \"value\": \"application/wasm\" }," [ref=e2842]': + - cell [ref=e2843] [cursor=pointer] + - cell "14" [ref=e2844] [cursor=pointer] + - 'cell "+ { \"key\": \"Content-Type\", \"value\": \"application/wasm\" }," [ref=e2845]': + - generic [ref=e2846]: "+ { \"key\": \"Content-Type\", \"value\": \"application/wasm\" }," + - 'row "15 + { \"key\": \"Cross-Origin-Embedder-Policy\", \"value\": \"require-corp\" }," [ref=e2847]': + - cell [ref=e2848] [cursor=pointer] + - cell "15" [ref=e2849] [cursor=pointer] + - 'cell "+ { \"key\": \"Cross-Origin-Embedder-Policy\", \"value\": \"require-corp\" }," [ref=e2850]': + - generic [ref=e2851]: "+ { \"key\": \"Cross-Origin-Embedder-Policy\", \"value\": \"require-corp\" }," + - 'row "16 + { \"key\": \"Cross-Origin-Opener-Policy\", \"value\": \"same-origin\" }" [ref=e2852]': + - cell [ref=e2853] [cursor=pointer] + - cell "16" [ref=e2854] [cursor=pointer] + - 'cell "+ { \"key\": \"Cross-Origin-Opener-Policy\", \"value\": \"same-origin\" }" [ref=e2855]': + - generic [ref=e2856]: "+ { \"key\": \"Cross-Origin-Opener-Policy\", \"value\": \"same-origin\" }" + - row "17 + ]" [ref=e2857]: + - cell [ref=e2858] [cursor=pointer] + - cell "17" [ref=e2859] [cursor=pointer] + - cell "+ ]" [ref=e2860]: + - generic [ref=e2861]: + ] + - 'row "18 + }," [ref=e2862]': + - cell [ref=e2863] [cursor=pointer] + - cell "18" [ref=e2864] [cursor=pointer] + - 'cell "+ }," [ref=e2865]': + - generic [ref=e2866]: "+ }," + - 'row "19 + {" [ref=e2867]': + - cell [ref=e2868] [cursor=pointer] + - cell "19" [ref=e2869] [cursor=pointer] + - 'cell "+ {" [ref=e2870]': + - generic [ref=e2871]: "+ {" + - 'row "20 + \"source\": \"/(.*)\"," [ref=e2872]': + - cell [ref=e2873] [cursor=pointer] + - cell "20" [ref=e2874] [cursor=pointer] + - 'cell "+ \"source\": \"/(.*)\"," [ref=e2875]': + - generic [ref=e2876]: "+ \"source\": \"/(.*)\"," + - 'row "21 + \"headers\": [" [ref=e2877]': + - cell [ref=e2878] [cursor=pointer] + - cell "21" [ref=e2879] [cursor=pointer] + - 'cell "+ \"headers\": [" [ref=e2880]': + - generic [ref=e2881]: "+ \"headers\": [" + - 'row "22 + { \"key\": \"Cross-Origin-Embedder-Policy\", \"value\": \"require-corp\" }," [ref=e2882]': + - cell [ref=e2883] [cursor=pointer] + - cell "22" [ref=e2884] [cursor=pointer] + - 'cell "+ { \"key\": \"Cross-Origin-Embedder-Policy\", \"value\": \"require-corp\" }," [ref=e2885]': + - generic [ref=e2886]: "+ { \"key\": \"Cross-Origin-Embedder-Policy\", \"value\": \"require-corp\" }," + - 'row "23 + { \"key\": \"Cross-Origin-Opener-Policy\", \"value\": \"same-origin\" }" [ref=e2887]': + - cell [ref=e2888] [cursor=pointer] + - cell "23" [ref=e2889] [cursor=pointer] + - 'cell "+ { \"key\": \"Cross-Origin-Opener-Policy\", \"value\": \"same-origin\" }" [ref=e2890]': + - generic [ref=e2891]: "+ { \"key\": \"Cross-Origin-Opener-Policy\", \"value\": \"same-origin\" }" + - row "24 + ]" [ref=e2892]: + - cell [ref=e2893] [cursor=pointer] + - cell "24" [ref=e2894] [cursor=pointer] + - cell "+ ]" [ref=e2895]: + - generic [ref=e2896]: + ] + - 'row "25 + }" [ref=e2897]': + - cell [ref=e2898] [cursor=pointer] + - cell "25" [ref=e2899] [cursor=pointer] + - 'cell "+ }" [ref=e2900]': + - generic [ref=e2901]: "+ }" + - generic [ref=e2908]: + - generic [ref=e2911]: + - heading "Copilot commented on Jun 4, 2026 7 minutes ago" [level=3] [ref=e2912]: + - text: Copilot commented + - generic "Jun 4, 2026, 6:44 AM EDT" [ref=e2913]: on Jun 4, 2026 7 minutes ago + - img "Copilot" [ref=e2916] + - generic [ref=e2917]: + - generic [ref=e2918]: + - generic [ref=e2919]: Copilot + - generic [ref=e2920]: AI + - link "on Jun 4, 20267 minutes ago" [ref=e2923] [cursor=pointer]: + - /url: https://github.com/CodeStorm-Hub/petfolio/pull/17#discussion_r3355378071 + - generic "Jun 4, 2026, 6:44 AM EDT" [ref=e2924]: on Jun 4, 20267 minutes ago + - generic [ref=e2926]: + - list [ref=e2928]: + - listitem + - listitem [ref=e2929]: + - generic [ref=e2930]: High + - button "Actions for Copilot's comment, 6:44 AM today" [ref=e2932] [cursor=pointer]: + - img [ref=e2933] + - generic [ref=e2936]: + - paragraph [ref=e2939]: + - text: Setting COEP/COOP to + - code [ref=e2940]: require-corp + - text: / + - code [ref=e2941]: same-origin + - text: for all routes will block cross-origin subresources that aren’t CORS/CORP-enabled. This app loads Stripe from + - code [ref=e2942]: https://js.stripe.com/v3/ + - text: without + - code [ref=e2943]: crossorigin + - text: ", so these headers are very likely to break Stripe and/or app boot." + - generic [ref=e2944]: + - generic [ref=e2946]: + - text: Suggested changeset + - generic [ref=e2947]: "1" + - generic [ref=e2948]: (1) + - generic [ref=e2949]: + - generic [ref=e2950]: + - button "Close review comment" [ref=e2951] [cursor=pointer]: + - img [ref=e2952] + - text: vercel.json + - table [ref=e2955]: + - rowgroup [ref=e2956]: + - row "Original file line number Diff line number Diff line change" [ref=e2957]: + - columnheader "Original file line number" [ref=e2958] + - columnheader "Diff line number" [ref=e2959] + - columnheader "Diff line change" [ref=e2960] + - rowgroup [ref=e2965]: + - row "@@ -11,16 +11,7 @@" [ref=e2966]: + - cell "@@ -11,16 +11,7 @@" [ref=e2967]: + - generic [ref=e2968]: + - img [ref=e2970] + - code [ref=e2972]: + - generic [ref=e2973]: "@@ -11,16 +11,7 @@" + - 'row "11 11 {" [ref=e2974]': + - cell "11" [ref=e2975]: + - code [ref=e2976]: "11" + - cell "11" [ref=e2977]: + - code [ref=e2978]: "11" + - 'cell "{" [ref=e2979]': + - code [ref=e2980]: + - generic [ref=e2981]: "{" + - 'row "12 12 \"source\": \"/(.*)\\\\.wasm\"," [ref=e2982]': + - cell "12" [ref=e2983]: + - code [ref=e2984]: "12" + - cell "12" [ref=e2985]: + - code [ref=e2986]: "12" + - 'cell "\"source\": \"/(.*)\\\\.wasm\"," [ref=e2987]': + - code [ref=e2988]: + - generic [ref=e2989]: + - text: "\"source\":" + - generic [ref=e2990]: "\"/(.*)\\\\.wasm\"" + - text: "," + - 'row "13 13 \"headers\": [" [ref=e2991]': + - cell "13" [ref=e2992]: + - code [ref=e2993]: "13" + - cell "13" [ref=e2994]: + - code [ref=e2995]: "13" + - 'cell "\"headers\": [" [ref=e2996]': + - code [ref=e2997]: + - generic [ref=e2998]: "\"headers\": [" + - 'row "14 - { \"key\": \"Content-Type\", \"value\": \"application/wasm\" }," [ref=e2999]': + - cell "14" [ref=e3000]: + - code [ref=e3001]: "14" + - cell [ref=e3002]: + - code + - 'cell "- { \"key\": \"Content-Type\", \"value\": \"application/wasm\" }," [ref=e3003]': + - code [ref=e3004]: + - generic [ref=e3005]: "-" + - generic [ref=e3006]: + - text: "{ \"key\":" + - generic [ref=e3007]: "\"Content-Type\"" + - text: ", \"value\":" + - generic [ref=e3008]: "\"application/wasm\"" + - text: "}," + - 'row "15 - { \"key\": \"Cross-Origin-Embedder-Policy\", \"value\": \"require-corp\" }," [ref=e3009]': + - cell "15" [ref=e3010]: + - code [ref=e3011]: "15" + - cell [ref=e3012]: + - code + - 'cell "- { \"key\": \"Cross-Origin-Embedder-Policy\", \"value\": \"require-corp\" }," [ref=e3013]': + - code [ref=e3014]: + - generic [ref=e3015]: "-" + - generic [ref=e3016]: + - text: "{ \"key\":" + - generic [ref=e3017]: "\"Cross-Origin-Embedder-Policy\"" + - text: ", \"value\":" + - generic [ref=e3018]: "\"require-corp\"" + - text: "}," + - 'row "16 - { \"key\": \"Cross-Origin-Opener-Policy\", \"value\": \"same-origin\" }" [ref=e3019]': + - cell "16" [ref=e3020]: + - code [ref=e3021]: "16" + - cell [ref=e3022]: + - code + - 'cell "- { \"key\": \"Cross-Origin-Opener-Policy\", \"value\": \"same-origin\" }" [ref=e3023]': + - code [ref=e3024]: + - generic [ref=e3025]: "-" + - generic [ref=e3026]: + - text: "{ \"key\":" + - generic [ref=e3027]: "\"Cross-Origin-Opener-Policy\"" + - text: ", \"value\":" + - generic [ref=e3028]: "\"same-origin\"" + - text: "}" + - row "17 - ]" [ref=e3029]: + - cell "17" [ref=e3030]: + - code [ref=e3031]: "17" + - cell [ref=e3032]: + - code + - cell "- ]" [ref=e3033]: + - code [ref=e3034]: + - generic [ref=e3035]: "-" + - generic [ref=e3036]: "]" + - 'row "18 - }," [ref=e3037]': + - cell "18" [ref=e3038]: + - code [ref=e3039]: "18" + - cell [ref=e3040]: + - code + - 'cell "- }," [ref=e3041]': + - code [ref=e3042]: + - generic [ref=e3043]: "-" + - generic [ref=e3044]: "}," + - 'row "19 - {" [ref=e3045]': + - cell "19" [ref=e3046]: + - code [ref=e3047]: "19" + - cell [ref=e3048]: + - code + - 'cell "- {" [ref=e3049]': + - code [ref=e3050]: + - generic [ref=e3051]: "-" + - generic [ref=e3052]: "{" + - 'row "20 - \"source\": \"/(.*)\"," [ref=e3053]': + - cell "20" [ref=e3054]: + - code [ref=e3055]: "20" + - cell [ref=e3056]: + - code + - 'cell "- \"source\": \"/(.*)\"," [ref=e3057]': + - code [ref=e3058]: + - generic [ref=e3059]: "-" + - generic [ref=e3060]: + - text: "\"source\":" + - generic [ref=e3061]: "\"/(.*)\"" + - text: "," + - 'row "21 - \"headers\": [" [ref=e3062]': + - cell "21" [ref=e3063]: + - code [ref=e3064]: "21" + - cell [ref=e3065]: + - code + - 'cell "- \"headers\": [" [ref=e3066]': + - code [ref=e3067]: + - generic [ref=e3068]: "-" + - generic [ref=e3069]: "\"headers\": [" + - 'row "22 - { \"key\": \"Cross-Origin-Embedder-Policy\", \"value\": \"require-corp\" }," [ref=e3070]': + - cell "22" [ref=e3071]: + - code [ref=e3072]: "22" + - cell [ref=e3073]: + - code + - 'cell "- { \"key\": \"Cross-Origin-Embedder-Policy\", \"value\": \"require-corp\" }," [ref=e3074]': + - code [ref=e3075]: + - generic [ref=e3076]: "-" + - generic [ref=e3077]: + - text: "{ \"key\":" + - generic [ref=e3078]: "\"Cross-Origin-Embedder-Policy\"" + - text: ", \"value\":" + - generic [ref=e3079]: "\"require-corp\"" + - text: "}," + - 'row "23 - { \"key\": \"Cross-Origin-Opener-Policy\", \"value\": \"same-origin\" }" [ref=e3080]': + - cell "23" [ref=e3081]: + - code [ref=e3082]: "23" + - cell [ref=e3083]: + - code + - 'cell "- { \"key\": \"Cross-Origin-Opener-Policy\", \"value\": \"same-origin\" }" [ref=e3084]': + - code [ref=e3085]: + - generic [ref=e3086]: "-" + - generic [ref=e3087]: + - text: "{ \"key\":" + - generic [ref=e3088]: "\"Cross-Origin-Opener-Policy\"" + - text: ", \"value\":" + - generic [ref=e3089]: "\"same-origin\"" + - text: "}" + - 'row "14 + { \"key\": \"Content-Type\", \"value\": \"application/wasm\" }" [ref=e3090]': + - cell [ref=e3091]: + - code + - cell "14" [ref=e3092]: + - code [ref=e3093]: "14" + - 'cell "+ { \"key\": \"Content-Type\", \"value\": \"application/wasm\" }" [ref=e3094]': + - code [ref=e3095]: + - generic [ref=e3096]: + + - generic [ref=e3097]: + - text: "{ \"key\":" + - generic [ref=e3098]: "\"Content-Type\"" + - text: ", \"value\":" + - generic [ref=e3099]: "\"application/wasm\"" + - text: "}" + - row "24 15 ]" [ref=e3100]: + - cell "24" [ref=e3101]: + - code [ref=e3102]: "24" + - cell "15" [ref=e3103]: + - code [ref=e3104]: "15" + - cell "]" [ref=e3105]: + - code [ref=e3106]: + - generic [ref=e3107]: "]" + - 'row "25 16 }" [ref=e3108]': + - cell "25" [ref=e3109]: + - code [ref=e3110]: "25" + - cell "16" [ref=e3111]: + - code [ref=e3112]: "16" + - 'cell "}" [ref=e3113]': + - code [ref=e3114]: + - generic [ref=e3115]: "}" + - row "26 17 ]," [ref=e3116]: + - cell "26" [ref=e3117]: + - code [ref=e3118]: "26" + - cell "17" [ref=e3119]: + - code [ref=e3120]: "17" + - cell "]," [ref=e3121]: + - code [ref=e3122]: + - generic [ref=e3123]: "]," + - button "Commit suggestion" [ref=e3125] [cursor=pointer]: + - generic [ref=e3127]: Commit suggestion + - generic [ref=e3128]: + - toolbar "Reactions" + - generic [ref=e3130]: + - button "Positive feedback" [ref=e3131] [cursor=pointer]: + - img [ref=e3132] + - button "Negative feedback" [ref=e3134] [cursor=pointer]: + - img [ref=e3135] + - generic [ref=e3137]: Copilot uses AI. Check for mistakes. + - generic [ref=e3139]: + - generic [ref=e3140]: + - button "Comment thread" [expanded] [ref=e3141] [cursor=pointer]: + - img + - link "web/index.html" [ref=e3143] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/files/610ee87712bfd0f063f722d6cadca2a5289430cb#diff-8f62b6ced28d3396b501d2e89a2e7cb761d16cd7dc977aebece03d4a5da5c24e + - generic [ref=e3144]: + - generic [ref=e3146]: Comment on lines +10 to +12 + - table [ref=e3149]: + - rowgroup [ref=e3150]: + - row "10 + " [ref=e3161]: + - cell [ref=e3162] [cursor=pointer] + - cell "12" [ref=e3163] [cursor=pointer] + - cell "+ user-scalable=no, viewport-fit=cover\">" [ref=e3164]: + - generic [ref=e3165]: + user-scalable=no, viewport-fit=cover"> + - generic [ref=e3172]: + - generic [ref=e3175]: + - heading "Copilot commented on Jun 4, 2026 7 minutes ago" [level=3] [ref=e3176]: + - text: Copilot commented + - generic "Jun 4, 2026, 6:44 AM EDT" [ref=e3177]: on Jun 4, 2026 7 minutes ago + - img "Copilot" [ref=e3180] + - generic [ref=e3181]: + - generic [ref=e3182]: + - generic [ref=e3183]: Copilot + - generic [ref=e3184]: AI + - link "on Jun 4, 20267 minutes ago" [ref=e3187] [cursor=pointer]: + - /url: https://github.com/CodeStorm-Hub/petfolio/pull/17#discussion_r3355378096 + - generic "Jun 4, 2026, 6:44 AM EDT" [ref=e3188]: on Jun 4, 20267 minutes ago + - generic [ref=e3190]: + - list [ref=e3192]: + - listitem + - listitem [ref=e3193]: + - generic [ref=e3194]: Medium + - button "Actions for Copilot's comment, 6:44 AM today" [ref=e3196] [cursor=pointer]: + - img [ref=e3197] + - generic [ref=e3200]: + - paragraph [ref=e3203]: + - text: The viewport meta disables pinch-zoom ( + - code [ref=e3204]: maximum-scale=1.0 + - text: + + - code [ref=e3205]: user-scalable=no + - text: ). This is an accessibility issue (users who rely on zoom cannot enlarge text/UI). Prefer allowing zoom while keeping + - code [ref=e3206]: viewport-fit=cover + - text: . + - generic [ref=e3207]: + - generic [ref=e3209]: + - text: Suggested changeset + - generic [ref=e3210]: "1" + - generic [ref=e3211]: (1) + - generic [ref=e3212]: + - generic [ref=e3213]: + - button "Close review comment" [ref=e3214] [cursor=pointer]: + - img [ref=e3215] + - text: web/index.html + - table [ref=e3218]: + - rowgroup [ref=e3219]: + - row "Original file line number Diff line number Diff line change" [ref=e3220]: + - columnheader "Original file line number" [ref=e3221] + - columnheader "Diff line number" [ref=e3222] + - columnheader "Diff line change" [ref=e3223] + - rowgroup [ref=e3228]: + - row "@@ -8,8 +8,7 @@" [ref=e3229]: + - cell "@@ -8,8 +8,7 @@" [ref=e3230]: + - generic [ref=e3231]: + - img [ref=e3233] + - code [ref=e3235]: + - generic [ref=e3236]: "@@ -8,8 +8,7 @@" + - row "8 8" [ref=e3237]: + - cell "8" [ref=e3238]: + - code [ref=e3239]: "8" + - cell "8" [ref=e3240]: + - code [ref=e3241]: "8" + - cell [ref=e3242]: + - code + - 'row "9 9 " [ref=e3243]': + - cell "9" [ref=e3244]: + - code [ref=e3245]: "9" + - cell "9" [ref=e3246]: + - code [ref=e3247]: "9" + - 'cell "" [ref=e3248]': + - code [ref=e3249]: + - generic [ref=e3250]: "" + - row "10 10 " [ref=e3267]: + - cell "12" [ref=e3268]: + - code [ref=e3269]: "12" + - cell [ref=e3270]: + - code + - cell "- user-scalable=no, viewport-fit=cover\">" [ref=e3271]: + - code [ref=e3272]: + - generic [ref=e3273]: "-" + - generic [ref=e3274]: user-scalable=no, viewport-fit=cover"> + - row "11 + content=\"width=device-width, initial-scale=1.0, viewport-fit=cover\">" [ref=e3275]: + - cell [ref=e3276]: + - code + - cell "11" [ref=e3277]: + - code [ref=e3278]: "11" + - cell "+ content=\"width=device-width, initial-scale=1.0, viewport-fit=cover\">" [ref=e3279]: + - code [ref=e3280]: + - generic [ref=e3281]: + + - generic [ref=e3282]: content="width=device-width, initial-scale=1.0, viewport-fit=cover"> + - row "13 12" [ref=e3283]: + - cell "13" [ref=e3284]: + - code [ref=e3285]: "13" + - cell "12" [ref=e3286]: + - code [ref=e3287]: "12" + - cell [ref=e3288]: + - code + - row "14 13 " [ref=e3297]: + - cell "15" [ref=e3298]: + - code [ref=e3299]: "15" + - cell "14" [ref=e3300]: + - code [ref=e3301]: "14" + - cell "content=\"PetFolio — Your pet's social network, health tracker & marketplace.\">" [ref=e3302]: + - code [ref=e3303]: + - generic [ref=e3304]: content="PetFolio — Your pet's social network, health tracker & marketplace."> + - button "Commit suggestion" [ref=e3306] [cursor=pointer]: + - generic [ref=e3308]: Commit suggestion + - generic [ref=e3309]: + - toolbar "Reactions" + - generic [ref=e3311]: + - button "Positive feedback" [ref=e3312] [cursor=pointer]: + - img [ref=e3313] + - button "Negative feedback" [ref=e3315] [cursor=pointer]: + - img [ref=e3316] + - generic [ref=e3318]: Copilot uses AI. Check for mistakes. + - generic [ref=e3320]: + - generic [ref=e3321]: + - button "Comment thread" [expanded] [ref=e3322] [cursor=pointer]: + - img + - link "web/index.html" [ref=e3324] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/files/610ee87712bfd0f063f722d6cadca2a5289430cb#diff-8f62b6ced28d3396b501d2e89a2e7cb761d16cd7dc977aebece03d4a5da5c24e + - generic [ref=e3325]: + - generic [ref=e3327]: Comment on lines +29 to +31 + - table [ref=e3330]: + - rowgroup [ref=e3331]: + - row "29 + " [ref=e3332]: + - cell [ref=e3333] [cursor=pointer] + - cell "29" [ref=e3334] [cursor=pointer] + - cell "+ " [ref=e3335]: + - generic [ref=e3336]: + + - row "30 + " [ref=e3337]: + - cell [ref=e3338] [cursor=pointer] + - cell "30" [ref=e3339] [cursor=pointer] + - cell "+ " [ref=e3340]: + - generic [ref=e3341]: + + - row "31 + " [ref=e3342]: + - cell [ref=e3343] [cursor=pointer] + - cell "31" [ref=e3344] [cursor=pointer] + - cell "+ " [ref=e3345]: + - generic [ref=e3346]: + + - generic [ref=e3353]: + - generic [ref=e3356]: + - heading "Copilot commented on Jun 4, 2026 7 minutes ago" [level=3] [ref=e3357]: + - text: Copilot commented + - generic "Jun 4, 2026, 6:44 AM EDT" [ref=e3358]: on Jun 4, 2026 7 minutes ago + - img "Copilot" [ref=e3361] + - generic [ref=e3362]: + - generic [ref=e3363]: + - generic [ref=e3364]: Copilot + - generic [ref=e3365]: AI + - link "on Jun 4, 20267 minutes ago" [ref=e3368] [cursor=pointer]: + - /url: https://github.com/CodeStorm-Hub/petfolio/pull/17#discussion_r3355378110 + - generic "Jun 4, 2026, 6:44 AM EDT" [ref=e3369]: on Jun 4, 20267 minutes ago + - generic [ref=e3371]: + - list [ref=e3373]: + - listitem + - listitem [ref=e3374]: + - generic [ref=e3375]: Medium + - button "Actions for Copilot's comment, 6:44 AM today" [ref=e3377] [cursor=pointer]: + - img [ref=e3378] + - generic [ref=e3381]: + - paragraph [ref=e3384]: + - text: The + - code [ref=e3385]: apple-touch-icon + - text: declares + - code [ref=e3386]: sizes="180x180" + - text: but points to + - code [ref=e3387]: Icon-192.png + - text: (192×192). iOS uses the + - code [ref=e3388]: sizes + - text: hint for selection; mismatching metadata can lead to suboptimal icon selection/caching. + - generic [ref=e3389]: + - generic [ref=e3391]: + - text: Suggested changeset + - generic [ref=e3392]: "1" + - generic [ref=e3393]: (1) + - generic [ref=e3394]: + - generic [ref=e3395]: + - button "Close review comment" [ref=e3396] [cursor=pointer]: + - img [ref=e3397] + - text: web/index.html + - table [ref=e3400]: + - rowgroup [ref=e3401]: + - row "Original file line number Diff line number Diff line change" [ref=e3402]: + - columnheader "Original file line number" [ref=e3403] + - columnheader "Diff line number" [ref=e3404] + - columnheader "Diff line change" [ref=e3405] + - rowgroup [ref=e3410]: + - row "@@ -27,7 +27,7 @@" [ref=e3411]: + - cell "@@ -27,7 +27,7 @@" [ref=e3412]: + - generic [ref=e3413]: + - img [ref=e3415] + - code [ref=e3417]: + - generic [ref=e3418]: "@@ -27,7 +27,7 @@" + - row "27 27 " [ref=e3419]: + - cell "27" [ref=e3420]: + - code [ref=e3421]: "27" + - cell "27" [ref=e3422]: + - code [ref=e3423]: "27" + - cell "" [ref=e3424]: + - code [ref=e3425]: + - generic [ref=e3426]: + - row "28 28" [ref=e3427]: + - cell "28" [ref=e3428]: + - code [ref=e3429]: "28" + - cell "28" [ref=e3430]: + - code [ref=e3431]: "28" + - cell [ref=e3432]: + - code + - row "29 29 " [ref=e3433]: + - cell "29" [ref=e3434]: + - code [ref=e3435]: "29" + - cell "29" [ref=e3436]: + - code [ref=e3437]: "29" + - cell "" [ref=e3438]: + - code [ref=e3439]: + - generic [ref=e3440]: + - row "30 - " [ref=e3441]: + - cell "30" [ref=e3442]: + - code [ref=e3443]: "30" + - cell [ref=e3444]: + - code + - cell "- " [ref=e3445]: + - code [ref=e3446]: + - generic [ref=e3447]: "-" + - generic [ref=e3448]: + - row "30 + " [ref=e3449]: + - cell [ref=e3450]: + - code + - cell "30" [ref=e3451]: + - code [ref=e3452]: "30" + - cell "+ " [ref=e3453]: + - code [ref=e3454]: + - generic [ref=e3455]: + + - generic [ref=e3456]: + - row "31 31 " [ref=e3457]: + - cell "31" [ref=e3458]: + - code [ref=e3459]: "31" + - cell "31" [ref=e3460]: + - code [ref=e3461]: "31" + - cell "" [ref=e3462]: + - code [ref=e3463]: + - generic [ref=e3464]: + - row "32 32" [ref=e3465]: + - cell "32" [ref=e3466]: + - code [ref=e3467]: "32" + - cell "32" [ref=e3468]: + - code [ref=e3469]: "32" + - cell [ref=e3470]: + - code + - row "33 33 " [ref=e3471]: + - cell "33" [ref=e3472]: + - code [ref=e3473]: "33" + - cell "33" [ref=e3474]: + - code [ref=e3475]: "33" + - cell "" [ref=e3476]: + - code [ref=e3477]: + - generic [ref=e3478]: + - button "Commit suggestion" [ref=e3480] [cursor=pointer]: + - generic [ref=e3482]: Commit suggestion + - generic [ref=e3483]: + - toolbar "Reactions" + - generic [ref=e3485]: + - button "Positive feedback" [ref=e3486] [cursor=pointer]: + - img [ref=e3487] + - button "Negative feedback" [ref=e3489] [cursor=pointer]: + - img [ref=e3490] + - generic [ref=e3492]: Copilot uses AI. Check for mistakes. + - generic [ref=e3494]: + - button "8 hidden conversations" [ref=e3495] [cursor=pointer] + - button "Load more…" [ref=e3496] [cursor=pointer] + - generic [ref=e3498]: + - generic [ref=e3499]: + - button "Comment thread" [expanded] [ref=e3500] [cursor=pointer]: + - img + - link "lib/features/care/presentation/widgets/gamified_care_ui.dart" [ref=e3502] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/files/610ee87712bfd0f063f722d6cadca2a5289430cb#diff-8e2cf796cdb83ed78c034ccd2f1ab099667749421148c7f255df9b4f1317c508 + - generic [ref=e3503]: + - generic [ref=e3505]: Comment on lines +1096 to +1115 + - table [ref=e3508]: + - rowgroup [ref=e3509]: + - row "1096 + @override" [ref=e3510]: + - cell [ref=e3511] [cursor=pointer] + - cell "1096" [ref=e3512] [cursor=pointer] + - cell "+ @override" [ref=e3513]: + - generic [ref=e3514]: + @override + - 'row "1097 + void initState() {" [ref=e3515]': + - cell [ref=e3516] [cursor=pointer] + - cell "1097" [ref=e3517] [cursor=pointer] + - 'cell "+ void initState() {" [ref=e3518]': + - generic [ref=e3519]: "+ void initState() {" + - row "1098 + super.initState();" [ref=e3520]: + - cell [ref=e3521] [cursor=pointer] + - cell "1098" [ref=e3522] [cursor=pointer] + - cell "+ super.initState();" [ref=e3523]: + - generic [ref=e3524]: + super.initState(); + - row "1099 + _floatCtrl = AnimationController(" [ref=e3525]: + - cell [ref=e3526] [cursor=pointer] + - cell "1099" [ref=e3527] [cursor=pointer] + - cell "+ _floatCtrl = AnimationController(" [ref=e3528]: + - generic [ref=e3529]: + _floatCtrl = AnimationController( + - 'row "1100 + vsync: this," [ref=e3530]': + - cell [ref=e3531] [cursor=pointer] + - cell "1100" [ref=e3532] [cursor=pointer] + - 'cell "+ vsync: this," [ref=e3533]': + - generic [ref=e3534]: "+ vsync: this," + - 'row "1101 + duration: Duration(milliseconds: 3200 + widget.index * 200)," [ref=e3535]': + - cell [ref=e3536] [cursor=pointer] + - cell "1101" [ref=e3537] [cursor=pointer] + - 'cell "+ duration: Duration(milliseconds: 3200 + widget.index * 200)," [ref=e3538]': + - generic [ref=e3539]: "+ duration: Duration(milliseconds: 3200 + widget.index * 200)," + - 'row "1102 + )..repeat(reverse: true);" [ref=e3540]': + - cell [ref=e3541] [cursor=pointer] + - cell "1102" [ref=e3542] [cursor=pointer] + - 'cell "+ )..repeat(reverse: true);" [ref=e3543]': + - generic [ref=e3544]: "+ )..repeat(reverse: true);" + - row "1103 +" [ref=e3545]: + - cell [ref=e3546] [cursor=pointer] + - cell "1103" [ref=e3547] [cursor=pointer] + - cell "+" [ref=e3548]: + - generic: + + - 'row "1104 + final sheenDuration = Duration(milliseconds: 3800 + widget.index * 200);" [ref=e3549]': + - cell [ref=e3550] [cursor=pointer] + - cell "1104" [ref=e3551] [cursor=pointer] + - 'cell "+ final sheenDuration = Duration(milliseconds: 3800 + widget.index * 200);" [ref=e3552]': + - generic [ref=e3553]: "+ final sheenDuration = Duration(milliseconds: 3800 + widget.index * 200);" + - 'row "1105 + _sheenCtrl = AnimationController(vsync: this, duration: sheenDuration);" [ref=e3554]': + - cell [ref=e3555] [cursor=pointer] + - cell "1105" [ref=e3556] [cursor=pointer] + - 'cell "+ _sheenCtrl = AnimationController(vsync: this, duration: sheenDuration);" [ref=e3557]': + - generic [ref=e3558]: "+ _sheenCtrl = AnimationController(vsync: this, duration: sheenDuration);" + - row "1106 +" [ref=e3559]: + - cell [ref=e3560] [cursor=pointer] + - cell "1106" [ref=e3561] [cursor=pointer] + - cell "+" [ref=e3562]: + - generic: + + - 'row "1107 + if (widget.owned) {" [ref=e3563]': + - cell [ref=e3564] [cursor=pointer] + - cell "1107" [ref=e3565] [cursor=pointer] + - 'cell "+ if (widget.owned) {" [ref=e3566]': + - generic [ref=e3567]: "+ if (widget.owned) {" + - row "1108 + final delayFraction =" [ref=e3568]: + - cell [ref=e3569] [cursor=pointer] + - cell "1108" [ref=e3570] [cursor=pointer] + - cell "+ final delayFraction =" [ref=e3571]: + - generic [ref=e3572]: + final delayFraction = + - row "1109 + (widget.index * 300 / sheenDuration.inMilliseconds).clamp(0.0, 1.0);" [ref=e3573]: + - cell [ref=e3574] [cursor=pointer] + - cell "1109" [ref=e3575] [cursor=pointer] + - cell "+ (widget.index * 300 / sheenDuration.inMilliseconds).clamp(0.0, 1.0);" [ref=e3576]: + - generic [ref=e3577]: + (widget.index * 300 / sheenDuration.inMilliseconds).clamp(0.0, 1.0); + - 'row "1110 + _sheenCtrl.forward(from: delayFraction);" [ref=e3578]': + - cell [ref=e3579] [cursor=pointer] + - cell "1110" [ref=e3580] [cursor=pointer] + - 'cell "+ _sheenCtrl.forward(from: delayFraction);" [ref=e3581]': + - generic [ref=e3582]: "+ _sheenCtrl.forward(from: delayFraction);" + - 'row "1111 + _sheenCtrl.addStatusListener((s) {" [ref=e3583]': + - cell [ref=e3584] [cursor=pointer] + - cell "1111" [ref=e3585] [cursor=pointer] + - 'cell "+ _sheenCtrl.addStatusListener((s) {" [ref=e3586]': + - generic [ref=e3587]: "+ _sheenCtrl.addStatusListener((s) {" + - row "1112 + if (s == AnimationStatus.completed && mounted) _sheenCtrl.repeat();" [ref=e3588]: + - cell [ref=e3589] [cursor=pointer] + - cell "1112" [ref=e3590] [cursor=pointer] + - cell "+ if (s == AnimationStatus.completed && mounted) _sheenCtrl.repeat();" [ref=e3591]: + - generic [ref=e3592]: + if (s == AnimationStatus.completed && mounted) _sheenCtrl.repeat(); + - 'row "1113 + });" [ref=e3593]': + - cell [ref=e3594] [cursor=pointer] + - cell "1113" [ref=e3595] [cursor=pointer] + - 'cell "+ });" [ref=e3596]': + - generic [ref=e3597]: "+ });" + - 'row "1114 + }" [ref=e3598]': + - cell [ref=e3599] [cursor=pointer] + - cell "1114" [ref=e3600] [cursor=pointer] + - 'cell "+ }" [ref=e3601]': + - generic [ref=e3602]: "+ }" + - 'row "1115 + }" [ref=e3603]': + - cell [ref=e3604] [cursor=pointer] + - cell "1115" [ref=e3605] [cursor=pointer] + - 'cell "+ }" [ref=e3606]': + - generic [ref=e3607]: "+ }" + - generic [ref=e3609]: + - generic [ref=e3610]: + - button "Comment thread" [expanded] [ref=e3611] [cursor=pointer]: + - img + - link ".vercel/project.json" [ref=e3613] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/files/610ee87712bfd0f063f722d6cadca2a5289430cb#diff-e2c270517efd9fd0ee81fc3bd3b0a169e5172ec31da017dc7c44eec97b21ae1a + - generic [ref=e3614]: + - generic [ref=e3616]: Comment on lines +1 to +4 + - table [ref=e3619]: + - rowgroup [ref=e3620]: + - 'row "1 + {" [ref=e3621]': + - cell [ref=e3622] [cursor=pointer] + - cell "1" [ref=e3623] [cursor=pointer] + - 'cell "+ {" [ref=e3624]': + - generic [ref=e3625]: "+ {" + - 'row "2 + \"orgId\": \"team_lC8aTJK0XiU9qDfaHeTfCJs6\"," [ref=e3626]': + - cell [ref=e3627] [cursor=pointer] + - cell "2" [ref=e3628] [cursor=pointer] + - 'cell "+ \"orgId\": \"team_lC8aTJK0XiU9qDfaHeTfCJs6\"," [ref=e3629]': + - generic [ref=e3630]: "+ \"orgId\": \"team_lC8aTJK0XiU9qDfaHeTfCJs6\"," + - 'row "3 + \"projectId\": \"prj_hMHouLWimZvr5dDOlZeAhbH8xtop\"" [ref=e3631]': + - cell [ref=e3632] [cursor=pointer] + - cell "3" [ref=e3633] [cursor=pointer] + - 'cell "+ \"projectId\": \"prj_hMHouLWimZvr5dDOlZeAhbH8xtop\"" [ref=e3634]': + - generic [ref=e3635]: "+ \"projectId\": \"prj_hMHouLWimZvr5dDOlZeAhbH8xtop\"" + - 'row "4 + }" [ref=e3636]': + - cell [ref=e3637] [cursor=pointer] + - cell "4" [ref=e3638] [cursor=pointer] + - 'cell "+ }" [ref=e3639]': + - generic [ref=e3640]: "+ }" + - generic [ref=e3642]: + - generic [ref=e3643]: + - button "Comment thread" [expanded] [ref=e3644] [cursor=pointer]: + - img + - link "lib/core/services/notification_service.dart" [ref=e3646] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/files/610ee87712bfd0f063f722d6cadca2a5289430cb#diff-5c208823dc1ba76bc93934240d965eb00a4f4b509e8117bd93193e0f9d489b6b + - generic [ref=e3647]: + - generic [ref=e3649]: Comment on lines 26 to 28 + - table [ref=e3652]: + - rowgroup [ref=e3653]: + - row "26 26 await _plugin.initialize(" [ref=e3654]: + - cell "26" [ref=e3655] [cursor=pointer] + - cell "26" [ref=e3656] [cursor=pointer] + - cell "await _plugin.initialize(" [ref=e3657]: + - generic [ref=e3658]: await _plugin.initialize( + - 'row "27 - const InitializationSettings(android: androidSettings, iOS: iosSettings)," [ref=e3659]': + - cell "27" [ref=e3660] [cursor=pointer] + - cell [ref=e3661] [cursor=pointer] + - 'cell "- const InitializationSettings(android: androidSettings, iOS: iosSettings)," [ref=e3662]': + - generic [ref=e3663]: "- const InitializationSettings(android: androidSettings, iOS: iosSettings)," + - 'row "27 + settings: const InitializationSettings(android: androidSettings, iOS: iosSettings)," [ref=e3664]': + - cell [ref=e3665] [cursor=pointer] + - cell "27" [ref=e3666] [cursor=pointer] + - 'cell "+ settings: const InitializationSettings(android: androidSettings, iOS: iosSettings)," [ref=e3667]': + - generic [ref=e3668]: "+ settings: const InitializationSettings(android: androidSettings, iOS: iosSettings)," + - row "28 28 );" [ref=e3669]: + - cell "28" [ref=e3670] [cursor=pointer] + - cell "28" [ref=e3671] [cursor=pointer] + - cell ");" [ref=e3672]: + - generic [ref=e3673]: ); + - generic [ref=e3675]: + - generic [ref=e3676]: + - button "Comment thread" [expanded] [ref=e3677] [cursor=pointer]: + - img + - link "lib/core/services/notification_service.dart" [ref=e3679] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/files/610ee87712bfd0f063f722d6cadca2a5289430cb#diff-5c208823dc1ba76bc93934240d965eb00a4f4b509e8117bd93193e0f9d489b6b + - generic [ref=e3680]: + - generic [ref=e3682]: Comment on lines 78 to +83 + - table [ref=e3685]: + - rowgroup [ref=e3686]: + - row "78 78 await _plugin.zonedSchedule(" [ref=e3687]: + - cell "78" [ref=e3688] [cursor=pointer] + - cell "78" [ref=e3689] [cursor=pointer] + - cell "await _plugin.zonedSchedule(" [ref=e3690]: + - generic [ref=e3691]: await _plugin.zonedSchedule( + - row "79 - _idFor(taskId)," [ref=e3692]: + - cell "79" [ref=e3693] [cursor=pointer] + - cell [ref=e3694] [cursor=pointer] + - cell "- _idFor(taskId)," [ref=e3695]: + - generic [ref=e3696]: "- _idFor(taskId)," + - row "80 - 'Care Reminder'," [ref=e3697]: + - cell "80" [ref=e3698] [cursor=pointer] + - cell [ref=e3699] [cursor=pointer] + - cell "- 'Care Reminder'," [ref=e3700]: + - generic [ref=e3701]: "- 'Care Reminder'," + - row "81 - title," [ref=e3702]: + - cell "81" [ref=e3703] [cursor=pointer] + - cell [ref=e3704] [cursor=pointer] + - cell "- title," [ref=e3705]: + - generic [ref=e3706]: "- title," + - row "82 - scheduled," [ref=e3707]: + - cell "82" [ref=e3708] [cursor=pointer] + - cell [ref=e3709] [cursor=pointer] + - cell "- scheduled," [ref=e3710]: + - generic [ref=e3711]: "- scheduled," + - 'row "83 - NotificationDetails(android: androidDetails)," [ref=e3712]': + - cell "83" [ref=e3713] [cursor=pointer] + - cell [ref=e3714] [cursor=pointer] + - 'cell "- NotificationDetails(android: androidDetails)," [ref=e3715]': + - generic [ref=e3716]: "- NotificationDetails(android: androidDetails)," + - 'row "79 + id: _idFor(taskId)," [ref=e3717]': + - cell [ref=e3718] [cursor=pointer] + - cell "79" [ref=e3719] [cursor=pointer] + - 'cell "+ id: _idFor(taskId)," [ref=e3720]': + - generic [ref=e3721]: "+ id: _idFor(taskId)," + - 'row "80 + title: ''Care Reminder''," [ref=e3722]': + - cell [ref=e3723] [cursor=pointer] + - cell "80" [ref=e3724] [cursor=pointer] + - 'cell "+ title: ''Care Reminder''," [ref=e3725]': + - generic [ref=e3726]: "+ title: 'Care Reminder'," + - 'row "81 + body: title," [ref=e3727]': + - cell [ref=e3728] [cursor=pointer] + - cell "81" [ref=e3729] [cursor=pointer] + - 'cell "+ body: title," [ref=e3730]': + - generic [ref=e3731]: "+ body: title," + - 'row "82 + scheduledDate: scheduled," [ref=e3732]': + - cell [ref=e3733] [cursor=pointer] + - cell "82" [ref=e3734] [cursor=pointer] + - 'cell "+ scheduledDate: scheduled," [ref=e3735]': + - generic [ref=e3736]: "+ scheduledDate: scheduled," + - 'row "83 + notificationDetails: NotificationDetails(android: androidDetails)," [ref=e3737]': + - cell [ref=e3738] [cursor=pointer] + - cell "83" [ref=e3739] [cursor=pointer] + - 'cell "+ notificationDetails: NotificationDetails(android: androidDetails)," [ref=e3740]': + - generic [ref=e3741]: "+ notificationDetails: NotificationDetails(android: androidDetails)," + - generic [ref=e3743]: + - generic [ref=e3744]: + - button "Comment thread" [expanded] [ref=e3745] [cursor=pointer]: + - img + - link "lib/features/care/presentation/widgets/gamified_care_ui.dart" [ref=e3747] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/files/610ee87712bfd0f063f722d6cadca2a5289430cb#diff-8e2cf796cdb83ed78c034ccd2f1ab099667749421148c7f255df9b4f1317c508 + - generic [ref=e3748]: + - generic [ref=e3750]: Comment on lines +71 to +74 + - table [ref=e3753]: + - rowgroup [ref=e3754]: + - row "71 + final tasks = widget.dashboard.tasks.value ?? [];" [ref=e3755]: + - cell [ref=e3756] [cursor=pointer] + - cell "71" [ref=e3757] [cursor=pointer] + - cell "+ final tasks = widget.dashboard.tasks.value ?? [];" [ref=e3758]: + - generic [ref=e3759]: + final tasks = widget.dashboard.tasks.value ?? []; + - row "72 + final planned = tasks.where((t) => !t.isLogDerived).toList();" [ref=e3760]: + - cell [ref=e3761] [cursor=pointer] + - cell "72" [ref=e3762] [cursor=pointer] + - cell "+ final planned = tasks.where((t) => !t.isLogDerived).toList();" [ref=e3763]: + - generic [ref=e3764]: + final planned = tasks.where((t) => !t.isLogDerived).toList(); + - row "73 + final doneToday = planned.where((t) => t.isCompleted).length;" [ref=e3765]: + - cell [ref=e3766] [cursor=pointer] + - cell "73" [ref=e3767] [cursor=pointer] + - cell "+ final doneToday = planned.where((t) => t.isCompleted).length;" [ref=e3768]: + - generic [ref=e3769]: + final doneToday = planned.where((t) => t.isCompleted).length; + - row "74 + final totalToday = planned.length;" [ref=e3770]: + - cell [ref=e3771] [cursor=pointer] + - cell "74" [ref=e3772] [cursor=pointer] + - cell "+ final totalToday = planned.length;" [ref=e3773]: + - generic [ref=e3774]: + final totalToday = planned.length; + - generic [ref=e3778]: + - img [ref=e3780] + - generic [ref=e3785]: + - link "@afsan123" [ref=e3788] [cursor=pointer]: + - /url: /afsan123 + - img "@afsan123" [ref=e3789] + - code [ref=e3791]: + - link "up" [ref=e3792] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/dcea9d5a22080e5be1ac8acebb3cb764362f5b75 + - group [ref=e3796]: + - generic "2 / 2 checks OK" [ref=e3797] [cursor=pointer]: + - img "2 / 2 checks OK" [ref=e3798] + - code [ref=e3801]: + - link "dcea9d5" [ref=e3802] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/commits/dcea9d5a22080e5be1ac8acebb3cb764362f5b75 + - generic [ref=e3806]: + - link "Sign up for free" [ref=e3807] [cursor=pointer]: + - /url: /join?source=comment-repo + - strong [ref=e3808]: to join this conversation on GitHub + - text: . Already have an account? + - link "Sign in to comment" [ref=e3809] [cursor=pointer]: + - /url: /login?return_to=https%3A%2F%2Fgithub.com%2FCodeStorm-Hub%2Fpetfolio%2Fpull%2F17 + - generic [ref=e3813]: + - form "Select reviewers" [ref=e3815]: + - heading "Reviewers" [level=3] [ref=e3816] + - paragraph [ref=e3818]: + - generic [ref=e3819]: + - link "Copilot code review" [ref=e3820] [cursor=pointer]: + - /url: /apps/copilot-pull-request-reviewer + - generic [ref=e3821]: Copilot code review + - img [ref=e3823] + - link "Copilot" [ref=e3826] [cursor=pointer]: + - /url: /apps/copilot-pull-request-reviewer + - link "Copilot left review comments" [ref=e3827] [cursor=pointer]: + - /url: /CodeStorm-Hub/petfolio/pull/17/files/610ee87712bfd0f063f722d6cadca2a5289430cb + - img [ref=e3829] + - form "Select assignees" [ref=e3832]: + - heading "Assignees" [level=3] [ref=e3833] + - text: No one assigned + - generic [ref=e3834]: + - heading "Labels" [level=3] [ref=e3835] + - generic [ref=e3836]: None yet + - form "Select projects" [ref=e3838]: + - heading "Projects" [level=3] [ref=e3839] + - text: None yet + - form "Select milestones" [ref=e3841]: + - heading "Milestone" [level=3] [ref=e3842] + - text: No milestone + - form "Link issues" [ref=e3848]: + - heading "Development" [level=3] [ref=e3849] + - paragraph [ref=e3850]: Successfully merging this pull request may close these issues. + - paragraph [ref=e3852]: None yet + - generic [ref=e3854]: + - heading "3 participants" [level=3] [ref=e3855] + - generic [ref=e3856]: + - link "@syed-reza98" [ref=e3857] [cursor=pointer]: + - /url: /syed-reza98 + - img "@syed-reza98" [ref=e3858] + - link [ref=e3859] [cursor=pointer]: + - /url: /apps/copilot-pull-request-reviewer + - img [ref=e3861] + - link "@afsan123" [ref=e3864] [cursor=pointer]: + - /url: /afsan123 + - img "@afsan123" [ref=e3865] + - contentinfo [ref=e3866]: + - heading "Footer" [level=2] [ref=e3867] + - generic [ref=e3868]: + - generic [ref=e3869]: + - link "GitHub Homepage" [ref=e3870] [cursor=pointer]: + - /url: https://github.com + - img [ref=e3871] + - generic [ref=e3873]: © 2026 GitHub, Inc. + - navigation "Footer" [ref=e3874]: + - heading "Footer navigation" [level=3] [ref=e3875] + - list "Footer navigation" [ref=e3876]: + - listitem [ref=e3877]: + - link "Terms" [ref=e3878] [cursor=pointer]: + - /url: https://docs.github.com/site-policy/github-terms/github-terms-of-service + - listitem [ref=e3879]: + - link "Privacy" [ref=e3880] [cursor=pointer]: + - /url: https://docs.github.com/site-policy/privacy-policies/github-privacy-statement + - listitem [ref=e3881]: + - link "Security" [ref=e3882] [cursor=pointer]: + - /url: https://github.com/security + - listitem [ref=e3883]: + - link "Status" [ref=e3884] [cursor=pointer]: + - /url: https://www.githubstatus.com/ + - listitem [ref=e3885]: + - link "Community" [ref=e3886] [cursor=pointer]: + - /url: https://github.community/ + - listitem [ref=e3887]: + - link "Docs" [ref=e3888] [cursor=pointer]: + - /url: https://docs.github.com/ + - listitem [ref=e3889]: + - link "Contact" [ref=e3890] [cursor=pointer]: + - /url: https://support.github.com?tags=dotcom-footer + - listitem [ref=e3891]: + - button "Manage cookies" [ref=e3893] [cursor=pointer] + - listitem [ref=e3894]: + - button "Do not share my personal information" [ref=e3896] [cursor=pointer] \ No newline at end of file From 88572b04c73c13f7628ffe8aaa0bedb412eec683 Mon Sep 17 00:00:00 2001 From: Anam Chowdhury Date: Thu, 4 Jun 2026 07:28:59 -0400 Subject: [PATCH 21/23] fix(ci): add --prebuilt to Vercel deploy steps to skip rebuild Running npx vercel deploy from the repo root (needed so Vercel reads vercel.json for headers/rewrites) caused Vercel to attempt its own build rather than use the pre-built Flutter Web output in build/web/. --prebuilt instructs Vercel to skip the build phase and deploy the files found in outputDirectory (build/web) directly. Also consolidate VERCEL_ORG_ID/VERCEL_PROJECT_ID to job-level env block. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/deploy-web.yml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/.github/workflows/deploy-web.yml b/.github/workflows/deploy-web.yml index 131f7b1..cd54dff 100644 --- a/.github/workflows/deploy-web.yml +++ b/.github/workflows/deploy-web.yml @@ -10,6 +10,10 @@ jobs: build-and-deploy: runs-on: ubuntu-latest + env: + VERCEL_ORG_ID: team_lC8aTJK0XiU9qDfaHeTfCJs6 + VERCEL_PROJECT_ID: prj_hMHouLWimZvr5dDOlZeAhbH8xtop + steps: - name: Checkout uses: actions/checkout@v4 @@ -34,14 +38,8 @@ jobs: - name: Deploy preview to Vercel (PRs) if: github.event_name == 'pull_request' - run: npx vercel deploy --yes --token=${{ secrets.VERCEL_TOKEN }} - env: - VERCEL_ORG_ID: team_lC8aTJK0XiU9qDfaHeTfCJs6 - VERCEL_PROJECT_ID: prj_hMHouLWimZvr5dDOlZeAhbH8xtop + run: npx vercel deploy --prebuilt --yes --token=${{ secrets.VERCEL_TOKEN }} - name: Deploy to Vercel production (main only) if: github.event_name == 'push' && github.ref == 'refs/heads/main' - run: npx vercel deploy --prod --yes --token=${{ secrets.VERCEL_TOKEN }} - env: - VERCEL_ORG_ID: team_lC8aTJK0XiU9qDfaHeTfCJs6 - VERCEL_PROJECT_ID: prj_hMHouLWimZvr5dDOlZeAhbH8xtop + run: npx vercel deploy --prebuilt --prod --yes --token=${{ secrets.VERCEL_TOKEN }} From 1f350ff2ab12ccb51e6262273aec81cd632f75d5 Mon Sep 17 00:00:00 2001 From: Anam Chowdhury Date: Thu, 4 Jun 2026 07:32:59 -0400 Subject: [PATCH 22/23] fix(vercel): remove trailing comma left after COEP/COOP header removal Trailing comma after the last headers[] entry made vercel.json invalid JSON, causing the Vercel CLI to fail with "Couldn't parse JSON file". Co-Authored-By: Claude Sonnet 4.6 --- vercel.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/vercel.json b/vercel.json index 53af47e..2e08613 100644 --- a/vercel.json +++ b/vercel.json @@ -15,8 +15,7 @@ { "key": "Cross-Origin-Embedder-Policy", "value": "require-corp" }, { "key": "Cross-Origin-Opener-Policy", "value": "same-origin" } ] - }, - + } ], "rewrites": [ { "source": "/((?!.*\\.).*)", "destination": "/index.html" } From 91149407f0ed928cc6404565a5c070250cd07067 Mon Sep 17 00:00:00 2001 From: Anam Chowdhury Date: Thu, 4 Jun 2026 07:41:55 -0400 Subject: [PATCH 23/23] fix(ci): add vercel build step to generate .vercel/output before deploy --prebuilt requires .vercel/output (Vercel Build Output API format), not the raw build/web directory. Adding a 'npx vercel build' step packages the Flutter output into the expected format without re-running any build. Also add buildCommand:"" and framework:null to vercel.json so Vercel does not attempt framework detection or a rebuild during 'vercel build'. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/deploy-web.yml | 3 +++ vercel.json | 2 ++ 2 files changed, 5 insertions(+) diff --git a/.github/workflows/deploy-web.yml b/.github/workflows/deploy-web.yml index cd54dff..d5d3253 100644 --- a/.github/workflows/deploy-web.yml +++ b/.github/workflows/deploy-web.yml @@ -36,6 +36,9 @@ jobs: --dart-define=STRIPE_PUBLISHABLE_KEY=${{ secrets.STRIPE_PUBLISHABLE_KEY }} \ --dart-define=NVIDIA_API_KEY=${{ secrets.NVIDIA_API_KEY }} + - name: Package build output (vercel build) + run: npx vercel build --yes --token=${{ secrets.VERCEL_TOKEN }} + - name: Deploy preview to Vercel (PRs) if: github.event_name == 'pull_request' run: npx vercel deploy --prebuilt --yes --token=${{ secrets.VERCEL_TOKEN }} diff --git a/vercel.json b/vercel.json index 2e08613..d6cdbdf 100644 --- a/vercel.json +++ b/vercel.json @@ -1,5 +1,7 @@ { "outputDirectory": "build/web", + "buildCommand": "", + "framework": null, "headers": [ { "source": "/flutter_service_worker.js",