"use client"; import { useState, useEffect, useCallback } from "react"; import { useAuth } from "@/lib/AuthContext"; import { useRouter } from "next/navigation"; import { ArrowLeft, Plus, X, Loader2, Check, Package, Image as ImageIcon, Tags, Clock, } from "lucide-react"; /* ------------------------------------------------------------------ */ /* Categories */ /* ------------------------------------------------------------------ */ const CATEGORIES = [ { id: "graphics-design", name: "Graphics & Design", icon: "🎨" }, { id: "digital-marketing", name: "Digital Marketing", icon: "πŸ“ˆ" }, { id: "writing-translation", name: "Writing & Translation", icon: "✍️" }, { id: "video-animation", name: "Video & Animation", icon: "🎬" }, { id: "music-audio", name: "Music & Audio", icon: "🎡" }, { id: "programming-tech", name: "Programming & Tech", icon: "πŸ’»" }, { id: "ai-services", name: "AI Services", icon: "πŸ€–" }, { id: "consulting", name: "Consulting", icon: "πŸ’Ό" }, { id: "data", name: "Data", icon: "πŸ“Š" }, { id: "business", name: "Business", icon: "🏒" }, { id: "personal-growth", name: "Personal Growth", icon: "🌱" }, { id: "photography", name: "Photography", icon: "πŸ“·" }, { id: "finance", name: "Finance", icon: "πŸ’°" }, ]; /* ------------------------------------------------------------------ */ /* Types */ /* ------------------------------------------------------------------ */ interface PackageField { id: string; name: string; description: string; price: string; deliveryDays: string; revisions: string; } interface FormErrors { title?: string; category?: string; description?: string; priceFlh?: string; } /* ------------------------------------------------------------------ */ /* Page Component */ /* ------------------------------------------------------------------ */ export default function SouqCreatePage() { const { user, token, loading } = useAuth(); const router = useRouter(); /* ---- form fields ---- */ const [title, setTitle] = useState(""); const [category, setCategory] = useState(""); const [description, setDescription] = useState(""); const [priceFlh, setPriceFlh] = useState(""); const [deliveryDays, setDeliveryDays] = useState(""); const [tagsInput, setTagsInput] = useState(""); const [imageUrl, setImageUrl] = useState(""); /* ---- packages ---- */ const [packages, setPackages] = useState([]); /* ---- ui state ---- */ const [errors, setErrors] = useState({}); const [submitting, setSubmitting] = useState(false); const [success, setSuccess] = useState(false); const [errorMessage, setErrorMessage] = useState(""); /* ---- auth guard ---- */ useEffect(() => { if (!loading && !token) { router.push("/auth"); } }, [loading, token, router]); /* ---- auto-redirect on success ---- */ useEffect(() => { if (success) { const timer = setTimeout(() => router.push("/souq"), 2000); return () => clearTimeout(timer); } }, [success, router]); /* ---- helpers ---- */ const generateId = useCallback( () => Math.random().toString(36).substring(2, 10), [] ); const addPackage = () => { setPackages((prev) => [ ...prev, { id: generateId(), name: "", description: "", price: "", deliveryDays: "", revisions: "", }, ]); }; const removePackage = (id: string) => { setPackages((prev) => prev.filter((p) => p.id !== id)); }; const updatePackage = (id: string, field: keyof PackageField, value: string) => { setPackages((prev) => prev.map((p) => (p.id === id ? { ...p, [field]: value } : p)) ); }; /* ---- validation ---- */ const validate = (): boolean => { const errs: FormErrors = {}; if (!title.trim()) errs.title = "Title is required"; if (!category) errs.category = "Please select a category"; if (!description.trim()) errs.description = "Description is required"; if (!priceFlh || isNaN(Number(priceFlh)) || Number(priceFlh) < 0) { errs.priceFlh = "Enter a valid price (0 or more)"; } setErrors(errs); return Object.keys(errs).length === 0; }; /* ---- submit ---- */ const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!validate()) return; setSubmitting(true); setErrorMessage(""); try { // Parse tags from comma-separated string const tagsArr = tagsInput .split(",") .map((t) => t.trim()) .filter(Boolean); // Build images array const imagesArr = imageUrl.trim() ? [imageUrl.trim()] : []; // Build packages array (only if user added any) const packagesArr = packages .filter((p) => p.name.trim()) .map((p) => ({ name: p.name.trim(), description: p.description.trim(), price: Number(p.price) || 0, deliveryDays: p.deliveryDays ? Number(p.deliveryDays) : undefined, revisions: p.revisions ? Number(p.revisions) : undefined, })); const body: Record = { title: title.trim(), description: description.trim(), category, priceFlh: Number(priceFlh), deliveryDays: deliveryDays ? Number(deliveryDays) : undefined, tags: tagsArr.length > 0 ? tagsArr : undefined, images: imagesArr.length > 0 ? imagesArr : undefined, packages: packagesArr.length > 0 ? packagesArr : undefined, }; const res = await fetch("/mobile/api/souq/listings", { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}`, }, body: JSON.stringify(body), }); const data = await res.json(); if (!res.ok) { throw new Error(data.error || "Failed to create listing"); } setSuccess(true); } catch (err: unknown) { const msg = err instanceof Error ? err.message : "Something went wrong"; setErrorMessage(msg); } finally { setSubmitting(false); } }; /* ---- early returns ---- */ if (loading) { return (
); } if (!user) return null; /* ---- success state ---- */ if (success) { return (

Listing Created!

Your service has been published on Souq.

Redirecting to Souq…

); } /* ---- main render ---- */ return (
{/* Header */}

Create Listing

Sell your service on Souq

{/* Form */}
{/* Title */}
setTitle(e.target.value)} placeholder="e.g. I will build a modern website" className="w-full bg-[#0a0a0f] border border-gray-800/60 rounded-xl px-4 py-3 text-sm text-white placeholder-gray-600 focus:outline-none focus:border-[#D4AF37]/50 focus:ring-1 focus:ring-[#D4AF37]/30 transition min-h-[48px]" /> {errors.title && (

{errors.title}

)}
{/* Category */}
{CATEGORIES.map((cat) => { const isActive = category === cat.id; return ( ); })}
{errors.category && (

{errors.category}

)}
{/* Description */}