chore: format project automatically before starting dev server
This commit is contained in:
@@ -16,26 +16,46 @@ export default function DashboardShell({children}: {children: ReactNode}) {
|
||||
const {locale} = useLanguage();
|
||||
const copy = accountCopy[locale];
|
||||
const links = [
|
||||
{href: '/dashboard', label: copy.dashboard, icon: <DashboardOutlined/>},
|
||||
{href: '/dashboard/orders', label: copy.orders, icon: <FileTextOutlined/>},
|
||||
{href: '/dashboard/profile', label: copy.profile, icon: <UserOutlined/>},
|
||||
{href: '/dashboard', label: copy.dashboard, icon: <DashboardOutlined />},
|
||||
{href: '/dashboard/orders', label: copy.orders, icon: <FileTextOutlined />},
|
||||
{href: '/dashboard/profile', label: copy.profile, icon: <UserOutlined />},
|
||||
];
|
||||
const active = (href: string) => href === '/dashboard' ? pathname === href : pathname.startsWith(href);
|
||||
const active = (href: string) => (href === '/dashboard' ? pathname === href : pathname.startsWith(href));
|
||||
return (
|
||||
<main className="max-w-7xl mx-auto min-h-[75vh] px-5 md:px-8 pt-28 pb-20">
|
||||
<div className="grid lg:grid-cols-[240px,minmax(0,1fr)] gap-7 items-start">
|
||||
<aside className="lg:sticky lg:top-28 rounded-2xl border border-subtle bg-elevated p-4">
|
||||
<div className="px-3 py-3 border-b border-subtle mb-3">
|
||||
<p className="font-bold text-primary">{auth.session?.profile.firstName || copy.account}</p>
|
||||
<p className="text-sm text-secondary mt-1" dir="ltr">{auth.session?.profile.phone}</p>
|
||||
<p className="text-sm text-secondary mt-1" dir="ltr">
|
||||
{auth.session?.profile.phone}
|
||||
</p>
|
||||
</div>
|
||||
<nav className="flex lg:flex-col gap-2 overflow-x-auto no-scrollbar">
|
||||
{links.map(link => <Link key={link.href} href={link.href}
|
||||
className={`flex items-center gap-2 whitespace-nowrap px-4 py-3 rounded-xl transition-colors ${active(link.href) ? 'bg-brand text-ink-950 font-bold' : 'text-secondary hover:bg-surface-strong hover:text-primary'}`}>
|
||||
{link.icon}{link.label}
|
||||
</Link>)}
|
||||
{links.map(link => (
|
||||
<Link
|
||||
key={link.href}
|
||||
href={link.href}
|
||||
className={`flex items-center gap-2 whitespace-nowrap px-4 py-3 rounded-xl transition-colors ${active(link.href) ? 'bg-brand text-ink-950 font-bold' : 'text-secondary hover:bg-surface-strong hover:text-primary'}`}
|
||||
>
|
||||
{link.icon}
|
||||
{link.label}
|
||||
</Link>
|
||||
))}
|
||||
</nav>
|
||||
<Button className="mt-3" type="text" danger icon={<LogoutOutlined/>} onClick={() => {auth.logout(); router.push('/');}} block>{copy.logout}</Button>
|
||||
<Button
|
||||
className="mt-3"
|
||||
type="text"
|
||||
danger
|
||||
icon={<LogoutOutlined />}
|
||||
onClick={() => {
|
||||
auth.logout();
|
||||
router.push('/');
|
||||
}}
|
||||
block
|
||||
>
|
||||
{copy.logout}
|
||||
</Button>
|
||||
</aside>
|
||||
<section className="min-w-0">{children}</section>
|
||||
</div>
|
||||
|
||||
@@ -13,27 +13,92 @@ const InvoiceDocument = forwardRef<HTMLDivElement, {order: CustomerOrder}>(({ord
|
||||
const money = (value: number) => `${value.toLocaleString(numberLocale)} ${locale === 'fa' ? 'ریال' : 'Rials'}`;
|
||||
const subtotal = order.items.reduce((sum, item) => sum + item.unitPrice * item.quantity, 0);
|
||||
const total = subtotal - invoice.discount + invoice.shipping + invoice.tax;
|
||||
const buyerName = order.customer.type === 'corporate' ? order.customer.companyName : `${order.customer.firstName} ${order.customer.lastName}`;
|
||||
const buyerName =
|
||||
order.customer.type === 'corporate'
|
||||
? order.customer.companyName
|
||||
: `${order.customer.firstName} ${order.customer.lastName}`;
|
||||
return (
|
||||
<div ref={ref} className="invoice-document" dir={locale === 'fa' ? 'rtl' : 'ltr'}>
|
||||
<div className="invoice-head">
|
||||
<img src="/images/icons/logo.png" alt="Robot Market"/>
|
||||
<div><h2>{copy.invoice}</h2><p>{copy.invoiceNumber}: <span dir="ltr">{invoice.number}</span></p></div>
|
||||
<img src="/images/icons/logo.png" alt="Robot Market" />
|
||||
<div>
|
||||
<h2>{copy.invoice}</h2>
|
||||
<p>
|
||||
{copy.invoiceNumber}: <span dir="ltr">{invoice.number}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="invoice-meta">
|
||||
<div><strong>{copy.seller}</strong><p>{copy.sellerName}</p><p>{copy.sellerPhone}</p></div>
|
||||
<div><strong>{copy.buyer}</strong><p>{buyerName}</p><p dir="ltr">{order.customer.phone}</p><p>{order.customer.city}، {order.customer.address}</p></div>
|
||||
<div><p>{copy.issueDate}: {invoice.issueDate}</p><p>{copy.validUntil}: {invoice.validUntil}</p></div>
|
||||
<div>
|
||||
<strong>{copy.seller}</strong>
|
||||
<p>{copy.sellerName}</p>
|
||||
<p>{copy.sellerPhone}</p>
|
||||
</div>
|
||||
<div>
|
||||
<strong>{copy.buyer}</strong>
|
||||
<p>{buyerName}</p>
|
||||
<p dir="ltr">{order.customer.phone}</p>
|
||||
<p>
|
||||
{order.customer.city}، {order.customer.address}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
{copy.issueDate}: {invoice.issueDate}
|
||||
</p>
|
||||
<p>
|
||||
{copy.validUntil}: {invoice.validUntil}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<table><thead><tr><th>#</th><th>{copy.orderItems}</th><th>{copy.modules}</th><th>{copy.quantity}</th><th>{copy.unitPrice}</th><th>{copy.total}</th></tr></thead>
|
||||
<tbody>{order.items.map((item, index) => <tr key={item.id}><td>{index + 1}</td><td>{item.name}<small>{item.model}</small></td><td>{item.modules.join('، ')}</td><td>{item.quantity}</td><td>{money(item.unitPrice)}</td><td>{money(item.unitPrice * item.quantity)}</td></tr>)}</tbody>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>{copy.orderItems}</th>
|
||||
<th>{copy.modules}</th>
|
||||
<th>{copy.quantity}</th>
|
||||
<th>{copy.unitPrice}</th>
|
||||
<th>{copy.total}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{order.items.map((item, index) => (
|
||||
<tr key={item.id}>
|
||||
<td>{index + 1}</td>
|
||||
<td>
|
||||
{item.name}
|
||||
<small>{item.model}</small>
|
||||
</td>
|
||||
<td>{item.modules.join('، ')}</td>
|
||||
<td>{item.quantity}</td>
|
||||
<td>{money(item.unitPrice)}</td>
|
||||
<td>{money(item.unitPrice * item.quantity)}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
<div className="invoice-totals">
|
||||
<p><span>{copy.subtotal}</span><strong>{money(subtotal)}</strong></p>
|
||||
<p><span>{copy.discount}</span><strong>{money(invoice.discount)}</strong></p>
|
||||
<p><span>{copy.shipping}</span><strong>{money(invoice.shipping)}</strong></p>
|
||||
<p><span>{copy.tax}</span><strong>{money(invoice.tax)}</strong></p>
|
||||
<p className="grand"><span>{copy.finalTotal}</span><strong>{money(total)}</strong></p>
|
||||
<p>
|
||||
<span>{copy.subtotal}</span>
|
||||
<strong>{money(subtotal)}</strong>
|
||||
</p>
|
||||
<p>
|
||||
<span>{copy.discount}</span>
|
||||
<strong>{money(invoice.discount)}</strong>
|
||||
</p>
|
||||
<p>
|
||||
<span>{copy.shipping}</span>
|
||||
<strong>{money(invoice.shipping)}</strong>
|
||||
</p>
|
||||
<p>
|
||||
<span>{copy.tax}</span>
|
||||
<strong>{money(invoice.tax)}</strong>
|
||||
</p>
|
||||
<p className="grand">
|
||||
<span>{copy.finalTotal}</span>
|
||||
<strong>{money(total)}</strong>
|
||||
</p>
|
||||
</div>
|
||||
<p className="invoice-note">این پیشفاکتور پس از هماهنگی تلفنی و تأیید ادمین روبات مارکت صادر شده است.</p>
|
||||
</div>
|
||||
|
||||
@@ -12,15 +12,38 @@ export default function OrderCard({order}: {order: CustomerOrder}) {
|
||||
return (
|
||||
<article className="rounded-2xl border border-subtle bg-elevated p-5">
|
||||
<div className="flex flex-wrap justify-between gap-4">
|
||||
<div><p className="text-sm text-secondary">{copy.orderNumber}</p><strong className="text-primary" dir="ltr">{order.number}</strong></div>
|
||||
<OrderStatusTag status={order.status}/>
|
||||
<div>
|
||||
<p className="text-sm text-secondary">{copy.orderNumber}</p>
|
||||
<strong className="text-primary" dir="ltr">
|
||||
{order.number}
|
||||
</strong>
|
||||
</div>
|
||||
<OrderStatusTag status={order.status} />
|
||||
</div>
|
||||
<div className="grid sm:grid-cols-3 gap-4 mt-5 pt-5 border-t border-subtle text-sm">
|
||||
<div><span className="text-secondary block">{copy.orderDate}</span><span className="text-primary">{order.createdAt}</span></div>
|
||||
<div><span className="text-secondary block">{copy.paymentStatus}</span><span className="text-primary">{paymentStatusLabels[locale][order.paymentStatus]}</span></div>
|
||||
<div><span className="text-secondary block">{copy.orderItems}</span><span className="text-primary">{order.items.reduce((sum, item) => sum + item.quantity, 0).toLocaleString(locale === 'fa' ? 'fa-IR' : 'en-US')}</span></div>
|
||||
<div>
|
||||
<span className="text-secondary block">{copy.orderDate}</span>
|
||||
<span className="text-primary">{order.createdAt}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span className="text-secondary block">{copy.paymentStatus}</span>
|
||||
<span className="text-primary">{paymentStatusLabels[locale][order.paymentStatus]}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span className="text-secondary block">{copy.orderItems}</span>
|
||||
<span className="text-primary">
|
||||
{order.items
|
||||
.reduce((sum, item) => sum + item.quantity, 0)
|
||||
.toLocaleString(locale === 'fa' ? 'fa-IR' : 'en-US')}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<Link href={`/dashboard/orders/${order.id}`} className="inline-block text-brand-400 font-semibold mt-5 hover:underline">{copy.details}</Link>
|
||||
<Link
|
||||
href={`/dashboard/orders/${order.id}`}
|
||||
className="inline-block text-brand-400 font-semibold mt-5 hover:underline"
|
||||
>
|
||||
{copy.details}
|
||||
</Link>
|
||||
</article>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,13 @@ import {orderStatusLabels} from '@/data/account';
|
||||
|
||||
export default function OrderStatusTag({status}: {status: OrderStatus}) {
|
||||
const {locale} = useLanguage();
|
||||
const color = status === 'cancelled' ? 'red' : status === 'delivered' ? 'green' : status === 'proforma_issued' ? 'cyan' : 'gold';
|
||||
const color =
|
||||
status === 'cancelled'
|
||||
? 'red'
|
||||
: status === 'delivered'
|
||||
? 'green'
|
||||
: status === 'proforma_issued'
|
||||
? 'cyan'
|
||||
: 'gold';
|
||||
return <Tag color={color}>{orderStatusLabels[locale][status]}</Tag>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user