IAM related required updates

This commit is contained in:
Stephanos A
2026-06-24 19:53:05 +03:00
parent d94e0e9d35
commit 58967e6e3d
19 changed files with 240 additions and 142 deletions

View File

@@ -91,7 +91,7 @@ export default function PassengersPage() {
case 'dateOfBirth': return p.dateOfBirth ? formatDate(p.dateOfBirth) : '';
case 'gender': return p.gender || '';
case 'nationality': return p.nationality || '';
case 'verified': return p.nationalId ? 'Yes' : 'No';
case 'verified': return p.faydaVerified ? 'Yes' : 'No';
default: return '';
}
});
@@ -117,15 +117,15 @@ export default function PassengersPage() {
</div>
),
},
{ key: 'phone', label: 'Phone', sortable: true, render: (p: any) => p.phone },
{ key: 'gender', label: 'Gender', sortable: true, render: (p: any) => p.gender || 'N/A' },
{ key: 'phone', label: 'Phone', sortable: true, render: (p: any) => p.phone || 'N/A' },
{ key: 'nationality', label: 'Nationality', sortable: true, render: (p: any) => p.nationality || 'N/A' },
{ key: 'gender', label: 'Gender', sortable: true, render: (p: any) => p.gender || 'N/A' },
{ key: 'dateOfBirth', label: 'Date of Birth', sortable: true, render: (p: any) => p.dateOfBirth ? formatDate(p.dateOfBirth) : 'N/A' },
{
key: 'verified', label: 'Status',
render: (p: any) => (
<Badge variant="status" status={p.nationalId ? 'CONFIRMED' : 'PENDING'}>
{p.nationalId ? 'Verified' : 'Unverified'}
<Badge variant="status" status={p.faydaVerified ? 'CONFIRMED' : 'PENDING'}>
{p.faydaVerified ? 'Verified' : 'Unverified'}
</Badge>
),
},
@@ -192,7 +192,7 @@ export default function PassengersPage() {
{selectedPassenger && (() => {
const p = selectedPassenger;
const isVerified = !!p.faydaVerified || !!p.nationalId;
const tier = p.passenger?.loyalty?.tier || p.loyalty?.tier;
const tier = p.loyalty?.tier || p.loyaltyTier;
const tierColor = TIER_COLORS[tier] || TIER_COLORS.BRONZE;
return (

View File

@@ -11,6 +11,7 @@ import ConfirmDialog from '@/components/ui/ConfirmDialog';
import Modal from '@/components/ui/Modal';
import { ticketsApi, apiClient, stationsApi, excessBaggageApi } from '@/lib/api';
import { formatDateTime, formatCurrency, formatDateTimeShort } from '@/lib/utils';
import { useAuthStore } from '@/lib/auth-store';
export default function TicketsPage() {
const [filters, setFilters] = useState({ search: '', status: '', originStationId: '', destinationStationId: '', arrivalDate: '' });
@@ -25,15 +26,23 @@ export default function TicketsPage() {
const [detailsModalOpen, setDetailsModalOpen] = useState(false);
const [selectedTicket, setSelectedTicket] = useState<any>(null);
const { user } = useAuthStore();
// Excess baggage state
const [excessModalOpen, setExcessModalOpen] = useState(false);
const [excessTicket, setExcessTicket] = useState<any>(null);
const [excessKg, setExcessKg] = useState('');
const [excessCollectCash, setExcessCollectCash] = useState(false);
const [excessAgentId, setExcessAgentId] = useState('');
const [excessError, setExcessError] = useState<string | null>(null);
const [excessResult, setExcessResult] = useState<any>(null);
const { data: agentData } = useQuery({
queryKey: ['agent-me'],
queryFn: () => apiClient.get<any>('/agents/me'),
enabled: !!user,
retry: false,
});
const Field = ({ label, value, mono = false, truncate = false }: { label: string; value: string; mono?: boolean; truncate?: boolean }) => (
<div className="bg-muted/40 rounded-lg p-3">
<p className="text-xs text-muted-foreground mb-1">{label}</p>
@@ -105,7 +114,6 @@ export default function TicketsPage() {
setExcessTicket(ticket);
setExcessKg('');
setExcessCollectCash(false);
setExcessAgentId('');
setExcessError(null);
setExcessResult(null);
setExcessModalOpen(true);
@@ -114,9 +122,11 @@ export default function TicketsPage() {
const handleExcessSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!excessTicket) return;
const agentId = agentData?.id;
if (!agentId) { setExcessError('No agent profile found for your account'); return; }
await excessMutation.mutateAsync({
bookingId: excessTicket.bookingId,
agentId: excessAgentId,
bookingId: excessTicket.booking?.id ?? excessTicket.bookingId,
agentId,
excessWeightKg: parseInt(excessKg),
collectCash: excessCollectCash,
});
@@ -371,6 +381,13 @@ export default function TicketsPage() {
];
const actions = [
{
label: 'Baggage',
onClick: openExcessModal,
variant: 'secondary' as const,
icon: Package,
show: (ticket: any) => !!ticket.booking && ['CONFIRMED', 'BOARDED'].includes(ticket.booking?.status ?? ticket.status),
},
{
label: 'Board',
onClick: handleBoard,
@@ -411,13 +428,6 @@ export default function TicketsPage() {
variant: 'danger' as const,
icon: Trash2,
},
{
label: 'Excess Baggage',
onClick: openExcessModal,
variant: 'secondary' as const,
icon: Package,
show: (ticket: any) => !!ticket.booking && ['CONFIRMED', 'BOARDED'].includes(ticket.booking?.status ?? ticket.status),
},
];
const stations = stationsData?.items || [];
@@ -736,16 +746,16 @@ export default function TicketsPage() {
<div className="text-sm text-muted-foreground">
Booking: <span className="font-semibold text-foreground">{excessTicket?.booking?.bookingRef}</span>
</div>
<div>
<label className="label">Agent ID</label>
<input
className="input"
placeholder="Enter your agent ID"
value={excessAgentId}
onChange={(e) => setExcessAgentId(e.target.value)}
required
/>
</div>
{agentData && (
<div className="text-sm text-muted-foreground">
Agent: <span className="font-semibold text-foreground">{agentData.agentCode}</span>
</div>
)}
{!agentData && (
<div className="text-sm text-amber-600 dark:text-amber-400">
No agent profile linked to your account.
</div>
)}
<div>
<label className="label">Excess weight (kg)</label>
<input

View File

@@ -413,6 +413,6 @@ export const excessBaggageApi = {
// System Config API
export const systemConfigApi = {
getAll: () => apiClient.get<Record<string, string>>('/system-config'),
update: (data: Record<string, string>) => apiClient.patch<Record<string, string>>('/system-config', data),
getAll: () => apiClient.get<Record<string, string>>('/config'),
update: (data: Record<string, string>) => apiClient.patch<Record<string, string>>('/config', data),
};