@fluid-app/portal-sdk 0.1.125 → 0.1.126
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/{ContactsScreen-CjFnJkt7.mjs → ContactsScreen-BKOHursc.mjs} +261 -610
- package/dist/ContactsScreen-BKOHursc.mjs.map +1 -0
- package/dist/{ContactsScreen-V9dHSQNX.cjs → ContactsScreen-DN8Qt2Ih.cjs} +260 -609
- package/dist/ContactsScreen-DN8Qt2Ih.cjs.map +1 -0
- package/dist/{ContactsScreen-CRROZFdR.cjs → ContactsScreen-FrVLbjGO.cjs} +1 -1
- package/dist/index.cjs +3 -3
- package/dist/index.mjs +3 -3
- package/package.json +12 -11
- package/dist/ContactsScreen-CjFnJkt7.mjs.map +0 -1
- package/dist/ContactsScreen-V9dHSQNX.cjs.map +0 -1
|
@@ -10,7 +10,7 @@ import { createContext, useCallback, useContext, useEffect, useImperativeHandle,
|
|
|
10
10
|
import { keepPreviousData, useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
11
11
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
12
12
|
import { z } from "zod";
|
|
13
|
-
import { AlignCenter, AlignJustify, AlignLeft, AlignRight, ArrowLeft, ArrowUpDown,
|
|
13
|
+
import { AlignCenter, AlignJustify, AlignLeft, AlignRight, ArrowLeft, ArrowUpDown, Building, Calendar, CalendarDays, ChevronLeft, ChevronRight, CircleCheck, ClipboardList, EllipsisVertical, List, ListChecks, ListOrdered, Mail, Paperclip, Pen, Pencil, Phone, Plus, Repeat2, Search, ShoppingCart, SquareCheckBig, StickyNote, Trash2, X } from "lucide-react";
|
|
14
14
|
import { FormProvider, useController, useFormContext, useWatch } from "react-hook-form";
|
|
15
15
|
//#region ../../contacts/ui/src/shared/components/contacts/statusBadge.tsx
|
|
16
16
|
const statusStyles = {
|
|
@@ -1965,7 +1965,7 @@ function formatDueDate$1(dateStr) {
|
|
|
1965
1965
|
year: "numeric"
|
|
1966
1966
|
});
|
|
1967
1967
|
}
|
|
1968
|
-
function EmptyState$
|
|
1968
|
+
function EmptyState$3({ onCreateNote }) {
|
|
1969
1969
|
return /* @__PURE__ */ jsxs("div", {
|
|
1970
1970
|
className: "flex flex-col items-center justify-center px-4 py-12 text-center",
|
|
1971
1971
|
children: [
|
|
@@ -2140,7 +2140,7 @@ function NotesList({ notes, isLoading, contactId, ref }) {
|
|
|
2140
2140
|
children: [/* @__PURE__ */ jsx(Plus, { className: "h-3.5 w-3.5" }), "Add Note"]
|
|
2141
2141
|
})]
|
|
2142
2142
|
}),
|
|
2143
|
-
notes.length === 0 ? /* @__PURE__ */ jsx(EmptyState$
|
|
2143
|
+
notes.length === 0 ? /* @__PURE__ */ jsx(EmptyState$3, { onCreateNote: openCreateModal }) : /* @__PURE__ */ jsx("div", {
|
|
2144
2144
|
className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3",
|
|
2145
2145
|
children: notes.map((note) => /* @__PURE__ */ jsx(NoteCard, {
|
|
2146
2146
|
note,
|
|
@@ -2179,327 +2179,6 @@ function NotesList({ notes, isLoading, contactId, ref }) {
|
|
|
2179
2179
|
});
|
|
2180
2180
|
}
|
|
2181
2181
|
//#endregion
|
|
2182
|
-
//#region ../../contacts/ui/src/portal/components/activities/activity-feed.tsx
|
|
2183
|
-
const SLUG_ICON_MAP = {
|
|
2184
|
-
order_placed: ShoppingCart,
|
|
2185
|
-
abandoned_cart: ShoppingCart,
|
|
2186
|
-
cart_items_added: ShoppingCart,
|
|
2187
|
-
new_cart_items_added: ShoppingCart,
|
|
2188
|
-
direct_message: MessageCircle,
|
|
2189
|
-
comment_reply: MessageCircle,
|
|
2190
|
-
message_received: MessageCircle,
|
|
2191
|
-
message_sent: MessageCircle,
|
|
2192
|
-
video: Play,
|
|
2193
|
-
video_complete: Play,
|
|
2194
|
-
video_contact: Play,
|
|
2195
|
-
video_complete_contact: Play,
|
|
2196
|
-
new_lead: UserPlus,
|
|
2197
|
-
page_views_contact: UserPlus,
|
|
2198
|
-
smart_link_clicked: UserPlus,
|
|
2199
|
-
page_views: Eye,
|
|
2200
|
-
upcoming_event: Calendar,
|
|
2201
|
-
review_left: Star,
|
|
2202
|
-
tasks: SquareCheckBig,
|
|
2203
|
-
announcements: Bell,
|
|
2204
|
-
fantasy_point: Trophy
|
|
2205
|
-
};
|
|
2206
|
-
function getActivityIcon(slug) {
|
|
2207
|
-
return slug && SLUG_ICON_MAP[slug] || User;
|
|
2208
|
-
}
|
|
2209
|
-
function getTypeLabel(slug) {
|
|
2210
|
-
if (!slug) return "Notification";
|
|
2211
|
-
if (slug.includes("message") || slug === "direct_message" || slug === "comment_reply") return "Message";
|
|
2212
|
-
if (slug.includes("page_view")) return "Alert from Fluid.app";
|
|
2213
|
-
if (slug.includes("video")) return "Alert from Fluid.app";
|
|
2214
|
-
if (slug.includes("order") || slug.includes("cart") || slug === "abandoned_cart") return "Alert from Fluid.app";
|
|
2215
|
-
if (slug === "tasks") return "Task";
|
|
2216
|
-
if (slug === "smart_link_clicked" || slug === "new_lead") return "Alert from Fluid.app";
|
|
2217
|
-
if (slug === "announcements") return "Announcement";
|
|
2218
|
-
if (slug === "upcoming_event") return "Event";
|
|
2219
|
-
if (slug === "review_left") return "Review";
|
|
2220
|
-
if (slug === "fantasy_point") return "Points";
|
|
2221
|
-
return "Notification";
|
|
2222
|
-
}
|
|
2223
|
-
function getSlugCategory(slug) {
|
|
2224
|
-
if (!slug) return "other";
|
|
2225
|
-
if (slug.includes("message") || slug === "direct_message" || slug === "comment_reply") return "message";
|
|
2226
|
-
if (slug === "tasks") return "task";
|
|
2227
|
-
if (slug.includes("page_view") || slug === "smart_link_clicked") return "page_view";
|
|
2228
|
-
if (slug.includes("video")) return "video";
|
|
2229
|
-
if (slug.includes("order") || slug.includes("cart") || slug === "abandoned_cart") return "order";
|
|
2230
|
-
return "other";
|
|
2231
|
-
}
|
|
2232
|
-
function getDateKey(timestamp) {
|
|
2233
|
-
return new Date(timestamp).toISOString().split("T")[0] ?? timestamp;
|
|
2234
|
-
}
|
|
2235
|
-
function formatDateHeader(timestamp) {
|
|
2236
|
-
const date = new Date(timestamp);
|
|
2237
|
-
const now = /* @__PURE__ */ new Date();
|
|
2238
|
-
const todayKey = now.toISOString().split("T")[0];
|
|
2239
|
-
const yesterdayKey = (/* @__PURE__ */ new Date(now.getTime() - 864e5)).toISOString().split("T")[0];
|
|
2240
|
-
const key = getDateKey(timestamp);
|
|
2241
|
-
if (key === todayKey) return "Today";
|
|
2242
|
-
if (key === yesterdayKey) return "Yesterday";
|
|
2243
|
-
return date.toLocaleDateString("en-US", {
|
|
2244
|
-
month: "long",
|
|
2245
|
-
day: "numeric"
|
|
2246
|
-
});
|
|
2247
|
-
}
|
|
2248
|
-
function formatTimestamp(timestamp) {
|
|
2249
|
-
return new Date(timestamp).toLocaleTimeString("en-US", {
|
|
2250
|
-
hour: "numeric",
|
|
2251
|
-
minute: "2-digit",
|
|
2252
|
-
hour12: true
|
|
2253
|
-
});
|
|
2254
|
-
}
|
|
2255
|
-
const filterOptions = ["All", "New"];
|
|
2256
|
-
function filterActivities(activities, filter) {
|
|
2257
|
-
if (filter === "New") return activities.filter((a) => !a.read_at);
|
|
2258
|
-
return activities;
|
|
2259
|
-
}
|
|
2260
|
-
function groupByDate(activities) {
|
|
2261
|
-
const sorted = [...activities].sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
|
|
2262
|
-
const map = /* @__PURE__ */ new Map();
|
|
2263
|
-
for (const activity of sorted) {
|
|
2264
|
-
const key = getDateKey(activity.created_at);
|
|
2265
|
-
const existing = map.get(key);
|
|
2266
|
-
if (existing) existing.push(activity);
|
|
2267
|
-
else map.set(key, [activity]);
|
|
2268
|
-
}
|
|
2269
|
-
return Array.from(map.entries()).map(([, items]) => ({
|
|
2270
|
-
label: formatDateHeader(items[0].created_at),
|
|
2271
|
-
items
|
|
2272
|
-
}));
|
|
2273
|
-
}
|
|
2274
|
-
function EmptyState$3() {
|
|
2275
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
2276
|
-
className: "flex flex-col items-center justify-center px-4 py-12 text-center",
|
|
2277
|
-
children: [
|
|
2278
|
-
/* @__PURE__ */ jsxs("div", {
|
|
2279
|
-
className: "relative mb-6",
|
|
2280
|
-
children: [/* @__PURE__ */ jsx("div", {
|
|
2281
|
-
className: "flex h-20 w-20 items-center justify-center rounded-full bg-gradient-to-br from-violet-100 to-indigo-100",
|
|
2282
|
-
children: /* @__PURE__ */ jsx(Rocket, { className: "h-9 w-9 text-violet-500" })
|
|
2283
|
-
}), /* @__PURE__ */ jsx("div", {
|
|
2284
|
-
className: "absolute -right-2 -bottom-1 flex h-9 w-9 items-center justify-center rounded-full border-2 border-white bg-gradient-to-br from-pink-100 to-rose-100 shadow-sm",
|
|
2285
|
-
children: /* @__PURE__ */ jsx(Share2, { className: "h-4 w-4 text-pink-500" })
|
|
2286
|
-
})]
|
|
2287
|
-
}),
|
|
2288
|
-
/* @__PURE__ */ jsx("h4", {
|
|
2289
|
-
className: "text-foreground text-base font-semibold",
|
|
2290
|
-
children: "No activity yet"
|
|
2291
|
-
}),
|
|
2292
|
-
/* @__PURE__ */ jsx("p", {
|
|
2293
|
-
className: "text-muted-foreground mt-1.5 max-w-[240px] text-sm leading-relaxed",
|
|
2294
|
-
children: "Reach out and share a product or media to start building this contact's story"
|
|
2295
|
-
})
|
|
2296
|
-
]
|
|
2297
|
-
});
|
|
2298
|
-
}
|
|
2299
|
-
function ContentCard({ activity }) {
|
|
2300
|
-
const category = getSlugCategory(activity.slug);
|
|
2301
|
-
const headerText = activity.formatted_description;
|
|
2302
|
-
const extraDescription = activity.description && activity.description !== headerText ? activity.description : null;
|
|
2303
|
-
const extraTitle = activity.title && activity.title !== headerText ? activity.title : null;
|
|
2304
|
-
if (!extraDescription && !extraTitle && category !== "task") return null;
|
|
2305
|
-
switch (category) {
|
|
2306
|
-
case "message":
|
|
2307
|
-
if (!extraDescription) return null;
|
|
2308
|
-
return /* @__PURE__ */ jsx("div", {
|
|
2309
|
-
className: "border-border bg-background mt-2 rounded-lg border p-3",
|
|
2310
|
-
children: /* @__PURE__ */ jsx("p", {
|
|
2311
|
-
className: "text-foreground text-sm leading-relaxed",
|
|
2312
|
-
children: extraDescription
|
|
2313
|
-
})
|
|
2314
|
-
});
|
|
2315
|
-
case "task":
|
|
2316
|
-
if (!extraDescription) return null;
|
|
2317
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
2318
|
-
className: "bg-muted/50 mt-2 rounded-lg p-3",
|
|
2319
|
-
children: [/* @__PURE__ */ jsx("p", {
|
|
2320
|
-
className: "text-muted-foreground text-sm",
|
|
2321
|
-
children: extraDescription
|
|
2322
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
2323
|
-
className: "text-primary mt-2 flex items-center gap-1.5",
|
|
2324
|
-
children: [/* @__PURE__ */ jsx(Calendar, { className: "h-3.5 w-3.5" }), /* @__PURE__ */ jsxs("span", {
|
|
2325
|
-
className: "text-xs font-medium",
|
|
2326
|
-
children: ["Due ", extraTitle || "TBD"]
|
|
2327
|
-
})]
|
|
2328
|
-
})]
|
|
2329
|
-
});
|
|
2330
|
-
case "page_view":
|
|
2331
|
-
if (!extraTitle && !extraDescription) return null;
|
|
2332
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
2333
|
-
className: "bg-muted/50 mt-2 rounded-lg p-3",
|
|
2334
|
-
children: [/* @__PURE__ */ jsx("p", {
|
|
2335
|
-
className: "text-foreground text-sm font-semibold",
|
|
2336
|
-
children: extraTitle || extraDescription
|
|
2337
|
-
}), /* @__PURE__ */ jsx("p", {
|
|
2338
|
-
className: "text-muted-foreground text-xs",
|
|
2339
|
-
children: getTypeLabel(activity.slug)
|
|
2340
|
-
})]
|
|
2341
|
-
});
|
|
2342
|
-
case "video":
|
|
2343
|
-
if (!extraTitle && !extraDescription) return null;
|
|
2344
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
2345
|
-
className: "bg-muted/50 mt-2 rounded-lg p-3",
|
|
2346
|
-
children: [extraTitle && /* @__PURE__ */ jsx("p", {
|
|
2347
|
-
className: "text-foreground text-sm font-semibold",
|
|
2348
|
-
children: extraTitle
|
|
2349
|
-
}), extraDescription && /* @__PURE__ */ jsx("p", {
|
|
2350
|
-
className: "text-muted-foreground mt-0.5 text-xs",
|
|
2351
|
-
children: extraDescription
|
|
2352
|
-
})]
|
|
2353
|
-
});
|
|
2354
|
-
case "order":
|
|
2355
|
-
if (!extraTitle && !extraDescription) return null;
|
|
2356
|
-
return /* @__PURE__ */ jsx("div", {
|
|
2357
|
-
className: "bg-muted/50 mt-2 rounded-lg p-3",
|
|
2358
|
-
children: /* @__PURE__ */ jsx("p", {
|
|
2359
|
-
className: "text-foreground text-sm font-semibold",
|
|
2360
|
-
children: extraTitle || extraDescription
|
|
2361
|
-
})
|
|
2362
|
-
});
|
|
2363
|
-
default: return null;
|
|
2364
|
-
}
|
|
2365
|
-
}
|
|
2366
|
-
function ActivityItem({ activity, isFirst, isLast }) {
|
|
2367
|
-
const Icon = getActivityIcon(activity.slug);
|
|
2368
|
-
const isUnread = !activity.read_at;
|
|
2369
|
-
const typeLabel = getTypeLabel(activity.slug);
|
|
2370
|
-
const headerText = activity.formatted_description;
|
|
2371
|
-
const subtitle = activity.description && activity.description !== headerText ? activity.description : activity.title && activity.title !== headerText ? activity.title : null;
|
|
2372
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
2373
|
-
className: "relative flex gap-3",
|
|
2374
|
-
children: [/* @__PURE__ */ jsxs("div", {
|
|
2375
|
-
className: "relative flex w-10 shrink-0 flex-col items-center",
|
|
2376
|
-
children: [
|
|
2377
|
-
!isFirst && !isLast && /* @__PURE__ */ jsx("div", { className: "absolute top-0 bottom-0 left-1/2 -translate-x-1/2 border-l-2 border-dashed border-blue-400" }),
|
|
2378
|
-
!isFirst && isLast && /* @__PURE__ */ jsx("div", { className: "absolute top-0 left-1/2 h-5 -translate-x-1/2 border-l-2 border-dashed border-blue-400" }),
|
|
2379
|
-
isFirst && !isLast && /* @__PURE__ */ jsx("div", { className: "absolute top-[44px] bottom-0 left-1/2 -translate-x-1/2 border-l-2 border-dashed border-blue-400" }),
|
|
2380
|
-
/* @__PURE__ */ jsxs("div", {
|
|
2381
|
-
className: "bg-background relative z-10 rounded-full",
|
|
2382
|
-
children: [/* @__PURE__ */ jsx("div", {
|
|
2383
|
-
className: "bg-foreground text-background flex h-10 w-10 items-center justify-center rounded-full",
|
|
2384
|
-
children: /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4" })
|
|
2385
|
-
}), isUnread && /* @__PURE__ */ jsx("div", { className: "border-background absolute -top-0.5 -right-0.5 h-3 w-3 rounded-full border-2 bg-blue-600" })]
|
|
2386
|
-
})
|
|
2387
|
-
]
|
|
2388
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
2389
|
-
className: "min-w-0 flex-1 pt-1 pb-8",
|
|
2390
|
-
children: [
|
|
2391
|
-
/* @__PURE__ */ jsxs("div", {
|
|
2392
|
-
className: "flex items-start gap-1.5",
|
|
2393
|
-
children: [
|
|
2394
|
-
/* @__PURE__ */ jsx("p", {
|
|
2395
|
-
className: "text-foreground text-sm font-semibold",
|
|
2396
|
-
children: headerText
|
|
2397
|
-
}),
|
|
2398
|
-
/* @__PURE__ */ jsx("span", {
|
|
2399
|
-
className: "text-muted-foreground mt-0.5 shrink-0 text-xs",
|
|
2400
|
-
children: typeLabel
|
|
2401
|
-
}),
|
|
2402
|
-
/* @__PURE__ */ jsx("span", {
|
|
2403
|
-
className: "text-muted-foreground mt-0.5 flex-1 text-right text-xs",
|
|
2404
|
-
children: formatTimestamp(activity.created_at)
|
|
2405
|
-
})
|
|
2406
|
-
]
|
|
2407
|
-
}),
|
|
2408
|
-
subtitle && /* @__PURE__ */ jsx("p", {
|
|
2409
|
-
className: "text-muted-foreground mt-0.5 text-sm",
|
|
2410
|
-
children: subtitle
|
|
2411
|
-
}),
|
|
2412
|
-
/* @__PURE__ */ jsx(ContentCard, { activity })
|
|
2413
|
-
]
|
|
2414
|
-
})]
|
|
2415
|
-
});
|
|
2416
|
-
}
|
|
2417
|
-
function DateSeparator({ label }) {
|
|
2418
|
-
return /* @__PURE__ */ jsx("div", {
|
|
2419
|
-
className: "py-3",
|
|
2420
|
-
children: /* @__PURE__ */ jsx("p", {
|
|
2421
|
-
className: "text-foreground text-base font-bold",
|
|
2422
|
-
children: label
|
|
2423
|
-
})
|
|
2424
|
-
});
|
|
2425
|
-
}
|
|
2426
|
-
function ActivityFeed({ activities, isLoading, onMarkRead }) {
|
|
2427
|
-
const [activeFilter, setActiveFilter] = useState("All");
|
|
2428
|
-
const handleFilterChange = (option) => {
|
|
2429
|
-
setActiveFilter(option);
|
|
2430
|
-
};
|
|
2431
|
-
const hasUnread = activities.some((a) => !a.read_at);
|
|
2432
|
-
const filtered = useMemo(() => filterActivities(activities, activeFilter), [activities, activeFilter]);
|
|
2433
|
-
const grouped = useMemo(() => groupByDate(filtered), [filtered]);
|
|
2434
|
-
const allItems = useMemo(() => grouped.flatMap((g) => g.items), [grouped]);
|
|
2435
|
-
if (isLoading) return /* @__PURE__ */ jsxs("div", {
|
|
2436
|
-
className: "space-y-4",
|
|
2437
|
-
children: [
|
|
2438
|
-
/* @__PURE__ */ jsx("div", { className: "bg-muted h-5 w-24 animate-pulse rounded" }),
|
|
2439
|
-
/* @__PURE__ */ jsx("div", {
|
|
2440
|
-
className: "flex gap-2",
|
|
2441
|
-
children: [
|
|
2442
|
-
1,
|
|
2443
|
-
2,
|
|
2444
|
-
3
|
|
2445
|
-
].map((i) => /* @__PURE__ */ jsx("div", { className: "bg-muted h-6 w-14 animate-pulse rounded-full" }, i))
|
|
2446
|
-
}),
|
|
2447
|
-
[
|
|
2448
|
-
1,
|
|
2449
|
-
2,
|
|
2450
|
-
3
|
|
2451
|
-
].map((i) => /* @__PURE__ */ jsxs("div", {
|
|
2452
|
-
className: "flex items-start gap-3",
|
|
2453
|
-
children: [/* @__PURE__ */ jsx("div", { className: "bg-muted h-10 w-10 animate-pulse rounded-full" }), /* @__PURE__ */ jsxs("div", {
|
|
2454
|
-
className: "flex-1 space-y-1.5",
|
|
2455
|
-
children: [/* @__PURE__ */ jsx("div", { className: "bg-muted h-4 w-3/4 animate-pulse rounded" }), /* @__PURE__ */ jsx("div", { className: "bg-muted h-3 w-1/3 animate-pulse rounded" })]
|
|
2456
|
-
})]
|
|
2457
|
-
}, i))
|
|
2458
|
-
]
|
|
2459
|
-
});
|
|
2460
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
2461
|
-
className: "space-y-4",
|
|
2462
|
-
children: [
|
|
2463
|
-
/* @__PURE__ */ jsx("h3", {
|
|
2464
|
-
className: "text-foreground text-lg font-semibold",
|
|
2465
|
-
children: "Recent Activity"
|
|
2466
|
-
}),
|
|
2467
|
-
/* @__PURE__ */ jsxs("div", {
|
|
2468
|
-
className: "flex items-center gap-2",
|
|
2469
|
-
children: [filterOptions.map((option) => /* @__PURE__ */ jsx("button", {
|
|
2470
|
-
type: "button",
|
|
2471
|
-
onClick: () => handleFilterChange(option),
|
|
2472
|
-
className: cn("rounded-full px-3 py-1 text-xs font-medium transition-colors", activeFilter === option ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground hover:bg-muted/80"),
|
|
2473
|
-
children: option
|
|
2474
|
-
}, option)), hasUnread && onMarkRead && /* @__PURE__ */ jsx("button", {
|
|
2475
|
-
type: "button",
|
|
2476
|
-
onClick: onMarkRead,
|
|
2477
|
-
className: "text-primary hover:text-primary/80 ml-auto text-xs font-medium transition-colors",
|
|
2478
|
-
children: "Mark all read"
|
|
2479
|
-
})]
|
|
2480
|
-
}),
|
|
2481
|
-
activities.length === 0 ? /* @__PURE__ */ jsx(EmptyState$3, {}) : filtered.length === 0 ? /* @__PURE__ */ jsxs("p", {
|
|
2482
|
-
className: "text-muted-foreground py-8 text-center text-sm",
|
|
2483
|
-
children: [
|
|
2484
|
-
"No ",
|
|
2485
|
-
activeFilter.toLowerCase(),
|
|
2486
|
-
" activities"
|
|
2487
|
-
]
|
|
2488
|
-
}) : /* @__PURE__ */ jsx("div", { children: grouped.map((group, groupIndex) => {
|
|
2489
|
-
const itemsBefore = grouped.slice(0, groupIndex).reduce((sum, g) => sum + g.items.length, 0);
|
|
2490
|
-
return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(DateSeparator, { label: group.label }), group.items.map((activity, itemIndex) => {
|
|
2491
|
-
const globalIndex = itemsBefore + itemIndex;
|
|
2492
|
-
return /* @__PURE__ */ jsx(ActivityItem, {
|
|
2493
|
-
activity,
|
|
2494
|
-
isFirst: globalIndex === 0,
|
|
2495
|
-
isLast: globalIndex === allItems.length - 1
|
|
2496
|
-
}, activity.id);
|
|
2497
|
-
})] }, group.label);
|
|
2498
|
-
}) })
|
|
2499
|
-
]
|
|
2500
|
-
});
|
|
2501
|
-
}
|
|
2502
|
-
//#endregion
|
|
2503
2182
|
//#region ../../contacts/ui/src/portal/hooks/contacts/use-toggle-task-completion.ts
|
|
2504
2183
|
function useToggleTaskCompletion(contactId) {
|
|
2505
2184
|
const queryClient = useQueryClient();
|
|
@@ -2916,9 +2595,9 @@ function useMarkContactRead(contactId) {
|
|
|
2916
2595
|
//#endregion
|
|
2917
2596
|
//#region ../../contacts/ui/src/portal/components/contacts/rep-contact-detail-view.tsx
|
|
2918
2597
|
const DEFAULT_COUNTRY_OPTIONS = [];
|
|
2919
|
-
function RepContactDetailView({ contact, contactId, countryOptions = DEFAULT_COUNTRY_OPTIONS, ordersSlot, subscriptionsSlot }) {
|
|
2920
|
-
const [activeTab, setActiveTab] = useState("
|
|
2921
|
-
const { data: activities = [], isLoading:
|
|
2598
|
+
function RepContactDetailView({ contact, contactId, countryOptions = DEFAULT_COUNTRY_OPTIONS, ordersSlot: _ordersSlot, subscriptionsSlot: _subscriptionsSlot }) {
|
|
2599
|
+
const [activeTab, setActiveTab] = useState("tasks");
|
|
2600
|
+
const { data: activities = [], isLoading: _isLoadingActivities } = useContactActivities(contactId);
|
|
2922
2601
|
const { data: tasks = [], isLoading: isLoadingTasks } = useContactTasks(contactId);
|
|
2923
2602
|
const { data: notes = [], isLoading: isLoadingNotes } = useContactNotes(contactId);
|
|
2924
2603
|
const markRead = useMarkContactRead(contactId);
|
|
@@ -2939,7 +2618,7 @@ function RepContactDetailView({ contact, contactId, countryOptions = DEFAULT_COU
|
|
|
2939
2618
|
const hasUnread = useMemo(() => activities.some((a) => !a.read_at), [activities]);
|
|
2940
2619
|
if (hasUnread && !prevHasUnreadRef.current) hasFiredRef.current = false;
|
|
2941
2620
|
prevHasUnreadRef.current = hasUnread;
|
|
2942
|
-
|
|
2621
|
+
useCallback(() => {
|
|
2943
2622
|
if (hasFiredRef.current || markRead.isPending) return;
|
|
2944
2623
|
hasFiredRef.current = true;
|
|
2945
2624
|
markRead.mutate();
|
|
@@ -2993,11 +2672,6 @@ function RepContactDetailView({ contact, contactId, countryOptions = DEFAULT_COU
|
|
|
2993
2672
|
className: "text-muted-foreground data-[state=active]:border-b-primary data-[state=active]:text-foreground rounded-none border-0 border-b-2 border-b-transparent px-4 py-2.5 text-sm font-medium shadow-none focus-visible:ring-0 focus-visible:outline-none data-[state=active]:bg-transparent data-[state=active]:shadow-none",
|
|
2994
2673
|
children: "Edit"
|
|
2995
2674
|
}),
|
|
2996
|
-
/* @__PURE__ */ jsx(TabsTrigger, {
|
|
2997
|
-
value: "activity",
|
|
2998
|
-
className: "text-muted-foreground data-[state=active]:border-b-primary data-[state=active]:text-foreground rounded-none border-0 border-b-2 border-b-transparent px-4 py-2.5 text-sm font-medium shadow-none focus-visible:ring-0 focus-visible:outline-none data-[state=active]:bg-transparent data-[state=active]:shadow-none",
|
|
2999
|
-
children: "Activity"
|
|
3000
|
-
}),
|
|
3001
2675
|
/* @__PURE__ */ jsx(TabsTrigger, {
|
|
3002
2676
|
value: "tasks",
|
|
3003
2677
|
className: "text-muted-foreground data-[state=active]:border-b-primary data-[state=active]:text-foreground rounded-none border-0 border-b-2 border-b-transparent px-4 py-2.5 text-sm font-medium shadow-none focus-visible:ring-0 focus-visible:outline-none data-[state=active]:bg-transparent data-[state=active]:shadow-none",
|
|
@@ -3007,16 +2681,6 @@ function RepContactDetailView({ contact, contactId, countryOptions = DEFAULT_COU
|
|
|
3007
2681
|
value: "notes",
|
|
3008
2682
|
className: "text-muted-foreground data-[state=active]:border-b-primary data-[state=active]:text-foreground rounded-none border-0 border-b-2 border-b-transparent px-4 py-2.5 text-sm font-medium shadow-none focus-visible:ring-0 focus-visible:outline-none data-[state=active]:bg-transparent data-[state=active]:shadow-none",
|
|
3009
2683
|
children: "Notes"
|
|
3010
|
-
}),
|
|
3011
|
-
/* @__PURE__ */ jsx(TabsTrigger, {
|
|
3012
|
-
value: "orders",
|
|
3013
|
-
className: "text-muted-foreground data-[state=active]:border-b-primary data-[state=active]:text-foreground rounded-none border-0 border-b-2 border-b-transparent px-4 py-2.5 text-sm font-medium shadow-none focus-visible:ring-0 focus-visible:outline-none data-[state=active]:bg-transparent data-[state=active]:shadow-none",
|
|
3014
|
-
children: "Orders"
|
|
3015
|
-
}),
|
|
3016
|
-
/* @__PURE__ */ jsx(TabsTrigger, {
|
|
3017
|
-
value: "subscriptions",
|
|
3018
|
-
className: "text-muted-foreground data-[state=active]:border-b-primary data-[state=active]:text-foreground rounded-none border-0 border-b-2 border-b-transparent px-4 py-2.5 text-sm font-medium shadow-none focus-visible:ring-0 focus-visible:outline-none data-[state=active]:bg-transparent data-[state=active]:shadow-none",
|
|
3019
|
-
children: "Subscriptions"
|
|
3020
2684
|
})
|
|
3021
2685
|
]
|
|
3022
2686
|
}),
|
|
@@ -3025,15 +2689,6 @@ function RepContactDetailView({ contact, contactId, countryOptions = DEFAULT_COU
|
|
|
3025
2689
|
className: "mt-6",
|
|
3026
2690
|
children: /* @__PURE__ */ jsx(ContactDetailsForm, { countries: countryOptions })
|
|
3027
2691
|
}),
|
|
3028
|
-
/* @__PURE__ */ jsx(TabsContent, {
|
|
3029
|
-
value: "activity",
|
|
3030
|
-
className: "mt-6",
|
|
3031
|
-
children: /* @__PURE__ */ jsx(ActivityFeed, {
|
|
3032
|
-
activities,
|
|
3033
|
-
isLoading: isLoadingActivities,
|
|
3034
|
-
onMarkRead: handleMarkRead
|
|
3035
|
-
})
|
|
3036
|
-
}),
|
|
3037
2692
|
/* @__PURE__ */ jsx(TabsContent, {
|
|
3038
2693
|
value: "tasks",
|
|
3039
2694
|
className: "mt-6",
|
|
@@ -3053,48 +2708,6 @@ function RepContactDetailView({ contact, contactId, countryOptions = DEFAULT_COU
|
|
|
3053
2708
|
contactId,
|
|
3054
2709
|
ref: openNoteModalRef
|
|
3055
2710
|
})
|
|
3056
|
-
}),
|
|
3057
|
-
/* @__PURE__ */ jsx(TabsContent, {
|
|
3058
|
-
value: "orders",
|
|
3059
|
-
className: "mt-6",
|
|
3060
|
-
children: ordersSlot ?? /* @__PURE__ */ jsxs("div", {
|
|
3061
|
-
className: "flex flex-col items-center justify-center py-16 text-center",
|
|
3062
|
-
children: [
|
|
3063
|
-
/* @__PURE__ */ jsx("div", {
|
|
3064
|
-
className: "bg-muted mb-4 flex h-14 w-14 items-center justify-center rounded-full",
|
|
3065
|
-
children: /* @__PURE__ */ jsx(ShoppingCart, { className: "text-muted-foreground h-6 w-6" })
|
|
3066
|
-
}),
|
|
3067
|
-
/* @__PURE__ */ jsx("h3", {
|
|
3068
|
-
className: "text-foreground text-sm font-medium",
|
|
3069
|
-
children: "No orders yet"
|
|
3070
|
-
}),
|
|
3071
|
-
/* @__PURE__ */ jsx("p", {
|
|
3072
|
-
className: "text-muted-foreground mt-1 text-sm",
|
|
3073
|
-
children: "Orders placed by this contact will appear here."
|
|
3074
|
-
})
|
|
3075
|
-
]
|
|
3076
|
-
})
|
|
3077
|
-
}),
|
|
3078
|
-
/* @__PURE__ */ jsx(TabsContent, {
|
|
3079
|
-
value: "subscriptions",
|
|
3080
|
-
className: "mt-6",
|
|
3081
|
-
children: subscriptionsSlot ?? /* @__PURE__ */ jsxs("div", {
|
|
3082
|
-
className: "flex flex-col items-center justify-center py-16 text-center",
|
|
3083
|
-
children: [
|
|
3084
|
-
/* @__PURE__ */ jsx("div", {
|
|
3085
|
-
className: "bg-muted mb-4 flex h-14 w-14 items-center justify-center rounded-full",
|
|
3086
|
-
children: /* @__PURE__ */ jsx(Repeat2, { className: "text-muted-foreground h-6 w-6" })
|
|
3087
|
-
}),
|
|
3088
|
-
/* @__PURE__ */ jsx("h3", {
|
|
3089
|
-
className: "text-foreground text-sm font-medium",
|
|
3090
|
-
children: "No subscriptions yet"
|
|
3091
|
-
}),
|
|
3092
|
-
/* @__PURE__ */ jsx("p", {
|
|
3093
|
-
className: "text-muted-foreground mt-1 text-sm",
|
|
3094
|
-
children: "Subscriptions for this contact will appear here."
|
|
3095
|
-
})
|
|
3096
|
-
]
|
|
3097
|
-
})
|
|
3098
2711
|
})
|
|
3099
2712
|
]
|
|
3100
2713
|
})
|
|
@@ -3867,345 +3480,383 @@ function useCreateContactMutation(queryKeyPrefix = "contacts", options) {
|
|
|
3867
3480
|
});
|
|
3868
3481
|
}
|
|
3869
3482
|
//#endregion
|
|
3870
|
-
//#region
|
|
3483
|
+
//#region src/contacts/use-contacts-config.ts
|
|
3871
3484
|
/**
|
|
3872
|
-
*
|
|
3873
|
-
*
|
|
3485
|
+
* Hook that derives a FetchClient from the portal SDK's FluidProvider context.
|
|
3874
3486
|
*
|
|
3875
|
-
*
|
|
3876
|
-
*
|
|
3877
|
-
* @param params? - params?
|
|
3487
|
+
* Maps FluidSDKConfig fields to a FetchClient suitable for contacts, notes, and tasks APIs.
|
|
3488
|
+
* Follows the same pattern as useMessagingConfig.
|
|
3878
3489
|
*/
|
|
3879
|
-
|
|
3880
|
-
|
|
3490
|
+
function useContactsConfig() {
|
|
3491
|
+
const { config } = useFluidContext();
|
|
3492
|
+
return { client: useMemo(() => {
|
|
3493
|
+
const baseUrl = config.baseUrl.replace(/\/+$/, "").replace(/\/api$/, "");
|
|
3494
|
+
const csrfToken = typeof document !== "undefined" ? document.querySelector("meta[name=\"csrf-token\"]")?.getAttribute("content") : null;
|
|
3495
|
+
return createFetchClient({
|
|
3496
|
+
baseUrl,
|
|
3497
|
+
getAuthToken: config.getAuthToken,
|
|
3498
|
+
onAuthError: config.onAuthError,
|
|
3499
|
+
defaultHeaders: {
|
|
3500
|
+
...config.defaultHeaders,
|
|
3501
|
+
...csrfToken ? { "X-CSRF-Token": csrfToken } : {}
|
|
3502
|
+
}
|
|
3503
|
+
});
|
|
3504
|
+
}, [
|
|
3505
|
+
config.baseUrl,
|
|
3506
|
+
config.getAuthToken,
|
|
3507
|
+
config.onAuthError,
|
|
3508
|
+
config.defaultHeaders
|
|
3509
|
+
]) };
|
|
3881
3510
|
}
|
|
3511
|
+
//#endregion
|
|
3512
|
+
//#region ../../api-clients/portal-tenant-contacts/src/namespaces/portal_tenant_contacts.ts
|
|
3882
3513
|
/**
|
|
3883
|
-
*
|
|
3884
|
-
*
|
|
3514
|
+
* List contacts with cursor pagination
|
|
3515
|
+
* Returns a paginated list of contacts belonging to the authenticated member.
|
|
3885
3516
|
*
|
|
3886
3517
|
* @param client - Fetch client instance
|
|
3887
|
-
* @param
|
|
3518
|
+
* @param [params] - params
|
|
3888
3519
|
*/
|
|
3889
|
-
async function
|
|
3890
|
-
return client.
|
|
3520
|
+
async function contacts_list(client, params) {
|
|
3521
|
+
return client.get(`/api/contacts`, params);
|
|
3891
3522
|
}
|
|
3892
3523
|
/**
|
|
3893
|
-
* Create a contact
|
|
3894
|
-
*
|
|
3524
|
+
* Create a new contact
|
|
3525
|
+
* Creates a new contact for the authenticated member.
|
|
3895
3526
|
*
|
|
3896
3527
|
* @param client - Fetch client instance
|
|
3897
3528
|
* @param body - body
|
|
3898
3529
|
*/
|
|
3899
|
-
async function
|
|
3900
|
-
return client.post(`/api/
|
|
3901
|
-
}
|
|
3902
|
-
/**
|
|
3903
|
-
* List user's contacts
|
|
3904
|
-
*
|
|
3905
|
-
*
|
|
3906
|
-
* @param client - Fetch client instance
|
|
3907
|
-
* @param params? - params?
|
|
3908
|
-
*/
|
|
3909
|
-
async function listUserContacts(client, params) {
|
|
3910
|
-
return client.get(`/api/users/v2025-06/contacts`, params);
|
|
3911
|
-
}
|
|
3912
|
-
/**
|
|
3913
|
-
* Delete a contact
|
|
3914
|
-
*
|
|
3915
|
-
*
|
|
3916
|
-
* @param client - Fetch client instance
|
|
3917
|
-
* @param id - id
|
|
3918
|
-
*/
|
|
3919
|
-
async function deleteUserContact(client, id) {
|
|
3920
|
-
return client.delete(`/api/users/v2025-06/contacts/${id}`);
|
|
3530
|
+
async function contacts_create(client, body) {
|
|
3531
|
+
return client.post(`/api/contacts`, body);
|
|
3921
3532
|
}
|
|
3922
3533
|
/**
|
|
3923
|
-
* Get a contact
|
|
3924
|
-
*
|
|
3534
|
+
* Get a specific contact
|
|
3535
|
+
* Returns a single contact by ID.
|
|
3925
3536
|
*
|
|
3926
3537
|
* @param client - Fetch client instance
|
|
3927
3538
|
* @param id - id
|
|
3928
3539
|
*/
|
|
3929
|
-
async function
|
|
3930
|
-
return client.get(`/api/
|
|
3540
|
+
async function contacts_show(client, id) {
|
|
3541
|
+
return client.get(`/api/contacts/${id}`);
|
|
3931
3542
|
}
|
|
3932
3543
|
/**
|
|
3933
3544
|
* Update a contact
|
|
3934
|
-
*
|
|
3545
|
+
* Updates an existing contact's attributes.
|
|
3935
3546
|
*
|
|
3936
3547
|
* @param client - Fetch client instance
|
|
3937
3548
|
* @param id - id
|
|
3938
3549
|
* @param body - body
|
|
3939
3550
|
*/
|
|
3940
|
-
async function
|
|
3941
|
-
return client.patch(`/api/
|
|
3551
|
+
async function contacts_update(client, id, body) {
|
|
3552
|
+
return client.patch(`/api/contacts/${id}`, body);
|
|
3942
3553
|
}
|
|
3943
3554
|
/**
|
|
3944
|
-
*
|
|
3945
|
-
*
|
|
3555
|
+
* Delete a contact
|
|
3556
|
+
* Soft-deletes a contact by ID.
|
|
3946
3557
|
*
|
|
3947
3558
|
* @param client - Fetch client instance
|
|
3948
3559
|
* @param id - id
|
|
3949
|
-
* @param body - body
|
|
3950
3560
|
*/
|
|
3951
|
-
async function
|
|
3952
|
-
return client.
|
|
3561
|
+
async function contacts_destroy(client, id) {
|
|
3562
|
+
return client.delete(`/api/contacts/${id}`);
|
|
3953
3563
|
}
|
|
3954
3564
|
/**
|
|
3955
|
-
*
|
|
3956
|
-
*
|
|
3565
|
+
* Delete multiple contacts
|
|
3566
|
+
* Soft-deletes multiple contacts by their IDs.
|
|
3957
3567
|
*
|
|
3958
3568
|
* @param client - Fetch client instance
|
|
3959
|
-
* @param
|
|
3569
|
+
* @param body - body
|
|
3960
3570
|
*/
|
|
3961
|
-
async function
|
|
3962
|
-
return client.
|
|
3571
|
+
async function contacts_bulk_destroy(client, body) {
|
|
3572
|
+
return client.delete(`/api/contacts/bulk`, { body });
|
|
3963
3573
|
}
|
|
3964
3574
|
/**
|
|
3965
|
-
* List
|
|
3966
|
-
*
|
|
3575
|
+
* List notes for a contact
|
|
3576
|
+
* Returns notes attached to a contact.
|
|
3967
3577
|
*
|
|
3968
3578
|
* @param client - Fetch client instance
|
|
3969
|
-
* @param
|
|
3970
|
-
* @param params
|
|
3579
|
+
* @param contact_id - contact_id
|
|
3580
|
+
* @param [params] - params
|
|
3971
3581
|
*/
|
|
3972
|
-
async function
|
|
3973
|
-
return client.get(`/api/
|
|
3582
|
+
async function contacts_notes_list(client, contact_id, params) {
|
|
3583
|
+
return client.get(`/api/contacts/${contact_id}/notes`, params);
|
|
3974
3584
|
}
|
|
3975
3585
|
/**
|
|
3976
|
-
*
|
|
3977
|
-
*
|
|
3586
|
+
* Create a note for a contact
|
|
3587
|
+
* Adds a new note to a contact.
|
|
3978
3588
|
*
|
|
3979
3589
|
* @param client - Fetch client instance
|
|
3980
|
-
* @param
|
|
3590
|
+
* @param contact_id - contact_id
|
|
3591
|
+
* @param body - body
|
|
3981
3592
|
*/
|
|
3982
|
-
async function
|
|
3983
|
-
return client.post(`/api/
|
|
3593
|
+
async function contacts_notes_create(client, contact_id, body) {
|
|
3594
|
+
return client.post(`/api/contacts/${contact_id}/notes`, body);
|
|
3984
3595
|
}
|
|
3985
3596
|
/**
|
|
3986
|
-
* List
|
|
3987
|
-
*
|
|
3597
|
+
* List tasks for a contact
|
|
3598
|
+
* Returns tasks assigned to a contact.
|
|
3988
3599
|
*
|
|
3989
3600
|
* @param client - Fetch client instance
|
|
3990
|
-
* @param
|
|
3991
|
-
* @param params
|
|
3601
|
+
* @param contact_id - contact_id
|
|
3602
|
+
* @param [params] - params
|
|
3992
3603
|
*/
|
|
3993
|
-
async function
|
|
3994
|
-
return client.get(`/api/
|
|
3604
|
+
async function contacts_tasks_list(client, contact_id, params) {
|
|
3605
|
+
return client.get(`/api/contacts/${contact_id}/tasks`, params);
|
|
3995
3606
|
}
|
|
3996
3607
|
/**
|
|
3997
3608
|
* Create a task for a contact
|
|
3998
|
-
*
|
|
3609
|
+
* Adds a new task to a contact.
|
|
3999
3610
|
*
|
|
4000
3611
|
* @param client - Fetch client instance
|
|
4001
|
-
* @param
|
|
3612
|
+
* @param contact_id - contact_id
|
|
4002
3613
|
* @param body - body
|
|
4003
3614
|
*/
|
|
4004
|
-
async function
|
|
4005
|
-
return client.post(`/api/
|
|
3615
|
+
async function contacts_tasks_create(client, contact_id, body) {
|
|
3616
|
+
return client.post(`/api/contacts/${contact_id}/tasks`, body);
|
|
4006
3617
|
}
|
|
4007
3618
|
/**
|
|
4008
|
-
*
|
|
4009
|
-
*
|
|
3619
|
+
* Update a note
|
|
3620
|
+
* Updates an existing note on a contact.
|
|
4010
3621
|
*
|
|
4011
3622
|
* @param client - Fetch client instance
|
|
3623
|
+
* @param contact_id - contact_id
|
|
4012
3624
|
* @param id - id
|
|
3625
|
+
* @param body - body
|
|
4013
3626
|
*/
|
|
4014
|
-
async function
|
|
4015
|
-
return client.
|
|
3627
|
+
async function contacts_notes_update(client, contact_id, id, body) {
|
|
3628
|
+
return client.patch(`/api/contacts/${contact_id}/notes/${id}`, body);
|
|
4016
3629
|
}
|
|
4017
|
-
//#endregion
|
|
4018
|
-
//#region ../../notes/fluid-user-notes-api-client/src/namespaces/users_notes.ts
|
|
4019
3630
|
/**
|
|
4020
3631
|
* Delete a note
|
|
4021
|
-
*
|
|
3632
|
+
* Removes a note from a contact.
|
|
4022
3633
|
*
|
|
4023
3634
|
* @param client - Fetch client instance
|
|
3635
|
+
* @param contact_id - contact_id
|
|
4024
3636
|
* @param id - id
|
|
4025
|
-
* @param params - params
|
|
4026
3637
|
*/
|
|
4027
|
-
async function
|
|
4028
|
-
return client.delete(`/api/
|
|
3638
|
+
async function contacts_notes_destroy(client, contact_id, id) {
|
|
3639
|
+
return client.delete(`/api/contacts/${contact_id}/notes/${id}`);
|
|
4029
3640
|
}
|
|
4030
3641
|
/**
|
|
4031
|
-
* Update a
|
|
4032
|
-
*
|
|
3642
|
+
* Update a task
|
|
3643
|
+
* Updates an existing task on a contact.
|
|
4033
3644
|
*
|
|
4034
3645
|
* @param client - Fetch client instance
|
|
3646
|
+
* @param contact_id - contact_id
|
|
4035
3647
|
* @param id - id
|
|
4036
3648
|
* @param body - body
|
|
4037
3649
|
*/
|
|
4038
|
-
async function
|
|
4039
|
-
return client.patch(`/api/
|
|
3650
|
+
async function contacts_tasks_update(client, contact_id, id, body) {
|
|
3651
|
+
return client.patch(`/api/contacts/${contact_id}/tasks/${id}`, body);
|
|
4040
3652
|
}
|
|
4041
|
-
//#endregion
|
|
4042
|
-
//#region ../../tasks/fluid-user-tasks-api-client/src/namespaces/users_tasks.ts
|
|
4043
3653
|
/**
|
|
4044
3654
|
* Delete a task
|
|
4045
|
-
*
|
|
3655
|
+
* Removes a task from a contact.
|
|
4046
3656
|
*
|
|
4047
3657
|
* @param client - Fetch client instance
|
|
3658
|
+
* @param contact_id - contact_id
|
|
4048
3659
|
* @param id - id
|
|
4049
3660
|
*/
|
|
4050
|
-
async function
|
|
4051
|
-
return client.delete(`/api/
|
|
4052
|
-
}
|
|
4053
|
-
/**
|
|
4054
|
-
* Update a task
|
|
4055
|
-
*
|
|
4056
|
-
*
|
|
4057
|
-
* @param client - Fetch client instance
|
|
4058
|
-
* @param id - id
|
|
4059
|
-
* @param body - body
|
|
4060
|
-
*/
|
|
4061
|
-
async function updateUserTask(client, id, body) {
|
|
4062
|
-
return client.patch(`/api/users/v2025-06/tasks/${id}`, body);
|
|
3661
|
+
async function contacts_tasks_destroy(client, contact_id, id) {
|
|
3662
|
+
return client.delete(`/api/contacts/${contact_id}/tasks/${id}`);
|
|
4063
3663
|
}
|
|
4064
3664
|
//#endregion
|
|
4065
|
-
//#region
|
|
3665
|
+
//#region src/contacts/create-portal-contacts-adapter.ts
|
|
3666
|
+
const EMPTY_META = {
|
|
3667
|
+
total_count: 0,
|
|
3668
|
+
total_pages: 0,
|
|
3669
|
+
current_page: 1
|
|
3670
|
+
};
|
|
3671
|
+
function paginationFromBff(meta, itemCount, currentPage, pageSize) {
|
|
3672
|
+
if (!meta) return EMPTY_META;
|
|
3673
|
+
const hasNext = !!meta.pagination?.next_cursor;
|
|
3674
|
+
const totalCount = meta.total_count ?? (hasNext ? (currentPage + 1) * pageSize : (currentPage - 1) * pageSize + itemCount);
|
|
3675
|
+
return {
|
|
3676
|
+
total_count: totalCount,
|
|
3677
|
+
total_pages: Math.max(1, Math.ceil(totalCount / pageSize)),
|
|
3678
|
+
current_page: currentPage,
|
|
3679
|
+
request_id: meta.request_id ?? void 0,
|
|
3680
|
+
timestamp: meta.timestamp ?? void 0
|
|
3681
|
+
};
|
|
3682
|
+
}
|
|
3683
|
+
/** BFF Contact → core Contact. Fills missing fields with safe defaults. */
|
|
3684
|
+
function mapContact(raw) {
|
|
3685
|
+
return {
|
|
3686
|
+
id: raw.id,
|
|
3687
|
+
full_name: `${raw.first_name ?? ""} ${raw.last_name ?? ""}`.trim(),
|
|
3688
|
+
first_name: raw.first_name ?? null,
|
|
3689
|
+
last_name: raw.last_name ?? null,
|
|
3690
|
+
email: raw.email ?? null,
|
|
3691
|
+
phone: raw.phone ?? null,
|
|
3692
|
+
status: raw.status ?? null,
|
|
3693
|
+
address: raw.address ?? null,
|
|
3694
|
+
city: raw.city ?? null,
|
|
3695
|
+
state: raw.state ?? null,
|
|
3696
|
+
postal_code: raw.postal_code ?? null,
|
|
3697
|
+
avatar_url: raw.avatar_url ?? null,
|
|
3698
|
+
country: raw.country ?? null,
|
|
3699
|
+
tags: raw.tags ?? [],
|
|
3700
|
+
metadata: {},
|
|
3701
|
+
created_at: raw.created_at,
|
|
3702
|
+
updated_at: raw.updated_at
|
|
3703
|
+
};
|
|
3704
|
+
}
|
|
3705
|
+
/** BFF Note → core ContactNote. */
|
|
3706
|
+
function mapNote(raw) {
|
|
3707
|
+
return {
|
|
3708
|
+
id: raw.id,
|
|
3709
|
+
title: raw.title ?? "",
|
|
3710
|
+
body: raw.body ?? "",
|
|
3711
|
+
note_type: null,
|
|
3712
|
+
due_date: null,
|
|
3713
|
+
due_time: null,
|
|
3714
|
+
pinned: null,
|
|
3715
|
+
created_at: raw.created_at,
|
|
3716
|
+
updated_at: raw.updated_at,
|
|
3717
|
+
contact_id: raw.contact_id ?? 0,
|
|
3718
|
+
assets: []
|
|
3719
|
+
};
|
|
3720
|
+
}
|
|
3721
|
+
/** BFF Task → core ContactTask. */
|
|
3722
|
+
function mapTask(raw) {
|
|
3723
|
+
return {
|
|
3724
|
+
id: raw.id,
|
|
3725
|
+
body: raw.title ?? "",
|
|
3726
|
+
due_at: raw.due_date ?? null,
|
|
3727
|
+
completed_at: raw.completed_at ?? (raw.completed ? (/* @__PURE__ */ new Date()).toISOString() : null),
|
|
3728
|
+
created_at: raw.created_at,
|
|
3729
|
+
contact_id: raw.contact_id ?? null
|
|
3730
|
+
};
|
|
3731
|
+
}
|
|
4066
3732
|
/**
|
|
4067
|
-
*
|
|
3733
|
+
* The contacts-ui sends offset pagination params (page, per_page, sort_by,
|
|
3734
|
+
* sort_direction, search, status). The BFF expects cursor pagination
|
|
3735
|
+
* (page[cursor], page[limit], search, tags). Translate between the two.
|
|
4068
3736
|
*
|
|
4069
|
-
*
|
|
4070
|
-
*
|
|
4071
|
-
*
|
|
4072
|
-
* Read methods map responses through `satisfies` for compile-time drift
|
|
4073
|
-
* detection. Mutation methods use input-side assertions where the port
|
|
4074
|
-
* intentionally uses loose types (Record<string, unknown>) that don't match
|
|
4075
|
-
* the generated client's strict body schemas.
|
|
3737
|
+
* `cursorCache` maps page numbers → cursor tokens so page-2+ requests can
|
|
3738
|
+
* resolve to the correct cursor. The cache is populated from BFF responses.
|
|
4076
3739
|
*/
|
|
4077
|
-
function
|
|
3740
|
+
function mapListParams(params, cursorCache) {
|
|
3741
|
+
if (!params) return void 0;
|
|
3742
|
+
const mapped = {};
|
|
3743
|
+
if (params.per_page || params.limit) mapped["page[limit]"] = params.per_page ?? params.limit;
|
|
3744
|
+
const page = params.page ?? 1;
|
|
3745
|
+
if (page > 1) {
|
|
3746
|
+
const cursor = cursorCache.get(page);
|
|
3747
|
+
if (cursor) mapped["page[cursor]"] = cursor;
|
|
3748
|
+
}
|
|
3749
|
+
if (params.search_query || params.search || params.query) mapped.search = params.search_query ?? params.search ?? params.query;
|
|
3750
|
+
if (params.tags) mapped.tags = params.tags;
|
|
3751
|
+
return mapped;
|
|
3752
|
+
}
|
|
3753
|
+
function createContactsAdapter(client) {
|
|
3754
|
+
const cursorCache = /* @__PURE__ */ new Map();
|
|
4078
3755
|
return {
|
|
4079
3756
|
getContact: async (id) => {
|
|
4080
|
-
return { contact: (await
|
|
3757
|
+
return { contact: mapContact((await contacts_show(client, id)).contact) };
|
|
4081
3758
|
},
|
|
4082
3759
|
listContacts: async (params) => {
|
|
4083
|
-
const
|
|
3760
|
+
const raw = params;
|
|
3761
|
+
const page = raw?.page ?? 1;
|
|
3762
|
+
const pageSize = raw?.per_page ?? 25;
|
|
3763
|
+
const body = await contacts_list(client, mapListParams(raw, cursorCache));
|
|
3764
|
+
const meta = body.meta;
|
|
3765
|
+
const nextCursor = (meta?.pagination)?.next_cursor;
|
|
3766
|
+
if (nextCursor) cursorCache.set(page + 1, nextCursor);
|
|
3767
|
+
const contacts = (body.contacts ?? []).map(mapContact);
|
|
4084
3768
|
return {
|
|
4085
|
-
contacts
|
|
4086
|
-
meta:
|
|
3769
|
+
contacts,
|
|
3770
|
+
meta: paginationFromBff(meta, contacts.length, page, pageSize)
|
|
4087
3771
|
};
|
|
4088
3772
|
},
|
|
4089
|
-
createContact: (data) =>
|
|
4090
|
-
|
|
4091
|
-
id: Number(id),
|
|
4092
|
-
contact: data
|
|
4093
|
-
}),
|
|
4094
|
-
deleteContact: (id) => deleteUserContact(client, id),
|
|
4095
|
-
bulkDeleteContacts: (ids) => bulkDeleteUserContacts(client, { contact_ids: ids }),
|
|
4096
|
-
listActivities: async (contactId) => {
|
|
4097
|
-
const response = await listUserContactActivities(client, contactId);
|
|
4098
|
-
return {
|
|
4099
|
-
activities: response.activities ?? [],
|
|
4100
|
-
meta: response.meta ?? {}
|
|
4101
|
-
};
|
|
3773
|
+
createContact: async (data) => {
|
|
3774
|
+
return contacts_create(client, { contact: data });
|
|
4102
3775
|
},
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
const response = await listUserContactOrders(client, contactId, params);
|
|
4106
|
-
return {
|
|
4107
|
-
orders: response.orders ?? [],
|
|
4108
|
-
meta: response.meta ?? {}
|
|
4109
|
-
};
|
|
3776
|
+
updateContact: async (id, data) => {
|
|
3777
|
+
return contacts_update(client, id, { contact: data });
|
|
4110
3778
|
},
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
3779
|
+
deleteContact: async (id) => {
|
|
3780
|
+
return contacts_destroy(client, id);
|
|
3781
|
+
},
|
|
3782
|
+
bulkDeleteContacts: async (ids) => {
|
|
3783
|
+
return contacts_bulk_destroy(client, { ids });
|
|
3784
|
+
},
|
|
3785
|
+
listActivities: async () => ({
|
|
3786
|
+
activities: [],
|
|
3787
|
+
meta: EMPTY_META
|
|
3788
|
+
}),
|
|
3789
|
+
markRead: async () => ({}),
|
|
3790
|
+
listOrders: async () => ({
|
|
3791
|
+
orders: [],
|
|
3792
|
+
meta: EMPTY_META
|
|
3793
|
+
}),
|
|
3794
|
+
listSubscriptionOrders: async () => ({
|
|
3795
|
+
subscription_orders: [],
|
|
3796
|
+
meta: EMPTY_META
|
|
3797
|
+
})
|
|
4118
3798
|
};
|
|
4119
3799
|
}
|
|
4120
|
-
|
|
4121
|
-
* Creates a NotesApi adapter backed by the user-contacts and user-notes
|
|
4122
|
-
* generated clients.
|
|
4123
|
-
*
|
|
4124
|
-
* List and create use the contact sub-resource endpoints (usersContacts),
|
|
4125
|
-
* while update and delete use the standalone notes endpoints (usersNotes).
|
|
4126
|
-
*/
|
|
4127
|
-
function createNotesApiAdapter(client) {
|
|
3800
|
+
function createNotesAdapter(client) {
|
|
4128
3801
|
return {
|
|
4129
3802
|
listNotes: async (contactId) => {
|
|
4130
|
-
return { notes: (await
|
|
3803
|
+
return { notes: ((await contacts_notes_list(client, contactId)).notes ?? []).map(mapNote) };
|
|
4131
3804
|
},
|
|
4132
|
-
createNote: (contactId, input) =>
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
}
|
|
4141
|
-
deleteNote: (noteId, contactId) => deleteUserNote(client, noteId, { contact_id: Number(contactId) })
|
|
3805
|
+
createNote: async (contactId, input) => {
|
|
3806
|
+
return contacts_notes_create(client, contactId, { note: input });
|
|
3807
|
+
},
|
|
3808
|
+
updateNote: async (noteId, contactId, input) => {
|
|
3809
|
+
return contacts_notes_update(client, contactId, noteId, { note: input });
|
|
3810
|
+
},
|
|
3811
|
+
deleteNote: async (noteId, contactId) => {
|
|
3812
|
+
return contacts_notes_destroy(client, contactId, noteId);
|
|
3813
|
+
}
|
|
4142
3814
|
};
|
|
4143
3815
|
}
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
* generated clients.
|
|
4147
|
-
*
|
|
4148
|
-
* List and create use the contact sub-resource endpoints (usersContacts),
|
|
4149
|
-
* while update and delete use the standalone tasks endpoints (usersTasks).
|
|
4150
|
-
*/
|
|
4151
|
-
function createTasksApiAdapter(client) {
|
|
3816
|
+
function createTasksAdapter(client) {
|
|
3817
|
+
let lastContactId = 0;
|
|
4152
3818
|
return {
|
|
4153
3819
|
listTasks: async (contactId) => {
|
|
4154
|
-
|
|
3820
|
+
lastContactId = contactId;
|
|
3821
|
+
return { tasks: ((await contacts_tasks_list(client, contactId)).tasks ?? []).map(mapTask) };
|
|
4155
3822
|
},
|
|
4156
|
-
createTask: (contactId, input) =>
|
|
4157
|
-
|
|
4158
|
-
task:
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
3823
|
+
createTask: async (contactId, input) => {
|
|
3824
|
+
lastContactId = contactId;
|
|
3825
|
+
return contacts_tasks_create(client, contactId, { task: {
|
|
3826
|
+
title: input.body,
|
|
3827
|
+
due_date: input.due_at
|
|
3828
|
+
} });
|
|
3829
|
+
},
|
|
3830
|
+
updateTask: async (taskId, input) => {
|
|
3831
|
+
return contacts_tasks_update(client, input.contact_id ?? lastContactId, taskId, { task: {
|
|
3832
|
+
title: input.body ?? void 0,
|
|
3833
|
+
completed: input.completed_at !== void 0 ? input.completed_at !== null : void 0,
|
|
3834
|
+
due_date: input.due_at
|
|
3835
|
+
} });
|
|
3836
|
+
},
|
|
3837
|
+
deleteTask: async (taskId) => {
|
|
3838
|
+
if (!lastContactId) throw new Error("deleteTask called before contact context is established");
|
|
3839
|
+
return contacts_tasks_destroy(client, lastContactId, taskId);
|
|
3840
|
+
}
|
|
4165
3841
|
};
|
|
4166
3842
|
}
|
|
4167
3843
|
/**
|
|
4168
|
-
* Creates a composite ContactsDomainApi
|
|
4169
|
-
*
|
|
4170
|
-
* ContactsApiProvider context.
|
|
3844
|
+
* Creates a composite ContactsDomainApi backed by the portal-tenant
|
|
3845
|
+
* Contacts BFF endpoints.
|
|
4171
3846
|
*/
|
|
4172
|
-
function
|
|
3847
|
+
function createPortalContactsDomainApiAdapter(client) {
|
|
4173
3848
|
return {
|
|
4174
|
-
contacts:
|
|
4175
|
-
notes:
|
|
4176
|
-
tasks:
|
|
3849
|
+
contacts: createContactsAdapter(client),
|
|
3850
|
+
notes: createNotesAdapter(client),
|
|
3851
|
+
tasks: createTasksAdapter(client)
|
|
4177
3852
|
};
|
|
4178
3853
|
}
|
|
4179
3854
|
//#endregion
|
|
4180
|
-
//#region src/contacts/use-contacts-config.ts
|
|
4181
|
-
/**
|
|
4182
|
-
* Hook that derives a FetchClient from the portal SDK's FluidProvider context.
|
|
4183
|
-
*
|
|
4184
|
-
* Maps FluidSDKConfig fields to a FetchClient suitable for contacts, notes, and tasks APIs.
|
|
4185
|
-
* Follows the same pattern as useMessagingConfig.
|
|
4186
|
-
*/
|
|
4187
|
-
function useContactsConfig() {
|
|
4188
|
-
const { config } = useFluidContext();
|
|
4189
|
-
return { client: useMemo(() => {
|
|
4190
|
-
return createFetchClient({
|
|
4191
|
-
baseUrl: config.baseUrl.replace(/\/+$/, "").replace(/\/api$/, ""),
|
|
4192
|
-
getAuthToken: config.getAuthToken,
|
|
4193
|
-
onAuthError: config.onAuthError,
|
|
4194
|
-
defaultHeaders: config.defaultHeaders
|
|
4195
|
-
});
|
|
4196
|
-
}, [
|
|
4197
|
-
config.baseUrl,
|
|
4198
|
-
config.getAuthToken,
|
|
4199
|
-
config.onAuthError,
|
|
4200
|
-
config.defaultHeaders
|
|
4201
|
-
]) };
|
|
4202
|
-
}
|
|
4203
|
-
//#endregion
|
|
4204
3855
|
//#region src/contacts/PortalContactsApiProvider.tsx
|
|
4205
3856
|
function PortalContactsApiProvider({ children }) {
|
|
4206
3857
|
const { client } = useContactsConfig();
|
|
4207
3858
|
return /* @__PURE__ */ jsx(ContactsApiProvider, {
|
|
4208
|
-
value: useMemo(() =>
|
|
3859
|
+
value: useMemo(() => createPortalContactsDomainApiAdapter(client), [client]),
|
|
4209
3860
|
children
|
|
4210
3861
|
});
|
|
4211
3862
|
}
|
|
@@ -4408,4 +4059,4 @@ const contactsScreenPropertySchema = {
|
|
|
4408
4059
|
//#endregion
|
|
4409
4060
|
export { ContactsScreen_exports as n, contactsScreenPropertySchema as r, ContactsScreen as t };
|
|
4410
4061
|
|
|
4411
|
-
//# sourceMappingURL=ContactsScreen-
|
|
4062
|
+
//# sourceMappingURL=ContactsScreen-BKOHursc.mjs.map
|