Merge pull request 'done recovery incidents' (#25) from azeem into development
Reviewed-on: https://gitea.maskantech.in/gitea_admin/aeroresolve_frontend/pulls/25
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
import { ApiClient } from '../api/ApiClient';
|
||||
import type { RecoveryIncident } from './RecoveryIncidentsTypes';
|
||||
|
||||
export const RecoveryIncidentsApi = {
|
||||
getAll: async (): Promise<RecoveryIncident[]> => {
|
||||
return ApiClient.get('/recovery-incidents');
|
||||
},
|
||||
|
||||
getById: async (id: string): Promise<RecoveryIncident> => {
|
||||
return ApiClient.get(`/recovery-incidents/${id}`);
|
||||
},
|
||||
|
||||
create: async (data: Omit<RecoveryIncident, 'id'>): Promise<RecoveryIncident> => {
|
||||
return ApiClient.post('/recovery-incidents', data);
|
||||
},
|
||||
|
||||
update: async (id: string, data: Partial<RecoveryIncident>): Promise<RecoveryIncident> => {
|
||||
return ApiClient.patch(`/recovery-incidents/${id}`, data);
|
||||
},
|
||||
|
||||
delete: async (id: string): Promise<void> => {
|
||||
return ApiClient.delete(`/recovery-incidents/${id}`);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { useState } from 'react';
|
||||
import { FileText, User, Airplane, WarningCircle, CaretRight } from '@phosphor-icons/react';
|
||||
import {
|
||||
CustomModal,
|
||||
CustomInput,
|
||||
CustomDropdown,
|
||||
} from "../../../components/custom";
|
||||
import { RecoveryIncidentsApi } from '../RecoveryIncidentsApi';
|
||||
|
||||
interface AddRecoveryIncidentsProps {
|
||||
isOpen: boolean;
|
||||
@@ -14,6 +16,52 @@ const SECTION_TITLE_CLASS = "flex items-center gap-2 mb-4 text-[#4A5568] font-bo
|
||||
const SECTION_CONTAINER_CLASS = "bg-[#F9FAFB] rounded-[14px] p-5 border border-gray-100";
|
||||
|
||||
export default function AddRecoveryIncidents({ isOpen, onClose }: AddRecoveryIncidentsProps) {
|
||||
const [formData, setFormData] = useState({
|
||||
passengerName: "",
|
||||
pnr: "",
|
||||
loyaltyTier: "",
|
||||
flightNumber: "",
|
||||
date: "",
|
||||
origin: "",
|
||||
destination: "",
|
||||
category: "",
|
||||
scenario: "",
|
||||
jurisdiction: "",
|
||||
delayDuration: "",
|
||||
});
|
||||
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const handleInputChange = (field: string, value: string) => {
|
||||
setFormData((prev) => ({ ...prev, [field]: value }));
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const payload = {
|
||||
recoveryId: "REC-" + Math.floor(Math.random() * 10000),
|
||||
passengerName: formData.passengerName || "Unknown",
|
||||
pnr: formData.pnr || "N/A",
|
||||
flightNumber: formData.flightNumber || "TBD",
|
||||
flightRoute: `${formData.origin || 'UNK'} → ${formData.destination || 'UNK'}`,
|
||||
date: formData.date ? new Date(formData.date).toISOString() : new Date().toISOString(),
|
||||
category: formData.category || "General",
|
||||
statuses: [{ text: "New", variant: "info" as const }],
|
||||
value: "$0",
|
||||
};
|
||||
|
||||
console.log("Submitting payload:", payload);
|
||||
await RecoveryIncidentsApi.create(payload);
|
||||
onClose(); // Will trigger refresh in parent list
|
||||
} catch (error: any) {
|
||||
console.error("Error creating incident:", error.response?.data || error.message || error);
|
||||
alert(`Failed to add incident: ${error.response?.data?.message || 'Unknown error'}`);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<CustomModal
|
||||
isOpen={isOpen}
|
||||
@@ -23,8 +71,8 @@ export default function AddRecoveryIncidents({ isOpen, onClose }: AddRecoveryInc
|
||||
icon={<FileText className="text-[#1B9869]" />}
|
||||
size="lg"
|
||||
primaryAction={{
|
||||
label: "Assess & Log Incident",
|
||||
onClick: onClose,
|
||||
label: loading ? "Logging..." : "Assess & Log Incident",
|
||||
onClick: handleSubmit,
|
||||
icon: <CaretRight size={16} />
|
||||
}}
|
||||
secondaryAction={{
|
||||
@@ -43,14 +91,20 @@ export default function AddRecoveryIncidents({ isOpen, onClose }: AddRecoveryInc
|
||||
<CustomInput
|
||||
label="Full Name"
|
||||
placeholder="e.g. John Doe"
|
||||
value={formData.passengerName}
|
||||
onChange={(e) => handleInputChange("passengerName", e.target.value)}
|
||||
/>
|
||||
<CustomInput
|
||||
label="PNR Reference"
|
||||
placeholder="e.g. FT7687T9I"
|
||||
value={formData.pnr}
|
||||
onChange={(e) => handleInputChange("pnr", e.target.value)}
|
||||
/>
|
||||
<CustomDropdown
|
||||
label="Loyalty Tier"
|
||||
placeholder="Selected Option"
|
||||
value={formData.loyaltyTier}
|
||||
onChange={(val) => handleInputChange("loyaltyTier", val as string)}
|
||||
options={[
|
||||
{ label: "Gold", value: "gold" },
|
||||
{ label: "Silver", value: "silver" },
|
||||
@@ -70,6 +124,8 @@ export default function AddRecoveryIncidents({ isOpen, onClose }: AddRecoveryInc
|
||||
<CustomDropdown
|
||||
label="Flight Number"
|
||||
placeholder="e.g. B7687YT"
|
||||
value={formData.flightNumber}
|
||||
onChange={(val) => handleInputChange("flightNumber", val as string)}
|
||||
options={[
|
||||
{ label: "B7687YT", value: "B7687YT" },
|
||||
{ label: "Q23SXD", value: "Q23SXD" },
|
||||
@@ -80,10 +136,14 @@ export default function AddRecoveryIncidents({ isOpen, onClose }: AddRecoveryInc
|
||||
type="date"
|
||||
label="Date"
|
||||
placeholder="Selected Option"
|
||||
value={formData.date}
|
||||
onChange={(e) => handleInputChange("date", e.target.value)}
|
||||
/>
|
||||
<CustomDropdown
|
||||
label="Origin (IATA)"
|
||||
placeholder="Selected Option"
|
||||
value={formData.origin}
|
||||
onChange={(val) => handleInputChange("origin", val as string)}
|
||||
options={[
|
||||
{ label: "FRA", value: "FRA" },
|
||||
{ label: "LHR", value: "LHR" },
|
||||
@@ -93,6 +153,8 @@ export default function AddRecoveryIncidents({ isOpen, onClose }: AddRecoveryInc
|
||||
<CustomDropdown
|
||||
label="Destination (IATA)"
|
||||
placeholder="Selected Option"
|
||||
value={formData.destination}
|
||||
onChange={(val) => handleInputChange("destination", val as string)}
|
||||
options={[
|
||||
{ label: "JFK", value: "JFK" },
|
||||
{ label: "CDG", value: "CDG" },
|
||||
@@ -112,6 +174,8 @@ export default function AddRecoveryIncidents({ isOpen, onClose }: AddRecoveryInc
|
||||
<CustomDropdown
|
||||
label="Category"
|
||||
placeholder="Selected Option"
|
||||
value={formData.category}
|
||||
onChange={(val) => handleInputChange("category", val as string)}
|
||||
options={[
|
||||
{ label: "Flight Ops", value: "flight_ops" },
|
||||
{ label: "Travel Exp", value: "travel_exp" },
|
||||
@@ -121,6 +185,8 @@ export default function AddRecoveryIncidents({ isOpen, onClose }: AddRecoveryInc
|
||||
<CustomDropdown
|
||||
label="Scenario"
|
||||
placeholder="Selected Option"
|
||||
value={formData.scenario}
|
||||
onChange={(val) => handleInputChange("scenario", val as string)}
|
||||
options={[
|
||||
{ label: "Delay", value: "delay" },
|
||||
{ label: "Cancellation", value: "cancellation" },
|
||||
@@ -130,6 +196,8 @@ export default function AddRecoveryIncidents({ isOpen, onClose }: AddRecoveryInc
|
||||
<CustomDropdown
|
||||
label="Jurisdiction"
|
||||
placeholder="Selected Option"
|
||||
value={formData.jurisdiction}
|
||||
onChange={(val) => handleInputChange("jurisdiction", val as string)}
|
||||
options={[
|
||||
{ label: "EU261", value: "eu261" },
|
||||
{ label: "US DOT", value: "us_dot" },
|
||||
@@ -139,6 +207,8 @@ export default function AddRecoveryIncidents({ isOpen, onClose }: AddRecoveryInc
|
||||
type="number"
|
||||
label="Delay Duration (Mins)"
|
||||
placeholder="0"
|
||||
value={formData.delayDuration}
|
||||
onChange={(e) => handleInputChange("delayDuration", e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
import type { Column } from "../../../components/custom/CustomTable";
|
||||
import type { RecoveryIncident } from "../RecoveryIncidentsTypes";
|
||||
import AddRecoveryIncidents from "./AddRecoveryIncidents";
|
||||
import { RecoveryIncidentsApi } from "../RecoveryIncidentsApi";
|
||||
|
||||
// ─── Constants ───────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -303,12 +304,13 @@ export default function RecoveryIncidentsList() {
|
||||
// ─── Fetch data ─────────────────────────────────────────────
|
||||
|
||||
const fetchIncidents = useCallback(
|
||||
(page: number) => {
|
||||
async (page: number) => {
|
||||
setLoading(true);
|
||||
|
||||
// Simulate API call with timeout
|
||||
setTimeout(() => {
|
||||
const filteredData = MOCK_INCIDENTS.filter((p) => {
|
||||
try {
|
||||
const data = await RecoveryIncidentsApi.getAll();
|
||||
|
||||
const filteredData = data.filter((p) => {
|
||||
const matchesSearch = p.recoveryId.toLowerCase().includes(search.toLowerCase()) ||
|
||||
p.flightNumber.toLowerCase().includes(search.toLowerCase());
|
||||
const matchesGroup = isGrouped ? true : !p.isGroupHeader;
|
||||
@@ -323,8 +325,12 @@ export default function RecoveryIncidentsList() {
|
||||
setIncidents(paginatedData);
|
||||
setTotalItems(total);
|
||||
setTotalPages(pages || 1);
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch recovery incidents", error);
|
||||
setIncidents([]);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}, 500);
|
||||
}
|
||||
},
|
||||
[search, isGrouped],
|
||||
);
|
||||
@@ -619,7 +625,10 @@ export default function RecoveryIncidentsList() {
|
||||
{/* Modal */}
|
||||
<AddRecoveryIncidents
|
||||
isOpen={isModalOpen}
|
||||
onClose={() => setIsModalOpen(false)}
|
||||
onClose={() => {
|
||||
setIsModalOpen(false);
|
||||
fetchIncidents(currentPage); // Refresh list
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user