import { useContext, useEffect, useRef, useState } from "react"; import { changePassword, getCurrentUser, updateCurrentUser } from "../api/users"; import { SettingsContext } from "../context/SettingsContext"; import useActionToast from "../hooks/useActionToast"; import getApiErrorMessage from "../lib/getApiErrorMessage"; import "../styles/pages/Settings.css"; export default function Settings() { const { settings, updateSettings, resetSettings } = useContext(SettingsContext); const toast = useActionToast(); const [activeTab, setActiveTab] = useState("appearance"); const tabsRef = useRef(null); const [showLeftArrow, setShowLeftArrow] = useState(false); const [showRightArrow, setShowRightArrow] = useState(false); // Account management state const [displayName, setDisplayName] = useState(""); const [currentPassword, setCurrentPassword] = useState(""); const [newPassword, setNewPassword] = useState(""); const [confirmPassword, setConfirmPassword] = useState(""); const [accountMessage, setAccountMessage] = useState({ type: "", text: "" }); const [loadingProfile, setLoadingProfile] = useState(false); const [loadingPassword, setLoadingPassword] = useState(false); // Load user profile useEffect(() => { const loadProfile = async () => { try { const response = await getCurrentUser(); setDisplayName(response.data.display_name || response.data.name || ""); } catch (error) { console.error("Failed to load profile:", error); } }; loadProfile(); }, []); useEffect(() => { const tabsElement = tabsRef.current; if (!tabsElement) return; const updateArrowVisibility = () => { const hasOverflow = tabsElement.scrollWidth > tabsElement.clientWidth + 1; if (!hasOverflow) { setShowLeftArrow(false); setShowRightArrow(false); return; } setShowLeftArrow(tabsElement.scrollLeft > 4); setShowRightArrow( tabsElement.scrollLeft + tabsElement.clientWidth < tabsElement.scrollWidth - 4 ); }; updateArrowVisibility(); tabsElement.addEventListener("scroll", updateArrowVisibility, { passive: true }); window.addEventListener("resize", updateArrowVisibility); return () => { tabsElement.removeEventListener("scroll", updateArrowVisibility); window.removeEventListener("resize", updateArrowVisibility); }; }, []); const handleThemeChange = (theme) => { updateSettings({ theme }); }; const handleUpdateDisplayName = async (e) => { e.preventDefault(); setLoadingProfile(true); setAccountMessage({ type: "", text: "" }); try { await updateCurrentUser(displayName); setAccountMessage({ type: "success", text: "Display name updated successfully!" }); toast.success("Updated display name", `Updated display name to ${displayName}`); } catch (error) { const message = getApiErrorMessage(error, "Failed to update display name"); setAccountMessage({ type: "error", text: message }); toast.error("Update display name failed", `Update display name failed: ${message}`); } finally { setLoadingProfile(false); } }; const handleChangePassword = async (e) => { e.preventDefault(); setLoadingPassword(true); setAccountMessage({ type: "", text: "" }); if (newPassword !== confirmPassword) { setAccountMessage({ type: "error", text: "New passwords don't match" }); setLoadingPassword(false); return; } if (newPassword.length < 6) { setAccountMessage({ type: "error", text: "Password must be at least 6 characters" }); setLoadingPassword(false); return; } try { await changePassword(currentPassword, newPassword); setAccountMessage({ type: "success", text: "Password changed successfully!" }); toast.success("Changed password", "Changed password successfully"); setCurrentPassword(""); setNewPassword(""); setConfirmPassword(""); } catch (error) { const message = getApiErrorMessage(error, "Failed to change password"); setAccountMessage({ type: "error", text: message }); toast.error("Change password failed", `Change password failed: ${message}`); } finally { setLoadingPassword(false); } }; const handleToggle = (key) => { updateSettings({ [key]: !settings[key] }); }; const handleNumberChange = (key, value) => { updateSettings({ [key]: parseInt(value, 10) }); }; const handleReset = () => { if (window.confirm("Reset all settings to defaults?")) { resetSettings(); } }; return (

Settings

{/* Appearance Tab */} {activeTab === "appearance" && (

Appearance

Auto mode follows your system preferences

Show more items on screen with reduced spacing

)} {/* List Display Tab */} {activeTab === "list" && (

List Display

Display items bought in the last 24 hours

{settings.showRecentlyBought && ( <>
handleNumberChange("recentlyBoughtCount", e.target.value)} className="settings-range" />

Number of items to show initially (5-50)

Start with the section collapsed

)}
)} {/* Behavior Tab */} {activeTab === "behavior" && (

Behavior

Show confirmation modal when marking items as bought

handleNumberChange("autoReloadInterval", e.target.value)} className="settings-range" />

Automatically refresh the list every X minutes (0 = disabled)

Vibrate on long-press and other interactions

)} {/* Account Tab */} {activeTab === "account" && (

Account Management

{accountMessage.text && (
{accountMessage.text}
)} {/* Display Name Section */}

Display Name

setDisplayName(e.target.value)} maxLength={100} className="form-input" placeholder="Your display name" />

{displayName.length}/100 characters


{/* Password Change Section */}

Change Password

setCurrentPassword(e.target.value)} className="form-input" required />
setNewPassword(e.target.value)} className="form-input" minLength={6} required />

Minimum 6 characters

setConfirmPassword(e.target.value)} className="form-input" minLength={6} required />
)}
); }