feat: home nudge for existing users with no phone number
Existing users (signed up before phone collection) won't have a number. Show a dismissable home banner prompting them to add one. - Checks /api/auth/profile on load; shows banner only if user.phone is empty - "Add" links to /profile; ✕ dismisses - Dismissal remembered in localStorage (tia_phone_nudge_dismissed) so it never nags repeatedly - Dark-mode styled, sits below the vaccine reminder banner Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
38bb5af01c
commit
0f3e87b67a
1 changed files with 42 additions and 0 deletions
|
|
@ -99,6 +99,7 @@ export default function HomePage() {
|
||||||
const [recentLogs, setRecentLogs] = useState<Log[]>([]);
|
const [recentLogs, setRecentLogs] = useState<Log[]>([]);
|
||||||
const [logsLoading, setLogsLoading] = useState(true);
|
const [logsLoading, setLogsLoading] = useState(true);
|
||||||
const [vaccineReminders, setVaccineReminders] = useState<any[]>([]);
|
const [vaccineReminders, setVaccineReminders] = useState<any[]>([]);
|
||||||
|
const [showPhoneNudge, setShowPhoneNudge] = useState(false);
|
||||||
const [aiChips, setAiChips] = useState<string[]>([]);
|
const [aiChips, setAiChips] = useState<string[]>([]);
|
||||||
const [uploadingPhoto, setUploadingPhoto] = useState(false);
|
const [uploadingPhoto, setUploadingPhoto] = useState(false);
|
||||||
const [photoError, setPhotoError] = useState(false);
|
const [photoError, setPhotoError] = useState(false);
|
||||||
|
|
@ -134,6 +135,24 @@ export default function HomePage() {
|
||||||
return () => window.removeEventListener("online", handleOnline);
|
return () => window.removeEventListener("online", handleOnline);
|
||||||
}, [childId]);
|
}, [childId]);
|
||||||
|
|
||||||
|
// One-time nudge for existing users who have no phone number on file.
|
||||||
|
// Dismissable; remembered in localStorage so it never nags repeatedly.
|
||||||
|
useEffect(() => {
|
||||||
|
if (!childId) return;
|
||||||
|
if (localStorage.getItem("tia_phone_nudge_dismissed") === "1") return;
|
||||||
|
fetch("/api/auth/profile")
|
||||||
|
.then(r => r.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.user && !data.user.phone) setShowPhoneNudge(true);
|
||||||
|
})
|
||||||
|
.catch(() => {});
|
||||||
|
}, [childId]);
|
||||||
|
|
||||||
|
const dismissPhoneNudge = () => {
|
||||||
|
setShowPhoneNudge(false);
|
||||||
|
localStorage.setItem("tia_phone_nudge_dismissed", "1");
|
||||||
|
};
|
||||||
|
|
||||||
const fetchRecentLogs = async () => {
|
const fetchRecentLogs = async () => {
|
||||||
if (!childId) return;
|
if (!childId) return;
|
||||||
try {
|
try {
|
||||||
|
|
@ -413,6 +432,29 @@ export default function HomePage() {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{showPhoneNudge && (
|
||||||
|
<div className="mx-4 mb-4 bg-rose-50 dark:bg-rose-900/20 border border-rose-200 dark:border-rose-800/40 px-4 py-3 rounded-xl flex items-center gap-3">
|
||||||
|
<span className="text-xl flex-shrink-0">📱</span>
|
||||||
|
<div className="flex-1 min-w-0">
|
||||||
|
<div className="font-semibold text-rose-700 dark:text-rose-300 text-sm">Add your phone number</div>
|
||||||
|
<div className="text-xs text-rose-600 dark:text-rose-400">Get important reminders & updates about your baby</div>
|
||||||
|
</div>
|
||||||
|
<Link
|
||||||
|
href="/profile"
|
||||||
|
className="flex-shrink-0 text-xs font-semibold text-white bg-rose-400 px-3 py-1.5 rounded-lg active:scale-95 transition-transform"
|
||||||
|
>
|
||||||
|
Add
|
||||||
|
</Link>
|
||||||
|
<button
|
||||||
|
onClick={dismissPhoneNudge}
|
||||||
|
className="flex-shrink-0 text-rose-300 dark:text-rose-500 text-lg leading-none px-1"
|
||||||
|
aria-label="Dismiss"
|
||||||
|
>
|
||||||
|
✕
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<TodaySummary logs={recentLogs} />
|
<TodaySummary logs={recentLogs} />
|
||||||
|
|
||||||
{stage && (() => {
|
{stage && (() => {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue