@burdenoff/microfe-crewfoundry 2026.703.1 → 2026.704.1
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/pages/AdminAdminPagePage.js +117 -164
- package/dist/crewfoundry/pages/AdminAdminPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/AnalyticsAnalyticsPagePage.js +99 -82
- package/dist/crewfoundry/pages/AnalyticsAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/AnalyticsEmployeeAnalyticsPagePage.js +160 -192
- package/dist/crewfoundry/pages/AnalyticsEmployeeAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js +238 -231
- package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.js +196 -166
- package/dist/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsCallsPagePage.js +45 -147
- package/dist/crewfoundry/pages/CommunicationsCallsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsDirectoryPagePage.js +20 -11
- package/dist/crewfoundry/pages/CommunicationsDirectoryPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsFilesPagePage.js +45 -152
- package/dist/crewfoundry/pages/CommunicationsFilesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js +50 -138
- package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsTeamsPagePage.js +149 -67
- package/dist/crewfoundry/pages/CommunicationsTeamsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsVideoCallsPagePage.js +50 -201
- package/dist/crewfoundry/pages/CommunicationsVideoCallsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js +205 -136
- package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyCompanyDashboardPagePage.js +25 -31
- package/dist/crewfoundry/pages/CompanyCompanyDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyCompanyProfilePagePage.js +118 -104
- package/dist/crewfoundry/pages/CompanyCompanyProfilePagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js +117 -58
- package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/DashboardAnalyticsPagePage.js +90 -94
- package/dist/crewfoundry/pages/DashboardAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/DashboardDashboardPagePage.js +210 -191
- package/dist/crewfoundry/pages/DashboardDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/DashboardEnhancedDashboardPagePage.js +213 -180
- package/dist/crewfoundry/pages/DashboardEnhancedDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/DashboardExecutiveDashboardPage.js +133 -264
- package/dist/crewfoundry/pages/DashboardExecutiveDashboardPage.js.map +1 -1
- package/dist/crewfoundry/pages/HelpApiDocumentationPagePage.js +279 -212
- package/dist/crewfoundry/pages/HelpApiDocumentationPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringApplicationsPagePage.js +131 -105
- package/dist/crewfoundry/pages/HiringApplicationsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringCandidatesPagePage.js +167 -148
- package/dist/crewfoundry/pages/HiringCandidatesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringCreateJobPagePage.js +3 -3
- package/dist/crewfoundry/pages/HiringCreateJobPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringInterviewsPagePage.js +13 -5
- package/dist/crewfoundry/pages/HiringInterviewsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js +151 -152
- package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringJobsPagePage.js +38 -21
- package/dist/crewfoundry/pages/HiringJobsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrDepartmentsPagePage.js +3 -3
- package/dist/crewfoundry/pages/HrDepartmentsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrEmployeesPagePage.js +134 -127
- package/dist/crewfoundry/pages/HrEmployeesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js +163 -132
- package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrPayrollPagePage.js +202 -160
- package/dist/crewfoundry/pages/HrPayrollPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js +104 -91
- package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningAssessmentsPagePage.js +29 -147
- package/dist/crewfoundry/pages/LearningAssessmentsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCertificatesPagePage.js +22 -106
- package/dist/crewfoundry/pages/LearningCertificatesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js +74 -74
- package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js +101 -97
- package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCoursesPagePage.js +64 -47
- package/dist/crewfoundry/pages/LearningCoursesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningAnalyticsPagePage.js +111 -121
- package/dist/crewfoundry/pages/LearningLearningAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningPagePage.js +131 -110
- package/dist/crewfoundry/pages/LearningLearningPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js +65 -64
- package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js +58 -43
- package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningMyLearningPagePage.js +66 -82
- package/dist/crewfoundry/pages/LearningMyLearningPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceBookingManagementPagePage.js +38 -88
- package/dist/crewfoundry/pages/MarketplaceBookingManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceEarningsPagePage.js +59 -65
- package/dist/crewfoundry/pages/MarketplaceEarningsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePageEnhancedPage.js +209 -323
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePageEnhancedPage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js +175 -220
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js +74 -59
- package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js +96 -80
- package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMessagingPagePage.js +28 -100
- package/dist/crewfoundry/pages/MarketplaceMessagingPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMyServicesPagePage.js +27 -20
- package/dist/crewfoundry/pages/MarketplaceMyServicesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceProjectDetailsPagePage.js +73 -73
- package/dist/crewfoundry/pages/MarketplaceProjectDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js +62 -56
- package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsEscrowPagePage.js +40 -138
- package/dist/crewfoundry/pages/PaymentsEscrowPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js +126 -93
- package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsPaymentDashboardPagePage.js +99 -77
- package/dist/crewfoundry/pages/PaymentsPaymentDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsSecurityPagePage.js +73 -74
- package/dist/crewfoundry/pages/PaymentsSecurityPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/ProjectsCreateProjectPagePage.js +1 -1
- package/dist/crewfoundry/pages/ProjectsCreateProjectPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/ProjectsProjectDetailsPagePage.js +122 -122
- package/dist/crewfoundry/pages/ProjectsProjectDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js +130 -113
- package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamAnalyticsPagePage.js +68 -59
- package/dist/crewfoundry/pages/TeamsTeamAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamDetailPagePage.js +73 -62
- package/dist/crewfoundry/pages/TeamsTeamDetailPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamDirectoryPagePage.js +82 -58
- package/dist/crewfoundry/pages/TeamsTeamDirectoryPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamSettingsPagePage.js +153 -153
- package/dist/crewfoundry/pages/TeamsTeamSettingsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamsPagePage.js +63 -48
- package/dist/crewfoundry/pages/TeamsTeamsPagePage.js.map +1 -1
- package/dist/crewfoundry/store/crewfoundryStore.js +35 -3
- package/dist/crewfoundry/store/crewfoundryStore.js.map +1 -1
- package/package.json +1 -1
|
@@ -3,11 +3,12 @@ import { FormModal as t, useFormModal as n } from "../components/forms/FormModal
|
|
|
3
3
|
import { getNumber as r, getText as i, newClientId as a } from "../components/forms/formValues.js";
|
|
4
4
|
import { useMemo as o, useState as s } from "react";
|
|
5
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 {
|
|
7
|
-
import { Badge as
|
|
8
|
-
import {
|
|
6
|
+
import { Fragment as m, jsx as h, jsxs as g } from "react/jsx-runtime";
|
|
7
|
+
import { Badge as _, Button as v, Card as y, CardContent as b, CardDescription as x, CardHeader as S, CardTitle as C, GlassCard as w, GradientText as T, PagePurpose as E, Pagination as D, ResponsiveTable as O, Separator as k } from "@burdenoff/fe-libs/ui";
|
|
8
|
+
import { usePagination as A } from "@burdenoff/fe-libs/shared/hooks";
|
|
9
|
+
import { useGlobalUi as j } from "@burdenoff/fe-libs/shared/providers/shell";
|
|
9
10
|
//#region src/crewfoundry/pages/HrPayrollPagePage.tsx
|
|
10
|
-
var
|
|
11
|
+
var M = [
|
|
11
12
|
{
|
|
12
13
|
label: "Draft",
|
|
13
14
|
value: "draft"
|
|
@@ -29,17 +30,17 @@ var O = [
|
|
|
29
30
|
value: "failed"
|
|
30
31
|
}
|
|
31
32
|
];
|
|
32
|
-
function
|
|
33
|
-
let { payrollRecords:
|
|
33
|
+
function N() {
|
|
34
|
+
let { payrollRecords: N, employees: P, addPayrollRecord: F, updatePayrollRecord: I } = e(), { showToast: L } = j(), [R, z] = s("January 2026"), B = n(), { page: V, pageSize: H, offset: U, setPage: W } = A({ initialPageSize: 10 }), G = o(() => P.map((e) => ({
|
|
34
35
|
label: `${e.firstName} ${e.lastName}`,
|
|
35
36
|
value: e.id
|
|
36
|
-
})), [
|
|
37
|
+
})), [P]), K = o(() => [
|
|
37
38
|
{
|
|
38
39
|
name: "employeeId",
|
|
39
40
|
label: "Employee",
|
|
40
41
|
type: "select",
|
|
41
42
|
required: !0,
|
|
42
|
-
options:
|
|
43
|
+
options: G,
|
|
43
44
|
colSpan: 2
|
|
44
45
|
},
|
|
45
46
|
{
|
|
@@ -82,11 +83,84 @@ function k() {
|
|
|
82
83
|
name: "status",
|
|
83
84
|
label: "Status",
|
|
84
85
|
type: "select",
|
|
85
|
-
options:
|
|
86
|
+
options: M
|
|
86
87
|
}
|
|
87
|
-
], [
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
], [G]), q = N.filter((e) => e.period === R), J = q.reduce((e, t) => e + t.grossPay, 0), Y = q.reduce((e, t) => e + t.netPay, 0), X = q.reduce((e, t) => e + t.deductions, 0), Z = q.filter((e) => e.status === "paid").length, Q = q.filter((e) => e.status === "processing").length, $ = q.slice(U, U + H), ee = [...new Set(N.map((e) => e.period))], te = (e) => {
|
|
89
|
+
z(e), W(1);
|
|
90
|
+
}, ne = [
|
|
91
|
+
{
|
|
92
|
+
key: "employee",
|
|
93
|
+
header: "Employee",
|
|
94
|
+
priority: "primary",
|
|
95
|
+
cell: (e) => /* @__PURE__ */ h("span", {
|
|
96
|
+
className: "font-medium",
|
|
97
|
+
children: e.employeeName
|
|
98
|
+
})
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
key: "department",
|
|
102
|
+
header: "Department",
|
|
103
|
+
cell: (e) => /* @__PURE__ */ h("span", {
|
|
104
|
+
className: "text-text-secondary",
|
|
105
|
+
children: e.department
|
|
106
|
+
})
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
key: "gross",
|
|
110
|
+
header: "Gross Pay",
|
|
111
|
+
headerClassName: "text-right",
|
|
112
|
+
cellClassName: "md:text-right",
|
|
113
|
+
cell: (e) => /* @__PURE__ */ g("span", { children: ["$", e.grossPay.toLocaleString()] })
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
key: "deductions",
|
|
117
|
+
header: "Deductions",
|
|
118
|
+
headerClassName: "text-right",
|
|
119
|
+
cellClassName: "md:text-right",
|
|
120
|
+
cell: (e) => /* @__PURE__ */ g("span", {
|
|
121
|
+
className: "text-status-error-text",
|
|
122
|
+
children: ["-$", e.deductions.toLocaleString()]
|
|
123
|
+
})
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
key: "net",
|
|
127
|
+
header: "Net Pay",
|
|
128
|
+
headerClassName: "text-right",
|
|
129
|
+
cellClassName: "md:text-right",
|
|
130
|
+
cell: (e) => /* @__PURE__ */ g("span", {
|
|
131
|
+
className: "font-medium",
|
|
132
|
+
children: ["$", e.netPay.toLocaleString()]
|
|
133
|
+
})
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
key: "method",
|
|
137
|
+
header: "Payment Method",
|
|
138
|
+
cell: (e) => /* @__PURE__ */ h("span", {
|
|
139
|
+
className: "text-text-secondary",
|
|
140
|
+
children: e.paymentMethod
|
|
141
|
+
})
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
key: "status",
|
|
145
|
+
header: "Status",
|
|
146
|
+
cell: (e) => /* @__PURE__ */ g("div", {
|
|
147
|
+
className: "flex items-center gap-2",
|
|
148
|
+
children: [/* @__PURE__ */ h(_, {
|
|
149
|
+
variant: e.status === "paid" ? "default" : e.status === "processing" ? "secondary" : "outline",
|
|
150
|
+
className: "text-[10px]",
|
|
151
|
+
children: e.status
|
|
152
|
+
}), e.status !== "paid" && /* @__PURE__ */ h(v, {
|
|
153
|
+
variant: "ghost",
|
|
154
|
+
size: "sm",
|
|
155
|
+
className: "h-6 px-2 text-[10px]",
|
|
156
|
+
onClick: () => ie(e),
|
|
157
|
+
children: "Mark paid"
|
|
158
|
+
})]
|
|
159
|
+
})
|
|
160
|
+
}
|
|
161
|
+
], re = async (e) => {
|
|
162
|
+
let t = i(e, "employeeId"), n = P.find((e) => e.id === t), o = r(e, "grossPay"), s = r(e, "deductions"), c = r(e, "netPay");
|
|
163
|
+
await F({
|
|
90
164
|
id: a(),
|
|
91
165
|
employeeId: t,
|
|
92
166
|
employeeName: n ? `${n.firstName} ${n.lastName}` : "",
|
|
@@ -99,245 +173,213 @@ function k() {
|
|
|
99
173
|
payDate: i(e, "payDate"),
|
|
100
174
|
paymentMethod: i(e, "paymentMethod")
|
|
101
175
|
});
|
|
102
|
-
},
|
|
176
|
+
}, ie = async (e) => {
|
|
103
177
|
try {
|
|
104
|
-
await
|
|
178
|
+
await I(e.id, {
|
|
105
179
|
status: "paid",
|
|
106
180
|
payDate: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10)
|
|
107
181
|
});
|
|
108
182
|
} catch (e) {
|
|
109
|
-
|
|
183
|
+
L(e instanceof Error ? e.message : "Unable to update payroll record", "error");
|
|
110
184
|
}
|
|
111
185
|
};
|
|
112
|
-
return /* @__PURE__ */
|
|
186
|
+
return /* @__PURE__ */ g("div", {
|
|
113
187
|
className: "space-y-6 p-6",
|
|
114
188
|
children: [
|
|
115
|
-
/* @__PURE__ */
|
|
189
|
+
/* @__PURE__ */ g("div", {
|
|
116
190
|
className: "flex items-center justify-between",
|
|
117
|
-
children: [/* @__PURE__ */
|
|
118
|
-
/* @__PURE__ */
|
|
191
|
+
children: [/* @__PURE__ */ g("div", { children: [
|
|
192
|
+
/* @__PURE__ */ h("h1", {
|
|
119
193
|
className: "text-2xl font-semibold",
|
|
120
|
-
children: /* @__PURE__ */
|
|
194
|
+
children: /* @__PURE__ */ h(T, { children: "Payroll Management" })
|
|
121
195
|
}),
|
|
122
|
-
/* @__PURE__ */
|
|
196
|
+
/* @__PURE__ */ h("p", {
|
|
123
197
|
className: "text-sm text-text-secondary",
|
|
124
198
|
children: "Process and manage employee payroll"
|
|
125
199
|
}),
|
|
126
|
-
/* @__PURE__ */
|
|
200
|
+
/* @__PURE__ */ h(E, {
|
|
127
201
|
className: "mt-1",
|
|
128
202
|
children: "Run and review payroll — track salaries, deductions, and pay runs so your team gets paid accurately and on time."
|
|
129
203
|
})
|
|
130
|
-
] }), /* @__PURE__ */
|
|
204
|
+
] }), /* @__PURE__ */ g("div", {
|
|
131
205
|
className: "flex gap-2",
|
|
132
|
-
children: [/* @__PURE__ */
|
|
206
|
+
children: [/* @__PURE__ */ g(v, {
|
|
133
207
|
variant: "outline",
|
|
134
208
|
size: "sm",
|
|
135
209
|
disabled: !0,
|
|
136
210
|
"aria-label": "Export payroll (coming soon)",
|
|
137
211
|
title: "Payroll export is coming soon",
|
|
138
212
|
children: [
|
|
139
|
-
/* @__PURE__ */
|
|
213
|
+
/* @__PURE__ */ h(d, { className: "h-4 w-4 mr-1" }),
|
|
140
214
|
"Export",
|
|
141
|
-
/* @__PURE__ */
|
|
215
|
+
/* @__PURE__ */ h(_, {
|
|
142
216
|
variant: "secondary",
|
|
143
217
|
className: "ml-1 text-[9px]",
|
|
144
218
|
children: "Soon"
|
|
145
219
|
})
|
|
146
220
|
]
|
|
147
|
-
}), /* @__PURE__ */
|
|
221
|
+
}), /* @__PURE__ */ g(v, {
|
|
148
222
|
size: "sm",
|
|
149
|
-
onClick: () =>
|
|
150
|
-
children: [/* @__PURE__ */
|
|
223
|
+
onClick: () => B.openModal(),
|
|
224
|
+
children: [/* @__PURE__ */ h(f, { className: "h-4 w-4 mr-1" }), "Add Record"]
|
|
151
225
|
})]
|
|
152
226
|
})]
|
|
153
227
|
}),
|
|
154
|
-
/* @__PURE__ */
|
|
228
|
+
/* @__PURE__ */ g("div", {
|
|
155
229
|
className: "grid gap-4 md:grid-cols-2 lg:grid-cols-4",
|
|
156
230
|
children: [
|
|
157
|
-
/* @__PURE__ */
|
|
231
|
+
/* @__PURE__ */ g(w, {
|
|
158
232
|
treatment: "glass",
|
|
159
233
|
glow: !0,
|
|
160
234
|
className: "border-border-seam",
|
|
161
|
-
children: [/* @__PURE__ */
|
|
235
|
+
children: [/* @__PURE__ */ g(S, {
|
|
162
236
|
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
163
|
-
children: [/* @__PURE__ */
|
|
237
|
+
children: [/* @__PURE__ */ h(C, {
|
|
164
238
|
className: "text-sm font-medium",
|
|
165
239
|
children: "Gross Payroll"
|
|
166
|
-
}), /* @__PURE__ */
|
|
167
|
-
}), /* @__PURE__ */
|
|
240
|
+
}), /* @__PURE__ */ h(u, { className: "h-4 w-4 text-text-secondary" })]
|
|
241
|
+
}), /* @__PURE__ */ g(b, { children: [/* @__PURE__ */ g("div", {
|
|
168
242
|
className: "text-2xl font-bold tabular-nums",
|
|
169
|
-
children: ["$",
|
|
170
|
-
}), /* @__PURE__ */
|
|
243
|
+
children: ["$", J.toLocaleString()]
|
|
244
|
+
}), /* @__PURE__ */ h("p", {
|
|
171
245
|
className: "text-xs text-text-secondary",
|
|
172
|
-
children:
|
|
246
|
+
children: R
|
|
173
247
|
})] })]
|
|
174
248
|
}),
|
|
175
|
-
/* @__PURE__ */
|
|
249
|
+
/* @__PURE__ */ g(w, {
|
|
176
250
|
treatment: "metric",
|
|
177
251
|
className: "border-border-seam",
|
|
178
|
-
children: [/* @__PURE__ */
|
|
252
|
+
children: [/* @__PURE__ */ g(S, {
|
|
179
253
|
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
180
|
-
children: [/* @__PURE__ */
|
|
254
|
+
children: [/* @__PURE__ */ h(C, {
|
|
181
255
|
className: "text-sm font-medium",
|
|
182
256
|
children: "Net Payroll"
|
|
183
|
-
}), /* @__PURE__ */
|
|
184
|
-
}), /* @__PURE__ */
|
|
257
|
+
}), /* @__PURE__ */ h(p, { className: "h-4 w-4 text-text-secondary" })]
|
|
258
|
+
}), /* @__PURE__ */ g(b, { children: [/* @__PURE__ */ g("div", {
|
|
185
259
|
className: "text-2xl font-bold tabular-nums",
|
|
186
|
-
children: ["$",
|
|
187
|
-
}), /* @__PURE__ */
|
|
260
|
+
children: ["$", Y.toLocaleString()]
|
|
261
|
+
}), /* @__PURE__ */ h("p", {
|
|
188
262
|
className: "text-xs text-text-secondary",
|
|
189
263
|
children: "After deductions"
|
|
190
264
|
})] })]
|
|
191
265
|
}),
|
|
192
|
-
/* @__PURE__ */
|
|
266
|
+
/* @__PURE__ */ g(w, {
|
|
193
267
|
treatment: "metric",
|
|
194
268
|
className: "border-border-seam",
|
|
195
|
-
children: [/* @__PURE__ */
|
|
269
|
+
children: [/* @__PURE__ */ g(S, {
|
|
196
270
|
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
197
|
-
children: [/* @__PURE__ */
|
|
271
|
+
children: [/* @__PURE__ */ h(C, {
|
|
198
272
|
className: "text-sm font-medium",
|
|
199
273
|
children: "Paid"
|
|
200
|
-
}), /* @__PURE__ */
|
|
201
|
-
}), /* @__PURE__ */
|
|
274
|
+
}), /* @__PURE__ */ h(c, { className: "h-4 w-4 text-status-success-text" })]
|
|
275
|
+
}), /* @__PURE__ */ g(b, { children: [/* @__PURE__ */ h("div", {
|
|
202
276
|
className: "text-2xl font-bold tabular-nums",
|
|
203
|
-
children:
|
|
204
|
-
}), /* @__PURE__ */
|
|
277
|
+
children: Z
|
|
278
|
+
}), /* @__PURE__ */ h("p", {
|
|
205
279
|
className: "text-xs text-text-secondary",
|
|
206
280
|
children: "employees paid"
|
|
207
281
|
})] })]
|
|
208
282
|
}),
|
|
209
|
-
/* @__PURE__ */
|
|
283
|
+
/* @__PURE__ */ g(w, {
|
|
210
284
|
treatment: "metric",
|
|
211
285
|
className: "border-border-seam",
|
|
212
|
-
children: [/* @__PURE__ */
|
|
286
|
+
children: [/* @__PURE__ */ g(S, {
|
|
213
287
|
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
214
|
-
children: [/* @__PURE__ */
|
|
288
|
+
children: [/* @__PURE__ */ h(C, {
|
|
215
289
|
className: "text-sm font-medium",
|
|
216
290
|
children: "Processing"
|
|
217
|
-
}), /* @__PURE__ */
|
|
218
|
-
}), /* @__PURE__ */
|
|
291
|
+
}), /* @__PURE__ */ h(l, { className: "h-4 w-4 text-status-warning-text" })]
|
|
292
|
+
}), /* @__PURE__ */ g(b, { children: [/* @__PURE__ */ h("div", {
|
|
219
293
|
className: "text-2xl font-bold tabular-nums",
|
|
220
|
-
children:
|
|
221
|
-
}), /* @__PURE__ */
|
|
294
|
+
children: Q
|
|
295
|
+
}), /* @__PURE__ */ h("p", {
|
|
222
296
|
className: "text-xs text-text-secondary",
|
|
223
297
|
children: "in progress"
|
|
224
298
|
})] })]
|
|
225
299
|
})
|
|
226
300
|
]
|
|
227
301
|
}),
|
|
228
|
-
/* @__PURE__ */
|
|
229
|
-
className: "flex gap-2",
|
|
230
|
-
children:
|
|
231
|
-
variant:
|
|
302
|
+
/* @__PURE__ */ h("div", {
|
|
303
|
+
className: "flex flex-wrap gap-2",
|
|
304
|
+
children: ee.map((e) => /* @__PURE__ */ h(v, {
|
|
305
|
+
variant: R === e ? "default" : "outline",
|
|
232
306
|
size: "sm",
|
|
233
|
-
onClick: () =>
|
|
307
|
+
onClick: () => te(e),
|
|
234
308
|
children: e
|
|
235
309
|
}, e))
|
|
236
310
|
}),
|
|
237
|
-
/* @__PURE__ */
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
/* @__PURE__ */ m("span", {
|
|
252
|
-
className: "text-right",
|
|
253
|
-
children: "Net Pay"
|
|
254
|
-
}),
|
|
255
|
-
/* @__PURE__ */ m("span", { children: "Payment Method" }),
|
|
256
|
-
/* @__PURE__ */ m("span", {
|
|
257
|
-
className: "text-center",
|
|
258
|
-
children: "Status"
|
|
259
|
-
})
|
|
260
|
-
]
|
|
261
|
-
}),
|
|
262
|
-
k.map((e) => /* @__PURE__ */ h("div", {
|
|
263
|
-
className: "grid grid-cols-7 gap-2 py-2 border-b last:border-0 text-sm",
|
|
264
|
-
children: [
|
|
265
|
-
/* @__PURE__ */ m("span", {
|
|
266
|
-
className: "font-medium",
|
|
267
|
-
children: e.employeeName
|
|
268
|
-
}),
|
|
269
|
-
/* @__PURE__ */ m("span", {
|
|
270
|
-
className: "text-text-secondary",
|
|
271
|
-
children: e.department
|
|
272
|
-
}),
|
|
273
|
-
/* @__PURE__ */ h("span", {
|
|
274
|
-
className: "text-right",
|
|
275
|
-
children: ["$", e.grossPay.toLocaleString()]
|
|
276
|
-
}),
|
|
277
|
-
/* @__PURE__ */ h("span", {
|
|
278
|
-
className: "text-right text-status-error-text",
|
|
279
|
-
children: ["-$", e.deductions.toLocaleString()]
|
|
280
|
-
}),
|
|
281
|
-
/* @__PURE__ */ h("span", {
|
|
282
|
-
className: "text-right font-medium",
|
|
283
|
-
children: ["$", e.netPay.toLocaleString()]
|
|
284
|
-
}),
|
|
285
|
-
/* @__PURE__ */ m("span", {
|
|
286
|
-
className: "text-text-secondary",
|
|
287
|
-
children: e.paymentMethod
|
|
288
|
-
}),
|
|
289
|
-
/* @__PURE__ */ h("div", {
|
|
290
|
-
className: "flex flex-col items-center gap-1",
|
|
291
|
-
children: [/* @__PURE__ */ m(g, {
|
|
292
|
-
variant: e.status === "paid" ? "default" : e.status === "processing" ? "secondary" : "outline",
|
|
293
|
-
className: "text-[10px]",
|
|
294
|
-
children: e.status
|
|
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
|
-
})]
|
|
311
|
+
/* @__PURE__ */ g(y, { children: [/* @__PURE__ */ g(S, { children: [/* @__PURE__ */ h(C, { children: "Payroll Records" }), /* @__PURE__ */ g(x, { children: ["Individual employee payroll details for ", R] })] }), /* @__PURE__ */ g(b, {
|
|
312
|
+
className: "space-y-4",
|
|
313
|
+
children: [
|
|
314
|
+
/* @__PURE__ */ h(O, {
|
|
315
|
+
data: $,
|
|
316
|
+
rowKey: (e) => e.id,
|
|
317
|
+
columns: ne,
|
|
318
|
+
emptyState: /* @__PURE__ */ g("p", {
|
|
319
|
+
className: "py-6 text-center text-sm text-text-secondary",
|
|
320
|
+
children: [
|
|
321
|
+
"No payroll records for ",
|
|
322
|
+
R,
|
|
323
|
+
"."
|
|
324
|
+
]
|
|
302
325
|
})
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
326
|
+
}),
|
|
327
|
+
q.length > H && /* @__PURE__ */ h(D, {
|
|
328
|
+
page: V,
|
|
329
|
+
pageSize: H,
|
|
330
|
+
totalItems: q.length,
|
|
331
|
+
onPageChange: W
|
|
332
|
+
}),
|
|
333
|
+
q.length > 0 && /* @__PURE__ */ g(m, { children: [/* @__PURE__ */ h(k, {}), /* @__PURE__ */ g("div", {
|
|
334
|
+
className: "flex flex-wrap items-center justify-between gap-4 text-sm font-semibold",
|
|
335
|
+
children: [/* @__PURE__ */ g("span", { children: ["Total for ", R] }), /* @__PURE__ */ g("div", {
|
|
336
|
+
className: "flex flex-wrap gap-x-6 gap-y-1",
|
|
337
|
+
children: [
|
|
338
|
+
/* @__PURE__ */ g("span", { children: [
|
|
339
|
+
/* @__PURE__ */ h("span", {
|
|
340
|
+
className: "text-text-secondary",
|
|
341
|
+
children: "Gross "
|
|
342
|
+
}),
|
|
343
|
+
"$",
|
|
344
|
+
J.toLocaleString()
|
|
345
|
+
] }),
|
|
346
|
+
/* @__PURE__ */ g("span", {
|
|
347
|
+
className: "text-status-error-text",
|
|
348
|
+
children: [
|
|
349
|
+
/* @__PURE__ */ h("span", {
|
|
350
|
+
className: "text-text-secondary",
|
|
351
|
+
children: "Deductions "
|
|
352
|
+
}),
|
|
353
|
+
"-$",
|
|
354
|
+
X.toLocaleString()
|
|
355
|
+
]
|
|
356
|
+
}),
|
|
357
|
+
/* @__PURE__ */ g("span", { children: [
|
|
358
|
+
/* @__PURE__ */ h("span", {
|
|
359
|
+
className: "text-text-secondary",
|
|
360
|
+
children: "Net "
|
|
361
|
+
}),
|
|
362
|
+
"$",
|
|
363
|
+
Y.toLocaleString()
|
|
364
|
+
] })
|
|
365
|
+
]
|
|
366
|
+
})]
|
|
367
|
+
})] })
|
|
368
|
+
]
|
|
369
|
+
})] }),
|
|
370
|
+
/* @__PURE__ */ h(t, {
|
|
371
|
+
open: B.open,
|
|
372
|
+
onOpenChange: B.onOpenChange,
|
|
331
373
|
title: "Add payroll record",
|
|
332
374
|
description: "Create a payroll entry for a team member.",
|
|
333
|
-
fields:
|
|
375
|
+
fields: K,
|
|
334
376
|
submitLabel: "Add record",
|
|
335
|
-
onSubmit:
|
|
377
|
+
onSubmit: re
|
|
336
378
|
})
|
|
337
379
|
]
|
|
338
380
|
});
|
|
339
381
|
}
|
|
340
382
|
//#endregion
|
|
341
|
-
export {
|
|
383
|
+
export { N as HrPayrollPagePage };
|
|
342
384
|
|
|
343
385
|
//# sourceMappingURL=HrPayrollPagePage.js.map
|
|
@@ -1 +1 @@
|
|
|
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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"}
|
|
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 Pagination,\n ResponsiveTable,\n Separator,\n type ResponsiveTableColumn,\n} from '@burdenoff/fe-libs/ui';\nimport { usePagination } from '@burdenoff/fe-libs/shared/hooks';\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 const { page, pageSize, offset, setPage } = usePagination({ initialPageSize: 10 });\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 totalDeductions = periodRecords.reduce((s, r) => s + r.deductions, 0);\n const paidCount = periodRecords.filter((r) => r.status === 'paid').length;\n const processingCount = periodRecords.filter((r) => r.status === 'processing').length;\n const recordPageItems = periodRecords.slice(offset, offset + pageSize);\n\n const periods = [...new Set(payrollRecords.map((r) => r.period))];\n\n const handlePeriodChange = (period: string) => {\n setSelectedPeriod(period);\n setPage(1);\n };\n\n const recordColumns: ResponsiveTableColumn<PayrollRecord>[] = [\n {\n key: 'employee',\n header: 'Employee',\n priority: 'primary',\n cell: (record) => <span className=\"font-medium\">{record.employeeName}</span>,\n },\n {\n key: 'department',\n header: 'Department',\n cell: (record) => <span className=\"text-text-secondary\">{record.department}</span>,\n },\n {\n key: 'gross',\n header: 'Gross Pay',\n headerClassName: 'text-right',\n cellClassName: 'md:text-right',\n cell: (record) => <span>${record.grossPay.toLocaleString()}</span>,\n },\n {\n key: 'deductions',\n header: 'Deductions',\n headerClassName: 'text-right',\n cellClassName: 'md:text-right',\n cell: (record) => (\n <span className=\"text-status-error-text\">-${record.deductions.toLocaleString()}</span>\n ),\n },\n {\n key: 'net',\n header: 'Net Pay',\n headerClassName: 'text-right',\n cellClassName: 'md:text-right',\n cell: (record) => <span className=\"font-medium\">${record.netPay.toLocaleString()}</span>,\n },\n {\n key: 'method',\n header: 'Payment Method',\n cell: (record) => <span className=\"text-text-secondary\">{record.paymentMethod}</span>,\n },\n {\n key: 'status',\n header: 'Status',\n cell: (record) => (\n <div className=\"flex items-center gap-2\">\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 ),\n },\n ];\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 flex-wrap gap-2\">\n {periods.map((period) => (\n <Button\n key={period}\n variant={selectedPeriod === period ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => handlePeriodChange(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 className=\"space-y-4\">\n <ResponsiveTable<PayrollRecord>\n data={recordPageItems}\n rowKey={(record) => record.id}\n columns={recordColumns}\n emptyState={\n <p className=\"py-6 text-center text-sm text-text-secondary\">\n No payroll records for {selectedPeriod}.\n </p>\n }\n />\n {periodRecords.length > pageSize && (\n <Pagination\n page={page}\n pageSize={pageSize}\n totalItems={periodRecords.length}\n onPageChange={setPage}\n />\n )}\n {periodRecords.length > 0 && (\n <>\n <Separator />\n <div className=\"flex flex-wrap items-center justify-between gap-4 text-sm font-semibold\">\n <span>Total for {selectedPeriod}</span>\n <div className=\"flex flex-wrap gap-x-6 gap-y-1\">\n <span>\n <span className=\"text-text-secondary\">Gross </span>${totalGross.toLocaleString()}\n </span>\n <span className=\"text-status-error-text\">\n <span className=\"text-text-secondary\">Deductions </span>-$\n {totalDeductions.toLocaleString()}\n </span>\n <span>\n <span className=\"text-text-secondary\">Net </span>${totalNet.toLocaleString()}\n </span>\n </div>\n </div>\n </>\n )}\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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"}
|