mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 12:18:11 +00:00
Project Initialization
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
import { FormEvent, useState } from 'react';
|
||||
import { Button, FormField } from '@edr/ui-common';
|
||||
|
||||
import type { CreateBookingPayload } from '../../services/bookings.service';
|
||||
|
||||
export interface BookingFormProps {
|
||||
onSubmit: (payload: CreateBookingPayload) => void;
|
||||
isSubmitting?: boolean;
|
||||
}
|
||||
|
||||
const BookingForm = ({ onSubmit, isSubmitting }: BookingFormProps) => {
|
||||
const [reference, setReference] = useState('');
|
||||
const [customerId, setCustomerId] = useState('');
|
||||
const [scheduledDate, setScheduledDate] = useState('');
|
||||
const [totalAmount, setTotalAmount] = useState('0');
|
||||
|
||||
const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault();
|
||||
onSubmit({
|
||||
reference,
|
||||
customerId,
|
||||
scheduledDate,
|
||||
totalAmount: Number(totalAmount),
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit} className="flex flex-col gap-3">
|
||||
<FormField label="Reference" value={reference} onChange={(e) => setReference(e.target.value)} required />
|
||||
<FormField label="Customer ID" value={customerId} onChange={(e) => setCustomerId(e.target.value)} required />
|
||||
<FormField
|
||||
label="Scheduled date"
|
||||
type="date"
|
||||
value={scheduledDate}
|
||||
onChange={(e) => setScheduledDate(e.target.value)}
|
||||
required
|
||||
/>
|
||||
<FormField
|
||||
label="Total amount"
|
||||
type="number"
|
||||
value={totalAmount}
|
||||
onChange={(e) => setTotalAmount(e.target.value)}
|
||||
min="0"
|
||||
/>
|
||||
<Button type="submit" isLoading={isSubmitting}>
|
||||
Create booking
|
||||
</Button>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
export default BookingForm;
|
||||
@@ -0,0 +1,28 @@
|
||||
import type { Freight } from '@edr/types';
|
||||
import { Table, type TableColumn } from '@edr/ui-common';
|
||||
|
||||
export interface BookingTableProps {
|
||||
bookings: Freight.IBooking[];
|
||||
}
|
||||
|
||||
const columns: TableColumn<Freight.IBooking>[] = [
|
||||
{ key: 'reference', header: 'Reference' },
|
||||
{ key: 'customerId', header: 'Customer' },
|
||||
{ key: 'status', header: 'Status' },
|
||||
{
|
||||
key: 'scheduledDate',
|
||||
header: 'Scheduled',
|
||||
render: (row) => new Date(row.scheduledDate).toLocaleDateString(),
|
||||
},
|
||||
{
|
||||
key: 'totalAmount',
|
||||
header: 'Total',
|
||||
render: (row) => row.totalAmount.toFixed(2),
|
||||
},
|
||||
];
|
||||
|
||||
const BookingTable = ({ bookings }: BookingTableProps) => (
|
||||
<Table columns={columns} data={bookings} rowKey={(row) => row.id} emptyMessage="No bookings yet" />
|
||||
);
|
||||
|
||||
export default BookingTable;
|
||||
@@ -0,0 +1,72 @@
|
||||
import { FormEvent, useState } from 'react';
|
||||
import { Button, FormField } from '@edr/ui-common';
|
||||
|
||||
export interface ConsignmentFormProps {
|
||||
onSubmit: (payload: {
|
||||
bookingId: string;
|
||||
trackingNumber: string;
|
||||
cargoType: string;
|
||||
weightKg: number;
|
||||
originStation: string;
|
||||
destinationStation: string;
|
||||
}) => void;
|
||||
isSubmitting?: boolean;
|
||||
}
|
||||
|
||||
const ConsignmentForm = ({ onSubmit, isSubmitting }: ConsignmentFormProps) => {
|
||||
const [bookingId, setBookingId] = useState('');
|
||||
const [trackingNumber, setTrackingNumber] = useState('');
|
||||
const [cargoType, setCargoType] = useState('GENERAL');
|
||||
const [weightKg, setWeightKg] = useState('0');
|
||||
const [originStation, setOriginStation] = useState('');
|
||||
const [destinationStation, setDestinationStation] = useState('');
|
||||
|
||||
const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault();
|
||||
onSubmit({
|
||||
bookingId,
|
||||
trackingNumber,
|
||||
cargoType,
|
||||
weightKg: Number(weightKg),
|
||||
originStation,
|
||||
destinationStation,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit} className="flex flex-col gap-3">
|
||||
<FormField label="Booking ID" value={bookingId} onChange={(e) => setBookingId(e.target.value)} required />
|
||||
<FormField
|
||||
label="Tracking #"
|
||||
value={trackingNumber}
|
||||
onChange={(e) => setTrackingNumber(e.target.value)}
|
||||
required
|
||||
/>
|
||||
<FormField label="Cargo type" value={cargoType} onChange={(e) => setCargoType(e.target.value)} />
|
||||
<FormField
|
||||
label="Weight (kg)"
|
||||
type="number"
|
||||
value={weightKg}
|
||||
onChange={(e) => setWeightKg(e.target.value)}
|
||||
min="0"
|
||||
/>
|
||||
<FormField
|
||||
label="Origin station"
|
||||
value={originStation}
|
||||
onChange={(e) => setOriginStation(e.target.value)}
|
||||
required
|
||||
/>
|
||||
<FormField
|
||||
label="Destination station"
|
||||
value={destinationStation}
|
||||
onChange={(e) => setDestinationStation(e.target.value)}
|
||||
required
|
||||
/>
|
||||
<Button type="submit" isLoading={isSubmitting}>
|
||||
Create consignment
|
||||
</Button>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
export default ConsignmentForm;
|
||||
@@ -0,0 +1,26 @@
|
||||
import type { Freight } from '@edr/types';
|
||||
import { Table, type TableColumn } from '@edr/ui-common';
|
||||
|
||||
export interface ConsignmentTableProps {
|
||||
consignments: Freight.IConsignment[];
|
||||
}
|
||||
|
||||
const columns: TableColumn<Freight.IConsignment>[] = [
|
||||
{ key: 'trackingNumber', header: 'Tracking #' },
|
||||
{ key: 'cargoType', header: 'Cargo' },
|
||||
{ key: 'status', header: 'Status' },
|
||||
{ key: 'originStation', header: 'Origin' },
|
||||
{ key: 'destinationStation', header: 'Destination' },
|
||||
{ key: 'weightKg', header: 'Weight (kg)', render: (row) => row.weightKg.toFixed(2) },
|
||||
];
|
||||
|
||||
const ConsignmentTable = ({ consignments }: ConsignmentTableProps) => (
|
||||
<Table
|
||||
columns={columns}
|
||||
data={consignments}
|
||||
rowKey={(row) => row.id}
|
||||
emptyMessage="No consignments yet"
|
||||
/>
|
||||
);
|
||||
|
||||
export default ConsignmentTable;
|
||||
@@ -0,0 +1,35 @@
|
||||
import type { Freight } from '@edr/types';
|
||||
import { Badge } from '@edr/ui-common';
|
||||
|
||||
export interface TrackingTimelineProps {
|
||||
events: Freight.ITrackingEvent[];
|
||||
}
|
||||
|
||||
const TrackingTimeline = ({ events }: TrackingTimelineProps) => {
|
||||
if (events.length === 0) {
|
||||
return <div className="text-sm text-gray-500">No tracking events yet.</div>;
|
||||
}
|
||||
return (
|
||||
<ol className="relative ml-3 border-l border-gray-200">
|
||||
{events.map((event) => (
|
||||
<li key={event.id} className="mb-4 ml-4">
|
||||
<div className="absolute -left-1.5 mt-1.5 h-3 w-3 rounded-full bg-blue-500" />
|
||||
<div className="flex flex-col gap-1">
|
||||
<div className="flex items-center gap-2 text-sm font-medium text-gray-900">
|
||||
<span>{event.location}</span>
|
||||
<Badge tone="info">{event.status}</Badge>
|
||||
</div>
|
||||
<time className="text-xs text-gray-500">
|
||||
{new Date(event.occurredAt).toLocaleString()}
|
||||
</time>
|
||||
{event.description ? (
|
||||
<p className="text-sm text-gray-700">{event.description}</p>
|
||||
) : null}
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ol>
|
||||
);
|
||||
};
|
||||
|
||||
export default TrackingTimeline;
|
||||
Reference in New Issue
Block a user