@appcorp/fusion-storybook 0.2.86 → 0.2.89
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/base-modules/admission/filter.js +3 -3
- package/base-modules/admission/form.js +1 -1
- package/base-modules/admission/more-actions.js +288 -2
- package/base-modules/admission/view.js +1 -1
- package/base-modules/attendance/form.js +3 -3
- package/base-modules/campus/form.js +2 -1
- package/base-modules/campus/validate.d.ts +13 -5
- package/base-modules/campus/validate.js +24 -19
- package/base-modules/class/form.js +2 -1
- package/base-modules/class/more-actions.js +2 -2
- package/base-modules/class/validate.d.ts +10 -5
- package/base-modules/class/validate.js +18 -16
- package/base-modules/class/view.js +2 -2
- package/base-modules/course/form.js +2 -1
- package/base-modules/course/validate.d.ts +7 -5
- package/base-modules/course/validate.js +12 -13
- package/base-modules/course/view.js +3 -3
- package/base-modules/discount-code/constants.d.ts +1 -1
- package/base-modules/discount-code/constants.js +1 -1
- package/base-modules/discount-code/form.js +2 -1
- package/base-modules/discount-code/more-actions.js +1 -1
- package/base-modules/discount-code/page.d.ts +10 -10
- package/base-modules/discount-code/page.js +31 -31
- package/base-modules/discount-code/validate.d.ts +5 -0
- package/base-modules/discount-code/validate.js +8 -3
- package/base-modules/discount-code/view.js +2 -2
- package/base-modules/enrollment/form.js +3 -2
- package/base-modules/enrollment/more-actions.js +5 -5
- package/base-modules/enrollment/page.d.ts +10 -10
- package/base-modules/enrollment/page.js +31 -31
- package/base-modules/enrollment/validate.d.ts +6 -0
- package/base-modules/enrollment/validate.js +13 -5
- package/base-modules/enrollment/view.js +2 -2
- package/base-modules/expense/filter.js +1 -1
- package/base-modules/expense/form.js +3 -3
- package/base-modules/expense/more-actions.js +6 -6
- package/base-modules/expense/page.d.ts +11 -11
- package/base-modules/expense/page.js +34 -34
- package/base-modules/expense/validate.d.ts +8 -0
- package/base-modules/expense/validate.js +13 -5
- package/base-modules/expense/view.js +2 -2
- package/base-modules/family/context.js +1 -1
- package/base-modules/family/form.js +1 -1
- package/base-modules/family/more-actions.js +2 -2
- package/base-modules/family/page.d.ts +10 -10
- package/base-modules/family/page.js +31 -31
- package/base-modules/family/validate.d.ts +4 -0
- package/base-modules/family/validate.js +8 -1
- package/base-modules/family/view.js +1 -1
- package/base-modules/family-member/context.js +1 -1
- package/base-modules/family-member/form.js +2 -1
- package/base-modules/family-member/more-actions.js +5 -5
- package/base-modules/family-member/page.d.ts +40 -13
- package/base-modules/family-member/page.js +34 -34
- package/base-modules/family-member/validate.d.ts +8 -0
- package/base-modules/family-member/validate.js +20 -5
- package/base-modules/family-member/view.js +3 -3
- package/base-modules/fee-structure/form.js +5 -4
- package/base-modules/fee-structure/more-actions.js +2 -2
- package/base-modules/fee-structure/page.d.ts +11 -11
- package/base-modules/fee-structure/page.js +34 -34
- package/base-modules/fee-structure/validate.d.ts +6 -0
- package/base-modules/fee-structure/validate.js +12 -3
- package/base-modules/fee-structure/view.js +3 -3
- package/base-modules/rbac/assign-permissions.js +9 -5
- package/base-modules/rbac/filter.js +5 -3
- package/base-modules/rbac/form.js +2 -1
- package/base-modules/rbac/more-actions.d.ts +0 -5
- package/base-modules/rbac/more-actions.js +3 -1
- package/base-modules/rbac/validate.d.ts +3 -0
- package/base-modules/rbac/validate.js +7 -1
- package/base-modules/rbac/view.js +7 -5
- package/base-modules/school/drawer.js +3 -1
- package/base-modules/school/form.js +2 -1
- package/base-modules/school/validate.d.ts +8 -0
- package/base-modules/school/validate.js +17 -6
- package/base-modules/school/view.js +2 -2
- package/base-modules/section/filter.js +1 -1
- package/base-modules/section/form.js +3 -2
- package/base-modules/section/page.d.ts +8 -8
- package/base-modules/section/page.js +25 -25
- package/base-modules/section/validate.d.ts +7 -0
- package/base-modules/section/validate.js +15 -5
- package/base-modules/section/view.js +3 -3
- package/base-modules/student-fee/filter.js +1 -1
- package/base-modules/student-fee/form.js +3 -2
- package/base-modules/student-fee/more-actions.js +11 -10
- package/base-modules/student-fee/page.d.ts +13 -13
- package/base-modules/student-fee/page.js +40 -40
- package/base-modules/student-fee/validate.d.ts +11 -3
- package/base-modules/student-fee/validate.js +20 -12
- package/base-modules/student-fee/view.js +4 -4
- package/base-modules/student-profile/context/use-student-profile-module.js +2 -2
- package/base-modules/student-profile/filter.js +2 -2
- package/base-modules/student-profile/form.js +6 -5
- package/base-modules/student-profile/page.d.ts +10 -10
- package/base-modules/student-profile/page.js +31 -31
- package/base-modules/student-profile/validate.d.ts +8 -2
- package/base-modules/student-profile/validate.js +13 -10
- package/base-modules/student-profile/view.js +2 -2
- package/base-modules/subject/filter.js +1 -1
- package/base-modules/subject/form.js +2 -1
- package/base-modules/subject/more-actions.js +3 -3
- package/base-modules/subject/page.d.ts +9 -9
- package/base-modules/subject/page.js +28 -28
- package/base-modules/subject/validate.d.ts +12 -1
- package/base-modules/subject/validate.js +24 -10
- package/base-modules/subject/view.js +3 -3
- package/base-modules/teacher/context.js +3 -3
- package/base-modules/teacher/filter.js +1 -1
- package/base-modules/teacher/form.js +9 -32
- package/base-modules/teacher/more-actions.js +2 -2
- package/base-modules/teacher/page.d.ts +10 -10
- package/base-modules/teacher/page.js +31 -31
- package/base-modules/teacher/validate.d.ts +5 -1
- package/base-modules/teacher/validate.js +10 -25
- package/base-modules/teacher/view.js +3 -3
- package/base-modules/user/filter.js +1 -1
- package/base-modules/user/form.js +3 -2
- package/base-modules/user/page.d.ts +9 -9
- package/base-modules/user/page.js +28 -28
- package/base-modules/user/validate.d.ts +8 -1
- package/base-modules/user/validate.js +16 -6
- package/base-modules/user/view.js +1 -1
- package/base-modules/workspace/context.js +3 -3
- package/base-modules/workspace/drawer.js +1 -1
- package/base-modules/workspace/filter.js +1 -1
- package/base-modules/workspace/form.js +2 -1
- package/base-modules/workspace/more-actions.js +1 -1
- package/base-modules/workspace/page.d.ts +1 -1
- package/base-modules/workspace/page.js +2 -2
- package/base-modules/workspace/validate.d.ts +4 -0
- package/base-modules/workspace/validate.js +6 -2
- package/base-modules/workspace/view.js +2 -2
- package/base-modules/workspace-user/context.js +6 -6
- package/base-modules/workspace-user/form.js +2 -1
- package/base-modules/workspace-user/page.d.ts +9 -9
- package/base-modules/workspace-user/page.js +28 -28
- package/base-modules/workspace-user/validate.d.ts +4 -5
- package/base-modules/workspace-user/validate.js +6 -10
- package/base-modules/workspace-user/view.js +1 -1
- package/constants.d.ts +5 -1
- package/constants.js +2 -0
- package/package.json +1 -1
- package/tsconfig.build.tsbuildinfo +1 -1
- package/utils/get-translated-error.d.ts +5 -0
- package/utils/get-translated-error.js +5 -0
|
@@ -55,20 +55,20 @@ const createComponentInstances = () => ({
|
|
|
55
55
|
moreActions: _jsx(TeacherMoreActions, {}),
|
|
56
56
|
view: _jsx(TeacherView, {}),
|
|
57
57
|
});
|
|
58
|
-
const createTeacherConfig = ({
|
|
58
|
+
const createTeacherConfig = ({ dispatch, drawerButtonCancel, drawerButtonSave, drawerFilterDescription, drawerFilterTitle, drawerFormDescription, drawerFormTitle, drawerMoreActionsDescription, drawerMoreActionsTitle, drawerViewDescription, drawerViewTitle, tableColumnHeaderActions, tableColumnHeaderEnabled, tableColumnHeaderId, tableColumnHeaderName, tableColumnHeaderPhone, tableColumnHeaderSpecialization, tableColumnHeaderTeacherCode, tableDescription, tableSearchPlaceholder, tableTitle, }) => {
|
|
59
59
|
const components = createComponentInstances();
|
|
60
60
|
return {
|
|
61
61
|
moduleName: "teacher",
|
|
62
62
|
tableColumns: [
|
|
63
|
-
{ label:
|
|
64
|
-
{ label:
|
|
65
|
-
{ label:
|
|
66
|
-
{ label:
|
|
67
|
-
{ label:
|
|
68
|
-
{ label:
|
|
69
|
-
{ label:
|
|
63
|
+
{ label: tableColumnHeaderId, width: "5%" },
|
|
64
|
+
{ label: tableColumnHeaderTeacherCode, width: "10%" },
|
|
65
|
+
{ label: tableColumnHeaderName, width: "30%" },
|
|
66
|
+
{ label: tableColumnHeaderPhone, width: "25%" },
|
|
67
|
+
{ label: tableColumnHeaderSpecialization, width: "20%" },
|
|
68
|
+
{ label: tableColumnHeaderEnabled, width: "5%" },
|
|
69
|
+
{ label: tableColumnHeaderActions, width: "5%" },
|
|
70
70
|
],
|
|
71
|
-
cancelLabel,
|
|
71
|
+
cancelLabel: drawerButtonCancel,
|
|
72
72
|
drawerFilterDescription,
|
|
73
73
|
drawerFilterTitle,
|
|
74
74
|
drawerFormDescription,
|
|
@@ -80,8 +80,8 @@ const createTeacherConfig = ({ cancelLabel, dispatch, drawerFilterDescription, d
|
|
|
80
80
|
filterContent: components.filter,
|
|
81
81
|
formContent: components.form,
|
|
82
82
|
moreActionsContent: components.moreActions,
|
|
83
|
-
saveLabel,
|
|
84
|
-
searchPlaceholder,
|
|
83
|
+
saveLabel: drawerButtonSave,
|
|
84
|
+
searchPlaceholder: tableSearchPlaceholder,
|
|
85
85
|
tableDescription,
|
|
86
86
|
tableTitle,
|
|
87
87
|
viewContent: components.view,
|
|
@@ -98,7 +98,8 @@ const TeacherPageInner = (props) => {
|
|
|
98
98
|
const context = useTeacherModule();
|
|
99
99
|
const teacherConfig = useMemo(() => createTeacherConfig({
|
|
100
100
|
dispatch: context.dispatch,
|
|
101
|
-
|
|
101
|
+
drawerButtonCancel: props.drawerButtonCancel,
|
|
102
|
+
drawerButtonSave: props.drawerButtonSave,
|
|
102
103
|
drawerFormTitle: props.drawerFormTitle,
|
|
103
104
|
drawerFormDescription: props.drawerFormDescription,
|
|
104
105
|
drawerViewTitle: props.drawerViewTitle,
|
|
@@ -107,20 +108,20 @@ const TeacherPageInner = (props) => {
|
|
|
107
108
|
drawerFilterDescription: props.drawerFilterDescription,
|
|
108
109
|
drawerMoreActionsTitle: props.drawerMoreActionsTitle,
|
|
109
110
|
drawerMoreActionsDescription: props.drawerMoreActionsDescription,
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
saveLabel: props.saveLabel,
|
|
118
|
-
searchPlaceholder: props.searchPlaceholder,
|
|
111
|
+
tableColumnHeaderActions: props.tableColumnHeaderActions,
|
|
112
|
+
tableColumnHeaderEnabled: props.tableColumnHeaderEnabled,
|
|
113
|
+
tableColumnHeaderId: props.tableColumnHeaderId,
|
|
114
|
+
tableColumnHeaderName: props.tableColumnHeaderName,
|
|
115
|
+
tableColumnHeaderPhone: props.tableColumnHeaderPhone,
|
|
116
|
+
tableColumnHeaderSpecialization: props.tableColumnHeaderSpecialization,
|
|
117
|
+
tableColumnHeaderTeacherCode: props.tableColumnHeaderTeacherCode,
|
|
119
118
|
tableDescription: props.tableDescription,
|
|
119
|
+
tableSearchPlaceholder: props.tableSearchPlaceholder,
|
|
120
120
|
tableTitle: props.tableTitle,
|
|
121
121
|
}), [
|
|
122
122
|
context.dispatch,
|
|
123
|
-
props.
|
|
123
|
+
props.drawerButtonCancel,
|
|
124
|
+
props.drawerButtonSave,
|
|
124
125
|
props.drawerFormTitle,
|
|
125
126
|
props.drawerFormDescription,
|
|
126
127
|
props.drawerViewTitle,
|
|
@@ -129,16 +130,15 @@ const TeacherPageInner = (props) => {
|
|
|
129
130
|
props.drawerFilterDescription,
|
|
130
131
|
props.drawerMoreActionsTitle,
|
|
131
132
|
props.drawerMoreActionsDescription,
|
|
132
|
-
props.
|
|
133
|
-
props.
|
|
134
|
-
props.
|
|
135
|
-
props.
|
|
136
|
-
props.
|
|
137
|
-
props.
|
|
138
|
-
props.
|
|
139
|
-
props.saveLabel,
|
|
140
|
-
props.searchPlaceholder,
|
|
133
|
+
props.tableColumnHeaderActions,
|
|
134
|
+
props.tableColumnHeaderEnabled,
|
|
135
|
+
props.tableColumnHeaderId,
|
|
136
|
+
props.tableColumnHeaderName,
|
|
137
|
+
props.tableColumnHeaderPhone,
|
|
138
|
+
props.tableColumnHeaderSpecialization,
|
|
139
|
+
props.tableColumnHeaderTeacherCode,
|
|
141
140
|
props.tableDescription,
|
|
141
|
+
props.tableSearchPlaceholder,
|
|
142
142
|
props.tableTitle,
|
|
143
143
|
]);
|
|
144
144
|
const hasPermission = resolveRbacPermissions({
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Teacher Validation Schema
|
|
3
3
|
*
|
|
4
|
-
* Zod validation schemas for teacher form data.
|
|
4
|
+
* Zod validation schemas for teacher form data with i18n-ready error keys.
|
|
5
5
|
*/
|
|
6
6
|
import { z } from "zod";
|
|
7
|
+
export declare const VALIDATION_KEYS: {
|
|
8
|
+
readonly firstName: "validationTeacherFirstNameRequired";
|
|
9
|
+
readonly lastName: "validationTeacherLastNameRequired";
|
|
10
|
+
};
|
|
7
11
|
export declare const teacherFormValidation: z.ZodObject<{
|
|
8
12
|
address: z.ZodNullable<z.ZodOptional<z.ZodString>>;
|
|
9
13
|
avatar: z.ZodNullable<z.ZodOptional<z.ZodString>>;
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Teacher Validation Schema
|
|
3
3
|
*
|
|
4
|
-
* Zod validation schemas for teacher form data.
|
|
4
|
+
* Zod validation schemas for teacher form data with i18n-ready error keys.
|
|
5
5
|
*/
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
// ============================================================================
|
|
8
|
+
// VALIDATION KEYS
|
|
9
|
+
// ============================================================================
|
|
10
|
+
export const VALIDATION_KEYS = {
|
|
11
|
+
firstName: "validationTeacherFirstNameRequired",
|
|
12
|
+
lastName: "validationTeacherLastNameRequired",
|
|
13
|
+
};
|
|
14
|
+
// ============================================================================
|
|
8
15
|
// VALIDATION SCHEMA
|
|
9
16
|
// ============================================================================
|
|
10
17
|
export const teacherFormValidation = z.object({
|
|
@@ -15,39 +22,17 @@ export const teacherFormValidation = z.object({
|
|
|
15
22
|
country: z.string().optional().nullable(),
|
|
16
23
|
dateOfBirth: z.string().optional().nullable(),
|
|
17
24
|
emergencyPhone: z.string().nullable().optional(),
|
|
18
|
-
// .superRefine((val, ctx) => {
|
|
19
|
-
// if (!val) return; // null, undefined, or empty string are OK
|
|
20
|
-
// if (
|
|
21
|
-
// !/^([+]?[\s0-9]+)?(\d{3}|[(]?[0-9]+[)]?)?([-]?[\s]?[0-9])+$/.test(val)
|
|
22
|
-
// ) {
|
|
23
|
-
// ctx.addIssue({
|
|
24
|
-
// code: z.ZodIssueCode.custom,
|
|
25
|
-
// message: "Invalid phone number format",
|
|
26
|
-
// });
|
|
27
|
-
// }
|
|
28
|
-
// }),
|
|
29
25
|
campusId: z.string().optional().nullable(),
|
|
30
26
|
experience: z.number().optional().nullable(),
|
|
31
|
-
firstName: z.string().min(1,
|
|
27
|
+
firstName: z.string().min(1, VALIDATION_KEYS.firstName),
|
|
32
28
|
gender: z
|
|
33
29
|
.preprocess((val) => (val === "" ? undefined : val), z
|
|
34
30
|
.enum(["MALE", "FEMALE", "OTHER", "PREFER_NOT_TO_SAY"])
|
|
35
31
|
.optional()
|
|
36
32
|
.nullable()),
|
|
37
33
|
joiningDate: z.string().optional(),
|
|
38
|
-
lastName: z.string().min(1,
|
|
34
|
+
lastName: z.string().min(1, VALIDATION_KEYS.lastName),
|
|
39
35
|
phone: z.string().nullable().optional(),
|
|
40
|
-
// .superRefine((val, ctx) => {
|
|
41
|
-
// if (!val) return; // null, undefined, or empty string are OK
|
|
42
|
-
// if (
|
|
43
|
-
// !/^([+]?[\s0-9]+)?(\d{3}|[(]?[0-9]+[)]?)?([-]?[\s]?[0-9])+$/.test(val)
|
|
44
|
-
// ) {
|
|
45
|
-
// ctx.addIssue({
|
|
46
|
-
// code: z.ZodIssueCode.custom,
|
|
47
|
-
// message: "Invalid phone number format",
|
|
48
|
-
// });
|
|
49
|
-
// }
|
|
50
|
-
// }),
|
|
51
36
|
postalCode: z.string().optional().nullable(),
|
|
52
37
|
qualification: z.string().optional().nullable(),
|
|
53
38
|
specialization: z.string().optional().nullable(),
|
|
@@ -22,8 +22,8 @@ export const TeacherView = () => {
|
|
|
22
22
|
const last = (lastName === null || lastName === void 0 ? void 0 : lastName.charAt(0)) || "";
|
|
23
23
|
return (first + last).toUpperCase() || "T";
|
|
24
24
|
};
|
|
25
|
-
return (_jsxs("div", { className: "space-y-4", children: [_jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(User, { className: "text-primary h-5 w-5" }), _jsx(CardTitle, { className: "text-lg", children: t("viewSectionBasicInformation") })] }), _jsx(CardDescription, { children: t("viewSectionTeachersPersonalDetails") })] }), _jsx(Separator, {}), _jsx(CardContent, { className: "pt-6", children: _jsxs("div", { className: "grid grid-cols-1 gap-6", children: [_jsxs("div", { className: "space-y-2", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("viewFieldProfilePicture") }), _jsxs(Avatar, { className: "h-20 w-20", children: [_jsx(AvatarImage, { src: avatar || undefined, alt: fullName }), _jsx(AvatarFallback, { className: "text-lg", children: getInitials() })] })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("viewFieldTeacherCode") }), _jsx("p", { className: "font-mono text-base", children: formatValue(teacherCode) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("viewFieldName") }), _jsx("p", { className: "text-base", children: fullName })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("
|
|
26
|
-
formatValue(emergencyPhone) })] })] }) })] }), _jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(GraduationCap, { className: "text-primary h-5 w-5" }), _jsx(CardTitle, { className: "text-lg", children: t("viewSectionProfessionalInformation") })] }), _jsx(CardDescription, { children: t("viewFieldTeachingCredentialsAndExperience") })] }), _jsx(Separator, {}), _jsx(CardContent, { className: "pt-6", children: _jsxs("div", { className: "grid grid-cols-1 gap-6", children: [_jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("
|
|
25
|
+
return (_jsxs("div", { className: "space-y-4", children: [_jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(User, { className: "text-primary h-5 w-5" }), _jsx(CardTitle, { className: "text-lg", children: t("viewSectionBasicInformation") })] }), _jsx(CardDescription, { children: t("viewSectionTeachersPersonalDetails") })] }), _jsx(Separator, {}), _jsx(CardContent, { className: "pt-6", children: _jsxs("div", { className: "grid grid-cols-1 gap-6", children: [_jsxs("div", { className: "space-y-2", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("viewFieldProfilePicture") }), _jsxs(Avatar, { className: "h-20 w-20", children: [_jsx(AvatarImage, { src: avatar || undefined, alt: fullName }), _jsx(AvatarFallback, { className: "text-lg", children: getInitials() })] })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("viewFieldTeacherCode") }), _jsx("p", { className: "font-mono text-base", children: formatValue(teacherCode) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("viewFieldName") }), _jsx("p", { className: "text-base", children: fullName })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("formGenderLabel") }), _jsx("p", { className: "text-base", children: formatValue(gender) })] }), _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Calendar, { className: "text-muted-foreground h-4 w-4" }), _jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("formDateOfBirthLabel") })] }), _jsx("p", { className: "text-base", children: formatDateValue(dateOfBirth) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("viewFieldStatus") }), _jsx("div", { className: "flex items-center gap-2", children: enabled ? (_jsxs(_Fragment, { children: [_jsx(CheckCircle2, { className: "h-4 w-4 text-green-600" }), _jsx(Badge, { variant: "default", children: t("badgeActive") })] })) : (_jsxs(_Fragment, { children: [_jsx(XCircle, { className: "h-4 w-4 text-red-600" }), _jsx(Badge, { variant: "destructive", children: t("badgeInactive") })] })) })] })] }) })] }), _jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Phone, { className: "text-primary h-5 w-5" }), _jsx(CardTitle, { className: "text-lg", children: t("viewSectionContactInformation") })] }), _jsx(CardDescription, { children: t("viewFieldHowToReachTheTeacher") })] }), _jsx(Separator, {}), _jsx(CardContent, { className: "pt-6", children: _jsxs("div", { className: "grid grid-cols-1 gap-6", children: [_jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Phone, { className: "text-muted-foreground h-4 w-4" }), _jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("viewFieldPhone") })] }), _jsx("p", { className: "text-base", children: formatPhoneDisplay(phone) || formatValue(phone) })] }), _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Phone, { className: "text-muted-foreground h-4 w-4" }), _jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("formEmergencyPhoneLabel") })] }), _jsx("p", { className: "text-base", children: formatPhoneDisplay(emergencyPhone) ||
|
|
26
|
+
formatValue(emergencyPhone) })] })] }) })] }), _jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(GraduationCap, { className: "text-primary h-5 w-5" }), _jsx(CardTitle, { className: "text-lg", children: t("viewSectionProfessionalInformation") })] }), _jsx(CardDescription, { children: t("viewFieldTeachingCredentialsAndExperience") })] }), _jsx(Separator, {}), _jsx(CardContent, { className: "pt-6", children: _jsxs("div", { className: "grid grid-cols-1 gap-6", children: [_jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("formQualificationLabel") }), _jsx("p", { className: "text-base", children: formatValue(qualification) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("formSpecializationLabel") }), _jsx("p", { className: "text-base", children: formatValue(specialization) })] }), _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Briefcase, { className: "text-muted-foreground h-4 w-4" }), _jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("viewFieldExperience") })] }), _jsx("p", { className: "text-base", children: experience
|
|
27
27
|
? t("experienceYears", { years: experience })
|
|
28
|
-
: "\u2014" })] }), _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Calendar, { className: "text-muted-foreground h-4 w-4" }), _jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("
|
|
28
|
+
: "\u2014" })] }), _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Calendar, { className: "text-muted-foreground h-4 w-4" }), _jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("formJoiningDateLabel") })] }), _jsx("p", { className: "text-base", children: formatDateValue(joiningDate) })] })] }) })] }), _jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(MapPin, { className: "text-primary h-5 w-5" }), _jsx(CardTitle, { className: "text-lg", children: t("viewSectionAddressInformation") })] }), _jsx(CardDescription, { children: t("viewFieldTeachersResidentialAddress") })] }), _jsx(Separator, {}), _jsx(CardContent, { className: "pt-6", children: _jsxs("div", { className: "grid grid-cols-1 gap-6", children: [_jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("formAddressLabel") }), _jsx("p", { className: "text-base", children: formatValue(address) })] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("formCityLabel") }), _jsx("p", { className: "text-base", children: formatValue(city) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("viewFieldStateProvince") }), _jsx("p", { className: "text-base", children: formatValue(stateValue) })] })] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("formCountryLabel") }), _jsx("p", { className: "text-base", children: formatValue(country) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("formPostalCodeLabel") }), _jsx("p", { className: "text-base", children: formatValue(postalCode) })] })] })] }) })] }), bio && (_jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsx(CardTitle, { className: "text-lg", children: t("viewFieldBiography") }), _jsx(CardDescription, { children: t("viewFieldAboutTheTeacher") })] }), _jsx(Separator, {}), _jsx(CardContent, { className: "pt-6", children: _jsx("p", { className: "text-base", children: bio }) })] }))] }));
|
|
29
29
|
};
|
|
@@ -12,7 +12,7 @@ export const UserFilter = () => {
|
|
|
12
12
|
: filterEnabled
|
|
13
13
|
? "true"
|
|
14
14
|
: "false";
|
|
15
|
-
return (_jsx("div", { className: "space-y-4", children: _jsx("div", { className: "grid grid-cols-1 gap-4", children: _jsx(EnhancedRadio, { label: t("
|
|
15
|
+
return (_jsx("div", { className: "space-y-4", children: _jsx("div", { className: "grid grid-cols-1 gap-4", children: _jsx(EnhancedRadio, { label: t("filterEnabledLabel"), name: "filterEnabled", value: filterEnabledValue, options: [
|
|
16
16
|
{ label: t("filterOptionAll"), value: "undefined" },
|
|
17
17
|
{ label: t("filterOptionEnabled"), value: "true" },
|
|
18
18
|
{ label: t("filterOptionDisabled"), value: "false" },
|
|
@@ -11,6 +11,7 @@ import { USER_API_ROUTES } from "../../constants";
|
|
|
11
11
|
import { formatPhone } from "@react-pakistan/util-functions/general/format-phone";
|
|
12
12
|
import { useState } from "react";
|
|
13
13
|
import { Eye, EyeOff } from "lucide-react";
|
|
14
|
+
import { getTranslatedError } from "../../utils/get-translated-error";
|
|
14
15
|
export const UserForm = () => {
|
|
15
16
|
const t = useTranslations("user");
|
|
16
17
|
const { handleAvatar, handleChange, state } = useUserModule();
|
|
@@ -52,8 +53,8 @@ export const UserForm = () => {
|
|
|
52
53
|
},
|
|
53
54
|
value: userRole !== null && userRole !== void 0 ? userRole : "",
|
|
54
55
|
});
|
|
55
|
-
return (_jsxs("div", { className: "space-y-4", children: [_jsx(EnhancedInput, { error: errors
|
|
56
|
+
return (_jsxs("div", { className: "space-y-4", children: [_jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "name", t }), id: "name", info: t("formNameInfo"), label: t("formNameLabel"), onChange: (e) => handleChange("name", e.target.value), placeholder: t("formNamePlaceholder"), required: true, value: name || "" }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "email", t }), id: "email", info: t("formEmailInfo"), label: t("formEmailLabel"), onChange: (e) => handleChange("email", e.target.value), placeholder: t("formEmailPlaceholder"), required: true, type: "email", value: email }), _jsxs("div", { className: "relative", children: [_jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "password", t }), id: "password", info: t("formPasswordInfo"), label: t("formPasswordLabel"), onChange: (e) => handleChange("password", e.target.value), placeholder: t("formPasswordPlaceholder"), type: passwordVisible ? "text" : "password", value: password || "" }), _jsx("button", { type: "button", "aria-label": passwordVisible ? t("actionHidePassword") : t("actionShowPassword"), onClick: () => setPasswordVisible(!passwordVisible), className: "text-muted-foreground hover:text-foreground absolute inset-y-0 top-1 right-3 flex items-center justify-center p-1 text-sm", children: passwordVisible ? (_jsx(EyeOff, { className: "h-4 w-4" })) : (_jsx(Eye, { className: "h-4 w-4" })) })] }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "phone", t }), id: "phone", info: t("formPhoneInfo"), label: t("formPhoneLabel"), onChange: (e) => {
|
|
56
57
|
var _a;
|
|
57
58
|
return handleChange("phone", ((_a = formatPhone(e.target.value)) === null || _a === void 0 ? void 0 : _a.international) || e.target.value);
|
|
58
|
-
}, placeholder: t("formPhonePlaceholder"), type: "tel", value: phone || "" }), _jsx(EnhancedDropzone, { accept: ["image/*"], error: errors
|
|
59
|
+
}, placeholder: t("formPhonePlaceholder"), type: "tel", value: phone || "" }), _jsx(EnhancedDropzone, { accept: ["image/*"], error: getTranslatedError({ errors, key: "avatar", t }), id: "avatar", info: t("formAvatarInfo"), label: t("formAvatarLabel"), maxFiles: 1, maxSize: 0.25 * 1024 * 1024, onChange: handleAvatar, onRemoveRemote: () => handleChange("avatar", ""), resize: true, value: avatar ? [avatar] : [] }), _jsx(EnhancedCheckbox, { checked: enabled, error: getTranslatedError({ errors, key: "enabled", t }), id: "enabled", info: t("formEnabledInfo"), label: t("formEnabledLabel"), onCheckedChange: (checked) => handleChange("enabled", checked) }), userRoleCombo] }));
|
|
59
60
|
};
|
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
import { FC } from "react";
|
|
19
19
|
import { USER_ROLE } from "../../type";
|
|
20
20
|
interface Props {
|
|
21
|
-
|
|
21
|
+
drawerButtonCancel: string;
|
|
22
|
+
drawerButtonSave: string;
|
|
22
23
|
drawerFilterDescription: string;
|
|
23
24
|
drawerFilterTitle: string;
|
|
24
25
|
drawerFormDescription: string;
|
|
@@ -27,15 +28,14 @@ interface Props {
|
|
|
27
28
|
drawerMoreActionsTitle: string;
|
|
28
29
|
drawerViewDescription: string;
|
|
29
30
|
drawerViewTitle: string;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
saveLabel: string;
|
|
37
|
-
searchPlaceholder: string;
|
|
31
|
+
tableColumnHeaderActions: string;
|
|
32
|
+
tableColumnHeaderEmail: string;
|
|
33
|
+
tableColumnHeaderEnabled: string;
|
|
34
|
+
tableColumnHeaderId: string;
|
|
35
|
+
tableColumnHeaderName: string;
|
|
36
|
+
tableColumnHeaderPhone: string;
|
|
38
37
|
tableDescription: string;
|
|
38
|
+
tableSearchPlaceholder: string;
|
|
39
39
|
tableTitle: string;
|
|
40
40
|
userRole: USER_ROLE;
|
|
41
41
|
}
|
|
@@ -47,19 +47,19 @@ const createComponentInstances = () => ({
|
|
|
47
47
|
moreActions: _jsx(UserMoreActions, {}),
|
|
48
48
|
view: _jsx(UserView, {}),
|
|
49
49
|
});
|
|
50
|
-
const createUserConfig = ({
|
|
50
|
+
const createUserConfig = ({ dispatch, drawerButtonCancel, drawerButtonSave, drawerFilterDescription, drawerFilterTitle, drawerFormDescription, drawerFormTitle, drawerMoreActionsDescription, drawerMoreActionsTitle, drawerViewDescription, drawerViewTitle, tableColumnHeaderActions, tableColumnHeaderEmail, tableColumnHeaderEnabled, tableColumnHeaderId, tableColumnHeaderName, tableColumnHeaderPhone, tableDescription, tableSearchPlaceholder, tableTitle, }) => {
|
|
51
51
|
const components = createComponentInstances();
|
|
52
52
|
return {
|
|
53
53
|
moduleName: "user",
|
|
54
54
|
tableColumns: [
|
|
55
|
-
{ label:
|
|
56
|
-
{ label:
|
|
57
|
-
{ label:
|
|
58
|
-
{ label:
|
|
59
|
-
{ label:
|
|
60
|
-
{ label:
|
|
55
|
+
{ label: tableColumnHeaderId, width: "5%" },
|
|
56
|
+
{ label: tableColumnHeaderName, width: "30%" },
|
|
57
|
+
{ label: tableColumnHeaderEmail, width: "30%" },
|
|
58
|
+
{ label: tableColumnHeaderPhone, width: "20%" },
|
|
59
|
+
{ label: tableColumnHeaderEnabled, width: "10%" },
|
|
60
|
+
{ label: tableColumnHeaderActions, width: "5%" },
|
|
61
61
|
],
|
|
62
|
-
cancelLabel,
|
|
62
|
+
cancelLabel: drawerButtonCancel,
|
|
63
63
|
drawerFilterDescription,
|
|
64
64
|
drawerFilterTitle,
|
|
65
65
|
drawerFormDescription,
|
|
@@ -71,8 +71,8 @@ const createUserConfig = ({ cancelLabel, dispatch, drawerFilterDescription, draw
|
|
|
71
71
|
filterContent: components.filter,
|
|
72
72
|
formContent: components.form,
|
|
73
73
|
moreActionsContent: components.moreActions,
|
|
74
|
-
saveLabel,
|
|
75
|
-
searchPlaceholder,
|
|
74
|
+
saveLabel: drawerButtonSave,
|
|
75
|
+
searchPlaceholder: tableSearchPlaceholder,
|
|
76
76
|
tableDescription,
|
|
77
77
|
tableTitle,
|
|
78
78
|
viewContent: components.view,
|
|
@@ -89,7 +89,8 @@ const UserPageInner = (props) => {
|
|
|
89
89
|
const context = useUserModule();
|
|
90
90
|
const userConfig = useMemo(() => createUserConfig({
|
|
91
91
|
dispatch: context.dispatch,
|
|
92
|
-
|
|
92
|
+
drawerButtonCancel: props.drawerButtonCancel,
|
|
93
|
+
drawerButtonSave: props.drawerButtonSave,
|
|
93
94
|
drawerFormTitle: props.drawerFormTitle,
|
|
94
95
|
drawerFormDescription: props.drawerFormDescription,
|
|
95
96
|
drawerViewTitle: props.drawerViewTitle,
|
|
@@ -98,19 +99,19 @@ const UserPageInner = (props) => {
|
|
|
98
99
|
drawerFilterDescription: props.drawerFilterDescription,
|
|
99
100
|
drawerMoreActionsTitle: props.drawerMoreActionsTitle,
|
|
100
101
|
drawerMoreActionsDescription: props.drawerMoreActionsDescription,
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
saveLabel: props.saveLabel,
|
|
108
|
-
searchPlaceholder: props.searchPlaceholder,
|
|
102
|
+
tableColumnHeaderActions: props.tableColumnHeaderActions,
|
|
103
|
+
tableColumnHeaderEmail: props.tableColumnHeaderEmail,
|
|
104
|
+
tableColumnHeaderEnabled: props.tableColumnHeaderEnabled,
|
|
105
|
+
tableColumnHeaderId: props.tableColumnHeaderId,
|
|
106
|
+
tableColumnHeaderName: props.tableColumnHeaderName,
|
|
107
|
+
tableColumnHeaderPhone: props.tableColumnHeaderPhone,
|
|
109
108
|
tableDescription: props.tableDescription,
|
|
109
|
+
tableSearchPlaceholder: props.tableSearchPlaceholder,
|
|
110
110
|
tableTitle: props.tableTitle,
|
|
111
111
|
}), [
|
|
112
112
|
context.dispatch,
|
|
113
|
-
props.
|
|
113
|
+
props.drawerButtonCancel,
|
|
114
|
+
props.drawerButtonSave,
|
|
114
115
|
props.drawerFormTitle,
|
|
115
116
|
props.drawerFormDescription,
|
|
116
117
|
props.drawerViewTitle,
|
|
@@ -119,15 +120,14 @@ const UserPageInner = (props) => {
|
|
|
119
120
|
props.drawerFilterDescription,
|
|
120
121
|
props.drawerMoreActionsTitle,
|
|
121
122
|
props.drawerMoreActionsDescription,
|
|
122
|
-
props.
|
|
123
|
-
props.
|
|
124
|
-
props.
|
|
125
|
-
props.
|
|
126
|
-
props.
|
|
127
|
-
props.
|
|
128
|
-
props.saveLabel,
|
|
129
|
-
props.searchPlaceholder,
|
|
123
|
+
props.tableColumnHeaderActions,
|
|
124
|
+
props.tableColumnHeaderEmail,
|
|
125
|
+
props.tableColumnHeaderEnabled,
|
|
126
|
+
props.tableColumnHeaderId,
|
|
127
|
+
props.tableColumnHeaderName,
|
|
128
|
+
props.tableColumnHeaderPhone,
|
|
130
129
|
props.tableDescription,
|
|
130
|
+
props.tableSearchPlaceholder,
|
|
131
131
|
props.tableTitle,
|
|
132
132
|
]);
|
|
133
133
|
const hasPermission = resolveRbacPermissions({
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* User Validation Schema
|
|
3
3
|
*
|
|
4
|
-
* Zod validation schemas for user form data.
|
|
4
|
+
* Zod validation schemas for user form data with i18n-ready error keys.
|
|
5
5
|
*/
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
import { USER_ROLE } from "../../type";
|
|
8
|
+
export declare const VALIDATION_KEYS: {
|
|
9
|
+
readonly name: "validationUserNameRequired";
|
|
10
|
+
readonly emailInvalid: "validationUserEmailInvalid";
|
|
11
|
+
readonly phoneInvalid: "validationUserPhoneInvalid";
|
|
12
|
+
readonly roleInvalid: "validationUserRoleInvalid";
|
|
13
|
+
readonly roleSchoolAdminNotAllowed: "validationUserRoleSchoolAdminNotAllowed";
|
|
14
|
+
};
|
|
8
15
|
export declare const userFormValidation: z.ZodObject<{
|
|
9
16
|
name: z.ZodString;
|
|
10
17
|
email: z.ZodEmail;
|
|
@@ -1,29 +1,39 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* User Validation Schema
|
|
3
3
|
*
|
|
4
|
-
* Zod validation schemas for user form data.
|
|
4
|
+
* Zod validation schemas for user form data with i18n-ready error keys.
|
|
5
5
|
*/
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
import { USER_ROLE } from "../../type";
|
|
8
8
|
// ============================================================================
|
|
9
|
+
// VALIDATION KEYS
|
|
10
|
+
// ============================================================================
|
|
11
|
+
export const VALIDATION_KEYS = {
|
|
12
|
+
name: "validationUserNameRequired",
|
|
13
|
+
emailInvalid: "validationUserEmailInvalid",
|
|
14
|
+
phoneInvalid: "validationUserPhoneInvalid",
|
|
15
|
+
roleInvalid: "validationUserRoleInvalid",
|
|
16
|
+
roleSchoolAdminNotAllowed: "validationUserRoleSchoolAdminNotAllowed",
|
|
17
|
+
};
|
|
18
|
+
// ============================================================================
|
|
9
19
|
// VALIDATION SCHEMA
|
|
10
20
|
// ============================================================================
|
|
11
21
|
export const userFormValidation = z.object({
|
|
12
|
-
name: z.string().min(1,
|
|
13
|
-
email: z.email(
|
|
22
|
+
name: z.string().min(1, VALIDATION_KEYS.name),
|
|
23
|
+
email: z.email(VALIDATION_KEYS.emailInvalid),
|
|
14
24
|
password: z.string().optional(),
|
|
15
25
|
phone: z
|
|
16
26
|
.string()
|
|
17
27
|
.optional()
|
|
18
28
|
.refine((val) => !val ||
|
|
19
|
-
/^([+]?[\s0-9]+)?(\d{3}|[(]?[0-9]+[)]?)?([-]?[\s]?[0-9])+$/.test(val),
|
|
29
|
+
/^([+]?[\s0-9]+)?(\d{3}|[(]?[0-9]+[)]?)?([-]?[\s]?[0-9])+$/.test(val), VALIDATION_KEYS.phoneInvalid),
|
|
20
30
|
avatar: z.string().optional(),
|
|
21
31
|
enabled: z.boolean().optional(),
|
|
22
32
|
userRole: z
|
|
23
33
|
.nativeEnum(USER_ROLE, {
|
|
24
|
-
error:
|
|
34
|
+
error: VALIDATION_KEYS.roleInvalid,
|
|
25
35
|
})
|
|
26
36
|
.refine((v) => v !== USER_ROLE.SCHOOL_ADMIN, {
|
|
27
|
-
message:
|
|
37
|
+
message: VALIDATION_KEYS.roleSchoolAdminNotAllowed,
|
|
28
38
|
}),
|
|
29
39
|
});
|
|
@@ -23,5 +23,5 @@ export const UserView = () => {
|
|
|
23
23
|
const t = useTranslations("user");
|
|
24
24
|
const { state } = useUserModule();
|
|
25
25
|
const { avatar, email, enabled, name, phone } = state;
|
|
26
|
-
return (_jsx("div", { className: "space-y-4", children: _jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(User, { className: "text-primary h-5 w-5" }), _jsx(CardTitle, { className: "text-lg", children: t("viewFieldUserInformation") })] }), _jsx(CardDescription, { children: t("viewUserAccountDetails") })] }), _jsx(Separator, {}), _jsx(CardContent, { className: "pt-6", children: _jsxs("div", { className: "grid grid-cols-1 gap-6", children: [_jsxs("div", { className: "space-y-2", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("viewFieldProfilePicture") }), _jsxs(Avatar, { className: "h-20 w-20", children: [_jsx(AvatarImage, { src: avatar || undefined, alt: name || t("viewFieldName") }), _jsx(AvatarFallback, { className: "text-lg", children: getInitials(name) })] })] }), _jsxs("div", { className: "space-y-1", children: [
|
|
26
|
+
return (_jsx("div", { className: "space-y-4", children: _jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(User, { className: "text-primary h-5 w-5" }), _jsx(CardTitle, { className: "text-lg", children: t("viewFieldUserInformation") })] }), _jsx(CardDescription, { children: t("viewUserAccountDetails") })] }), _jsx(Separator, {}), _jsx(CardContent, { className: "pt-6", children: _jsxs("div", { className: "grid grid-cols-1 gap-6", children: [_jsxs("div", { className: "space-y-2", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("viewFieldProfilePicture") }), _jsxs(Avatar, { className: "h-20 w-20", children: [_jsx(AvatarImage, { src: avatar || undefined, alt: name || t("viewFieldName") }), _jsx(AvatarFallback, { className: "text-lg", children: getInitials(name) })] })] }), _jsxs("div", { className: "space-y-1", children: [_jsxs("p", { className: "text-muted-foreground text-sm font-medium", children: [" ", t("formNameLabel")] }), _jsx("p", { className: "text-base", children: formatValue(name) })] }), _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Mail, { className: "text-muted-foreground h-4 w-4" }), _jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("formEmailLabel") })] }), _jsx("p", { className: "text-base", children: formatValue(email) })] }), _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Phone, { className: "text-muted-foreground h-4 w-4" }), _jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("formPhoneLabel") })] }), _jsx("p", { className: "text-base", children: formatPhoneDisplay(phone) || formatValue(phone) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("viewFieldStatus") }), _jsxs(Badge, { variant: enabled ? "default" : "destructive", className: "gap-1", children: [enabled ? (_jsx(CheckCircle2, { className: "h-3 w-3" })) : (_jsx(XCircle, { className: "h-3 w-3" })), enabled ? t("badgeActive") : t("badgeInactive")] })] })] }) })] }) }));
|
|
27
27
|
};
|
|
@@ -101,7 +101,7 @@ export const WorkspaceStateContextProvider = ({ children, }) => {
|
|
|
101
101
|
}
|
|
102
102
|
catch (_a) {
|
|
103
103
|
generateThemeToast({
|
|
104
|
-
description: t("
|
|
104
|
+
description: t("messagesWorkspaceFetchFailed"),
|
|
105
105
|
variant: TOAST_VARIANT.ERROR,
|
|
106
106
|
});
|
|
107
107
|
}
|
|
@@ -203,11 +203,11 @@ export const useWorkspaceModule = () => {
|
|
|
203
203
|
const listCallback = useCallback(() => { }, []);
|
|
204
204
|
const updateCallback = useCallback(({ data, error }) => {
|
|
205
205
|
if (error) {
|
|
206
|
-
showToast(t("
|
|
206
|
+
showToast(t("messagesWorkspaceUpdateFailed"), TOAST_VARIANT.ERROR);
|
|
207
207
|
return;
|
|
208
208
|
}
|
|
209
209
|
if (data) {
|
|
210
|
-
showToast(t("
|
|
210
|
+
showToast(t("messagesWorkspaceUpdated"), TOAST_VARIANT.SUCCESS);
|
|
211
211
|
invalidateWorkspaceCache();
|
|
212
212
|
resetFormAndCloseDrawer();
|
|
213
213
|
}
|
|
@@ -22,5 +22,5 @@ export const WorkspaceDrawer = () => {
|
|
|
22
22
|
const isMoreActionsDrawer = drawer === WORKSPACE_DRAWER.MORE_ACTIONS_DRAWER;
|
|
23
23
|
const applyFilters = () => { };
|
|
24
24
|
const clearFilters = () => { };
|
|
25
|
-
return (_jsx(DrawerGeneric, { filterDrawer: null, filterDrawerHeader: null, filterDrawerFooter: null, formDrawer: isFormDrawer ? _jsx(WorkspaceForm, {}) : null, formDrawerHeader: isFormDrawer ? (_jsx(EnhancedDrawerHeader, { title: t("
|
|
25
|
+
return (_jsx(DrawerGeneric, { filterDrawer: null, filterDrawerHeader: null, filterDrawerFooter: null, formDrawer: isFormDrawer ? _jsx(WorkspaceForm, {}) : null, formDrawerHeader: isFormDrawer ? (_jsx(EnhancedDrawerHeader, { title: t("drawerFormTitle"), description: t("drawerFormDescription") })) : null, formDrawerFooter: isFormDrawer ? (_jsx(EnhancedDrawerFooter, { applyFilters: applyFilters, clearFilters: clearFilters, closeDrawer: handleCloseDrawer, disableSaveButton: disableSaveButton, drawerType: DRAWER_FOOTER_COMPONENT_TYPE.FORM_DRAWER, errors: errors, handleSubmit: handleSubmit, updateLoading: updateLoading })) : null, viewDrawer: isViewDrawer ? _jsx(WorkspaceView, {}) : null, viewDrawerHeader: isViewDrawer ? (_jsx(EnhancedDrawerHeader, { title: t("drawerViewTitle"), description: t("drawerViewDescription") })) : null, viewDrawerFooter: isViewDrawer ? (_jsx(EnhancedDrawerFooter, { applyFilters: applyFilters, clearFilters: clearFilters, closeDrawer: handleCloseDrawer, disableSaveButton: disableSaveButton, drawerType: DRAWER_FOOTER_COMPONENT_TYPE.VIEW_DRAWER, errors: errors, handleSubmit: handleSubmit, updateLoading: updateLoading })) : null, moreActionsDrawer: isMoreActionsDrawer ? _jsx(WorkspaceMoreActions, {}) : null, moreActionsDrawerHeader: isMoreActionsDrawer ? (_jsx(EnhancedDrawerHeader, { title: t("drawerMoreActionsTitle"), description: t("drawerMoreActionsDescription") })) : null, moreActionsDrawerFooter: isMoreActionsDrawer ? (_jsx(EnhancedDrawerFooter, { applyFilters: applyFilters, clearFilters: clearFilters, closeDrawer: handleCloseDrawer, disableSaveButton: disableSaveButton, drawerType: DRAWER_FOOTER_COMPONENT_TYPE.MORE_ACTIONS_DRAWER, errors: errors, handleSubmit: handleSubmit, updateLoading: updateLoading })) : null, onOpenChange: (open) => !open && handleCloseDrawer(), open: isFormDrawer || isViewDrawer || isMoreActionsDrawer }));
|
|
26
26
|
};
|
|
@@ -9,5 +9,5 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
9
9
|
import { useTranslations } from "next-intl";
|
|
10
10
|
export const WorkspaceFilter = () => {
|
|
11
11
|
const t = useTranslations("workspace");
|
|
12
|
-
return (_jsx("div", { className: "p-6 text-center text-muted-foreground", children: _jsx("p", { children: t("
|
|
12
|
+
return (_jsx("div", { className: "p-6 text-center text-muted-foreground", children: _jsx("p", { children: t("messagesNoFiltersAvailable") }) }));
|
|
13
13
|
};
|
|
@@ -11,6 +11,7 @@ import { useTranslations } from "next-intl";
|
|
|
11
11
|
import { EnhancedInput } from "@appcorp/shadcn/components/enhanced-input";
|
|
12
12
|
import { EnhancedTextarea } from "@appcorp/shadcn/components/enhanced-textarea";
|
|
13
13
|
import { useEnhancedCombobox } from "@appcorp/shadcn/hooks/use-enhanced-combobox";
|
|
14
|
+
import { getTranslatedError } from "@/utils/get-translated-error";
|
|
14
15
|
import { Shield, Eye, EyeOff } from "lucide-react";
|
|
15
16
|
import { secretKeys } from "./constants";
|
|
16
17
|
import { PLAN_API_ROUTES } from "../../constants";
|
|
@@ -54,5 +55,5 @@ export const WorkspaceForm = () => {
|
|
|
54
55
|
});
|
|
55
56
|
},
|
|
56
57
|
});
|
|
57
|
-
return (_jsxs("div", { className: "space-y-6", children: [_jsx(EnhancedInput, { id: "name", label: t("formNameLabel"), value: state.name, onChange: (e) => handleChange("name", e.target.value), error: state.errors
|
|
58
|
+
return (_jsxs("div", { className: "space-y-6", children: [_jsx(EnhancedInput, { id: "name", label: t("formNameLabel"), value: state.name, onChange: (e) => handleChange("name", e.target.value), error: getTranslatedError({ errors: state.errors, key: "name", t }), placeholder: t("formNamePlaceholder"), required: true, readOnly: true }), _jsx(EnhancedInput, { id: "subdomain", label: t("formSubdomainLabel"), value: state.subdomain, onChange: (e) => handleChange("subdomain", e.target.value), error: getTranslatedError({ errors: state.errors, key: "subdomain", t }), placeholder: t("formSubdomainPlaceholder"), required: true, info: t("formSubdomainUrlInfo", { subdomain: state.subdomain }), readOnly: true }), _jsx(EnhancedTextarea, { id: "description", label: t("formDescriptionLabel"), value: state.description || "", onChange: (e) => handleChange("description", e.target.value), error: state.errors.description, placeholder: t("formDescriptionPlaceholder"), rows: 3 }), _jsx(EnhancedInput, { id: "logo", label: t("formLogoLabel"), value: state.logo || "", onChange: (e) => handleChange("logo", e.target.value), error: state.errors.logo, placeholder: t("formLogoPlaceholder"), type: "url", readOnly: true }), planIdCombo, _jsxs("div", { className: "mt-6 border-t pt-6", children: [_jsxs("div", { className: "mb-4 flex items-center gap-2", children: [_jsx(Shield, { className: "text-primary h-5 w-5" }), _jsx("h3", { className: "text-lg font-semibold", children: t("formSectionSecrets") })] }), _jsx("p", { className: "text-muted-foreground mb-4 text-sm", children: t("formSecretsDescription") }), _jsx(SecretsEditor, { secrets: secrets, errors: state.errors, onChange: handleSecretChange, secretPlaceholder: t("formSecretPlaceholder") })] })] }));
|
|
58
59
|
};
|
|
@@ -9,5 +9,5 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
9
9
|
import { useTranslations } from "next-intl";
|
|
10
10
|
export const WorkspaceMoreActions = () => {
|
|
11
11
|
const t = useTranslations("workspace");
|
|
12
|
-
return (_jsx("div", { className: "p-6 text-center text-muted-foreground", children: _jsx("p", { children: t("
|
|
12
|
+
return (_jsx("div", { className: "p-6 text-center text-muted-foreground", children: _jsx("p", { children: t("messagesNoAdditionalActions") }) }));
|
|
13
13
|
};
|
|
@@ -21,7 +21,7 @@ import { RbacNoAccess } from "../../components/rbac-no-access";
|
|
|
21
21
|
// ============================================================================
|
|
22
22
|
// INNER PAGE (requires WorkspaceStateContextProvider)
|
|
23
23
|
// ============================================================================
|
|
24
|
-
const WorkspaceInnerPage = ({
|
|
24
|
+
const WorkspaceInnerPage = ({ actionsButtonEdit, tableDescription, tableTitle, userRole, }) => {
|
|
25
25
|
const { handleEdit } = useWorkspaceModule();
|
|
26
26
|
const hasPermission = resolveRbacPermissions({
|
|
27
27
|
userRole,
|
|
@@ -30,7 +30,7 @@ const WorkspaceInnerPage = ({ labelEdit, tableDescription, tableTitle, userRole,
|
|
|
30
30
|
if (!hasPermission) {
|
|
31
31
|
return _jsx(RbacNoAccess, { moduleName: "Workspace" });
|
|
32
32
|
}
|
|
33
|
-
return (_jsx("div", { className: "container mx-auto px-4 py-8", children: _jsxs("div", { className: "mx-auto max-w-6xl", children: [_jsxs("div", { className: "mb-8", children: [_jsx("h1", { className: "text-3xl font-bold text-gray-900", children: tableTitle }), _jsx("p", { className: "mt-2 text-gray-600", children: tableDescription })] }), _jsx("div", { className: "mb-6 flex justify-end", children: _jsxs(Button, { onClick: handleEdit, className: "flex items-center space-x-2", children: [_jsx(Edit, { className: "h-4 w-4" }), _jsx("span", { children:
|
|
33
|
+
return (_jsx("div", { className: "container mx-auto px-4 py-8", children: _jsxs("div", { className: "mx-auto max-w-6xl", children: [_jsxs("div", { className: "mb-8", children: [_jsx("h1", { className: "text-3xl font-bold text-gray-900", children: tableTitle }), _jsx("p", { className: "mt-2 text-gray-600", children: tableDescription })] }), _jsx("div", { className: "mb-6 flex justify-end", children: _jsxs(Button, { onClick: handleEdit, className: "flex items-center space-x-2", children: [_jsx(Edit, { className: "h-4 w-4" }), _jsx("span", { children: actionsButtonEdit })] }) }), _jsx(WorkspaceView, {}), _jsx(WorkspaceDrawer, {})] }) }));
|
|
34
34
|
};
|
|
35
35
|
// ============================================================================
|
|
36
36
|
// ROOT PAGE COMPONENT (wraps with provider)
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
export declare const VALIDATION_KEYS: {
|
|
3
|
+
readonly name: "validationWorkspaceNameRequired";
|
|
4
|
+
readonly subdomain: "validationWorkspaceSubdomainRequired";
|
|
5
|
+
};
|
|
2
6
|
export declare const workspaceFormValidation: z.ZodObject<{
|
|
3
7
|
id: z.ZodOptional<z.ZodString>;
|
|
4
8
|
name: z.ZodString;
|