Show payment and order status with paid/all order tabs.
Default to successful (paid) orders, keep fulfillment status editable, and display gateway payment separately. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
bc1c5f0747
commit
41f21999d2
@@ -1236,6 +1236,10 @@ const en = {
|
|||||||
'orders.search': 'Search',
|
'orders.search': 'Search',
|
||||||
'orders.clearFilters': 'Clear filters',
|
'orders.clearFilters': 'Clear filters',
|
||||||
'orders.listTitle': 'Order list',
|
'orders.listTitle': 'Order list',
|
||||||
|
'orders.tabsAria': 'Order lists',
|
||||||
|
'orders.tab.paid': 'Successful orders',
|
||||||
|
'orders.tab.all': 'All orders',
|
||||||
|
'orders.emptyPaid': 'No paid orders yet.',
|
||||||
'orders.showing': 'Showing {from} - {to} of {total}',
|
'orders.showing': 'Showing {from} - {to} of {total}',
|
||||||
'orders.none': 'No orders',
|
'orders.none': 'No orders',
|
||||||
'orders.empty': 'No results found.',
|
'orders.empty': 'No results found.',
|
||||||
@@ -1244,12 +1248,18 @@ const en = {
|
|||||||
'orders.error.minMax': 'Minimum cost cannot be greater than maximum cost.',
|
'orders.error.minMax': 'Minimum cost cannot be greater than maximum cost.',
|
||||||
'orders.error.remove': 'Unable to remove order.',
|
'orders.error.remove': 'Unable to remove order.',
|
||||||
'orders.removed': 'Order {orderNumber} has been removed.',
|
'orders.removed': 'Order {orderNumber} has been removed.',
|
||||||
|
'orders.payment.paid': 'Paid',
|
||||||
|
'orders.payment.unpaid': 'Unpaid',
|
||||||
|
'orders.payment.failed': 'Failed',
|
||||||
|
'orders.fulfillment.new': 'New',
|
||||||
|
'orders.fulfillment.ready': 'Ready to process',
|
||||||
'orders.col.orderId': 'Order ID',
|
'orders.col.orderId': 'Order ID',
|
||||||
'orders.col.customer': 'Customer',
|
'orders.col.customer': 'Customer',
|
||||||
'orders.col.items': 'Items',
|
'orders.col.items': 'Items',
|
||||||
'orders.col.total': 'Total cost',
|
'orders.col.total': 'Total cost',
|
||||||
'orders.col.date': 'Date & time',
|
'orders.col.date': 'Date & time',
|
||||||
'orders.col.step': 'Step',
|
'orders.col.payment': 'Payment',
|
||||||
|
'orders.col.step': 'Order status',
|
||||||
'orders.col.source': 'Registered by',
|
'orders.col.source': 'Registered by',
|
||||||
'orders.col.actions': 'Actions',
|
'orders.col.actions': 'Actions',
|
||||||
'orders.pageMeta': 'Page {page} / {totalPages} · {pageSize} per page · {total} total',
|
'orders.pageMeta': 'Page {page} / {totalPages} · {pageSize} per page · {total} total',
|
||||||
@@ -4116,6 +4126,10 @@ const fa: Record<MessageKey, string> = {
|
|||||||
'orders.search': 'جستجو',
|
'orders.search': 'جستجو',
|
||||||
'orders.clearFilters': 'پاک کردن فیلترها',
|
'orders.clearFilters': 'پاک کردن فیلترها',
|
||||||
'orders.listTitle': 'فهرست سفارشها',
|
'orders.listTitle': 'فهرست سفارشها',
|
||||||
|
'orders.tabsAria': 'فهرستهای سفارش',
|
||||||
|
'orders.tab.paid': 'سفارشهای موفق',
|
||||||
|
'orders.tab.all': 'همه سفارشها',
|
||||||
|
'orders.emptyPaid': 'هنوز سفارش پرداختشدهای وجود ندارد.',
|
||||||
'orders.showing': 'نمایش {from} تا {to} از {total}',
|
'orders.showing': 'نمایش {from} تا {to} از {total}',
|
||||||
'orders.none': 'بدون سفارش',
|
'orders.none': 'بدون سفارش',
|
||||||
'orders.empty': 'نتیجهای یافت نشد.',
|
'orders.empty': 'نتیجهای یافت نشد.',
|
||||||
@@ -4124,12 +4138,18 @@ const fa: Record<MessageKey, string> = {
|
|||||||
'orders.error.minMax': 'حداقل مبلغ نمیتواند از حداکثر بیشتر باشد.',
|
'orders.error.minMax': 'حداقل مبلغ نمیتواند از حداکثر بیشتر باشد.',
|
||||||
'orders.error.remove': 'حذف سفارش ممکن نشد.',
|
'orders.error.remove': 'حذف سفارش ممکن نشد.',
|
||||||
'orders.removed': 'سفارش {orderNumber} حذف شد.',
|
'orders.removed': 'سفارش {orderNumber} حذف شد.',
|
||||||
|
'orders.payment.paid': 'پرداخت شده',
|
||||||
|
'orders.payment.unpaid': 'پرداخت نشده',
|
||||||
|
'orders.payment.failed': 'ناموفق',
|
||||||
|
'orders.fulfillment.new': 'جدید',
|
||||||
|
'orders.fulfillment.ready': 'آماده پردازش',
|
||||||
'orders.col.orderId': 'شماره سفارش',
|
'orders.col.orderId': 'شماره سفارش',
|
||||||
'orders.col.customer': 'مشتری',
|
'orders.col.customer': 'مشتری',
|
||||||
'orders.col.items': 'اقلام',
|
'orders.col.items': 'اقلام',
|
||||||
'orders.col.total': 'مبلغ کل',
|
'orders.col.total': 'مبلغ کل',
|
||||||
'orders.col.date': 'تاریخ و ساعت',
|
'orders.col.date': 'تاریخ و ساعت',
|
||||||
'orders.col.step': 'وضعیت',
|
'orders.col.payment': 'وضعیت پرداخت',
|
||||||
|
'orders.col.step': 'وضعیت سفارش',
|
||||||
'orders.col.source': 'ثبتشده توسط',
|
'orders.col.source': 'ثبتشده توسط',
|
||||||
'orders.col.actions': 'عملیات',
|
'orders.col.actions': 'عملیات',
|
||||||
'orders.pageMeta': 'صفحه {page} / {totalPages} · {pageSize} در هر صفحه · {total} کل',
|
'orders.pageMeta': 'صفحه {page} / {totalPages} · {pageSize} در هر صفحه · {total} کل',
|
||||||
|
|||||||
@@ -19,19 +19,60 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
gap: 12px;
|
||||||
border-bottom: 1px solid rgba(148, 163, 184, 0.2);
|
border-bottom: 1px solid rgba(148, 163, 184, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tableHeaderMain {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px 16px;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.tableHeaderTitle {
|
.tableHeaderTitle {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tabs {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
padding: 3px;
|
||||||
|
border-radius: 999px;
|
||||||
|
background: rgba(148, 163, 184, 0.14);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab {
|
||||||
|
border: 0;
|
||||||
|
background: transparent;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 700;
|
||||||
|
padding: 6px 12px;
|
||||||
|
border-radius: 999px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background 0.15s, color 0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab:hover {
|
||||||
|
color: var(--text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabActive {
|
||||||
|
background: var(--surface, #fff);
|
||||||
|
color: var(--text-primary);
|
||||||
|
box-shadow: 0 1px 2px rgba(15, 23, 42, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
.meta {
|
.meta {
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table {
|
.table {
|
||||||
@@ -41,35 +82,39 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.colOrderId {
|
.colOrderId {
|
||||||
width: 14%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.colCustomer {
|
|
||||||
width: 16%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.colItems {
|
|
||||||
width: 8%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.colTotal {
|
|
||||||
width: 11%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.colDate {
|
|
||||||
width: 12%;
|
width: 12%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.colStep {
|
.colCustomer {
|
||||||
width: 14%;
|
width: 14%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.colItems {
|
||||||
|
width: 6%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.colTotal {
|
||||||
|
width: 10%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.colDate {
|
||||||
|
width: 11%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.colPayment {
|
||||||
|
width: 11%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.colStep {
|
||||||
|
width: 12%;
|
||||||
|
}
|
||||||
|
|
||||||
.colSource {
|
.colSource {
|
||||||
width: 10%;
|
width: 10%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.colActions {
|
.colActions {
|
||||||
width: 128px;
|
width: 120px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.th,
|
.th,
|
||||||
@@ -159,6 +204,32 @@
|
|||||||
background: rgba(139, 92, 246, 0.12);
|
background: rgba(139, 92, 246, 0.12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.paymentBadge {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
max-width: 100%;
|
||||||
|
padding: 4px 10px;
|
||||||
|
border-radius: 999px;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 700;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.paymentPaid {
|
||||||
|
color: #047857;
|
||||||
|
background: rgba(16, 185, 129, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
|
.paymentUnpaid {
|
||||||
|
color: #64748b;
|
||||||
|
background: rgba(100, 116, 139, 0.14);
|
||||||
|
}
|
||||||
|
|
||||||
|
.paymentFailed {
|
||||||
|
color: #b91c1c;
|
||||||
|
background: rgba(239, 68, 68, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
.stepBadge {
|
.stepBadge {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import {
|
|||||||
listOrders,
|
listOrders,
|
||||||
removeOrder,
|
removeOrder,
|
||||||
type Order,
|
type Order,
|
||||||
|
type OrderPaymentStatus,
|
||||||
type OrdersListResponse,
|
type OrdersListResponse,
|
||||||
type OrderSource,
|
type OrderSource,
|
||||||
} from '../services/orderService'
|
} from '../services/orderService'
|
||||||
@@ -33,7 +34,9 @@ import pageStyles from '../components/PageContent.module.css'
|
|||||||
import styles from './OrdersPage.module.css'
|
import styles from './OrdersPage.module.css'
|
||||||
|
|
||||||
const PAGE_SIZE = 24
|
const PAGE_SIZE = 24
|
||||||
const COLUMN_COUNT = 8
|
const COLUMN_COUNT = 9
|
||||||
|
|
||||||
|
type OrdersTab = 'paid' | 'all'
|
||||||
|
|
||||||
interface AppliedFilters {
|
interface AppliedFilters {
|
||||||
orderNumber?: string
|
orderNumber?: string
|
||||||
@@ -98,6 +101,14 @@ function stepLabel(
|
|||||||
return step?.label ?? processStepId
|
return step?.label ?? processStepId
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function derivePaymentStatus(order: Order): OrderPaymentStatus {
|
||||||
|
if (order.paymentStatus) return order.paymentStatus
|
||||||
|
const txs = order.transactions ?? []
|
||||||
|
if (txs.some((tx) => tx.status === 'completed')) return 'paid'
|
||||||
|
if (txs.length > 0 && txs.every((tx) => tx.status === 'failed')) return 'failed'
|
||||||
|
return 'unpaid'
|
||||||
|
}
|
||||||
|
|
||||||
function sourceClass(source: OrderSource) {
|
function sourceClass(source: OrderSource) {
|
||||||
switch (source) {
|
switch (source) {
|
||||||
case 'admin':
|
case 'admin':
|
||||||
@@ -154,6 +165,7 @@ export function OrdersPage() {
|
|||||||
const [processSteps, setProcessSteps] = useState<OrderProcessStep[]>(DEFAULT_ORDER_PROCESS_STEPS)
|
const [processSteps, setProcessSteps] = useState<OrderProcessStep[]>(DEFAULT_ORDER_PROCESS_STEPS)
|
||||||
const [removeTarget, setRemoveTarget] = useState<Order | null>(null)
|
const [removeTarget, setRemoveTarget] = useState<Order | null>(null)
|
||||||
const [removing, setRemoving] = useState(false)
|
const [removing, setRemoving] = useState(false)
|
||||||
|
const [ordersTab, setOrdersTab] = useState<OrdersTab>('paid')
|
||||||
|
|
||||||
function sourceLabel(source: OrderSource) {
|
function sourceLabel(source: OrderSource) {
|
||||||
switch (source) {
|
switch (source) {
|
||||||
@@ -167,6 +179,50 @@ export function OrdersPage() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function paymentStatusLabel(status: OrderPaymentStatus) {
|
||||||
|
switch (status) {
|
||||||
|
case 'paid':
|
||||||
|
return t('orders.payment.paid')
|
||||||
|
case 'failed':
|
||||||
|
return t('orders.payment.failed')
|
||||||
|
case 'unpaid':
|
||||||
|
default:
|
||||||
|
return t('orders.payment.unpaid')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function paymentStatusClass(status: OrderPaymentStatus) {
|
||||||
|
switch (status) {
|
||||||
|
case 'paid':
|
||||||
|
return styles.paymentPaid
|
||||||
|
case 'failed':
|
||||||
|
return styles.paymentFailed
|
||||||
|
case 'unpaid':
|
||||||
|
default:
|
||||||
|
return styles.paymentUnpaid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function orderStatusLabel(order: Order) {
|
||||||
|
const stepId = order.processStepId ?? processSteps[0]?.id ?? 'processing'
|
||||||
|
if (stepId === 'awaiting-payment') return t('orders.fulfillment.new')
|
||||||
|
if (stepId === 'payment-successful') return t('orders.fulfillment.ready')
|
||||||
|
return stepLabel(
|
||||||
|
processSteps,
|
||||||
|
stepId,
|
||||||
|
order.processStepLabel,
|
||||||
|
order.processStepLabelFa,
|
||||||
|
locale,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function orderStatusColor(order: Order) {
|
||||||
|
const stepId = order.processStepId ?? processSteps[0]?.id ?? 'processing'
|
||||||
|
if (stepId === 'awaiting-payment') return '#64748B'
|
||||||
|
if (stepId === 'payment-successful') return '#3B82F6'
|
||||||
|
return stepColor(processSteps, stepId, order.processStepColor)
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const controller = new AbortController()
|
const controller = new AbortController()
|
||||||
|
|
||||||
@@ -195,6 +251,7 @@ export function OrdersPage() {
|
|||||||
page,
|
page,
|
||||||
pageSize: PAGE_SIZE,
|
pageSize: PAGE_SIZE,
|
||||||
...appliedFilters,
|
...appliedFilters,
|
||||||
|
...(ordersTab === 'paid' ? { paymentStatus: 'paid' } : {}),
|
||||||
},
|
},
|
||||||
controller.signal,
|
controller.signal,
|
||||||
)
|
)
|
||||||
@@ -215,6 +272,7 @@ export function OrdersPage() {
|
|||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
page,
|
page,
|
||||||
|
ordersTab,
|
||||||
appliedFilters.orderNumber,
|
appliedFilters.orderNumber,
|
||||||
appliedFilters.customerQuery,
|
appliedFilters.customerQuery,
|
||||||
appliedFilters.dateFrom,
|
appliedFilters.dateFrom,
|
||||||
@@ -416,7 +474,37 @@ export function OrdersPage() {
|
|||||||
<div className={styles.tablePanel}>
|
<div className={styles.tablePanel}>
|
||||||
<div className={styles.tableWrap}>
|
<div className={styles.tableWrap}>
|
||||||
<div className={styles.tableHeader}>
|
<div className={styles.tableHeader}>
|
||||||
<div className={styles.tableHeaderTitle}>{t('orders.listTitle')}</div>
|
<div className={styles.tableHeaderMain}>
|
||||||
|
<div className={styles.tableHeaderTitle}>{t('orders.listTitle')}</div>
|
||||||
|
<div className={styles.tabs} role="tablist" aria-label={t('orders.tabsAria')}>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
role="tab"
|
||||||
|
aria-selected={ordersTab === 'paid'}
|
||||||
|
className={`${styles.tab} ${ordersTab === 'paid' ? styles.tabActive : ''}`}
|
||||||
|
onClick={() => {
|
||||||
|
if (ordersTab === 'paid') return
|
||||||
|
setOrdersTab('paid')
|
||||||
|
setPage(1)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t('orders.tab.paid')}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
role="tab"
|
||||||
|
aria-selected={ordersTab === 'all'}
|
||||||
|
className={`${styles.tab} ${ordersTab === 'all' ? styles.tabActive : ''}`}
|
||||||
|
onClick={() => {
|
||||||
|
if (ordersTab === 'all') return
|
||||||
|
setOrdersTab('all')
|
||||||
|
setPage(1)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t('orders.tab.all')}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div className={styles.meta}>
|
<div className={styles.meta}>
|
||||||
{data ? (
|
{data ? (
|
||||||
data.total > 0 ? (
|
data.total > 0 ? (
|
||||||
@@ -443,6 +531,7 @@ export function OrdersPage() {
|
|||||||
<col className={styles.colItems} />
|
<col className={styles.colItems} />
|
||||||
<col className={styles.colTotal} />
|
<col className={styles.colTotal} />
|
||||||
<col className={styles.colDate} />
|
<col className={styles.colDate} />
|
||||||
|
<col className={styles.colPayment} />
|
||||||
<col className={styles.colStep} />
|
<col className={styles.colStep} />
|
||||||
<col className={styles.colSource} />
|
<col className={styles.colSource} />
|
||||||
<col className={styles.colActions} />
|
<col className={styles.colActions} />
|
||||||
@@ -454,6 +543,7 @@ export function OrdersPage() {
|
|||||||
<th className={styles.th}>{t('orders.col.items')}</th>
|
<th className={styles.th}>{t('orders.col.items')}</th>
|
||||||
<th className={styles.th}>{t('orders.col.total')}</th>
|
<th className={styles.th}>{t('orders.col.total')}</th>
|
||||||
<th className={styles.th}>{t('orders.col.date')}</th>
|
<th className={styles.th}>{t('orders.col.date')}</th>
|
||||||
|
<th className={styles.th}>{t('orders.col.payment')}</th>
|
||||||
<th className={styles.th}>{t('orders.col.step')}</th>
|
<th className={styles.th}>{t('orders.col.step')}</th>
|
||||||
<th className={styles.th}>{t('orders.col.source')}</th>
|
<th className={styles.th}>{t('orders.col.source')}</th>
|
||||||
<th className={`${styles.th} ${styles.thActions}`}>{t('orders.col.actions')}</th>
|
<th className={`${styles.th} ${styles.thActions}`}>{t('orders.col.actions')}</th>
|
||||||
@@ -472,7 +562,9 @@ export function OrdersPage() {
|
|||||||
<EmptyTableRow
|
<EmptyTableRow
|
||||||
colSpan={COLUMN_COUNT}
|
colSpan={COLUMN_COUNT}
|
||||||
icon={ShoppingBag}
|
icon={ShoppingBag}
|
||||||
message={t('orders.empty')}
|
message={
|
||||||
|
ordersTab === 'paid' ? t('orders.emptyPaid') : t('orders.empty')
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -480,13 +572,8 @@ export function OrdersPage() {
|
|||||||
data?.items?.map((order) => {
|
data?.items?.map((order) => {
|
||||||
const { date, time } = formatDateTime(order.createdAt, locale)
|
const { date, time } = formatDateTime(order.createdAt, locale)
|
||||||
const itemQty = totalItemQuantity(order)
|
const itemQty = totalItemQuantity(order)
|
||||||
const currentStepLabel = stepLabel(
|
const paymentStatus = derivePaymentStatus(order)
|
||||||
processSteps,
|
const currentStepLabel = orderStatusLabel(order)
|
||||||
order.processStepId ?? processSteps[0]?.id ?? 'processing',
|
|
||||||
order.processStepLabel,
|
|
||||||
order.processStepLabelFa,
|
|
||||||
locale,
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<tr key={order.id}>
|
<tr key={order.id}>
|
||||||
@@ -507,17 +594,18 @@ export function OrdersPage() {
|
|||||||
<div className={styles.dateTime}>{date}</div>
|
<div className={styles.dateTime}>{date}</div>
|
||||||
{time && <div className={styles.dateTimeSub}>{time}</div>}
|
{time && <div className={styles.dateTimeSub}>{time}</div>}
|
||||||
</td>
|
</td>
|
||||||
|
<td className={styles.td}>
|
||||||
|
<span
|
||||||
|
className={`${styles.paymentBadge} ${paymentStatusClass(paymentStatus)}`}
|
||||||
|
>
|
||||||
|
{paymentStatusLabel(paymentStatus)}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
<td className={styles.td}>
|
<td className={styles.td}>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className={styles.stepBadge}
|
className={styles.stepBadge}
|
||||||
style={stepBadgeStyle(
|
style={stepBadgeStyle(orderStatusColor(order))}
|
||||||
stepColor(
|
|
||||||
processSteps,
|
|
||||||
order.processStepId ?? processSteps[0]?.id ?? 'processing',
|
|
||||||
order.processStepColor,
|
|
||||||
),
|
|
||||||
)}
|
|
||||||
onClick={() => setStepOrder(order)}
|
onClick={() => setStepOrder(order)}
|
||||||
aria-label={t('orders.changeStep', { step: currentStepLabel })}
|
aria-label={t('orders.changeStep', { step: currentStepLabel })}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -61,6 +61,8 @@ export interface OrderTransaction {
|
|||||||
updatedAt: string
|
updatedAt: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type OrderPaymentStatus = 'paid' | 'unpaid' | 'failed'
|
||||||
|
|
||||||
export interface Order {
|
export interface Order {
|
||||||
id: string
|
id: string
|
||||||
businessId: string
|
businessId: string
|
||||||
@@ -70,6 +72,7 @@ export interface Order {
|
|||||||
processStepLabel?: string | null
|
processStepLabel?: string | null
|
||||||
processStepLabelFa?: string | null
|
processStepLabelFa?: string | null
|
||||||
processStepColor?: string | null
|
processStepColor?: string | null
|
||||||
|
paymentStatus?: OrderPaymentStatus
|
||||||
source: OrderSource
|
source: OrderSource
|
||||||
subtotal: number
|
subtotal: number
|
||||||
shippingTotal: number
|
shippingTotal: number
|
||||||
@@ -104,6 +107,7 @@ export interface ListOrdersParams {
|
|||||||
dateTo?: string
|
dateTo?: string
|
||||||
minTotal?: number
|
minTotal?: number
|
||||||
maxTotal?: number
|
maxTotal?: number
|
||||||
|
paymentStatus?: OrderPaymentStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CreateAdminOrderPayment {
|
export interface CreateAdminOrderPayment {
|
||||||
@@ -144,6 +148,7 @@ export async function listOrders(params: ListOrdersParams = {}, signal?: AbortSi
|
|||||||
if (params.dateTo) q.set('dateTo', params.dateTo)
|
if (params.dateTo) q.set('dateTo', params.dateTo)
|
||||||
if (params.minTotal !== undefined) q.set('minTotal', String(params.minTotal))
|
if (params.minTotal !== undefined) q.set('minTotal', String(params.minTotal))
|
||||||
if (params.maxTotal !== undefined) q.set('maxTotal', String(params.maxTotal))
|
if (params.maxTotal !== undefined) q.set('maxTotal', String(params.maxTotal))
|
||||||
|
if (params.paymentStatus) q.set('paymentStatus', params.paymentStatus)
|
||||||
|
|
||||||
const query = q.toString()
|
const query = q.toString()
|
||||||
const path = `${businessPath()}${query ? `?${query}` : ''}`
|
const path = `${businessPath()}${query ? `?${query}` : ''}`
|
||||||
|
|||||||
Reference in New Issue
Block a user