Spaces:
Running
Running
| "use client"; | |
| import { useEffect, useState } from "react"; | |
| import { | |
| getStoredPlayer, | |
| storePlayer, | |
| type StoredPlayer, | |
| } from "@/lib/player-store"; | |
| import { isSupabaseConfigured } from "@/lib/supabase/client"; | |
| import { getOrCreatePlayer, recordPlayerVisit } from "@/lib/supabase/queries"; | |
| /** | |
| * Hook that ensures the locally-stored player has a real Supabase UUID. | |
| * | |
| * On mount it reads the player from localStorage. If the player exists but | |
| * has an empty `id` and Supabase is configured, it calls | |
| * `getOrCreatePlayer(anonymousId, displayName)` and updates localStorage | |
| * with the returned UUID. | |
| * | |
| * @returns `{ player, isLoading }` -- player may be null if none is stored, | |
| * and isLoading is true while the Supabase sync is in-flight. | |
| */ | |
| export function usePlayerSync(): { | |
| player: StoredPlayer | null; | |
| isLoading: boolean; | |
| } { | |
| const [player, setPlayer] = useState<StoredPlayer | null>(null); | |
| const [isLoading, setIsLoading] = useState(true); | |
| useEffect(() => { | |
| let cancelled = false; | |
| async function sync() { | |
| const stored = getStoredPlayer(); | |
| if (!stored) { | |
| setIsLoading(false); | |
| return; | |
| } | |
| setPlayer(stored); | |
| // Always verify player exists in DB -- heals stale/reset UUIDs in localStorage | |
| if (!isSupabaseConfigured) { | |
| setIsLoading(false); | |
| return; | |
| } | |
| try { | |
| const dbPlayer = await getOrCreatePlayer( | |
| stored.anonymousId, | |
| stored.displayName | |
| ); | |
| if (cancelled) return; | |
| if (dbPlayer) { | |
| const synced: StoredPlayer = { | |
| ...stored, | |
| id: dbPlayer.id, | |
| }; | |
| storePlayer(synced); | |
| setPlayer(synced); | |
| // Record this session visit in the background | |
| recordPlayerVisit(dbPlayer.id).catch(() => {}); | |
| } | |
| } catch (err) { | |
| console.error("[usePlayerSync] failed to sync player:", err); | |
| } finally { | |
| if (!cancelled) { | |
| setIsLoading(false); | |
| } | |
| } | |
| } | |
| sync(); | |
| return () => { | |
| cancelled = true; | |
| }; | |
| }, []); | |
| return { player, isLoading }; | |
| } | |