@appcorp/fusion-storybook 0.3.59 → 0.3.61
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.
|
@@ -7,7 +7,10 @@ export declare const usePushCampaignModule: () => {
|
|
|
7
7
|
closeDrawer: () => void;
|
|
8
8
|
deleteLoading: boolean;
|
|
9
9
|
handleAiCheck: () => Promise<void>;
|
|
10
|
-
handleChange: (field: string, value: string | number | boolean | undefined | null
|
|
10
|
+
handleChange: (field: string, value: string | number | boolean | undefined | null | Array<{
|
|
11
|
+
classId: string | null;
|
|
12
|
+
sectionId: string | null;
|
|
13
|
+
}>) => void;
|
|
11
14
|
handleCreate: () => void;
|
|
12
15
|
handleDelete: (row?: TableRow) => void;
|
|
13
16
|
handleEdit: (row?: TableRow) => void;
|
|
@@ -4,8 +4,13 @@ import { EnhancedInput } from "@appcorp/shadcn/components/enhanced-input";
|
|
|
4
4
|
import { EnhancedTextarea } from "@appcorp/shadcn/components/enhanced-textarea";
|
|
5
5
|
import { EnhancedCheckbox } from "@appcorp/shadcn/components/enhanced-checkbox";
|
|
6
6
|
import { useTranslations } from "next-intl";
|
|
7
|
+
import { useEffect, useMemo } from "react";
|
|
8
|
+
import { useFetch } from "@react-pakistan/util-functions/hooks/use-fetch";
|
|
9
|
+
import { API_METHODS } from "@react-pakistan/util-functions/constants/api-methods";
|
|
7
10
|
import { usePushCampaignModule } from "./context";
|
|
8
11
|
import { getTranslatedError } from "../../utils/get-translated-error";
|
|
12
|
+
import { CLASS_API_ROUTES, SECTION_API_ROUTES } from "../../constants";
|
|
13
|
+
import { getCachedWorkspaceSync } from "../workspace/cache";
|
|
9
14
|
const getMinScheduleDatetime = () => {
|
|
10
15
|
const d = new Date();
|
|
11
16
|
d.setHours(d.getHours() + 1);
|
|
@@ -15,7 +20,61 @@ const getMinScheduleDatetime = () => {
|
|
|
15
20
|
export const PushCampaignForm = () => {
|
|
16
21
|
const t = useTranslations("pushCampaign");
|
|
17
22
|
const context = usePushCampaignModule();
|
|
18
|
-
const { allStudents, body, errors, enabled, name, scheduledAt, status, title, aiCheckLoading, aiCheckPassed, aiCheckScore, aiSuggestions, } = context.state;
|
|
23
|
+
const { allStudents, audience, body, errors, enabled, name, scheduledAt, status, title, aiCheckLoading, aiCheckPassed, aiCheckScore, aiSuggestions, } = context.state;
|
|
19
24
|
const { handleAiCheck, handleChange, } = context;
|
|
20
|
-
|
|
25
|
+
const workspace = getCachedWorkspaceSync();
|
|
26
|
+
const { fetchNow: classFetchNow, data: classData } = useFetch(CLASS_API_ROUTES.UNIT, { method: API_METHODS.GET, params: { workspaceId: workspace === null || workspace === void 0 ? void 0 : workspace.id } });
|
|
27
|
+
const { fetchNow: sectionFetchNow, data: sectionData } = useFetch(SECTION_API_ROUTES.UNIT, { method: API_METHODS.GET, params: { workspaceId: workspace === null || workspace === void 0 ? void 0 : workspace.id } });
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
if (workspace === null || workspace === void 0 ? void 0 : workspace.id) {
|
|
30
|
+
classFetchNow();
|
|
31
|
+
sectionFetchNow();
|
|
32
|
+
}
|
|
33
|
+
}, [workspace === null || workspace === void 0 ? void 0 : workspace.id]);
|
|
34
|
+
const classes = (classData === null || classData === void 0 ? void 0 : classData.items) || [];
|
|
35
|
+
const sections = (sectionData === null || sectionData === void 0 ? void 0 : sectionData.items) || [];
|
|
36
|
+
const sectionsByClass = useMemo(() => {
|
|
37
|
+
const map = {};
|
|
38
|
+
sections.forEach((s) => {
|
|
39
|
+
var _a;
|
|
40
|
+
const classId = (_a = s.class) === null || _a === void 0 ? void 0 : _a.id;
|
|
41
|
+
if (classId) {
|
|
42
|
+
if (!map[classId])
|
|
43
|
+
map[classId] = [];
|
|
44
|
+
map[classId].push(s);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
return map;
|
|
48
|
+
}, [sections]);
|
|
49
|
+
const isClassChecked = (classId) => audience.some((a) => a.classId === classId);
|
|
50
|
+
const isSectionChecked = (classId, sectionId) => audience.some((a) => a.classId === classId && a.sectionId === sectionId);
|
|
51
|
+
const handleClassToggle = (classId, checked) => {
|
|
52
|
+
if (checked) {
|
|
53
|
+
handleChange("audience", [...audience, { classId, sectionId: null }]);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
handleChange("audience", audience.filter((a) => a.classId !== classId));
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
const handleSectionToggle = (classId, sectionId, checked) => {
|
|
60
|
+
if (checked) {
|
|
61
|
+
const withoutAllSections = audience.filter((a) => !(a.classId === classId && a.sectionId === null));
|
|
62
|
+
handleChange("audience", [
|
|
63
|
+
...withoutAllSections,
|
|
64
|
+
{ classId, sectionId },
|
|
65
|
+
]);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
const filtered = audience.filter((a) => !(a.classId === classId && a.sectionId === sectionId));
|
|
69
|
+
if (!filtered.some((a) => a.classId === classId)) {
|
|
70
|
+
filtered.push({ classId, sectionId: null });
|
|
71
|
+
}
|
|
72
|
+
handleChange("audience", filtered);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
return (_jsxs("div", { className: "space-y-4", children: [_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: "title", t }), id: "title", info: t("formTitleInfo"), label: t("formTitleLabel"), maxLength: 100, onChange: (e) => handleChange("title", e.target.value), placeholder: t("formTitlePlaceholder"), required: true, value: title }), _jsx(EnhancedTextarea, { error: getTranslatedError({ errors, key: "body", t }), id: "body", info: t("formBodyInfo"), label: t("formBodyLabel"), maxLength: 300, onChange: (e) => handleChange("body", e.target.value), placeholder: t("formBodyPlaceholder"), required: true, rows: 4, value: body }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "scheduledAt", t }), id: "scheduledAt", info: t("formScheduledAtInfo"), label: t("formScheduledAtLabel"), min: getMinScheduleDatetime(), onChange: (e) => handleChange("scheduledAt", e.target.value), onClick: (e) => { var _a, _b; return (_b = (_a = e.target) === null || _a === void 0 ? void 0 : _a.showPicker) === null || _b === void 0 ? void 0 : _b.call(_a); }, required: true, type: "datetime-local", value: scheduledAt })] }), _jsxs("div", { className: "space-y-4", children: [_jsx("h3", { className: "text-lg font-semibold", children: t("formSectionAudience") }), _jsx(EnhancedCheckbox, { checked: allStudents, info: t("formAllStudentsInfo"), label: t("formAllStudentsLabel"), onCheckedChange: (checked) => handleChange("allStudents", checked) }), !allStudents && (_jsxs("div", { className: "space-y-3 rounded-md border p-3", children: [_jsx("p", { className: "text-sm text-muted-foreground", children: t("formAudienceSelectLabel") }), _jsxs("div", { className: "space-y-2", children: [classes.map((cls) => {
|
|
76
|
+
const classSections = sectionsByClass[cls.id];
|
|
77
|
+
const checked = isClassChecked(cls.id);
|
|
78
|
+
return (_jsxs("div", { className: "space-y-1", children: [_jsx(EnhancedCheckbox, { checked: checked, label: `${cls.name} (${cls.code})`, onCheckedChange: (c) => handleClassToggle(cls.id, c) }), checked && classSections && classSections.length > 0 && (_jsx("div", { className: "ml-7 space-y-1 border-l-2 pl-3", children: classSections.map((sec) => (_jsx(EnhancedCheckbox, { checked: isSectionChecked(cls.id, sec.id), label: sec.name, onCheckedChange: (c) => handleSectionToggle(cls.id, sec.id, c) }, sec.id))) }))] }, cls.id));
|
|
79
|
+
}), classes.length === 0 && (_jsx("p", { className: "text-sm text-muted-foreground", children: t("formAudienceNoClasses") }))] })] }))] }), _jsxs("div", { className: "space-y-4", children: [_jsx("h3", { className: "text-lg font-semibold", children: t("formSectionAiReview") }), _jsxs("div", { className: "flex items-center gap-4", children: [_jsx("button", { className: "rounded bg-primary px-4 py-2 text-primary-foreground disabled:opacity-50", disabled: aiCheckLoading || !title || !body, onClick: handleAiCheck, type: "button", children: aiCheckLoading ? t("aiCheckRunning") : t("aiCheckButton") }), aiCheckScore !== null && (_jsxs("span", { className: "text-sm font-medium", children: [t("aiCheckScore"), ": ", Math.round(aiCheckScore), "/10", aiCheckPassed ? " ✅" : " ❌"] }))] }), aiSuggestions && (_jsx("p", { className: "text-sm text-muted-foreground whitespace-pre-wrap", children: aiSuggestions }))] }), status && (_jsx("div", { className: "space-y-4", children: _jsx(EnhancedInput, { id: "status", label: t("formStatusLabel"), value: status, disabled: true }) })), _jsx(EnhancedCheckbox, { checked: enabled, info: t("formEnabledInfo"), label: t("formEnabledLabel"), onCheckedChange: (checked) => handleChange("enabled", checked) })] }));
|
|
21
80
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@appcorp/fusion-storybook",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.61",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"build-storybook": "storybook build",
|
|
6
6
|
"build:next": "next build",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
]
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@appcorp/shadcn": "^2.0.
|
|
40
|
+
"@appcorp/shadcn": "^2.0.6",
|
|
41
41
|
"@chromatic-com/storybook": "^5.1.2",
|
|
42
42
|
"@commitlint/cli": "^20.5.0",
|
|
43
43
|
"@commitlint/config-conventional": "^20.5.0",
|