203 lines
11 KiB
TypeScript
203 lines
11 KiB
TypeScript
import { cookies } from 'next/headers'
|
|
import { redirect } from 'next/navigation'
|
|
import { supabase } from '@/lib/supabase'
|
|
import { LogoutButton } from '@/components/logout-button'
|
|
import { ArrowLeft, Building2, MapPin, User, ExternalLink, Map as MapIcon } from 'lucide-react'
|
|
import Link from 'next/link'
|
|
import { AdminReviewList } from './AdminReviewList'
|
|
|
|
interface Props {
|
|
params: Promise<{ id: string }>
|
|
}
|
|
|
|
export default async function ReviewPosyanduPage({ params }: Props) {
|
|
const { id } = await params
|
|
const cookieStore = await cookies()
|
|
const sessionCookie = cookieStore.get('user_session')
|
|
if (!sessionCookie) redirect('/')
|
|
|
|
const session = JSON.parse(sessionCookie.value)
|
|
if (session.role !== 'admin') redirect('/dashboard')
|
|
|
|
const { data: posyandu, error } = await supabase
|
|
.from('detail_posyandu')
|
|
.select(`
|
|
*,
|
|
petugas:petugas_posyandu_lokal(*),
|
|
reviews:ulasan_posyandu(*)
|
|
`)
|
|
.eq('id', id)
|
|
.single()
|
|
|
|
if (error || !posyandu) {
|
|
return (
|
|
<div className="min-h-screen flex items-center justify-center text-red-500 font-semibold bg-white p-8">
|
|
<div className="bg-red-50 p-6 rounded-2xl border-2 border-red-200 text-center max-w-md">
|
|
<p className="font-black text-xl mb-2">Data Tidak Ditemukan</p>
|
|
<Link href="/dashboard/manajemen-posyandu" className="inline-block mt-4 text-xs font-bold underline">Kembali ke Daftar Posyandu</Link>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
const mapSrc = `https://maps.google.com/maps?q=${encodeURIComponent(posyandu.alamat)}&z=15&output=embed`
|
|
|
|
return (
|
|
<div className="min-h-screen bg-white font-sans text-black flex flex-col">
|
|
{/* Header */}
|
|
<header className="flex justify-between items-center px-8 py-6 border-b border-gray-100">
|
|
<div className="flex items-center gap-4">
|
|
<Link href="/dashboard/manajemen-posyandu" className="group flex items-center gap-2 text-sm font-bold hover:text-gray-600 transition-colors">
|
|
<div className="p-2 rounded-full border border-black flex items-center justify-center group-hover:bg-black group-hover:text-white transition-all">
|
|
<ArrowLeft className="h-5 w-5" />
|
|
</div>
|
|
<span className="hidden md:block">Kembali</span>
|
|
</Link>
|
|
<div className="h-8 w-px bg-gray-200 mx-2 hidden md:block"></div>
|
|
<div className="flex flex-col justify-center">
|
|
<h1 className="text-xl font-bold leading-none">{posyandu.nama_posyandu}</h1>
|
|
<p className="text-[10px] text-gray-500 tracking-widest uppercase mt-0.5">DETAIL OPERASIONAL</p>
|
|
</div>
|
|
</div>
|
|
<LogoutButton />
|
|
</header>
|
|
|
|
<main className="p-8 max-w-6xl mx-auto w-full grid grid-cols-1 lg:grid-cols-3 gap-8">
|
|
|
|
{/* Left Column - Information */}
|
|
<div className="lg:col-span-2 flex flex-col gap-8">
|
|
|
|
{/* Basic Info Card */}
|
|
<div className="bg-white rounded-3xl border-2 border-black shadow-[8px_8px_0px_0px_rgba(0,0,0,1)] overflow-hidden">
|
|
<div className="p-8 bg-purple-600 border-b-2 border-black">
|
|
<h3 className="text-2xl font-black text-white flex items-center gap-3">
|
|
<Building2 className="w-7 h-7" />
|
|
Informasi Utama
|
|
</h3>
|
|
</div>
|
|
<div className="p-8">
|
|
<div className="flex flex-col gap-2">
|
|
<span className="text-[10px] font-black uppercase text-gray-400 tracking-widest flex items-center gap-2">
|
|
<MapPin className="w-3 h-3" />
|
|
Alamat Posyandu
|
|
</span>
|
|
<p className="text-lg font-bold leading-relaxed">{posyandu.alamat}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Petugas Card */}
|
|
<div className="bg-white rounded-3xl border-2 border-black shadow-[8px_8px_0px_0px_rgba(147,51,234,0.3)] overflow-hidden">
|
|
<div className="p-6 border-b border-gray-100 flex items-center justify-between">
|
|
<h3 className="text-base font-black flex items-center gap-3">
|
|
<User className="w-5 h-5 text-purple-600" />
|
|
Daftar Petugas Terdaftar
|
|
</h3>
|
|
<span className="text-xs font-bold text-purple-600 bg-purple-50 px-3 py-1 rounded-full border border-purple-100 uppercase tracking-widest">
|
|
{posyandu.petugas?.length || 0} Orang
|
|
</span>
|
|
</div>
|
|
<div className="divide-y divide-gray-100">
|
|
{posyandu.petugas && posyandu.petugas.length > 0 ? (
|
|
posyandu.petugas.map((pt: any) => (
|
|
<div key={pt.id} className="p-6 flex items-center justify-between hover:bg-gray-50/50 transition-all">
|
|
<div className="flex items-center gap-4">
|
|
<div className="w-12 h-12 rounded-xl bg-purple-100 text-purple-600 flex items-center justify-center font-black text-xl">
|
|
{pt.nama_petugas?.[0]}
|
|
</div>
|
|
<div>
|
|
<p className="font-bold text-gray-900">{pt.nama_petugas}</p>
|
|
<p className="text-xs text-gray-500 font-semibold uppercase tracking-wider">{pt.jabatan || 'Anggota'}</p>
|
|
</div>
|
|
</div>
|
|
<div className="flex items-center gap-3">
|
|
<div className="text-right">
|
|
<p className="text-xs font-bold text-gray-400 uppercase tracking-widest mb-0.5">Kontak</p>
|
|
<p className="text-sm font-bold">{pt.nomor_hp || '-'}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
))
|
|
) : (
|
|
<div className="p-12 text-center text-gray-400 italic text-sm">
|
|
Belum ada data petugas terdaftar di posyandu ini.
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Admin Review List Card */}
|
|
<AdminReviewList
|
|
posyanduId={posyandu.id}
|
|
initialReviews={posyandu.reviews || []}
|
|
/>
|
|
</div>
|
|
|
|
{/* Right Column - Map & Quick Sync */}
|
|
<div className="flex flex-col gap-8 sticky top-8 self-start">
|
|
|
|
{/* Map Card */}
|
|
<div className="bg-white rounded-3xl border-2 border-black shadow-[8px_8px_0px_0px_rgba(59,130,246,0.3)] overflow-hidden">
|
|
<div className="p-6 border-b border-gray-100 flex items-center justify-between bg-blue-50/30">
|
|
<h3 className="text-base font-black flex items-center gap-3">
|
|
<MapIcon className="w-5 h-5 text-blue-600" />
|
|
Lokasi Geografis
|
|
</h3>
|
|
{posyandu.link_google_maps && (
|
|
<a
|
|
href={posyandu.link_google_maps}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="p-2 bg-white text-blue-600 border border-blue-200 rounded-lg hover:shadow-md transition-all"
|
|
>
|
|
<ExternalLink className="w-4 h-4" />
|
|
</a>
|
|
)}
|
|
</div>
|
|
<div className="aspect-square w-full bg-gray-100 relative">
|
|
{posyandu.alamat ? (
|
|
<iframe
|
|
width="100%"
|
|
height="100%"
|
|
style={{ border: 0 }}
|
|
loading="lazy"
|
|
allowFullScreen
|
|
src={mapSrc}
|
|
></iframe>
|
|
) : (
|
|
<div className="absolute inset-0 flex flex-col items-center justify-center p-8 text-center gap-4 text-gray-400">
|
|
<MapIcon className="w-12 h-12 opacity-20" />
|
|
<p className="text-xs font-bold font-semibold px-4">
|
|
Alamat belum diatur. Edit data untuk menambahkan alamat.
|
|
</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
<div className="p-6 bg-gray-50 border-t border-gray-100">
|
|
<p className="text-[10px] text-gray-500 leading-relaxed italic">
|
|
Peta di atas ditampilkan secara otomatis berdasarkan alamat Posyandu yang terdaftar.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Stats Card */}
|
|
<div className="bg-black text-white rounded-3xl p-8 flex flex-col gap-4 relative overflow-hidden">
|
|
<div className="z-10">
|
|
<p className="text-purple-400 text-[10px] font-black uppercase tracking-widest mb-1">Status Operasional</p>
|
|
<div className="flex items-center gap-2 mb-4">
|
|
<div className="w-2 h-2 bg-emerald-500 rounded-full animate-pulse"></div>
|
|
<span className="text-xs font-bold uppercase tracking-wider">Aktif & Terpantau</span>
|
|
</div>
|
|
<p className="text-sm text-gray-400 leading-relaxed font-semibold">
|
|
Terakhir diperbarui pada {new Date(posyandu.created_at).toLocaleDateString('id-ID', { day: 'numeric', month: 'long', year: 'numeric' })}
|
|
</p>
|
|
</div>
|
|
<Building2 className="absolute -right-8 -bottom-8 w-24 h-24 text-white/5" />
|
|
</div>
|
|
</div>
|
|
|
|
</main>
|
|
</div>
|
|
)
|
|
}
|