@appcorp/fusion-storybook 0.2.18 → 0.2.20

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.
@@ -14,9 +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",
18
17
  UNIT: "/api/v1/teacher",
19
18
  AVATAR: "/api/v1/teacher-avatar",
19
+ BULK: "/api/v1/teacher/bulk",
20
20
  };
21
21
  // ============================================================================
22
22
  // GENDER OPTIONS
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { downloadFromUrl } from "@react-pakistan/util-functions";
4
4
  import { showErrorToast, showSuccessToast, } from "@appcorp/shadcn/lib/toast-utils";
5
5
  import { getCachedWorkspaceSync } from "../workspace/cache";
@@ -8,72 +8,101 @@ import { Timeline } from "../../components/timeline";
8
8
  import { useTranslations } from "next-intl";
9
9
  import { CSVS } from "../../constants";
10
10
  import { teacherFormValidation } from "./validate";
11
+ import { TEACHER_API_ROUTES } from "./constants";
12
+ import { invalidateTeachersCache } from "./cache";
13
+ import { useTeacherContext, TEACHER_ACTION_TYPES } from "./context";
11
14
  const workspace = getCachedWorkspaceSync();
12
- export const TeacherMoreActions = () => {
13
- const t = useTranslations("teacher");
14
- const handleBulkCreate = async (files) => {
15
- var _a;
16
- if (!files || files.length === 0)
17
- return;
18
- const file = files[0];
19
- try {
20
- const text = await file.text();
21
- const records = converter.csv2json(text);
22
- if (!Array.isArray(records) || records.length === 0) {
23
- showErrorToast("CSV file is empty or invalid");
24
- return;
25
- }
26
- const errors = [];
27
- const validRecords = [];
28
- for (let i = 0; i < records.length; i++) {
29
- const result = teacherFormValidation.safeParse(records[i]);
30
- if (!result.success) {
31
- errors.push({
32
- row: i + 1,
33
- messages: result.error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`),
34
- });
35
- }
36
- else {
37
- validRecords.push(result.data);
38
- }
39
- }
40
- if (errors.length > 0) {
41
- const summary = errors
42
- .slice(0, 5)
43
- .map((e) => `Row ${e.row}: ${e.messages.join("; ")}`)
44
- .join("\n");
45
- const remaining = errors.length - 5;
46
- showErrorToast(`Validation failed for ${errors.length} row(s).\n${summary}${remaining > 0 ? `\n...and ${remaining} more` : ""}`);
47
- return;
48
- }
49
- const schoolId = ((_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.id) || "";
50
- try {
51
- const response = await fetch("/api/v1/teacher/bulk", {
52
- method: "POST",
53
- headers: {
54
- "Content-Type": "application/json",
55
- "x-api-token": process.env.NEXT_PUBLIC_API_KEY,
56
- },
57
- body: JSON.stringify({
58
- schoolId,
59
- csvData: text,
60
- }),
15
+ const handleGetAllRecords = async (schoolId) => {
16
+ const response = await fetch(`/${TEACHER_API_ROUTES.UNIT}?pageLimit=1000&currentPage=1&schoolId=${schoolId}`);
17
+ const result = await response.json();
18
+ const csv = await converter.json2csv(result.items || [], {});
19
+ const blob = new Blob([csv], { type: "text/csv;charset=utf-8;" });
20
+ await downloadFromUrl(blob, "teacher.csv");
21
+ };
22
+ async function processBulkCsv(files, method) {
23
+ var _a;
24
+ if (!files || files.length === 0)
25
+ return false;
26
+ const file = files[0];
27
+ try {
28
+ const text = await file.text();
29
+ const records = converter.csv2json(text);
30
+ if (!Array.isArray(records) || records.length === 0) {
31
+ showErrorToast("CSV file is empty or invalid");
32
+ return false;
33
+ }
34
+ const errors = [];
35
+ for (let i = 0; i < records.length; i++) {
36
+ const result = teacherFormValidation.safeParse(records[i]);
37
+ if (!result.success) {
38
+ errors.push({
39
+ row: i + 1,
40
+ messages: result.error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`),
61
41
  });
62
- if (response.ok) {
63
- showSuccessToast(`Successfully created ${validRecords.length} teacher(s)`);
64
- }
65
- else {
66
- const errorData = await response.json().catch(() => ({}));
67
- showErrorToast(errorData.error ||
68
- `Bulk create failed with status ${response.status}`);
69
- }
70
42
  }
71
- catch (_b) {
72
- showErrorToast("Network error during bulk create");
43
+ }
44
+ if (errors.length > 0) {
45
+ const summary = errors
46
+ .slice(0, 5)
47
+ .map((e) => `Row ${e.row}: ${e.messages.join("; ")}`)
48
+ .join("\n");
49
+ const remaining = errors.length - 5;
50
+ showErrorToast(`Validation failed for ${errors.length} row(s).\n${summary}${remaining > 0 ? `\n...and ${remaining} more` : ""}`);
51
+ return false;
52
+ }
53
+ const schoolId = ((_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.id) || "";
54
+ try {
55
+ const response = await fetch(TEACHER_API_ROUTES.BULK, {
56
+ method,
57
+ headers: {
58
+ "Content-Type": "application/json",
59
+ "x-api-token": process.env.NEXT_PUBLIC_API_KEY,
60
+ },
61
+ body: JSON.stringify({
62
+ schoolId,
63
+ csvData: text,
64
+ }),
65
+ });
66
+ if (response.ok) {
67
+ showSuccessToast(`Successfully processed ${records.length} teacher(s)`);
68
+ return true;
73
69
  }
70
+ const errorData = await response.json().catch(() => ({}));
71
+ showErrorToast(errorData.error ||
72
+ `Bulk operation failed with status ${response.status}`);
73
+ return false;
74
74
  }
75
- catch (error) {
76
- showErrorToast(`Failed to process CSV: ${error instanceof Error ? error.message : "Unknown error"}`);
75
+ catch (_b) {
76
+ showErrorToast("Network error during bulk operation");
77
+ return false;
78
+ }
79
+ }
80
+ catch (error) {
81
+ showErrorToast(`Failed to process CSV: ${error instanceof Error ? error.message : "Unknown error"}`);
82
+ return false;
83
+ }
84
+ }
85
+ export const TeacherMoreActions = () => {
86
+ const t = useTranslations("teacher");
87
+ const { dispatch } = useTeacherContext();
88
+ const closeDrawer = () => {
89
+ dispatch({
90
+ type: TEACHER_ACTION_TYPES.SET_DRAWER,
91
+ payload: { drawer: null },
92
+ });
93
+ };
94
+ const handleBulkCreate = async (files) => {
95
+ const ok = await processBulkCsv(files, "POST");
96
+ if (ok) {
97
+ invalidateTeachersCache();
98
+ closeDrawer();
99
+ }
100
+ };
101
+ const handleBulkUpdate = async (files) => {
102
+ const ok = await processBulkCsv(files, "PUT");
103
+ if (ok) {
104
+ invalidateTeachersCache();
105
+ closeDrawer();
77
106
  }
78
107
  };
79
108
  const create = [
@@ -90,5 +119,20 @@ export const TeacherMoreActions = () => {
90
119
  title: t("moreActionsUploadTheCompletedCsvToTheSystem"),
91
120
  },
92
121
  ];
93
- return (_jsx("div", { className: "space-y-4", children: _jsx(Timeline, { events: create, heading: t("moreActionsBulkCreate"), handleOnBulkCreate: handleBulkCreate }) }));
122
+ const update = [
123
+ {
124
+ id: "1",
125
+ title: t("moreActionsDownloadPopulatedCsvTemplate"),
126
+ handleOnClick: async () => {
127
+ var _a;
128
+ await handleGetAllRecords(((_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.id) || "");
129
+ },
130
+ },
131
+ { id: "2", title: t("moreActionsUpdateYourDataToTheCsv") },
132
+ {
133
+ id: "3",
134
+ title: t("moreActionsUploadTheCompletedCsvToTheSystem"),
135
+ },
136
+ ];
137
+ return (_jsxs("div", { className: "space-y-4", children: [_jsx(Timeline, { events: create, heading: t("moreActionsBulkCreate"), handleOnBulkCreate: handleBulkCreate }), _jsx(Timeline, { events: update, heading: t("moreActionsBulkUpdate"), handleOnBulkCreate: handleBulkUpdate })] }));
94
138
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appcorp/fusion-storybook",
3
- "version": "0.2.18",
3
+ "version": "0.2.20",
4
4
  "scripts": {
5
5
  "build-storybook": "storybook build",
6
6
  "build:next": "next build",