Files
edr-platform/apps/edr-passenger-web/backoffice/src/app/tariff-rates/page.tsx
2026-07-14 22:43:57 +03:00

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>
);
}