"use client"; import { useEffect, useState } from "react"; import { useRouter } from "next/navigation"; interface Profile { id: string; slug: string; display_name: string; bio: string | null; avatar_url: string | null; is_public: boolean; } interface Product { id: string; title: string; description: string | null; url: string; image_url: string | null; category: string; display_order: number; click_count: number; } const CATEGORIES = ["general", "feeding", "sleep", "play", "clothing"] as const; const CATEGORY_EMOJI: Record = { feeding: "๐Ÿผ", sleep: "๐Ÿ’ค", play: "๐ŸŽฎ", clothing: "๐Ÿ‘—", general: "๐Ÿ›๏ธ" }; export default function ProfileSettingsPage() { const router = useRouter(); const [profile, setProfile] = useState(null); const [products, setProducts] = useState([]); const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); const [saveMsg, setSaveMsg] = useState(""); const [slug, setSlug] = useState(""); const [displayName, setDisplayName] = useState(""); const [bio, setBio] = useState(""); const [isPublic, setIsPublic] = useState(false); const [showAddProduct, setShowAddProduct] = useState(false); const [editingProduct, setEditingProduct] = useState(null); const [pTitle, setPTitle] = useState(""); const [pUrl, setPUrl] = useState(""); const [pDesc, setPDesc] = useState(""); const [pImageUrl, setPImageUrl] = useState(""); const [pCategory, setPCategory] = useState("general"); useEffect(() => { Promise.all([ fetch("/api/profile").then(r => r.json()), fetch("/api/profile/products").then(r => r.json()), ]).then(([pd, prods]) => { if (pd.profile) { setProfile(pd.profile); setSlug(pd.profile.slug); setDisplayName(pd.profile.display_name); setBio(pd.profile.bio ?? ""); setIsPublic(pd.profile.is_public); } setProducts(prods.items || []); setLoading(false); }).catch(() => setLoading(false)); }, []); async function saveProfile() { setSaving(true); setSaveMsg(""); const r = await fetch("/api/profile", { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ slug, display_name: displayName, bio: bio || null, is_public: isPublic }), }); const d = await r.json(); if (r.ok) { setProfile(d.profile); setSaveMsg(`Saved! View at /m/${d.profile.slug}`); } else { setSaveMsg(d.error || "Save failed"); } setSaving(false); } function resetProductForm() { setPTitle(""); setPUrl(""); setPDesc(""); setPImageUrl(""); setPCategory("general"); setShowAddProduct(false); setEditingProduct(null); } async function saveProduct() { const body = { title: pTitle, url: pUrl, description: pDesc || null, image_url: pImageUrl || null, category: pCategory }; if (editingProduct) { await fetch(`/api/profile/products/${editingProduct.id}`, { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body), }); } else { await fetch("/api/profile/products", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ ...body, display_order: products.length }), }); } const r = await fetch("/api/profile/products"); const d = await r.json(); setProducts(d.items || []); resetProductForm(); } async function deleteProduct(id: string) { if (!confirm("Remove this product?")) return; await fetch(`/api/profile/products/${id}`, { method: "DELETE" }); setProducts(p => p.filter(x => x.id !== id)); } async function moveProduct(id: string, dir: "up" | "down") { const idx = products.findIndex(p => p.id === id); if ((dir === "up" && idx === 0) || (dir === "down" && idx === products.length - 1)) return; const swapIdx = dir === "up" ? idx - 1 : idx + 1; await fetch(`/api/profile/products/${id}`, { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ display_order: products[swapIdx].display_order }), }); await fetch(`/api/profile/products/${products[swapIdx].id}`, { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ display_order: products[idx].display_order }), }); const r = await fetch("/api/profile/products"); const d = await r.json(); setProducts(d.items || []); } function startEdit(p: Product) { setEditingProduct(p); setPTitle(p.title); setPUrl(p.url); setPDesc(p.description ?? ""); setPImageUrl(p.image_url ?? ""); setPCategory(p.category); setShowAddProduct(true); } const slugValid = /^[a-z0-9-]{3,40}$/.test(slug); const baseUrl = typeof window !== "undefined" ? window.location.origin : ""; const inputClass = "w-full border border-gray-200 dark:border-gray-600 rounded-xl px-3 py-2.5 text-sm bg-white dark:bg-gray-700 dark:text-white focus:outline-none focus:ring-2 focus:ring-rose-300"; if (loading) return (
{["๐Ÿผ", "๐Ÿ˜ด", "๐Ÿšผ", "๐Ÿ‘ถ"].map((e, i) => ( {e} ))}

Loading profileโ€ฆ

); return (
{/* Header */}

My Profile Page

{/* Profile section */}

Profile

setDisplayName(e.target.value)} className={`${inputClass} mb-3`} placeholder="Priya Sharma" />
{baseUrl}/m/ setSlug(e.target.value.toLowerCase().replace(/[^a-z0-9-]/g, ""))} className="flex-1 bg-transparent outline-none dark:text-white text-sm" placeholder="priya-sharma" />
{slug && !slugValid && (

3โ€“40 chars, lowercase letters, numbers, hyphens only

)}