"use client"; import React, { useState, useEffect } from "react"; import Link from "next/link"; import Header from "@/components/Header"; import Footer from "@/components/Footer"; import AppImage from "@/components/ui/AppImage"; import { createClient } from "@/lib/supabase/client"; import { useRouter } from "next/navigation"; interface UserProfile { id: string; email: string; full_name: string; avatar_url: string | null; bio: string | null; website: string | null; location: string | null; reputation: number; created_at: string; } interface BookmarkItem { id: string; article_slug: string; article_title: string; article_excerpt: string | null; article_image: string | null; article_image_alt: string | null; article_category: string | null; article_author: string | null; article_read_time: string | null; article_date: string | null; saved_at: string; } interface HistoryItem { id: string; article_slug: string; article_title: string; article_excerpt: string | null; article_image: string | null; article_image_alt: string | null; article_category: string | null; article_author: string | null; article_read_time: string | null; article_date: string | null; viewed_at: string; } interface TopicPref { id: string; topic: string; view_count: number; last_viewed_at: string; } type ActiveTab = "profile" | "security" | "bookmarks" | "history" | "topics" | "preferences"; export default function AccountPage() { const router = useRouter(); const supabase = createClient(); const [user, setUser] = useState(null); const [profile, setProfile] = useState(null); const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); const [activeTab, setActiveTab] = useState("profile"); const [toast, setToast] = useState<{ message: string; type: "success" | "error" } | null>(null); // Profile form state const [fullName, setFullName] = useState(""); const [bio, setBio] = useState(""); const [website, setWebsite] = useState(""); const [location, setLocation] = useState(""); // Security form state const [newPassword, setNewPassword] = useState(""); const [confirmPassword, setConfirmPassword] = useState(""); const [changingPassword, setChangingPassword] = useState(false); // Digest preference state const [weeklyDigest, setWeeklyDigest] = useState(false); const [savingDigest, setSavingDigest] = useState(false); // Bookmarks const [bookmarks, setBookmarks] = useState([]); const [bookmarksLoading, setBookmarksLoading] = useState(false); // Reading History const [history, setHistory] = useState([]); const [historyLoading, setHistoryLoading] = useState(false); // Topic Preferences const [topics, setTopics] = useState([]); const [topicsLoading, setTopicsLoading] = useState(false); const showToast = (message: string, type: "success" | "error") => { setToast({ message, type }); setTimeout(() => setToast(null), 3500); }; useEffect(() => { const init = async () => { const { data: { user: authUser } } = await supabase.auth.getUser(); if (!authUser) { router.push("/login"); return; } setUser(authUser); const { data: profileData } = await supabase .from("user_profiles") .select("*") .eq("id", authUser.id) .maybeSingle(); if (profileData) { setProfile(profileData); setFullName(profileData.full_name || ""); setBio(profileData.bio || ""); setWebsite(profileData.website || ""); setLocation(profileData.location || ""); } setLoading(false); }; init(); }, []); useEffect(() => { if (!user) return; fetch("/api/digest/preferences") .then((r) => r.json()) .then((d) => setWeeklyDigest(d.weekly_digest_enabled ?? false)) .catch(() => {}); }, [user]); // Load bookmarks when tab is active useEffect(() => { if (activeTab !== "bookmarks" || !user) return; setBookmarksLoading(true); supabase .from("reading_list") .select("*") .eq("user_id", user.id) .order("saved_at", { ascending: false }) .then(({ data }) => { setBookmarks(data || []); setBookmarksLoading(false); }); }, [activeTab, user]); // Load reading history when tab is active useEffect(() => { if (activeTab !== "history" || !user) return; setHistoryLoading(true); supabase .from("reading_history") .select("*") .eq("user_id", user.id) .order("viewed_at", { ascending: false }) .limit(50) .then(({ data }) => { setHistory(data || []); setHistoryLoading(false); }); }, [activeTab, user]); // Load topic preferences when tab is active useEffect(() => { if (activeTab !== "topics" || !user) return; setTopicsLoading(true); supabase .from("user_topic_preferences") .select("*") .eq("user_id", user.id) .order("view_count", { ascending: false }) .then(({ data }) => { setTopics(data || []); setTopicsLoading(false); }); }, [activeTab, user]); const handleSaveProfile = async (e: React.FormEvent) => { e.preventDefault(); if (!user) return; setSaving(true); try { const { error } = await supabase .from("user_profiles") .upsert({ id: user.id, email: user.email, full_name: fullName, bio, website, location, }); if (error) throw error; showToast("Profile updated successfully", "success"); } catch (err: any) { showToast(err?.message || "Failed to update profile", "error"); } finally { setSaving(false); } }; const handleChangePassword = async (e: React.FormEvent) => { e.preventDefault(); if (newPassword !== confirmPassword) { showToast("Passwords do not match", "error"); return; } if (newPassword.length < 6) { showToast("Password must be at least 6 characters", "error"); return; } setChangingPassword(true); try { const { error } = await supabase.auth.updateUser({ password: newPassword }); if (error) throw error; setNewPassword(""); setConfirmPassword(""); showToast("Password updated successfully", "success"); } catch (err: any) { showToast(err?.message || "Failed to update password", "error"); } finally { setChangingPassword(false); } }; const handleSignOut = async () => { await supabase.auth.signOut(); router.push("/home-page"); }; const handleToggleDigest = async (enabled: boolean) => { setSavingDigest(true); try { const res = await fetch("/api/digest/preferences", { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ weekly_digest_enabled: enabled }), }); if (!res.ok) throw new Error("Failed to update"); setWeeklyDigest(enabled); showToast(enabled ? "Weekly digest enabled" : "Weekly digest disabled", "success"); } catch { showToast("Failed to update digest preference", "error"); } finally { setSavingDigest(false); } }; const handleRemoveBookmark = async (id: string, slug: string) => { if (!user) return; try { await supabase.from("reading_list").delete().eq("id", id).eq("user_id", user.id); setBookmarks((prev) => prev.filter((b) => b.id !== id)); showToast("Bookmark removed", "success"); } catch { showToast("Failed to remove bookmark", "error"); } }; const handleClearHistory = async () => { if (!user) return; try { await supabase.from("reading_history").delete().eq("user_id", user.id); setHistory([]); showToast("Reading history cleared", "success"); } catch { showToast("Failed to clear history", "error"); } }; const tabs: { id: ActiveTab; label: string }[] = [ { id: "profile", label: "Profile" }, { id: "security", label: "Security" }, { id: "bookmarks", label: "Bookmarks" }, { id: "history", label: "History" }, { id: "topics", label: "Topics" }, { id: "preferences", label: "Preferences" }, ]; if (loading) { return (
); } return (
{/* Toast */} {toast && (
{toast.type === "success" ? ( ) : ( )} {toast.message}
)} {/* Breadcrumb */}
{/* Page Header */}

Account Settings

{user?.email}

{/* Tabs */}
{tabs.map((tab) => ( ))}
{/* Profile Tab */} {activeTab === "profile" && (

Public Profile

setFullName(e.target.value)} placeholder="Your full name" className="w-full bg-[#1c1815] border border-[#3a322b] text-[#e0e0e0] font-body text-sm px-3 py-2.5 rounded-sm focus:outline-none focus:border-[#F0A623] focus:ring-1 focus:ring-[#F0A623] transition-colors placeholder-[#444]" />