@burdenoff/microfe-crewfoundry 2026.704.6 → 2026.704.7
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/CrewFoundryRoutes.js +51 -43
- package/dist/crewfoundry/CrewFoundryRoutes.js.map +1 -1
- package/dist/crewfoundry/components/forms/formValues.js +5 -2
- package/dist/crewfoundry/components/forms/formValues.js.map +1 -1
- package/dist/crewfoundry/components/viz/AllocationBar.js +68 -0
- package/dist/crewfoundry/components/viz/AllocationBar.js.map +1 -0
- package/dist/crewfoundry/components/viz/AreaChart.js +102 -0
- package/dist/crewfoundry/components/viz/AreaChart.js.map +1 -0
- package/dist/crewfoundry/components/viz/AvatarStack.js +36 -0
- package/dist/crewfoundry/components/viz/AvatarStack.js.map +1 -0
- package/dist/crewfoundry/components/viz/BarChart.js +83 -0
- package/dist/crewfoundry/components/viz/BarChart.js.map +1 -0
- package/dist/crewfoundry/components/viz/CertificateCard.js +118 -0
- package/dist/crewfoundry/components/viz/CertificateCard.js.map +1 -0
- package/dist/crewfoundry/components/viz/DonutChart.js +109 -0
- package/dist/crewfoundry/components/viz/DonutChart.js.map +1 -0
- package/dist/crewfoundry/components/viz/HBarFunnel.js +54 -0
- package/dist/crewfoundry/components/viz/HBarFunnel.js.map +1 -0
- package/dist/crewfoundry/components/viz/Heatmap.js +91 -0
- package/dist/crewfoundry/components/viz/Heatmap.js.map +1 -0
- package/dist/crewfoundry/components/viz/KanbanBoard.js +50 -0
- package/dist/crewfoundry/components/viz/KanbanBoard.js.map +1 -0
- package/dist/crewfoundry/components/viz/LineChart.js +123 -0
- package/dist/crewfoundry/components/viz/LineChart.js.map +1 -0
- package/dist/crewfoundry/components/viz/OrgTree.js +83 -0
- package/dist/crewfoundry/components/viz/OrgTree.js.map +1 -0
- package/dist/crewfoundry/components/viz/PathSteps.js +68 -0
- package/dist/crewfoundry/components/viz/PathSteps.js.map +1 -0
- package/dist/crewfoundry/components/viz/ProgressRing.js +68 -0
- package/dist/crewfoundry/components/viz/ProgressRing.js.map +1 -0
- package/dist/crewfoundry/components/viz/RatingStars.js +51 -0
- package/dist/crewfoundry/components/viz/RatingStars.js.map +1 -0
- package/dist/crewfoundry/components/viz/SegmentedTabs.js +69 -0
- package/dist/crewfoundry/components/viz/SegmentedTabs.js.map +1 -0
- package/dist/crewfoundry/components/viz/SkillBar.js +3 -0
- package/dist/crewfoundry/components/viz/Sparkline.js +74 -0
- package/dist/crewfoundry/components/viz/Sparkline.js.map +1 -0
- package/dist/crewfoundry/components/viz/StatCard.js +60 -0
- package/dist/crewfoundry/components/viz/StatCard.js.map +1 -0
- package/dist/crewfoundry/components/viz/StepProgress.js +3 -0
- package/dist/crewfoundry/components/viz/Timeline.js +66 -0
- package/dist/crewfoundry/components/viz/Timeline.js.map +1 -0
- package/dist/crewfoundry/components/viz/index.js +23 -0
- package/dist/crewfoundry/components/viz/lib/Avatar.js +30 -0
- package/dist/crewfoundry/components/viz/lib/Avatar.js.map +1 -0
- package/dist/crewfoundry/components/viz/lib/CartesianFrame.js +119 -0
- package/dist/crewfoundry/components/viz/lib/CartesianFrame.js.map +1 -0
- package/dist/crewfoundry/components/viz/lib/ResponsiveSvg.js +35 -0
- package/dist/crewfoundry/components/viz/lib/ResponsiveSvg.js.map +1 -0
- package/dist/crewfoundry/components/viz/lib/format.js +21 -0
- package/dist/crewfoundry/components/viz/lib/format.js.map +1 -0
- package/dist/crewfoundry/components/viz/lib/geometry.js +69 -0
- package/dist/crewfoundry/components/viz/lib/geometry.js.map +1 -0
- package/dist/crewfoundry/components/viz/lib/hooks.js +39 -0
- package/dist/crewfoundry/components/viz/lib/hooks.js.map +1 -0
- package/dist/crewfoundry/components/viz/lib/palette.js +27 -0
- package/dist/crewfoundry/components/viz/lib/palette.js.map +1 -0
- package/dist/crewfoundry/lib/analytics.js +323 -0
- package/dist/crewfoundry/lib/analytics.js.map +1 -0
- package/dist/crewfoundry/lib/companyFinance.js +16 -0
- package/dist/crewfoundry/lib/companyFinance.js.map +1 -0
- package/dist/crewfoundry/pages/AnalyticsAnalyticsPagePage.js +226 -283
- package/dist/crewfoundry/pages/AnalyticsAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/AnalyticsEmployeeAnalyticsPagePage.js +107 -120
- package/dist/crewfoundry/pages/AnalyticsEmployeeAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js +122 -162
- package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.js +121 -158
- package/dist/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js +316 -211
- package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js +75 -27
- package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js +167 -165
- package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js +168 -109
- package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/DashboardDashboardPagePage.js +401 -290
- package/dist/crewfoundry/pages/DashboardDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringApplicationsPagePage.js +84 -75
- package/dist/crewfoundry/pages/HiringApplicationsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringCandidatesPagePage.js +368 -174
- package/dist/crewfoundry/pages/HiringCandidatesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringCreateJobPagePage.js +236 -201
- package/dist/crewfoundry/pages/HiringCreateJobPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringInterviewsPagePage.js +369 -196
- package/dist/crewfoundry/pages/HiringInterviewsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js +269 -270
- package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringJobsPagePage.js +210 -110
- package/dist/crewfoundry/pages/HiringJobsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrDepartmentsPagePage.js +216 -178
- package/dist/crewfoundry/pages/HrDepartmentsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrEmployeeProfilePagePage.js +385 -0
- package/dist/crewfoundry/pages/HrEmployeeProfilePagePage.js.map +1 -0
- package/dist/crewfoundry/pages/HrEmployeesPagePage.js +189 -130
- package/dist/crewfoundry/pages/HrEmployeesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js +397 -241
- package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrPayrollPagePage.js +262 -147
- package/dist/crewfoundry/pages/HrPayrollPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js +345 -167
- package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCertificatesPagePage.js +98 -24
- package/dist/crewfoundry/pages/LearningCertificatesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js +1 -1
- package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js +289 -108
- package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCoursesPagePage.js +221 -114
- package/dist/crewfoundry/pages/LearningCoursesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js +134 -135
- package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js +148 -97
- package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningMyLearningPagePage.js +264 -157
- package/dist/crewfoundry/pages/LearningMyLearningPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js +85 -93
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js +211 -122
- package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js +94 -54
- package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js +289 -140
- package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js +169 -79
- package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js +296 -125
- package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/ProjectsResourcingPagePage.js +187 -0
- package/dist/crewfoundry/pages/ProjectsResourcingPagePage.js.map +1 -0
- package/dist/crewfoundry/pages/TeamsTeamDetailPagePage.js +140 -78
- package/dist/crewfoundry/pages/TeamsTeamDetailPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamDirectoryPagePage.js +93 -43
- package/dist/crewfoundry/pages/TeamsTeamDirectoryPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamsPagePage.js +250 -98
- package/dist/crewfoundry/pages/TeamsTeamsPagePage.js.map +1 -1
- package/dist/crewfoundry/store/crewfoundryStore.js +1 -1
- package/dist/crewfoundry/store/crewfoundryStore.js.map +1 -1
- package/dist/crewfoundry/utils/cn.js +10 -0
- package/dist/crewfoundry/utils/cn.js.map +1 -0
- package/dist/crewfoundry/utils/courseProgress.js +46 -0
- package/dist/crewfoundry/utils/courseProgress.js.map +1 -0
- package/dist/node_modules/clsx/dist/clsx.js +18 -0
- package/dist/node_modules/clsx/dist/clsx.js.map +1 -0
- package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js +1716 -0
- package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js.map +1 -0
- package/package.json +1 -1
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import { useCrewFoundryStore as e } from "../store/crewfoundryStore.js";
|
|
2
2
|
import { formatEnumLabel as t } from "../utils/formatEnumLabel.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
3
|
+
import { AreaChart as n } from "../components/viz/AreaChart.js";
|
|
4
|
+
import { StatCard as r } from "../components/viz/StatCard.js";
|
|
5
|
+
import "../components/viz/index.js";
|
|
6
|
+
import { revenueTrend as i } from "../lib/analytics.js";
|
|
7
|
+
import { FormModal as ee, useFormModal as a } from "../components/forms/FormModal.js";
|
|
8
|
+
import { useState as o } from "react";
|
|
9
|
+
import { CheckCircle2 as s, MoreHorizontal as c, Pencil as l, Plus as u, Trash2 as d } from "lucide-react";
|
|
10
|
+
import { jsx as f, jsxs as p } from "react/jsx-runtime";
|
|
11
|
+
import { AlertDialog as m, AlertDialogAction as te, AlertDialogCancel as ne, AlertDialogContent as re, AlertDialogDescription as h, AlertDialogFooter as g, AlertDialogHeader as _, AlertDialogTitle as v, Badge as ie, Button as y, CardContent as ae, CardHeader as oe, CardTitle as b, DropdownMenu as x, DropdownMenuContent as S, DropdownMenuItem as C, DropdownMenuSeparator as w, DropdownMenuTrigger as T, GlassCard as E, GradientText as D, IllustratedEmptyState as O, PagePurpose as k, Pagination as A, ResponsiveTable as j } from "@burdenoff/fe-libs/ui";
|
|
12
|
+
import { usePagination as M } from "@burdenoff/fe-libs/shared/hooks";
|
|
8
13
|
//#region src/crewfoundry/pages/PaymentsInvoicesPagePage.tsx
|
|
9
|
-
var
|
|
14
|
+
var N = [
|
|
10
15
|
{
|
|
11
16
|
name: "number",
|
|
12
17
|
label: "Invoice number",
|
|
@@ -71,7 +76,7 @@ var y = [
|
|
|
71
76
|
colSpan: 2,
|
|
72
77
|
placeholder: "e.g. Consulting services"
|
|
73
78
|
}
|
|
74
|
-
],
|
|
79
|
+
], P = (e) => ({
|
|
75
80
|
number: e.number,
|
|
76
81
|
clientName: e.clientName,
|
|
77
82
|
amount: e.amount,
|
|
@@ -79,7 +84,7 @@ var y = [
|
|
|
79
84
|
issueDate: e.issueDate ? e.issueDate.slice(0, 10) : "",
|
|
80
85
|
dueDate: e.dueDate ? e.dueDate.slice(0, 10) : "",
|
|
81
86
|
lineItem: e.items[0]?.description ?? ""
|
|
82
|
-
}),
|
|
87
|
+
}), F = (e, t) => {
|
|
83
88
|
let n = typeof e.amount == "number" ? e.amount : Number(e.amount) || 0, r = String(e.lineItem ?? "").trim() || "Services rendered";
|
|
84
89
|
return {
|
|
85
90
|
id: t?.id ?? crypto.randomUUID(),
|
|
@@ -94,48 +99,98 @@ var y = [
|
|
|
94
99
|
amount: n
|
|
95
100
|
}]
|
|
96
101
|
};
|
|
97
|
-
},
|
|
98
|
-
function
|
|
99
|
-
let { invoices:
|
|
100
|
-
|
|
102
|
+
}, I = (e) => e === "paid" ? "default" : e === "overdue" ? "destructive" : e === "draft" ? "outline" : "secondary", L = (e) => `$${Math.round(e).toLocaleString()}`;
|
|
103
|
+
function R() {
|
|
104
|
+
let { invoices: R, addInvoice: se, updateInvoice: z, removeInvoice: B } = e(), V = a(), { page: H, pageSize: U, offset: W, setPage: G } = M({ initialPageSize: 25 }), [K, q] = o(null), [J, Y] = o(!1), X = [...R].sort((e, t) => (t.issueDate ?? "").localeCompare(e.issueDate ?? "")), ce = X.slice(W, W + U), Z = R.filter((e) => e.status !== "cancelled").reduce((e, t) => e + t.amount, 0), Q = R.filter((e) => e.status === "paid").reduce((e, t) => e + t.amount, 0), le = R.filter((e) => e.status === "overdue").reduce((e, t) => e + t.amount, 0), ue = Math.max(Z - Q, 0), $ = i(R), de = async (e) => {
|
|
105
|
+
V.context ? await z(V.context.id, F(e, V.context)) : await se(F(e));
|
|
106
|
+
}, fe = async () => {
|
|
107
|
+
if (K) {
|
|
108
|
+
Y(!0);
|
|
109
|
+
try {
|
|
110
|
+
await B(K.id), q(null);
|
|
111
|
+
} finally {
|
|
112
|
+
Y(!1);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
return /* @__PURE__ */ p("div", {
|
|
101
117
|
className: "space-y-6 p-6",
|
|
102
118
|
children: [
|
|
103
|
-
/* @__PURE__ */
|
|
119
|
+
/* @__PURE__ */ p("div", {
|
|
104
120
|
className: "flex items-center justify-between",
|
|
105
|
-
children: [/* @__PURE__ */
|
|
106
|
-
/* @__PURE__ */
|
|
121
|
+
children: [/* @__PURE__ */ p("div", { children: [
|
|
122
|
+
/* @__PURE__ */ f("h1", {
|
|
107
123
|
className: "text-2xl font-semibold",
|
|
108
|
-
children: /* @__PURE__ */
|
|
124
|
+
children: /* @__PURE__ */ f(D, { children: "Invoices" })
|
|
109
125
|
}),
|
|
110
|
-
/* @__PURE__ */
|
|
126
|
+
/* @__PURE__ */ p("p", {
|
|
111
127
|
className: "text-sm text-text-secondary",
|
|
112
|
-
children: [
|
|
128
|
+
children: [R.length, " invoices"]
|
|
113
129
|
}),
|
|
114
|
-
/* @__PURE__ */
|
|
130
|
+
/* @__PURE__ */ f(k, {
|
|
115
131
|
className: "mt-1",
|
|
116
132
|
children: "Create, send, and track invoices — see what's paid, pending, or overdue so you stay on top of getting paid."
|
|
117
133
|
})
|
|
118
|
-
] }), /* @__PURE__ */
|
|
134
|
+
] }), /* @__PURE__ */ p(y, {
|
|
119
135
|
size: "sm",
|
|
120
|
-
onClick: () =>
|
|
121
|
-
children: [/* @__PURE__ */
|
|
136
|
+
onClick: () => V.openModal(),
|
|
137
|
+
children: [/* @__PURE__ */ f(u, { className: "h-4 w-4 mr-1" }), "Create Invoice"]
|
|
122
138
|
})]
|
|
123
139
|
}),
|
|
124
|
-
/* @__PURE__ */
|
|
140
|
+
/* @__PURE__ */ p("div", {
|
|
141
|
+
className: "grid gap-4 sm:grid-cols-2 xl:grid-cols-5",
|
|
142
|
+
children: [
|
|
143
|
+
/* @__PURE__ */ f(r, {
|
|
144
|
+
label: "Total Billed",
|
|
145
|
+
value: L(Z)
|
|
146
|
+
}),
|
|
147
|
+
/* @__PURE__ */ f(r, {
|
|
148
|
+
label: "Paid",
|
|
149
|
+
value: L(Q)
|
|
150
|
+
}),
|
|
151
|
+
/* @__PURE__ */ f(r, {
|
|
152
|
+
label: "Outstanding",
|
|
153
|
+
value: L(ue)
|
|
154
|
+
}),
|
|
155
|
+
/* @__PURE__ */ f(r, {
|
|
156
|
+
label: "Overdue",
|
|
157
|
+
value: /* @__PURE__ */ f("span", {
|
|
158
|
+
className: "text-status-error-text",
|
|
159
|
+
children: L(le)
|
|
160
|
+
})
|
|
161
|
+
}),
|
|
162
|
+
/* @__PURE__ */ p("div", {
|
|
163
|
+
className: "flex flex-col gap-2 rounded-[var(--radius-card)] border border-border-subtle bg-bg-surface p-5 shadow-elevation-1 sm:col-span-2 xl:col-span-1",
|
|
164
|
+
children: [/* @__PURE__ */ f("span", {
|
|
165
|
+
className: "text-sm font-medium text-text-secondary",
|
|
166
|
+
children: "Revenue trend"
|
|
167
|
+
}), $.length > 1 ? /* @__PURE__ */ f(n, {
|
|
168
|
+
series: $,
|
|
169
|
+
height: 96,
|
|
170
|
+
valueFormatter: (e) => L(e),
|
|
171
|
+
title: "Recognised revenue from paid invoices by month"
|
|
172
|
+
}) : /* @__PURE__ */ f("p", {
|
|
173
|
+
className: "flex flex-1 items-center text-xs text-text-muted",
|
|
174
|
+
children: "Revenue trend appears once paid invoices span more than one month."
|
|
175
|
+
})]
|
|
176
|
+
})
|
|
177
|
+
]
|
|
178
|
+
}),
|
|
179
|
+
/* @__PURE__ */ p(E, {
|
|
125
180
|
treatment: "glass",
|
|
126
181
|
glow: !0,
|
|
127
182
|
className: "border-border-seam",
|
|
128
|
-
children: /* @__PURE__ */
|
|
129
|
-
className: "p-4",
|
|
130
|
-
children: [/* @__PURE__ */
|
|
131
|
-
data:
|
|
183
|
+
children: [/* @__PURE__ */ f(oe, { children: /* @__PURE__ */ f(b, { children: "Invoices" }) }), /* @__PURE__ */ p(ae, {
|
|
184
|
+
className: "p-4 pt-0",
|
|
185
|
+
children: [/* @__PURE__ */ f(j, {
|
|
186
|
+
data: ce,
|
|
132
187
|
rowKey: (e) => e.id,
|
|
133
188
|
columns: [
|
|
134
189
|
{
|
|
135
190
|
key: "number",
|
|
136
191
|
header: "Invoice #",
|
|
137
192
|
priority: "primary",
|
|
138
|
-
cell: (e) => /* @__PURE__ */
|
|
193
|
+
cell: (e) => /* @__PURE__ */ f("span", {
|
|
139
194
|
className: "font-medium",
|
|
140
195
|
children: e.number
|
|
141
196
|
})
|
|
@@ -144,18 +199,27 @@ function C() {
|
|
|
144
199
|
key: "client",
|
|
145
200
|
header: "Client",
|
|
146
201
|
priority: "secondary",
|
|
147
|
-
cell: (e) => /* @__PURE__ */
|
|
202
|
+
cell: (e) => /* @__PURE__ */ f("span", {
|
|
148
203
|
className: "text-text-secondary",
|
|
149
204
|
children: e.clientName
|
|
150
205
|
})
|
|
151
206
|
},
|
|
152
207
|
{
|
|
153
|
-
key: "
|
|
154
|
-
header: "
|
|
208
|
+
key: "issueDate",
|
|
209
|
+
header: "Issue Date",
|
|
155
210
|
priority: "hidden-on-mobile",
|
|
156
|
-
cell: (e) => /* @__PURE__ */
|
|
157
|
-
className: "text-
|
|
158
|
-
children: e.
|
|
211
|
+
cell: (e) => /* @__PURE__ */ f("span", {
|
|
212
|
+
className: "text-text-secondary",
|
|
213
|
+
children: e.issueDate || "—"
|
|
214
|
+
})
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
key: "dueDate",
|
|
218
|
+
header: "Due Date",
|
|
219
|
+
priority: "secondary",
|
|
220
|
+
cell: (e) => /* @__PURE__ */ f("span", {
|
|
221
|
+
className: "text-text-secondary",
|
|
222
|
+
children: e.dueDate || "—"
|
|
159
223
|
})
|
|
160
224
|
},
|
|
161
225
|
{
|
|
@@ -164,82 +228,108 @@ function C() {
|
|
|
164
228
|
priority: "secondary",
|
|
165
229
|
headerClassName: "text-right",
|
|
166
230
|
cellClassName: "text-right",
|
|
167
|
-
cell: (e) => /* @__PURE__ */
|
|
168
|
-
className: "font-medium",
|
|
231
|
+
cell: (e) => /* @__PURE__ */ p("span", {
|
|
232
|
+
className: "font-medium tabular-nums",
|
|
169
233
|
children: ["$", e.amount.toLocaleString()]
|
|
170
234
|
})
|
|
171
235
|
},
|
|
172
|
-
{
|
|
173
|
-
key: "dueDate",
|
|
174
|
-
header: "Due Date",
|
|
175
|
-
priority: "secondary",
|
|
176
|
-
cell: (e) => /* @__PURE__ */ s("span", {
|
|
177
|
-
className: "text-text-secondary",
|
|
178
|
-
children: e.dueDate
|
|
179
|
-
})
|
|
180
|
-
},
|
|
181
236
|
{
|
|
182
237
|
key: "status",
|
|
183
238
|
header: "Status",
|
|
184
239
|
priority: "secondary",
|
|
185
|
-
cell: (e) => /* @__PURE__ */
|
|
186
|
-
variant:
|
|
240
|
+
cell: (e) => /* @__PURE__ */ f(ie, {
|
|
241
|
+
variant: I(e.status),
|
|
187
242
|
className: "text-[10px]",
|
|
188
243
|
children: t(e.status)
|
|
189
244
|
})
|
|
190
245
|
}
|
|
191
246
|
],
|
|
192
|
-
emptyState: /* @__PURE__ */
|
|
247
|
+
emptyState: /* @__PURE__ */ f(O, {
|
|
193
248
|
illustration: "empty-data",
|
|
194
249
|
title: "No invoices yet",
|
|
195
250
|
description: "Create your first invoice to start getting paid."
|
|
196
251
|
}),
|
|
197
|
-
rowActions: (e) => /* @__PURE__ */
|
|
252
|
+
rowActions: (e) => /* @__PURE__ */ p("div", {
|
|
198
253
|
className: "flex items-center justify-end gap-1",
|
|
199
|
-
children: [/* @__PURE__ */
|
|
200
|
-
variant: "ghost",
|
|
201
|
-
size: "sm",
|
|
202
|
-
"aria-label": `Edit invoice ${e.number}`,
|
|
203
|
-
onClick: () => E.openModal(e),
|
|
204
|
-
children: /* @__PURE__ */ s(a, { className: "h-3.5 w-3.5" })
|
|
205
|
-
}), e.status === "paid" ? /* @__PURE__ */ c("span", {
|
|
254
|
+
children: [e.status === "paid" ? /* @__PURE__ */ p("span", {
|
|
206
255
|
className: "inline-flex items-center gap-1 text-xs text-status-success-text",
|
|
207
|
-
children: [/* @__PURE__ */ s
|
|
208
|
-
}) : /* @__PURE__ */
|
|
256
|
+
children: [/* @__PURE__ */ f(s, { className: "h-3.5 w-3.5" }), "Paid"]
|
|
257
|
+
}) : /* @__PURE__ */ p(y, {
|
|
209
258
|
variant: "outline",
|
|
210
259
|
size: "sm",
|
|
211
260
|
"aria-label": `Mark invoice ${e.number} as paid`,
|
|
212
|
-
onClick: () => void
|
|
213
|
-
children: [/* @__PURE__ */ s
|
|
214
|
-
})
|
|
261
|
+
onClick: () => void z(e.id, { status: "paid" }),
|
|
262
|
+
children: [/* @__PURE__ */ f(s, { className: "h-3.5 w-3.5 mr-1" }), "Mark Paid"]
|
|
263
|
+
}), /* @__PURE__ */ p(x, { children: [/* @__PURE__ */ f(T, {
|
|
264
|
+
asChild: !0,
|
|
265
|
+
children: /* @__PURE__ */ f(y, {
|
|
266
|
+
variant: "ghost",
|
|
267
|
+
size: "icon",
|
|
268
|
+
className: "h-8 w-8",
|
|
269
|
+
"aria-label": `More actions for invoice ${e.number}`,
|
|
270
|
+
children: /* @__PURE__ */ f(c, { className: "h-4 w-4" })
|
|
271
|
+
})
|
|
272
|
+
}), /* @__PURE__ */ p(S, {
|
|
273
|
+
align: "end",
|
|
274
|
+
children: [
|
|
275
|
+
/* @__PURE__ */ p(C, {
|
|
276
|
+
onSelect: () => V.openModal(e),
|
|
277
|
+
children: [/* @__PURE__ */ f(l, { className: "mr-2 h-4 w-4" }), "Edit"]
|
|
278
|
+
}),
|
|
279
|
+
e.status !== "paid" && /* @__PURE__ */ p(C, {
|
|
280
|
+
onSelect: () => void z(e.id, { status: "paid" }),
|
|
281
|
+
children: [/* @__PURE__ */ f(s, { className: "mr-2 h-4 w-4" }), "Mark as paid"]
|
|
282
|
+
}),
|
|
283
|
+
/* @__PURE__ */ f(w, {}),
|
|
284
|
+
/* @__PURE__ */ p(C, {
|
|
285
|
+
className: "text-status-error-text",
|
|
286
|
+
onSelect: () => q(e),
|
|
287
|
+
children: [/* @__PURE__ */ f(d, { className: "mr-2 h-4 w-4" }), "Delete"]
|
|
288
|
+
})
|
|
289
|
+
]
|
|
290
|
+
})] })]
|
|
215
291
|
})
|
|
216
|
-
}),
|
|
292
|
+
}), X.length > U && /* @__PURE__ */ f("div", {
|
|
217
293
|
className: "mt-4",
|
|
218
|
-
children: /* @__PURE__ */
|
|
219
|
-
page:
|
|
220
|
-
pageSize:
|
|
221
|
-
totalItems:
|
|
222
|
-
onPageChange:
|
|
294
|
+
children: /* @__PURE__ */ f(A, {
|
|
295
|
+
page: H,
|
|
296
|
+
pageSize: U,
|
|
297
|
+
totalItems: X.length,
|
|
298
|
+
onPageChange: G
|
|
223
299
|
})
|
|
224
300
|
})]
|
|
225
|
-
})
|
|
301
|
+
})]
|
|
226
302
|
}),
|
|
227
|
-
/* @__PURE__ */
|
|
228
|
-
open:
|
|
229
|
-
onOpenChange:
|
|
230
|
-
title:
|
|
303
|
+
/* @__PURE__ */ f(ee, {
|
|
304
|
+
open: V.open,
|
|
305
|
+
onOpenChange: V.onOpenChange,
|
|
306
|
+
title: V.context ? "Edit invoice" : "Create invoice",
|
|
231
307
|
description: "Issue a new invoice to a client and track its payment status.",
|
|
232
|
-
fields:
|
|
233
|
-
initialValues:
|
|
234
|
-
submitLabel:
|
|
235
|
-
onSubmit:
|
|
236
|
-
|
|
237
|
-
|
|
308
|
+
fields: N,
|
|
309
|
+
initialValues: V.context ? P(V.context) : void 0,
|
|
310
|
+
submitLabel: V.context ? "Save changes" : "Create invoice",
|
|
311
|
+
onSubmit: de
|
|
312
|
+
}),
|
|
313
|
+
/* @__PURE__ */ f(m, {
|
|
314
|
+
open: K !== null,
|
|
315
|
+
onOpenChange: (e) => {
|
|
316
|
+
e || q(null);
|
|
317
|
+
},
|
|
318
|
+
children: /* @__PURE__ */ p(re, { children: [/* @__PURE__ */ p(_, { children: [/* @__PURE__ */ f(v, { children: "Delete invoice?" }), /* @__PURE__ */ f(h, { children: K ? `Invoice ${K.number} will be permanently removed. This cannot be undone.` : "" })] }), /* @__PURE__ */ p(g, { children: [/* @__PURE__ */ f(ne, {
|
|
319
|
+
disabled: J,
|
|
320
|
+
children: "Cancel"
|
|
321
|
+
}), /* @__PURE__ */ f(te, {
|
|
322
|
+
onClick: (e) => {
|
|
323
|
+
e.preventDefault(), fe();
|
|
324
|
+
},
|
|
325
|
+
disabled: J,
|
|
326
|
+
children: J ? "Deleting…" : "Delete"
|
|
327
|
+
})] })] })
|
|
238
328
|
})
|
|
239
329
|
]
|
|
240
330
|
});
|
|
241
331
|
}
|
|
242
332
|
//#endregion
|
|
243
|
-
export {
|
|
333
|
+
export { R as PaymentsInvoicesPagePage };
|
|
244
334
|
|
|
245
335
|
//# sourceMappingURL=PaymentsInvoicesPagePage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PaymentsInvoicesPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/PaymentsInvoicesPagePage.tsx"],"sourcesContent":["import {\n Badge,\n Button,\n CardContent,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n PagePurpose,\n Pagination,\n ResponsiveTable,\n type ResponsiveTableColumn,\n} from '@burdenoff/fe-libs/ui';\nimport { usePagination } from '@burdenoff/fe-libs/shared/hooks';\nimport { CheckCircle2, Pencil, Plus } from 'lucide-react';\nimport {\n FormModal,\n useFormModal,\n type FieldConfig,\n type FormValues,\n} from '../components/forms/FormModal';\nimport { useCrewFoundryStore, type Invoice } from '../store/crewfoundryStore';\nimport { formatEnumLabel } from '../utils/formatEnumLabel';\n\nconst INVOICE_FIELDS: FieldConfig[] = [\n {\n name: 'number',\n label: 'Invoice number',\n type: 'text',\n required: true,\n placeholder: 'INV-0001',\n },\n { name: 'clientName', label: 'Client name', type: 'text', required: true },\n { name: 'amount', label: 'Amount (USD)', type: 'number', required: true },\n {\n name: 'status',\n label: 'Status',\n type: 'select',\n options: [\n { label: 'Draft', value: 'draft' },\n { label: 'Sent', value: 'sent' },\n { label: 'Paid', value: 'paid' },\n { label: 'Overdue', value: 'overdue' },\n { label: 'Cancelled', value: 'cancelled' },\n ],\n },\n { name: 'issueDate', label: 'Issue date', type: 'date', required: true },\n { name: 'dueDate', label: 'Due date', type: 'date' },\n {\n name: 'lineItem',\n label: 'Line item description',\n type: 'text',\n colSpan: 2,\n placeholder: 'e.g. Consulting services',\n },\n];\n\nconst toInitialValues = (invoice: Invoice): FormValues => ({\n number: invoice.number,\n clientName: invoice.clientName,\n amount: invoice.amount,\n status: invoice.status,\n issueDate: invoice.issueDate ? invoice.issueDate.slice(0, 10) : '',\n dueDate: invoice.dueDate ? invoice.dueDate.slice(0, 10) : '',\n lineItem: invoice.items[0]?.description ?? '',\n});\n\nconst valuesToInvoice = (values: FormValues, base?: Invoice): Invoice => {\n const amount = typeof values.amount === 'number' ? values.amount : Number(values.amount) || 0;\n const description = String(values.lineItem ?? '').trim() || 'Services rendered';\n return {\n id: base?.id ?? crypto.randomUUID(),\n number: String(values.number ?? ''),\n clientName: String(values.clientName ?? ''),\n amount,\n status: (values.status as Invoice['status']) || 'draft',\n issueDate: String(values.issueDate ?? ''),\n dueDate: String(values.dueDate ?? ''),\n items: [{ description, amount }],\n };\n};\n\nconst statusVariant = (status: Invoice['status']) =>\n status === 'paid'\n ? 'default'\n : status === 'overdue'\n ? 'destructive'\n : status === 'draft'\n ? 'outline'\n : 'secondary';\n\nexport function PaymentsInvoicesPagePage() {\n const { invoices, addInvoice, updateInvoice } = useCrewFoundryStore();\n const modal = useFormModal<Invoice>();\n const { page, pageSize, offset, setPage } = usePagination({ initialPageSize: 25 });\n\n const sorted = [...invoices].sort((a, b) => (b.issueDate ?? '').localeCompare(a.issueDate ?? ''));\n const paged = sorted.slice(offset, offset + pageSize);\n\n const handleSubmit = async (values: FormValues) => {\n if (modal.context) {\n await updateInvoice(modal.context.id, valuesToInvoice(values, modal.context));\n } else {\n await addInvoice(valuesToInvoice(values));\n }\n };\n\n const columns: ResponsiveTableColumn<Invoice>[] = [\n {\n key: 'number',\n header: 'Invoice #',\n priority: 'primary',\n cell: (inv) => <span className=\"font-medium\">{inv.number}</span>,\n },\n {\n key: 'client',\n header: 'Client',\n priority: 'secondary',\n cell: (inv) => <span className=\"text-text-secondary\">{inv.clientName}</span>,\n },\n {\n key: 'items',\n header: 'Items',\n priority: 'hidden-on-mobile',\n cell: (inv) => (\n <span className=\"text-xs text-text-secondary\">\n {inv.items.map((i) => i.description).join(', ')}\n </span>\n ),\n },\n {\n key: 'amount',\n header: 'Amount',\n priority: 'secondary',\n headerClassName: 'text-right',\n cellClassName: 'text-right',\n cell: (inv) => <span className=\"font-medium\">${inv.amount.toLocaleString()}</span>,\n },\n {\n key: 'dueDate',\n header: 'Due Date',\n priority: 'secondary',\n cell: (inv) => <span className=\"text-text-secondary\">{inv.dueDate}</span>,\n },\n {\n key: 'status',\n header: 'Status',\n priority: 'secondary',\n cell: (inv) => (\n <Badge variant={statusVariant(inv.status)} className=\"text-[10px]\">\n {formatEnumLabel(inv.status)}\n </Badge>\n ),\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>Invoices</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">{invoices.length} invoices</p>\n <PagePurpose className=\"mt-1\">\n Create, send, and track invoices — see what's paid, pending, or overdue so you stay\n on top of getting paid.\n </PagePurpose>\n </div>\n <Button size=\"sm\" onClick={() => modal.openModal()}>\n <Plus className=\"h-4 w-4 mr-1\" />\n Create Invoice\n </Button>\n </div>\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam\">\n <CardContent className=\"p-4\">\n <ResponsiveTable\n data={paged}\n rowKey={(inv) => inv.id}\n columns={columns}\n emptyState={\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No invoices yet\"\n description=\"Create your first invoice to start getting paid.\"\n />\n }\n rowActions={(inv) => (\n <div className=\"flex items-center justify-end gap-1\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n aria-label={`Edit invoice ${inv.number}`}\n onClick={() => modal.openModal(inv)}\n >\n <Pencil className=\"h-3.5 w-3.5\" />\n </Button>\n {inv.status === 'paid' ? (\n <span className=\"inline-flex items-center gap-1 text-xs text-status-success-text\">\n <CheckCircle2 className=\"h-3.5 w-3.5\" />\n Paid\n </span>\n ) : (\n <Button\n variant=\"outline\"\n size=\"sm\"\n aria-label={`Mark invoice ${inv.number} as paid`}\n onClick={() => void updateInvoice(inv.id, { status: 'paid' })}\n >\n <CheckCircle2 className=\"h-3.5 w-3.5 mr-1\" />\n Mark Paid\n </Button>\n )}\n </div>\n )}\n />\n {sorted.length > pageSize && (\n <div className=\"mt-4\">\n <Pagination\n page={page}\n pageSize={pageSize}\n totalItems={sorted.length}\n onPageChange={setPage}\n />\n </div>\n )}\n </CardContent>\n </GlassCard>\n\n <FormModal\n open={modal.open}\n onOpenChange={modal.onOpenChange}\n title={modal.context ? 'Edit invoice' : 'Create invoice'}\n description=\"Issue a new invoice to a client and track its payment status.\"\n fields={INVOICE_FIELDS}\n initialValues={modal.context ? toInitialValues(modal.context) : undefined}\n submitLabel={modal.context ? 'Save changes' : 'Create invoice'}\n onSubmit={handleSubmit}\n />\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PaymentsInvoicesPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/PaymentsInvoicesPagePage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n Badge,\n Button,\n CardContent,\n CardHeader,\n CardTitle,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n PagePurpose,\n Pagination,\n ResponsiveTable,\n type ResponsiveTableColumn,\n} from '@burdenoff/fe-libs/ui';\nimport { usePagination } from '@burdenoff/fe-libs/shared/hooks';\nimport { CheckCircle2, MoreHorizontal, Pencil, Plus, Trash2 } from 'lucide-react';\nimport {\n FormModal,\n useFormModal,\n type FieldConfig,\n type FormValues,\n} from '../components/forms/FormModal';\nimport { useCrewFoundryStore, type Invoice } from '../store/crewfoundryStore';\nimport { formatEnumLabel } from '../utils/formatEnumLabel';\nimport { AreaChart, StatCard } from '../components/viz';\nimport { revenueTrend } from '../lib/analytics';\n\nconst INVOICE_FIELDS: FieldConfig[] = [\n {\n name: 'number',\n label: 'Invoice number',\n type: 'text',\n required: true,\n placeholder: 'INV-0001',\n },\n { name: 'clientName', label: 'Client name', type: 'text', required: true },\n { name: 'amount', label: 'Amount (USD)', type: 'number', required: true },\n {\n name: 'status',\n label: 'Status',\n type: 'select',\n options: [\n { label: 'Draft', value: 'draft' },\n { label: 'Sent', value: 'sent' },\n { label: 'Paid', value: 'paid' },\n { label: 'Overdue', value: 'overdue' },\n { label: 'Cancelled', value: 'cancelled' },\n ],\n },\n { name: 'issueDate', label: 'Issue date', type: 'date', required: true },\n { name: 'dueDate', label: 'Due date', type: 'date' },\n {\n name: 'lineItem',\n label: 'Line item description',\n type: 'text',\n colSpan: 2,\n placeholder: 'e.g. Consulting services',\n },\n];\n\nconst toInitialValues = (invoice: Invoice): FormValues => ({\n number: invoice.number,\n clientName: invoice.clientName,\n amount: invoice.amount,\n status: invoice.status,\n issueDate: invoice.issueDate ? invoice.issueDate.slice(0, 10) : '',\n dueDate: invoice.dueDate ? invoice.dueDate.slice(0, 10) : '',\n lineItem: invoice.items[0]?.description ?? '',\n});\n\nconst valuesToInvoice = (values: FormValues, base?: Invoice): Invoice => {\n const amount = typeof values.amount === 'number' ? values.amount : Number(values.amount) || 0;\n const description = String(values.lineItem ?? '').trim() || 'Services rendered';\n return {\n id: base?.id ?? crypto.randomUUID(),\n number: String(values.number ?? ''),\n clientName: String(values.clientName ?? ''),\n amount,\n status: (values.status as Invoice['status']) || 'draft',\n issueDate: String(values.issueDate ?? ''),\n dueDate: String(values.dueDate ?? ''),\n items: [{ description, amount }],\n };\n};\n\nconst statusVariant = (status: Invoice['status']) =>\n status === 'paid'\n ? 'default'\n : status === 'overdue'\n ? 'destructive'\n : status === 'draft'\n ? 'outline'\n : 'secondary';\n\nconst formatMoney = (value: number): string => `$${Math.round(value).toLocaleString()}`;\n\nexport function PaymentsInvoicesPagePage() {\n const { invoices, addInvoice, updateInvoice, removeInvoice } = useCrewFoundryStore();\n const modal = useFormModal<Invoice>();\n const { page, pageSize, offset, setPage } = usePagination({ initialPageSize: 25 });\n const [deleteTarget, setDeleteTarget] = useState<Invoice | null>(null);\n const [deleting, setDeleting] = useState(false);\n\n const sorted = [...invoices].sort((a, b) => (b.issueDate ?? '').localeCompare(a.issueDate ?? ''));\n const paged = sorted.slice(offset, offset + pageSize);\n\n // Finance KPIs — all computed from real invoice entities.\n const totalBilled = invoices\n .filter((inv) => inv.status !== 'cancelled')\n .reduce((sum, inv) => sum + inv.amount, 0);\n const totalPaid = invoices\n .filter((inv) => inv.status === 'paid')\n .reduce((sum, inv) => sum + inv.amount, 0);\n const totalOverdue = invoices\n .filter((inv) => inv.status === 'overdue')\n .reduce((sum, inv) => sum + inv.amount, 0);\n const outstanding = Math.max(totalBilled - totalPaid, 0);\n\n const revenueSeries = revenueTrend(invoices);\n\n const handleSubmit = async (values: FormValues) => {\n if (modal.context) {\n await updateInvoice(modal.context.id, valuesToInvoice(values, modal.context));\n } else {\n await addInvoice(valuesToInvoice(values));\n }\n };\n\n const confirmDelete = async () => {\n if (!deleteTarget) {\n return;\n }\n setDeleting(true);\n try {\n await removeInvoice(deleteTarget.id);\n setDeleteTarget(null);\n } finally {\n setDeleting(false);\n }\n };\n\n const columns: ResponsiveTableColumn<Invoice>[] = [\n {\n key: 'number',\n header: 'Invoice #',\n priority: 'primary',\n cell: (inv) => <span className=\"font-medium\">{inv.number}</span>,\n },\n {\n key: 'client',\n header: 'Client',\n priority: 'secondary',\n cell: (inv) => <span className=\"text-text-secondary\">{inv.clientName}</span>,\n },\n {\n key: 'issueDate',\n header: 'Issue Date',\n priority: 'hidden-on-mobile',\n cell: (inv) => <span className=\"text-text-secondary\">{inv.issueDate || '—'}</span>,\n },\n {\n key: 'dueDate',\n header: 'Due Date',\n priority: 'secondary',\n cell: (inv) => <span className=\"text-text-secondary\">{inv.dueDate || '—'}</span>,\n },\n {\n key: 'amount',\n header: 'Amount',\n priority: 'secondary',\n headerClassName: 'text-right',\n cellClassName: 'text-right',\n cell: (inv) => <span className=\"font-medium tabular-nums\">${inv.amount.toLocaleString()}</span>,\n },\n {\n key: 'status',\n header: 'Status',\n priority: 'secondary',\n cell: (inv) => (\n <Badge variant={statusVariant(inv.status)} className=\"text-[10px]\">\n {formatEnumLabel(inv.status)}\n </Badge>\n ),\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>Invoices</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">{invoices.length} invoices</p>\n <PagePurpose className=\"mt-1\">\n Create, send, and track invoices — see what's paid, pending, or overdue so you stay\n on top of getting paid.\n </PagePurpose>\n </div>\n <Button size=\"sm\" onClick={() => modal.openModal()}>\n <Plus className=\"h-4 w-4 mr-1\" />\n Create Invoice\n </Button>\n </div>\n\n {/* Finance header: 4 KPI tiles + revenue-trend chart */}\n <div className=\"grid gap-4 sm:grid-cols-2 xl:grid-cols-5\">\n <StatCard label=\"Total Billed\" value={formatMoney(totalBilled)} />\n <StatCard label=\"Paid\" value={formatMoney(totalPaid)} />\n <StatCard label=\"Outstanding\" value={formatMoney(outstanding)} />\n <StatCard\n label=\"Overdue\"\n value={<span className=\"text-status-error-text\">{formatMoney(totalOverdue)}</span>}\n />\n <div className=\"flex flex-col gap-2 rounded-[var(--radius-card)] border border-border-subtle bg-bg-surface p-5 shadow-elevation-1 sm:col-span-2 xl:col-span-1\">\n <span className=\"text-sm font-medium text-text-secondary\">Revenue trend</span>\n {revenueSeries.length > 1 ? (\n <AreaChart\n series={revenueSeries}\n height={96}\n valueFormatter={(value) => formatMoney(value)}\n title=\"Recognised revenue from paid invoices by month\"\n />\n ) : (\n <p className=\"flex flex-1 items-center text-xs text-text-muted\">\n Revenue trend appears once paid invoices span more than one month.\n </p>\n )}\n </div>\n </div>\n\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam\">\n <CardHeader>\n <CardTitle>Invoices</CardTitle>\n </CardHeader>\n <CardContent className=\"p-4 pt-0\">\n <ResponsiveTable\n data={paged}\n rowKey={(inv) => inv.id}\n columns={columns}\n emptyState={\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No invoices yet\"\n description=\"Create your first invoice to start getting paid.\"\n />\n }\n rowActions={(inv) => (\n <div className=\"flex items-center justify-end gap-1\">\n {inv.status === 'paid' ? (\n <span className=\"inline-flex items-center gap-1 text-xs text-status-success-text\">\n <CheckCircle2 className=\"h-3.5 w-3.5\" />\n Paid\n </span>\n ) : (\n <Button\n variant=\"outline\"\n size=\"sm\"\n aria-label={`Mark invoice ${inv.number} as paid`}\n onClick={() => void updateInvoice(inv.id, { status: 'paid' })}\n >\n <CheckCircle2 className=\"h-3.5 w-3.5 mr-1\" />\n Mark Paid\n </Button>\n )}\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"h-8 w-8\"\n aria-label={`More actions for invoice ${inv.number}`}\n >\n <MoreHorizontal className=\"h-4 w-4\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem onSelect={() => modal.openModal(inv)}>\n <Pencil className=\"mr-2 h-4 w-4\" />\n Edit\n </DropdownMenuItem>\n {inv.status !== 'paid' && (\n <DropdownMenuItem\n onSelect={() => void updateInvoice(inv.id, { status: 'paid' })}\n >\n <CheckCircle2 className=\"mr-2 h-4 w-4\" />\n Mark as paid\n </DropdownMenuItem>\n )}\n <DropdownMenuSeparator />\n <DropdownMenuItem\n className=\"text-status-error-text\"\n onSelect={() => setDeleteTarget(inv)}\n >\n <Trash2 className=\"mr-2 h-4 w-4\" />\n Delete\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n )}\n />\n {sorted.length > pageSize && (\n <div className=\"mt-4\">\n <Pagination\n page={page}\n pageSize={pageSize}\n totalItems={sorted.length}\n onPageChange={setPage}\n />\n </div>\n )}\n </CardContent>\n </GlassCard>\n\n <FormModal\n open={modal.open}\n onOpenChange={modal.onOpenChange}\n title={modal.context ? 'Edit invoice' : 'Create invoice'}\n description=\"Issue a new invoice to a client and track its payment status.\"\n fields={INVOICE_FIELDS}\n initialValues={modal.context ? toInitialValues(modal.context) : undefined}\n submitLabel={modal.context ? 'Save changes' : 'Create invoice'}\n onSubmit={handleSubmit}\n />\n\n <AlertDialog\n open={deleteTarget !== null}\n onOpenChange={(open) => {\n if (!open) {\n setDeleteTarget(null);\n }\n }}\n >\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>Delete invoice?</AlertDialogTitle>\n <AlertDialogDescription>\n {deleteTarget\n ? `Invoice ${deleteTarget.number} will be permanently removed. This cannot be undone.`\n : ''}\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel disabled={deleting}>Cancel</AlertDialogCancel>\n <AlertDialogAction\n onClick={(event) => {\n event.preventDefault();\n void confirmDelete();\n }}\n disabled={deleting}\n >\n {deleting ? 'Deleting…' : 'Delete'}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n </div>\n );\n}\n"],"mappings":"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"}
|