@burdenoff/microfe-crewfoundry 2026.704.3 → 2026.704.5
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 +76 -75
- package/dist/crewfoundry/pages/AdminAdminPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js +118 -117
- package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.js +115 -114
- package/dist/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js +105 -104
- package/dist/crewfoundry/pages/CommunicationsAnnouncementsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsTeamsPagePage.js +52 -51
- package/dist/crewfoundry/pages/CommunicationsTeamsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js +94 -93
- package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyCompanyProfilePagePage.js +97 -96
- package/dist/crewfoundry/pages/CompanyCompanyProfilePagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js +68 -67
- package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/DashboardAnalyticsPagePage.js +96 -95
- package/dist/crewfoundry/pages/DashboardAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/DashboardDashboardPagePage.js +153 -152
- package/dist/crewfoundry/pages/DashboardDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/DashboardEnhancedDashboardPagePage.js +111 -110
- package/dist/crewfoundry/pages/DashboardEnhancedDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringApplicationsPagePage.js +77 -76
- package/dist/crewfoundry/pages/HiringApplicationsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringCandidatesPagePage.js +80 -79
- package/dist/crewfoundry/pages/HiringCandidatesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringCreateJobPagePage.js +1 -1
- package/dist/crewfoundry/pages/HiringCreateJobPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringInterviewsPagePage.js +102 -101
- package/dist/crewfoundry/pages/HiringInterviewsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js +126 -125
- package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringJobsPagePage.js +64 -63
- package/dist/crewfoundry/pages/HiringJobsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrDepartmentsPagePage.js +96 -95
- package/dist/crewfoundry/pages/HrDepartmentsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js +129 -127
- package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrPayrollPagePage.js +118 -117
- package/dist/crewfoundry/pages/HrPayrollPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js +123 -122
- package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningAssessmentsPagePage.js +1 -1
- package/dist/crewfoundry/pages/LearningAssessmentsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCertificatesPagePage.js +1 -1
- package/dist/crewfoundry/pages/LearningCertificatesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js +77 -76
- package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js +49 -48
- package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCoursesPagePage.js +62 -61
- package/dist/crewfoundry/pages/LearningCoursesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningPagePage.js +72 -71
- package/dist/crewfoundry/pages/LearningLearningPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js +70 -69
- package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js +57 -56
- package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceEarningsPagePage.js +58 -57
- package/dist/crewfoundry/pages/MarketplaceEarningsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePageEnhancedPage.js +122 -121
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePageEnhancedPage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js +2 -2
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js +70 -69
- package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js +41 -40
- package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMyServicesPagePage.js +65 -64
- package/dist/crewfoundry/pages/MarketplaceMyServicesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceProjectDetailsPagePage.js +75 -74
- package/dist/crewfoundry/pages/MarketplaceProjectDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js +4 -4
- package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js +60 -59
- package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsPaymentDashboardPagePage.js +53 -52
- package/dist/crewfoundry/pages/PaymentsPaymentDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsPaymentMethodsPagePage.js +37 -36
- package/dist/crewfoundry/pages/PaymentsPaymentMethodsPagePage.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 +126 -125
- package/dist/crewfoundry/pages/ProjectsProjectDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js +62 -61
- package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamAnalyticsPagePage.js +50 -49
- package/dist/crewfoundry/pages/TeamsTeamAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamDetailPagePage.js +72 -71
- package/dist/crewfoundry/pages/TeamsTeamDetailPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamDirectoryPagePage.js +40 -39
- package/dist/crewfoundry/pages/TeamsTeamDirectoryPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamSettingsPagePage.js +134 -133
- package/dist/crewfoundry/pages/TeamsTeamSettingsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamsPagePage.js +60 -59
- package/dist/crewfoundry/pages/TeamsTeamsPagePage.js.map +1 -1
- package/dist/crewfoundry/store/crewfoundryStore.js +177 -146
- package/dist/crewfoundry/store/crewfoundryStore.js.map +1 -1
- package/dist/crewfoundry/utils/formatEnumLabel.js +8 -0
- package/dist/crewfoundry/utils/formatEnumLabel.js.map +1 -0
- package/package.json +1 -1
|
@@ -1,108 +1,109 @@
|
|
|
1
1
|
import { useCrewFoundryStore as e } from "../store/crewfoundryStore.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
2
|
+
import { formatEnumLabel as t } from "../utils/formatEnumLabel.js";
|
|
3
|
+
import { CreditCard as n, DollarSign as r, Receipt as i, TrendingUp as a } from "lucide-react";
|
|
4
|
+
import { useNavigate as o } from "react-router-dom";
|
|
5
|
+
import { jsx as s, jsxs as c } from "react/jsx-runtime";
|
|
6
|
+
import { Badge as l, Button as u, Card as d, CardContent as f, CardHeader as p, CardTitle as m, GlassCard as h, GradientText as g, IllustratedEmptyState as _, PagePurpose as v, ResponsiveTable as y } from "@burdenoff/fe-libs/ui";
|
|
6
7
|
//#region src/crewfoundry/pages/PaymentsPaymentDashboardPagePage.tsx
|
|
7
|
-
var
|
|
8
|
-
function
|
|
9
|
-
let
|
|
10
|
-
return /* @__PURE__ */
|
|
8
|
+
var b = 5, x = (e) => e === "paid" ? "default" : e === "overdue" ? "destructive" : "secondary";
|
|
9
|
+
function S() {
|
|
10
|
+
let S = o(), { invoices: C, payrollRecords: w } = e(), T = C.reduce((e, t) => e + t.amount, 0), E = C.filter((e) => e.status === "paid").reduce((e, t) => e + t.amount, 0), D = w.reduce((e, t) => e + t.grossPay, 0), O = [...C].sort((e, t) => (t.issueDate ?? "").localeCompare(e.issueDate ?? "")).slice(0, b);
|
|
11
|
+
return /* @__PURE__ */ c("div", {
|
|
11
12
|
className: "space-y-6 p-6",
|
|
12
13
|
children: [
|
|
13
|
-
/* @__PURE__ */
|
|
14
|
-
/* @__PURE__ */
|
|
14
|
+
/* @__PURE__ */ c("div", { children: [
|
|
15
|
+
/* @__PURE__ */ s("h1", {
|
|
15
16
|
className: "text-2xl font-semibold",
|
|
16
|
-
children: /* @__PURE__ */
|
|
17
|
+
children: /* @__PURE__ */ s(g, { children: "Payment Dashboard" })
|
|
17
18
|
}),
|
|
18
|
-
/* @__PURE__ */
|
|
19
|
+
/* @__PURE__ */ s("p", {
|
|
19
20
|
className: "text-sm text-text-secondary",
|
|
20
21
|
children: "Financial transactions and payment overview"
|
|
21
22
|
}),
|
|
22
|
-
/* @__PURE__ */
|
|
23
|
+
/* @__PURE__ */ s(v, {
|
|
23
24
|
className: "mt-1",
|
|
24
25
|
children: "A snapshot of all money movement — incoming payments, payouts, and balances so you understand your financial position at a glance."
|
|
25
26
|
})
|
|
26
27
|
] }),
|
|
27
|
-
/* @__PURE__ */
|
|
28
|
+
/* @__PURE__ */ c("div", {
|
|
28
29
|
className: "grid gap-4 md:grid-cols-2 lg:grid-cols-4",
|
|
29
30
|
children: [
|
|
30
|
-
/* @__PURE__ */
|
|
31
|
+
/* @__PURE__ */ c(h, {
|
|
31
32
|
treatment: "glass",
|
|
32
33
|
glow: !0,
|
|
33
34
|
className: "border-border-seam",
|
|
34
|
-
children: [/* @__PURE__ */
|
|
35
|
+
children: [/* @__PURE__ */ c(p, {
|
|
35
36
|
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
36
|
-
children: [/* @__PURE__ */
|
|
37
|
+
children: [/* @__PURE__ */ s(m, {
|
|
37
38
|
className: "text-sm font-medium",
|
|
38
39
|
children: "Total Invoiced"
|
|
39
|
-
}), /* @__PURE__ */
|
|
40
|
-
}), /* @__PURE__ */
|
|
40
|
+
}), /* @__PURE__ */ s(i, { className: "h-4 w-4 text-text-secondary" })]
|
|
41
|
+
}), /* @__PURE__ */ s(f, { children: /* @__PURE__ */ c("div", {
|
|
41
42
|
className: "text-2xl font-bold tabular-nums",
|
|
42
|
-
children: ["$",
|
|
43
|
+
children: ["$", T.toLocaleString()]
|
|
43
44
|
}) })]
|
|
44
45
|
}),
|
|
45
|
-
/* @__PURE__ */
|
|
46
|
+
/* @__PURE__ */ c(h, {
|
|
46
47
|
treatment: "metric",
|
|
47
48
|
className: "border-border-seam",
|
|
48
|
-
children: [/* @__PURE__ */
|
|
49
|
+
children: [/* @__PURE__ */ c(p, {
|
|
49
50
|
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
50
|
-
children: [/* @__PURE__ */
|
|
51
|
+
children: [/* @__PURE__ */ s(m, {
|
|
51
52
|
className: "text-sm font-medium",
|
|
52
53
|
children: "Collected"
|
|
53
|
-
}), /* @__PURE__ */
|
|
54
|
-
}), /* @__PURE__ */
|
|
54
|
+
}), /* @__PURE__ */ s(r, { className: "h-4 w-4 text-status-success-text" })]
|
|
55
|
+
}), /* @__PURE__ */ s(f, { children: /* @__PURE__ */ c("div", {
|
|
55
56
|
className: "text-2xl font-bold tabular-nums",
|
|
56
|
-
children: ["$",
|
|
57
|
+
children: ["$", E.toLocaleString()]
|
|
57
58
|
}) })]
|
|
58
59
|
}),
|
|
59
|
-
/* @__PURE__ */
|
|
60
|
+
/* @__PURE__ */ c(h, {
|
|
60
61
|
treatment: "metric",
|
|
61
62
|
className: "border-border-seam",
|
|
62
|
-
children: [/* @__PURE__ */
|
|
63
|
+
children: [/* @__PURE__ */ c(p, {
|
|
63
64
|
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
64
|
-
children: [/* @__PURE__ */
|
|
65
|
+
children: [/* @__PURE__ */ s(m, {
|
|
65
66
|
className: "text-sm font-medium",
|
|
66
67
|
children: "Payroll Processed"
|
|
67
|
-
}), /* @__PURE__ */
|
|
68
|
-
}), /* @__PURE__ */
|
|
68
|
+
}), /* @__PURE__ */ s(n, { className: "h-4 w-4 text-text-secondary" })]
|
|
69
|
+
}), /* @__PURE__ */ s(f, { children: /* @__PURE__ */ c("div", {
|
|
69
70
|
className: "text-2xl font-bold tabular-nums",
|
|
70
|
-
children: ["$",
|
|
71
|
+
children: ["$", D.toLocaleString()]
|
|
71
72
|
}) })]
|
|
72
73
|
}),
|
|
73
|
-
/* @__PURE__ */
|
|
74
|
+
/* @__PURE__ */ c(h, {
|
|
74
75
|
treatment: "metric",
|
|
75
76
|
className: "border-border-seam",
|
|
76
|
-
children: [/* @__PURE__ */
|
|
77
|
+
children: [/* @__PURE__ */ c(p, {
|
|
77
78
|
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
78
|
-
children: [/* @__PURE__ */
|
|
79
|
+
children: [/* @__PURE__ */ s(m, {
|
|
79
80
|
className: "text-sm font-medium",
|
|
80
81
|
children: "Outstanding"
|
|
81
|
-
}), /* @__PURE__ */
|
|
82
|
-
}), /* @__PURE__ */
|
|
82
|
+
}), /* @__PURE__ */ s(a, { className: "h-4 w-4 text-status-warning-text" })]
|
|
83
|
+
}), /* @__PURE__ */ s(f, { children: /* @__PURE__ */ c("div", {
|
|
83
84
|
className: "text-2xl font-bold tabular-nums",
|
|
84
|
-
children: ["$", (
|
|
85
|
+
children: ["$", (T - E).toLocaleString()]
|
|
85
86
|
}) })]
|
|
86
87
|
})
|
|
87
88
|
]
|
|
88
89
|
}),
|
|
89
|
-
/* @__PURE__ */
|
|
90
|
+
/* @__PURE__ */ c(d, { children: [/* @__PURE__ */ c(p, {
|
|
90
91
|
className: "flex flex-row items-center justify-between space-y-0",
|
|
91
|
-
children: [/* @__PURE__ */
|
|
92
|
+
children: [/* @__PURE__ */ s(m, { children: "Recent Invoices" }), C.length > b && /* @__PURE__ */ s(u, {
|
|
92
93
|
variant: "ghost",
|
|
93
94
|
size: "sm",
|
|
94
|
-
onClick: () =>
|
|
95
|
+
onClick: () => S("../payments/invoices-page"),
|
|
95
96
|
children: "View all"
|
|
96
97
|
})]
|
|
97
|
-
}), /* @__PURE__ */
|
|
98
|
-
data:
|
|
98
|
+
}), /* @__PURE__ */ s(f, { children: /* @__PURE__ */ s(y, {
|
|
99
|
+
data: O,
|
|
99
100
|
rowKey: (e) => e.id,
|
|
100
101
|
columns: [
|
|
101
102
|
{
|
|
102
103
|
key: "number",
|
|
103
104
|
header: "Invoice",
|
|
104
105
|
priority: "primary",
|
|
105
|
-
cell: (e) => /* @__PURE__ */
|
|
106
|
+
cell: (e) => /* @__PURE__ */ s("span", {
|
|
106
107
|
className: "font-medium",
|
|
107
108
|
children: e.number
|
|
108
109
|
})
|
|
@@ -111,7 +112,7 @@ function x() {
|
|
|
111
112
|
key: "client",
|
|
112
113
|
header: "Client",
|
|
113
114
|
priority: "secondary",
|
|
114
|
-
cell: (e) => /* @__PURE__ */
|
|
115
|
+
cell: (e) => /* @__PURE__ */ s("span", {
|
|
115
116
|
className: "text-text-secondary",
|
|
116
117
|
children: e.clientName
|
|
117
118
|
})
|
|
@@ -122,13 +123,13 @@ function x() {
|
|
|
122
123
|
priority: "secondary",
|
|
123
124
|
headerClassName: "text-right",
|
|
124
125
|
cellClassName: "text-right",
|
|
125
|
-
cell: (e) => /* @__PURE__ */
|
|
126
|
+
cell: (e) => /* @__PURE__ */ c("span", { children: ["$", e.amount.toLocaleString()] })
|
|
126
127
|
},
|
|
127
128
|
{
|
|
128
129
|
key: "dueDate",
|
|
129
130
|
header: "Due Date",
|
|
130
131
|
priority: "hidden-on-mobile",
|
|
131
|
-
cell: (e) => /* @__PURE__ */
|
|
132
|
+
cell: (e) => /* @__PURE__ */ s("span", {
|
|
132
133
|
className: "text-text-secondary",
|
|
133
134
|
children: e.dueDate
|
|
134
135
|
})
|
|
@@ -137,14 +138,14 @@ function x() {
|
|
|
137
138
|
key: "status",
|
|
138
139
|
header: "Status",
|
|
139
140
|
priority: "secondary",
|
|
140
|
-
cell: (e) => /* @__PURE__ */
|
|
141
|
-
variant:
|
|
141
|
+
cell: (e) => /* @__PURE__ */ s(l, {
|
|
142
|
+
variant: x(e.status),
|
|
142
143
|
className: "text-[10px]",
|
|
143
|
-
children: e.status
|
|
144
|
+
children: t(e.status)
|
|
144
145
|
})
|
|
145
146
|
}
|
|
146
147
|
],
|
|
147
|
-
emptyState: /* @__PURE__ */
|
|
148
|
+
emptyState: /* @__PURE__ */ s(_, {
|
|
148
149
|
illustration: "empty-data",
|
|
149
150
|
title: "No invoices yet",
|
|
150
151
|
description: "Invoices you create will show up here."
|
|
@@ -154,6 +155,6 @@ function x() {
|
|
|
154
155
|
});
|
|
155
156
|
}
|
|
156
157
|
//#endregion
|
|
157
|
-
export {
|
|
158
|
+
export { S as PaymentsPaymentDashboardPagePage };
|
|
158
159
|
|
|
159
160
|
//# sourceMappingURL=PaymentsPaymentDashboardPagePage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PaymentsPaymentDashboardPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/PaymentsPaymentDashboardPagePage.tsx"],"sourcesContent":["import {\n Badge,\n Button,\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n PagePurpose,\n ResponsiveTable,\n type ResponsiveTableColumn,\n} from '@burdenoff/fe-libs/ui';\nimport { CreditCard, DollarSign, Receipt, TrendingUp } from 'lucide-react';\nimport { useNavigate } from 'react-router-dom';\nimport { useCrewFoundryStore, type Invoice } from '../store/crewfoundryStore';\n\nconst RECENT_LIMIT = 5;\n\nconst statusVariant = (status: Invoice['status']) =>\n status === 'paid' ? 'default' : status === 'overdue' ? 'destructive' : 'secondary';\n\nexport function PaymentsPaymentDashboardPagePage() {\n const navigate = useNavigate();\n const { invoices, payrollRecords } = useCrewFoundryStore();\n const totalInvoiced = invoices.reduce((s, i) => s + i.amount, 0);\n const totalPaid = invoices.filter((i) => i.status === 'paid').reduce((s, i) => s + i.amount, 0);\n const totalPayroll = payrollRecords.reduce((s, r) => s + r.grossPay, 0);\n\n const recentInvoices = [...invoices]\n .sort((a, b) => (b.issueDate ?? '').localeCompare(a.issueDate ?? ''))\n .slice(0, RECENT_LIMIT);\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: 'amount',\n header: 'Amount',\n priority: 'secondary',\n headerClassName: 'text-right',\n cellClassName: 'text-right',\n cell: (inv) => <span>${inv.amount.toLocaleString()}</span>,\n },\n {\n key: 'dueDate',\n header: 'Due Date',\n priority: 'hidden-on-mobile',\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 {inv.status}\n </Badge>\n ),\n },\n ];\n\n return (\n <div className=\"space-y-6 p-6\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>Payment Dashboard</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">Financial transactions and payment overview</p>\n <PagePurpose className=\"mt-1\">\n A snapshot of all money movement — incoming payments, payouts, and balances so you\n understand your financial position at a glance.\n </PagePurpose>\n </div>\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\">Total Invoiced</CardTitle>\n <Receipt className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">${totalInvoiced.toLocaleString()}</div>\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\">Collected</CardTitle>\n <DollarSign className=\"h-4 w-4 text-status-success-text\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">${totalPaid.toLocaleString()}</div>\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\">Payroll Processed</CardTitle>\n <CreditCard className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">${totalPayroll.toLocaleString()}</div>\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\">Outstanding</CardTitle>\n <TrendingUp className=\"h-4 w-4 text-status-warning-text\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">\n ${(totalInvoiced - totalPaid).toLocaleString()}\n </div>\n </CardContent>\n </GlassCard>\n </div>\n <Card>\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0\">\n <CardTitle>Recent Invoices</CardTitle>\n {invoices.length > RECENT_LIMIT && (\n <Button
|
|
1
|
+
{"version":3,"file":"PaymentsPaymentDashboardPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/PaymentsPaymentDashboardPagePage.tsx"],"sourcesContent":["import {\n Badge,\n Button,\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n PagePurpose,\n ResponsiveTable,\n type ResponsiveTableColumn,\n} from '@burdenoff/fe-libs/ui';\nimport { CreditCard, DollarSign, Receipt, TrendingUp } from 'lucide-react';\nimport { useNavigate } from 'react-router-dom';\nimport { useCrewFoundryStore, type Invoice } from '../store/crewfoundryStore';\nimport { formatEnumLabel } from '../utils/formatEnumLabel';\n\nconst RECENT_LIMIT = 5;\n\nconst statusVariant = (status: Invoice['status']) =>\n status === 'paid' ? 'default' : status === 'overdue' ? 'destructive' : 'secondary';\n\nexport function PaymentsPaymentDashboardPagePage() {\n const navigate = useNavigate();\n const { invoices, payrollRecords } = useCrewFoundryStore();\n const totalInvoiced = invoices.reduce((s, i) => s + i.amount, 0);\n const totalPaid = invoices.filter((i) => i.status === 'paid').reduce((s, i) => s + i.amount, 0);\n const totalPayroll = payrollRecords.reduce((s, r) => s + r.grossPay, 0);\n\n const recentInvoices = [...invoices]\n .sort((a, b) => (b.issueDate ?? '').localeCompare(a.issueDate ?? ''))\n .slice(0, RECENT_LIMIT);\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: 'amount',\n header: 'Amount',\n priority: 'secondary',\n headerClassName: 'text-right',\n cellClassName: 'text-right',\n cell: (inv) => <span>${inv.amount.toLocaleString()}</span>,\n },\n {\n key: 'dueDate',\n header: 'Due Date',\n priority: 'hidden-on-mobile',\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>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>Payment Dashboard</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">Financial transactions and payment overview</p>\n <PagePurpose className=\"mt-1\">\n A snapshot of all money movement — incoming payments, payouts, and balances so you\n understand your financial position at a glance.\n </PagePurpose>\n </div>\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\">Total Invoiced</CardTitle>\n <Receipt className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">${totalInvoiced.toLocaleString()}</div>\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\">Collected</CardTitle>\n <DollarSign className=\"h-4 w-4 text-status-success-text\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">${totalPaid.toLocaleString()}</div>\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\">Payroll Processed</CardTitle>\n <CreditCard className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">${totalPayroll.toLocaleString()}</div>\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\">Outstanding</CardTitle>\n <TrendingUp className=\"h-4 w-4 text-status-warning-text\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">\n ${(totalInvoiced - totalPaid).toLocaleString()}\n </div>\n </CardContent>\n </GlassCard>\n </div>\n <Card>\n <CardHeader className=\"flex flex-row items-center justify-between space-y-0\">\n <CardTitle>Recent Invoices</CardTitle>\n {invoices.length > RECENT_LIMIT && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => navigate('../payments/invoices-page')}\n >\n View all\n </Button>\n )}\n </CardHeader>\n <CardContent>\n <ResponsiveTable\n data={recentInvoices}\n rowKey={(inv) => inv.id}\n columns={columns}\n emptyState={\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No invoices yet\"\n description=\"Invoices you create will show up here.\"\n />\n }\n />\n </CardContent>\n </Card>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,72 +1,73 @@
|
|
|
1
1
|
import { useCrewFoundryStore as e } from "../store/crewfoundryStore.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
2
|
+
import { formatEnumLabel as t } from "../utils/formatEnumLabel.js";
|
|
3
|
+
import { Building2 as n, CreditCard as r, ExternalLink as i } from "lucide-react";
|
|
4
|
+
import { useNavigate as a } from "react-router-dom";
|
|
5
|
+
import { jsx as o, jsxs as s } from "react/jsx-runtime";
|
|
6
|
+
import { Badge as c, Button as l, CardContent as u, GlassCard as d, GradientText as f, IllustratedEmptyState as p, PagePurpose as m } from "@burdenoff/fe-libs/ui";
|
|
6
7
|
//#region src/crewfoundry/pages/PaymentsPaymentMethodsPagePage.tsx
|
|
7
|
-
var
|
|
8
|
-
function
|
|
9
|
-
let
|
|
10
|
-
return /* @__PURE__ */
|
|
8
|
+
var h = "/billing/payment-methods";
|
|
9
|
+
function g() {
|
|
10
|
+
let g = a(), { paymentMethods: _ } = e(), v = () => g(h);
|
|
11
|
+
return /* @__PURE__ */ s("div", {
|
|
11
12
|
className: "space-y-6 p-6",
|
|
12
|
-
children: [/* @__PURE__ */
|
|
13
|
+
children: [/* @__PURE__ */ s("div", {
|
|
13
14
|
className: "flex items-center justify-between",
|
|
14
|
-
children: [/* @__PURE__ */
|
|
15
|
-
/* @__PURE__ */
|
|
15
|
+
children: [/* @__PURE__ */ s("div", { children: [
|
|
16
|
+
/* @__PURE__ */ o("h1", {
|
|
16
17
|
className: "text-2xl font-semibold",
|
|
17
|
-
children: /* @__PURE__ */
|
|
18
|
+
children: /* @__PURE__ */ o(f, { children: "Payment Methods" })
|
|
18
19
|
}),
|
|
19
|
-
/* @__PURE__ */
|
|
20
|
+
/* @__PURE__ */ o("p", {
|
|
20
21
|
className: "text-sm text-text-secondary",
|
|
21
22
|
children: "Managed in your platform Billing settings"
|
|
22
23
|
}),
|
|
23
|
-
/* @__PURE__ */
|
|
24
|
+
/* @__PURE__ */ o(m, {
|
|
24
25
|
className: "mt-1",
|
|
25
26
|
children: "Manage how you pay and get paid — cards, bank accounts, and payout methods are held securely in Billing settings."
|
|
26
27
|
})
|
|
27
|
-
] }), /* @__PURE__ */
|
|
28
|
+
] }), /* @__PURE__ */ s(l, {
|
|
28
29
|
size: "sm",
|
|
29
|
-
onClick:
|
|
30
|
-
children: [/* @__PURE__ */
|
|
30
|
+
onClick: v,
|
|
31
|
+
children: [/* @__PURE__ */ o(i, { className: "mr-1 h-4 w-4" }), "Manage in Billing settings"]
|
|
31
32
|
})]
|
|
32
|
-
}), /* @__PURE__ */
|
|
33
|
+
}), /* @__PURE__ */ o("div", {
|
|
33
34
|
className: "grid gap-4 md:grid-cols-2",
|
|
34
|
-
children:
|
|
35
|
+
children: _.length === 0 ? /* @__PURE__ */ o("div", {
|
|
35
36
|
className: "col-span-full",
|
|
36
|
-
children: /* @__PURE__ */
|
|
37
|
+
children: /* @__PURE__ */ o(p, {
|
|
37
38
|
illustration: "empty-generic",
|
|
38
39
|
title: "No payment methods",
|
|
39
40
|
description: "Payment methods live in your platform Billing settings. Add a card or bank account there to pay and get paid.",
|
|
40
|
-
action: /* @__PURE__ */
|
|
41
|
+
action: /* @__PURE__ */ s(l, {
|
|
41
42
|
size: "sm",
|
|
42
|
-
onClick:
|
|
43
|
-
children: [/* @__PURE__ */
|
|
43
|
+
onClick: v,
|
|
44
|
+
children: [/* @__PURE__ */ o(i, { className: "mr-1 h-4 w-4" }), "Open Billing settings"]
|
|
44
45
|
})
|
|
45
46
|
})
|
|
46
|
-
}) :
|
|
47
|
-
treatment:
|
|
48
|
-
glow:
|
|
49
|
-
children: /* @__PURE__ */
|
|
47
|
+
}) : _.map((e, i) => /* @__PURE__ */ o(d, {
|
|
48
|
+
treatment: i === 0 ? "glass" : "plain",
|
|
49
|
+
glow: i === 0,
|
|
50
|
+
children: /* @__PURE__ */ s(u, {
|
|
50
51
|
className: "p-4",
|
|
51
|
-
children: [/* @__PURE__ */
|
|
52
|
+
children: [/* @__PURE__ */ s("div", {
|
|
52
53
|
className: "mb-3 flex items-center justify-between",
|
|
53
|
-
children: [/* @__PURE__ */
|
|
54
|
+
children: [/* @__PURE__ */ s("div", {
|
|
54
55
|
className: "flex items-center gap-2",
|
|
55
|
-
children: [e.type === "bank" ? /* @__PURE__ */
|
|
56
|
+
children: [e.type === "bank" ? /* @__PURE__ */ o(n, { className: "h-5 w-5 text-text-secondary" }) : /* @__PURE__ */ o(r, { className: "h-5 w-5 text-text-secondary" }), /* @__PURE__ */ s("div", { children: [/* @__PURE__ */ o("p", {
|
|
56
57
|
className: "text-sm font-medium",
|
|
57
58
|
children: e.name
|
|
58
|
-
}), /* @__PURE__ */
|
|
59
|
+
}), /* @__PURE__ */ o("p", {
|
|
59
60
|
className: "text-xs text-text-secondary",
|
|
60
61
|
children: e.bank
|
|
61
62
|
})] })]
|
|
62
|
-
}), /* @__PURE__ */
|
|
63
|
+
}), /* @__PURE__ */ o(c, {
|
|
63
64
|
variant: e.status === "primary" ? "default" : "secondary",
|
|
64
65
|
className: "text-[10px]",
|
|
65
|
-
children: e.status
|
|
66
|
+
children: t(e.status)
|
|
66
67
|
})]
|
|
67
|
-
}), /* @__PURE__ */
|
|
68
|
+
}), /* @__PURE__ */ s("div", {
|
|
68
69
|
className: "flex items-center justify-between text-sm text-text-secondary",
|
|
69
|
-
children: [/* @__PURE__ */
|
|
70
|
+
children: [/* @__PURE__ */ s("span", { children: ["•••• •••• •••• ", e.last4] }), e.expiry ? /* @__PURE__ */ s("span", { children: ["Exp: ", e.expiry] }) : null]
|
|
70
71
|
})]
|
|
71
72
|
})
|
|
72
73
|
}, e.id))
|
|
@@ -74,6 +75,6 @@ function h() {
|
|
|
74
75
|
});
|
|
75
76
|
}
|
|
76
77
|
//#endregion
|
|
77
|
-
export {
|
|
78
|
+
export { g as PaymentsPaymentMethodsPagePage };
|
|
78
79
|
|
|
79
80
|
//# sourceMappingURL=PaymentsPaymentMethodsPagePage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PaymentsPaymentMethodsPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/PaymentsPaymentMethodsPagePage.tsx"],"sourcesContent":["import { useNavigate } from 'react-router-dom';\nimport {\n Badge,\n Button,\n CardContent,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport { Building2, CreditCard, ExternalLink } from 'lucide-react';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\n\n// Payment methods are owned by the platform Billing module (global billing\n// account), not by CrewFoundry. We read the real methods surfaced via the\n// billing overlap and send all add/manage actions to Billing settings — there\n// is deliberately no crew-local payment-method store.\nconst BILLING_PAYMENT_METHODS_ROUTE = '/billing/payment-methods';\n\nexport function PaymentsPaymentMethodsPagePage() {\n const navigate = useNavigate();\n const { paymentMethods } = useCrewFoundryStore();\n\n const goToBilling = () => navigate(BILLING_PAYMENT_METHODS_ROUTE);\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>Payment Methods</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">Managed in your platform Billing settings</p>\n <PagePurpose className=\"mt-1\">\n Manage how you pay and get paid — cards, bank accounts, and payout methods are held\n securely in Billing settings.\n </PagePurpose>\n </div>\n <Button size=\"sm\" onClick={goToBilling}>\n <ExternalLink className=\"mr-1 h-4 w-4\" />\n Manage in Billing settings\n </Button>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-2\">\n {paymentMethods.length === 0 ? (\n <div className=\"col-span-full\">\n <IllustratedEmptyState\n illustration=\"empty-generic\"\n title=\"No payment methods\"\n description=\"Payment methods live in your platform Billing settings. Add a card or bank account there to pay and get paid.\"\n action={\n <Button size=\"sm\" onClick={goToBilling}>\n <ExternalLink className=\"mr-1 h-4 w-4\" />\n Open Billing settings\n </Button>\n }\n />\n </div>\n ) : (\n paymentMethods.map((method, _idx) => (\n <GlassCard key={method.id} treatment={_idx === 0 ? 'glass' : 'plain'} glow={_idx === 0}>\n <CardContent className=\"p-4\">\n <div className=\"mb-3 flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n {method.type === 'bank' ? (\n <Building2 className=\"h-5 w-5 text-text-secondary\" />\n ) : (\n <CreditCard className=\"h-5 w-5 text-text-secondary\" />\n )}\n <div>\n <p className=\"text-sm font-medium\">{method.name}</p>\n <p className=\"text-xs text-text-secondary\">{method.bank}</p>\n </div>\n </div>\n <Badge\n variant={method.status === 'primary' ? 'default' : 'secondary'}\n className=\"text-[10px]\"\n >\n {method.status}\n </Badge>\n </div>\n <div className=\"flex items-center justify-between text-sm text-text-secondary\">\n <span>•••• •••• •••• {method.last4}</span>\n {method.expiry ? <span>Exp: {method.expiry}</span> : null}\n </div>\n </CardContent>\n </GlassCard>\n ))\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"PaymentsPaymentMethodsPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/PaymentsPaymentMethodsPagePage.tsx"],"sourcesContent":["import { useNavigate } from 'react-router-dom';\nimport {\n Badge,\n Button,\n CardContent,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport { Building2, CreditCard, ExternalLink } from 'lucide-react';\nimport { useCrewFoundryStore } from '../store/crewfoundryStore';\nimport { formatEnumLabel } from '../utils/formatEnumLabel';\n\n// Payment methods are owned by the platform Billing module (global billing\n// account), not by CrewFoundry. We read the real methods surfaced via the\n// billing overlap and send all add/manage actions to Billing settings — there\n// is deliberately no crew-local payment-method store.\nconst BILLING_PAYMENT_METHODS_ROUTE = '/billing/payment-methods';\n\nexport function PaymentsPaymentMethodsPagePage() {\n const navigate = useNavigate();\n const { paymentMethods } = useCrewFoundryStore();\n\n const goToBilling = () => navigate(BILLING_PAYMENT_METHODS_ROUTE);\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>Payment Methods</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">Managed in your platform Billing settings</p>\n <PagePurpose className=\"mt-1\">\n Manage how you pay and get paid — cards, bank accounts, and payout methods are held\n securely in Billing settings.\n </PagePurpose>\n </div>\n <Button size=\"sm\" onClick={goToBilling}>\n <ExternalLink className=\"mr-1 h-4 w-4\" />\n Manage in Billing settings\n </Button>\n </div>\n\n <div className=\"grid gap-4 md:grid-cols-2\">\n {paymentMethods.length === 0 ? (\n <div className=\"col-span-full\">\n <IllustratedEmptyState\n illustration=\"empty-generic\"\n title=\"No payment methods\"\n description=\"Payment methods live in your platform Billing settings. Add a card or bank account there to pay and get paid.\"\n action={\n <Button size=\"sm\" onClick={goToBilling}>\n <ExternalLink className=\"mr-1 h-4 w-4\" />\n Open Billing settings\n </Button>\n }\n />\n </div>\n ) : (\n paymentMethods.map((method, _idx) => (\n <GlassCard key={method.id} treatment={_idx === 0 ? 'glass' : 'plain'} glow={_idx === 0}>\n <CardContent className=\"p-4\">\n <div className=\"mb-3 flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n {method.type === 'bank' ? (\n <Building2 className=\"h-5 w-5 text-text-secondary\" />\n ) : (\n <CreditCard className=\"h-5 w-5 text-text-secondary\" />\n )}\n <div>\n <p className=\"text-sm font-medium\">{method.name}</p>\n <p className=\"text-xs text-text-secondary\">{method.bank}</p>\n </div>\n </div>\n <Badge\n variant={method.status === 'primary' ? 'default' : 'secondary'}\n className=\"text-[10px]\"\n >\n {formatEnumLabel(method.status)}\n </Badge>\n </div>\n <div className=\"flex items-center justify-between text-sm text-text-secondary\">\n <span>•••• •••• •••• {method.last4}</span>\n {method.expiry ? <span>Exp: {method.expiry}</span> : null}\n </div>\n </CardContent>\n </GlassCard>\n ))\n )}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;AAkBA,IAAM,IAAgC;AAEtC,SAAgB,IAAiC;CAC/C,IAAM,IAAW,GAAa,EACxB,EAAE,sBAAmB,GAAqB,EAE1C,UAAoB,EAAS,EAA8B;AAEjE,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD,EAAA,UAAA;IACE,kBAAC,MAAD;KAAI,WAAU;eACZ,kBAAC,GAAD,EAAA,UAAc,mBAA8B,CAAA;KACzC,CAAA;IACL,kBAAC,KAAD;KAAG,WAAU;eAA8B;KAA6C,CAAA;IACxF,kBAAC,GAAD;KAAa,WAAU;eAAO;KAGhB,CAAA;IACV,EAAA,CAAA,EACN,kBAAC,GAAD;IAAQ,MAAK;IAAK,SAAS;cAA3B,CACE,kBAAC,GAAD,EAAc,WAAU,gBAAiB,CAAA,EAAA,6BAElC;MACL;MAEN,kBAAC,OAAD;GAAK,WAAU;aACZ,EAAe,WAAW,IACzB,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,GAAD;KACE,cAAa;KACb,OAAM;KACN,aAAY;KACZ,QACE,kBAAC,GAAD;MAAQ,MAAK;MAAK,SAAS;gBAA3B,CACE,kBAAC,GAAD,EAAc,WAAU,gBAAiB,CAAA,EAAA,wBAElC;;KAEX,CAAA;IACE,CAAA,GAEN,EAAe,KAAK,GAAQ,MAC1B,kBAAC,GAAD;IAA2B,WAAW,MAAS,IAAI,UAAU;IAAS,MAAM,MAAS;cACnF,kBAAC,GAAD;KAAa,WAAU;eAAvB,CACE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACG,EAAO,SAAS,SACf,kBAAC,GAAD,EAAW,WAAU,+BAAgC,CAAA,GAErD,kBAAC,GAAD,EAAY,WAAU,+BAAgC,CAAA,EAExD,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;QAAG,WAAU;kBAAuB,EAAO;QAAS,CAAA,EACpD,kBAAC,KAAD;QAAG,WAAU;kBAA+B,EAAO;QAAS,CAAA,CACxD,EAAA,CAAA,CACF;UACN,kBAAC,GAAD;OACE,SAAS,EAAO,WAAW,YAAY,YAAY;OACnD,WAAU;iBAET,EAAgB,EAAO,OAAO;OACzB,CAAA,CACJ;SACN,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,QAAD,EAAA,UAAA,CAAM,mBAAgB,EAAO,MAAa,EAAA,CAAA,EACzC,EAAO,SAAS,kBAAC,QAAD,EAAA,UAAA,CAAM,SAAM,EAAO,OAAc,EAAA,CAAA,GAAG,KACjD;QACM;;IACJ,EA1BI,EAAO,GA0BX,CACZ;GAEA,CAAA,CACF"}
|
|
@@ -28,7 +28,7 @@ function m() {
|
|
|
28
28
|
};
|
|
29
29
|
j(!0);
|
|
30
30
|
try {
|
|
31
|
-
await g(r), h(e === "planning" ? "Draft project saved" : "Project created", "success"), m("
|
|
31
|
+
await g(r), h(e === "planning" ? "Draft project saved" : "Project created", "success"), m("../projects/projects-page");
|
|
32
32
|
} catch (e) {
|
|
33
33
|
h(e instanceof Error ? e.message : "Unable to create project", "error");
|
|
34
34
|
} finally {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProjectsCreateProjectPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/ProjectsCreateProjectPagePage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport {\n Button,\n EmphasisPanel,\n GradientText,\n Input,\n PagePurpose,\n Textarea,\n} from '@burdenoff/fe-libs/ui';\nimport { useGlobalUi } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { FolderKanban, Save } from 'lucide-react';\nimport { useNavigate } from 'react-router-dom';\nimport { useCrewFoundryStore, type Project } from '../store/crewfoundryStore';\n\nexport function ProjectsCreateProjectPagePage() {\n const navigate = useNavigate();\n const { showToast } = useGlobalUi();\n const addProject = useCrewFoundryStore((state) => state.addProject);\n const teams = useCrewFoundryStore((state) => state.teams);\n\n const [name, setName] = useState('');\n const [description, setDescription] = useState('');\n const [startDate, setStartDate] = useState('');\n const [endDate, setEndDate] = useState('');\n const [budget, setBudget] = useState('');\n const [teamId, setTeamId] = useState('');\n const [submitting, setSubmitting] = useState(false);\n\n const handleCreate = async (status: Project['status']) => {\n if (submitting) return;\n if (name.trim() === '') {\n showToast('Project Name is required', 'warning');\n return;\n }\n const selectedTeam = teams.find((team) => team.id === teamId);\n const budgetValue = budget.trim() === '' ? undefined : Number(budget);\n // CreateCrewProjectInput only accepts a known field subset; build exactly\n // that shape. The store replaces this optimistic row with the server's\n // complete Project, so display-only fields need not be provided here.\n const payload: Partial<Project> = {\n name: name.trim(),\n description: description.trim(),\n status,\n priority: 'medium',\n ...(startDate ? { startDate } : {}),\n ...(endDate ? { endDate } : {}),\n ...(budgetValue !== undefined && !Number.isNaN(budgetValue) ? { budget: budgetValue } : {}),\n ...(selectedTeam ? { teamId: selectedTeam.id, teamName: selectedTeam.name } : {}),\n };\n setSubmitting(true);\n try {\n await addProject(payload as Project);\n showToast(status === 'planning' ? 'Draft project saved' : 'Project created', 'success');\n navigate('../../projects/projects-page');\n } catch (error) {\n showToast(error instanceof Error ? error.message : 'Unable to create project', 'error');\n } finally {\n setSubmitting(false);\n }\n };\n\n const selectClass =\n 'flex h-10 w-full rounded-input border border-border-default bg-bg-surface px-3 py-2 text-sm text-text-primary transition-colors duration-200 focus-visible:border-border-focus focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50';\n\n return (\n <div className=\"space-y-6 p-6 max-w-3xl\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>Create Project</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">Set up a new project for your team</p>\n <PagePurpose className=\"mt-1\">\n Start a new project — define its scope, budget, and team here so you can begin tracking\n work toward a clear goal.\n </PagePurpose>\n </div>\n <EmphasisPanel>\n <div className=\"mb-4 flex items-center gap-2 text-lg font-semibold\">\n <FolderKanban className=\"h-5 w-5\" />\n Project Details\n </div>\n <div className=\"space-y-4\">\n <div className=\"space-y-2\">\n <label htmlFor=\"cpName\" className=\"text-sm font-medium\">\n Project Name\n </label>\n <Input\n id=\"cpName\"\n placeholder=\"e.g. HR Analytics Dashboard v3\"\n value={name}\n disabled={submitting}\n onChange={(e) => setName(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <label htmlFor=\"cpDesc\" className=\"text-sm font-medium\">\n Description\n </label>\n <Textarea\n id=\"cpDesc\"\n placeholder=\"Describe the project objectives and scope...\"\n rows={3}\n value={description}\n disabled={submitting}\n onChange={(e) => setDescription(e.target.value)}\n />\n </div>\n {teams.length > 0 ? (\n <div className=\"space-y-2\">\n <label htmlFor=\"cpTeam\" className=\"text-sm font-medium\">\n Team\n </label>\n <select\n id=\"cpTeam\"\n className={selectClass}\n value={teamId}\n disabled={submitting}\n onChange={(e) => setTeamId(e.target.value)}\n >\n <option value=\"\">Unassigned</option>\n {teams.map((team) => (\n <option key={team.id} value={team.id}>\n {team.name}\n </option>\n ))}\n </select>\n </div>\n ) : null}\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div className=\"space-y-2\">\n <label htmlFor=\"cpStart\" className=\"text-sm font-medium\">\n Start Date\n </label>\n <Input\n id=\"cpStart\"\n type=\"date\"\n value={startDate}\n disabled={submitting}\n onChange={(e) => setStartDate(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <label htmlFor=\"cpEnd\" className=\"text-sm font-medium\">\n End Date\n </label>\n <Input\n id=\"cpEnd\"\n type=\"date\"\n value={endDate}\n disabled={submitting}\n onChange={(e) => setEndDate(e.target.value)}\n />\n </div>\n </div>\n <div className=\"space-y-2\">\n <label htmlFor=\"cpBudget\" className=\"text-sm font-medium\">\n Budget ($)\n </label>\n <Input\n id=\"cpBudget\"\n type=\"number\"\n placeholder=\"e.g. 250000\"\n value={budget}\n disabled={submitting}\n onChange={(e) => setBudget(e.target.value)}\n />\n </div>\n </div>\n </EmphasisPanel>\n <div className=\"flex justify-end gap-2\">\n <Button variant=\"outline\" disabled={submitting} onClick={() => handleCreate('planning')}>\n Save as Draft\n </Button>\n <Button disabled={submitting} onClick={() => handleCreate('active')}>\n <Save className=\"h-4 w-4 mr-1\" />\n {submitting ? 'Saving…' : 'Create Project'}\n </Button>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;AAcA,SAAgB,IAAgC;CAC9C,IAAM,IAAW,GAAa,EACxB,EAAE,iBAAc,GAAa,EAC7B,IAAa,GAAqB,MAAU,EAAM,WAAW,EAC7D,IAAQ,GAAqB,MAAU,EAAM,MAAM,EAEnD,CAAC,GAAM,KAAW,EAAS,GAAG,EAC9B,CAAC,GAAa,KAAkB,EAAS,GAAG,EAC5C,CAAC,GAAW,KAAgB,EAAS,GAAG,EACxC,CAAC,GAAS,KAAc,EAAS,GAAG,EACpC,CAAC,GAAQ,KAAa,EAAS,GAAG,EAClC,CAAC,GAAQ,KAAa,EAAS,GAAG,EAClC,CAAC,GAAY,KAAiB,EAAS,GAAM,EAE7C,IAAe,OAAO,MAA8B;AACxD,MAAI,EAAY;AAChB,MAAI,EAAK,MAAM,KAAK,IAAI;AACtB,KAAU,4BAA4B,UAAU;AAChD;;EAEF,IAAM,IAAe,EAAM,MAAM,MAAS,EAAK,OAAO,EAAO,EACvD,IAAc,EAAO,MAAM,KAAK,KAAK,KAAA,IAAY,OAAO,EAAO,EAI/D,IAA4B;GAChC,MAAM,EAAK,MAAM;GACjB,aAAa,EAAY,MAAM;GAC/B;GACA,UAAU;GACV,GAAI,IAAY,EAAE,cAAW,GAAG,EAAE;GAClC,GAAI,IAAU,EAAE,YAAS,GAAG,EAAE;GAC9B,GAAI,MAAgB,KAAA,KAAa,CAAC,OAAO,MAAM,EAAY,GAAG,EAAE,QAAQ,GAAa,GAAG,EAAE;GAC1F,GAAI,IAAe;IAAE,QAAQ,EAAa;IAAI,UAAU,EAAa;IAAM,GAAG,EAAE;GACjF;AACD,IAAc,GAAK;AACnB,MAAI;AAGF,GAFA,MAAM,EAAW,EAAmB,EACpC,EAAU,MAAW,aAAa,wBAAwB,mBAAmB,UAAU,EACvF,EAAS,+BAA+B;WACjC,GAAO;AACd,KAAU,aAAiB,QAAQ,EAAM,UAAU,4BAA4B,QAAQ;YAC/E;AACR,KAAc,GAAM;;;AAOxB,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,OAAD,EAAA,UAAA;IACE,kBAAC,MAAD;KAAI,WAAU;eACZ,kBAAC,GAAD,EAAA,UAAc,kBAA6B,CAAA;KACxC,CAAA;IACL,kBAAC,KAAD;KAAG,WAAU;eAA8B;KAAsC,CAAA;IACjF,kBAAC,GAAD;KAAa,WAAU;eAAO;KAGhB,CAAA;IACV,EAAA,CAAA;GACN,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD,EAAc,WAAU,WAAY,CAAA,EAAA,kBAEhC;OACN,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,SAAD;OAAO,SAAQ;OAAS,WAAU;iBAAsB;OAEhD,CAAA,EACR,kBAAC,GAAD;OACE,IAAG;OACH,aAAY;OACZ,OAAO;OACP,UAAU;OACV,WAAW,MAAM,EAAQ,EAAE,OAAO,MAAM;OACxC,CAAA,CACE;;KACN,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,SAAD;OAAO,SAAQ;OAAS,WAAU;iBAAsB;OAEhD,CAAA,EACR,kBAAC,GAAD;OACE,IAAG;OACH,aAAY;OACZ,MAAM;OACN,OAAO;OACP,UAAU;OACV,WAAW,MAAM,EAAe,EAAE,OAAO,MAAM;OAC/C,CAAA,CACE;;KACL,EAAM,SAAS,IACd,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,SAAD;OAAO,SAAQ;OAAS,WAAU;iBAAsB;OAEhD,CAAA,EACR,kBAAC,UAAD;OACE,IAAG;OACH,WApDZ;OAqDY,OAAO;OACP,UAAU;OACV,WAAW,MAAM,EAAU,EAAE,OAAO,MAAM;iBAL5C,CAOE,kBAAC,UAAD;QAAQ,OAAM;kBAAG;QAAmB,CAAA,EACnC,EAAM,KAAK,MACV,kBAAC,UAAD;QAAsB,OAAO,EAAK;kBAC/B,EAAK;QACC,EAFI,EAAK,GAET,CACT,CACK;SACL;UACJ;KACJ,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,SAAD;QAAO,SAAQ;QAAU,WAAU;kBAAsB;QAEjD,CAAA,EACR,kBAAC,GAAD;QACE,IAAG;QACH,MAAK;QACL,OAAO;QACP,UAAU;QACV,WAAW,MAAM,EAAa,EAAE,OAAO,MAAM;QAC7C,CAAA,CACE;UACN,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,SAAD;QAAO,SAAQ;QAAQ,WAAU;kBAAsB;QAE/C,CAAA,EACR,kBAAC,GAAD;QACE,IAAG;QACH,MAAK;QACL,OAAO;QACP,UAAU;QACV,WAAW,MAAM,EAAW,EAAE,OAAO,MAAM;QAC3C,CAAA,CACE;SACF;;KACN,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,SAAD;OAAO,SAAQ;OAAW,WAAU;iBAAsB;OAElD,CAAA,EACR,kBAAC,GAAD;OACE,IAAG;OACH,MAAK;OACL,aAAY;OACZ,OAAO;OACP,UAAU;OACV,WAAW,MAAM,EAAU,EAAE,OAAO,MAAM;OAC1C,CAAA,CACE;;KACF;MACQ,EAAA,CAAA;GAChB,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD;KAAQ,SAAQ;KAAU,UAAU;KAAY,eAAe,EAAa,WAAW;eAAE;KAEhF,CAAA,EACT,kBAAC,GAAD;KAAQ,UAAU;KAAY,eAAe,EAAa,SAAS;eAAnE,CACE,kBAAC,GAAD,EAAM,WAAU,gBAAiB,CAAA,EAChC,IAAa,YAAY,iBACnB;OACL;;GACF"}
|
|
1
|
+
{"version":3,"file":"ProjectsCreateProjectPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/ProjectsCreateProjectPagePage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport {\n Button,\n EmphasisPanel,\n GradientText,\n Input,\n PagePurpose,\n Textarea,\n} from '@burdenoff/fe-libs/ui';\nimport { useGlobalUi } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { FolderKanban, Save } from 'lucide-react';\nimport { useNavigate } from 'react-router-dom';\nimport { useCrewFoundryStore, type Project } from '../store/crewfoundryStore';\n\nexport function ProjectsCreateProjectPagePage() {\n const navigate = useNavigate();\n const { showToast } = useGlobalUi();\n const addProject = useCrewFoundryStore((state) => state.addProject);\n const teams = useCrewFoundryStore((state) => state.teams);\n\n const [name, setName] = useState('');\n const [description, setDescription] = useState('');\n const [startDate, setStartDate] = useState('');\n const [endDate, setEndDate] = useState('');\n const [budget, setBudget] = useState('');\n const [teamId, setTeamId] = useState('');\n const [submitting, setSubmitting] = useState(false);\n\n const handleCreate = async (status: Project['status']) => {\n if (submitting) return;\n if (name.trim() === '') {\n showToast('Project Name is required', 'warning');\n return;\n }\n const selectedTeam = teams.find((team) => team.id === teamId);\n const budgetValue = budget.trim() === '' ? undefined : Number(budget);\n // CreateCrewProjectInput only accepts a known field subset; build exactly\n // that shape. The store replaces this optimistic row with the server's\n // complete Project, so display-only fields need not be provided here.\n const payload: Partial<Project> = {\n name: name.trim(),\n description: description.trim(),\n status,\n priority: 'medium',\n ...(startDate ? { startDate } : {}),\n ...(endDate ? { endDate } : {}),\n ...(budgetValue !== undefined && !Number.isNaN(budgetValue) ? { budget: budgetValue } : {}),\n ...(selectedTeam ? { teamId: selectedTeam.id, teamName: selectedTeam.name } : {}),\n };\n setSubmitting(true);\n try {\n await addProject(payload as Project);\n showToast(status === 'planning' ? 'Draft project saved' : 'Project created', 'success');\n navigate('../projects/projects-page');\n } catch (error) {\n showToast(error instanceof Error ? error.message : 'Unable to create project', 'error');\n } finally {\n setSubmitting(false);\n }\n };\n\n const selectClass =\n 'flex h-10 w-full rounded-input border border-border-default bg-bg-surface px-3 py-2 text-sm text-text-primary transition-colors duration-200 focus-visible:border-border-focus focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50';\n\n return (\n <div className=\"space-y-6 p-6 max-w-3xl\">\n <div>\n <h1 className=\"text-2xl font-semibold\">\n <GradientText>Create Project</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">Set up a new project for your team</p>\n <PagePurpose className=\"mt-1\">\n Start a new project — define its scope, budget, and team here so you can begin tracking\n work toward a clear goal.\n </PagePurpose>\n </div>\n <EmphasisPanel>\n <div className=\"mb-4 flex items-center gap-2 text-lg font-semibold\">\n <FolderKanban className=\"h-5 w-5\" />\n Project Details\n </div>\n <div className=\"space-y-4\">\n <div className=\"space-y-2\">\n <label htmlFor=\"cpName\" className=\"text-sm font-medium\">\n Project Name\n </label>\n <Input\n id=\"cpName\"\n placeholder=\"e.g. HR Analytics Dashboard v3\"\n value={name}\n disabled={submitting}\n onChange={(e) => setName(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <label htmlFor=\"cpDesc\" className=\"text-sm font-medium\">\n Description\n </label>\n <Textarea\n id=\"cpDesc\"\n placeholder=\"Describe the project objectives and scope...\"\n rows={3}\n value={description}\n disabled={submitting}\n onChange={(e) => setDescription(e.target.value)}\n />\n </div>\n {teams.length > 0 ? (\n <div className=\"space-y-2\">\n <label htmlFor=\"cpTeam\" className=\"text-sm font-medium\">\n Team\n </label>\n <select\n id=\"cpTeam\"\n className={selectClass}\n value={teamId}\n disabled={submitting}\n onChange={(e) => setTeamId(e.target.value)}\n >\n <option value=\"\">Unassigned</option>\n {teams.map((team) => (\n <option key={team.id} value={team.id}>\n {team.name}\n </option>\n ))}\n </select>\n </div>\n ) : null}\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div className=\"space-y-2\">\n <label htmlFor=\"cpStart\" className=\"text-sm font-medium\">\n Start Date\n </label>\n <Input\n id=\"cpStart\"\n type=\"date\"\n value={startDate}\n disabled={submitting}\n onChange={(e) => setStartDate(e.target.value)}\n />\n </div>\n <div className=\"space-y-2\">\n <label htmlFor=\"cpEnd\" className=\"text-sm font-medium\">\n End Date\n </label>\n <Input\n id=\"cpEnd\"\n type=\"date\"\n value={endDate}\n disabled={submitting}\n onChange={(e) => setEndDate(e.target.value)}\n />\n </div>\n </div>\n <div className=\"space-y-2\">\n <label htmlFor=\"cpBudget\" className=\"text-sm font-medium\">\n Budget ($)\n </label>\n <Input\n id=\"cpBudget\"\n type=\"number\"\n placeholder=\"e.g. 250000\"\n value={budget}\n disabled={submitting}\n onChange={(e) => setBudget(e.target.value)}\n />\n </div>\n </div>\n </EmphasisPanel>\n <div className=\"flex justify-end gap-2\">\n <Button variant=\"outline\" disabled={submitting} onClick={() => handleCreate('planning')}>\n Save as Draft\n </Button>\n <Button disabled={submitting} onClick={() => handleCreate('active')}>\n <Save className=\"h-4 w-4 mr-1\" />\n {submitting ? 'Saving…' : 'Create Project'}\n </Button>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|