- Added RequestReturnDialog component for initiating return requests. - Enhanced OrderDetailPageView to handle return requests and display order timeline. - Updated OrderActions to include return request button based on order status. - Introduced OrderTimeline component to visualize order events. - Modified order-related types and constants to support return functionality. - Updated UI components for better styling and user experience. This commit improves the order management system by allowing users to request returns and view the timeline of their orders.
92 lines
2.7 KiB
TypeScript
92 lines
2.7 KiB
TypeScript
import Image from "next/image";
|
||
import { Card, ScrollShadow } from "@heroui/react";
|
||
import { formatPrice } from "@repo/utils";
|
||
import type { OrderLineItem } from "@/lib/orders";
|
||
|
||
interface Props {
|
||
items: OrderLineItem[];
|
||
currency: string;
|
||
}
|
||
|
||
function LineItem({
|
||
item,
|
||
currency,
|
||
}: {
|
||
item: OrderLineItem;
|
||
currency: string;
|
||
}) {
|
||
return (
|
||
<div className="flex gap-3 py-3 first:pt-0 last:pb-0">
|
||
{/* Product image */}
|
||
<div className="relative h-16 w-16 shrink-0 overflow-hidden rounded-md border border-gray-100 bg-gray-50 md:h-20 md:w-20">
|
||
{item.imageUrl ? (
|
||
<Image
|
||
src={item.imageUrl}
|
||
alt={item.productName}
|
||
fill
|
||
className="object-cover"
|
||
sizes="(max-width: 768px) 64px, 80px"
|
||
/>
|
||
) : (
|
||
<div className="flex h-full w-full items-center justify-center text-2xl text-gray-300">
|
||
🐾
|
||
</div>
|
||
)}
|
||
</div>
|
||
|
||
{/* Item details */}
|
||
<div className="flex flex-1 flex-col justify-between gap-1 md:flex-row md:items-start">
|
||
<div className="space-y-0.5">
|
||
<p className="text-sm font-medium text-[#1a2e2d]">
|
||
{item.productName}
|
||
</p>
|
||
<p className="text-xs text-gray-500">
|
||
{item.variantName}
|
||
</p>
|
||
<p className="text-xs text-gray-400">SKU: {item.sku}</p>
|
||
</div>
|
||
|
||
<div className="flex items-center gap-2 text-sm md:flex-col md:items-end">
|
||
<span className="text-gray-500">
|
||
{item.quantity} × {formatPrice(item.unitPrice, currency)}
|
||
</span>
|
||
<span className="font-semibold text-[#236f6b]">
|
||
{formatPrice(item.totalPrice, currency)}
|
||
</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
export function OrderLineItems({ items, currency }: Props) {
|
||
const scrollable = items.length > 4;
|
||
|
||
return (
|
||
<Card className="rounded-xl p-5">
|
||
<Card.Header>
|
||
<Card.Title className="text-base">
|
||
Items ({items.length})
|
||
</Card.Title>
|
||
</Card.Header>
|
||
<Card.Content className="p-0">
|
||
{scrollable ? (
|
||
<ScrollShadow className="max-h-[400px] px-4 pb-4" hideScrollBar>
|
||
<div className="divide-y divide-gray-100">
|
||
{items.map((item) => (
|
||
<LineItem key={item._id} item={item} currency={currency} />
|
||
))}
|
||
</div>
|
||
</ScrollShadow>
|
||
) : (
|
||
<div className="divide-y divide-gray-100 px-4 pb-4">
|
||
{items.map((item) => (
|
||
<LineItem key={item._id} item={item} currency={currency} />
|
||
))}
|
||
</div>
|
||
)}
|
||
</Card.Content>
|
||
</Card>
|
||
);
|
||
}
|