This commit is contained in:
JuruSysadmin
2025-06-17 13:41:48 -03:00
commit af154c3f7f
197 changed files with 50658 additions and 0 deletions

View 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>
);
}