party-order list ok,

This commit is contained in:
louiscklaw
2025-06-16 00:01:36 +08:00
parent 77f7211317
commit 7370316ea0
10 changed files with 135 additions and 1876 deletions

View File

@@ -25,11 +25,11 @@ export async function GET(req: NextRequest) {
const debug = { 'req.headers': flattenNextjsRequest(req) }; const debug = { 'req.headers': flattenNextjsRequest(req) };
try { try {
const orders = await listPartyOrders(); const partyOrders = await listPartyOrders();
createAppLog(L_INFO, 'party-order list ok', {}); createAppLog(L_INFO, 'party-order list ok', {});
return response({ orders }, STATUS.OK); return response({ partyOrders }, STATUS.OK);
} catch (error) { } catch (error) {
createAppLog(L_ERROR, 'party-order list error', debug); createAppLog(L_ERROR, 'party-order list error', debug);

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +1,10 @@
// src/actions/order.ts // src/actions/party-order.ts
//
import { useMemo } from 'react'; import { useMemo } from 'react';
import axiosInstance, { endpoints, fetcher } from 'src/lib/axios'; import axiosInstance, { endpoints, fetcher } from 'src/lib/axios';
import type { IOrderItem } from 'src/types/party-order'; import type { IPartyOrderItem } from 'src/types/party-order';
import type { IProductItem } from 'src/types/product';
import type { SWRConfiguration } from 'swr'; import type { SWRConfiguration } from 'swr';
import useSWR from 'swr'; import useSWR, { mutate } from 'swr';
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
@@ -16,14 +16,14 @@ const swrOptions: SWRConfiguration = {
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
type OrdersData = { type PartyOrdersData = {
partyOrders: IOrderItem[]; partyOrders: IPartyOrderItem[];
}; };
export function useGetPartyOrders() { export function useGetPartyOrders() {
const url = endpoints.partyOrder.list; const url = endpoints.partyOrder.list;
const { data, isLoading, error, isValidating, mutate } = useSWR<OrdersData>( const { data, isLoading, error, isValidating } = useSWR<PartyOrdersData>(
url, url,
fetcher, fetcher,
swrOptions swrOptions
@@ -31,14 +31,13 @@ export function useGetPartyOrders() {
const memoizedValue = useMemo( const memoizedValue = useMemo(
() => ({ () => ({
orders: data?.partyOrders || [], partyOrders: data?.partyOrders || [],
ordersLoading: isLoading, partyOrdersLoading: isLoading,
ordersError: error, partyOrdersError: error,
ordersValidating: isValidating, partyOrdersValidating: isValidating,
ordersEmpty: !isLoading && !isValidating && !data?.partyOrders.length, partyOrdersEmpty: !isLoading && !isValidating && !data?.partyOrders.length,
mutate,
}), }),
[data?.partyOrders, error, isLoading, isValidating, mutate] [data?.partyOrders, error, isLoading, isValidating]
); );
return memoizedValue; return memoizedValue;
@@ -46,23 +45,24 @@ export function useGetPartyOrders() {
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
type OrderData = { type PartyOrderData = {
order: IOrderItem; partyOrder: IPartyOrderItem;
}; };
export function useGetOrder(orderId: string) { export function useGetPartyOrder(partyOrderId: string) {
const url = orderId ? [endpoints.order.details, { params: { orderId } }] : ''; const url = partyOrderId ? [endpoints.partyOrder.details, { params: { partyOrderId } }] : '';
const { data, isLoading, error, isValidating } = useSWR<OrderData>(url, fetcher, swrOptions); const { data, isLoading, error, isValidating } = useSWR<PartyOrderData>(url, fetcher, swrOptions);
const memoizedValue = useMemo( const memoizedValue = useMemo(
() => ({ () => ({
order: data?.order, partyOrder: data?.partyOrder,
orderLoading: isLoading, partyOrderLoading: isLoading,
orderError: error, partyOrderError: error,
orderValidating: isValidating, partyOrderValidating: isValidating,
mutate,
}), }),
[data?.order, error, isLoading, isValidating] [data?.partyOrder, error, isLoading, isValidating]
); );
return memoizedValue; return memoizedValue;
@@ -71,7 +71,7 @@ export function useGetOrder(orderId: string) {
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
type SearchResultsData = { type SearchResultsData = {
results: IProductItem[]; results: IPartyOrderItem[];
}; };
export function useSearchProducts(query: string) { export function useSearchProducts(query: string) {
@@ -98,129 +98,112 @@ export function useSearchProducts(query: string) {
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
type SaveOrderData = { export async function createPartyOrder(partyOrderData: IPartyOrderItem) {
name: string; /**
city: string; * Work on server
role: string; */
email: string; const data = { partyOrderData };
state: string; const {
status: string; data: { id },
address: string; } = await axiosInstance.post(endpoints.partyOrder.create, data);
country: string;
zipCode: string;
company: string;
avatarUrl: string;
phoneNumber: string;
isVerified: boolean;
//
ordername: string;
password: string;
};
export async function saveOrder(orderId: string, saveOrderData: SaveOrderData) { /**
// const url = orderId ? [endpoints.order.details, { params: { orderId } }] : ''; * Work in local
*/
mutate(
endpoints.partyOrder.list,
(currentData: any) => {
const currentPartyOrders: IPartyOrderItem[] = currentData?.partyOrders;
const res = await axiosInstance.post( const partyOrders = [...currentPartyOrders, { ...partyOrderData, id }];
//
`http://localhost:7272/api/order/saveOrder?orderId=${orderId}`, return { ...currentData, partyOrders };
{ },
data: saveOrderData, false
}
); );
return res;
}
export async function uploadOrderImage(saveOrderData: SaveOrderData) {
console.log('uploadOrderImage ?');
// const url = orderId ? [endpoints.order.details, { params: { orderId } }] : '';
const res = await axiosInstance.get('http://localhost:7272/api/product/helloworld');
return res;
} }
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
type CreateOrderData = { export async function updatePartyOrder(partyOrderData: Partial<IPartyOrderItem>) {
name: string; /**
city: string; * Work on server
role: string; */
email: string; const data = { partyOrderData };
state: string; await axiosInstance.put(endpoints.partyOrder.update, data);
status: string;
address: string;
country: string;
zipCode: string;
company: string;
avatarUrl: string;
phoneNumber: string;
isVerified: boolean;
//
ordername: string;
password: string;
};
export async function createOrder(createOrderData: CreateOrderData) { /**
console.log('create product ?'); * Work in local
// const url = productId ? [endpoints.product.details, { params: { productId } }] : ''; */
const res = await axiosInstance.post('http://localhost:7272/api/order/createOrder', { mutate(
data: createOrderData, endpoints.partyOrder.list,
}); (currentData: any) => {
const currentPartyOrders: IPartyOrderItem[] = currentData?.partyOrders;
return res; const partyOrders = currentPartyOrders.map((partyOrder) =>
partyOrder.id === partyOrderData.id ? { ...partyOrder, ...partyOrderData } : partyOrder
);
return { ...currentData, partyOrders };
},
false
);
} }
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
type DeleteOrderResponse = { export async function deletePartyOrder(partyOrderId: string) {
success: boolean; /**
message?: string; * Work on server
}; */
const data = { partyOrderId };
await axiosInstance.patch(endpoints.partyOrder.delete, data);
export async function deletePartyOrder(orderId: string): Promise<DeleteOrderResponse> { /**
const url = `http://localhost:7272/api/order/deleteOrder?orderId=${orderId}`; * Work in local
*/
try { mutate(
const res = await axiosInstance.delete(url); endpoints.partyOrder.list,
(currentData: any) => {
const currentProducts: IPartyOrderItem[] = currentData?.partyOrders;
return { const partyOrders = currentProducts.filter((partyOrder) => partyOrder.id !== partyOrderId);
success: true,
message: 'Order deleted successfully', return { ...currentData, partyOrders };
}; },
} catch (error) { false
return { );
success: false,
message: error instanceof Error ? error.message : 'Failed to delete product',
};
}
} }
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
type ChangeStatusResponse = { // TODO: implement partyOrder changeStatus with url below
success: boolean; // const url = endpoints.order.changeStatus(orderId);
message?: string; export async function changeStatus(partyOrderData: any, dummy: any) {
}; return true;
// /**
// * Work on server
// */
// const data = { partyOrderData };
// await axiosInstance.put(endpoints.partyOrder.update, data);
export async function changeStatus( // /**
orderId: string, // * Work in local
newOrderStatus: string // */
): Promise<ChangeStatusResponse> {
const url = endpoints.order.changeStatus(orderId);
try { // mutate(
const res = await axiosInstance.put(url, { data: { status: newOrderStatus } }); // endpoints.partyOrder.list,
// (currentData: any) => {
// const currentPartyOrders: IPartyOrderItem[] = currentData?.partyOrders;
return { // const partyOrders = currentPartyOrders.map((partyOrder) =>
success: true, // partyOrder.id === partyOrderData.id ? { ...partyOrder, ...partyOrderData } : partyOrder
message: 'status updated successfully', // );
};
} catch (error) { // return { ...currentData, partyOrders };
return { // },
success: false, // false
message: error instanceof Error ? error.message : 'Failed to delete product', // );
};
}
} }

View File

@@ -96,6 +96,8 @@ export const endpoints = {
delete: '/api/party-event/delete', delete: '/api/party-event/delete',
}, },
partyOrder: { partyOrder: {
create: '/api/party-order/create',
delete: '/api/party-order/delete',
list: '/api/party-order/list', list: '/api/party-order/list',
profile: '/api/party-order/profile', profile: '/api/party-order/profile',
update: '/api/party-order/update', update: '/api/party-order/update',

View File

@@ -3,14 +3,14 @@ import type { UseSetStateReturn } from 'minimal-shared/hooks';
import { useCallback } from 'react'; import { useCallback } from 'react';
import type { FiltersResultProps } from 'src/components/filters-result'; import type { FiltersResultProps } from 'src/components/filters-result';
import { chipProps, FiltersBlock, FiltersResult } from 'src/components/filters-result'; import { chipProps, FiltersBlock, FiltersResult } from 'src/components/filters-result';
import type { IOrderTableFilters } from 'src/types/party-order'; import type { IPartyOrderTableFilters } from 'src/types/party-order';
import { fDateRangeShortLabel } from 'src/utils/format-time'; import { fDateRangeShortLabel } from 'src/utils/format-time';
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
type Props = FiltersResultProps & { type Props = FiltersResultProps & {
onResetPage: () => void; onResetPage: () => void;
filters: UseSetStateReturn<IOrderTableFilters>; filters: UseSetStateReturn<IPartyOrderTableFilters>;
}; };
export function PartyOrderTableFiltersResult({ filters, totalResults, onResetPage, sx }: Props) { export function PartyOrderTableFiltersResult({ filters, totalResults, onResetPage, sx }: Props) {

View File

@@ -20,14 +20,14 @@ import { CustomPopover } from 'src/components/custom-popover';
import { Iconify } from 'src/components/iconify'; import { Iconify } from 'src/components/iconify';
import { Label } from 'src/components/label'; import { Label } from 'src/components/label';
import { RouterLink } from 'src/routes/components'; import { RouterLink } from 'src/routes/components';
import type { IOrderItem } from 'src/types/party-order'; import type { IPartyOrderItem } from 'src/types/party-order';
import { fCurrency } from 'src/utils/format-number'; import { fCurrency } from 'src/utils/format-number';
import { fDate, fTime } from 'src/utils/format-time'; import { fDate, fTime } from 'src/utils/format-time';
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
type Props = { type Props = {
row: IOrderItem; row: IPartyOrderItem;
selected: boolean; selected: boolean;
detailsHref: string; detailsHref: string;
onSelectRow: () => void; onSelectRow: () => void;

View File

@@ -13,14 +13,14 @@ import { useTranslation } from 'react-i18next';
import { CustomPopover } from 'src/components/custom-popover'; import { CustomPopover } from 'src/components/custom-popover';
import { Iconify } from 'src/components/iconify'; import { Iconify } from 'src/components/iconify';
import type { IDatePickerControl } from 'src/types/common'; import type { IDatePickerControl } from 'src/types/common';
import type { IOrderTableFilters } from 'src/types/party-order'; import type { IPartyOrderTableFilters } from 'src/types/party-order';
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
type Props = { type Props = {
dateError: boolean; dateError: boolean;
onResetPage: () => void; onResetPage: () => void;
filters: UseSetStateReturn<IOrderTableFilters>; filters: UseSetStateReturn<IPartyOrderTableFilters>;
}; };
export function PartyOrderTableToolbar({ filters, onResetPage, dateError }: Props) { export function PartyOrderTableToolbar({ filters, onResetPage, dateError }: Props) {

View File

@@ -12,7 +12,7 @@ import { changeStatus } from 'src/actions/party-order';
import { DashboardContent } from 'src/layouts/dashboard'; import { DashboardContent } from 'src/layouts/dashboard';
import { useTranslate } from 'src/locales'; import { useTranslate } from 'src/locales';
import { paths } from 'src/routes/paths'; import { paths } from 'src/routes/paths';
import type { IOrderItem } from 'src/types/party-order'; import type { IPartyOrderItem } from 'src/types/party-order';
import { OrderDetailsCustomer } from '../party-order-details-customer'; import { OrderDetailsCustomer } from '../party-order-details-customer';
import { OrderDetailsDelivery } from '../party-order-details-delivery'; import { OrderDetailsDelivery } from '../party-order-details-delivery';
import { OrderDetailsHistory } from '../party-order-details-history'; import { OrderDetailsHistory } from '../party-order-details-history';
@@ -24,7 +24,7 @@ import { OrderDetailsToolbar } from '../party-order-details-toolbar';
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
type Props = { type Props = {
order: IOrderItem; order: IPartyOrderItem;
}; };
export function OrderDetailsView({ order }: Props) { export function OrderDetailsView({ order }: Props) {

View File

@@ -36,7 +36,7 @@ import {
import { DashboardContent } from 'src/layouts/dashboard'; import { DashboardContent } from 'src/layouts/dashboard';
import { useRouter } from 'src/routes/hooks'; import { useRouter } from 'src/routes/hooks';
import { paths } from 'src/routes/paths'; import { paths } from 'src/routes/paths';
import type { IOrderItem, IOrderTableFilters } from 'src/types/party-order'; import type { IPartyOrderItem, IPartyOrderTableFilters } from 'src/types/party-order';
import { fIsAfter, fIsBetween } from 'src/utils/format-time'; import { fIsAfter, fIsBetween } from 'src/utils/format-time';
import { PartyOrderTableFiltersResult } from '../party-order-table-filters-result'; import { PartyOrderTableFiltersResult } from '../party-order-table-filters-result';
import { PartyOrderTableRow } from '../party-order-table-row'; import { PartyOrderTableRow } from '../party-order-table-row';
@@ -50,7 +50,6 @@ const STATUS_OPTIONS = [{ value: 'all', label: 'All' }, ...PARTY_ORDER_STATUS_OP
export function PartyOrderListView() { export function PartyOrderListView() {
const { t } = useTranslation(); const { t } = useTranslation();
const router = useRouter();
const TABLE_HEAD: TableHeadCellProps[] = [ const TABLE_HEAD: TableHeadCellProps[] = [
{ id: 'orderNumber', label: t('Order'), width: 88 }, { id: 'orderNumber', label: t('Order'), width: 88 },
@@ -62,19 +61,19 @@ export function PartyOrderListView() {
{ id: '', width: 88 }, { id: '', width: 88 },
]; ];
const { orders, mutate, ordersLoading } = useGetPartyOrders(); const { partyOrders, partyOrdersLoading } = useGetPartyOrders();
const table = useTable({ defaultOrderBy: 'orderNumber' }); const table = useTable({ defaultOrderBy: 'orderNumber' });
const confirmDialog = useBoolean(); const confirmDialog = useBoolean();
const [tableData, setTableData] = useState<IOrderItem[]>([]); const [tableData, setTableData] = useState<IPartyOrderItem[]>([]);
useEffect(() => { useEffect(() => {
setTableData(orders); setTableData(partyOrders);
}, [orders]); }, [partyOrders]);
const filters = useSetState<IOrderTableFilters>({ const filters = useSetState<IPartyOrderTableFilters>({
name: '', name: '',
status: 'all', status: 'all',
startDate: null, startDate: null,
@@ -107,7 +106,6 @@ export function PartyOrderListView() {
try { try {
await deletePartyOrder(id); await deletePartyOrder(id);
toast.success('Delete success!'); toast.success('Delete success!');
mutate();
} catch (error) { } catch (error) {
console.error(error); console.error(error);
toast.error('Delete failed!'); toast.error('Delete failed!');
@@ -117,7 +115,7 @@ export function PartyOrderListView() {
// setTableData(deleteRow); // setTableData(deleteRow);
// table.onUpdatePageDeleteRow(dataInPage.length); // table.onUpdatePageDeleteRow(dataInPage.length);
}, },
[table, tableData, mutate] [table, tableData]
); );
const handleDeleteRows = useCallback(() => { const handleDeleteRows = useCallback(() => {
@@ -163,12 +161,9 @@ export function PartyOrderListView() {
/> />
); );
useEffect(() => { // TODO: remove below loading screen as mutate is not used
mutate(); if (!partyOrders) return <>loading</>;
}, []); if (partyOrdersLoading) return <>loading</>;
if (!orders) return <>loading</>;
if (ordersLoading) return <>loading</>;
return ( return (
<> <>
@@ -324,8 +319,8 @@ export function PartyOrderListView() {
type ApplyFilterProps = { type ApplyFilterProps = {
dateError: boolean; dateError: boolean;
inputData: IOrderItem[]; inputData: IPartyOrderItem[];
filters: IOrderTableFilters; filters: IPartyOrderTableFilters;
comparator: (a: any, b: any) => number; comparator: (a: any, b: any) => number;
}; };

View File

@@ -2,7 +2,7 @@ import type { IDatePickerControl, IDateValue } from './common';
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
export type IOrderTableFilters = { export type IPartyOrderTableFilters = {
name: string; name: string;
status: string; status: string;
endDate: IDatePickerControl; endDate: IDatePickerControl;
@@ -50,7 +50,7 @@ export type IOrderProductItem = {
quantity: number; quantity: number;
}; };
export type IOrderItem = { export type IPartyOrderItem = {
id: string; id: string;
createdAt: IDateValue; createdAt: IDateValue;
// //