canina/frontend/application/components/OrderTracking.tsx
parsa aghaei 7615aa0e51 fix: resolve seed encoding, search param, and wiki data source issues
- Fix seed-products.ts TS error (implicit any) and BOM handling
- Re-run full seed to restore correct Persian encoding in DB
- Fix productService query→search param mismatch
- Fix IngredientWiki hardcoded port 4000→use settingsStore
- Restore seed-products-data.json from git after accidental corruption
2026-07-11 15:40:49 +03:30

172 lines
8.9 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import React, { useState } from "react";
import { motion } from "motion/react";
import {
Package,
Truck,
CheckCircle2,
MapPin,
Search,
ChevronRight,
ChevronLeft,
Clock,
ExternalLink
} from "lucide-react";
import { useCartStore } from "../lib/store/cartStore";
import { useRouter } from 'next/navigation';
export default function OrderTracking() {
const router = useRouter();
const { orders } = useCartStore();
const [searchId, setSearchId] = useState("");
const [activeOrder, setActiveOrder] = useState(orders[0] || null);
const handleSearch = () => {
const found = orders.find(o => o.id === searchId || o.trackingNumber === searchId);
if (found) {
setActiveOrder(found);
}
};
const steps = [
{ label: 'ثبت سفارش', sub: 'تایید شده', status: 'completed', icon: <Clock className="w-5 h-5" /> },
{ label: 'آماده‌سازی در انبار', sub: 'در حال بسته‌بندی', status: 'active', icon: <Package className="w-5 h-5" /> },
{ label: 'تحویل به پست/کوریر', sub: 'ارسال شده', status: 'pending', icon: <Truck className="w-5 h-5" /> },
{ label: 'تحویل نهایی', sub: 'در مقصد', status: 'pending', icon: <CheckCircle2 className="w-5 h-5" /> },
];
return (
<div className="min-h-screen bg-medical-gray-50 py-12 px-6 font-vazir" dir="rtl">
<div className="max-w-5xl mx-auto">
{/* Mobile Navigation & Breadcrumbs */}
<div className="lg:hidden mb-12 space-y-4">
<button
onClick={() => router.back()}
className="flex items-center gap-2 text-medical-gray-500 font-bold hover:text-canina-blue transition-colors"
>
<ChevronRight className="w-5 h-5 font-vazir" />
<span>بازگشت</span>
</button>
<div className="flex items-center gap-2 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest overflow-x-auto whitespace-nowrap pb-2">
<span className="cursor-pointer hover:text-canina-blue" onClick={() => router.push('/')}>کانینا</span>
<ChevronLeft className="w-2.5 h-2.5" />
<span className="text-canina-blue">پیگیری سفارش</span>
</div>
</div>
{/* Desktop Breadcrumbs */}
<div className="hidden lg:flex items-center gap-2 text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-12">
<span className="cursor-pointer hover:text-canina-blue" onClick={() => router.push('/')}>خانه</span>
<ChevronLeft className="w-2.5 h-2.5" />
<span className="text-canina-blue">رهگیری هوشمند محموله</span>
</div>
<div className="flex items-center justify-between mb-12">
<h2 className="text-3xl font-black text-medical-gray-900 italic">وضعیت لحظهای سفارش</h2>
</div>
{/* Search Bar */}
<div className="bg-white rounded-[2.5rem] p-8 border border-medical-gray-200 shadow-sm mb-10">
<div className="flex flex-col md:flex-row gap-4">
<div className="flex-1 relative">
<Search className="absolute right-4 top-1/2 -translate-y-1/2 w-5 h-5 text-medical-gray-400" />
<input
type="text"
placeholder="شماره سفارش (CN-XXXXX) یا کد رهگیری پستی را وارد کنید..."
value={searchId}
onChange={(e) => setSearchId(e.target.value)}
className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 pr-12 pl-6 text-sm focus:ring-2 focus:ring-canina-blue/20 outline-none font-mono"
/>
</div>
<button
onClick={handleSearch}
className="bg-medical-gray-900 text-white px-10 py-4 rounded-2xl font-black italic hover:bg-canina-blue transition-all"
>
رهگیری آنی
</button>
</div>
</div>
{activeOrder ? (
<div className="grid lg:grid-cols-12 gap-10">
{/* Status Timeline */}
<div className="lg:col-span-8 bg-white rounded-[3rem] p-10 border border-medical-gray-200 shadow-sm">
<div className="flex items-center justify-between mb-12">
<div>
<p className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-1">کد رهگیری پستی</p>
<p className="text-sm font-mono font-bold text-canina-blue">{activeOrder.trackingNumber}</p>
</div>
<div className="text-left">
<p className="text-[10px] font-black text-medical-gray-400 uppercase tracking-widest mb-1">تاریخ ثبت</p>
<p className="text-sm font-bold text-medical-gray-900">{new Date(activeOrder.date).toLocaleDateString('fa-IR')}</p>
</div>
</div>
<div className="relative space-y-12 pr-6">
<div className="absolute top-0 right-[23px] bottom-0 w-0.5 bg-medical-gray-100" />
{steps.map((step, i) => (
<div key={i} className={`relative flex items-center gap-8 ${step.status === 'pending' ? 'opacity-30' : ''}`}>
<div className={`w-12 h-12 rounded-2xl flex items-center justify-center z-10 shadow-sm transition-all ${step.status === 'completed' ? 'bg-green-600 text-white' : step.status === 'active' ? 'bg-canina-blue text-white ring-8 ring-canina-blue/10 scale-110' : 'bg-medical-gray-50 text-medical-gray-300 border border-medical-gray-100'}`}>
{step.status === 'completed' ? <CheckCircle2 className="w-6 h-6" /> : step.icon}
</div>
<div>
<h4 className="font-black text-medical-gray-900">{step.label}</h4>
<p className="text-xs font-bold text-medical-gray-500">{step.sub}</p>
</div>
</div>
))}
</div>
</div>
{/* Sidebar Details */}
<div className="lg:col-span-4 space-y-6">
<div className="bg-medical-gray-900 rounded-[2.5rem] p-8 text-white">
<h3 className="text-lg font-black italic mb-6 border-b border-white/10 pb-4">محتویات محموله</h3>
<div className="space-y-4">
{activeOrder.items.map(item => (
<div key={item.product.id} className="flex justify-between items-center text-xs font-bold">
<span className="text-white/60">{item.product.name}</span>
<span>{item.quantity} عدد</span>
</div>
))}
</div>
<div className="mt-8 pt-6 border-t border-white/10 flex justify-between items-center font-black">
<span className="text-xs italic">مجموع فاکتور</span>
<span className="text-lg text-canina-blue">{activeOrder.total.toLocaleString()} تومان</span>
</div>
</div>
<div className="bg-white rounded-[2rem] p-6 border border-medical-gray-200">
<div className="flex items-center gap-3 mb-4">
<div className="w-10 h-10 bg-canina-blue/10 text-canina-blue rounded-xl flex items-center justify-center">
<MapPin className="w-5 h-5" />
</div>
<h4 className="text-xs font-black italic">آدرس تحویل</h4>
</div>
<p className="text-[10px] font-bold text-medical-gray-500 leading-relaxed mb-4">
تهران، خیابان ولیعصر، بالاتر از میدان ونک، بنبست آفتاب، پلاک ۱۲، واحد ۳
</p>
<button className="w-full py-3 bg-medical-gray-50 text-medical-gray-900 rounded-xl text-[10px] font-black flex items-center justify-center gap-2 hover:bg-medical-gray-100 transition-all">
<ExternalLink className="w-3 h-3" />
مشاهده در نقشه
</button>
</div>
</div>
</div>
) : (
<div className="text-center py-20 bg-white rounded-[3rem] border border-dashed border-medical-gray-200">
<div className="w-20 h-20 bg-medical-gray-50 rounded-full flex items-center justify-center mx-auto mb-6 text-medical-gray-300">
<Package className="w-10 h-10" />
</div>
<p className="text-medical-gray-500 font-bold">سفارشی یافت نشد. لطفاً شماره سفارش صحیح را وارد کنید.</p>
</div>
)}
</div>
</div>
);
}