@appcorp/fusion-storybook 0.3.60 → 0.3.62

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.
@@ -44,6 +44,8 @@ export declare const PUSH_CAMPAIGN_ACTION_TYPES: {
44
44
  }>;
45
45
  filterEnabled: boolean | undefined;
46
46
  filterStatus: string | undefined;
47
+ filterStartDate: string;
48
+ filterEndDate: string;
47
49
  aiCheckPassed: boolean;
48
50
  aiCheckLoading: boolean;
49
51
  aiCheckScore: number | null;
@@ -76,6 +78,8 @@ export declare const PUSH_CAMPAIGN_ACTION_TYPES: {
76
78
  }>;
77
79
  filterEnabled: boolean | undefined;
78
80
  filterStatus: string | undefined;
81
+ filterStartDate: string;
82
+ filterEndDate: string;
79
83
  aiCheckPassed: boolean;
80
84
  aiCheckLoading: boolean;
81
85
  aiCheckScore: number | null;
@@ -110,6 +114,8 @@ export declare const PUSH_CAMPAIGN_ACTION_TYPES: {
110
114
  }>;
111
115
  filterEnabled: boolean | undefined;
112
116
  filterStatus: string | undefined;
117
+ filterStartDate: string;
118
+ filterEndDate: string;
113
119
  aiCheckPassed: boolean;
114
120
  aiCheckLoading: boolean;
115
121
  aiCheckScore: number | null;
@@ -142,6 +148,8 @@ export declare const PUSH_CAMPAIGN_ACTION_TYPES: {
142
148
  }>;
143
149
  filterEnabled: boolean | undefined;
144
150
  filterStatus: string | undefined;
151
+ filterStartDate: string;
152
+ filterEndDate: string;
145
153
  aiCheckPassed: boolean;
146
154
  aiCheckLoading: boolean;
147
155
  aiCheckScore: number | null;
@@ -174,6 +182,8 @@ export declare const PUSH_CAMPAIGN_ACTION_TYPES: {
174
182
  }>;
175
183
  filterEnabled: boolean | undefined;
176
184
  filterStatus: string | undefined;
185
+ filterStartDate: string;
186
+ filterEndDate: string;
177
187
  aiCheckPassed: boolean;
178
188
  aiCheckLoading: boolean;
179
189
  aiCheckScore: number | null;
@@ -36,6 +36,8 @@ const pushCampaignConfig = {
36
36
  audience: [],
37
37
  filterEnabled: undefined,
38
38
  filterStatus: undefined,
39
+ filterStartDate: "",
40
+ filterEndDate: "",
39
41
  aiCheckPassed: false,
40
42
  aiCheckLoading: false,
41
43
  aiCheckScore: null,
@@ -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) => void;
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;
@@ -57,6 +60,8 @@ export declare const usePushCampaignModule: () => {
57
60
  }>;
58
61
  filterEnabled: boolean | undefined;
59
62
  filterStatus: string | undefined;
63
+ filterStartDate: string;
64
+ filterEndDate: string;
60
65
  aiCheckPassed: boolean;
61
66
  aiCheckLoading: boolean;
62
67
  aiCheckScore: number | null;
@@ -22,13 +22,17 @@ export const usePushCampaignModule = () => {
22
22
  const debouncedQuery = useDebounce(state.searchQuery, 800);
23
23
  const listParams = useMemo(() => {
24
24
  var _a;
25
- return (Object.assign(Object.assign(Object.assign({ currentPage: state.currentPage, pageLimit: state.pageLimit, schoolId: ((_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.id) || "" }, (debouncedQuery ? { searchQuery: debouncedQuery } : {})), (state.filterEnabled !== undefined
25
+ return (Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({ currentPage: state.currentPage, pageLimit: state.pageLimit, schoolId: ((_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.id) || "" }, (debouncedQuery ? { searchQuery: debouncedQuery } : {})), (state.filterEnabled !== undefined
26
26
  ? { filterEnabled: String(state.filterEnabled) }
27
- : {})), (state.filterStatus ? { filterStatus: state.filterStatus } : {})));
27
+ : {})), (state.filterStatus ? { filterStatus: state.filterStatus } : {})), (state.filterStartDate
28
+ ? { filterStartDate: state.filterStartDate }
29
+ : {})), (state.filterEndDate ? { filterEndDate: state.filterEndDate } : {})));
28
30
  }, [
29
31
  state.currentPage,
30
32
  state.filterEnabled,
31
33
  state.filterStatus,
34
+ state.filterStartDate,
35
+ state.filterEndDate,
32
36
  state.pageLimit,
33
37
  debouncedQuery,
34
38
  (_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.id,
@@ -343,6 +347,8 @@ export const usePushCampaignModule = () => {
343
347
  filters: {
344
348
  filterEnabled: undefined,
345
349
  filterStatus: undefined,
350
+ filterStartDate: undefined,
351
+ filterEndDate: undefined,
346
352
  },
347
353
  },
348
354
  });
@@ -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
- 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), 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) })] }), _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) })] }));
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.60",
3
+ "version": "0.3.62",
4
4
  "scripts": {
5
5
  "build-storybook": "storybook build",
6
6
  "build:next": "next build",