@skalfa/skalfa-component 1.0.9 → 1.0.11
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/dist/modal/ModalConfirm.component.js +5 -3
- package/dist/nav/Tabbar.component.js +1 -3
- package/dist/supervision/FormSupervision.component.js +5 -2
- package/dist/supervision/TableSupervision.component.js +16 -16
- package/dist/table/ControlBar.component.js +14 -12
- package/dist/table/FilterComponent.js +15 -12
- package/dist/table/Table.component.js +4 -2
- package/dist/wrap/ShortcutProvider.js +4 -2
- package/package.json +1 -1
- package/src/modal/ModalConfirm.component.tsx +6 -4
- package/src/nav/Footer.component.tsx +9 -9
- package/src/nav/Navbar.component.tsx +6 -6
- package/src/nav/Tabbar.component.tsx +1 -3
- package/src/supervision/FormSupervision.component.tsx +9 -5
- package/src/supervision/TableSupervision.component.tsx +26 -27
- package/src/table/ControlBar.component.tsx +15 -13
- package/src/table/FilterComponent.tsx +22 -17
- package/src/table/Table.component.tsx +6 -3
- package/src/wrap/ShortcutProvider.tsx +4 -2
|
@@ -7,8 +7,10 @@ const react_1 = require("react");
|
|
|
7
7
|
const _utils_1 = require("@utils");
|
|
8
8
|
const _components_1 = require("@components");
|
|
9
9
|
const skalfa_icon_1 = require("@skalfa/skalfa-icon");
|
|
10
|
+
const skalfa_lang_1 = require("@skalfa/skalfa-lang");
|
|
10
11
|
;
|
|
11
12
|
function ModalConfirmComponent({ show, title, children, footer, submitControl, onClose, className = "", }) {
|
|
13
|
+
const l = (0, skalfa_lang_1.useLang)();
|
|
12
14
|
const { isSm } = (0, _utils_1.useResponsive)();
|
|
13
15
|
const [toast, setToast] = (0, react_1.useState)(false);
|
|
14
16
|
const [loading, setLoading] = (0, react_1.useState)(false);
|
|
@@ -28,12 +30,12 @@ function ModalConfirmComponent({ show, title, children, footer, submitControl, o
|
|
|
28
30
|
}, [show]);
|
|
29
31
|
const renderChildren = (actionSize = 'md') => {
|
|
30
32
|
if (toast == "success") {
|
|
31
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-center justify-center h-full py-6 transition-all duration-300 animate-intro-down", children: [(0, jsx_runtime_1.jsx)("div", { className: "w-12 h-12 rounded-full bg-blue-50 flex items-center justify-center", children: (0, jsx_runtime_1.jsx)(skalfa_icon_1.Icon, { icon: "solid/check", className: "text-primary text-2xl" }) }), (0, jsx_runtime_1.jsx)("p", { className: "text-primary text-lg font-semibold mt-4", children: "
|
|
33
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-center justify-center h-full py-6 transition-all duration-300 animate-intro-down", children: [(0, jsx_runtime_1.jsx)("div", { className: "w-12 h-12 rounded-full bg-blue-50 flex items-center justify-center", children: (0, jsx_runtime_1.jsx)(skalfa_icon_1.Icon, { icon: "solid/check", className: "text-primary text-2xl" }) }), (0, jsx_runtime_1.jsx)("p", { className: "text-primary text-lg font-semibold mt-4", children: l.base.success ? l.base.success() : "Success" })] }));
|
|
32
34
|
}
|
|
33
|
-
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [title && ((0, jsx_runtime_1.jsx)("div", { className: (0, _utils_1.cn)("flex flex-col gap-2 p-6", (0, _utils_1.pcn)(className, "header")), children: (0, jsx_runtime_1.jsx)("h6", { className: "font-semibold text-lg", children: title }) })), children, toast == "failed" && ((0, jsx_runtime_1.jsx)("div", { className: "px-4", children: (0, jsx_runtime_1.jsxs)("div", { className: "mt-4 w-full p-4 rounded-sm border border-danger bg-light-danger flex gap-4 items-center", children: [(0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)("div", { className: "w-10 h-10 rounded-full bg-danger/20 flex items-center justify-center", children: (0, jsx_runtime_1.jsx)(skalfa_icon_1.Icon, { icon: "solid/exclamation-triangle", className: "text-danger text-lg" }) }) }), (0, jsx_runtime_1.jsx)("p", { className: "text-danger text-sm font-semibold", children:
|
|
35
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [title && ((0, jsx_runtime_1.jsx)("div", { className: (0, _utils_1.cn)("flex flex-col gap-2 p-6", (0, _utils_1.pcn)(className, "header")), children: (0, jsx_runtime_1.jsx)("h6", { className: "font-semibold text-lg", children: title }) })), children, toast == "failed" && ((0, jsx_runtime_1.jsx)("div", { className: "px-4", children: (0, jsx_runtime_1.jsxs)("div", { className: "mt-4 w-full p-4 rounded-sm border border-danger bg-light-danger flex gap-4 items-center", children: [(0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)("div", { className: "w-10 h-10 rounded-full bg-danger/20 flex items-center justify-center", children: (0, jsx_runtime_1.jsx)(skalfa_icon_1.Icon, { icon: "solid/exclamation-triangle", className: "text-danger text-lg" }) }) }), (0, jsx_runtime_1.jsx)("p", { className: "text-danger text-sm font-semibold", children: l.base.confirmFailed ? l.base.confirmFailed() : "Failed" })] }) })), renderAction(actionSize)] }));
|
|
34
36
|
};
|
|
35
37
|
const renderAction = (size = 'md') => {
|
|
36
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className: "flex justify-center gap-4 p-6 pt-2", children: [(0, jsx_runtime_1.jsx)(_components_1.ButtonComponent, { label: "
|
|
38
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: "flex justify-center gap-4 p-6 pt-2", children: [(0, jsx_runtime_1.jsx)(_components_1.ButtonComponent, { label: l.base.cancel ? l.base.cancel() : "", variant: "outline", onClick: () => onClose(), block: true, size: size }), (0, jsx_runtime_1.jsx)(_components_1.ButtonComponent, { label: l.base.confirm ? l.base.confirm() : "", loading: loading, onClick: async () => {
|
|
37
39
|
if (!submitControl?.onSubmit)
|
|
38
40
|
return;
|
|
39
41
|
setLoading(true);
|
|
@@ -10,8 +10,6 @@ function TabbarComponent({ items, onChange, active,
|
|
|
10
10
|
className = "", }) {
|
|
11
11
|
return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)("div", { className: (0, _utils_1.cn)("tabbar-base", (0, _utils_1.pcn)(className, "base")), children: items?.map((item, i) => {
|
|
12
12
|
const isItemActive = active == (typeof item != "string" ? item?.value : item);
|
|
13
|
-
return ((0, jsx_runtime_1.jsx)("div", { className: (0, _utils_1.cn)("tabbar-item", isItemActive
|
|
14
|
-
? "tabbar-item-active"
|
|
15
|
-
: "tabbar-item-inactive", (0, _utils_1.pcn)(className, "item"), (0, _utils_1.pcn)(className, "active")), onClick: () => onChange?.(typeof item != "string" ? item?.value : item), children: typeof item != "string" ? item?.label : item }, i));
|
|
13
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: (0, _utils_1.cn)("tabbar-item", isItemActive ? "tabbar-item-active" : "tabbar-item-inactive", (0, _utils_1.pcn)(className, "item"), (0, _utils_1.pcn)(className, "active")), onClick: () => onChange?.(typeof item != "string" ? item?.value : item), children: typeof item != "string" ? item?.label : item }, i));
|
|
16
14
|
}) }) }));
|
|
17
15
|
}
|
|
@@ -116,7 +116,7 @@ function FormSupervisionComponent({ title, fields, submitControl, confirmation,
|
|
|
116
116
|
});
|
|
117
117
|
setValues(updatedValues);
|
|
118
118
|
};
|
|
119
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, _utils_1.cn)("flex flex-col gap-4", generateColClass(form.col || "12")), children: [group.map((gIndex) => ((0, jsx_runtime_1.jsxs)("div", { className: (0, _utils_1.cn)("relative pr-8", wrap && "p-4 rounded border", className), children: [label && (0, jsx_runtime_1.jsxs)("p", { className: "input-label", children: [label, " ", gIndex + 1] }), tip && (0, jsx_runtime_1.jsx)("small", { className: (0, _utils_1.cn)("input-tip"), children: tip }), (label || tip) && (0, jsx_runtime_1.jsx)("div", { className: "mb-2" }), (0, jsx_runtime_1.jsx)("div", { className: "w-full grid grid-cols-12 gap-4", children: innerForms.map((inner, i) => renderInput(inner, i, `${mapName}[${gIndex}]`)) }), (0, jsx_runtime_1.jsx)(__1.ButtonComponent, { icon: "solid/times", paint: "danger", variant: "outline", size: "xs", className: (0, _utils_1.cn)("absolute top-10 right-2 translate-x-[50%] -translate-y-[50%]", wrap && "translate-x-0 -translate-y-0 top-1 right-1"), onClick: () => removeGroup(gIndex) })] }, gIndex))), (0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)(__1.ButtonComponent, { icon: "solid/plus", label:
|
|
119
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, _utils_1.cn)("flex flex-col gap-4", generateColClass(form.col || "12")), children: [group.map((gIndex) => ((0, jsx_runtime_1.jsxs)("div", { className: (0, _utils_1.cn)("relative pr-8", wrap && "p-4 rounded border", className), children: [label && (0, jsx_runtime_1.jsxs)("p", { className: "input-label", children: [label, " ", gIndex + 1] }), tip && (0, jsx_runtime_1.jsx)("small", { className: (0, _utils_1.cn)("input-tip"), children: tip }), (label || tip) && (0, jsx_runtime_1.jsx)("div", { className: "mb-2" }), (0, jsx_runtime_1.jsx)("div", { className: "w-full grid grid-cols-12 gap-4", children: innerForms.map((inner, i) => renderInput(inner, i, `${mapName}[${gIndex}]`)) }), (0, jsx_runtime_1.jsx)(__1.ButtonComponent, { icon: "solid/times", paint: "danger", variant: "outline", size: "xs", className: (0, _utils_1.cn)("absolute top-10 right-2 translate-x-[50%] -translate-y-[50%]", wrap && "translate-x-0 -translate-y-0 top-1 right-1"), onClick: () => removeGroup(gIndex) })] }, gIndex))), (0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)(__1.ButtonComponent, { icon: "solid/plus", label: `${l.base.add ? l.base.add() : "Add"} ${label || mapName}`, variant: "outline", size: "sm", onClick: addGroup }) })] }, key));
|
|
120
120
|
}
|
|
121
121
|
if (inputType === "custom") {
|
|
122
122
|
const customRender = form.construction;
|
|
@@ -125,5 +125,8 @@ function FormSupervisionComponent({ title, fields, submitControl, confirmation,
|
|
|
125
125
|
const Component = inputMap[inputType] || __1.InputComponent;
|
|
126
126
|
return ((0, jsx_runtime_1.jsx)("div", { className: (0, _utils_1.cn)(form.className, generateColClass(form.col || "12")), children: (0, jsx_runtime_1.jsx)(Component, { ...form.construction, ...formControl(name) }) }, key));
|
|
127
127
|
};
|
|
128
|
-
|
|
128
|
+
(0, react_1.useEffect)(() => {
|
|
129
|
+
setModal(false);
|
|
130
|
+
}, [values]);
|
|
131
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [title && (0, jsx_runtime_1.jsx)("h4", { className: (0, _utils_1.cn)("text-lg font-semibold mb-4", (0, _utils_1.pcn)(className, "title")), children: title }), modal == "success" ? ((0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col items-center justify-center h-full py-6 transition-all duration-300 animate-intro-down", children: [(0, jsx_runtime_1.jsx)("div", { className: "w-12 h-12 rounded-full bg-blue-50 flex items-center justify-center", children: (0, jsx_runtime_1.jsx)(skalfa_icon_1.Icon, { icon: "solid/check", className: "text-primary text-2xl" }) }), (0, jsx_runtime_1.jsx)("p", { className: "text-primary text-lg font-semibold mt-4", children: successMessage || l.base?.success ? l.base.success() : "Success!" })] })) : ((0, jsx_runtime_1.jsx)("form", { id: id, className: (0, _utils_1.cn)("flex flex-col h-full pb-8"), onSubmit: submit, children: (0, jsx_runtime_1.jsxs)("div", { className: (0, _utils_1.cn)("grid grid-cols-12 gap-4 flex-1 content-start", (0, _utils_1.pcn)(className, "base")), children: [fresh && fields.map((f, i) => renderInput(f, i)), !footerControl && ((0, jsx_runtime_1.jsx)("div", { className: "hidden md:block col-span-12", children: (0, jsx_runtime_1.jsx)("div", { className: "flex justify-end mt-4", children: (0, jsx_runtime_1.jsx)(__1.ButtonComponent, { type: "submit", label: l.base?.save ? l.base.save() : "Save", icon: "solid/save", loading: loading, className: (0, _utils_1.pcn)(className, "submit") }) }) })), !footerControl && ((0, jsx_runtime_1.jsx)("div", { className: "md:hidden col-span-12 mt-4", children: (0, jsx_runtime_1.jsx)(__1.ButtonComponent, { label: l.base?.save ? l.base.save() : "Save", icon: "solid/save", type: "submit", loading: loading, block: true, className: (0, _utils_1.pcn)(className, "submit") }) })), footerControl && ((0, jsx_runtime_1.jsx)("div", { className: "col-span-12", children: footerControl?.({ loading }) })), modal == "failed" && ((0, jsx_runtime_1.jsxs)("div", { className: "col-span-12 mt-4 w-full p-4 rounded-sm border border-danger bg-light-danger flex gap-4 items-center", children: [(0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)("div", { className: "w-10 h-10 rounded-full bg-danger/20 flex items-center justify-center", children: (0, jsx_runtime_1.jsx)(skalfa_icon_1.Icon, { icon: "solid/exclamation-triangle", className: "text-danger text-lg" }) }) }), (0, jsx_runtime_1.jsx)("p", { className: "text-danger text-sm font-semibold", children: l.base.formFailed ? l.base.formFailed() : "Failed to save data, please check your data and internet connection then try again!" })] }))] }) })), (0, jsx_runtime_1.jsx)(__1.ModalConfirmComponent, { show: confirm.show, onClose: () => confirm.onClose(), title: l.base?.formConfirm ? l.base.formConfirm() : "Are you sure all data is correct?", submitControl: { onSubmit: () => confirm?.onConfirm(), paint: "primary" } })] }));
|
|
129
132
|
}
|
|
@@ -23,26 +23,26 @@ function TableSupervisionComponent({ title, id, fetchControl, columnControl, for
|
|
|
23
23
|
_utils_1.shortcut.register("arrowdown", () => {
|
|
24
24
|
const max = data?.data?.length - 1;
|
|
25
25
|
setFocus(focus == null ? 0 : focus >= max ? max : (focus + 1));
|
|
26
|
-
},
|
|
26
|
+
}, l.base.shortcutDown ? l.base.shortcutDown() : "");
|
|
27
27
|
_utils_1.shortcut.register("arrowup", () => {
|
|
28
28
|
setFocus(focus == null ? 0 : focus <= 0 ? 0 : (focus - 1));
|
|
29
|
-
},
|
|
29
|
+
}, l.base.shortcutUp ? l.base.shortcutUp() : "");
|
|
30
30
|
if (focus != null) {
|
|
31
31
|
_utils_1.shortcut.register("delete", () => {
|
|
32
32
|
setSelected(data?.data?.at(focus));
|
|
33
33
|
setToggle(`MODAL_DELETE_${toggleKey}`);
|
|
34
|
-
},
|
|
34
|
+
}, l.base.shortcutDelete ? l.base.shortcutDelete() : "");
|
|
35
35
|
_utils_1.shortcut.register(" ", () => {
|
|
36
36
|
setSelected(data?.data?.at(focus));
|
|
37
37
|
setToggle(`MODAL_FORM_${toggleKey}`);
|
|
38
|
-
},
|
|
38
|
+
}, l.base.shortcutEdit ? l.base.shortcutEdit() : "");
|
|
39
39
|
_utils_1.shortcut.register("enter", () => {
|
|
40
40
|
setSelected(data?.data?.at(focus));
|
|
41
41
|
setToggle(`MODAL_SHOW_${toggleKey}`);
|
|
42
|
-
},
|
|
42
|
+
}, l.base.shortcutDetail ? l.base.shortcutDetail() : "");
|
|
43
43
|
_utils_1.shortcut.register("escape", () => {
|
|
44
44
|
setFocus(null);
|
|
45
|
-
}, "
|
|
45
|
+
}, l.base.shortcutBack ? l.base.shortcutBack() : "");
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
return () => {
|
|
@@ -166,7 +166,7 @@ function TableSupervisionComponent({ title, id, fetchControl, columnControl, for
|
|
|
166
166
|
construction: {
|
|
167
167
|
name: typeof col == "string" ? col : col?.selector,
|
|
168
168
|
label: typeof col == "string" ? col : col?.label,
|
|
169
|
-
placeholder: `
|
|
169
|
+
placeholder: l.base.inputPlaceholder ? l.base.inputPlaceholder(`${typeof col == "string" ? col : col?.label}`) : `Enter ${typeof col == "string" ? col : col?.label}...`,
|
|
170
170
|
},
|
|
171
171
|
};
|
|
172
172
|
}) || (data?.data?.at(0) ? Object.keys(data.data[0]).map((col) => {
|
|
@@ -176,7 +176,7 @@ function TableSupervisionComponent({ title, id, fetchControl, columnControl, for
|
|
|
176
176
|
construction: {
|
|
177
177
|
name: col,
|
|
178
178
|
label: col,
|
|
179
|
-
placeholder: `
|
|
179
|
+
placeholder: l.base.inputPlaceholder ? l.base.inputPlaceholder(col) : `Enter ${col}...`,
|
|
180
180
|
},
|
|
181
181
|
};
|
|
182
182
|
})
|
|
@@ -205,24 +205,24 @@ function TableSupervisionComponent({ title, id, fetchControl, columnControl, for
|
|
|
205
205
|
if (cb == "CREATE") {
|
|
206
206
|
if (isSm)
|
|
207
207
|
return;
|
|
208
|
-
return ((0, jsx_runtime_1.jsx)("div", { className: "pl-1.5 pr-3 mr-2 border-r", children: (0, jsx_runtime_1.jsx)(__1.ButtonComponent, { icon: "solid/plus", label:
|
|
208
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: "pl-1.5 pr-3 mr-2 border-r", children: (0, jsx_runtime_1.jsx)(__1.ButtonComponent, { icon: "solid/plus", label: l.base.add ? l.base.add() : "Add", size: "sm", onClick: () => {
|
|
209
209
|
setToggle(`MODAL_FORM_${toggleKey}`);
|
|
210
210
|
setSelected(null);
|
|
211
211
|
} }) }, "button-add"));
|
|
212
212
|
}
|
|
213
213
|
if (cb == "IMPORT") {
|
|
214
|
-
return ((0, jsx_runtime_1.jsx)("div", { className: "px-1.5 rounded-md relative", children: (0, jsx_runtime_1.jsx)(__1.ButtonComponent, { icon: "solid/file-excel",
|
|
214
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: "px-1.5 rounded-md relative", children: (0, jsx_runtime_1.jsx)(__1.ButtonComponent, { icon: "solid/file-excel", variant: "outline", className: "!text-foreground", onClick: () => setToggle(`MODAL_IMPORT_${toggleKey}`), size: "sm" }) }, "import"));
|
|
215
215
|
}
|
|
216
216
|
if (cb == "EXPORT") {
|
|
217
|
-
return ((0, jsx_runtime_1.jsx)("div", { className: "px-1.5 rounded-md relative", children: (0, jsx_runtime_1.jsx)(__1.ButtonComponent, { icon: "solid/file-excel",
|
|
217
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: "px-1.5 rounded-md relative", children: (0, jsx_runtime_1.jsx)(__1.ButtonComponent, { icon: "solid/file-excel", variant: "outline", className: "!text-foreground", onClick: () => setToggle(`MODAL_EXPORT_${toggleKey}`), size: "sm" }) }, "export-excel"));
|
|
218
218
|
}
|
|
219
219
|
if (cb == "PRINT") {
|
|
220
|
-
return ((0, jsx_runtime_1.jsx)("div", { className: "px-1.5 rounded-md relative", children: (0, jsx_runtime_1.jsx)(__1.ButtonComponent, { icon: "solid/file-pdf", label: "
|
|
220
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: "px-1.5 rounded-md relative", children: (0, jsx_runtime_1.jsx)(__1.ButtonComponent, { icon: "solid/file-pdf", label: l.base.print ? l.base.print() : "Print", variant: "outline", className: "!text-foreground", onClick: () => setToggle(`MODAL_PRINT_${toggleKey}`), size: "sm" }) }, "export-pdf"));
|
|
221
221
|
}
|
|
222
222
|
return cb;
|
|
223
223
|
}) || [
|
|
224
224
|
...(!isSm ? [
|
|
225
|
-
(0, jsx_runtime_1.jsx)("div", { className: "pl-1.5 pr-3 mr-2 border-r", children: (0, jsx_runtime_1.jsx)(__1.ButtonComponent, { icon: "solid/plus", label:
|
|
225
|
+
(0, jsx_runtime_1.jsx)("div", { className: "pl-1.5 pr-3 mr-2 border-r", children: (0, jsx_runtime_1.jsx)(__1.ButtonComponent, { icon: "solid/plus", label: l.base.add ? l.base.add() : "Add", size: "sm", onClick: () => {
|
|
226
226
|
setToggle(`MODAL_FORM_${toggleKey}`);
|
|
227
227
|
setSelected(null);
|
|
228
228
|
} }) }, "button-add")
|
|
@@ -255,13 +255,13 @@ function TableSupervisionComponent({ title, id, fetchControl, columnControl, for
|
|
|
255
255
|
} : undefined, ...tableControl }), controlBar?.find((cb) => cb == "CREATE") && ((0, jsx_runtime_1.jsx)(__1.ButtonComponent, { icon: "solid/plus", className: "fixed bottom-24 right-4 w-14 h-14 z-20 md:hidden", size: "lg", rounded: true, onClick: () => {
|
|
256
256
|
setToggle(`MODAL_FORM_${toggleKey}`);
|
|
257
257
|
setSelected(null);
|
|
258
|
-
} })), (0, jsx_runtime_1.jsx)(__1.FloatingPageComponent, { show: !!toggle[`MODAL_SHOW_${toggleKey}`], onClose: () => setToggle(`MODAL_SHOW_${toggleKey}`, false), title: "Detail", className: "bg-background", footer: renderTableAction(actionControl, undefined, { className: isSm ? "justify-end p-2 bg-background" : "justify-end", size: isSm ? "sm" : "md" }), children: detailPage }), (0, jsx_runtime_1.jsx)(__1.FloatingPageComponent, { show: !!toggle[`MODAL_FORM_${toggleKey}`], onClose: () => setToggle(`MODAL_FORM_${toggleKey}`, false), title: !!selected ?
|
|
258
|
+
} })), (0, jsx_runtime_1.jsx)(__1.FloatingPageComponent, { show: !!toggle[`MODAL_SHOW_${toggleKey}`], onClose: () => setToggle(`MODAL_SHOW_${toggleKey}`, false), title: l.base.detailTitle ? l.base.detailTitle() : "Detail", className: "bg-background", footer: renderTableAction(actionControl, undefined, { className: isSm ? "justify-end p-2 bg-background" : "justify-end", size: isSm ? "sm" : "md" }), children: detailPage }), (0, jsx_runtime_1.jsx)(__1.FloatingPageComponent, { show: !!toggle[`MODAL_FORM_${toggleKey}`], onClose: () => setToggle(`MODAL_FORM_${toggleKey}`, false), title: !!selected ? (l.base.editTitle ? l.base.editTitle() : "Edit") : (l.base.addTitle ? l.base.addTitle() : "Add"), className: (0, _utils_1.cn)("bg-white", formControl?.modalControl?.className), children: (0, jsx_runtime_1.jsx)("div", { className: "p-4", children: formPage }) }), (0, jsx_runtime_1.jsx)(__1.FloatingPageComponent, { show: !!toggle[`MODAL_EXPORT_${toggleKey}`], onClose: () => setToggle(`MODAL_EXPORT_${toggleKey}`, false), title: l.base.exportTitle ? l.base.exportTitle() : "Export", className: "bg-white md:w-[1200px] max-w-[1200px]", children: (0, jsx_runtime_1.jsx)(ExportExcel, { fetchControl: fetchControl, filename: "export", columnControl: columns?.map((cc) => ({
|
|
259
259
|
label: cc.label || "",
|
|
260
260
|
selector: cc.selector || "",
|
|
261
|
-
})) }) }), (0, jsx_runtime_1.jsx)(__1.FloatingPageComponent, { show: !!toggle[`MODAL_IMPORT_${toggleKey}`], onClose: () => setToggle(`MODAL_IMPORT_${toggleKey}`, false), title:
|
|
261
|
+
})) }) }), (0, jsx_runtime_1.jsx)(__1.FloatingPageComponent, { show: !!toggle[`MODAL_IMPORT_${toggleKey}`], onClose: () => setToggle(`MODAL_IMPORT_${toggleKey}`, false), title: l.base.importTitle ? l.base.importTitle() : "Import", className: "bg-white md:w-[1200px] max-w-[1200px]", children: (0, jsx_runtime_1.jsx)(ImportExcel, { submitControl: { path: fetchControl?.path + "/import" }, columnControl: columns?.map((cc) => ({
|
|
262
262
|
label: cc.label || "",
|
|
263
263
|
selector: cc.selector || "",
|
|
264
|
-
})) }) }), (0, jsx_runtime_1.jsx)(__1.ModalConfirmComponent, { show: !!toggle[`MODAL_DELETE_${toggleKey}`], onClose: () => setToggle(`MODAL_DELETE_${toggleKey}`, false), title:
|
|
264
|
+
})) }) }), (0, jsx_runtime_1.jsx)(__1.ModalConfirmComponent, { show: !!toggle[`MODAL_DELETE_${toggleKey}`], onClose: () => setToggle(`MODAL_DELETE_${toggleKey}`, false), title: l.base.deleteTitle ? l.base.deleteTitle({ data: selected?.[columns?.at(0)?.selector || ""] }) : `Delete ${selected?.[columns?.at(0)?.selector || ""]}?`, submitControl: {
|
|
265
265
|
onSubmit: {
|
|
266
266
|
...(fetchControl.path
|
|
267
267
|
? { path: `${fetchControl.path}/${selected?.id || ""}` }
|
|
@@ -14,7 +14,9 @@ const OutsideClick_component_1 = require("../wrap/OutsideClick.component");
|
|
|
14
14
|
const Button_component_1 = require("../button/Button.component");
|
|
15
15
|
const BottomSheet_component_1 = require("../modal/BottomSheet.component");
|
|
16
16
|
const FilterComponent_1 = require("./FilterComponent");
|
|
17
|
+
const skalfa_lang_1 = require("@skalfa/skalfa-lang");
|
|
17
18
|
function ControlBarComponent({ id = "", options, className, search, onSearch, searchableOptions, searchable, onSearchable, selectableOptions, selectable, onSelectable, sortableOptions, sort, onSort, filterableColumns, onFilter, filter, onRefresh }) {
|
|
19
|
+
const l = (0, skalfa_lang_1.useLang)();
|
|
18
20
|
const { toggle, setToggle } = (0, _contexts_1.useToggleContext)();
|
|
19
21
|
const { isSm } = (0, _utils_1.useResponsive)();
|
|
20
22
|
const searchRef = (0, react_1.useRef)(null);
|
|
@@ -22,27 +24,27 @@ function ControlBarComponent({ id = "", options, className, search, onSearch, se
|
|
|
22
24
|
if (options?.includes("SEARCH")) {
|
|
23
25
|
_utils_1.shortcut.register("ctrl+s", () => {
|
|
24
26
|
searchRef.current?.focus();
|
|
25
|
-
}, "
|
|
27
|
+
}, l.base.shortcutSearch ? l.base.shortcutSearch() : "Search");
|
|
26
28
|
}
|
|
27
29
|
if (options?.includes("FILTER")) {
|
|
28
30
|
_utils_1.shortcut.register("ctrl+f", () => {
|
|
29
31
|
setToggle("FILTER");
|
|
30
|
-
}, "Filter");
|
|
32
|
+
}, l.base.shortcutFilter ? l.base.shortcutFilter() : "Filter");
|
|
31
33
|
}
|
|
32
34
|
if (options?.includes("SORT")) {
|
|
33
35
|
_utils_1.shortcut.register("ctrl+o", () => {
|
|
34
36
|
setToggle("SORT");
|
|
35
|
-
}, "
|
|
37
|
+
}, l.base.shortcutSort ? l.base.shortcutSort() : "Sort");
|
|
36
38
|
}
|
|
37
39
|
if (options?.includes("SELECTABLE")) {
|
|
38
40
|
_utils_1.shortcut.register("ctrl+l", () => {
|
|
39
41
|
setToggle("SELECTABLE");
|
|
40
|
-
},
|
|
42
|
+
}, l.base.shortcutSelectable ? l.base.shortcutSelectable() : "Select");
|
|
41
43
|
}
|
|
42
44
|
if (options?.includes("REFRESH")) {
|
|
43
45
|
_utils_1.shortcut.register("ctrl+shift+r", () => {
|
|
44
46
|
onRefresh?.();
|
|
45
|
-
}, "Refresh
|
|
47
|
+
}, l.base.shortcutRefresh ? l.base.shortcutRefresh() : "Refresh");
|
|
46
48
|
}
|
|
47
49
|
return () => {
|
|
48
50
|
options?.includes("SEARCH") && _utils_1.shortcut.unregister("ctrl+s");
|
|
@@ -78,7 +80,7 @@ function ControlBarComponent({ id = "", options, className, search, onSearch, se
|
|
|
78
80
|
// =========================>
|
|
79
81
|
}
|
|
80
82
|
if (option == "CREATE") {
|
|
81
|
-
return ((0, jsx_runtime_1.jsx)("div", { className: "control-bar-create-wrapper", children: (0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/plus", label:
|
|
83
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: "control-bar-create-wrapper", children: (0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/plus", label: l.base.add ? l.base.add() : "Add", size: "sm", onClick: () => setToggle(`MODAL_FORM_${_utils_1.conversion.strSnake(id).toUpperCase()}`) }) }, "button-add"));
|
|
82
84
|
}
|
|
83
85
|
{
|
|
84
86
|
// =========================>
|
|
@@ -87,7 +89,7 @@ function ControlBarComponent({ id = "", options, className, search, onSearch, se
|
|
|
87
89
|
}
|
|
88
90
|
if (option == "SEARCH") {
|
|
89
91
|
const searchable = !!options?.find((option) => option == "SEARCHABLE");
|
|
90
|
-
return ((0, jsx_runtime_1.jsx)("div", { className: (0, _utils_1.cn)("control-bar-search-wrapper", searchable ? "control-bar-search-wrapper-searchable" : "control-bar-search-wrapper-standalone"), children: (0, jsx_runtime_1.jsx)(Input_component_1.InputComponent, { ref: searchRef, name: "search", placeholder: "
|
|
92
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: (0, _utils_1.cn)("control-bar-search-wrapper", searchable ? "control-bar-search-wrapper-searchable" : "control-bar-search-wrapper-standalone"), children: (0, jsx_runtime_1.jsx)(Input_component_1.InputComponent, { ref: searchRef, name: "search", placeholder: l.base.searchPlaceholder ? l.base.searchPlaceholder() : "Search here...", rightIcon: "solid/magnifying-glass", value: search, onChange: (e) => onSearch?.(e), className: (0, _utils_1.cn)("control-bar-search-input", searchable && "control-bar-search-input-searchable") }) }, key));
|
|
91
93
|
}
|
|
92
94
|
{
|
|
93
95
|
// =========================>
|
|
@@ -108,7 +110,7 @@ function ControlBarComponent({ id = "", options, className, search, onSearch, se
|
|
|
108
110
|
// =========================>
|
|
109
111
|
}
|
|
110
112
|
if (option == "SELECTABLE") {
|
|
111
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className: "control-bar-button-wrapper", children: [(0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/eye-low-vision", variant: "outline", className: "control-bar-icon-button", onClick: () => setToggle("SELECTABLE"), size: "sm" }), (0, jsx_runtime_1.jsx)(OutsideClick_component_1.OutsideClickComponent, { onOutsideClick: () => setToggle("SELECTABLE", false), children: (0, jsx_runtime_1.jsxs)("div", { className: (0, _utils_1.cn)("control-bar-dropdown", !toggle.SELECTABLE && "control-bar-dropdown-hidden"), children: [(0, jsx_runtime_1.jsx)("p", { className: 'control-bar-dropdown-title', children: "
|
|
113
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: "control-bar-button-wrapper", children: [(0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/eye-low-vision", variant: "outline", className: "control-bar-icon-button", onClick: () => setToggle("SELECTABLE"), size: "sm" }), (0, jsx_runtime_1.jsx)(OutsideClick_component_1.OutsideClickComponent, { onOutsideClick: () => setToggle("SELECTABLE", false), children: (0, jsx_runtime_1.jsxs)("div", { className: (0, _utils_1.cn)("control-bar-dropdown", !toggle.SELECTABLE && "control-bar-dropdown-hidden"), children: [(0, jsx_runtime_1.jsx)("p", { className: 'control-bar-dropdown-title', children: l.base.selectable ? l.base.selectable() : "Show Column" }), (0, jsx_runtime_1.jsx)(InputCheckbox_component_1.InputCheckboxComponent, { vertical: true, name: "show_column", options: selectableOptions?.map((option) => {
|
|
112
114
|
return {
|
|
113
115
|
label: option.label,
|
|
114
116
|
value: option.selector,
|
|
@@ -121,7 +123,7 @@ function ControlBarComponent({ id = "", options, className, search, onSearch, se
|
|
|
121
123
|
// =========================>
|
|
122
124
|
}
|
|
123
125
|
if (option == "SORT") {
|
|
124
|
-
return sortableOptions?.length ? ((0, jsx_runtime_1.jsxs)("div", { className: "control-bar-button-wrapper", children: [(0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/sort", variant: "outline", className: "control-bar-icon-button", onClick: () => setToggle("SORT"), size: "sm" }), (0, jsx_runtime_1.jsx)(OutsideClick_component_1.OutsideClickComponent, { onOutsideClick: () => setToggle("SORT", false), children: (0, jsx_runtime_1.jsxs)("div", { className: (0, _utils_1.cn)("control-bar-dropdown", !toggle.SORT && "control-bar-dropdown-hidden"), children: [(0, jsx_runtime_1.jsx)("p", { className: 'control-bar-dropdown-title', children: "
|
|
126
|
+
return sortableOptions?.length ? ((0, jsx_runtime_1.jsxs)("div", { className: "control-bar-button-wrapper", children: [(0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/sort", variant: "outline", className: "control-bar-icon-button", onClick: () => setToggle("SORT"), size: "sm" }), (0, jsx_runtime_1.jsx)(OutsideClick_component_1.OutsideClickComponent, { onOutsideClick: () => setToggle("SORT", false), children: (0, jsx_runtime_1.jsxs)("div", { className: (0, _utils_1.cn)("control-bar-dropdown", !toggle.SORT && "control-bar-dropdown-hidden"), children: [(0, jsx_runtime_1.jsx)("p", { className: 'control-bar-dropdown-title', children: l.base.sort ? l.base.sort() : "Sort By" }), (0, jsx_runtime_1.jsx)("div", { className: 'control-bar-sort-list', children: sortableOptions?.map((option, key) => {
|
|
125
127
|
const sortBy = sort?.find((s) => s.split(" ")?.at(0) == option?.selector)?.split(" ")?.at(1) || "";
|
|
126
128
|
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, _utils_1.cn)('control-bar-sort-item', !!sortBy && "control-bar-sort-item-active"), onClick: () => onChangeSort(option.selector), children: [(0, jsx_runtime_1.jsx)("p", { children: option.label }), sortBy && ((0, jsx_runtime_1.jsxs)("div", { className: 'control-bar-sort-active-icon', children: [(0, jsx_runtime_1.jsx)(skalfa_icon_1.Icon, { icon: sortBy == "desc" ? "solid/arrow-down-z-a" : "solid/arrow-up-a-z", className: 'control-bar-sort-icon' }), sort?.length && sort?.length > 1 && (0, jsx_runtime_1.jsx)("span", { className: 'control-bar-sort-badge', children: sort.findIndex((s) => s.split(" ")?.at(0) == option?.selector) + 1 })] }))] }, key));
|
|
127
129
|
}) })] }) })] }, key)) : (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, {});
|
|
@@ -158,7 +160,7 @@ function ControlBarComponent({ id = "", options, className, search, onSearch, se
|
|
|
158
160
|
// =========================>
|
|
159
161
|
}
|
|
160
162
|
if (option == "SEARCH") {
|
|
161
|
-
return ((0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)(Input_component_1.InputComponent, { name: "search", placeholder: "
|
|
163
|
+
return ((0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)(Input_component_1.InputComponent, { name: "search", placeholder: l.base.searchPlaceholder ? l.base.searchPlaceholder() : "Search here...", rightIcon: "solid/magnifying-glass", value: search, onChange: (e) => onSearch?.(e) }) }, key));
|
|
162
164
|
}
|
|
163
165
|
{
|
|
164
166
|
// =========================>
|
|
@@ -179,7 +181,7 @@ function ControlBarComponent({ id = "", options, className, search, onSearch, se
|
|
|
179
181
|
// =========================>
|
|
180
182
|
}
|
|
181
183
|
if (option == "SELECTABLE") {
|
|
182
|
-
return ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("p", { className: 'control-bar-mobile-title', children: "
|
|
184
|
+
return ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("p", { className: 'control-bar-mobile-title', children: l.base.selectable ? l.base.selectable() : "Show Column" }), (0, jsx_runtime_1.jsx)(InputCheckbox_component_1.InputCheckboxComponent, { vertical: true, name: "show_column", options: selectableOptions?.map((option) => {
|
|
183
185
|
return {
|
|
184
186
|
label: option.label,
|
|
185
187
|
value: option.selector,
|
|
@@ -192,7 +194,7 @@ function ControlBarComponent({ id = "", options, className, search, onSearch, se
|
|
|
192
194
|
// =========================>
|
|
193
195
|
}
|
|
194
196
|
if (option == "SORT") {
|
|
195
|
-
return sortableOptions?.length ? ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("p", { className: 'control-bar-mobile-title', children: "
|
|
197
|
+
return sortableOptions?.length ? ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("p", { className: 'control-bar-mobile-title', children: l.base.sort ? l.base.sort() : "Sort By" }), (0, jsx_runtime_1.jsx)("div", { className: 'flex flex-col', children: sortableOptions?.map((option, key) => {
|
|
196
198
|
const sortBy = sort?.find((s) => s.split(" ")?.at(0) == option?.selector)?.split(" ")?.at(1) || "";
|
|
197
199
|
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, _utils_1.cn)('control-bar-mobile-sort-item', !!sortBy && "control-bar-mobile-sort-item-active"), onClick: () => onChangeSort(option.selector), children: [(0, jsx_runtime_1.jsx)("p", { children: option.label }), sortBy && ((0, jsx_runtime_1.jsxs)("div", { className: 'text-primary', children: [(0, jsx_runtime_1.jsx)(skalfa_icon_1.Icon, { icon: sortBy == "desc" ? "solid/arrow-down-z-a" : "solid/arrow-up-a-z", className: 'text-xs' }), sort?.length && sort?.length > 1 && (0, jsx_runtime_1.jsx)("span", { className: 'text-[9px] ml-1', children: sort.findIndex((s) => s.split(" ")?.at(0) == option?.selector) + 1 })] }))] }, key));
|
|
198
200
|
}) })] }, key)) : (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, {});
|
|
@@ -15,6 +15,7 @@ const InputNumber_component_1 = require("../input/InputNumber.component");
|
|
|
15
15
|
const Modal_component_1 = require("../modal/Modal.component");
|
|
16
16
|
const Select_component_1 = require("../input/Select.component");
|
|
17
17
|
const _contexts_1 = require("@contexts");
|
|
18
|
+
const skalfa_lang_1 = require("@skalfa/skalfa-lang");
|
|
18
19
|
const FILTER_OPERATORS = [
|
|
19
20
|
{ label: "Cari", value: "li" },
|
|
20
21
|
{ label: "Sama", value: "eq" },
|
|
@@ -29,6 +30,7 @@ const LOGIC_OPTIONS = [
|
|
|
29
30
|
];
|
|
30
31
|
const BOOKMARK_KEY = "filter-bookmarks";
|
|
31
32
|
function FilterComponent({ columns, onChange, value, onMinimize, className = "", }) {
|
|
33
|
+
const l = (0, skalfa_lang_1.useLang)();
|
|
32
34
|
const { isSm } = (0, _utils_1.useResponsive)();
|
|
33
35
|
const { toggle, setToggle } = (0, _contexts_1.useToggleContext)();
|
|
34
36
|
const [filters, setFilters] = (0, react_1.useState)([]);
|
|
@@ -63,16 +65,16 @@ function FilterComponent({ columns, onChange, value, onMinimize, className = "",
|
|
|
63
65
|
(0, react_1.useEffect)(() => {
|
|
64
66
|
localStorage.setItem(BOOKMARK_KEY, JSON.stringify(bookmarks));
|
|
65
67
|
}, [bookmarks]);
|
|
66
|
-
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { className: (0, _utils_1.cn)("filter-panel", (0, _utils_1.pcn)(className, "base")), children: [(0, jsx_runtime_1.jsxs)("div", { className: "filter-panel-header", children: [(0, jsx_runtime_1.jsx)("p", { className: (0, _utils_1.cn)((0, _utils_1.pcn)(className, "title")), children: "Filter" }), (0, jsx_runtime_1.jsxs)("div", { className: "filter-panel-controls", children: [(0, jsx_runtime_1.jsxs)("div", { className: "filter-panel-bookmarks-wrapper", children: [(0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/bookmark", variant: "outline", paint: "primary", className: "filter-panel-bookmark-btn icon::text-slate-400", size: "xs", onClick: () => setToggle("MODAL_BOOKMARK", { bookmark_id: "new" }) }), !!bookmarks?.length && ((0, jsx_runtime_1.jsx)(Chip_component_1.ChipComponent, { items: bookmarks.slice(0, 5).map((b) => b.name), onClick: (_, index) => setFilters(bookmarks[index]?.filters), onDelete: (_, index) => setBookmarks(bookmarks.filter((_, bi) => bi != index)) })), bookmarks?.length > 5 && ((0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/ellipsis-h", variant: "outline", paint: "primary", className: "filter-panel-bookmark-btn icon::text-slate-400", size: "xs", onClick: () => setToggle("MODAL_BOOKMARK_LIST") }))] }), (0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/rotate", label: "
|
|
68
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { className: (0, _utils_1.cn)("filter-panel", (0, _utils_1.pcn)(className, "base")), children: [(0, jsx_runtime_1.jsxs)("div", { className: "filter-panel-header", children: [(0, jsx_runtime_1.jsx)("p", { className: (0, _utils_1.cn)((0, _utils_1.pcn)(className, "title")), children: l.base.filter ? l.base.filter() : "Filter" }), (0, jsx_runtime_1.jsxs)("div", { className: "filter-panel-controls", children: [(0, jsx_runtime_1.jsxs)("div", { className: "filter-panel-bookmarks-wrapper", children: [(0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/bookmark", variant: "outline", paint: "primary", className: "filter-panel-bookmark-btn icon::text-slate-400", size: "xs", onClick: () => setToggle("MODAL_BOOKMARK", { bookmark_id: "new" }) }), !!bookmarks?.length && ((0, jsx_runtime_1.jsx)(Chip_component_1.ChipComponent, { items: bookmarks.slice(0, 5).map((b) => b.name), onClick: (_, index) => setFilters(bookmarks[index]?.filters), onDelete: (_, index) => setBookmarks(bookmarks.filter((_, bi) => bi != index)) })), bookmarks?.length > 5 && ((0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/ellipsis-h", variant: "outline", paint: "primary", className: "filter-panel-bookmark-btn icon::text-slate-400", size: "xs", onClick: () => setToggle("MODAL_BOOKMARK_LIST") }))] }), (0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/rotate", label: l.base.clear ? l.base.clear() : "Filter", variant: "outline", paint: "primary", className: "filter-panel-bookmark-btn icon::text-slate-400", size: "xs", onClick: () => setFilters([]) }), onMinimize && ((0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/chevron-up", variant: "outline", paint: "primary", className: "filter-panel-bookmark-btn icon::text-slate-400", size: "xs", onClick: onMinimize }))] })] }), filters.map((f, i) => {
|
|
67
69
|
const column = columns.find((c) => c.selector === f.column);
|
|
68
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className: "filter-row", children: [i > 0 && ((0, jsx_runtime_1.jsx)("div", { className: "filter-col-logic", children: (0, jsx_runtime_1.jsx)(Select_component_1.SelectComponent, { name: `filter_logic_${i}`, options: LOGIC_OPTIONS, placeholder: "
|
|
70
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: "filter-row", children: [i > 0 && ((0, jsx_runtime_1.jsx)("div", { className: "filter-col-logic", children: (0, jsx_runtime_1.jsx)(Select_component_1.SelectComponent, { name: `filter_logic_${i}`, options: LOGIC_OPTIONS, placeholder: l.base.filterLogic ? l.base.filterLogic() : "And/Or", value: f.logic, onChange: (e) => handleChange(i, "logic", e), className: "filter-input-field" }) })), (0, jsx_runtime_1.jsx)("div", { className: i > 0 ? "filter-col-column-with-logic" : "filter-col-column", children: (0, jsx_runtime_1.jsx)(Select_component_1.SelectComponent, { name: `filter_column_${i}`, options: columns.map((c) => ({
|
|
69
71
|
label: c.label,
|
|
70
72
|
value: c.selector,
|
|
71
|
-
})), placeholder: "
|
|
72
|
-
}), (0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { label: "
|
|
73
|
+
})), placeholder: l.base.column ? l.base.column() : "Column", value: f.column, onChange: (e) => handleChange(i, "column", e), className: "filter-input-field" }) }), (0, jsx_runtime_1.jsx)("div", { className: "filter-col-operator", children: (0, jsx_runtime_1.jsx)(Select_component_1.SelectComponent, { name: `filter_operator_${i}`, options: FILTER_OPERATORS, placeholder: l.base.filterOperator ? l.base.filterOperator() : "Operation", value: f.type, onChange: (e) => handleChange(i, "type", e), className: "filter-input-field" }) }), isSm && ((0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/times", paint: "danger", variant: "outline", onClick: () => removeFilter(i), size: "xs" })), column && ((0, jsx_runtime_1.jsx)("div", { className: "filter-col-value", children: (0, jsx_runtime_1.jsx)(InputFilterValueComponent, { type: column.type, name: `filter_value_${i}`, placeholder: "...", value: f.value || "", onChange: (e) => handleChange(i, "value", e), options: column.type === "select" && column.options ? column.options : [], className: "filter-input-field", between: f.type === "bw", multiple: ["in", "ni"].includes(f.type || "") }) })), !isSm && ((0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/times", paint: "danger", variant: "outline", onClick: () => removeFilter(i), size: "xs" }))] }, i));
|
|
74
|
+
}), (0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { label: l.base.add ? l.base.add() : "Add", icon: "solid/plus", variant: "outline", paint: "primary", size: isSm ? "xs" : "sm", onClick: addFilter, className: "filter-add-btn" })] }), (0, jsx_runtime_1.jsx)(Modal_component_1.ModalComponent, { show: !!toggle["MODAL_BOOKMARK_LIST"], onClose: () => setToggle("MODAL_BOOKMARK_LIST", false), title: l.base.filterBookmarks ? l.base.filterBookmarks() : "Filter Bookmark", children: (0, jsx_runtime_1.jsx)("div", { className: "filter-bookmark-list-container", children: bookmarks?.length ? bookmarks?.map((b, key) => ((0, jsx_runtime_1.jsxs)("div", { className: "filter-bookmark-row", children: [(0, jsx_runtime_1.jsx)("p", { className: "filter-bookmark-name", children: b.name }), (0, jsx_runtime_1.jsxs)("div", { className: "flex gap-2", children: [(0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/plus", variant: "outline", paint: "primary", className: "", size: "xs", onClick: () => {
|
|
73
75
|
setFilters(b.filters);
|
|
74
76
|
setToggle("MODAL_BOOKMARK_LIST", false);
|
|
75
|
-
} }), (0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/times", variant: "outline", paint: "danger", className: "", size: "xs", onClick: () => setBookmarks(bookmarks.filter((_, bi) => bi != key)) })] })] }, key))) : ((0, jsx_runtime_1.
|
|
77
|
+
} }), (0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { icon: "solid/times", variant: "outline", paint: "danger", className: "", size: "xs", onClick: () => setBookmarks(bookmarks.filter((_, bi) => bi != key)) })] })] }, key))) : ((0, jsx_runtime_1.jsxs)("div", { className: "filter-bookmark-empty-text", children: [" -- ", l.base.filterBookmarkEmpty ? l.base.filterBookmarkEmpty() : "No Bookmark", " --"] })) }) }), (0, jsx_runtime_1.jsx)(Modal_component_1.ModalComponent, { show: !!toggle["MODAL_BOOKMARK"], onClose: () => setToggle("MODAL_BOOKMARK", false), title: l.base.filterBookmark ? l.base.filterBookmark() : "Filter Bookmark", footer: (0, jsx_runtime_1.jsx)("div", { className: "flex justify-end", children: (0, jsx_runtime_1.jsx)(Button_component_1.ButtonComponent, { label: l.base.apply ? l.base.apply() : "Apply", onClick: () => {
|
|
76
78
|
let updated = [];
|
|
77
79
|
if (toggle["MODAL_BOOKMARK"]?.bookmark_id == "new") {
|
|
78
80
|
const newBookmark = {
|
|
@@ -90,18 +92,19 @@ function FilterComponent({ columns, onChange, value, onMinimize, className = "",
|
|
|
90
92
|
}
|
|
91
93
|
setBookmarks(updated);
|
|
92
94
|
setToggle("MODAL_BOOKMARK", false);
|
|
93
|
-
} }) }), children: (0, jsx_runtime_1.jsxs)("div", { className: "filter-bookmark-form-container", children: [(0, jsx_runtime_1.jsx)(Select_component_1.SelectComponent, { name: `bookmark_id`, placeholder: "Pilih bookmark filter...", value: toggle["MODAL_BOOKMARK"]?.bookmark_id ?? "", onChange: e => setToggle("MODAL_BOOKMARK", { ...toggle["MODAL_BOOKMARK"], bookmark_id: e }), options: [
|
|
95
|
+
} }) }), children: (0, jsx_runtime_1.jsxs)("div", { className: "filter-bookmark-form-container", children: [(0, jsx_runtime_1.jsx)(Select_component_1.SelectComponent, { name: `bookmark_id`, placeholder: l.base.filterBookmarkPlaceholder ? l.base.filterBookmarkPlaceholder() : "Pilih bookmark filter...", value: toggle["MODAL_BOOKMARK"]?.bookmark_id ?? "", onChange: e => setToggle("MODAL_BOOKMARK", { ...toggle["MODAL_BOOKMARK"], bookmark_id: e }), options: [
|
|
94
96
|
{
|
|
95
|
-
label: "
|
|
97
|
+
label: `-- ${l.base.filterBookmarkNew ? l.base.filterBookmarkNew() : "New Filter Bookmark"} --`,
|
|
96
98
|
value: "new",
|
|
97
99
|
},
|
|
98
100
|
...bookmarks.map((b) => ({
|
|
99
101
|
label: b.name,
|
|
100
102
|
value: b.id,
|
|
101
103
|
}))
|
|
102
|
-
] }), toggle["MODAL_BOOKMARK"]?.bookmark_id == "new" && ((0, jsx_runtime_1.jsx)(Input_component_1.InputComponent, { name: "bookmark_name", placeholder: "Masukkan nama bookmark...", value: toggle["MODAL_BOOKMARK"]?.bookmark_name ?? "", onChange: e => setToggle("MODAL_BOOKMARK", { ...toggle["MODAL_BOOKMARK"], bookmark_name: e }), className: "filter-bookmark-form-input" }))] }) })] }));
|
|
104
|
+
] }), toggle["MODAL_BOOKMARK"]?.bookmark_id == "new" && ((0, jsx_runtime_1.jsx)(Input_component_1.InputComponent, { name: "bookmark_name", placeholder: l.base.filterBookmarkNewPlaceholder ? l.base.filterBookmarkNewPlaceholder() : "Masukkan nama bookmark...", value: toggle["MODAL_BOOKMARK"]?.bookmark_name ?? "", onChange: e => setToggle("MODAL_BOOKMARK", { ...toggle["MODAL_BOOKMARK"], bookmark_name: e }), className: "filter-bookmark-form-input" }))] }) })] }));
|
|
103
105
|
}
|
|
104
106
|
function InputFilterValueComponent({ type, name, value, onChange, options = [], placeholder = "", className = "", between, multiple, }) {
|
|
107
|
+
const l = (0, skalfa_lang_1.useLang)();
|
|
105
108
|
const resolvedType = type || "text";
|
|
106
109
|
if (!between) {
|
|
107
110
|
switch (resolvedType) {
|
|
@@ -124,13 +127,13 @@ function InputFilterValueComponent({ type, name, value, onChange, options = [],
|
|
|
124
127
|
const handle = (v) => onChange(pos === "from" ? [v, to] : [from, v]);
|
|
125
128
|
switch (resolvedType) {
|
|
126
129
|
case "number":
|
|
127
|
-
return ((0, jsx_runtime_1.jsx)(InputNumber_component_1.InputNumberComponent, { name: `${name}_${pos}`, value: Number(currentValue) || 0, onChange: handle, placeholder: pos === "from" ? "Dari" : "Sampai", className: className }));
|
|
130
|
+
return ((0, jsx_runtime_1.jsx)(InputNumber_component_1.InputNumberComponent, { name: `${name}_${pos}`, value: Number(currentValue) || 0, onChange: handle, placeholder: pos === "from" ? l.base.filterFrom ? l.base.filterFrom() : "Dari" : l.base.filterTo ? l.base.filterTo() : "Sampai", className: className }));
|
|
128
131
|
case "currency":
|
|
129
|
-
return ((0, jsx_runtime_1.jsx)(InputCurrency_component_1.InputCurrencyComponent, { name: `${name}_${pos}`, value: Number(currentValue) || 0, onChange: handle, placeholder: pos === "from" ? "Dari" : "Sampai", className: className }));
|
|
132
|
+
return ((0, jsx_runtime_1.jsx)(InputCurrency_component_1.InputCurrencyComponent, { name: `${name}_${pos}`, value: Number(currentValue) || 0, onChange: handle, placeholder: pos === "from" ? l.base.filterFrom ? l.base.filterFrom() : "Dari" : l.base.filterTo ? l.base.filterTo() : "Sampai", className: className }));
|
|
130
133
|
case "date":
|
|
131
|
-
return ((0, jsx_runtime_1.jsx)(InputDate_component_1.InputDateComponent, { name: `${name}_${pos}`, value: currentValue || "", onChange: handle, placeholder: pos === "from" ? "Dari" : "Sampai", className: className }));
|
|
134
|
+
return ((0, jsx_runtime_1.jsx)(InputDate_component_1.InputDateComponent, { name: `${name}_${pos}`, value: currentValue || "", onChange: handle, placeholder: pos === "from" ? l.base.filterFrom ? l.base.filterFrom() : "Dari" : l.base.filterTo ? l.base.filterTo() : "Sampai", className: className }));
|
|
132
135
|
default:
|
|
133
|
-
return ((0, jsx_runtime_1.jsx)(Input_component_1.InputComponent, { name: `${name}_${pos}`, value: currentValue || "", onChange: (e) => handle(e.target.value), placeholder: pos === "from" ? "Dari" : "Sampai", className: className }));
|
|
136
|
+
return ((0, jsx_runtime_1.jsx)(Input_component_1.InputComponent, { name: `${name}_${pos}`, value: currentValue || "", onChange: (e) => handle(e.target.value), placeholder: pos === "from" ? l.base.filterFrom ? l.base.filterFrom() : "Dari" : l.base.filterTo ? l.base.filterTo() : "Sampai", className: className }));
|
|
134
137
|
}
|
|
135
138
|
};
|
|
136
139
|
return ((0, jsx_runtime_1.jsxs)("div", { className: "filter-between-container", children: [renderInput("from"), (0, jsx_runtime_1.jsx)("span", { children: "s/d" }), renderInput("to")] }));
|
|
@@ -11,7 +11,9 @@ const Pagination_component_1 = require("./Pagination.component");
|
|
|
11
11
|
const ScrollContainer_component_1 = require("../wrap/ScrollContainer.component");
|
|
12
12
|
const Checkbox_component_1 = require("../input/Checkbox.component");
|
|
13
13
|
const Swipe_component_1 = require("../wrap/Swipe.component");
|
|
14
|
+
const skalfa_lang_1 = require("@skalfa/skalfa-lang");
|
|
14
15
|
function TableComponent({ id, controlBar, columns, data, pagination, loading, sortBy, onChangeSortBy, search, onChangeSearch, searchableColumn, onChangeSearchableColumn, filter, onChangeFilter, checks, onChangeChecks, actionBulking, focus, onRowClick, onRefresh, block, noIndex, responsiveControl, className = "", }) {
|
|
16
|
+
const l = (0, skalfa_lang_1.useLang)();
|
|
15
17
|
const [displayColumns, setDisplayColumns] = (0, react_1.useState)([]);
|
|
16
18
|
const [showFloatingAction, setShowFloatingAction] = (0, react_1.useState)(false);
|
|
17
19
|
const [floatingActionActive, setFloatingActionActive] = (0, react_1.useState)(false);
|
|
@@ -98,10 +100,10 @@ function TableComponent({ id, controlBar, columns, data, pagination, loading, so
|
|
|
98
100
|
})), onFilter: (filters) => onChangeFilter?.(filters), filter: filter, className: (0, _utils_1.pcn)(className, "controller-bar") || "" })), (0, jsx_runtime_1.jsx)("div", { className: "relative", children: (0, jsx_runtime_1.jsx)(ScrollContainer_component_1.ScrollContainerComponent, { scrollFloating: !isSm && block, className: "w-full", onScroll: (e) => {
|
|
99
101
|
actionColumnRef.current?.clientWidth && e.scrollLeft &&
|
|
100
102
|
setShowFloatingAction(e.scrollLeft + e.clientWidth <= e.scrollWidth - actionColumnRef.current?.clientWidth);
|
|
101
|
-
}, footer: (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: block && pagination && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: "py-6" }), (0, jsx_runtime_1.jsx)("div", { className: "my-2 absolute bottom-0 w-full", children: (0, jsx_runtime_1.jsx)(Pagination_component_1.PaginationComponent, { ...pagination }) })] })) }), children: loading ? ((0, jsx_runtime_1.jsx)("div", { className: "w-max min-w-full", children: (0, jsx_runtime_1.jsx)("div", { className: "table-loading-container", children: (0, jsx_runtime_1.jsx)("h1", { className: "table-loading-text", children:
|
|
103
|
+
}, footer: (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: block && pagination && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: "py-6" }), (0, jsx_runtime_1.jsx)("div", { className: "my-2 absolute bottom-0 w-full", children: (0, jsx_runtime_1.jsx)(Pagination_component_1.PaginationComponent, { ...pagination }) })] })) }), children: loading ? ((0, jsx_runtime_1.jsx)("div", { className: "w-max min-w-full", children: (0, jsx_runtime_1.jsx)("div", { className: "table-loading-container", children: (0, jsx_runtime_1.jsx)("h1", { className: "table-loading-text", children: l.base.tableLoading ? l.base.tableLoading() : "" }) }) })) : !data || !data.length ? ((0, jsx_runtime_1.jsx)("div", { className: "table-empty-container", children: (0, jsx_runtime_1.jsx)("h1", { className: "table-empty-text", children: l.base.tableEmpty ? l.base.tableEmpty() : "Data empty" }) })) : ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: !isSm || !responsiveControl?.mobile ? ((0, jsx_runtime_1.jsxs)("div", { className: "w-max min-w-full", children: [(0, jsx_runtime_1.jsxs)("div", { className: (0, _utils_1.cn)("table-head-row", (0, _utils_1.pcn)(className, "row")), children: [!!actionBulking && ((0, jsx_runtime_1.jsx)("div", { className: "table-head-column w-max", children: (0, jsx_runtime_1.jsx)(Checkbox_component_1.CheckboxComponent, { name: "selected_table", className: "w-5 h-5", checked: data.length > 0 && checks?.length === data.length, onChange: () => data.length > 0 && checks?.length === data.length ? onChangeChecks?.([]) : onChangeChecks?.(data.map((d) => d.id)) }) })), !noIndex && (0, jsx_runtime_1.jsx)("div", { className: (0, _utils_1.cn)("table-head-column w-8", (0, _utils_1.pcn)(className, "head-column")), children: "#" }), renderHead()] }), (0, jsx_runtime_1.jsx)("div", { className: "table-body", children: data.map((item, key) => {
|
|
102
104
|
return ((0, jsx_runtime_1.jsxs)("div", { style: { animationDelay: `${(key + 1) * 0.05}s` }, className: (0, _utils_1.cn)("table-body-row", key % 2 ? "bg-light-primary/10" : "bg-white", focus == key && "bg-light-primary/30", (0, _utils_1.pcn)(className, "row")), children: [!!actionBulking && ((0, jsx_runtime_1.jsx)("div", { className: (0, _utils_1.cn)("table-body-column w-max", (0, _utils_1.pcn)(className, "column")), children: (0, jsx_runtime_1.jsx)(Checkbox_component_1.CheckboxComponent, { name: "selected_table", className: "w-5 h-5", checked: checks?.includes(item?.id), onChange: () => checks?.includes(item?.id) ? onChangeChecks?.(checks.filter((i) => i !== item?.id)) : onChangeChecks?.([...(checks || []), item?.id]) }) })), !noIndex && (0, jsx_runtime_1.jsx)("div", { className: (0, _utils_1.cn)("table-body-column w-8", (0, _utils_1.pcn)(className, "column")), children: numberOfRow(key) }), renderItem(item, key), (0, jsx_runtime_1.jsx)("div", { ref: actionColumnRef, className: "table-action-column", children: item["action"] }), item["action"] && showFloatingAction && ((0, jsx_runtime_1.jsxs)("div", { className: (0, _utils_1.cn)("table-floating-action", (0, _utils_1.pcn)(className, "floating-action")), onClick: () => floatingActionActive !== false &&
|
|
103
105
|
floatingActionActive == key ? setFloatingActionActive(false) : setFloatingActionActive(key), children: [(0, jsx_runtime_1.jsx)("div", { className: "table-floating-action-icon-wrapper", children: (0, jsx_runtime_1.jsx)(skalfa_icon_1.Icon, { icon: floatingActionActive === false || floatingActionActive != key ? "solid/chevron-left" : "solid/chevron-right" }) }), (0, jsx_runtime_1.jsx)("div", { className: (0, _utils_1.cn)("table-floating-action-content", floatingActionActive === key && "table-floating-action-content-active"), children: item["action"] })] }))] }, key));
|
|
104
106
|
}) })] })) : ((0, jsx_runtime_1.jsx)("div", { className: "table-mobile-list", children: data.map((item, key) => {
|
|
105
107
|
return ((0, jsx_runtime_1.jsx)("div", { style: { animationDelay: `${(key + 1) * 0.05}s` }, children: renderItem(item, key) }, key));
|
|
106
|
-
}) })) })) }) }), !!actionBulking && !!checks?.length && ((0, jsx_runtime_1.jsxs)("div", { className: "table-bulk-actions-bar", children: [(0, jsx_runtime_1.jsxs)("div", { className: "table-bulk-actions-title", children: [checks?.length, "
|
|
108
|
+
}) })) })) }) }), !!actionBulking && !!checks?.length && ((0, jsx_runtime_1.jsxs)("div", { className: "table-bulk-actions-bar", children: [(0, jsx_runtime_1.jsxs)("div", { className: "table-bulk-actions-title", children: [checks?.length, " ", l.base.tableSelected ? l.base.tableSelected() : ""] }), (0, jsx_runtime_1.jsx)("div", { className: "table-bulk-actions-buttons", children: actionBulking?.(checks) })] })), !block && pagination && ((0, jsx_runtime_1.jsx)("div", { className: "table-pagination-desktop", children: (0, jsx_runtime_1.jsx)(Pagination_component_1.PaginationComponent, { ...pagination }) })), pagination && ((0, jsx_runtime_1.jsx)("div", { className: "table-pagination-mobile", children: (0, jsx_runtime_1.jsx)(Pagination_component_1.PaginationComponent, { ...pagination }) }))] }));
|
|
107
109
|
}
|
|
@@ -7,7 +7,9 @@ const react_1 = require("react");
|
|
|
7
7
|
const _utils_1 = require("@utils");
|
|
8
8
|
const _contexts_1 = require("@contexts");
|
|
9
9
|
const Modal_component_1 = require("../modal/Modal.component");
|
|
10
|
+
const skalfa_lang_1 = require("@skalfa/skalfa-lang");
|
|
10
11
|
function ShortcutProvider() {
|
|
12
|
+
const l = (0, skalfa_lang_1.useLang)();
|
|
11
13
|
const { setToggle, toggle } = (0, _contexts_1.useToggleContext)();
|
|
12
14
|
const shortcuts = _utils_1.shortcut.list();
|
|
13
15
|
(0, react_1.useEffect)(() => {
|
|
@@ -16,7 +18,7 @@ function ShortcutProvider() {
|
|
|
16
18
|
(0, react_1.useEffect)(() => {
|
|
17
19
|
_utils_1.shortcut.register("ctrl+/", () => {
|
|
18
20
|
setToggle("MODAL_SHORTCUT_HELP");
|
|
19
|
-
},
|
|
21
|
+
}, l.base.shortcutList ? l.base.shortcutList() : "");
|
|
20
22
|
}, []);
|
|
21
23
|
function formatShortcutKey(key) {
|
|
22
24
|
return key
|
|
@@ -38,5 +40,5 @@ function ShortcutProvider() {
|
|
|
38
40
|
})
|
|
39
41
|
.join(" + ");
|
|
40
42
|
}
|
|
41
|
-
return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)(Modal_component_1.ModalComponent, { show: !!toggle["MODAL_SHORTCUT_HELP"], onClose: () => setToggle("MODAL_SHORTCUT_HELP"), title: "
|
|
43
|
+
return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)(Modal_component_1.ModalComponent, { show: !!toggle["MODAL_SHORTCUT_HELP"], onClose: () => setToggle("MODAL_SHORTCUT_HELP"), title: l.base.shortcut ? l.base.shortcut() : "", children: (0, jsx_runtime_1.jsx)("div", { className: "shortcut-help-grid", children: shortcuts.map(({ key, description }) => ((0, jsx_runtime_1.jsxs)(react_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("kbd", { className: "shortcut-key-badge", children: formatShortcutKey(key) }), (0, jsx_runtime_1.jsxs)("span", { children: [": ", description] })] }, key))) }) }) }));
|
|
42
44
|
}
|
package/package.json
CHANGED
|
@@ -4,6 +4,7 @@ import { ReactNode, useEffect, useMemo, useState } from "react";
|
|
|
4
4
|
import { api, ApiType, cn, pcn, registry, shortcut, useResponsive } from "@utils";
|
|
5
5
|
import { ButtonComponent, ButtonProps, BottomSheetComponent } from "@components";
|
|
6
6
|
import { Icon } from "@skalfa/skalfa-icon";
|
|
7
|
+
import { useLang } from "@skalfa/skalfa-lang";
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
|
|
@@ -41,6 +42,7 @@ export function ModalConfirmComponent({
|
|
|
41
42
|
|
|
42
43
|
className = "",
|
|
43
44
|
}: ModalConfirmProps) {
|
|
45
|
+
const l = useLang()
|
|
44
46
|
const { isSm } = useResponsive();
|
|
45
47
|
const [toast, setToast] = useState<boolean | "success" | "failed">(false);
|
|
46
48
|
const [loading, setLoading] = useState(false);
|
|
@@ -69,7 +71,7 @@ export function ModalConfirmComponent({
|
|
|
69
71
|
<div className="w-12 h-12 rounded-full bg-blue-50 flex items-center justify-center">
|
|
70
72
|
<Icon icon={"solid/check"} className="text-primary text-2xl" />
|
|
71
73
|
</div>
|
|
72
|
-
<p className="text-primary text-lg font-semibold mt-4">{"
|
|
74
|
+
<p className="text-primary text-lg font-semibold mt-4">{l.base.success ? l.base.success() : "Success"}</p>
|
|
73
75
|
</div>
|
|
74
76
|
)
|
|
75
77
|
}
|
|
@@ -97,7 +99,7 @@ export function ModalConfirmComponent({
|
|
|
97
99
|
<Icon icon={"solid/exclamation-triangle"} className="text-danger text-lg" />
|
|
98
100
|
</div>
|
|
99
101
|
</div>
|
|
100
|
-
<p className="text-danger text-sm font-semibold">{
|
|
102
|
+
<p className="text-danger text-sm font-semibold">{l.base.confirmFailed ? l.base.confirmFailed() : "Failed"}</p>
|
|
101
103
|
</div>
|
|
102
104
|
</div>
|
|
103
105
|
)}
|
|
@@ -112,14 +114,14 @@ export function ModalConfirmComponent({
|
|
|
112
114
|
return (
|
|
113
115
|
<div className="flex justify-center gap-4 p-6 pt-2">
|
|
114
116
|
<ButtonComponent
|
|
115
|
-
label="
|
|
117
|
+
label={l.base.cancel ? l.base.cancel() : ""}
|
|
116
118
|
variant="outline"
|
|
117
119
|
onClick={() => onClose()}
|
|
118
120
|
block
|
|
119
121
|
size={size}
|
|
120
122
|
/>
|
|
121
123
|
<ButtonComponent
|
|
122
|
-
label={"
|
|
124
|
+
label={l.base.confirm ? l.base.confirm() : ""}
|
|
123
125
|
loading={loading}
|
|
124
126
|
onClick={async () => {
|
|
125
127
|
if(!submitControl?.onSubmit) return;
|
|
@@ -69,15 +69,15 @@ const defaultColumns: FooterColumnProps[] = [
|
|
|
69
69
|
];
|
|
70
70
|
|
|
71
71
|
export function FooterComponent({
|
|
72
|
-
brandTitle
|
|
73
|
-
brandSubtitle
|
|
74
|
-
address
|
|
75
|
-
phone
|
|
76
|
-
email
|
|
77
|
-
supportHours
|
|
78
|
-
socials
|
|
79
|
-
columns
|
|
80
|
-
copyrightLink
|
|
72
|
+
brandTitle = "Next Light v.3",
|
|
73
|
+
brandSubtitle = "The Magic Starter Template",
|
|
74
|
+
address = { label: "Soekarno Hatta No 27 C, Ponorogo, Jawa Timur, Indonesia", path: "https://maps.app.goo.gl/TY2QDjFPm3RfwjUq6" },
|
|
75
|
+
phone = { label: "+62 888888888888", path: "https://wa.me/6281456140392" },
|
|
76
|
+
email = { label: "example@gmail.com", path: "mailto:sejedigital@gmail.com" },
|
|
77
|
+
supportHours = "24 / 7 Online Suport | Senin - Sabtu ( 09.00 s/d 17.00 )",
|
|
78
|
+
socials = defaultSocials,
|
|
79
|
+
columns = defaultColumns,
|
|
80
|
+
copyrightLink = { label: "sejedigital.com 2020 - 2025", path: "https://sejedigital.com/" },
|
|
81
81
|
}: FooterProps) {
|
|
82
82
|
return (
|
|
83
83
|
<>
|
|
@@ -37,12 +37,12 @@ const defaultSpecialLink = {
|
|
|
37
37
|
} as const;
|
|
38
38
|
|
|
39
39
|
export function NavbarComponent({
|
|
40
|
-
logoTitle
|
|
41
|
-
logoSubtitle
|
|
42
|
-
logoPath
|
|
43
|
-
specialLink
|
|
44
|
-
items
|
|
45
|
-
isLoggedIn
|
|
40
|
+
logoTitle = "Next Light v.3",
|
|
41
|
+
logoSubtitle = "The Magic Starter Template",
|
|
42
|
+
logoPath = "/",
|
|
43
|
+
specialLink = defaultSpecialLink,
|
|
44
|
+
items = defaultItems,
|
|
45
|
+
isLoggedIn = false,
|
|
46
46
|
onLogin,
|
|
47
47
|
onRegister,
|
|
48
48
|
onProfile,
|
|
@@ -41,9 +41,7 @@ export function TabbarComponent({
|
|
|
41
41
|
key={i}
|
|
42
42
|
className={cn(
|
|
43
43
|
"tabbar-item",
|
|
44
|
-
isItemActive
|
|
45
|
-
? "tabbar-item-active"
|
|
46
|
-
: "tabbar-item-inactive",
|
|
44
|
+
isItemActive ? "tabbar-item-active" : "tabbar-item-inactive",
|
|
47
45
|
pcn<CT>(className, "item"),
|
|
48
46
|
pcn<CT>(className, "active"),
|
|
49
47
|
)}
|
|
@@ -301,7 +301,7 @@ export function FormSupervisionComponent({
|
|
|
301
301
|
<div>
|
|
302
302
|
<ButtonComponent
|
|
303
303
|
icon={"solid/plus"}
|
|
304
|
-
label={
|
|
304
|
+
label={`${l.base.add ? l.base.add() : "Add"} ${label || mapName}`}
|
|
305
305
|
variant="outline"
|
|
306
306
|
size="sm"
|
|
307
307
|
onClick={addGroup}
|
|
@@ -332,6 +332,10 @@ export function FormSupervisionComponent({
|
|
|
332
332
|
);
|
|
333
333
|
};
|
|
334
334
|
|
|
335
|
+
useEffect(() => {
|
|
336
|
+
setModal(false)
|
|
337
|
+
}, [values]);
|
|
338
|
+
|
|
335
339
|
return (
|
|
336
340
|
<>
|
|
337
341
|
{title && <h4 className={cn("text-lg font-semibold mb-4", pcn<CT>(className, "title"))}>{title}</h4>}
|
|
@@ -341,7 +345,7 @@ export function FormSupervisionComponent({
|
|
|
341
345
|
<div className="w-12 h-12 rounded-full bg-blue-50 flex items-center justify-center">
|
|
342
346
|
<Icon icon={"solid/check"} className="text-primary text-2xl" />
|
|
343
347
|
</div>
|
|
344
|
-
<p className="text-primary text-lg font-semibold mt-4">{successMessage || "
|
|
348
|
+
<p className="text-primary text-lg font-semibold mt-4">{successMessage || l.base?.success ? l.base.success() : "Success!"}</p>
|
|
345
349
|
</div>
|
|
346
350
|
) : (
|
|
347
351
|
<form id={id} className={cn("flex flex-col h-full pb-8")} onSubmit={submit}>
|
|
@@ -380,13 +384,13 @@ export function FormSupervisionComponent({
|
|
|
380
384
|
)}
|
|
381
385
|
|
|
382
386
|
{modal == "failed" && (
|
|
383
|
-
<div className="mt-4 w-full p-4 rounded-sm border border-danger bg-light-danger flex gap-4 items-center">
|
|
387
|
+
<div className="col-span-12 mt-4 w-full p-4 rounded-sm border border-danger bg-light-danger flex gap-4 items-center">
|
|
384
388
|
<div>
|
|
385
389
|
<div className="w-10 h-10 rounded-full bg-danger/20 flex items-center justify-center">
|
|
386
390
|
<Icon icon={"solid/exclamation-triangle"} className="text-danger text-lg" />
|
|
387
391
|
</div>
|
|
388
392
|
</div>
|
|
389
|
-
<p className="text-danger text-sm font-semibold">{"
|
|
393
|
+
<p className="text-danger text-sm font-semibold">{l.base.formFailed ? l.base.formFailed() : "Failed to save data, please check your data and internet connection then try again!"}</p>
|
|
390
394
|
</div>
|
|
391
395
|
)}
|
|
392
396
|
</div>
|
|
@@ -396,7 +400,7 @@ export function FormSupervisionComponent({
|
|
|
396
400
|
<ModalConfirmComponent
|
|
397
401
|
show={confirm.show}
|
|
398
402
|
onClose={() => confirm.onClose()}
|
|
399
|
-
title={l.base?.
|
|
403
|
+
title={l.base?.formConfirm ? l.base.formConfirm() : "Are you sure all data is correct?"}
|
|
400
404
|
submitControl={{ onSubmit: () => confirm?.onConfirm(), paint: "primary" }}
|
|
401
405
|
/>
|
|
402
406
|
</>
|
|
@@ -112,31 +112,31 @@ export function TableSupervisionComponent({
|
|
|
112
112
|
shortcut.register("arrowdown", () => {
|
|
113
113
|
const max = data?.data?.length - 1;
|
|
114
114
|
setFocus(focus == null ? 0 : focus >= max ? max : (focus + 1))
|
|
115
|
-
},
|
|
115
|
+
}, l.base.shortcutDown ? l.base.shortcutDown() : "")
|
|
116
116
|
|
|
117
117
|
shortcut.register("arrowup", () => {
|
|
118
118
|
setFocus(focus == null ? 0 : focus <= 0 ? 0 : (focus - 1))
|
|
119
|
-
},
|
|
119
|
+
}, l.base.shortcutUp ? l.base.shortcutUp() : "")
|
|
120
120
|
|
|
121
121
|
if(focus != null) {
|
|
122
122
|
shortcut.register("delete", () => {
|
|
123
123
|
setSelected(data?.data?.at(focus))
|
|
124
124
|
setToggle(`MODAL_DELETE_${toggleKey}`)
|
|
125
|
-
},
|
|
125
|
+
}, l.base.shortcutDelete ? l.base.shortcutDelete() : "")
|
|
126
126
|
|
|
127
127
|
shortcut.register(" ", () => {
|
|
128
128
|
setSelected(data?.data?.at(focus))
|
|
129
129
|
setToggle(`MODAL_FORM_${toggleKey}`)
|
|
130
|
-
},
|
|
130
|
+
}, l.base.shortcutEdit ? l.base.shortcutEdit() : "")
|
|
131
131
|
|
|
132
132
|
shortcut.register("enter", () => {
|
|
133
133
|
setSelected(data?.data?.at(focus))
|
|
134
134
|
setToggle(`MODAL_SHOW_${toggleKey}`)
|
|
135
|
-
},
|
|
135
|
+
}, l.base.shortcutDetail ? l.base.shortcutDetail() : "")
|
|
136
136
|
|
|
137
137
|
shortcut.register("escape", () => {
|
|
138
138
|
setFocus(null)
|
|
139
|
-
}, "
|
|
139
|
+
}, l.base.shortcutBack ? l.base.shortcutBack() : "")
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
142
|
|
|
@@ -339,9 +339,9 @@ export function TableSupervisionComponent({
|
|
|
339
339
|
col : 12,
|
|
340
340
|
type : "text",
|
|
341
341
|
construction : {
|
|
342
|
-
name : typeof col == "string" ? col
|
|
343
|
-
label : typeof col == "string" ? col
|
|
344
|
-
placeholder : `
|
|
342
|
+
name : typeof col == "string" ? col : col?.selector,
|
|
343
|
+
label : typeof col == "string" ? col : col?.label,
|
|
344
|
+
placeholder : l.base.inputPlaceholder ? l.base.inputPlaceholder(`${ typeof col == "string" ? col : col?.label}`) : `Enter ${ typeof col == "string" ? col : col?.label}...`,
|
|
345
345
|
},
|
|
346
346
|
};
|
|
347
347
|
}) || (data?.data?.at(0) ? Object.keys(data.data[0]).map((col) => {
|
|
@@ -351,7 +351,7 @@ export function TableSupervisionComponent({
|
|
|
351
351
|
construction : {
|
|
352
352
|
name : col,
|
|
353
353
|
label : col,
|
|
354
|
-
placeholder : `
|
|
354
|
+
placeholder : l.base.inputPlaceholder ? l.base.inputPlaceholder(col) : `Enter ${col}...`,
|
|
355
355
|
},
|
|
356
356
|
};
|
|
357
357
|
})
|
|
@@ -367,12 +367,12 @@ export function TableSupervisionComponent({
|
|
|
367
367
|
return (
|
|
368
368
|
<FormSupervisionComponent
|
|
369
369
|
submitControl={(fetchControl as ApiType).path ? {
|
|
370
|
-
path:
|
|
371
|
-
method:
|
|
372
|
-
}
|
|
373
|
-
url:
|
|
374
|
-
method:
|
|
375
|
-
}
|
|
370
|
+
path : `${(fetchControl as ApiType).path}/${(selected as { id: number })?.id || "" }`,
|
|
371
|
+
method : !(selected as { id: number })?.id ? "POST" : "PUT",
|
|
372
|
+
} : (fetchControl as ApiType).url ? {
|
|
373
|
+
url : `${(fetchControl as ApiType).url}/${(selected as { id: number })?.id || ""}`,
|
|
374
|
+
method : !(selected as { id: number })?.id ? "POST" : "PUT",
|
|
375
|
+
} : { idb: (fetchControl as ({ idb: UseResourceIdb }))?.idb }
|
|
376
376
|
}
|
|
377
377
|
fields={fields?.filter((f: any) => f.visibility ? !(selected as { id: number })?.id ? ["*", "create"]?.includes(f.visibility) : ["*", "update"]?.includes(f.visibility) : true) as FormType[]}
|
|
378
378
|
defaultValue={formControl?.defaultValue ? await formControl?.defaultValue(selected || null) : selected}
|
|
@@ -401,11 +401,12 @@ export function TableSupervisionComponent({
|
|
|
401
401
|
controlBar={controlBar?.map((cb) => {
|
|
402
402
|
if (cb == "CREATE") {
|
|
403
403
|
if (isSm) return
|
|
404
|
+
|
|
404
405
|
return (
|
|
405
406
|
<div className="pl-1.5 pr-3 mr-2 border-r" key="button-add">
|
|
406
407
|
<ButtonComponent
|
|
407
408
|
icon={"solid/plus"}
|
|
408
|
-
label=
|
|
409
|
+
label={l.base.add ? l.base.add() : "Add"}
|
|
409
410
|
size="sm"
|
|
410
411
|
onClick={() => {
|
|
411
412
|
setToggle(`MODAL_FORM_${toggleKey}`)
|
|
@@ -421,7 +422,6 @@ export function TableSupervisionComponent({
|
|
|
421
422
|
<div className="px-1.5 rounded-md relative" key={"import"}>
|
|
422
423
|
<ButtonComponent
|
|
423
424
|
icon={"solid/file-excel"}
|
|
424
|
-
label="Import"
|
|
425
425
|
variant="outline"
|
|
426
426
|
className="!text-foreground"
|
|
427
427
|
onClick={() => setToggle(`MODAL_IMPORT_${toggleKey}`)}
|
|
@@ -436,7 +436,6 @@ export function TableSupervisionComponent({
|
|
|
436
436
|
<div className="px-1.5 rounded-md relative" key={"export-excel"}>
|
|
437
437
|
<ButtonComponent
|
|
438
438
|
icon={"solid/file-excel"}
|
|
439
|
-
label="Export"
|
|
440
439
|
variant="outline"
|
|
441
440
|
className="!text-foreground"
|
|
442
441
|
onClick={() => setToggle(`MODAL_EXPORT_${toggleKey}`)}
|
|
@@ -451,7 +450,7 @@ export function TableSupervisionComponent({
|
|
|
451
450
|
<div className="px-1.5 rounded-md relative" key={"export-pdf"}>
|
|
452
451
|
<ButtonComponent
|
|
453
452
|
icon={"solid/file-pdf"}
|
|
454
|
-
label="
|
|
453
|
+
label={l.base.print ? l.base.print() : "Print"}
|
|
455
454
|
variant="outline"
|
|
456
455
|
className="!text-foreground"
|
|
457
456
|
onClick={() => setToggle(`MODAL_PRINT_${toggleKey}`)}
|
|
@@ -467,7 +466,7 @@ export function TableSupervisionComponent({
|
|
|
467
466
|
<div className="pl-1.5 pr-3 mr-2 border-r" key="button-add">
|
|
468
467
|
<ButtonComponent
|
|
469
468
|
icon={"solid/plus"}
|
|
470
|
-
label=
|
|
469
|
+
label={l.base.add ? l.base.add() : "Add"}
|
|
471
470
|
size="sm"
|
|
472
471
|
onClick={() => {
|
|
473
472
|
setToggle(`MODAL_FORM_${toggleKey}`)
|
|
@@ -532,7 +531,7 @@ export function TableSupervisionComponent({
|
|
|
532
531
|
<FloatingPageComponent
|
|
533
532
|
show={!!toggle[`MODAL_SHOW_${toggleKey}`]}
|
|
534
533
|
onClose={() => setToggle(`MODAL_SHOW_${toggleKey}`, false)}
|
|
535
|
-
title="Detail"
|
|
534
|
+
title={l.base.detailTitle ? l.base.detailTitle() : "Detail"}
|
|
536
535
|
className="bg-background"
|
|
537
536
|
footer={renderTableAction(actionControl, undefined, {className: isSm ? "justify-end p-2 bg-background" : "justify-end", size: isSm ? "sm" : "md"})}
|
|
538
537
|
>
|
|
@@ -543,7 +542,7 @@ export function TableSupervisionComponent({
|
|
|
543
542
|
<FloatingPageComponent
|
|
544
543
|
show={!!toggle[`MODAL_FORM_${toggleKey}`]}
|
|
545
544
|
onClose={() => setToggle(`MODAL_FORM_${toggleKey}`, false)}
|
|
546
|
-
title={!!selected ?
|
|
545
|
+
title={!!selected ? (l.base.editTitle ? l.base.editTitle() : "Edit") : (l.base.addTitle ? l.base.addTitle() : "Add")}
|
|
547
546
|
className={cn("bg-white", formControl?.modalControl?.className)}
|
|
548
547
|
>
|
|
549
548
|
<div className="p-4">
|
|
@@ -555,12 +554,12 @@ export function TableSupervisionComponent({
|
|
|
555
554
|
<FloatingPageComponent
|
|
556
555
|
show={!!toggle[`MODAL_EXPORT_${toggleKey}`]}
|
|
557
556
|
onClose={() => setToggle(`MODAL_EXPORT_${toggleKey}`, false)}
|
|
558
|
-
title=
|
|
557
|
+
title={l.base.exportTitle ? l.base.exportTitle() : "Export"}
|
|
559
558
|
className="bg-white md:w-[1200px] max-w-[1200px]"
|
|
560
559
|
>
|
|
561
560
|
<ExportExcel
|
|
562
561
|
fetchControl={fetchControl}
|
|
563
|
-
filename={"
|
|
562
|
+
filename={"export"}
|
|
564
563
|
columnControl={columns?.map((cc) => ({
|
|
565
564
|
label: cc.label || "",
|
|
566
565
|
selector: cc.selector || "",
|
|
@@ -572,7 +571,7 @@ export function TableSupervisionComponent({
|
|
|
572
571
|
<FloatingPageComponent
|
|
573
572
|
show={!!toggle[`MODAL_IMPORT_${toggleKey}`]}
|
|
574
573
|
onClose={() => setToggle(`MODAL_IMPORT_${toggleKey}`, false)}
|
|
575
|
-
title=
|
|
574
|
+
title={l.base.importTitle ? l.base.importTitle() : "Import"}
|
|
576
575
|
className="bg-white md:w-[1200px] max-w-[1200px]"
|
|
577
576
|
>
|
|
578
577
|
<ImportExcel
|
|
@@ -605,7 +604,7 @@ export function TableSupervisionComponent({
|
|
|
605
604
|
<ModalConfirmComponent
|
|
606
605
|
show={!!toggle[`MODAL_DELETE_${toggleKey}`]}
|
|
607
606
|
onClose={() => setToggle(`MODAL_DELETE_${toggleKey}`, false)}
|
|
608
|
-
title={
|
|
607
|
+
title={l.base.deleteTitle ? l.base.deleteTitle({ data: selected?.[columns?.at(0)?.selector || ""] }) : `Delete ${selected?.[columns?.at(0)?.selector || ""]}?`}
|
|
609
608
|
submitControl={{
|
|
610
609
|
onSubmit: {
|
|
611
610
|
...((fetchControl as ApiType).path
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client"
|
|
2
|
-
import { Icon
|
|
2
|
+
import { Icon } from "@skalfa/skalfa-icon";
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
import { ReactNode, useEffect, useRef } from 'react'
|
|
@@ -12,6 +12,7 @@ import { OutsideClickComponent } from "../wrap/OutsideClick.component";
|
|
|
12
12
|
import { ButtonComponent } from "../button/Button.component";
|
|
13
13
|
import { BottomSheetComponent } from "../modal/BottomSheet.component";
|
|
14
14
|
import { FilterComponent, FilterColumnOption } from "./FilterComponent";
|
|
15
|
+
import { useLang } from "@skalfa/skalfa-lang";
|
|
15
16
|
|
|
16
17
|
export type ControlBarOptionType = "SEARCH" | "SEARCHABLE" | "FILTER" | "SELECTABLE" | "REFRESH" | ReactNode;
|
|
17
18
|
|
|
@@ -56,6 +57,7 @@ export function ControlBarComponent({
|
|
|
56
57
|
filter,
|
|
57
58
|
onRefresh
|
|
58
59
|
}: ControlBarProps) {
|
|
60
|
+
const l = useLang();
|
|
59
61
|
const {toggle, setToggle} = useToggleContext()
|
|
60
62
|
const { isSm } = useResponsive();
|
|
61
63
|
|
|
@@ -65,31 +67,31 @@ export function ControlBarComponent({
|
|
|
65
67
|
if (options?.includes("SEARCH")) {
|
|
66
68
|
shortcut.register("ctrl+s", () => {
|
|
67
69
|
searchRef.current?.focus()
|
|
68
|
-
}, "
|
|
70
|
+
}, l.base.shortcutSearch ? l.base.shortcutSearch() : "Search")
|
|
69
71
|
}
|
|
70
72
|
|
|
71
73
|
if (options?.includes("FILTER")) {
|
|
72
74
|
shortcut.register("ctrl+f", () => {
|
|
73
75
|
setToggle("FILTER")
|
|
74
|
-
}, "Filter")
|
|
76
|
+
}, l.base.shortcutFilter ? l.base.shortcutFilter() : "Filter")
|
|
75
77
|
}
|
|
76
78
|
|
|
77
79
|
if (options?.includes("SORT")) {
|
|
78
80
|
shortcut.register("ctrl+o", () => {
|
|
79
81
|
setToggle("SORT")
|
|
80
|
-
}, "
|
|
82
|
+
}, l.base.shortcutSort ? l.base.shortcutSort() : "Sort")
|
|
81
83
|
}
|
|
82
84
|
|
|
83
85
|
if (options?.includes("SELECTABLE")) {
|
|
84
86
|
shortcut.register("ctrl+l", () => {
|
|
85
87
|
setToggle("SELECTABLE")
|
|
86
|
-
},
|
|
88
|
+
}, l.base.shortcutSelectable ? l.base.shortcutSelectable() : "Select")
|
|
87
89
|
}
|
|
88
90
|
|
|
89
91
|
if (options?.includes("REFRESH")) {
|
|
90
92
|
shortcut.register("ctrl+shift+r", () => {
|
|
91
93
|
onRefresh?.()
|
|
92
|
-
}, "Refresh
|
|
94
|
+
}, l.base.shortcutRefresh ? l.base.shortcutRefresh() : "Refresh")
|
|
93
95
|
}
|
|
94
96
|
|
|
95
97
|
return () => {
|
|
@@ -134,7 +136,7 @@ export function ControlBarComponent({
|
|
|
134
136
|
<div className="control-bar-create-wrapper" key="button-add">
|
|
135
137
|
<ButtonComponent
|
|
136
138
|
icon="solid/plus"
|
|
137
|
-
label=
|
|
139
|
+
label={l.base.add ? l.base.add() : "Add"}
|
|
138
140
|
size="sm"
|
|
139
141
|
onClick={() => setToggle(`MODAL_FORM_${conversion.strSnake(id).toUpperCase()}`)}
|
|
140
142
|
/>
|
|
@@ -155,7 +157,7 @@ export function ControlBarComponent({
|
|
|
155
157
|
<InputComponent
|
|
156
158
|
ref={searchRef}
|
|
157
159
|
name="search"
|
|
158
|
-
placeholder="
|
|
160
|
+
placeholder={l.base.searchPlaceholder ? l.base.searchPlaceholder() : "Search here..."}
|
|
159
161
|
rightIcon="solid/magnifying-glass"
|
|
160
162
|
value={search}
|
|
161
163
|
onChange={(e) => onSearch?.(e)}
|
|
@@ -213,7 +215,7 @@ export function ControlBarComponent({
|
|
|
213
215
|
!toggle.SELECTABLE && "control-bar-dropdown-hidden"
|
|
214
216
|
)}
|
|
215
217
|
>
|
|
216
|
-
<p className='control-bar-dropdown-title'>
|
|
218
|
+
<p className='control-bar-dropdown-title'>{l.base.selectable ? l.base.selectable() : "Show Column"}</p>
|
|
217
219
|
<InputCheckboxComponent
|
|
218
220
|
vertical
|
|
219
221
|
name="show_column"
|
|
@@ -256,7 +258,7 @@ export function ControlBarComponent({
|
|
|
256
258
|
!toggle.SORT && "control-bar-dropdown-hidden"
|
|
257
259
|
)}
|
|
258
260
|
>
|
|
259
|
-
<p className='control-bar-dropdown-title'>
|
|
261
|
+
<p className='control-bar-dropdown-title'>{l.base.sort ? l.base.sort() : "Sort By"}</p>
|
|
260
262
|
<div className='control-bar-sort-list'>
|
|
261
263
|
{sortableOptions?.map((option, key) => {
|
|
262
264
|
const sortBy = sort?.find((s) => s.split(" ")?.at(0) == option?.selector)?.split(" ")?.at(1) || "";
|
|
@@ -376,7 +378,7 @@ export function ControlBarComponent({
|
|
|
376
378
|
<div key={key}>
|
|
377
379
|
<InputComponent
|
|
378
380
|
name="search"
|
|
379
|
-
placeholder="
|
|
381
|
+
placeholder={l.base.searchPlaceholder ? l.base.searchPlaceholder() : "Search here..."}
|
|
380
382
|
rightIcon="solid/magnifying-glass"
|
|
381
383
|
value={search}
|
|
382
384
|
onChange={(e) => onSearch?.(e)}
|
|
@@ -418,7 +420,7 @@ export function ControlBarComponent({
|
|
|
418
420
|
if (option == "SELECTABLE") {
|
|
419
421
|
return (
|
|
420
422
|
<div key={key}>
|
|
421
|
-
<p className='control-bar-mobile-title'>
|
|
423
|
+
<p className='control-bar-mobile-title'>{l.base.selectable ? l.base.selectable() : "Show Column"}</p>
|
|
422
424
|
<InputCheckboxComponent
|
|
423
425
|
vertical
|
|
424
426
|
name="show_column"
|
|
@@ -445,7 +447,7 @@ export function ControlBarComponent({
|
|
|
445
447
|
if (option == "SORT") {
|
|
446
448
|
return sortableOptions?.length ? (
|
|
447
449
|
<div key={key}>
|
|
448
|
-
<p className='control-bar-mobile-title'>
|
|
450
|
+
<p className='control-bar-mobile-title'>{l.base.sort ? l.base.sort() : "Sort By"}</p>
|
|
449
451
|
<div className='flex flex-col'>
|
|
450
452
|
{sortableOptions?.map((option, key) => {
|
|
451
453
|
const sortBy = sort?.find((s) => s.split(" ")?.at(0) == option?.selector)?.split(" ")?.at(1) || "";
|
|
@@ -11,6 +11,7 @@ import { InputNumberComponent } from "../input/InputNumber.component";
|
|
|
11
11
|
import { ModalComponent } from "../modal/Modal.component";
|
|
12
12
|
import { SelectComponent } from "../input/Select.component";
|
|
13
13
|
import { useToggleContext } from "@contexts";
|
|
14
|
+
import { useLang } from "@skalfa/skalfa-lang";
|
|
14
15
|
|
|
15
16
|
type CT = "base" | "title";
|
|
16
17
|
|
|
@@ -65,6 +66,8 @@ export function FilterComponent({
|
|
|
65
66
|
onMinimize,
|
|
66
67
|
className = "",
|
|
67
68
|
}: AdvancedFilterProps) {
|
|
69
|
+
const l = useLang();
|
|
70
|
+
|
|
68
71
|
const { isSm } = useResponsive();
|
|
69
72
|
const { toggle, setToggle } = useToggleContext()
|
|
70
73
|
const [filters, setFilters] = useState<ApiFilterType[]>([]);
|
|
@@ -116,7 +119,7 @@ export function FilterComponent({
|
|
|
116
119
|
<>
|
|
117
120
|
<div className={cn("filter-panel", pcn<CT>(className, "base"))}>
|
|
118
121
|
<div className="filter-panel-header">
|
|
119
|
-
<p className={cn(pcn<CT>(className, "title"))}>Filter</p>
|
|
122
|
+
<p className={cn(pcn<CT>(className, "title"))}>{l.base.filter ? l.base.filter() : "Filter"}</p>
|
|
120
123
|
<div className="filter-panel-controls">
|
|
121
124
|
<div className="filter-panel-bookmarks-wrapper">
|
|
122
125
|
<ButtonComponent
|
|
@@ -150,7 +153,7 @@ export function FilterComponent({
|
|
|
150
153
|
|
|
151
154
|
<ButtonComponent
|
|
152
155
|
icon="solid/rotate"
|
|
153
|
-
label="
|
|
156
|
+
label={l.base.clear ? l.base.clear() : "Filter"}
|
|
154
157
|
variant="outline"
|
|
155
158
|
paint="primary"
|
|
156
159
|
className="filter-panel-bookmark-btn icon::text-slate-400"
|
|
@@ -181,7 +184,7 @@ export function FilterComponent({
|
|
|
181
184
|
<SelectComponent
|
|
182
185
|
name={`filter_logic_${i}`}
|
|
183
186
|
options={LOGIC_OPTIONS}
|
|
184
|
-
placeholder="
|
|
187
|
+
placeholder={l.base.filterLogic ? l.base.filterLogic() : "And/Or"}
|
|
185
188
|
value={f.logic}
|
|
186
189
|
onChange={(e) => handleChange(i, "logic", e as "and" | "or")}
|
|
187
190
|
className="filter-input-field"
|
|
@@ -196,7 +199,7 @@ export function FilterComponent({
|
|
|
196
199
|
label: c.label,
|
|
197
200
|
value: c.selector,
|
|
198
201
|
}))}
|
|
199
|
-
placeholder="
|
|
202
|
+
placeholder={l.base.column ? l.base.column() : "Column"}
|
|
200
203
|
value={f.column}
|
|
201
204
|
onChange={(e) => handleChange(i, "column", e)}
|
|
202
205
|
className="filter-input-field"
|
|
@@ -207,7 +210,7 @@ export function FilterComponent({
|
|
|
207
210
|
<SelectComponent
|
|
208
211
|
name={`filter_operator_${i}`}
|
|
209
212
|
options={FILTER_OPERATORS}
|
|
210
|
-
placeholder="
|
|
213
|
+
placeholder={l.base.filterOperator ? l.base.filterOperator() : "Operation"}
|
|
211
214
|
value={f.type}
|
|
212
215
|
onChange={(e) => handleChange(i, "type", e)}
|
|
213
216
|
className="filter-input-field"
|
|
@@ -254,7 +257,7 @@ export function FilterComponent({
|
|
|
254
257
|
})}
|
|
255
258
|
|
|
256
259
|
<ButtonComponent
|
|
257
|
-
label="
|
|
260
|
+
label={l.base.add ? l.base.add() : "Add"}
|
|
258
261
|
icon="solid/plus"
|
|
259
262
|
variant="outline"
|
|
260
263
|
paint="primary"
|
|
@@ -267,7 +270,7 @@ export function FilterComponent({
|
|
|
267
270
|
<ModalComponent
|
|
268
271
|
show={!!toggle["MODAL_BOOKMARK_LIST"]}
|
|
269
272
|
onClose={() => setToggle("MODAL_BOOKMARK_LIST", false)}
|
|
270
|
-
title="Bookmark
|
|
273
|
+
title={l.base.filterBookmarks ? l.base.filterBookmarks() : "Filter Bookmark"}
|
|
271
274
|
>
|
|
272
275
|
<div className="filter-bookmark-list-container">
|
|
273
276
|
{bookmarks?.length ? bookmarks?.map((b, key) => (
|
|
@@ -296,7 +299,7 @@ export function FilterComponent({
|
|
|
296
299
|
</div>
|
|
297
300
|
</div>
|
|
298
301
|
)) : (
|
|
299
|
-
<div className="filter-bookmark-empty-text"> --
|
|
302
|
+
<div className="filter-bookmark-empty-text"> -- {l.base.filterBookmarkEmpty ? l.base.filterBookmarkEmpty() : "No Bookmark"} --</div>
|
|
300
303
|
)}
|
|
301
304
|
</div>
|
|
302
305
|
</ModalComponent>
|
|
@@ -304,11 +307,11 @@ export function FilterComponent({
|
|
|
304
307
|
<ModalComponent
|
|
305
308
|
show={!!toggle["MODAL_BOOKMARK"]}
|
|
306
309
|
onClose={() => setToggle("MODAL_BOOKMARK", false)}
|
|
307
|
-
title="Bookmark
|
|
310
|
+
title={l.base.filterBookmark ? l.base.filterBookmark() : "Filter Bookmark"}
|
|
308
311
|
footer={
|
|
309
312
|
<div className="flex justify-end">
|
|
310
313
|
<ButtonComponent
|
|
311
|
-
label="
|
|
314
|
+
label={l.base.apply ? l.base.apply() : "Apply"}
|
|
312
315
|
onClick={() => {
|
|
313
316
|
let updated: FilterBookmark[] = [];
|
|
314
317
|
|
|
@@ -339,12 +342,12 @@ export function FilterComponent({
|
|
|
339
342
|
<div className="filter-bookmark-form-container">
|
|
340
343
|
<SelectComponent
|
|
341
344
|
name={`bookmark_id`}
|
|
342
|
-
placeholder="Pilih bookmark filter..."
|
|
345
|
+
placeholder={l.base.filterBookmarkPlaceholder ? l.base.filterBookmarkPlaceholder() : "Pilih bookmark filter..."}
|
|
343
346
|
value={(toggle["MODAL_BOOKMARK"] as { bookmark_id: string })?.bookmark_id ?? ""}
|
|
344
347
|
onChange={e => setToggle("MODAL_BOOKMARK", {...(toggle["MODAL_BOOKMARK"] as object), bookmark_id: e})}
|
|
345
348
|
options={[
|
|
346
349
|
{
|
|
347
|
-
label: "
|
|
350
|
+
label: `-- ${l.base.filterBookmarkNew ? l.base.filterBookmarkNew() : "New Filter Bookmark"} --`,
|
|
348
351
|
value: "new",
|
|
349
352
|
},
|
|
350
353
|
...bookmarks.map((b) => ({
|
|
@@ -357,7 +360,7 @@ export function FilterComponent({
|
|
|
357
360
|
{(toggle["MODAL_BOOKMARK"] as { bookmark_id: string })?.bookmark_id == "new" && (
|
|
358
361
|
<InputComponent
|
|
359
362
|
name="bookmark_name"
|
|
360
|
-
placeholder="Masukkan nama bookmark..."
|
|
363
|
+
placeholder={l.base.filterBookmarkNewPlaceholder ? l.base.filterBookmarkNewPlaceholder() : "Masukkan nama bookmark..."}
|
|
361
364
|
value={(toggle["MODAL_BOOKMARK"] as { bookmark_name: string })?.bookmark_name ?? ""}
|
|
362
365
|
onChange={e => setToggle("MODAL_BOOKMARK", {...(toggle["MODAL_BOOKMARK"] as object), bookmark_name: e})}
|
|
363
366
|
className="filter-bookmark-form-input"
|
|
@@ -392,6 +395,8 @@ export function InputFilterValueComponent({
|
|
|
392
395
|
between,
|
|
393
396
|
multiple,
|
|
394
397
|
}: FilterInputProps) {
|
|
398
|
+
const l = useLang();
|
|
399
|
+
|
|
395
400
|
const resolvedType = type || "text";
|
|
396
401
|
|
|
397
402
|
if (!between) {
|
|
@@ -470,7 +475,7 @@ export function InputFilterValueComponent({
|
|
|
470
475
|
name={`${name}_${pos}`}
|
|
471
476
|
value={Number(currentValue) || 0}
|
|
472
477
|
onChange={handle}
|
|
473
|
-
placeholder={pos === "from" ? "Dari" : "Sampai"}
|
|
478
|
+
placeholder={pos === "from" ? l.base.filterFrom ? l.base.filterFrom() : "Dari" : l.base.filterTo ? l.base.filterTo() : "Sampai"}
|
|
474
479
|
className={className}
|
|
475
480
|
/>
|
|
476
481
|
);
|
|
@@ -480,7 +485,7 @@ export function InputFilterValueComponent({
|
|
|
480
485
|
name={`${name}_${pos}`}
|
|
481
486
|
value={Number(currentValue) || 0}
|
|
482
487
|
onChange={handle}
|
|
483
|
-
placeholder={pos === "from" ? "Dari" : "Sampai"}
|
|
488
|
+
placeholder={pos === "from" ? l.base.filterFrom ? l.base.filterFrom() : "Dari" : l.base.filterTo ? l.base.filterTo() : "Sampai"}
|
|
484
489
|
className={className}
|
|
485
490
|
/>
|
|
486
491
|
);
|
|
@@ -490,7 +495,7 @@ export function InputFilterValueComponent({
|
|
|
490
495
|
name={`${name}_${pos}`}
|
|
491
496
|
value={currentValue as string || ""}
|
|
492
497
|
onChange={handle}
|
|
493
|
-
placeholder={pos === "from" ? "Dari" : "Sampai"}
|
|
498
|
+
placeholder={pos === "from" ? l.base.filterFrom ? l.base.filterFrom() : "Dari" : l.base.filterTo ? l.base.filterTo() : "Sampai"}
|
|
494
499
|
className={className}
|
|
495
500
|
/>
|
|
496
501
|
);
|
|
@@ -500,7 +505,7 @@ export function InputFilterValueComponent({
|
|
|
500
505
|
name={`${name}_${pos}`}
|
|
501
506
|
value={currentValue || ""}
|
|
502
507
|
onChange={(e: any) => handle(e.target.value)}
|
|
503
|
-
placeholder={pos === "from" ? "Dari" : "Sampai"}
|
|
508
|
+
placeholder={pos === "from" ? l.base.filterFrom ? l.base.filterFrom() : "Dari" : l.base.filterTo ? l.base.filterTo() : "Sampai"}
|
|
504
509
|
className={className}
|
|
505
510
|
/>
|
|
506
511
|
);
|
|
@@ -10,6 +10,7 @@ import { ScrollContainerComponent } from "../wrap/ScrollContainer.component";
|
|
|
10
10
|
import { FilterColumnOption } from "./FilterComponent";
|
|
11
11
|
import { CheckboxComponent } from "../input/Checkbox.component";
|
|
12
12
|
import { SwipeComponent, SwipeActionType } from "../wrap/Swipe.component";
|
|
13
|
+
import { useLang } from "@skalfa/skalfa-lang";
|
|
13
14
|
|
|
14
15
|
type CT = "controller-bar" | "head-column" | "column" | "row" | "floating-action" | "base";
|
|
15
16
|
|
|
@@ -102,6 +103,8 @@ export function TableComponent({
|
|
|
102
103
|
|
|
103
104
|
className = "",
|
|
104
105
|
}: TableProps) {
|
|
106
|
+
const l = useLang();
|
|
107
|
+
|
|
105
108
|
const [displayColumns, setDisplayColumns] = useState<string[]>([]);
|
|
106
109
|
const [showFloatingAction, setShowFloatingAction] = useState(false);
|
|
107
110
|
const [floatingActionActive, setFloatingActionActive] = useState<false | number>(false);
|
|
@@ -312,14 +315,14 @@ export function TableComponent({
|
|
|
312
315
|
<div className="w-max min-w-full">
|
|
313
316
|
<div className="table-loading-container">
|
|
314
317
|
<h1 className="table-loading-text">
|
|
315
|
-
|
|
318
|
+
{l.base.tableLoading ? l.base.tableLoading() : ""}
|
|
316
319
|
</h1>
|
|
317
320
|
</div>
|
|
318
321
|
</div>
|
|
319
322
|
) : !data || !data.length ? (
|
|
320
323
|
<div className="table-empty-container">
|
|
321
324
|
<h1 className="table-empty-text">
|
|
322
|
-
|
|
325
|
+
{l.base.tableEmpty ? l.base.tableEmpty() : "Data empty"}
|
|
323
326
|
</h1>
|
|
324
327
|
</div>
|
|
325
328
|
) : (
|
|
@@ -413,7 +416,7 @@ export function TableComponent({
|
|
|
413
416
|
|
|
414
417
|
{!!actionBulking && !!checks?.length && (
|
|
415
418
|
<div className="table-bulk-actions-bar">
|
|
416
|
-
<div className="table-bulk-actions-title">{checks?.length}
|
|
419
|
+
<div className="table-bulk-actions-title">{checks?.length} {l.base.tableSelected ? l.base.tableSelected() : ""}</div>
|
|
417
420
|
<div className="table-bulk-actions-buttons">
|
|
418
421
|
{actionBulking?.(checks)}
|
|
419
422
|
</div>
|
|
@@ -4,8 +4,10 @@ import { useEffect, Fragment } from "react";
|
|
|
4
4
|
import { shortcut } from "@utils"
|
|
5
5
|
import { useToggleContext } from "@contexts"
|
|
6
6
|
import { ModalComponent } from "../modal/Modal.component";
|
|
7
|
+
import { useLang } from "@skalfa/skalfa-lang";
|
|
7
8
|
|
|
8
9
|
export function ShortcutProvider() {
|
|
10
|
+
const l = useLang();
|
|
9
11
|
const { setToggle, toggle } = useToggleContext();
|
|
10
12
|
const shortcuts = shortcut.list()
|
|
11
13
|
|
|
@@ -16,7 +18,7 @@ export function ShortcutProvider() {
|
|
|
16
18
|
useEffect(() => {
|
|
17
19
|
shortcut.register("ctrl+/", () => {
|
|
18
20
|
setToggle("MODAL_SHORTCUT_HELP")
|
|
19
|
-
},
|
|
21
|
+
}, l.base.shortcutList ? l.base.shortcutList() : "")
|
|
20
22
|
}, [])
|
|
21
23
|
|
|
22
24
|
function formatShortcutKey(key: string) {
|
|
@@ -39,7 +41,7 @@ export function ShortcutProvider() {
|
|
|
39
41
|
<ModalComponent
|
|
40
42
|
show={!!toggle["MODAL_SHORTCUT_HELP"]}
|
|
41
43
|
onClose={() => setToggle("MODAL_SHORTCUT_HELP")}
|
|
42
|
-
title="
|
|
44
|
+
title={l.base.shortcut ? l.base.shortcut() : ""}
|
|
43
45
|
>
|
|
44
46
|
<div className="shortcut-help-grid">
|
|
45
47
|
{shortcuts.map(({ key, description }) => (
|