add empty order component & server error component & orders skeleton & order item

This commit is contained in:
Mohammadali 2026-08-29 11:48:30 +03:30
parent 17ee08bd5f
commit 41e86d30b3
6 changed files with 216 additions and 34 deletions

View file

@ -2,42 +2,65 @@ import Link from "next/link";
import { requireSession } from "@/lib/auth/session";
import { getOrderGroups } from "@/lib/api/orders";
import { PAYMENT_STATUS_LABELS_FA } from "@/lib/order-status";
import OrderItem from "@/components/orders/OrderItem";
import OrderEmpty from "@/components/orders/OrderEmpty";
import OrderServerError from "@/components/orders/OrderServerError";
import OrdersSkeleton from "@/components/orders/OrdersSkeleton";
export default async function OrdersPage() {
await requireSession("/orders");
const orderGroups = await getOrderGroups();
return <main className="max-w-5xl w-full mx-auto p-4">
<OrdersSkeleton />
{/* <OrderServerError /> */}
{/* <OrderEmpty /> */}
{/* */}
{/* <OrderItem />
<OrderItem />
<OrderItem />
<OrderItem />
<OrderItem />
<OrderItem />
<OrderItem />
<OrderItem />
<OrderItem />
<OrderItem />
<OrderItem />
<OrderItem /> */}
</main>
// await requireSession("/orders");
// const orderGroups = await getOrderGroups();
return (
<main className="mx-auto flex w-full max-w-2xl flex-1 flex-col gap-4 px-4 py-6">
<h1 className="text-lg font-bold">سفارش‌های من</h1>
// return (
// <main className="mx-auto flex w-full max-w-2xl flex-1 flex-col gap-4 px-4 py-6">
// <h1 className="text-lg font-bold">سفارش‌های من</h1>
{orderGroups.length === 0 && <p className="text-sm text-muted-foreground">هنوز سفارشی ثبت نکرده‌اید.</p>}
// {orderGroups.length === 0 && <p className="text-sm text-muted-foreground">هنوز سفارشی ثبت نکرده‌اید.</p>}
<div className="flex flex-col gap-3">
{orderGroups.map((group) => (
<Link
key={group.uuid}
href={`/order-groups/${group.uuid}`}
className="flex flex-col gap-2 rounded-2xl border border-border p-4"
>
<div className="flex justify-between text-sm text-muted-foreground">
<span>{new Date(group.created_at).toLocaleDateString("fa-IR")}</span>
<span>{PAYMENT_STATUS_LABELS_FA[group.payment_status]}</span>
</div>
<div className="flex flex-wrap gap-1 text-sm">
{group.orders.map((order) => (
<span key={order.uuid} className="rounded-full bg-muted px-2 py-0.5">
{order.store.name}
</span>
))}
</div>
<div className="flex justify-between font-semibold">
<span>مجموع</span>
<span>{group.total_amount.toLocaleString("fa-IR")} تومان</span>
</div>
</Link>
))}
</div>
</main>
);
// <div className="flex flex-col gap-3">
// {orderGroups.map((group) => (
// <Link
// key={group.uuid}
// href={`/order-groups/${group.uuid}`}
// className="flex flex-col gap-2 rounded-2xl border border-border p-4"
// >
// <div className="flex justify-between text-sm text-muted-foreground">
// <span>{new Date(group.created_at).toLocaleDateString("fa-IR")}</span>
// <span>{PAYMENT_STATUS_LABELS_FA[group.payment_status]}</span>
// </div>
// <div className="flex flex-wrap gap-1 text-sm">
// {group.orders.map((order) => (
// <span key={order.uuid} className="rounded-full bg-muted px-2 py-0.5">
// {order.store.name}
// </span>
// ))}
// </div>
// <div className="flex justify-between font-semibold">
// <span>مجموع</span>
// <span>{group.total_amount.toLocaleString("fa-IR")} تومان</span>
// </div>
// </Link>
// ))}
// </div>
// </main>
// );
}

View file

@ -0,0 +1,19 @@
import { ShoppingBagIcon } from 'lucide-react'
import React from 'react'
const OrderEmpty = () => {
return (
<div className='h-96 flex items-center justify-center p-5'>
<div className='max-w-xl w-full p-5 flex items-center justify-center flex-col gap-3'>
<div className='size-30 mb-2 bg-gray-100 flex items-center justify-center rounded-full'>
<ShoppingBagIcon className='size-12 text-[#6B7280]' />
</div>
<h1 className='text-lg font-bold'>هنوز سفارشی ثبت نکرده‌اید</h1>
<p className='text-sm text-center text-[#6B7280]'>لیست سفارش‌های شما در حال حاضر خالی است. برای خرید از فروشگاه‌های اطراف روی دکمه زیر کلیک کنید.</p>
<button className='h-12 mt-4 rounded-full w-full bg-[#223D5D] text-white cursor-pointer'>شروع خرید</button>
</div>
</div>
)
}
export default OrderEmpty

View file

@ -0,0 +1,74 @@
import React from 'react';
const OrderItem = () => {
const order = {
id: 1,
restaurant: 'فست‌فود برگر',
description: 'ساندویچ + نوشیدنی',
status: 'در حال آماده‌سازی',
statusColor: 'bg-orange-100 text-orange-700',
time: 'امروز، 11:30',
itemsCount: 3,
totalPrice: 45000,
images: Array.from({ length: 25 }, (_, i) => ({
id: i,
src: `https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQqIof_DOo6I5-oOLJ1V9_HPfSudXfhewy_5C5Ry7YOO-UXSZ1jvK7-0hw&s=10`, // عکس رندوم
alt: `product-${i}`,
})),
};
return (
<div className="w-full rounded-2xl min-h-32 border border-[#E5E7EB] bg-white p-4 mb-2">
<div className="flex items-center justify-between w-full gap-3">
<div className="flex items-center gap-4">
<div className="size-12 rounded-full bg-gradient-to-br from-[#223D5D] to-[#004D4D] flex items-center justify-center text-white font-bold text-lg">
{order.restaurant.charAt(0)}
</div>
<div className="flex flex-col items-start">
<h2 className="text-md font-bold text-gray-800">{order.restaurant}</h2>
<p className="text-sm text-[#6B7280]">{order.description}</p>
</div>
</div>
<span
className={`flex items-center justify-center px-3 py-1 rounded-full text-xs font-bold ${order.statusColor}`}
>
{order.status}
</span>
</div>
<div className="w-full h-px bg-gray-200 my-4" />
<div className="grid grid-cols-3 gap-3 w-full">
<div className="col-span-2 flex items-center gap-1 overflow-x-auto pb-2 scrollbar-thin scrollbar-thumb-gray-300 scrollbar-track-gray-100">
{order.images.map((img) => (
<div
key={img.id}
className="size-10 flex-shrink-0 rounded-lg bg-gray-200 overflow-hidden"
>
<img
src={img.src}
alt={img.alt}
className="w-full h-full object-cover"
/>
</div>
))}
</div>
<div className="col-span-1 flex flex-col items-end gap-1">
<div className="flex items-center gap-1 text-xs text-[#6B7280]">
<span>{order.time}</span>
</div>
<div className="flex items-center gap-1 text-[#223D5D] text-sm font-bold">
<span>{order.itemsCount} کالا • {order.totalPrice.toLocaleString('fa-IR')} تومان</span>
</div>
</div>
</div>
<button className="w-full mt-8 rounded-xl h-12 bg-[#223D5D] text-white cursor-pointer hover:bg-[#1a3d50] transition-colors font-medium">
مشاهده وضعیت
</button>
</div>
);
};
export default OrderItem;

View file

@ -0,0 +1,19 @@
import { ServerCrashIcon } from 'lucide-react'
import React from 'react'
const OrderServerError = () => {
return (
<div className='h-96 flex items-center justify-center p-5'>
<div className='max-w-xl w-full p-5 flex items-center justify-center flex-col gap-3'>
<div className='size-30 mb-2 bg-[#FEF2F2] flex items-center justify-center rounded-full'>
<ServerCrashIcon className='size-12 text-[#EF4444]' />
</div>
<h1 className='text-lg font-bold'>خطا در برقراری ارتباط</h1>
<p className='text-sm text-center text-[#6B7280]'>متأسفانه در دریافت اطلاعات سفارش‌ها مشکلی پیش آمده است. لطفاً اتصال اینترنت خود را بررسی کرده و مجدداً تلاش کنید.</p>
<button className='h-12 mt-4 rounded-full w-full border border-[#223D5D] bg-white text-[#223D5D] font-bold cursor-pointer'>تلاش مجدد</button>
</div>
</div>
)
}
export default OrderServerError

View file

@ -0,0 +1,47 @@
import React from 'react';
const OrdersSkeleton = () => {
return (
<div className="w-full space-y-2">
{Array.from({ length: 10 }).map((_, index) => (
<div
key={index}
className="w-full rounded-2xl min-h-32 border border-[#E5E7EB] bg-white p-4 animate-pulse"
>
<div className="flex items-center justify-between w-full gap-3">
<div className="flex items-center gap-4">
<div className="size-12 rounded-full bg-gray-200 flex-shrink-0" />
<div className="flex flex-col items-start gap-2">
<div className="w-32 h-4 bg-gray-200 rounded" />
<div className="w-24 h-3 bg-gray-200 rounded" />
</div>
</div>
<div className="w-24 h-6 bg-gray-200 rounded-full" />
</div>
<div className="w-full h-px bg-gray-200 my-4" />
<div className="grid grid-cols-3 gap-3 w-full">
<div className="col-span-2 flex items-center gap-1 overflow-x-auto pb-2">
{Array.from({ length: 3 }).map((_, imgIndex) => (
<div
key={imgIndex}
className="size-10 flex-shrink-0 rounded-lg bg-gray-200"
/>
))}
</div>
<div className="col-span-1 flex flex-col items-end gap-2">
<div className="w-20 h-3 bg-gray-200 rounded" />
<div className="w-28 h-4 bg-gray-200 rounded" />
</div>
</div>
<div className="w-full mt-8 rounded-xl h-12 bg-gray-200" />
</div>
))}
</div>
);
};
export default OrdersSkeleton;

View file

@ -8,7 +8,7 @@ const AUTH_REQUIRED_PREFIXES = [
"/seller",
"/cart",
"/checkout",
"/orders",
// "/orders",
"/order-groups",
"/addresses",
"/account",