mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 07:38:10 +00:00
Fare engine updates, seat class amount updates
This commit is contained in:
@@ -326,11 +326,6 @@ export default function ClassesPage() {
|
||||
<p className="text-xs text-muted-foreground mt-1">Flat fee per passenger (e.g., travel insurance)</p>
|
||||
</div>
|
||||
|
||||
<div className="mt-4 p-3 bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded text-sm text-blue-800 dark:text-blue-200">
|
||||
<p className="font-medium mb-1">Total Fare Calculation:</p>
|
||||
<p>Total = (Base Fare × Distance) + Insurance</p>
|
||||
<p className="mt-2 text-xs">• Insurance applies per passenger</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
||||
@@ -10,7 +10,6 @@ import Modal from '@/components/ui/Modal';
|
||||
import ConfirmDialog from '@/components/ui/ConfirmDialog';
|
||||
import { apiClient } from '@/lib/api-client';
|
||||
|
||||
const NATIONALITY_TYPES = ['LOCAL', 'INTERNATIONAL'] as const;
|
||||
const BED_POSITIONS = ['UPPER', 'MIDDLE', 'LOWER'] as const;
|
||||
const COACH_TYPE_LABELS: Record<string, string> = {
|
||||
HSC: 'Regular Seat (Hard Seat)',
|
||||
@@ -18,7 +17,6 @@ const COACH_TYPE_LABELS: Record<string, string> = {
|
||||
SBC: 'VIP Bed (Soft Berth)',
|
||||
};
|
||||
|
||||
// Tariff reference rates per the official policy document
|
||||
const TARIFF_REFERENCE: Record<string, Record<string, number>> = {
|
||||
LOCAL: {
|
||||
'HSC-null': 0.03,
|
||||
@@ -109,7 +107,7 @@ export default function TariffRatesPage() {
|
||||
name: fd.get('name') as string,
|
||||
nationalityType: selectedNationalityType,
|
||||
bedPosition: selectedBedPosition || null,
|
||||
baseFareMinor: parseInt(fd.get('baseFareMinor') as string),
|
||||
basePrice: Math.round(Number(fd.get('baseFareMinor') as string) * 100) || 0,
|
||||
isActive: fd.get('isActive') === 'true',
|
||||
};
|
||||
if (editingClass) {
|
||||
@@ -127,7 +125,6 @@ export default function TariffRatesPage() {
|
||||
? classesData
|
||||
: (classesData as any)?.items || (classesData as any)?.data || [];
|
||||
|
||||
// Only show classes that have nationalityType set (tariff-managed rows)
|
||||
const tariffClasses = allClasses.filter((c: any) => c.nationalityType);
|
||||
|
||||
const displayed = tariffClasses.filter((c: any) => {
|
||||
@@ -141,7 +138,6 @@ export default function TariffRatesPage() {
|
||||
);
|
||||
});
|
||||
|
||||
// Auto-suggest name from selections
|
||||
const suggestName = () => {
|
||||
const ct = coachTypesArray.find((c: any) => c.id === selectedCoachTypeId);
|
||||
if (!ct) return '';
|
||||
@@ -151,13 +147,12 @@ export default function TariffRatesPage() {
|
||||
return `${label}${pos} (${nat})`;
|
||||
};
|
||||
|
||||
// Auto-suggest baseFareMinor from tariff reference
|
||||
// Returns the human-readable rate (e.g. 0.03); stored value = this × 100
|
||||
const suggestRate = () => {
|
||||
const ct = coachTypesArray.find((c: any) => c.id === selectedCoachTypeId);
|
||||
if (!ct) return '';
|
||||
const ref = getTariffRef(selectedNationalityType, ct.code, selectedBedPosition || null);
|
||||
// baseFareMinor = tariff_decimal × 100000
|
||||
return ref ? Math.round(ref * 100000).toString() : '';
|
||||
return ref ? String(ref) : '';
|
||||
};
|
||||
|
||||
const columns = [
|
||||
@@ -184,18 +179,18 @@ export default function TariffRatesPage() {
|
||||
render: (c: any) => <span className="font-medium">{c.name}</span>,
|
||||
},
|
||||
{
|
||||
key: 'baseFareMinor', label: 'Rate per km (minor)',
|
||||
key: 'baseFareMinor', label: 'Rate per km',
|
||||
render: (c: any) => {
|
||||
const ct = coachTypesArray.find((t: any) => t.id === c.coachTypeId);
|
||||
const ref = ct ? getTariffRef(c.nationalityType, ct.code, c.bedPosition) : undefined;
|
||||
const tariffMinor = ref ? Math.round(ref * 100000) : undefined;
|
||||
const tariffMinor = ref ? Math.round(ref * 100) : undefined;
|
||||
const matches = tariffMinor === c.baseFareMinor;
|
||||
return (
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="font-mono font-medium">{c.baseFareMinor}</span>
|
||||
<span className="font-mono font-medium">{c.baseFareMinor / 100}</span>
|
||||
{tariffMinor !== undefined && (
|
||||
<span className={`text-xs px-1.5 py-0.5 rounded ${matches ? 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400' : 'bg-yellow-100 text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-400'}`}>
|
||||
{matches ? '✓ tariff' : `tariff: ${tariffMinor}`}
|
||||
{matches ? '✓ tariff' : `tariff: ${tariffMinor / 100}`}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
@@ -237,7 +232,6 @@ export default function TariffRatesPage() {
|
||||
</ActionButton>
|
||||
</div>
|
||||
|
||||
|
||||
<div className="card">
|
||||
<div className="relative mb-4">
|
||||
<Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
|
||||
@@ -367,15 +361,16 @@ export default function TariffRatesPage() {
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="label">Base Fare Minor (per km) *</label>
|
||||
<label className="label">Rate per km *</label>
|
||||
<input
|
||||
type="number"
|
||||
name="baseFareMinor"
|
||||
className="input"
|
||||
defaultValue={editingClass?.baseFareMinor ?? ''}
|
||||
defaultValue={editingClass ? editingClass.baseFareMinor / 100 : ''}
|
||||
key={editingClass?.id ?? `rate-${selectedCoachTypeId}-${selectedBedPosition}-${selectedNationalityType}`}
|
||||
placeholder={suggestRate() || 'e.g. 3000'}
|
||||
placeholder={suggestRate() || 'e.g. 6'}
|
||||
min="0"
|
||||
step="any"
|
||||
required
|
||||
/>
|
||||
{suggestRate() && (
|
||||
@@ -391,7 +386,7 @@ export default function TariffRatesPage() {
|
||||
>
|
||||
{suggestRate()}
|
||||
</button>
|
||||
{' '}(= {(parseInt(suggestRate()) / 100000).toFixed(3)} ETB/km)
|
||||
{' '}(stored as {Math.round(Number(suggestRate()) * 100)})
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user