freightdesk/frontend/src/components/LoadsList.jsx

132 lines
No EOL
3.9 KiB
JavaScript

import React, { useState } from 'react';
import { useQuery } from '@tanstack/react-query';
import { supabase } from '../supabaseClient';
// Utility functions (mirroring india.js logic for now)
const formatINR = (n) => {
if (n === null || n === undefined || isNaN(n)) return '—';
return '₹' + parseFloat(n).toLocaleString('en-IN');
};
const getStatusColor = (status) => {
const colors = {
'settled': 'success',
'completed': 'success',
'commission received': 'success',
'reconciled': 'success',
'loaded / in transit': 'primary',
'assigned': 'primary',
'assigned vehicle': 'primary',
'pending collection': 'warning',
'partially pending': 'warning',
'fully pending from shipper': 'warning',
'commission due': 'warning',
'cancelled': 'danger',
'partial': 'secondary',
'available vehicle': 'secondary',
};
return colors[status] || 'secondary';
};
function LoadsList() {
const [filterStatus, setFilterStatus] = useState('');
const [searchTerm, setSearchTerm] = useState('');
const { data: loads = [], isLoading, isError, refetch } = useQuery({
queryKey: ['loads', filterStatus, searchTerm],
queryFn: async () => {
let query = supabase
.from('loads')
.select(`
id,
date,
from_city,
to_city,
freight_charged,
commission,
status,
shipper:shippers(name),
vehicle:vehicles(number)
`)
.order('date', { ascending: false })
.limit(100);
if (filterStatus) query = query.eq('status', filterStatus);
if (searchTerm) {
query = query.or(`from_city.ilike.%${searchTerm}%,to_city.ilike.%${searchTerm}%`);
}
const { data, error } = await query;
if (error) throw error;
return data;
},
staleTime: 5 * 60 * 1000, // 5 minutes
});
if (isLoading) return <div className="text-center py-5">Loading loads...</div>;
if (isError) return <div className="text-center py-5 text-danger">Error loading loads</div>;
return (
<div className="container mt-4">
<h2>Loads Management</h2>
{/* Filters */}
<div className="row mb-3 g-2">
<div className="col-md-4">
<input
type="text"
className="form-control"
placeholder="Search cities..."
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
</div>
<div className="col-md-4">
<select
className="form-select"
value={filterStatus}
onChange={(e) => setFilterStatus(e.target.value)}
>
<option value="">All Statuses</option>
<option value="settled">Settled</option>
<option value="loaded / in transit">In Transit</option>
<option value="pending collection">Pending Collection</option>
<option value="cancelled">Cancelled</option>
</select>
</div>
</div>
{/* Loads Table */}
<table className="table table-hover">
<thead>
<tr>
<th>Date</th>
<th>Route</th>
<th>Shipper</th>
<th>Freight</th>
<th>Commission</th>
<th>Status</th>
</tr>
</thead>
<tbody>
{loads.map((load) => (
<tr key={load.id}>
<td>{new Date(load.date).toLocaleDateString('en-IN')}</td>
<td>{load.from_city} {load.to_city}</td>
<td>{load.shipper?.name || '—'}</td>
<td>{formatINR(load.freight_charged)}</td>
<td>{formatINR(load.commission)}</td>
<td>
<span className={`badge bg-${getStatusColor(load.status)}`}>
{load.status}
</span>
</td>
</tr>
))}
</tbody>
</table>
</div>
);
}
export default LoadsList;