@burdenoff/microfe-timecampus 2026.703.2 → 2026.703.3
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/timecampus/pages/client-portal/ClientPortalPage.js +175 -109
- package/dist/timecampus/pages/client-portal/ClientPortalPage.js.map +1 -1
- package/dist/timecampus/pages/expense-tracking/ExpenseTrackingPage.js +270 -167
- package/dist/timecampus/pages/expense-tracking/ExpenseTrackingPage.js.map +1 -1
- package/dist/timecampus/pages/meetings/MeetingFormModal.js +127 -75
- package/dist/timecampus/pages/meetings/MeetingFormModal.js.map +1 -1
- package/dist/timecampus/pages/time-approval/TimeApprovalPage.js +120 -96
- package/dist/timecampus/pages/time-approval/TimeApprovalPage.js.map +1 -1
- package/package.json +1 -1
|
@@ -9,43 +9,51 @@ import { StatusBadge as oe } from "../../components/StatusBadge.js";
|
|
|
9
9
|
import { ToastContainer as se, useToast as ce } from "../../components/Toast.js";
|
|
10
10
|
import { useState as s } from "react";
|
|
11
11
|
import { Building2 as c, Check as l, DollarSign as u, FolderOpen as d, Link2 as f, Pencil as p, Plus as le, Power as ue, RefreshCw as de, Trash2 as fe } from "lucide-react";
|
|
12
|
-
import {
|
|
12
|
+
import { gql as m } from "@apollo/client";
|
|
13
|
+
import { useApolloClient as pe } from "@apollo/client/react";
|
|
14
|
+
import { Fragment as h, jsx as g, jsxs as _ } from "react/jsx-runtime";
|
|
15
|
+
import { uploadBlobToFiles as me } from "@burdenoff/fe-libs/storage";
|
|
13
16
|
//#region src/timecampus/pages/client-portal/ClientPortalPage.tsx
|
|
14
|
-
var
|
|
15
|
-
|
|
17
|
+
var v = 25, y = "mt-1 w-full rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary placeholder:text-text-secondary", he = "mt-1 block w-full text-sm text-text-secondary file:mr-3 file:rounded-md file:border-0 file:bg-action-primary-bg file:px-3 file:py-1.5 file:text-sm file:font-medium file:text-action-primary-text hover:file:bg-action-primary-bg/90", ge = m`
|
|
18
|
+
query TimeCampus_GetFileDownloadUrl($id: ID!, $expiresIn: Int) {
|
|
19
|
+
getFileDownloadUrl(id: $id, expiresIn: $expiresIn)
|
|
20
|
+
}
|
|
21
|
+
`;
|
|
22
|
+
function _e(e) {
|
|
16
23
|
return `${typeof window < "u" ? window.location.origin : ""}/portal/${e}`;
|
|
17
24
|
}
|
|
18
|
-
var
|
|
25
|
+
var b = {
|
|
19
26
|
clientName: "",
|
|
20
27
|
contactEmail: "",
|
|
21
28
|
contactPhone: "",
|
|
22
|
-
description: ""
|
|
29
|
+
description: "",
|
|
30
|
+
logoUrl: ""
|
|
23
31
|
};
|
|
24
|
-
function
|
|
25
|
-
let { toasts:
|
|
32
|
+
function x() {
|
|
33
|
+
let { toasts: m, addToast: x, dismissToast: ve } = ce(), S = pe(), [C, w] = s(null), [T, E] = s(!1), { data: D, loading: O, error: k, refetch: A, fetchMore: j } = i({
|
|
26
34
|
variables: {
|
|
27
|
-
limit:
|
|
35
|
+
limit: v,
|
|
28
36
|
offset: 0
|
|
29
37
|
},
|
|
30
38
|
notifyOnNetworkStatusChange: !0
|
|
31
|
-
}), { data:
|
|
32
|
-
await Promise.all([
|
|
33
|
-
},
|
|
39
|
+
}), { data: M, refetch: N } = te(), [P, { loading: F }] = ne(), [ye, { loading: I }] = r(), [be, { loading: L }] = ie(), [xe, { loading: R }] = ee(), [Se] = re(), z = D?.clientPortalConfigs?.items ?? [], Ce = D?.clientPortalConfigs?.hasMore ?? !1, B = M?.clientPortalStats, [V, H] = s(!1), [we, U] = s(!1), [W, G] = s(null), [K, q] = s(b), [J, Y] = s(null), [Te, X] = s(null), Z = async () => {
|
|
40
|
+
await Promise.all([A(), N()]);
|
|
41
|
+
}, Ee = async (e) => {
|
|
34
42
|
if (e.shareToken) try {
|
|
35
|
-
await navigator.clipboard.writeText(
|
|
43
|
+
await navigator.clipboard.writeText(_e(e.shareToken)), w(e.id), window.setTimeout(() => w(null), 2e3);
|
|
36
44
|
} catch {
|
|
37
45
|
x({
|
|
38
46
|
title: "Clipboard unavailable",
|
|
39
47
|
variant: "error"
|
|
40
48
|
});
|
|
41
49
|
}
|
|
42
|
-
},
|
|
50
|
+
}, De = async (e) => {
|
|
43
51
|
X(e.id);
|
|
44
52
|
try {
|
|
45
|
-
await
|
|
53
|
+
await P({ variables: { id: e.id } }), x({
|
|
46
54
|
title: "Share link regenerated",
|
|
47
55
|
variant: "success"
|
|
48
|
-
}), await
|
|
56
|
+
}), await A();
|
|
49
57
|
} catch {
|
|
50
58
|
x({
|
|
51
59
|
title: "Failed to regenerate link",
|
|
@@ -54,35 +62,68 @@ function b() {
|
|
|
54
62
|
} finally {
|
|
55
63
|
X(null);
|
|
56
64
|
}
|
|
57
|
-
},
|
|
58
|
-
G(null), q(
|
|
59
|
-
},
|
|
65
|
+
}, Oe = () => {
|
|
66
|
+
G(null), q(b), U(!0);
|
|
67
|
+
}, ke = (e) => {
|
|
60
68
|
G(e), q({
|
|
61
69
|
clientName: e.clientName,
|
|
62
70
|
contactEmail: e.contactEmail ?? "",
|
|
63
71
|
contactPhone: e.contactPhone ?? "",
|
|
64
|
-
description: e.description ?? ""
|
|
72
|
+
description: e.description ?? "",
|
|
73
|
+
logoUrl: e.logoUrl ?? ""
|
|
65
74
|
}), U(!0);
|
|
75
|
+
}, Ae = async (e) => {
|
|
76
|
+
E(!0);
|
|
77
|
+
try {
|
|
78
|
+
let t = await me({
|
|
79
|
+
client: S,
|
|
80
|
+
blob: e,
|
|
81
|
+
filename: e.name,
|
|
82
|
+
mimeType: e.type || "application/octet-stream",
|
|
83
|
+
folderId: ""
|
|
84
|
+
}), { data: n } = await S.query({
|
|
85
|
+
query: ge,
|
|
86
|
+
variables: {
|
|
87
|
+
id: t.id,
|
|
88
|
+
expiresIn: 604800
|
|
89
|
+
},
|
|
90
|
+
fetchPolicy: "no-cache"
|
|
91
|
+
}), r = n?.getFileDownloadUrl;
|
|
92
|
+
if (!r) throw Error("No download URL returned");
|
|
93
|
+
q((e) => ({
|
|
94
|
+
...e,
|
|
95
|
+
logoUrl: r
|
|
96
|
+
}));
|
|
97
|
+
} catch {
|
|
98
|
+
x({
|
|
99
|
+
title: "Failed to upload logo",
|
|
100
|
+
variant: "error"
|
|
101
|
+
});
|
|
102
|
+
} finally {
|
|
103
|
+
E(!1);
|
|
104
|
+
}
|
|
66
105
|
}, Q = () => {
|
|
67
106
|
U(!1), G(null);
|
|
68
|
-
},
|
|
107
|
+
}, je = async () => {
|
|
69
108
|
if (K.clientName.trim()) try {
|
|
70
|
-
W ? (await
|
|
109
|
+
W ? (await be({ variables: {
|
|
71
110
|
id: W.id,
|
|
72
111
|
input: {
|
|
73
112
|
clientName: K.clientName.trim(),
|
|
74
113
|
contactEmail: K.contactEmail.trim() || void 0,
|
|
75
114
|
contactPhone: K.contactPhone.trim() || void 0,
|
|
76
|
-
description: K.description.trim() || void 0
|
|
115
|
+
description: K.description.trim() || void 0,
|
|
116
|
+
logoUrl: K.logoUrl || void 0
|
|
77
117
|
}
|
|
78
118
|
} }), x({
|
|
79
119
|
title: "Client updated",
|
|
80
120
|
variant: "success"
|
|
81
|
-
})) : (await
|
|
121
|
+
})) : (await ye({ variables: { input: {
|
|
82
122
|
clientName: K.clientName.trim(),
|
|
83
123
|
contactEmail: K.contactEmail.trim() || void 0,
|
|
84
124
|
contactPhone: K.contactPhone.trim() || void 0,
|
|
85
125
|
description: K.description.trim() || void 0,
|
|
126
|
+
logoUrl: K.logoUrl || void 0,
|
|
86
127
|
isActive: !0
|
|
87
128
|
} } }), x({
|
|
88
129
|
title: "Client added",
|
|
@@ -94,9 +135,9 @@ function b() {
|
|
|
94
135
|
variant: "error"
|
|
95
136
|
});
|
|
96
137
|
}
|
|
97
|
-
},
|
|
138
|
+
}, Me = async () => {
|
|
98
139
|
if (J) try {
|
|
99
|
-
await
|
|
140
|
+
await xe({ variables: { id: J.id } }), x({
|
|
100
141
|
title: "Client deleted",
|
|
101
142
|
variant: "success"
|
|
102
143
|
}), Y(null), await Z();
|
|
@@ -106,10 +147,10 @@ function b() {
|
|
|
106
147
|
variant: "error"
|
|
107
148
|
});
|
|
108
149
|
}
|
|
109
|
-
},
|
|
150
|
+
}, Ne = async (e) => {
|
|
110
151
|
X(e.id);
|
|
111
152
|
try {
|
|
112
|
-
await
|
|
153
|
+
await Se({ variables: {
|
|
113
154
|
id: e.id,
|
|
114
155
|
isActive: !e.isActive
|
|
115
156
|
} }), x({
|
|
@@ -124,12 +165,12 @@ function b() {
|
|
|
124
165
|
} finally {
|
|
125
166
|
X(null);
|
|
126
167
|
}
|
|
127
|
-
},
|
|
168
|
+
}, Pe = async () => {
|
|
128
169
|
H(!0);
|
|
129
170
|
try {
|
|
130
|
-
await
|
|
171
|
+
await j({
|
|
131
172
|
variables: {
|
|
132
|
-
limit:
|
|
173
|
+
limit: v,
|
|
133
174
|
offset: z.length
|
|
134
175
|
},
|
|
135
176
|
updateQuery: (e, { fetchMoreResult: t }) => t ? {
|
|
@@ -144,53 +185,53 @@ function b() {
|
|
|
144
185
|
H(!1);
|
|
145
186
|
}
|
|
146
187
|
};
|
|
147
|
-
if (
|
|
188
|
+
if (O && z.length === 0) return /* @__PURE__ */ g(a, {
|
|
148
189
|
title: "Client Portal",
|
|
149
190
|
description: "Manage clients and their projects",
|
|
150
|
-
children: /* @__PURE__ */
|
|
191
|
+
children: /* @__PURE__ */ g(n, {
|
|
151
192
|
variant: "list",
|
|
152
193
|
count: 4
|
|
153
194
|
})
|
|
154
195
|
});
|
|
155
|
-
if (
|
|
196
|
+
if (k) return /* @__PURE__ */ g(a, {
|
|
156
197
|
title: "Client Portal",
|
|
157
198
|
description: "Manage clients and their projects",
|
|
158
|
-
children: /* @__PURE__ */
|
|
199
|
+
children: /* @__PURE__ */ g("div", {
|
|
159
200
|
className: "rounded-lg border border-status-error-bg/40 bg-status-error-bg p-4 text-sm text-status-error-text",
|
|
160
201
|
children: "Failed to load client portal data. Please try again later."
|
|
161
202
|
})
|
|
162
203
|
});
|
|
163
|
-
let $ = /* @__PURE__ */
|
|
164
|
-
onClick:
|
|
204
|
+
let $ = /* @__PURE__ */ _("button", {
|
|
205
|
+
onClick: Oe,
|
|
165
206
|
className: "inline-flex items-center gap-1.5 rounded-md bg-action-primary-bg px-3 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90",
|
|
166
|
-
children: [/* @__PURE__ */
|
|
207
|
+
children: [/* @__PURE__ */ g(le, { className: "h-4 w-4" }), "Add Client"]
|
|
167
208
|
});
|
|
168
|
-
return /* @__PURE__ */
|
|
209
|
+
return /* @__PURE__ */ _(a, {
|
|
169
210
|
title: "Client Portal",
|
|
170
211
|
description: "Manage clients and their projects",
|
|
171
212
|
purpose: "Give clients a transparent window into the work you do for them — the projects, hours and progress tied to each one — so billing conversations are backed by data and trust, not spreadsheets.",
|
|
172
213
|
actions: $,
|
|
173
214
|
children: [
|
|
174
|
-
/* @__PURE__ */
|
|
215
|
+
/* @__PURE__ */ _("div", {
|
|
175
216
|
className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4",
|
|
176
217
|
children: [
|
|
177
|
-
/* @__PURE__ */
|
|
218
|
+
/* @__PURE__ */ g(t, {
|
|
178
219
|
featured: !0,
|
|
179
220
|
title: "Active Clients",
|
|
180
221
|
value: String(B?.activeClients ?? 0),
|
|
181
|
-
icon: /* @__PURE__ */
|
|
222
|
+
icon: /* @__PURE__ */ g(c, { className: "h-5 w-5" })
|
|
182
223
|
}),
|
|
183
|
-
/* @__PURE__ */
|
|
224
|
+
/* @__PURE__ */ g(t, {
|
|
184
225
|
title: "Total Projects",
|
|
185
226
|
value: String(B?.totalProjectsShared ?? 0),
|
|
186
|
-
icon: /* @__PURE__ */
|
|
227
|
+
icon: /* @__PURE__ */ g(d, { className: "h-5 w-5" })
|
|
187
228
|
}),
|
|
188
|
-
/* @__PURE__ */
|
|
229
|
+
/* @__PURE__ */ g(t, {
|
|
189
230
|
title: "Total Clients",
|
|
190
231
|
value: String(B?.totalClients ?? 0),
|
|
191
|
-
icon: /* @__PURE__ */
|
|
232
|
+
icon: /* @__PURE__ */ g(u, { className: "h-5 w-5" })
|
|
192
233
|
}),
|
|
193
|
-
/* @__PURE__ */
|
|
234
|
+
/* @__PURE__ */ g(t, {
|
|
194
235
|
title: "Active",
|
|
195
236
|
value: String(B?.activeClients ?? 0),
|
|
196
237
|
trend: {
|
|
@@ -200,28 +241,28 @@ function b() {
|
|
|
200
241
|
})
|
|
201
242
|
]
|
|
202
243
|
}),
|
|
203
|
-
z.length === 0 ? /* @__PURE__ */
|
|
244
|
+
z.length === 0 ? /* @__PURE__ */ g(ae, {
|
|
204
245
|
illustration: "empty-people",
|
|
205
246
|
title: "No clients configured yet",
|
|
206
247
|
description: "Add your first client to share projects and tracked hours with them.",
|
|
207
248
|
action: $
|
|
208
|
-
}) : /* @__PURE__ */
|
|
249
|
+
}) : /* @__PURE__ */ _(h, { children: [/* @__PURE__ */ g("div", {
|
|
209
250
|
className: "rounded-xl border border-border-seam bg-gloss-card shadow-pop",
|
|
210
|
-
children: /* @__PURE__ */
|
|
251
|
+
children: /* @__PURE__ */ g("div", {
|
|
211
252
|
className: "divide-y divide-border",
|
|
212
253
|
children: z.map((t) => {
|
|
213
|
-
let n = t.projects.reduce((e, t) => e + t.trackedHours, 0), r =
|
|
214
|
-
return /* @__PURE__ */
|
|
254
|
+
let n = t.projects.reduce((e, t) => e + t.trackedHours, 0), r = Te === t.id;
|
|
255
|
+
return /* @__PURE__ */ _("div", {
|
|
215
256
|
className: "flex flex-col gap-3 p-4 hover:bg-bg-sunken/50 transition-colors sm:flex-row sm:items-center sm:justify-between",
|
|
216
|
-
children: [/* @__PURE__ */
|
|
257
|
+
children: [/* @__PURE__ */ _("div", {
|
|
217
258
|
className: "flex items-center gap-3",
|
|
218
|
-
children: [/* @__PURE__ */
|
|
259
|
+
children: [/* @__PURE__ */ g("div", {
|
|
219
260
|
className: "flex h-10 w-10 items-center justify-center rounded-lg bg-action-primary-bg/10 text-sm font-medium text-primary",
|
|
220
261
|
children: e(t.clientName)
|
|
221
|
-
}), /* @__PURE__ */
|
|
262
|
+
}), /* @__PURE__ */ _("div", { children: [/* @__PURE__ */ g("p", {
|
|
222
263
|
className: "text-sm font-medium text-text-primary",
|
|
223
264
|
children: t.clientName
|
|
224
|
-
}), /* @__PURE__ */
|
|
265
|
+
}), /* @__PURE__ */ _("p", {
|
|
225
266
|
className: "text-xs text-text-secondary",
|
|
226
267
|
children: [
|
|
227
268
|
t.projects.length,
|
|
@@ -229,88 +270,88 @@ function b() {
|
|
|
229
270
|
" ",
|
|
230
271
|
n,
|
|
231
272
|
"h tracked",
|
|
232
|
-
t.contactEmail && /* @__PURE__ */
|
|
273
|
+
t.contactEmail && /* @__PURE__ */ _(h, { children: [" · ", t.contactEmail] })
|
|
233
274
|
]
|
|
234
275
|
})] })]
|
|
235
|
-
}), /* @__PURE__ */
|
|
276
|
+
}), /* @__PURE__ */ _("div", {
|
|
236
277
|
className: "flex flex-wrap items-center gap-2",
|
|
237
278
|
children: [
|
|
238
|
-
t.isActive && t.shareToken && /* @__PURE__ */
|
|
279
|
+
t.isActive && t.shareToken && /* @__PURE__ */ _(h, { children: [/* @__PURE__ */ g("button", {
|
|
239
280
|
type: "button",
|
|
240
|
-
onClick: () => void
|
|
281
|
+
onClick: () => void Ee(t),
|
|
241
282
|
title: "Copy the client's private share link",
|
|
242
283
|
className: "inline-flex items-center gap-1 rounded-md border border-border-seam bg-bg-surface px-2 py-1 text-xs text-text-secondary hover:bg-bg-sunken/50",
|
|
243
|
-
children:
|
|
244
|
-
}), /* @__PURE__ */
|
|
284
|
+
children: C === t.id ? /* @__PURE__ */ _(h, { children: [/* @__PURE__ */ g(l, { className: "h-3.5 w-3.5" }), " Copied"] }) : /* @__PURE__ */ _(h, { children: [/* @__PURE__ */ g(f, { className: "h-3.5 w-3.5" }), " Share link"] })
|
|
285
|
+
}), /* @__PURE__ */ g("button", {
|
|
245
286
|
type: "button",
|
|
246
|
-
disabled: r &&
|
|
247
|
-
onClick: () => void
|
|
287
|
+
disabled: r && F,
|
|
288
|
+
onClick: () => void De(t),
|
|
248
289
|
title: "Regenerate the link (invalidates the old one)",
|
|
249
290
|
className: "inline-flex items-center rounded-md border border-border-seam bg-bg-surface p-1.5 text-text-secondary hover:bg-bg-sunken/50 disabled:opacity-50",
|
|
250
|
-
children: /* @__PURE__ */
|
|
291
|
+
children: /* @__PURE__ */ g(de, { className: `h-3.5 w-3.5 ${r && F ? "animate-spin" : ""}` })
|
|
251
292
|
})] }),
|
|
252
|
-
/* @__PURE__ */
|
|
293
|
+
/* @__PURE__ */ _("button", {
|
|
253
294
|
type: "button",
|
|
254
295
|
disabled: r,
|
|
255
|
-
onClick: () => void
|
|
296
|
+
onClick: () => void Ne(t),
|
|
256
297
|
title: t.isActive ? "Deactivate client portal" : "Activate client portal",
|
|
257
298
|
className: "inline-flex items-center gap-1 rounded-md border border-border-seam bg-bg-surface px-2 py-1 text-xs text-text-secondary hover:bg-bg-sunken/50 disabled:opacity-50",
|
|
258
|
-
children: [/* @__PURE__ */
|
|
299
|
+
children: [/* @__PURE__ */ g(ue, { className: "h-3.5 w-3.5" }), t.isActive ? "Deactivate" : "Activate"]
|
|
259
300
|
}),
|
|
260
|
-
/* @__PURE__ */
|
|
301
|
+
/* @__PURE__ */ g(oe, {
|
|
261
302
|
label: t.isActive ? "active" : "inactive",
|
|
262
303
|
status: t.isActive ? "active" : "inactive"
|
|
263
304
|
}),
|
|
264
|
-
/* @__PURE__ */
|
|
305
|
+
/* @__PURE__ */ g("button", {
|
|
265
306
|
type: "button",
|
|
266
|
-
onClick: () =>
|
|
307
|
+
onClick: () => ke(t),
|
|
267
308
|
title: "Edit client",
|
|
268
309
|
className: "inline-flex items-center rounded-md border border-border-seam bg-bg-surface p-1.5 text-text-secondary hover:bg-bg-sunken/50",
|
|
269
|
-
children: /* @__PURE__ */
|
|
310
|
+
children: /* @__PURE__ */ g(p, { className: "h-3.5 w-3.5" })
|
|
270
311
|
}),
|
|
271
|
-
/* @__PURE__ */
|
|
312
|
+
/* @__PURE__ */ g("button", {
|
|
272
313
|
type: "button",
|
|
273
314
|
onClick: () => Y(t),
|
|
274
315
|
title: "Delete client",
|
|
275
316
|
className: "inline-flex items-center rounded-md border border-border-seam bg-bg-surface p-1.5 text-status-error-text hover:bg-status-error-bg",
|
|
276
|
-
children: /* @__PURE__ */
|
|
317
|
+
children: /* @__PURE__ */ g(fe, { className: "h-3.5 w-3.5" })
|
|
277
318
|
})
|
|
278
319
|
]
|
|
279
320
|
})]
|
|
280
321
|
}, t.id);
|
|
281
322
|
})
|
|
282
323
|
})
|
|
283
|
-
}),
|
|
324
|
+
}), Ce && /* @__PURE__ */ g("div", {
|
|
284
325
|
className: "mt-4 flex justify-center",
|
|
285
|
-
children: /* @__PURE__ */
|
|
286
|
-
onClick:
|
|
326
|
+
children: /* @__PURE__ */ g("button", {
|
|
327
|
+
onClick: Pe,
|
|
287
328
|
disabled: V,
|
|
288
329
|
className: "rounded-md border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken/50 disabled:opacity-50",
|
|
289
330
|
children: V ? "Loading..." : "Load more"
|
|
290
331
|
})
|
|
291
332
|
})] }),
|
|
292
|
-
/* @__PURE__ */
|
|
293
|
-
open:
|
|
333
|
+
/* @__PURE__ */ g(o, {
|
|
334
|
+
open: we,
|
|
294
335
|
onClose: Q,
|
|
295
336
|
title: W ? "Edit Client" : "Add Client",
|
|
296
337
|
description: W ? "Update this client's portal details." : "Set up a client so you can share projects and tracked hours with them.",
|
|
297
|
-
footer: /* @__PURE__ */
|
|
338
|
+
footer: /* @__PURE__ */ _(h, { children: [/* @__PURE__ */ g("button", {
|
|
298
339
|
onClick: Q,
|
|
299
340
|
className: "rounded-md border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken/50",
|
|
300
341
|
children: "Cancel"
|
|
301
|
-
}), /* @__PURE__ */
|
|
302
|
-
onClick:
|
|
303
|
-
disabled:
|
|
342
|
+
}), /* @__PURE__ */ g("button", {
|
|
343
|
+
onClick: je,
|
|
344
|
+
disabled: I || L || !K.clientName.trim(),
|
|
304
345
|
className: "rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 disabled:opacity-50",
|
|
305
|
-
children:
|
|
346
|
+
children: I || L ? "Saving..." : W ? "Save Changes" : "Add Client"
|
|
306
347
|
})] }),
|
|
307
|
-
children: /* @__PURE__ */
|
|
348
|
+
children: /* @__PURE__ */ _("div", {
|
|
308
349
|
className: "space-y-4",
|
|
309
350
|
children: [
|
|
310
|
-
/* @__PURE__ */
|
|
351
|
+
/* @__PURE__ */ _("div", { children: [/* @__PURE__ */ g("label", {
|
|
311
352
|
className: "block text-sm font-medium text-text-primary",
|
|
312
353
|
children: "Client Name"
|
|
313
|
-
}), /* @__PURE__ */
|
|
354
|
+
}), /* @__PURE__ */ g("input", {
|
|
314
355
|
type: "text",
|
|
315
356
|
placeholder: "e.g. Acme Corp",
|
|
316
357
|
value: K.clientName,
|
|
@@ -318,14 +359,14 @@ function b() {
|
|
|
318
359
|
...K,
|
|
319
360
|
clientName: e.target.value
|
|
320
361
|
}),
|
|
321
|
-
className:
|
|
362
|
+
className: y
|
|
322
363
|
})] }),
|
|
323
|
-
/* @__PURE__ */
|
|
364
|
+
/* @__PURE__ */ _("div", {
|
|
324
365
|
className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
|
|
325
|
-
children: [/* @__PURE__ */
|
|
366
|
+
children: [/* @__PURE__ */ _("div", { children: [/* @__PURE__ */ g("label", {
|
|
326
367
|
className: "block text-sm font-medium text-text-primary",
|
|
327
368
|
children: "Contact Email"
|
|
328
|
-
}), /* @__PURE__ */
|
|
369
|
+
}), /* @__PURE__ */ g("input", {
|
|
329
370
|
type: "email",
|
|
330
371
|
placeholder: "contact@client.com",
|
|
331
372
|
value: K.contactEmail,
|
|
@@ -333,11 +374,11 @@ function b() {
|
|
|
333
374
|
...K,
|
|
334
375
|
contactEmail: e.target.value
|
|
335
376
|
}),
|
|
336
|
-
className:
|
|
337
|
-
})] }), /* @__PURE__ */
|
|
377
|
+
className: y
|
|
378
|
+
})] }), /* @__PURE__ */ _("div", { children: [/* @__PURE__ */ g("label", {
|
|
338
379
|
className: "block text-sm font-medium text-text-primary",
|
|
339
380
|
children: "Contact Phone"
|
|
340
|
-
}), /* @__PURE__ */
|
|
381
|
+
}), /* @__PURE__ */ g("input", {
|
|
341
382
|
type: "tel",
|
|
342
383
|
placeholder: "Optional",
|
|
343
384
|
value: K.contactPhone,
|
|
@@ -345,13 +386,13 @@ function b() {
|
|
|
345
386
|
...K,
|
|
346
387
|
contactPhone: e.target.value
|
|
347
388
|
}),
|
|
348
|
-
className:
|
|
389
|
+
className: y
|
|
349
390
|
})] })]
|
|
350
391
|
}),
|
|
351
|
-
/* @__PURE__ */
|
|
392
|
+
/* @__PURE__ */ _("div", { children: [/* @__PURE__ */ g("label", {
|
|
352
393
|
className: "block text-sm font-medium text-text-primary",
|
|
353
394
|
children: "Description"
|
|
354
|
-
}), /* @__PURE__ */
|
|
395
|
+
}), /* @__PURE__ */ g("textarea", {
|
|
355
396
|
rows: 3,
|
|
356
397
|
placeholder: "Notes about this client (optional)",
|
|
357
398
|
value: K.description,
|
|
@@ -359,40 +400,65 @@ function b() {
|
|
|
359
400
|
...K,
|
|
360
401
|
description: e.target.value
|
|
361
402
|
}),
|
|
362
|
-
className:
|
|
363
|
-
})] })
|
|
403
|
+
className: y
|
|
404
|
+
})] }),
|
|
405
|
+
/* @__PURE__ */ _("div", { children: [
|
|
406
|
+
/* @__PURE__ */ g("label", {
|
|
407
|
+
className: "block text-sm font-medium text-text-primary",
|
|
408
|
+
children: "Logo"
|
|
409
|
+
}),
|
|
410
|
+
/* @__PURE__ */ g("input", {
|
|
411
|
+
type: "file",
|
|
412
|
+
accept: "image/*",
|
|
413
|
+
disabled: T,
|
|
414
|
+
onChange: (e) => {
|
|
415
|
+
let t = e.target.files?.[0];
|
|
416
|
+
t && Ae(t), e.target.value = "";
|
|
417
|
+
},
|
|
418
|
+
className: he
|
|
419
|
+
}),
|
|
420
|
+
T && /* @__PURE__ */ g("p", {
|
|
421
|
+
className: "mt-1 text-xs text-text-secondary",
|
|
422
|
+
children: "Uploading…"
|
|
423
|
+
}),
|
|
424
|
+
K.logoUrl && /* @__PURE__ */ g("img", {
|
|
425
|
+
src: K.logoUrl,
|
|
426
|
+
alt: "Client logo preview",
|
|
427
|
+
className: "mt-2 h-16 w-16 rounded-md border border-border-seam object-cover"
|
|
428
|
+
})
|
|
429
|
+
] })
|
|
364
430
|
]
|
|
365
431
|
})
|
|
366
432
|
}),
|
|
367
|
-
/* @__PURE__ */
|
|
433
|
+
/* @__PURE__ */ g(o, {
|
|
368
434
|
open: J !== null,
|
|
369
435
|
onClose: () => Y(null),
|
|
370
436
|
title: "Delete client?",
|
|
371
437
|
description: J ? `"${J.clientName}" and its share link will be removed.` : void 0,
|
|
372
438
|
size: "sm",
|
|
373
|
-
footer: /* @__PURE__ */
|
|
439
|
+
footer: /* @__PURE__ */ _(h, { children: [/* @__PURE__ */ g("button", {
|
|
374
440
|
onClick: () => Y(null),
|
|
375
441
|
className: "rounded-md border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken/50",
|
|
376
442
|
children: "Cancel"
|
|
377
|
-
}), /* @__PURE__ */
|
|
378
|
-
onClick:
|
|
379
|
-
disabled:
|
|
443
|
+
}), /* @__PURE__ */ g("button", {
|
|
444
|
+
onClick: Me,
|
|
445
|
+
disabled: R,
|
|
380
446
|
className: "rounded-md bg-status-error-bg px-4 py-2 text-sm font-medium text-status-error-text hover:bg-status-error-bg/80 disabled:opacity-50",
|
|
381
|
-
children:
|
|
447
|
+
children: R ? "Deleting..." : "Delete"
|
|
382
448
|
})] }),
|
|
383
|
-
children: /* @__PURE__ */
|
|
449
|
+
children: /* @__PURE__ */ g("p", {
|
|
384
450
|
className: "text-sm text-text-secondary",
|
|
385
451
|
children: "The client will lose access to their shared portal immediately. This cannot be undone."
|
|
386
452
|
})
|
|
387
453
|
}),
|
|
388
|
-
/* @__PURE__ */
|
|
389
|
-
toasts:
|
|
390
|
-
onDismiss:
|
|
454
|
+
/* @__PURE__ */ g(se, {
|
|
455
|
+
toasts: m,
|
|
456
|
+
onDismiss: ve
|
|
391
457
|
})
|
|
392
458
|
]
|
|
393
459
|
});
|
|
394
460
|
}
|
|
395
461
|
//#endregion
|
|
396
|
-
export {
|
|
462
|
+
export { x as ClientPortalPage };
|
|
397
463
|
|
|
398
464
|
//# sourceMappingURL=ClientPortalPage.js.map
|