DocDoeAI / src /lib /api /study-profile.ts
asnannp's picture
deploy: sync backend to Space root (learn-lesson HF cache fix)
65d68f5
Raw History Blame Contribute Delete
2.08 kB
import { apiGet, apiPost } from "@/lib/api/client";
import { hasLiveSession } from "@/lib/api/mode";
/**
* Backend persistence for the onboarding study profile.
*
* Matches the tuition-profile.ts pattern: localStorage stays the offline
* source of truth; the backend is the durable per-user copy that survives a
* device change. Both helpers are best-effort and no-op when the student is
* not logged in (preview/demo/anonymous), so they never 401-spam anonymous
* visitors.
*/
export type StudyProfileRemote = {
id: string;
user_id: string;
exam: string | null;
board: string | null;
grade: string | null;
subject: string | null;
chapter: string | null;
topic: string | null;
level: string | null;
goal: string | null;
time_left: string | null;
language_preference: string | null;
primary_need: string | null;
weak_areas: string[];
selected_plan: string | null;
trial_started: boolean;
onboarding_completed: boolean;
extra: Record<string, unknown>;
created_at: string;
updated_at: string;
};
export type StudyProfileInput = Partial<
Pick<
StudyProfileRemote,
| "exam"
| "board"
| "grade"
| "subject"
| "chapter"
| "topic"
| "level"
| "goal"
| "time_left"
| "language_preference"
| "primary_need"
| "weak_areas"
| "selected_plan"
| "trial_started"
| "onboarding_completed"
| "extra"
>
>;
/** Returns true when the profile was persisted to the backend. */
export async function saveStudyProfileRemote(input: StudyProfileInput): Promise<boolean> {
if (!hasLiveSession()) return false;
try {
await apiPost<StudyProfileRemote, StudyProfileInput>("/study-profile", input);
return true;
} catch {
return false;
}
}
/** Returns the saved study profile, or null (404/no session/failure). */
export async function getStudyProfileRemote(): Promise<StudyProfileRemote | null> {
if (!hasLiveSession()) return null;
try {
return await apiGet<StudyProfileRemote | null>("/study-profile/me?optional=true");
} catch {
return null;
}
}