@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
|
@@ -19,8 +19,8 @@ export const FeeStructureView = () => {
|
|
|
19
19
|
const { amount, description, enabled, feeType, frequency, name } = state;
|
|
20
20
|
const t = useTranslations("feeStructure");
|
|
21
21
|
const workspace = getCachedWorkspaceSync();
|
|
22
|
-
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(DollarSign, { className: "text-primary h-5 w-5" }), _jsx(CardTitle, { className: "text-lg", children: t("viewSectionFeeStructureDetails") })] }), _jsx(CardDescription, { children: t("viewSectionFeeStructureRecordDetails") })] }), _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("
|
|
23
|
-
? t("
|
|
24
|
-
: t("
|
|
22
|
+
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(DollarSign, { className: "text-primary h-5 w-5" }), _jsx(CardTitle, { className: "text-lg", children: t("viewSectionFeeStructureDetails") })] }), _jsx(CardDescription, { children: t("viewSectionFeeStructureRecordDetails") })] }), _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("formNameLabel") }), _jsx("p", { className: "text-base font-semibold", children: formatValue(name) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("formFeeTypeLabel") }), _jsx(Badge, { variant: "secondary", children: formatValue(feeType) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("formAmountLabel") }), _jsxs("p", { className: "text-base", children: [(_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.currency, " ", Number(amount !== null && amount !== void 0 ? amount : 0).toFixed(2)] })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("formFrequencyLabel") }), _jsx("p", { className: "text-base", children: formatValue(frequency) })] })] }) })] }), description ? (_jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(FileText, { className: "text-primary h-5 w-5" }), _jsx(CardTitle, { className: "text-lg", children: t("viewSectionAdditionalDetails") })] }), _jsx(CardDescription, { children: t("viewFieldOptionalNotes") })] }), _jsx(Separator, {}), _jsx(CardContent, { className: "pt-6", children: _jsx("p", { className: "text-base", children: description }) })] })) : null, _jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(CheckCircle2, { className: "text-primary h-5 w-5" }), _jsx(CardTitle, { className: "text-lg", children: t("viewFieldStatus") })] }), _jsx(CardDescription, { children: t("viewFieldRecordState") })] }), _jsx(Separator, {}), _jsx(CardContent, { className: "pt-6", children: _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
|
|
23
|
+
? t("badgeActive")
|
|
24
|
+
: t("badgeInactive")] }) })] })] }));
|
|
25
25
|
};
|
|
26
26
|
FeeStructureView.displayName = "FeeStructureView";
|
|
@@ -12,13 +12,10 @@ import { Badge } from "@appcorp/shadcn/components/ui/badge";
|
|
|
12
12
|
import { EnhancedCheckbox } from "@appcorp/shadcn/components/enhanced-checkbox";
|
|
13
13
|
import { ACCESS_LEVEL } from "../../type";
|
|
14
14
|
import { useRbacModule } from "./context";
|
|
15
|
+
import { useTranslations } from "next-intl";
|
|
15
16
|
// ============================================================================
|
|
16
17
|
// HELPERS
|
|
17
18
|
// ============================================================================
|
|
18
|
-
const ACCESS_LEVEL_LABELS = {
|
|
19
|
-
[ACCESS_LEVEL.READ]: "Read",
|
|
20
|
-
[ACCESS_LEVEL.READ_WRITE]: "Read & Write",
|
|
21
|
-
};
|
|
22
19
|
const ACCESS_LEVEL_VARIANT = {
|
|
23
20
|
[ACCESS_LEVEL.READ]: "outline",
|
|
24
21
|
[ACCESS_LEVEL.READ_WRITE]: "default",
|
|
@@ -28,6 +25,11 @@ const ACCESS_LEVEL_VARIANT = {
|
|
|
28
25
|
// ============================================================================
|
|
29
26
|
export const AssignPermissions = () => {
|
|
30
27
|
const { state, handleTogglePermission } = useRbacModule();
|
|
28
|
+
const t = useTranslations("rbac");
|
|
29
|
+
const ACCESS_LEVEL_LABELS = {
|
|
30
|
+
[ACCESS_LEVEL.READ]: t("formOptionRead"),
|
|
31
|
+
[ACCESS_LEVEL.READ_WRITE]: t("formOptionReadWrite"),
|
|
32
|
+
};
|
|
31
33
|
const assignedIds = new Set(state.rolePermissions.map((rp) => rp.permissionId));
|
|
32
34
|
// Group permissions by module name
|
|
33
35
|
const grouped = state.availablePermissions.reduce((acc, perm) => {
|
|
@@ -37,7 +39,9 @@ export const AssignPermissions = () => {
|
|
|
37
39
|
return acc;
|
|
38
40
|
}, {});
|
|
39
41
|
const modules = Object.keys(grouped).sort();
|
|
40
|
-
return (_jsxs("div", { className: "space-y-5", children: [
|
|
42
|
+
return (_jsxs("div", { className: "space-y-5", children: [_jsx("p", { className: "text-muted-foreground text-sm", children: t.rich("viewTextTogglePermissions", {
|
|
43
|
+
name: (chunks) => _jsx("strong", { children: chunks }),
|
|
44
|
+
}) }), modules.length === 0 ? (_jsx("div", { className: "rounded-md border border-dashed p-6 text-center", children: _jsx("p", { className: "text-muted-foreground text-sm", children: t("viewTextNoPermissionsFound") }) })) : (modules.map((module) => (_jsxs("div", { children: [_jsxs("div", { className: "mb-3 flex items-center gap-3", children: [_jsx("p", { className: "text-sm font-semibold tracking-wide capitalize", children: module }), _jsx(Separator, { className: "flex-1" })] }), _jsx("div", { className: "space-y-1 pl-1", children: grouped[module].map((perm) => {
|
|
41
45
|
const isAssigned = assignedIds.has(perm.id);
|
|
42
46
|
return (_jsxs("div", { className: [
|
|
43
47
|
"flex cursor-pointer items-center gap-3 rounded-md px-3 py-2",
|
|
@@ -7,12 +7,14 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
7
7
|
* since roles don't have enabled/status fields.
|
|
8
8
|
*/
|
|
9
9
|
import { useRbacModule } from "./context";
|
|
10
|
+
import { useTranslations } from "next-intl";
|
|
10
11
|
export const RbacFilter = () => {
|
|
11
12
|
const { applyFilters, clearFilters, closeDrawer } = useRbacModule();
|
|
12
|
-
|
|
13
|
+
const t = useTranslations("rbac");
|
|
14
|
+
return (_jsxs("div", { className: "space-y-4", children: [_jsx("p", { className: "text-muted-foreground text-sm", children: t("filterTextDescription") }), _jsxs("div", { className: "mt-4 flex gap-2", children: [_jsx("button", { className: "text-muted-foreground text-sm underline", onClick: () => {
|
|
13
15
|
clearFilters();
|
|
14
16
|
closeDrawer();
|
|
15
|
-
}, children: "
|
|
17
|
+
}, children: t("drawerButtonClearFilter") }), _jsx("button", { className: "text-sm underline", onClick: () => {
|
|
16
18
|
applyFilters();
|
|
17
|
-
}, children: "
|
|
19
|
+
}, children: t("drawerButtonApply") })] })] }));
|
|
18
20
|
};
|
|
@@ -10,8 +10,9 @@ import { Separator } from "@appcorp/shadcn/components/ui/separator";
|
|
|
10
10
|
import { useRbacModule } from "./context";
|
|
11
11
|
import { AssignPermissions } from "./assign-permissions";
|
|
12
12
|
import { useTranslations } from "next-intl";
|
|
13
|
+
import { getTranslatedError } from "../../utils/get-translated-error";
|
|
13
14
|
export const RbacForm = () => {
|
|
14
15
|
const t = useTranslations("rbac");
|
|
15
16
|
const { state, handleChange } = useRbacModule();
|
|
16
|
-
return (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "grid grid-cols-1 gap-4", children: [_jsx(EnhancedInput, { id: "name", label: t("formNameLabel"), required: true, type: "text", value: state.name || "", onChange: (e) => handleChange("name", e.target.value), error: state.errors
|
|
17
|
+
return (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "grid grid-cols-1 gap-4", children: [_jsx(EnhancedInput, { id: "name", label: t("formNameLabel"), required: true, type: "text", value: state.name || "", onChange: (e) => handleChange("name", e.target.value), error: getTranslatedError({ errors: state.errors, key: "name", t }), placeholder: t("formNamePlaceholder"), info: t("formNameInfo") }), _jsx(EnhancedInput, { id: "description", label: t("formDescriptionLabel"), type: "text", value: state.description || "", onChange: (e) => handleChange("description", e.target.value || undefined), error: getTranslatedError({ errors: state.errors, key: "description", t }), placeholder: t("formDescriptionPlaceholder"), info: t("formDescriptionInfo") })] }), state.id && (_jsxs(_Fragment, { children: [_jsx(Separator, {}), _jsxs("div", { className: "space-y-2", children: [_jsx("p", { className: "text-sm font-medium", children: t("viewSectionPermissions") }), _jsx(AssignPermissions, {})] })] }))] }));
|
|
17
18
|
};
|
|
@@ -5,6 +5,8 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
5
5
|
*
|
|
6
6
|
* Placeholder for additional actions like bulk operations, exports, etc.
|
|
7
7
|
*/
|
|
8
|
+
import { useTranslations } from "next-intl";
|
|
8
9
|
export const RbacMoreActions = () => {
|
|
9
|
-
|
|
10
|
+
const t = useTranslations("rbac");
|
|
11
|
+
return (_jsx("div", { className: "space-y-4", children: _jsx("p", { className: "text-muted-foreground text-sm", children: t("moreActionsTextPlaceholder") }) }));
|
|
10
12
|
};
|
|
@@ -4,6 +4,9 @@
|
|
|
4
4
|
* Zod validation schemas for role form data.
|
|
5
5
|
*/
|
|
6
6
|
import { z } from "zod";
|
|
7
|
+
export declare const VALIDATION_KEYS: {
|
|
8
|
+
readonly name: "validationRoleNameRequired";
|
|
9
|
+
};
|
|
7
10
|
export declare const roleFormValidation: z.ZodObject<{
|
|
8
11
|
name: z.ZodString;
|
|
9
12
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
@@ -5,9 +5,15 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
// ============================================================================
|
|
8
|
+
// VALIDATION KEYS
|
|
9
|
+
// ============================================================================
|
|
10
|
+
export const VALIDATION_KEYS = {
|
|
11
|
+
name: "validationRoleNameRequired",
|
|
12
|
+
};
|
|
13
|
+
// ============================================================================
|
|
8
14
|
// VALIDATION SCHEMA
|
|
9
15
|
// ============================================================================
|
|
10
16
|
export const roleFormValidation = z.object({
|
|
11
|
-
name: z.string().min(1,
|
|
17
|
+
name: z.string().min(1, VALIDATION_KEYS.name),
|
|
12
18
|
description: z.string().nullable().optional(),
|
|
13
19
|
});
|
|
@@ -5,13 +5,10 @@ import { Badge } from "@appcorp/shadcn/components/ui/badge";
|
|
|
5
5
|
import { Separator } from "@appcorp/shadcn/components/ui/separator";
|
|
6
6
|
import { useRbacModule } from "./context";
|
|
7
7
|
import { ACCESS_LEVEL } from "../../type";
|
|
8
|
+
import { useTranslations } from "next-intl";
|
|
8
9
|
// ============================================================================
|
|
9
10
|
// HELPERS
|
|
10
11
|
// ============================================================================
|
|
11
|
-
const accessLevelLabel = {
|
|
12
|
-
[ACCESS_LEVEL.READ]: "Read",
|
|
13
|
-
[ACCESS_LEVEL.READ_WRITE]: "Read & Write",
|
|
14
|
-
};
|
|
15
12
|
const accessLevelVariant = (access) => {
|
|
16
13
|
if (access === ACCESS_LEVEL.READ_WRITE)
|
|
17
14
|
return "default";
|
|
@@ -22,7 +19,12 @@ const accessLevelVariant = (access) => {
|
|
|
22
19
|
// ============================================================================
|
|
23
20
|
export const RbacView = () => {
|
|
24
21
|
const { state } = useRbacModule();
|
|
25
|
-
|
|
22
|
+
const t = useTranslations("rbac");
|
|
23
|
+
const accessLevelLabel = {
|
|
24
|
+
[ACCESS_LEVEL.READ]: t("formOptionRead"),
|
|
25
|
+
[ACCESS_LEVEL.READ_WRITE]: t("formOptionReadWrite"),
|
|
26
|
+
};
|
|
27
|
+
return (_jsxs("div", { className: "space-y-4", children: [_jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsx(CardTitle, { className: "text-lg", children: t("viewSectionRoleInformation") }), _jsx(CardDescription, { children: t("viewFieldRoleDetails") })] }), _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("formNameLabel") }), _jsx("p", { className: "text-base", children: state.name || "—" })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("formDescriptionLabel") }), _jsx("p", { className: "text-base", children: state.description || "—" })] })] }) })] }), _jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsx(CardTitle, { className: "text-lg", children: t("viewSectionAssignedPermissions") }), _jsx(CardDescription, { children: t("viewTextPermissionsDescription") })] }), _jsx(Separator, {}), _jsx(CardContent, { className: "pt-6", children: state.rolePermissions.length === 0 ? (_jsx("p", { className: "text-muted-foreground text-sm", children: t("viewTextNoPermissions") })) : (_jsx("div", { className: "space-y-3", children: state.rolePermissions.map((rp) => {
|
|
26
28
|
var _a, _b;
|
|
27
29
|
return (_jsxs("div", { className: "flex items-center justify-between border-b py-2 last:border-0", children: [_jsx("span", { className: "text-sm font-medium", children: (_b = (_a = rp.permission) === null || _a === void 0 ? void 0 : _a.module) !== null && _b !== void 0 ? _b : rp.permissionId }), _jsx(Badge, { variant: rp.permission
|
|
28
30
|
? accessLevelVariant(rp.permission.access)
|
|
@@ -9,16 +9,18 @@ import { EnhancedDrawerHeader } from "@appcorp/shadcn/components/enhanced-drawer
|
|
|
9
9
|
import { EnhancedDrawerFooter, DRAWER_FOOTER_COMPONENT_TYPE, } from "@appcorp/shadcn/components/enhanced-drawer-footer";
|
|
10
10
|
import { DrawerGeneric } from "@appcorp/shadcn/components/drawer-generic";
|
|
11
11
|
import { useSchoolModule, SCHOOL_DRAWER } from "./context";
|
|
12
|
+
import { useTranslations } from "next-intl";
|
|
12
13
|
import { SchoolForm } from "./form";
|
|
13
14
|
import { SchoolView } from "./view";
|
|
14
15
|
import { SchoolMoreActions } from "./more-actions";
|
|
15
16
|
export const SchoolDrawer = () => {
|
|
16
17
|
const { closeDrawer, handleSubmit, state, updateLoading } = useSchoolModule();
|
|
18
|
+
const t = useTranslations("school");
|
|
17
19
|
const { disableSaveButton, drawer, errors } = state;
|
|
18
20
|
const isFormDrawer = drawer === SCHOOL_DRAWER.FORM_DRAWER;
|
|
19
21
|
const isViewDrawer = drawer === SCHOOL_DRAWER.VIEW_DRAWER;
|
|
20
22
|
const isMoreActionsDrawer = drawer === SCHOOL_DRAWER.MORE_ACTIONS_DRAWER;
|
|
21
23
|
const applyFilters = () => { };
|
|
22
24
|
const clearFilters = () => { };
|
|
23
|
-
return (_jsx(DrawerGeneric, { filterDrawer: null, filterDrawerHeader: null, filterDrawerFooter: null, formDrawer: isFormDrawer ? _jsx(SchoolForm, {}) : null, formDrawerHeader: isFormDrawer ? (_jsx(EnhancedDrawerHeader, { title: "
|
|
25
|
+
return (_jsx(DrawerGeneric, { filterDrawer: null, filterDrawerHeader: null, filterDrawerFooter: null, formDrawer: isFormDrawer ? _jsx(SchoolForm, {}) : null, formDrawerHeader: isFormDrawer ? (_jsx(EnhancedDrawerHeader, { title: t("drawerFormTitle"), description: t("drawerFormDescription") })) : null, formDrawerFooter: isFormDrawer ? (_jsx(EnhancedDrawerFooter, { applyFilters: applyFilters, clearFilters: clearFilters, closeDrawer: closeDrawer, disableSaveButton: disableSaveButton, drawerType: DRAWER_FOOTER_COMPONENT_TYPE.FORM_DRAWER, errors: errors, handleSubmit: handleSubmit, updateLoading: updateLoading })) : null, viewDrawer: isViewDrawer ? _jsx(SchoolView, {}) : null, viewDrawerHeader: isViewDrawer ? (_jsx(EnhancedDrawerHeader, { title: t("drawerViewTitle"), description: t("drawerViewDescription") })) : null, viewDrawerFooter: isViewDrawer ? (_jsx(EnhancedDrawerFooter, { applyFilters: applyFilters, clearFilters: clearFilters, closeDrawer: closeDrawer, disableSaveButton: disableSaveButton, drawerType: DRAWER_FOOTER_COMPONENT_TYPE.VIEW_DRAWER, errors: errors, handleSubmit: handleSubmit, updateLoading: updateLoading })) : null, moreActionsDrawer: isMoreActionsDrawer ? _jsx(SchoolMoreActions, {}) : null, moreActionsDrawerHeader: isMoreActionsDrawer ? (_jsx(EnhancedDrawerHeader, { title: t("drawerMoreActionsTitle"), description: t("drawerMoreActionsDescription") })) : null, moreActionsDrawerFooter: isMoreActionsDrawer ? (_jsx(EnhancedDrawerFooter, { applyFilters: applyFilters, clearFilters: clearFilters, closeDrawer: closeDrawer, disableSaveButton: disableSaveButton, drawerType: DRAWER_FOOTER_COMPONENT_TYPE.MORE_ACTIONS_DRAWER, errors: errors, handleSubmit: handleSubmit, updateLoading: updateLoading })) : null, onOpenChange: (open) => !open && closeDrawer(), open: isFormDrawer || isViewDrawer || isMoreActionsDrawer }));
|
|
24
26
|
};
|
|
@@ -12,6 +12,7 @@ import { useSchoolModule } from "./context";
|
|
|
12
12
|
import { CURRENCY } from "../../type";
|
|
13
13
|
import { SCHOOL_API_ROUTES } from "../../constants";
|
|
14
14
|
import { useTranslations } from "next-intl";
|
|
15
|
+
import { getTranslatedError } from "../../utils/get-translated-error";
|
|
15
16
|
export const SchoolForm = () => {
|
|
16
17
|
const t = useTranslations("school");
|
|
17
18
|
const { state, handleChange } = useSchoolModule();
|
|
@@ -56,5 +57,5 @@ export const SchoolForm = () => {
|
|
|
56
57
|
// searchPlaceholder: t("formPrincipalSearchPlaceholder"),
|
|
57
58
|
// value: principalId || "",
|
|
58
59
|
// });
|
|
59
|
-
return (_jsxs("div", { className: "space-y-6", children: [_jsxs("div", { className: "grid grid-cols-1 gap-4", children: [_jsx(EnhancedInput, { id: "name", label: t("formNameLabel"), value: name, onChange: (e) => handleChange("name", e.target.value), error: errors
|
|
60
|
+
return (_jsxs("div", { className: "space-y-6", children: [_jsxs("div", { className: "grid grid-cols-1 gap-4", children: [_jsx(EnhancedInput, { id: "name", label: t("formNameLabel"), value: name, onChange: (e) => handleChange("name", e.target.value), error: getTranslatedError({ errors, key: "name", t }), placeholder: t("formNamePlaceholder"), required: true }), _jsx(EnhancedInput, { id: "code", label: t("formCodeLabel"), value: code, onChange: (e) => handleChange("code", e.target.value), error: getTranslatedError({ errors, key: "code", t }), placeholder: t("formCodePlaceholder"), required: true, info: t("formCodeInfo") }), currencyCombo, _jsx(EnhancedInput, { id: "address", label: t("formAddressLabel"), value: address || "", onChange: (e) => handleChange("address", e.target.value), error: getTranslatedError({ errors, key: "address", t }), placeholder: t("formAddressPlaceholder") }), _jsx(EnhancedInput, { id: "city", label: t("formCityLabel"), value: city || "", onChange: (e) => handleChange("city", e.target.value), error: getTranslatedError({ errors, key: "city", t }), placeholder: t("formCityPlaceholder") }), _jsx(EnhancedInput, { id: "state", label: t("formStateLabel"), value: stateField || "", onChange: (e) => handleChange("state", e.target.value), error: getTranslatedError({ errors, key: "state", t }), placeholder: t("formStatePlaceholder") }), _jsx(EnhancedInput, { id: "country", label: t("formCountryLabel"), value: country || "", onChange: (e) => handleChange("country", e.target.value), error: getTranslatedError({ errors, key: "country", t }), placeholder: t("formCountryPlaceholder") }), _jsx(EnhancedInput, { id: "postalCode", label: t("formPostalCodeLabel"), value: postalCode || "", onChange: (e) => handleChange("postalCode", e.target.value), error: getTranslatedError({ errors, key: "postalCode", t }), placeholder: t("formPostalCodePlaceholder") }), _jsx(EnhancedInput, { id: "phone", label: t("formPhoneLabel"), value: phone || "", onChange: (e) => handleChange("phone", e.target.value), error: getTranslatedError({ errors, key: "phone", t }), placeholder: t("formPhonePlaceholder"), type: "tel" }), _jsx(EnhancedInput, { id: "email", label: t("formEmailLabel"), value: email || "", onChange: (e) => handleChange("email", e.target.value), error: getTranslatedError({ errors, key: "email", t }), placeholder: t("formEmailPlaceholder"), type: "email" })] }), _jsx(EnhancedInput, { id: "website", label: t("formWebsiteLabel"), value: website || "", onChange: (e) => handleChange("website", e.target.value), error: getTranslatedError({ errors, key: "website", t }), placeholder: t("formWebsitePlaceholder"), type: "url" }), _jsx(EnhancedInput, { id: "logo", label: t("formLogoLabel"), value: logo || "", onChange: (e) => handleChange("logo", e.target.value), error: getTranslatedError({ errors, key: "logo", t }), placeholder: t("formLogoPlaceholder"), type: "url" }), _jsx(EnhancedCheckbox, { id: "enabled", label: t("formEnabledLabel"), checked: enabled, error: getTranslatedError({ errors, key: "enabled", t }), onCheckedChange: (checked) => handleChange("enabled", checked), info: t("formEnabledInfo") })] }));
|
|
60
61
|
};
|
|
@@ -4,6 +4,14 @@
|
|
|
4
4
|
* Zod validation schemas for account-school form data.
|
|
5
5
|
*/
|
|
6
6
|
import { z } from "zod";
|
|
7
|
+
export declare const VALIDATION_KEYS: {
|
|
8
|
+
readonly workspaceId: "validationSchoolWorkspaceRequired";
|
|
9
|
+
readonly name: "validationSchoolNameRequired";
|
|
10
|
+
readonly code: "validationSchoolCodeRequired";
|
|
11
|
+
readonly email: "validationSchoolEmailInvalid";
|
|
12
|
+
readonly website: "validationSchoolWebsiteInvalid";
|
|
13
|
+
readonly currency: "validationSchoolCurrencyRequired";
|
|
14
|
+
};
|
|
7
15
|
export declare const schoolFormValidation: z.ZodObject<{
|
|
8
16
|
workspaceId: z.ZodString;
|
|
9
17
|
name: z.ZodString;
|
|
@@ -5,22 +5,33 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
// ============================================================================
|
|
8
|
+
// VALIDATION KEYS
|
|
9
|
+
// ============================================================================
|
|
10
|
+
export const VALIDATION_KEYS = {
|
|
11
|
+
workspaceId: "validationSchoolWorkspaceRequired",
|
|
12
|
+
name: "validationSchoolNameRequired",
|
|
13
|
+
code: "validationSchoolCodeRequired",
|
|
14
|
+
email: "validationSchoolEmailInvalid",
|
|
15
|
+
website: "validationSchoolWebsiteInvalid",
|
|
16
|
+
currency: "validationSchoolCurrencyRequired",
|
|
17
|
+
};
|
|
18
|
+
// ============================================================================
|
|
8
19
|
// VALIDATION SCHEMA
|
|
9
20
|
// ============================================================================
|
|
10
21
|
export const schoolFormValidation = z.object({
|
|
11
|
-
workspaceId: z.string().min(1,
|
|
12
|
-
name: z.string().min(1,
|
|
13
|
-
code: z.string().min(1,
|
|
22
|
+
workspaceId: z.string().min(1, VALIDATION_KEYS.workspaceId),
|
|
23
|
+
name: z.string().min(1, VALIDATION_KEYS.name),
|
|
24
|
+
code: z.string().min(1, VALIDATION_KEYS.code),
|
|
14
25
|
address: z.string().nullable().optional(),
|
|
15
26
|
city: z.string().nullable().optional(),
|
|
16
27
|
state: z.string().nullable().optional(),
|
|
17
28
|
country: z.string().nullable().optional(),
|
|
18
29
|
postalCode: z.string().nullable().optional(),
|
|
19
30
|
phone: z.string().nullable().optional(),
|
|
20
|
-
email: z.string().email(
|
|
21
|
-
website: z.string().url(
|
|
31
|
+
email: z.string().email(VALIDATION_KEYS.email).nullable().optional(),
|
|
32
|
+
website: z.string().url(VALIDATION_KEYS.website).nullable().optional(),
|
|
22
33
|
logo: z.string().nullable().optional(),
|
|
23
34
|
principalId: z.string().nullable().optional(),
|
|
24
35
|
enabled: z.boolean().optional(),
|
|
25
|
-
currency: z.string().min(1,
|
|
36
|
+
currency: z.string().min(1, VALIDATION_KEYS.currency),
|
|
26
37
|
});
|
|
@@ -17,9 +17,9 @@ export const SchoolView = () => {
|
|
|
17
17
|
const { state } = useSchoolModule();
|
|
18
18
|
const { name, code, currency, address, city, state: _state, country, postalCode, enabled, phone, email, website, logo, principalId, } = state;
|
|
19
19
|
const t = useTranslations("school");
|
|
20
|
-
return (_jsxs("div", { className: "space-y-6", children: [_jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Building2, { className: "text-primary h-5 w-5" }), _jsx(CardTitle, { className: "text-lg", children: t("viewSectionBasicInfo") })] }), _jsx(CardDescription, { children: t("viewBasicInfoDescription") })] }), _jsx(Separator, {}), _jsx(CardContent, { className: "pt-6", children: _jsxs("div", { className: "grid grid-cols-2 gap-6 md:grid-cols-2", children: [_jsxs("div", { className: "space-y-1 md:col-span-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Building2, { className: "text-muted-foreground h-4 w-4" }), _jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("viewFieldName") })] }), _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(Building2, { className: "text-muted-foreground h-4 w-4" }), _jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("viewFieldCode") })] }), _jsx("p", { className: "font-mono text-sm", children: formatValue(code) })] }), _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(DollarSign, { className: "text-muted-foreground h-4 w-4" }), _jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("
|
|
20
|
+
return (_jsxs("div", { className: "space-y-6", children: [_jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Building2, { className: "text-primary h-5 w-5" }), _jsx(CardTitle, { className: "text-lg", children: t("viewSectionBasicInfo") })] }), _jsx(CardDescription, { children: t("viewBasicInfoDescription") })] }), _jsx(Separator, {}), _jsx(CardContent, { className: "pt-6", children: _jsxs("div", { className: "grid grid-cols-2 gap-6 md:grid-cols-2", children: [_jsxs("div", { className: "space-y-1 md:col-span-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Building2, { className: "text-muted-foreground h-4 w-4" }), _jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("viewFieldName") })] }), _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(Building2, { className: "text-muted-foreground h-4 w-4" }), _jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("viewFieldCode") })] }), _jsx("p", { className: "font-mono text-sm", children: formatValue(code) })] }), _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(DollarSign, { className: "text-muted-foreground h-4 w-4" }), _jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("formCurrencyLabel") })] }), _jsx("p", { className: "text-base", children: formatValue(currency) })] }), _jsxs("div", { className: "space-y-1 md:col-span-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(MapPin, { className: "text-muted-foreground h-4 w-4" }), _jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("formAddressLabel") })] }), _jsx("p", { className: "text-base", children: formatValue(address) === "—"
|
|
21
21
|
? t("viewTextAddressNotProvided")
|
|
22
|
-
: address })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("
|
|
22
|
+
: address })] }), _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("viewFieldState") }), _jsx("p", { className: "text-base", children: formatValue(_state) })] }), _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) })] }), _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("viewStatusEnabled") : t("viewStatusDisabled")] })] })] }) })] }), _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("viewSectionContactInfo") })] }), _jsx(CardDescription, { children: t("viewContactInfoDescription") })] }), _jsx(Separator, {}), _jsx(CardContent, { className: "pt-6", children: _jsxs("div", { className: "grid grid-cols-1 gap-6 md:grid-cols-2", 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("formPhoneLabel") })] }), _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(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 md:col-span-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Globe, { className: "text-muted-foreground h-4 w-4" }), _jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("formWebsiteLabel") })] }), _jsx("p", { className: "text-base", children: formatValue(website) === "—" ? (t("viewTextWebsiteNotProvided")) : (_jsx("a", { href: website, target: "_blank", rel: "noopener noreferrer", className: "text-primary hover:underline", children: website })) })] }), logo && (_jsxs("div", { className: "space-y-1 md:col-span-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Image, { className: "text-muted-foreground h-4 w-4" }), _jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("viewFieldLogo") })] }), _jsx("div", { className: "mt-2", children: _jsx("img", { src: logo, alt: t("viewFieldLogoAlt"), className: "h-16 w-16 rounded border object-contain", onError: (e) => {
|
|
23
23
|
e.currentTarget.style.display = "none";
|
|
24
24
|
} }) })] }))] }) })] }), _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("viewSectionAdministration") })] }), _jsx(CardDescription, { children: t("viewAdministrationDescription") })] }), _jsx(Separator, {}), _jsx(CardContent, { className: "pt-6", children: _jsx("div", { className: "grid grid-cols-1 gap-6 md:grid-cols-2", children: _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(User, { className: "text-muted-foreground h-4 w-4" }), _jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("viewFieldPrincipalId") })] }), _jsx("p", { className: "font-mono text-sm", children: formatValue(principalId) })] }) }) })] })] }));
|
|
25
25
|
};
|
|
@@ -17,7 +17,7 @@ export const SectionFilter = () => {
|
|
|
17
17
|
: filterEnabled
|
|
18
18
|
? "true"
|
|
19
19
|
: "false";
|
|
20
|
-
return (_jsx("div", { className: "space-y-4", children: _jsx("div", { className: "grid grid-cols-1 gap-4", children: _jsx(EnhancedRadio, { label: t("
|
|
20
|
+
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: [
|
|
21
21
|
{ label: t("filterOptionAll"), value: "undefined" },
|
|
22
22
|
{ label: t("filterOptionEnabled"), value: "true" },
|
|
23
23
|
{ label: t("filterOptionDisabled"), value: "false" },
|
|
@@ -10,12 +10,13 @@ import { EnhancedInput } from "@appcorp/shadcn/components/enhanced-input";
|
|
|
10
10
|
import { EnhancedCheckbox } from "@appcorp/shadcn/components/enhanced-checkbox";
|
|
11
11
|
import { useSectionModule } from "./context";
|
|
12
12
|
import { useTranslations } from "next-intl";
|
|
13
|
+
import { getTranslatedError } from "../../utils/get-translated-error";
|
|
13
14
|
export const SectionForm = () => {
|
|
14
15
|
const { state, handleChange } = useSectionModule();
|
|
15
16
|
const { capacity, enabled, errors, name } = state;
|
|
16
17
|
const t = useTranslations("section");
|
|
17
|
-
return (_jsxs("div", { className: "grid grid-cols-1 gap-4", children: [_jsx(EnhancedInput, { error: errors
|
|
18
|
+
return (_jsxs("div", { className: "grid grid-cols-1 gap-4", children: [_jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "name", t }), id: "name", info: t("formSectionNameInfo"), label: t("formSectionNameLabel"), onChange: (e) => handleChange("name", e.target.value), placeholder: t("formSectionNamePlaceholder"), required: true, value: name }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "capacity", t }), id: "capacity", info: t("formCapacityInfo"), label: t("formCapacityLabel"), onChange: (e) => {
|
|
18
19
|
const value = e.target.value;
|
|
19
20
|
handleChange("capacity", value ? Number(value) : 0);
|
|
20
|
-
}, placeholder: t("formCapacityPlaceholder"), type: "number", value: (capacity === null || capacity === void 0 ? void 0 : capacity.toString()) || "" }), _jsx(EnhancedCheckbox, { label: t("
|
|
21
|
+
}, placeholder: t("formCapacityPlaceholder"), type: "number", value: (capacity === null || capacity === void 0 ? void 0 : capacity.toString()) || "" }), _jsx(EnhancedCheckbox, { label: t("formEnabledLabel"), defaultChecked: enabled, onCheckedChange: (checked) => handleChange("enabled", checked), info: t("formEnabledInfo") })] }));
|
|
21
22
|
};
|
|
@@ -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,14 +28,13 @@ interface Props {
|
|
|
27
28
|
drawerMoreActionsTitle: string;
|
|
28
29
|
drawerViewDescription: string;
|
|
29
30
|
drawerViewTitle: string;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
saveLabel: string;
|
|
36
|
-
searchPlaceholder: string;
|
|
31
|
+
tableColumnHeaderActions: string;
|
|
32
|
+
tableColumnHeaderCapacity: string;
|
|
33
|
+
tableColumnHeaderEnabled: string;
|
|
34
|
+
tableColumnHeaderId: string;
|
|
35
|
+
tableColumnHeaderName: string;
|
|
37
36
|
tableDescription: string;
|
|
37
|
+
tableSearchPlaceholder: string;
|
|
38
38
|
tableTitle: string;
|
|
39
39
|
userRole: USER_ROLE;
|
|
40
40
|
}
|
|
@@ -46,18 +46,18 @@ const createComponentInstances = () => ({
|
|
|
46
46
|
moreActions: _jsx(SectionMoreActions, {}),
|
|
47
47
|
view: _jsx(SectionView, {}),
|
|
48
48
|
});
|
|
49
|
-
const createSectionConfig = ({
|
|
49
|
+
const createSectionConfig = ({ dispatch, drawerButtonCancel, drawerButtonSave, drawerFilterDescription, drawerFilterTitle, drawerFormDescription, drawerFormTitle, drawerMoreActionsDescription, drawerMoreActionsTitle, drawerViewDescription, drawerViewTitle, tableColumnHeaderActions, tableColumnHeaderCapacity, tableColumnHeaderEnabled, tableColumnHeaderId, tableColumnHeaderName, tableDescription, tableSearchPlaceholder, tableTitle, }) => {
|
|
50
50
|
const components = createComponentInstances();
|
|
51
51
|
return {
|
|
52
52
|
moduleName: "section",
|
|
53
53
|
tableColumns: [
|
|
54
|
-
{ label:
|
|
55
|
-
{ label:
|
|
56
|
-
{ label:
|
|
57
|
-
{ label:
|
|
58
|
-
{ label:
|
|
54
|
+
{ label: tableColumnHeaderId, width: "5%" },
|
|
55
|
+
{ label: tableColumnHeaderName, width: "30%" },
|
|
56
|
+
{ label: tableColumnHeaderCapacity, width: "25%" },
|
|
57
|
+
{ label: tableColumnHeaderEnabled, width: "15%" },
|
|
58
|
+
{ label: tableColumnHeaderActions, width: "5%" },
|
|
59
59
|
],
|
|
60
|
-
cancelLabel,
|
|
60
|
+
cancelLabel: drawerButtonCancel,
|
|
61
61
|
drawerFilterDescription,
|
|
62
62
|
drawerFilterTitle,
|
|
63
63
|
drawerFormDescription,
|
|
@@ -69,8 +69,8 @@ const createSectionConfig = ({ cancelLabel, dispatch, drawerFilterDescription, d
|
|
|
69
69
|
filterContent: components.filter,
|
|
70
70
|
formContent: components.form,
|
|
71
71
|
moreActionsContent: components.moreActions,
|
|
72
|
-
saveLabel,
|
|
73
|
-
searchPlaceholder,
|
|
72
|
+
saveLabel: drawerButtonSave,
|
|
73
|
+
searchPlaceholder: tableSearchPlaceholder,
|
|
74
74
|
tableDescription,
|
|
75
75
|
tableTitle,
|
|
76
76
|
viewContent: components.view,
|
|
@@ -87,7 +87,8 @@ const SectionPageInner = (props) => {
|
|
|
87
87
|
const context = useSectionModule();
|
|
88
88
|
const sectionConfig = useMemo(() => createSectionConfig({
|
|
89
89
|
dispatch: context.dispatch,
|
|
90
|
-
|
|
90
|
+
drawerButtonCancel: props.drawerButtonCancel,
|
|
91
|
+
drawerButtonSave: props.drawerButtonSave,
|
|
91
92
|
drawerFormTitle: props.drawerFormTitle,
|
|
92
93
|
drawerFormDescription: props.drawerFormDescription,
|
|
93
94
|
drawerViewTitle: props.drawerViewTitle,
|
|
@@ -96,18 +97,18 @@ const SectionPageInner = (props) => {
|
|
|
96
97
|
drawerFilterDescription: props.drawerFilterDescription,
|
|
97
98
|
drawerMoreActionsTitle: props.drawerMoreActionsTitle,
|
|
98
99
|
drawerMoreActionsDescription: props.drawerMoreActionsDescription,
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
saveLabel: props.saveLabel,
|
|
105
|
-
searchPlaceholder: props.searchPlaceholder,
|
|
100
|
+
tableColumnHeaderActions: props.tableColumnHeaderActions,
|
|
101
|
+
tableColumnHeaderCapacity: props.tableColumnHeaderCapacity,
|
|
102
|
+
tableColumnHeaderEnabled: props.tableColumnHeaderEnabled,
|
|
103
|
+
tableColumnHeaderId: props.tableColumnHeaderId,
|
|
104
|
+
tableColumnHeaderName: props.tableColumnHeaderName,
|
|
106
105
|
tableDescription: props.tableDescription,
|
|
106
|
+
tableSearchPlaceholder: props.tableSearchPlaceholder,
|
|
107
107
|
tableTitle: props.tableTitle,
|
|
108
108
|
}), [
|
|
109
109
|
context.dispatch,
|
|
110
|
-
props.
|
|
110
|
+
props.drawerButtonCancel,
|
|
111
|
+
props.drawerButtonSave,
|
|
111
112
|
props.drawerFormTitle,
|
|
112
113
|
props.drawerFormDescription,
|
|
113
114
|
props.drawerViewTitle,
|
|
@@ -116,14 +117,13 @@ const SectionPageInner = (props) => {
|
|
|
116
117
|
props.drawerFilterDescription,
|
|
117
118
|
props.drawerMoreActionsTitle,
|
|
118
119
|
props.drawerMoreActionsDescription,
|
|
119
|
-
props.
|
|
120
|
-
props.
|
|
121
|
-
props.
|
|
122
|
-
props.
|
|
123
|
-
props.
|
|
124
|
-
props.saveLabel,
|
|
125
|
-
props.searchPlaceholder,
|
|
120
|
+
props.tableColumnHeaderActions,
|
|
121
|
+
props.tableColumnHeaderCapacity,
|
|
122
|
+
props.tableColumnHeaderEnabled,
|
|
123
|
+
props.tableColumnHeaderId,
|
|
124
|
+
props.tableColumnHeaderName,
|
|
126
125
|
props.tableDescription,
|
|
126
|
+
props.tableSearchPlaceholder,
|
|
127
127
|
props.tableTitle,
|
|
128
128
|
]);
|
|
129
129
|
const hasPermission = resolveRbacPermissions({
|
|
@@ -4,6 +4,13 @@
|
|
|
4
4
|
* Zod validation schemas for section form data.
|
|
5
5
|
*/
|
|
6
6
|
import { z } from "zod";
|
|
7
|
+
export declare const VALIDATION_KEYS: {
|
|
8
|
+
readonly name: "validationSectionNameRequired";
|
|
9
|
+
readonly nameMaxLength: "validationSectionNameMaxLength";
|
|
10
|
+
readonly nameInvalid: "validationSectionNameInvalid";
|
|
11
|
+
readonly capacityMin: "validationSectionCapacityMin";
|
|
12
|
+
readonly capacityMax: "validationSectionCapacityMax";
|
|
13
|
+
};
|
|
7
14
|
export declare const sectionFormValidation: z.ZodObject<{
|
|
8
15
|
name: z.ZodString;
|
|
9
16
|
capacity: z.ZodNullable<z.ZodOptional<z.ZodNumber>>;
|
|
@@ -5,19 +5,29 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
// ============================================================================
|
|
8
|
+
// VALIDATION KEYS
|
|
9
|
+
// ============================================================================
|
|
10
|
+
export const VALIDATION_KEYS = {
|
|
11
|
+
name: "validationSectionNameRequired",
|
|
12
|
+
nameMaxLength: "validationSectionNameMaxLength",
|
|
13
|
+
nameInvalid: "validationSectionNameInvalid",
|
|
14
|
+
capacityMin: "validationSectionCapacityMin",
|
|
15
|
+
capacityMax: "validationSectionCapacityMax",
|
|
16
|
+
};
|
|
17
|
+
// ============================================================================
|
|
8
18
|
// VALIDATION SCHEMA
|
|
9
19
|
// ============================================================================
|
|
10
20
|
export const sectionFormValidation = z.object({
|
|
11
21
|
name: z
|
|
12
22
|
.string()
|
|
13
|
-
.min(1,
|
|
14
|
-
.max(100,
|
|
15
|
-
.regex(/^[a-zA-Z0-9\s\-_]+$/,
|
|
23
|
+
.min(1, VALIDATION_KEYS.name)
|
|
24
|
+
.max(100, VALIDATION_KEYS.nameMaxLength)
|
|
25
|
+
.regex(/^[a-zA-Z0-9\s\-_]+$/, VALIDATION_KEYS.nameInvalid),
|
|
16
26
|
capacity: z
|
|
17
27
|
.number()
|
|
18
28
|
.int()
|
|
19
|
-
.min(1,
|
|
20
|
-
.max(1000,
|
|
29
|
+
.min(1, VALIDATION_KEYS.capacityMin)
|
|
30
|
+
.max(1000, VALIDATION_KEYS.capacityMax)
|
|
21
31
|
.optional()
|
|
22
32
|
.nullable(),
|
|
23
33
|
enabled: z.boolean().optional(),
|
|
@@ -16,7 +16,7 @@ export const SectionView = () => {
|
|
|
16
16
|
const { state } = useSectionModule();
|
|
17
17
|
const { capacity, enabled, name } = state;
|
|
18
18
|
const t = useTranslations("section");
|
|
19
|
-
return (_jsxs("div", { className: "space-y-4", children: [_jsx(Card, { children: _jsx(CardContent, { className: "pt-6", children: _jsxs("div", { className: "flex items-center gap-6", children: [_jsx("div", { className: "bg-primary/10 flex h-24 w-24 items-center justify-center rounded-full", children: _jsx(Users, { className: "text-primary h-12 w-12" }) }), _jsx("div", { className: "flex-1", children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("h2", { className: "text-2xl font-bold", children: name }), enabled ? (_jsx(CheckCircle2, { className: "h-5 w-5 text-green-500" })) : (_jsx(XCircle, { className: "h-5 w-5 text-red-500" }))] }) })] }) }) }), _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("viewSectionDetails") })] }), _jsx(CardDescription, { children: t("viewSectionCompleteSectionInformation") })] }), _jsx(Separator, {}), _jsx(CardContent, { className: "pt-6", children: _jsxs("div", { className: "grid grid-cols-1 gap-6 md:grid-cols-2", children: [_jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("
|
|
20
|
-
? t("
|
|
21
|
-
: t("
|
|
19
|
+
return (_jsxs("div", { className: "space-y-4", children: [_jsx(Card, { children: _jsx(CardContent, { className: "pt-6", children: _jsxs("div", { className: "flex items-center gap-6", children: [_jsx("div", { className: "bg-primary/10 flex h-24 w-24 items-center justify-center rounded-full", children: _jsx(Users, { className: "text-primary h-12 w-12" }) }), _jsx("div", { className: "flex-1", children: _jsxs("div", { className: "flex items-center gap-3", children: [_jsx("h2", { className: "text-2xl font-bold", children: name }), enabled ? (_jsx(CheckCircle2, { className: "h-5 w-5 text-green-500" })) : (_jsx(XCircle, { className: "h-5 w-5 text-red-500" }))] }) })] }) }) }), _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("viewSectionDetails") })] }), _jsx(CardDescription, { children: t("viewSectionCompleteSectionInformation") })] }), _jsx(Separator, {}), _jsx(CardContent, { className: "pt-6", children: _jsxs("div", { className: "grid grid-cols-1 gap-6 md:grid-cols-2", children: [_jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("formSectionNameLabel") }), _jsx("p", { className: "text-base", children: formatValue(name) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("formCapacityLabel") }), _jsxs("p", { className: "text-base", children: [formatValue(capacity), " ", capacity !== null ? t("viewFieldStudents") : ""] })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("viewFieldStatus") }), _jsx(Badge, { variant: enabled ? "default" : "secondary", children: enabled
|
|
20
|
+
? t("badgeActive")
|
|
21
|
+
: t("badgeInactive") })] })] }) })] })] }));
|
|
22
22
|
};
|
|
@@ -51,7 +51,7 @@ export const StudentFeeFilter = () => {
|
|
|
51
51
|
},
|
|
52
52
|
value: filterStatus || "",
|
|
53
53
|
});
|
|
54
|
-
return (_jsxs("div", { className: "space-y-4", children: [filterStatusCombo, _jsx(EnhancedRadio, { label: t("
|
|
54
|
+
return (_jsxs("div", { className: "space-y-4", children: [filterStatusCombo, _jsx(EnhancedRadio, { label: t("filterEnabledLabel"), name: "filterEnabled", value: filterEnabledValue, options: [
|
|
55
55
|
{ label: t("filterOptionAll"), value: "undefined" },
|
|
56
56
|
{ label: t("filterOptionEnabled"), value: "true" },
|
|
57
57
|
{ label: t("filterOptionDisabled"), value: "false" },
|