@wealthx/shadcn 1.3.0 → 1.3.2
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/.turbo/turbo-build.log +53 -53
- package/CHANGELOG.md +12 -0
- package/dist/chunk-N6TNTQL6.mjs +446 -0
- package/dist/{chunk-FNQXOAYJ.mjs → chunk-Q2BGOAMG.mjs} +61 -28
- package/dist/components/ui/advisor-card.js +61 -28
- package/dist/components/ui/advisor-card.mjs +5 -3
- package/dist/components/ui/sidebar-nav.js +269 -176
- package/dist/components/ui/sidebar-nav.mjs +2 -1
- package/dist/index.js +516 -428
- package/dist/index.mjs +5 -3
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/src/components/index.tsx +2 -1
- package/src/components/ui/advisor-card.tsx +111 -54
- package/src/components/ui/sidebar-nav.tsx +195 -141
- package/src/styles/styles-css.ts +1 -1
- package/dist/chunk-ZC45IGZO.mjs +0 -388
package/package.json
CHANGED
package/src/components/index.tsx
CHANGED
|
@@ -11,9 +11,10 @@ export type {
|
|
|
11
11
|
AccordionContentProps,
|
|
12
12
|
} from "./ui/accordion";
|
|
13
13
|
|
|
14
|
-
export { AdvisorCard } from "./ui/advisor-card";
|
|
14
|
+
export { AdvisorCard, AdvisorInviteCard } from "./ui/advisor-card";
|
|
15
15
|
export type {
|
|
16
16
|
AdvisorCardProps,
|
|
17
|
+
AdvisorInviteCardProps,
|
|
17
18
|
AdvisorAppointmentStrip,
|
|
18
19
|
} from "./ui/advisor-card";
|
|
19
20
|
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
Mail,
|
|
11
11
|
MoreVertical,
|
|
12
12
|
Phone,
|
|
13
|
+
Plus,
|
|
13
14
|
} from "lucide-react";
|
|
14
15
|
import type { AppointmentStatus } from "./appointment-time-slot-picker";
|
|
15
16
|
|
|
@@ -39,27 +40,34 @@ export interface AdvisorCardProps {
|
|
|
39
40
|
phone: string;
|
|
40
41
|
/** Email address */
|
|
41
42
|
email: string;
|
|
43
|
+
/** Broker company name — shown as text fallback when no logo is provided */
|
|
44
|
+
companyName?: string;
|
|
42
45
|
/** URL of the broker company logo — renders as avatar image */
|
|
43
46
|
companyLogoUrl?: string;
|
|
44
|
-
/**
|
|
47
|
+
/** Explicit initials for the avatar fallback; derived from companyName if omitted */
|
|
45
48
|
avatarInitials?: string;
|
|
46
49
|
/** Whether this is the client's primary assigned advisor */
|
|
47
50
|
isPrimary?: boolean;
|
|
48
51
|
/**
|
|
49
|
-
* Upcoming
|
|
50
|
-
* - `undefined` — strip
|
|
51
|
-
* - `null` — empty state: "No upcoming appointments"
|
|
52
|
-
* -
|
|
52
|
+
* Upcoming appointments shown as stacked strips.
|
|
53
|
+
* - `undefined` — strip section hidden
|
|
54
|
+
* - `null` or `[]` — empty state: "No upcoming appointments"
|
|
55
|
+
* - array of items — one coloured strip per appointment
|
|
53
56
|
*/
|
|
54
|
-
|
|
57
|
+
appointments?: AdvisorAppointmentStrip[] | null;
|
|
55
58
|
/** Called when "Refer [name] to Others" is clicked */
|
|
56
59
|
onRefer?: () => void;
|
|
57
60
|
/** Called when the ⋮ overflow menu is clicked */
|
|
58
61
|
onMoreOptions?: () => void;
|
|
59
62
|
/** Called when "Book Appointment" is clicked */
|
|
60
63
|
onBookAppointment?: () => void;
|
|
61
|
-
/** Called when "View →" in
|
|
62
|
-
onViewAppointment?: () => void;
|
|
64
|
+
/** Called when "View →" in an appointment strip is clicked; receives the appointment index */
|
|
65
|
+
onViewAppointment?: (index: number) => void;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface AdvisorInviteCardProps {
|
|
69
|
+
/** Called when the "Add Advisor" CTA is clicked */
|
|
70
|
+
onInvite?: () => void;
|
|
63
71
|
}
|
|
64
72
|
|
|
65
73
|
// ---------------------------------------------------------------------------
|
|
@@ -99,15 +107,23 @@ export function AdvisorCard({
|
|
|
99
107
|
role,
|
|
100
108
|
phone,
|
|
101
109
|
email,
|
|
110
|
+
companyName,
|
|
102
111
|
companyLogoUrl,
|
|
103
112
|
avatarInitials,
|
|
104
113
|
isPrimary = false,
|
|
105
|
-
|
|
114
|
+
appointments,
|
|
106
115
|
onRefer,
|
|
107
116
|
onMoreOptions,
|
|
108
117
|
onBookAppointment,
|
|
109
118
|
onViewAppointment,
|
|
110
119
|
}: AdvisorCardProps) {
|
|
120
|
+
const hasAppointments = appointments !== undefined;
|
|
121
|
+
const appointmentList =
|
|
122
|
+
appointments === null ||
|
|
123
|
+
(Array.isArray(appointments) && appointments.length === 0)
|
|
124
|
+
? null
|
|
125
|
+
: appointments;
|
|
126
|
+
|
|
111
127
|
return (
|
|
112
128
|
<div className="flex flex-col border border-border bg-card">
|
|
113
129
|
{/* ── Advisor info ── */}
|
|
@@ -117,7 +133,15 @@ export function AdvisorCard({
|
|
|
117
133
|
<AvatarImage src={companyLogoUrl} alt={`${name} company logo`} />
|
|
118
134
|
)}
|
|
119
135
|
<AvatarFallback className="text-sm">
|
|
120
|
-
{avatarInitials ??
|
|
136
|
+
{avatarInitials ??
|
|
137
|
+
(companyName
|
|
138
|
+
? companyName
|
|
139
|
+
.split(" ")
|
|
140
|
+
.map((w) => w[0])
|
|
141
|
+
.join("")
|
|
142
|
+
.slice(0, 2)
|
|
143
|
+
.toUpperCase()
|
|
144
|
+
: name.slice(0, 2).toUpperCase())}
|
|
121
145
|
</AvatarFallback>
|
|
122
146
|
</Avatar>
|
|
123
147
|
|
|
@@ -125,12 +149,12 @@ export function AdvisorCard({
|
|
|
125
149
|
<p className="text-sm font-semibold leading-tight">{name}</p>
|
|
126
150
|
<p className="text-sm text-muted-foreground">{role}</p>
|
|
127
151
|
<div className="mt-2 flex flex-col gap-1">
|
|
128
|
-
<div className="flex items-center gap-1.5 text-
|
|
129
|
-
<Phone className="h-
|
|
152
|
+
<div className="flex items-center gap-1.5 text-sm text-muted-foreground">
|
|
153
|
+
<Phone className="h-4 w-4 shrink-0" />
|
|
130
154
|
<span>{phone}</span>
|
|
131
155
|
</div>
|
|
132
|
-
<div className="flex items-center gap-1.5 text-
|
|
133
|
-
<Mail className="h-
|
|
156
|
+
<div className="flex items-center gap-1.5 text-sm text-muted-foreground">
|
|
157
|
+
<Mail className="h-4 w-4 shrink-0" />
|
|
134
158
|
<span>{email}</span>
|
|
135
159
|
</div>
|
|
136
160
|
</div>
|
|
@@ -151,49 +175,52 @@ export function AdvisorCard({
|
|
|
151
175
|
</div>
|
|
152
176
|
</div>
|
|
153
177
|
|
|
154
|
-
{/* ── Appointment
|
|
155
|
-
{
|
|
178
|
+
{/* ── Appointment strips ── */}
|
|
179
|
+
{hasAppointments && (
|
|
156
180
|
<>
|
|
157
181
|
<Separator />
|
|
158
|
-
{
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
<
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
{
|
|
175
|
-
|
|
182
|
+
{appointmentList ? (
|
|
183
|
+
appointmentList.map((appt, i) => (
|
|
184
|
+
<React.Fragment key={i}>
|
|
185
|
+
{i > 0 && <Separator />}
|
|
186
|
+
<div
|
|
187
|
+
className={`flex items-center gap-3 px-4 py-3 ${STRIP_BG[appt.status]}`}
|
|
188
|
+
>
|
|
189
|
+
<CalendarCheck className="h-4 w-4 shrink-0 text-muted-foreground" />
|
|
190
|
+
<div className="flex min-w-0 flex-1 flex-col gap-0.5">
|
|
191
|
+
<div className="flex items-center gap-2">
|
|
192
|
+
<Badge
|
|
193
|
+
variant={STATUS_VARIANT[appt.status]}
|
|
194
|
+
className="text-[10px]"
|
|
195
|
+
>
|
|
196
|
+
{STATUS_LABEL[appt.status]}
|
|
197
|
+
</Badge>
|
|
198
|
+
{appt.appointmentType && (
|
|
199
|
+
<span className="truncate text-sm font-semibold">
|
|
200
|
+
{appt.appointmentType}
|
|
201
|
+
</span>
|
|
202
|
+
)}
|
|
203
|
+
</div>
|
|
204
|
+
<p className="whitespace-nowrap text-sm text-muted-foreground">
|
|
205
|
+
{appt.date} · {appt.timeStart}–{appt.timeEnd}
|
|
206
|
+
</p>
|
|
207
|
+
</div>
|
|
208
|
+
{onViewAppointment && (
|
|
209
|
+
<Button
|
|
210
|
+
variant="ghost"
|
|
211
|
+
size="sm"
|
|
212
|
+
className="h-7 shrink-0 gap-1 px-2 text-xs"
|
|
213
|
+
onClick={() => onViewAppointment(i)}
|
|
214
|
+
>
|
|
215
|
+
View
|
|
216
|
+
<ChevronRight className="h-3 w-3" />
|
|
217
|
+
</Button>
|
|
176
218
|
)}
|
|
177
219
|
</div>
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
{appointment.timeEnd}
|
|
181
|
-
</p>
|
|
182
|
-
</div>
|
|
183
|
-
{onViewAppointment && (
|
|
184
|
-
<Button
|
|
185
|
-
variant="ghost"
|
|
186
|
-
size="sm"
|
|
187
|
-
className="h-7 shrink-0 gap-1 px-2 text-xs"
|
|
188
|
-
onClick={onViewAppointment}
|
|
189
|
-
>
|
|
190
|
-
View
|
|
191
|
-
<ChevronRight className="h-3 w-3" />
|
|
192
|
-
</Button>
|
|
193
|
-
)}
|
|
194
|
-
</div>
|
|
220
|
+
</React.Fragment>
|
|
221
|
+
))
|
|
195
222
|
) : (
|
|
196
|
-
/*
|
|
223
|
+
/* Empty state */
|
|
197
224
|
<div className="flex items-center gap-3 px-4 py-3">
|
|
198
225
|
<Calendar className="h-4 w-4 shrink-0 text-muted-foreground" />
|
|
199
226
|
<p className="flex-1 text-xs text-muted-foreground">
|
|
@@ -206,18 +233,24 @@ export function AdvisorCard({
|
|
|
206
233
|
|
|
207
234
|
{/* ── Footer actions ── */}
|
|
208
235
|
<Separator />
|
|
209
|
-
<div className="flex
|
|
236
|
+
<div className="flex flex-col gap-2 px-4 py-3">
|
|
210
237
|
{onBookAppointment && (
|
|
211
238
|
<Button
|
|
212
239
|
variant="outline-primary"
|
|
213
240
|
size="sm"
|
|
241
|
+
className="w-full"
|
|
214
242
|
onClick={onBookAppointment}
|
|
215
243
|
>
|
|
216
244
|
Book Appointment
|
|
217
245
|
</Button>
|
|
218
246
|
)}
|
|
219
247
|
{onRefer && (
|
|
220
|
-
<Button
|
|
248
|
+
<Button
|
|
249
|
+
variant="outline"
|
|
250
|
+
size="sm"
|
|
251
|
+
className="w-full"
|
|
252
|
+
onClick={onRefer}
|
|
253
|
+
>
|
|
221
254
|
Refer {name} to Others
|
|
222
255
|
</Button>
|
|
223
256
|
)}
|
|
@@ -225,3 +258,27 @@ export function AdvisorCard({
|
|
|
225
258
|
</div>
|
|
226
259
|
);
|
|
227
260
|
}
|
|
261
|
+
|
|
262
|
+
// ---------------------------------------------------------------------------
|
|
263
|
+
// AdvisorInviteCard
|
|
264
|
+
// ---------------------------------------------------------------------------
|
|
265
|
+
|
|
266
|
+
export function AdvisorInviteCard({ onInvite }: AdvisorInviteCardProps) {
|
|
267
|
+
return (
|
|
268
|
+
<Button
|
|
269
|
+
variant="ghost"
|
|
270
|
+
onClick={onInvite}
|
|
271
|
+
className="flex h-auto w-full flex-col items-center justify-center gap-3 border border-dashed border-border bg-card p-8 text-center transition-colors hover:bg-muted/40"
|
|
272
|
+
>
|
|
273
|
+
<div className="flex h-10 w-10 items-center justify-center border border-dashed border-muted-foreground/40">
|
|
274
|
+
<Plus className="h-5 w-5 text-muted-foreground" />
|
|
275
|
+
</div>
|
|
276
|
+
<div className="flex flex-col gap-1">
|
|
277
|
+
<p className="text-sm font-medium">Add Another Advisor</p>
|
|
278
|
+
<p className="text-xs text-muted-foreground">
|
|
279
|
+
Connect more advisors to your account
|
|
280
|
+
</p>
|
|
281
|
+
</div>
|
|
282
|
+
</Button>
|
|
283
|
+
);
|
|
284
|
+
}
|