update init teacher ,

This commit is contained in:
louiscklaw
2025-04-24 12:09:47 +08:00
parent 29b074f6dd
commit ca2a9c235b
38 changed files with 309 additions and 292 deletions

View File

@@ -1,39 +0,0 @@
# AI GUIDELINE
## getting started
Imagine there is a:
1. developer (provide the modification)
2. QA engineer (provide the feedback, and testing)
3. software engineer
software engineer will:
- conclude and integrate the ideas from developer and QA engineer
- make decision to modify the code accordingly.
no need to reply me what you are going on and your digest in this phase.
just reply me "OK" when done
base_dir=`/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project`
- `schema.dbml`
- read `<base_dir>/001_documentation/Requirements/REQ0006/schema.dbml`
this is file in `dbml` format stating the main database structure
- `schema.json`
- read `<base_dir>/002_source/cms/src/db/schema.json`
this is the file of current pocketbase schema
- read `<base_dir>/002_source/cms/src/constants.ts`
this is the content of `@/constants`
- look into the md files in folder `<base_dir>/002_source/cms/_AI_WORKSPACE/001_guideline`
- directory may contain `repomix-output.xml` file, that is a simple summary of all files inside the directory
- read, remember and link up the ideas in file stated above,
i will tell them the task afterwards

View File

@@ -1,22 +0,0 @@
Hi, i need your help.
i am working on a nextjs react typescript project
i've already copied the code(and it sub-directories) from
`/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project/002_source/cms/src/components/dashboard/lp` (a.k.a. `lp`)
to
`/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project/002_source/cms/src/components/dashboard/cr` (a.k.a. `cr`)
i want you to:
- understand the relations (e.g. `lp` -> `lp_categories`, `lp` -> `COL_QUIZ_LP_CATEGORIES`)
- review if any remaining `lp` or `mf` exist in `cr` directory and please help to do replace it to `cr`. (e.g. `COL_QUIZ_LP_CATEGORIES` -> `COL_QUIZ_CR_CATEGORIES` )
- please create if you find any missing files/codes/constants
thank you
---
- compare the difference between `lp` and `mf`,
- remember the differences and
- draft the new type `cr` (e.g. modify the `import` locations, variables, functions, classes, constants name etc.)

View File

@@ -1,66 +0,0 @@
The software engineer will provide solutions,
while QA engineer will feedback the opinion.
this is now not in debug phase,
so, no need to reply me what they are going on or their insight throught the prompt.
just reply me "OK" when done
---
clone `GetVisibleCount.tsx` and `GetHiddenCount.tsx` from `LessonTypes` to `LessonCategories` and update it
please draft `GetHiddenCount.tsx` for COL_LESSON_TYPES and `status = hidden`
well done !, please proceed to another request
working directory: `/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project/002_source/cms/src/db`
according information from `schema.json`, get the collection of `Students`
pleaes clone the `tsx` files from `LessonTypes` and `LessonCategories` to `Students` and update the content
when you draft coding, review file and append with `.tsx.draft`
---
- this is part of react typescript project, with pocketbase
- `schema.dbml`, describe the collections(tables)
- folder `LessonCategories`, the correct references
- folder `LessonTypes`, the correct references
- you can find the `schema.dbml` and schema information from `/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project/001_documentation/Requirements/REQ0006`
- do not read root directory, assume it is a fresh copy of nextjs project is ok
## instruction
- break the questions into smaller parts
- review file append with `.draft`, see if the content aligned with the correct references
- read and understand `dbml` file
- lookup the every folder
## tasks
Thanks
---
---
please revise
please revise
`/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project/002_source/cms/src/types/LpCategory.tsx` `interface LpCategory`
to the collection `QuizLPCategories` align the dbml file in the previous prompt
please modify `/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project/002_source/cms/src/components/dashboard/lp_categories/_constants.tsx`
to follow the type definition in `/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project/002_source/cms/src/types/LpCategory.tsx`, the constant `defaultLpCategory`
---
the constants file (`@/constants`) was `/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project/002_source/cms/src/constants.ts`
please help to fix the `tsx` files in folder `/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project/002_source/cms/src/db/QuizMFCategories`,
the `COL` constants is wrongly used, it should refer to `COL_QUIZ_MF_CATEGORIES`. thanks
please update the `COL_XXXX` TO COL_MF_CATEGORIES

View File

@@ -2,19 +2,24 @@
## getting started
Imagine there is a
Imagine there is a:
1. software developer and a
2. QA engineer
1. developer (provide the modification)
2. QA engineer (provide the feedback, and testing)
3. software engineer
4. technical writer
to solve the problems together
they will:
They will:
- conclude and integrate the ideas from developer and QA engineer
- make decision to modify the code accordingly.
no need to reply me what you are going on and your digest in this phase.
just reply me "OK" when done
## project background and initial setup
base_dir=`/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project`
- No need to reply me what you are going on and your digest in this phase.
Just reply me "OK" when done
- base_dir=`/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project`
- `schema.dbml`
@@ -33,5 +38,7 @@ base_dir=`/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/letterso
- directory may contain `repomix-output.xml` file, that is a simple summary of all files inside the directory
- read, remember and link up the ideas in file stated above,
- if the directory user provided contins `_GUIDELINES.md`, please read the file
- read the files, remember and link up the ideas in file stated above,
i will tell them the task afterwards

View File

@@ -10,7 +10,7 @@ i want you to:
- understand the relations (e.g. `lp` -> `lp_Questions`, `lp` -> `COL_QUIZ_LP_QUESTIONS`)
- review if any remaining `lp` or `mf` exist in `cr` directory and please help to do replace it to `cr`. (e.g. `COL_QUIZ_LP_QUESTIONS` -> `COL_QUIZ_CR_Questions` )
- please create if you find any missing files/codes/constants
- using template, create the similar code for `cr` named `QuizCRQuestions`
- using template, create the similar code for `customer` named `Customers`
thank you

View File

@@ -0,0 +1,20 @@
Hi, i need your help.
## task
i am working on a dbml file
i got a schema.json from exported from pocketbase
and i want to update it to my current dbml file (for documentation)
## Rules
- the collection from json file started with `_` can be ignored. they are system collection and should not appear in dbml
- one collection from json file mapped with one table in dbml file
- the `presentable` field from json file should be ignored.
## information
json file: `/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project/002_source/cms/src/db/schema.json`
dbml file: `/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project/001_documentation/Requirements/REQ0006/schema.dbml`
thanks

View File

@@ -0,0 +1,10 @@
---
tags: db, driver
---
# clone db driver
please understand the tsx files in folder
`/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project/002_source/cms/src/db/Teachers`
change all occurrence of `customer` to `teacher` thanks.

View File

@@ -0,0 +1,18 @@
# task
update `dbml` from `schema.json`
## things to note
1. please skip `presentable` properties from `schema.json`
## steps
1. read file `/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project/002_source/cms/src/db/schema.json`. this is the export from `pocketbase`.
1. read file `/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project/001_documentation/Requirements/REQ0006/schema.dbml`. this is file written in dbml format.
1. currently the collection in `schama.json` is mapped to table in `schema.dbml`
1. compare the `schema.json` and `schema.dbml`, remember the differences
1. you may found some comment already exist in `schema.dbml`, please keep them
1. while keeping `schema.json` content unchanged. write file to `/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project/001_documentation/Requirements/REQ0006/schema.dbml` content based on `schema.json`.
thanks.

View File

@@ -0,0 +1,10 @@
# task
extend function by clone and updating exist code
## steps
please read file
`/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project/002_source/cms/src/db/QuizListenings/GetAllCount.tsx`
duplicate it to cover `GetActiveCount`, `GetPendingCount` and `GetBlockedCount`. create them in `/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project/002_source/cms/src/db/Customers` directory thanks.

Binary file not shown.

View File

@@ -1,3 +1,32 @@
# AI GUIDELINE
## getting started
Imagine there is a software developer and a QA engineer to solve the problems together
They will:
no need to reply me what you are going on and your digest in this phase.
just reply me "OK" when done
base_dir=`/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project`
- read `<base_dir>/001_documentation/Requirements/REQ0006/schema.dbml`
this is file in dbml syntax state the main database
- read `<base_dir>/002_source/cms/src/db/schema.json`
this is the file of live pocketbase schema output
- read `/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project/002_source/cms/src/constants.ts`
this is the content of `@/constants`
- look into the md files in folder `<base_dir>/002_source/cms/_AI_GUIDELINE`
- read, remember and link up the ideas in file stated above,
i will tell them the task afterwards
---
The software engineer will provide solutions,
while QA engineer will feedback the opinion.
@@ -41,8 +70,19 @@ when you draft coding, review file and append with `.tsx.draft`
Thanks
---
please take a look in `schema.dbml` and `schema.json`,
associate the collection from json file to the table in dbml file
please modify the `schema.dbml` to align with `schema.json`
to the collection `QuizLPCategories` align the dbml file in the previous prompt
---
please revise
@@ -52,6 +92,7 @@ please revise
to the collection `QuizLPCategories` align the dbml file in the previous prompt
please modify `/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project/002_source/cms/src/components/dashboard/lp_categories/_constants.tsx`
to follow the type definition in `/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project/002_source/cms/src/types/LpCategory.tsx`, the constant `defaultLpCategory`
@@ -63,4 +104,5 @@ the constants file (`@/constants`) was `/home/logic/_wsl_workspace/001_github_ws
please help to fix the `tsx` files in folder `/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project/002_source/cms/src/db/QuizMFCategories`,
the `COL` constants is wrongly used, it should refer to `COL_QUIZ_MF_CATEGORIES`. thanks
please update the `COL_XXXX` TO COL_MF_CATEGORIES

View File

@@ -1,37 +0,0 @@
# AI GUIDELINE
## getting started
Imagine there is a
1. software developer and a
2. QA engineer
to solve the problems together
They will:
no need to reply me what you are going on and your digest in this phase.
just reply me "OK" when done
base_dir=`/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project`
- `schema.dbml`
- read `<base_dir>/001_documentation/Requirements/REQ0006/schema.dbml`
this is file in `dbml` format stating the main database structure
- `schema.json`
- read `<base_dir>/002_source/cms/src/db/schema.json`
this is the file of current pocketbase schema
- read `<base_dir>/002_source/cms/src/constants.ts`
this is the content of `@/constants`
- look into the md files in folder `<base_dir>/002_source/cms/_AI_WORKSPACE/001_guideline`
- directory may contain `repomix-output.xml` file, that is a simple summary of all files inside the directory
- read, remember and link up the ideas in file stated above,
i will tell them the task afterwards

View File

@@ -1,25 +0,0 @@
Hi, i need your help.
i am working on a nextjs react typescript project
i've already copied the code(and it sub-directories) from `/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project/002_source/cms/src/app/dashboard/lp` (a.k.a. `lp`) to `/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project/002_source/cms/src/app/dashboard/cr` (a.k.a. `cr`)
i want you to:
- list files from directory
- `/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project/002_source/cms/src/app/dashboard/lp`
- `/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project/002_source/cms/src/app/dashboard/cr`
- understand the relations (e.g. `lp` -> `lp_categories`, `lp` -> `COL_QUIZ_LP_CATEGORIES`)
- review if any remaining `lp` or `mf` exist in `cr` directory and please help to do replace it to `cr`. (e.g. `COL_QUIZ_LP_CATEGORIES` -> `COL_QUIZ_CR_CATEGORIES` )
- please create if you find any missing files/codes/constants
thank you
---
- I proofed the code is working already, what you need to do is refactoring of the `variables`, `functions`, `classes`, `constants` (`lp` -> `cr`)
- compare the difference between `lp` and `mf`,
- remember the differences and
- draft the new type `cr` (e.g. modify the `import` locations, variables, functions, classes, constants name etc.)

View File

@@ -3,7 +3,7 @@
import type { Customer } from '@/components/dashboard/customer/type.d';
import { dayjs } from '@/lib/dayjs';
export const SampleCustomers = [
export const SampleTeachers = [
{
id: 'USR-005',
name: 'Fran Perez',

View File

@@ -24,13 +24,13 @@ import { toast } from '@/components/core/toaster';
import ErrorDisplay from '@/components/dashboard/error';
import { Notifications } from '@/components/dashboard/customer/notifications';
import { Notifications } from '@/components/dashboard/teacher/notifications';
import FormLoading from '@/components/loading';
import BasicDetailCard from './BasicDetailCard';
import TitleCard from './TitleCard';
import { defaultCustomer } from '@/components/dashboard/customer/_constants';
import type { Customer } from '@/components/dashboard/customer/type.d';
import { COL_CUSTOMERS } from '@/constants';
import { defaultTeacher } from '@/components/dashboard/teacher/_constants';
import type { Teacher } from '@/components/dashboard/teacher/type.d';
import { COL_TEACHERS } from '@/constants';
export default function Page(): React.JSX.Element {
const { t } = useTranslation();
@@ -41,18 +41,18 @@ export default function Page(): React.JSX.Element {
const [showLoading, setShowLoading] = React.useState<boolean>(true);
const [showError, setShowError] = React.useState({ show: false, detail: '' });
//
const [showLessonCategory, setShowLessonCategory] = React.useState<Customer>(defaultCustomer);
const [showLessonCategory, setShowLessonCategory] = React.useState<Teacher>(defaultTeacher);
function handleEditClick(): void {
router.push(paths.dashboard.customers.edit(showLessonCategory.id));
router.push(paths.dashboard.teachers.edit(showLessonCategory.id));
}
React.useEffect(() => {
if (customerId) {
pb.collection(COL_CUSTOMERS)
pb.collection(COL_TEACHERS)
.getOne(customerId)
.then((model: RecordModel) => {
setShowLessonCategory({ ...defaultCustomer, ...model });
setShowLessonCategory({ ...defaultTeacher, ...model });
})
.catch((err) => {
logger.error(err);
@@ -93,12 +93,12 @@ export default function Page(): React.JSX.Element {
<Link
color="text.primary"
component={RouterLink}
href={paths.dashboard.customers.list}
href={paths.dashboard.teachers.list}
sx={{ alignItems: 'center', display: 'inline-flex', gap: 1 }}
variant="subtitle2"
>
<ArrowLeftIcon fontSize="var(--icon-fontSize-md)" />
Customers
Teachers
</Link>
</div>
<Stack

View File

@@ -1,5 +1,5 @@
'use client';
import * as React from 'react';
import type { Metadata } from 'next';
import RouterLink from 'next/link';
import Box from '@mui/material/Box';
import Link from '@mui/material/Link';
@@ -9,9 +9,7 @@ import { ArrowLeft as ArrowLeftIcon } from '@phosphor-icons/react/dist/ssr/Arrow
import { config } from '@/config';
import { paths } from '@/paths';
import { CustomerCreateForm } from '@/components/dashboard/customer/customer-create-form';
export const metadata = { title: `Create | Customers | Dashboard | ${config.site.name}` } satisfies Metadata;
import { TeacherCreateForm } from '@/components/dashboard/teacher/teacher-create-form';
export default function Page(): React.JSX.Element {
return (
@@ -29,19 +27,19 @@ export default function Page(): React.JSX.Element {
<Link
color="text.primary"
component={RouterLink}
href={paths.dashboard.customers.list}
href={paths.dashboard.teachers.list}
sx={{ alignItems: 'center', display: 'inline-flex', gap: 1 }}
variant="subtitle2"
>
<ArrowLeftIcon fontSize="var(--icon-fontSize-md)" />
Customers
Teachers
</Link>
</div>
<div>
<Typography variant="h4">Create customer</Typography>
<Typography variant="h4">Create teacher</Typography>
</div>
</Stack>
<CustomerCreateForm />
<TeacherCreateForm />
</Stack>
</Box>
);

View File

@@ -11,7 +11,7 @@ import { useTranslation } from 'react-i18next';
import { paths } from '@/paths';
import { CrCategoryEditForm } from '@/components/dashboard/cr/categories/cr-category-edit-form';
import { CustomerEditForm } from '@/components/dashboard/customer/customer-edit-form';
import { TeacherEditForm } from '@/components/dashboard/teacher/teacher-edit-form';
export default function Page(): React.JSX.Element {
const { t } = useTranslation(['lp_categories']);
@@ -47,7 +47,7 @@ export default function Page(): React.JSX.Element {
<Typography variant="h4">{t('edit.title')}</Typography>
</div>
</Stack>
<CustomerEditForm />
<TeacherEditForm />
</Stack>
</Box>
);

View File

@@ -1,13 +1,13 @@
// src/app/dashboard/customers/page.tsx
// src/app/dashboard/teachers/page.tsx
'use client';
// RULES:
// contains list page for customers (Customers)
// contains list page for teachers (Teachers)
// contain definition to collection only
//
import * as React from 'react';
import { useRouter } from 'next/navigation';
import { COL_CUSTOMERS } from '@/constants';
import { COL_TEACHERS } from '@/constants';
import { LoadingButton } from '@mui/lab';
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
@@ -19,13 +19,13 @@ import { Plus as PlusIcon } from '@phosphor-icons/react/dist/ssr/Plus';
import type { ListResult, RecordModel } from 'pocketbase';
import { config } from '@/config';
import { CustomersFilters } from '@/components/dashboard/customer/customers-filters';
// import type { Filters } from '@/components/dashboard/customer/customers-filters';
import { CustomersPagination } from '@/components/dashboard/customer/customers-pagination';
import { CustomersSelectionProvider } from '@/components/dashboard/customer/customers-selection-context';
import { CustomersTable } from '@/components/dashboard/customer/customers-table';
import type { Customer, Filters } from '@/components/dashboard/customer/type.d';
import { SampleCustomers } from './SampleCustomers';
import { TeachersFilters } from '@/components/dashboard/teacher/teachers-filters';
// import type { Filters } from '@/components/dashboard/teacher/customers-filters';
import { TeachersPagination } from '@/components/dashboard/teacher/teachers-pagination';
import { TeachersSelectionProvider } from '@/components/dashboard/teacher/teachers-selection-context';
import { TeachersTable } from '@/components/dashboard/teacher/teachers-table';
import type { Teacher, Filters } from '@/components/dashboard/teacher/type.d';
import { SampleTeachers } from './SampleTeachers';
import { useTranslation } from 'react-i18next';
import { paths } from '@/paths';
@@ -34,16 +34,16 @@ import { logger } from '@/lib/default-logger';
import { pb } from '@/lib/pb';
import { toast } from '@/components/core/toaster';
import ErrorDisplay from '@/components/dashboard/error';
import { defaultCustomer } from '@/components/dashboard/customer/_constants';
import { defaultTeacher } from '@/components/dashboard/teacher/_constants';
import FormLoading from '@/components/loading';
export default function Page({ searchParams }: PageProps): React.JSX.Element {
const { t } = useTranslation(['customers']);
const { t } = useTranslation(['teachers']);
const router = useRouter();
const { email, phone, sortDir, status } = searchParams;
const [lessonCategoriesData, setLessonCategoriesData] = React.useState<Customer[]>([]);
const [lessonCategoriesData, setLessonCategoriesData] = React.useState<Teacher[]>([]);
//
const [isLoadingAddPage, setIsLoadingAddPage] = React.useState<boolean>(false);
@@ -52,26 +52,22 @@ export default function Page({ searchParams }: PageProps): React.JSX.Element {
//
const [rowsPerPage, setRowsPerPage] = React.useState<number>(5);
//
const [f, setF] = React.useState<Customer[]>([]);
const [f, setF] = React.useState<Teacher[]>([]);
const [currentPage, setCurrentPage] = React.useState<number>(0);
//
const [recordCount, setRecordCount] = React.useState<number>(0);
const [listOption, setListOption] = React.useState({});
const [listSort, setListSort] = React.useState({});
//
// const sortedCustomers = applySort(SampleCustomers, sortDir);
// const filteredCustomers = applyFilters(sortedCustomers, { email, phone, status });
//
const reloadRows = async (): Promise<void> => {
try {
const models: ListResult<RecordModel> = await pb
.collection(COL_CUSTOMERS)
.collection(COL_TEACHERS)
.getList(currentPage + 1, rowsPerPage, listOption);
const { items, totalItems } = models;
const tempLessonTypes: Customer[] = items.map((lt) => {
return { ...defaultCustomer, ...lt };
const tempLessonTypes: Teacher[] = items.map((lt) => {
return { ...defaultTeacher, ...lt };
});
setLessonCategoriesData(tempLessonTypes);
@@ -174,7 +170,7 @@ export default function Page({ searchParams }: PageProps): React.JSX.Element {
loading={isLoadingAddPage}
onClick={(): void => {
setIsLoadingAddPage(true);
router.push(paths.dashboard.customers.create);
router.push(paths.dashboard.teachers.create);
}}
startIcon={<PlusIcon />}
variant="contained"
@@ -183,22 +179,22 @@ export default function Page({ searchParams }: PageProps): React.JSX.Element {
</LoadingButton>
</Box>
</Stack>
<CustomersSelectionProvider customers={f}>
<TeachersSelectionProvider teachers={f}>
<Card>
<CustomersFilters
<TeachersFilters
filters={{ email, phone, status }}
fullData={lessonCategoriesData}
sortDir={sortDir}
/>
<Divider />
<Box sx={{ overflowX: 'auto' }}>
<CustomersTable
<TeachersTable
reloadRows={reloadRows}
rows={f}
/>
</Box>
<Divider />
<CustomersPagination
<TeachersPagination
count={recordCount}
page={currentPage}
rowsPerPage={rowsPerPage}
@@ -206,7 +202,7 @@ export default function Page({ searchParams }: PageProps): React.JSX.Element {
setRowsPerPage={setRowsPerPage}
/>
</Card>
</CustomersSelectionProvider>
</TeachersSelectionProvider>
</Stack>
<Box sx={{ display: isDevelopment ? 'block' : 'none' }}>
<pre>{JSON.stringify(f, null, 2)}</pre>
@@ -217,7 +213,7 @@ export default function Page({ searchParams }: PageProps): React.JSX.Element {
// Sorting and filtering has to be done on the server.
function applySort(row: Customer[], sortDir: 'asc' | 'desc' | undefined): Customer[] {
function applySort(row: Teacher[], sortDir: 'asc' | 'desc' | undefined): Teacher[] {
return row.sort((a, b) => {
if (sortDir === 'asc') {
return a.createdAt.getTime() - b.createdAt.getTime();
@@ -227,7 +223,7 @@ function applySort(row: Customer[], sortDir: 'asc' | 'desc' | undefined): Custom
});
}
function applyFilters(row: Customer[], { email, phone, status }: Filters): Customer[] {
function applyFilters(row: Teacher[], { email, phone, status }: Filters): Teacher[] {
return row.filter((item) => {
if (email) {
if (!item.email?.toLowerCase().includes(email.toLowerCase())) {

View File

@@ -3,9 +3,9 @@
// empty valur for customer
import { dayjs } from '@/lib/dayjs';
import type { Customer } from './type.d';
import type { Teacher } from './type.d';
export const defaultCustomer: Customer = {
export const defaultTeacher: Teacher = {
id: '',
name: '',
avatar: undefined,
@@ -16,6 +16,6 @@ export const defaultCustomer: Customer = {
createdAt: dayjs().toDate(),
};
export const emptyLpCategory: Customer = {
...defaultCustomer,
export const emptyLpCategory: Teacher = {
...defaultTeacher,
};

View File

@@ -16,7 +16,7 @@ import { useTranslation } from 'react-i18next';
import { logger } from '@/lib/default-logger';
import { toast } from '@/components/core/toaster';
import { deleteCustomer } from '@/db/Customers/Delete';
import { deleteTeacher } from '@/db/Teachers/Delete';
export default function ConfirmDeleteModal({
open,
@@ -49,7 +49,7 @@ export default function ConfirmDeleteModal({
setIsDeleteing(true);
// RULES: delete<CollectionName>
deleteCustomer(idToDelete)
deleteTeacher(idToDelete)
.then(() => {
reloadRows();
handleClose();

View File

@@ -29,7 +29,7 @@ import { paths } from '@/paths';
import { logger } from '@/lib/default-logger';
import { Option } from '@/components/core/option';
import { toast } from '@/components/core/toaster';
import { createCustomer } from '@/db/Customers/Create';
import { createTeacher } from '@/db/Teachers/Create';
import isDevelopment from '@/lib/check-is-development';
function fileToBase64(file: Blob): Promise<string> {
@@ -87,7 +87,7 @@ const defaultValues = {
currency: 'USD',
} satisfies Values;
export function CustomerCreateForm(): React.JSX.Element {
export function TeacherCreateForm(): React.JSX.Element {
const router = useRouter();
const {
@@ -102,9 +102,9 @@ export function CustomerCreateForm(): React.JSX.Element {
async (values: Values): Promise<void> => {
try {
// Use standard create method from db/Customers/Create
const record = await createCustomer(values);
const record = await createTeacher(values);
toast.success('Customer created');
router.push(paths.dashboard.customers.details(record.id));
router.push(paths.dashboard.teachers.details(record.id));
} catch (err) {
logger.error(err);
toast.error('Failed to create customer');
@@ -509,7 +509,7 @@ export function CustomerCreateForm(): React.JSX.Element {
<Button
color="secondary"
component={RouterLink}
href={paths.dashboard.customers.list}
href={paths.dashboard.teachers.list}
>
Cancel
</Button>
@@ -517,7 +517,7 @@ export function CustomerCreateForm(): React.JSX.Element {
type="submit"
variant="contained"
>
Create customer
Create teacher
</Button>
</CardActions>
</Card>

View File

@@ -4,7 +4,7 @@ import * as React from 'react';
import RouterLink from 'next/link';
import { useParams, useRouter } from 'next/navigation';
//
import { COL_CUSTOMERS } from '@/constants';
import { COL_TEACHERS } from '@/constants';
import { zodResolver } from '@hookform/resolvers/zod';
import { LoadingButton } from '@mui/lab';
//
@@ -85,7 +85,7 @@ const defaultValues = {
avatar: '',
} satisfies Values;
export function CustomerEditForm(): React.JSX.Element {
export function TeacherEditForm(): React.JSX.Element {
const router = useRouter();
const { t } = useTranslation(['lp_categories']);
@@ -123,9 +123,9 @@ export function CustomerEditForm(): React.JSX.Element {
};
try {
await pb.collection(COL_CUSTOMERS).update(customerId, updateData);
await pb.collection(COL_TEACHERS).update(customerId, updateData);
toast.success('Customer updated successfully');
router.push(paths.dashboard.customers.list);
router.push(paths.dashboard.teachers.list);
} catch (error) {
logger.error(error);
toast.error('Failed to update customer');
@@ -162,7 +162,7 @@ export function CustomerEditForm(): React.JSX.Element {
setShowLoading(true);
try {
const result = await pb.collection(COL_CUSTOMERS).getOne(id);
const result = await pb.collection(COL_TEACHERS).getOne(id);
reset({ ...defaultValues, ...result });
console.log({ result });
@@ -581,7 +581,7 @@ export function CustomerEditForm(): React.JSX.Element {
<Button
color="secondary"
component={RouterLink}
href={paths.dashboard.customers.list}
href={paths.dashboard.teachers.list}
>
{t('edit.cancelButton')}
</Button>

View File

@@ -21,7 +21,7 @@ import { paths } from '@/paths';
import { FilterButton } from '@/components/core/filter-button';
import { Option } from '@/components/core/option';
import { useCustomersSelection } from './customers-selection-context';
import { useTeachersSelection } from './teachers-selection-context';
import GetBlockedCount from '@/db/Customers/GetBlockedCount';
import GetPendingCount from '@/db/Customers/GetPendingCount';
import GetActiveCount from '@/db/Customers/GetActiveCount';
@@ -29,7 +29,7 @@ import PhoneFilterPopover from './phone-filter-popover';
import EmailFilterPopover from './email-filter-popover';
import type { CustomersFiltersProps, Filters, SortDir } from './type.d';
export function CustomersFilters({
export function TeachersFilters({
filters = {},
sortDir = 'desc',
fullData,
@@ -45,7 +45,7 @@ export function CustomersFilters({
const router = useRouter();
const selection = useCustomersSelection();
const selection = useTeachersSelection();
// function getVisible(): number {
// return fullData.reduce((count, item: CrQuestion) => {
@@ -87,7 +87,7 @@ export function CustomersFilters({
searchParams.set('phone', newFilters.phone);
}
router.push(`${paths.dashboard.customers.list}?${searchParams.toString()}`);
router.push(`${paths.dashboard.teachers.list}?${searchParams.toString()}`);
},
[router]
);

View File

@@ -16,7 +16,7 @@ interface CustomersPaginationProps {
rowsPerPage: number;
}
export function CustomersPagination({
export function TeachersPagination({
count,
page,
//

View File

@@ -5,7 +5,7 @@ import * as React from 'react';
import { useSelection } from '@/hooks/use-selection';
import type { Selection } from '@/hooks/use-selection';
import type { Customer } from './type.d';
import type { Teacher } from './type.d';
function noop(): void {
return undefined;
@@ -25,19 +25,19 @@ export const CustomersSelectionContext = React.createContext<CustomersSelectionC
interface CustomersSelectionProviderProps {
children: React.ReactNode;
customers: Customer[];
teachers: Teacher[];
}
export function CustomersSelectionProvider({
export function TeachersSelectionProvider({
children,
customers = [],
teachers = [],
}: CustomersSelectionProviderProps): React.JSX.Element {
const customerIds = React.useMemo(() => customers.map((customer) => customer.id), [customers]);
const customerIds = React.useMemo(() => teachers.map((customer) => customer.id), [teachers]);
const selection = useSelection(customerIds);
return <CustomersSelectionContext.Provider value={{ ...selection }}>{children}</CustomersSelectionContext.Provider>;
}
export function useCustomersSelection(): CustomersSelectionContextValue {
export function useTeachersSelection(): CustomersSelectionContextValue {
return React.useContext(CustomersSelectionContext);
}

View File

@@ -27,10 +27,10 @@ import { DataTable } from '@/components/core/data-table';
import type { ColumnDef } from '@/components/core/data-table';
import ConfirmDeleteModal from './confirm-delete-modal';
import { useCustomersSelection } from './customers-selection-context';
import type { Customer } from './type.d';
import { useTeachersSelection } from './teachers-selection-context';
import type { Teacher } from './type.d';
function columns(handleDeleteClick: (testId: string) => void): ColumnDef<Customer>[] {
function columns(handleDeleteClick: (testId: string) => void): ColumnDef<Teacher>[] {
return [
{
formatter: (row): React.JSX.Element => (
@@ -44,7 +44,7 @@ function columns(handleDeleteClick: (testId: string) => void): ColumnDef<Custome
<Link
color="inherit"
component={RouterLink}
href={paths.dashboard.customers.details(row.id)}
href={paths.dashboard.teachers.details(row.id)}
sx={{ whiteSpace: 'nowrap' }}
variant="subtitle2"
>
@@ -89,8 +89,6 @@ function columns(handleDeleteClick: (testId: string) => void): ColumnDef<Custome
{
formatter: (row): React.JSX.Element => {
// eslint-disable-next-line react-hooks/rules-of-hooks
const mapping = {
active: {
label: 'Active',
@@ -143,7 +141,7 @@ function columns(handleDeleteClick: (testId: string) => void): ColumnDef<Custome
//
color="secondary"
component={RouterLink}
href={paths.dashboard.customers.details(row.id)}
href={paths.dashboard.teachers.details(row.id)}
>
<PencilSimpleIcon size={24} />
</LoadingButton>
@@ -167,13 +165,13 @@ function columns(handleDeleteClick: (testId: string) => void): ColumnDef<Custome
}
export interface CustomersTableProps {
rows: Customer[];
rows: Teacher[];
reloadRows: () => void;
}
export function CustomersTable({ rows, reloadRows }: CustomersTableProps): React.JSX.Element {
export function TeachersTable({ rows, reloadRows }: CustomersTableProps): React.JSX.Element {
const { t } = useTranslation(['customers']);
const { deselectAll, deselectOne, selectAll, selectOne, selected } = useCustomersSelection();
const { deselectAll, deselectOne, selectAll, selectOne, selected } = useTeachersSelection();
const [idToDelete, setIdToDelete] = React.useState('');
const [open, setOpen] = React.useState(false);
@@ -191,7 +189,7 @@ export function CustomersTable({ rows, reloadRows }: CustomersTableProps): React
reloadRows={reloadRows}
setOpen={setOpen}
/>
<DataTable<Customer>
<DataTable<Teacher>
columns={columns(handleDeleteClick)}
onDeselectAll={deselectAll}
onDeselectOne={(_, row) => {
@@ -213,7 +211,7 @@ export function CustomersTable({ rows, reloadRows }: CustomersTableProps): React
variant="body2"
>
{/* TODO: update this */}
{t('no-record-found')}
{t('no-teachers-found')}
</Typography>
</Box>
) : null}

View File

@@ -2,7 +2,7 @@
export type SortDir = 'asc' | 'desc';
export interface Customer {
export interface Teacher {
id: string;
name: string;
avatar?: string;
@@ -60,7 +60,7 @@ export interface EditFormProps {
export interface CustomersFiltersProps {
filters?: Filters;
sortDir?: SortDir;
fullData: Customer[];
fullData: Teacher[];
}
export interface Filters {
email?: string;

View File

@@ -0,0 +1,11 @@
// api method for crate teacher record
// RULES:
// TBA
import { pb } from '@/lib/pb';
import { COL_TEACHERS } from '@/constants';
import type { CreateFormProps } from '@/components/dashboard/teacher/type.d';
import type { RecordModel } from 'pocketbase';
export async function createTeacher(data: CreateFormProps): Promise<RecordModel> {
return pb.collection(COL_TEACHERS).create(data);
}

View File

@@ -0,0 +1,6 @@
import { pb } from '@/lib/pb';
import { COL_TEACHERS } from '@/constants';
export async function deleteTeacher(id: string): Promise<boolean> {
return pb.collection(COL_TEACHERS).delete(id);
}

View File

@@ -0,0 +1,9 @@
import { COL_TEACHERS } from '@/constants';
import { pb } from '@/lib/pb';
export default async function GetActiveCount(): Promise<number> {
const { totalItems: count } = await pb.collection(COL_TEACHERS).getList(1, 1, {
filter: 'status = "active"',
});
return count;
}

View File

@@ -0,0 +1,7 @@
import { pb } from '@/lib/pb';
import { COL_TEACHERS } from '@/constants';
import { RecordModel } from 'pocketbase';
export async function getAllTeachers(options = {}): Promise<RecordModel[]> {
return pb.collection(COL_TEACHERS).getFullList(options);
}

View File

@@ -0,0 +1,7 @@
import { pb } from '@/lib/pb';
import { COL_TEACHERS } from '@/constants';
export async function getAllTeachersCount(): Promise<number> {
const result = await pb.collection(COL_TEACHERS).getList(1, 1);
return result.totalItems;
}

View File

@@ -0,0 +1,9 @@
import { COL_TEACHERS } from '@/constants';
import { pb } from '@/lib/pb';
export default async function GetBlockedCount(): Promise<number> {
const { totalItems: count } = await pb.collection(COL_TEACHERS).getList(1, 1, {
filter: 'status = "blocked"',
});
return count;
}

View File

@@ -0,0 +1,7 @@
import { pb } from '@/lib/pb';
import { COL_TEACHERS } from '@/constants';
import { RecordModel } from 'pocketbase';
export async function getTeacherById(id: string): Promise<RecordModel> {
return pb.collection(COL_TEACHERS).getOne(id);
}

View File

@@ -0,0 +1,9 @@
import { COL_CUSTOMERS } from '@/constants';
import { pb } from '@/lib/pb';
export default async function GetPendingCount(): Promise<number> {
const { totalItems: count } = await pb.collection(COL_CUSTOMERS).getList(1, 1, {
filter: 'status = "pending"',
});
return count;
}

View File

@@ -0,0 +1,3 @@
export function helloCustomer() {
return 'Hello from Customers module!';
}

View File

@@ -0,0 +1,8 @@
import { pb } from '@/lib/pb';
import { COL_TEACHERS } from '@/constants';
import type { RecordModel } from 'pocketbase';
import type { EditFormProps } from '@/components/dashboard/teacher/type.d';
export async function updateTeacher(id: string, data: Partial<EditFormProps>): Promise<RecordModel> {
return pb.collection(COL_TEACHERS).update(id, data);
}

View File

@@ -0,0 +1,31 @@
# GUIDELINES
This folder contains drivers for `Teacher`/`Teachers` records using PocketBase:
- create (Create.tsx)
- read (GetById.tsx)
- write (Update.tsx)
- count (GetAllCount.tsx, GetActiveCount.tsx, GetBlockedCount.tsx, GetPendingCount.tsx)
- misc (Helloworld.tsx)
- delete (Delete.tsx)
- list (GetAll.tsx)
the `@` sign refer to `/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project/002_source/cms/src`
## Assumption and Requirements
- assume `pb` is located in `@/lib/pb`
- no need to handle error in this function, i'll handle it in the caller
- type information defined in `/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project/002_source/cms/src/db/Customers/type.d.tsx`
simple template:
```typescript
import { pb } from '@/lib/pb';
import { COL_CUSTOMERS } from '@/constants';
export async function createCustomer(data: CreateFormProps) {
// ...content
// use direct return of pb.collection (e.g. return pb.collection(xxx))
}
```