Show full special-order details and order codes in admin.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
d63e3a83d5
commit
0e403c4915
@@ -64,6 +64,30 @@
|
|||||||
gap: 12px;
|
gap: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.section {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 14px 12px;
|
||||||
|
border-radius: var(--radius-sm);
|
||||||
|
border: 1px solid rgba(143, 65, 12, 0.1);
|
||||||
|
background: rgba(255, 250, 250, 0.45);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sectionTitle {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 0.84rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--brown);
|
||||||
|
}
|
||||||
|
|
||||||
|
.branchMeta {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 0.84rem;
|
||||||
|
line-height: 1.7;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
.empty {
|
.empty {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
|
|||||||
@@ -30,6 +30,22 @@ function formatDateTime(iso: string) {
|
|||||||
}).format(date)
|
}).format(date)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatJalaliDate(iso: string | null) {
|
||||||
|
if (!iso) return '—'
|
||||||
|
const date = new Date(iso)
|
||||||
|
if (Number.isNaN(date.getTime())) return '—'
|
||||||
|
return new Intl.DateTimeFormat('fa-IR-u-ca-persian', {
|
||||||
|
year: 'numeric',
|
||||||
|
month: 'long',
|
||||||
|
day: 'numeric',
|
||||||
|
}).format(date)
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayText(value: string | null | undefined) {
|
||||||
|
const trimmed = value?.trim()
|
||||||
|
return trimmed ? trimmed : '—'
|
||||||
|
}
|
||||||
|
|
||||||
export function SpecialOrderDetailsModal({
|
export function SpecialOrderDetailsModal({
|
||||||
open,
|
open,
|
||||||
order,
|
order,
|
||||||
@@ -56,6 +72,12 @@ export function SpecialOrderDetailsModal({
|
|||||||
|
|
||||||
const images = order.images.map((item) => item.url)
|
const images = order.images.map((item) => item.url)
|
||||||
const userName = formatUserName(order.user) || order.user.name
|
const userName = formatUserName(order.user) || order.user.name
|
||||||
|
const branchLabel =
|
||||||
|
order.branchName ||
|
||||||
|
order.branch?.name ||
|
||||||
|
(order.branch
|
||||||
|
? `${order.branch.name} — ${order.branch.district}`
|
||||||
|
: '')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -91,22 +113,24 @@ export function SpecialOrderDetailsModal({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={localStyles.body}>
|
<div className={localStyles.body}>
|
||||||
<div className={localStyles.block}>
|
|
||||||
<span className={localStyles.label}>نام</span>
|
|
||||||
<p className={localStyles.value}>{order.name}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={localStyles.metaRow}>
|
<div className={localStyles.metaRow}>
|
||||||
|
<div className={localStyles.block}>
|
||||||
|
<span className={localStyles.label}>کد سفارش</span>
|
||||||
|
<p className={localStyles.value} dir="ltr">
|
||||||
|
{order.code || `BL-S-${order.number}`}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
<div className={localStyles.block}>
|
<div className={localStyles.block}>
|
||||||
<span className={localStyles.label}>دستهبندی</span>
|
<span className={localStyles.label}>دستهبندی</span>
|
||||||
<p className={localStyles.value}>
|
<p className={localStyles.value}>
|
||||||
{specialOrderCategoryLabel[order.category]}
|
{specialOrderCategoryLabel[order.category]}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className={localStyles.block}>
|
|
||||||
<span className={localStyles.label}>تاریخ و ساعت</span>
|
|
||||||
<p className={localStyles.value}>{formatDateTime(order.createdAt)}</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className={localStyles.block}>
|
||||||
|
<span className={localStyles.label}>زمان ثبت</span>
|
||||||
|
<p className={localStyles.value}>{formatDateTime(order.createdAt)}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={`${localStyles.block} ${localStyles.userBlock}`}>
|
<div className={`${localStyles.block} ${localStyles.userBlock}`}>
|
||||||
@@ -116,12 +140,118 @@ export function SpecialOrderDetailsModal({
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<section className={localStyles.section}>
|
||||||
|
<h3 className={localStyles.sectionTitle}>۱. اطلاعات سفارش</h3>
|
||||||
<div className={localStyles.block}>
|
<div className={localStyles.block}>
|
||||||
<span className={localStyles.label}>توضیحات</span>
|
<span className={localStyles.label}>مناسبت سفارش</span>
|
||||||
<p className={localStyles.desc}>
|
<p className={localStyles.value}>{displayText(order.name)}</p>
|
||||||
{order.description.trim() || '—'}
|
</div>
|
||||||
|
<div className={localStyles.metaRow}>
|
||||||
|
<div className={localStyles.block}>
|
||||||
|
<span className={localStyles.label}>تاریخ موردنیاز</span>
|
||||||
|
<p className={localStyles.value}>
|
||||||
|
{formatJalaliDate(order.neededDate)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div className={localStyles.block}>
|
||||||
|
<span className={localStyles.label}>ساعت دریافت</span>
|
||||||
|
<p className={localStyles.value} dir="ltr">
|
||||||
|
{displayText(order.receiveTime)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section className={localStyles.section}>
|
||||||
|
<h3 className={localStyles.sectionTitle}>۲. اندازه کیک</h3>
|
||||||
|
<div className={localStyles.block}>
|
||||||
|
<span className={localStyles.label}>تعداد نفرات</span>
|
||||||
|
<p className={localStyles.value}>
|
||||||
|
{order.servings != null
|
||||||
|
? order.servings.toLocaleString('fa-IR')
|
||||||
|
: '—'}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section className={localStyles.section}>
|
||||||
|
<h3 className={localStyles.sectionTitle}>۳. طعم کیک</h3>
|
||||||
|
<div className={localStyles.metaRow}>
|
||||||
|
<div className={localStyles.block}>
|
||||||
|
<span className={localStyles.label}>طعم اسفنج</span>
|
||||||
|
<p className={localStyles.value}>
|
||||||
|
{displayText(order.cakeFlavor)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className={localStyles.block}>
|
||||||
|
<span className={localStyles.label}>فیلینگ / مغزی</span>
|
||||||
|
<p className={localStyles.value}>
|
||||||
|
{displayText(order.filling)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={localStyles.block}>
|
||||||
|
<span className={localStyles.label}>روکش کیک</span>
|
||||||
|
<p className={localStyles.value}>{displayText(order.coating)}</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section className={localStyles.section}>
|
||||||
|
<h3 className={localStyles.sectionTitle}>۴. نوشته و تزئینات</h3>
|
||||||
|
<div className={localStyles.block}>
|
||||||
|
<span className={localStyles.label}>متن روی کیک</span>
|
||||||
|
<p className={localStyles.value}>{displayText(order.cakeText)}</p>
|
||||||
|
</div>
|
||||||
|
<div className={localStyles.block}>
|
||||||
|
<span className={localStyles.label}>تزئینات خاص</span>
|
||||||
|
<p className={localStyles.desc}>
|
||||||
|
{displayText(order.decorations)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section className={localStyles.section}>
|
||||||
|
<h3 className={localStyles.sectionTitle}>۵. سبک طراحی</h3>
|
||||||
|
<div className={localStyles.block}>
|
||||||
|
<span className={localStyles.label}>سبک</span>
|
||||||
|
<p className={localStyles.value}>
|
||||||
|
{displayText(order.designStyle)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section className={localStyles.section}>
|
||||||
|
<h3 className={localStyles.sectionTitle}>۶. اطلاعات دریافت</h3>
|
||||||
|
<div className={localStyles.metaRow}>
|
||||||
|
<div className={localStyles.block}>
|
||||||
|
<span className={localStyles.label}>نحوه دریافت</span>
|
||||||
|
<p className={localStyles.value}>
|
||||||
|
{order.deliveryTypeLabel ||
|
||||||
|
(order.deliveryType === 'pickup'
|
||||||
|
? 'دریافت حضوری'
|
||||||
|
: order.deliveryType === 'shipping'
|
||||||
|
? 'ارسال با پیک'
|
||||||
|
: '—')}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className={localStyles.block}>
|
||||||
|
<span className={localStyles.label}>شعبه</span>
|
||||||
|
<p className={localStyles.value}>{displayText(branchLabel)}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{order.branch ? (
|
||||||
|
<p className={localStyles.branchMeta}>
|
||||||
|
{order.branch.district} — {order.branch.address}
|
||||||
|
</p>
|
||||||
|
) : null}
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{order.description.trim() ? (
|
||||||
|
<div className={localStyles.block}>
|
||||||
|
<span className={localStyles.label}>توضیحات</span>
|
||||||
|
<p className={localStyles.desc}>{order.description}</p>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
|
||||||
<div className={localStyles.block}>
|
<div className={localStyles.block}>
|
||||||
<span className={localStyles.label}>تصاویر</span>
|
<span className={localStyles.label}>تصاویر</span>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { apiRequest } from './api'
|
import { apiRequest } from './api'
|
||||||
|
|
||||||
export type SpecialOrderCategory = 'specialCake' | 'specialPastry'
|
export type SpecialOrderCategory = 'specialCake' | 'specialPastry'
|
||||||
|
export type SpecialOrderDeliveryType = 'pickup' | 'shipping'
|
||||||
|
|
||||||
export type SpecialOrderImage = {
|
export type SpecialOrderImage = {
|
||||||
id?: string
|
id?: string
|
||||||
@@ -19,12 +20,36 @@ export type SpecialOrderUser = {
|
|||||||
name: string
|
name: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type SpecialOrderBranch = {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
district: string
|
||||||
|
address: string
|
||||||
|
}
|
||||||
|
|
||||||
export type SpecialOrder = {
|
export type SpecialOrder = {
|
||||||
id: string
|
id: string
|
||||||
|
number: number
|
||||||
|
code: string
|
||||||
userId: string
|
userId: string
|
||||||
category: SpecialOrderCategory
|
category: SpecialOrderCategory
|
||||||
name: string
|
name: string
|
||||||
description: string
|
description: string
|
||||||
|
neededDate: string | null
|
||||||
|
receiveTime: string
|
||||||
|
servings: number | null
|
||||||
|
cakeFlavor: string
|
||||||
|
filling: string
|
||||||
|
baloutSuggestedCombo: boolean
|
||||||
|
coating: string
|
||||||
|
designStyle: string
|
||||||
|
cakeText: string
|
||||||
|
decorations: string
|
||||||
|
deliveryType: SpecialOrderDeliveryType | null
|
||||||
|
deliveryTypeLabel: string | null
|
||||||
|
branchId: string | null
|
||||||
|
branchName: string
|
||||||
|
branch: SpecialOrderBranch | null
|
||||||
createdAt: string
|
createdAt: string
|
||||||
updatedAt: string
|
updatedAt: string
|
||||||
images: SpecialOrderImage[]
|
images: SpecialOrderImage[]
|
||||||
|
|||||||
@@ -252,6 +252,9 @@ export function SpecialOrdersPage() {
|
|||||||
<li key={item.id} className={pageStyles.row}>
|
<li key={item.id} className={pageStyles.row}>
|
||||||
<div className={pageStyles.identity}>
|
<div className={pageStyles.identity}>
|
||||||
<span className={pageStyles.name}>{item.name}</span>
|
<span className={pageStyles.name}>{item.name}</span>
|
||||||
|
<span className={pageStyles.chip} dir="ltr">
|
||||||
|
{item.code || `BL-S-${item.number}`}
|
||||||
|
</span>
|
||||||
<span className={pageStyles.chip}>
|
<span className={pageStyles.chip}>
|
||||||
{specialOrderCategoryLabel[item.category]}
|
{specialOrderCategoryLabel[item.category]}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
Reference in New Issue
Block a user