first
This commit is contained in:
296
src/components/orders/OrderDetail.tsx
Normal file
296
src/components/orders/OrderDetail.tsx
Normal file
@@ -0,0 +1,296 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { ArrowLeft } from "lucide-react";
|
||||
import { useNavigation } from "../../hooks";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import { OrderInfoCard } from "./OrderInfoCard";
|
||||
import Timeline from "./OrderTimeline";
|
||||
import { QRCodeRastreamento } from "../../components/qr-code-rastreamento";
|
||||
import { ordersApi } from "../../lib/api";
|
||||
import { createSearchParams, buildUrl } from "../../utils/url-helpers";
|
||||
import {
|
||||
Order,
|
||||
OrderItem,
|
||||
OrderDelivery,
|
||||
cutitens,
|
||||
transfer,
|
||||
status,
|
||||
TimelineEvent,
|
||||
leadtime,
|
||||
} from "../types";
|
||||
|
||||
/**
|
||||
* Interface que define a estrutura de um evento na timeline
|
||||
*/
|
||||
export interface TimelineDisplayEvent {
|
||||
id: string;
|
||||
codigoFuncionario: string;
|
||||
description: string;
|
||||
date: string;
|
||||
status: string;
|
||||
icon: any;
|
||||
color: string;
|
||||
}
|
||||
|
||||
interface OrderDetailProps {
|
||||
order: Order;
|
||||
timelineEvents: leadtime[];
|
||||
}
|
||||
|
||||
export function mapTimelineEvents(events: leadtime[]): TimelineEvent[] {
|
||||
return events.map(event => ({
|
||||
id: event.descricaoEtapa,
|
||||
title: event.descricaoEtapa,
|
||||
description: event.descricao || "Status updated",
|
||||
date: event.data || new Date().toISOString(),
|
||||
status: event.descricaoEtapa,
|
||||
user: event.codigoFuncionario,
|
||||
}));
|
||||
}
|
||||
|
||||
export function OrderDetail({ order, timelineEvents }: OrderDetailProps) {
|
||||
const { searchParams, navigateTo, goBack, goToOrdersFind } = useNavigation();
|
||||
const from = searchParams.get("from");
|
||||
const returnPath = searchParams.get("returnPath") || "/orders/find";
|
||||
|
||||
const [orderItems, setOrderItems] = useState<OrderItem[]>([]);
|
||||
const [loadingItems, setLoadingItems] = useState(false);
|
||||
const [itemsError, setItemsError] = useState<string | null>(null);
|
||||
const [cutItems, setCutItems] = useState<cutitens[]>([]);
|
||||
const [transfers, setTransfers] = useState<transfer[]>([]);
|
||||
const [statusData, setStatusData] = useState<status[]>([]);
|
||||
const [orderDelivery, setOrderDelivery] = useState<OrderDelivery>({
|
||||
placeId: 0,
|
||||
placeName: "",
|
||||
street: "",
|
||||
addressNumber: "",
|
||||
bairro: "",
|
||||
city: "",
|
||||
state: "",
|
||||
addressComplement: "",
|
||||
cep: "",
|
||||
commentOrder1: "",
|
||||
commentOrder2: "",
|
||||
commentDelivery1: order.commentDelivery1 || "",
|
||||
commentDelivery2: "",
|
||||
commentDelivery3: "",
|
||||
commentDelivery4: "",
|
||||
shippimentId: 0,
|
||||
shippimentDate: new Date(),
|
||||
shippimentComment: "",
|
||||
place: order.deliveryLocal || "",
|
||||
driver: order.driver || "",
|
||||
car: order.carDescription || "",
|
||||
closeDate: new Date(),
|
||||
separatorName: "",
|
||||
confName: "",
|
||||
releaseDate: new Date(),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
async function fetchOrderItems() {
|
||||
if (!order.orderId) return;
|
||||
|
||||
setLoadingItems(true);
|
||||
setItemsError(null);
|
||||
|
||||
try {
|
||||
const response = await ordersApi.getOrderItems(order.orderId);
|
||||
const items = Array.isArray(response?.data)
|
||||
? response.data
|
||||
: Array.isArray(response)
|
||||
? response
|
||||
: [];
|
||||
|
||||
setOrderItems(items);
|
||||
} catch {
|
||||
setItemsError("Could not load order items.");
|
||||
} finally {
|
||||
setLoadingItems(false);
|
||||
}
|
||||
}
|
||||
|
||||
fetchOrderItems();
|
||||
}, [order.orderId]);
|
||||
|
||||
useEffect(() => {
|
||||
async function fetchDeliveryInfo() {
|
||||
if (!order.orderId) return;
|
||||
|
||||
try {
|
||||
const response = await ordersApi.getOrderDelivery(order.orderId);
|
||||
const data = response?.data || response;
|
||||
|
||||
setOrderDelivery(prev => ({
|
||||
...prev,
|
||||
...data,
|
||||
place: data.place || order.deliveryLocal || "",
|
||||
driver: data.driver || order.driver || "",
|
||||
car: data.car || order.carDescription || "",
|
||||
}));
|
||||
} catch {}
|
||||
}
|
||||
|
||||
fetchDeliveryInfo();
|
||||
}, [order.orderId]);
|
||||
|
||||
useEffect(() => {
|
||||
async function fetchCutItems() {
|
||||
if (!order.orderId) return;
|
||||
|
||||
try {
|
||||
const response = await ordersApi.getCutItems(order.orderId);
|
||||
const items = Array.isArray(response?.data)
|
||||
? response.data
|
||||
: Array.isArray(response)
|
||||
? response
|
||||
: [];
|
||||
|
||||
setCutItems(items);
|
||||
} catch {}
|
||||
}
|
||||
|
||||
fetchCutItems();
|
||||
}, [order.orderId]);
|
||||
|
||||
useEffect(() => {
|
||||
async function fetchTransfers() {
|
||||
if (!order.orderId) return;
|
||||
|
||||
try {
|
||||
const id = parseInt(order.orderId);
|
||||
if (isNaN(id)) return;
|
||||
|
||||
const response = await ordersApi.getTransfer(id);
|
||||
const items = Array.isArray(response?.data)
|
||||
? response.data
|
||||
: Array.isArray(response)
|
||||
? response
|
||||
: [];
|
||||
|
||||
setTransfers(
|
||||
items.map(item => ({
|
||||
...item,
|
||||
oldShipmentId: Number(item.oldShipmentId ?? 0),
|
||||
newShipmentId: Number(item.newShipmentId ?? 0),
|
||||
}))
|
||||
);
|
||||
} catch {}
|
||||
}
|
||||
|
||||
fetchTransfers();
|
||||
}, [order.orderId]);
|
||||
|
||||
useEffect(() => {
|
||||
async function fetchStatusData() {
|
||||
if (!order.orderId) return;
|
||||
|
||||
try {
|
||||
const id = parseInt(order.orderId);
|
||||
if (isNaN(id)) return;
|
||||
|
||||
const response = await ordersApi.getStatusOrder(id);
|
||||
const items = Array.isArray(response?.data)
|
||||
? response.data
|
||||
: Array.isArray(response)
|
||||
? response
|
||||
: [];
|
||||
|
||||
setStatusData(items);
|
||||
} catch {}
|
||||
}
|
||||
|
||||
fetchStatusData();
|
||||
}, [order.orderId]);
|
||||
|
||||
const returnParams = createSearchParams(
|
||||
searchParams,
|
||||
["from", "returnPath"],
|
||||
{ origem: "detail", noRefresh: "true", preserveState: "true" }
|
||||
);
|
||||
|
||||
const handleBack = () => {
|
||||
if (from === "lista") {
|
||||
const baseUrl = returnPath;
|
||||
const params: Record<string, string> = {};
|
||||
|
||||
searchParams.forEach((value, key) => {
|
||||
params[key] = value;
|
||||
});
|
||||
|
||||
const url = buildUrl(baseUrl, {
|
||||
...params,
|
||||
origem: "detail",
|
||||
noRefresh: "true",
|
||||
preserveState: "true",
|
||||
});
|
||||
|
||||
navigateTo(url);
|
||||
} else if (window.history.length > 2) {
|
||||
goBack();
|
||||
} else {
|
||||
goToOrdersFind();
|
||||
}
|
||||
};
|
||||
|
||||
const orderWithDefaults = {
|
||||
...order,
|
||||
paymentMethod: order.paymentMethod || "Not provided",
|
||||
paymentPlan: order.paymentPlan || "Not provided",
|
||||
paymentName: order.paymentName || "Not provided",
|
||||
driver: order.driver || "Not provided",
|
||||
carDescription: order.carDescription || "Not provided",
|
||||
deliveryLocal: order.deliveryLocal || "Not provided",
|
||||
deliveryType: order.deliveryType || "Not provided",
|
||||
};
|
||||
|
||||
const store = {
|
||||
storeId: order.storeId,
|
||||
store: order.storeName,
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="pl-0 w-full">
|
||||
<div className="bg-white border-b p-1 sm:p-2 flex justify-between items-center">
|
||||
<div className="flex items-center gap-1 sm:gap-3">
|
||||
<Button variant="ghost" size="sm" onClick={handleBack} className="p-1 sm:p-2">
|
||||
<ArrowLeft className="h-4 w-4 sm:h-5 sm:w-5 text-muted-foreground" />
|
||||
<span className="ml-1 sm:ml-2 text-xs sm:text-sm hidden xs:inline">Voltar</span>
|
||||
</Button>
|
||||
<div>
|
||||
<h1 className="text-sm sm:text-lg font-semibold text-gray-800">
|
||||
Pedido {order.orderId}
|
||||
</h1>
|
||||
<p className="text-xs sm:text-sm text-muted-foreground hidden sm:block">
|
||||
Detalhes completos do pedido
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex justify-center p-2">
|
||||
<QRCodeRastreamento orderId={order.orderId} /> </div>
|
||||
</div>
|
||||
|
||||
<div className="p-2 sm:p-6 space-y-4 sm:space-y-6 mx-auto">
|
||||
<div className="grid grid-cols-1 xl:grid-cols-4 gap-4 sm:gap-6">
|
||||
<div className="xl:col-span-3">
|
||||
<OrderInfoCard
|
||||
order={orderWithDefaults}
|
||||
delivery={orderDelivery}
|
||||
loja={store}
|
||||
orderItems={orderItems}
|
||||
cutitens={cutItems}
|
||||
transfers={transfers}
|
||||
status={statusData}
|
||||
/>
|
||||
</div>
|
||||
<div className="hidden sm:block xl:col-span-1">
|
||||
<div className="bg-white border rounded-lg p-4 shadow-sm">
|
||||
<Timeline orderId={order.orderId} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user