@burdenoff/microfe-crewfoundry 2026.703.1 → 2026.704.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/crewfoundry/pages/AdminAdminPagePage.js +117 -164
- package/dist/crewfoundry/pages/AdminAdminPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/AnalyticsAnalyticsPagePage.js +99 -82
- package/dist/crewfoundry/pages/AnalyticsAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/AnalyticsEmployeeAnalyticsPagePage.js +160 -192
- package/dist/crewfoundry/pages/AnalyticsEmployeeAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js +238 -231
- package/dist/crewfoundry/pages/AnalyticsFinancialAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.js +196 -166
- package/dist/crewfoundry/pages/AnalyticsHiringAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsCallsPagePage.js +45 -147
- package/dist/crewfoundry/pages/CommunicationsCallsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsDirectoryPagePage.js +20 -11
- package/dist/crewfoundry/pages/CommunicationsDirectoryPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsFilesPagePage.js +45 -152
- package/dist/crewfoundry/pages/CommunicationsFilesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js +50 -138
- package/dist/crewfoundry/pages/CommunicationsMessagesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsTeamsPagePage.js +149 -67
- package/dist/crewfoundry/pages/CommunicationsTeamsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CommunicationsVideoCallsPagePage.js +50 -201
- package/dist/crewfoundry/pages/CommunicationsVideoCallsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js +205 -136
- package/dist/crewfoundry/pages/CompanyClientManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyCompanyDashboardPagePage.js +25 -31
- package/dist/crewfoundry/pages/CompanyCompanyDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyCompanyProfilePagePage.js +118 -104
- package/dist/crewfoundry/pages/CompanyCompanyProfilePagePage.js.map +1 -1
- package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js +117 -58
- package/dist/crewfoundry/pages/CompanyVendorManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/DashboardAnalyticsPagePage.js +90 -94
- package/dist/crewfoundry/pages/DashboardAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/DashboardDashboardPagePage.js +210 -191
- package/dist/crewfoundry/pages/DashboardDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/DashboardEnhancedDashboardPagePage.js +213 -180
- package/dist/crewfoundry/pages/DashboardEnhancedDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/DashboardExecutiveDashboardPage.js +133 -264
- package/dist/crewfoundry/pages/DashboardExecutiveDashboardPage.js.map +1 -1
- package/dist/crewfoundry/pages/HelpApiDocumentationPagePage.js +279 -212
- package/dist/crewfoundry/pages/HelpApiDocumentationPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringApplicationsPagePage.js +131 -105
- package/dist/crewfoundry/pages/HiringApplicationsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringCandidatesPagePage.js +167 -148
- package/dist/crewfoundry/pages/HiringCandidatesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringCreateJobPagePage.js +3 -3
- package/dist/crewfoundry/pages/HiringCreateJobPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringInterviewsPagePage.js +13 -5
- package/dist/crewfoundry/pages/HiringInterviewsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js +151 -152
- package/dist/crewfoundry/pages/HiringJobDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HiringJobsPagePage.js +38 -21
- package/dist/crewfoundry/pages/HiringJobsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrDepartmentsPagePage.js +3 -3
- package/dist/crewfoundry/pages/HrDepartmentsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrEmployeesPagePage.js +134 -127
- package/dist/crewfoundry/pages/HrEmployeesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js +163 -132
- package/dist/crewfoundry/pages/HrLeaveManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrPayrollPagePage.js +202 -160
- package/dist/crewfoundry/pages/HrPayrollPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js +104 -91
- package/dist/crewfoundry/pages/HrTimeTrackingPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningAssessmentsPagePage.js +29 -147
- package/dist/crewfoundry/pages/LearningAssessmentsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCertificatesPagePage.js +22 -106
- package/dist/crewfoundry/pages/LearningCertificatesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js +74 -74
- package/dist/crewfoundry/pages/LearningCourseDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js +101 -97
- package/dist/crewfoundry/pages/LearningCourseLearningPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningCoursesPagePage.js +64 -47
- package/dist/crewfoundry/pages/LearningCoursesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningAnalyticsPagePage.js +111 -121
- package/dist/crewfoundry/pages/LearningLearningAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningPagePage.js +131 -110
- package/dist/crewfoundry/pages/LearningLearningPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js +65 -64
- package/dist/crewfoundry/pages/LearningLearningPathDetailPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js +58 -43
- package/dist/crewfoundry/pages/LearningLearningPathsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/LearningMyLearningPagePage.js +66 -82
- package/dist/crewfoundry/pages/LearningMyLearningPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceBookingManagementPagePage.js +38 -88
- package/dist/crewfoundry/pages/MarketplaceBookingManagementPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceEarningsPagePage.js +59 -65
- package/dist/crewfoundry/pages/MarketplaceEarningsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePageEnhancedPage.js +209 -323
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePageEnhancedPage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js +175 -220
- package/dist/crewfoundry/pages/MarketplaceFreelancerProfilePagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js +74 -59
- package/dist/crewfoundry/pages/MarketplaceMarketplacePagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js +96 -80
- package/dist/crewfoundry/pages/MarketplaceMarketplaceServicesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMessagingPagePage.js +28 -100
- package/dist/crewfoundry/pages/MarketplaceMessagingPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceMyServicesPagePage.js +27 -20
- package/dist/crewfoundry/pages/MarketplaceMyServicesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceProjectDetailsPagePage.js +73 -73
- package/dist/crewfoundry/pages/MarketplaceProjectDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js +62 -56
- package/dist/crewfoundry/pages/MarketplaceServiceDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsEscrowPagePage.js +40 -138
- package/dist/crewfoundry/pages/PaymentsEscrowPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js +126 -93
- package/dist/crewfoundry/pages/PaymentsInvoicesPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsPaymentDashboardPagePage.js +99 -77
- package/dist/crewfoundry/pages/PaymentsPaymentDashboardPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/PaymentsSecurityPagePage.js +73 -74
- package/dist/crewfoundry/pages/PaymentsSecurityPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/ProjectsCreateProjectPagePage.js +1 -1
- package/dist/crewfoundry/pages/ProjectsCreateProjectPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/ProjectsProjectDetailsPagePage.js +122 -122
- package/dist/crewfoundry/pages/ProjectsProjectDetailsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js +130 -113
- package/dist/crewfoundry/pages/ProjectsProjectsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamAnalyticsPagePage.js +68 -59
- package/dist/crewfoundry/pages/TeamsTeamAnalyticsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamDetailPagePage.js +73 -62
- package/dist/crewfoundry/pages/TeamsTeamDetailPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamDirectoryPagePage.js +82 -58
- package/dist/crewfoundry/pages/TeamsTeamDirectoryPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamSettingsPagePage.js +153 -153
- package/dist/crewfoundry/pages/TeamsTeamSettingsPagePage.js.map +1 -1
- package/dist/crewfoundry/pages/TeamsTeamsPagePage.js +63 -48
- package/dist/crewfoundry/pages/TeamsTeamsPagePage.js.map +1 -1
- package/dist/crewfoundry/store/crewfoundryStore.js +35 -3
- package/dist/crewfoundry/store/crewfoundryStore.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { useCrewFoundryStore as e } from "../store/crewfoundryStore.js";
|
|
2
2
|
import { FormModal as t, useFormModal as n } from "../components/forms/FormModal.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { useState as r } from "react";
|
|
4
|
+
import { Building2 as i, DollarSign as a, FolderKanban as o, Pencil as s, Plus as ee, Search as c, Trash2 as l } from "lucide-react";
|
|
5
|
+
import { jsx as u, jsxs as d } from "react/jsx-runtime";
|
|
6
|
+
import { AlertDialog as f, AlertDialogAction as p, AlertDialogCancel as m, AlertDialogContent as h, AlertDialogDescription as g, AlertDialogFooter as _, AlertDialogHeader as te, AlertDialogTitle as ne, AlertDialogTrigger as re, Badge as ie, Button as v, Card as y, CardContent as b, CardHeader as x, CardTitle as S, GlassCard as C, GradientText as w, IllustratedEmptyState as T, Input as E, PagePurpose as D, Pagination as O, ResponsiveTable as k, Select as A, SelectContent as j, SelectItem as M, SelectTrigger as N, SelectValue as ae } from "@burdenoff/fe-libs/ui";
|
|
7
|
+
import { usePagination as P } from "@burdenoff/fe-libs/shared/hooks";
|
|
6
8
|
//#region src/crewfoundry/pages/CompanyClientManagementPagePage.tsx
|
|
7
|
-
var
|
|
9
|
+
var F = [
|
|
8
10
|
{
|
|
9
11
|
name: "name",
|
|
10
12
|
label: "Client name",
|
|
@@ -65,7 +67,7 @@ var k = [
|
|
|
65
67
|
label: "Client since",
|
|
66
68
|
type: "date"
|
|
67
69
|
}
|
|
68
|
-
],
|
|
70
|
+
], I = (e) => ({
|
|
69
71
|
name: e.name,
|
|
70
72
|
industry: e.industry,
|
|
71
73
|
contactPerson: e.contactPerson,
|
|
@@ -75,7 +77,7 @@ var k = [
|
|
|
75
77
|
revenue: e.revenue,
|
|
76
78
|
projects: e.projects,
|
|
77
79
|
since: e.since ? e.since.slice(0, 10) : ""
|
|
78
|
-
}),
|
|
80
|
+
}), L = (e, t) => ({
|
|
79
81
|
id: t?.id ?? crypto.randomUUID(),
|
|
80
82
|
name: String(e.name ?? ""),
|
|
81
83
|
industry: String(e.industry ?? ""),
|
|
@@ -86,199 +88,266 @@ var k = [
|
|
|
86
88
|
revenue: typeof e.revenue == "number" ? e.revenue : Number(e.revenue) || 0,
|
|
87
89
|
projects: typeof e.projects == "number" ? e.projects : Number(e.projects) || 0,
|
|
88
90
|
since: String(e.since ?? "")
|
|
89
|
-
});
|
|
90
|
-
function
|
|
91
|
-
let { clients:
|
|
92
|
-
|
|
91
|
+
}), R = (e) => e === "active" ? "default" : e === "prospect" ? "secondary" : "destructive";
|
|
92
|
+
function z() {
|
|
93
|
+
let { clients: z, addClient: B, updateClient: V, removeClient: H } = e(), U = n(), [W, G] = r(""), [K, q] = r("all"), { page: J, pageSize: Y, offset: X, setPage: Z } = P({ initialPageSize: 25 }), Q = z.reduce((e, t) => e + t.revenue, 0), oe = z.filter((e) => e.status === "active"), $ = z.filter((e) => {
|
|
94
|
+
let t = `${e.name} ${e.industry} ${e.contactPerson} ${e.email}`.toLowerCase().includes(W.toLowerCase()), n = K === "all" || e.status === K;
|
|
95
|
+
return t && n;
|
|
96
|
+
}), se = $.slice(X, X + Y);
|
|
97
|
+
return /* @__PURE__ */ d("div", {
|
|
93
98
|
className: "space-y-6 p-6",
|
|
94
99
|
children: [
|
|
95
|
-
/* @__PURE__ */
|
|
100
|
+
/* @__PURE__ */ d("div", {
|
|
96
101
|
className: "flex items-center justify-between",
|
|
97
|
-
children: [/* @__PURE__ */
|
|
98
|
-
/* @__PURE__ */
|
|
102
|
+
children: [/* @__PURE__ */ d("div", { children: [
|
|
103
|
+
/* @__PURE__ */ u("h1", {
|
|
99
104
|
className: "text-2xl font-semibold",
|
|
100
|
-
children: /* @__PURE__ */
|
|
105
|
+
children: /* @__PURE__ */ u(w, { children: "Client Management" })
|
|
101
106
|
}),
|
|
102
|
-
/* @__PURE__ */
|
|
107
|
+
/* @__PURE__ */ d("p", {
|
|
103
108
|
className: "text-sm text-text-secondary",
|
|
104
109
|
children: [
|
|
105
|
-
|
|
110
|
+
z.length,
|
|
106
111
|
" clients · $",
|
|
107
|
-
(
|
|
112
|
+
(Q / 1e6).toFixed(1),
|
|
108
113
|
"M revenue"
|
|
109
114
|
]
|
|
110
115
|
}),
|
|
111
|
-
/* @__PURE__ */
|
|
116
|
+
/* @__PURE__ */ u(D, {
|
|
112
117
|
className: "mt-1",
|
|
113
118
|
children: "Keep track of the clients you work with — their contacts, status, and engagements — so account relationships never slip through the cracks."
|
|
114
119
|
})
|
|
115
|
-
] }), /* @__PURE__ */
|
|
120
|
+
] }), /* @__PURE__ */ d(v, {
|
|
116
121
|
size: "sm",
|
|
117
|
-
onClick: () =>
|
|
118
|
-
children: [/* @__PURE__ */
|
|
122
|
+
onClick: () => U.openModal(),
|
|
123
|
+
children: [/* @__PURE__ */ u(ee, { className: "h-4 w-4 mr-1" }), "Add Client"]
|
|
119
124
|
})]
|
|
120
125
|
}),
|
|
121
|
-
/* @__PURE__ */
|
|
126
|
+
/* @__PURE__ */ d("div", {
|
|
122
127
|
className: "grid gap-4 md:grid-cols-3",
|
|
123
128
|
children: [
|
|
124
|
-
/* @__PURE__ */
|
|
129
|
+
/* @__PURE__ */ d(C, {
|
|
125
130
|
treatment: "glass",
|
|
126
131
|
glow: !0,
|
|
127
132
|
className: "border-border-seam",
|
|
128
|
-
children: [/* @__PURE__ */
|
|
133
|
+
children: [/* @__PURE__ */ d(x, {
|
|
129
134
|
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
130
|
-
children: [/* @__PURE__ */
|
|
135
|
+
children: [/* @__PURE__ */ u(S, {
|
|
131
136
|
className: "text-sm font-medium",
|
|
132
137
|
children: "Active Clients"
|
|
133
|
-
}), /* @__PURE__ */
|
|
134
|
-
}), /* @__PURE__ */
|
|
138
|
+
}), /* @__PURE__ */ u(i, { className: "h-4 w-4 text-text-secondary" })]
|
|
139
|
+
}), /* @__PURE__ */ u(b, { children: /* @__PURE__ */ u("div", {
|
|
135
140
|
className: "text-2xl font-bold tabular-nums",
|
|
136
|
-
children:
|
|
141
|
+
children: oe.length
|
|
137
142
|
}) })]
|
|
138
143
|
}),
|
|
139
|
-
/* @__PURE__ */
|
|
144
|
+
/* @__PURE__ */ d(C, {
|
|
140
145
|
treatment: "metric",
|
|
141
146
|
className: "border-border-seam",
|
|
142
|
-
children: [/* @__PURE__ */
|
|
147
|
+
children: [/* @__PURE__ */ d(x, {
|
|
143
148
|
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
144
|
-
children: [/* @__PURE__ */
|
|
149
|
+
children: [/* @__PURE__ */ u(S, {
|
|
145
150
|
className: "text-sm font-medium",
|
|
146
151
|
children: "Total Revenue"
|
|
147
|
-
}), /* @__PURE__ */
|
|
148
|
-
}), /* @__PURE__ */
|
|
152
|
+
}), /* @__PURE__ */ u(a, { className: "h-4 w-4 text-text-secondary" })]
|
|
153
|
+
}), /* @__PURE__ */ u(b, { children: /* @__PURE__ */ d("div", {
|
|
149
154
|
className: "text-2xl font-bold tabular-nums",
|
|
150
155
|
children: [
|
|
151
156
|
"$",
|
|
152
|
-
(
|
|
157
|
+
(Q / 1e6).toFixed(1),
|
|
153
158
|
"M"
|
|
154
159
|
]
|
|
155
160
|
}) })]
|
|
156
161
|
}),
|
|
157
|
-
/* @__PURE__ */
|
|
162
|
+
/* @__PURE__ */ d(C, {
|
|
158
163
|
treatment: "metric",
|
|
159
164
|
className: "border-border-seam",
|
|
160
|
-
children: [/* @__PURE__ */
|
|
165
|
+
children: [/* @__PURE__ */ d(x, {
|
|
161
166
|
className: "flex flex-row items-center justify-between space-y-0 pb-2",
|
|
162
|
-
children: [/* @__PURE__ */
|
|
167
|
+
children: [/* @__PURE__ */ u(S, {
|
|
163
168
|
className: "text-sm font-medium",
|
|
164
169
|
children: "Total Projects"
|
|
165
|
-
}), /* @__PURE__ */
|
|
166
|
-
}), /* @__PURE__ */
|
|
170
|
+
}), /* @__PURE__ */ u(o, { className: "h-4 w-4 text-text-secondary" })]
|
|
171
|
+
}), /* @__PURE__ */ u(b, { children: /* @__PURE__ */ u("div", {
|
|
167
172
|
className: "text-2xl font-bold tabular-nums",
|
|
168
|
-
children:
|
|
173
|
+
children: z.reduce((e, t) => e + t.projects, 0)
|
|
169
174
|
}) })]
|
|
170
175
|
})
|
|
171
176
|
]
|
|
172
177
|
}),
|
|
173
|
-
/* @__PURE__ */
|
|
174
|
-
className: "
|
|
178
|
+
/* @__PURE__ */ d(y, { children: [/* @__PURE__ */ u(x, { children: /* @__PURE__ */ u(S, { children: "Client Portfolio" }) }), /* @__PURE__ */ d(b, {
|
|
179
|
+
className: "space-y-4",
|
|
175
180
|
children: [
|
|
176
|
-
/* @__PURE__ */
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
181
|
+
/* @__PURE__ */ d("div", {
|
|
182
|
+
className: "flex flex-col gap-2 sm:flex-row sm:items-center",
|
|
183
|
+
children: [/* @__PURE__ */ d("div", {
|
|
184
|
+
className: "relative flex-1",
|
|
185
|
+
children: [/* @__PURE__ */ u(c, { className: "absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 text-text-secondary" }), /* @__PURE__ */ u(E, {
|
|
186
|
+
placeholder: "Search clients...",
|
|
187
|
+
className: "pl-9",
|
|
188
|
+
value: W,
|
|
189
|
+
onChange: (e) => {
|
|
190
|
+
G(e.target.value), Z(1);
|
|
191
|
+
}
|
|
192
|
+
})]
|
|
193
|
+
}), /* @__PURE__ */ d(A, {
|
|
194
|
+
value: K,
|
|
195
|
+
onValueChange: (e) => {
|
|
196
|
+
q(e), Z(1);
|
|
197
|
+
},
|
|
198
|
+
children: [/* @__PURE__ */ u(N, {
|
|
199
|
+
className: "w-full sm:w-40",
|
|
200
|
+
"aria-label": "Filter by status",
|
|
201
|
+
children: /* @__PURE__ */ u(ae, {})
|
|
202
|
+
}), /* @__PURE__ */ d(j, { children: [
|
|
203
|
+
/* @__PURE__ */ u(M, {
|
|
204
|
+
value: "all",
|
|
205
|
+
children: "All statuses"
|
|
206
|
+
}),
|
|
207
|
+
/* @__PURE__ */ u(M, {
|
|
208
|
+
value: "active",
|
|
209
|
+
children: "Active"
|
|
210
|
+
}),
|
|
211
|
+
/* @__PURE__ */ u(M, {
|
|
212
|
+
value: "prospect",
|
|
213
|
+
children: "Prospect"
|
|
214
|
+
}),
|
|
215
|
+
/* @__PURE__ */ u(M, {
|
|
216
|
+
value: "churned",
|
|
217
|
+
children: "Churned"
|
|
218
|
+
})
|
|
219
|
+
] })]
|
|
220
|
+
})]
|
|
182
221
|
}),
|
|
183
|
-
/* @__PURE__ */
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
222
|
+
/* @__PURE__ */ u(k, {
|
|
223
|
+
data: se,
|
|
224
|
+
rowKey: (e) => e.id,
|
|
225
|
+
columns: [
|
|
226
|
+
{
|
|
227
|
+
key: "name",
|
|
228
|
+
header: "Client",
|
|
229
|
+
priority: "primary",
|
|
230
|
+
cell: (e) => /* @__PURE__ */ u("span", {
|
|
231
|
+
className: "font-medium",
|
|
232
|
+
children: e.name
|
|
233
|
+
})
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
key: "industry",
|
|
237
|
+
header: "Industry",
|
|
238
|
+
priority: "secondary",
|
|
239
|
+
cell: (e) => /* @__PURE__ */ u("span", {
|
|
240
|
+
className: "text-text-secondary",
|
|
241
|
+
children: e.industry
|
|
242
|
+
})
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
key: "contact",
|
|
246
|
+
header: "Contact",
|
|
247
|
+
priority: "secondary",
|
|
248
|
+
cell: (e) => /* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("p", {
|
|
249
|
+
className: "text-xs",
|
|
250
|
+
children: e.contactPerson
|
|
251
|
+
}), /* @__PURE__ */ u("p", {
|
|
252
|
+
className: "text-xs text-text-secondary",
|
|
253
|
+
children: e.email
|
|
254
|
+
})] })
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
key: "revenue",
|
|
258
|
+
header: "Revenue",
|
|
259
|
+
priority: "secondary",
|
|
260
|
+
headerClassName: "text-right",
|
|
261
|
+
cellClassName: "text-right",
|
|
262
|
+
cell: (e) => /* @__PURE__ */ d("span", { children: [
|
|
263
|
+
"$",
|
|
264
|
+
(e.revenue / 1e3).toFixed(0),
|
|
265
|
+
"K"
|
|
266
|
+
] })
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
key: "projects",
|
|
270
|
+
header: "Projects",
|
|
271
|
+
priority: "hidden-on-mobile",
|
|
272
|
+
headerClassName: "text-right",
|
|
273
|
+
cellClassName: "text-right",
|
|
274
|
+
cell: (e) => /* @__PURE__ */ u("span", { children: e.projects })
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
key: "since",
|
|
278
|
+
header: "Since",
|
|
279
|
+
priority: "hidden-on-mobile",
|
|
280
|
+
cell: (e) => /* @__PURE__ */ u("span", {
|
|
281
|
+
className: "text-text-secondary",
|
|
282
|
+
children: e.since
|
|
283
|
+
})
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
key: "status",
|
|
287
|
+
header: "Status",
|
|
288
|
+
priority: "secondary",
|
|
289
|
+
cell: (e) => /* @__PURE__ */ u(ie, {
|
|
290
|
+
variant: R(e.status),
|
|
291
|
+
className: "text-[10px]",
|
|
292
|
+
children: e.status
|
|
293
|
+
})
|
|
294
|
+
}
|
|
295
|
+
],
|
|
296
|
+
emptyState: /* @__PURE__ */ u(T, {
|
|
297
|
+
illustration: "empty-search",
|
|
298
|
+
title: "No clients match",
|
|
299
|
+
description: "Try a different search term or status filter."
|
|
300
|
+
}),
|
|
301
|
+
rowActions: (e) => /* @__PURE__ */ d("div", {
|
|
302
|
+
className: "flex items-center justify-end gap-1",
|
|
303
|
+
children: [/* @__PURE__ */ u(v, {
|
|
250
304
|
variant: "ghost",
|
|
251
305
|
size: "icon",
|
|
252
|
-
"aria-label": `
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
306
|
+
"aria-label": `Edit ${e.name}`,
|
|
307
|
+
onClick: () => U.openModal(e),
|
|
308
|
+
children: /* @__PURE__ */ u(s, { className: "h-4 w-4" })
|
|
309
|
+
}), /* @__PURE__ */ d(f, { children: [/* @__PURE__ */ u(re, {
|
|
310
|
+
asChild: !0,
|
|
311
|
+
children: /* @__PURE__ */ u(v, {
|
|
312
|
+
variant: "ghost",
|
|
313
|
+
size: "icon",
|
|
314
|
+
"aria-label": `Delete ${e.name}`,
|
|
315
|
+
children: /* @__PURE__ */ u(l, { className: "h-4 w-4 text-status-error-text" })
|
|
316
|
+
})
|
|
317
|
+
}), /* @__PURE__ */ d(h, { children: [/* @__PURE__ */ d(te, { children: [/* @__PURE__ */ u(ne, { children: "Delete client?" }), /* @__PURE__ */ d(g, { children: [
|
|
318
|
+
"This removes “",
|
|
319
|
+
e.name,
|
|
320
|
+
"” from your client portfolio. This action cannot be undone."
|
|
321
|
+
] })] }), /* @__PURE__ */ d(_, { children: [/* @__PURE__ */ u(m, { children: "Cancel" }), /* @__PURE__ */ u(p, {
|
|
322
|
+
onClick: () => void H(e.id),
|
|
323
|
+
children: "Delete"
|
|
324
|
+
})] })] })] })]
|
|
325
|
+
})
|
|
326
|
+
}),
|
|
327
|
+
$.length > Y && /* @__PURE__ */ u(O, {
|
|
328
|
+
page: J,
|
|
329
|
+
pageSize: Y,
|
|
330
|
+
totalItems: $.length,
|
|
331
|
+
onPageChange: Z
|
|
263
332
|
})
|
|
264
333
|
]
|
|
265
|
-
}
|
|
266
|
-
/* @__PURE__ */
|
|
267
|
-
open:
|
|
268
|
-
onOpenChange:
|
|
269
|
-
title:
|
|
334
|
+
})] }),
|
|
335
|
+
/* @__PURE__ */ u(t, {
|
|
336
|
+
open: U.open,
|
|
337
|
+
onOpenChange: U.onOpenChange,
|
|
338
|
+
title: U.context ? "Edit client" : "Add client",
|
|
270
339
|
description: "Track the client relationship, contacts, and engagement value.",
|
|
271
|
-
fields:
|
|
272
|
-
initialValues:
|
|
273
|
-
submitLabel:
|
|
340
|
+
fields: F,
|
|
341
|
+
initialValues: U.context ? I(U.context) : void 0,
|
|
342
|
+
submitLabel: U.context ? "Save changes" : "Add client",
|
|
274
343
|
onSubmit: async (e) => {
|
|
275
|
-
|
|
344
|
+
U.context ? await V(U.context.id, L(e, U.context)) : await B(L(e));
|
|
276
345
|
}
|
|
277
346
|
})
|
|
278
347
|
]
|
|
279
348
|
});
|
|
280
349
|
}
|
|
281
350
|
//#endregion
|
|
282
|
-
export {
|
|
351
|
+
export { z as CompanyClientManagementPagePage };
|
|
283
352
|
|
|
284
353
|
//# sourceMappingURL=CompanyClientManagementPagePage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CompanyClientManagementPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/CompanyClientManagementPagePage.tsx"],"sourcesContent":["import {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n AlertDialogTrigger,\n Badge,\n Button,\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\nimport { Building2, DollarSign, FolderKanban, 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 Client } from '../store/crewfoundryStore';\n\nconst CLIENT_FIELDS: FieldConfig[] = [\n { name: 'name', label: 'Client name', type: 'text', required: true },\n { name: 'industry', label: 'Industry', type: 'text' },\n { name: 'contactPerson', label: 'Contact person', type: 'text' },\n { name: 'email', label: 'Contact email', type: 'email' },\n { name: 'phone', label: 'Phone', type: 'text' },\n {\n name: 'status',\n label: 'Status',\n type: 'select',\n options: [\n { label: 'Active', value: 'active' },\n { label: 'Prospect', value: 'prospect' },\n { label: 'Churned', value: 'churned' },\n ],\n },\n { name: 'revenue', label: 'Revenue (USD)', type: 'number' },\n { name: 'projects', label: 'Projects', type: 'number' },\n { name: 'since', label: 'Client since', type: 'date' },\n];\n\nconst toInitialValues = (client: Client): FormValues => ({\n name: client.name,\n industry: client.industry,\n contactPerson: client.contactPerson,\n email: client.email,\n phone: client.phone,\n status: client.status,\n revenue: client.revenue,\n projects: client.projects,\n since: client.since ? client.since.slice(0, 10) : '',\n});\n\nconst valuesToClient = (values: FormValues, base?: Client): Client => ({\n id: base?.id ?? crypto.randomUUID(),\n name: String(values.name ?? ''),\n industry: String(values.industry ?? ''),\n contactPerson: String(values.contactPerson ?? ''),\n email: String(values.email ?? ''),\n phone: String(values.phone ?? ''),\n status: (values.status as Client['status']) || 'prospect',\n revenue: typeof values.revenue === 'number' ? values.revenue : Number(values.revenue) || 0,\n projects: typeof values.projects === 'number' ? values.projects : Number(values.projects) || 0,\n since: String(values.since ?? ''),\n});\n\nexport function CompanyClientManagementPagePage() {\n const { clients, addClient, updateClient, removeClient } = useCrewFoundryStore();\n const modal = useFormModal<Client>();\n const totalRevenue = clients.reduce((s, c) => s + c.revenue, 0);\n const activeClients = clients.filter((c) => c.status === 'active');\n\n const handleSubmit = async (values: FormValues) => {\n if (modal.context) {\n await updateClient(modal.context.id, valuesToClient(values, modal.context));\n } else {\n await addClient(valuesToClient(values));\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>Client Management</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n {clients.length} clients · ${(totalRevenue / 1000000).toFixed(1)}M revenue\n </p>\n <PagePurpose className=\"mt-1\">Keep track of the clients you work with — their contacts, status, and engagements — so account relationships never slip through the cracks.</PagePurpose>\n </div>\n <Button size=\"sm\" onClick={() => modal.openModal()}>\n <Plus className=\"h-4 w-4 mr-1\" />\n Add Client\n </Button>\n </div>\n <div className=\"grid gap-4 md:grid-cols-3\">\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\">Active Clients</CardTitle>\n <Building2 className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{activeClients.length}</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\">Total Revenue</CardTitle>\n <DollarSign className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">\n ${(totalRevenue / 1000000).toFixed(1)}M\n </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\">Total Projects</CardTitle>\n <FolderKanban className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">\n {clients.reduce((s, c) => s + c.projects, 0)}\n </div>\n </CardContent>\n </GlassCard>\n </div>\n <Card>\n <CardHeader>\n <CardTitle>Client Portfolio</CardTitle>\n </CardHeader>\n <CardContent>\n <div className=\"grid grid-cols-8 gap-2 text-xs font-medium text-text-secondary border-b pb-2 mb-2\">\n <span>Client</span>\n <span>Industry</span>\n <span>Contact</span>\n <span className=\"text-right\">Revenue</span>\n <span className=\"text-right\">Projects</span>\n <span>Since</span>\n <span className=\"text-center\">Status</span>\n <span className=\"text-right\">Actions</span>\n </div>\n {clients.map((c) => (\n <div key={c.id} className=\"grid grid-cols-8 gap-2 py-2 border-b last:border-0 text-sm\">\n <span className=\"font-medium\">{c.name}</span>\n <span className=\"text-text-secondary\">{c.industry}</span>\n <div>\n <p className=\"text-xs\">{c.contactPerson}</p>\n <p className=\"text-xs text-text-secondary\">{c.email}</p>\n </div>\n <span className=\"text-right\">${(c.revenue / 1000).toFixed(0)}K</span>\n <span className=\"text-right\">{c.projects}</span>\n <span className=\"text-text-secondary\">{c.since}</span>\n <div className=\"text-center\">\n <Badge\n variant={\n c.status === 'active'\n ? 'default'\n : c.status === 'prospect'\n ? 'secondary'\n : 'destructive'\n }\n className=\"text-[10px]\"\n >\n {c.status}\n </Badge>\n </div>\n <div className=\"flex items-center justify-end gap-1\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={`Edit ${c.name}`}\n onClick={() => modal.openModal(c)}\n >\n <Pencil className=\"h-4 w-4\" />\n </Button>\n <AlertDialog>\n <AlertDialogTrigger asChild>\n <Button variant=\"ghost\" size=\"icon\" aria-label={`Delete ${c.name}`}>\n <Trash2 className=\"h-4 w-4 text-status-error-text\" />\n </Button>\n </AlertDialogTrigger>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>Delete client?</AlertDialogTitle>\n <AlertDialogDescription>\n This removes “{c.name}” from your client portfolio. This action cannot be undone.\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel>Cancel</AlertDialogCancel>\n <AlertDialogAction onClick={() => void removeClient(c.id)}>\n Delete\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n </div>\n </div>\n ))}\n </CardContent>\n </Card>\n\n <FormModal\n open={modal.open}\n onOpenChange={modal.onOpenChange}\n title={modal.context ? 'Edit client' : 'Add client'}\n description=\"Track the client relationship, contacts, and engagement value.\"\n fields={CLIENT_FIELDS}\n initialValues={modal.context ? toInitialValues(modal.context) : undefined}\n submitLabel={modal.context ? 'Save changes' : 'Add client'}\n onSubmit={handleSubmit}\n />\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CompanyClientManagementPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/CompanyClientManagementPagePage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n AlertDialogTrigger,\n Badge,\n Button,\n Card,\n CardContent,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n Input,\n PagePurpose,\n Pagination,\n ResponsiveTable,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n type ResponsiveTableColumn,\n} from '@burdenoff/fe-libs/ui';\nimport { usePagination } from '@burdenoff/fe-libs/shared/hooks';\nimport { Building2, DollarSign, FolderKanban, Pencil, Plus, Search, Trash2 } from 'lucide-react';\nimport {\n FormModal,\n useFormModal,\n type FieldConfig,\n type FormValues,\n} from '../components/forms/FormModal';\nimport { useCrewFoundryStore, type Client } from '../store/crewfoundryStore';\n\nconst CLIENT_FIELDS: FieldConfig[] = [\n { name: 'name', label: 'Client name', type: 'text', required: true },\n { name: 'industry', label: 'Industry', type: 'text' },\n { name: 'contactPerson', label: 'Contact person', type: 'text' },\n { name: 'email', label: 'Contact email', type: 'email' },\n { name: 'phone', label: 'Phone', type: 'text' },\n {\n name: 'status',\n label: 'Status',\n type: 'select',\n options: [\n { label: 'Active', value: 'active' },\n { label: 'Prospect', value: 'prospect' },\n { label: 'Churned', value: 'churned' },\n ],\n },\n { name: 'revenue', label: 'Revenue (USD)', type: 'number' },\n { name: 'projects', label: 'Projects', type: 'number' },\n { name: 'since', label: 'Client since', type: 'date' },\n];\n\nconst toInitialValues = (client: Client): FormValues => ({\n name: client.name,\n industry: client.industry,\n contactPerson: client.contactPerson,\n email: client.email,\n phone: client.phone,\n status: client.status,\n revenue: client.revenue,\n projects: client.projects,\n since: client.since ? client.since.slice(0, 10) : '',\n});\n\nconst valuesToClient = (values: FormValues, base?: Client): Client => ({\n id: base?.id ?? crypto.randomUUID(),\n name: String(values.name ?? ''),\n industry: String(values.industry ?? ''),\n contactPerson: String(values.contactPerson ?? ''),\n email: String(values.email ?? ''),\n phone: String(values.phone ?? ''),\n status: (values.status as Client['status']) || 'prospect',\n revenue: typeof values.revenue === 'number' ? values.revenue : Number(values.revenue) || 0,\n projects: typeof values.projects === 'number' ? values.projects : Number(values.projects) || 0,\n since: String(values.since ?? ''),\n});\n\nconst statusVariant = (status: Client['status']) =>\n status === 'active' ? 'default' : status === 'prospect' ? 'secondary' : 'destructive';\n\nexport function CompanyClientManagementPagePage() {\n const { clients, addClient, updateClient, removeClient } = useCrewFoundryStore();\n const modal = useFormModal<Client>();\n const [search, setSearch] = useState('');\n const [filterStatus, setFilterStatus] = useState<string>('all');\n const { page, pageSize, offset, setPage } = usePagination({ initialPageSize: 25 });\n\n const totalRevenue = clients.reduce((s, c) => s + c.revenue, 0);\n const activeClients = clients.filter((c) => c.status === 'active');\n\n const filtered = clients.filter((c) => {\n const matchSearch = `${c.name} ${c.industry} ${c.contactPerson} ${c.email}`\n .toLowerCase()\n .includes(search.toLowerCase());\n const matchStatus = filterStatus === 'all' || c.status === filterStatus;\n return matchSearch && matchStatus;\n });\n const paged = filtered.slice(offset, offset + pageSize);\n\n const handleSubmit = async (values: FormValues) => {\n if (modal.context) {\n await updateClient(modal.context.id, valuesToClient(values, modal.context));\n } else {\n await addClient(valuesToClient(values));\n }\n };\n\n const columns: ResponsiveTableColumn<Client>[] = [\n {\n key: 'name',\n header: 'Client',\n priority: 'primary',\n cell: (c) => <span className=\"font-medium\">{c.name}</span>,\n },\n {\n key: 'industry',\n header: 'Industry',\n priority: 'secondary',\n cell: (c) => <span className=\"text-text-secondary\">{c.industry}</span>,\n },\n {\n key: 'contact',\n header: 'Contact',\n priority: 'secondary',\n cell: (c) => (\n <div>\n <p className=\"text-xs\">{c.contactPerson}</p>\n <p className=\"text-xs text-text-secondary\">{c.email}</p>\n </div>\n ),\n },\n {\n key: 'revenue',\n header: 'Revenue',\n priority: 'secondary',\n headerClassName: 'text-right',\n cellClassName: 'text-right',\n cell: (c) => <span>${(c.revenue / 1000).toFixed(0)}K</span>,\n },\n {\n key: 'projects',\n header: 'Projects',\n priority: 'hidden-on-mobile',\n headerClassName: 'text-right',\n cellClassName: 'text-right',\n cell: (c) => <span>{c.projects}</span>,\n },\n {\n key: 'since',\n header: 'Since',\n priority: 'hidden-on-mobile',\n cell: (c) => <span className=\"text-text-secondary\">{c.since}</span>,\n },\n {\n key: 'status',\n header: 'Status',\n priority: 'secondary',\n cell: (c) => (\n <Badge variant={statusVariant(c.status)} className=\"text-[10px]\">\n {c.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>Client Management</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n {clients.length} clients · ${(totalRevenue / 1000000).toFixed(1)}M revenue\n </p>\n <PagePurpose className=\"mt-1\">Keep track of the clients you work with — their contacts, status, and engagements — so account relationships never slip through the cracks.</PagePurpose>\n </div>\n <Button size=\"sm\" onClick={() => modal.openModal()}>\n <Plus className=\"h-4 w-4 mr-1\" />\n Add Client\n </Button>\n </div>\n <div className=\"grid gap-4 md:grid-cols-3\">\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\">Active Clients</CardTitle>\n <Building2 className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">{activeClients.length}</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\">Total Revenue</CardTitle>\n <DollarSign className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">\n ${(totalRevenue / 1000000).toFixed(1)}M\n </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\">Total Projects</CardTitle>\n <FolderKanban className=\"h-4 w-4 text-text-secondary\" />\n </CardHeader>\n <CardContent>\n <div className=\"text-2xl font-bold tabular-nums\">\n {clients.reduce((s, c) => s + c.projects, 0)}\n </div>\n </CardContent>\n </GlassCard>\n </div>\n <Card>\n <CardHeader>\n <CardTitle>Client Portfolio</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <div className=\"flex flex-col gap-2 sm:flex-row sm:items-center\">\n <div className=\"relative flex-1\">\n <Search className=\"absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 text-text-secondary\" />\n <Input\n placeholder=\"Search clients...\"\n className=\"pl-9\"\n value={search}\n onChange={(event) => {\n setSearch(event.target.value);\n setPage(1);\n }}\n />\n </div>\n <Select\n value={filterStatus}\n onValueChange={(value) => {\n setFilterStatus(value);\n setPage(1);\n }}\n >\n <SelectTrigger className=\"w-full sm:w-40\" aria-label=\"Filter by status\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"all\">All statuses</SelectItem>\n <SelectItem value=\"active\">Active</SelectItem>\n <SelectItem value=\"prospect\">Prospect</SelectItem>\n <SelectItem value=\"churned\">Churned</SelectItem>\n </SelectContent>\n </Select>\n </div>\n <ResponsiveTable\n data={paged}\n rowKey={(c) => c.id}\n columns={columns}\n emptyState={\n <IllustratedEmptyState\n illustration=\"empty-search\"\n title=\"No clients match\"\n description=\"Try a different search term or status filter.\"\n />\n }\n rowActions={(c) => (\n <div className=\"flex items-center justify-end gap-1\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={`Edit ${c.name}`}\n onClick={() => modal.openModal(c)}\n >\n <Pencil className=\"h-4 w-4\" />\n </Button>\n <AlertDialog>\n <AlertDialogTrigger asChild>\n <Button variant=\"ghost\" size=\"icon\" aria-label={`Delete ${c.name}`}>\n <Trash2 className=\"h-4 w-4 text-status-error-text\" />\n </Button>\n </AlertDialogTrigger>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>Delete client?</AlertDialogTitle>\n <AlertDialogDescription>\n This removes “{c.name}” from your client portfolio. This action cannot be undone.\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel>Cancel</AlertDialogCancel>\n <AlertDialogAction onClick={() => void removeClient(c.id)}>\n Delete\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n </div>\n )}\n />\n {filtered.length > pageSize && (\n <Pagination\n page={page}\n pageSize={pageSize}\n totalItems={filtered.length}\n onPageChange={setPage}\n />\n )}\n </CardContent>\n </Card>\n\n <FormModal\n open={modal.open}\n onOpenChange={modal.onOpenChange}\n title={modal.context ? 'Edit client' : 'Add client'}\n description=\"Track the client relationship, contacts, and engagement value.\"\n fields={CLIENT_FIELDS}\n initialValues={modal.context ? toInitialValues(modal.context) : undefined}\n submitLabel={modal.context ? 'Save changes' : 'Add client'}\n onSubmit={handleSubmit}\n />\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -4,7 +4,7 @@ import { jsx as a, jsxs as o } from "react/jsx-runtime";
|
|
|
4
4
|
import { Card as s, CardContent as c, CardHeader as l, CardTitle as u, GlassCard as d, GradientText as f, PagePurpose as p } from "@burdenoff/fe-libs/ui";
|
|
5
5
|
//#region src/crewfoundry/pages/CompanyCompanyDashboardPagePage.tsx
|
|
6
6
|
function m() {
|
|
7
|
-
let { employees: m, departments: h, projects: g, clients: _ } = e(), v = _.reduce((e, t) => e + t.revenue, 0);
|
|
7
|
+
let { employees: m, departments: h, projects: g, clients: _ } = e(), v = _.reduce((e, t) => e + t.revenue, 0), y = Array.from(new Set(m.map((e) => e.location).filter((e) => e.trim() !== ""))), b = Array.from(new Set(_.map((e) => e.industry).filter((e) => e.trim() !== ""))), x = g.filter((e) => e.status === "active").length, S = _.filter((e) => e.status === "active").length;
|
|
8
8
|
return /* @__PURE__ */ o("div", {
|
|
9
9
|
className: "space-y-6 p-6",
|
|
10
10
|
children: [
|
|
@@ -91,38 +91,35 @@ function m() {
|
|
|
91
91
|
})
|
|
92
92
|
]
|
|
93
93
|
}),
|
|
94
|
-
/* @__PURE__ */ o(s, { children: [/* @__PURE__ */ a(l, { children: /* @__PURE__ */ a(u, { children: "Company
|
|
94
|
+
/* @__PURE__ */ o(s, { children: [/* @__PURE__ */ a(l, { children: /* @__PURE__ */ a(u, { children: "Company at a Glance" }) }), /* @__PURE__ */ o(c, {
|
|
95
95
|
className: "grid gap-4 md:grid-cols-2",
|
|
96
96
|
children: [/* @__PURE__ */ o("div", {
|
|
97
97
|
className: "space-y-3",
|
|
98
98
|
children: [
|
|
99
99
|
/* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("p", {
|
|
100
100
|
className: "text-xs text-text-secondary",
|
|
101
|
-
children: "
|
|
102
|
-
}), /* @__PURE__ */
|
|
103
|
-
className: "text-sm font-medium",
|
|
104
|
-
children: "CrewFoundry Inc."
|
|
105
|
-
})] }),
|
|
106
|
-
/* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("p", {
|
|
107
|
-
className: "text-xs text-text-secondary",
|
|
108
|
-
children: "Industry"
|
|
109
|
-
}), /* @__PURE__ */ a("p", {
|
|
101
|
+
children: "Headcount"
|
|
102
|
+
}), /* @__PURE__ */ o("p", {
|
|
110
103
|
className: "text-sm font-medium",
|
|
111
|
-
children: "
|
|
104
|
+
children: [m.length, " employees"]
|
|
112
105
|
})] }),
|
|
113
106
|
/* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("p", {
|
|
114
107
|
className: "text-xs text-text-secondary",
|
|
115
|
-
children: "
|
|
108
|
+
children: "Departments"
|
|
116
109
|
}), /* @__PURE__ */ a("p", {
|
|
117
110
|
className: "text-sm font-medium",
|
|
118
|
-
children:
|
|
111
|
+
children: h.length
|
|
119
112
|
})] }),
|
|
120
113
|
/* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("p", {
|
|
121
114
|
className: "text-xs text-text-secondary",
|
|
122
|
-
children: "
|
|
123
|
-
}), /* @__PURE__ */
|
|
115
|
+
children: "Active projects"
|
|
116
|
+
}), /* @__PURE__ */ o("p", {
|
|
124
117
|
className: "text-sm font-medium",
|
|
125
|
-
children:
|
|
118
|
+
children: [
|
|
119
|
+
x,
|
|
120
|
+
" of ",
|
|
121
|
+
g.length
|
|
122
|
+
]
|
|
126
123
|
})] })
|
|
127
124
|
]
|
|
128
125
|
}), /* @__PURE__ */ o("div", {
|
|
@@ -130,31 +127,28 @@ function m() {
|
|
|
130
127
|
children: [
|
|
131
128
|
/* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("p", {
|
|
132
129
|
className: "text-xs text-text-secondary",
|
|
133
|
-
children: "
|
|
134
|
-
}), /* @__PURE__ */
|
|
135
|
-
className: "text-sm font-medium",
|
|
136
|
-
children: "Alex Rivera"
|
|
137
|
-
})] }),
|
|
138
|
-
/* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("p", {
|
|
139
|
-
className: "text-xs text-text-secondary",
|
|
140
|
-
children: "Website"
|
|
141
|
-
}), /* @__PURE__ */ a("p", {
|
|
130
|
+
children: "Active clients"
|
|
131
|
+
}), /* @__PURE__ */ o("p", {
|
|
142
132
|
className: "text-sm font-medium",
|
|
143
|
-
children:
|
|
133
|
+
children: [
|
|
134
|
+
S,
|
|
135
|
+
" of ",
|
|
136
|
+
_.length
|
|
137
|
+
]
|
|
144
138
|
})] }),
|
|
145
139
|
/* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("p", {
|
|
146
140
|
className: "text-xs text-text-secondary",
|
|
147
|
-
children: "
|
|
141
|
+
children: "Client industries served"
|
|
148
142
|
}), /* @__PURE__ */ a("p", {
|
|
149
143
|
className: "text-sm font-medium",
|
|
150
|
-
children:
|
|
144
|
+
children: b.length
|
|
151
145
|
})] }),
|
|
152
146
|
/* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("p", {
|
|
153
147
|
className: "text-xs text-text-secondary",
|
|
154
|
-
children: "
|
|
148
|
+
children: "Office locations"
|
|
155
149
|
}), /* @__PURE__ */ a("p", {
|
|
156
150
|
className: "text-sm font-medium",
|
|
157
|
-
children: "
|
|
151
|
+
children: y.length > 0 ? y.join(", ") : "—"
|
|
158
152
|
})] })
|
|
159
153
|
]
|
|
160
154
|
})]
|