add empty order component & server error component & orders skeleton & order item
This commit is contained in:
parent
17ee08bd5f
commit
41e86d30b3
6 changed files with 216 additions and 34 deletions
|
|
@ -2,42 +2,65 @@ import Link from "next/link";
|
||||||
import { requireSession } from "@/lib/auth/session";
|
import { requireSession } from "@/lib/auth/session";
|
||||||
import { getOrderGroups } from "@/lib/api/orders";
|
import { getOrderGroups } from "@/lib/api/orders";
|
||||||
import { PAYMENT_STATUS_LABELS_FA } from "@/lib/order-status";
|
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() {
|
export default async function OrdersPage() {
|
||||||
await requireSession("/orders");
|
return <main className="max-w-5xl w-full mx-auto p-4">
|
||||||
const orderGroups = await getOrderGroups();
|
<OrdersSkeleton />
|
||||||
|
{/* <OrderServerError /> */}
|
||||||
|
{/* <OrderEmpty /> */}
|
||||||
|
{/* */}
|
||||||
|
|
||||||
return (
|
{/* <OrderItem />
|
||||||
<main className="mx-auto flex w-full max-w-2xl flex-1 flex-col gap-4 px-4 py-6">
|
<OrderItem />
|
||||||
<h1 className="text-lg font-bold">سفارشهای من</h1>
|
<OrderItem />
|
||||||
|
<OrderItem />
|
||||||
|
<OrderItem />
|
||||||
|
<OrderItem />
|
||||||
|
<OrderItem />
|
||||||
|
<OrderItem />
|
||||||
|
<OrderItem />
|
||||||
|
<OrderItem />
|
||||||
|
<OrderItem />
|
||||||
|
<OrderItem /> */}
|
||||||
|
</main>
|
||||||
|
// await requireSession("/orders");
|
||||||
|
// const orderGroups = await getOrderGroups();
|
||||||
|
|
||||||
{orderGroups.length === 0 && <p className="text-sm text-muted-foreground">هنوز سفارشی ثبت نکردهاید.</p>}
|
// 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>
|
||||||
|
|
||||||
<div className="flex flex-col gap-3">
|
// {orderGroups.length === 0 && <p className="text-sm text-muted-foreground">هنوز سفارشی ثبت نکردهاید.</p>}
|
||||||
{orderGroups.map((group) => (
|
|
||||||
<Link
|
// <div className="flex flex-col gap-3">
|
||||||
key={group.uuid}
|
// {orderGroups.map((group) => (
|
||||||
href={`/order-groups/${group.uuid}`}
|
// <Link
|
||||||
className="flex flex-col gap-2 rounded-2xl border border-border p-4"
|
// key={group.uuid}
|
||||||
>
|
// href={`/order-groups/${group.uuid}`}
|
||||||
<div className="flex justify-between text-sm text-muted-foreground">
|
// className="flex flex-col gap-2 rounded-2xl border border-border p-4"
|
||||||
<span>{new Date(group.created_at).toLocaleDateString("fa-IR")}</span>
|
// >
|
||||||
<span>{PAYMENT_STATUS_LABELS_FA[group.payment_status]}</span>
|
// <div className="flex justify-between text-sm text-muted-foreground">
|
||||||
</div>
|
// <span>{new Date(group.created_at).toLocaleDateString("fa-IR")}</span>
|
||||||
<div className="flex flex-wrap gap-1 text-sm">
|
// <span>{PAYMENT_STATUS_LABELS_FA[group.payment_status]}</span>
|
||||||
{group.orders.map((order) => (
|
// </div>
|
||||||
<span key={order.uuid} className="rounded-full bg-muted px-2 py-0.5">
|
// <div className="flex flex-wrap gap-1 text-sm">
|
||||||
{order.store.name}
|
// {group.orders.map((order) => (
|
||||||
</span>
|
// <span key={order.uuid} className="rounded-full bg-muted px-2 py-0.5">
|
||||||
))}
|
// {order.store.name}
|
||||||
</div>
|
// </span>
|
||||||
<div className="flex justify-between font-semibold">
|
// ))}
|
||||||
<span>مجموع</span>
|
// </div>
|
||||||
<span>{group.total_amount.toLocaleString("fa-IR")} تومان</span>
|
// <div className="flex justify-between font-semibold">
|
||||||
</div>
|
// <span>مجموع</span>
|
||||||
</Link>
|
// <span>{group.total_amount.toLocaleString("fa-IR")} تومان</span>
|
||||||
))}
|
// </div>
|
||||||
</div>
|
// </Link>
|
||||||
</main>
|
// ))}
|
||||||
);
|
// </div>
|
||||||
|
// </main>
|
||||||
|
// );
|
||||||
}
|
}
|
||||||
|
|
|
||||||
19
src/components/orders/OrderEmpty.tsx
Normal file
19
src/components/orders/OrderEmpty.tsx
Normal 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
|
||||||
74
src/components/orders/OrderItem.tsx
Normal file
74
src/components/orders/OrderItem.tsx
Normal 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;
|
||||||
19
src/components/orders/OrderServerError.tsx
Normal file
19
src/components/orders/OrderServerError.tsx
Normal 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
|
||||||
47
src/components/orders/OrdersSkeleton.tsx
Normal file
47
src/components/orders/OrdersSkeleton.tsx
Normal 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;
|
||||||
|
|
@ -8,7 +8,7 @@ const AUTH_REQUIRED_PREFIXES = [
|
||||||
"/seller",
|
"/seller",
|
||||||
"/cart",
|
"/cart",
|
||||||
"/checkout",
|
"/checkout",
|
||||||
"/orders",
|
// "/orders",
|
||||||
"/order-groups",
|
"/order-groups",
|
||||||
"/addresses",
|
"/addresses",
|
||||||
"/account",
|
"/account",
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue