@burdenoff/microfe-crewfoundry 2026.626.1 → 2026.703.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/crewfoundry/components/forms/ConfirmDialog.js +43 -0
- package/dist/crewfoundry/components/forms/ConfirmDialog.js.map +1 -0
- package/dist/crewfoundry/components/forms/FormModal.js +220 -0
- package/dist/crewfoundry/components/forms/FormModal.js.map +1 -0
- package/dist/crewfoundry/components/forms/formValues.js +20 -0
- package/dist/crewfoundry/components/forms/formValues.js.map +1 -0
- package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js +255 -65
- package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsCallsPagePage.js +28 -17
- package/dist/crewfoundry/pages/CommunicationsCallsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsFilesPagePage.js +57 -53
- package/dist/crewfoundry/pages/CommunicationsFilesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js +32 -23
- package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsVideoCallsPagePage.js +44 -29
- package/dist/crewfoundry/pages/CommunicationsVideoCallsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js +183 -57
- package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyCompanyDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js +214 -92
- package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/DashboardDashboardPagePage.js +165 -131
- package/dist/crewfoundry/pages/DashboardDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/DashboardEnhancedDashboardPagePage.js +163 -133
- package/dist/crewfoundry/pages/DashboardEnhancedDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringCandidatesPagePage.js +269 -54
- package/dist/crewfoundry/pages/HiringCandidatesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringCreateJobPagePage.js +225 -78
- package/dist/crewfoundry/pages/HiringCreateJobPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringInterviewsPagePage.js +213 -59
- package/dist/crewfoundry/pages/HiringInterviewsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js +287 -90
- package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringJobsPagePage.js +49 -47
- package/dist/crewfoundry/pages/HiringJobsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrDepartmentsPagePage.js +166 -59
- package/dist/crewfoundry/pages/HrDepartmentsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrEmployeesPagePage.js +274 -83
- package/dist/crewfoundry/pages/HrEmployeesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js +198 -88
- package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrPayrollPagePage.js +216 -88
- package/dist/crewfoundry/pages/HrPayrollPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js +216 -66
- package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningAssessmentsPagePage.js +6 -7
- package/dist/crewfoundry/pages/LearningAssessmentsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js +83 -68
- package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCoursesPagePage.js +167 -46
- package/dist/crewfoundry/pages/LearningCoursesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js +75 -55
- package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js +152 -79
- package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningMyLearningPagePage.js +75 -63
- package/dist/crewfoundry/pages/LearningMyLearningPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceBookingManagementPagePage.js +3 -1
- package/dist/crewfoundry/pages/MarketplaceBookingManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMyServicesPagePage.js +235 -87
- package/dist/crewfoundry/pages/MarketplaceMyServicesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js +199 -86
- package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsPaymentDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsPaymentMethodsPagePage.js +21 -40
- package/dist/crewfoundry/pages/PaymentsPaymentMethodsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/ProjectsCreateProjectPagePage.js +117 -45
- package/dist/crewfoundry/pages/ProjectsCreateProjectPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/ProjectsProjectDetailsPagePage.js +249 -90
- package/dist/crewfoundry/pages/ProjectsProjectDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js +47 -45
- package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamSettingsPagePage.js +262 -133
- package/dist/crewfoundry/pages/TeamsTeamSettingsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamsPagePage.js +144 -77
- package/dist/crewfoundry/pages/TeamsTeamsPagePage.js.map +1 -1
- package/dist/crewfoundry/store/crewfoundryStore.js +339 -52
- package/dist/crewfoundry/store/crewfoundryStore.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,215 +1,343 @@
|
|
|
1
1
|
import { useCrewFoundryStore as e } from "../store/crewfoundryStore.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
2
|
+
import { FormModal as t, useFormModal as n } from "../components/forms/FormModal.js";
|
|
3
|
+
import { getNumber as r, getText as i, newClientId as a } from "../components/forms/formValues.js";
|
|
4
|
+
import { useMemo as o, useState as s } from "react";
|
|
5
|
+
import { CheckCircle as c, Clock as l, DollarSign as u, Download as d, Plus as f, TrendingUp as p } from "lucide-react";
|
|
6
|
+
import { jsx as m, jsxs as h } from "react/jsx-runtime";
|
|
7
|
+
import { Badge as g, Button as _, Card as v, CardContent as y, CardDescription as b, CardHeader as x, CardTitle as S, GlassCard as C, GradientText as w, PagePurpose as T, Separator as E } from "@burdenoff/fe-libs/ui";
|
|
8
|
+
import { useGlobalUi as D } from "@burdenoff/fe-libs/shared/providers/shell";
|
|
6
9
|
//#region src/crewfoundry/pages/HrPayrollPagePage.tsx
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
var O = [
|
|
11
|
+
{
|
|
12
|
+
label: "Draft",
|
|
13
|
+
value: "draft"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
label: "Processing",
|
|
17
|
+
value: "processing"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
label: "Approved",
|
|
21
|
+
value: "approved"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
label: "Paid",
|
|
25
|
+
value: "paid"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
label: "Failed",
|
|
29
|
+
value: "failed"
|
|
30
|
+
}
|
|
31
|
+
];
|
|
32
|
+
function k() {
|
|
33
|
+
let { payrollRecords: k, employees: A, addPayrollRecord: j, updatePayrollRecord: M } = e(), { showToast: N } = D(), [P, F] = s("January 2026"), I = n(), L = o(() => A.map((e) => ({
|
|
34
|
+
label: `${e.firstName} ${e.lastName}`,
|
|
35
|
+
value: e.id
|
|
36
|
+
})), [A]), R = o(() => [
|
|
37
|
+
{
|
|
38
|
+
name: "employeeId",
|
|
39
|
+
label: "Employee",
|
|
40
|
+
type: "select",
|
|
41
|
+
required: !0,
|
|
42
|
+
options: L,
|
|
43
|
+
colSpan: 2
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
name: "period",
|
|
47
|
+
label: "Pay period",
|
|
48
|
+
type: "text",
|
|
49
|
+
required: !0,
|
|
50
|
+
placeholder: "e.g. February 2026"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: "paymentMethod",
|
|
54
|
+
label: "Payment method",
|
|
55
|
+
type: "text",
|
|
56
|
+
required: !0,
|
|
57
|
+
placeholder: "e.g. Bank Transfer"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
name: "grossPay",
|
|
61
|
+
label: "Gross pay",
|
|
62
|
+
type: "number",
|
|
63
|
+
required: !0
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
name: "deductions",
|
|
67
|
+
label: "Deductions",
|
|
68
|
+
type: "number",
|
|
69
|
+
required: !0
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
name: "netPay",
|
|
73
|
+
label: "Net pay (auto if blank)",
|
|
74
|
+
type: "number"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: "payDate",
|
|
78
|
+
label: "Pay date",
|
|
79
|
+
type: "date"
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
name: "status",
|
|
83
|
+
label: "Status",
|
|
84
|
+
type: "select",
|
|
85
|
+
options: O
|
|
86
|
+
}
|
|
87
|
+
], [L]), z = k.filter((e) => e.period === P), B = z.reduce((e, t) => e + t.grossPay, 0), V = z.reduce((e, t) => e + t.netPay, 0), H = z.filter((e) => e.status === "paid").length, U = z.filter((e) => e.status === "processing").length, W = [...new Set(k.map((e) => e.period))], G = async (e) => {
|
|
88
|
+
let t = i(e, "employeeId"), n = A.find((e) => e.id === t), o = r(e, "grossPay"), s = r(e, "deductions"), c = r(e, "netPay");
|
|
89
|
+
await j({
|
|
90
|
+
id: a(),
|
|
91
|
+
employeeId: t,
|
|
92
|
+
employeeName: n ? `${n.firstName} ${n.lastName}` : "",
|
|
93
|
+
department: n?.department ?? "",
|
|
94
|
+
period: i(e, "period"),
|
|
95
|
+
grossPay: o,
|
|
96
|
+
deductions: s,
|
|
97
|
+
netPay: c > 0 ? c : Math.max(o - s, 0),
|
|
98
|
+
status: i(e, "status") || "draft",
|
|
99
|
+
payDate: i(e, "payDate"),
|
|
100
|
+
paymentMethod: i(e, "paymentMethod")
|
|
101
|
+
});
|
|
102
|
+
}, K = async (e) => {
|
|
103
|
+
try {
|
|
104
|
+
await M(e.id, {
|
|
105
|
+
status: "paid",
|
|
106
|
+
payDate: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10)
|
|
107
|
+
});
|
|
108
|
+
} catch (e) {
|
|
109
|
+
N(e instanceof Error ? e.message : "Unable to update payroll record", "error");
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
return /* @__PURE__ */ h("div", {
|
|
12
113
|
className: "space-y-6 p-6",
|
|
13
114
|
children: [
|
|
14
|
-
/* @__PURE__ */
|
|
115
|
+
/* @__PURE__ */ h("div", {
|
|
15
116
|
className: "flex items-center justify-between",
|
|
16
|
-
children: [/* @__PURE__ */
|
|
17
|
-
/* @__PURE__ */
|
|
117
|
+
children: [/* @__PURE__ */ h("div", { children: [
|
|
118
|
+
/* @__PURE__ */ m("h1", {
|
|
18
119
|
className: "text-2xl font-semibold",
|
|
19
|
-
children: /* @__PURE__ */
|
|
120
|
+
children: /* @__PURE__ */ m(w, { children: "Payroll Management" })
|
|
20
121
|
}),
|
|
21
|
-
/* @__PURE__ */
|
|
122
|
+
/* @__PURE__ */ m("p", {
|
|
22
123
|
className: "text-sm text-text-secondary",
|
|
23
124
|
children: "Process and manage employee payroll"
|
|
24
125
|
}),
|
|
25
|
-
/* @__PURE__ */
|
|
126
|
+
/* @__PURE__ */ m(T, {
|
|
26
127
|
className: "mt-1",
|
|
27
128
|
children: "Run and review payroll — track salaries, deductions, and pay runs so your team gets paid accurately and on time."
|
|
28
129
|
})
|
|
29
|
-
] }), /* @__PURE__ */
|
|
130
|
+
] }), /* @__PURE__ */ h("div", {
|
|
30
131
|
className: "flex gap-2",
|
|
31
|
-
children: [/* @__PURE__ */
|
|
132
|
+
children: [/* @__PURE__ */ h(_, {
|
|
32
133
|
variant: "outline",
|
|
33
134
|
size: "sm",
|
|
34
|
-
|
|
35
|
-
|
|
135
|
+
disabled: !0,
|
|
136
|
+
"aria-label": "Export payroll (coming soon)",
|
|
137
|
+
title: "Payroll export is coming soon",
|
|
138
|
+
children: [
|
|
139
|
+
/* @__PURE__ */ m(d, { className: "h-4 w-4 mr-1" }),
|
|
140
|
+
"Export",
|
|
141
|
+
/* @__PURE__ */ m(g, {
|
|
142
|
+
variant: "secondary",
|
|
143
|
+
className: "ml-1 text-[9px]",
|
|
144
|
+
children: "Soon"
|
|
145
|
+
})
|
|
146
|
+
]
|
|
147
|
+
}), /* @__PURE__ */ h(_, {
|
|
36
148
|
size: "sm",
|
|
37
|
-
|
|
149
|
+
onClick: () => I.openModal(),
|
|
150
|
+
children: [/* @__PURE__ */ m(f, { className: "h-4 w-4 mr-1" }), "Add Record"]
|
|
38
151
|
})]
|
|
39
152
|
})]
|
|
40
153
|
}),
|
|
41
|
-
/* @__PURE__ */
|
|
154
|
+
/* @__PURE__ */ h("div", {
|
|
42
155
|
className: "grid gap-4 md:grid-cols-2 lg:grid-cols-4",
|
|
43
156
|
children: [
|
|
44
|
-
/* @__PURE__ */
|
|
157
|
+
/* @__PURE__ */ h(C, {
|
|
45
158
|
treatment: "glass",
|
|
46
159
|
glow: !0,
|
|
47
160
|
className: "border-border-seam",
|
|
48
|
-
children: [/* @__PURE__ */
|
|
161
|
+
children: [/* @__PURE__ */ h(x, {
|
|
49
162
|
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
50
|
-
children: [/* @__PURE__ */
|
|
163
|
+
children: [/* @__PURE__ */ m(S, {
|
|
51
164
|
className: "text-sm font-medium",
|
|
52
165
|
children: "Gross Payroll"
|
|
53
|
-
}), /* @__PURE__ */
|
|
54
|
-
}), /* @__PURE__ */
|
|
166
|
+
}), /* @__PURE__ */ m(u, { className: "h-4 w-4 text-text-secondary" })]
|
|
167
|
+
}), /* @__PURE__ */ h(y, { children: [/* @__PURE__ */ h("div", {
|
|
55
168
|
className: "text-2xl font-bold tabular-nums",
|
|
56
|
-
children: ["$",
|
|
57
|
-
}), /* @__PURE__ */
|
|
169
|
+
children: ["$", B.toLocaleString()]
|
|
170
|
+
}), /* @__PURE__ */ m("p", {
|
|
58
171
|
className: "text-xs text-text-secondary",
|
|
59
|
-
children:
|
|
172
|
+
children: P
|
|
60
173
|
})] })]
|
|
61
174
|
}),
|
|
62
|
-
/* @__PURE__ */
|
|
175
|
+
/* @__PURE__ */ h(C, {
|
|
63
176
|
treatment: "metric",
|
|
64
177
|
className: "border-border-seam",
|
|
65
|
-
children: [/* @__PURE__ */
|
|
178
|
+
children: [/* @__PURE__ */ h(x, {
|
|
66
179
|
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
67
|
-
children: [/* @__PURE__ */
|
|
180
|
+
children: [/* @__PURE__ */ m(S, {
|
|
68
181
|
className: "text-sm font-medium",
|
|
69
182
|
children: "Net Payroll"
|
|
70
|
-
}), /* @__PURE__ */
|
|
71
|
-
}), /* @__PURE__ */
|
|
183
|
+
}), /* @__PURE__ */ m(p, { className: "h-4 w-4 text-text-secondary" })]
|
|
184
|
+
}), /* @__PURE__ */ h(y, { children: [/* @__PURE__ */ h("div", {
|
|
72
185
|
className: "text-2xl font-bold tabular-nums",
|
|
73
|
-
children: ["$",
|
|
74
|
-
}), /* @__PURE__ */
|
|
186
|
+
children: ["$", V.toLocaleString()]
|
|
187
|
+
}), /* @__PURE__ */ m("p", {
|
|
75
188
|
className: "text-xs text-text-secondary",
|
|
76
189
|
children: "After deductions"
|
|
77
190
|
})] })]
|
|
78
191
|
}),
|
|
79
|
-
/* @__PURE__ */
|
|
192
|
+
/* @__PURE__ */ h(C, {
|
|
80
193
|
treatment: "metric",
|
|
81
194
|
className: "border-border-seam",
|
|
82
|
-
children: [/* @__PURE__ */
|
|
195
|
+
children: [/* @__PURE__ */ h(x, {
|
|
83
196
|
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
84
|
-
children: [/* @__PURE__ */
|
|
197
|
+
children: [/* @__PURE__ */ m(S, {
|
|
85
198
|
className: "text-sm font-medium",
|
|
86
199
|
children: "Paid"
|
|
87
|
-
}), /* @__PURE__ */ c
|
|
88
|
-
}), /* @__PURE__ */
|
|
200
|
+
}), /* @__PURE__ */ m(c, { className: "h-4 w-4 text-status-success-text" })]
|
|
201
|
+
}), /* @__PURE__ */ h(y, { children: [/* @__PURE__ */ m("div", {
|
|
89
202
|
className: "text-2xl font-bold tabular-nums",
|
|
90
|
-
children:
|
|
91
|
-
}), /* @__PURE__ */
|
|
203
|
+
children: H
|
|
204
|
+
}), /* @__PURE__ */ m("p", {
|
|
92
205
|
className: "text-xs text-text-secondary",
|
|
93
206
|
children: "employees paid"
|
|
94
207
|
})] })]
|
|
95
208
|
}),
|
|
96
|
-
/* @__PURE__ */
|
|
209
|
+
/* @__PURE__ */ h(C, {
|
|
97
210
|
treatment: "metric",
|
|
98
211
|
className: "border-border-seam",
|
|
99
|
-
children: [/* @__PURE__ */
|
|
212
|
+
children: [/* @__PURE__ */ h(x, {
|
|
100
213
|
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
101
|
-
children: [/* @__PURE__ */
|
|
214
|
+
children: [/* @__PURE__ */ m(S, {
|
|
102
215
|
className: "text-sm font-medium",
|
|
103
216
|
children: "Processing"
|
|
104
|
-
}), /* @__PURE__ */
|
|
105
|
-
}), /* @__PURE__ */
|
|
217
|
+
}), /* @__PURE__ */ m(l, { className: "h-4 w-4 text-status-warning-text" })]
|
|
218
|
+
}), /* @__PURE__ */ h(y, { children: [/* @__PURE__ */ m("div", {
|
|
106
219
|
className: "text-2xl font-bold tabular-nums",
|
|
107
|
-
children:
|
|
108
|
-
}), /* @__PURE__ */
|
|
220
|
+
children: U
|
|
221
|
+
}), /* @__PURE__ */ m("p", {
|
|
109
222
|
className: "text-xs text-text-secondary",
|
|
110
223
|
children: "in progress"
|
|
111
224
|
})] })]
|
|
112
225
|
})
|
|
113
226
|
]
|
|
114
227
|
}),
|
|
115
|
-
/* @__PURE__ */
|
|
228
|
+
/* @__PURE__ */ m("div", {
|
|
116
229
|
className: "flex gap-2",
|
|
117
|
-
children:
|
|
118
|
-
variant:
|
|
230
|
+
children: W.map((e) => /* @__PURE__ */ m(_, {
|
|
231
|
+
variant: P === e ? "default" : "outline",
|
|
119
232
|
size: "sm",
|
|
120
|
-
onClick: () =>
|
|
233
|
+
onClick: () => F(e),
|
|
121
234
|
children: e
|
|
122
235
|
}, e))
|
|
123
236
|
}),
|
|
124
|
-
/* @__PURE__ */
|
|
125
|
-
/* @__PURE__ */
|
|
237
|
+
/* @__PURE__ */ h(v, { children: [/* @__PURE__ */ h(x, { children: [/* @__PURE__ */ m(S, { children: "Payroll Records" }), /* @__PURE__ */ h(b, { children: ["Individual employee payroll details for ", P] })] }), /* @__PURE__ */ h(y, { children: [
|
|
238
|
+
/* @__PURE__ */ h("div", {
|
|
126
239
|
className: "grid grid-cols-7 gap-2 text-xs font-medium text-text-secondary border-b pb-2 mb-2",
|
|
127
240
|
children: [
|
|
128
|
-
/* @__PURE__ */
|
|
129
|
-
/* @__PURE__ */
|
|
130
|
-
/* @__PURE__ */
|
|
241
|
+
/* @__PURE__ */ m("span", { children: "Employee" }),
|
|
242
|
+
/* @__PURE__ */ m("span", { children: "Department" }),
|
|
243
|
+
/* @__PURE__ */ m("span", {
|
|
131
244
|
className: "text-right",
|
|
132
245
|
children: "Gross Pay"
|
|
133
246
|
}),
|
|
134
|
-
/* @__PURE__ */
|
|
247
|
+
/* @__PURE__ */ m("span", {
|
|
135
248
|
className: "text-right",
|
|
136
249
|
children: "Deductions"
|
|
137
250
|
}),
|
|
138
|
-
/* @__PURE__ */
|
|
251
|
+
/* @__PURE__ */ m("span", {
|
|
139
252
|
className: "text-right",
|
|
140
253
|
children: "Net Pay"
|
|
141
254
|
}),
|
|
142
|
-
/* @__PURE__ */
|
|
143
|
-
/* @__PURE__ */
|
|
255
|
+
/* @__PURE__ */ m("span", { children: "Payment Method" }),
|
|
256
|
+
/* @__PURE__ */ m("span", {
|
|
144
257
|
className: "text-center",
|
|
145
258
|
children: "Status"
|
|
146
259
|
})
|
|
147
260
|
]
|
|
148
261
|
}),
|
|
149
|
-
|
|
262
|
+
k.map((e) => /* @__PURE__ */ h("div", {
|
|
150
263
|
className: "grid grid-cols-7 gap-2 py-2 border-b last:border-0 text-sm",
|
|
151
264
|
children: [
|
|
152
|
-
/* @__PURE__ */
|
|
265
|
+
/* @__PURE__ */ m("span", {
|
|
153
266
|
className: "font-medium",
|
|
154
267
|
children: e.employeeName
|
|
155
268
|
}),
|
|
156
|
-
/* @__PURE__ */
|
|
269
|
+
/* @__PURE__ */ m("span", {
|
|
157
270
|
className: "text-text-secondary",
|
|
158
271
|
children: e.department
|
|
159
272
|
}),
|
|
160
|
-
/* @__PURE__ */
|
|
273
|
+
/* @__PURE__ */ h("span", {
|
|
161
274
|
className: "text-right",
|
|
162
275
|
children: ["$", e.grossPay.toLocaleString()]
|
|
163
276
|
}),
|
|
164
|
-
/* @__PURE__ */
|
|
277
|
+
/* @__PURE__ */ h("span", {
|
|
165
278
|
className: "text-right text-status-error-text",
|
|
166
279
|
children: ["-$", e.deductions.toLocaleString()]
|
|
167
280
|
}),
|
|
168
|
-
/* @__PURE__ */
|
|
281
|
+
/* @__PURE__ */ h("span", {
|
|
169
282
|
className: "text-right font-medium",
|
|
170
283
|
children: ["$", e.netPay.toLocaleString()]
|
|
171
284
|
}),
|
|
172
|
-
/* @__PURE__ */
|
|
285
|
+
/* @__PURE__ */ m("span", {
|
|
173
286
|
className: "text-text-secondary",
|
|
174
287
|
children: e.paymentMethod
|
|
175
288
|
}),
|
|
176
|
-
/* @__PURE__ */
|
|
177
|
-
className: "
|
|
178
|
-
children: /* @__PURE__ */
|
|
289
|
+
/* @__PURE__ */ h("div", {
|
|
290
|
+
className: "flex flex-col items-center gap-1",
|
|
291
|
+
children: [/* @__PURE__ */ m(g, {
|
|
179
292
|
variant: e.status === "paid" ? "default" : e.status === "processing" ? "secondary" : "outline",
|
|
180
293
|
className: "text-[10px]",
|
|
181
294
|
children: e.status
|
|
182
|
-
})
|
|
295
|
+
}), e.status !== "paid" && /* @__PURE__ */ m(_, {
|
|
296
|
+
variant: "ghost",
|
|
297
|
+
size: "sm",
|
|
298
|
+
className: "h-6 px-2 text-[10px]",
|
|
299
|
+
onClick: () => K(e),
|
|
300
|
+
children: "Mark paid"
|
|
301
|
+
})]
|
|
183
302
|
})
|
|
184
303
|
]
|
|
185
304
|
}, e.id)),
|
|
186
|
-
/* @__PURE__ */
|
|
187
|
-
/* @__PURE__ */
|
|
305
|
+
/* @__PURE__ */ m(E, { className: "my-2" }),
|
|
306
|
+
/* @__PURE__ */ h("div", {
|
|
188
307
|
className: "grid grid-cols-7 gap-2 text-sm font-bold",
|
|
189
308
|
children: [
|
|
190
|
-
/* @__PURE__ */
|
|
191
|
-
/* @__PURE__ */
|
|
192
|
-
/* @__PURE__ */
|
|
309
|
+
/* @__PURE__ */ m("span", { children: "Total" }),
|
|
310
|
+
/* @__PURE__ */ m("span", {}),
|
|
311
|
+
/* @__PURE__ */ h("span", {
|
|
193
312
|
className: "text-right",
|
|
194
|
-
children: ["$",
|
|
313
|
+
children: ["$", k.reduce((e, t) => e + t.grossPay, 0).toLocaleString()]
|
|
195
314
|
}),
|
|
196
|
-
/* @__PURE__ */
|
|
315
|
+
/* @__PURE__ */ h("span", {
|
|
197
316
|
className: "text-right text-status-error-text",
|
|
198
|
-
children: ["-$",
|
|
317
|
+
children: ["-$", k.reduce((e, t) => e + t.deductions, 0).toLocaleString()]
|
|
199
318
|
}),
|
|
200
|
-
/* @__PURE__ */
|
|
319
|
+
/* @__PURE__ */ h("span", {
|
|
201
320
|
className: "text-right",
|
|
202
|
-
children: ["$",
|
|
321
|
+
children: ["$", k.reduce((e, t) => e + t.netPay, 0).toLocaleString()]
|
|
203
322
|
}),
|
|
204
|
-
/* @__PURE__ */
|
|
205
|
-
/* @__PURE__ */
|
|
323
|
+
/* @__PURE__ */ m("span", {}),
|
|
324
|
+
/* @__PURE__ */ m("span", {})
|
|
206
325
|
]
|
|
207
326
|
})
|
|
208
|
-
] })] })
|
|
327
|
+
] })] }),
|
|
328
|
+
/* @__PURE__ */ m(t, {
|
|
329
|
+
open: I.open,
|
|
330
|
+
onOpenChange: I.onOpenChange,
|
|
331
|
+
title: "Add payroll record",
|
|
332
|
+
description: "Create a payroll entry for a team member.",
|
|
333
|
+
fields: R,
|
|
334
|
+
submitLabel: "Add record",
|
|
335
|
+
onSubmit: G
|
|
336
|
+
})
|
|
209
337
|
]
|
|
210
338
|
});
|
|
211
339
|
}
|
|
212
340
|
//#endregion
|
|
213
|
-
export {
|
|
341
|
+
export { k as HrPayrollPagePage };
|
|
214
342
|
|
|
215
343
|
//# sourceMappingURL=HrPayrollPagePage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HrPayrollPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/HrPayrollPagePage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n PagePurpose,\n Separator,\n} from '@burdenoff/fe-libs/ui';\nimport { CheckCircle, Clock, DollarSign, Download, FileText, Play, TrendingUp } from 'lucide-react';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\n\nexport function HrPayrollPagePage() {\n const { payrollRecords, employees } = useCrewFoundryStore();\n const [selectedPeriod, setSelectedPeriod] = useState('January 2026');\n\n const periodRecords = payrollRecords.filter((r) => r.period === selectedPeriod);\n const totalGross = periodRecords.reduce((s, r) => s + r.grossPay, 0);\n const totalDeductions = periodRecords.reduce((s, r) => s + r.deductions, 0);\n const totalNet = periodRecords.reduce((s, r) => s + r.netPay, 0);\n const paidCount = periodRecords.filter((r) => r.status === 'paid').length;\n const processingCount = periodRecords.filter((r) => r.status === 'processing').length;\n\n const periods = [...new Set(payrollRecords.map((r) => r.period))];\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>Payroll Management</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">Process and manage employee payroll</p>\n <PagePurpose className=\"mt-1\">Run and review payroll — track salaries, deductions, and pay runs so your team gets paid accurately and on time.</PagePurpose>\n </div>\n <div className=\"flex gap-2\">\n <Button variant=\"outline\" size=\"sm\">\n <Download className=\"h-4 w-4 mr-1\" />\n Export\n </Button>\n <Button size=\"sm\">\n <Play className=\"h-4 w-4 mr-1\" />\n Run Payroll\n </Button>\n </div>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-4\">\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Gross Payroll</CardTitle>\n <DollarSign className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">${totalGross.toLocaleString()}</div>\n <p className=\"text-xs text-text-secondary\">{selectedPeriod}</p>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Net Payroll</CardTitle>\n <TrendingUp className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">${totalNet.toLocaleString()}</div>\n <p className=\"text-xs text-text-secondary\">After deductions</p>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Paid</CardTitle>\n <CheckCircle className=\"h-4 w-4 text-status-success-text\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{paidCount}</div>\n <p className=\"text-xs text-text-secondary\">employees paid</p>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Processing</CardTitle>\n <Clock className=\"h-4 w-4 text-status-warning-text\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{processingCount}</div>\n <p className=\"text-xs text-text-secondary\">in progress</p>\n </CardContent>\n </GlassCard>\n </div>\n\n <div className=\"flex gap-2\">\n {periods.map((period) => (\n <Button\n key={period}\n variant={selectedPeriod === period ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => setSelectedPeriod(period)}\n >\n {period}\n </Button>\n ))}\n </div>\n\n <Card>\n <CardHeader>\n <CardTitle>Payroll Records</CardTitle>\n <CardDescription>\n Individual employee payroll details for {selectedPeriod}\n </CardDescription>\n </CardHeader>\n <CardContent>\n <div className=\"grid grid-cols-7 gap-2 text-xs font-medium text-text-secondary border-b pb-2 mb-2\">\n <span>Employee</span>\n <span>Department</span>\n <span className=\"text-right\">Gross Pay</span>\n <span className=\"text-right\">Deductions</span>\n <span className=\"text-right\">Net Pay</span>\n <span>Payment Method</span>\n <span className=\"text-center\">Status</span>\n </div>\n {payrollRecords.map((record) => (\n <div\n key={record.id}\n className=\"grid grid-cols-7 gap-2 py-2 border-b last:border-0 text-sm\"\n >\n <span className=\"font-medium\">{record.employeeName}</span>\n <span className=\"text-text-secondary\">{record.department}</span>\n <span className=\"text-right\">${record.grossPay.toLocaleString()}</span>\n <span className=\"text-right text-status-error-text\">\n -${record.deductions.toLocaleString()}\n </span>\n <span className=\"text-right font-medium\">${record.netPay.toLocaleString()}</span>\n <span className=\"text-text-secondary\">{record.paymentMethod}</span>\n <div className=\"text-center\">\n <Badge\n variant={\n record.status === 'paid'\n ? 'default'\n : record.status === 'processing'\n ? 'secondary'\n : 'outline'\n }\n className=\"text-[10px]\"\n >\n {record.status}\n </Badge>\n </div>\n </div>\n ))}\n <Separator className=\"my-2\" />\n <div className=\"grid grid-cols-7 gap-2 text-sm font-bold\">\n <span>Total</span>\n <span />\n <span className=\"text-right\">\n ${payrollRecords.reduce((s, r) => s + r.grossPay, 0).toLocaleString()}\n </span>\n <span className=\"text-right text-status-error-text\">\n -${payrollRecords.reduce((s, r) => s + r.deductions, 0).toLocaleString()}\n </span>\n <span className=\"text-right\">\n ${payrollRecords.reduce((s, r) => s + r.netPay, 0).toLocaleString()}\n </span>\n <span />\n <span />\n </div>\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"HrPayrollPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/HrPayrollPagePage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport {\n Badge,\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n PagePurpose,\n Separator,\n} from '@burdenoff/fe-libs/ui';\nimport { useGlobalUi } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { CheckCircle, Clock, DollarSign, Download, Plus, TrendingUp } from 'lucide-react';\nimport { useCrewFoundryStore, type PayrollRecord } from '../store/crewfoundryStore';\nimport { FormModal, useFormModal, type FieldConfig, type FormValues } from '../components/forms/FormModal';\nimport { getNumber, getText, newClientId } from '../components/forms/formValues';\n\nconst STATUS_OPTIONS = [\n { label: 'Draft', value: 'draft' },\n { label: 'Processing', value: 'processing' },\n { label: 'Approved', value: 'approved' },\n { label: 'Paid', value: 'paid' },\n { label: 'Failed', value: 'failed' },\n];\n\nexport function HrPayrollPagePage() {\n const { payrollRecords, employees, addPayrollRecord, updatePayrollRecord } = useCrewFoundryStore();\n const { showToast } = useGlobalUi();\n const [selectedPeriod, setSelectedPeriod] = useState('January 2026');\n const createForm = useFormModal<void>();\n\n const employeeOptions = useMemo(\n () =>\n employees.map((employee) => ({\n label: `${employee.firstName} ${employee.lastName}`,\n value: employee.id,\n })),\n [employees]\n );\n\n const payrollFields = useMemo<FieldConfig[]>(\n () => [\n {\n name: 'employeeId',\n label: 'Employee',\n type: 'select',\n required: true,\n options: employeeOptions,\n colSpan: 2,\n },\n { name: 'period', label: 'Pay period', type: 'text', required: true, placeholder: 'e.g. February 2026' },\n { name: 'paymentMethod', label: 'Payment method', type: 'text', required: true, placeholder: 'e.g. Bank Transfer' },\n { name: 'grossPay', label: 'Gross pay', type: 'number', required: true },\n { name: 'deductions', label: 'Deductions', type: 'number', required: true },\n { name: 'netPay', label: 'Net pay (auto if blank)', type: 'number' },\n { name: 'payDate', label: 'Pay date', type: 'date' },\n { name: 'status', label: 'Status', type: 'select', options: STATUS_OPTIONS },\n ],\n [employeeOptions]\n );\n\n const periodRecords = payrollRecords.filter((r) => r.period === selectedPeriod);\n const totalGross = periodRecords.reduce((s, r) => s + r.grossPay, 0);\n const totalNet = periodRecords.reduce((s, r) => s + r.netPay, 0);\n const paidCount = periodRecords.filter((r) => r.status === 'paid').length;\n const processingCount = periodRecords.filter((r) => r.status === 'processing').length;\n\n const periods = [...new Set(payrollRecords.map((r) => r.period))];\n\n const handleCreate = async (values: FormValues) => {\n const employeeId = getText(values, 'employeeId');\n const employee = employees.find((item) => item.id === employeeId);\n const grossPay = getNumber(values, 'grossPay');\n const deductions = getNumber(values, 'deductions');\n const netPayInput = getNumber(values, 'netPay');\n const payload: PayrollRecord = {\n id: newClientId(),\n employeeId,\n employeeName: employee ? `${employee.firstName} ${employee.lastName}` : '',\n department: employee?.department ?? '',\n period: getText(values, 'period'),\n grossPay,\n deductions,\n netPay: netPayInput > 0 ? netPayInput : Math.max(grossPay - deductions, 0),\n status: (getText(values, 'status') as PayrollRecord['status']) || 'draft',\n payDate: getText(values, 'payDate'),\n paymentMethod: getText(values, 'paymentMethod'),\n };\n await addPayrollRecord(payload);\n };\n\n const handleMarkPaid = async (record: PayrollRecord) => {\n try {\n await updatePayrollRecord(record.id, {\n status: 'paid',\n payDate: new Date().toISOString().slice(0, 10),\n });\n } catch (error) {\n showToast(error instanceof Error ? error.message : 'Unable to update payroll record', 'error');\n }\n };\n\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>Payroll Management</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">Process and manage employee payroll</p>\n <PagePurpose className=\"mt-1\">Run and review payroll — track salaries, deductions, and pay runs so your team gets paid accurately and on time.</PagePurpose>\n </div>\n <div className=\"flex gap-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled\n aria-label=\"Export payroll (coming soon)\"\n title=\"Payroll export is coming soon\"\n >\n <Download className=\"h-4 w-4 mr-1\" />\n Export\n <Badge variant=\"secondary\" className=\"ml-1 text-[9px]\">\n Soon\n </Badge>\n </Button>\n <Button size=\"sm\" onClick={() => createForm.openModal()}>\n <Plus className=\"h-4 w-4 mr-1\" />\n Add Record\n </Button>\n </div>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-4\">\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Gross Payroll</CardTitle>\n <DollarSign className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">${totalGross.toLocaleString()}</div>\n <p className=\"text-xs text-text-secondary\">{selectedPeriod}</p>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Net Payroll</CardTitle>\n <TrendingUp className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">${totalNet.toLocaleString()}</div>\n <p className=\"text-xs text-text-secondary\">After deductions</p>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Paid</CardTitle>\n <CheckCircle className=\"h-4 w-4 text-status-success-text\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{paidCount}</div>\n <p className=\"text-xs text-text-secondary\">employees paid</p>\n </CardContent>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"border-border-seam\">\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0 pb-2\">\n <CardTitle className=\"text-sm font-medium\">Processing</CardTitle>\n <Clock className=\"h-4 w-4 text-status-warning-text\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{processingCount}</div>\n <p className=\"text-xs text-text-secondary\">in progress</p>\n </CardContent>\n </GlassCard>\n </div>\n\n <div className=\"flex gap-2\">\n {periods.map((period) => (\n <Button\n key={period}\n variant={selectedPeriod === period ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => setSelectedPeriod(period)}\n >\n {period}\n </Button>\n ))}\n </div>\n\n <Card>\n <CardHeader>\n <CardTitle>Payroll Records</CardTitle>\n <CardDescription>\n Individual employee payroll details for {selectedPeriod}\n </CardDescription>\n </CardHeader>\n <CardContent>\n <div className=\"grid grid-cols-7 gap-2 text-xs font-medium text-text-secondary border-b pb-2 mb-2\">\n <span>Employee</span>\n <span>Department</span>\n <span className=\"text-right\">Gross Pay</span>\n <span className=\"text-right\">Deductions</span>\n <span className=\"text-right\">Net Pay</span>\n <span>Payment Method</span>\n <span className=\"text-center\">Status</span>\n </div>\n {payrollRecords.map((record) => (\n <div\n key={record.id}\n className=\"grid grid-cols-7 gap-2 py-2 border-b last:border-0 text-sm\"\n >\n <span className=\"font-medium\">{record.employeeName}</span>\n <span className=\"text-text-secondary\">{record.department}</span>\n <span className=\"text-right\">${record.grossPay.toLocaleString()}</span>\n <span className=\"text-right text-status-error-text\">\n -${record.deductions.toLocaleString()}\n </span>\n <span className=\"text-right font-medium\">${record.netPay.toLocaleString()}</span>\n <span className=\"text-text-secondary\">{record.paymentMethod}</span>\n <div className=\"flex flex-col items-center gap-1\">\n <Badge\n variant={\n record.status === 'paid'\n ? 'default'\n : record.status === 'processing'\n ? 'secondary'\n : 'outline'\n }\n className=\"text-[10px]\"\n >\n {record.status}\n </Badge>\n {record.status !== 'paid' && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-6 px-2 text-[10px]\"\n onClick={() => handleMarkPaid(record)}\n >\n Mark paid\n </Button>\n )}\n </div>\n </div>\n ))}\n <Separator className=\"my-2\" />\n <div className=\"grid grid-cols-7 gap-2 text-sm font-bold\">\n <span>Total</span>\n <span />\n <span className=\"text-right\">\n ${payrollRecords.reduce((s, r) => s + r.grossPay, 0).toLocaleString()}\n </span>\n <span className=\"text-right text-status-error-text\">\n -${payrollRecords.reduce((s, r) => s + r.deductions, 0).toLocaleString()}\n </span>\n <span className=\"text-right\">\n ${payrollRecords.reduce((s, r) => s + r.netPay, 0).toLocaleString()}\n </span>\n <span />\n <span />\n </div>\n </CardContent>\n </Card>\n\n <FormModal\n open={createForm.open}\n onOpenChange={createForm.onOpenChange}\n title=\"Add payroll record\"\n description=\"Create a payroll entry for a team member.\"\n fields={payrollFields}\n submitLabel=\"Add record\"\n onSubmit={handleCreate}\n />\n </div>\n );\n}\n"],"mappings":"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"}
|