108 lines
4.1 KiB
TypeScript
108 lines
4.1 KiB
TypeScript
'use client';
|
||
|
||
import { useState, useEffect } from 'react';
|
||
import { useParams } from 'next/navigation';
|
||
import Link from 'next/link';
|
||
import Header from '@/components/Header';
|
||
import Footer from '@/components/Footer';
|
||
import { createClient } from '@/lib/supabase/client';
|
||
|
||
export default function GigDetailPage() {
|
||
const params = useParams();
|
||
const id = params?.id as string;
|
||
const supabase = createClient();
|
||
const [gig, setGig] = useState<any>(null);
|
||
const [loading, setLoading] = useState(true);
|
||
|
||
useEffect(() => {
|
||
if (!id) return;
|
||
const fetchGig = async () => {
|
||
const { data } = await supabase
|
||
.from('marketplace_gigs')
|
||
.select('*')
|
||
.eq('id', id)
|
||
.eq('status', 'active')
|
||
.maybeSingle();
|
||
setGig(data);
|
||
setLoading(false);
|
||
};
|
||
fetchGig();
|
||
}, [id]);
|
||
|
||
if (loading) {
|
||
return (
|
||
<div className="min-h-screen bg-[#0d0d0d] flex items-center justify-center">
|
||
<div className="w-8 h-8 border-4 border-[#CC0000] border-t-transparent rounded-full animate-spin" />
|
||
</div>
|
||
);
|
||
}
|
||
|
||
if (!gig) {
|
||
return (
|
||
<div className="min-h-screen bg-[#0d0d0d] text-white flex items-center justify-center">
|
||
<div className="text-center">
|
||
<h1 className="text-2xl font-bold mb-2">Gig Not Found</h1>
|
||
<Link href="/marketplace/gigs" className="text-[#CC0000] hover:underline">Back to Gigs</Link>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
return (
|
||
<div className="min-h-screen bg-[#0d0d0d] text-white">
|
||
<Header />
|
||
<div className="max-w-3xl mx-auto px-4 py-24">
|
||
<div className="flex items-center gap-2 text-sm text-gray-500 mb-8">
|
||
<Link href="/marketplace" className="hover:text-[#CC0000]">Marketplace</Link>
|
||
<span>/</span>
|
||
<Link href="/marketplace/gigs" className="hover:text-[#CC0000]">Gigs</Link>
|
||
<span>/</span>
|
||
<span className="text-white truncate">{gig.title}</span>
|
||
</div>
|
||
|
||
<div className="bg-[#1a1a1a] rounded-2xl border border-white/10 overflow-hidden">
|
||
<div className="bg-gradient-to-r from-[#CC0000]/20 to-transparent p-8">
|
||
<h1 className="text-2xl font-black mb-2">{gig.title}</h1>
|
||
<div className="text-[#CC0000] font-bold text-lg mb-4">{gig.company}</div>
|
||
<div className="flex flex-wrap gap-4 text-sm text-gray-300">
|
||
<span>📍 {gig.location}</span>
|
||
<span>🎬 {gig.gig_type}</span>
|
||
{gig.rate && <span>💵 {gig.rate}</span>}
|
||
{gig.start_date && (
|
||
<span>📅 {new Date(gig.start_date).toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' })}
|
||
{gig.end_date && ` – ${new Date(gig.end_date).toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' })}`}
|
||
</span>
|
||
)}
|
||
</div>
|
||
</div>
|
||
|
||
<div className="p-8 space-y-6">
|
||
<section>
|
||
<h2 className="text-sm font-bold uppercase tracking-wide text-gray-400 mb-3">Project Details</h2>
|
||
<div className="text-gray-300 leading-relaxed whitespace-pre-wrap">{gig.description}</div>
|
||
</section>
|
||
|
||
<div className="border-t border-white/10 pt-6">
|
||
<h2 className="text-sm font-bold uppercase tracking-wide text-gray-400 mb-4">How to Respond</h2>
|
||
{gig.contact_method ? (
|
||
<div className="bg-[#0d0d0d] rounded-lg p-4 text-sm text-gray-300">{gig.contact_method}</div>
|
||
) : (
|
||
<p className="text-gray-400 text-sm">Contact the poster directly through the platform.</p>
|
||
)}
|
||
</div>
|
||
|
||
<div className="text-xs text-gray-500 border-t border-white/10 pt-4">
|
||
Posted {new Date(gig.created_at).toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' })}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="mt-6 text-center">
|
||
<Link href="/marketplace/gigs" className="text-[#CC0000] hover:underline text-sm">← Back to Gig Board</Link>
|
||
</div>
|
||
</div>
|
||
<Footer />
|
||
</div>
|
||
);
|
||
}
|