194 lines
7.8 KiB
TypeScript
194 lines
7.8 KiB
TypeScript
|
|
import { mdiPackageVariantClosed, mdiArrowLeft } from '@mdi/js';
|
|
import Head from 'next/head';
|
|
import React, { ReactElement, useEffect, useState } from 'react';
|
|
import { useRouter } from 'next/router';
|
|
import CardBox from '../components/CardBox';
|
|
import LayoutAuthenticated from '../layouts/Authenticated';
|
|
import SectionMain from '../components/SectionMain';
|
|
import SectionTitleLineWithButton from '../components/SectionTitleLineWithButton';
|
|
import { getPageTitle } from '../config';
|
|
import axios from 'axios';
|
|
import BaseButton from '../components/BaseButton';
|
|
import { useTranslation } from 'next-i18next';
|
|
import Link from 'next/link';
|
|
|
|
const OrderDetailsPage = () => {
|
|
const router = useRouter();
|
|
const { id } = router.query;
|
|
const { t } = useTranslation('common');
|
|
const [order, setOrder] = useState<any>(null);
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
useEffect(() => {
|
|
if (!id) return;
|
|
|
|
const fetchOrder = async () => {
|
|
try {
|
|
const response = await axios.get(`/orders/${id}`);
|
|
setOrder(response.data);
|
|
} catch (error) {
|
|
console.error('Error fetching order:', error);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
fetchOrder();
|
|
}, [id]);
|
|
|
|
if (loading) {
|
|
return (
|
|
<LayoutAuthenticated>
|
|
<SectionMain>
|
|
<div className="text-center py-10">Loading order details...</div>
|
|
</SectionMain>
|
|
</LayoutAuthenticated>
|
|
);
|
|
}
|
|
|
|
if (!order) {
|
|
return (
|
|
<LayoutAuthenticated>
|
|
<SectionMain>
|
|
<div className="text-center py-10">Order not found.</div>
|
|
</SectionMain>
|
|
</LayoutAuthenticated>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<Head>
|
|
<title>{getPageTitle(`Order #${order.order_number || order.id.slice(0, 8)}`)}</title>
|
|
</Head>
|
|
<SectionMain>
|
|
<SectionTitleLineWithButton
|
|
icon={mdiPackageVariantClosed}
|
|
title={`Order #${order.order_number || order.id.slice(0, 8)}`}
|
|
main
|
|
>
|
|
<Link href="/my-orders">
|
|
<BaseButton icon={mdiArrowLeft} label="Back to Orders" color="white" small />
|
|
</Link>
|
|
</SectionTitleLineWithButton>
|
|
|
|
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
|
{/* Order Summary */}
|
|
<div className="lg:col-span-2 space-y-6">
|
|
<CardBox title="Items Ordered">
|
|
<div className="divide-y">
|
|
{order.order_items_order?.map((item: any) => (
|
|
<div key={item.id} className="py-4 flex items-center">
|
|
<div className="h-16 w-16 bg-gray-100 rounded overflow-hidden flex-shrink-0">
|
|
{item.product?.image && item.product.image.length > 0 ? (
|
|
<img
|
|
src={item.product.image[0].downloadUrl || item.product.image[0].publicUrl}
|
|
alt={item.product.name}
|
|
className="h-full w-full object-cover"
|
|
/>
|
|
) : (
|
|
<div className="h-full w-full flex items-center justify-center text-gray-400">
|
|
No Image
|
|
</div>
|
|
)}
|
|
</div>
|
|
<div className="ml-4 flex-grow">
|
|
<h4 className="font-semibold">{item.product?.name || 'Unknown Product'}</h4>
|
|
<p className="text-sm text-gray-500">Qty: {item.quantity}</p>
|
|
</div>
|
|
<div className="text-right">
|
|
<p className="font-bold">${parseFloat(item.price).toFixed(2)}</p>
|
|
<p className="text-xs text-gray-500">ea</p>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
<div className="mt-6 border-t pt-4 space-y-2">
|
|
<div className="flex justify-between">
|
|
<span className="text-gray-600">Subtotal</span>
|
|
<span className="font-medium">${parseFloat(order.total).toFixed(2)}</span>
|
|
</div>
|
|
<div className="flex justify-between">
|
|
<span className="text-gray-600">Shipping</span>
|
|
<span className="font-medium text-green-600">Free</span>
|
|
</div>
|
|
<div className="flex justify-between border-t pt-2 text-xl">
|
|
<span className="font-bold">Total</span>
|
|
<span className="font-bold">${parseFloat(order.total).toFixed(2)}</span>
|
|
</div>
|
|
</div>
|
|
</CardBox>
|
|
|
|
<CardBox title="Delivery Information">
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
<div>
|
|
<h4 className="font-bold text-gray-700 mb-2 uppercase text-xs tracking-wider">Shipping Address</h4>
|
|
<p className="text-gray-600 whitespace-pre-wrap">{order.shipping_address}</p>
|
|
</div>
|
|
<div>
|
|
<h4 className="font-bold text-gray-700 mb-2 uppercase text-xs tracking-wider">Order Status</h4>
|
|
<div className={`inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold uppercase ${
|
|
order.status === 'delivered' ? 'bg-green-100 text-green-800' :
|
|
order.status === 'cancelled' ? 'bg-red-100 text-red-800' :
|
|
'bg-blue-100 text-blue-800'
|
|
}`}>
|
|
{order.status || 'Pending'}
|
|
</div>
|
|
<div className="mt-4">
|
|
<h4 className="font-bold text-gray-700 mb-2 uppercase text-xs tracking-wider">Placed On</h4>
|
|
<p className="text-gray-600">{new Date(order.createdAt).toLocaleString()}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</CardBox>
|
|
</div>
|
|
|
|
{/* Side Info */}
|
|
<div className="space-y-6">
|
|
<CardBox title="Payment Details">
|
|
<div className="space-y-4">
|
|
<div>
|
|
<h4 className="font-bold text-gray-700 mb-1 uppercase text-xs tracking-wider">Payment Status</h4>
|
|
<div className={`inline-flex items-center px-2 py-0.5 rounded text-xs font-bold uppercase ${
|
|
order.payment_status === 'paid' ? 'bg-green-100 text-green-700' :
|
|
'bg-yellow-100 text-yellow-700'
|
|
}`}>
|
|
{order.payment_status || 'Unpaid'}
|
|
</div>
|
|
</div>
|
|
{order.payments_order?.[0] && (
|
|
<div>
|
|
<h4 className="font-bold text-gray-700 mb-1 uppercase text-xs tracking-wider">Payment Method</h4>
|
|
<p className="text-gray-600">
|
|
Stripe Payment
|
|
</p>
|
|
</div>
|
|
)}
|
|
<div>
|
|
<h4 className="font-bold text-gray-700 mb-1 uppercase text-xs tracking-wider">Billing Address</h4>
|
|
<p className="text-gray-600 text-sm whitespace-pre-wrap">{order.billing_address || order.shipping_address}</p>
|
|
</div>
|
|
</div>
|
|
</CardBox>
|
|
|
|
<CardBox className="bg-blue-50 dark:bg-dark-700">
|
|
<h4 className="font-bold mb-2">Need Help?</h4>
|
|
<p className="text-sm text-gray-600 dark:text-gray-400 mb-4">
|
|
If you have any questions about your order, please contact our support team.
|
|
</p>
|
|
<BaseButton color="info" label="Contact Support" small outline block />
|
|
</CardBox>
|
|
</div>
|
|
</div>
|
|
</SectionMain>
|
|
</>
|
|
);
|
|
};
|
|
|
|
OrderDetailsPage.getLayout = function getLayout(page: ReactElement) {
|
|
return <LayoutAuthenticated>{page}</LayoutAuthenticated>;
|
|
};
|
|
|
|
export default OrderDetailsPage;
|