fix(native): useUserPlan derive from useMe (was a stale module cache)

useUserPlan had its own module-level cache + fetch-once-on-mount, separate
from useMe's invalidateMe(). So the __DEV__ tier-override toggle (which calls
invalidateMe()) never reached useUserPlan consumers → the app didn't react to
a plan switch. Now useUserPlan just reads me.plan from useMe → inherits its
live-invalidation, the toggle propagates everywhere.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
chahinebrini 2026-05-11 15:18:59 +02:00
parent 790b5e5c24
commit f6852be760

View File

@ -1,43 +1,18 @@
import { useEffect, useState } from "react";
import { apiFetch } from "../lib/api";
import { useMe } from "./useMe";
import type { Plan } from "./useMe";
export type Plan = "free" | "pro" | "legend";
type MeResponse = {
id: string;
email: string;
username: string;
plan: Plan;
};
let cachedPlan: Plan | null = null;
export type { Plan };
/**
* Holt den User-Plan vom Backend (/api/auth/me).
* Plan wird in DB gespeichert (nicht in user_metadata) daher BFF-Call nötig.
* Plan des eingeloggten Users abgeleitet aus useMe() (single source of truth,
* inkl. Live-Invalidierung via invalidateMe()).
*
* Vorher hatte useUserPlan einen eigenen Modul-Cache + fetch-once-on-mount
* das war ein Bug: der __DEV__-Tier-Toggle (ruft invalidateMe() auf) erreichte
* die useUserPlan-Consumer NICHT, also reagierte die App nicht auf den Plan-Wechsel.
* Jetzt erbt useUserPlan die Invalidierung von useMe Toggle propagiert überall.
*/
export function useUserPlan(): { plan: Plan; loading: boolean } {
const [plan, setPlan] = useState<Plan>(cachedPlan ?? "free");
const [loading, setLoading] = useState(cachedPlan === null);
useEffect(() => {
let cancelled = false;
(async () => {
try {
const res = await apiFetch<MeResponse>("/api/auth/me");
if (cancelled) return;
cachedPlan = res.plan ?? "free";
setPlan(cachedPlan);
} catch (e) {
console.warn("[useUserPlan] failed:", e);
} finally {
if (!cancelled) setLoading(false);
}
})();
return () => {
cancelled = true;
};
}, []);
return { plan, loading };
const { me, loading } = useMe();
return { plan: me?.plan ?? "free", loading };
}