@burdenoff/microfe-crewfoundry 2026.704.2 → 2026.704.4
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 +107 -106
- 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 +127 -126
- 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/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/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/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/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 +130 -129
- 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,12 +1,13 @@
|
|
|
1
1
|
import { useCrewFoundryStore as e } from "../store/crewfoundryStore.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { formatEnumLabel as t } from "../utils/formatEnumLabel.js";
|
|
3
|
+
import { FormModal as n, useFormModal as r } from "../components/forms/FormModal.js";
|
|
4
|
+
import { useState as i } from "react";
|
|
5
|
+
import { Mail as a, Pencil as o, Plus as s, Search as c, Star as ee, Trash2 as l } from "lucide-react";
|
|
5
6
|
import { jsx as u, jsxs as d } from "react/jsx-runtime";
|
|
6
|
-
import { AlertDialog as
|
|
7
|
-
import { usePagination as
|
|
7
|
+
import { AlertDialog as f, AlertDialogAction as p, AlertDialogCancel as m, AlertDialogContent as h, AlertDialogDescription as g, AlertDialogFooter as _, AlertDialogHeader as v, AlertDialogTitle as y, AlertDialogTrigger as b, Badge as x, Button as S, CardContent as C, CardHeader as w, CardTitle as T, GlassCard as E, GradientText as D, IllustratedEmptyState as O, Input as k, PagePurpose as A, Pagination as j, Select as M, SelectContent as N, SelectItem as P, SelectTrigger as te, SelectValue as F } from "@burdenoff/fe-libs/ui";
|
|
8
|
+
import { usePagination as I } from "@burdenoff/fe-libs/shared/hooks";
|
|
8
9
|
//#region src/crewfoundry/pages/CompanyVendorManagementPagePage.tsx
|
|
9
|
-
var
|
|
10
|
+
var L = [
|
|
10
11
|
{
|
|
11
12
|
name: "name",
|
|
12
13
|
label: "Vendor name",
|
|
@@ -63,7 +64,7 @@ var I = [
|
|
|
63
64
|
label: "Rating (0-5)",
|
|
64
65
|
type: "number"
|
|
65
66
|
}
|
|
66
|
-
],
|
|
67
|
+
], R = (e) => ({
|
|
67
68
|
name: e.name,
|
|
68
69
|
category: e.category,
|
|
69
70
|
contactPerson: e.contactPerson,
|
|
@@ -72,7 +73,7 @@ var I = [
|
|
|
72
73
|
status: e.status,
|
|
73
74
|
contractValue: e.contractValue,
|
|
74
75
|
rating: e.rating
|
|
75
|
-
}),
|
|
76
|
+
}), z = (e, t) => ({
|
|
76
77
|
id: t?.id ?? crypto.randomUUID(),
|
|
77
78
|
name: String(e.name ?? ""),
|
|
78
79
|
category: String(e.category ?? ""),
|
|
@@ -83,11 +84,11 @@ var I = [
|
|
|
83
84
|
contractValue: typeof e.contractValue == "number" ? e.contractValue : Number(e.contractValue) || 0,
|
|
84
85
|
rating: typeof e.rating == "number" ? e.rating : Number(e.rating) || 0
|
|
85
86
|
});
|
|
86
|
-
function
|
|
87
|
-
let { vendors:
|
|
88
|
-
let t = `${e.name} ${e.category} ${e.contactPerson} ${e.email}`.toLowerCase().includes(
|
|
87
|
+
function B() {
|
|
88
|
+
let { vendors: B, addVendor: V, updateVendor: H, removeVendor: U } = e(), W = r(), [G, K] = i(""), [q, J] = i("all"), { page: Y, pageSize: X, offset: Z, setPage: Q } = I({ initialPageSize: 12 }), ne = B.reduce((e, t) => e + t.contractValue, 0), $ = B.filter((e) => {
|
|
89
|
+
let t = `${e.name} ${e.category} ${e.contactPerson} ${e.email}`.toLowerCase().includes(G.toLowerCase()), n = q === "all" || e.status === q;
|
|
89
90
|
return t && n;
|
|
90
|
-
}),
|
|
91
|
+
}), re = $.slice(Z, Z + X);
|
|
91
92
|
return /* @__PURE__ */ d("div", {
|
|
92
93
|
className: "space-y-6 p-6",
|
|
93
94
|
children: [
|
|
@@ -96,62 +97,62 @@ function z() {
|
|
|
96
97
|
children: [/* @__PURE__ */ d("div", { children: [
|
|
97
98
|
/* @__PURE__ */ u("h1", {
|
|
98
99
|
className: "text-2xl font-semibold",
|
|
99
|
-
children: /* @__PURE__ */ u(
|
|
100
|
+
children: /* @__PURE__ */ u(D, { children: "Vendor Management" })
|
|
100
101
|
}),
|
|
101
102
|
/* @__PURE__ */ d("p", {
|
|
102
103
|
className: "text-sm text-text-secondary",
|
|
103
104
|
children: [
|
|
104
|
-
|
|
105
|
+
B.length,
|
|
105
106
|
" vendors · $",
|
|
106
|
-
(
|
|
107
|
+
(ne / 1e3).toFixed(0),
|
|
107
108
|
"K total contract value"
|
|
108
109
|
]
|
|
109
110
|
}),
|
|
110
|
-
/* @__PURE__ */ u(
|
|
111
|
+
/* @__PURE__ */ u(A, {
|
|
111
112
|
className: "mt-1",
|
|
112
113
|
children: "Track the vendors and suppliers you depend on — contracts, contacts, and status — to manage external relationships in one place."
|
|
113
114
|
})
|
|
114
|
-
] }), /* @__PURE__ */ d(
|
|
115
|
+
] }), /* @__PURE__ */ d(S, {
|
|
115
116
|
size: "sm",
|
|
116
|
-
onClick: () =>
|
|
117
|
-
children: [/* @__PURE__ */ u(
|
|
117
|
+
onClick: () => W.openModal(),
|
|
118
|
+
children: [/* @__PURE__ */ u(s, { className: "h-4 w-4 mr-1" }), "Add Vendor"]
|
|
118
119
|
})]
|
|
119
120
|
}),
|
|
120
121
|
/* @__PURE__ */ d("div", {
|
|
121
122
|
className: "flex flex-col gap-2 sm:flex-row sm:items-center",
|
|
122
123
|
children: [/* @__PURE__ */ d("div", {
|
|
123
124
|
className: "relative flex-1",
|
|
124
|
-
children: [/* @__PURE__ */ u(
|
|
125
|
+
children: [/* @__PURE__ */ u(c, { className: "absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 text-text-secondary" }), /* @__PURE__ */ u(k, {
|
|
125
126
|
placeholder: "Search vendors...",
|
|
126
127
|
className: "pl-9",
|
|
127
|
-
value:
|
|
128
|
+
value: G,
|
|
128
129
|
onChange: (e) => {
|
|
129
|
-
|
|
130
|
+
K(e.target.value), Q(1);
|
|
130
131
|
}
|
|
131
132
|
})]
|
|
132
|
-
}), /* @__PURE__ */ d(
|
|
133
|
-
value:
|
|
133
|
+
}), /* @__PURE__ */ d(M, {
|
|
134
|
+
value: q,
|
|
134
135
|
onValueChange: (e) => {
|
|
135
|
-
|
|
136
|
+
J(e), Q(1);
|
|
136
137
|
},
|
|
137
|
-
children: [/* @__PURE__ */ u(
|
|
138
|
+
children: [/* @__PURE__ */ u(te, {
|
|
138
139
|
className: "w-full sm:w-40",
|
|
139
140
|
"aria-label": "Filter by status",
|
|
140
|
-
children: /* @__PURE__ */ u(
|
|
141
|
-
}), /* @__PURE__ */ d(
|
|
142
|
-
/* @__PURE__ */ u(
|
|
141
|
+
children: /* @__PURE__ */ u(F, {})
|
|
142
|
+
}), /* @__PURE__ */ d(N, { children: [
|
|
143
|
+
/* @__PURE__ */ u(P, {
|
|
143
144
|
value: "all",
|
|
144
145
|
children: "All statuses"
|
|
145
146
|
}),
|
|
146
|
-
/* @__PURE__ */ u(
|
|
147
|
+
/* @__PURE__ */ u(P, {
|
|
147
148
|
value: "active",
|
|
148
149
|
children: "Active"
|
|
149
150
|
}),
|
|
150
|
-
/* @__PURE__ */ u(
|
|
151
|
+
/* @__PURE__ */ u(P, {
|
|
151
152
|
value: "inactive",
|
|
152
153
|
children: "Inactive"
|
|
153
154
|
}),
|
|
154
|
-
/* @__PURE__ */ u(
|
|
155
|
+
/* @__PURE__ */ u(P, {
|
|
155
156
|
value: "pending",
|
|
156
157
|
children: "Pending"
|
|
157
158
|
})
|
|
@@ -160,65 +161,65 @@ function z() {
|
|
|
160
161
|
}),
|
|
161
162
|
/* @__PURE__ */ u("div", {
|
|
162
163
|
className: "grid gap-4 md:grid-cols-2 lg:grid-cols-3",
|
|
163
|
-
children:
|
|
164
|
+
children: B.length === 0 ? /* @__PURE__ */ u("div", {
|
|
164
165
|
className: "col-span-full",
|
|
165
|
-
children: /* @__PURE__ */ u(
|
|
166
|
+
children: /* @__PURE__ */ u(O, {
|
|
166
167
|
illustration: "empty-data",
|
|
167
168
|
title: "No vendors yet",
|
|
168
169
|
description: "Add a vendor to start tracking external relationships."
|
|
169
170
|
})
|
|
170
171
|
}) : $.length === 0 ? /* @__PURE__ */ u("div", {
|
|
171
172
|
className: "col-span-full",
|
|
172
|
-
children: /* @__PURE__ */ u(
|
|
173
|
+
children: /* @__PURE__ */ u(O, {
|
|
173
174
|
illustration: "empty-search",
|
|
174
175
|
title: "No vendors match",
|
|
175
176
|
description: "Try a different search term or status filter."
|
|
176
177
|
})
|
|
177
|
-
}) :
|
|
178
|
-
treatment:
|
|
179
|
-
glow:
|
|
180
|
-
children: [/* @__PURE__ */ u(
|
|
178
|
+
}) : re.map((e, n) => /* @__PURE__ */ d(E, {
|
|
179
|
+
treatment: n === 0 ? "glass" : "plain",
|
|
180
|
+
glow: n === 0,
|
|
181
|
+
children: [/* @__PURE__ */ u(w, { children: /* @__PURE__ */ d("div", {
|
|
181
182
|
className: "flex items-center justify-between",
|
|
182
|
-
children: [/* @__PURE__ */ u(
|
|
183
|
+
children: [/* @__PURE__ */ u(T, {
|
|
183
184
|
className: "text-base",
|
|
184
185
|
children: e.name
|
|
185
186
|
}), /* @__PURE__ */ d("div", {
|
|
186
187
|
className: "flex items-center gap-1",
|
|
187
188
|
children: [
|
|
188
|
-
/* @__PURE__ */ u(
|
|
189
|
+
/* @__PURE__ */ u(x, {
|
|
189
190
|
variant: e.status === "active" ? "default" : "secondary",
|
|
190
191
|
className: "text-[10px]",
|
|
191
|
-
children: e.status
|
|
192
|
+
children: t(e.status)
|
|
192
193
|
}),
|
|
193
|
-
/* @__PURE__ */ u(
|
|
194
|
+
/* @__PURE__ */ u(S, {
|
|
194
195
|
variant: "ghost",
|
|
195
196
|
size: "icon",
|
|
196
197
|
"aria-label": `Edit ${e.name}`,
|
|
197
|
-
onClick: () =>
|
|
198
|
-
children: /* @__PURE__ */ u(
|
|
198
|
+
onClick: () => W.openModal(e),
|
|
199
|
+
children: /* @__PURE__ */ u(o, { className: "h-4 w-4" })
|
|
199
200
|
}),
|
|
200
|
-
/* @__PURE__ */ d(
|
|
201
|
+
/* @__PURE__ */ d(f, { children: [/* @__PURE__ */ u(b, {
|
|
201
202
|
asChild: !0,
|
|
202
|
-
children: /* @__PURE__ */ u(
|
|
203
|
+
children: /* @__PURE__ */ u(S, {
|
|
203
204
|
variant: "ghost",
|
|
204
205
|
size: "icon",
|
|
205
206
|
"aria-label": `Delete ${e.name}`,
|
|
206
207
|
children: /* @__PURE__ */ u(l, { className: "h-4 w-4 text-status-error-text" })
|
|
207
208
|
})
|
|
208
|
-
}), /* @__PURE__ */ d(
|
|
209
|
+
}), /* @__PURE__ */ d(h, { children: [/* @__PURE__ */ d(v, { children: [/* @__PURE__ */ u(y, { children: "Delete vendor?" }), /* @__PURE__ */ d(g, { children: [
|
|
209
210
|
"This removes “",
|
|
210
211
|
e.name,
|
|
211
212
|
"” from your vendor directory. This action cannot be undone."
|
|
212
|
-
] })] }), /* @__PURE__ */ d(
|
|
213
|
-
onClick: () => void
|
|
213
|
+
] })] }), /* @__PURE__ */ d(_, { children: [/* @__PURE__ */ u(m, { children: "Cancel" }), /* @__PURE__ */ u(p, {
|
|
214
|
+
onClick: () => void U(e.id),
|
|
214
215
|
children: "Delete"
|
|
215
216
|
})] })] })] })
|
|
216
217
|
]
|
|
217
218
|
})]
|
|
218
|
-
}) }), /* @__PURE__ */ u(
|
|
219
|
+
}) }), /* @__PURE__ */ u(C, { children: /* @__PURE__ */ d("div", {
|
|
219
220
|
className: "space-y-2",
|
|
220
221
|
children: [
|
|
221
|
-
/* @__PURE__ */ u(
|
|
222
|
+
/* @__PURE__ */ u(x, {
|
|
222
223
|
variant: "outline",
|
|
223
224
|
className: "text-[10px]",
|
|
224
225
|
children: e.category
|
|
@@ -243,10 +244,10 @@ function z() {
|
|
|
243
244
|
className: "flex items-center justify-between pt-2 border-t mt-2",
|
|
244
245
|
children: [/* @__PURE__ */ d("div", {
|
|
245
246
|
className: "flex items-center gap-1 text-xs text-text-secondary",
|
|
246
|
-
children: [/* @__PURE__ */ u(
|
|
247
|
+
children: [/* @__PURE__ */ u(a, { className: "h-3 w-3" }), e.email]
|
|
247
248
|
}), /* @__PURE__ */ d("div", {
|
|
248
249
|
className: "flex items-center gap-1",
|
|
249
|
-
children: [/* @__PURE__ */ u(
|
|
250
|
+
children: [/* @__PURE__ */ u(ee, { className: "h-3 w-3 text-status-warning-text" }), /* @__PURE__ */ u("span", {
|
|
250
251
|
className: "text-sm",
|
|
251
252
|
children: e.rating
|
|
252
253
|
})]
|
|
@@ -256,28 +257,28 @@ function z() {
|
|
|
256
257
|
}) })]
|
|
257
258
|
}, e.id))
|
|
258
259
|
}),
|
|
259
|
-
$.length >
|
|
260
|
-
page:
|
|
261
|
-
pageSize:
|
|
260
|
+
$.length > X && /* @__PURE__ */ u(j, {
|
|
261
|
+
page: Y,
|
|
262
|
+
pageSize: X,
|
|
262
263
|
totalItems: $.length,
|
|
263
|
-
onPageChange:
|
|
264
|
+
onPageChange: Q
|
|
264
265
|
}),
|
|
265
|
-
/* @__PURE__ */ u(
|
|
266
|
-
open:
|
|
267
|
-
onOpenChange:
|
|
268
|
-
title:
|
|
266
|
+
/* @__PURE__ */ u(n, {
|
|
267
|
+
open: W.open,
|
|
268
|
+
onOpenChange: W.onOpenChange,
|
|
269
|
+
title: W.context ? "Edit vendor" : "Add vendor",
|
|
269
270
|
description: "Track the vendor, its contract value, and primary contact.",
|
|
270
|
-
fields:
|
|
271
|
-
initialValues:
|
|
272
|
-
submitLabel:
|
|
271
|
+
fields: L,
|
|
272
|
+
initialValues: W.context ? R(W.context) : void 0,
|
|
273
|
+
submitLabel: W.context ? "Save changes" : "Add vendor",
|
|
273
274
|
onSubmit: async (e) => {
|
|
274
|
-
|
|
275
|
+
W.context ? await H(W.context.id, z(e, W.context)) : await V(z(e));
|
|
275
276
|
}
|
|
276
277
|
})
|
|
277
278
|
]
|
|
278
279
|
});
|
|
279
280
|
}
|
|
280
281
|
//#endregion
|
|
281
|
-
export {
|
|
282
|
+
export { B as CompanyVendorManagementPagePage };
|
|
282
283
|
|
|
283
284
|
//# sourceMappingURL=CompanyVendorManagementPagePage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CompanyVendorManagementPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/CompanyVendorManagementPagePage.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 CardContent,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n Input,\n PagePurpose,\n Pagination,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@burdenoff/fe-libs/ui';\nimport { usePagination } from '@burdenoff/fe-libs/shared/hooks';\nimport { Mail, Pencil, Plus, Search, Star, Trash2 } from 'lucide-react';\nimport {\n FormModal,\n useFormModal,\n type FieldConfig,\n type FormValues,\n} from '../components/forms/FormModal';\nimport { useCrewFoundryStore, type Vendor } from '../store/crewfoundryStore';\n\nconst VENDOR_FIELDS: FieldConfig[] = [\n { name: 'name', label: 'Vendor name', type: 'text', required: true },\n { name: 'category', label: 'Category', type: 'text', required: true },\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: 'Inactive', value: 'inactive' },\n { label: 'Pending', value: 'pending' },\n ],\n },\n { name: 'contractValue', label: 'Contract value (USD)', type: 'number' },\n { name: 'rating', label: 'Rating (0-5)', type: 'number' },\n];\n\nconst toInitialValues = (vendor: Vendor): FormValues => ({\n name: vendor.name,\n category: vendor.category,\n contactPerson: vendor.contactPerson,\n email: vendor.email,\n phone: vendor.phone,\n status: vendor.status,\n contractValue: vendor.contractValue,\n rating: vendor.rating,\n});\n\nconst valuesToVendor = (values: FormValues, base?: Vendor): Vendor => ({\n id: base?.id ?? crypto.randomUUID(),\n name: String(values.name ?? ''),\n category: String(values.category ?? ''),\n contactPerson: String(values.contactPerson ?? ''),\n email: String(values.email ?? ''),\n phone: String(values.phone ?? ''),\n status: (values.status as Vendor['status']) || 'pending',\n contractValue:\n typeof values.contractValue === 'number'\n ? values.contractValue\n : Number(values.contractValue) || 0,\n rating: typeof values.rating === 'number' ? values.rating : Number(values.rating) || 0,\n});\n\nexport function CompanyVendorManagementPagePage() {\n const { vendors, addVendor, updateVendor, removeVendor } = useCrewFoundryStore();\n const modal = useFormModal<Vendor>();\n const [search, setSearch] = useState('');\n const [filterStatus, setFilterStatus] = useState<string>('all');\n const { page, pageSize, offset, setPage } = usePagination({ initialPageSize: 12 });\n const totalContractValue = vendors.reduce((s, v) => s + v.contractValue, 0);\n\n const filtered = vendors.filter((v) => {\n const matchSearch = `${v.name} ${v.category} ${v.contactPerson} ${v.email}`\n .toLowerCase()\n .includes(search.toLowerCase());\n const matchStatus = filterStatus === 'all' || v.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 updateVendor(modal.context.id, valuesToVendor(values, modal.context));\n } else {\n await addVendor(valuesToVendor(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>Vendor Management</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n {vendors.length} vendors · ${(totalContractValue / 1000).toFixed(0)}K total contract\n value\n </p>\n <PagePurpose className=\"mt-1\">\n Track the vendors and suppliers you depend on — contracts, contacts, and status — to\n manage external relationships in one place.\n </PagePurpose>\n </div>\n <Button size=\"sm\" onClick={() => modal.openModal()}>\n <Plus className=\"h-4 w-4 mr-1\" />\n Add Vendor\n </Button>\n </div>\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 vendors...\"\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=\"inactive\">Inactive</SelectItem>\n <SelectItem value=\"pending\">Pending</SelectItem>\n </SelectContent>\n </Select>\n </div>\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-3\">\n {vendors.length === 0 ? (\n <div className=\"col-span-full\">\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No vendors yet\"\n description=\"Add a vendor to start tracking external relationships.\"\n />\n </div>\n ) : filtered.length === 0 ? (\n <div className=\"col-span-full\">\n <IllustratedEmptyState\n illustration=\"empty-search\"\n title=\"No vendors match\"\n description=\"Try a different search term or status filter.\"\n />\n </div>\n ) : (\n paged.map((vendor, _idx) => (\n <GlassCard key={vendor.id} treatment={_idx === 0 ? 'glass' : 'plain'} glow={_idx === 0}>\n <CardHeader>\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base\">{vendor.name}</CardTitle>\n <div className=\"flex items-center gap-1\">\n <Badge\n variant={vendor.status === 'active' ? 'default' : 'secondary'}\n className=\"text-[10px]\"\n >\n {vendor.status}\n </Badge>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={`Edit ${vendor.name}`}\n onClick={() => modal.openModal(vendor)}\n >\n <Pencil className=\"h-4 w-4\" />\n </Button>\n <AlertDialog>\n <AlertDialogTrigger asChild>\n <Button variant=\"ghost\" size=\"icon\" aria-label={`Delete ${vendor.name}`}>\n <Trash2 className=\"h-4 w-4 text-status-error-text\" />\n </Button>\n </AlertDialogTrigger>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>Delete vendor?</AlertDialogTitle>\n <AlertDialogDescription>\n This removes “{vendor.name}” from your vendor directory. This action\n cannot be undone.\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel>Cancel</AlertDialogCancel>\n <AlertDialogAction onClick={() => void removeVendor(vendor.id)}>\n Delete\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n </div>\n </div>\n </CardHeader>\n <CardContent>\n <div className=\"space-y-2\">\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {vendor.category}\n </Badge>\n <div className=\"grid grid-cols-2 gap-2 mt-2\">\n <div>\n <p className=\"text-xs text-text-secondary\">Contact</p>\n <p className=\"text-sm\">{vendor.contactPerson}</p>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary\">Contract Value</p>\n <p className=\"text-sm font-medium\">\n ${vendor.contractValue.toLocaleString()}\n </p>\n </div>\n </div>\n <div className=\"flex items-center justify-between pt-2 border-t mt-2\">\n <div className=\"flex items-center gap-1 text-xs text-text-secondary\">\n <Mail className=\"h-3 w-3\" />\n {vendor.email}\n </div>\n <div className=\"flex items-center gap-1\">\n <Star className=\"h-3 w-3 text-status-warning-text\" />\n <span className=\"text-sm\">{vendor.rating}</span>\n </div>\n </div>\n </div>\n </CardContent>\n </GlassCard>\n ))\n )}\n </div>\n {filtered.length > pageSize && (\n <Pagination\n page={page}\n pageSize={pageSize}\n totalItems={filtered.length}\n onPageChange={setPage}\n />\n )}\n\n <FormModal\n open={modal.open}\n onOpenChange={modal.onOpenChange}\n title={modal.context ? 'Edit vendor' : 'Add vendor'}\n description=\"Track the vendor, its contract value, and primary contact.\"\n fields={VENDOR_FIELDS}\n initialValues={modal.context ? toInitialValues(modal.context) : undefined}\n submitLabel={modal.context ? 'Save changes' : 'Add vendor'}\n onSubmit={handleSubmit}\n />\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CompanyVendorManagementPagePage.js","names":[],"sources":["../../../src/crewfoundry/pages/CompanyVendorManagementPagePage.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 CardContent,\n CardHeader,\n CardTitle,\n GlassCard,\n GradientText,\n IllustratedEmptyState,\n Input,\n PagePurpose,\n Pagination,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@burdenoff/fe-libs/ui';\nimport { usePagination } from '@burdenoff/fe-libs/shared/hooks';\nimport { Mail, Pencil, Plus, Search, Star, Trash2 } from 'lucide-react';\nimport {\n FormModal,\n useFormModal,\n type FieldConfig,\n type FormValues,\n} from '../components/forms/FormModal';\nimport { useCrewFoundryStore, type Vendor } from '../store/crewfoundryStore';\nimport { formatEnumLabel } from '../utils/formatEnumLabel';\n\nconst VENDOR_FIELDS: FieldConfig[] = [\n { name: 'name', label: 'Vendor name', type: 'text', required: true },\n { name: 'category', label: 'Category', type: 'text', required: true },\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: 'Inactive', value: 'inactive' },\n { label: 'Pending', value: 'pending' },\n ],\n },\n { name: 'contractValue', label: 'Contract value (USD)', type: 'number' },\n { name: 'rating', label: 'Rating (0-5)', type: 'number' },\n];\n\nconst toInitialValues = (vendor: Vendor): FormValues => ({\n name: vendor.name,\n category: vendor.category,\n contactPerson: vendor.contactPerson,\n email: vendor.email,\n phone: vendor.phone,\n status: vendor.status,\n contractValue: vendor.contractValue,\n rating: vendor.rating,\n});\n\nconst valuesToVendor = (values: FormValues, base?: Vendor): Vendor => ({\n id: base?.id ?? crypto.randomUUID(),\n name: String(values.name ?? ''),\n category: String(values.category ?? ''),\n contactPerson: String(values.contactPerson ?? ''),\n email: String(values.email ?? ''),\n phone: String(values.phone ?? ''),\n status: (values.status as Vendor['status']) || 'pending',\n contractValue:\n typeof values.contractValue === 'number'\n ? values.contractValue\n : Number(values.contractValue) || 0,\n rating: typeof values.rating === 'number' ? values.rating : Number(values.rating) || 0,\n});\n\nexport function CompanyVendorManagementPagePage() {\n const { vendors, addVendor, updateVendor, removeVendor } = useCrewFoundryStore();\n const modal = useFormModal<Vendor>();\n const [search, setSearch] = useState('');\n const [filterStatus, setFilterStatus] = useState<string>('all');\n const { page, pageSize, offset, setPage } = usePagination({ initialPageSize: 12 });\n const totalContractValue = vendors.reduce((s, v) => s + v.contractValue, 0);\n\n const filtered = vendors.filter((v) => {\n const matchSearch = `${v.name} ${v.category} ${v.contactPerson} ${v.email}`\n .toLowerCase()\n .includes(search.toLowerCase());\n const matchStatus = filterStatus === 'all' || v.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 updateVendor(modal.context.id, valuesToVendor(values, modal.context));\n } else {\n await addVendor(valuesToVendor(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>Vendor Management</GradientText>\n </h1>\n <p className=\"text-sm text-text-secondary\">\n {vendors.length} vendors · ${(totalContractValue / 1000).toFixed(0)}K total contract\n value\n </p>\n <PagePurpose className=\"mt-1\">\n Track the vendors and suppliers you depend on — contracts, contacts, and status — to\n manage external relationships in one place.\n </PagePurpose>\n </div>\n <Button size=\"sm\" onClick={() => modal.openModal()}>\n <Plus className=\"h-4 w-4 mr-1\" />\n Add Vendor\n </Button>\n </div>\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 vendors...\"\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=\"inactive\">Inactive</SelectItem>\n <SelectItem value=\"pending\">Pending</SelectItem>\n </SelectContent>\n </Select>\n </div>\n <div className=\"grid gap-4 md:grid-cols-2 lg:grid-cols-3\">\n {vendors.length === 0 ? (\n <div className=\"col-span-full\">\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title=\"No vendors yet\"\n description=\"Add a vendor to start tracking external relationships.\"\n />\n </div>\n ) : filtered.length === 0 ? (\n <div className=\"col-span-full\">\n <IllustratedEmptyState\n illustration=\"empty-search\"\n title=\"No vendors match\"\n description=\"Try a different search term or status filter.\"\n />\n </div>\n ) : (\n paged.map((vendor, _idx) => (\n <GlassCard key={vendor.id} treatment={_idx === 0 ? 'glass' : 'plain'} glow={_idx === 0}>\n <CardHeader>\n <div className=\"flex items-center justify-between\">\n <CardTitle className=\"text-base\">{vendor.name}</CardTitle>\n <div className=\"flex items-center gap-1\">\n <Badge\n variant={vendor.status === 'active' ? 'default' : 'secondary'}\n className=\"text-[10px]\"\n >\n {formatEnumLabel(vendor.status)}\n </Badge>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n aria-label={`Edit ${vendor.name}`}\n onClick={() => modal.openModal(vendor)}\n >\n <Pencil className=\"h-4 w-4\" />\n </Button>\n <AlertDialog>\n <AlertDialogTrigger asChild>\n <Button variant=\"ghost\" size=\"icon\" aria-label={`Delete ${vendor.name}`}>\n <Trash2 className=\"h-4 w-4 text-status-error-text\" />\n </Button>\n </AlertDialogTrigger>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>Delete vendor?</AlertDialogTitle>\n <AlertDialogDescription>\n This removes “{vendor.name}” from your vendor directory. This action\n cannot be undone.\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel>Cancel</AlertDialogCancel>\n <AlertDialogAction onClick={() => void removeVendor(vendor.id)}>\n Delete\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n </div>\n </div>\n </CardHeader>\n <CardContent>\n <div className=\"space-y-2\">\n <Badge variant=\"outline\" className=\"text-[10px]\">\n {vendor.category}\n </Badge>\n <div className=\"grid grid-cols-2 gap-2 mt-2\">\n <div>\n <p className=\"text-xs text-text-secondary\">Contact</p>\n <p className=\"text-sm\">{vendor.contactPerson}</p>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary\">Contract Value</p>\n <p className=\"text-sm font-medium\">\n ${vendor.contractValue.toLocaleString()}\n </p>\n </div>\n </div>\n <div className=\"flex items-center justify-between pt-2 border-t mt-2\">\n <div className=\"flex items-center gap-1 text-xs text-text-secondary\">\n <Mail className=\"h-3 w-3\" />\n {vendor.email}\n </div>\n <div className=\"flex items-center gap-1\">\n <Star className=\"h-3 w-3 text-status-warning-text\" />\n <span className=\"text-sm\">{vendor.rating}</span>\n </div>\n </div>\n </div>\n </CardContent>\n </GlassCard>\n ))\n )}\n </div>\n {filtered.length > pageSize && (\n <Pagination\n page={page}\n pageSize={pageSize}\n totalItems={filtered.length}\n onPageChange={setPage}\n />\n )}\n\n <FormModal\n open={modal.open}\n onOpenChange={modal.onOpenChange}\n title={modal.context ? 'Edit vendor' : 'Add vendor'}\n description=\"Track the vendor, its contract value, and primary contact.\"\n fields={VENDOR_FIELDS}\n initialValues={modal.context ? toInitialValues(modal.context) : undefined}\n submitLabel={modal.context ? 'Save changes' : 'Add vendor'}\n onSubmit={handleSubmit}\n />\n </div>\n );\n}\n"],"mappings":"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"}
|