Skip family check when pathname starts with /admin to prevent redirect to onboarding Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
145 lines
No EOL
3.8 KiB
TypeScript
145 lines
No EOL
3.8 KiB
TypeScript
"use client";
|
|
|
|
import { useState, useEffect, createContext, useContext } from "react";
|
|
import { ReactNode } from "react";
|
|
import { useRouter } from "next/navigation";
|
|
|
|
interface Child {
|
|
id: string;
|
|
name: string;
|
|
birthDate: string;
|
|
sex: string;
|
|
}
|
|
|
|
interface FamilyContextType {
|
|
familyId: string | null;
|
|
familyName: string | null;
|
|
childId: string | null;
|
|
child: Child | null;
|
|
children: Child[];
|
|
loading: boolean;
|
|
tier: "free" | "pro";
|
|
memberCount: number;
|
|
}
|
|
|
|
const FamilyContext = createContext<FamilyContextType>({
|
|
familyId: null,
|
|
familyName: null,
|
|
childId: null,
|
|
child: null,
|
|
children: [],
|
|
loading: true,
|
|
tier: "free",
|
|
memberCount: 2,
|
|
});
|
|
|
|
export function useFamily() {
|
|
return useContext(FamilyContext);
|
|
}
|
|
|
|
export function FamilyProvider({ children: providerChildren }: { children: ReactNode }) {
|
|
const router = useRouter();
|
|
const [familyId, setFamilyId] = useState<string | null>(null);
|
|
const [familyName, setFamilyName] = useState<string | null>(null);
|
|
const [childId, setChildId] = useState<string | null>(null);
|
|
const [child, setChild] = useState<Child | null>(null);
|
|
const [children, setChildren] = useState<Child[]>([]);
|
|
const [loading, setLoading] = useState(true);
|
|
const [tier, setTier] = useState<"free" | "pro">("free");
|
|
const [memberCount, setMemberCount] = useState(2);
|
|
|
|
useEffect(() => {
|
|
// Skip family check for admin pages
|
|
if (typeof window !== "undefined" && window.location.pathname.startsWith("/admin")) {
|
|
setLoading(false);
|
|
return;
|
|
}
|
|
|
|
async function fetchFamilyData() {
|
|
try {
|
|
// Get current session from database
|
|
const sessionRes = await fetch("/api/auth/signin");
|
|
const sessionData = await sessionRes.json();
|
|
|
|
// Not authenticated - stay on current page, don't redirect
|
|
if (!sessionData.authenticated) {
|
|
setLoading(false);
|
|
return;
|
|
}
|
|
|
|
// Authenticated but no family - go to onboarding
|
|
if (!sessionData.familyId) {
|
|
router.push("/onboarding");
|
|
setLoading(false);
|
|
return;
|
|
}
|
|
|
|
// Authenticated with family - check for children
|
|
const familyId = sessionData.familyId;
|
|
const res = await fetch(`/api/children?familyId=${familyId}`);
|
|
const data = await res.json();
|
|
|
|
// Handle API error
|
|
if (!res.ok || data.error) {
|
|
console.error("Failed to fetch children:", data.error);
|
|
setLoading(false);
|
|
return;
|
|
}
|
|
|
|
if (data.children?.length > 0) {
|
|
const childList = data.children.map((c: any) => ({
|
|
id: c.id,
|
|
name: c.name,
|
|
birthDate: c.birthDate,
|
|
sex: c.sex,
|
|
}));
|
|
|
|
setChildren(childList);
|
|
setChild(childList[0]);
|
|
setChildId(childList[0].id);
|
|
} else {
|
|
// No children - go to onboarding
|
|
router.push("/onboarding");
|
|
setLoading(false);
|
|
return;
|
|
}
|
|
|
|
setFamilyId(familyId);
|
|
setFamilyName(sessionData.familyName || "My Family");
|
|
setTier(sessionData.tier || "free");
|
|
|
|
// Fetch actual member count
|
|
try {
|
|
const membersRes = await fetch(`/api/family/members?familyId=${familyId}`);
|
|
const membersData = await membersRes.json();
|
|
setMemberCount(membersData.members?.length || 2);
|
|
} catch {
|
|
setMemberCount(2);
|
|
}
|
|
} catch (err) {
|
|
console.error("Failed to fetch family:", err);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}
|
|
|
|
fetchFamilyData();
|
|
}, [router]);
|
|
|
|
return (
|
|
<FamilyContext.Provider
|
|
value={{
|
|
familyId,
|
|
familyName,
|
|
childId,
|
|
child,
|
|
children,
|
|
loading,
|
|
tier,
|
|
memberCount,
|
|
}}
|
|
>
|
|
{providerChildren}
|
|
</FamilyContext.Provider>
|
|
);
|
|
} |