"feat: enhance order management with new APIs and schema changes"
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
// src/sections/order/order-details-history.tsx
|
||||
import type { IOrderHistory } from 'src/types/order';
|
||||
|
||||
import Box from '@mui/material/Box';
|
||||
@@ -13,6 +14,7 @@ import TimelineConnector from '@mui/lab/TimelineConnector';
|
||||
import TimelineItem, { timelineItemClasses } from '@mui/lab/TimelineItem';
|
||||
|
||||
import { fDateTime } from 'src/utils/format-time';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
@@ -21,6 +23,8 @@ type Props = {
|
||||
};
|
||||
|
||||
export function OrderDetailsHistory({ history }: Props) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const renderSummary = () => (
|
||||
<Paper
|
||||
variant="outlined"
|
||||
@@ -37,22 +41,22 @@ export function OrderDetailsHistory({ history }: Props) {
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<Box sx={{ mb: 0.5, color: 'text.disabled' }}>Order time</Box>
|
||||
<Box sx={{ mb: 0.5, color: 'text.disabled' }}>{t('Order time')}</Box>
|
||||
{fDateTime(history?.orderTime)}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Box sx={{ mb: 0.5, color: 'text.disabled' }}>Payment time</Box>
|
||||
<Box sx={{ mb: 0.5, color: 'text.disabled' }}>{t('Payment time')}</Box>
|
||||
{fDateTime(history?.orderTime)}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Box sx={{ mb: 0.5, color: 'text.disabled' }}>Delivery time for the carrier</Box>
|
||||
<Box sx={{ mb: 0.5, color: 'text.disabled' }}>{t('Delivery time for the carrier')}</Box>
|
||||
{fDateTime(history?.orderTime)}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Box sx={{ mb: 0.5, color: 'text.disabled' }}>Completion time</Box>
|
||||
<Box sx={{ mb: 0.5, color: 'text.disabled' }}>{t('Completion time')}</Box>
|
||||
{fDateTime(history?.orderTime)}
|
||||
</div>
|
||||
</Paper>
|
||||
|
@@ -12,6 +12,7 @@ import { fCurrency } from 'src/utils/format-number';
|
||||
|
||||
import { Iconify } from 'src/components/iconify';
|
||||
import { Scrollbar } from 'src/components/scrollbar';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
@@ -34,6 +35,7 @@ export function OrderDetailsItems({
|
||||
totalAmount,
|
||||
...other
|
||||
}: Props) {
|
||||
const { t } = useTranslation();
|
||||
const renderTotal = () => (
|
||||
<Box
|
||||
sx={{
|
||||
@@ -47,32 +49,32 @@ export function OrderDetailsItems({
|
||||
}}
|
||||
>
|
||||
<Box sx={{ display: 'flex' }}>
|
||||
<Box sx={{ color: 'text.secondary' }}>Subtotal</Box>
|
||||
<Box sx={{ color: 'text.secondary' }}>{t('Subtotal')}</Box>
|
||||
<Box sx={{ width: 160, typography: 'subtitle2' }}>{fCurrency(subtotal) || '-'}</Box>
|
||||
</Box>
|
||||
|
||||
<Box sx={{ display: 'flex' }}>
|
||||
<Box sx={{ color: 'text.secondary' }}>Shipping</Box>
|
||||
<Box sx={{ color: 'text.secondary' }}>{t('Shipping')}</Box>
|
||||
<Box sx={{ width: 160, ...(shipping && { color: 'error.main' }) }}>
|
||||
{shipping ? `- ${fCurrency(shipping)}` : '-'}
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<Box sx={{ display: 'flex' }}>
|
||||
<Box sx={{ color: 'text.secondary' }}>Discount</Box>
|
||||
<Box sx={{ color: 'text.secondary' }}>{t('Discount')}</Box>
|
||||
<Box sx={{ width: 160, ...(discount && { color: 'error.main' }) }}>
|
||||
{discount ? `- ${fCurrency(discount)}` : '-'}
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<Box sx={{ display: 'flex' }}>
|
||||
<Box sx={{ color: 'text.secondary' }}>Taxes</Box>
|
||||
<Box sx={{ color: 'text.secondary' }}>{t('Taxes')}</Box>
|
||||
|
||||
<Box sx={{ width: 160 }}>{taxes ? fCurrency(taxes) : '-'}</Box>
|
||||
</Box>
|
||||
|
||||
<Box sx={{ display: 'flex', typography: 'subtitle1' }}>
|
||||
<div>Total</div>
|
||||
<div>{t('Total')}</div>
|
||||
<Box sx={{ width: 160 }}>{fCurrency(totalAmount) || '-'}</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
|
@@ -1,3 +1,5 @@
|
||||
// src/sections/order/order-details-toolbar.tsx
|
||||
|
||||
import type { IDateValue } from 'src/types/common';
|
||||
|
||||
import { usePopover } from 'minimal-shared/hooks';
|
||||
@@ -17,6 +19,7 @@ import { fDateTime } from 'src/utils/format-time';
|
||||
import { Label } from 'src/components/label';
|
||||
import { Iconify } from 'src/components/iconify';
|
||||
import { CustomPopover } from 'src/components/custom-popover';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
@@ -37,6 +40,7 @@ export function OrderDetailsToolbar({
|
||||
statusOptions,
|
||||
onChangeStatus,
|
||||
}: Props) {
|
||||
const { t } = useTranslation();
|
||||
const menuActions = usePopover();
|
||||
|
||||
const renderMenuActions = () => (
|
||||
@@ -56,7 +60,7 @@ export function OrderDetailsToolbar({
|
||||
onChangeStatus(option.value);
|
||||
}}
|
||||
>
|
||||
{option.label}
|
||||
{t(option.label)}
|
||||
</MenuItem>
|
||||
))}
|
||||
</MenuList>
|
||||
@@ -124,11 +128,11 @@ export function OrderDetailsToolbar({
|
||||
variant="outlined"
|
||||
startIcon={<Iconify icon="solar:printer-minimalistic-bold" />}
|
||||
>
|
||||
Print
|
||||
{t('Print (not implemented)')}
|
||||
</Button>
|
||||
|
||||
<Button color="inherit" variant="contained" startIcon={<Iconify icon="solar:pen-bold" />}>
|
||||
Edit
|
||||
{t('Edit')}
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
|
@@ -1,6 +1,8 @@
|
||||
// src/sections/order/view/order-details-view.tsx
|
||||
|
||||
import type { IOrderItem } from 'src/types/order';
|
||||
|
||||
import { useState, useCallback } from 'react';
|
||||
import { useState, useCallback, useEffect } from 'react';
|
||||
|
||||
import Box from '@mui/material/Box';
|
||||
import Card from '@mui/material/Card';
|
||||
@@ -19,19 +21,39 @@ import { OrderDetailsPayment } from '../order-details-payment';
|
||||
import { OrderDetailsCustomer } from '../order-details-customer';
|
||||
import { OrderDetailsDelivery } from '../order-details-delivery';
|
||||
import { OrderDetailsShipping } from '../order-details-shipping';
|
||||
import { useTranslate } from 'src/locales';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { changeStatus } from 'src/actions/order';
|
||||
import { toast } from 'sonner';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
type Props = {
|
||||
order?: IOrderItem;
|
||||
order: IOrderItem;
|
||||
};
|
||||
|
||||
export function OrderDetailsView({ order }: Props) {
|
||||
const [status, setStatus] = useState(order?.status);
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleChangeStatus = useCallback((newValue: string) => {
|
||||
setStatus(newValue);
|
||||
}, []);
|
||||
const [status, setStatus] = useState(order.status);
|
||||
|
||||
const handleChangeStatus = useCallback(
|
||||
async (newValue: string) => {
|
||||
setStatus(newValue);
|
||||
// change order status
|
||||
try {
|
||||
if (order?.id) {
|
||||
await changeStatus(order.id, newValue);
|
||||
|
||||
toast.success('order status updated');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
toast.warning('error during update order status');
|
||||
}
|
||||
},
|
||||
[order.id]
|
||||
);
|
||||
|
||||
return (
|
||||
<DashboardContent>
|
||||
@@ -47,7 +69,12 @@ export function OrderDetailsView({ order }: Props) {
|
||||
<Grid container spacing={3}>
|
||||
<Grid size={{ xs: 12, md: 8 }}>
|
||||
<Box
|
||||
sx={{ gap: 3, display: 'flex', flexDirection: { xs: 'column-reverse', md: 'column' } }}
|
||||
sx={{
|
||||
//
|
||||
gap: 3,
|
||||
display: 'flex',
|
||||
flexDirection: { xs: 'column-reverse', md: 'column' },
|
||||
}}
|
||||
>
|
||||
<OrderDetailsItems
|
||||
items={order?.items}
|
||||
|
@@ -3,7 +3,7 @@
|
||||
import type { TableHeadCellProps } from 'src/components/table';
|
||||
import type { IOrderItem, IOrderTableFilters } from 'src/types/order';
|
||||
|
||||
import { useState, useCallback } from 'react';
|
||||
import { useState, useCallback, useEffect } from 'react';
|
||||
import { varAlpha } from 'minimal-shared/utils';
|
||||
import { useBoolean, useSetState } from 'minimal-shared/hooks';
|
||||
|
||||
@@ -46,6 +46,8 @@ import { OrderTableRow } from '../order-table-row';
|
||||
import { OrderTableToolbar } from '../order-table-toolbar';
|
||||
import { OrderTableFiltersResult } from '../order-table-filters-result';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useRouter } from 'src/routes/hooks';
|
||||
import { deleteOrder, useGetOrders } from 'src/actions/order';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
@@ -55,12 +57,7 @@ const STATUS_OPTIONS = [{ value: 'all', label: 'All' }, ...ORDER_STATUS_OPTIONS]
|
||||
|
||||
export function OrderListView() {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const table = useTable({ defaultOrderBy: 'orderNumber' });
|
||||
|
||||
const confirmDialog = useBoolean();
|
||||
|
||||
const [tableData, setTableData] = useState<IOrderItem[]>(_orders);
|
||||
const router = useRouter();
|
||||
|
||||
const TABLE_HEAD: TableHeadCellProps[] = [
|
||||
{ id: 'orderNumber', label: t('Order'), width: 88 },
|
||||
@@ -72,6 +69,18 @@ export function OrderListView() {
|
||||
{ id: '', width: 88 },
|
||||
];
|
||||
|
||||
const { orders, mutate, ordersLoading } = useGetOrders();
|
||||
|
||||
const table = useTable({ defaultOrderBy: 'orderNumber' });
|
||||
|
||||
const confirmDialog = useBoolean();
|
||||
|
||||
const [tableData, setTableData] = useState<IOrderItem[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
setTableData(orders);
|
||||
}, [orders]);
|
||||
|
||||
const filters = useSetState<IOrderTableFilters>({
|
||||
name: '',
|
||||
status: 'all',
|
||||
@@ -99,16 +108,23 @@ export function OrderListView() {
|
||||
const notFound = (!dataFiltered.length && canReset) || !dataFiltered.length;
|
||||
|
||||
const handleDeleteRow = useCallback(
|
||||
(id: string) => {
|
||||
const deleteRow = tableData.filter((row) => row.id !== id);
|
||||
async (id: string) => {
|
||||
// const deleteRow = tableData.filter((row) => row.id !== id);
|
||||
|
||||
toast.success('Delete success!');
|
||||
try {
|
||||
await deleteOrder(id);
|
||||
toast.success('Delete success!');
|
||||
mutate();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
toast.error('Delete failed!');
|
||||
}
|
||||
|
||||
setTableData(deleteRow);
|
||||
|
||||
table.onUpdatePageDeleteRow(dataInPage.length);
|
||||
// toast.success('Delete success!');
|
||||
// setTableData(deleteRow);
|
||||
// table.onUpdatePageDeleteRow(dataInPage.length);
|
||||
},
|
||||
[dataInPage.length, table, tableData]
|
||||
[table, tableData, mutate]
|
||||
);
|
||||
|
||||
const handleDeleteRows = useCallback(() => {
|
||||
@@ -133,7 +149,7 @@ export function OrderListView() {
|
||||
<ConfirmDialog
|
||||
open={confirmDialog.value}
|
||||
onClose={confirmDialog.onFalse}
|
||||
title="Delete"
|
||||
title={t('Delete')}
|
||||
content={
|
||||
<>
|
||||
Are you sure want to delete <strong> {table.selected.length} </strong> items?
|
||||
@@ -145,7 +161,7 @@ export function OrderListView() {
|
||||
color="error"
|
||||
onClick={() => {
|
||||
handleDeleteRows();
|
||||
confirmDialog.onFalse();
|
||||
// confirmDialog.onFalse();
|
||||
}}
|
||||
>
|
||||
{t('Delete')}
|
||||
@@ -154,12 +170,20 @@ export function OrderListView() {
|
||||
/>
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
mutate();
|
||||
}, []);
|
||||
|
||||
if (!orders) return <>loading</>;
|
||||
if (ordersLoading) return <>loading</>;
|
||||
|
||||
return (
|
||||
<>
|
||||
<DashboardContent>
|
||||
<CustomBreadcrumbs
|
||||
heading="List"
|
||||
links={[
|
||||
//
|
||||
{ name: t('Dashboard'), href: paths.dashboard.root },
|
||||
{ name: t('Order'), href: paths.dashboard.order.root },
|
||||
{ name: t('List') },
|
||||
|
Reference in New Issue
Block a user