|
|
|
|
@ -18,6 +18,7 @@ import {
|
|
|
|
|
ListOrdered,
|
|
|
|
|
FileText,
|
|
|
|
|
CalendarClock,
|
|
|
|
|
Trash2,
|
|
|
|
|
} from 'lucide-react';
|
|
|
|
|
import useTranslation from '@/src/hooks/useTranslation';
|
|
|
|
|
import Card from '@/src/components/cards/Card';
|
|
|
|
|
@ -28,7 +29,9 @@ import {
|
|
|
|
|
useStartCompetition,
|
|
|
|
|
useFinishCompetition,
|
|
|
|
|
useCancelCompetition,
|
|
|
|
|
useDeleteCompetition,
|
|
|
|
|
} from '@/src/hooks/mutations/useCompetitionMutations';
|
|
|
|
|
import { useRouter } from 'next/navigation';
|
|
|
|
|
import OverviewTab from './tabs/OverviewTab';
|
|
|
|
|
import RegistrationsTab from './tabs/RegistrationsTab';
|
|
|
|
|
import ParticipantsTab from './tabs/ParticipantsTab';
|
|
|
|
|
@ -71,20 +74,76 @@ function formatDate(dateString: string): string {
|
|
|
|
|
function StatusTransitionButton({
|
|
|
|
|
status,
|
|
|
|
|
competitionId,
|
|
|
|
|
facilityId,
|
|
|
|
|
locale,
|
|
|
|
|
}: {
|
|
|
|
|
status: CompetitionStatus;
|
|
|
|
|
competitionId: number;
|
|
|
|
|
facilityId: number;
|
|
|
|
|
locale: string;
|
|
|
|
|
}) {
|
|
|
|
|
const router = useRouter();
|
|
|
|
|
const publishMutation = usePublishCompetition(competitionId);
|
|
|
|
|
const startMutation = useStartCompetition(competitionId);
|
|
|
|
|
const finishMutation = useFinishCompetition(competitionId);
|
|
|
|
|
const cancelMutation = useCancelCompetition(competitionId);
|
|
|
|
|
const deleteMutation = useDeleteCompetition(competitionId);
|
|
|
|
|
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
|
|
|
|
|
|
|
|
|
|
const isPending =
|
|
|
|
|
publishMutation.isPending ||
|
|
|
|
|
startMutation.isPending ||
|
|
|
|
|
finishMutation.isPending ||
|
|
|
|
|
cancelMutation.isPending;
|
|
|
|
|
cancelMutation.isPending ||
|
|
|
|
|
deleteMutation.isPending;
|
|
|
|
|
|
|
|
|
|
const canDelete = status === 'draft' || status === 'cancelled';
|
|
|
|
|
|
|
|
|
|
const handleDelete = () => {
|
|
|
|
|
deleteMutation.mutate(undefined, {
|
|
|
|
|
onSuccess: () => {
|
|
|
|
|
router.push(`/${locale}/admin/facilities/${facilityId}/competitions`);
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const DeleteButton = () => (
|
|
|
|
|
<>
|
|
|
|
|
{showDeleteConfirm ? (
|
|
|
|
|
<div className="flex items-center gap-2">
|
|
|
|
|
<span className="text-sm text-red-700">Delete permanently?</span>
|
|
|
|
|
<button
|
|
|
|
|
onClick={handleDelete}
|
|
|
|
|
disabled={isPending}
|
|
|
|
|
className="inline-flex items-center px-3 py-1.5 bg-red-600 text-white text-sm font-semibold rounded-lg hover:bg-red-700 transition-colors disabled:opacity-50"
|
|
|
|
|
>
|
|
|
|
|
{deleteMutation.isPending ? (
|
|
|
|
|
<Loader2 className="w-4 h-4 animate-spin" />
|
|
|
|
|
) : (
|
|
|
|
|
'Yes, delete'
|
|
|
|
|
)}
|
|
|
|
|
</button>
|
|
|
|
|
<button
|
|
|
|
|
onClick={() => setShowDeleteConfirm(false)}
|
|
|
|
|
disabled={isPending}
|
|
|
|
|
className="inline-flex items-center px-3 py-1.5 bg-slate-100 text-slate-700 text-sm font-semibold rounded-lg hover:bg-slate-200 transition-colors disabled:opacity-50"
|
|
|
|
|
>
|
|
|
|
|
No
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
) : (
|
|
|
|
|
<button
|
|
|
|
|
onClick={() => setShowDeleteConfirm(true)}
|
|
|
|
|
disabled={isPending}
|
|
|
|
|
className="inline-flex items-center px-4 py-2 bg-red-100 text-red-700 font-semibold rounded-xl hover:bg-red-200 transition-colors disabled:opacity-50"
|
|
|
|
|
title="Delete competition permanently"
|
|
|
|
|
>
|
|
|
|
|
<Trash2 className="w-4 h-4 mr-2" />
|
|
|
|
|
Delete
|
|
|
|
|
</button>
|
|
|
|
|
)}
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (status === 'draft') {
|
|
|
|
|
return (
|
|
|
|
|
@ -101,6 +160,7 @@ function StatusTransitionButton({
|
|
|
|
|
)}
|
|
|
|
|
Publish
|
|
|
|
|
</button>
|
|
|
|
|
<DeleteButton />
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
@ -155,6 +215,15 @@ function StatusTransitionButton({
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// For cancelled status, show delete button
|
|
|
|
|
if (canDelete) {
|
|
|
|
|
return (
|
|
|
|
|
<div className="flex gap-2">
|
|
|
|
|
<DeleteButton />
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -234,7 +303,7 @@ export default function CompetitionDetailComponent({
|
|
|
|
|
<FileText className="w-4 h-4 mr-2" />
|
|
|
|
|
Save as Template
|
|
|
|
|
</button>
|
|
|
|
|
<StatusTransitionButton status={competition.status} competitionId={competitionId} />
|
|
|
|
|
<StatusTransitionButton status={competition.status} competitionId={competitionId} facilityId={facilityId} locale={locale} />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|