refactor: rename product to party-event across frontend modules and types

This commit is contained in:
louiscklaw
2025-06-15 16:33:50 +08:00
parent a88de2f17f
commit 4b64778b59
16 changed files with 93 additions and 77 deletions

View File

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

View File

@@ -2,7 +2,7 @@
//
import { useMemo } from 'react';
import axiosInstance, { endpoints, fetcher } from 'src/lib/axios';
import type { IProductItem } from 'src/types/party-event';
import type { IPartyEventItem } from 'src/types/party-event';
import type { SWRConfiguration } from 'swr';
import useSWR, { mutate } from 'swr';
@@ -16,24 +16,28 @@ const swrOptions: SWRConfiguration = {
// ----------------------------------------------------------------------
type ProductsData = {
products: IProductItem[];
type PartyEventsData = {
partyEvents: IPartyEventItem[];
};
export function useGetProducts() {
const url = endpoints.product.list;
export function useGetPartyEvents() {
const url = endpoints.partyEvent.list;
const { data, isLoading, error, isValidating } = useSWR<ProductsData>(url, fetcher, swrOptions);
const { data, isLoading, error, isValidating } = useSWR<PartyEventsData>(
url,
fetcher,
swrOptions
);
const memoizedValue = useMemo(
() => ({
products: data?.products || [],
productsLoading: isLoading,
productsError: error,
productsValidating: isValidating,
productsEmpty: !isLoading && !isValidating && !data?.products.length,
partyEvents: data?.partyEvents || [],
partyEventsLoading: isLoading,
partyEventsError: error,
partyEventsValidating: isValidating,
partyEventsEmpty: !isLoading && !isValidating && !data?.partyEvents.length,
}),
[data?.products, error, isLoading, isValidating]
[data?.partyEvents, error, isLoading, isValidating]
);
return memoizedValue;
@@ -42,7 +46,7 @@ export function useGetProducts() {
// ----------------------------------------------------------------------
type ProductData = {
product: IProductItem;
product: IPartyEventItem;
};
export function useGetPartyEvent(productId: string) {
@@ -67,7 +71,7 @@ export function useGetPartyEvent(productId: string) {
// ----------------------------------------------------------------------
type SearchResultsData = {
results: IProductItem[];
results: IPartyEventItem[];
};
export function useSearchProducts(query: string) {
@@ -94,7 +98,7 @@ export function useSearchProducts(query: string) {
// ----------------------------------------------------------------------
export async function createProduct(productData: IProductItem) {
export async function createProduct(productData: IPartyEventItem) {
/**
* Work on server
*/
@@ -109,7 +113,7 @@ export async function createProduct(productData: IProductItem) {
mutate(
endpoints.product.list,
(currentData: any) => {
const currentProducts: IProductItem[] = currentData?.products;
const currentProducts: IPartyEventItem[] = currentData?.products;
const products = [...currentProducts, { ...productData, id }];
@@ -121,7 +125,7 @@ export async function createProduct(productData: IProductItem) {
// ----------------------------------------------------------------------
export async function updateProduct(productData: Partial<IProductItem>) {
export async function updateProduct(productData: Partial<IPartyEventItem>) {
/**
* Work on server
*/
@@ -135,7 +139,7 @@ export async function updateProduct(productData: Partial<IProductItem>) {
mutate(
endpoints.product.list,
(currentData: any) => {
const currentProducts: IProductItem[] = currentData?.products;
const currentProducts: IPartyEventItem[] = currentData?.products;
const products = currentProducts.map((product) =>
product.id === productData.id ? { ...product, ...productData } : product
@@ -149,7 +153,7 @@ export async function updateProduct(productData: Partial<IProductItem>) {
// ----------------------------------------------------------------------
export async function deleteProduct(productId: string) {
export async function deletePartyEvent(productId: string) {
/**
* Work on server
*/
@@ -164,7 +168,7 @@ export async function deleteProduct(productId: string) {
endpoints.product.list,
(currentData: any) => {
console.log({ currentData });
const currentProducts: IProductItem[] = currentData?.products;
const currentProducts: IPartyEventItem[] = currentData?.products;
const products = currentProducts.filter((product) => product.id !== productId);

View File

@@ -84,4 +84,12 @@ export const endpoints = {
changeStatus: (invoiceId: string) => `/api/invoice/changeStatus?invoiceId=${invoiceId}`,
search: '/api/invoice/search',
},
partyEvent: {
list: '/api/party-event/list',
details: '/api/party-event/details',
search: '/api/party-event/search',
create: '/api/party-event/create',
update: '/api/party-event/update',
delete: '/api/party-event/delete',
},
};

View File

@@ -9,12 +9,12 @@ import {
} from 'src/components/carousel';
import { Image } from 'src/components/image';
import { Lightbox, useLightBox } from 'src/components/lightbox';
import type { IProductItem } from 'src/types/party-event';
import type { IPartyEventItem } from 'src/types/party-event';
// ----------------------------------------------------------------------
type Props = {
images?: IProductItem['images'];
images?: IPartyEventItem['images'];
};
export function ProductDetailsCarousel({ images }: Props) {

View File

@@ -17,13 +17,13 @@ import { NumberInput } from 'src/components/number-input';
import { useRouter } from 'src/routes/hooks';
import { paths } from 'src/routes/paths';
import type { CheckoutContextValue } from 'src/types/checkout';
import type { IProductItem } from 'src/types/party-event';
import type { IPartyEventItem } from 'src/types/party-event';
import { fCurrency, fShortenNumber } from 'src/utils/format-number';
// ----------------------------------------------------------------------
type Props = {
product: IProductItem;
product: IPartyEventItem;
disableActions?: boolean;
items?: CheckoutContextValue['state']['items'];
onAddToCart?: CheckoutContextValue['onAddToCart'];

View File

@@ -9,14 +9,14 @@ import { Iconify } from 'src/components/iconify';
import { Image } from 'src/components/image';
import { Label } from 'src/components/label';
import { RouterLink } from 'src/routes/components';
import type { IProductItem } from 'src/types/party-event';
import type { IPartyEventItem } from 'src/types/party-event';
import { fCurrency } from 'src/utils/format-number';
import { useCheckoutContext } from '../checkout/context';
// ----------------------------------------------------------------------
type Props = {
product: IProductItem;
product: IPartyEventItem;
detailsHref: string;
};

View File

@@ -2,7 +2,7 @@ import type { BoxProps } from '@mui/material/Box';
import Box from '@mui/material/Box';
import Pagination, { paginationClasses } from '@mui/material/Pagination';
import { paths } from 'src/routes/paths';
import type { IProductItem } from 'src/types/party-event';
import type { IPartyEventItem } from 'src/types/party-event';
import { ProductItem } from './party-event-item';
import { ProductItemSkeleton } from './party-event-skeleton';
@@ -10,10 +10,10 @@ import { ProductItemSkeleton } from './party-event-skeleton';
type Props = BoxProps & {
loading?: boolean;
products: IProductItem[];
products: IPartyEventItem[];
};
export function ProductList({ products, loading, sx, ...other }: Props) {
export function PartyEventList({ products, loading, sx, ...other }: Props) {
const renderLoading = () => <ProductItemSkeleton />;
const renderList = () =>

View File

@@ -27,7 +27,7 @@ import { Iconify } from 'src/components/iconify';
import { toast } from 'src/components/snackbar';
import { useRouter } from 'src/routes/hooks';
import { paths } from 'src/routes/paths';
import type { IProductItem } from 'src/types/party-event';
import type { IPartyEventItem } from 'src/types/party-event';
import { fileToBase64 } from 'src/utils/file-to-base64';
import { z as zod } from 'zod';
@@ -128,7 +128,7 @@ export const NewProductSchema = zod.object({
// ----------------------------------------------------------------------
type Props = {
currentProduct?: IProductItem;
currentProduct?: IPartyEventItem;
};
export function ProductNewEditForm({ currentProduct }: Props) {
@@ -202,7 +202,7 @@ export function ProductNewEditForm({ currentProduct }: Props) {
}
}
const sanitizedValues: IProductItem = values as unknown as IProductItem;
const sanitizedValues: IPartyEventItem = values as unknown as IPartyEventItem;
if (currentProduct) {
// perform save

View File

@@ -15,7 +15,7 @@ import { Iconify } from 'src/components/iconify';
import { SearchNotFound } from 'src/components/search-not-found';
import { RouterLink } from 'src/routes/components';
import { useRouter } from 'src/routes/hooks';
import type { IProductItem } from 'src/types/party-event';
import type { IPartyEventItem } from 'src/types/party-event';
// ----------------------------------------------------------------------
@@ -28,13 +28,13 @@ export function ProductSearch({ redirectPath, sx }: Props) {
const router = useRouter();
const [searchQuery, setSearchQuery] = useState('');
const [selectedItem, setSelectedItem] = useState<IProductItem | null>(null);
const [selectedItem, setSelectedItem] = useState<IPartyEventItem | null>(null);
const debouncedQuery = useDebounce(searchQuery);
const { searchResults: options, searchLoading: loading } = useSearchProducts(debouncedQuery);
const handleChange = useCallback(
(item: IProductItem | null) => {
(item: IPartyEventItem | null) => {
setSelectedItem(item);
if (item) {
router.push(redirectPath(item.id));
@@ -45,7 +45,7 @@ export function ProductSearch({ redirectPath, sx }: Props) {
const filterOptions = createFilterOptions({
matchFrom: 'any',
stringify: (option: IProductItem) => `${option.name} ${option.sku}`,
stringify: (option: IPartyEventItem) => `${option.name} ${option.sku}`,
});
const paperStyles: SxProps<Theme> = {

View File

@@ -25,7 +25,7 @@ type Props = {
};
};
export function ProductTableToolbar({ filters, options }: Props) {
export function PartyEventTableToolbar({ filters, options }: Props) {
const menuActions = usePopover();
const { state: currentFilters, setState: updateFilters } = filters;

View File

@@ -17,7 +17,7 @@ import { Iconify } from 'src/components/iconify';
import { DashboardContent } from 'src/layouts/dashboard';
import { RouterLink } from 'src/routes/components';
import { paths } from 'src/routes/paths';
import type { IProductItem } from 'src/types/party-event';
import type { IPartyEventItem } from 'src/types/party-event';
import { ProductDetailsCarousel } from '../party-event-details-carousel';
import { ProductDetailsDescription } from '../party-event-details-description';
import { ProductDetailsReview } from '../party-event-details-review';
@@ -48,7 +48,7 @@ const SUMMARY = [
// ----------------------------------------------------------------------
type Props = {
product?: IProductItem;
product?: IPartyEventItem;
loading?: boolean;
error?: any;
};

View File

@@ -1,13 +1,13 @@
import { CustomBreadcrumbs } from 'src/components/custom-breadcrumbs';
import { DashboardContent } from 'src/layouts/dashboard';
import { paths } from 'src/routes/paths';
import type { IProductItem } from 'src/types/party-event';
import type { IPartyEventItem } from 'src/types/party-event';
import { ProductNewEditForm } from '../party-event-new-edit-form';
// ----------------------------------------------------------------------
type Props = {
product?: IProductItem;
product?: IPartyEventItem;
};
export function PartyEventEditView({ product }: Props) {

View File

@@ -1,4 +1,5 @@
// src/sections/product/view/product-list-view.tsx
// src/sections/party-event/view/party-event-list-view.tsx
//
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import Card from '@mui/material/Card';
@@ -28,7 +29,7 @@ import { useBoolean, useSetState } from 'minimal-shared/hooks';
import { useCallback, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
// import { PRODUCT_STOCK_OPTIONS } from 'src/_mock';
import { deleteProduct, useGetProducts } from 'src/actions/party-event';
import { deletePartyEvent, useGetPartyEvents } from 'src/actions/party-event';
import { CustomBreadcrumbs } from 'src/components/custom-breadcrumbs';
import { ConfirmDialog } from 'src/components/custom-dialog';
import { EmptyContent } from 'src/components/empty-content';
@@ -38,7 +39,7 @@ import { DashboardContent } from 'src/layouts/dashboard';
import { endpoints } from 'src/lib/axios';
import { RouterLink } from 'src/routes/components';
import { paths } from 'src/routes/paths';
import type { IProductItem, IProductTableFilters } from 'src/types/party-event';
import type { IPartyEventItem, IProductTableFilters } from 'src/types/party-event';
import { mutate } from 'swr';
import { ProductTableFiltersResult } from '../party-event-table-filters-result';
import {
@@ -48,7 +49,7 @@ import {
RenderCellPublish,
RenderCellStock,
} from '../party-event-table-row';
import { ProductTableToolbar } from '../party-event-table-toolbar';
import { PartyEventTableToolbar } from '../party-event-table-toolbar';
// ----------------------------------------------------------------------
@@ -79,9 +80,9 @@ export function PartyEventListView() {
const confirmDeleteSingleItemDialog = useBoolean();
const [idToDelete, setIdToDelete] = useState<string | null>(null);
const { products, productsLoading } = useGetProducts();
const { partyEvents, partyEventsLoading } = useGetPartyEvents();
const [tableData, setTableData] = useState<IProductItem[]>(products);
const [tableData, setTableData] = useState<IPartyEventItem[]>(partyEvents);
const [selectedRowIds, setSelectedRowIds] = useState<GridRowSelectionModel>([]);
const [filterButtonEl, setFilterButtonEl] = useState<HTMLButtonElement | null>(null);
@@ -92,10 +93,10 @@ export function PartyEventListView() {
useState<GridColumnVisibilityModel>(HIDE_COLUMNS);
useEffect(() => {
if (products.length) {
setTableData(products);
if (partyEvents.length) {
setTableData(partyEvents);
}
}, [products]);
}, [partyEvents]);
const canReset = currentFilters.publish.length > 0 || currentFilters.stock.length > 0;
@@ -109,7 +110,7 @@ export function PartyEventListView() {
try {
if (idToDelete) {
await deleteProduct(idToDelete);
await deletePartyEvent(idToDelete);
toast.success('Delete success!');
}
} catch (error) {
@@ -125,10 +126,10 @@ export function PartyEventListView() {
const handleDeleteRow = useCallback(
async (id: string) => {
try {
await deleteProduct(id);
await deletePartyEvent(id);
// invalidate cache to reload list
await mutate(endpoints.product.list);
await mutate(endpoints.partyEvent.list);
toast.success('Delete success!');
} catch (error) {
@@ -167,12 +168,15 @@ export function PartyEventListView() {
{ field: 'category', headerName: t('Category'), filterable: false },
{
field: 'name',
headerName: t('Product'),
headerName: t('Party Event'),
flex: 1,
minWidth: 360,
hideable: false,
renderCell: (params) => (
<RenderCellProduct params={params} href={paths.dashboard.product.details(params.row.id)} />
<RenderCellProduct
params={params}
href={paths.dashboard.partyEvent.details(params.row.id)}
/>
),
},
{
@@ -220,13 +224,13 @@ export function PartyEventListView() {
showInMenu
icon={<Iconify icon="solar:eye-bold" />}
label="View"
href={paths.dashboard.product.details(params.row.id)}
href={paths.dashboard.partyEvent.details(params.row.id)}
/>,
<GridActionsLinkItem
showInMenu
icon={<Iconify icon="solar:pen-bold" />}
label="Edit"
href={paths.dashboard.product.edit(params.row.id)}
href={paths.dashboard.partyEvent.edit(params.row.id)}
/>,
<GridActionsCellItem
showInMenu
@@ -251,7 +255,7 @@ export function PartyEventListView() {
<ConfirmDialog
open={confirmDeleteMultiItemsDialog.value}
onClose={confirmDeleteMultiItemsDialog.onFalse}
title="Delete multiple products"
title="Delete multiple party events"
content={
<>
Are you sure want to delete <strong> {selectedRowIds.length} </strong> items?
@@ -277,7 +281,7 @@ export function PartyEventListView() {
<ConfirmDialog
open={confirmDeleteSingleItemDialog.value}
onClose={confirmDeleteSingleItemDialog.onFalse}
title="Delete product"
title="Delete party event"
content={<>Are you sure want to delete item?</>}
action={
<Button
@@ -303,17 +307,17 @@ export function PartyEventListView() {
heading={t('Product List')}
links={[
{ name: t('Dashboard'), href: paths.dashboard.root },
{ name: t('Product'), href: paths.dashboard.product.root },
{ name: t('Product'), href: paths.dashboard.partyEvent.root },
{ name: t('List') },
]}
action={
<Button
component={RouterLink}
href={paths.dashboard.product.new}
href={paths.dashboard.partyEvent.new}
variant="contained"
startIcon={<Iconify icon="mingcute:add-line" />}
>
{t('new-product')}
{t('new-party-event')}
</Button>
}
sx={{ mb: { xs: 3, md: 5 } }}
@@ -333,7 +337,7 @@ export function PartyEventListView() {
disableRowSelectionOnClick
rows={dataFiltered}
columns={columns}
loading={productsLoading}
loading={partyEventsLoading}
getRowHeight={() => 'auto'}
pageSizeOptions={[5, 10, 20, { value: -1, label: 'All' }]}
initialState={{ pagination: { paginationModel: { pageSize: 10 } } }}
@@ -402,7 +406,7 @@ function CustomToolbar({
return (
<>
<GridToolbarContainer>
<ProductTableToolbar
<PartyEventTableToolbar
filters={filters}
options={{ stocks: PRODUCT_STOCK_OPTIONS, publishs: PUBLISH_OPTIONS }}
/>
@@ -474,7 +478,7 @@ export function GridActionsLinkItem({ ref, href, label, icon, sx }: GridActionsL
// ----------------------------------------------------------------------
type ApplyFilterProps = {
inputData: IProductItem[];
inputData: IPartyEventItem[];
filters: IProductTableFilters;
};
@@ -482,11 +486,11 @@ function applyFilter({ inputData, filters }: ApplyFilterProps) {
const { stock, publish } = filters;
if (stock.length) {
inputData = inputData.filter((product) => stock.includes(product.inventoryType));
inputData = inputData.filter((partyEvent) => stock.includes(partyEvent.inventoryType));
}
if (publish.length) {
inputData = inputData.filter((product) => publish.includes(product.publish));
inputData = inputData.filter((partyEvent) => publish.includes(partyEvent.publish));
}
return inputData;

View File

@@ -15,7 +15,7 @@ import { EmptyContent } from 'src/components/empty-content';
import { Iconify } from 'src/components/iconify';
import { RouterLink } from 'src/routes/components';
import { paths } from 'src/routes/paths';
import type { IProductItem } from 'src/types/party-event';
import type { IPartyEventItem } from 'src/types/party-event';
import { useCheckoutContext } from '../../checkout/context';
import { CartIcon } from '../cart-icon';
import { ProductDetailsCarousel } from '../party-event-details-carousel';
@@ -47,7 +47,7 @@ const SUMMARY = [
// ----------------------------------------------------------------------
type Props = {
product?: IProductItem;
product?: IPartyEventItem;
loading?: boolean;
error?: any;
};

View File

@@ -14,19 +14,19 @@ import {
} from 'src/_mock';
import { EmptyContent } from 'src/components/empty-content';
import { paths } from 'src/routes/paths';
import type { IProductFilters, IProductItem } from 'src/types/party-event';
import type { IPartyEventItem, IProductFilters } from 'src/types/party-event';
import { useCheckoutContext } from '../../checkout/context';
import { CartIcon } from '../cart-icon';
import { ProductFiltersDrawer } from '../party-event-filters-drawer';
import { ProductFiltersResult } from '../party-event-filters-result';
import { ProductList } from '../party-event-list';
import { PartyEventList } from '../party-event-list';
import { ProductSearch } from '../party-event-search';
import { ProductSort } from '../party-event-sort';
// ----------------------------------------------------------------------
type Props = {
products: IProductItem[];
products: IPartyEventItem[];
loading?: boolean;
};
@@ -121,7 +121,7 @@ export function ProductShopView({ products, loading }: Props) {
{notFound || isEmpty ? (
renderNotFound()
) : (
<ProductList products={dataFiltered} loading={loading} />
<PartyEventList products={dataFiltered} loading={loading} />
)}
</Container>
);
@@ -132,7 +132,7 @@ export function ProductShopView({ products, loading }: Props) {
type ApplyFilterProps = {
sortBy: string;
filters: IProductFilters;
inputData: IProductItem[];
inputData: IPartyEventItem[];
};
function applyFilter({ inputData, filters, sortBy }: ApplyFilterProps) {

View File

@@ -27,7 +27,7 @@ export type IProductReview = {
attachments?: string[];
};
export type IProductItem = {
export type IPartyEventItem = {
id: string;
createdAt: IDateValue;
//