You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
174 lines
5.7 KiB
TypeScript
174 lines
5.7 KiB
TypeScript
'use client';
|
|
|
|
import { useState, useEffect } from 'react';
|
|
import { ArrowLeft, Loader2, AlertCircle, Lock } from 'lucide-react';
|
|
import Link from 'next/link';
|
|
import { getAdminClubDetail } from '@/src/lib/api/admin-clubs';
|
|
import type { AdminClubDetail, AdminApiError } from '@/src/types/admin-api';
|
|
import useTranslation from '@/src/hooks/useTranslation';
|
|
import FacilityTabNavigation from './FacilityTabNavigation';
|
|
|
|
interface FacilityDetailHeaderProps {
|
|
facilityId: number;
|
|
children: React.ReactNode;
|
|
}
|
|
|
|
export default function FacilityDetailHeader({ facilityId, children }: FacilityDetailHeaderProps) {
|
|
const { locale } = useTranslation();
|
|
const [facilityDetail, setFacilityDetail] = useState<AdminClubDetail | null>(null);
|
|
const [error, setError] = useState<AdminApiError | null>(null);
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
useEffect(() => {
|
|
loadFacilityDetail();
|
|
}, [facilityId]);
|
|
|
|
async function loadFacilityDetail() {
|
|
setLoading(true);
|
|
const result = await getAdminClubDetail(facilityId);
|
|
|
|
if (result.success) {
|
|
setFacilityDetail(result.data);
|
|
setError(null);
|
|
} else {
|
|
setError(result.error);
|
|
setFacilityDetail(null);
|
|
}
|
|
|
|
setLoading(false);
|
|
}
|
|
|
|
// Loading state
|
|
if (loading) {
|
|
return (
|
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-20">
|
|
<div className="flex flex-col items-center justify-center space-y-4">
|
|
<Loader2 className="w-12 h-12 text-slate-900 animate-spin" />
|
|
<p className="text-slate-600 font-medium">Loading facility details...</p>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
// Authentication error (401)
|
|
if (error && error.status === 401) {
|
|
return (
|
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-20">
|
|
<div className="max-w-2xl mx-auto">
|
|
<div className="bg-amber-50 border-2 border-amber-200 rounded-2xl p-8">
|
|
<div className="flex items-start space-x-4">
|
|
<Lock className="w-8 h-8 text-amber-700 flex-shrink-0 mt-1" />
|
|
<div>
|
|
<h2 className="text-2xl font-bold text-slate-900 mb-4">
|
|
Authentication Required
|
|
</h2>
|
|
<p className="text-slate-700 leading-relaxed">
|
|
Please log in to access the venue management portal.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
// Forbidden error (403)
|
|
if (error && error.status === 403) {
|
|
return (
|
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-20">
|
|
<div className="max-w-2xl mx-auto">
|
|
<div className="bg-red-50 border-2 border-red-200 rounded-2xl p-8">
|
|
<div className="flex items-start space-x-4">
|
|
<Lock className="w-8 h-8 text-red-600 flex-shrink-0 mt-1" />
|
|
<div>
|
|
<h2 className="text-2xl font-bold text-slate-900 mb-4">
|
|
Access Denied
|
|
</h2>
|
|
<p className="text-slate-700 mb-6 leading-relaxed">
|
|
{error.detail}
|
|
</p>
|
|
<Link
|
|
href={`/${locale}/admin/facilities`}
|
|
className="inline-flex items-center px-4 py-2 bg-slate-900 text-white font-semibold rounded-lg hover:bg-slate-800 transition-colors"
|
|
>
|
|
<ArrowLeft className="w-4 h-4 mr-2" />
|
|
Back to facilities
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
// Other API errors
|
|
if (error) {
|
|
return (
|
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-20">
|
|
<div className="max-w-2xl mx-auto">
|
|
<div className="bg-red-50 border-2 border-red-200 rounded-2xl p-8">
|
|
<div className="flex items-start space-x-4">
|
|
<AlertCircle className="w-8 h-8 text-red-600 flex-shrink-0 mt-1" />
|
|
<div className="flex-1">
|
|
<h2 className="text-2xl font-bold text-slate-900 mb-4">
|
|
Error Loading Facility
|
|
</h2>
|
|
<p className="text-slate-700 mb-4 leading-relaxed">
|
|
{error.detail}
|
|
</p>
|
|
<p className="text-sm text-slate-600 font-mono mb-6">
|
|
Error code: {error.code}
|
|
</p>
|
|
<Link
|
|
href={`/${locale}/admin/facilities`}
|
|
className="inline-flex items-center px-4 py-2 bg-slate-900 text-white font-semibold rounded-lg hover:bg-slate-800 transition-colors"
|
|
>
|
|
<ArrowLeft className="w-4 h-4 mr-2" />
|
|
Back to facilities
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (!facilityDetail) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
|
|
{/* Breadcrumb */}
|
|
<div className="mb-8">
|
|
<Link
|
|
href={`/${locale}/admin/facilities`}
|
|
className="inline-flex items-center text-slate-600 hover:text-slate-900 font-medium transition-colors"
|
|
>
|
|
<ArrowLeft className="w-4 h-4 mr-2" />
|
|
Back to facilities
|
|
</Link>
|
|
</div>
|
|
|
|
{/* Facility Header */}
|
|
<div className="mb-8">
|
|
<h1 className="text-4xl font-bold text-slate-900 mb-2 tracking-tight">
|
|
{facilityDetail.facility.name}
|
|
</h1>
|
|
<p className="text-lg text-slate-600 font-light">
|
|
{facilityDetail.facility.timezone}
|
|
</p>
|
|
</div>
|
|
|
|
{/* Tab Navigation */}
|
|
<FacilityTabNavigation facilityId={facilityId} />
|
|
|
|
{/* Content */}
|
|
{children}
|
|
</div>
|
|
);
|
|
}
|