diff --git a/002_source/cms/.eslintrc.js b/002_source/cms/.eslintrc.js index 7a5746b..2b244e1 100644 --- a/002_source/cms/.eslintrc.js +++ b/002_source/cms/.eslintrc.js @@ -83,5 +83,5 @@ module.exports = { 'eslintreact/jsx-sort-props': 'off', 'react/jsx-sort-props': 'off', }, - ignorePatterns: ['**/*del', '**/*bak'], + ignorePatterns: ['**/*del', '**/*bak', '**/*copy.*', '**/*copy*.*'], }; diff --git a/002_source/cms/.gitignore b/002_source/cms/.gitignore index af4d62b..48b2552 100644 --- a/002_source/cms/.gitignore +++ b/002_source/cms/.gitignore @@ -1,44 +1,46 @@ -# **/repomix-output.xml -**/*:Zone.Identifier -**/*bak -**/*log -**/*tmp -*del -**/_archive - -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/node_modules -/.pnp -.pnp.js - -# testing -/coverage - -# next.js -/.next/ -/out/ - -# production -/build - -# misc -.DS_Store -*.pem -.swc - -# debug -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# local env files -.env*.local - -# vercel -.vercel - -# typescript -*.tsbuildinfo -next-env.d.ts +**/*copy.tsx + +# **/repomix-output.xml +**/*:Zone.Identifier +**/*bak +**/*log +**/*tmp +*del +**/_archive + +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem +.swc + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env*.local + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/002_source/cms/public/locales/dev/PROMPT.md b/002_source/cms/public/locales/dev/PROMPT.md new file mode 100644 index 0000000..8fb9ed5 --- /dev/null +++ b/002_source/cms/public/locales/dev/PROMPT.md @@ -0,0 +1,22 @@ +# PROMPT + +please update `/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project/002_source/cms/public/locales/dev/translation.json` +to add below translations, thanks. + +``` +dashboard.lessonCategories.edit.title +dashboard.lessonCategories.edit.avatar +dashboard.lessonCategories.edit.avatarRequirements +dashboard.lessonCategories.edit.name +dashboard.lessonCategories.edit.type + +``` +--- + +please read `/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project/002_source/cms/src/components/dashboard/lesson_category/lesson-category-edit-form.tsx` +and update `/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project/002_source/cms/public/locales/dev/translation.json` the missing translations, thanks. + +--- + +please refactor `common.json` to smaller translation files, thanks +e.g. `lessonTypes` -> `lesson_type` diff --git a/002_source/cms/public/locales/dev/common.json b/002_source/cms/public/locales/dev/common.json new file mode 100644 index 0000000..d78d762 --- /dev/null +++ b/002_source/cms/public/locales/dev/common.json @@ -0,0 +1,135 @@ +{ + "languageChanged": "語言已更改", + "type": "類型", + "helloworld": "你好,世界", + "Add": "新增項目", + "visible": "可視", + "hidden": "屏閉", + "Hidden": "屏閉", + "Newest": "最新", + "Oldest": "最舊", + "Lesson position": "位置", + "Lesson type": "種類", + "Type": "種類", + "Name": "名稱", + "Filter by name": "依名稱過濾", + "Filter by type": "依類型過濾", + "Actions": "動作", + "Created at": "建立時間", + "Updated at": "更新時間", + "Position": "位置", + "Visible": "顯示", + "Apply": "套用", + "Overview": "概觀", + "Dashboard": "儀表板", + "Tickets": "票券", + "Sign ups": "註冊", + "Open issues": "開啟問題", + "Closed issues": "關閉問題", + "increase": "增加", + "decrease": "減少", + "common.loading": "載入中", + "vs last month": "與上個月相比", + "Dashboards": "儀表板", + "App usage": "應用程式使用情況", + "Find your dream job": "找到你的夢想工作", + "Need help figuring things out?": "需要幫助嗎?", + "Search for jobs that match your skills and apply to them directly": "搜索符合你技能的工作,直接申請", + "Find answers to your questions and get in touch with our team.": "找到你的問題並與我們的團隊聯繫", + "Explore documentation": "探索文件", + "Learn how to get started with our product and make the most of it.": "學習如何開始使用我們的產品並充分利用它", + "Search Jobs": "搜索工作", + "Help Center": "幫助中心", + "Documentation": "文件", + "increase_in_app_usage_with": "使用者量增加", + "new_products_purchased": "新產品購買", + "Our subscriptions": "我們的訂閱", + "this_year": "今年", + "is_forecasted_to_increase_in_your_traffic_by_the_end_of_the_current_month": "今年預計增加你的流量", + "Jan": "一月", + "Feb": "二月", + "Mar": "三月", + "Apr": "四月", + "May": "五月", + "Jun": "六月", + "Jul": "七月", + "Aug": "八月", + "Sep": "九月", + "Oct": "十月", + "Nov": "十一月", + "Dec": "十二月", + "See all subscriptions": "查看所有訂閱", + "app_chat": "應用程式聊天", + "Upcoming events": "即將發生的事件", + "Based on the linked bank accounts": "基於連結的銀行帳戶", + "App limits": "應用程式限制", + "You have used {percentage} of your available spots.": "您已使用 {percentage} 的可用座位。升級計劃以建立更多專案", + "userMessagesUnread": "hello userMessagesUnread", + "Upgrade plan to create more projects": "升級計劃以建立更多專案", + "You have almost reached your limit": "您已接近您的限制", + "Upgrade plan": "升級計劃", + "Help center": "幫助中心", + "Jobs": "工作", + "go_to_chat": "前往聊天", + "See all events": "查看所有事件", + "You have used": "您已使用", + "of your available spots": "的可用座位", + "Paid": "已付款", + "Canceled": "已取消", + "Pending": "待付款", + "Expiring": "已過期", + "Refunded": "已退款", + "Total": "總計", + "Total paid": "已付款", + "Total cancelled": "已取消", + "Total pending": "待付款", + "year": "年", + "month": "月", + "week": "週", + "day": "日", + "hour": "小時", + "minute": "分鐘", + "second": "秒", + "ago": "前", + "remaining": "剩下", + "days": "天", + "hours": "小時", + "minutes": "分鐘", + "seconds": "秒", + "Clear filters": "清除篩選", + "Type information": "輸入資訊", + "Cancel": "取消", + "Delete": "刪除", + "All": "全部", + "categories": "課程分類", + "loading": "載入中", + "Notifications": "通知", + "Mark all as read": "標記所有為已讀", + "There are no notifications": "沒有通知", + "listenings": "聽講 (Listenings)", + "question_category": "問題分類", + "question_list": "問題", + "matching_frenzy": "配對 (Matching Frenzy)", + "connective_revision": "連接詞 (Connective Revision)", + "settings": "設定", + "students": "學生", + "dashboard.lessonCategories.add": "新增課程分類", + "dashboard.lessonCategories.title": "課程分類", + "dashboard.lessonCategorys.edit.name": "課程分類名稱", + "dashboard.lessonCategorys.edit.position": "課程分類順序", + "dashboard.lessonCategorys.edit.title": "編輯課程分類", + "dashboard.lessonCategorys.edit.visibleToUser": "顯示給使用者", + "dashboard.lessonCategorys.edit.visible": "顯示", + "dashboard.lessonCategorys.edit.hidden": "隱藏", + "dashboard.lessonCategorys.edit.cancelButton": "取消", + "dashboard.lessonCategorys.edit.updateButton": "更新", + "dashboard.lessonCategorys.list.title": "課堂種類", + "word-count": "字數", + "unable-to-process-request": "無法處理請求", + "detailed-error-information": "詳細錯誤資訊", + "error": { + "unable-to-process-request": "無法處理您的請求", + "detailed-error-information": "詳細錯誤資訊" + }, + "name-is-required": "名稱為必填" +} diff --git a/002_source/cms/public/locales/dev/lesson_category.json b/002_source/cms/public/locales/dev/lesson_category.json new file mode 100644 index 0000000..be2303d --- /dev/null +++ b/002_source/cms/public/locales/dev/lesson_category.json @@ -0,0 +1,69 @@ +{ + "add": "新增課程分類", + "title": "課程分類", + "basic_info": "基本資訊", + "error": { + "unable-to-process-request": "無法處理您的請求", + "detailed-error-information": "詳細錯誤資訊" + }, + "create": { + "title": "建立課程類型", + "createButton": "建立", + "cancelButton": "取消", + "message": "請輸入課程類型名稱", + "success": "課程類型建立成功", + "error": "課程類型建立失敗", + "typeInformation": "輸入課程類型資訊", + "avatar": "上傳課程類型圖片", + "avatar_select": "選擇圖片", + "avatarRequirements": "最小 400x400 像素,PNG 或 JPEG", + "select": "請選擇", + "name": "課程類型名稱", + "position": "課程類型順序", + "visibleToUser": "顯示給使用者", + "detail-information": "詳細資訊", + "description": "課程類型描述", + "remarks": "備註" + }, + "edit": { + "avatar": "上傳圖片", + "avatarRequirements": "最小 400x400 像素,PNG 或 JPEG", + "cancelButton": "取消", + "error": "課程類型更新失敗", + "hidden": "隱藏", + "name": "課程分類名稱", + "position": "課程分類順序", + "select": "請選擇", + "success": "課程類型更新成功", + "title": "編輯課程分類", + "basic-info": "基本資訊", + "type": "類型", + "updateButton": "更新", + "visible": "顯示", + "visibleToUser": "顯示給使用者", + "write-something": "輸入一些內容" + }, + "delete": { + "title": "刪除課程類型", + "message": "確定要刪除課程類型嗎?", + "success": "課程類型刪除成功", + "error": "課程類型刪除失敗", + "cancelButton": "取消", + "deleteButton": "刪除" + }, + "list": { + "title": "課堂種類", + "message": "請選擇課程類型", + "empty": { + "title": "目前沒有課程類型", + "message": "請建立課程類型", + "create": "建立課程類型" + }, + "error": "課程類型載入失敗" + }, + "view": { + "basic-details": "基本資訊" + }, + "Delete Lesson Type ?": "刪除課程類型?", + "Are you sure you want to delete lesson type ?": "確定要刪除課程類型嗎?" +} diff --git a/002_source/cms/public/locales/dev/lesson_type.json b/002_source/cms/public/locales/dev/lesson_type.json new file mode 100644 index 0000000..c383ad1 --- /dev/null +++ b/002_source/cms/public/locales/dev/lesson_type.json @@ -0,0 +1,65 @@ +{ + "add": "新增課程類型", + "title": "課程類型", + "type": "類型", + "error": { + "unable-to-process-request": "無法處理您的請求", + "detailed-error-information": "詳細錯誤資訊" + }, + "create": { + "title": "建立課程類型", + "createButton": "建立", + "cancelButton": "取消", + "message": "請輸入課程類型名稱", + "success": "課程類型建立成功", + "error": "課程類型建立失敗", + "typeInformation": "輸入課程類型資訊", + "avatar": "上傳課程類型圖片", + "avatarRequirements": "上傳課程類型圖片", + "select": "請選擇", + "name": "課程類型名稱", + "position": "課程類型順序", + "visibleToUser": "顯示給使用者" + }, + "edit": { + "avatar": "上傳課程類型圖片", + "avatarRequirements": "上傳課程類型圖片", + "cancelButton": "取消", + "error": "課程類型更新失敗", + "hidden": "隱藏", + "name": "課程類型名稱", + "position": "課程類型順序", + "select": "請選擇", + "success": "課程類型更新成功", + "title": "編輯課程類型", + "typeInformation": "輸入課程類型資訊", + "updateButton": "更新", + "visible": "顯示", + "visibleToUser": "顯示給使用者" + }, + "delete": { + "title": "刪除課程類型", + "message": "確定要刪除課程類型嗎?", + "success": "課程類型刪除成功", + "error": "課程類型刪除失敗", + "cancelButton": "取消", + "deleteButton": "刪除" + }, + "list": { + "title": "課程類型列表", + "message": "請選擇課程類型", + "empty": { + "title": "目前沒有課程類型", + "message": "請建立課程類型", + "create": "建立課程類型" + }, + "error": "課程類型載入失敗" + }, + "view": { + "basic-details": "基本資訊" + }, + "Lesson Type": "課程類型", + "Lesson Types": "課程類型", + "Delete Lesson Type ?": "刪除課程類型?", + "Are you sure you want to delete lesson type ?": "確定要刪除課程類型嗎?" +} diff --git a/002_source/cms/public/locales/dev/translation.json b/002_source/cms/public/locales/dev/translation.json index e3f8bef..8ecdb10 100644 --- a/002_source/cms/public/locales/dev/translation.json +++ b/002_source/cms/public/locales/dev/translation.json @@ -188,5 +188,8 @@ "dashboard.lessonCategorys.edit.cancelButton": "取消", "dashboard.lessonCategorys.edit.updateButton": "更新", "dashboard.lessonCategorys.list.title": "課堂種類", - "word-count": "字數" + "word-count": "字數", + "dashboard.lessonTypes.list.error": "課程類型載入失敗", + "unable-to-process-request": "無法處理請求", + "detailed-error-information": "詳細錯誤資訊" } \ No newline at end of file diff --git a/002_source/cms/src/.vscode/settings.json b/002_source/cms/src/.vscode/settings.json new file mode 100644 index 0000000..23830fb --- /dev/null +++ b/002_source/cms/src/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "git.ignoreLimitWarning": true +} diff --git a/002_source/cms/src/app/dashboard/lesson_categories/.vscode/settings.json b/002_source/cms/src/app/dashboard/lesson_categories/.vscode/settings.json new file mode 100644 index 0000000..23830fb --- /dev/null +++ b/002_source/cms/src/app/dashboard/lesson_categories/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "git.ignoreLimitWarning": true +} diff --git a/002_source/cms/src/app/dashboard/lesson_categories/[cat_id]/page.tsx b/002_source/cms/src/app/dashboard/lesson_categories/[cat_id]/page.tsx index 151422d..6711445 100644 --- a/002_source/cms/src/app/dashboard/lesson_categories/[cat_id]/page.tsx +++ b/002_source/cms/src/app/dashboard/lesson_categories/[cat_id]/page.tsx @@ -38,24 +38,25 @@ import { pb } from '@/lib/pb'; import { PropertyItem } from '@/components/core/property-item'; import { PropertyList } from '@/components/core/property-list'; import { toast } from '@/components/core/toaster'; +import ErrorDisplay from '@/components/dashboard/error'; import { defaultLessonCategory } from '@/components/dashboard/lesson_category/_constants.ts'; // import { defaultLessonCategory } from '@/components/dashboard/lesson_category/defaultLessonCategory'; import { Notifications } from '@/components/dashboard/lesson_category/notifications'; import { Payments } from '@/components/dashboard/lesson_category/payments'; import type { Address } from '@/components/dashboard/lesson_category/shipping-address'; import { ShippingAddress } from '@/components/dashboard/lesson_category/shipping-address'; -import type { LessonCategory } from '@/components/dashboard/lesson_category/type.d.ts'; +import type { LessonCategory } from '@/components/dashboard/lesson_category/types'; import FormLoading from '@/components/loading'; // export const metadata = { title: `Details | Customers | Dashboard | ${config.site.name}` } satisfies Metadata; export default function Page(): React.JSX.Element { - const { t } = useTranslation(); + const { t } = useTranslation(['common']); const router = useRouter(); // const { cat_id: catId } = useParams<{ cat_id: string }>(); // - const [showLoadin, setIsLoading] = React.useState(true); + const [showLoading, setShowLoading] = React.useState(true); const [showError, setShowError] = React.useState(false); // const [showLessonCategory, setShowLessonCategory] = React.useState(defaultLessonCategory); @@ -70,16 +71,29 @@ export default function Page(): React.JSX.Element { .getOne(catId) .then((model: RecordModel) => { setShowLessonCategory({ ...defaultLessonCategory, ...model }); - setIsLoading(false); }) .catch((err) => { logger.error(err); toast(t('dashboard.lessonTypes.list.error')); + + setShowError(true); + }) + .finally(() => { + setShowLoading(false); }); } }, [catId]); - if (showLoadin) return ; + if (showLoading) return ; + + if (showError) + return ( + + ); return ( - - MV + + empty
@@ -150,7 +168,7 @@ export default function Page(): React.JSX.Element { } - title="Basic details" + title={t('basic-details', { ns: 'lesson_category' })} /> } @@ -199,7 +217,7 @@ export default function Page(): React.JSX.Element { } - title="Security" + title={t('security', { ns: 'lesson_category' })} /> @@ -272,7 +290,7 @@ export default function Page(): React.JSX.Element { } - title="Billing details" + title={t('billing-details', { ns: 'lesson_category' })} /> @@ -307,7 +325,7 @@ export default function Page(): React.JSX.Element { } - title="Shipping addresses" + title={t('shipping-addresses', { ns: 'lesson_category' })} /> diff --git a/002_source/cms/src/app/dashboard/lesson_categories/create/page.tsx b/002_source/cms/src/app/dashboard/lesson_categories/create/page.tsx index 166b21d..fd45b0a 100644 --- a/002_source/cms/src/app/dashboard/lesson_categories/create/page.tsx +++ b/002_source/cms/src/app/dashboard/lesson_categories/create/page.tsx @@ -34,11 +34,11 @@ export default function Page(): React.JSX.Element { variant="subtitle2" > - {t('dashboard.lessonCategories.title')} + {t('title', { ns: 'lesson_category' })}
- {t('dashboard.lessonCategories.create.title')} + {t('create.title', { ns: 'lesson_category' })}
diff --git a/002_source/cms/src/app/dashboard/lesson_categories/edit/[cat_id]/_PROMPT.md b/002_source/cms/src/app/dashboard/lesson_categories/edit/[cat_id]/_PROMPT.md new file mode 100644 index 0000000..abf4465 --- /dev/null +++ b/002_source/cms/src/app/dashboard/lesson_categories/edit/[cat_id]/_PROMPT.md @@ -0,0 +1,11 @@ +# task + +## instruction + +with reference to `/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project/002_source/cms/src/app/_helloworld/page.tsx` + +with reference to `/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project/002_source/cms/src/app/dashboard/lesson_types/edit/[typeId]/page.tsx` + +please modify `/home/logic/_wsl_workspace/001_github_ws/lettersoup-online-ws/lettersoup-online/project/002_source/cms/src/app/dashboard/lesson_categories/edit/page.tsx` + +please draft a tsx for showing error to user thanks, diff --git a/002_source/cms/src/app/dashboard/lesson_categories/edit/[cat_id]/page.tsx b/002_source/cms/src/app/dashboard/lesson_categories/edit/[cat_id]/page.tsx new file mode 100644 index 0000000..fb4b074 --- /dev/null +++ b/002_source/cms/src/app/dashboard/lesson_categories/edit/[cat_id]/page.tsx @@ -0,0 +1,55 @@ +'use client'; + +import * as React from 'react'; +import RouterLink from 'next/link'; +import Box from '@mui/material/Box'; +import Link from '@mui/material/Link'; +import Stack from '@mui/material/Stack'; +import Typography from '@mui/material/Typography'; +import { ArrowLeft as ArrowLeftIcon } from '@phosphor-icons/react/dist/ssr/ArrowLeft'; +import { useTranslation } from 'react-i18next'; + +import { paths } from '@/paths'; +import { LessonCategoryEditForm } from '@/components/dashboard/lesson_category/lesson-category-edit-form'; + +// import { LessonCategoryEditForm } from '@/components/dashboard/lesson_category/lesson-category-edit-form'; + +export default function Page(): React.JSX.Element { + const { t } = useTranslation(['common', 'lesson_category']); + + React.useEffect(() => { + console.log('helloworld'); + }, []); + + return ( + + + +
+ + + {t('edit.title', { ns: 'lesson_category' })} + +
+
+ {t('edit.title', { ns: 'lesson_category' })} +
+
+ +
+
+ ); +} diff --git a/002_source/cms/src/app/dashboard/lesson_categories/lesson-categories-sample-data.tsx b/002_source/cms/src/app/dashboard/lesson_categories/lesson-categories-sample-data.tsx index 525606d..13aecfd 100644 --- a/002_source/cms/src/app/dashboard/lesson_categories/lesson-categories-sample-data.tsx +++ b/002_source/cms/src/app/dashboard/lesson_categories/lesson-categories-sample-data.tsx @@ -1,5 +1,5 @@ import { dayjs } from '@/lib/dayjs'; -import { LessonCategory } from '@/components/dashboard/lesson_category/type'; +import { LessonCategory } from '@/components/dashboard/lesson_category/types'; // import type { LessonCategory } from '@/components/dashboard/lesson_category/lesson-categories-table'; // import type { LessonCategory } from '@/components/dashboard/lesson_category/interfaces'; @@ -14,6 +14,7 @@ export const lessonCategoriesSampleData = [ quota: 50, status: 'active', createdAt: dayjs().subtract(1, 'hour').toDate(), + collectionId: '0000000001', cat_name: '', pos: 99, visible: 'visible', @@ -30,6 +31,7 @@ export const lessonCategoriesSampleData = [ quota: 100, status: 'active', createdAt: dayjs().subtract(3, 'hour').toDate(), + collectionId: '0000000001', cat_name: '', pos: 99, visible: 'visible', @@ -46,6 +48,7 @@ export const lessonCategoriesSampleData = [ quota: 10, status: 'blocked', createdAt: dayjs().subtract(1, 'hour').subtract(1, 'day').toDate(), + collectionId: '0000000001', cat_name: '', pos: 99, visible: 'visible', @@ -62,6 +65,7 @@ export const lessonCategoriesSampleData = [ quota: 0, status: 'pending', createdAt: dayjs().subtract(7, 'hour').subtract(1, 'day').toDate(), + collectionId: '0000000001', cat_name: '', pos: 99, visible: 'visible', @@ -78,6 +82,7 @@ export const lessonCategoriesSampleData = [ quota: 50, status: 'active', createdAt: dayjs().subtract(2, 'hour').subtract(2, 'day').toDate(), + collectionId: '0000000001', cat_name: '', pos: 99, visible: 'visible', diff --git a/002_source/cms/src/app/dashboard/lesson_categories/page.tsx b/002_source/cms/src/app/dashboard/lesson_categories/page.tsx index 89a7a75..283bb5b 100644 --- a/002_source/cms/src/app/dashboard/lesson_categories/page.tsx +++ b/002_source/cms/src/app/dashboard/lesson_categories/page.tsx @@ -25,7 +25,7 @@ import type { Filters } from '@/components/dashboard/lesson_category/lesson-cate import { LessonCategoriesPagination } from '@/components/dashboard/lesson_category/lesson-categories-pagination'; import { LessonCategoriesSelectionProvider } from '@/components/dashboard/lesson_category/lesson-categories-selection-context'; import { LessonCategoriesTable } from '@/components/dashboard/lesson_category/lesson-categories-table'; -import type { LessonCategory } from '@/components/dashboard/lesson_category/type'; +import type { LessonCategory } from '@/components/dashboard/lesson_category/types'; import FormLoading from '@/components/loading'; // import { lessonCategoriesSampleData } from './lesson-categories-sample-data'; @@ -44,7 +44,7 @@ interface PageProps { } export default function Page({ searchParams }: PageProps): React.JSX.Element { - const { t } = useTranslation(); + const { t } = useTranslation(['common']); const { email, phone, sortDir, spStatus } = searchParams; const router = useRouter(); @@ -96,9 +96,9 @@ export default function Page({ searchParams }: PageProps): React.JSX.Element { if (showError) return ( ); diff --git a/002_source/cms/src/app/dashboard/lesson_types/[type_id]/page.tsx b/002_source/cms/src/app/dashboard/lesson_types/[type_id]/page.tsx index 16d9646..20526a5 100644 --- a/002_source/cms/src/app/dashboard/lesson_types/[type_id]/page.tsx +++ b/002_source/cms/src/app/dashboard/lesson_types/[type_id]/page.tsx @@ -36,6 +36,7 @@ import { pb } from '@/lib/pb'; import { PropertyItem } from '@/components/core/property-item'; import { PropertyList } from '@/components/core/property-list'; import { toast } from '@/components/core/toaster'; +import ErrorDisplay from '@/components/dashboard/error'; // import { getLessonTypeById } from '@/components/dashboard/lesson_type/http-actions'; import { LessonTypeDefaultValue, type LessonType } from '@/components/dashboard/lesson_type/ILessonType'; import { defaultLessonType } from '@/components/dashboard/lesson_type/interfaces'; @@ -43,14 +44,15 @@ import { Notifications } from '@/components/dashboard/lesson_type/notifications' import { Payments } from '@/components/dashboard/lesson_type/payments'; import type { Address } from '@/components/dashboard/lesson_type/shipping-address'; import { ShippingAddress } from '@/components/dashboard/lesson_type/shipping-address'; +import FormLoading from '@/components/loading'; export default function Page(): React.JSX.Element { - const { t } = useTranslation(); + const { t } = useTranslation(['common']); const router = useRouter(); - + // const { type_id: typeId } = useParams<{ type_id: string }>(); // - const [showLoading, setIsLoading] = React.useState(true); + const [showLoading, setShowLoading] = React.useState(true); const [showError, setShowError] = React.useState(false); // const [showLessonType, setShowLessonType] = React.useState(LessonTypeDefaultValue); @@ -63,18 +65,31 @@ export default function Page(): React.JSX.Element { if (typeId) { pb.collection('LessonsTypes') .getOne(typeId) - .then((lessonType: RecordModel) => { - setShowLessonType({ ...defaultLessonType, ...lessonType }); - setIsLoading(false); + .then((model: RecordModel) => { + setShowLessonType({ ...defaultLessonType, ...model }); }) .catch((err) => { logger.error(err); toast(t('dashboard.lessonTypes.list.error')); + + setShowError(true); + }) + .finally(() => { + setShowLoading(false); }); } }, [typeId]); - if (showLoading) return
{t('common.loading')}
; + if (showLoading) return ; + + if (showError) + return ( + + ); return ( - {t('Lesson Types')} + {t('list.title', { ns: 'lesson_type' })} - MV + empty
@@ -145,7 +160,7 @@ export default function Page(): React.JSX.Element { } - title="Basic details" + title={t('basic-details', { ns: 'lesson_type' })} /> } @@ -195,7 +210,7 @@ export default function Page(): React.JSX.Element { } - title="Security" + title={t('security', { ns: 'lesson_type' })} /> @@ -268,7 +283,7 @@ export default function Page(): React.JSX.Element { } - title="Billing details" + title={t('billing-details', { ns: 'lesson_type' })} /> @@ -303,7 +318,7 @@ export default function Page(): React.JSX.Element { } - title="Shipping addresses" + title={t('shipping-addresses', { ns: 'lesson_type' })} /> diff --git a/002_source/cms/src/app/dashboard/lesson_types/page.tsx b/002_source/cms/src/app/dashboard/lesson_types/page.tsx index eb9a449..8b1df75 100644 --- a/002_source/cms/src/app/dashboard/lesson_types/page.tsx +++ b/002_source/cms/src/app/dashboard/lesson_types/page.tsx @@ -17,6 +17,7 @@ import { paths } from '@/paths'; import { logger } from '@/lib/default-logger'; import { pb } from '@/lib/pb'; import { toast } from '@/components/core/toaster'; +import ErrorDisplay from '@/components/dashboard/error'; import type { LessonType } from '@/components/dashboard/lesson_type/ILessonType'; import { emptyLessonType, safeAssignment } from '@/components/dashboard/lesson_type/interfaces'; import { LessonTypesFilters } from '@/components/dashboard/lesson_type/lesson-types-filters'; @@ -50,6 +51,8 @@ export default function Page({ searchParams }: PageProps): React.JSX.Element { // const [isLoadingAddPage, setIsLoadingAddPage] = React.useState(false); + const [showLoading, setShowLoading] = React.useState(true); + const [showError, setShowError] = React.useState(false); const [lessonTypesData, setLessonTypesData] = React.useState([]); // const [recordModel, setRecordModel] = React.useState([]); const sortedLessonTypes = applySort(lessonTypesData, sortDir); @@ -86,6 +89,11 @@ export default function Page({ searchParams }: PageProps): React.JSX.Element { .catch((err) => { logger.error(err); toast(t('dashboard.lessonTypes.list.error')); + + setShowError(true); + }) + .finally(() => { + setShowLoading(false); }); }; @@ -93,7 +101,12 @@ export default function Page({ searchParams }: PageProps): React.JSX.Element { reloadRows(); }, []); - if (lessonTypesData.length < 1) return ; + if (showLoading) return ; + + if (showError) + return ( + + ); return ( void): ColumnDef[] { return [ @@ -43,7 +43,10 @@ function columns(handleDeleteClick: (testId: string) => void): ColumnDef - + {' '}
@@ -72,9 +75,6 @@ function columns(handleDeleteClick: (testId: string) => void): ColumnDef { // eslint-disable-next-line react-hooks/rules-of-hooks diff --git a/002_source/cms/src/components/dashboard/lesson_category/lesson-category-create-form.tsx b/002_source/cms/src/components/dashboard/lesson_category/lesson-category-create-form.tsx index 17b53c4..84073ff 100644 --- a/002_source/cms/src/components/dashboard/lesson_category/lesson-category-create-form.tsx +++ b/002_source/cms/src/components/dashboard/lesson_category/lesson-category-create-form.tsx @@ -3,8 +3,10 @@ import * as React from 'react'; import RouterLink from 'next/link'; import { useRouter } from 'next/navigation'; +import { COL_LESSON_CATEGORIES, NS_LESSON_CATEGORY } from '@/constants'; import { zodResolver } from '@hookform/resolvers/zod'; -import { Avatar } from '@mui/material'; +import { LoadingButton } from '@mui/lab'; +import { Avatar, Divider, MenuItem } from '@mui/material'; // import Avatar from '@mui/material/Avatar'; import Box from '@mui/material/Box'; import Button from '@mui/material/Button'; @@ -12,7 +14,6 @@ import Card from '@mui/material/Card'; import CardActions from '@mui/material/CardActions'; import CardContent from '@mui/material/CardContent'; import Checkbox from '@mui/material/Checkbox'; -import Divider from '@mui/material/Divider'; import FormControl from '@mui/material/FormControl'; import FormControlLabel from '@mui/material/FormControlLabel'; import FormHelperText from '@mui/material/FormHelperText'; @@ -25,11 +26,13 @@ import Grid from '@mui/material/Unstable_Grid2'; import { Camera as CameraIcon } from '@phosphor-icons/react/dist/ssr/Camera'; // import axios from 'axios'; import { Controller, useForm } from 'react-hook-form'; +import { useTranslation } from 'react-i18next'; import { z as zod } from 'zod'; import { paths } from '@/paths'; import { logger } from '@/lib/default-logger'; import { Option } from '@/components/core/option'; +import { TextEditor } from '@/components/core/text-editor/text-editor'; import { toast } from '@/components/core/toaster'; import { fileToBase64 } from './file-to-base64'; @@ -71,6 +74,11 @@ const defaultValues = { export function LessonCategoryCreateForm(): React.JSX.Element { const router = useRouter(); + const { t } = useTranslation(['common', 'lesson_category']); + + const NS_DEFAULT = { ns: 'lesson_category' }; + + const [isCreating, setIsCreating] = React.useState(false); const { control, @@ -81,7 +89,8 @@ export function LessonCategoryCreateForm(): React.JSX.Element { } = useForm({ defaultValues, resolver: zodResolver(schema) }); const onSubmit = React.useCallback( - async (_: Values): Promise => { + async (values: Values): Promise => { + setIsCreating(true); try { // Make API request toast.success('Customer updated'); @@ -115,19 +124,20 @@ export function LessonCategoryCreateForm(): React.JSX.Element { } spacing={4}> - Account information + {t('create.typeInformation', NS_DEFAULT)} - Avatar - Min 400x400px, PNG or JPEG + {t('create.avatar', NS_DEFAULT)} + {t('create.avatarRequirements', NS_DEFAULT)} @@ -164,7 +174,7 @@ export function LessonCategoryCreateForm(): React.JSX.Element { name="name" render={({ field }) => ( - Name + {t('create.name', NS_DEFAULT)} {errors.name ? {errors.name.message} : null} @@ -213,25 +223,21 @@ export function LessonCategoryCreateForm(): React.JSX.Element { - Billing information + {t('create.detail-information', NS_DEFAULT)} ( - - Country - - {errors.billingAddress?.country ? ( - {errors.billingAddress?.country?.message} - ) : null} - + + + {t('create.description', NS_DEFAULT)} + + + + + )} /> @@ -240,134 +246,14 @@ export function LessonCategoryCreateForm(): React.JSX.Element { control={control} name="billingAddress.state" render={({ field }) => ( - - State - - {errors.billingAddress?.state ? ( - {errors.billingAddress?.state?.message} - ) : null} - - )} - /> - - - ( - - City - - {errors.billingAddress?.city ? ( - {errors.billingAddress?.city?.message} - ) : null} - - )} - /> - - - ( - - Zip code - - {errors.billingAddress?.zipCode ? ( - {errors.billingAddress?.zipCode?.message} - ) : null} - - )} - /> - - - ( - - Address - - {errors.billingAddress?.line1 ? ( - {errors.billingAddress?.line1?.message} - ) : null} - - )} - /> - - - ( - - Tax ID - - {errors.taxId ? {errors.taxId.message} : null} - - )} - /> - - - - - Shipping information - } label="Same as billing address" /> - - - Additional information - - - ( - - Timezone - - {errors.timezone ? {errors.timezone.message} : null} - - )} - /> - - - ( - - Language - - {errors.language ? {errors.language.message} : null} - - )} - /> - - - ( - - Currency - - {errors.currency ? {errors.currency.message} : null} - + + + {t('create.remarks', NS_DEFAULT)} + + + + + )} /> @@ -377,11 +263,12 @@ export function LessonCategoryCreateForm(): React.JSX.Element { - + + + {t('create.createButton', NS_DEFAULT)} + diff --git a/002_source/cms/src/components/dashboard/lesson_category/lesson-category-edit-form copy 2.tsx b/002_source/cms/src/components/dashboard/lesson_category/lesson-category-edit-form copy 2.tsx new file mode 100644 index 0000000..e4aa1d5 --- /dev/null +++ b/002_source/cms/src/components/dashboard/lesson_category/lesson-category-edit-form copy 2.tsx @@ -0,0 +1,334 @@ +'use client'; + +import * as React from 'react'; +import RouterLink from 'next/link'; +import { useParams, useRouter } from 'next/navigation'; +import { COL_LESSON_CATEGORIES, NS_LESSON_CATEGORY } from '@/constants'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { LoadingButton } from '@mui/lab'; +import { Avatar, Divider, MenuItem } from '@mui/material'; +// import Avatar from '@mui/material/Avatar'; +import Box from '@mui/material/Box'; +import Button from '@mui/material/Button'; +import Card from '@mui/material/Card'; +import CardActions from '@mui/material/CardActions'; +import CardContent from '@mui/material/CardContent'; +// import Checkbox from '@mui/material/Checkbox'; + +import FormControl from '@mui/material/FormControl'; +// import FormControlLabel from '@mui/material/FormControlLabel'; +import FormHelperText from '@mui/material/FormHelperText'; +import InputLabel from '@mui/material/InputLabel'; +import OutlinedInput from '@mui/material/OutlinedInput'; +import Select from '@mui/material/Select'; +import Stack from '@mui/material/Stack'; +import Typography from '@mui/material/Typography'; +import Grid from '@mui/material/Unstable_Grid2'; +import { Camera as CameraIcon } from '@phosphor-icons/react/dist/ssr/Camera'; +import type { RecordModel } from 'pocketbase'; +import { Controller, useForm } from 'react-hook-form'; +import { useTranslation } from 'react-i18next'; +import { z as zod } from 'zod'; + +import { paths } from '@/paths'; +import { logger } from '@/lib/default-logger'; +import { pb } from '@/lib/pb'; +import { Option } from '@/components/core/option'; +import { TextEditor } from '@/components/core/text-editor/text-editor'; +import { toast } from '@/components/core/toaster'; +import FormLoading from '@/components/loading'; + +import ErrorDisplay from '../error'; +import { defaultLessonCategory } from './_constants'; +import { fileToBase64 } from './file-to-base64'; +import { LessonCategory, EditFormProps } from './types'; + +const schema = zod.object({ + cat_name: zod.string().min(1, 'Name is required').max(255), + type: zod.string().min(1, 'Name is required').max(255), + pos: zod.number().min(1, 'Phone is required').max(15), + visible: zod.string().max(255), + description: zod.string().optional(), + remarks: zod.string().optional(), +}); + +type Values = zod.infer; + +const defaultValues = { + cat_name: '', + type: '', + pos: 1, + visible: 'visible', +} satisfies Values; + +export function LessonCategoryEditForm(): React.JSX.Element { + const router = useRouter(); + const { t } = useTranslation(['common', 'lesson_category']); + + const NS_DEFAULT = { ns: 'lesson_category' }; + const { cat_id: catId } = useParams<{ cat_id: string }>(); + // + const [isUpdating, setIsUpdating] = React.useState(false); + const [showLoading, setShowLoading] = React.useState(false); + const [showError, setShowError] = React.useState(false); + + const { + control, + handleSubmit, + formState: { errors }, + setValue, + reset, + watch, + } = useForm({ defaultValues, resolver: zodResolver(schema) }); + + const onSubmit = React.useCallback(async (values: Values): Promise => { + // setIsUpdating(true); + // const tempUpdate: LessonCategoryEditFormProps = { + // name: values.cat_name, + // type: values.type, + // pos: values.pos, + // visible: values.visible ? 'visible' : 'hidden', + // }; + + + // pb.collection(COL_LESSON_CATEGORIES) + // .update(catId, tempUpdate) + // .then((res) => { + // logger.debug(res); + // toast.success(t('update.success', NS_DEFAULT)); + // setIsUpdating(false); + // router.push(paths.dashboard.lesson_categories.list); + // }) + // .catch((err) => { + // logger.error(err); + // toast.error('Something went wrong!'); + // }) + // .finally(() => { + // // + // setIsUpdating(false); + // }); + }, []); + + const avatarInputRef = React.useRef(null); + // const avatar = watch('avatar'); + + const handleAvatarChange = React.useCallback( + async (event: React.ChangeEvent) => { + const file = event.target.files?.[0]; + + if (file) { + const url = await fileToBase64(file); + // setValue('avatar', url); + } + }, + [setValue] + ); + + const [textDescription, setTextDescription] = React.useState('loading'); + const handleLoad = React.useCallback( + (id: string) => { + setShowLoading(true); + pb.collection(COL_LESSON_CATEGORIES) + .getOne(id) + .then((model: RecordModel) => { + const temp: LessonCategory = { ...defaultLessonCategory, ...model }; + reset(temp); + setTextDescription(temp.description); + }) + .catch((err) => { + logger.error(err); + toast(t('list.error', NS_DEFAULT)); + }) + .finally(() => { + setShowLoading(false); + }); + }, + // eslint-disable-next-line react-hooks/exhaustive-deps + [catId] + ); + + React.useEffect(() => { + handleLoad(catId); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [catId]); + + if (showLoading) return ; + if (showError) + return ( + + ); + + return ( +
+ + + } spacing={4}> + + {t('edit.basic-info', NS_DEFAULT)} + + + + + {/* + + // TODO: resume me + + + */} + + + {t('edit.avatar', NS_DEFAULT)} + {t('edit.avatarRequirements', NS_DEFAULT)} + + + + + + + ( + + {t('edit.name', NS_DEFAULT)} + + {errors.cat_name ? {errors.cat_name.message} : null} + + )} + /> + + + + ( + + {t('edit.position', NS_DEFAULT)} + { + field.onChange(parseInt(e.target.value)); + }} + type="number" + /> + + {errors.pos ? {errors.pos.message} : null} + + )} + /> + + + ( + + {t('edit.visible', NS_DEFAULT)} + + + {errors.visible ? {errors.visible.message} : null} + + )} + /> + + + + + + {t('create.detail-information', NS_DEFAULT)} + + + { + console.log({ field }); + return ( + + + {t('create.description', NS_DEFAULT)} + + + {JSON.stringify({ field })} + { + console.log(editor.getHTML()); + field.onChange({ target: { value: editor.getHTML() } }); + }} + placeholder={t('edit.write-something', NS_DEFAULT)} + /> + + + ); + }} + /> + + + ( + + + {t('create.remarks', NS_DEFAULT)} + + + + + + )} + /> + + + + + + + + + + {t('edit.updateButton', NS_DEFAULT)} + + + +
+ ); +} diff --git a/002_source/cms/src/components/dashboard/lesson_category/lesson-category-edit-form.tsx b/002_source/cms/src/components/dashboard/lesson_category/lesson-category-edit-form.tsx new file mode 100644 index 0000000..ac6cde9 --- /dev/null +++ b/002_source/cms/src/components/dashboard/lesson_category/lesson-category-edit-form.tsx @@ -0,0 +1,352 @@ +'use client'; + +import * as React from 'react'; +import RouterLink from 'next/link'; +import { useParams, useRouter } from 'next/navigation'; +import { COL_LESSON_CATEGORIES, NS_LESSON_CATEGORY } from '@/constants'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { LoadingButton } from '@mui/lab'; +import { Avatar, Divider, MenuItem } from '@mui/material'; +// import Avatar from '@mui/material/Avatar'; +import Box from '@mui/material/Box'; +import Button from '@mui/material/Button'; +import Card from '@mui/material/Card'; +import CardActions from '@mui/material/CardActions'; +import CardContent from '@mui/material/CardContent'; +// import Checkbox from '@mui/material/Checkbox'; + +import FormControl from '@mui/material/FormControl'; +// import FormControlLabel from '@mui/material/FormControlLabel'; +import FormHelperText from '@mui/material/FormHelperText'; +import InputLabel from '@mui/material/InputLabel'; +import OutlinedInput from '@mui/material/OutlinedInput'; +import Select from '@mui/material/Select'; +import Stack from '@mui/material/Stack'; +import Typography from '@mui/material/Typography'; +import Grid from '@mui/material/Unstable_Grid2'; +import { Camera as CameraIcon } from '@phosphor-icons/react/dist/ssr/Camera'; +import type { RecordModel } from 'pocketbase'; +import { Controller, useForm } from 'react-hook-form'; +import { useTranslation } from 'react-i18next'; +import { z as zod } from 'zod'; + +import { paths } from '@/paths'; +import { dayjs } from '@/lib/dayjs'; +import { logger } from '@/lib/default-logger'; +import { pb } from '@/lib/pb'; +import { Option } from '@/components/core/option'; +import { TextEditor } from '@/components/core/text-editor/text-editor'; +import { toast } from '@/components/core/toaster'; +import FormLoading from '@/components/loading'; + +import ErrorDisplay from '../error'; +import { defaultLessonCategory } from './_constants'; +import { fileToBase64 } from './file-to-base64'; +import { EditFormProps, LessonCategory } from './types'; + +// TODO: review this +const schema = zod.object({ + cat_name: zod.string().min(1, 'name-is-required').max(255), + // + pos: zod.number().min(1, 'Phone is required').max(99), + visible: zod.string().max(255), + // + description: zod.string().optional(), + remarks: zod.string().optional(), +}); + +type Values = zod.infer; + +const defaultValues = { + cat_name: '', + // cat_image: undefined, + pos: 0, + visible: 'hidden', + // lesson_id: 'default-lesson-id', + description: 'default-description', + remarks: 'default-remarks', + // +} satisfies Values; + +export function LessonCategoryEditForm(): React.JSX.Element { + const router = useRouter(); + const { t } = useTranslation(['common', 'lesson_category']); + + const NS_DEFAULT = { ns: 'lesson_category' }; + + const { cat_id: catId } = useParams<{ cat_id: string }>(); + // + const [isUpdating, setIsUpdating] = React.useState(false); + const [showLoading, setShowLoading] = React.useState(false); + const [showError, setShowError] = React.useState(false); + + const { + control, + handleSubmit, + formState: { errors }, + setValue, + reset, + watch, + } = useForm({ defaultValues, resolver: zodResolver(schema) }); + + const onSubmit = React.useCallback(async (values: Values): Promise => { + setIsUpdating(true); + const tempUpdate: EditFormProps = { + cat_name: values.cat_name, + pos: values.pos, + visible: values.visible, + description: values.description, + remarks: values.remarks, + }; + + pb.collection(COL_LESSON_CATEGORIES) + .update(catId, tempUpdate) + .then((res) => { + logger.debug(res); + toast.success(t('update.success', NS_DEFAULT)); + router.push(paths.dashboard.lesson_categories.list); + }) + .catch((err) => { + logger.error(err); + toast.error('Something went wrong!'); + }) + .finally(() => { + // + setIsUpdating(false); + }); + }, []); + + const avatarInputRef = React.useRef(null); + // const avatar = watch('avatar'); + + const handleAvatarChange = React.useCallback( + async (event: React.ChangeEvent) => { + const file = event.target.files?.[0]; + + if (file) { + const url = await fileToBase64(file); + // setValue('avatar', url); + } + }, + [setValue] + ); + + const [textDescription, setTextDescription] = React.useState('loading'); + const [textRemarks, setTextRemarks] = React.useState('loading'); + const handleLoad = React.useCallback( + (id: string) => { + setShowLoading(true); + pb.collection(COL_LESSON_CATEGORIES) + .getOne(id) + .then((model: RecordModel) => { + const temp: LessonCategory = { ...defaultLessonCategory, ...model }; + reset(temp); + setTextDescription(temp.description); + setTextRemarks(temp.remarks); + }) + .catch((err) => { + logger.error(err); + toast(t('list.error', NS_DEFAULT)); + }) + .finally(() => { + setShowLoading(false); + }); + }, + // eslint-disable-next-line react-hooks/exhaustive-deps + [catId] + ); + + React.useEffect(() => { + handleLoad(catId); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [catId]); + + if (showLoading) return ; + if (showError) + return ( + + ); + + return ( +
+ + + } spacing={4}> + + {t('edit.basic-info', NS_DEFAULT)} + + + + + {/* + + // TODO: resume me + + + */} + + + {t('edit.avatar', NS_DEFAULT)} + {t('edit.avatarRequirements', NS_DEFAULT)} + + + + + + + ( + + {t('edit.name', NS_DEFAULT)} + + {errors.cat_name ? {errors.cat_name.message} : null} + + )} + /> + + + + ( + + {t('edit.position', NS_DEFAULT)} + { + field.onChange(parseInt(e.target.value)); + }} + type="number" + /> + + {errors.pos ? {errors.pos.message} : null} + + )} + /> + + + ( + + {t('edit.visible', NS_DEFAULT)} + + + {errors.visible ? {errors.visible.message} : null} + + )} + /> + + + + + + {t('create.detail-information', NS_DEFAULT)} + + + { + return ( + + + {t('create.description', NS_DEFAULT)} + + + { + field.onChange({ target: { value: editor.getHTML() } }); + }} + placeholder={t('edit.write-something', NS_DEFAULT)} + /> + + + ); + }} + /> + + + ( + + + {t('create.remarks', NS_DEFAULT)} + + + { + field.onChange({ target: { value: editor.getText() } }); + }} + hideToolbar={true} + placeholder={t('edit.write-something', NS_DEFAULT)} + /> + + + )} + /> + + + + + + + + + + {t('edit.updateButton', NS_DEFAULT)} + + + +
+ ); +} diff --git a/002_source/cms/src/components/dashboard/lesson_category/type.d.ts b/002_source/cms/src/components/dashboard/lesson_category/types.d.ts similarity index 75% rename from 002_source/cms/src/components/dashboard/lesson_category/type.d.ts rename to 002_source/cms/src/components/dashboard/lesson_category/types.d.ts index 120edf1..5212809 100644 --- a/002_source/cms/src/components/dashboard/lesson_category/type.d.ts +++ b/002_source/cms/src/components/dashboard/lesson_category/types.d.ts @@ -10,6 +10,7 @@ export interface LessonCategory { lesson_id: string; description: string; remarks: string; + collectionId: string; // name: string; avatar: string; @@ -26,3 +27,11 @@ export interface CreateForm { pos: number; visible: string; } + +export interface EditFormProps { + cat_name: string; + pos: number; + visible: string; + description?: string; + remarks?: string; +} diff --git a/002_source/cms/src/components/dashboard/lesson_type/lesson-type-create-form.tsx b/002_source/cms/src/components/dashboard/lesson_type/lesson-type-create-form.tsx index 2b0e518..f917d98 100644 --- a/002_source/cms/src/components/dashboard/lesson_type/lesson-type-create-form.tsx +++ b/002_source/cms/src/components/dashboard/lesson_type/lesson-type-create-form.tsx @@ -60,6 +60,7 @@ const defaultValues = { export function LessonTypeCreateForm(): React.JSX.Element { const router = useRouter(); const { t } = useTranslation(); + const [isCreating, setIsCreating] = React.useState(false); const { @@ -79,7 +80,6 @@ export function LessonTypeCreateForm(): React.JSX.Element { pb.collection(COL_LESSON_TYPES) .create(data) .then((res) => { - console.log(res); logger.debug(res); toast.success(t('dashboard.lessonTypes.update.success')); setIsCreating(false); @@ -90,23 +90,6 @@ export function LessonTypeCreateForm(): React.JSX.Element { toast.error('Something went wrong!'); setIsCreating(false); }); - - // const tempCreate: LessonTypeCreateForm = LessonTypeCreateFormDefault; - // tempCreate.name = values.name; - // tempCreate.type = values.type; - // tempCreate.pos = 1; - // tempCreate.visible = 'visible'; - - // createLessonType(tempCreate) - // .then((res) => { - // router.push(paths.dashboard.lesson_types.list); - // toast.success(t('dashboard.lessonTypes.create.success')); - // }) - // .catch((err) => { - // logger.error(err); - // toast.error(t('dashboard.lessonTypes.create.error')); - // setIsCreating(false); - // }); }, [router] ); diff --git a/002_source/cms/src/components/dashboard/lesson_type/lesson-type-edit-form.tsx b/002_source/cms/src/components/dashboard/lesson_type/lesson-type-edit-form.tsx index ba574d2..80904d3 100644 --- a/002_source/cms/src/components/dashboard/lesson_type/lesson-type-edit-form.tsx +++ b/002_source/cms/src/components/dashboard/lesson_type/lesson-type-edit-form.tsx @@ -6,7 +6,7 @@ import { useParams, useRouter } from 'next/navigation'; import { COL_LESSON_TYPES } from '@/constants'; import { zodResolver } from '@hookform/resolvers/zod'; import { LoadingButton } from '@mui/lab'; -import { MenuItem } from '@mui/material'; +import { Avatar, MenuItem } from '@mui/material'; // import Avatar from '@mui/material/Avatar'; import Box from '@mui/material/Box'; import Button from '@mui/material/Button'; @@ -35,6 +35,7 @@ import { logger } from '@/lib/default-logger'; import { pb } from '@/lib/pb'; // import { Option } from '@/components/core/option'; import { toast } from '@/components/core/toaster'; +import FormLoading from '@/components/loading'; // import { getLessonTypeById, updateLessonType } from './http-actions'; // TODO: this may be wrong @@ -74,8 +75,9 @@ export function LessonTypeEditForm(): React.JSX.Element { const router = useRouter(); const { t } = useTranslation(); const { typeId } = useParams<{ typeId: string }>(); + // const [isUpdating, setIsUpdating] = React.useState(false); - const [isLoading, setIsLoading] = React.useState(false); + const [showLoading, setShowLoading] = React.useState(false); const { control, @@ -83,7 +85,7 @@ export function LessonTypeEditForm(): React.JSX.Element { formState: { errors }, setValue, reset, - // watch, + watch, } = useForm({ defaultValues, resolver: zodResolver(schema) }); const onSubmit = React.useCallback(async (values: Values): Promise => { @@ -129,10 +131,10 @@ export function LessonTypeEditForm(): React.JSX.Element { (id: string) => { pb.collection(COL_LESSON_TYPES) .getOne(id) - .then((lessonType: RecordModel) => { - reset({ ...defaultLessonType, ...lessonType }); + .then((model: RecordModel) => { + reset({ ...defaultLessonType, ...model }); - setIsLoading(false); + setShowLoading(false); }) .catch((err) => { logger.error(err); @@ -148,7 +150,7 @@ export function LessonTypeEditForm(): React.JSX.Element { // eslint-disable-next-line react-hooks/exhaustive-deps }, [typeId]); - if (isLoading) return <>loading; + if (showLoading) return ; return (
diff --git a/002_source/cms/src/constants.ts b/002_source/cms/src/constants.ts index 4f8cbb9..0c7fc45 100644 --- a/002_source/cms/src/constants.ts +++ b/002_source/cms/src/constants.ts @@ -2,5 +2,6 @@ const COL_LESSON_TYPES = 'LessonsTypes'; const COL_LESSON_CATEGORIES = 'LessonsCategories'; const NO_VALUE = 'NO_VALUE'; const NO_NUM = -Infinity; +const NS_LESSON_CATEGORY = 'lesson_category'; -export { COL_LESSON_TYPES, NO_VALUE, NO_NUM, COL_LESSON_CATEGORIES }; +export { COL_LESSON_TYPES, NO_VALUE, NO_NUM, COL_LESSON_CATEGORIES, NS_LESSON_CATEGORY }; diff --git a/002_source/cms/src/lib/i18n.ts b/002_source/cms/src/lib/i18n.ts index d7626c1..617714a 100644 --- a/002_source/cms/src/lib/i18n.ts +++ b/002_source/cms/src/lib/i18n.ts @@ -7,7 +7,6 @@ import { initReactI18next } from 'react-i18next'; import { logger } from '@/lib/default-logger'; -// // . // .use(detector) // use(detector); diff --git a/002_source/cms/tsconfig.json b/002_source/cms/tsconfig.json index 9927274..cc03d59 100644 --- a/002_source/cms/tsconfig.json +++ b/002_source/cms/tsconfig.json @@ -41,8 +41,8 @@ "**/*.bug", "**/*.del", "**/*.draft", - "**/*copy.*", - "**/*copy*.*" + "**/* copy *.tsx", + "**/* copy.tsx" // ] }