dynomic orders first commit
This commit is contained in:
parent
464f2b34a2
commit
4e3eb2de9f
6 changed files with 234 additions and 156 deletions
29
package-lock.json
generated
29
package-lock.json
generated
|
|
@ -292,9 +292,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@emnapi/wasi-threads": {
|
"node_modules/@emnapi/wasi-threads": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.3.tgz",
|
||||||
"integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==",
|
"integrity": "sha512-ELEBe8PsLvvJ6QMr0zLt8ffvOHW/dc1m3CEzNMg7aJUv3bMaoDtw2TXyDAwkYBuroxxuHEwhRTLJSe5sya547g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
|
|
@ -2996,6 +2996,18 @@
|
||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@unrs/resolver-binding-wasm32-wasi/node_modules/@emnapi/core": {
|
||||||
|
"version": "1.10.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz",
|
||||||
|
"integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@emnapi/wasi-threads": "1.2.1",
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@unrs/resolver-binding-wasm32-wasi/node_modules/@emnapi/runtime": {
|
"node_modules/@unrs/resolver-binding-wasm32-wasi/node_modules/@emnapi/runtime": {
|
||||||
"version": "1.10.0",
|
"version": "1.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz",
|
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz",
|
||||||
|
|
@ -3007,6 +3019,17 @@
|
||||||
"tslib": "^2.4.0"
|
"tslib": "^2.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@unrs/resolver-binding-wasm32-wasi/node_modules/@emnapi/wasi-threads": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@unrs/resolver-binding-win32-arm64-msvc": {
|
"node_modules/@unrs/resolver-binding-win32-arm64-msvc": {
|
||||||
"version": "1.12.2",
|
"version": "1.12.2",
|
||||||
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.12.2.tgz",
|
"resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.12.2.tgz",
|
||||||
|
|
|
||||||
|
|
@ -1,76 +1,43 @@
|
||||||
import Link from "next/link";
|
"use client";
|
||||||
import { requireSession } from "@/lib/auth/session";
|
|
||||||
import { getOrderGroups } from "@/lib/api/orders";
|
import { useOrders } from "@/lib/providers/orders-provider";
|
||||||
import { PAYMENT_STATUS_LABELS_FA } from "@/lib/order-status";
|
|
||||||
import OrderItem from "@/components/orders/order-item";
|
import OrderItem from "@/components/orders/order-item";
|
||||||
import OrderEmpty from "@/components/orders/order-empty";
|
import OrderEmpty from "@/components/orders/order-empty";
|
||||||
import OrderServerError from "@/components/orders/order-server-error";
|
import OrderServerError from "@/components/orders/order-server-error";
|
||||||
import OrdersSkeleton from "@/components/orders/orders-skeleton";
|
import OrdersSkeleton from "@/components/orders/orders-skeleton";
|
||||||
import OrderHeader from "@/components/orders/order-header";
|
|
||||||
|
|
||||||
export default async function OrdersPage() {
|
export default function OrdersPage() {
|
||||||
return <section>
|
const { data, error, isLoading } = useOrders();
|
||||||
{/* <OrderEmpty /> */}
|
|
||||||
{/* <OrderServerError /> */}
|
|
||||||
{
|
|
||||||
Array.from({ length: 20 }, (_, index) => <OrderItem />)
|
|
||||||
}
|
|
||||||
{/* <OrderEmpty />
|
|
||||||
<OrderServerError />
|
|
||||||
<OrdersSkeleton /> */}
|
|
||||||
|
|
||||||
{/* <OrdersSkeleton /> */}
|
if (isLoading) {
|
||||||
{/* <OrderServerError /> */}
|
return (
|
||||||
{/* <OrderEmpty /> */}
|
<section className="p-4">
|
||||||
{/* */}
|
<OrdersSkeleton />
|
||||||
|
|
||||||
{/* <OrderItem />
|
|
||||||
<OrderItem />
|
|
||||||
<OrderItem />
|
|
||||||
<OrderItem />
|
|
||||||
<OrderItem />
|
|
||||||
<OrderItem />
|
|
||||||
<OrderItem />
|
|
||||||
<OrderItem />
|
|
||||||
<OrderItem />
|
|
||||||
<OrderItem />
|
|
||||||
<OrderItem />
|
|
||||||
<OrderItem /> */}
|
|
||||||
</section>
|
</section>
|
||||||
// await requireSession("/orders");
|
);
|
||||||
// const orderGroups = await getOrderGroups();
|
}
|
||||||
|
|
||||||
// return (
|
if (error) {
|
||||||
// <main className="mx-auto flex w-full max-w-2xl flex-1 flex-col gap-4 px-4 py-6">
|
return (
|
||||||
// <h1 className="text-lg font-bold">سفارشهای من</h1>
|
<section className="p-4">
|
||||||
|
<OrderServerError />
|
||||||
// {orderGroups.length === 0 && <p className="text-sm text-muted-foreground">هنوز سفارشی ثبت نکردهاید.</p>}
|
</section>
|
||||||
|
);
|
||||||
// <div className="flex flex-col gap-3">
|
}
|
||||||
// {orderGroups.map((group) => (
|
|
||||||
// <Link
|
if (!data || data.length === 0) {
|
||||||
// key={group.uuid}
|
return (
|
||||||
// href={`/order-groups/${group.uuid}`}
|
<section className="p-4">
|
||||||
// className="flex flex-col gap-2 rounded-2xl border border-border p-4"
|
<OrderEmpty />
|
||||||
// >
|
</section>
|
||||||
// <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>
|
return (
|
||||||
// <div className="flex flex-wrap gap-1 text-sm">
|
<section className="p-4 space-y-3">
|
||||||
// {group.orders.map((order) => (
|
{data.map((group) => (
|
||||||
// <span key={order.uuid} className="rounded-full bg-muted px-2 py-0.5">
|
<OrderItem key={group.uuid} orderGroup={group} />
|
||||||
// {order.store.name}
|
))}
|
||||||
// </span>
|
</section>
|
||||||
// ))}
|
);
|
||||||
// </div>
|
|
||||||
// <div className="flex justify-between font-semibold">
|
|
||||||
// <span>مجموع</span>
|
|
||||||
// <span>{group.total_amount.toLocaleString("fa-IR")} تومان</span>
|
|
||||||
// </div>
|
|
||||||
// </Link>
|
|
||||||
// ))}
|
|
||||||
// </div>
|
|
||||||
// </main>
|
|
||||||
// );
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,15 +1,30 @@
|
||||||
import OrderHeader from '@/components/orders/order-header';
|
import OrderHeader from '@/components/orders/order-header';
|
||||||
import React from 'react'
|
import { requireSession } from "@/lib/auth/session";
|
||||||
|
import { getOrderGroups } from "@/lib/api/orders";
|
||||||
|
import { OrdersProvider } from "@/lib/providers/orders-provider";
|
||||||
|
|
||||||
interface OrderLayoutInterface {
|
interface OrderLayoutInterface {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const OrderLayout = async ({ children }: OrderLayoutInterface) => {
|
export default async function OrderLayout({ children }: OrderLayoutInterface) {
|
||||||
return <main className='max-w-5xl w-full mx-auto p-0'>
|
await requireSession("/login");
|
||||||
<OrderHeader />
|
|
||||||
{children}
|
let orderGroups: Awaited<ReturnType<typeof getOrderGroups>> | null = null;
|
||||||
</main>
|
let error: string | null = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
orderGroups = await getOrderGroups();
|
||||||
|
} catch (e: any) {
|
||||||
|
error = e?.message ?? "خطا در دریافت سفارشها";
|
||||||
}
|
}
|
||||||
|
|
||||||
export default OrderLayout
|
return (
|
||||||
|
<main className="max-w-5xl w-full mx-auto p-0">
|
||||||
|
<OrdersProvider orderGroups={orderGroups} error={error}>
|
||||||
|
<OrderHeader />
|
||||||
|
{children}
|
||||||
|
</OrdersProvider>
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -1,90 +1,121 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import React from 'react';
|
import type { OrderGroup } from "@/types/api";
|
||||||
|
import { PAYMENT_STATUS_LABELS_FA } from "@/lib/order-status"; // اگه داری
|
||||||
|
|
||||||
const OrderItem = () => {
|
interface OrderItemProps {
|
||||||
|
orderGroup: OrderGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
const OrderItem = ({ orderGroup }: OrderItemProps) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const goToOrderDetail = () => router.push(`/orders/uuid`);
|
const goToOrderDetail = () => {
|
||||||
|
router.push(`/orders/${orderGroup.uuid}`); // یا مسیر واقعی جزئیات
|
||||||
const statusClasses: Record<string, string> = {
|
|
||||||
'ارسال شد': 'bg-teal-bg text-primary-action',
|
|
||||||
'در حال آمادهسازی': 'bg-[#E5F3FF] text-[#007BFF]',
|
|
||||||
'در انتظار تأیید': 'bg-[#FFF4E5] text-[#E67E22]',
|
|
||||||
'آماده تحویل حضوری': 'bg-[#EBE5FF] text-[#734DBF]',
|
|
||||||
'لغو شد': 'bg-[#FCE8E8] text-error',
|
|
||||||
'تحویل داده شد': 'bg-emerald-bg text-success',
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const order = {
|
// وضعیت کلی (از اولین سفارش یا payment_status)
|
||||||
id: 1,
|
const mainOrder = orderGroup.orders[0];
|
||||||
restaurant: 'فستفود برگر',
|
const status = mainOrder?.status ?? "placed";
|
||||||
description: 'ساندویچ + نوشیدنی',
|
|
||||||
status: 'آماده تحویل حضوری',
|
// مپ وضعیت به فارسی و کلاس
|
||||||
time: 'امروز، 11:30',
|
const statusMap: Record<string, { label: string; className: string }> = {
|
||||||
itemsCount: 3,
|
placed: { label: "ثبت شده", className: "bg-[#FFF4E5] text-[#E67E22]" },
|
||||||
totalPrice: 45000,
|
preparing: { label: "در حال آمادهسازی", className: "bg-[#E5F3FF] text-[#007BFF]" },
|
||||||
images: Array.from({ length: 5 }, (_, i) => ({
|
ready_to_ship: { label: "آماده ارسال", className: "bg-[#EBE5FF] text-[#734DBF]" },
|
||||||
id: i,
|
handed_to_courier: { label: "ارسال شد", className: "bg-teal-bg text-primary-action" },
|
||||||
src: `https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQqIof_DOo6I5-oOLJ1V9_HPfSudXfhewy_5C5Ry7YOO-UXSZ1jvK7-0hw&s=10`,
|
delivered: { label: "تحویل داده شد", className: "bg-emerald-bg text-success" },
|
||||||
alt: `product-${i}`,
|
cancelled: { label: "لغو شد", className: "bg-[#FCE8E8] text-error" },
|
||||||
})),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const currentStatus = statusMap[status] ?? { label: status, className: "bg-gray-100 text-gray-700" };
|
||||||
|
|
||||||
|
// نام فروشگاهها
|
||||||
|
const storeNames = orderGroup.orders.map(o => o.store.name).join(" + ");
|
||||||
|
|
||||||
|
// تعداد کل کالاها
|
||||||
|
const totalItems = orderGroup.orders.reduce((sum, order) => {
|
||||||
|
return sum + order.items.reduce((s, item) => s + item.quantity, 0);
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
// تصاویر محصولات (حداکثر ۵ تا)
|
||||||
|
const images = orderGroup.orders
|
||||||
|
.flatMap(order => order.items)
|
||||||
|
.slice(0, 5)
|
||||||
|
.map((item, index) => ({
|
||||||
|
id: index,
|
||||||
|
src: "", // اگر تصویر محصول داری اینجا بذار، فعلاً خالی
|
||||||
|
alt: item.product_name_snapshot,
|
||||||
|
}));
|
||||||
|
|
||||||
|
// تاریخ و ساعت
|
||||||
|
const createdDate = new Date(orderGroup.created_at);
|
||||||
|
const timeText = createdDate.toLocaleDateString("fa-IR", {
|
||||||
|
weekday: "long",
|
||||||
|
hour: "2-digit",
|
||||||
|
minute: "2-digit",
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full rounded-2xl min-h-32 border border-gray-300 bg-background p-4 mb-2">
|
<div className="w-full rounded-2xl min-h-32 border border-gray-300 bg-background p-4 mb-2">
|
||||||
|
{/* هدر */}
|
||||||
<div className="flex items-center justify-between w-full gap-3">
|
<div className="flex items-center justify-between w-full gap-3">
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<div className="size-12 rounded-full bg-gradient-to-br from-primary-action to-primary flex items-center justify-center text-primary-foreground font-bold text-lg">
|
<div className="size-12 rounded-full bg-gradient-to-br from-primary-action to-primary flex items-center justify-center text-primary-foreground font-bold text-lg overflow-hidden">
|
||||||
{order.restaurant.charAt(0)}
|
{mainOrder?.store.logo_url ? (
|
||||||
|
<img src={mainOrder.store.logo_url} alt={mainOrder.store.name} className="w-full h-full object-cover" />
|
||||||
|
) : (
|
||||||
|
mainOrder?.store.name?.charAt(0) ?? "س"
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col items-start">
|
<div className="flex flex-col items-start">
|
||||||
<h2 className="text-md font-bold text-gray-800">{order.restaurant}</h2>
|
<h2 className="text-md font-bold text-gray-800 line-clamp-1">{storeNames}</h2>
|
||||||
<p className="text-sm text-gray-600">{order.description}</p>
|
<p className="text-sm text-gray-600 line-clamp-1">
|
||||||
|
{orderGroup.orders.length > 1
|
||||||
|
? `${orderGroup.orders.length} فروشگاه`
|
||||||
|
: mainOrder?.items[0]?.product_name_snapshot ?? "سفارش"}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span
|
<span className={`flex items-center justify-center px-3 py-1 rounded-full text-xs font-bold ${currentStatus.className}`}>
|
||||||
className={`flex items-center justify-center px-3 py-1 rounded-full text-xs font-bold ${statusClasses[order.status]
|
{currentStatus.label}
|
||||||
}`}
|
|
||||||
>
|
|
||||||
{order.status}
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="w-full h-px bg-gray-200 my-4" />
|
<div className="w-full h-px bg-gray-200 my-4" />
|
||||||
|
|
||||||
|
{/* پایین کارت */}
|
||||||
<div className="grid grid-cols-3 gap-3 w-full">
|
<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">
|
<div className="col-span-2 flex items-center gap-1 overflow-x-auto pb-2">
|
||||||
{order.images.map((img) => (
|
{images.length > 0 ? (
|
||||||
<div
|
images.map((img) => (
|
||||||
key={img.id}
|
<div key={img.id} className="size-10 flex-shrink-0 rounded-lg bg-gray-200 overflow-hidden">
|
||||||
className="size-10 flex-shrink-0 rounded-lg bg-gray-200 overflow-hidden"
|
{img.src ? (
|
||||||
>
|
<img src={img.src} alt={img.alt} className="w-full h-full object-cover" />
|
||||||
<img
|
) : (
|
||||||
src={img.src}
|
<div className="w-full h-full flex items-center justify-center text-xs text-gray-400">
|
||||||
alt={img.alt}
|
{img.alt.charAt(0)}
|
||||||
className="w-full h-full object-cover"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
))}
|
)}
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<div className="text-sm text-gray-500">بدون تصویر</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="col-span-1 flex flex-col items-end gap-1">
|
<div className="col-span-1 flex flex-col items-end gap-1">
|
||||||
<div className="flex items-center gap-1 text-xs text-gray-600">
|
<div className="text-xs text-gray-600">{timeText}</div>
|
||||||
<span>{order.time}</span>
|
<div className="text-primary-action text-sm font-bold text-left">
|
||||||
</div>
|
{totalItems} کالا • {orderGroup.total_amount.toLocaleString("fa-IR")} تومان
|
||||||
<div className="flex items-center gap-1 text-primary-action text-sm text-left font-bold">
|
|
||||||
<span>
|
|
||||||
{order.itemsCount} کالا • {order.totalPrice.toLocaleString('fa-IR')} تومان
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
className="w-full mt-8 rounded-xl h-12 bg-primary-action text-primary-foreground cursor-pointer hover:bg-primary-action/90 transition-colors font-medium"
|
className="w-full mt-6 rounded-xl h-12 bg-primary-action text-primary-foreground cursor-pointer hover:bg-primary-action/90 transition-colors font-medium"
|
||||||
onClick={goToOrderDetail}
|
onClick={goToOrderDetail}
|
||||||
>
|
>
|
||||||
مشاهده وضعیت
|
مشاهده وضعیت
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import "server-only";
|
import "server-only";
|
||||||
import { getValidSession } from "@/lib/auth/session";
|
import { getValidSession } from "@/lib/auth/session";
|
||||||
import { ApiError, type WinofyErrorDetails } from "./errors";
|
import { ApiError, type WinofyErrorDetails } from "./errors";
|
||||||
import { logWinofyRequest, logWinofyResponse } from "./dev-logger";
|
// import { logWinofyRequest, logWinofyResponse } from "./dev-logger";
|
||||||
|
|
||||||
const BASE_URL = process.env.GOOYAL_ACCOUNTS_BASE_URL!;
|
const BASE_URL = process.env.GOOYAL_ACCOUNTS_BASE_URL!;
|
||||||
|
|
||||||
|
|
@ -35,7 +35,7 @@ export async function gooyalFetch<T>(path: string, options: GooyalFetchOptions =
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logWinofyRequest?.(method, url.toString(), body);
|
// logWinofyRequest?.(method, url.toString(), body);
|
||||||
|
|
||||||
const res = await fetch(url.toString(), {
|
const res = await fetch(url.toString(), {
|
||||||
...rest,
|
...rest,
|
||||||
|
|
@ -45,12 +45,12 @@ export async function gooyalFetch<T>(path: string, options: GooyalFetchOptions =
|
||||||
});
|
});
|
||||||
|
|
||||||
if (res.status === 204) {
|
if (res.status === 204) {
|
||||||
logWinofyResponse?.(method, url.toString(), res.status, null);
|
// logWinofyResponse?.(method, url.toString(), res.status, null);
|
||||||
return undefined as T;
|
return undefined as T;
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await res.json().catch(() => null);
|
const data = await res.json().catch(() => null);
|
||||||
logWinofyResponse?.(method, url.toString(), res.status, data);
|
// logWinofyResponse?.(method, url.toString(), res.status, data);
|
||||||
|
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
const envelope = data as { status_message?: string; details?: WinofyErrorDetails } | null;
|
const envelope = data as { status_message?: string; details?: WinofyErrorDetails } | null;
|
||||||
|
|
|
||||||
42
src/lib/providers/orders-provider.tsx
Normal file
42
src/lib/providers/orders-provider.tsx
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import { createContext, useContext, type ReactNode } from "react";
|
||||||
|
import type { OrderGroup } from "@/types/api";
|
||||||
|
|
||||||
|
type OrdersContextValue = {
|
||||||
|
data: OrderGroup[] | null;
|
||||||
|
error: string | null;
|
||||||
|
isLoading: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
const OrdersContext = createContext<OrdersContextValue | undefined>(undefined);
|
||||||
|
|
||||||
|
export function OrdersProvider({
|
||||||
|
children,
|
||||||
|
orderGroups,
|
||||||
|
error = null,
|
||||||
|
}: {
|
||||||
|
children: ReactNode;
|
||||||
|
orderGroups: OrderGroup[] | null;
|
||||||
|
error?: string | null;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<OrdersContext.Provider
|
||||||
|
value={{
|
||||||
|
data: orderGroups,
|
||||||
|
error,
|
||||||
|
isLoading: false,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</OrdersContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useOrders() {
|
||||||
|
const ctx = useContext(OrdersContext);
|
||||||
|
if (ctx === undefined) {
|
||||||
|
throw new Error("useOrders must be used within OrdersProvider");
|
||||||
|
}
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue