@appcorp/fusion-storybook 0.2.3 → 0.2.5

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.
@@ -27,6 +27,7 @@ import { useDebounce } from "@react-pakistan/util-functions/hooks/use-debounce";
27
27
  import { createGenericModule } from "@react-pakistan/util-functions/factory/generic-module-factory";
28
28
  import { DRAWER_TYPES } from "@react-pakistan/util-functions/factory/generic-component-factory";
29
29
  import { generateThemeToast, TOAST_VARIANT, } from "@appcorp/shadcn/lib/toast-utils";
30
+ import { USER_ROLE } from "../../type";
30
31
  import { RBAC_API_ROUTES, pageLimit } from "./constants";
31
32
  import { getCachedRoles, invalidateRolesCache } from "./cache";
32
33
  import { roleFormValidation } from "./validate";
@@ -452,13 +453,13 @@ export const useRbacModule = () => {
452
453
  order: 1,
453
454
  },
454
455
  {
455
- enabled: true,
456
+ enabled: false,
456
457
  handleOnClick: handleEdit,
457
458
  label: t("actionsButtonEdit"),
458
459
  order: 2,
459
460
  },
460
461
  {
461
- enabled: true,
462
+ enabled: false,
462
463
  handleOnClick: handleDelete,
463
464
  label: t("actionsButtonDelete"),
464
465
  order: 4,
@@ -479,7 +480,7 @@ export const useRbacModule = () => {
479
480
  dispatch({
480
481
  type: RBAC_ACTION_TYPES.SET_ITEMS,
481
482
  payload: {
482
- items: items.filter((item) => item.name !== "SUPER_ADMIN") || [],
483
+ items: items.filter((item) => item.userRole !== USER_ROLE.SUPER_ADMIN) || [],
483
484
  count: count || 0,
484
485
  },
485
486
  });
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Teacher avatar upload utility
3
+ * Handles client-side file validation, WebP conversion, and upload orchestration
4
+ */
5
+ /**
6
+ * Validation error type
7
+ */
8
+ export interface AvatarUploadError {
9
+ type: "size" | "format" | "conversion" | "unknown";
10
+ message: string;
11
+ }
12
+ /**
13
+ * Result of avatar upload process
14
+ */
15
+ export interface AvatarUploadResult {
16
+ success: true;
17
+ fileBase64: string;
18
+ contentType: "image/webp";
19
+ originalFileName: string;
20
+ }
21
+ /**
22
+ * Validate file size and format
23
+ */
24
+ export declare function validateAvatarFile(file: File): AvatarUploadError | null;
25
+ /**
26
+ * Convert image file to WebP format
27
+ */
28
+ export declare function convertToWebPFormat(file: File): Promise<Blob | AvatarUploadError>;
29
+ /**
30
+ * Convert blob to base64 string
31
+ */
32
+ export declare function blobToBase64(blob: Blob): Promise<string>;
33
+ /**
34
+ * Process avatar file: validate, convert to WebP, return base64
35
+ */
36
+ export declare function processAvatarFile(file: File): Promise<AvatarUploadResult | AvatarUploadError>;
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Teacher avatar upload utility
3
+ * Handles client-side file validation, WebP conversion, and upload orchestration
4
+ */
5
+ import { blobToWebP } from "webp-converter-browser";
6
+ // Constants
7
+ const MAX_FILE_SIZE = 100 * 1024; // 100KB in bytes
8
+ const ALLOWED_MIME_TYPES = [
9
+ "image/webp",
10
+ "image/png",
11
+ "image/jpeg",
12
+ "image/jpg",
13
+ "image/gif",
14
+ "image/bmp",
15
+ ];
16
+ /**
17
+ * Validate file size and format
18
+ */
19
+ export function validateAvatarFile(file) {
20
+ // Check file size
21
+ if (file.size > MAX_FILE_SIZE) {
22
+ return {
23
+ type: "size",
24
+ message: `File size must be less than 100KB. Your file is ${Math.round(file.size / 1024)}KB.`,
25
+ };
26
+ }
27
+ // Check MIME type
28
+ if (!ALLOWED_MIME_TYPES.includes(file.type)) {
29
+ return {
30
+ type: "format",
31
+ message: `Unsupported image format. Allowed formats: PNG, JPEG, GIF, BMP, WebP.`,
32
+ };
33
+ }
34
+ return null;
35
+ }
36
+ /**
37
+ * Convert image file to WebP format
38
+ */
39
+ export async function convertToWebPFormat(file) {
40
+ try {
41
+ // blobToWebP expects a Blob, so we use the file directly (File is a Blob)
42
+ const webpBlob = await blobToWebP(file, { quality: 0.8 });
43
+ return webpBlob;
44
+ }
45
+ catch (error) {
46
+ const errorMessage = error instanceof Error
47
+ ? error.message
48
+ : "Unknown error during WebP conversion";
49
+ return {
50
+ type: "conversion",
51
+ message: `Failed to convert image: ${errorMessage}`,
52
+ };
53
+ }
54
+ }
55
+ /**
56
+ * Convert blob to base64 string
57
+ */
58
+ export function blobToBase64(blob) {
59
+ return new Promise((resolve, reject) => {
60
+ const reader = new FileReader();
61
+ reader.onloadend = () => {
62
+ const base64String = reader.result;
63
+ // Remove "data:image/webp;base64," prefix
64
+ const base64 = base64String.split(",")[1];
65
+ resolve(base64);
66
+ };
67
+ reader.onerror = reject;
68
+ reader.readAsDataURL(blob);
69
+ });
70
+ }
71
+ /**
72
+ * Process avatar file: validate, convert to WebP, return base64
73
+ */
74
+ export async function processAvatarFile(file) {
75
+ // Validate file
76
+ const validationError = validateAvatarFile(file);
77
+ if (validationError) {
78
+ return validationError;
79
+ }
80
+ // Convert to WebP
81
+ const conversionResult = await convertToWebPFormat(file);
82
+ if ("type" in conversionResult) {
83
+ // It's an error
84
+ return conversionResult;
85
+ }
86
+ // Convert blob to base64
87
+ try {
88
+ const fileBase64 = await blobToBase64(conversionResult);
89
+ return {
90
+ success: true,
91
+ fileBase64,
92
+ contentType: "image/webp",
93
+ originalFileName: file.name,
94
+ };
95
+ }
96
+ catch (error) {
97
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
98
+ return {
99
+ type: "unknown",
100
+ message: `Failed to encode image: ${errorMessage}`,
101
+ };
102
+ }
103
+ }
@@ -21,3 +21,5 @@ export declare const GENDER_OPTIONS: readonly [{
21
21
  readonly label: "Other";
22
22
  readonly value: "OTHER";
23
23
  }];
24
+ export declare const AVATAR_MAX_FILE_SIZE: number;
25
+ export declare const AVATAR_ALLOWED_MIME_TYPES: readonly ["image/webp", "image/png", "image/jpeg", "image/jpg", "image/gif", "image/bmp"];
@@ -14,7 +14,9 @@ export const pageLimit = Number(process.env.NEXT_PUBLIC_PAGE_LIMIT) || 10;
14
14
  // API ROUTES
15
15
  // ============================================================================
16
16
  export const TEACHER_API_ROUTES = {
17
+ LIST: "/api/v1/teacher",
17
18
  UNIT: "/api/v1/teacher",
19
+ AVATAR: "/api/v1/teacher-avatar",
18
20
  };
19
21
  // ============================================================================
20
22
  // GENDER OPTIONS
@@ -25,3 +27,15 @@ export const GENDER_OPTIONS = [
25
27
  { label: "Female", value: "FEMALE" },
26
28
  { label: "Other", value: "OTHER" },
27
29
  ];
30
+ // ============================================================================
31
+ // AVATAR UPLOAD CONFIGURATION
32
+ // ============================================================================
33
+ export const AVATAR_MAX_FILE_SIZE = 100 * 1024; // 100KB in bytes
34
+ export const AVATAR_ALLOWED_MIME_TYPES = [
35
+ "image/webp",
36
+ "image/png",
37
+ "image/jpeg",
38
+ "image/jpg",
39
+ "image/gif",
40
+ "image/bmp",
41
+ ];
@@ -27,6 +27,7 @@ export declare const TEACHER_ACTION_TYPES: {
27
27
  disableSaveButton: boolean;
28
28
  drawer: string | null;
29
29
  errors: Record<string, string>;
30
+ avatarUploading: boolean;
30
31
  address: string | null;
31
32
  avatar: string | null;
32
33
  bio: string | null;
@@ -59,6 +60,7 @@ export declare const TEACHER_ACTION_TYPES: {
59
60
  disableSaveButton: boolean;
60
61
  drawer: string | null;
61
62
  errors: Record<string, string>;
63
+ avatarUploading: boolean;
62
64
  address: string | null;
63
65
  avatar: string | null;
64
66
  bio: string | null;
@@ -93,6 +95,7 @@ export declare const TEACHER_ACTION_TYPES: {
93
95
  disableSaveButton: boolean;
94
96
  drawer: string | null;
95
97
  errors: Record<string, string>;
98
+ avatarUploading: boolean;
96
99
  address: string | null;
97
100
  avatar: string | null;
98
101
  bio: string | null;
@@ -125,6 +128,7 @@ export declare const TEACHER_ACTION_TYPES: {
125
128
  disableSaveButton: boolean;
126
129
  drawer: string | null;
127
130
  errors: Record<string, string>;
131
+ avatarUploading: boolean;
128
132
  address: string | null;
129
133
  avatar: string | null;
130
134
  bio: string | null;
@@ -157,6 +161,7 @@ export declare const TEACHER_ACTION_TYPES: {
157
161
  disableSaveButton: boolean;
158
162
  drawer: string | null;
159
163
  errors: Record<string, string>;
164
+ avatarUploading: boolean;
160
165
  address: string | null;
161
166
  avatar: string | null;
162
167
  bio: string | null;
@@ -189,6 +194,7 @@ export declare const useTeacherModule: () => {
189
194
  closeDrawer: () => void;
190
195
  deleteLoading: boolean;
191
196
  handleAvatar: (files: File[]) => void;
197
+ handleAvatarUpload: (file: File) => Promise<void>;
192
198
  handleChange: (field: string, value: string | number | boolean | Date | null | undefined) => void;
193
199
  handleCreate: () => void;
194
200
  handleDelete: (row?: TableRow) => void;
@@ -220,6 +226,7 @@ export declare const useTeacherModule: () => {
220
226
  disableSaveButton: boolean;
221
227
  drawer: string | null;
222
228
  errors: Record<string, string>;
229
+ avatarUploading: boolean;
223
230
  address: string | null;
224
231
  avatar: string | null;
225
232
  bio: string | null;
@@ -33,6 +33,7 @@ import { TEACHER_API_ROUTES, pageLimit } from "./constants";
33
33
  import { teacherFormValidation } from "./validate";
34
34
  import { getCachedTeachers, invalidateTeachersCache } from "./cache";
35
35
  import { getCachedWorkspaceSync } from "../workspace/cache";
36
+ import { processAvatarFile } from "./avatar-upload";
36
37
  // ============================================================================
37
38
  // 1.1 DRAWER TYPES
38
39
  // ============================================================================
@@ -58,6 +59,7 @@ const teacherConfig = {
58
59
  disableSaveButton: false,
59
60
  drawer: null,
60
61
  errors: {},
62
+ avatarUploading: false,
61
63
  // Form State
62
64
  address: null,
63
65
  avatar: null,
@@ -352,6 +354,80 @@ export const useTeacherModule = () => {
352
354
  payload: { key: "avatar", value: url },
353
355
  });
354
356
  }, [dispatch]);
357
+ const handleAvatarUpload = useCallback(async (file) => {
358
+ try {
359
+ // Set uploading state
360
+ dispatch({
361
+ type: TEACHER_ACTION_TYPES.SET_INPUT_FIELD,
362
+ payload: { key: "avatarUploading", value: true },
363
+ });
364
+ // Process avatar file (validate, convert to WebP)
365
+ const result = await processAvatarFile(file);
366
+ if ("type" in result) {
367
+ // Error result
368
+ const error = result;
369
+ showToast(error.message, TOAST_VARIANT.ERROR);
370
+ dispatch({
371
+ type: TEACHER_ACTION_TYPES.SET_INPUT_FIELD,
372
+ payload: { key: "avatarUploading", value: false },
373
+ });
374
+ return;
375
+ }
376
+ // Get teacherId from current state (if creating, id will be empty)
377
+ const teacherId = state.id;
378
+ if (!teacherId) {
379
+ showToast("Please save the teacher record first before uploading an avatar", TOAST_VARIANT.ERROR);
380
+ dispatch({
381
+ type: TEACHER_ACTION_TYPES.SET_INPUT_FIELD,
382
+ payload: { key: "avatarUploading", value: false },
383
+ });
384
+ return;
385
+ }
386
+ // Upload to S3 via teacher-avatar endpoint
387
+ const response = await fetch(TEACHER_API_ROUTES.AVATAR, {
388
+ method: "POST",
389
+ headers: {
390
+ "Content-Type": "application/json",
391
+ "x-api-token": process.env.NEXT_PUBLIC_API_KEY,
392
+ },
393
+ body: JSON.stringify({
394
+ teacherId,
395
+ fileBase64: result.fileBase64,
396
+ contentType: result.contentType,
397
+ }),
398
+ });
399
+ if (!response.ok) {
400
+ const errorData = await response.json().catch(() => ({}));
401
+ const errorMessage = errorData.error || `Upload failed with status ${response.status}`;
402
+ showToast(errorMessage, TOAST_VARIANT.ERROR);
403
+ dispatch({
404
+ type: TEACHER_ACTION_TYPES.SET_INPUT_FIELD,
405
+ payload: { key: "avatarUploading", value: false },
406
+ });
407
+ return;
408
+ }
409
+ const data = await response.json();
410
+ const avatarUrl = data.url;
411
+ // Update avatar field with presigned URL
412
+ dispatch({
413
+ type: TEACHER_ACTION_TYPES.SET_INPUT_FIELD,
414
+ payload: { key: "avatar", value: avatarUrl },
415
+ });
416
+ showToast("Avatar uploaded successfully", TOAST_VARIANT.SUCCESS);
417
+ }
418
+ catch (error) {
419
+ const errorMessage = error instanceof Error
420
+ ? error.message
421
+ : "Unknown error uploading avatar";
422
+ showToast(errorMessage, TOAST_VARIANT.ERROR);
423
+ }
424
+ finally {
425
+ dispatch({
426
+ type: TEACHER_ACTION_TYPES.SET_INPUT_FIELD,
427
+ payload: { key: "avatarUploading", value: false },
428
+ });
429
+ }
430
+ }, [state.id, dispatch, showToast, theme]);
355
431
  const applyFilters = useCallback(() => {
356
432
  dispatch({
357
433
  type: TEACHER_ACTION_TYPES.SET_CURRENT_PAGE,
@@ -492,6 +568,7 @@ export const useTeacherModule = () => {
492
568
  closeDrawer,
493
569
  deleteLoading,
494
570
  handleAvatar,
571
+ handleAvatarUpload,
495
572
  handleChange,
496
573
  handleCreate,
497
574
  handleDelete,
@@ -16,15 +16,18 @@ export const TeacherForm = () => {
16
16
  const context = useTeacherModule();
17
17
  const { address, avatar, bio, city, country, dateOfBirth, emergencyPhone, enabled, errors, experience, firstName, gender, joiningDate, lastName, phone, postalCode, qualification, specialization, teacherCode, userId, } = context.state;
18
18
  const stateValue = context.state.state;
19
- const { handleChange } = context;
19
+ const { handleChange, handleAvatarUpload } = context;
20
20
  const users = getCachedUsersSync();
21
- return (_jsxs("div", { className: "space-y-4", children: [_jsx(EnhancedInput, { error: errors.teacherCode, id: "teacherCode", info: t("formUniqueTeacherIdentifierLabel"), label: t("formTeacherCodeLabel"), onChange: (e) => handleChange("teacherCode", e.target.value), placeholder: t("formTeacherCodePlaceholder"), required: true, value: teacherCode }), _jsx(EnhancedInput, { error: errors.firstName, id: "firstName", info: t("formTeachersFirstNameLabel"), label: t("formFirstNameLabel"), onChange: (e) => handleChange("firstName", e.target.value), placeholder: t("formFirstNamePlaceholder"), required: true, value: firstName }), _jsx(EnhancedInput, { error: errors.lastName, id: "lastName", info: t("formTeachersLastNameLabel"), label: t("formLastNameLabel"), onChange: (e) => handleChange("lastName", e.target.value), placeholder: t("formLastNamePlaceholder"), required: true, value: lastName }), _jsx(EnhancedInput, { error: errors.joiningDate, id: "joiningDate", info: t("formDateTeacherJoinedTheSchoolLabel"), label: t("formJoiningDateLabel"), onChange: (e) => handleChange("joiningDate", e.target.value), onClick: (e) => { var _a, _b; return (_b = (_a = e.currentTarget).showPicker) === null || _b === void 0 ? void 0 : _b.call(_a); }, required: true, type: "date", value: joiningDate ? new Date(joiningDate).toISOString().split("formTLabel")[0] : "" }), _jsx(EnhancedCombobox, { emptyText: t("formNoTeacherUsersEmpty"), error: errors.userId, id: "userId", info: t("formLinkedSystemUserLabel"), label: t("formTeacherUserPlaceholder"), onValueChange: (value) => handleChange("userId", value || null), options: (_a = users.items) === null || _a === void 0 ? void 0 : _a.filter(({ workspaces }) => workspaces === null || workspaces === void 0 ? void 0 : workspaces.filter(({ role }) => (role === null || role === void 0 ? void 0 : role.userRole) === USER_ROLE.TEACHER).length).map((u) => ({
21
+ return (_jsxs("div", { className: "space-y-4", children: [_jsx(EnhancedInput, { error: errors.teacherCode, id: "teacherCode", info: t("formUniqueTeacherIdentifierLabel"), label: t("formTeacherCodeLabel"), onChange: (e) => handleChange("teacherCode", e.target.value), placeholder: t("formTeacherCodePlaceholder"), required: true, value: teacherCode }), _jsx(EnhancedInput, { error: errors.firstName, id: "firstName", info: t("formTeachersFirstNameLabel"), label: t("formFirstNameLabel"), onChange: (e) => handleChange("firstName", e.target.value), placeholder: t("formFirstNamePlaceholder"), required: true, value: firstName }), _jsx(EnhancedInput, { error: errors.lastName, id: "lastName", info: t("formTeachersLastNameLabel"), label: t("formLastNameLabel"), onChange: (e) => handleChange("lastName", e.target.value), placeholder: t("formLastNamePlaceholder"), required: true, value: lastName }), _jsx(EnhancedInput, { error: errors.joiningDate, id: "joiningDate", info: t("formDateTeacherJoinedTheSchoolLabel"), label: t("formJoiningDateLabel"), onChange: (e) => handleChange("joiningDate", e.target.value), onClick: (e) => { var _a, _b; return (_b = (_a = e.currentTarget).showPicker) === null || _b === void 0 ? void 0 : _b.call(_a); }, required: true, type: "date", value: joiningDate
22
+ ? new Date(joiningDate).toISOString().split("formTLabel")[0]
23
+ : "" }), _jsx(EnhancedCombobox, { emptyText: t("formNoTeacherUsersEmpty"), error: errors.userId, id: "userId", info: t("formLinkedSystemUserLabel"), label: t("formTeacherUserPlaceholder"), onValueChange: (value) => handleChange("userId", value || null), options: (_a = users.items) === null || _a === void 0 ? void 0 : _a.filter(({ workspaces }) => workspaces === null || workspaces === void 0 ? void 0 : workspaces.filter(({ role }) => (role === null || role === void 0 ? void 0 : role.userRole) === USER_ROLE.TEACHER).length).map((u) => ({
22
24
  label: (u === null || u === void 0 ? void 0 : u.name) || (u === null || u === void 0 ? void 0 : u.email) || u.id,
23
25
  value: u.id,
24
- })), placeholder: t("formSelectLinkedUserPlaceholder"), searchPlaceholder: t("formSearchUsersPlaceholder"), value: userId || "" }), _jsx(EnhancedCombobox, { error: errors.gender, id: "gender", info: t("formTeachersGenderPlaceholder"), label: t("formGenderLabel"), onValueChange: (value) => handleChange("gender", value || null), options: GENDER_OPTIONS.slice(1), value: gender || "" }), _jsx(EnhancedInput, { error: errors.dateOfBirth, id: "dateOfBirth", info: t("formTeachersDateOfBirthLabel"), label: t("formDateOfBirthLabel"), onChange: (e) => handleChange("dateOfBirth", e.target.value), onClick: (e) => { var _a, _b; return (_b = (_a = e.currentTarget).showPicker) === null || _b === void 0 ? void 0 : _b.call(_a); }, type: "date", value: dateOfBirth ? new Date(dateOfBirth).toISOString().split("formTLabel")[0] : "" }), _jsx(EnhancedInput, { error: errors.phone, id: "phone", info: t("formTeachersPhoneNumberLabel"), label: t("formPhoneLabel"), onChange: (e) => handleChange("phone", e.target.value), placeholder: t("formPhonePlaceholder"), type: "tel", value: phone || "" }), _jsx(EnhancedInput, { error: errors.emergencyPhone, id: "emergencyPhone", info: t("formEmergencyContactNumberLabel"), label: t("formEmergencyPhoneLabel"), onChange: (e) => handleChange("emergencyPhone", e.target.value), placeholder: t("formEmergencyPhonePlaceholder"), type: "tel", value: emergencyPhone || "" }), _jsx(EnhancedInput, { error: errors.qualification, id: "qualification", info: t("formTeachersEducationalQualificationLabel"), label: t("formQualificationLabel"), onChange: (e) => handleChange("qualification", e.target.value), placeholder: t("formQualificationPlaceholder"), value: qualification || "" }), _jsx(EnhancedInput, { error: errors.specialization, id: "specialization", info: t("formTeachersAreaOfSpecializationLabel"), label: t("formSpecializationLabel"), onChange: (e) => handleChange("specialization", e.target.value), placeholder: t("formSpecializationPlaceholder"), value: specialization || "" }), _jsx(EnhancedInput, { error: errors.experience, id: "experience", info: t("formYearsOfTeachingExperienceLabel"), label: t("formExperienceLabel"), onChange: (e) => handleChange("experience", parseInt(e.target.value) || null), placeholder: t("formExperiencePlaceholder"), type: "number", value: (experience === null || experience === void 0 ? void 0 : experience.toString()) || "" }), _jsx(EnhancedInput, { error: errors.address, id: "address", info: t("formStreetAddressLabel"), label: t("formAddressLabel"), onChange: (e) => handleChange("address", e.target.value), placeholder: t("formAddressPlaceholder"), value: address || "" }), _jsx(EnhancedInput, { error: errors.city, id: "city", info: t("formCityNameLabel"), label: t("formCityLabel"), onChange: (e) => handleChange("city", e.target.value), placeholder: t("formCityPlaceholder"), value: city || "" }), _jsx(EnhancedInput, { error: errors.state, id: "state", info: t("formStateOrProvinceLabel"), label: t("formStateProvinceLabel"), onChange: (e) => handleChange("state", e.target.value), placeholder: t("formStatePlaceholder"), value: stateValue || "" }), _jsx(EnhancedInput, { error: errors.country, id: "country", info: t("formCountryNameLabel"), label: t("formCountryLabel"), onChange: (e) => handleChange("country", e.target.value), placeholder: t("formCountryPlaceholder"), value: country || "" }), _jsx(EnhancedInput, { error: errors.postalCode, id: "postalCode", info: t("formPostalOrZipCodeLabel"), label: t("formPostalCodeLabel"), onChange: (e) => handleChange("postalCode", e.target.value), placeholder: t("formPostalCodePlaceholder"), value: postalCode || "" }), _jsx(EnhancedDropzone, { accept: ["image/*"], error: errors.avatar, id: "avatar", info: t("formUploadTeachersPhoto"), label: t("formAvatarLabel"), maxFiles: 1, maxSize: 1 * 1024 * 1024, onChange: (files) => {
26
+ })), placeholder: t("formSelectLinkedUserPlaceholder"), searchPlaceholder: t("formSearchUsersPlaceholder"), value: userId || "" }), _jsx(EnhancedCombobox, { error: errors.gender, id: "gender", info: t("formTeachersGenderPlaceholder"), label: t("formGenderLabel"), onValueChange: (value) => handleChange("gender", value || null), options: GENDER_OPTIONS.slice(1), value: gender || "" }), _jsx(EnhancedInput, { error: errors.dateOfBirth, id: "dateOfBirth", info: t("formTeachersDateOfBirthLabel"), label: t("formDateOfBirthLabel"), onChange: (e) => handleChange("dateOfBirth", e.target.value), onClick: (e) => { var _a, _b; return (_b = (_a = e.currentTarget).showPicker) === null || _b === void 0 ? void 0 : _b.call(_a); }, type: "date", value: dateOfBirth
27
+ ? new Date(dateOfBirth).toISOString().split("formTLabel")[0]
28
+ : "" }), _jsx(EnhancedInput, { error: errors.phone, id: "phone", info: t("formTeachersPhoneNumberLabel"), label: t("formPhoneLabel"), onChange: (e) => handleChange("phone", e.target.value), placeholder: t("formPhonePlaceholder"), type: "tel", value: phone || "" }), _jsx(EnhancedInput, { error: errors.emergencyPhone, id: "emergencyPhone", info: t("formEmergencyContactNumberLabel"), label: t("formEmergencyPhoneLabel"), onChange: (e) => handleChange("emergencyPhone", e.target.value), placeholder: t("formEmergencyPhonePlaceholder"), type: "tel", value: emergencyPhone || "" }), _jsx(EnhancedInput, { error: errors.qualification, id: "qualification", info: t("formTeachersEducationalQualificationLabel"), label: t("formQualificationLabel"), onChange: (e) => handleChange("qualification", e.target.value), placeholder: t("formQualificationPlaceholder"), value: qualification || "" }), _jsx(EnhancedInput, { error: errors.specialization, id: "specialization", info: t("formTeachersAreaOfSpecializationLabel"), label: t("formSpecializationLabel"), onChange: (e) => handleChange("specialization", e.target.value), placeholder: t("formSpecializationPlaceholder"), value: specialization || "" }), _jsx(EnhancedInput, { error: errors.experience, id: "experience", info: t("formYearsOfTeachingExperienceLabel"), label: t("formExperienceLabel"), onChange: (e) => handleChange("experience", parseInt(e.target.value) || null), placeholder: t("formExperiencePlaceholder"), type: "number", value: (experience === null || experience === void 0 ? void 0 : experience.toString()) || "" }), _jsx(EnhancedInput, { error: errors.address, id: "address", info: t("formStreetAddressLabel"), label: t("formAddressLabel"), onChange: (e) => handleChange("address", e.target.value), placeholder: t("formAddressPlaceholder"), value: address || "" }), _jsx(EnhancedInput, { error: errors.city, id: "city", info: t("formCityNameLabel"), label: t("formCityLabel"), onChange: (e) => handleChange("city", e.target.value), placeholder: t("formCityPlaceholder"), value: city || "" }), _jsx(EnhancedInput, { error: errors.state, id: "state", info: t("formStateOrProvinceLabel"), label: t("formStateProvinceLabel"), onChange: (e) => handleChange("state", e.target.value), placeholder: t("formStatePlaceholder"), value: stateValue || "" }), _jsx(EnhancedInput, { error: errors.country, id: "country", info: t("formCountryNameLabel"), label: t("formCountryLabel"), onChange: (e) => handleChange("country", e.target.value), placeholder: t("formCountryPlaceholder"), value: country || "" }), _jsx(EnhancedInput, { error: errors.postalCode, id: "postalCode", info: t("formPostalOrZipCodeLabel"), label: t("formPostalCodeLabel"), onChange: (e) => handleChange("postalCode", e.target.value), placeholder: t("formPostalCodePlaceholder"), value: postalCode || "" }), _jsx(EnhancedDropzone, { accept: ["image/*"], error: errors.avatar, id: "avatar", info: t("formUploadTeachersPhoto"), label: t("formAvatarLabel"), maxFiles: 1, maxSize: 100 * 1024, onChange: (files) => {
25
29
  if (files.length > 0) {
26
- const fileUrl = URL.createObjectURL(files[0]);
27
- handleChange("avatar", fileUrl);
30
+ handleAvatarUpload === null || handleAvatarUpload === void 0 ? void 0 : handleAvatarUpload(files[0]);
28
31
  }
29
32
  }, onRemoveRemote: () => handleChange("avatar", null), value: avatar ? [avatar] : [] }), _jsx(EnhancedTextarea, { error: errors.bio, id: "bio", info: t("formBriefBiographyOrDescriptionLabel"), label: t("formBioLabel"), onChange: (e) => handleChange("bio", e.target.value), placeholder: t("formBioPlaceholder"), rows: 4, value: bio || "" }), _jsx(EnhancedCheckbox, { checked: enabled, info: t("actionToggleActivateOrDeactivateTeacher"), label: t("formActiveTeacherLabel"), onCheckedChange: (checked) => handleChange("enabled", checked) })] }));
30
33
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appcorp/fusion-storybook",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "scripts": {
5
5
  "build-storybook": "storybook build",
6
6
  "build:next": "next build",