import { useState, useEffect, ChangeEvent, CSSProperties, ReactNode } from "react"; import { useNavigate } from "react-router-dom"; import { useAuth } from "../../lib/authContext"; import { getApiBaseUrl } from "../../lib/api/config"; // ── Types ───────────────────────────────────────────────────────────────────── type StatusType = "success" | "error" | "loading"; interface Status { text: string; type: StatusType; } interface StudentProfileForm { birthDate: string; birthTime: string; country: string; gender: string; phone: string; quranLevel: string; preferredLanguage: string; preferredAccent: string; profilePhotoUrl: string; } interface StudentProfileBody { birthDateTime: string; country: string; gender: string; phone: string | null; quranLevel: string | null; preferredLanguage: string | null; preferredAccent: string | null; profilePhotoUrl: string | null; } interface FormGroupProps { label: string; required?: boolean; children: ReactNode; } // ── Constants ───────────────────────────────────────────────────────────────── const BACKEND_URL = `${getApiBaseUrl()}/api/auth/complete-google-profile`; const COUNTRIES: string[] = [ "Egypt", "Saudi Arabia", "UAE", "Jordan", "Kuwait", "Qatar", "Bahrain", "Oman", "Libya", "Tunisia", "Morocco", "Algeria", "Sudan", "Other", ]; const STATUS_COLORS: Record = { success: { bg: "#d4edda", color: "#155724" }, error: { bg: "#f8d7da", color: "#721c24" }, loading: { bg: "#fff3cd", color: "#856404" }, }; // ── Sub-component ───────────────────────────────────────────────────────────── function FormGroup({ label, required = false, children }: FormGroupProps) { return (
{children}
); } // ── Component ───────────────────────────────────────────────────────────────── export default function CompleteStudentProfile() { const navigate = useNavigate(); const { updateProfile } = useAuth(); const [hasToken, setHasToken] = useState(true); const [loading, setLoading] = useState(false); const [status, setStatus] = useState(null); const [response, setResponse] = useState(null); const [form, setForm] = useState({ birthDate: "", birthTime: "00:00", country: "", gender: "", phone: "", quranLevel: "", preferredLanguage: "", preferredAccent: "", profilePhotoUrl: "", }); useEffect(() => { setHasToken(!!localStorage.getItem("authToken")); }, []); function handleChange(e: ChangeEvent): void { const { id, value } = e.target; setForm((prev) => ({ ...prev, [id]: value })); } async function submitProfile(): Promise { const jwt = localStorage.getItem("authToken"); if (!jwt) { setStatus({ text: "❌ No authentication token found. Please sign in first.", type: "error" }); return; } if (!form.birthDate){ setStatus({ text: "❌ Birth date is required", type: "error" }); return; } if (!form.country) { setStatus({ text: "❌ Country is required", type: "error" }); return; } if (!form.gender) { setStatus({ text: "❌ Gender is required", type: "error" }); return; } const birthDateTime = `${form.birthDate}T${form.birthTime || "00:00"}:00`; const body: StudentProfileBody = { birthDateTime, country: form.country, gender: form.gender, phone: form.phone || null, quranLevel: form.quranLevel || null, preferredLanguage: form.preferredLanguage || null, preferredAccent: form.preferredAccent || null, profilePhotoUrl: form.profilePhotoUrl || null, }; setLoading(true); setStatus({ text: "⏳ Saving profile...", type: "loading" }); try { const res = await fetch(BACKEND_URL, { method: "POST", headers: { "Content-Type": "application/json", Authorization: "Bearer " + jwt }, body: JSON.stringify(body), }); const text = await res.text(); setResponse(text); if (res.ok) { setStatus({ text: "✅ Profile completed successfully!", type: "success" }); updateProfile({ profileCompleted: true }); setTimeout(() => navigate("/student/dashboard", { replace: true }), 1000); } else { setStatus({ text: "❌ Error: " + text, type: "error" }); setLoading(false); } } catch (err: unknown) { const message = err instanceof Error ? err.message : "Unknown error"; setStatus({ text: "❌ Failed: " + message, type: "error" }); setLoading(false); } } return (
{/* Header */}
🎓

Complete Student Profile

Fill in the remaining details to get started

STUDENT
{/* No token warning */} {!hasToken && (
⚠️ No JWT found. Please{" "} sign in with Google first.
)} {/* Personal Info */}
👤 Personal Information
{/* Quran Profile */}
📖 Quran Profile
{status && (
{status.text}
)}
); } // ── Styles ──────────────────────────────────────────────────────────────────── const styles: Record = { page: { fontFamily: "'Segoe UI', sans-serif", background: "#f0f4f8", minHeight: "100vh", display: "flex", alignItems: "center", justifyContent: "center", padding: "40px 20px" }, container: { background: "white", borderRadius: 16, padding: 40, width: 600, boxShadow: "0 4px 24px rgba(0,0,0,0.10)" }, header: { textAlign: "center", marginBottom: 32 }, icon: { fontSize: 48, marginBottom: 12 }, h1: { color: "#1a6b3c", fontSize: 24, marginBottom: 6 }, subtitle: { color: "#777", fontSize: 14 }, roleBadgeStudent: { display: "inline-block", background: "#e8f5e9", color: "#1a6b3c", padding: "4px 12px", borderRadius: 20, fontSize: 12, fontWeight: 700, marginBottom: 16 }, warning: { background: "#fff3cd", border: "1px solid #ffc107", borderRadius: 8, padding: "12px 16px", fontSize: 13, color: "#856404", marginBottom: 20 }, link: { color: "#1a6b3c", fontWeight: 600 }, sectionTitle: { fontSize: 13, fontWeight: 700, color: "#1a6b3c", textTransform: "uppercase", letterSpacing: 1, margin: "24px 0 12px", paddingBottom: 6, borderBottom: "2px solid #e8f5e9" }, formRow: { display: "flex", gap: 16 }, label: { display: "block", fontSize: 13, fontWeight: 600, color: "#444", marginBottom: 6 }, input: { width: "100%", padding: "11px 14px", border: "1.5px solid #ddd", borderRadius: 8, fontSize: 14, color: "#333", outline: "none", background: "white", fontFamily: "inherit", boxSizing: "border-box" }, submitBtn: { width: "100%", padding: 14, background: "#1a6b3c", color: "white", border: "none", borderRadius: 10, fontSize: 16, fontWeight: 600, cursor: "pointer", marginTop: 24 }, submitBtnDisabled: { background: "#aaa", cursor: "not-allowed" }, statusBadge: { padding: "12px 16px", borderRadius: 8, fontSize: 14, fontWeight: 500, marginTop: 16, textAlign: "center" }, responseBox: { background: "#1e1e1e", borderRadius: 10, padding: 16, marginTop: 16 }, responseTitle: { color: "#4ec9b0", fontSize: 12, marginBottom: 8, textTransform: "uppercase" }, responsePre: { color: "#d4d4d4", fontSize: 12, fontFamily: "'Courier New', monospace", whiteSpace: "pre-wrap", wordBreak: "break-all" }, };