update build ok,
This commit is contained in:
@@ -39,9 +39,11 @@ function ErrorDetails({ details }: { details: string }): React.JSX.Element {
|
||||
|
||||
<Collapse in={expanded}>
|
||||
<Box sx={{ mt: 1, p: 1, bgcolor: 'background.paper' }}>
|
||||
<Typography variant="body2" component="pre" sx={{ whiteSpace: 'pre-wrap' }}>
|
||||
{details}
|
||||
</Typography>
|
||||
<pre>
|
||||
<Typography variant="body2" component="pre" sx={{ whiteSpace: 'pre-wrap' }}>
|
||||
{details}
|
||||
</Typography>
|
||||
</pre>
|
||||
</Box>
|
||||
</Collapse>
|
||||
</Box>
|
||||
|
@@ -24,9 +24,8 @@ import { pb } from '@/lib/pb';
|
||||
import { FilterButton, FilterPopover, useFilterContext } from '@/components/core/filter-button';
|
||||
import { Option } from '@/components/core/option';
|
||||
|
||||
// import type { LessonType } from './ILessonType';
|
||||
import { useLessonTypesSelection } from './lesson-types-selection-context';
|
||||
import { LessonType } from './types';
|
||||
import type { LessonType } from './types';
|
||||
|
||||
export interface Filters {
|
||||
email?: string;
|
||||
@@ -61,18 +60,6 @@ export function LessonTypesFilters({
|
||||
|
||||
const selection = useLessonTypesSelection();
|
||||
|
||||
function getVisible(): number {
|
||||
return fullData.reduce((count, item: LessonType) => {
|
||||
return item.visible === 'visible' ? count + 1 : count;
|
||||
}, 0);
|
||||
}
|
||||
|
||||
function getHidden(): number {
|
||||
return fullData.reduce((count, item: LessonType) => {
|
||||
return item.visible === 'hidden' ? count + 1 : count;
|
||||
}, 0);
|
||||
}
|
||||
|
||||
// The tabs should be generated using API data.
|
||||
const tabs = [
|
||||
{ label: t('All'), value: '', count: totalCount },
|
||||
@@ -195,7 +182,13 @@ export function LessonTypesFilters({
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Tabs onChange={handleVisibleChange} sx={{ px: 3 }} value={visible ?? ''} variant="scrollable">
|
||||
<Tabs
|
||||
onChange={handleVisibleChange}
|
||||
sx={{ px: 3 }}
|
||||
value={visible ?? ''}
|
||||
variant="scrollable"
|
||||
//
|
||||
>
|
||||
{tabs.map((tab) => (
|
||||
<Tab
|
||||
icon={<Chip label={tab.count} size="small" variant="soft" />}
|
||||
|
@@ -0,0 +1,41 @@
|
||||
import { NO_NUM, NO_VALUE } from '@/constants';
|
||||
import type { RecordModel } from 'pocketbase';
|
||||
|
||||
import { CreateForm, LpCategory } from '@/types/LpCategory';
|
||||
import { dayjs } from '@/lib/dayjs';
|
||||
|
||||
// import type { CreateForm, LpCategory } from './types';
|
||||
|
||||
export const LpCategoryCreateFormDefault: CreateForm = {
|
||||
name: '',
|
||||
description: '',
|
||||
isActive: true,
|
||||
order: 1,
|
||||
imageUrl: '',
|
||||
};
|
||||
|
||||
export const defaultLpCategory: LpCategory = {
|
||||
id: '',
|
||||
name: '',
|
||||
description: '',
|
||||
isActive: true,
|
||||
order: 1,
|
||||
imageUrl: '',
|
||||
createdAt: dayjs().toDate(),
|
||||
updatedAt: dayjs().toDate(),
|
||||
visible: 'active',
|
||||
status: '',
|
||||
};
|
||||
|
||||
export const emptyLpCategory: LpCategory = {
|
||||
...defaultLpCategory,
|
||||
isActive: false,
|
||||
};
|
||||
|
||||
export const LpCategoryDefaultValue = {
|
||||
createForm: LpCategoryCreateFormDefault,
|
||||
default: defaultLpCategory,
|
||||
empty: emptyLpCategory,
|
||||
};
|
||||
|
||||
export default LpCategoryDefaultValue;
|
@@ -3,6 +3,8 @@
|
||||
import * as React from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import GetAllCount from '@/db/QuizListenings/GetAllCount';
|
||||
import GetHiddenCount from '@/db/QuizListenings/GetHiddenCount';
|
||||
import GetVisibleCount from '@/db/QuizListenings/GetVisibleCount';
|
||||
import Button from '@mui/material/Button';
|
||||
import Chip from '@mui/material/Chip';
|
||||
import Divider from '@mui/material/Divider';
|
||||
@@ -16,41 +18,56 @@ import Tabs from '@mui/material/Tabs';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import type { LpCategory } from '@/types/LpCategory';
|
||||
import { paths } from '@/paths';
|
||||
import { FilterButton, FilterPopover, useFilterContext } from '@/components/core/filter-button';
|
||||
import { Option } from '@/components/core/option';
|
||||
|
||||
import { useLpCategoriesSelection } from './lp-categories-selection-context';
|
||||
|
||||
// The tabs should be generated using API data.
|
||||
const tabs1 = [
|
||||
{ label: 'All', value: '', count: 5 },
|
||||
{ label: 'Active', value: 'active', count: 3 },
|
||||
{ label: 'Pending', value: 'pending', count: 1 },
|
||||
{ label: 'Blocked', value: 'blocked', count: 1 },
|
||||
] as const;
|
||||
|
||||
export interface Filters {
|
||||
email?: string;
|
||||
phone?: string;
|
||||
status?: string;
|
||||
name?: string;
|
||||
visible?: string;
|
||||
type?: string;
|
||||
}
|
||||
|
||||
export type SortDir = 'asc' | 'desc';
|
||||
|
||||
export interface CustomersFiltersProps {
|
||||
export interface LpCategoriesFiltersProps {
|
||||
filters?: Filters;
|
||||
sortDir?: SortDir;
|
||||
fullData: LpCategory[];
|
||||
}
|
||||
|
||||
export function LpCategoriesFilters({ filters = {}, sortDir = 'desc' }: CustomersFiltersProps): React.JSX.Element {
|
||||
export function LpCategoriesFilters({
|
||||
filters = {},
|
||||
sortDir = 'desc',
|
||||
fullData,
|
||||
}: LpCategoriesFiltersProps): React.JSX.Element {
|
||||
const { t } = useTranslation();
|
||||
const { email, phone, status } = filters;
|
||||
const { email, phone, status, name, visible, type } = filters;
|
||||
|
||||
const [totalCount, setTotalCount] = React.useState<number>(0);
|
||||
const [visibleCount, setVisibleCount] = React.useState<number>(0);
|
||||
const [hiddenCount, setHiddenCount] = React.useState<number>(0);
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const selection = useLpCategoriesSelection();
|
||||
|
||||
// The tabs should be generated using API data.
|
||||
const tabs = [
|
||||
{ label: t('All'), value: '', count: totalCount },
|
||||
// { label: 'Active', value: 'active', count: 3 },
|
||||
// { label: 'Pending', value: 'pending', count: 1 },
|
||||
// { label: 'Blocked', value: 'blocked', count: 1 },
|
||||
{ label: t('visible'), value: 'visible', count: visibleCount },
|
||||
{ label: t('hidden'), value: 'hidden', count: hiddenCount },
|
||||
] as const;
|
||||
|
||||
const updateSearchParams = React.useCallback(
|
||||
(newFilters: Filters, newSortDir: SortDir): void => {
|
||||
const searchParams = new URLSearchParams();
|
||||
@@ -71,6 +88,18 @@ export function LpCategoriesFilters({ filters = {}, sortDir = 'desc' }: Customer
|
||||
searchParams.set('phone', newFilters.phone);
|
||||
}
|
||||
|
||||
if (newFilters.name) {
|
||||
searchParams.set('name', newFilters.name);
|
||||
}
|
||||
|
||||
if (newFilters.type) {
|
||||
searchParams.set('type', newFilters.type);
|
||||
}
|
||||
|
||||
if (newFilters.visible) {
|
||||
searchParams.set('visible', newFilters.visible);
|
||||
}
|
||||
|
||||
router.push(`${paths.dashboard.lp_categories.list}?${searchParams.toString()}`);
|
||||
},
|
||||
[router]
|
||||
@@ -87,6 +116,27 @@ export function LpCategoriesFilters({ filters = {}, sortDir = 'desc' }: Customer
|
||||
[updateSearchParams, filters, sortDir]
|
||||
);
|
||||
|
||||
const handleVisibleChange = React.useCallback(
|
||||
(_: React.SyntheticEvent, value: string) => {
|
||||
updateSearchParams({ ...filters, visible: value }, sortDir);
|
||||
},
|
||||
[updateSearchParams, filters, sortDir]
|
||||
);
|
||||
|
||||
const handleNameChange = React.useCallback(
|
||||
(value?: string) => {
|
||||
updateSearchParams({ ...filters, name: value }, sortDir);
|
||||
},
|
||||
[updateSearchParams, filters, sortDir]
|
||||
);
|
||||
|
||||
const handleTypeChange = React.useCallback(
|
||||
(value?: string) => {
|
||||
updateSearchParams({ ...filters, type: value }, sortDir);
|
||||
},
|
||||
[updateSearchParams, filters, sortDir]
|
||||
);
|
||||
|
||||
const handleEmailChange = React.useCallback(
|
||||
(value?: string) => {
|
||||
updateSearchParams({ ...filters, email: value }, sortDir);
|
||||
@@ -108,28 +158,35 @@ export function LpCategoriesFilters({ filters = {}, sortDir = 'desc' }: Customer
|
||||
[updateSearchParams, filters]
|
||||
);
|
||||
|
||||
const [allCount, setAllCount] = React.useState<number>(0);
|
||||
|
||||
React.useEffect(() => {
|
||||
async function fetchAllCount(): Promise<void> {
|
||||
setAllCount(await GetAllCount());
|
||||
}
|
||||
const fetchCount = async (): Promise<void> => {
|
||||
try {
|
||||
const tc = await GetAllCount();
|
||||
setTotalCount(tc);
|
||||
|
||||
void fetchAllCount();
|
||||
const vc = await GetVisibleCount();
|
||||
setVisibleCount(vc);
|
||||
|
||||
const hc = await GetHiddenCount();
|
||||
setHiddenCount(hc);
|
||||
} catch (error) {
|
||||
//
|
||||
}
|
||||
};
|
||||
void fetchCount();
|
||||
}, []);
|
||||
|
||||
const tabs = [
|
||||
{ label: 'All', value: '', count: allCount },
|
||||
{ label: 'Active', value: 'active', count: 3 },
|
||||
{ label: 'Pending', value: 'pending', count: 1 },
|
||||
{ label: 'Blocked', value: 'blocked', count: 1 },
|
||||
] as const;
|
||||
|
||||
const hasFilters = status || email || phone;
|
||||
const hasFilters = status || email || phone || visible || name || type;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Tabs onChange={handleStatusChange} sx={{ px: 3 }} value={status ?? ''} variant="scrollable">
|
||||
<Tabs
|
||||
onChange={handleVisibleChange}
|
||||
sx={{ px: 3 }}
|
||||
value={visible ?? ''}
|
||||
variant="scrollable"
|
||||
//
|
||||
>
|
||||
{tabs.map((tab) => (
|
||||
<Tab
|
||||
icon={<Chip label={tab.count} size="small" variant="soft" />}
|
||||
@@ -146,35 +203,37 @@ export function LpCategoriesFilters({ filters = {}, sortDir = 'desc' }: Customer
|
||||
<Stack direction="row" spacing={2} sx={{ alignItems: 'center', flexWrap: 'wrap', px: 3, py: 2 }}>
|
||||
<Stack direction="row" spacing={2} sx={{ alignItems: 'center', flex: '1 1 auto', flexWrap: 'wrap' }}>
|
||||
<FilterButton
|
||||
displayValue={email}
|
||||
label="Email"
|
||||
displayValue={name}
|
||||
label={t('Name')}
|
||||
onFilterApply={(value) => {
|
||||
handleEmailChange(value as string);
|
||||
handleNameChange(value as string);
|
||||
}}
|
||||
onFilterDelete={() => {
|
||||
handleEmailChange();
|
||||
handleNameChange();
|
||||
}}
|
||||
popover={<EmailFilterPopover />}
|
||||
value={email}
|
||||
popover={<NameFilterPopover />}
|
||||
value={name}
|
||||
/>
|
||||
|
||||
<FilterButton
|
||||
displayValue={phone}
|
||||
label="Phone number"
|
||||
displayValue={type}
|
||||
label={t('Type')}
|
||||
onFilterApply={(value) => {
|
||||
handlePhoneChange(value as string);
|
||||
handleTypeChange(value as string);
|
||||
}}
|
||||
onFilterDelete={() => {
|
||||
handlePhoneChange();
|
||||
handleTypeChange();
|
||||
}}
|
||||
popover={<PhoneFilterPopover />}
|
||||
value={phone}
|
||||
popover={<TypeFilterPopover />}
|
||||
value={type}
|
||||
/>
|
||||
|
||||
{hasFilters ? <Button onClick={handleClearFilters}>{t('Clear filters')}</Button> : null}
|
||||
</Stack>
|
||||
{selection.selectedAny ? (
|
||||
<Stack direction="row" spacing={2} sx={{ alignItems: 'center' }}>
|
||||
<Typography color="text.secondary" variant="body2">
|
||||
{selection.selected.size} selected
|
||||
{selection.selected.size} {t('selected')}
|
||||
</Typography>
|
||||
<Button color="error" variant="contained">
|
||||
{t('Delete')}
|
||||
@@ -190,7 +249,7 @@ export function LpCategoriesFilters({ filters = {}, sortDir = 'desc' }: Customer
|
||||
);
|
||||
}
|
||||
|
||||
function EmailFilterPopover(): React.JSX.Element {
|
||||
function TypeFilterPopover(): React.JSX.Element {
|
||||
const { t } = useTranslation();
|
||||
const { anchorEl, onApply, onClose, open, value: initialValue } = useFilterContext();
|
||||
const [value, setValue] = React.useState<string>('');
|
||||
@@ -200,7 +259,7 @@ function EmailFilterPopover(): React.JSX.Element {
|
||||
}, [initialValue]);
|
||||
|
||||
return (
|
||||
<FilterPopover anchorEl={anchorEl} onClose={onClose} open={open} title={t('Filter by email')}>
|
||||
<FilterPopover anchorEl={anchorEl} onClose={onClose} open={open} title={t('Filter by type')}>
|
||||
<FormControl>
|
||||
<OutlinedInput
|
||||
onChange={(event) => {
|
||||
@@ -226,8 +285,78 @@ function EmailFilterPopover(): React.JSX.Element {
|
||||
);
|
||||
}
|
||||
|
||||
function NameFilterPopover(): React.JSX.Element {
|
||||
const { t } = useTranslation();
|
||||
const { anchorEl, onApply, onClose, open, value: initialValue } = useFilterContext();
|
||||
const [value, setValue] = React.useState<string>('');
|
||||
|
||||
React.useEffect(() => {
|
||||
setValue((initialValue as string | undefined) ?? '');
|
||||
}, [initialValue]);
|
||||
|
||||
return (
|
||||
<FilterPopover anchorEl={anchorEl} onClose={onClose} open={open} title={t('Filter by name')}>
|
||||
<FormControl>
|
||||
<OutlinedInput
|
||||
onChange={(event) => {
|
||||
setValue(event.target.value);
|
||||
}}
|
||||
onKeyUp={(event) => {
|
||||
if (event.key === 'Enter') {
|
||||
onApply(value);
|
||||
}
|
||||
}}
|
||||
value={value}
|
||||
/>
|
||||
</FormControl>
|
||||
<Button
|
||||
onClick={() => {
|
||||
onApply(value);
|
||||
}}
|
||||
variant="contained"
|
||||
>
|
||||
{t('Apply')}
|
||||
</Button>
|
||||
</FilterPopover>
|
||||
);
|
||||
}
|
||||
|
||||
function EmailFilterPopover(): React.JSX.Element {
|
||||
const { anchorEl, onApply, onClose, open, value: initialValue } = useFilterContext();
|
||||
const [value, setValue] = React.useState<string>('');
|
||||
|
||||
React.useEffect(() => {
|
||||
setValue((initialValue as string | undefined) ?? '');
|
||||
}, [initialValue]);
|
||||
|
||||
return (
|
||||
<FilterPopover anchorEl={anchorEl} onClose={onClose} open={open} title="Filter by email">
|
||||
<FormControl>
|
||||
<OutlinedInput
|
||||
onChange={(event) => {
|
||||
setValue(event.target.value);
|
||||
}}
|
||||
onKeyUp={(event) => {
|
||||
if (event.key === 'Enter') {
|
||||
onApply(value);
|
||||
}
|
||||
}}
|
||||
value={value}
|
||||
/>
|
||||
</FormControl>
|
||||
<Button
|
||||
onClick={() => {
|
||||
onApply(value);
|
||||
}}
|
||||
variant="contained"
|
||||
>
|
||||
Apply
|
||||
</Button>
|
||||
</FilterPopover>
|
||||
);
|
||||
}
|
||||
|
||||
function PhoneFilterPopover(): React.JSX.Element {
|
||||
const { t } = useTranslation();
|
||||
const { anchorEl, onApply, onClose, open, value: initialValue } = useFilterContext();
|
||||
const [value, setValue] = React.useState<string>('');
|
||||
|
||||
@@ -236,7 +365,7 @@ function PhoneFilterPopover(): React.JSX.Element {
|
||||
}, [initialValue]);
|
||||
|
||||
return (
|
||||
<FilterPopover anchorEl={anchorEl} onClose={onClose} open={open} title={t('Filter by phone number')}>
|
||||
<FilterPopover anchorEl={anchorEl} onClose={onClose} open={open} title="Filter by phone number">
|
||||
<FormControl>
|
||||
<OutlinedInput
|
||||
onChange={(event) => {
|
||||
@@ -248,7 +377,6 @@ function PhoneFilterPopover(): React.JSX.Element {
|
||||
}
|
||||
}}
|
||||
value={value}
|
||||
placeholder={t('Enter phone number')}
|
||||
/>
|
||||
</FormControl>
|
||||
<Button
|
||||
@@ -257,7 +385,7 @@ function PhoneFilterPopover(): React.JSX.Element {
|
||||
}}
|
||||
variant="contained"
|
||||
>
|
||||
{t('Apply')}
|
||||
Apply
|
||||
</Button>
|
||||
</FilterPopover>
|
||||
);
|
||||
|
@@ -7,25 +7,42 @@ function noop(): void {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
interface CustomersPaginationProps {
|
||||
interface LpCategoriesPaginationProps {
|
||||
count: number;
|
||||
page: number;
|
||||
setPage: (page: number) => void;
|
||||
setRowsPerPage: (page: number) => void;
|
||||
rowsPerPage: number;
|
||||
}
|
||||
|
||||
export function LpCategoriesPagination({ count, page }: CustomersPaginationProps): React.JSX.Element {
|
||||
export function LpCategoriesPagination({
|
||||
count,
|
||||
page,
|
||||
setPage,
|
||||
setRowsPerPage,
|
||||
rowsPerPage,
|
||||
}: LpCategoriesPaginationProps): React.JSX.Element {
|
||||
// You should implement the pagination using a similar logic as the filters.
|
||||
// Note that when page change, you should keep the filter search params.
|
||||
const handleChangePage = (event: unknown, newPage: number) => {
|
||||
setPage(newPage);
|
||||
};
|
||||
|
||||
const handleChangeRowsPerPage = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setRowsPerPage(parseInt(event.target.value));
|
||||
// console.log(parseInt(event.target.value));
|
||||
};
|
||||
|
||||
return (
|
||||
<TablePagination
|
||||
component="div"
|
||||
count={count}
|
||||
onPageChange={noop}
|
||||
onRowsPerPageChange={noop}
|
||||
page={page}
|
||||
rowsPerPage={5}
|
||||
rowsPerPage={rowsPerPage}
|
||||
rowsPerPageOptions={[5, 10, 25]}
|
||||
//
|
||||
onPageChange={handleChangePage}
|
||||
onRowsPerPageChange={handleChangeRowsPerPage}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@@ -29,77 +29,6 @@ import type { ColumnDef } from '@/components/core/data-table';
|
||||
import type { LessonCategory } from '../lesson_category/types';
|
||||
import { useLpCategoriesSelection } from './lp-categories-selection-context';
|
||||
|
||||
const columns1 = [
|
||||
{
|
||||
formatter: (row): React.JSX.Element => (
|
||||
<Stack direction="row" spacing={1} sx={{ alignItems: 'center' }}>
|
||||
<Avatar src={row.avatar} />{' '}
|
||||
<div>
|
||||
<Link
|
||||
color="inherit"
|
||||
component={RouterLink}
|
||||
href={paths.dashboard.customers.details('1')}
|
||||
sx={{ whiteSpace: 'nowrap' }}
|
||||
variant="subtitle2"
|
||||
>
|
||||
{row.name}
|
||||
</Link>
|
||||
<Typography color="text.secondary" variant="body2">
|
||||
{row.email}
|
||||
</Typography>
|
||||
</div>
|
||||
</Stack>
|
||||
),
|
||||
name: 'Name',
|
||||
width: '250px',
|
||||
},
|
||||
{
|
||||
formatter: (row): React.JSX.Element => (
|
||||
<Stack direction="row" spacing={2} sx={{ alignItems: 'center' }}>
|
||||
<LinearProgress sx={{ flex: '1 1 auto' }} value={row.quota} variant="determinate" />
|
||||
<Typography color="text.secondary" variant="body2">
|
||||
{new Intl.NumberFormat('en-US', { style: 'percent', maximumFractionDigits: 2 }).format(row.quota / 100)}
|
||||
</Typography>
|
||||
</Stack>
|
||||
),
|
||||
name: 'Quota',
|
||||
width: '250px',
|
||||
},
|
||||
{ field: 'phone', name: 'Phone number', width: '150px' },
|
||||
{
|
||||
formatter(row) {
|
||||
return dayjs(row.createdAt).format('MMM D, YYYY h:mm A');
|
||||
},
|
||||
name: 'Created at',
|
||||
width: '200px',
|
||||
},
|
||||
{
|
||||
formatter: (row): React.JSX.Element => {
|
||||
const mapping = {
|
||||
active: { label: 'Active', icon: <CheckCircleIcon color="var(--mui-palette-success-main)" weight="fill" /> },
|
||||
blocked: { label: 'Blocked', icon: <MinusIcon color="var(--mui-palette-error-main)" /> },
|
||||
pending: { label: 'Pending', icon: <ClockIcon color="var(--mui-palette-warning-main)" weight="fill" /> },
|
||||
} as const;
|
||||
const { label, icon } = mapping[row.status] ?? { label: 'Unknown', icon: null };
|
||||
|
||||
return <Chip icon={icon} label={label} size="small" variant="outlined" />;
|
||||
},
|
||||
name: 'Status',
|
||||
width: '150px',
|
||||
},
|
||||
{
|
||||
formatter: (): React.JSX.Element => (
|
||||
<IconButton component={RouterLink} href={paths.dashboard.customers.details('1')}>
|
||||
<PencilSimpleIcon />
|
||||
</IconButton>
|
||||
),
|
||||
name: 'Actions',
|
||||
hideName: true,
|
||||
width: '100px',
|
||||
align: 'right',
|
||||
},
|
||||
] satisfies ColumnDef<LpCategory>[];
|
||||
|
||||
function columns(handleDeleteClick: (testId: string) => void): ColumnDef<LpCategory>[] {
|
||||
return [
|
||||
{
|
||||
@@ -134,7 +63,9 @@ function columns(handleDeleteClick: (testId: string) => void): ColumnDef<LpCateg
|
||||
<Stack direction="row" spacing={2} sx={{ alignItems: 'center' }}>
|
||||
<LinearProgress sx={{ flex: '1 1 auto' }} value={row.quota} variant="determinate" />
|
||||
<Typography color="text.secondary" variant="body2">
|
||||
{new Intl.NumberFormat('en-US', { style: 'percent', maximumFractionDigits: 2 }).format(row.quota / 100)}
|
||||
{new Intl.NumberFormat('en-US', { style: 'percent', maximumFractionDigits: 2 }).format(
|
||||
row?.quota ? row.quota / 100 : 0
|
||||
)}
|
||||
</Typography>
|
||||
</Stack>
|
||||
),
|
||||
@@ -153,7 +84,7 @@ function columns(handleDeleteClick: (testId: string) => void): ColumnDef<LpCateg
|
||||
pending: { label: 'Pending', icon: <ClockIcon color="var(--mui-palette-warning-main)" weight="fill" /> },
|
||||
NA: { label: 'NA', icon: <ClockIcon color="var(--mui-palette-warning-main)" weight="fill" /> },
|
||||
} as const;
|
||||
const { label, icon } = mapping[row.status] ?? { label: 'Unknown', icon: null };
|
||||
const { label, icon } = mapping[row.visible] ?? { label: 'Unknown', icon: null };
|
||||
|
||||
return (
|
||||
<Button
|
||||
@@ -211,7 +142,8 @@ export interface LpCategoriesTableProps {
|
||||
}
|
||||
|
||||
function getCatImageFromId(row: LpCategory): string | undefined {
|
||||
return `http://127.0.0.1:8090/api/files/${row.collectionId}/${row.id}/${row.cat_image}`;
|
||||
return 'get cat image from id';
|
||||
// return `http://127.0.0.1:8090/api/files/${'row.collectionId'}/${'row.id'}/${'row.cat_image'}`;
|
||||
}
|
||||
|
||||
export function LpCategoriesTable({ rows }: LpCategoriesTableProps): React.JSX.Element {
|
||||
|
Reference in New Issue
Block a user