@diwauhris/ui 1.5.0 → 1.6.0
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/lib/assets/ui.css +109 -51
- package/lib/index.cjs +2751 -115
- package/lib/index.mjs +2742 -118
- package/lib/types/ui-library/gallery/charts/AreaChart.d.ts +110 -0
- package/lib/types/ui-library/gallery/charts/BarList.d.ts +65 -0
- package/lib/types/ui-library/gallery/charts/Charts.d.ts +21 -5
- package/lib/types/ui-library/gallery/combobox/Combobox.d.ts +2 -1
- package/lib/types/ui-library/gallery/org-chart/OrgChart.d.ts +77 -0
- package/lib/types/ui-library/gallery/org-unit-tree/OrgUnitTree.d.ts +84 -0
- package/lib/types/ui-library/gallery/page-sample/IsoCubeBlock.d.ts +28 -0
- package/lib/types/ui-library/gallery/template-samples/templates/PafTemplate.d.ts +57 -0
- package/lib/types/ui-library/gallery/template-samples/templates/PayslipTemplate.d.ts +42 -0
- package/lib/types/ui-library/gallery/template-samples/templates/ReportTemplate.d.ts +18 -0
- package/lib/types/ui-library/gallery/template-samples/templates/TimekeepingTemplate.d.ts +22 -0
- package/lib/types/ui-library/index.d.ts +19 -1
- package/lib/types/ui-library/registry.d.ts +3 -9
- package/package.json +15 -2
package/lib/index.cjs
CHANGED
|
@@ -32,6 +32,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
32
32
|
//#endregion
|
|
33
33
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
34
34
|
let react = require("react");
|
|
35
|
+
react = __toESM(react, 1);
|
|
35
36
|
let clsx = require("clsx");
|
|
36
37
|
let tailwind_merge = require("tailwind-merge");
|
|
37
38
|
let lucide_react = require("lucide-react");
|
|
@@ -46,6 +47,8 @@ _radix_ui_react_popover = __toESM(_radix_ui_react_popover, 1);
|
|
|
46
47
|
let _radix_ui_react_tooltip = require("@radix-ui/react-tooltip");
|
|
47
48
|
_radix_ui_react_tooltip = __toESM(_radix_ui_react_tooltip, 1);
|
|
48
49
|
let react_router_dom = require("react-router-dom");
|
|
50
|
+
let d3 = require("d3");
|
|
51
|
+
d3 = __toESM(d3, 1);
|
|
49
52
|
let sonner = require("sonner");
|
|
50
53
|
//#region src/ui-library/gallery/button/Button.tsx
|
|
51
54
|
var VARIANT_STYLES$1 = {
|
|
@@ -212,15 +215,15 @@ function getInitials(name) {
|
|
|
212
215
|
return ((parts[0] ?? "").charAt(0) + (parts[parts.length - 1] ?? "").charAt(0)).toUpperCase();
|
|
213
216
|
}
|
|
214
217
|
var PALETTE = [
|
|
215
|
-
"#
|
|
218
|
+
"#00377B",
|
|
219
|
+
"#034EA2",
|
|
220
|
+
"#2D8ACA",
|
|
221
|
+
"#00ADCC",
|
|
222
|
+
"#00A74C",
|
|
223
|
+
"#B61D66",
|
|
224
|
+
"#F68B1F",
|
|
216
225
|
"#0F4C81",
|
|
217
|
-
"#0369A1"
|
|
218
|
-
"#1E3A8A",
|
|
219
|
-
"#0D9488",
|
|
220
|
-
"#0F766E",
|
|
221
|
-
"#B45309",
|
|
222
|
-
"#C2410C",
|
|
223
|
-
"#BE185D"
|
|
226
|
+
"#0369A1"
|
|
224
227
|
];
|
|
225
228
|
function deriveColor(name) {
|
|
226
229
|
if (!name) return PALETTE[0];
|
|
@@ -718,6 +721,7 @@ function RadioItem({ value, label, description, disabled: itemDisabled = false,
|
|
|
718
721
|
const isDisabled = groupDisabled || itemDisabled;
|
|
719
722
|
const isChecked = activeValue === value;
|
|
720
723
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
724
|
+
htmlFor: id,
|
|
721
725
|
className: [
|
|
722
726
|
"group flex cursor-pointer items-start gap-3",
|
|
723
727
|
isDisabled ? "cursor-not-allowed opacity-50" : "",
|
|
@@ -733,7 +737,8 @@ function RadioItem({ value, label, description, disabled: itemDisabled = false,
|
|
|
733
737
|
disabled: isDisabled,
|
|
734
738
|
required,
|
|
735
739
|
onChange: () => !isDisabled && select(value),
|
|
736
|
-
className: "peer sr-only"
|
|
740
|
+
className: "peer sr-only",
|
|
741
|
+
"aria-label": typeof label === "string" ? label : void 0
|
|
737
742
|
}),
|
|
738
743
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
739
744
|
className: [
|
|
@@ -773,6 +778,7 @@ function Switch({ checked, onChange, label, description, disabled = false, loadi
|
|
|
773
778
|
role: "switch",
|
|
774
779
|
"aria-checked": checked,
|
|
775
780
|
"aria-labelledby": labelId,
|
|
781
|
+
"aria-label": !label ? "Toggle" : void 0,
|
|
776
782
|
"aria-disabled": !isInteractive || void 0,
|
|
777
783
|
disabled: !isInteractive,
|
|
778
784
|
onClick: () => isInteractive && onChange(!checked),
|
|
@@ -812,7 +818,7 @@ function Switch({ checked, onChange, label, description, disabled = false, loadi
|
|
|
812
818
|
*/
|
|
813
819
|
var fieldInputClass = "w-full rounded-xl border border-slate-200 bg-slate-50 px-4 py-2.5 text-sm font-medium text-slate-900 outline-none transition placeholder:text-slate-400 focus:border-brand-blue/40 focus:ring-2 focus:ring-brand-blue/15 disabled:cursor-not-allowed disabled:opacity-60";
|
|
814
820
|
var fieldInputErrorClass = "border-rose-300 focus:border-rose-400 focus:ring-rose-100";
|
|
815
|
-
function Combobox({ value, onChange, options, placeholder, className, disabled, loading, error }) {
|
|
821
|
+
function Combobox({ value, onChange, options, placeholder, className, disabled, loading, error, "aria-label": ariaLabel }) {
|
|
816
822
|
const [isOpen, setIsOpen] = (0, react.useState)(false);
|
|
817
823
|
const [search, setSearch] = (0, react.useState)(value);
|
|
818
824
|
const [highlightIndex, setHighlightIndex] = (0, react.useState)(-1);
|
|
@@ -893,6 +899,7 @@ function Combobox({ value, onChange, options, placeholder, className, disabled,
|
|
|
893
899
|
"aria-activedescendant": highlightIndex >= 0 ? optionId(highlightIndex) : void 0,
|
|
894
900
|
"aria-autocomplete": "list",
|
|
895
901
|
"aria-invalid": error ? "true" : void 0,
|
|
902
|
+
"aria-label": ariaLabel,
|
|
896
903
|
value: search,
|
|
897
904
|
onChange: handleInputChange,
|
|
898
905
|
onFocus: () => setIsOpen(true),
|
|
@@ -2394,12 +2401,6 @@ var radius = {
|
|
|
2394
2401
|
* - Use gallery Button component (Phase 11 — replaces legacy inlined btn* strings)
|
|
2395
2402
|
* - Use a simple inline ErrorBanner instead of importing from ui.tsx
|
|
2396
2403
|
*/
|
|
2397
|
-
function ErrorBanner$1({ message }) {
|
|
2398
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2399
|
-
className: "rounded-lg border border-rose-100 bg-rose-50 px-4 py-3 text-sm font-medium text-rose-700",
|
|
2400
|
-
children: message
|
|
2401
|
-
});
|
|
2402
|
-
}
|
|
2403
2404
|
function ConfirmAction({ title, message, label, description, confirmLabel = "Confirm", tone = "danger", disabled = false, onConfirm, children }) {
|
|
2404
2405
|
const [open, setOpen] = (0, react.useState)(false);
|
|
2405
2406
|
const [pending, setPending] = (0, react.useState)(false);
|
|
@@ -2461,7 +2462,7 @@ function ConfirmAction({ title, message, label, description, confirmLabel = "Con
|
|
|
2461
2462
|
className: "text-sm font-medium leading-relaxed text-slate-600",
|
|
2462
2463
|
children: effectiveMessage
|
|
2463
2464
|
})]
|
|
2464
|
-
}), error && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ErrorBanner
|
|
2465
|
+
}), error && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ErrorBanner, { message: error })]
|
|
2465
2466
|
})
|
|
2466
2467
|
})] });
|
|
2467
2468
|
}
|
|
@@ -2952,8 +2953,8 @@ function StepCircle({ state, number, icon }) {
|
|
|
2952
2953
|
}
|
|
2953
2954
|
function Stepper({ steps, currentStep, completedSteps = [], disabledSteps = [], orientation = "horizontal", className = "" }) {
|
|
2954
2955
|
if (!(orientation === "horizontal")) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2956
|
+
role: "group",
|
|
2955
2957
|
"aria-label": "Progress",
|
|
2956
|
-
"aria-orientation": "vertical",
|
|
2957
2958
|
className: ["flex flex-col", className].filter(Boolean).join(" "),
|
|
2958
2959
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ol", {
|
|
2959
2960
|
className: "flex flex-col",
|
|
@@ -3001,34 +3002,48 @@ function Stepper({ steps, currentStep, completedSteps = [], disabledSteps = [],
|
|
|
3001
3002
|
disabled: "text-slate-300"
|
|
3002
3003
|
};
|
|
3003
3004
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3005
|
+
role: "group",
|
|
3004
3006
|
"aria-label": "Progress",
|
|
3005
|
-
"aria-orientation": "horizontal",
|
|
3006
3007
|
className: ["w-full", className].filter(Boolean).join(" "),
|
|
3007
3008
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ol", {
|
|
3008
|
-
className: "
|
|
3009
|
+
className: "grid w-full",
|
|
3010
|
+
style: { gridTemplateColumns: `repeat(${steps.length}, 1fr)` },
|
|
3009
3011
|
children: steps.map((step, idx) => {
|
|
3010
3012
|
const state = resolvedStates[idx];
|
|
3011
3013
|
const isCurrent = state === "current";
|
|
3012
3014
|
const isLast = idx === steps.length - 1;
|
|
3015
|
+
const prevState = idx > 0 ? resolvedStates[idx - 1] : null;
|
|
3013
3016
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
|
|
3014
3017
|
"aria-current": isCurrent ? "step" : void 0,
|
|
3015
|
-
className:
|
|
3018
|
+
className: "flex flex-col items-center",
|
|
3016
3019
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3017
|
-
className: "flex items-center
|
|
3018
|
-
children: [
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3020
|
+
className: "flex w-full items-center",
|
|
3021
|
+
children: [
|
|
3022
|
+
idx > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3023
|
+
className: `h-0.5 flex-1 ${prevState === "completed" || prevState === "current" ? "bg-brand-blue/50" : "bg-slate-200"}`,
|
|
3024
|
+
"aria-hidden": "true"
|
|
3025
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3026
|
+
className: "flex-1",
|
|
3027
|
+
"aria-hidden": "true"
|
|
3028
|
+
}),
|
|
3029
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3030
|
+
className: "shrink-0 z-10",
|
|
3031
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StepCircle, {
|
|
3032
|
+
state,
|
|
3033
|
+
number: idx + 1,
|
|
3034
|
+
icon: step.icon
|
|
3035
|
+
})
|
|
3036
|
+
}),
|
|
3037
|
+
!isLast ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3038
|
+
className: `h-0.5 flex-1 ${state === "completed" ? "bg-brand-blue/50" : "bg-slate-200"}`,
|
|
3039
|
+
"aria-hidden": "true"
|
|
3040
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3041
|
+
className: "flex-1",
|
|
3042
|
+
"aria-hidden": "true"
|
|
3024
3043
|
})
|
|
3025
|
-
|
|
3026
|
-
className: `h-0.5 flex-1 ${state === "completed" ? "bg-brand-blue/50" : "bg-slate-200"}`,
|
|
3027
|
-
"aria-hidden": "true"
|
|
3028
|
-
})]
|
|
3044
|
+
]
|
|
3029
3045
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3030
|
-
className: "mt-2 flex flex-col items-center text-center
|
|
3031
|
-
style: { transform: isLast ? "translateX(calc(50% - 1.125rem))" : idx === 0 ? "translateX(calc(-50% + 1.125rem))" : void 0 },
|
|
3046
|
+
className: "mt-2 flex flex-col items-center text-center px-1",
|
|
3032
3047
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3033
3048
|
className: `text-sm leading-tight ${labelColor[state]}`,
|
|
3034
3049
|
children: step.label
|
|
@@ -3310,20 +3325,22 @@ function Menu({ trigger, items, ariaLabel = "Menu", align = "right" }) {
|
|
|
3310
3325
|
focusItem(items.length - 1);
|
|
3311
3326
|
}
|
|
3312
3327
|
};
|
|
3328
|
+
const panelAlign = align === "left" ? "left-0" : "right-0";
|
|
3313
3329
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3314
3330
|
className: "relative inline-block",
|
|
3315
3331
|
ref: containerRef,
|
|
3316
3332
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3317
3333
|
ref: triggerRef,
|
|
3318
|
-
"aria-expanded": open,
|
|
3319
|
-
"aria-haspopup": "menu",
|
|
3320
3334
|
onClick: () => setOpen((v) => !v),
|
|
3321
3335
|
className: "cursor-pointer",
|
|
3322
|
-
children: trigger
|
|
3336
|
+
children: (0, react.isValidElement)(trigger) ? (0, react.cloneElement)(trigger, {
|
|
3337
|
+
"aria-expanded": open,
|
|
3338
|
+
"aria-haspopup": "menu"
|
|
3339
|
+
}) : trigger
|
|
3323
3340
|
}), open && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3324
3341
|
role: "menu",
|
|
3325
3342
|
"aria-label": ariaLabel,
|
|
3326
|
-
className: `absolute top-full ${
|
|
3343
|
+
className: `absolute top-full ${panelAlign} z-30 mt-1 min-w-[11rem] overflow-hidden rounded-xl border border-slate-200 bg-white py-1 shadow-xl`,
|
|
3327
3344
|
children: items.map((item, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
3328
3345
|
ref: (node) => {
|
|
3329
3346
|
itemRefs.current[index] = node;
|
|
@@ -3727,6 +3744,7 @@ function TimelineValueCard({ beforeLabel = "Previous", afterLabel = "Current", b
|
|
|
3727
3744
|
})]
|
|
3728
3745
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3729
3746
|
className: "text-sm text-slate-500 leading-snug",
|
|
3747
|
+
role: "group",
|
|
3730
3748
|
"aria-label": `${beforeLabel} value`,
|
|
3731
3749
|
children: beforeContent
|
|
3732
3750
|
})]
|
|
@@ -3753,6 +3771,7 @@ function TimelineValueCard({ beforeLabel = "Previous", afterLabel = "Current", b
|
|
|
3753
3771
|
})]
|
|
3754
3772
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3755
3773
|
className: "text-sm font-semibold text-slate-800 leading-snug",
|
|
3774
|
+
role: "group",
|
|
3756
3775
|
"aria-label": `${afterLabel} value`,
|
|
3757
3776
|
children: afterContent
|
|
3758
3777
|
})]
|
|
@@ -3918,11 +3937,11 @@ function EmployeeCard({ name, role, avatarSrc, status, meta, actions, className
|
|
|
3918
3937
|
* onSelect={setSelected}
|
|
3919
3938
|
* />
|
|
3920
3939
|
*/
|
|
3921
|
-
function flattenVisible(items, expanded) {
|
|
3940
|
+
function flattenVisible$1(items, expanded) {
|
|
3922
3941
|
const result = [];
|
|
3923
3942
|
for (const item of items) {
|
|
3924
3943
|
result.push(item);
|
|
3925
|
-
if (item.children && expanded.has(item.id)) result.push(...flattenVisible(item.children, expanded));
|
|
3944
|
+
if (item.children && expanded.has(item.id)) result.push(...flattenVisible$1(item.children, expanded));
|
|
3926
3945
|
}
|
|
3927
3946
|
return result;
|
|
3928
3947
|
}
|
|
@@ -4012,7 +4031,7 @@ function TreeView({ items, selectedId, onSelect, "aria-label": ariaLabel, classN
|
|
|
4012
4031
|
onSelect?.(id);
|
|
4013
4032
|
}, [onSelect]);
|
|
4014
4033
|
const handleKeyDown = (e) => {
|
|
4015
|
-
const visible = flattenVisible(items, expanded);
|
|
4034
|
+
const visible = flattenVisible$1(items, expanded);
|
|
4016
4035
|
if (visible.length === 0) return;
|
|
4017
4036
|
const currentId = selectedId ?? visible[0]?.id;
|
|
4018
4037
|
const currentIdx = visible.findIndex((v) => v.id === currentId);
|
|
@@ -4361,67 +4380,154 @@ function Calendar({ value, defaultValue, onChange, minDate, maxDate, className =
|
|
|
4361
4380
|
}
|
|
4362
4381
|
//#endregion
|
|
4363
4382
|
//#region src/ui-library/gallery/charts/Charts.tsx
|
|
4364
|
-
|
|
4383
|
+
/**
|
|
4384
|
+
* Charts — Design System Components
|
|
4385
|
+
*
|
|
4386
|
+
* Lightweight SVG-native chart primitives. No charting library dependency.
|
|
4387
|
+
* Suitable for simple analytics/KPI displays.
|
|
4388
|
+
*
|
|
4389
|
+
* Components:
|
|
4390
|
+
* BarChart — vertical bar chart
|
|
4391
|
+
* LineChart — line/area chart (SVG path)
|
|
4392
|
+
* CHART_PALETTE — shared default color sequence for multi-series charts
|
|
4393
|
+
*
|
|
4394
|
+
* Visual language (applied as defaults, no new props):
|
|
4395
|
+
* - BarChart: top-only rounded corners, subtle same-hue gradient fill,
|
|
4396
|
+
* baseline rule, value labels inside SVG above bars, comfortable gaps
|
|
4397
|
+
* - LineChart: gradient area fill fading to transparent, strokeWidth 2,
|
|
4398
|
+
* white-ring dots only when ≤ 12 data points, no horizontal distortion
|
|
4399
|
+
*
|
|
4400
|
+
* Accessibility:
|
|
4401
|
+
* - role="img" on every SVG with aria-label describing the chart
|
|
4402
|
+
* - Each bar/point has aria-label with label and value
|
|
4403
|
+
* - Decorative elements are aria-hidden
|
|
4404
|
+
*/
|
|
4405
|
+
/**
|
|
4406
|
+
* Default color sequence for multi-series / per-item charts.
|
|
4407
|
+
* Built on the brand's blue-sky hue family with a single warm accent.
|
|
4408
|
+
* Import this directly when constructing per-item color arrays:
|
|
4409
|
+
*
|
|
4410
|
+
* import { CHART_PALETTE } from '@diwauhris/ui';
|
|
4411
|
+
* const data = items.map((item, i) => ({ ...item, color: CHART_PALETTE[i % CHART_PALETTE.length] }));
|
|
4412
|
+
*/
|
|
4413
|
+
var CHART_PALETTE = [
|
|
4414
|
+
"#034EA2",
|
|
4415
|
+
"#2D8ACA",
|
|
4416
|
+
"#4F6FBF",
|
|
4417
|
+
"#0E7490",
|
|
4418
|
+
"#B45309"
|
|
4419
|
+
];
|
|
4420
|
+
function BarChart({ data, height = 160, barColor = "#034EA2", "aria-label": ariaLabel, className = "" }) {
|
|
4421
|
+
const uid = (0, react.useId)().replace(/:/g, "");
|
|
4365
4422
|
const max = Math.max(...data.map((d) => d.value), 1);
|
|
4366
|
-
const
|
|
4367
|
-
const
|
|
4423
|
+
const n = data.length;
|
|
4424
|
+
const W = Math.max(n * 50, 200);
|
|
4425
|
+
const w = W / n;
|
|
4426
|
+
const gap = w * .2;
|
|
4368
4427
|
const bw = w - gap * 2;
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4428
|
+
const bottomPad = 24;
|
|
4429
|
+
const labelGap = 4;
|
|
4430
|
+
const chartH = height - bottomPad;
|
|
4431
|
+
const baselineY = chartH;
|
|
4432
|
+
const isDefaultBarColor = barColor === "#034EA2";
|
|
4433
|
+
const fillColors = data.map((d, i) => d.color ?? (isDefaultBarColor ? CHART_PALETTE[i % CHART_PALETTE.length] ?? barColor : barColor));
|
|
4434
|
+
const distinctColors = Array.from(new Set(fillColors));
|
|
4435
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4436
|
+
className,
|
|
4437
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
|
|
4372
4438
|
role: "img",
|
|
4373
4439
|
"aria-label": ariaLabel,
|
|
4374
|
-
viewBox: `0 0
|
|
4440
|
+
viewBox: `0 0 ${W} ${height}`,
|
|
4375
4441
|
preserveAspectRatio: "none",
|
|
4376
4442
|
className: "w-full",
|
|
4377
4443
|
style: { height },
|
|
4378
|
-
children: [
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
|
|
4382
|
-
|
|
4383
|
-
"
|
|
4384
|
-
|
|
4385
|
-
|
|
4386
|
-
|
|
4387
|
-
|
|
4388
|
-
|
|
4389
|
-
|
|
4390
|
-
|
|
4391
|
-
|
|
4392
|
-
|
|
4393
|
-
|
|
4394
|
-
|
|
4395
|
-
|
|
4396
|
-
|
|
4397
|
-
|
|
4398
|
-
|
|
4399
|
-
|
|
4400
|
-
|
|
4401
|
-
|
|
4402
|
-
|
|
4403
|
-
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
|
|
4412
|
-
|
|
4413
|
-
|
|
4444
|
+
children: [
|
|
4445
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("defs", { children: distinctColors.map((color) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("linearGradient", {
|
|
4446
|
+
id: `${uid}-bg-${color.replace("#", "")}`,
|
|
4447
|
+
x1: "0",
|
|
4448
|
+
y1: "0",
|
|
4449
|
+
x2: "0",
|
|
4450
|
+
y2: height - bottomPad,
|
|
4451
|
+
gradientUnits: "userSpaceOnUse",
|
|
4452
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("stop", {
|
|
4453
|
+
offset: "0%",
|
|
4454
|
+
stopColor: color,
|
|
4455
|
+
stopOpacity: 1
|
|
4456
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("stop", {
|
|
4457
|
+
offset: "100%",
|
|
4458
|
+
stopColor: color,
|
|
4459
|
+
stopOpacity: .7
|
|
4460
|
+
})]
|
|
4461
|
+
}, color)) }),
|
|
4462
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("line", {
|
|
4463
|
+
x1: 0,
|
|
4464
|
+
y1: baselineY,
|
|
4465
|
+
x2: W,
|
|
4466
|
+
y2: baselineY,
|
|
4467
|
+
stroke: "#e2e8f0",
|
|
4468
|
+
strokeWidth: .5,
|
|
4469
|
+
"aria-hidden": "true"
|
|
4470
|
+
}),
|
|
4471
|
+
data.map((d, i) => {
|
|
4472
|
+
const fillColor = fillColors[i];
|
|
4473
|
+
const gradId = `${uid}-bg-${fillColor.replace("#", "")}`;
|
|
4474
|
+
const barH = d.value / max * (chartH - 16);
|
|
4475
|
+
const x = i * w + gap;
|
|
4476
|
+
const barY = chartH - barH;
|
|
4477
|
+
const rx = Math.min(3, barH * .4);
|
|
4478
|
+
const barPath = barH < 1 ? "" : [
|
|
4479
|
+
`M ${x + rx},${barY}`,
|
|
4480
|
+
`Q ${x},${barY} ${x},${barY + rx}`,
|
|
4481
|
+
`L ${x},${barY + barH}`,
|
|
4482
|
+
`L ${x + bw},${barY + barH}`,
|
|
4483
|
+
`L ${x + bw},${barY + rx}`,
|
|
4484
|
+
`Q ${x + bw},${barY} ${x + bw - rx},${barY}`,
|
|
4485
|
+
"Z"
|
|
4486
|
+
].join(" ");
|
|
4487
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("g", {
|
|
4488
|
+
"aria-label": `${d.label}: ${d.value}`,
|
|
4489
|
+
role: "img",
|
|
4490
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
4491
|
+
d: barPath,
|
|
4492
|
+
fill: `url(#${gradId})`
|
|
4493
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("text", {
|
|
4494
|
+
x: x + bw / 2,
|
|
4495
|
+
y: barY - labelGap,
|
|
4496
|
+
textAnchor: "middle",
|
|
4497
|
+
fontSize: 7,
|
|
4498
|
+
fill: "#64748b",
|
|
4499
|
+
fontWeight: "600",
|
|
4500
|
+
fontFamily: "inherit",
|
|
4501
|
+
"aria-hidden": "true",
|
|
4502
|
+
children: d.value
|
|
4503
|
+
})]
|
|
4504
|
+
}, d.label);
|
|
4505
|
+
}),
|
|
4506
|
+
data.map((d, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("text", {
|
|
4507
|
+
x: i * w + w / 2,
|
|
4508
|
+
y: height - 4,
|
|
4509
|
+
textAnchor: "middle",
|
|
4510
|
+
fontSize: 7,
|
|
4511
|
+
fill: "#94a3b8",
|
|
4512
|
+
fontWeight: "600",
|
|
4513
|
+
fontFamily: "inherit",
|
|
4514
|
+
"aria-hidden": "true",
|
|
4515
|
+
children: d.label
|
|
4516
|
+
}, `lbl-${d.label}`))
|
|
4517
|
+
]
|
|
4518
|
+
})
|
|
4414
4519
|
});
|
|
4415
4520
|
}
|
|
4416
|
-
function LineChart({ data, height = 120, lineColor = "#
|
|
4521
|
+
function LineChart({ data, height = 120, lineColor = "#034EA2", filled = true, "aria-label": ariaLabel, className = "" }) {
|
|
4522
|
+
const uid = (0, react.useId)().replace(/:/g, "");
|
|
4417
4523
|
const max = Math.max(...data.map((d) => d.value), 1);
|
|
4418
4524
|
const n = data.length;
|
|
4419
4525
|
if (n < 2) return null;
|
|
4420
|
-
const
|
|
4421
|
-
const W = 100;
|
|
4526
|
+
const W = 300;
|
|
4422
4527
|
const H = height;
|
|
4423
|
-
const
|
|
4424
|
-
const
|
|
4528
|
+
const pad = Math.round(H * .07);
|
|
4529
|
+
const px = (i) => pad + i / (n - 1) * (W - pad * 2);
|
|
4530
|
+
const py = (v) => pad + (max - v) / max * (H - pad * 2);
|
|
4425
4531
|
const points = data.map((d, i) => ({
|
|
4426
4532
|
x: px(i),
|
|
4427
4533
|
y: py(d.value),
|
|
@@ -4430,38 +4536,314 @@ function LineChart({ data, height = 120, lineColor = "#6366f1", filled = true, "
|
|
|
4430
4536
|
}));
|
|
4431
4537
|
const linePath = points.map((p, i) => `${i === 0 ? "M" : "L"}${p.x},${p.y}`).join(" ");
|
|
4432
4538
|
const areaPath = `${linePath} L${points[n - 1].x},${H - pad} L${points[0].x},${H - pad} Z`;
|
|
4539
|
+
const showDots = n <= 12;
|
|
4433
4540
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
|
|
4434
4541
|
role: "img",
|
|
4435
4542
|
"aria-label": ariaLabel,
|
|
4436
4543
|
viewBox: `0 0 ${W} ${H}`,
|
|
4437
|
-
preserveAspectRatio: "none",
|
|
4438
4544
|
className: `w-full ${className}`,
|
|
4439
4545
|
style: { height },
|
|
4440
4546
|
children: [
|
|
4547
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("defs", { children: filled && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("linearGradient", {
|
|
4548
|
+
id: `${uid}-lc-fill`,
|
|
4549
|
+
x1: "0",
|
|
4550
|
+
y1: "0",
|
|
4551
|
+
x2: "0",
|
|
4552
|
+
y2: "1",
|
|
4553
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("stop", {
|
|
4554
|
+
offset: "0%",
|
|
4555
|
+
stopColor: lineColor,
|
|
4556
|
+
stopOpacity: .2
|
|
4557
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("stop", {
|
|
4558
|
+
offset: "100%",
|
|
4559
|
+
stopColor: lineColor,
|
|
4560
|
+
stopOpacity: 0
|
|
4561
|
+
})]
|
|
4562
|
+
}) }),
|
|
4441
4563
|
filled && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
4442
4564
|
d: areaPath,
|
|
4443
|
-
fill:
|
|
4444
|
-
|
|
4565
|
+
fill: `url(#${uid}-lc-fill)`,
|
|
4566
|
+
"aria-hidden": "true"
|
|
4445
4567
|
}),
|
|
4446
4568
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
4447
4569
|
d: linePath,
|
|
4448
4570
|
fill: "none",
|
|
4449
4571
|
stroke: lineColor,
|
|
4450
|
-
strokeWidth:
|
|
4572
|
+
strokeWidth: 2,
|
|
4451
4573
|
strokeLinejoin: "round",
|
|
4452
|
-
strokeLinecap: "round"
|
|
4574
|
+
strokeLinecap: "round",
|
|
4575
|
+
"aria-hidden": "true"
|
|
4453
4576
|
}),
|
|
4454
|
-
points.map((p) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
|
|
4577
|
+
showDots && points.map((p) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
|
|
4455
4578
|
cx: p.x,
|
|
4456
4579
|
cy: p.y,
|
|
4457
|
-
r: 2,
|
|
4580
|
+
r: 2.5,
|
|
4458
4581
|
fill: lineColor,
|
|
4582
|
+
stroke: "white",
|
|
4583
|
+
strokeWidth: 1.5,
|
|
4584
|
+
role: "img",
|
|
4459
4585
|
"aria-label": `${p.label}: ${p.value}`
|
|
4460
4586
|
}, p.label))
|
|
4461
4587
|
]
|
|
4462
4588
|
});
|
|
4463
4589
|
}
|
|
4464
4590
|
//#endregion
|
|
4591
|
+
//#region src/ui-library/gallery/charts/AreaChart.tsx
|
|
4592
|
+
/**
|
|
4593
|
+
* AreaChart — Design System Component
|
|
4594
|
+
*
|
|
4595
|
+
* SVG area/line chart with gradient fill, explicit Y-axis ticks, optional
|
|
4596
|
+
* threshold line, point annotations, highlight regions, and multi-series support.
|
|
4597
|
+
* No external charting library — native SVG only.
|
|
4598
|
+
*
|
|
4599
|
+
* Gradient IDs are scoped per instance via useId() to avoid SVG ID collisions
|
|
4600
|
+
* when multiple charts appear on the same page.
|
|
4601
|
+
*
|
|
4602
|
+
* Usage:
|
|
4603
|
+
* <AreaChart
|
|
4604
|
+
* data={monthlyData}
|
|
4605
|
+
* series={{ dataKey: 'value', color: '#6366f1', fillOpacity: { top: 0.22, bottom: 0.01 } }}
|
|
4606
|
+
* yTicks={[0, 25, 50, 75, 100]}
|
|
4607
|
+
* yTickFormat={(v) => `${v}%`}
|
|
4608
|
+
* annotations={[{ dataIndex: 5, label: 'Peak', radius: 5, color: '#ef4444' }]}
|
|
4609
|
+
* height={170}
|
|
4610
|
+
* />
|
|
4611
|
+
*
|
|
4612
|
+
* Accessibility:
|
|
4613
|
+
* - role="img" on the SVG with aria-label
|
|
4614
|
+
* - Each dot has aria-label with label and value
|
|
4615
|
+
* - Decorative elements are aria-hidden
|
|
4616
|
+
*/
|
|
4617
|
+
function resolveOpacity(op) {
|
|
4618
|
+
if (op === void 0) return {
|
|
4619
|
+
top: .15,
|
|
4620
|
+
bottom: 0
|
|
4621
|
+
};
|
|
4622
|
+
if (typeof op === "number") return {
|
|
4623
|
+
top: op,
|
|
4624
|
+
bottom: op
|
|
4625
|
+
};
|
|
4626
|
+
return op;
|
|
4627
|
+
}
|
|
4628
|
+
function AreaChart({ data, series, yTicks, yTickFormat, showDots = true, threshold, annotations = [], highlightRegion, height = 170, "aria-label": ariaLabel = "Area chart", className = "" }) {
|
|
4629
|
+
const uid = (0, react.useId)().replace(/:/g, "");
|
|
4630
|
+
const seriesArr = Array.isArray(series) ? series : [series];
|
|
4631
|
+
const primary = seriesArr[0];
|
|
4632
|
+
const W = 560;
|
|
4633
|
+
const pl = 52;
|
|
4634
|
+
const pt = 14;
|
|
4635
|
+
const pb = 30;
|
|
4636
|
+
const cW = 492;
|
|
4637
|
+
const cH = height - pt - pb;
|
|
4638
|
+
const n = data.length;
|
|
4639
|
+
const yTicksSafe = yTicks && yTicks.length > 0 ? yTicks : void 0;
|
|
4640
|
+
const minY = yTicksSafe ? Math.min(...yTicksSafe) : 0;
|
|
4641
|
+
const maxY = yTicksSafe ? Math.max(...yTicksSafe) : Math.max(...seriesArr.flatMap((s) => data.map((d) => Number(d[s.dataKey] ?? 0))), 1);
|
|
4642
|
+
const cx = (i) => pl + i / Math.max(n - 1, 1) * cW;
|
|
4643
|
+
const cy = (v) => pt + (1 - (v - minY) / (maxY - minY)) * cH;
|
|
4644
|
+
const paths = seriesArr.map((s) => {
|
|
4645
|
+
const vals = data.map((d) => Number(d[s.dataKey] ?? 0));
|
|
4646
|
+
const line = "M" + vals.map((v, i) => `${cx(i)},${cy(v)}`).join("L");
|
|
4647
|
+
return {
|
|
4648
|
+
line,
|
|
4649
|
+
area: `${line}L${cx(n - 1)},${height - pb}L${cx(0)},${height - pb}Z`,
|
|
4650
|
+
vals
|
|
4651
|
+
};
|
|
4652
|
+
});
|
|
4653
|
+
const annotatedIdx = new Set(annotations.map((a) => a.dataIndex));
|
|
4654
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
|
|
4655
|
+
role: "img",
|
|
4656
|
+
"aria-label": ariaLabel,
|
|
4657
|
+
viewBox: `0 0 ${W} ${height}`,
|
|
4658
|
+
className: `w-full ${className}`,
|
|
4659
|
+
style: { height },
|
|
4660
|
+
children: [
|
|
4661
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("defs", { children: seriesArr.map((s, si) => {
|
|
4662
|
+
const op = resolveOpacity(s.fillOpacity);
|
|
4663
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("linearGradient", {
|
|
4664
|
+
id: `${uid}-g${si}`,
|
|
4665
|
+
x1: "0",
|
|
4666
|
+
y1: "0",
|
|
4667
|
+
x2: "0",
|
|
4668
|
+
y2: "1",
|
|
4669
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("stop", {
|
|
4670
|
+
offset: "0%",
|
|
4671
|
+
stopColor: s.color,
|
|
4672
|
+
stopOpacity: op.top
|
|
4673
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("stop", {
|
|
4674
|
+
offset: "100%",
|
|
4675
|
+
stopColor: s.color,
|
|
4676
|
+
stopOpacity: op.bottom
|
|
4677
|
+
})]
|
|
4678
|
+
}, si);
|
|
4679
|
+
}) }),
|
|
4680
|
+
highlightRegion && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("g", {
|
|
4681
|
+
"aria-hidden": "true",
|
|
4682
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("rect", {
|
|
4683
|
+
x: cx(highlightRegion.startIndex),
|
|
4684
|
+
y: pt,
|
|
4685
|
+
width: cx(highlightRegion.endIndex) - cx(highlightRegion.startIndex),
|
|
4686
|
+
height: cH,
|
|
4687
|
+
fill: highlightRegion.color ?? "#eef0ff",
|
|
4688
|
+
rx: 3,
|
|
4689
|
+
opacity: .7
|
|
4690
|
+
}), highlightRegion.label && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("text", {
|
|
4691
|
+
x: (cx(highlightRegion.startIndex) + cx(highlightRegion.endIndex)) / 2,
|
|
4692
|
+
y: 23,
|
|
4693
|
+
textAnchor: "middle",
|
|
4694
|
+
fontSize: 7.5,
|
|
4695
|
+
fill: "#a5b4fc",
|
|
4696
|
+
children: highlightRegion.label
|
|
4697
|
+
})]
|
|
4698
|
+
}),
|
|
4699
|
+
yTicks?.map((v) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("g", {
|
|
4700
|
+
"aria-hidden": "true",
|
|
4701
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("line", {
|
|
4702
|
+
x1: pl,
|
|
4703
|
+
y1: cy(v),
|
|
4704
|
+
x2: 544,
|
|
4705
|
+
y2: cy(v),
|
|
4706
|
+
stroke: "#f1f5f9",
|
|
4707
|
+
strokeWidth: 1
|
|
4708
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("text", {
|
|
4709
|
+
x: 46,
|
|
4710
|
+
y: cy(v) + 4,
|
|
4711
|
+
textAnchor: "end",
|
|
4712
|
+
fontSize: 9,
|
|
4713
|
+
fill: "#94a3b8",
|
|
4714
|
+
children: yTickFormat ? yTickFormat(v) : String(v)
|
|
4715
|
+
})]
|
|
4716
|
+
}, v)),
|
|
4717
|
+
threshold && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("line", {
|
|
4718
|
+
x1: pl,
|
|
4719
|
+
y1: cy(threshold.value),
|
|
4720
|
+
x2: 544,
|
|
4721
|
+
y2: cy(threshold.value),
|
|
4722
|
+
stroke: threshold.color ?? "#f59e0b",
|
|
4723
|
+
strokeWidth: 1,
|
|
4724
|
+
strokeDasharray: threshold.strokeStyle === "solid" ? void 0 : "4,2",
|
|
4725
|
+
"aria-hidden": "true"
|
|
4726
|
+
}),
|
|
4727
|
+
seriesArr.map((s, si) => {
|
|
4728
|
+
const op = resolveOpacity(s.fillOpacity);
|
|
4729
|
+
if (op.top === 0 && op.bottom === 0) return null;
|
|
4730
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
4731
|
+
d: paths[si].area,
|
|
4732
|
+
fill: `url(#${uid}-g${si})`,
|
|
4733
|
+
"aria-hidden": "true"
|
|
4734
|
+
}, `area-${si}`);
|
|
4735
|
+
}),
|
|
4736
|
+
seriesArr.map((s, si) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
4737
|
+
d: paths[si].line,
|
|
4738
|
+
fill: "none",
|
|
4739
|
+
stroke: s.color,
|
|
4740
|
+
strokeWidth: si === 0 ? 2.5 : 1.5,
|
|
4741
|
+
strokeLinecap: "round",
|
|
4742
|
+
strokeLinejoin: "round",
|
|
4743
|
+
strokeDasharray: s.strokeStyle === "dashed" ? "4,2" : void 0,
|
|
4744
|
+
"aria-hidden": "true"
|
|
4745
|
+
}, `line-${si}`)),
|
|
4746
|
+
showDots && paths[0].vals.map((v, i) => {
|
|
4747
|
+
if (annotatedIdx.has(i)) return null;
|
|
4748
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
|
|
4749
|
+
cx: cx(i),
|
|
4750
|
+
cy: cy(v),
|
|
4751
|
+
r: 3.5,
|
|
4752
|
+
fill: primary.color,
|
|
4753
|
+
stroke: "white",
|
|
4754
|
+
strokeWidth: 2,
|
|
4755
|
+
"aria-label": `${data[i].label}: ${v}`
|
|
4756
|
+
}, `dot-${i}`);
|
|
4757
|
+
}),
|
|
4758
|
+
data.map((d, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("text", {
|
|
4759
|
+
x: cx(i),
|
|
4760
|
+
y: height - 4,
|
|
4761
|
+
textAnchor: "middle",
|
|
4762
|
+
fontSize: 9,
|
|
4763
|
+
fill: "#94a3b8",
|
|
4764
|
+
"aria-hidden": "true",
|
|
4765
|
+
children: d.label
|
|
4766
|
+
}, `x-${i}`)),
|
|
4767
|
+
annotations.map((ann) => {
|
|
4768
|
+
const v = Number(data[ann.dataIndex]?.[primary.dataKey] ?? 0);
|
|
4769
|
+
const x = cx(ann.dataIndex);
|
|
4770
|
+
const y = cy(v);
|
|
4771
|
+
const r = ann.radius ?? 4;
|
|
4772
|
+
const col = ann.color ?? primary.color;
|
|
4773
|
+
const ly = ann.labelPosition === "below" ? y + r + 10 : Math.max(22, y - r - 5);
|
|
4774
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("g", {
|
|
4775
|
+
"aria-label": `${data[ann.dataIndex].label}: ${ann.label}`,
|
|
4776
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
|
|
4777
|
+
cx: x,
|
|
4778
|
+
cy: y,
|
|
4779
|
+
r,
|
|
4780
|
+
fill: col,
|
|
4781
|
+
stroke: "white",
|
|
4782
|
+
strokeWidth: 2
|
|
4783
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("text", {
|
|
4784
|
+
x,
|
|
4785
|
+
y: ly,
|
|
4786
|
+
textAnchor: "middle",
|
|
4787
|
+
fontSize: 8,
|
|
4788
|
+
fill: col,
|
|
4789
|
+
fontWeight: "bold",
|
|
4790
|
+
children: ann.label
|
|
4791
|
+
})]
|
|
4792
|
+
}, `ann-${ann.dataIndex}`);
|
|
4793
|
+
})
|
|
4794
|
+
]
|
|
4795
|
+
});
|
|
4796
|
+
}
|
|
4797
|
+
//#endregion
|
|
4798
|
+
//#region src/ui-library/gallery/charts/BarList.tsx
|
|
4799
|
+
function BarList({ items, valueFormat, totalLabel, barHeight = "h-2", staggerDelay = 70, className = "" }) {
|
|
4800
|
+
const maxValue = Math.max(...items.map((item) => item.value), 1);
|
|
4801
|
+
const total = items.reduce((sum, item) => sum + item.value, 0);
|
|
4802
|
+
const fmt = valueFormat ?? ((v) => String(v));
|
|
4803
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4804
|
+
role: "list",
|
|
4805
|
+
"aria-label": "Bar list",
|
|
4806
|
+
className: `space-y-3 pt-1 ${className}`,
|
|
4807
|
+
children: [items.map((item, i) => {
|
|
4808
|
+
const pct = item.value / maxValue * 100;
|
|
4809
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4810
|
+
role: "listitem",
|
|
4811
|
+
"aria-label": `${item.label}: ${fmt(item.value)}`,
|
|
4812
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4813
|
+
className: "flex justify-between items-baseline mb-1",
|
|
4814
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4815
|
+
className: "text-xs font-bold text-slate-700",
|
|
4816
|
+
children: item.label
|
|
4817
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4818
|
+
className: "text-xs text-slate-400 font-medium",
|
|
4819
|
+
children: fmt(item.value)
|
|
4820
|
+
})]
|
|
4821
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4822
|
+
className: `${barHeight} w-full bg-slate-100/60 rounded-full overflow-hidden`,
|
|
4823
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4824
|
+
className: `${barHeight} rounded-full os-bar-in`,
|
|
4825
|
+
style: {
|
|
4826
|
+
width: `${pct}%`,
|
|
4827
|
+
backgroundColor: item.color,
|
|
4828
|
+
animationDelay: `${i * staggerDelay}ms`
|
|
4829
|
+
},
|
|
4830
|
+
"aria-hidden": "true"
|
|
4831
|
+
})
|
|
4832
|
+
})]
|
|
4833
|
+
}, item.label);
|
|
4834
|
+
}), totalLabel !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4835
|
+
className: "pt-2 border-t border-slate-50 flex justify-between items-center",
|
|
4836
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4837
|
+
className: "text-[10px] font-bold text-slate-400 uppercase tracking-widest",
|
|
4838
|
+
children: totalLabel
|
|
4839
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4840
|
+
className: "text-sm font-bold text-slate-700",
|
|
4841
|
+
children: total
|
|
4842
|
+
})]
|
|
4843
|
+
})]
|
|
4844
|
+
});
|
|
4845
|
+
}
|
|
4846
|
+
//#endregion
|
|
4465
4847
|
//#region src/ui-library/gallery/heatmap/Heatmap.tsx
|
|
4466
4848
|
/**
|
|
4467
4849
|
* Heatmap — Design System Component
|
|
@@ -4480,31 +4862,31 @@ function LineChart({ data, height = 120, lineColor = "#6366f1", filled = true, "
|
|
|
4480
4862
|
var SCALES = {
|
|
4481
4863
|
blue: { cells: [
|
|
4482
4864
|
"bg-slate-100",
|
|
4483
|
-
"bg-
|
|
4484
|
-
"bg-
|
|
4485
|
-
"bg-
|
|
4486
|
-
"bg-
|
|
4865
|
+
"bg-sky-200",
|
|
4866
|
+
"bg-sky-400",
|
|
4867
|
+
"bg-blue-600",
|
|
4868
|
+
"bg-[#00377B]"
|
|
4487
4869
|
] },
|
|
4488
4870
|
navy: { cells: [
|
|
4489
4871
|
"bg-slate-100",
|
|
4490
|
-
"bg-
|
|
4491
|
-
"bg-
|
|
4492
|
-
"bg-
|
|
4493
|
-
"bg-
|
|
4872
|
+
"bg-slate-300",
|
|
4873
|
+
"bg-slate-500",
|
|
4874
|
+
"bg-slate-700",
|
|
4875
|
+
"bg-slate-900"
|
|
4494
4876
|
] },
|
|
4495
4877
|
teal: { cells: [
|
|
4496
4878
|
"bg-slate-100",
|
|
4497
|
-
"bg-cyan-
|
|
4498
|
-
"bg-cyan-
|
|
4499
|
-
"bg-cyan-
|
|
4500
|
-
"bg-cyan-
|
|
4879
|
+
"bg-cyan-200",
|
|
4880
|
+
"bg-cyan-400",
|
|
4881
|
+
"bg-cyan-600",
|
|
4882
|
+
"bg-cyan-800"
|
|
4501
4883
|
] },
|
|
4502
4884
|
orange: { cells: [
|
|
4503
4885
|
"bg-slate-100",
|
|
4504
|
-
"bg-orange-
|
|
4505
|
-
"bg-orange-300",
|
|
4886
|
+
"bg-orange-200",
|
|
4506
4887
|
"bg-orange-400",
|
|
4507
|
-
"bg-orange-
|
|
4888
|
+
"bg-orange-500",
|
|
4889
|
+
"bg-orange-700"
|
|
4508
4890
|
] }
|
|
4509
4891
|
};
|
|
4510
4892
|
var MONTHS = [
|
|
@@ -4645,6 +5027,2250 @@ function Heatmap({ data, scale = "blue", showLegend = true, showMonthLabels = tr
|
|
|
4645
5027
|
});
|
|
4646
5028
|
}
|
|
4647
5029
|
//#endregion
|
|
5030
|
+
//#region src/ui-library/gallery/org-chart/OrgChart.tsx
|
|
5031
|
+
/**
|
|
5032
|
+
* OrgChart — Design System Component
|
|
5033
|
+
*
|
|
5034
|
+
* A D3-powered SVG organization chart matching the UHRIS Company Structure
|
|
5035
|
+
* diagram mode. Renders a top-down tree with rectangular nodes and
|
|
5036
|
+
* stepped orthogonal connectors.
|
|
5037
|
+
*
|
|
5038
|
+
* Technology: D3 v7 (d3.hierarchy + d3.tree layout + d3.zoom)
|
|
5039
|
+
* Already a production dependency — no new packages introduced.
|
|
5040
|
+
*
|
|
5041
|
+
* Visual design (sourced from CompanyStructurePage diagram mode):
|
|
5042
|
+
* Nodes:
|
|
5043
|
+
* - 250 × 84 px rounded rectangles (rx=14)
|
|
5044
|
+
* - Root (depth 0): dark navy fill (#0f172a), white text
|
|
5045
|
+
* - Children: white fill (#fff), slate border (#e2e8f0)
|
|
5046
|
+
* - drop-shadow: 0 6px 12px rgba(15,23,42,0.08)
|
|
5047
|
+
* - Name: 13px, font-weight 800, centered
|
|
5048
|
+
* - Description: 11px, font-weight 600, #64748b / #cbd5e1 (root)
|
|
5049
|
+
* - Selected: indigo border overlay ring
|
|
5050
|
+
* Connectors:
|
|
5051
|
+
* - Stepped orthogonal path: M→V→H→V
|
|
5052
|
+
* - Stroke: #cbd5e1, stroke-width 1.5
|
|
5053
|
+
* Canvas:
|
|
5054
|
+
* - Viewport sized to container; fit-to-view on render
|
|
5055
|
+
* - Zoom: scaleExtent [0.05, 1.8]
|
|
5056
|
+
* - Pan: mouse/touch drag
|
|
5057
|
+
* - Layout: nodeSize [280, 185] — horizontal × vertical spacing
|
|
5058
|
+
* Controls:
|
|
5059
|
+
* - ZoomIn, Reset, ZoomOut buttons (top-right overlay panel)
|
|
5060
|
+
*
|
|
5061
|
+
* Accessibility:
|
|
5062
|
+
* - SVG has role="img" + aria-label
|
|
5063
|
+
* - Zoom controls have aria-label
|
|
5064
|
+
* - Keyboard: Tab to control buttons; diagram itself is navigated visually
|
|
5065
|
+
* - Note: full ARIA tree semantics are not possible in an SVG diagram;
|
|
5066
|
+
* use OrgUnitTree for a fully keyboard-accessible list-based alternative
|
|
5067
|
+
*
|
|
5068
|
+
* Usage:
|
|
5069
|
+
* <OrgChart
|
|
5070
|
+
* nodes={orgNodes}
|
|
5071
|
+
* selectedId={selectedId}
|
|
5072
|
+
* onSelect={setSelectedId}
|
|
5073
|
+
* aria-label="Company organization chart"
|
|
5074
|
+
* />
|
|
5075
|
+
*/
|
|
5076
|
+
function buildD3Tree(nodes) {
|
|
5077
|
+
function convert(node, depth) {
|
|
5078
|
+
return {
|
|
5079
|
+
id: node.id,
|
|
5080
|
+
name: node.label,
|
|
5081
|
+
description: node.description ?? "",
|
|
5082
|
+
isRoot: depth === 0,
|
|
5083
|
+
isSyntheticRoot: false,
|
|
5084
|
+
originalId: node.id,
|
|
5085
|
+
children: node.children?.map((c) => convert(c, depth + 1))
|
|
5086
|
+
};
|
|
5087
|
+
}
|
|
5088
|
+
if (nodes.length === 1) return convert(nodes[0], 0);
|
|
5089
|
+
return {
|
|
5090
|
+
id: "__synthetic_root__",
|
|
5091
|
+
name: "",
|
|
5092
|
+
description: "",
|
|
5093
|
+
isRoot: true,
|
|
5094
|
+
isSyntheticRoot: true,
|
|
5095
|
+
originalId: "__synthetic_root__",
|
|
5096
|
+
children: nodes.map((n) => convert(n, 0))
|
|
5097
|
+
};
|
|
5098
|
+
}
|
|
5099
|
+
function OrgChart({ nodes, selectedId, onSelect, height = "75vh", "aria-label": ariaLabel = "Organization chart", className = "" }) {
|
|
5100
|
+
const svgRef = (0, react.useRef)(null);
|
|
5101
|
+
const zoomRef = (0, react.useRef)(null);
|
|
5102
|
+
const initialTransformRef = (0, react.useRef)(null);
|
|
5103
|
+
const treeBoundsRef = (0, react.useRef)(null);
|
|
5104
|
+
const uid = (0, react.useId)().replace(/:/g, "");
|
|
5105
|
+
const fitToView = () => {
|
|
5106
|
+
if (!svgRef.current || !zoomRef.current || !treeBoundsRef.current) return;
|
|
5107
|
+
const { width: W, height: H } = svgRef.current.getBoundingClientRect();
|
|
5108
|
+
if (W === 0 || H === 0) return;
|
|
5109
|
+
const { minX, maxX, minY, maxY } = treeBoundsRef.current;
|
|
5110
|
+
const contentLeft = minX - 125;
|
|
5111
|
+
const contentRight = maxX + 125;
|
|
5112
|
+
const contentTop = minY - 42;
|
|
5113
|
+
const contentBottom = maxY + 42;
|
|
5114
|
+
const contentWidth = contentRight - contentLeft;
|
|
5115
|
+
const contentHeight = contentBottom - contentTop;
|
|
5116
|
+
const scaleX = (W - 80) / Math.max(1, contentWidth);
|
|
5117
|
+
const scaleY = (H - 80) / Math.max(1, contentHeight);
|
|
5118
|
+
const scale = Math.max(.05, Math.min(1.8, scaleX, scaleY));
|
|
5119
|
+
const contentCenterX = (contentLeft + contentRight) / 2;
|
|
5120
|
+
const contentCenterY = (contentTop + contentBottom) / 2;
|
|
5121
|
+
const tx = W / 2 - contentCenterX * scale;
|
|
5122
|
+
const ty = H / 2 - contentCenterY * scale;
|
|
5123
|
+
const t = d3.zoomIdentity.translate(tx, ty).scale(scale);
|
|
5124
|
+
initialTransformRef.current = t;
|
|
5125
|
+
d3.select(svgRef.current).call(zoomRef.current.transform, t);
|
|
5126
|
+
};
|
|
5127
|
+
(0, react.useEffect)(() => {
|
|
5128
|
+
if (!svgRef.current || nodes.length === 0) return;
|
|
5129
|
+
const svg = d3.select(svgRef.current);
|
|
5130
|
+
svg.selectAll("*").remove();
|
|
5131
|
+
const treeData = buildD3Tree(nodes);
|
|
5132
|
+
const root = d3.hierarchy(treeData);
|
|
5133
|
+
d3.tree().nodeSize([280, 185])(root);
|
|
5134
|
+
const descendants = root.descendants();
|
|
5135
|
+
treeBoundsRef.current = {
|
|
5136
|
+
minX: d3.min(descendants, (d) => d.x) ?? 0,
|
|
5137
|
+
maxX: d3.max(descendants, (d) => d.x) ?? 0,
|
|
5138
|
+
minY: d3.min(descendants, (d) => d.y) ?? 0,
|
|
5139
|
+
maxY: d3.max(descendants, (d) => d.y) ?? 0
|
|
5140
|
+
};
|
|
5141
|
+
const g = svg.append("g");
|
|
5142
|
+
const zoom = d3.zoom().scaleExtent([.05, 1.8]).on("zoom", (e) => g.attr("transform", e.transform.toString()));
|
|
5143
|
+
zoomRef.current = zoom;
|
|
5144
|
+
svg.call(zoom);
|
|
5145
|
+
g.selectAll("path").data(root.links().filter((l) => !l.source.data.isSyntheticRoot)).join("path").attr("fill", "none").attr("stroke", "#cbd5e1").attr("stroke-width", 1.5).attr("d", (link) => {
|
|
5146
|
+
const sx = link.source.x ?? 0;
|
|
5147
|
+
const sy = link.source.y ?? 0;
|
|
5148
|
+
const tx = link.target.x ?? 0;
|
|
5149
|
+
const ty = link.target.y ?? 0;
|
|
5150
|
+
return `M${sx},${sy}V${(sy + ty) / 2}H${tx}V${ty}`;
|
|
5151
|
+
});
|
|
5152
|
+
const node = g.selectAll("g.node").data(root.descendants().filter((d) => !d.data.isSyntheticRoot)).join("g").attr("class", "node").attr("transform", (d) => `translate(${d.x},${d.y})`).style("cursor", (d) => d.data.originalId !== "__synthetic_root__" ? "pointer" : "default").on("click", (_e, d) => {
|
|
5153
|
+
if (d.data.isSyntheticRoot) return;
|
|
5154
|
+
onSelect?.(d.data.originalId);
|
|
5155
|
+
});
|
|
5156
|
+
node.append("rect").attr("x", -125).attr("y", -42).attr("width", 250).attr("height", 84).attr("rx", 14).attr("fill", (d) => d.data.isRoot ? "#0f172a" : "#fff").attr("stroke", (d) => {
|
|
5157
|
+
if (selectedId && d.data.originalId === selectedId) return "#6366f1";
|
|
5158
|
+
return d.data.isRoot ? "#0f172a" : "#e2e8f0";
|
|
5159
|
+
}).attr("stroke-width", (d) => selectedId && d.data.originalId === selectedId ? 2.5 : 1).attr("filter", "drop-shadow(0 6px 12px rgba(15,23,42,0.08))");
|
|
5160
|
+
node.append("text").attr("text-anchor", "middle").attr("y", -8).attr("font-size", 13).attr("font-weight", 800).attr("fill", (d) => d.data.isRoot ? "#fff" : "#0f172a").text((d) => d.data.name);
|
|
5161
|
+
node.append("text").attr("text-anchor", "middle").attr("y", 16).attr("font-size", 11).attr("font-weight", 600).attr("fill", (d) => d.data.isRoot ? "#cbd5e1" : "#64748b").text((d) => d.data.description);
|
|
5162
|
+
if (selectedId) node.filter((d) => d.data.originalId === selectedId).append("rect").attr("x", -128).attr("y", -45).attr("width", 256).attr("height", 90).attr("rx", 16).attr("fill", "none").attr("stroke", "#6366f1").attr("stroke-width", 2.5).attr("opacity", .6);
|
|
5163
|
+
requestAnimationFrame(() => {
|
|
5164
|
+
fitToView();
|
|
5165
|
+
});
|
|
5166
|
+
}, [
|
|
5167
|
+
nodes,
|
|
5168
|
+
selectedId,
|
|
5169
|
+
onSelect
|
|
5170
|
+
]);
|
|
5171
|
+
(0, react.useEffect)(() => {
|
|
5172
|
+
const el = svgRef.current;
|
|
5173
|
+
if (!el) return;
|
|
5174
|
+
const ro = new ResizeObserver(() => {
|
|
5175
|
+
fitToView();
|
|
5176
|
+
});
|
|
5177
|
+
ro.observe(el);
|
|
5178
|
+
return () => ro.disconnect();
|
|
5179
|
+
}, []);
|
|
5180
|
+
const zoomBy = (factor) => {
|
|
5181
|
+
if (!svgRef.current || !zoomRef.current) return;
|
|
5182
|
+
d3.select(svgRef.current).transition().duration(250).call(zoomRef.current.scaleBy, factor);
|
|
5183
|
+
};
|
|
5184
|
+
const resetZoom = () => {
|
|
5185
|
+
fitToView();
|
|
5186
|
+
};
|
|
5187
|
+
const controlBtnClass = [
|
|
5188
|
+
"appearance-none border-0 bg-none font-[inherit]",
|
|
5189
|
+
"flex items-center justify-center rounded-lg p-2",
|
|
5190
|
+
"text-slate-400 transition hover:bg-slate-100 hover:text-slate-700",
|
|
5191
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-blue/30"
|
|
5192
|
+
].join(" ");
|
|
5193
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5194
|
+
className: `relative w-full overflow-hidden bg-slate-50/50 ${className}`,
|
|
5195
|
+
style: { height },
|
|
5196
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5197
|
+
className: "absolute right-4 top-4 z-10 flex flex-col gap-2 rounded-lg border border-slate-100 bg-white p-2 shadow-md",
|
|
5198
|
+
children: [
|
|
5199
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5200
|
+
type: "button",
|
|
5201
|
+
className: controlBtnClass,
|
|
5202
|
+
onClick: () => zoomBy(1.2),
|
|
5203
|
+
"aria-label": "Zoom in",
|
|
5204
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ZoomIn, {
|
|
5205
|
+
size: 16,
|
|
5206
|
+
"aria-hidden": "true"
|
|
5207
|
+
})
|
|
5208
|
+
}),
|
|
5209
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5210
|
+
type: "button",
|
|
5211
|
+
className: controlBtnClass,
|
|
5212
|
+
onClick: resetZoom,
|
|
5213
|
+
"aria-label": "Reset zoom",
|
|
5214
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.RotateCcw, {
|
|
5215
|
+
size: 16,
|
|
5216
|
+
"aria-hidden": "true"
|
|
5217
|
+
})
|
|
5218
|
+
}),
|
|
5219
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5220
|
+
type: "button",
|
|
5221
|
+
className: controlBtnClass,
|
|
5222
|
+
onClick: () => zoomBy(.8),
|
|
5223
|
+
"aria-label": "Zoom out",
|
|
5224
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ZoomOut, {
|
|
5225
|
+
size: 16,
|
|
5226
|
+
"aria-hidden": "true"
|
|
5227
|
+
})
|
|
5228
|
+
})
|
|
5229
|
+
]
|
|
5230
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
5231
|
+
ref: svgRef,
|
|
5232
|
+
id: uid,
|
|
5233
|
+
width: "100%",
|
|
5234
|
+
height: "100%",
|
|
5235
|
+
className: "block touch-none",
|
|
5236
|
+
role: "img",
|
|
5237
|
+
"aria-label": ariaLabel
|
|
5238
|
+
})]
|
|
5239
|
+
});
|
|
5240
|
+
}
|
|
5241
|
+
//#endregion
|
|
5242
|
+
//#region src/ui-library/gallery/org-unit-tree/OrgUnitTree.tsx
|
|
5243
|
+
/**
|
|
5244
|
+
* OrgUnitTree — Design System Component
|
|
5245
|
+
*
|
|
5246
|
+
* A card-based hierarchical organization tree matching the UHRIS
|
|
5247
|
+
* Company Structure list-mode visual design. Purely presentational —
|
|
5248
|
+
* no API calls, no domain logic, no permissions.
|
|
5249
|
+
*
|
|
5250
|
+
* Visual design (sourced from CompanyStructurePage StructureDesigner):
|
|
5251
|
+
* - Root node: dark navy (bg-slate-900) card with light text
|
|
5252
|
+
* - Child nodes: white bordered cards with blue hover accent
|
|
5253
|
+
* - Connector: left border (border-l border-slate-200) + indentation
|
|
5254
|
+
* - Icon badge: rounded-xl colored square containing the icon
|
|
5255
|
+
* - Actions: hover-reveal slot (opacity-0 → group-hover:opacity-100)
|
|
5256
|
+
* - Meta: right-aligned, hidden on narrow screens
|
|
5257
|
+
*
|
|
5258
|
+
* Accessibility (WAI-ARIA Tree pattern, RFC 1.2):
|
|
5259
|
+
* - role="tree" on root list
|
|
5260
|
+
* - role="treeitem" + aria-expanded + aria-selected + aria-level + aria-disabled
|
|
5261
|
+
* - role="group" on nested lists
|
|
5262
|
+
* - Keyboard: ArrowDown/Up/Left/Right/Home/End/Enter/Space
|
|
5263
|
+
* - Roving tabIndex: only focused item has tabIndex=0
|
|
5264
|
+
*
|
|
5265
|
+
* Usage:
|
|
5266
|
+
* <OrgUnitTree
|
|
5267
|
+
* nodes={orgNodes}
|
|
5268
|
+
* onSelect={(id) => navigate(`/org/${id}`)}
|
|
5269
|
+
* aria-label="Company structure"
|
|
5270
|
+
* />
|
|
5271
|
+
*/
|
|
5272
|
+
function flattenVisible(nodes, expanded) {
|
|
5273
|
+
const result = [];
|
|
5274
|
+
for (const node of nodes) {
|
|
5275
|
+
result.push(node);
|
|
5276
|
+
if (node.children?.length && expanded.has(node.id)) result.push(...flattenVisible(node.children, expanded));
|
|
5277
|
+
}
|
|
5278
|
+
return result;
|
|
5279
|
+
}
|
|
5280
|
+
function findParentId(nodes, targetId) {
|
|
5281
|
+
for (const node of nodes) {
|
|
5282
|
+
if (node.children?.some((c) => c.id === targetId)) return node.id;
|
|
5283
|
+
if (node.children) {
|
|
5284
|
+
const found = findParentId(node.children, targetId);
|
|
5285
|
+
if (found !== null) return found;
|
|
5286
|
+
}
|
|
5287
|
+
}
|
|
5288
|
+
return null;
|
|
5289
|
+
}
|
|
5290
|
+
function OrgUnitTree({ nodes, selectedId, onSelect, defaultExpandedIds, expandedIds: controlledExpandedIds, onExpandedChange, "aria-label": ariaLabel, className = "" }) {
|
|
5291
|
+
const baseId = (0, react.useId)().replace(/:/g, "");
|
|
5292
|
+
const treeRef = (0, react.useRef)(null);
|
|
5293
|
+
const [internalExpanded, setInternalExpanded] = (0, react.useState)(() => {
|
|
5294
|
+
if (defaultExpandedIds) return new Set(defaultExpandedIds);
|
|
5295
|
+
return new Set(nodes.map((n) => n.id));
|
|
5296
|
+
});
|
|
5297
|
+
const expanded = controlledExpandedIds ? new Set(controlledExpandedIds) : internalExpanded;
|
|
5298
|
+
const setExpanded = (0, react.useCallback)((next) => {
|
|
5299
|
+
if (!controlledExpandedIds) setInternalExpanded(next);
|
|
5300
|
+
onExpandedChange?.(Array.from(next));
|
|
5301
|
+
}, [controlledExpandedIds, onExpandedChange]);
|
|
5302
|
+
const [focusedId, setFocusedId] = (0, react.useState)(() => {
|
|
5303
|
+
return flattenVisible(nodes, new Set(nodes.map((n) => n.id))).find((n) => !n.disabled)?.id ?? null;
|
|
5304
|
+
});
|
|
5305
|
+
const toggleExpand = (0, react.useCallback)((id) => {
|
|
5306
|
+
const next = new Set(expanded);
|
|
5307
|
+
if (next.has(id)) next.delete(id);
|
|
5308
|
+
else next.add(id);
|
|
5309
|
+
setExpanded(next);
|
|
5310
|
+
}, [expanded, setExpanded]);
|
|
5311
|
+
const handleSelect = (0, react.useCallback)((id) => {
|
|
5312
|
+
setFocusedId(id);
|
|
5313
|
+
onSelect?.(id);
|
|
5314
|
+
}, [onSelect]);
|
|
5315
|
+
const handleKeyDown = (e) => {
|
|
5316
|
+
const visible = flattenVisible(nodes, expanded).filter((n) => !n.disabled);
|
|
5317
|
+
if (visible.length === 0) return;
|
|
5318
|
+
const focusEl = (id) => {
|
|
5319
|
+
setFocusedId(id);
|
|
5320
|
+
document.getElementById(`${baseId}-${id}`)?.focus();
|
|
5321
|
+
};
|
|
5322
|
+
const currentIdx = focusedId ? visible.findIndex((n) => n.id === focusedId) : -1;
|
|
5323
|
+
const current = focusedId ? visible.find((n) => n.id === focusedId) : null;
|
|
5324
|
+
switch (e.key) {
|
|
5325
|
+
case "ArrowDown": {
|
|
5326
|
+
e.preventDefault();
|
|
5327
|
+
const next = visible[currentIdx + 1];
|
|
5328
|
+
if (next) focusEl(next.id);
|
|
5329
|
+
break;
|
|
5330
|
+
}
|
|
5331
|
+
case "ArrowUp": {
|
|
5332
|
+
e.preventDefault();
|
|
5333
|
+
const prev = visible[currentIdx - 1];
|
|
5334
|
+
if (prev) focusEl(prev.id);
|
|
5335
|
+
break;
|
|
5336
|
+
}
|
|
5337
|
+
case "ArrowRight":
|
|
5338
|
+
e.preventDefault();
|
|
5339
|
+
if (!current) break;
|
|
5340
|
+
if (current.children?.length && !expanded.has(current.id)) {
|
|
5341
|
+
const next = new Set(expanded);
|
|
5342
|
+
next.add(current.id);
|
|
5343
|
+
setExpanded(next);
|
|
5344
|
+
} else if (current.children?.length && expanded.has(current.id)) {
|
|
5345
|
+
const firstChild = visible.find((n, i) => i > currentIdx && n.id === current.children[0]?.id);
|
|
5346
|
+
if (firstChild) focusEl(firstChild.id);
|
|
5347
|
+
}
|
|
5348
|
+
break;
|
|
5349
|
+
case "ArrowLeft":
|
|
5350
|
+
e.preventDefault();
|
|
5351
|
+
if (!current) break;
|
|
5352
|
+
if (current.children?.length && expanded.has(current.id)) {
|
|
5353
|
+
const next = new Set(expanded);
|
|
5354
|
+
next.delete(current.id);
|
|
5355
|
+
setExpanded(next);
|
|
5356
|
+
} else {
|
|
5357
|
+
const parentId = findParentId(nodes, current.id);
|
|
5358
|
+
if (parentId) focusEl(parentId);
|
|
5359
|
+
}
|
|
5360
|
+
break;
|
|
5361
|
+
case "Home":
|
|
5362
|
+
e.preventDefault();
|
|
5363
|
+
if (visible[0]) focusEl(visible[0].id);
|
|
5364
|
+
break;
|
|
5365
|
+
case "End": {
|
|
5366
|
+
e.preventDefault();
|
|
5367
|
+
const last = visible[visible.length - 1];
|
|
5368
|
+
if (last) focusEl(last.id);
|
|
5369
|
+
break;
|
|
5370
|
+
}
|
|
5371
|
+
case "Enter":
|
|
5372
|
+
case " ":
|
|
5373
|
+
e.preventDefault();
|
|
5374
|
+
if (current) {
|
|
5375
|
+
handleSelect(current.id);
|
|
5376
|
+
if (current.children?.length) toggleExpand(current.id);
|
|
5377
|
+
}
|
|
5378
|
+
}
|
|
5379
|
+
};
|
|
5380
|
+
const nodeRefs = (0, react.useRef)(/* @__PURE__ */ new Map());
|
|
5381
|
+
function renderNodes(branch, depth) {
|
|
5382
|
+
return branch.map((node) => {
|
|
5383
|
+
const isExpanded = expanded.has(node.id);
|
|
5384
|
+
const isRoot = depth === 1;
|
|
5385
|
+
const hasChildren = Boolean(node.children?.length);
|
|
5386
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
|
|
5387
|
+
ref: (el) => {
|
|
5388
|
+
if (el) nodeRefs.current.set(node.id, el);
|
|
5389
|
+
else nodeRefs.current.delete(node.id);
|
|
5390
|
+
},
|
|
5391
|
+
id: `${baseId}-${node.id}`,
|
|
5392
|
+
role: "treeitem",
|
|
5393
|
+
"aria-expanded": hasChildren ? isExpanded : void 0,
|
|
5394
|
+
"aria-selected": selectedId === node.id,
|
|
5395
|
+
"aria-disabled": node.disabled || void 0,
|
|
5396
|
+
"aria-level": depth,
|
|
5397
|
+
tabIndex: focusedId === node.id ? 0 : -1,
|
|
5398
|
+
onFocus: () => setFocusedId(node.id),
|
|
5399
|
+
className: "outline-none",
|
|
5400
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5401
|
+
className: ["group mb-2 flex items-center gap-3 rounded-xl border px-3 py-3 transition select-none", isRoot ? "border-slate-900 bg-slate-900 text-slate-300 shadow-md" : selectedId === node.id ? "border-brand-blue/40 bg-blue-50 shadow-sm" : node.disabled ? "border-slate-100 bg-slate-50 opacity-50 cursor-not-allowed" : "border-slate-200 bg-white hover:border-blue-300 hover:shadow-sm cursor-pointer"].filter(Boolean).join(" "),
|
|
5402
|
+
onClick: () => {
|
|
5403
|
+
if (node.disabled) return;
|
|
5404
|
+
if (hasChildren) toggleExpand(node.id);
|
|
5405
|
+
handleSelect(node.id);
|
|
5406
|
+
},
|
|
5407
|
+
children: [
|
|
5408
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5409
|
+
type: "button",
|
|
5410
|
+
"aria-label": isExpanded ? `Collapse ${node.label}` : `Expand ${node.label}`,
|
|
5411
|
+
tabIndex: -1,
|
|
5412
|
+
disabled: !hasChildren,
|
|
5413
|
+
onClick: (e) => {
|
|
5414
|
+
e.stopPropagation();
|
|
5415
|
+
if (hasChildren) toggleExpand(node.id);
|
|
5416
|
+
},
|
|
5417
|
+
className: [
|
|
5418
|
+
"flex items-center justify-center rounded p-1 shrink-0 transition",
|
|
5419
|
+
!hasChildren && "invisible",
|
|
5420
|
+
isRoot ? "hover:bg-slate-700" : "hover:bg-slate-100"
|
|
5421
|
+
].filter(Boolean).join(" "),
|
|
5422
|
+
children: isExpanded ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ChevronDown, {
|
|
5423
|
+
size: 16,
|
|
5424
|
+
"aria-hidden": "true"
|
|
5425
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ChevronRight, {
|
|
5426
|
+
size: 16,
|
|
5427
|
+
"aria-hidden": "true"
|
|
5428
|
+
})
|
|
5429
|
+
}),
|
|
5430
|
+
node.icon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5431
|
+
className: isRoot ? "flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-slate-800 text-slate-200" : "flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-blue-50 text-blue-600",
|
|
5432
|
+
"aria-hidden": "true",
|
|
5433
|
+
children: node.icon
|
|
5434
|
+
}),
|
|
5435
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5436
|
+
className: "min-w-0 flex-1",
|
|
5437
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5438
|
+
className: ["flex flex-wrap items-center gap-2 text-sm font-bold", isRoot ? "text-white" : selectedId === node.id ? "text-brand-blue" : "text-slate-900"].filter(Boolean).join(" "),
|
|
5439
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5440
|
+
className: "truncate",
|
|
5441
|
+
children: node.label
|
|
5442
|
+
}), node.badge && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: node.badge })]
|
|
5443
|
+
}), node.description && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5444
|
+
className: `mt-0.5 truncate text-xs font-medium ${isRoot ? "text-slate-400" : "text-slate-500"}`,
|
|
5445
|
+
children: node.description
|
|
5446
|
+
})]
|
|
5447
|
+
}),
|
|
5448
|
+
node.meta && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5449
|
+
className: `hidden md:flex items-center gap-3 text-xs ${isRoot ? "text-slate-300" : "text-slate-500"}`,
|
|
5450
|
+
children: node.meta
|
|
5451
|
+
}),
|
|
5452
|
+
node.actions && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5453
|
+
className: "flex items-center gap-1 opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100",
|
|
5454
|
+
onClick: (e) => e.stopPropagation(),
|
|
5455
|
+
children: node.actions
|
|
5456
|
+
})
|
|
5457
|
+
]
|
|
5458
|
+
}), hasChildren && isExpanded && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
5459
|
+
role: "group",
|
|
5460
|
+
className: "ml-6 border-l border-slate-200 pl-4",
|
|
5461
|
+
children: renderNodes(node.children, depth + 1)
|
|
5462
|
+
})]
|
|
5463
|
+
}, node.id);
|
|
5464
|
+
});
|
|
5465
|
+
}
|
|
5466
|
+
if (nodes.length === 0) return null;
|
|
5467
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
5468
|
+
ref: treeRef,
|
|
5469
|
+
role: "tree",
|
|
5470
|
+
"aria-label": ariaLabel,
|
|
5471
|
+
onKeyDown: handleKeyDown,
|
|
5472
|
+
className: `w-full outline-none ${className}`,
|
|
5473
|
+
children: renderNodes(nodes, 1)
|
|
5474
|
+
});
|
|
5475
|
+
}
|
|
5476
|
+
//#endregion
|
|
5477
|
+
//#region src/ui-library/gallery/template-samples/templates/PafTemplate.tsx
|
|
5478
|
+
var fmt = new Intl.DateTimeFormat("en-US", {
|
|
5479
|
+
month: "short",
|
|
5480
|
+
day: "2-digit",
|
|
5481
|
+
year: "numeric"
|
|
5482
|
+
});
|
|
5483
|
+
var fmtDate = (v) => {
|
|
5484
|
+
if (!v?.trim()) return "";
|
|
5485
|
+
const n = /^\d{4}-\d{2}-\d{2}$/.test(v.trim()) ? `${v.trim()}T00:00:00` : v.trim();
|
|
5486
|
+
const d = new Date(n);
|
|
5487
|
+
return isNaN(d.getTime()) ? v : fmt.format(d);
|
|
5488
|
+
};
|
|
5489
|
+
var STANDARD_LABELS = [
|
|
5490
|
+
"Basic Salary",
|
|
5491
|
+
"Cola",
|
|
5492
|
+
"Trasa",
|
|
5493
|
+
"Trarep",
|
|
5494
|
+
"Communication",
|
|
5495
|
+
"Car",
|
|
5496
|
+
"Motor",
|
|
5497
|
+
"Others"
|
|
5498
|
+
];
|
|
5499
|
+
function PafTemplate({ data }) {
|
|
5500
|
+
const allComponents = STANDARD_LABELS.map((label) => {
|
|
5501
|
+
const found = data.salaryComponents?.find((c) => c.label.toLowerCase() === label.toLowerCase());
|
|
5502
|
+
if (found) return found;
|
|
5503
|
+
if (label === "Basic Salary") return {
|
|
5504
|
+
label,
|
|
5505
|
+
from: data.from.basicSalary,
|
|
5506
|
+
to: data.to.basicSalary
|
|
5507
|
+
};
|
|
5508
|
+
return {
|
|
5509
|
+
label,
|
|
5510
|
+
from: "",
|
|
5511
|
+
to: ""
|
|
5512
|
+
};
|
|
5513
|
+
});
|
|
5514
|
+
const shownComponents = allComponents.filter((c) => {
|
|
5515
|
+
if (c.label === "Basic Salary") return true;
|
|
5516
|
+
const hasFrom = c.from && parseFloat(c.from.replace(/,/g, "")) !== 0;
|
|
5517
|
+
const hasTo = c.to && parseFloat(c.to.replace(/,/g, "")) !== 0;
|
|
5518
|
+
return hasFrom || hasTo;
|
|
5519
|
+
});
|
|
5520
|
+
const paddingRows = Array.from({ length: Math.max(0, 7 - shownComponents.length) });
|
|
5521
|
+
const calcTotal = (type) => {
|
|
5522
|
+
const t = allComponents.reduce((acc, c) => {
|
|
5523
|
+
const v = parseFloat((type === "from" ? c.from : c.to).replace(/,/g, ""));
|
|
5524
|
+
return acc + (isNaN(v) ? 0 : v);
|
|
5525
|
+
}, 0);
|
|
5526
|
+
return t === 0 ? "" : t.toLocaleString("en-US", {
|
|
5527
|
+
minimumFractionDigits: 2,
|
|
5528
|
+
maximumFractionDigits: 2
|
|
5529
|
+
});
|
|
5530
|
+
};
|
|
5531
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5532
|
+
className: "bg-white text-black font-sans",
|
|
5533
|
+
style: {
|
|
5534
|
+
width: "816px",
|
|
5535
|
+
minHeight: "1056px",
|
|
5536
|
+
padding: "60px 50px",
|
|
5537
|
+
boxSizing: "border-box"
|
|
5538
|
+
},
|
|
5539
|
+
children: [
|
|
5540
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h1", {
|
|
5541
|
+
className: "text-center italic font-bold text-2xl tracking-widest mb-8 uppercase",
|
|
5542
|
+
children: "Personnel Action Form"
|
|
5543
|
+
}),
|
|
5544
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5545
|
+
className: "mb-6",
|
|
5546
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
|
|
5547
|
+
className: "text-sm font-bold italic border-b border-black mb-2 uppercase tracking-tight",
|
|
5548
|
+
children: "Employee Data"
|
|
5549
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5550
|
+
className: "grid grid-cols-12 gap-x-4",
|
|
5551
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5552
|
+
className: "col-span-8 space-y-2",
|
|
5553
|
+
children: [{
|
|
5554
|
+
label: "Employee ID:",
|
|
5555
|
+
value: data.employee.idNo
|
|
5556
|
+
}, {
|
|
5557
|
+
label: "Employee Name:",
|
|
5558
|
+
value: data.employee.name.toUpperCase()
|
|
5559
|
+
}].map((r, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5560
|
+
className: "flex items-center",
|
|
5561
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5562
|
+
className: "w-32 text-[11px] font-bold italic",
|
|
5563
|
+
children: r.label
|
|
5564
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5565
|
+
className: "flex-1 border border-black px-2 py-0.5 text-[12px] min-h-[24px] font-semibold",
|
|
5566
|
+
children: r.value
|
|
5567
|
+
})]
|
|
5568
|
+
}, i))
|
|
5569
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5570
|
+
className: "col-span-4 space-y-2",
|
|
5571
|
+
children: [{
|
|
5572
|
+
label: "Date Hired:",
|
|
5573
|
+
value: fmtDate(data.employee.dateHired) || "Jan 01, 2024"
|
|
5574
|
+
}, {
|
|
5575
|
+
label: "Date Prepared:",
|
|
5576
|
+
value: fmtDate(data.date)
|
|
5577
|
+
}].map((r, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5578
|
+
className: "flex items-center",
|
|
5579
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5580
|
+
className: "w-24 text-[11px] font-bold italic",
|
|
5581
|
+
children: r.label
|
|
5582
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5583
|
+
className: "flex-1 border border-black px-2 py-0.5 text-[12px] min-h-[24px] text-center",
|
|
5584
|
+
children: r.value
|
|
5585
|
+
})]
|
|
5586
|
+
}, i))
|
|
5587
|
+
})]
|
|
5588
|
+
})]
|
|
5589
|
+
}),
|
|
5590
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5591
|
+
className: "mb-6",
|
|
5592
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
|
|
5593
|
+
className: "text-sm font-bold italic border-b border-black mb-2 uppercase tracking-tight",
|
|
5594
|
+
children: "Position/Salary Change Details"
|
|
5595
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("table", {
|
|
5596
|
+
className: "w-full border-collapse",
|
|
5597
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [
|
|
5598
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
|
|
5599
|
+
className: "w-[124px]",
|
|
5600
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5601
|
+
className: "sr-only",
|
|
5602
|
+
children: "Field"
|
|
5603
|
+
})
|
|
5604
|
+
}),
|
|
5605
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
|
|
5606
|
+
className: "text-[12px] italic font-bold text-center pb-1",
|
|
5607
|
+
children: "FROM"
|
|
5608
|
+
}),
|
|
5609
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
|
|
5610
|
+
className: "text-[12px] italic font-bold text-center pb-1",
|
|
5611
|
+
children: "TO"
|
|
5612
|
+
})
|
|
5613
|
+
] }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tbody", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [
|
|
5614
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
5615
|
+
className: "text-[10px] italic font-bold py-1",
|
|
5616
|
+
children: "Pay Template"
|
|
5617
|
+
}),
|
|
5618
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
5619
|
+
className: "border border-black p-1 text-[11px] font-bold w-[300px]",
|
|
5620
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5621
|
+
className: "px-1 min-h-[16px]",
|
|
5622
|
+
children: data.fromTemplate || "—"
|
|
5623
|
+
})
|
|
5624
|
+
}),
|
|
5625
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
5626
|
+
className: "border border-black p-1 text-[11px] font-bold w-[300px]",
|
|
5627
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5628
|
+
className: "px-1 min-h-[16px]",
|
|
5629
|
+
children: data.toTemplate || "—"
|
|
5630
|
+
})
|
|
5631
|
+
})
|
|
5632
|
+
] }), [
|
|
5633
|
+
{
|
|
5634
|
+
label: "Rank",
|
|
5635
|
+
from: data.from.rank,
|
|
5636
|
+
to: data.to.rank
|
|
5637
|
+
},
|
|
5638
|
+
{
|
|
5639
|
+
label: "Employment Status",
|
|
5640
|
+
from: data.from.status,
|
|
5641
|
+
to: data.to.status
|
|
5642
|
+
},
|
|
5643
|
+
{
|
|
5644
|
+
label: "Position",
|
|
5645
|
+
from: data.from.position,
|
|
5646
|
+
to: data.to.position
|
|
5647
|
+
},
|
|
5648
|
+
{
|
|
5649
|
+
label: "Department",
|
|
5650
|
+
from: data.from.department,
|
|
5651
|
+
to: data.to.department
|
|
5652
|
+
},
|
|
5653
|
+
{
|
|
5654
|
+
label: "Supervisor",
|
|
5655
|
+
from: data.from.supervisor,
|
|
5656
|
+
to: data.to.supervisor
|
|
5657
|
+
},
|
|
5658
|
+
{
|
|
5659
|
+
label: "Department Head",
|
|
5660
|
+
from: data.from.departmentHead,
|
|
5661
|
+
to: data.to.departmentHead
|
|
5662
|
+
},
|
|
5663
|
+
{
|
|
5664
|
+
label: "Company",
|
|
5665
|
+
from: data.from.company,
|
|
5666
|
+
to: data.to.company
|
|
5667
|
+
}
|
|
5668
|
+
].map((row, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [
|
|
5669
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
5670
|
+
className: "text-[10px] italic font-bold py-1",
|
|
5671
|
+
children: row.label
|
|
5672
|
+
}),
|
|
5673
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
5674
|
+
className: "border border-black p-1 text-[11px] w-[300px]",
|
|
5675
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5676
|
+
className: "px-1 min-h-[16px]",
|
|
5677
|
+
children: row.from
|
|
5678
|
+
})
|
|
5679
|
+
}),
|
|
5680
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
5681
|
+
className: "border border-black p-1 text-[11px] w-[300px]",
|
|
5682
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5683
|
+
className: "px-1 min-h-[16px]",
|
|
5684
|
+
children: row.to
|
|
5685
|
+
})
|
|
5686
|
+
})
|
|
5687
|
+
] }, i))] })]
|
|
5688
|
+
})]
|
|
5689
|
+
}),
|
|
5690
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5691
|
+
className: "mb-6",
|
|
5692
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
|
|
5693
|
+
className: "text-sm font-bold italic border-b border-black mb-2 uppercase tracking-tight",
|
|
5694
|
+
children: "Reason for Adjustment"
|
|
5695
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5696
|
+
className: "flex mb-2",
|
|
5697
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5698
|
+
className: "flex-1",
|
|
5699
|
+
children: [
|
|
5700
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5701
|
+
className: "flex items-center mb-1",
|
|
5702
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5703
|
+
className: "text-[10px] italic font-bold w-32",
|
|
5704
|
+
children: "Date of Effectivity:"
|
|
5705
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5706
|
+
className: "text-[11px] font-bold",
|
|
5707
|
+
children: fmtDate(data.effectiveDate)
|
|
5708
|
+
})]
|
|
5709
|
+
}),
|
|
5710
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5711
|
+
className: "text-[10px] italic font-bold mb-1",
|
|
5712
|
+
children: "Reason for Adjustment:"
|
|
5713
|
+
}),
|
|
5714
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5715
|
+
className: "flex items-start ml-4",
|
|
5716
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5717
|
+
className: "text-[10px] italic mt-1",
|
|
5718
|
+
children: "Others"
|
|
5719
|
+
})
|
|
5720
|
+
})
|
|
5721
|
+
]
|
|
5722
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5723
|
+
className: "w-[450px]",
|
|
5724
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("table", {
|
|
5725
|
+
className: "w-full border-collapse",
|
|
5726
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [
|
|
5727
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
|
|
5728
|
+
className: "w-1/3",
|
|
5729
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5730
|
+
className: "sr-only",
|
|
5731
|
+
children: "Component"
|
|
5732
|
+
})
|
|
5733
|
+
}),
|
|
5734
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
|
|
5735
|
+
className: "text-[11px] italic font-bold text-center border-x border-t border-black py-1",
|
|
5736
|
+
children: "FROM"
|
|
5737
|
+
}),
|
|
5738
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
|
|
5739
|
+
className: "text-[11px] italic font-bold text-center border-r border-t border-black py-1",
|
|
5740
|
+
children: "TO"
|
|
5741
|
+
})
|
|
5742
|
+
] }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tbody", {
|
|
5743
|
+
className: "border-b border-black",
|
|
5744
|
+
children: [
|
|
5745
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [
|
|
5746
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
5747
|
+
className: "text-[10px] italic pr-4 text-right font-bold uppercase",
|
|
5748
|
+
children: "Template"
|
|
5749
|
+
}),
|
|
5750
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
5751
|
+
className: "border-x border-black px-2 py-0.5 text-[9px] text-center font-bold",
|
|
5752
|
+
children: data.fromTemplate || "—"
|
|
5753
|
+
}),
|
|
5754
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
5755
|
+
className: "border-r border-black px-2 py-0.5 text-[9px] text-center font-bold",
|
|
5756
|
+
children: data.toTemplate || "—"
|
|
5757
|
+
})
|
|
5758
|
+
] }),
|
|
5759
|
+
shownComponents.map((c, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [
|
|
5760
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
5761
|
+
className: "text-[10px] italic pr-4 text-right font-bold",
|
|
5762
|
+
children: c.label
|
|
5763
|
+
}),
|
|
5764
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
5765
|
+
className: "border-x border-black px-2 py-0.5 text-[11px] text-right min-h-[18px]",
|
|
5766
|
+
children: c.from && parseFloat(c.from.replace(/,/g, "")) !== 0 ? c.from : ""
|
|
5767
|
+
}),
|
|
5768
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
5769
|
+
className: "border-r border-black px-2 py-0.5 text-[11px] text-right min-h-[18px]",
|
|
5770
|
+
children: c.to && parseFloat(c.to.replace(/,/g, "")) !== 0 ? c.to : ""
|
|
5771
|
+
})
|
|
5772
|
+
] }, i)),
|
|
5773
|
+
paddingRows.map((_, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [
|
|
5774
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
5775
|
+
className: "text-[10px] py-1",
|
|
5776
|
+
children: "\xA0"
|
|
5777
|
+
}),
|
|
5778
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
5779
|
+
className: "border-x border-black",
|
|
5780
|
+
children: "\xA0"
|
|
5781
|
+
}),
|
|
5782
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
5783
|
+
className: "border-r border-black",
|
|
5784
|
+
children: "\xA0"
|
|
5785
|
+
})
|
|
5786
|
+
] }, `p-${i}`)),
|
|
5787
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", {
|
|
5788
|
+
className: "border-t border-black",
|
|
5789
|
+
children: [
|
|
5790
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
5791
|
+
className: "text-[10px] italic pr-4 text-right font-bold uppercase py-1",
|
|
5792
|
+
children: "Total"
|
|
5793
|
+
}),
|
|
5794
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
5795
|
+
className: "border-x border-black px-2 py-1 text-[11px] text-right font-bold",
|
|
5796
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5797
|
+
className: "border-b-4 border-double border-black pb-0.5",
|
|
5798
|
+
children: calcTotal("from")
|
|
5799
|
+
})
|
|
5800
|
+
}),
|
|
5801
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
5802
|
+
className: "border-r border-black px-2 py-1 text-[11px] text-right font-bold",
|
|
5803
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5804
|
+
className: "border-b-4 border-double border-black pb-0.5",
|
|
5805
|
+
children: calcTotal("to")
|
|
5806
|
+
})
|
|
5807
|
+
})
|
|
5808
|
+
]
|
|
5809
|
+
})
|
|
5810
|
+
]
|
|
5811
|
+
})]
|
|
5812
|
+
})
|
|
5813
|
+
})]
|
|
5814
|
+
})]
|
|
5815
|
+
}),
|
|
5816
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5817
|
+
className: "mb-8",
|
|
5818
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
|
|
5819
|
+
className: "text-sm font-bold italic border-b border-black mb-2 uppercase tracking-tight",
|
|
5820
|
+
children: "Reason for Change"
|
|
5821
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5822
|
+
className: "border border-black p-2 min-h-[60px] text-[11px] break-words whitespace-pre-wrap",
|
|
5823
|
+
children: data.reason
|
|
5824
|
+
})]
|
|
5825
|
+
}),
|
|
5826
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5827
|
+
className: "mt-10",
|
|
5828
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
|
|
5829
|
+
className: "text-sm font-bold italic border-b border-black mb-4 uppercase tracking-tight",
|
|
5830
|
+
children: "Authorized Signatories"
|
|
5831
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5832
|
+
className: "grid grid-cols-3 gap-6 mb-8",
|
|
5833
|
+
children: [
|
|
5834
|
+
{
|
|
5835
|
+
heading: "Prepared By",
|
|
5836
|
+
name: data.preparedBy,
|
|
5837
|
+
title: data.preparedByTitle || "HRMD Supervisor"
|
|
5838
|
+
},
|
|
5839
|
+
{
|
|
5840
|
+
heading: "Verified By",
|
|
5841
|
+
name: data.approvedBy || "VP of HRMD",
|
|
5842
|
+
title: data.approvedByTitle || "Vice President for HRMD"
|
|
5843
|
+
},
|
|
5844
|
+
{
|
|
5845
|
+
heading: "Conforme",
|
|
5846
|
+
name: data.employee.name,
|
|
5847
|
+
title: "Employee"
|
|
5848
|
+
}
|
|
5849
|
+
].map((sig, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5850
|
+
className: "flex flex-col",
|
|
5851
|
+
children: [
|
|
5852
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
|
|
5853
|
+
className: "text-[11px] italic font-bold mb-3",
|
|
5854
|
+
children: sig.heading
|
|
5855
|
+
}),
|
|
5856
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "border-b border-black min-h-[48px] mb-1" }),
|
|
5857
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5858
|
+
className: "text-center",
|
|
5859
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5860
|
+
className: "text-[10px] font-bold uppercase",
|
|
5861
|
+
children: sig.name
|
|
5862
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5863
|
+
className: "text-[9px] font-bold text-slate-400",
|
|
5864
|
+
children: sig.title
|
|
5865
|
+
})]
|
|
5866
|
+
})
|
|
5867
|
+
]
|
|
5868
|
+
}, i))
|
|
5869
|
+
})]
|
|
5870
|
+
}),
|
|
5871
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5872
|
+
className: "mt-6 border-t-2 border-dashed border-black pt-2 opacity-30 text-center",
|
|
5873
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5874
|
+
className: "text-[7px] font-black uppercase tracking-[0.2em] italic",
|
|
5875
|
+
children: "Authorized Document — DIWA HRIS"
|
|
5876
|
+
})
|
|
5877
|
+
})
|
|
5878
|
+
]
|
|
5879
|
+
});
|
|
5880
|
+
}
|
|
5881
|
+
//#endregion
|
|
5882
|
+
//#region src/ui-library/gallery/page-sample/IsoCubeBlock.tsx
|
|
5883
|
+
function IsoCubeBlock({ boxWidth = 80, className = "" }) {
|
|
5884
|
+
const BW = boxWidth;
|
|
5885
|
+
const IH = BW * .575;
|
|
5886
|
+
const SH = BW * .525;
|
|
5887
|
+
const TOP_C = "#F3F3F5";
|
|
5888
|
+
const LEFT_C = "#7D739B";
|
|
5889
|
+
const RIGHT_C = "#9B92B8";
|
|
5890
|
+
function Box({ cx, cy }) {
|
|
5891
|
+
const hw = BW / 2;
|
|
5892
|
+
const A = `${cx + hw},${cy - IH}`;
|
|
5893
|
+
const B = `${cx + BW},${cy - IH / 2}`;
|
|
5894
|
+
const C = `${cx + hw},${cy}`;
|
|
5895
|
+
const D = `${cx},${cy - IH / 2}`;
|
|
5896
|
+
const E = `${cx + hw},${cy + SH}`;
|
|
5897
|
+
const F = `${cx},${cy - IH / 2 + SH}`;
|
|
5898
|
+
const G = `${cx + BW},${cy - IH / 2 + SH}`;
|
|
5899
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("g", { children: [
|
|
5900
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("polygon", {
|
|
5901
|
+
points: `${A} ${B} ${C} ${D}`,
|
|
5902
|
+
fill: TOP_C
|
|
5903
|
+
}),
|
|
5904
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("polygon", {
|
|
5905
|
+
points: `${D} ${C} ${E} ${F}`,
|
|
5906
|
+
fill: LEFT_C
|
|
5907
|
+
}),
|
|
5908
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("polygon", {
|
|
5909
|
+
points: `${B} ${C} ${E} ${G}`,
|
|
5910
|
+
fill: RIGHT_C
|
|
5911
|
+
})
|
|
5912
|
+
] });
|
|
5913
|
+
}
|
|
5914
|
+
const COLS = 4;
|
|
5915
|
+
const ROWS = 4;
|
|
5916
|
+
const SVG_W = BW * 6;
|
|
5917
|
+
const SVG_H = BW * 4.75;
|
|
5918
|
+
const rowDY = -(IH / 2 + SH);
|
|
5919
|
+
const baseX = SVG_W - BW / 2;
|
|
5920
|
+
const baseY = SVG_H;
|
|
5921
|
+
const boxes = [];
|
|
5922
|
+
for (let row = 0; row < ROWS; row++) for (let col = 0; col < COLS; col++) {
|
|
5923
|
+
const cx = baseX - col * BW + row * (BW / 2);
|
|
5924
|
+
const cy = baseY + row * rowDY;
|
|
5925
|
+
boxes.push({
|
|
5926
|
+
cx,
|
|
5927
|
+
cy,
|
|
5928
|
+
key: `${row}-${col}`
|
|
5929
|
+
});
|
|
5930
|
+
}
|
|
5931
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
5932
|
+
"aria-hidden": "true",
|
|
5933
|
+
className: `pointer-events-none absolute bottom-0 right-0 ${className}`,
|
|
5934
|
+
width: SVG_W,
|
|
5935
|
+
height: SVG_H,
|
|
5936
|
+
viewBox: `0 0 ${SVG_W} ${SVG_H}`,
|
|
5937
|
+
style: { zIndex: 0 },
|
|
5938
|
+
overflow: "visible",
|
|
5939
|
+
children: [...boxes].sort((a, b) => {
|
|
5940
|
+
const [ar, ac] = a.key.split("-").map(Number);
|
|
5941
|
+
const [br, bc] = b.key.split("-").map(Number);
|
|
5942
|
+
if (ar !== br) return (br ?? 0) - (ar ?? 0);
|
|
5943
|
+
return (bc ?? 0) - (ac ?? 0);
|
|
5944
|
+
}).map(({ cx, cy, key }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Box, {
|
|
5945
|
+
cx,
|
|
5946
|
+
cy
|
|
5947
|
+
}, key))
|
|
5948
|
+
});
|
|
5949
|
+
}
|
|
5950
|
+
//#endregion
|
|
5951
|
+
//#region src/ui-library/gallery/template-samples/templates/PayslipTemplate.tsx
|
|
5952
|
+
var DEDUCTIONS = [
|
|
5953
|
+
{
|
|
5954
|
+
label: "W-Tax",
|
|
5955
|
+
amount: 117.59,
|
|
5956
|
+
remainingBalance: void 0,
|
|
5957
|
+
base: void 0
|
|
5958
|
+
},
|
|
5959
|
+
{
|
|
5960
|
+
label: "Pag-Ibig",
|
|
5961
|
+
amount: 100,
|
|
5962
|
+
remainingBalance: void 0,
|
|
5963
|
+
base: void 0
|
|
5964
|
+
},
|
|
5965
|
+
{
|
|
5966
|
+
label: "HMO Premium",
|
|
5967
|
+
amount: 229.99,
|
|
5968
|
+
remainingBalance: void 0,
|
|
5969
|
+
base: 5059.84
|
|
5970
|
+
},
|
|
5971
|
+
{
|
|
5972
|
+
label: "Insurance",
|
|
5973
|
+
amount: 19.44,
|
|
5974
|
+
remainingBalance: void 0,
|
|
5975
|
+
base: 427.62
|
|
5976
|
+
},
|
|
5977
|
+
{
|
|
5978
|
+
label: "COOP Share",
|
|
5979
|
+
amount: 300,
|
|
5980
|
+
remainingBalance: 4500,
|
|
5981
|
+
base: void 0
|
|
5982
|
+
},
|
|
5983
|
+
{
|
|
5984
|
+
label: "Salary Loan",
|
|
5985
|
+
amount: 1250,
|
|
5986
|
+
remainingBalance: 12500,
|
|
5987
|
+
base: void 0
|
|
5988
|
+
}
|
|
5989
|
+
];
|
|
5990
|
+
var ATTENDANCE_LOGS = [
|
|
5991
|
+
{
|
|
5992
|
+
in: "07:00",
|
|
5993
|
+
out: "16:00"
|
|
5994
|
+
},
|
|
5995
|
+
{
|
|
5996
|
+
in: "07:15",
|
|
5997
|
+
out: "16:00"
|
|
5998
|
+
},
|
|
5999
|
+
{
|
|
6000
|
+
in: "Reg. Hol",
|
|
6001
|
+
out: "Reg. Hol"
|
|
6002
|
+
},
|
|
6003
|
+
{
|
|
6004
|
+
in: "Sp. Hol",
|
|
6005
|
+
out: "Sp. Hol"
|
|
6006
|
+
},
|
|
6007
|
+
{
|
|
6008
|
+
in: "-",
|
|
6009
|
+
out: "-"
|
|
6010
|
+
},
|
|
6011
|
+
{
|
|
6012
|
+
in: "-",
|
|
6013
|
+
out: "-"
|
|
6014
|
+
},
|
|
6015
|
+
{
|
|
6016
|
+
in: "07:00",
|
|
6017
|
+
out: "16:00"
|
|
6018
|
+
},
|
|
6019
|
+
{
|
|
6020
|
+
in: "VL w/pay",
|
|
6021
|
+
out: "VL w/pay"
|
|
6022
|
+
},
|
|
6023
|
+
{
|
|
6024
|
+
in: "SL w/pay",
|
|
6025
|
+
out: "SL w/pay"
|
|
6026
|
+
},
|
|
6027
|
+
{
|
|
6028
|
+
in: "07:00",
|
|
6029
|
+
out: "12:00 (VL)"
|
|
6030
|
+
},
|
|
6031
|
+
{
|
|
6032
|
+
in: "07:00",
|
|
6033
|
+
out: "13:00 (SL)"
|
|
6034
|
+
},
|
|
6035
|
+
{
|
|
6036
|
+
in: "07:00 (RH)",
|
|
6037
|
+
out: "16:00"
|
|
6038
|
+
},
|
|
6039
|
+
{
|
|
6040
|
+
in: "-",
|
|
6041
|
+
out: "-"
|
|
6042
|
+
},
|
|
6043
|
+
{
|
|
6044
|
+
in: "07:00",
|
|
6045
|
+
out: "16:00"
|
|
6046
|
+
},
|
|
6047
|
+
{
|
|
6048
|
+
in: "07:00",
|
|
6049
|
+
out: "16:00"
|
|
6050
|
+
},
|
|
6051
|
+
{
|
|
6052
|
+
in: "07:00",
|
|
6053
|
+
out: "16:00"
|
|
6054
|
+
}
|
|
6055
|
+
];
|
|
6056
|
+
var WHOLE_DAY_TYPES = /* @__PURE__ */ new Set([
|
|
6057
|
+
"Reg. Hol",
|
|
6058
|
+
"Sp. Hol",
|
|
6059
|
+
"VL w/pay",
|
|
6060
|
+
"VL wo/pay",
|
|
6061
|
+
"SL w/pay",
|
|
6062
|
+
"SL wo/pay"
|
|
6063
|
+
]);
|
|
6064
|
+
var fc = (n) => n.toLocaleString(void 0, {
|
|
6065
|
+
minimumFractionDigits: 2,
|
|
6066
|
+
maximumFractionDigits: 2
|
|
6067
|
+
});
|
|
6068
|
+
var fr = (n) => n.toLocaleString(void 0, {
|
|
6069
|
+
minimumFractionDigits: 2,
|
|
6070
|
+
maximumFractionDigits: 6
|
|
6071
|
+
});
|
|
6072
|
+
function AttendanceTable({ logs }) {
|
|
6073
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("table", {
|
|
6074
|
+
className: "flex-1 w-full text-center",
|
|
6075
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", {
|
|
6076
|
+
className: "border-b border-black",
|
|
6077
|
+
children: [
|
|
6078
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
|
|
6079
|
+
className: "font-black text-[8px]",
|
|
6080
|
+
children: "Date"
|
|
6081
|
+
}),
|
|
6082
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
|
|
6083
|
+
className: "font-black text-[8px]",
|
|
6084
|
+
children: "IN"
|
|
6085
|
+
}),
|
|
6086
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
|
|
6087
|
+
className: "font-black text-[8px]",
|
|
6088
|
+
children: "OUT"
|
|
6089
|
+
})
|
|
6090
|
+
]
|
|
6091
|
+
}) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tbody", { children: logs.map((log, i) => {
|
|
6092
|
+
const isWholeDay = WHOLE_DAY_TYPES.has(log.in) && log.in === log.out;
|
|
6093
|
+
const isAbsence = log.in === "-" && log.out === "-";
|
|
6094
|
+
const isTiny = log.in.includes("(") || log.out.includes("(");
|
|
6095
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
6096
|
+
className: "font-bold text-[8px]",
|
|
6097
|
+
children: log.date
|
|
6098
|
+
}), isWholeDay ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
6099
|
+
colSpan: 2,
|
|
6100
|
+
className: "text-center font-bold text-[5px] tracking-tight uppercase border-b border-black/10",
|
|
6101
|
+
children: log.in
|
|
6102
|
+
}) : isAbsence ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
6103
|
+
className: "text-[6px]",
|
|
6104
|
+
children: "—"
|
|
6105
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
6106
|
+
className: "text-[6px]",
|
|
6107
|
+
children: "—"
|
|
6108
|
+
})] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
6109
|
+
className: isTiny ? "text-[5px]" : "text-[8px]",
|
|
6110
|
+
children: log.in
|
|
6111
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
6112
|
+
className: isTiny ? "text-[5px]" : "text-[8px]",
|
|
6113
|
+
children: log.out
|
|
6114
|
+
})] })] }, i);
|
|
6115
|
+
}) })]
|
|
6116
|
+
});
|
|
6117
|
+
}
|
|
6118
|
+
function PayslipTemplate({ data }) {
|
|
6119
|
+
const rates = data.rates ?? {
|
|
6120
|
+
hourly: 107.9713,
|
|
6121
|
+
daily: 863.77,
|
|
6122
|
+
monthly: 22601.9
|
|
6123
|
+
};
|
|
6124
|
+
const taxCode = data.taxCode ?? "S";
|
|
6125
|
+
const taxableGross = data.taxableGross ?? (data.netPay ? data.netPay * 1.1 : 22601.9);
|
|
6126
|
+
const nonTaxableGross = data.nonTaxableGross ?? 0;
|
|
6127
|
+
const totalGross = taxableGross + nonTaxableGross;
|
|
6128
|
+
const totalDeductions = DEDUCTIONS.reduce((s, d) => s + d.amount, 0);
|
|
6129
|
+
const finalNet = totalGross - totalDeductions;
|
|
6130
|
+
const buildLogs = () => {
|
|
6131
|
+
const period = data.payPeriod;
|
|
6132
|
+
return ATTENDANCE_LOGS.map((log, idx) => {
|
|
6133
|
+
let date = String(16 + idx).padStart(2, "0");
|
|
6134
|
+
if (period && period.includes("-")) {
|
|
6135
|
+
const monthMap = {
|
|
6136
|
+
Jan: 0,
|
|
6137
|
+
Feb: 1,
|
|
6138
|
+
Mar: 2,
|
|
6139
|
+
Apr: 3,
|
|
6140
|
+
May: 4,
|
|
6141
|
+
Jun: 5,
|
|
6142
|
+
Jul: 6,
|
|
6143
|
+
Aug: 7,
|
|
6144
|
+
Sep: 8,
|
|
6145
|
+
Oct: 9,
|
|
6146
|
+
Nov: 10,
|
|
6147
|
+
Dec: 11
|
|
6148
|
+
};
|
|
6149
|
+
const parts = period.split(" ");
|
|
6150
|
+
const startMonth = monthMap[parts[0]] ?? 0;
|
|
6151
|
+
const startDay = parseInt(parts[1]) || 1;
|
|
6152
|
+
const year = parseInt(period.match(/\d{4}$/)?.[0] ?? String((/* @__PURE__ */ new Date()).getFullYear()));
|
|
6153
|
+
const d = new Date(year, startMonth, startDay + idx);
|
|
6154
|
+
date = `${String(d.getMonth() + 1).padStart(2, "0")}/${String(d.getDate()).padStart(2, "0")}`;
|
|
6155
|
+
}
|
|
6156
|
+
return {
|
|
6157
|
+
...log,
|
|
6158
|
+
date
|
|
6159
|
+
};
|
|
6160
|
+
});
|
|
6161
|
+
};
|
|
6162
|
+
const logs = buildLogs();
|
|
6163
|
+
const leftLogs = logs.slice(0, 8);
|
|
6164
|
+
const rightLogs = logs.slice(8, 16);
|
|
6165
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6166
|
+
className: "bg-white text-[#1a1a1a] p-8 font-mono text-[10px] max-w-[900px] mx-auto leading-tight",
|
|
6167
|
+
children: [
|
|
6168
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6169
|
+
className: "grid grid-cols-12 gap-0 mb-2 items-start h-[70px]",
|
|
6170
|
+
children: [
|
|
6171
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6172
|
+
className: "col-span-4 translate-y-2",
|
|
6173
|
+
children: [
|
|
6174
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h1", {
|
|
6175
|
+
className: "text-lg font-black tracking-tight leading-none mb-2",
|
|
6176
|
+
children: "DIWA HRIS PAYSLIP"
|
|
6177
|
+
}),
|
|
6178
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
6179
|
+
className: "font-bold flex gap-1 text-[9px]",
|
|
6180
|
+
children: ["Period: ", /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6181
|
+
className: "font-normal",
|
|
6182
|
+
children: data.payPeriod || "No Period Selected"
|
|
6183
|
+
})]
|
|
6184
|
+
}),
|
|
6185
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
6186
|
+
className: "font-bold flex gap-1 text-[8px]",
|
|
6187
|
+
children: ["Printed: ", /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6188
|
+
className: "font-normal",
|
|
6189
|
+
children: (/* @__PURE__ */ new Date()).toLocaleDateString()
|
|
6190
|
+
})]
|
|
6191
|
+
})
|
|
6192
|
+
]
|
|
6193
|
+
}),
|
|
6194
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6195
|
+
className: "col-span-4 border border-black p-1.5 mt-2 mb-1 relative z-10",
|
|
6196
|
+
children: [
|
|
6197
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6198
|
+
className: "flex gap-2 mb-0.5 border-b border-black pb-0.5",
|
|
6199
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6200
|
+
className: "font-black border-r border-black pr-2",
|
|
6201
|
+
children: data.id
|
|
6202
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6203
|
+
className: "font-black tracking-tight",
|
|
6204
|
+
children: data.name.toUpperCase()
|
|
6205
|
+
})]
|
|
6206
|
+
}),
|
|
6207
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6208
|
+
className: "font-bold text-[9px] border-b border-black pb-0.5 mb-0.5",
|
|
6209
|
+
children: data.role
|
|
6210
|
+
}),
|
|
6211
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6212
|
+
className: "font-bold text-[9px]",
|
|
6213
|
+
children: data.department
|
|
6214
|
+
})
|
|
6215
|
+
]
|
|
6216
|
+
}),
|
|
6217
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6218
|
+
className: "col-span-4 text-[9px] pl-8 text-right pr-2 mt-4 space-y-0",
|
|
6219
|
+
children: [
|
|
6220
|
+
["Hourly :", fr(rates.hourly)],
|
|
6221
|
+
["Daily :", fr(rates.daily)],
|
|
6222
|
+
["Monthly :", fr(rates.monthly)],
|
|
6223
|
+
["Tax Code :", taxCode]
|
|
6224
|
+
].map(([k, v]) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6225
|
+
className: "grid grid-cols-2",
|
|
6226
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6227
|
+
className: "text-left font-bold",
|
|
6228
|
+
children: k
|
|
6229
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6230
|
+
className: "font-bold",
|
|
6231
|
+
children: v
|
|
6232
|
+
})]
|
|
6233
|
+
}, k))
|
|
6234
|
+
})
|
|
6235
|
+
]
|
|
6236
|
+
}),
|
|
6237
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6238
|
+
className: "grid grid-cols-12 border-t border-black min-h-[160px]",
|
|
6239
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6240
|
+
className: "col-span-8 grid grid-cols-2 border-r border-black min-h-[160px]",
|
|
6241
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6242
|
+
className: "border-r border-black p-1 flex flex-col h-full",
|
|
6243
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6244
|
+
className: "flex-1",
|
|
6245
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6246
|
+
className: "font-black border-b border-black mb-1 p-0.5 flex justify-between",
|
|
6247
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "EARNINGS:" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6248
|
+
className: "flex gap-8 text-[7px] pr-2 items-center",
|
|
6249
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "UNIT" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "AMOUNT" })]
|
|
6250
|
+
})]
|
|
6251
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6252
|
+
className: "space-y-0.5",
|
|
6253
|
+
children: [
|
|
6254
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6255
|
+
className: "grid grid-cols-12 gap-1 px-1",
|
|
6256
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6257
|
+
className: "col-span-7",
|
|
6258
|
+
children: "Basic Salary"
|
|
6259
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6260
|
+
className: "col-span-5 text-right",
|
|
6261
|
+
children: fc(taxableGross)
|
|
6262
|
+
})]
|
|
6263
|
+
}),
|
|
6264
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6265
|
+
className: "grid grid-cols-12 gap-1 px-1",
|
|
6266
|
+
children: [
|
|
6267
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6268
|
+
className: "col-span-6",
|
|
6269
|
+
children: "Holiday Pay"
|
|
6270
|
+
}),
|
|
6271
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6272
|
+
className: "col-span-2 text-right",
|
|
6273
|
+
children: "1.00"
|
|
6274
|
+
}),
|
|
6275
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6276
|
+
className: "col-span-4 text-right",
|
|
6277
|
+
children: "863.77"
|
|
6278
|
+
})
|
|
6279
|
+
]
|
|
6280
|
+
}),
|
|
6281
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6282
|
+
className: "grid grid-cols-12 gap-1 px-1 italic",
|
|
6283
|
+
children: [
|
|
6284
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6285
|
+
className: "col-span-6",
|
|
6286
|
+
children: "Absences"
|
|
6287
|
+
}),
|
|
6288
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6289
|
+
className: "col-span-2 text-right",
|
|
6290
|
+
children: "1.00"
|
|
6291
|
+
}),
|
|
6292
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
6293
|
+
className: "col-span-4 text-right",
|
|
6294
|
+
children: [
|
|
6295
|
+
"(",
|
|
6296
|
+
fc(863.77),
|
|
6297
|
+
")"
|
|
6298
|
+
]
|
|
6299
|
+
})
|
|
6300
|
+
]
|
|
6301
|
+
})
|
|
6302
|
+
]
|
|
6303
|
+
})]
|
|
6304
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6305
|
+
className: "pt-2 border-t border-dotted border-black space-y-0.5",
|
|
6306
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6307
|
+
className: "grid grid-cols-12 gap-1 px-1",
|
|
6308
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
6309
|
+
className: "col-span-8 font-bold",
|
|
6310
|
+
children: ["Gross ", /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6311
|
+
className: "font-normal",
|
|
6312
|
+
children: "(taxable)"
|
|
6313
|
+
})]
|
|
6314
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6315
|
+
className: "col-span-4 text-right",
|
|
6316
|
+
children: fc(taxableGross)
|
|
6317
|
+
})]
|
|
6318
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6319
|
+
className: "grid grid-cols-12 gap-1 px-1",
|
|
6320
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
6321
|
+
className: "col-span-8 font-bold",
|
|
6322
|
+
children: ["Gross ", /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6323
|
+
className: "font-normal",
|
|
6324
|
+
children: "(nontaxable)"
|
|
6325
|
+
})]
|
|
6326
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6327
|
+
className: "col-span-4 text-right",
|
|
6328
|
+
children: fc(nonTaxableGross)
|
|
6329
|
+
})]
|
|
6330
|
+
})]
|
|
6331
|
+
})]
|
|
6332
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6333
|
+
className: "p-1",
|
|
6334
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6335
|
+
className: "font-black border-b border-black mb-1 p-0.5 flex justify-between",
|
|
6336
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "DEDUCTIONS:" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6337
|
+
className: "flex gap-4 text-[7px] pr-2 items-center",
|
|
6338
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6339
|
+
className: "w-16 text-center",
|
|
6340
|
+
children: "REM. BAL"
|
|
6341
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6342
|
+
className: "w-12 text-right",
|
|
6343
|
+
children: "AMOUNT"
|
|
6344
|
+
})]
|
|
6345
|
+
})]
|
|
6346
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6347
|
+
className: "space-y-0.5",
|
|
6348
|
+
children: DEDUCTIONS.map((d, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6349
|
+
className: "grid grid-cols-12 gap-1 px-1",
|
|
6350
|
+
children: [
|
|
6351
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6352
|
+
className: "col-span-5",
|
|
6353
|
+
children: d.label
|
|
6354
|
+
}),
|
|
6355
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6356
|
+
className: "col-span-3 text-center text-[8px] text-slate-500",
|
|
6357
|
+
children: d.remainingBalance ? fc(d.remainingBalance) : d.base ? fc(d.base) : ""
|
|
6358
|
+
}),
|
|
6359
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6360
|
+
className: "col-span-4 text-right",
|
|
6361
|
+
children: fc(d.amount)
|
|
6362
|
+
})
|
|
6363
|
+
]
|
|
6364
|
+
}, i))
|
|
6365
|
+
})]
|
|
6366
|
+
})]
|
|
6367
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6368
|
+
className: "col-span-4 p-1 text-[8px]",
|
|
6369
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6370
|
+
className: "flex gap-4",
|
|
6371
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(AttendanceTable, { logs: leftLogs }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AttendanceTable, { logs: rightLogs })]
|
|
6372
|
+
})
|
|
6373
|
+
})]
|
|
6374
|
+
}),
|
|
6375
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6376
|
+
className: "border-t border-black mb-1",
|
|
6377
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6378
|
+
className: "grid grid-cols-12",
|
|
6379
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6380
|
+
className: "col-span-8 border-r border-black",
|
|
6381
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6382
|
+
className: "grid grid-cols-2 bg-slate-100 py-1.5 border-y border-black font-black uppercase tracking-tight",
|
|
6383
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6384
|
+
className: "grid grid-cols-12 px-2 border-r border-black",
|
|
6385
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6386
|
+
className: "col-span-7",
|
|
6387
|
+
children: "Total Gross"
|
|
6388
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6389
|
+
className: "col-span-5 text-right",
|
|
6390
|
+
children: fc(totalGross)
|
|
6391
|
+
})]
|
|
6392
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6393
|
+
className: "grid grid-cols-12 px-2",
|
|
6394
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6395
|
+
className: "col-span-8 text-right pr-4",
|
|
6396
|
+
children: "Total Deductions:"
|
|
6397
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6398
|
+
className: "col-span-4 text-right",
|
|
6399
|
+
children: fc(totalDeductions)
|
|
6400
|
+
})]
|
|
6401
|
+
})]
|
|
6402
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6403
|
+
className: "p-1 px-2 flex gap-4 items-center h-8",
|
|
6404
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6405
|
+
className: "text-[11px] font-black uppercase",
|
|
6406
|
+
children: "Net Pay:"
|
|
6407
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6408
|
+
className: "text-[16px] font-black pl-4",
|
|
6409
|
+
children: fc(finalNet)
|
|
6410
|
+
})]
|
|
6411
|
+
})]
|
|
6412
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6413
|
+
className: "col-span-4 p-1 px-2",
|
|
6414
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6415
|
+
className: "grid grid-cols-2 border border-black text-center mb-2",
|
|
6416
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6417
|
+
className: "border-r border-black p-0.5",
|
|
6418
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6419
|
+
className: "border-b border-black font-bold uppercase text-[7px] mb-0.5",
|
|
6420
|
+
children: "YTD Gross"
|
|
6421
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6422
|
+
className: "font-black text-[12px]",
|
|
6423
|
+
children: fc(data.ytd?.gross ?? taxableGross)
|
|
6424
|
+
})]
|
|
6425
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6426
|
+
className: "p-0.5",
|
|
6427
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6428
|
+
className: "border-b border-black font-bold uppercase text-[7px] mb-0.5",
|
|
6429
|
+
children: "YTD Tax"
|
|
6430
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6431
|
+
className: "font-black text-[12px]",
|
|
6432
|
+
children: fc(data.ytd?.tax ?? totalDeductions * .1)
|
|
6433
|
+
})]
|
|
6434
|
+
})]
|
|
6435
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6436
|
+
className: "flex justify-between text-[8px] font-bold uppercase px-1 pb-0.5 pt-1",
|
|
6437
|
+
children: [
|
|
6438
|
+
["VL", data.leaveBalances?.vacation.remaining ?? 10],
|
|
6439
|
+
["SL", data.leaveBalances?.sick.remaining ?? 14],
|
|
6440
|
+
["PL", data.leaveBalances?.personal?.remaining ?? 0]
|
|
6441
|
+
].map(([k, v]) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6442
|
+
className: "flex gap-1",
|
|
6443
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [k, " Bal:"] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6444
|
+
className: "font-normal",
|
|
6445
|
+
children: String(v)
|
|
6446
|
+
})]
|
|
6447
|
+
}, String(k)))
|
|
6448
|
+
})]
|
|
6449
|
+
})]
|
|
6450
|
+
})
|
|
6451
|
+
}),
|
|
6452
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6453
|
+
className: "mt-4 border-t-2 border-dashed border-black pt-2 opacity-30 text-center",
|
|
6454
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6455
|
+
className: "text-[7px] font-black uppercase tracking-[0.2em] italic",
|
|
6456
|
+
children: "Authorized Document — DIWA HRIS Fin-Audit System"
|
|
6457
|
+
})
|
|
6458
|
+
})
|
|
6459
|
+
]
|
|
6460
|
+
});
|
|
6461
|
+
}
|
|
6462
|
+
//#endregion
|
|
6463
|
+
//#region src/ui-library/gallery/template-samples/templates/ReportTemplate.tsx
|
|
6464
|
+
var MOCK_ROWS = [
|
|
6465
|
+
{
|
|
6466
|
+
id: "DL-0001",
|
|
6467
|
+
name: "Maria Santos",
|
|
6468
|
+
dept: "Finance",
|
|
6469
|
+
position: "Senior Accountant",
|
|
6470
|
+
status: "Regular",
|
|
6471
|
+
dateHired: "Jan 15, 2021",
|
|
6472
|
+
rate: "25,000.00"
|
|
6473
|
+
},
|
|
6474
|
+
{
|
|
6475
|
+
id: "DL-0002",
|
|
6476
|
+
name: "Jose Reyes",
|
|
6477
|
+
dept: "IT",
|
|
6478
|
+
position: "IT Infrastructure Lead",
|
|
6479
|
+
status: "Regular",
|
|
6480
|
+
dateHired: "Mar 08, 2020",
|
|
6481
|
+
rate: "38,000.00"
|
|
6482
|
+
},
|
|
6483
|
+
{
|
|
6484
|
+
id: "DL-0003",
|
|
6485
|
+
name: "Ana Dela Cruz",
|
|
6486
|
+
dept: "HR",
|
|
6487
|
+
position: "HR Business Partner",
|
|
6488
|
+
status: "Regular",
|
|
6489
|
+
dateHired: "Jun 01, 2019",
|
|
6490
|
+
rate: "32,000.00"
|
|
6491
|
+
},
|
|
6492
|
+
{
|
|
6493
|
+
id: "DL-0004",
|
|
6494
|
+
name: "Carlo Mendoza",
|
|
6495
|
+
dept: "Operations",
|
|
6496
|
+
position: "Operations Manager",
|
|
6497
|
+
status: "Regular",
|
|
6498
|
+
dateHired: "Sep 22, 2022",
|
|
6499
|
+
rate: "45,000.00"
|
|
6500
|
+
},
|
|
6501
|
+
{
|
|
6502
|
+
id: "DL-0005",
|
|
6503
|
+
name: "Liza Bautista",
|
|
6504
|
+
dept: "Legal",
|
|
6505
|
+
position: "Legal Counsel",
|
|
6506
|
+
status: "Probationary",
|
|
6507
|
+
dateHired: "Feb 10, 2024",
|
|
6508
|
+
rate: "28,000.00"
|
|
6509
|
+
},
|
|
6510
|
+
{
|
|
6511
|
+
id: "DL-0006",
|
|
6512
|
+
name: "Mark Villanueva",
|
|
6513
|
+
dept: "Academic",
|
|
6514
|
+
position: "Academic Coordinator",
|
|
6515
|
+
status: "Regular",
|
|
6516
|
+
dateHired: "Nov 03, 2023",
|
|
6517
|
+
rate: "22,000.00"
|
|
6518
|
+
},
|
|
6519
|
+
{
|
|
6520
|
+
id: "DL-0007",
|
|
6521
|
+
name: "Rosa Castillo",
|
|
6522
|
+
dept: "Finance",
|
|
6523
|
+
position: "Bookkeeper",
|
|
6524
|
+
status: "Regular",
|
|
6525
|
+
dateHired: "Apr 14, 2018",
|
|
6526
|
+
rate: "20,000.00"
|
|
6527
|
+
},
|
|
6528
|
+
{
|
|
6529
|
+
id: "DL-0008",
|
|
6530
|
+
name: "Noel Ramos",
|
|
6531
|
+
dept: "IT",
|
|
6532
|
+
position: "Systems Analyst",
|
|
6533
|
+
status: "Regular",
|
|
6534
|
+
dateHired: "Jul 30, 2021",
|
|
6535
|
+
rate: "30,000.00"
|
|
6536
|
+
},
|
|
6537
|
+
{
|
|
6538
|
+
id: "DL-0009",
|
|
6539
|
+
name: "Cynthia Torres",
|
|
6540
|
+
dept: "HR",
|
|
6541
|
+
position: "Recruitment Officer",
|
|
6542
|
+
status: "Regular",
|
|
6543
|
+
dateHired: "Dec 05, 2022",
|
|
6544
|
+
rate: "24,000.00"
|
|
6545
|
+
},
|
|
6546
|
+
{
|
|
6547
|
+
id: "DL-0010",
|
|
6548
|
+
name: "Ramon Aquino",
|
|
6549
|
+
dept: "Operations",
|
|
6550
|
+
position: "Logistics Coordinator",
|
|
6551
|
+
status: "Probationary",
|
|
6552
|
+
dateHired: "Aug 18, 2024",
|
|
6553
|
+
rate: "19,500.00"
|
|
6554
|
+
},
|
|
6555
|
+
{
|
|
6556
|
+
id: "DL-0011",
|
|
6557
|
+
name: "Elena Fuentes",
|
|
6558
|
+
dept: "Academic",
|
|
6559
|
+
position: "Faculty Member",
|
|
6560
|
+
status: "Regular",
|
|
6561
|
+
dateHired: "Jun 12, 2017",
|
|
6562
|
+
rate: "27,000.00"
|
|
6563
|
+
},
|
|
6564
|
+
{
|
|
6565
|
+
id: "DL-0012",
|
|
6566
|
+
name: "Dennis Lacerna",
|
|
6567
|
+
dept: "Finance",
|
|
6568
|
+
position: "Payroll Officer",
|
|
6569
|
+
status: "Regular",
|
|
6570
|
+
dateHired: "Oct 01, 2020",
|
|
6571
|
+
rate: "23,500.00"
|
|
6572
|
+
}
|
|
6573
|
+
];
|
|
6574
|
+
var HEADERS = [
|
|
6575
|
+
"#",
|
|
6576
|
+
"Employee ID",
|
|
6577
|
+
"Full Name",
|
|
6578
|
+
"Department",
|
|
6579
|
+
"Position",
|
|
6580
|
+
"Status",
|
|
6581
|
+
"Date Hired",
|
|
6582
|
+
"Monthly Rate"
|
|
6583
|
+
];
|
|
6584
|
+
function ReportTemplate({ data }) {
|
|
6585
|
+
const today = (/* @__PURE__ */ new Date()).toLocaleDateString("en-US", {
|
|
6586
|
+
month: "long",
|
|
6587
|
+
day: "numeric",
|
|
6588
|
+
year: "numeric"
|
|
6589
|
+
});
|
|
6590
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6591
|
+
className: "bg-white text-black font-sans",
|
|
6592
|
+
style: {
|
|
6593
|
+
width: "816px",
|
|
6594
|
+
minHeight: "1056px",
|
|
6595
|
+
padding: "48px 50px",
|
|
6596
|
+
boxSizing: "border-box"
|
|
6597
|
+
},
|
|
6598
|
+
children: [
|
|
6599
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6600
|
+
className: "flex justify-between items-start mb-6 border-b-2 border-black pb-4",
|
|
6601
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [
|
|
6602
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6603
|
+
className: "text-[9px] text-slate-500 uppercase tracking-widest mb-1 font-bold",
|
|
6604
|
+
children: data.company || "DIWA Learning Systems, Inc."
|
|
6605
|
+
}),
|
|
6606
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h1", {
|
|
6607
|
+
className: "text-[20px] font-black uppercase tracking-tight leading-tight",
|
|
6608
|
+
children: data.title || "Employee Masterlist Report"
|
|
6609
|
+
}),
|
|
6610
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
6611
|
+
className: "text-[11px] text-slate-500 mt-0.5 italic",
|
|
6612
|
+
children: data.subtitle || "All Active Employees — Direct Labor"
|
|
6613
|
+
})
|
|
6614
|
+
] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6615
|
+
className: "text-right text-[9px] space-y-0.5",
|
|
6616
|
+
children: [
|
|
6617
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [
|
|
6618
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6619
|
+
className: "font-bold",
|
|
6620
|
+
children: "As of:"
|
|
6621
|
+
}),
|
|
6622
|
+
" ",
|
|
6623
|
+
data.asOf || today
|
|
6624
|
+
] }),
|
|
6625
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [
|
|
6626
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6627
|
+
className: "font-bold",
|
|
6628
|
+
children: "Date Printed:"
|
|
6629
|
+
}),
|
|
6630
|
+
" ",
|
|
6631
|
+
today
|
|
6632
|
+
] }),
|
|
6633
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6634
|
+
className: "font-bold",
|
|
6635
|
+
children: "Page:"
|
|
6636
|
+
}), " 1 of 1"] }),
|
|
6637
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [
|
|
6638
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6639
|
+
className: "font-bold",
|
|
6640
|
+
children: "Prepared by:"
|
|
6641
|
+
}),
|
|
6642
|
+
" ",
|
|
6643
|
+
data.preparedBy || "System"
|
|
6644
|
+
] })
|
|
6645
|
+
]
|
|
6646
|
+
})]
|
|
6647
|
+
}),
|
|
6648
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6649
|
+
className: "flex gap-6 mb-5 text-[10px]",
|
|
6650
|
+
children: [
|
|
6651
|
+
["Total Employees", String(MOCK_ROWS.length)],
|
|
6652
|
+
["Regular", String(MOCK_ROWS.filter((r) => r.status === "Regular").length)],
|
|
6653
|
+
["Probationary", String(MOCK_ROWS.filter((r) => r.status === "Probationary").length)],
|
|
6654
|
+
["Departments", "5"]
|
|
6655
|
+
].map(([label, value]) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6656
|
+
className: "border border-black px-3 py-1.5 text-center min-w-[80px]",
|
|
6657
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6658
|
+
className: "font-black text-[16px]",
|
|
6659
|
+
children: value
|
|
6660
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6661
|
+
className: "text-[8px] text-slate-500 font-bold uppercase tracking-tight",
|
|
6662
|
+
children: label
|
|
6663
|
+
})]
|
|
6664
|
+
}, label))
|
|
6665
|
+
}),
|
|
6666
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("table", {
|
|
6667
|
+
className: "w-full border-collapse text-[9px]",
|
|
6668
|
+
children: [
|
|
6669
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tr", {
|
|
6670
|
+
className: "bg-[#00377B] text-white",
|
|
6671
|
+
children: HEADERS.map((h) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
|
|
6672
|
+
className: "border border-[#00377B] px-2 py-1.5 text-left font-bold uppercase tracking-wide text-[8px]",
|
|
6673
|
+
children: h
|
|
6674
|
+
}, h))
|
|
6675
|
+
}) }),
|
|
6676
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("tbody", { children: MOCK_ROWS.map((row, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", {
|
|
6677
|
+
className: i % 2 === 0 ? "bg-white" : "bg-slate-50",
|
|
6678
|
+
children: [
|
|
6679
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
6680
|
+
className: "border border-slate-200 px-2 py-1 text-slate-400",
|
|
6681
|
+
children: i + 1
|
|
6682
|
+
}),
|
|
6683
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
6684
|
+
className: "border border-slate-200 px-2 py-1 font-mono font-bold",
|
|
6685
|
+
children: row.id
|
|
6686
|
+
}),
|
|
6687
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
6688
|
+
className: "border border-slate-200 px-2 py-1 font-bold uppercase",
|
|
6689
|
+
children: row.name
|
|
6690
|
+
}),
|
|
6691
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
6692
|
+
className: "border border-slate-200 px-2 py-1",
|
|
6693
|
+
children: row.dept
|
|
6694
|
+
}),
|
|
6695
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
6696
|
+
className: "border border-slate-200 px-2 py-1",
|
|
6697
|
+
children: row.position
|
|
6698
|
+
}),
|
|
6699
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
6700
|
+
className: "border border-slate-200 px-2 py-1",
|
|
6701
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6702
|
+
className: ["inline-flex items-center rounded px-1.5 py-0.5 text-[8px] font-bold uppercase tracking-tight", row.status === "Regular" ? "bg-emerald-50 text-emerald-700" : "bg-amber-50 text-amber-700"].join(" "),
|
|
6703
|
+
children: row.status
|
|
6704
|
+
})
|
|
6705
|
+
}),
|
|
6706
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
6707
|
+
className: "border border-slate-200 px-2 py-1",
|
|
6708
|
+
children: row.dateHired
|
|
6709
|
+
}),
|
|
6710
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
6711
|
+
className: "border border-slate-200 px-2 py-1 text-right font-mono",
|
|
6712
|
+
children: row.rate
|
|
6713
|
+
})
|
|
6714
|
+
]
|
|
6715
|
+
}, row.id)) }),
|
|
6716
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("tfoot", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", {
|
|
6717
|
+
className: "bg-slate-100 font-black border-t-2 border-black",
|
|
6718
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
6719
|
+
colSpan: 7,
|
|
6720
|
+
className: "border border-slate-300 px-2 py-1.5 text-right uppercase text-[8px] tracking-widest",
|
|
6721
|
+
children: "Total Monthly Cost:"
|
|
6722
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
6723
|
+
className: "border border-slate-300 px-2 py-1.5 text-right font-mono",
|
|
6724
|
+
children: MOCK_ROWS.reduce((s, r) => s + parseFloat(r.rate.replace(/,/g, "")), 0).toLocaleString("en-US", { minimumFractionDigits: 2 })
|
|
6725
|
+
})]
|
|
6726
|
+
}) })
|
|
6727
|
+
]
|
|
6728
|
+
}),
|
|
6729
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6730
|
+
className: "mt-8 flex justify-between items-end text-[9px]",
|
|
6731
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [
|
|
6732
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "border-b border-black w-48 mb-1" }),
|
|
6733
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6734
|
+
className: "font-bold",
|
|
6735
|
+
children: ["Prepared by: ", data.preparedBy || "HRIS System"]
|
|
6736
|
+
}),
|
|
6737
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6738
|
+
className: "text-slate-400",
|
|
6739
|
+
children: "Human Resources Management Division"
|
|
6740
|
+
})
|
|
6741
|
+
] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6742
|
+
className: "text-right",
|
|
6743
|
+
children: [
|
|
6744
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "border-b border-black w-48 mb-1 ml-auto" }),
|
|
6745
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6746
|
+
className: "font-bold",
|
|
6747
|
+
children: "Noted by: ___________________________"
|
|
6748
|
+
}),
|
|
6749
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6750
|
+
className: "text-slate-400",
|
|
6751
|
+
children: "HR Director / VP Operations"
|
|
6752
|
+
})
|
|
6753
|
+
]
|
|
6754
|
+
})]
|
|
6755
|
+
}),
|
|
6756
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6757
|
+
className: "mt-6 border-t border-dashed border-black/40 pt-2 text-center opacity-40",
|
|
6758
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6759
|
+
className: "text-[7px] font-black uppercase tracking-[0.2em] italic",
|
|
6760
|
+
children: "System-Generated Report — DIWA HRIS — Confidential"
|
|
6761
|
+
})
|
|
6762
|
+
})
|
|
6763
|
+
]
|
|
6764
|
+
});
|
|
6765
|
+
}
|
|
6766
|
+
//#endregion
|
|
6767
|
+
//#region src/ui-library/gallery/template-samples/templates/TimekeepingTemplate.tsx
|
|
6768
|
+
/**
|
|
6769
|
+
* TimekeepingTemplate — self-contained preview component
|
|
6770
|
+
*
|
|
6771
|
+
* Ported from unified-hris/components/TimekeepingFileTemplate.tsx.
|
|
6772
|
+
* No context deps. All data is mock + prop-driven.
|
|
6773
|
+
*/
|
|
6774
|
+
var RECORDS = [
|
|
6775
|
+
{
|
|
6776
|
+
dateIn: "16-Jan-25",
|
|
6777
|
+
day: "Thu",
|
|
6778
|
+
shift: 1,
|
|
6779
|
+
timeIn: "7:00 am",
|
|
6780
|
+
dateOut: "16-Jan-25",
|
|
6781
|
+
timeOut: "4:00 pm",
|
|
6782
|
+
hours: "8.00",
|
|
6783
|
+
actual: "9.00",
|
|
6784
|
+
late: "-",
|
|
6785
|
+
utime: "-",
|
|
6786
|
+
ot: "-",
|
|
6787
|
+
nd2: "-",
|
|
6788
|
+
rem: "-"
|
|
6789
|
+
},
|
|
6790
|
+
{
|
|
6791
|
+
dateIn: "17-Jan-25",
|
|
6792
|
+
day: "Fri",
|
|
6793
|
+
shift: 1,
|
|
6794
|
+
timeIn: "7:15 am",
|
|
6795
|
+
dateOut: "17-Jan-25",
|
|
6796
|
+
timeOut: "4:00 pm",
|
|
6797
|
+
hours: "8.00",
|
|
6798
|
+
actual: "9.00",
|
|
6799
|
+
late: "15",
|
|
6800
|
+
utime: "-",
|
|
6801
|
+
ot: "-",
|
|
6802
|
+
nd2: "-",
|
|
6803
|
+
rem: "-"
|
|
6804
|
+
},
|
|
6805
|
+
{
|
|
6806
|
+
dateIn: "18-Jan-25",
|
|
6807
|
+
day: "Sat",
|
|
6808
|
+
shift: 1,
|
|
6809
|
+
timeIn: "-",
|
|
6810
|
+
dateOut: "-",
|
|
6811
|
+
timeOut: "-",
|
|
6812
|
+
hours: "-",
|
|
6813
|
+
actual: "-",
|
|
6814
|
+
late: "-",
|
|
6815
|
+
utime: "-",
|
|
6816
|
+
ot: "-",
|
|
6817
|
+
nd2: "-",
|
|
6818
|
+
rem: "-"
|
|
6819
|
+
},
|
|
6820
|
+
{
|
|
6821
|
+
dateIn: "19-Jan-25",
|
|
6822
|
+
day: "Sun",
|
|
6823
|
+
shift: 1,
|
|
6824
|
+
timeIn: "-",
|
|
6825
|
+
dateOut: "-",
|
|
6826
|
+
timeOut: "-",
|
|
6827
|
+
hours: "-",
|
|
6828
|
+
actual: "-",
|
|
6829
|
+
late: "-",
|
|
6830
|
+
utime: "-",
|
|
6831
|
+
ot: "-",
|
|
6832
|
+
nd2: "-",
|
|
6833
|
+
rem: "-"
|
|
6834
|
+
},
|
|
6835
|
+
{
|
|
6836
|
+
dateIn: "20-Jan-25",
|
|
6837
|
+
day: "Mon",
|
|
6838
|
+
shift: 1,
|
|
6839
|
+
timeIn: "7:00 am",
|
|
6840
|
+
dateOut: "20-Jan-25",
|
|
6841
|
+
timeOut: "4:00 pm",
|
|
6842
|
+
hours: "8.00",
|
|
6843
|
+
actual: "9.00",
|
|
6844
|
+
late: "-",
|
|
6845
|
+
utime: "-",
|
|
6846
|
+
ot: "-",
|
|
6847
|
+
nd2: "-",
|
|
6848
|
+
rem: "-"
|
|
6849
|
+
},
|
|
6850
|
+
{
|
|
6851
|
+
dateIn: "21-Jan-25",
|
|
6852
|
+
day: "Tue",
|
|
6853
|
+
shift: 1,
|
|
6854
|
+
timeIn: "7:00 am",
|
|
6855
|
+
dateOut: "21-Jan-25",
|
|
6856
|
+
timeOut: "4:00 pm",
|
|
6857
|
+
hours: "8.00",
|
|
6858
|
+
actual: "9.00",
|
|
6859
|
+
late: "-",
|
|
6860
|
+
utime: "-",
|
|
6861
|
+
ot: "-",
|
|
6862
|
+
nd2: "-",
|
|
6863
|
+
rem: "-"
|
|
6864
|
+
},
|
|
6865
|
+
{
|
|
6866
|
+
dateIn: "22-Jan-25",
|
|
6867
|
+
day: "Wed",
|
|
6868
|
+
shift: 1,
|
|
6869
|
+
timeIn: "7:00 am",
|
|
6870
|
+
dateOut: "22-Jan-25",
|
|
6871
|
+
timeOut: "4:00 pm",
|
|
6872
|
+
hours: "8.00",
|
|
6873
|
+
actual: "9.00",
|
|
6874
|
+
late: "-",
|
|
6875
|
+
utime: "-",
|
|
6876
|
+
ot: "-",
|
|
6877
|
+
nd2: "-",
|
|
6878
|
+
rem: "-"
|
|
6879
|
+
},
|
|
6880
|
+
{
|
|
6881
|
+
dateIn: "23-Jan-25",
|
|
6882
|
+
day: "Thu",
|
|
6883
|
+
shift: 1,
|
|
6884
|
+
timeIn: "7:00 am",
|
|
6885
|
+
dateOut: "23-Jan-25",
|
|
6886
|
+
timeOut: "4:00 pm",
|
|
6887
|
+
hours: "8.00",
|
|
6888
|
+
actual: "9.00",
|
|
6889
|
+
late: "-",
|
|
6890
|
+
utime: "-",
|
|
6891
|
+
ot: "-",
|
|
6892
|
+
nd2: "-",
|
|
6893
|
+
rem: "-"
|
|
6894
|
+
},
|
|
6895
|
+
{
|
|
6896
|
+
dateIn: "24-Jan-25",
|
|
6897
|
+
day: "Fri",
|
|
6898
|
+
shift: 1,
|
|
6899
|
+
timeIn: "7:00 am",
|
|
6900
|
+
dateOut: "24-Jan-25",
|
|
6901
|
+
timeOut: "4:00 pm",
|
|
6902
|
+
hours: "8.00",
|
|
6903
|
+
actual: "9.00",
|
|
6904
|
+
late: "-",
|
|
6905
|
+
utime: "-",
|
|
6906
|
+
ot: "-",
|
|
6907
|
+
nd2: "-",
|
|
6908
|
+
rem: "-"
|
|
6909
|
+
},
|
|
6910
|
+
{
|
|
6911
|
+
dateIn: "25-Jan-25",
|
|
6912
|
+
day: "Sat",
|
|
6913
|
+
shift: 1,
|
|
6914
|
+
timeIn: "-",
|
|
6915
|
+
dateOut: "-",
|
|
6916
|
+
timeOut: "-",
|
|
6917
|
+
hours: "-",
|
|
6918
|
+
actual: "-",
|
|
6919
|
+
late: "-",
|
|
6920
|
+
utime: "-",
|
|
6921
|
+
ot: "-",
|
|
6922
|
+
nd2: "-",
|
|
6923
|
+
rem: "-"
|
|
6924
|
+
},
|
|
6925
|
+
{
|
|
6926
|
+
dateIn: "26-Jan-25",
|
|
6927
|
+
day: "Sun",
|
|
6928
|
+
shift: 1,
|
|
6929
|
+
timeIn: "-",
|
|
6930
|
+
dateOut: "-",
|
|
6931
|
+
timeOut: "-",
|
|
6932
|
+
hours: "-",
|
|
6933
|
+
actual: "-",
|
|
6934
|
+
late: "-",
|
|
6935
|
+
utime: "-",
|
|
6936
|
+
ot: "-",
|
|
6937
|
+
nd2: "-",
|
|
6938
|
+
rem: "-"
|
|
6939
|
+
},
|
|
6940
|
+
{
|
|
6941
|
+
dateIn: "27-Jan-25",
|
|
6942
|
+
day: "Mon",
|
|
6943
|
+
shift: 1,
|
|
6944
|
+
timeIn: "7:00 am",
|
|
6945
|
+
dateOut: "27-Jan-25",
|
|
6946
|
+
timeOut: "4:00 pm",
|
|
6947
|
+
hours: "8.00",
|
|
6948
|
+
actual: "9.00",
|
|
6949
|
+
late: "-",
|
|
6950
|
+
utime: "-",
|
|
6951
|
+
ot: "-",
|
|
6952
|
+
nd2: "-",
|
|
6953
|
+
rem: "-"
|
|
6954
|
+
},
|
|
6955
|
+
{
|
|
6956
|
+
dateIn: "28-Jan-25",
|
|
6957
|
+
day: "Tue",
|
|
6958
|
+
shift: 1,
|
|
6959
|
+
timeIn: "7:00 am",
|
|
6960
|
+
dateOut: "28-Jan-25",
|
|
6961
|
+
timeOut: "4:00 pm",
|
|
6962
|
+
hours: "8.00",
|
|
6963
|
+
actual: "9.00",
|
|
6964
|
+
late: "-",
|
|
6965
|
+
utime: "-",
|
|
6966
|
+
ot: "-",
|
|
6967
|
+
nd2: "-",
|
|
6968
|
+
rem: "-"
|
|
6969
|
+
},
|
|
6970
|
+
{
|
|
6971
|
+
dateIn: "29-Jan-25",
|
|
6972
|
+
day: "Wed",
|
|
6973
|
+
shift: 1,
|
|
6974
|
+
timeIn: "-",
|
|
6975
|
+
dateOut: "-",
|
|
6976
|
+
timeOut: "-",
|
|
6977
|
+
hours: "-",
|
|
6978
|
+
actual: "-",
|
|
6979
|
+
late: "-",
|
|
6980
|
+
utime: "-",
|
|
6981
|
+
ot: "-",
|
|
6982
|
+
nd2: "-",
|
|
6983
|
+
rem: "Sp. Hol"
|
|
6984
|
+
},
|
|
6985
|
+
{
|
|
6986
|
+
dateIn: "30-Jan-25",
|
|
6987
|
+
day: "Thu",
|
|
6988
|
+
shift: 1,
|
|
6989
|
+
timeIn: "7:00 am",
|
|
6990
|
+
dateOut: "30-Jan-25",
|
|
6991
|
+
timeOut: "4:00 pm",
|
|
6992
|
+
hours: "8.00",
|
|
6993
|
+
actual: "9.00",
|
|
6994
|
+
late: "-",
|
|
6995
|
+
utime: "-",
|
|
6996
|
+
ot: "-",
|
|
6997
|
+
nd2: "-",
|
|
6998
|
+
rem: "-"
|
|
6999
|
+
},
|
|
7000
|
+
{
|
|
7001
|
+
dateIn: "31-Jan-25",
|
|
7002
|
+
day: "Fri",
|
|
7003
|
+
shift: 1,
|
|
7004
|
+
timeIn: "7:00 am",
|
|
7005
|
+
dateOut: "31-Jan-25",
|
|
7006
|
+
timeOut: "4:00 pm",
|
|
7007
|
+
hours: "8.00",
|
|
7008
|
+
actual: "9.00",
|
|
7009
|
+
late: "-",
|
|
7010
|
+
utime: "-",
|
|
7011
|
+
ot: "-",
|
|
7012
|
+
nd2: "-",
|
|
7013
|
+
rem: "-"
|
|
7014
|
+
}
|
|
7015
|
+
];
|
|
7016
|
+
var OT_SUMMARY = [
|
|
7017
|
+
"OT 0.30",
|
|
7018
|
+
"OT 1.00",
|
|
7019
|
+
"OT 1.25",
|
|
7020
|
+
"OT 1.30",
|
|
7021
|
+
"OT 1.69",
|
|
7022
|
+
"OT 1.50",
|
|
7023
|
+
"OT 1.95",
|
|
7024
|
+
"OT 2.00",
|
|
7025
|
+
"OT 2.69",
|
|
7026
|
+
"OT 3.38"
|
|
7027
|
+
];
|
|
7028
|
+
function TimekeepingTemplate({ data }) {
|
|
7029
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7030
|
+
className: "w-[297mm] min-h-[210mm] bg-white text-black font-sans text-[10px] leading-tight p-10 mx-auto",
|
|
7031
|
+
children: [
|
|
7032
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7033
|
+
className: "flex justify-between items-start mb-4",
|
|
7034
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [
|
|
7035
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7036
|
+
className: "mb-2 text-[10px]",
|
|
7037
|
+
children: ["DatePrinted: \xA0 ", (/* @__PURE__ */ new Date()).toLocaleDateString("en-US", {
|
|
7038
|
+
month: "2-digit",
|
|
7039
|
+
day: "2-digit",
|
|
7040
|
+
year: "numeric"
|
|
7041
|
+
})]
|
|
7042
|
+
}),
|
|
7043
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h1", {
|
|
7044
|
+
className: "text-xl font-bold uppercase tracking-tight",
|
|
7045
|
+
children: "DIWA HRIS — TimeSheet"
|
|
7046
|
+
}),
|
|
7047
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7048
|
+
className: "mt-4 flex gap-8",
|
|
7049
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7050
|
+
className: "flex gap-2",
|
|
7051
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7052
|
+
className: "w-16",
|
|
7053
|
+
children: "Emp. ID:"
|
|
7054
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7055
|
+
className: "font-bold",
|
|
7056
|
+
children: data.employee.empId || "DL250814-002"
|
|
7057
|
+
})]
|
|
7058
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7059
|
+
className: "flex gap-2",
|
|
7060
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7061
|
+
className: "w-16",
|
|
7062
|
+
children: "Name:"
|
|
7063
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7064
|
+
className: "font-bold uppercase",
|
|
7065
|
+
children: data.employee.name
|
|
7066
|
+
})]
|
|
7067
|
+
})] })
|
|
7068
|
+
})
|
|
7069
|
+
] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7070
|
+
className: "text-right",
|
|
7071
|
+
children: [
|
|
7072
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7073
|
+
className: "mb-1",
|
|
7074
|
+
children: "Page 1 of 1"
|
|
7075
|
+
}),
|
|
7076
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7077
|
+
className: "font-bold text-sm mb-2",
|
|
7078
|
+
children: data.period || "01/16/2025 – 01/31/2025"
|
|
7079
|
+
}),
|
|
7080
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7081
|
+
className: "grid grid-cols-[80px_1fr] gap-x-2 text-left",
|
|
7082
|
+
children: [
|
|
7083
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "Shift:" }),
|
|
7084
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7085
|
+
className: "font-bold",
|
|
7086
|
+
children: "1"
|
|
7087
|
+
}),
|
|
7088
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "Position:" }),
|
|
7089
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7090
|
+
className: "font-bold",
|
|
7091
|
+
children: data.employee.role
|
|
7092
|
+
}),
|
|
7093
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "Department:" }),
|
|
7094
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7095
|
+
className: "font-bold",
|
|
7096
|
+
children: data.employee.department
|
|
7097
|
+
}),
|
|
7098
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "Imm. Superior:" }),
|
|
7099
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7100
|
+
className: "font-bold",
|
|
7101
|
+
children: data.employee.supervisor || "ACGarcia"
|
|
7102
|
+
})
|
|
7103
|
+
]
|
|
7104
|
+
})
|
|
7105
|
+
]
|
|
7106
|
+
})]
|
|
7107
|
+
}),
|
|
7108
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7109
|
+
className: "border-t border-b border-black mb-1",
|
|
7110
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("table", {
|
|
7111
|
+
className: "w-full text-center border-collapse",
|
|
7112
|
+
children: [
|
|
7113
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tr", {
|
|
7114
|
+
className: "border-b border-black",
|
|
7115
|
+
children: [
|
|
7116
|
+
"DateIn",
|
|
7117
|
+
"Day",
|
|
7118
|
+
"Shift",
|
|
7119
|
+
"TimeIn",
|
|
7120
|
+
"DateOut",
|
|
7121
|
+
"TimeOut",
|
|
7122
|
+
"Hours",
|
|
7123
|
+
"Actual",
|
|
7124
|
+
"Late",
|
|
7125
|
+
"Utime",
|
|
7126
|
+
"OT",
|
|
7127
|
+
"ND2",
|
|
7128
|
+
"Rem."
|
|
7129
|
+
].map((h) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
|
|
7130
|
+
className: "py-1 text-[9px]",
|
|
7131
|
+
children: h
|
|
7132
|
+
}, h))
|
|
7133
|
+
}) }),
|
|
7134
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("tbody", { children: RECORDS.map((r, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", {
|
|
7135
|
+
className: "h-4",
|
|
7136
|
+
children: [
|
|
7137
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: r.dateIn }),
|
|
7138
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: r.day }),
|
|
7139
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: r.shift }),
|
|
7140
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: r.timeIn }),
|
|
7141
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: r.dateOut }),
|
|
7142
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: r.timeOut }),
|
|
7143
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: r.hours }),
|
|
7144
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: r.actual }),
|
|
7145
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: r.late }),
|
|
7146
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: r.utime }),
|
|
7147
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: r.ot }),
|
|
7148
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: r.nd2 }),
|
|
7149
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: r.rem })
|
|
7150
|
+
]
|
|
7151
|
+
}, i)) }),
|
|
7152
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("tfoot", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", {
|
|
7153
|
+
className: "border-t border-black font-bold",
|
|
7154
|
+
children: [
|
|
7155
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
7156
|
+
colSpan: 6,
|
|
7157
|
+
className: "text-left py-1 pl-2",
|
|
7158
|
+
children: "Totals: ( 11 WorkDays )"
|
|
7159
|
+
}),
|
|
7160
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: "88.00" }),
|
|
7161
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: "99.00" }),
|
|
7162
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: "0.00" }),
|
|
7163
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: "0.00" }),
|
|
7164
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: "0.00" }),
|
|
7165
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", { children: "0.00" }),
|
|
7166
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {})
|
|
7167
|
+
]
|
|
7168
|
+
}) })
|
|
7169
|
+
]
|
|
7170
|
+
})
|
|
7171
|
+
}),
|
|
7172
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7173
|
+
className: "flex justify-end mb-6 font-bold text-[10px]",
|
|
7174
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7175
|
+
className: "text-right w-[120px]",
|
|
7176
|
+
children: [
|
|
7177
|
+
"Employment Status:",
|
|
7178
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("br", {}),
|
|
7179
|
+
"Regular",
|
|
7180
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("br", {}),
|
|
7181
|
+
"Monthly",
|
|
7182
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("br", {}),
|
|
7183
|
+
"Rest Day: Sunday"
|
|
7184
|
+
]
|
|
7185
|
+
})
|
|
7186
|
+
}),
|
|
7187
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7188
|
+
className: "text-center mb-10 px-12",
|
|
7189
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7190
|
+
className: "mb-1",
|
|
7191
|
+
children: "I hereby certify that the above records are true and correct. Any"
|
|
7192
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: "unauthorized overtime will not be paid by the management." })]
|
|
7193
|
+
}),
|
|
7194
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7195
|
+
className: "flex justify-between px-16 mb-10",
|
|
7196
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7197
|
+
className: "text-center w-48",
|
|
7198
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "border-b border-black mb-1" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: "Employee Signature" })]
|
|
7199
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7200
|
+
className: "text-center w-48",
|
|
7201
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "border-b border-black mb-1" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: "Immediate Superior" })]
|
|
7202
|
+
})]
|
|
7203
|
+
}),
|
|
7204
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7205
|
+
className: "text-center mb-2",
|
|
7206
|
+
children: "For HRD use only, please do not tamper with."
|
|
7207
|
+
}),
|
|
7208
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7209
|
+
className: "border-t border-black pt-2 flex justify-between items-start mb-6",
|
|
7210
|
+
children: [
|
|
7211
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7212
|
+
className: "grid grid-cols-[90px_60px] gap-y-0.5",
|
|
7213
|
+
children: [
|
|
7214
|
+
["Days Worked:", "11.00"],
|
|
7215
|
+
["Hours Worked:", "88.00"],
|
|
7216
|
+
["Absences:", "1.00"],
|
|
7217
|
+
["", ""],
|
|
7218
|
+
["Tardiness:", "0.00"],
|
|
7219
|
+
["Reg. ND1", "0.00"],
|
|
7220
|
+
["Reg. ND2", "0.00"],
|
|
7221
|
+
["Holiday", "1.00"],
|
|
7222
|
+
["", ""],
|
|
7223
|
+
["Undertime:", "0.00"]
|
|
7224
|
+
].map(([k, v], i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react.default.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: k }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7225
|
+
className: "text-right",
|
|
7226
|
+
children: v
|
|
7227
|
+
})] }, i))
|
|
7228
|
+
}),
|
|
7229
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7230
|
+
className: "w-1/3",
|
|
7231
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7232
|
+
className: "flex border-b border-black pb-0.5 mb-1",
|
|
7233
|
+
children: [
|
|
7234
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7235
|
+
className: "underline mr-auto",
|
|
7236
|
+
children: "Summary:"
|
|
7237
|
+
}),
|
|
7238
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7239
|
+
className: "w-10 text-center underline",
|
|
7240
|
+
children: "10%"
|
|
7241
|
+
}),
|
|
7242
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7243
|
+
className: "w-10 text-center underline",
|
|
7244
|
+
children: "15%"
|
|
7245
|
+
})
|
|
7246
|
+
]
|
|
7247
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7248
|
+
className: "grid grid-cols-1 gap-y-0.5 pl-2",
|
|
7249
|
+
children: OT_SUMMARY.map((ot) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: ot }, ot))
|
|
7250
|
+
})]
|
|
7251
|
+
}),
|
|
7252
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7253
|
+
className: "grid grid-cols-[90px_30px] gap-y-0.5 text-right",
|
|
7254
|
+
children: [
|
|
7255
|
+
["VL Bal :", "10"],
|
|
7256
|
+
["SL Bal :", "14"],
|
|
7257
|
+
["VL w/ Pay :", "0"],
|
|
7258
|
+
["VL w/o Pay :", "0"],
|
|
7259
|
+
["Prev.VL w/ Pay :", "0"],
|
|
7260
|
+
["SL w/ Pay :", "0"],
|
|
7261
|
+
["SL w/o Pay :", "0"],
|
|
7262
|
+
["PL Taken :", "0"],
|
|
7263
|
+
["BL Taken :", "0"],
|
|
7264
|
+
["Meal Allow. :", "0"]
|
|
7265
|
+
].map(([k, v], i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react.default.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: k }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: v })] }, i))
|
|
7266
|
+
})
|
|
7267
|
+
]
|
|
7268
|
+
}),
|
|
7269
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "border-t border-black/50 border-dashed pt-2" })
|
|
7270
|
+
]
|
|
7271
|
+
});
|
|
7272
|
+
}
|
|
7273
|
+
//#endregion
|
|
4648
7274
|
//#region src/ui-library/gallery/stat-card/Statistic.tsx
|
|
4649
7275
|
/**
|
|
4650
7276
|
* Statistic — Design System Component
|
|
@@ -4773,12 +7399,12 @@ var DOT_STYLES = {
|
|
|
4773
7399
|
shadow: "0 0 0 3px rgba(239,68,68,0.18)"
|
|
4774
7400
|
},
|
|
4775
7401
|
inactive: {
|
|
4776
|
-
bg: "#
|
|
4777
|
-
shadow: "0 0 0 3px rgba(
|
|
7402
|
+
bg: "#b45309",
|
|
7403
|
+
shadow: "0 0 0 3px rgba(180,83,9,0.18)"
|
|
4778
7404
|
},
|
|
4779
7405
|
pending: {
|
|
4780
|
-
bg: "#
|
|
4781
|
-
shadow: "0 0 0 3px rgba(
|
|
7406
|
+
bg: "#0284c7",
|
|
7407
|
+
shadow: "0 0 0 3px rgba(2,132,199,0.18)"
|
|
4782
7408
|
}
|
|
4783
7409
|
};
|
|
4784
7410
|
function StatusDot({ status, label, className = "" }) {
|
|
@@ -4998,11 +7624,14 @@ exports.AccordionTrigger = AccordionTrigger;
|
|
|
4998
7624
|
exports.ActivityFeed = ActivityFeed;
|
|
4999
7625
|
exports.Alert = Alert;
|
|
5000
7626
|
exports.ApprovalTimeline = ApprovalTimeline;
|
|
7627
|
+
exports.AreaChart = AreaChart;
|
|
5001
7628
|
exports.Avatar = Avatar;
|
|
5002
7629
|
exports.Badge = Badge;
|
|
5003
7630
|
exports.BarChart = BarChart;
|
|
7631
|
+
exports.BarList = BarList;
|
|
5004
7632
|
exports.Breadcrumb = Breadcrumb;
|
|
5005
7633
|
exports.Button = Button;
|
|
7634
|
+
exports.CHART_PALETTE = CHART_PALETTE;
|
|
5006
7635
|
exports.Calendar = Calendar;
|
|
5007
7636
|
exports.Card = Card;
|
|
5008
7637
|
exports.CardContent = CardContent;
|
|
@@ -5033,13 +7662,18 @@ exports.FilterChip = FilterChip;
|
|
|
5033
7662
|
exports.Heatmap = Heatmap;
|
|
5034
7663
|
exports.IconButton = IconButton;
|
|
5035
7664
|
exports.Input = Input;
|
|
7665
|
+
exports.IsoCubeBlock = IsoCubeBlock;
|
|
5036
7666
|
exports.Kanban = Kanban;
|
|
5037
7667
|
exports.LineChart = LineChart;
|
|
5038
7668
|
exports.Menu = Menu;
|
|
5039
7669
|
exports.Modal = Modal;
|
|
7670
|
+
exports.OrgChart = OrgChart;
|
|
7671
|
+
exports.OrgUnitTree = OrgUnitTree;
|
|
5040
7672
|
exports.OtpInput = OtpInput;
|
|
7673
|
+
exports.PafTemplate = PafTemplate;
|
|
5041
7674
|
exports.PageHeader = PageHeader;
|
|
5042
7675
|
exports.Pagination = Pagination;
|
|
7676
|
+
exports.PayslipTemplate = PayslipTemplate;
|
|
5043
7677
|
exports.PermissionMatrix = PermissionMatrix;
|
|
5044
7678
|
exports.Popover = Popover;
|
|
5045
7679
|
exports.PopoverContent = PopoverContent;
|
|
@@ -5047,6 +7681,7 @@ exports.PopoverTrigger = PopoverTrigger;
|
|
|
5047
7681
|
exports.Progress = Progress;
|
|
5048
7682
|
exports.RadioGroup = RadioGroup;
|
|
5049
7683
|
exports.RadioItem = RadioItem;
|
|
7684
|
+
exports.ReportTemplate = ReportTemplate;
|
|
5050
7685
|
exports.Section = Section;
|
|
5051
7686
|
exports.SegmentedControl = SegmentedControl;
|
|
5052
7687
|
exports.Select = Select;
|
|
@@ -5071,6 +7706,7 @@ exports.TabPanel = TabPanel;
|
|
|
5071
7706
|
exports.TabPanels = TabPanels;
|
|
5072
7707
|
exports.Tabs = Tabs;
|
|
5073
7708
|
exports.Textarea = Textarea;
|
|
7709
|
+
exports.TimekeepingTemplate = TimekeepingTemplate;
|
|
5074
7710
|
exports.Timeline = Timeline;
|
|
5075
7711
|
exports.TimelineEmptyState = TimelineEmptyState;
|
|
5076
7712
|
exports.TimelineFooter = TimelineFooter;
|