update to use,
This commit is contained in:
@@ -34,6 +34,7 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import { paths } from '@/paths';
|
import { paths } from '@/paths';
|
||||||
import { dayjs } from '@/lib/dayjs';
|
import { dayjs } from '@/lib/dayjs';
|
||||||
import { logger } from '@/lib/default-logger';
|
import { logger } from '@/lib/default-logger';
|
||||||
|
import getImageUrlFromFile from '@/lib/get-image-url-from-file.ts';
|
||||||
import { pb } from '@/lib/pb';
|
import { pb } from '@/lib/pb';
|
||||||
import { PropertyItem } from '@/components/core/property-item';
|
import { PropertyItem } from '@/components/core/property-item';
|
||||||
import { PropertyList } from '@/components/core/property-list';
|
import { PropertyList } from '@/components/core/property-list';
|
||||||
@@ -119,39 +120,72 @@ export default function Page(): React.JSX.Element {
|
|||||||
{t('dashboard.lessonCategorys.list.title')}
|
{t('dashboard.lessonCategorys.list.title')}
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<Stack direction={{ xs: 'column', sm: 'row' }} spacing={3} sx={{ alignItems: 'flex-start' }}>
|
<Stack
|
||||||
<Stack direction="row" spacing={2} sx={{ alignItems: 'center', flex: '1 1 auto' }}>
|
direction={{ xs: 'column', sm: 'row' }}
|
||||||
|
spacing={3}
|
||||||
|
sx={{ alignItems: 'flex-start' }}
|
||||||
|
>
|
||||||
|
<Stack
|
||||||
|
direction="row"
|
||||||
|
spacing={2}
|
||||||
|
sx={{ alignItems: 'center', flex: '1 1 auto' }}
|
||||||
|
>
|
||||||
<Avatar
|
<Avatar
|
||||||
src={`http://127.0.0.1:8090/api/files/${showLessonCategory.collectionId}/${showLessonCategory.id}/${showLessonCategory.cat_image}`}
|
src={getImageUrlFromFile(
|
||||||
|
showLessonCategory.collectionId,
|
||||||
|
showLessonCategory.id,
|
||||||
|
showLessonCategory.cat_image
|
||||||
|
)}
|
||||||
sx={{ '--Avatar-size': '64px' }}
|
sx={{ '--Avatar-size': '64px' }}
|
||||||
variant="rounded"
|
variant="rounded"
|
||||||
>
|
>
|
||||||
empty
|
empty
|
||||||
</Avatar>
|
</Avatar>
|
||||||
<div>
|
<div>
|
||||||
<Stack direction="row" spacing={2} sx={{ alignItems: 'center', flexWrap: 'wrap' }}>
|
<Stack
|
||||||
|
direction="row"
|
||||||
|
spacing={2}
|
||||||
|
sx={{ alignItems: 'center', flexWrap: 'wrap' }}
|
||||||
|
>
|
||||||
<Typography variant="h4">{showLessonCategory.name}</Typography>
|
<Typography variant="h4">{showLessonCategory.name}</Typography>
|
||||||
<Chip
|
<Chip
|
||||||
icon={<CheckCircleIcon color="var(--mui-palette-success-main)" weight="fill" />}
|
icon={
|
||||||
|
<CheckCircleIcon
|
||||||
|
color="var(--mui-palette-success-main)"
|
||||||
|
weight="fill"
|
||||||
|
/>
|
||||||
|
}
|
||||||
label={showLessonCategory.visible}
|
label={showLessonCategory.visible}
|
||||||
size="small"
|
size="small"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
<Typography color="text.secondary" variant="body1">
|
<Typography
|
||||||
|
color="text.secondary"
|
||||||
|
variant="body1"
|
||||||
|
>
|
||||||
{showLessonCategory.id}
|
{showLessonCategory.id}
|
||||||
</Typography>
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
</Stack>
|
</Stack>
|
||||||
<div>
|
<div>
|
||||||
<Button endIcon={<CaretDownIcon />} variant="contained">
|
<Button
|
||||||
|
endIcon={<CaretDownIcon />}
|
||||||
|
variant="contained"
|
||||||
|
>
|
||||||
Action
|
Action
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Stack>
|
</Stack>
|
||||||
<Grid container spacing={4}>
|
<Grid
|
||||||
<Grid lg={4} xs={12}>
|
container
|
||||||
|
spacing={4}
|
||||||
|
>
|
||||||
|
<Grid
|
||||||
|
lg={4}
|
||||||
|
xs={12}
|
||||||
|
>
|
||||||
<Stack spacing={4}>
|
<Stack spacing={4}>
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader
|
<CardHeader
|
||||||
@@ -178,7 +212,16 @@ export default function Page(): React.JSX.Element {
|
|||||||
>
|
>
|
||||||
{(
|
{(
|
||||||
[
|
[
|
||||||
{ key: 'Customer ID', value: <Chip label={showLessonCategory.id} size="small" variant="soft" /> },
|
{
|
||||||
|
key: 'Customer ID',
|
||||||
|
value: (
|
||||||
|
<Chip
|
||||||
|
label={showLessonCategory.id}
|
||||||
|
size="small"
|
||||||
|
variant="soft"
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
{ key: 'Name', value: showLessonCategory.name },
|
{ key: 'Name', value: showLessonCategory.name },
|
||||||
{ key: 'Pos', value: showLessonCategory.pos },
|
{ key: 'Pos', value: showLessonCategory.pos },
|
||||||
{
|
{
|
||||||
@@ -195,9 +238,20 @@ export default function Page(): React.JSX.Element {
|
|||||||
{
|
{
|
||||||
key: 'Quota',
|
key: 'Quota',
|
||||||
value: (
|
value: (
|
||||||
<Stack direction="row" spacing={2} sx={{ alignItems: 'center' }}>
|
<Stack
|
||||||
<LinearProgress sx={{ flex: '1 1 auto' }} value={50} variant="determinate" />
|
direction="row"
|
||||||
<Typography color="text.secondary" variant="body2">
|
spacing={2}
|
||||||
|
sx={{ alignItems: 'center' }}
|
||||||
|
>
|
||||||
|
<LinearProgress
|
||||||
|
sx={{ flex: '1 1 auto' }}
|
||||||
|
value={50}
|
||||||
|
variant="determinate"
|
||||||
|
/>
|
||||||
|
<Typography
|
||||||
|
color="text.secondary"
|
||||||
|
variant="body2"
|
||||||
|
>
|
||||||
50%
|
50%
|
||||||
</Typography>
|
</Typography>
|
||||||
</Stack>
|
</Stack>
|
||||||
@@ -206,7 +260,11 @@ export default function Page(): React.JSX.Element {
|
|||||||
] satisfies { key: string; value: React.ReactNode }[]
|
] satisfies { key: string; value: React.ReactNode }[]
|
||||||
).map(
|
).map(
|
||||||
(item): React.JSX.Element => (
|
(item): React.JSX.Element => (
|
||||||
<PropertyItem key={item.key} name={item.key} value={item.value} />
|
<PropertyItem
|
||||||
|
key={item.key}
|
||||||
|
name={item.key}
|
||||||
|
value={item.value}
|
||||||
|
/>
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
</PropertyList>
|
</PropertyList>
|
||||||
@@ -223,11 +281,17 @@ export default function Page(): React.JSX.Element {
|
|||||||
<CardContent>
|
<CardContent>
|
||||||
<Stack spacing={1}>
|
<Stack spacing={1}>
|
||||||
<div>
|
<div>
|
||||||
<Button color="error" variant="contained">
|
<Button
|
||||||
|
color="error"
|
||||||
|
variant="contained"
|
||||||
|
>
|
||||||
Delete account
|
Delete account
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<Typography color="text.secondary" variant="body2">
|
<Typography
|
||||||
|
color="text.secondary"
|
||||||
|
variant="body2"
|
||||||
|
>
|
||||||
A deleted lesson category cannot be restored. All data will be permanently removed.
|
A deleted lesson category cannot be restored. All data will be permanently removed.
|
||||||
</Typography>
|
</Typography>
|
||||||
</Stack>
|
</Stack>
|
||||||
@@ -235,7 +299,10 @@ export default function Page(): React.JSX.Element {
|
|||||||
</Card>
|
</Card>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid lg={8} xs={12}>
|
<Grid
|
||||||
|
lg={8}
|
||||||
|
xs={12}
|
||||||
|
>
|
||||||
<Stack spacing={4}>
|
<Stack spacing={4}>
|
||||||
<Payments
|
<Payments
|
||||||
ordersValue={2069.48}
|
ordersValue={2069.48}
|
||||||
@@ -282,7 +349,10 @@ export default function Page(): React.JSX.Element {
|
|||||||
<Card>
|
<Card>
|
||||||
<CardHeader
|
<CardHeader
|
||||||
action={
|
action={
|
||||||
<Button color="secondary" startIcon={<PencilSimpleIcon />}>
|
<Button
|
||||||
|
color="secondary"
|
||||||
|
startIcon={<PencilSimpleIcon />}
|
||||||
|
>
|
||||||
Edit
|
Edit
|
||||||
</Button>
|
</Button>
|
||||||
}
|
}
|
||||||
@@ -294,8 +364,14 @@ export default function Page(): React.JSX.Element {
|
|||||||
title={t('billing-details', { ns: 'lesson_category' })}
|
title={t('billing-details', { ns: 'lesson_category' })}
|
||||||
/>
|
/>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Card sx={{ borderRadius: 1 }} variant="outlined">
|
<Card
|
||||||
<PropertyList divider={<Divider />} sx={{ '--PropertyItem-padding': '16px' }}>
|
sx={{ borderRadius: 1 }}
|
||||||
|
variant="outlined"
|
||||||
|
>
|
||||||
|
<PropertyList
|
||||||
|
divider={<Divider />}
|
||||||
|
sx={{ '--PropertyItem-padding': '16px' }}
|
||||||
|
>
|
||||||
{(
|
{(
|
||||||
[
|
[
|
||||||
{ key: 'Credit card', value: '**** 4142' },
|
{ key: 'Credit card', value: '**** 4142' },
|
||||||
@@ -307,7 +383,11 @@ export default function Page(): React.JSX.Element {
|
|||||||
] satisfies { key: string; value: React.ReactNode }[]
|
] satisfies { key: string; value: React.ReactNode }[]
|
||||||
).map(
|
).map(
|
||||||
(item): React.JSX.Element => (
|
(item): React.JSX.Element => (
|
||||||
<PropertyItem key={item.key} name={item.key} value={item.value} />
|
<PropertyItem
|
||||||
|
key={item.key}
|
||||||
|
name={item.key}
|
||||||
|
value={item.value}
|
||||||
|
/>
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
</PropertyList>
|
</PropertyList>
|
||||||
@@ -317,7 +397,10 @@ export default function Page(): React.JSX.Element {
|
|||||||
<Card>
|
<Card>
|
||||||
<CardHeader
|
<CardHeader
|
||||||
action={
|
action={
|
||||||
<Button color="secondary" startIcon={<PlusIcon />}>
|
<Button
|
||||||
|
color="secondary"
|
||||||
|
startIcon={<PlusIcon />}
|
||||||
|
>
|
||||||
Add
|
Add
|
||||||
</Button>
|
</Button>
|
||||||
}
|
}
|
||||||
@@ -329,7 +412,10 @@ export default function Page(): React.JSX.Element {
|
|||||||
title={t('shipping-addresses', { ns: 'lesson_category' })}
|
title={t('shipping-addresses', { ns: 'lesson_category' })}
|
||||||
/>
|
/>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Grid container spacing={3}>
|
<Grid
|
||||||
|
container
|
||||||
|
spacing={3}
|
||||||
|
>
|
||||||
{(
|
{(
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@@ -351,7 +437,11 @@ export default function Page(): React.JSX.Element {
|
|||||||
},
|
},
|
||||||
] satisfies Address[]
|
] satisfies Address[]
|
||||||
).map((address) => (
|
).map((address) => (
|
||||||
<Grid key={address.id} md={6} xs={12}>
|
<Grid
|
||||||
|
key={address.id}
|
||||||
|
md={6}
|
||||||
|
xs={12}
|
||||||
|
>
|
||||||
<ShippingAddress address={address} />
|
<ShippingAddress address={address} />
|
||||||
</Grid>
|
</Grid>
|
||||||
))}
|
))}
|
||||||
|
@@ -10,12 +10,9 @@ import { CaretDown as CaretDownIcon } from '@phosphor-icons/react/dist/ssr/Caret
|
|||||||
import { CheckCircle as CheckCircleIcon } from '@phosphor-icons/react/dist/ssr/CheckCircle';
|
import { CheckCircle as CheckCircleIcon } from '@phosphor-icons/react/dist/ssr/CheckCircle';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import getImageUrlFromFile from '@/lib/get-image-url-from-file.ts';
|
||||||
import type { CrCategory } from '@/components/dashboard/cr/categories/type';
|
import type { CrCategory } from '@/components/dashboard/cr/categories/type';
|
||||||
|
|
||||||
function getImageUrlFrRecord(record: CrCategory): string {
|
|
||||||
return `http://127.0.0.1:8090/api/files/${record.collectionId}/${record.id}/${record.cat_image}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function SampleTitleCard({ lpModel }: { lpModel: CrCategory }): React.JSX.Element {
|
export default function SampleTitleCard({ lpModel }: { lpModel: CrCategory }): React.JSX.Element {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
@@ -28,7 +25,7 @@ export default function SampleTitleCard({ lpModel }: { lpModel: CrCategory }): R
|
|||||||
>
|
>
|
||||||
<Avatar
|
<Avatar
|
||||||
variant="rounded"
|
variant="rounded"
|
||||||
src={getImageUrlFrRecord(lpModel)}
|
src={getImageUrlFromFile(lpModel.collectionId, lpModel.id, lpModel.cat_image)}
|
||||||
sx={{ '--Avatar-size': '64px' }}
|
sx={{ '--Avatar-size': '64px' }}
|
||||||
>
|
>
|
||||||
{t('empty')}
|
{t('empty')}
|
||||||
|
@@ -10,12 +10,9 @@ import { CaretDown as CaretDownIcon } from '@phosphor-icons/react/dist/ssr/Caret
|
|||||||
import { CheckCircle as CheckCircleIcon } from '@phosphor-icons/react/dist/ssr/CheckCircle';
|
import { CheckCircle as CheckCircleIcon } from '@phosphor-icons/react/dist/ssr/CheckCircle';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import getImageUrlFromFile from '@/lib/get-image-url-from-file.ts';
|
||||||
import { LpCategory } from '@/components/dashboard/lp/categories/type';
|
import { LpCategory } from '@/components/dashboard/lp/categories/type';
|
||||||
|
|
||||||
function getImageUrlFrRecord(record: LpCategory): string {
|
|
||||||
return `http://127.0.0.1:8090/api/files/${record.collectionId}/${record.id}/${record.cat_image}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function SampleTitleCard({ lpModel }: { lpModel: LpCategory }): React.JSX.Element {
|
export default function SampleTitleCard({ lpModel }: { lpModel: LpCategory }): React.JSX.Element {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
@@ -28,7 +25,7 @@ export default function SampleTitleCard({ lpModel }: { lpModel: LpCategory }): R
|
|||||||
>
|
>
|
||||||
<Avatar
|
<Avatar
|
||||||
variant="rounded"
|
variant="rounded"
|
||||||
src={getImageUrlFrRecord(lpModel)}
|
src={getImageUrlFromFile(lpModel.collectionId, lpModel.id, lpModel.cat_image)}
|
||||||
sx={{ '--Avatar-size': '64px' }}
|
sx={{ '--Avatar-size': '64px' }}
|
||||||
>
|
>
|
||||||
{t('empty')}
|
{t('empty')}
|
||||||
|
@@ -9,14 +9,14 @@ import Typography from '@mui/material/Typography';
|
|||||||
import { CaretDown as CaretDownIcon } from '@phosphor-icons/react/dist/ssr/CaretDown';
|
import { CaretDown as CaretDownIcon } from '@phosphor-icons/react/dist/ssr/CaretDown';
|
||||||
import { CheckCircle as CheckCircleIcon } from '@phosphor-icons/react/dist/ssr/CheckCircle';
|
import { CheckCircle as CheckCircleIcon } from '@phosphor-icons/react/dist/ssr/CheckCircle';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import type { Customer } from '@/components/dashboard/customer/type.d';
|
import type { Customer } from '@/components/dashboard/customer/type.d';
|
||||||
|
|
||||||
// import type { CrCategory } from '@/components/dashboard/cr/categories/type';
|
// import type { CrCategory } from '@/components/dashboard/cr/categories/type';
|
||||||
|
|
||||||
function getImageUrlFrRecord(record: Customer): string {
|
function getImageUrlFrRecord(record: Customer): string {
|
||||||
// TODO: fix this
|
// TODO: implement getImageUrlFrRecord
|
||||||
// `http://127.0.0.1:8090/api/files/${'record.collectionId'}/${'record.id'}/${'record.cat_image'}`;
|
return 'not implemented';
|
||||||
return 'getImageUrlFrRecord(helloworld)';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function SampleTitleCard({ lpModel }: { lpModel: Customer }): React.JSX.Element {
|
export default function SampleTitleCard({ lpModel }: { lpModel: Customer }): React.JSX.Element {
|
||||||
|
@@ -28,12 +28,13 @@ import { PencilSimple as PencilSimpleIcon } from '@phosphor-icons/react/dist/ssr
|
|||||||
import { Plus as PlusIcon } from '@phosphor-icons/react/dist/ssr/Plus';
|
import { Plus as PlusIcon } from '@phosphor-icons/react/dist/ssr/Plus';
|
||||||
import { ShieldWarning as ShieldWarningIcon } from '@phosphor-icons/react/dist/ssr/ShieldWarning';
|
import { ShieldWarning as ShieldWarningIcon } from '@phosphor-icons/react/dist/ssr/ShieldWarning';
|
||||||
import { User as UserIcon } from '@phosphor-icons/react/dist/ssr/User';
|
import { User as UserIcon } from '@phosphor-icons/react/dist/ssr/User';
|
||||||
import { RecordModel } from 'pocketbase';
|
import type { RecordModel } from 'pocketbase';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import { paths } from '@/paths';
|
import { paths } from '@/paths';
|
||||||
import { dayjs } from '@/lib/dayjs';
|
import { dayjs } from '@/lib/dayjs';
|
||||||
import { logger } from '@/lib/default-logger';
|
import { logger } from '@/lib/default-logger';
|
||||||
|
import getImageUrlFromFile from '@/lib/get-image-url-from-file.ts';
|
||||||
import { pb } from '@/lib/pb';
|
import { pb } from '@/lib/pb';
|
||||||
import { PropertyItem } from '@/components/core/property-item';
|
import { PropertyItem } from '@/components/core/property-item';
|
||||||
import { PropertyList } from '@/components/core/property-list';
|
import { PropertyList } from '@/components/core/property-list';
|
||||||
@@ -45,7 +46,7 @@ import { Notifications } from '@/components/dashboard/lesson_category/notificati
|
|||||||
import { Payments } from '@/components/dashboard/lesson_category/payments';
|
import { Payments } from '@/components/dashboard/lesson_category/payments';
|
||||||
import type { Address } from '@/components/dashboard/lesson_category/shipping-address';
|
import type { Address } from '@/components/dashboard/lesson_category/shipping-address';
|
||||||
import { ShippingAddress } from '@/components/dashboard/lesson_category/shipping-address';
|
import { ShippingAddress } from '@/components/dashboard/lesson_category/shipping-address';
|
||||||
import { LessonCategory } from '@/components/dashboard/lesson_category/type';
|
import type { LessonCategory } from '@/components/dashboard/lesson_category/type';
|
||||||
// import type { LessonCategory } from '@/components/dashboard/lp_categories/type';
|
// import type { LessonCategory } from '@/components/dashboard/lp_categories/type';
|
||||||
import FormLoading from '@/components/loading';
|
import FormLoading from '@/components/loading';
|
||||||
|
|
||||||
@@ -119,39 +120,72 @@ export default function Page(): React.JSX.Element {
|
|||||||
{t('dashboard.lessonCategorys.list.title')}
|
{t('dashboard.lessonCategorys.list.title')}
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<Stack direction={{ xs: 'column', sm: 'row' }} spacing={3} sx={{ alignItems: 'flex-start' }}>
|
<Stack
|
||||||
<Stack direction="row" spacing={2} sx={{ alignItems: 'center', flex: '1 1 auto' }}>
|
direction={{ xs: 'column', sm: 'row' }}
|
||||||
|
spacing={3}
|
||||||
|
sx={{ alignItems: 'flex-start' }}
|
||||||
|
>
|
||||||
|
<Stack
|
||||||
|
direction="row"
|
||||||
|
spacing={2}
|
||||||
|
sx={{ alignItems: 'center', flex: '1 1 auto' }}
|
||||||
|
>
|
||||||
<Avatar
|
<Avatar
|
||||||
src={`http://127.0.0.1:8090/api/files/${showLessonCategory.collectionId}/${showLessonCategory.id}/${showLessonCategory.cat_image}`}
|
src={getImageUrlFromFile(
|
||||||
|
showLessonCategory.collectionId,
|
||||||
|
showLessonCategory.id,
|
||||||
|
showLessonCategory.cat_image
|
||||||
|
)}
|
||||||
sx={{ '--Avatar-size': '64px' }}
|
sx={{ '--Avatar-size': '64px' }}
|
||||||
variant="rounded"
|
variant="rounded"
|
||||||
>
|
>
|
||||||
empty
|
empty
|
||||||
</Avatar>
|
</Avatar>
|
||||||
<div>
|
<div>
|
||||||
<Stack direction="row" spacing={2} sx={{ alignItems: 'center', flexWrap: 'wrap' }}>
|
<Stack
|
||||||
|
direction="row"
|
||||||
|
spacing={2}
|
||||||
|
sx={{ alignItems: 'center', flexWrap: 'wrap' }}
|
||||||
|
>
|
||||||
<Typography variant="h4">{showLessonCategory.name}</Typography>
|
<Typography variant="h4">{showLessonCategory.name}</Typography>
|
||||||
<Chip
|
<Chip
|
||||||
icon={<CheckCircleIcon color="var(--mui-palette-success-main)" weight="fill" />}
|
icon={
|
||||||
|
<CheckCircleIcon
|
||||||
|
color="var(--mui-palette-success-main)"
|
||||||
|
weight="fill"
|
||||||
|
/>
|
||||||
|
}
|
||||||
label={showLessonCategory.visible}
|
label={showLessonCategory.visible}
|
||||||
size="small"
|
size="small"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
<Typography color="text.secondary" variant="body1">
|
<Typography
|
||||||
|
color="text.secondary"
|
||||||
|
variant="body1"
|
||||||
|
>
|
||||||
{showLessonCategory.id}
|
{showLessonCategory.id}
|
||||||
</Typography>
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
</Stack>
|
</Stack>
|
||||||
<div>
|
<div>
|
||||||
<Button endIcon={<CaretDownIcon />} variant="contained">
|
<Button
|
||||||
|
endIcon={<CaretDownIcon />}
|
||||||
|
variant="contained"
|
||||||
|
>
|
||||||
Action
|
Action
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Stack>
|
</Stack>
|
||||||
<Grid container spacing={4}>
|
<Grid
|
||||||
<Grid lg={4} xs={12}>
|
container
|
||||||
|
spacing={4}
|
||||||
|
>
|
||||||
|
<Grid
|
||||||
|
lg={4}
|
||||||
|
xs={12}
|
||||||
|
>
|
||||||
<Stack spacing={4}>
|
<Stack spacing={4}>
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader
|
<CardHeader
|
||||||
@@ -178,7 +212,16 @@ export default function Page(): React.JSX.Element {
|
|||||||
>
|
>
|
||||||
{(
|
{(
|
||||||
[
|
[
|
||||||
{ key: 'Customer ID', value: <Chip label={showLessonCategory.id} size="small" variant="soft" /> },
|
{
|
||||||
|
key: 'Customer ID',
|
||||||
|
value: (
|
||||||
|
<Chip
|
||||||
|
label={showLessonCategory.id}
|
||||||
|
size="small"
|
||||||
|
variant="soft"
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
{ key: 'Name', value: showLessonCategory.name },
|
{ key: 'Name', value: showLessonCategory.name },
|
||||||
{ key: 'Pos', value: showLessonCategory.pos },
|
{ key: 'Pos', value: showLessonCategory.pos },
|
||||||
{
|
{
|
||||||
@@ -195,9 +238,20 @@ export default function Page(): React.JSX.Element {
|
|||||||
{
|
{
|
||||||
key: 'Quota',
|
key: 'Quota',
|
||||||
value: (
|
value: (
|
||||||
<Stack direction="row" spacing={2} sx={{ alignItems: 'center' }}>
|
<Stack
|
||||||
<LinearProgress sx={{ flex: '1 1 auto' }} value={50} variant="determinate" />
|
direction="row"
|
||||||
<Typography color="text.secondary" variant="body2">
|
spacing={2}
|
||||||
|
sx={{ alignItems: 'center' }}
|
||||||
|
>
|
||||||
|
<LinearProgress
|
||||||
|
sx={{ flex: '1 1 auto' }}
|
||||||
|
value={50}
|
||||||
|
variant="determinate"
|
||||||
|
/>
|
||||||
|
<Typography
|
||||||
|
color="text.secondary"
|
||||||
|
variant="body2"
|
||||||
|
>
|
||||||
50%
|
50%
|
||||||
</Typography>
|
</Typography>
|
||||||
</Stack>
|
</Stack>
|
||||||
@@ -206,7 +260,11 @@ export default function Page(): React.JSX.Element {
|
|||||||
] satisfies { key: string; value: React.ReactNode }[]
|
] satisfies { key: string; value: React.ReactNode }[]
|
||||||
).map(
|
).map(
|
||||||
(item): React.JSX.Element => (
|
(item): React.JSX.Element => (
|
||||||
<PropertyItem key={item.key} name={item.key} value={item.value} />
|
<PropertyItem
|
||||||
|
key={item.key}
|
||||||
|
name={item.key}
|
||||||
|
value={item.value}
|
||||||
|
/>
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
</PropertyList>
|
</PropertyList>
|
||||||
@@ -223,11 +281,17 @@ export default function Page(): React.JSX.Element {
|
|||||||
<CardContent>
|
<CardContent>
|
||||||
<Stack spacing={1}>
|
<Stack spacing={1}>
|
||||||
<div>
|
<div>
|
||||||
<Button color="error" variant="contained">
|
<Button
|
||||||
|
color="error"
|
||||||
|
variant="contained"
|
||||||
|
>
|
||||||
Delete account
|
Delete account
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<Typography color="text.secondary" variant="body2">
|
<Typography
|
||||||
|
color="text.secondary"
|
||||||
|
variant="body2"
|
||||||
|
>
|
||||||
A deleted lesson category cannot be restored. All data will be permanently removed.
|
A deleted lesson category cannot be restored. All data will be permanently removed.
|
||||||
</Typography>
|
</Typography>
|
||||||
</Stack>
|
</Stack>
|
||||||
@@ -235,7 +299,10 @@ export default function Page(): React.JSX.Element {
|
|||||||
</Card>
|
</Card>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid lg={8} xs={12}>
|
<Grid
|
||||||
|
lg={8}
|
||||||
|
xs={12}
|
||||||
|
>
|
||||||
<Stack spacing={4}>
|
<Stack spacing={4}>
|
||||||
<Payments
|
<Payments
|
||||||
ordersValue={2069.48}
|
ordersValue={2069.48}
|
||||||
@@ -282,7 +349,10 @@ export default function Page(): React.JSX.Element {
|
|||||||
<Card>
|
<Card>
|
||||||
<CardHeader
|
<CardHeader
|
||||||
action={
|
action={
|
||||||
<Button color="secondary" startIcon={<PencilSimpleIcon />}>
|
<Button
|
||||||
|
color="secondary"
|
||||||
|
startIcon={<PencilSimpleIcon />}
|
||||||
|
>
|
||||||
Edit
|
Edit
|
||||||
</Button>
|
</Button>
|
||||||
}
|
}
|
||||||
@@ -294,8 +364,14 @@ export default function Page(): React.JSX.Element {
|
|||||||
title={t('billing-details', { ns: 'lesson_category' })}
|
title={t('billing-details', { ns: 'lesson_category' })}
|
||||||
/>
|
/>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Card sx={{ borderRadius: 1 }} variant="outlined">
|
<Card
|
||||||
<PropertyList divider={<Divider />} sx={{ '--PropertyItem-padding': '16px' }}>
|
sx={{ borderRadius: 1 }}
|
||||||
|
variant="outlined"
|
||||||
|
>
|
||||||
|
<PropertyList
|
||||||
|
divider={<Divider />}
|
||||||
|
sx={{ '--PropertyItem-padding': '16px' }}
|
||||||
|
>
|
||||||
{(
|
{(
|
||||||
[
|
[
|
||||||
{ key: 'Credit card', value: '**** 4142' },
|
{ key: 'Credit card', value: '**** 4142' },
|
||||||
@@ -307,7 +383,11 @@ export default function Page(): React.JSX.Element {
|
|||||||
] satisfies { key: string; value: React.ReactNode }[]
|
] satisfies { key: string; value: React.ReactNode }[]
|
||||||
).map(
|
).map(
|
||||||
(item): React.JSX.Element => (
|
(item): React.JSX.Element => (
|
||||||
<PropertyItem key={item.key} name={item.key} value={item.value} />
|
<PropertyItem
|
||||||
|
key={item.key}
|
||||||
|
name={item.key}
|
||||||
|
value={item.value}
|
||||||
|
/>
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
</PropertyList>
|
</PropertyList>
|
||||||
@@ -317,7 +397,10 @@ export default function Page(): React.JSX.Element {
|
|||||||
<Card>
|
<Card>
|
||||||
<CardHeader
|
<CardHeader
|
||||||
action={
|
action={
|
||||||
<Button color="secondary" startIcon={<PlusIcon />}>
|
<Button
|
||||||
|
color="secondary"
|
||||||
|
startIcon={<PlusIcon />}
|
||||||
|
>
|
||||||
Add
|
Add
|
||||||
</Button>
|
</Button>
|
||||||
}
|
}
|
||||||
@@ -329,7 +412,10 @@ export default function Page(): React.JSX.Element {
|
|||||||
title={t('shipping-addresses', { ns: 'lesson_category' })}
|
title={t('shipping-addresses', { ns: 'lesson_category' })}
|
||||||
/>
|
/>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Grid container spacing={3}>
|
<Grid
|
||||||
|
container
|
||||||
|
spacing={3}
|
||||||
|
>
|
||||||
{(
|
{(
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@@ -351,7 +437,11 @@ export default function Page(): React.JSX.Element {
|
|||||||
},
|
},
|
||||||
] satisfies Address[]
|
] satisfies Address[]
|
||||||
).map((address) => (
|
).map((address) => (
|
||||||
<Grid key={address.id} md={6} xs={12}>
|
<Grid
|
||||||
|
key={address.id}
|
||||||
|
md={6}
|
||||||
|
xs={12}
|
||||||
|
>
|
||||||
<ShippingAddress address={address} />
|
<ShippingAddress address={address} />
|
||||||
</Grid>
|
</Grid>
|
||||||
))}
|
))}
|
||||||
|
@@ -10,11 +10,8 @@ import { CaretDown as CaretDownIcon } from '@phosphor-icons/react/dist/ssr/Caret
|
|||||||
import { CheckCircle as CheckCircleIcon } from '@phosphor-icons/react/dist/ssr/CheckCircle';
|
import { CheckCircle as CheckCircleIcon } from '@phosphor-icons/react/dist/ssr/CheckCircle';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import { LpCategory } from '@/components/dashboard/lp/categories/type';
|
import getImageUrlFromFile from '@/lib/get-image-url-from-file.ts';
|
||||||
|
import type { LpCategory } from '@/components/dashboard/lp/categories/type';
|
||||||
function getImageUrlFrRecord(record: LpCategory): string {
|
|
||||||
return `http://127.0.0.1:8090/api/files/${record.collectionId}/${record.id}/${record.cat_image}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function SampleTitleCard({ lpModel }: { lpModel: LpCategory }): React.JSX.Element {
|
export default function SampleTitleCard({ lpModel }: { lpModel: LpCategory }): React.JSX.Element {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -28,7 +25,7 @@ export default function SampleTitleCard({ lpModel }: { lpModel: LpCategory }): R
|
|||||||
>
|
>
|
||||||
<Avatar
|
<Avatar
|
||||||
variant="rounded"
|
variant="rounded"
|
||||||
src={getImageUrlFrRecord(lpModel)}
|
src={getImageUrlFromFile(lpModel.collectionId, lpModel.id, lpModel.cat_image)}
|
||||||
sx={{ '--Avatar-size': '64px' }}
|
sx={{ '--Avatar-size': '64px' }}
|
||||||
>
|
>
|
||||||
{t('empty')}
|
{t('empty')}
|
||||||
|
@@ -10,12 +10,9 @@ import { CaretDown as CaretDownIcon } from '@phosphor-icons/react/dist/ssr/Caret
|
|||||||
import { CheckCircle as CheckCircleIcon } from '@phosphor-icons/react/dist/ssr/CheckCircle';
|
import { CheckCircle as CheckCircleIcon } from '@phosphor-icons/react/dist/ssr/CheckCircle';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import getImageUrlFromFile from '@/lib/get-image-url-from-file.ts';
|
||||||
import { LpCategory } from '@/components/dashboard/lp/categories/type';
|
import { LpCategory } from '@/components/dashboard/lp/categories/type';
|
||||||
|
|
||||||
function getImageUrlFrRecord(record: LpCategory): string {
|
|
||||||
return `http://127.0.0.1:8090/api/files/${record.collectionId}/${record.id}/${record.cat_image}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function SampleTitleCard({ lpModel }: { lpModel: LpCategory }): React.JSX.Element {
|
export default function SampleTitleCard({ lpModel }: { lpModel: LpCategory }): React.JSX.Element {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
@@ -28,7 +25,7 @@ export default function SampleTitleCard({ lpModel }: { lpModel: LpCategory }): R
|
|||||||
>
|
>
|
||||||
<Avatar
|
<Avatar
|
||||||
variant="rounded"
|
variant="rounded"
|
||||||
src={getImageUrlFrRecord(lpModel)}
|
src={getImageUrlFromFile(lpModel.collectionId, lpModel.id, lpModel.cat_image)}
|
||||||
sx={{ '--Avatar-size': '64px' }}
|
sx={{ '--Avatar-size': '64px' }}
|
||||||
>
|
>
|
||||||
{t('empty')}
|
{t('empty')}
|
||||||
|
@@ -10,12 +10,9 @@ import { CaretDown as CaretDownIcon } from '@phosphor-icons/react/dist/ssr/Caret
|
|||||||
import { CheckCircle as CheckCircleIcon } from '@phosphor-icons/react/dist/ssr/CheckCircle';
|
import { CheckCircle as CheckCircleIcon } from '@phosphor-icons/react/dist/ssr/CheckCircle';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import getImageUrlFromFile from '@/lib/get-image-url-from-file.ts';
|
||||||
import type { MfCategory } from '@/components/dashboard/mf/categories/type';
|
import type { MfCategory } from '@/components/dashboard/mf/categories/type';
|
||||||
|
|
||||||
function getImageUrlFrRecord(record: MfCategory): string {
|
|
||||||
return `http://127.0.0.1:8090/api/files/${record.collectionId}/${record.id}/${record.cat_image}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function SampleTitleCard({ lpModel }: { lpModel: MfCategory }): React.JSX.Element {
|
export default function SampleTitleCard({ lpModel }: { lpModel: MfCategory }): React.JSX.Element {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
@@ -28,7 +25,7 @@ export default function SampleTitleCard({ lpModel }: { lpModel: MfCategory }): R
|
|||||||
>
|
>
|
||||||
<Avatar
|
<Avatar
|
||||||
variant="rounded"
|
variant="rounded"
|
||||||
src={getImageUrlFrRecord(lpModel)}
|
src={getImageUrlFromFile(lpModel.collectionId, lpModel.id, lpModel.cat_image)}
|
||||||
sx={{ '--Avatar-size': '64px' }}
|
sx={{ '--Avatar-size': '64px' }}
|
||||||
>
|
>
|
||||||
{t('empty')}
|
{t('empty')}
|
||||||
|
@@ -10,12 +10,9 @@ import { CaretDown as CaretDownIcon } from '@phosphor-icons/react/dist/ssr/Caret
|
|||||||
import { CheckCircle as CheckCircleIcon } from '@phosphor-icons/react/dist/ssr/CheckCircle';
|
import { CheckCircle as CheckCircleIcon } from '@phosphor-icons/react/dist/ssr/CheckCircle';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import getImageUrlFromFile from '@/lib/get-image-url-from-file.ts';
|
||||||
import type { MfCategory } from '@/components/dashboard/mf/categories/type';
|
import type { MfCategory } from '@/components/dashboard/mf/categories/type';
|
||||||
|
|
||||||
function getImageUrlFrRecord(record: MfCategory): string {
|
|
||||||
return `http://127.0.0.1:8090/api/files/${record.collectionId}/${record.id}/${record.cat_image}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function SampleTitleCard({ lpModel }: { lpModel: MfCategory }): React.JSX.Element {
|
export default function SampleTitleCard({ lpModel }: { lpModel: MfCategory }): React.JSX.Element {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
@@ -28,7 +25,7 @@ export default function SampleTitleCard({ lpModel }: { lpModel: MfCategory }): R
|
|||||||
>
|
>
|
||||||
<Avatar
|
<Avatar
|
||||||
variant="rounded"
|
variant="rounded"
|
||||||
src={getImageUrlFrRecord(lpModel)}
|
src={getImageUrlFromFile(lpModel.collectionId, lpModel.id, lpModel.cat_image)}
|
||||||
sx={{ '--Avatar-size': '64px' }}
|
sx={{ '--Avatar-size': '64px' }}
|
||||||
>
|
>
|
||||||
{t('empty')}
|
{t('empty')}
|
||||||
|
@@ -9,14 +9,10 @@ import Typography from '@mui/material/Typography';
|
|||||||
import { CaretDown as CaretDownIcon } from '@phosphor-icons/react/dist/ssr/CaretDown';
|
import { CaretDown as CaretDownIcon } from '@phosphor-icons/react/dist/ssr/CaretDown';
|
||||||
import { CheckCircle as CheckCircleIcon } from '@phosphor-icons/react/dist/ssr/CheckCircle';
|
import { CheckCircle as CheckCircleIcon } from '@phosphor-icons/react/dist/ssr/CheckCircle';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import getImageUrlFromFile from '@/lib/get-image-url-from-file.ts';
|
||||||
import type { Student } from '@/components/dashboard/student/type.d';
|
import type { Student } from '@/components/dashboard/student/type.d';
|
||||||
|
|
||||||
// import type { CrCategory } from '@/components/dashboard/cr/categories/type';
|
|
||||||
|
|
||||||
function getImageUrlForStudent(student: Student): string {
|
|
||||||
return `http://127.0.0.1:8090/api/files/${student.collectionId}/${student.id}/${student.avatar}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function SampleTitleCard({ studentRecord }: { studentRecord: Student }): React.JSX.Element {
|
export default function SampleTitleCard({ studentRecord }: { studentRecord: Student }): React.JSX.Element {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
@@ -29,7 +25,7 @@ export default function SampleTitleCard({ studentRecord }: { studentRecord: Stud
|
|||||||
>
|
>
|
||||||
<Avatar
|
<Avatar
|
||||||
variant="rounded"
|
variant="rounded"
|
||||||
src={getImageUrlForStudent(studentRecord)}
|
src={getImageUrlFromFile(studentRecord.collectionId, studentRecord.id, studentRecord.avatar)}
|
||||||
sx={{ '--Avatar-size': '64px' }}
|
sx={{ '--Avatar-size': '64px' }}
|
||||||
>
|
>
|
||||||
{t('empty')}
|
{t('empty')}
|
||||||
|
@@ -9,13 +9,9 @@ import Typography from '@mui/material/Typography';
|
|||||||
import { CaretDown as CaretDownIcon } from '@phosphor-icons/react/dist/ssr/CaretDown';
|
import { CaretDown as CaretDownIcon } from '@phosphor-icons/react/dist/ssr/CaretDown';
|
||||||
import { CheckCircle as CheckCircleIcon } from '@phosphor-icons/react/dist/ssr/CheckCircle';
|
import { CheckCircle as CheckCircleIcon } from '@phosphor-icons/react/dist/ssr/CheckCircle';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Teacher } from '@/components/dashboard/teacher/type.d';
|
|
||||||
|
|
||||||
// import type { CrCategory } from '@/components/dashboard/cr/categories/type';
|
import getImageUrlFromFile from '@/lib/get-image-url-from-file.ts';
|
||||||
|
import type { Teacher } from '@/components/dashboard/teacher/type.d';
|
||||||
function getImageUrlFrRecord(teacher: Teacher): string {
|
|
||||||
return `http://127.0.0.1:8090/api/files/${teacher.collectionId}/${teacher.id}/${teacher.avatar}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function SampleTitleCard({ teacherRecord }: { teacherRecord: Teacher }): React.JSX.Element {
|
export default function SampleTitleCard({ teacherRecord }: { teacherRecord: Teacher }): React.JSX.Element {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -29,7 +25,7 @@ export default function SampleTitleCard({ teacherRecord }: { teacherRecord: Teac
|
|||||||
>
|
>
|
||||||
<Avatar
|
<Avatar
|
||||||
variant="rounded"
|
variant="rounded"
|
||||||
src={getImageUrlFrRecord(teacherRecord)}
|
src={getImageUrlFromFile(teacherRecord.collectionId, teacherRecord.id, teacherRecord.avatar)}
|
||||||
sx={{ '--Avatar-size': '64px' }}
|
sx={{ '--Avatar-size': '64px' }}
|
||||||
>
|
>
|
||||||
{t('empty')}
|
{t('empty')}
|
||||||
|
@@ -9,13 +9,9 @@ import Typography from '@mui/material/Typography';
|
|||||||
import { CaretDown as CaretDownIcon } from '@phosphor-icons/react/dist/ssr/CaretDown';
|
import { CaretDown as CaretDownIcon } from '@phosphor-icons/react/dist/ssr/CaretDown';
|
||||||
import { CheckCircle as CheckCircleIcon } from '@phosphor-icons/react/dist/ssr/CheckCircle';
|
import { CheckCircle as CheckCircleIcon } from '@phosphor-icons/react/dist/ssr/CheckCircle';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Teacher } from '@/components/dashboard/teacher/type.d';
|
|
||||||
|
|
||||||
// import type { CrCategory } from '@/components/dashboard/cr/categories/type';
|
import getImageUrlFromFile from '@/lib/get-image-url-from-file.ts';
|
||||||
|
import type { Teacher } from '@/components/dashboard/teacher/type.d';
|
||||||
function getImageUrlFrRecord(teacher: Teacher): string {
|
|
||||||
return `http://127.0.0.1:8090/api/files/${teacher.collectionId}/${teacher.id}/${teacher.avatar}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function SampleTitleCard({ teacherRecord }: { teacherRecord: Teacher }): React.JSX.Element {
|
export default function SampleTitleCard({ teacherRecord }: { teacherRecord: Teacher }): React.JSX.Element {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -29,7 +25,7 @@ export default function SampleTitleCard({ teacherRecord }: { teacherRecord: Teac
|
|||||||
>
|
>
|
||||||
<Avatar
|
<Avatar
|
||||||
variant="rounded"
|
variant="rounded"
|
||||||
src={getImageUrlFrRecord(teacherRecord)}
|
src={getImageUrlFromFile(teacherRecord.collectionId, teacherRecord.id, teacherRecord.avatar)}
|
||||||
sx={{ '--Avatar-size': '64px' }}
|
sx={{ '--Avatar-size': '64px' }}
|
||||||
>
|
>
|
||||||
{t('empty')}
|
{t('empty')}
|
||||||
|
@@ -34,6 +34,7 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import { paths } from '@/paths';
|
import { paths } from '@/paths';
|
||||||
import { dayjs } from '@/lib/dayjs';
|
import { dayjs } from '@/lib/dayjs';
|
||||||
import { logger } from '@/lib/default-logger';
|
import { logger } from '@/lib/default-logger';
|
||||||
|
import getImageUrlFromFile from '@/lib/get-image-url-from-file.ts';
|
||||||
import { pb } from '@/lib/pb';
|
import { pb } from '@/lib/pb';
|
||||||
import { PropertyItem } from '@/components/core/property-item';
|
import { PropertyItem } from '@/components/core/property-item';
|
||||||
import { PropertyList } from '@/components/core/property-list';
|
import { PropertyList } from '@/components/core/property-list';
|
||||||
@@ -128,7 +129,11 @@ export default function Page(): React.JSX.Element {
|
|||||||
sx={{ alignItems: 'center', flex: '1 1 auto' }}
|
sx={{ alignItems: 'center', flex: '1 1 auto' }}
|
||||||
>
|
>
|
||||||
<Avatar
|
<Avatar
|
||||||
src={`http://127.0.0.1:8090/api/files/${showLessonCategory.collectionId}/${showLessonCategory.id}/${showLessonCategory.cat_image}`}
|
src={getImageUrlFromFile(
|
||||||
|
showLessonCategory.collectionId,
|
||||||
|
showLessonCategory.id,
|
||||||
|
showLessonCategory.image
|
||||||
|
)}
|
||||||
sx={{ '--Avatar-size': '64px' }}
|
sx={{ '--Avatar-size': '64px' }}
|
||||||
variant="rounded"
|
variant="rounded"
|
||||||
>
|
>
|
||||||
|
@@ -26,6 +26,7 @@ import { useTranslation } from 'react-i18next';
|
|||||||
|
|
||||||
import { paths } from '@/paths';
|
import { paths } from '@/paths';
|
||||||
import { dayjs } from '@/lib/dayjs';
|
import { dayjs } from '@/lib/dayjs';
|
||||||
|
import getImageUrlFromFile from '@/lib/get-image-url-from-file.ts';
|
||||||
import { DataTable } from '@/components/core/data-table';
|
import { DataTable } from '@/components/core/data-table';
|
||||||
import type { ColumnDef } from '@/components/core/data-table';
|
import type { ColumnDef } from '@/components/core/data-table';
|
||||||
|
|
||||||
@@ -43,7 +44,7 @@ function columns(handleDeleteClick: (userMetaId: string) => void): ColumnDef<Use
|
|||||||
sx={{ alignItems: 'center' }}
|
sx={{ alignItems: 'center' }}
|
||||||
>
|
>
|
||||||
<Avatar
|
<Avatar
|
||||||
src={`http://127.0.0.1:8090/api/files/${row.collectionId}/${row.id}/${row.avatar}`}
|
src={getImageUrlFromFile(row.collectionId, row.id, row.avatar)}
|
||||||
variant="rounded"
|
variant="rounded"
|
||||||
/>
|
/>
|
||||||
<div>
|
<div>
|
||||||
|
@@ -1,10 +1,9 @@
|
|||||||
// RULES:
|
// RULES:
|
||||||
// should match the collection `Vocabularies` from `schema.dbml`
|
// should match the collection `Vocabularies` from `schema.dbml`
|
||||||
export interface Vocabulary {
|
export interface Vocabulary {
|
||||||
id: string;
|
|
||||||
created?: string;
|
created?: string;
|
||||||
updated?: string;
|
updated?: string;
|
||||||
image?: string;
|
image: string;
|
||||||
sound?: string;
|
sound?: string;
|
||||||
word?: string;
|
word?: string;
|
||||||
word_c?: string;
|
word_c?: string;
|
||||||
@@ -23,6 +22,9 @@ export interface Vocabulary {
|
|||||||
//
|
//
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
//
|
||||||
|
id: string;
|
||||||
|
collectionId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// RULES: for use with vocabulary-create-form.tsx
|
// RULES: for use with vocabulary-create-form.tsx
|
||||||
|
@@ -16,12 +16,13 @@ import { useTranslation } from 'react-i18next';
|
|||||||
|
|
||||||
import { paths } from '@/paths';
|
import { paths } from '@/paths';
|
||||||
import { dayjs } from '@/lib/dayjs';
|
import { dayjs } from '@/lib/dayjs';
|
||||||
|
import getImageUrlFromFile from '@/lib/get-image-url-from-file.ts';
|
||||||
import { DataTable } from '@/components/core/data-table';
|
import { DataTable } from '@/components/core/data-table';
|
||||||
import type { ColumnDef } from '@/components/core/data-table';
|
import type { ColumnDef } from '@/components/core/data-table';
|
||||||
|
|
||||||
import ConfirmDeleteModal from './confirm-delete-modal';
|
import ConfirmDeleteModal from './confirm-delete-modal';
|
||||||
import { useVocabulariesSelection } from './vocabularies-selection-context';
|
|
||||||
import type { Vocabulary } from './type';
|
import type { Vocabulary } from './type';
|
||||||
|
import { useVocabulariesSelection } from './vocabularies-selection-context';
|
||||||
|
|
||||||
function columns(handleDeleteClick: (testId: string) => void): ColumnDef<Vocabulary>[] {
|
function columns(handleDeleteClick: (testId: string) => void): ColumnDef<Vocabulary>[] {
|
||||||
return [
|
return [
|
||||||
@@ -45,7 +46,7 @@ function columns(handleDeleteClick: (testId: string) => void): ColumnDef<Vocabul
|
|||||||
sx={{ alignItems: 'center' }}
|
sx={{ alignItems: 'center' }}
|
||||||
>
|
>
|
||||||
<Avatar
|
<Avatar
|
||||||
src={`http://127.0.0.1:8090/api/files/${row.collectionId}/${row.id}/${row.cat_image}`}
|
src={getImageUrlFromFile(row.collectionId, row.id, row.image)}
|
||||||
variant="rounded"
|
variant="rounded"
|
||||||
>
|
>
|
||||||
<ImagesIcon size={32} />
|
<ImagesIcon size={32} />
|
||||||
|
@@ -4,6 +4,7 @@ import * as React from 'react';
|
|||||||
import RouterLink from 'next/link';
|
import RouterLink from 'next/link';
|
||||||
import { useParams, useRouter } from 'next/navigation';
|
import { useParams, useRouter } from 'next/navigation';
|
||||||
import { COL_VOCABULARIES } from '@/constants';
|
import { COL_VOCABULARIES } from '@/constants';
|
||||||
|
import { listLessonCategories } from '@/db/LessonCategories/listLessonCategories';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { LoadingButton } from '@mui/lab';
|
import { LoadingButton } from '@mui/lab';
|
||||||
import { Avatar, Divider } from '@mui/material';
|
import { Avatar, Divider } from '@mui/material';
|
||||||
@@ -12,7 +13,6 @@ import Button from '@mui/material/Button';
|
|||||||
import Card from '@mui/material/Card';
|
import Card from '@mui/material/Card';
|
||||||
import CardActions from '@mui/material/CardActions';
|
import CardActions from '@mui/material/CardActions';
|
||||||
import CardContent from '@mui/material/CardContent';
|
import CardContent from '@mui/material/CardContent';
|
||||||
|
|
||||||
import FormControl from '@mui/material/FormControl';
|
import FormControl from '@mui/material/FormControl';
|
||||||
import FormHelperText from '@mui/material/FormHelperText';
|
import FormHelperText from '@mui/material/FormHelperText';
|
||||||
import InputLabel from '@mui/material/InputLabel';
|
import InputLabel from '@mui/material/InputLabel';
|
||||||
@@ -27,8 +27,10 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import { z as zod } from 'zod';
|
import { z as zod } from 'zod';
|
||||||
|
|
||||||
import { paths } from '@/paths';
|
import { paths } from '@/paths';
|
||||||
|
import isDevelopment from '@/lib/check-is-development';
|
||||||
import { logger } from '@/lib/default-logger';
|
import { logger } from '@/lib/default-logger';
|
||||||
import { base64ToFile, fileToBase64 } from '@/lib/file-to-base64';
|
import { base64ToFile, fileToBase64 } from '@/lib/file-to-base64';
|
||||||
|
import getImageUrlFromFile from '@/lib/get-image-url-from-file.ts';
|
||||||
import { pb } from '@/lib/pb';
|
import { pb } from '@/lib/pb';
|
||||||
import { Option } from '@/components/core/option';
|
import { Option } from '@/components/core/option';
|
||||||
import { toast } from '@/components/core/toaster';
|
import { toast } from '@/components/core/toaster';
|
||||||
@@ -36,8 +38,6 @@ import FormLoading from '@/components/loading';
|
|||||||
|
|
||||||
import ErrorDisplay from '../error';
|
import ErrorDisplay from '../error';
|
||||||
import type { EditFormProps } from './type';
|
import type { EditFormProps } from './type';
|
||||||
import { listLessonCategories } from '@/db/LessonCategories/listLessonCategories';
|
|
||||||
import isDevelopment from '@/lib/check-is-development';
|
|
||||||
|
|
||||||
const schema = zod.object({
|
const schema = zod.object({
|
||||||
image: zod.union([zod.array(zod.any()), zod.string()]).optional(),
|
image: zod.union([zod.array(zod.any()), zod.string()]).optional(),
|
||||||
@@ -144,9 +144,7 @@ export function VocabularyEditForm(): React.JSX.Element {
|
|||||||
reset({ ...defaultValues, ...result });
|
reset({ ...defaultValues, ...result });
|
||||||
|
|
||||||
if (result.image !== '') {
|
if (result.image !== '') {
|
||||||
const fetchResult = await fetch(
|
const fetchResult = await fetch(getImageUrlFromFile(result.collectionId, result.id, result.image));
|
||||||
`http://127.0.0.1:8090/api/files/${result.collectionId}/${result.id}/${result.image}`
|
|
||||||
);
|
|
||||||
|
|
||||||
const blob = await fetchResult.blob();
|
const blob = await fetchResult.blob();
|
||||||
const url = await fileToBase64(blob);
|
const url = await fileToBase64(blob);
|
||||||
|
@@ -3,6 +3,8 @@
|
|||||||
// get file url from pocketbase record
|
// get file url from pocketbase record
|
||||||
//
|
//
|
||||||
|
|
||||||
export default function getImageUrlFromFile(collectionId: string, id: string, imgFile: string): string {
|
import { POCKETBASE_URL } from './pb';
|
||||||
return `http://127.0.0.1:8090/api/files/${collectionId}/${id}/${imgFile}`;
|
|
||||||
|
export default function getImageUrlFromFile(collectionId: string, id: string, imgFile: string | undefined): string {
|
||||||
|
return `${POCKETBASE_URL}/api/files/${collectionId}/${id}/${imgFile}`;
|
||||||
}
|
}
|
||||||
|
@@ -1,3 +1,6 @@
|
|||||||
import PocketBase from 'pocketbase';
|
import PocketBase from 'pocketbase';
|
||||||
|
|
||||||
|
if (!process.env.NEXT_PUBLIC_POCKETBASE_URL) throw new Error('the pocketbase url cannot empty');
|
||||||
|
export const POCKETBASE_URL: string = process.env.NEXT_PUBLIC_POCKETBASE_URL;
|
||||||
|
|
||||||
export const pb = new PocketBase(process.env.NEXT_PUBLIC_POCKETBASE_URL);
|
export const pb = new PocketBase(process.env.NEXT_PUBLIC_POCKETBASE_URL);
|
||||||
|
Reference in New Issue
Block a user