mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-09 07:08:18 +00:00
146 lines
5.1 KiB
TypeScript
146 lines
5.1 KiB
TypeScript
'use client';
|
|
|
|
import { useState } from 'react';
|
|
import { Plus } from 'lucide-react';
|
|
import ActionButton from '@/components/ui/ActionButton';
|
|
import TariffTab from './TariffTab';
|
|
import OverridesTab from './OverridesTab';
|
|
import SegmentOverridesTab from './SegmentOverridesTab';
|
|
import BaggageTab from './BaggageTab';
|
|
import RateModal from './RateModal';
|
|
import { useSeatClasses, useCoachTypes, useRoutes, useSeatClassMutations, useRouteFareRuleMutations } from './hooks';
|
|
import type { SeatClass, TabType } from './types';
|
|
|
|
export default function TariffRatesPage() {
|
|
const [tab, setTab] = useState<TabType>('tariff');
|
|
const [showRateModal, setShowRateModal] = useState(false);
|
|
const [editingClass, setEditingClass] = useState<SeatClass | null>(null);
|
|
const [showBaggageModal, setShowBaggageModal] = useState(false);
|
|
const [preselectedRouteId, setPreselectedRouteId] = useState<string | null>(null);
|
|
const [deleteError, setDeleteError] = useState<string | undefined>(undefined);
|
|
const [deleteSuccess, setDeleteSuccess] = useState(0);
|
|
|
|
const { allClasses, isLoading } = useSeatClasses();
|
|
const { coachTypes } = useCoachTypes();
|
|
const { routes } = useRoutes();
|
|
|
|
const closeRateModal = () => { setShowRateModal(false); setEditingClass(null); setPreselectedRouteId(null); };
|
|
|
|
const seatClassMutations = useSeatClassMutations(closeRateModal);
|
|
const overrideMutations = useRouteFareRuleMutations(preselectedRouteId);
|
|
|
|
const handleSubmitGlobal = async (payload: any) => {
|
|
if (editingClass) {
|
|
await seatClassMutations.update.mutateAsync({ id: editingClass.id, data: payload });
|
|
} else {
|
|
await seatClassMutations.create.mutateAsync(payload);
|
|
}
|
|
closeRateModal();
|
|
};
|
|
|
|
const handleSubmitOverride = async (routeId: string, payload: any) => {
|
|
await overrideMutations.create.mutateAsync({ routeId, ...payload });
|
|
closeRateModal();
|
|
};
|
|
|
|
const handleDelete = async (id: string, cascade: boolean) => {
|
|
setDeleteError(undefined);
|
|
try {
|
|
await seatClassMutations.remove.mutateAsync({ id, cascade });
|
|
setDeleteSuccess(n => n + 1);
|
|
} catch (err: any) {
|
|
const msg = err?.response?.data?.message ?? err?.message ?? 'Delete failed';
|
|
setDeleteError(Array.isArray(msg) ? msg.join(' ') : msg);
|
|
}
|
|
};
|
|
|
|
const tabs: { key: TabType; label: string }[] = [
|
|
{ key: 'tariff', label: 'Seat Class Tariffs' },
|
|
{ key: 'overrides', label: 'Route Overrides' },
|
|
{ key: 'segment-overrides', label: 'Segment Overrides' },
|
|
{ key: 'baggage', label: 'Excess Luggage Rates' },
|
|
];
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
<div className="flex items-center justify-between">
|
|
<div>
|
|
<h1 className="text-2xl font-bold text-foreground">Tariff Rates</h1>
|
|
<p className="text-muted-foreground">
|
|
Manage per-km fare rates and excess luggage allowances per the official EDR tariff policy
|
|
</p>
|
|
</div>
|
|
{tab !== 'overrides' && tab !== 'segment-overrides' && (
|
|
<ActionButton icon={Plus} onClick={() => {
|
|
if (tab === 'baggage') {
|
|
setShowBaggageModal(true);
|
|
} else {
|
|
setEditingClass(null);
|
|
setPreselectedRouteId(null);
|
|
setShowRateModal(true);
|
|
}
|
|
}}>
|
|
{tab === 'baggage' ? 'Add Allowance Rule' : 'Add Rate'}
|
|
</ActionButton>
|
|
)}
|
|
</div>
|
|
|
|
<div className="card">
|
|
<div className="flex gap-4 border-b mb-6">
|
|
{tabs.map(t => (
|
|
<button
|
|
key={t.key}
|
|
onClick={() => setTab(t.key)}
|
|
className={`px-4 py-2 font-medium border-b-2 transition-colors ${tab === t.key ? 'border-primary text-primary' : 'border-transparent text-muted-foreground'}`}
|
|
>
|
|
{t.label}
|
|
</button>
|
|
))}
|
|
</div>
|
|
|
|
{tab === 'tariff' && (
|
|
<TariffTab
|
|
classes={allClasses}
|
|
coachTypes={coachTypes}
|
|
isLoading={isLoading}
|
|
onEdit={cls => { setEditingClass(cls); setPreselectedRouteId(null); setShowRateModal(true); }}
|
|
onDelete={handleDelete}
|
|
isDeleting={seatClassMutations.remove.isPending}
|
|
deleteError={deleteError}
|
|
deleteSuccess={deleteSuccess}
|
|
/>
|
|
)}
|
|
|
|
{tab === 'overrides' && (
|
|
<OverridesTab routes={routes} />
|
|
)}
|
|
|
|
{tab === 'segment-overrides' && (
|
|
<SegmentOverridesTab routes={routes} />
|
|
)}
|
|
|
|
{tab === 'baggage' && (
|
|
<BaggageTab
|
|
allClasses={allClasses}
|
|
isOpen={showBaggageModal}
|
|
onClose={() => setShowBaggageModal(false)}
|
|
/>
|
|
)}
|
|
</div>
|
|
|
|
<RateModal
|
|
isOpen={showRateModal}
|
|
onClose={closeRateModal}
|
|
editingClass={editingClass}
|
|
allClasses={allClasses}
|
|
coachTypes={coachTypes}
|
|
routes={routes}
|
|
preselectedRouteId={preselectedRouteId}
|
|
onSubmitGlobal={handleSubmitGlobal}
|
|
onSubmitOverride={handleSubmitOverride}
|
|
isPending={seatClassMutations.create.isPending || seatClassMutations.update.isPending || overrideMutations.create.isPending}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|