From 7e9ab5d68fcd45253ce9bf9d4b9132f4888714cf Mon Sep 17 00:00:00 2001 From: Mohammadali Date: Sat, 12 Sep 2026 16:32:41 +0330 Subject: [PATCH] change more files --- .idea/.gitignore | 10 +++ .idea/inspectionProfiles/Project_Default.xml | 6 ++ .idea/modules.xml | 8 +++ .idea/vcs.xml | 6 ++ .idea/winofy-front.iml | 8 +++ .../(shop)/orders/(routes)/[orderId]/page.tsx | 45 +++++++------ .../orders/order-detail-content.tsx | 63 +++++++++++++++++++ src/components/orders/order-items.tsx | 57 ++++++++++++----- .../orders/order-payment-sticky.tsx | 38 +++++++---- .../orders/order-time-address-info-alert.tsx | 52 +++++++++------ src/lib/providers/order-detail-provider.tsx | 42 +++++++++++++ 11 files changed, 268 insertions(+), 67 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 .idea/winofy-front.iml create mode 100644 src/components/orders/order-detail-content.tsx create mode 100644 src/lib/providers/order-detail-provider.tsx diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..30cf57e --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,10 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Ignored default folder with query files +/queries/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..03d9549 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..ebc0d49 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/winofy-front.iml b/.idea/winofy-front.iml new file mode 100644 index 0000000..c956989 --- /dev/null +++ b/.idea/winofy-front.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/app/(customer)/(shop)/orders/(routes)/[orderId]/page.tsx b/src/app/(customer)/(shop)/orders/(routes)/[orderId]/page.tsx index fe00623..df4adf9 100644 --- a/src/app/(customer)/(shop)/orders/(routes)/[orderId]/page.tsx +++ b/src/app/(customer)/(shop)/orders/(routes)/[orderId]/page.tsx @@ -1,22 +1,29 @@ -import OrderItems from '@/components/orders/order-items' -import OrderPaymentSticky from '@/components/orders/order-payment-sticky' -import OrderStepperStatus from '@/components/orders/order-stepper-status' -import OrderTimeAddressInfoAlert from '@/components/orders/order-time-address-info-alert' -import React from 'react' +import { requireSession } from "@/lib/auth/session"; +import { getOrderGroup } from "@/lib/api/orders"; +import { OrderDetailProvider } from "@/lib/providers/order-detail-provider"; +import OrderDetailContent from "@/components/orders/order-detail-content"; -const OrderDetail = () => { - return
- -

- در حال آماده‌سازی -

- - - - - - -
+interface Props { + params: Promise<{ orderId: string }>; } -export default OrderDetail \ No newline at end of file +export default async function OrderDetailPage({ params }: Props) { + await requireSession("/login"); + + const { orderId } = await params; + + let orderGroup = null; + let error: string | null = null; + + try { + orderGroup = await getOrderGroup(orderId); + } catch (e: any) { + error = e?.message ?? "خطا در دریافت اطلاعات سفارش"; + } + + return ( + + + + ); +} \ No newline at end of file diff --git a/src/components/orders/order-detail-content.tsx b/src/components/orders/order-detail-content.tsx new file mode 100644 index 0000000..f8fdd13 --- /dev/null +++ b/src/components/orders/order-detail-content.tsx @@ -0,0 +1,63 @@ +"use client"; + +import { useOrderDetail } from "@/lib/providers/order-detail-provider"; +import OrderStepperStatus from "./order-stepper-status"; +import OrderTimeAddressInfoAlert from "./order-time-address-info-alert"; +import OrderItems from "./order-items"; +import OrderPaymentSticky from "./order-payment-sticky"; + +const STATUS_LABELS: Record = { + placed: "ثبت شد", + preparing: "در حال آماده‌سازی", + ready_to_ship: "آماده ارسال", + handed_to_courier: "ارسال شد", + delivered: "تحویل داده شد", + cancelled: "لغو شد", +}; + +export default function OrderDetailContent() { + const { data: orderGroup, error, isLoading } = useOrderDetail(); + + if (isLoading) { + return
در حال بارگذاری...
; + } + + if (error || !orderGroup) { + return ( +
+ {error ?? "سفارش یافت نشد"} +
+ ); + } + + // وضعیت اصلی رو از اولین سفارش می‌گیریم (یا می‌تونی منطق پیچیده‌تری بذاری) + const mainStatus = orderGroup.orders[0]?.status ?? "placed"; + + const statusToStep: Record = { + placed: 0, + preparing: 2, + ready_to_ship: 3, + handed_to_courier: 3, + delivered: 4, + cancelled: -1, + }; + + const currentStep = statusToStep[mainStatus] ?? 0; + const statusLabel = STATUS_LABELS[mainStatus] ?? mainStatus; + + return ( +
+

+ {statusLabel} +

+ + {mainStatus !== "cancelled" && ( + + )} + + + + +
+ ); +} \ No newline at end of file diff --git a/src/components/orders/order-items.tsx b/src/components/orders/order-items.tsx index 0d857d1..5e86468 100644 --- a/src/components/orders/order-items.tsx +++ b/src/components/orders/order-items.tsx @@ -1,20 +1,45 @@ -import React from 'react' +"use client"; -const OrderItems = () => { - return ( -
-

اقلام سفارش

+import type { OrderGroup } from "@/types/api"; +import {formatTomanPrice} from "@/lib/utils/priceUtils"; - {/* order items */} -
-
- نان سنگک - 10 عدد -
- ۱۲،۰۰۰ تومان -
-
- ) +interface Props { + order: OrderGroup; } -export default OrderItems \ No newline at end of file +const OrderItems = ({ order }: Props) => { + // همه آیتم‌های همه فروشگاه‌ها رو جمع می‌کنیم + const allItems = order.orders.flatMap((o) => + o.items.map((item) => ({ + ...item, + storeName: o.store.name, + })) + ); + + return ( +
+

اقلام سفارش

+ + {allItems.map((item) => ( +
+
+
+ {item.product_name_snapshot} + + {item.quantity.toLocaleString("fa-IR")} عدد + +
+ {order.orders.length > 1 && ( + {item.storeName} + )} +
+ + {formatTomanPrice(item.line_total)} + +
+ ))} +
+ ); +}; + +export default OrderItems; \ No newline at end of file diff --git a/src/components/orders/order-payment-sticky.tsx b/src/components/orders/order-payment-sticky.tsx index 6aec3b6..afc47bb 100644 --- a/src/components/orders/order-payment-sticky.tsx +++ b/src/components/orders/order-payment-sticky.tsx @@ -1,26 +1,40 @@ -const OrderPaymentSticky = () => { +"use client"; + +import type { OrderGroup } from "@/types/api"; +import {formatTomanPrice} from "@/lib/utils/priceUtils"; + +interface Props { + order: OrderGroup; +} + +const OrderPaymentSticky = ({ order }: Props) => { + const paymentMethodLabel: Record = { + wallet: "پرداخت از کیف پول", + online: "پرداخت آنلاین", + cash_on_delivery: "پرداخت در محل", + }; + return (
- - مبلغ پرداختی - + مبلغ پرداختی - پرداخت از کیف پول - + {paymentMethodLabel[order.payment_method] ?? order.payment_method} +
- 1000000 تومان - + {formatTomanPrice(order.total_amount)} +
+ {/* فعلاً فقط نمایش، بعداً می‌تونی دکمه لغو اضافه کنی */}
@@ -28,7 +42,7 @@ const OrderPaymentSticky = () => {
- ) -} + ); +}; -export default OrderPaymentSticky \ No newline at end of file +export default OrderPaymentSticky; \ No newline at end of file diff --git a/src/components/orders/order-time-address-info-alert.tsx b/src/components/orders/order-time-address-info-alert.tsx index a005d76..b490233 100644 --- a/src/components/orders/order-time-address-info-alert.tsx +++ b/src/components/orders/order-time-address-info-alert.tsx @@ -1,23 +1,35 @@ -import { ClockIcon, MapPinIcon } from 'lucide-react' -import React from 'react' +"use client"; -const OrderTimeAddressInfoAlert = () => { - return ( -
-
- -

- زمان تخمینی تحویل: ۳۰–۴۵ دقیقه دیگر -

-
-
- -

- نارمک، خیابان شهید دستغیب، پلاک ۱۲، واحد ۳ -

-
-
- ) +import { ClockIcon, MapPinIcon } from "lucide-react"; +import type { OrderGroup } from "@/types/api"; + +interface Props { + order: OrderGroup; } -export default OrderTimeAddressInfoAlert \ No newline at end of file +const OrderTimeAddressInfoAlert = ({ order }: Props) => { + // زمان تخمینی (فعلاً ساده) + const estimatedTime = + order.delivery_type === "express" + ? "۳۰–۴۵ دقیقه دیگر" + : order.scheduled_at + ? new Date(order.scheduled_at).toLocaleString("fa-IR") + : "زمان مشخص نشده"; + + return ( +
+
+ +

+ زمان تخمینی تحویل: {estimatedTime} +

+
+
+ +

{order.full_address}

+
+
+ ); +}; + +export default OrderTimeAddressInfoAlert; \ No newline at end of file diff --git a/src/lib/providers/order-detail-provider.tsx b/src/lib/providers/order-detail-provider.tsx new file mode 100644 index 0000000..9d95b9a --- /dev/null +++ b/src/lib/providers/order-detail-provider.tsx @@ -0,0 +1,42 @@ +"use client"; + +import {createContext, useContext, type ReactNode} from "react"; +import type {Order, OrderGroup} from "@/types/api"; + +type OrderDetailContextValue = { + data: OrderGroup | null; + error: string | null; + isLoading: boolean; +}; + +const OrderDetailContext = createContext(undefined); + +export function OrderDetailProvider({ + children, + order, + error = null, + }: { + children: ReactNode; + order: OrderGroup | null; + error?: string | null; +}) { + return ( + + {children} + + ); +} + +export function useOrderDetail() { + const ctx = useContext(OrderDetailContext); + if (ctx === undefined) { + throw new Error("useOrderDetail must be used within OrderDetailProvider"); + } + return ctx; +} \ No newline at end of file