@retinalabsllc/zairusjs 21.1.4 → 21.1.6
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/index.d.mts +183 -1
- package/dist/index.d.ts +183 -1
- package/dist/index.js +1010 -0
- package/dist/index.mjs +1038 -0
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -6397,6 +6397,1038 @@ var HomeHuddleCalendar = ({
|
|
|
6397
6397
|
}
|
|
6398
6398
|
));
|
|
6399
6399
|
};
|
|
6400
|
+
|
|
6401
|
+
// src/components/UniversalApplicationsPage.tsx
|
|
6402
|
+
import React55 from "react";
|
|
6403
|
+
import { HugeiconsIcon as HugeiconsIcon41 } from "@hugeicons/react";
|
|
6404
|
+
import {
|
|
6405
|
+
ArrowLeft01Icon as ArrowLeft01Icon21,
|
|
6406
|
+
ArrowRight01Icon as ArrowRight01Icon16,
|
|
6407
|
+
Loading03Icon as Loading03Icon29
|
|
6408
|
+
} from "@hugeicons/core-free-icons";
|
|
6409
|
+
var formatType = (type) => {
|
|
6410
|
+
if (!type) return "";
|
|
6411
|
+
return type.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ");
|
|
6412
|
+
};
|
|
6413
|
+
var ApplicationIcon = ({ icon, sizeClass = "w-10 h-10" }) => {
|
|
6414
|
+
return /* @__PURE__ */ React55.createElement("div", { className: `relative shrink-0 aspect-square ${sizeClass}` }, /* @__PURE__ */ React55.createElement("div", { className: "w-full h-full aspect-square rounded-lg bg-neutral-50 flex items-center justify-center overflow-hidden" }, icon ? /* @__PURE__ */ React55.createElement(HugeiconsIcon41, { icon, size: 20, className: "text-stone-500" }) : /* @__PURE__ */ React55.createElement("div", { className: "w-4 h-4 rounded-sm bg-stone-300" })));
|
|
6415
|
+
};
|
|
6416
|
+
var PageSpinner9 = () => /* @__PURE__ */ React55.createElement("div", { className: "flex justify-center items-center py-12" }, /* @__PURE__ */ React55.createElement(HugeiconsIcon41, { icon: Loading03Icon29, size: 32, className: "animate-spin mb-4 text-black" }));
|
|
6417
|
+
var UniversalApplicationsPage = ({
|
|
6418
|
+
headerTitle,
|
|
6419
|
+
headerDescription,
|
|
6420
|
+
applications,
|
|
6421
|
+
isLoading,
|
|
6422
|
+
currentPage,
|
|
6423
|
+
totalPages,
|
|
6424
|
+
onPageChange,
|
|
6425
|
+
onApplicationClick,
|
|
6426
|
+
onCreateApplication
|
|
6427
|
+
}) => {
|
|
6428
|
+
return /* @__PURE__ */ React55.createElement("div", { className: "w-full max-w-3xl mx-auto flex flex-col animate-in fade-in duration-300 relative" }, /* @__PURE__ */ React55.createElement("div", { className: "flex flex-col gap-8 p-6 rounded-2xl bg-white w-full" }, /* @__PURE__ */ React55.createElement("div", { className: "flex flex-col gap-1" }, /* @__PURE__ */ React55.createElement("div", { className: "flex flex-row items-center justify-between gap-4" }, /* @__PURE__ */ React55.createElement("h2", { className: "text-black text-xl tracking-tight" }, headerTitle), /* @__PURE__ */ React55.createElement(
|
|
6429
|
+
"button",
|
|
6430
|
+
{
|
|
6431
|
+
onClick: () => onCreateApplication?.(),
|
|
6432
|
+
className: "shrink-0 px-4 py-1.5 border border-stone-200 text-black text-xs tracking-wide rounded-full hover:bg-stone-50 transition-colors outline-none"
|
|
6433
|
+
},
|
|
6434
|
+
"Create new"
|
|
6435
|
+
)), headerDescription && /* @__PURE__ */ React55.createElement("p", { className: "text-xs text-stone-500" }, headerDescription)), /* @__PURE__ */ React55.createElement("div", { className: "w-full overflow-hidden" }, isLoading ? /* @__PURE__ */ React55.createElement(PageSpinner9, null) : /* @__PURE__ */ React55.createElement("div", { className: "flex flex-col min-w-0" }, /* @__PURE__ */ React55.createElement("div", null, applications.length === 0 ? /* @__PURE__ */ React55.createElement("p", { className: "text-xs text-stone-400 py-6 text-center" }, "No applications available") : applications.map((app) => /* @__PURE__ */ React55.createElement(
|
|
6436
|
+
"div",
|
|
6437
|
+
{
|
|
6438
|
+
key: app.id,
|
|
6439
|
+
onClick: () => onApplicationClick(app.id),
|
|
6440
|
+
className: "flex flex-row items-center gap-4 py-2 hover:bg-stone-50 transition-colors cursor-pointer group min-w-0 px-3 -mx-3 rounded-xl"
|
|
6441
|
+
},
|
|
6442
|
+
/* @__PURE__ */ React55.createElement(ApplicationIcon, { icon: app.icon }),
|
|
6443
|
+
/* @__PURE__ */ React55.createElement("div", { className: "flex flex-col min-w-0 flex-1" }, /* @__PURE__ */ React55.createElement("p", { className: "text-sm text-black tracking-tight truncate" }, formatType(app.type)), /* @__PURE__ */ React55.createElement("span", { className: "text-xs text-stone-500 truncate block mt-0.5" }, app.timeString)),
|
|
6444
|
+
/* @__PURE__ */ React55.createElement(HugeiconsIcon41, { icon: ArrowRight01Icon16, size: 14, className: "shrink-0 text-stone-400" })
|
|
6445
|
+
))), /* @__PURE__ */ React55.createElement("div", { className: "flex items-center justify-between pt-6 mt-2 " }, /* @__PURE__ */ React55.createElement("span", { className: "text-xs text-stone-400 tracking-[0.2em]" }, "Page ", currentPage, " of ", totalPages === 0 ? 1 : totalPages), /* @__PURE__ */ React55.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React55.createElement(
|
|
6446
|
+
"button",
|
|
6447
|
+
{
|
|
6448
|
+
onClick: () => onPageChange(currentPage - 1),
|
|
6449
|
+
disabled: currentPage <= 1 || isLoading,
|
|
6450
|
+
className: "p-2 bg-white border border-stone-200 rounded-full text-black hover:bg-stone-50 disabled:opacity-30 disabled:cursor-not-allowed transition-all outline-none"
|
|
6451
|
+
},
|
|
6452
|
+
/* @__PURE__ */ React55.createElement(HugeiconsIcon41, { icon: ArrowLeft01Icon21, size: 14 })
|
|
6453
|
+
), /* @__PURE__ */ React55.createElement(
|
|
6454
|
+
"button",
|
|
6455
|
+
{
|
|
6456
|
+
onClick: () => onPageChange(currentPage + 1),
|
|
6457
|
+
disabled: currentPage >= totalPages || isLoading || totalPages === 0,
|
|
6458
|
+
className: "p-2 bg-white border border-stone-200 rounded-full text-black hover:bg-stone-50 disabled:opacity-30 disabled:cursor-not-allowed transition-all outline-none"
|
|
6459
|
+
},
|
|
6460
|
+
/* @__PURE__ */ React55.createElement(HugeiconsIcon41, { icon: ArrowRight01Icon16, size: 14 })
|
|
6461
|
+
)))))));
|
|
6462
|
+
};
|
|
6463
|
+
|
|
6464
|
+
// src/components/UniversalHome3.tsx
|
|
6465
|
+
import React56, { useState as useState40 } from "react";
|
|
6466
|
+
import { useRouter as useRouter5 } from "next/navigation";
|
|
6467
|
+
import { HugeiconsIcon as HugeiconsIcon42 } from "@hugeicons/react";
|
|
6468
|
+
import toast17 from "react-hot-toast";
|
|
6469
|
+
import {
|
|
6470
|
+
Loading03Icon as Loading03Icon30,
|
|
6471
|
+
Notification01Icon as Notification01Icon3,
|
|
6472
|
+
ArrowLeft01Icon as ArrowLeft01Icon22,
|
|
6473
|
+
ArrowRight01Icon as ArrowRight01Icon17,
|
|
6474
|
+
CancelCircleIcon as CancelCircleIcon14,
|
|
6475
|
+
ArrowUpRight01Icon as ArrowUpRight01Icon4,
|
|
6476
|
+
Robot01Icon as Robot01Icon2,
|
|
6477
|
+
SidebarLeft01Icon
|
|
6478
|
+
} from "@hugeicons/core-free-icons";
|
|
6479
|
+
var UniversalHome3 = ({
|
|
6480
|
+
createApplicationAction,
|
|
6481
|
+
checkApplicationAction,
|
|
6482
|
+
notifications = [],
|
|
6483
|
+
notificationPage = 1,
|
|
6484
|
+
notificationTotalPages = 1,
|
|
6485
|
+
isNotifsLoading = false,
|
|
6486
|
+
onNotificationPageChange,
|
|
6487
|
+
onNotificationClick,
|
|
6488
|
+
onResolveInvite,
|
|
6489
|
+
formatNotifDate,
|
|
6490
|
+
customContent,
|
|
6491
|
+
applicationsProps
|
|
6492
|
+
}) => {
|
|
6493
|
+
const [showNotifDialog, setShowNotifDialog] = useState40(false);
|
|
6494
|
+
const [selectedNotif, setSelectedNotif] = useState40(null);
|
|
6495
|
+
const [isResolving, setIsResolving] = useState40(false);
|
|
6496
|
+
const router = useRouter5();
|
|
6497
|
+
const hasUnreadNotifs = notifications.some((n) => !n.isRead);
|
|
6498
|
+
const handleResolve = async (resolution) => {
|
|
6499
|
+
if (!onResolveInvite || !selectedNotif) return;
|
|
6500
|
+
setIsResolving(true);
|
|
6501
|
+
try {
|
|
6502
|
+
await onResolveInvite(selectedNotif, resolution);
|
|
6503
|
+
window.location.reload();
|
|
6504
|
+
} catch (error) {
|
|
6505
|
+
toast17.error("Failed to process invitation");
|
|
6506
|
+
setIsResolving(false);
|
|
6507
|
+
}
|
|
6508
|
+
};
|
|
6509
|
+
return /* @__PURE__ */ React56.createElement("div", { className: "w-full max-w-3xl mx-auto flex flex-col animate-in fade-in duration-300 relative" }, /* @__PURE__ */ React56.createElement("div", { className: "flex items-center justify-between w-full pb-4" }, /* @__PURE__ */ React56.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ React56.createElement(
|
|
6510
|
+
"button",
|
|
6511
|
+
{
|
|
6512
|
+
onClick: () => window.dispatchEvent(new Event("open-sidebar")),
|
|
6513
|
+
className: "md:hidden flex items-center justify-center w-7 h-7 bg-white rounded-full text-black transition-all duration-300 outline-none hover:bg-stone-50",
|
|
6514
|
+
"aria-label": "Open Menu"
|
|
6515
|
+
},
|
|
6516
|
+
/* @__PURE__ */ React56.createElement(HugeiconsIcon42, { icon: SidebarLeft01Icon, size: 16 })
|
|
6517
|
+
)), /* @__PURE__ */ React56.createElement("div", { className: "flex items-center gap-2 shrink-0" }, /* @__PURE__ */ React56.createElement(
|
|
6518
|
+
"button",
|
|
6519
|
+
{
|
|
6520
|
+
onClick: () => router.push("/app/ai"),
|
|
6521
|
+
className: "relative w-7 h-7 flex items-center justify-center rounded-full bg-white outline-none hover:bg-stone-50 transition-colors"
|
|
6522
|
+
},
|
|
6523
|
+
/* @__PURE__ */ React56.createElement(HugeiconsIcon42, { icon: Robot01Icon2, size: 16, className: "text-black" })
|
|
6524
|
+
), /* @__PURE__ */ React56.createElement(
|
|
6525
|
+
"button",
|
|
6526
|
+
{
|
|
6527
|
+
onClick: () => {
|
|
6528
|
+
setShowNotifDialog(true);
|
|
6529
|
+
setSelectedNotif(null);
|
|
6530
|
+
},
|
|
6531
|
+
className: "relative w-7 h-7 flex items-center justify-center rounded-full bg-white outline-none hover:bg-stone-50 transition-colors"
|
|
6532
|
+
},
|
|
6533
|
+
/* @__PURE__ */ React56.createElement(HugeiconsIcon42, { icon: Notification01Icon3, size: 16, className: "text-black" }),
|
|
6534
|
+
hasUnreadNotifs && /* @__PURE__ */ React56.createElement("span", { className: "absolute top-2.5 right-2.5 w-2 h-2 bg-[#d97757] rounded-full border border-white" })
|
|
6535
|
+
))), /* @__PURE__ */ React56.createElement("div", { className: "w-full pb-6 flex flex-col gap-4" }, /* @__PURE__ */ React56.createElement("div", { className: "grid grid-cols-2 gap-2" }, /* @__PURE__ */ React56.createElement(
|
|
6536
|
+
"div",
|
|
6537
|
+
{
|
|
6538
|
+
onClick: createApplicationAction?.onClick,
|
|
6539
|
+
className: "bg-[#d97757] rounded-2xl p-5 relative overflow-hidden flex flex-col h-32 sm:h-36 cursor-pointer hover:opacity-90 transition-opacity"
|
|
6540
|
+
},
|
|
6541
|
+
/* @__PURE__ */ React56.createElement("div", { className: "relative z-10 flex flex-col h-full justify-between" }, /* @__PURE__ */ React56.createElement("p", { className: "text-sm sm:text-sm text-white leading-tight" }, "New", /* @__PURE__ */ React56.createElement("br", null), /* @__PURE__ */ React56.createElement("span", { className: "text-white/70" }, "Application")), /* @__PURE__ */ React56.createElement("div", { className: "w-8 h-8 rounded-full bg-white/10 flex items-center justify-center" }, /* @__PURE__ */ React56.createElement(HugeiconsIcon42, { icon: ArrowUpRight01Icon4, size: 16, className: "text-white" }))),
|
|
6542
|
+
/* @__PURE__ */ React56.createElement(
|
|
6543
|
+
"img",
|
|
6544
|
+
{
|
|
6545
|
+
src: "https://storage.googleapis.com/retina-cloud-v2/assets/images/cal_b.avif",
|
|
6546
|
+
alt: "New Application",
|
|
6547
|
+
className: "absolute bottom-4 right-2 translate-x-1/4 translate-y-1/2 w-32 h-auto object-contain z-0 pointer-events-none opacity-30"
|
|
6548
|
+
}
|
|
6549
|
+
)
|
|
6550
|
+
), /* @__PURE__ */ React56.createElement(
|
|
6551
|
+
"div",
|
|
6552
|
+
{
|
|
6553
|
+
onClick: checkApplicationAction?.onClick,
|
|
6554
|
+
className: "bg-[#ffffff] rounded-2xl p-5 relative overflow-hidden flex flex-col h-32 sm:h-36 cursor-pointer hover:opacity-90 transition-opacity"
|
|
6555
|
+
},
|
|
6556
|
+
/* @__PURE__ */ React56.createElement("div", { className: "relative z-10 flex flex-col h-full justify-between" }, /* @__PURE__ */ React56.createElement("p", { className: "text-sm sm:text-sm text-black leading-tight" }, "Check", /* @__PURE__ */ React56.createElement("br", null), /* @__PURE__ */ React56.createElement("span", { className: "text-black/60" }, "Application")), /* @__PURE__ */ React56.createElement("div", { className: "w-8 h-8 rounded-full bg-black/5 flex items-center justify-center" }, /* @__PURE__ */ React56.createElement(HugeiconsIcon42, { icon: ArrowRight01Icon17, size: 16, className: "text-black" }))),
|
|
6557
|
+
/* @__PURE__ */ React56.createElement(
|
|
6558
|
+
"img",
|
|
6559
|
+
{
|
|
6560
|
+
src: "https://storage.googleapis.com/retina-cloud-v2/assets/images/cam_c.avif",
|
|
6561
|
+
alt: "Check Application",
|
|
6562
|
+
className: "absolute bottom-4 right-2 translate-x-1/4 translate-y-1/2 w-32 h-auto object-contain z-0 pointer-events-none opacity-30"
|
|
6563
|
+
}
|
|
6564
|
+
)
|
|
6565
|
+
))), customContent && /* @__PURE__ */ React56.createElement("div", { className: "w-full" }, customContent), /* @__PURE__ */ React56.createElement("div", { className: "w-full mt-2" }, /* @__PURE__ */ React56.createElement(
|
|
6566
|
+
UniversalApplicationsPage,
|
|
6567
|
+
{
|
|
6568
|
+
...applicationsProps
|
|
6569
|
+
}
|
|
6570
|
+
)), showNotifDialog && /* @__PURE__ */ React56.createElement("div", { className: "fixed inset-0 z-120 flex items-center justify-center p-4 pointer-events-auto" }, /* @__PURE__ */ React56.createElement("div", { className: "absolute inset-0 bg-black/30", onClick: () => setShowNotifDialog(false) }), /* @__PURE__ */ React56.createElement("div", { className: "relative w-full max-w-sm bg-white rounded-2xl flex flex-col overflow-hidden shadow-2xl animate-in zoom-in-95 duration-200 max-h-[80vh] h-auto" }, /* @__PURE__ */ React56.createElement("div", { className: "flex items-center justify-between p-5 shrink-0" }, selectedNotif ? /* @__PURE__ */ React56.createElement("button", { onClick: () => setSelectedNotif(null), disabled: isResolving, className: "text-[#d97757] hover:text-[#d97757] transition-colors outline-none flex items-center gap-2 text-xs tracking-widest disabled:opacity-50" }, /* @__PURE__ */ React56.createElement(HugeiconsIcon42, { icon: ArrowLeft01Icon22, size: 14 }), " Back") : /* @__PURE__ */ React56.createElement("h3", { className: "text-sm text-black tracking-tight flex items-center gap-2" }, "Notifications"), /* @__PURE__ */ React56.createElement("button", { onClick: () => setShowNotifDialog(false), disabled: isResolving, className: "text-stone-400 hover:text-black transition-colors outline-none disabled:opacity-50" }, /* @__PURE__ */ React56.createElement(HugeiconsIcon42, { icon: CancelCircleIcon14, size: 18 }))), /* @__PURE__ */ React56.createElement("div", { className: "flex-1 overflow-y-auto custom-scrollbar p-2 relative" }, isNotifsLoading && !selectedNotif && /* @__PURE__ */ React56.createElement("div", { className: "absolute inset-0 z-10 flex items-center justify-center" }, /* @__PURE__ */ React56.createElement(HugeiconsIcon42, { icon: Loading03Icon30, size: 28, className: "animate-spin text-black" })), selectedNotif ? /* @__PURE__ */ React56.createElement("div", { className: "p-4 text-left" }, selectedNotif.type === "HUDDLE_INVITE" && selectedNotif.meta_json?.action === "RESOLVE_INVITE" && selectedNotif.meta_json?.completed ? /* @__PURE__ */ React56.createElement("div", { className: "" }) : /* @__PURE__ */ React56.createElement("h4", { className: "text-sm text-black mb-1" }, selectedNotif.title), /* @__PURE__ */ React56.createElement("span", { className: "text-xs text-stone-400 tracking-widest mb-4 block" }, formatNotifDate(selectedNotif.createdAt)), /* @__PURE__ */ React56.createElement("p", { className: "text-xs text-stone-600 leading-relaxed whitespace-pre-wrap" }, selectedNotif.message), selectedNotif.type === "HUDDLE_INVITE" && selectedNotif.meta_json?.action === "RESOLVE_INVITE" && /* @__PURE__ */ React56.createElement("div", { className: `mt-8 flex gap-3 pt-6 ${selectedNotif.meta_json?.completed ? "opacity-40 pointer-events-none cursor-not-allowed" : ""}` }, /* @__PURE__ */ React56.createElement(
|
|
6571
|
+
"button",
|
|
6572
|
+
{
|
|
6573
|
+
onClick: () => handleResolve("ACCEPTED"),
|
|
6574
|
+
disabled: isResolving || selectedNotif.meta_json?.completed,
|
|
6575
|
+
className: "flex-1 py-2.5 rounded-full bg-black text-white text-xs tracking-wide transition-all outline-none hover:bg-stone-800 flex justify-center items-center disabled:opacity-50"
|
|
6576
|
+
},
|
|
6577
|
+
isResolving ? /* @__PURE__ */ React56.createElement(HugeiconsIcon42, { icon: Loading03Icon30, className: "animate-spin", size: 16 }) : "Accept"
|
|
6578
|
+
), /* @__PURE__ */ React56.createElement(
|
|
6579
|
+
"button",
|
|
6580
|
+
{
|
|
6581
|
+
onClick: () => handleResolve("REJECTED"),
|
|
6582
|
+
disabled: isResolving || selectedNotif.meta_json?.completed,
|
|
6583
|
+
className: "flex-1 py-2.5 rounded-full bg-white border border-stone-200 text-black text-xs tracking-wide transition-all outline-none hover:bg-stone-50 flex justify-center items-center disabled:opacity-50"
|
|
6584
|
+
},
|
|
6585
|
+
"Reject"
|
|
6586
|
+
))) : /* @__PURE__ */ React56.createElement("div", { className: "flex flex-col divide-y divide-stone-50/50" }, notifications?.length === 0 && !isNotifsLoading ? /* @__PURE__ */ React56.createElement("div", { className: "p-8 text-center text-xs text-stone-400" }, "You have no notifications.") : notifications?.map((notif) => /* @__PURE__ */ React56.createElement(
|
|
6587
|
+
"div",
|
|
6588
|
+
{
|
|
6589
|
+
key: notif.id,
|
|
6590
|
+
onClick: () => {
|
|
6591
|
+
setSelectedNotif(notif);
|
|
6592
|
+
onNotificationClick?.(notif);
|
|
6593
|
+
},
|
|
6594
|
+
className: `p-3 flex items-start gap-3 rounded-xl cursor-pointer transition-colors ${isNotifsLoading ? "opacity-50 pointer-events-none" : "hover:bg-stone-50"}`
|
|
6595
|
+
},
|
|
6596
|
+
/* @__PURE__ */ React56.createElement("div", { className: "mt-1.5 shrink-0" }, !notif.isRead ? /* @__PURE__ */ React56.createElement("div", { className: "w-1.5 h-1.5 bg-[#d97757] rounded-full" }) : /* @__PURE__ */ React56.createElement("div", { className: "w-1.5 h-1.5 bg-transparent" })),
|
|
6597
|
+
/* @__PURE__ */ React56.createElement("div", { className: "flex-1 min-w-0 text-left" }, /* @__PURE__ */ React56.createElement("h5", { className: `text-xs truncate ${notif.isRead ? "text-stone-500" : "text-black"}` }, notif.title), /* @__PURE__ */ React56.createElement("p", { className: "text-xs text-stone-400 truncate mt-0.5" }, notif.message), /* @__PURE__ */ React56.createElement("span", { className: "text-xs text-stone-400 tracking-widest mt-2 block" }, formatNotifDate(notif.createdAt)))
|
|
6598
|
+
)))), !selectedNotif && /* @__PURE__ */ React56.createElement("div", { className: "p-4 flex items-center justify-between shrink-0" }, /* @__PURE__ */ React56.createElement("span", { className: "text-xs text-stone-400 tracking-widest" }, "Page ", notificationPage, " of ", notificationTotalPages === 0 ? 1 : notificationTotalPages), /* @__PURE__ */ React56.createElement("div", { className: "flex gap-1" }, /* @__PURE__ */ React56.createElement(
|
|
6599
|
+
"button",
|
|
6600
|
+
{
|
|
6601
|
+
disabled: notificationPage <= 1 || isNotifsLoading,
|
|
6602
|
+
onClick: () => onNotificationPageChange?.(notificationPage - 1),
|
|
6603
|
+
className: "w-7 h-7 flex items-center justify-center rounded-full bg-white border border-stone-200 text-stone-600 disabled:opacity-30 outline-none hover:bg-stone-50 transition-colors"
|
|
6604
|
+
},
|
|
6605
|
+
/* @__PURE__ */ React56.createElement(HugeiconsIcon42, { icon: ArrowLeft01Icon22, size: 12 })
|
|
6606
|
+
), /* @__PURE__ */ React56.createElement(
|
|
6607
|
+
"button",
|
|
6608
|
+
{
|
|
6609
|
+
disabled: notificationPage >= notificationTotalPages || notificationTotalPages === 0 || isNotifsLoading,
|
|
6610
|
+
onClick: () => onNotificationPageChange?.(notificationPage + 1),
|
|
6611
|
+
className: "w-7 h-7 flex items-center justify-center rounded-full bg-white border border-stone-200 text-stone-600 disabled:opacity-30 outline-none hover:bg-stone-50 transition-colors"
|
|
6612
|
+
},
|
|
6613
|
+
/* @__PURE__ */ React56.createElement(HugeiconsIcon42, { icon: ArrowRight01Icon17, size: 12 })
|
|
6614
|
+
))))));
|
|
6615
|
+
};
|
|
6616
|
+
|
|
6617
|
+
// src/components/RootSidebar.tsx
|
|
6618
|
+
import React57, { useState as useState41, useEffect as useEffect23 } from "react";
|
|
6619
|
+
import Link10 from "next/link";
|
|
6620
|
+
import { HugeiconsIcon as HugeiconsIcon43 } from "@hugeicons/react";
|
|
6621
|
+
import {
|
|
6622
|
+
SidebarLeft01Icon as SidebarLeft01Icon2,
|
|
6623
|
+
CancelCircleIcon as CancelCircleIcon15,
|
|
6624
|
+
UserIcon as UserIcon3,
|
|
6625
|
+
CheckmarkCircle01Icon as CheckmarkCircle01Icon2,
|
|
6626
|
+
LogoutCircle02Icon as LogoutCircle02Icon3,
|
|
6627
|
+
Loading03Icon as Loading03Icon31
|
|
6628
|
+
} from "@hugeicons/core-free-icons";
|
|
6629
|
+
function RootSidebar({
|
|
6630
|
+
NavItem2s,
|
|
6631
|
+
currentPath,
|
|
6632
|
+
isMobileOpen,
|
|
6633
|
+
closeMobile,
|
|
6634
|
+
onNavClick,
|
|
6635
|
+
avatarSrc,
|
|
6636
|
+
title = "App",
|
|
6637
|
+
subtitle,
|
|
6638
|
+
homeUrl = "/app",
|
|
6639
|
+
showWorkspaceSwitcher = false,
|
|
6640
|
+
workspaces = [],
|
|
6641
|
+
activeWorkspaceId,
|
|
6642
|
+
onSwitchWorkspace,
|
|
6643
|
+
showLogoutAction = false,
|
|
6644
|
+
onLogout
|
|
6645
|
+
}) {
|
|
6646
|
+
const [isCollapsed, setIsCollapsed] = useState41(false);
|
|
6647
|
+
const [isAvatarLoaded, setIsAvatarLoaded] = useState41(false);
|
|
6648
|
+
const [showSwitcherDialog, setShowSwitcherDialog] = useState41(false);
|
|
6649
|
+
const [showLogoutDialog, setShowLogoutDialog] = useState41(false);
|
|
6650
|
+
const [isLoggingOut, setIsLoggingOut] = useState41(false);
|
|
6651
|
+
useEffect23(() => {
|
|
6652
|
+
if (isMobileOpen) {
|
|
6653
|
+
closeMobile();
|
|
6654
|
+
}
|
|
6655
|
+
}, [currentPath]);
|
|
6656
|
+
const hasActiveMatch = NavItem2s.some(
|
|
6657
|
+
(item) => item.path === "/applications" || item.path === "/app" ? currentPath === item.path : currentPath === item.path || currentPath?.startsWith(`${item.path}/`)
|
|
6658
|
+
);
|
|
6659
|
+
const handleLogoutInitiation = async () => {
|
|
6660
|
+
if (isLoggingOut || !onLogout) return;
|
|
6661
|
+
setIsLoggingOut(true);
|
|
6662
|
+
try {
|
|
6663
|
+
await onLogout();
|
|
6664
|
+
} catch (error) {
|
|
6665
|
+
setIsLoggingOut(false);
|
|
6666
|
+
setShowLogoutDialog(false);
|
|
6667
|
+
}
|
|
6668
|
+
};
|
|
6669
|
+
const finalAvatarSrc = avatarSrc || "https://storage.googleapis.com/retina-cloud-v2/assets/images/avatar.avif";
|
|
6670
|
+
return /* @__PURE__ */ React57.createElement(React57.Fragment, null, /* @__PURE__ */ React57.createElement(
|
|
6671
|
+
"div",
|
|
6672
|
+
{
|
|
6673
|
+
className: `fixed inset-0 bg-black/30 shadow-2xl transition-opacity duration-300 md:hidden z-90 ${isMobileOpen ? "opacity-100 pointer-events-auto" : "opacity-0 pointer-events-none"}`,
|
|
6674
|
+
onClick: closeMobile
|
|
6675
|
+
}
|
|
6676
|
+
), /* @__PURE__ */ React57.createElement(
|
|
6677
|
+
"aside",
|
|
6678
|
+
{
|
|
6679
|
+
className: `
|
|
6680
|
+
fixed md:sticky rounded-2xl top-4 md:top-4 md:my-4 left-4 md:left-0 md:ml-4 h-[calc(100dvh-2rem)] bg-white
|
|
6681
|
+
transition-all duration-300 ease-in-out shrink-0 flex flex-col z-100 md:z-10
|
|
6682
|
+
${isMobileOpen ? "translate-x-0" : "translate-x-[-120%] md:translate-x-0"}
|
|
6683
|
+
${isCollapsed ? "md:w-16 w-64" : "w-64"}
|
|
6684
|
+
`
|
|
6685
|
+
},
|
|
6686
|
+
/* @__PURE__ */ React57.createElement("div", { className: `flex items-center shrink-0 p-5 ${isCollapsed && !isMobileOpen ? "justify-center" : "justify-between"}` }, /* @__PURE__ */ React57.createElement(Link10, { href: homeUrl, className: `flex items-center outline-none group min-w-0 ${isCollapsed && !isMobileOpen ? "" : "gap-3 pr-2"}` }, /* @__PURE__ */ React57.createElement("div", { className: "w-8 h-8 shrink-0 relative rounded-lg overflow-hidden bg-stone-50 flex items-center justify-center" }, !isAvatarLoaded && /* @__PURE__ */ React57.createElement(HugeiconsIcon43, { icon: Loading03Icon31, size: 14, className: "animate-spin text-stone-300 absolute" }), /* @__PURE__ */ React57.createElement(
|
|
6687
|
+
"img",
|
|
6688
|
+
{
|
|
6689
|
+
src: finalAvatarSrc,
|
|
6690
|
+
alt: "User Avatar",
|
|
6691
|
+
onLoad: () => setIsAvatarLoaded(true),
|
|
6692
|
+
className: `w-full h-full object-cover transition-opacity duration-300 ${isAvatarLoaded ? "opacity-100" : "opacity-0"}`
|
|
6693
|
+
}
|
|
6694
|
+
)), (!isCollapsed || isMobileOpen) && /* @__PURE__ */ React57.createElement("div", { className: "flex flex-col justify-center min-w-0" }, /* @__PURE__ */ React57.createElement("span", { className: "text-[13px] font-serif text-black leading-none truncate max-w-32.5 tracking-wide mb-1 group-hover:opacity-70 transition-opacity" }, title), subtitle && /* @__PURE__ */ React57.createElement("span", { className: "text-[9px] text-neutral-500 truncate max-w-32.5 tracking-[0.2em] leading-none uppercase" }, subtitle))), (!isCollapsed || isMobileOpen) && /* @__PURE__ */ React57.createElement("div", { className: "md:hidden flex shrink-0" }, /* @__PURE__ */ React57.createElement(
|
|
6695
|
+
"button",
|
|
6696
|
+
{
|
|
6697
|
+
onClick: closeMobile,
|
|
6698
|
+
className: "text-neutral-400 hover:text-black transition-colors outline-none",
|
|
6699
|
+
"aria-label": "Close Menu"
|
|
6700
|
+
},
|
|
6701
|
+
/* @__PURE__ */ React57.createElement(HugeiconsIcon43, { icon: CancelCircleIcon15, size: 24 })
|
|
6702
|
+
))),
|
|
6703
|
+
/* @__PURE__ */ React57.createElement("nav", { className: "flex-1 py-2 flex flex-col gap-1.5 px-3 overflow-y-auto custom-scrollbar" }, NavItem2s.map((item, index) => {
|
|
6704
|
+
const isExactOrSubMatch = item.path === "/applications" || item.path === "/app" ? currentPath === item.path : currentPath === item.path || currentPath?.startsWith(`${item.path}/`);
|
|
6705
|
+
const isCurrentRoute = isExactOrSubMatch || !hasActiveMatch && index === 0;
|
|
6706
|
+
return /* @__PURE__ */ React57.createElement(
|
|
6707
|
+
Link10,
|
|
6708
|
+
{
|
|
6709
|
+
key: item.name,
|
|
6710
|
+
href: item.path,
|
|
6711
|
+
onClick: (e) => onNavClick ? onNavClick(e, item.path) : void 0,
|
|
6712
|
+
className: `flex items-center gap-3 px-3 py-2 rounded-full transition-all outline-none group shrink-0 ${isCurrentRoute ? "bg-neutral-100 text-black " : "text-neutral-500 hover:text-black hover:bg-neutral-50"}`,
|
|
6713
|
+
title: isCollapsed && !isMobileOpen ? item.name : void 0
|
|
6714
|
+
},
|
|
6715
|
+
/* @__PURE__ */ React57.createElement(
|
|
6716
|
+
HugeiconsIcon43,
|
|
6717
|
+
{
|
|
6718
|
+
icon: item.icon,
|
|
6719
|
+
size: 18,
|
|
6720
|
+
className: `shrink-0 transition-colors ${isCurrentRoute ? "text-black" : "text-neutral-400 group-hover:text-black"}`
|
|
6721
|
+
}
|
|
6722
|
+
),
|
|
6723
|
+
(!isCollapsed || isMobileOpen) && /* @__PURE__ */ React57.createElement("span", { className: "text-xs tracking-wide truncate" }, item.name)
|
|
6724
|
+
);
|
|
6725
|
+
})),
|
|
6726
|
+
/* @__PURE__ */ React57.createElement("div", { className: "p-4 shrink-0 flex flex-col gap-2 " }, (showWorkspaceSwitcher || showLogoutAction) && /* @__PURE__ */ React57.createElement("div", { className: `flex gap-2 px-1 pb-2 ${isCollapsed && !isMobileOpen ? "flex-col items-center" : "flex-col items-start md:flex-row md:items-center"}` }, showWorkspaceSwitcher && workspaces && workspaces.length > 0 && /* @__PURE__ */ React57.createElement(
|
|
6727
|
+
"button",
|
|
6728
|
+
{
|
|
6729
|
+
onClick: () => setShowSwitcherDialog(true),
|
|
6730
|
+
className: "w-8 h-8 shrink-0 rounded-full bg-neutral-50 flex items-center justify-center text-neutral-500 hover:text-black hover:bg-neutral-100 transition-all outline-none",
|
|
6731
|
+
title: "Switch Workspace"
|
|
6732
|
+
},
|
|
6733
|
+
/* @__PURE__ */ React57.createElement(HugeiconsIcon43, { icon: UserIcon3, size: 16 })
|
|
6734
|
+
), showLogoutAction && /* @__PURE__ */ React57.createElement(
|
|
6735
|
+
"button",
|
|
6736
|
+
{
|
|
6737
|
+
onClick: () => setShowLogoutDialog(true),
|
|
6738
|
+
className: "w-8 h-8 shrink-0 rounded-full bg-neutral-50 flex items-center justify-center text-neutral-500 hover:text-black hover:bg-neutral-100 transition-all outline-none",
|
|
6739
|
+
title: "Secure Logout"
|
|
6740
|
+
},
|
|
6741
|
+
/* @__PURE__ */ React57.createElement(HugeiconsIcon43, { icon: LogoutCircle02Icon3, size: 16 })
|
|
6742
|
+
)), /* @__PURE__ */ React57.createElement("div", { className: "hidden md:block" }, /* @__PURE__ */ React57.createElement(
|
|
6743
|
+
"button",
|
|
6744
|
+
{
|
|
6745
|
+
onClick: () => setIsCollapsed(!isCollapsed),
|
|
6746
|
+
className: "flex items-center justify-center md:justify-start gap-3 w-full p-2.5 rounded-full text-neutral-500 hover:text-black hover:bg-neutral-50 transition-colors outline-none"
|
|
6747
|
+
},
|
|
6748
|
+
/* @__PURE__ */ React57.createElement(HugeiconsIcon43, { icon: SidebarLeft01Icon2, size: 18, className: "shrink-0 text-neutral-400" }),
|
|
6749
|
+
!isCollapsed && /* @__PURE__ */ React57.createElement("span", { className: "text-xs" }, "Collapse")
|
|
6750
|
+
)))
|
|
6751
|
+
), showSwitcherDialog && showWorkspaceSwitcher && workspaces && workspaces.length > 0 && /* @__PURE__ */ React57.createElement("div", { className: "fixed inset-0 z-110 flex items-center justify-center p-4 pointer-events-auto" }, /* @__PURE__ */ React57.createElement(
|
|
6752
|
+
"div",
|
|
6753
|
+
{
|
|
6754
|
+
className: "absolute inset-0 bg-black/30",
|
|
6755
|
+
onClick: () => setShowSwitcherDialog(false)
|
|
6756
|
+
}
|
|
6757
|
+
), /* @__PURE__ */ React57.createElement("div", { className: "relative w-full max-w-sm bg-white rounded-2xl flex flex-col overflow-hidden shadow-2xl animate-in zoom-in-95 duration-200" }, /* @__PURE__ */ React57.createElement("div", { className: "p-5 text-center w-full" }, /* @__PURE__ */ React57.createElement("h3", { className: " font-serif text-[17px] text-black tracking-tight mb-1" }, "Switch Workspace"), /* @__PURE__ */ React57.createElement("p", { className: "text-[11px] text-neutral-500 leading-snug" }, "Select an organization to switch your current context.")), /* @__PURE__ */ React57.createElement("div", { className: "max-h-75 overflow-y-auto w-full custom-scrollbar" }, workspaces.map((org) => /* @__PURE__ */ React57.createElement(
|
|
6758
|
+
"button",
|
|
6759
|
+
{
|
|
6760
|
+
key: org.id,
|
|
6761
|
+
onClick: () => {
|
|
6762
|
+
if (onSwitchWorkspace) onSwitchWorkspace(org.id);
|
|
6763
|
+
setShowSwitcherDialog(false);
|
|
6764
|
+
},
|
|
6765
|
+
className: "w-full text-left px-5 py-4 flex items-center justify-between hover:bg-neutral-50 transition-colors group outline-none last:border-0"
|
|
6766
|
+
},
|
|
6767
|
+
/* @__PURE__ */ React57.createElement("div", { className: "flex flex-col truncate pr-4" }, /* @__PURE__ */ React57.createElement("span", { className: `text-[13px] truncate ${activeWorkspaceId === org.id ? "text-black" : "text-neutral-600 group-hover:text-black"}` }, org.name), /* @__PURE__ */ React57.createElement("span", { className: "text-[9px] text-neutral-400 tracking-[0.2em] mt-1 uppercase" }, "Role: ", org.role)),
|
|
6768
|
+
activeWorkspaceId === org.id && /* @__PURE__ */ React57.createElement(HugeiconsIcon43, { icon: CheckmarkCircle01Icon2, size: 16, className: "text-black shrink-0" })
|
|
6769
|
+
))), /* @__PURE__ */ React57.createElement("div", { className: "w-full flex mt-auto" }, /* @__PURE__ */ React57.createElement(
|
|
6770
|
+
"button",
|
|
6771
|
+
{
|
|
6772
|
+
onClick: () => setShowSwitcherDialog(false),
|
|
6773
|
+
className: "w-full py-3.5 text-[13px] text-neutral-600 hover:bg-neutral-50 transition-colors outline-none"
|
|
6774
|
+
},
|
|
6775
|
+
"Cancel"
|
|
6776
|
+
)))), /* @__PURE__ */ React57.createElement(
|
|
6777
|
+
ConfirmationDialog,
|
|
6778
|
+
{
|
|
6779
|
+
isOpen: showLogoutDialog && showLogoutAction,
|
|
6780
|
+
title: "Secure Logout",
|
|
6781
|
+
message: "Are you sure you want to log out? You will need to authenticate to return.",
|
|
6782
|
+
confirmText: "Log Out",
|
|
6783
|
+
cancelText: "Cancel",
|
|
6784
|
+
isProcessing: isLoggingOut,
|
|
6785
|
+
isDestructive: true,
|
|
6786
|
+
onClose: () => !isLoggingOut && setShowLogoutDialog(false),
|
|
6787
|
+
onConfirm: handleLogoutInitiation
|
|
6788
|
+
}
|
|
6789
|
+
));
|
|
6790
|
+
}
|
|
6791
|
+
|
|
6792
|
+
// src/components/UniversalSettings2.tsx
|
|
6793
|
+
import React58, { useState as useState42, useEffect as useEffect24, useRef as useRef17 } from "react";
|
|
6794
|
+
import toast18 from "react-hot-toast";
|
|
6795
|
+
import { HugeiconsIcon as HugeiconsIcon44 } from "@hugeicons/react";
|
|
6796
|
+
import {
|
|
6797
|
+
ArrowLeft01Icon as ArrowLeft01Icon23,
|
|
6798
|
+
ArrowRight01Icon as ArrowRight01Icon18,
|
|
6799
|
+
Loading03Icon as Loading03Icon32,
|
|
6800
|
+
Search01Icon as Search01Icon9,
|
|
6801
|
+
SearchList02Icon as SearchList02Icon4,
|
|
6802
|
+
ListSettingIcon as ListSettingIcon4,
|
|
6803
|
+
CircleLock02Icon as CircleLock02Icon5,
|
|
6804
|
+
CloudUploadIcon as CloudUploadIcon2,
|
|
6805
|
+
SidebarLeft01Icon as SidebarLeft01Icon3
|
|
6806
|
+
} from "@hugeicons/core-free-icons";
|
|
6807
|
+
var MemberAvatar5 = ({ src, status, sizeClass = "w-10 h-10" }) => {
|
|
6808
|
+
const [loaded, setLoaded] = useState42(false);
|
|
6809
|
+
const [error, setError] = useState42(false);
|
|
6810
|
+
const defaultAvatar = "https://storage.googleapis.com/retina-cloud-v2/assets/images/avatar.avif";
|
|
6811
|
+
const finalSrc = error || !src ? defaultAvatar : src;
|
|
6812
|
+
const getStatusColor = () => {
|
|
6813
|
+
switch (status?.toUpperCase()) {
|
|
6814
|
+
case "ACTIVE":
|
|
6815
|
+
return "bg-emerald-500";
|
|
6816
|
+
case "BUSY":
|
|
6817
|
+
return "bg-amber-500";
|
|
6818
|
+
case "OFFLINE":
|
|
6819
|
+
return "bg-[#d97757]";
|
|
6820
|
+
case "AWAY":
|
|
6821
|
+
return "bg-stone-400";
|
|
6822
|
+
default:
|
|
6823
|
+
return "bg-stone-200";
|
|
6824
|
+
}
|
|
6825
|
+
};
|
|
6826
|
+
return /* @__PURE__ */ React58.createElement("div", { className: `relative shrink-0 ${sizeClass}` }, /* @__PURE__ */ React58.createElement("div", { className: "w-full h-full rounded-lg bg-stone-100 flex items-center justify-center overflow-hidden" }, !loaded && !error && /* @__PURE__ */ React58.createElement(HugeiconsIcon44, { icon: Loading03Icon32, className: "animate-spin text-stone-400 absolute", size: 14 }), /* @__PURE__ */ React58.createElement("img", { src: finalSrc, alt: "Member", className: `w-full h-full object-cover transition-opacity duration-300 ${loaded || error ? "opacity-100" : "opacity-0"}`, onLoad: () => setLoaded(true), onError: () => setError(true) })), /* @__PURE__ */ React58.createElement("div", { className: `absolute -bottom-1 -right-1 w-3.5 h-3.5 rounded-full border-2 border-white z-10 ${getStatusColor()}` }));
|
|
6827
|
+
};
|
|
6828
|
+
var OrgAvatar3 = ({ src, sizeClass = "w-10 h-10" }) => {
|
|
6829
|
+
const [loaded, setLoaded] = useState42(false);
|
|
6830
|
+
const [error, setError] = useState42(false);
|
|
6831
|
+
const defaultAvatar = "https://storage.googleapis.com/retina-cloud-v2/assets/images/office_a.avif";
|
|
6832
|
+
const finalSrc = error || !src ? defaultAvatar : src;
|
|
6833
|
+
return /* @__PURE__ */ React58.createElement("div", { className: `relative shrink-0 ${sizeClass}` }, /* @__PURE__ */ React58.createElement("div", { className: "w-full h-full rounded-lg bg-stone-100 flex items-center justify-center overflow-hidden" }, !loaded && !error && /* @__PURE__ */ React58.createElement(HugeiconsIcon44, { icon: Loading03Icon32, className: "animate-spin text-stone-400 absolute", size: 14 }), /* @__PURE__ */ React58.createElement(
|
|
6834
|
+
"img",
|
|
6835
|
+
{
|
|
6836
|
+
src: finalSrc,
|
|
6837
|
+
alt: "Workspace Avatar",
|
|
6838
|
+
className: `w-full h-full object-cover transition-opacity duration-300 ${loaded || error ? "opacity-100" : "opacity-0"}`,
|
|
6839
|
+
onLoad: () => setLoaded(true),
|
|
6840
|
+
onError: () => setError(true)
|
|
6841
|
+
}
|
|
6842
|
+
)));
|
|
6843
|
+
};
|
|
6844
|
+
var PageSpinner10 = () => /* @__PURE__ */ React58.createElement("div", { className: "flex justify-center items-center py-12" }, /* @__PURE__ */ React58.createElement(HugeiconsIcon44, { icon: Loading03Icon32, size: 32, className: "animate-spin mb-4 text-black" }));
|
|
6845
|
+
var InputSpinner4 = () => /* @__PURE__ */ React58.createElement("svg", { className: "animate-spin h-4 w-4 text-stone-400", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24" }, /* @__PURE__ */ React58.createElement("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), /* @__PURE__ */ React58.createElement("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" }));
|
|
6846
|
+
var UniversalSettings2 = ({
|
|
6847
|
+
accountType,
|
|
6848
|
+
userRole,
|
|
6849
|
+
members = [],
|
|
6850
|
+
isMembersLoading = false,
|
|
6851
|
+
membersCurrentPage = 1,
|
|
6852
|
+
membersTotalPages = 1,
|
|
6853
|
+
onMembersPageChange = () => {
|
|
6854
|
+
},
|
|
6855
|
+
membersSearchQuery = "",
|
|
6856
|
+
onMembersSearchChange = () => {
|
|
6857
|
+
},
|
|
6858
|
+
activeStatusFilter = "ALL",
|
|
6859
|
+
onStatusFilterChange = () => {
|
|
6860
|
+
},
|
|
6861
|
+
activeRoleFilter = "ALL",
|
|
6862
|
+
onRoleFilterChange = () => {
|
|
6863
|
+
},
|
|
6864
|
+
onRemoveMember,
|
|
6865
|
+
onInviteMember,
|
|
6866
|
+
onUpdateRole,
|
|
6867
|
+
initialOrgName = "",
|
|
6868
|
+
initialOrgSlug = "",
|
|
6869
|
+
initialOrgAvatarUrl = "",
|
|
6870
|
+
initialFullName = "",
|
|
6871
|
+
initialEmail = "",
|
|
6872
|
+
initialJobTitle = "",
|
|
6873
|
+
initialDescription = "",
|
|
6874
|
+
initialAvatarUrl = "",
|
|
6875
|
+
onSaveProfile,
|
|
6876
|
+
onSaveOrganization,
|
|
6877
|
+
onCheckSlugAvailability,
|
|
6878
|
+
onUploadAvatar
|
|
6879
|
+
}) => {
|
|
6880
|
+
const isOrg = accountType === "ORGANIZATION";
|
|
6881
|
+
const safeRole = String(userRole || "").toUpperCase().trim();
|
|
6882
|
+
const canManage = ["ADMIN", "MANAGER", "OWNER"].includes(safeRole);
|
|
6883
|
+
const [activeTab, setActiveTab] = useState42(isOrg ? "MEMBERS" : "ACCOUNT");
|
|
6884
|
+
const [expandedId, setExpandedId] = useState42(null);
|
|
6885
|
+
const [memberToRemove, setMemberToRemove] = useState42(null);
|
|
6886
|
+
const [isRemoving, setIsRemoving] = useState42(false);
|
|
6887
|
+
const [isInviteMode, setIsInviteMode] = useState42(false);
|
|
6888
|
+
const [inviteEmail, setInviteEmail] = useState42("");
|
|
6889
|
+
const [isInviting, setIsInviting] = useState42(false);
|
|
6890
|
+
const [localSearchQuery, setLocalSearchQuery] = useState42(membersSearchQuery);
|
|
6891
|
+
const [isTyping, setIsTyping] = useState42(false);
|
|
6892
|
+
const isFirstSearchMount = useRef17(true);
|
|
6893
|
+
const [isStatusModalOpen, setIsStatusModalOpen] = useState42(false);
|
|
6894
|
+
const [isRoleModalOpen, setIsRoleModalOpen] = useState42(false);
|
|
6895
|
+
const [roleEditTarget, setRoleEditTarget] = useState42(null);
|
|
6896
|
+
const [isUpdatingRole, setIsUpdatingRole] = useState42(false);
|
|
6897
|
+
const [orgName, setOrgName] = useState42(initialOrgName);
|
|
6898
|
+
const [orgSlug, setOrgSlug] = useState42(initialOrgSlug);
|
|
6899
|
+
const [orgAvatarUrl, setOrgAvatarUrl] = useState42(initialOrgAvatarUrl);
|
|
6900
|
+
const [firstName, setFirstName] = useState42("");
|
|
6901
|
+
const [lastName, setLastName] = useState42("");
|
|
6902
|
+
const [jobTitle, setJobTitle] = useState42(initialJobTitle);
|
|
6903
|
+
const [description, setDescription] = useState42(initialDescription);
|
|
6904
|
+
const [avatarUrl, setAvatarUrl] = useState42(initialAvatarUrl);
|
|
6905
|
+
const [isCheckingSlug, setIsCheckingSlug] = useState42(false);
|
|
6906
|
+
const [slugAvailable, setSlugAvailable] = useState42(null);
|
|
6907
|
+
const [isSavingOrg, setIsSavingOrg] = useState42(false);
|
|
6908
|
+
const [isSavingProfile, setIsSavingProfile] = useState42(false);
|
|
6909
|
+
const orgFileInputRef = useRef17(null);
|
|
6910
|
+
const userFileInputRef = useRef17(null);
|
|
6911
|
+
const [pendingOrgAvatar, setPendingOrgAvatar] = useState42(null);
|
|
6912
|
+
const [pendingUserAvatar, setPendingUserAvatar] = useState42(null);
|
|
6913
|
+
const [isUploadingOrgAvatar, setIsUploadingOrgAvatar] = useState42(false);
|
|
6914
|
+
const [isUploadingUserAvatar, setIsUploadingUserAvatar] = useState42(false);
|
|
6915
|
+
useEffect24(() => {
|
|
6916
|
+
setOrgName(initialOrgName || "");
|
|
6917
|
+
setOrgSlug(initialOrgSlug || "");
|
|
6918
|
+
setOrgAvatarUrl(initialOrgAvatarUrl || "");
|
|
6919
|
+
const parts = (initialFullName || "").split(" ");
|
|
6920
|
+
setFirstName(parts[0] || "");
|
|
6921
|
+
setLastName(parts.slice(1).join(" ") || "");
|
|
6922
|
+
setJobTitle(initialJobTitle || "");
|
|
6923
|
+
setDescription(initialDescription || "");
|
|
6924
|
+
setAvatarUrl(initialAvatarUrl || "");
|
|
6925
|
+
}, [initialOrgName, initialOrgSlug, initialOrgAvatarUrl, initialFullName, initialJobTitle, initialDescription, initialAvatarUrl]);
|
|
6926
|
+
const handleFileSelect = (e, type) => {
|
|
6927
|
+
const file = e.target.files?.[0];
|
|
6928
|
+
if (!file) return;
|
|
6929
|
+
if (file.size > 1024 * 1024) {
|
|
6930
|
+
toast18.error("Image size must be less than 1MB.");
|
|
6931
|
+
e.target.value = "";
|
|
6932
|
+
return;
|
|
6933
|
+
}
|
|
6934
|
+
const validTypes = ["image/jpeg", "image/jpg", "image/png"];
|
|
6935
|
+
if (!validTypes.includes(file.type)) {
|
|
6936
|
+
toast18.error("Only PNG and JPEG images are allowed.");
|
|
6937
|
+
e.target.value = "";
|
|
6938
|
+
return;
|
|
6939
|
+
}
|
|
6940
|
+
const previewUrl = URL.createObjectURL(file);
|
|
6941
|
+
if (type === "USER") {
|
|
6942
|
+
setPendingUserAvatar(file);
|
|
6943
|
+
setAvatarUrl(previewUrl);
|
|
6944
|
+
} else if (type === "ORGANIZATION") {
|
|
6945
|
+
setPendingOrgAvatar(file);
|
|
6946
|
+
setOrgAvatarUrl(previewUrl);
|
|
6947
|
+
}
|
|
6948
|
+
e.target.value = "";
|
|
6949
|
+
};
|
|
6950
|
+
useEffect24(() => {
|
|
6951
|
+
if (activeTab !== "MEMBERS") return;
|
|
6952
|
+
if (isFirstSearchMount.current) {
|
|
6953
|
+
isFirstSearchMount.current = false;
|
|
6954
|
+
return;
|
|
6955
|
+
}
|
|
6956
|
+
setIsTyping(true);
|
|
6957
|
+
const handler = setTimeout(() => {
|
|
6958
|
+
onMembersSearchChange(localSearchQuery);
|
|
6959
|
+
setIsTyping(false);
|
|
6960
|
+
}, 600);
|
|
6961
|
+
return () => clearTimeout(handler);
|
|
6962
|
+
}, [localSearchQuery, activeTab]);
|
|
6963
|
+
const cleanEmailId = (val) => val.toLowerCase().replace(/[^a-z0-9@._-]/g, "");
|
|
6964
|
+
const handleOrgSlugChange = (val) => setOrgSlug(val.toLowerCase().replace(/[^a-z0-9-]/g, "").replace(/-+/g, "-").substring(0, 50));
|
|
6965
|
+
const handleOrgNameChange = (val) => setOrgName(val.replace(/[^a-zA-Z0-9\s-]/g, "").substring(0, 50));
|
|
6966
|
+
const handleConfirmRemove = async () => {
|
|
6967
|
+
if (!memberToRemove || !onRemoveMember) return;
|
|
6968
|
+
setIsRemoving(true);
|
|
6969
|
+
try {
|
|
6970
|
+
await onRemoveMember(memberToRemove.userId);
|
|
6971
|
+
toast18.success("Member removed successfully.");
|
|
6972
|
+
setExpandedId(null);
|
|
6973
|
+
setMemberToRemove(null);
|
|
6974
|
+
} catch (error) {
|
|
6975
|
+
toast18.error(error.message || "Failed to remove member.");
|
|
6976
|
+
} finally {
|
|
6977
|
+
setIsRemoving(false);
|
|
6978
|
+
}
|
|
6979
|
+
};
|
|
6980
|
+
const handleInviteSubmit = async (e) => {
|
|
6981
|
+
e.preventDefault();
|
|
6982
|
+
if (inviteEmail.length < 5 || isInviting || !onInviteMember) return;
|
|
6983
|
+
setIsInviting(true);
|
|
6984
|
+
try {
|
|
6985
|
+
await onInviteMember(inviteEmail);
|
|
6986
|
+
setInviteEmail("");
|
|
6987
|
+
setIsInviteMode(false);
|
|
6988
|
+
} catch (error) {
|
|
6989
|
+
toast18.error(error.message || "Failed to send invitation.");
|
|
6990
|
+
} finally {
|
|
6991
|
+
setIsInviting(false);
|
|
6992
|
+
}
|
|
6993
|
+
};
|
|
6994
|
+
const handleRoleUpdate = async (newRole) => {
|
|
6995
|
+
if (!roleEditTarget || !onUpdateRole) return;
|
|
6996
|
+
setIsUpdatingRole(true);
|
|
6997
|
+
const targetId = roleEditTarget.userId;
|
|
6998
|
+
setRoleEditTarget(null);
|
|
6999
|
+
try {
|
|
7000
|
+
await onUpdateRole(targetId, newRole);
|
|
7001
|
+
} catch (error) {
|
|
7002
|
+
} finally {
|
|
7003
|
+
setIsUpdatingRole(false);
|
|
7004
|
+
}
|
|
7005
|
+
};
|
|
7006
|
+
const activeExpandedMember = expandedId ? members.find((m) => m.id === expandedId) : null;
|
|
7007
|
+
useEffect24(() => {
|
|
7008
|
+
if (!isOrg || !orgSlug || orgSlug === initialOrgSlug) {
|
|
7009
|
+
setSlugAvailable(null);
|
|
7010
|
+
setIsCheckingSlug(false);
|
|
7011
|
+
return;
|
|
7012
|
+
}
|
|
7013
|
+
if (orgSlug.length < 3) {
|
|
7014
|
+
setSlugAvailable(false);
|
|
7015
|
+
setIsCheckingSlug(false);
|
|
7016
|
+
return;
|
|
7017
|
+
}
|
|
7018
|
+
setIsCheckingSlug(true);
|
|
7019
|
+
setSlugAvailable(null);
|
|
7020
|
+
const checkTimer = setTimeout(async () => {
|
|
7021
|
+
try {
|
|
7022
|
+
if (onCheckSlugAvailability) {
|
|
7023
|
+
const res = await onCheckSlugAvailability(orgSlug);
|
|
7024
|
+
setSlugAvailable(res.available);
|
|
7025
|
+
}
|
|
7026
|
+
} catch (error) {
|
|
7027
|
+
setSlugAvailable(null);
|
|
7028
|
+
} finally {
|
|
7029
|
+
setIsCheckingSlug(false);
|
|
7030
|
+
}
|
|
7031
|
+
}, 1500);
|
|
7032
|
+
return () => clearTimeout(checkTimer);
|
|
7033
|
+
}, [orgSlug, initialOrgSlug, onCheckSlugAvailability, isOrg]);
|
|
7034
|
+
const handleSaveOrganization = async (e) => {
|
|
7035
|
+
e.preventDefault();
|
|
7036
|
+
if (isSavingOrg || isCheckingSlug || !canManage || !onSaveOrganization) return;
|
|
7037
|
+
if (orgSlug !== initialOrgSlug && slugAvailable === false) return toast18.error("Address handle unavailable.");
|
|
7038
|
+
setIsSavingOrg(true);
|
|
7039
|
+
try {
|
|
7040
|
+
let finalAvatarUrl = orgAvatarUrl;
|
|
7041
|
+
if (pendingOrgAvatar && onUploadAvatar) {
|
|
7042
|
+
setIsUploadingOrgAvatar(true);
|
|
7043
|
+
try {
|
|
7044
|
+
const res2 = await onUploadAvatar(pendingOrgAvatar, "ORGANIZATION");
|
|
7045
|
+
if (res2?.url) {
|
|
7046
|
+
finalAvatarUrl = res2.url;
|
|
7047
|
+
setOrgAvatarUrl(finalAvatarUrl);
|
|
7048
|
+
}
|
|
7049
|
+
} catch (err) {
|
|
7050
|
+
toast18.error("Failed to securely upload workspace avatar.");
|
|
7051
|
+
setIsSavingOrg(false);
|
|
7052
|
+
setIsUploadingOrgAvatar(false);
|
|
7053
|
+
return;
|
|
7054
|
+
}
|
|
7055
|
+
setPendingOrgAvatar(null);
|
|
7056
|
+
setIsUploadingOrgAvatar(false);
|
|
7057
|
+
}
|
|
7058
|
+
const res = await onSaveOrganization({ name: orgName, slug: orgSlug, avatarUrl: finalAvatarUrl });
|
|
7059
|
+
if (res.success) toast18.success("Workspace updated successfully.");
|
|
7060
|
+
else toast18.error(res.error || "Failed to update workspace.");
|
|
7061
|
+
} catch (error) {
|
|
7062
|
+
toast18.error("Service unavailable.");
|
|
7063
|
+
} finally {
|
|
7064
|
+
setIsSavingOrg(false);
|
|
7065
|
+
setIsUploadingOrgAvatar(false);
|
|
7066
|
+
}
|
|
7067
|
+
};
|
|
7068
|
+
const handleSaveProfile = async (e) => {
|
|
7069
|
+
e.preventDefault();
|
|
7070
|
+
if (isSavingProfile || !onSaveProfile) return;
|
|
7071
|
+
setIsSavingProfile(true);
|
|
7072
|
+
try {
|
|
7073
|
+
let finalAvatarUrl = avatarUrl;
|
|
7074
|
+
if (pendingUserAvatar && onUploadAvatar) {
|
|
7075
|
+
setIsUploadingUserAvatar(true);
|
|
7076
|
+
try {
|
|
7077
|
+
const res2 = await onUploadAvatar(pendingUserAvatar, "USER");
|
|
7078
|
+
if (res2?.url) {
|
|
7079
|
+
finalAvatarUrl = res2.url;
|
|
7080
|
+
setAvatarUrl(finalAvatarUrl);
|
|
7081
|
+
}
|
|
7082
|
+
} catch (err) {
|
|
7083
|
+
toast18.error("Failed to securely upload profile avatar.");
|
|
7084
|
+
setIsSavingProfile(false);
|
|
7085
|
+
setIsUploadingUserAvatar(false);
|
|
7086
|
+
return;
|
|
7087
|
+
}
|
|
7088
|
+
setPendingUserAvatar(null);
|
|
7089
|
+
setIsUploadingUserAvatar(false);
|
|
7090
|
+
}
|
|
7091
|
+
const res = await onSaveProfile({ firstName, lastName, jobTitle, description, avatarUrl: finalAvatarUrl });
|
|
7092
|
+
if (res.success) toast18.success("Identity updated successfully.");
|
|
7093
|
+
else toast18.error(res.error || "Failed to update identity.");
|
|
7094
|
+
} catch (error) {
|
|
7095
|
+
toast18.error("Service unavailable.");
|
|
7096
|
+
} finally {
|
|
7097
|
+
setIsSavingProfile(false);
|
|
7098
|
+
setIsUploadingUserAvatar(false);
|
|
7099
|
+
}
|
|
7100
|
+
};
|
|
7101
|
+
const hasOrgChanges = orgName !== initialOrgName || orgSlug !== initialOrgSlug || orgAvatarUrl !== initialOrgAvatarUrl;
|
|
7102
|
+
const isOrgSaveDisabled = isSavingOrg || !canManage || isCheckingSlug || !hasOrgChanges || orgName.length < 3 || orgSlug.length < 3 || orgSlug !== initialOrgSlug && slugAvailable === false;
|
|
7103
|
+
const hasProfileChanges = `${firstName} ${lastName}`.trim() !== initialFullName || jobTitle !== initialJobTitle || description !== initialDescription || avatarUrl !== initialAvatarUrl;
|
|
7104
|
+
const isProfileSaveDisabled = isSavingProfile || !hasProfileChanges || firstName.length < 2 || lastName.length < 2;
|
|
7105
|
+
const tabs = [];
|
|
7106
|
+
if (isOrg) {
|
|
7107
|
+
tabs.push({ id: "MEMBERS", label: "Members" });
|
|
7108
|
+
tabs.push({ id: "ORGANIZATION", label: "Organization" });
|
|
7109
|
+
}
|
|
7110
|
+
tabs.push({ id: "ACCOUNT", label: "Profile" });
|
|
7111
|
+
return /* @__PURE__ */ React58.createElement("div", { className: "w-full max-w-3xl mx-auto flex flex-col animate-in fade-in duration-300" }, /* @__PURE__ */ React58.createElement(ManagedToaster, null), /* @__PURE__ */ React58.createElement("div", { className: "flex flex-col gap-1 mb-8 px-1" }, /* @__PURE__ */ React58.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React58.createElement(
|
|
7112
|
+
"button",
|
|
7113
|
+
{
|
|
7114
|
+
onClick: () => window.dispatchEvent(new Event("open-sidebar")),
|
|
7115
|
+
className: "md:hidden flex shrink-0 items-center justify-center w-7 h-7 bg-white rounded-full text-black transition-all duration-300 outline-none hover:bg-stone-50",
|
|
7116
|
+
"aria-label": "Open Menu"
|
|
7117
|
+
},
|
|
7118
|
+
/* @__PURE__ */ React58.createElement(HugeiconsIcon44, { icon: SidebarLeft01Icon3, size: 16 })
|
|
7119
|
+
), /* @__PURE__ */ React58.createElement("h1", { className: "text-black text-xl tracking-tight" }, "System Settings")), /* @__PURE__ */ React58.createElement("p", { className: "text-xs text-stone-500" }, "Manage your workspace identity, team configurations, and AI billing parameters.")), /* @__PURE__ */ React58.createElement("div", { className: "flex items-center mb-4 w-full animate-in fade-in duration-300 px-2" }, /* @__PURE__ */ React58.createElement("div", { className: "flex items-center bg-white rounded-full p-1 sm:p-1.5 max-w-full overflow-x-auto custom-scrollbar" }, tabs.map((tab, idx) => {
|
|
7120
|
+
const isActive = activeTab === tab.id;
|
|
7121
|
+
return /* @__PURE__ */ React58.createElement(
|
|
7122
|
+
"button",
|
|
7123
|
+
{
|
|
7124
|
+
key: idx,
|
|
7125
|
+
onClick: () => {
|
|
7126
|
+
setActiveTab(tab.id);
|
|
7127
|
+
if (tab.id === "MEMBERS") {
|
|
7128
|
+
setExpandedId(null);
|
|
7129
|
+
setIsInviteMode(false);
|
|
7130
|
+
}
|
|
7131
|
+
},
|
|
7132
|
+
className: `px-4 py-1.5 rounded-full text-xs transition-all duration-200 outline-none whitespace-nowrap shrink-0 ${isActive ? "bg-stone-50 text-black" : "text-stone-500 hover:text-black hover:bg-stone-50/50"}`
|
|
7133
|
+
},
|
|
7134
|
+
tab.label
|
|
7135
|
+
);
|
|
7136
|
+
}))), activeTab === "MEMBERS" && isOrg && /* @__PURE__ */ React58.createElement("div", { className: "flex flex-col animate-in fade-in duration-300" }, /* @__PURE__ */ React58.createElement(
|
|
7137
|
+
ConfirmationDialog,
|
|
7138
|
+
{
|
|
7139
|
+
isOpen: !!memberToRemove,
|
|
7140
|
+
title: "Remove Member",
|
|
7141
|
+
message: `Are you sure you want to remove ${memberToRemove?.fullName}? This action cannot be undone.`,
|
|
7142
|
+
confirmText: "Remove",
|
|
7143
|
+
cancelText: "Cancel",
|
|
7144
|
+
isProcessing: isRemoving,
|
|
7145
|
+
isDestructive: true,
|
|
7146
|
+
onClose: () => setMemberToRemove(null),
|
|
7147
|
+
onConfirm: handleConfirmRemove
|
|
7148
|
+
}
|
|
7149
|
+
), !isInviteMode && !activeExpandedMember && /* @__PURE__ */ React58.createElement("div", { className: "flex flex-row flex-nowrap mb-4 items-center justify-between gap-4 w-full px-1" }, /* @__PURE__ */ React58.createElement("div", { className: "relative flex-1 min-w-0 max-w-full" }, /* @__PURE__ */ React58.createElement("div", { className: "absolute inset-y-0 left-0 pl-4 flex items-center pointer-events-none" }, /* @__PURE__ */ React58.createElement(HugeiconsIcon44, { icon: Search01Icon9, size: 16, className: "text-stone-400" })), /* @__PURE__ */ React58.createElement("input", { type: "text", placeholder: "Search members...", value: localSearchQuery, onChange: (e) => setLocalSearchQuery(e.target.value), className: "w-full pl-10 pr-4 py-2 bg-white rounded-full text-sm text-black placeholder-stone-400 outline-none transition-colors focus:border-[#d97757] border border-transparent " })), /* @__PURE__ */ React58.createElement("div", { className: "flex items-center gap-3 w-auto pb-0 shrink-0" }, /* @__PURE__ */ React58.createElement("button", { onClick: () => setIsStatusModalOpen(true), className: "flex items-center justify-center bg-white w-9 h-9 rounded-full text-stone-500 hover:text-black transition-colors outline-none" }, /* @__PURE__ */ React58.createElement(HugeiconsIcon44, { icon: SearchList02Icon4, size: 16 })), /* @__PURE__ */ React58.createElement("button", { onClick: () => setIsRoleModalOpen(true), className: "flex items-center justify-center bg-white w-9 h-9 rounded-full text-stone-500 hover:text-black transition-colors outline-none" }, /* @__PURE__ */ React58.createElement(HugeiconsIcon44, { icon: ListSettingIcon4, size: 16 })))), /* @__PURE__ */ React58.createElement("div", { className: "flex flex-col gap-8 p-6 rounded-2xl bg-white w-full" }, activeExpandedMember ? /* @__PURE__ */ React58.createElement("div", { className: "flex flex-col animate-in fade-in zoom-in-95 duration-300 w-full" }, /* @__PURE__ */ React58.createElement("div", { className: "mb-6 flex w-full items-center" }, /* @__PURE__ */ React58.createElement(
|
|
7150
|
+
"button",
|
|
7151
|
+
{
|
|
7152
|
+
onClick: () => setExpandedId(null),
|
|
7153
|
+
disabled: isUpdatingRole,
|
|
7154
|
+
className: "flex items-center gap-2 text-[#d97757] hover:text-[#d97757] transition-colors text-sm outline-none disabled:opacity-50"
|
|
7155
|
+
},
|
|
7156
|
+
/* @__PURE__ */ React58.createElement(HugeiconsIcon44, { icon: ArrowLeft01Icon23, size: 16 }),
|
|
7157
|
+
" Back"
|
|
7158
|
+
)), /* @__PURE__ */ React58.createElement("div", { className: "flex flex-col gap-1 mb-8" }, /* @__PURE__ */ React58.createElement("h2", { className: "text-black text-xl tracking-tight" }, "Member Profile"), /* @__PURE__ */ React58.createElement("p", { className: "text-xs text-stone-500" }, "View and manage this member's access privileges.")), /* @__PURE__ */ React58.createElement("div", { className: "flex items-center gap-4 mb-4" }, /* @__PURE__ */ React58.createElement(MemberAvatar5, { src: activeExpandedMember.avatarUrl, status: activeExpandedMember.status, sizeClass: "w-14 h-14" }), /* @__PURE__ */ React58.createElement("div", { className: "flex flex-col min-w-0" }, /* @__PURE__ */ React58.createElement("span", { className: "text-sm text-black tracking-tight truncate" }, activeExpandedMember.fullName), /* @__PURE__ */ React58.createElement("div", { className: "flex items-center gap-2 mt-0.5" }, /* @__PURE__ */ React58.createElement("span", { className: "text-xs text-stone-500 capitalize" }, activeExpandedMember.role.toLowerCase()), canManage && (isUpdatingRole ? /* @__PURE__ */ React58.createElement(HugeiconsIcon44, { icon: Loading03Icon32, size: 12, className: "animate-spin text-stone-400 ml-1" }) : /* @__PURE__ */ React58.createElement(React58.Fragment, null, /* @__PURE__ */ React58.createElement("span", { className: "text-stone-300 text-xs px-0.5" }, "\u2022"), /* @__PURE__ */ React58.createElement("button", { onClick: () => setRoleEditTarget(activeExpandedMember), className: "text-xs text-[#d97757] hover:underline outline-none" }, "Edit"), /* @__PURE__ */ React58.createElement("span", { className: "text-stone-300 text-xs px-0.5" }, "\u2022"), /* @__PURE__ */ React58.createElement(
|
|
7159
|
+
"button",
|
|
7160
|
+
{
|
|
7161
|
+
onClick: () => setMemberToRemove(activeExpandedMember),
|
|
7162
|
+
disabled: isUpdatingRole,
|
|
7163
|
+
className: "text-xs text-[#d97757] hover:underline outline-none disabled:opacity-50"
|
|
7164
|
+
},
|
|
7165
|
+
"Remove"
|
|
7166
|
+
))))))) : /* @__PURE__ */ React58.createElement(React58.Fragment, null, /* @__PURE__ */ React58.createElement("div", { className: "flex flex-col gap-1" }, /* @__PURE__ */ React58.createElement("div", { className: "flex flex-row items-center justify-between gap-4" }, /* @__PURE__ */ React58.createElement("h2", { className: "text-black text-xl tracking-tight" }, isInviteMode ? "Add Member" : "Team Directory"), !isInviteMode && canManage && /* @__PURE__ */ React58.createElement("button", { onClick: () => setIsInviteMode(true), className: "shrink-0 px-4 py-1.5 border border-stone-200 text-black text-xs tracking-wide rounded-full hover:bg-stone-50 transition-colors outline-none" }, "Invite Team")), !isInviteMode && /* @__PURE__ */ React58.createElement("p", { className: "text-xs text-stone-500" }, "Manage members and access controls across your organization.")), /* @__PURE__ */ React58.createElement("div", { className: "w-full overflow-hidden" }, isInviteMode ? /* @__PURE__ */ React58.createElement("form", { onSubmit: handleInviteSubmit, className: "flex flex-col gap-8 animate-in fade-in duration-300" }, /* @__PURE__ */ React58.createElement("div", { className: "space-y-1.5 mt-2" }, /* @__PURE__ */ React58.createElement("label", { className: "text-xs text-stone-400 tracking-[0.2em] block" }, "Email Address"), /* @__PURE__ */ React58.createElement("input", { type: "email", value: inviteEmail, onChange: (e) => setInviteEmail(cleanEmailId(e.target.value)), required: true, autoFocus: true, className: "w-full px-2 py-3 bg-transparent text-sm border-b border-stone-200 text-black outline-none focus:border-black transition-all duration-300", placeholder: "name@company.com" })), /* @__PURE__ */ React58.createElement("div", { className: "flex flex-col gap-3" }, /* @__PURE__ */ React58.createElement(ThreeDActionButton, { type: "submit", disabled: inviteEmail.length < 5 || isInviting, isLoading: isInviting, className: "w-full" }, "Send Invitation"), /* @__PURE__ */ React58.createElement("button", { type: "button", onClick: () => {
|
|
7167
|
+
setIsInviteMode(false);
|
|
7168
|
+
setInviteEmail("");
|
|
7169
|
+
}, disabled: isInviting, className: "w-full flex items-center justify-center py-2.5 rounded-full border border-stone-200 text-black hover:bg-stone-50 transition-colors outline-none text-xs tracking-wide" }, "Cancel"))) : isMembersLoading || isTyping ? /* @__PURE__ */ React58.createElement(PageSpinner10, null) : /* @__PURE__ */ React58.createElement("div", { className: "flex flex-col min-w-0 animate-in fade-in duration-300" }, /* @__PURE__ */ React58.createElement("div", null, members.length === 0 ? /* @__PURE__ */ React58.createElement("p", { className: "text-xs text-stone-400 py-6 text-center" }, "No members found") : members.map((member) => /* @__PURE__ */ React58.createElement("div", { key: member.id, onClick: () => setExpandedId(member.id), className: "flex items-center justify-between py-3 hover:bg-stone-50 transition-colors cursor-pointer group min-w-0 px-3 -mx-3 rounded-xl" }, /* @__PURE__ */ React58.createElement("div", { className: "flex items-center gap-4 min-w-0 flex-1" }, /* @__PURE__ */ React58.createElement(MemberAvatar5, { src: member.avatarUrl, status: member.status }), /* @__PURE__ */ React58.createElement("div", { className: "min-w-0 flex-1 flex flex-col gap-0.5" }, /* @__PURE__ */ React58.createElement("p", { className: "text-sm text-black truncate" }, member.fullName), /* @__PURE__ */ React58.createElement("p", { className: "text-xs text-stone-500 capitalize truncate" }, member.role.toLowerCase())))))), /* @__PURE__ */ React58.createElement("div", { className: "flex items-center justify-between pt-6 mt-2 " }, /* @__PURE__ */ React58.createElement("span", { className: "text-xs text-stone-400 tracking-[0.2em]" }, "Page ", membersCurrentPage, " of ", membersTotalPages === 0 ? 1 : membersTotalPages), /* @__PURE__ */ React58.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React58.createElement("button", { onClick: () => onMembersPageChange(membersCurrentPage - 1), disabled: membersCurrentPage <= 1 || isMembersLoading, className: "p-2 bg-white border border-stone-200 rounded-full text-black hover:bg-stone-50 disabled:opacity-30 disabled:cursor-not-allowed transition-all outline-none" }, /* @__PURE__ */ React58.createElement(HugeiconsIcon44, { icon: ArrowLeft01Icon23, size: 14 })), /* @__PURE__ */ React58.createElement("button", { onClick: () => onMembersPageChange(membersCurrentPage + 1), disabled: membersCurrentPage >= membersTotalPages || isMembersLoading || membersTotalPages === 0, className: "p-2 bg-white border border-stone-200 rounded-full text-black hover:bg-stone-50 disabled:opacity-30 disabled:cursor-not-allowed transition-all outline-none" }, /* @__PURE__ */ React58.createElement(HugeiconsIcon44, { icon: ArrowRight01Icon18, size: 14 })))))))), /* @__PURE__ */ React58.createElement(ReusableOptions, { isOpen: isStatusModalOpen, onClose: () => setIsStatusModalOpen(false), title: "Status Filter", options: ["ALL", "ACTIVE", "BUSY", "OFFLINE", "AWAY"], selectedOption: activeStatusFilter, onSelect: (status) => onStatusFilterChange(status) }), /* @__PURE__ */ React58.createElement(ReusableOptions, { isOpen: isRoleModalOpen, onClose: () => setIsRoleModalOpen(false), title: "Role Filter", options: ["ALL", "OWNER", "ADMIN", "MANAGER", "MEMBER", "GUEST"], selectedOption: activeRoleFilter, onSelect: (role) => onRoleFilterChange(role) }), /* @__PURE__ */ React58.createElement(ReusableOptions, { isOpen: !!roleEditTarget, onClose: () => setRoleEditTarget(null), title: "Modify Access Role", options: ["ADMIN", "MANAGER", "MEMBER"], selectedOption: roleEditTarget?.role || "", onSelect: handleRoleUpdate })), activeTab === "ORGANIZATION" && isOrg && /* @__PURE__ */ React58.createElement("div", { className: "flex flex-col gap-8 animate-in rounded-2xl p-6 bg-white fade-in duration-300" }, /* @__PURE__ */ React58.createElement("div", { className: "flex items-start justify-between gap-4" }, /* @__PURE__ */ React58.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ React58.createElement("div", { className: "relative group cursor-pointer shrink-0", onClick: () => canManage && !isSavingOrg ? orgFileInputRef.current?.click() : void 0 }, /* @__PURE__ */ React58.createElement(OrgAvatar3, { src: orgAvatarUrl, sizeClass: "w-14 h-14" }), canManage && /* @__PURE__ */ React58.createElement("div", { className: "absolute -bottom-1 -right-1 w-6 h-6 bg-white border border-stone-200 rounded-full flex items-center justify-center text-stone-500 group-hover:text-black transition-colors z-10" }, isUploadingOrgAvatar ? /* @__PURE__ */ React58.createElement(HugeiconsIcon44, { icon: Loading03Icon32, size: 12, className: "animate-spin" }) : /* @__PURE__ */ React58.createElement(HugeiconsIcon44, { icon: CloudUploadIcon2, size: 14 })), /* @__PURE__ */ React58.createElement("input", { type: "file", ref: orgFileInputRef, className: "hidden", accept: ".png, .jpg, .jpeg", onChange: (e) => handleFileSelect(e, "ORGANIZATION") })), /* @__PURE__ */ React58.createElement("div", null, /* @__PURE__ */ React58.createElement("h2", { className: "text-black text-xl mb-1 tracking-tight" }, "Workspace Details"), /* @__PURE__ */ React58.createElement("p", { className: "text-xs text-stone-500" }, "Manage your organizational identity and handles."))), !canManage && /* @__PURE__ */ React58.createElement("span", { className: "p-2 w-9 h-9 bg-stone-100 text-stone-400 rounded-full shrink-0" }, /* @__PURE__ */ React58.createElement(HugeiconsIcon44, { icon: CircleLock02Icon5, size: 18, className: "text-current" }))), /* @__PURE__ */ React58.createElement("form", { className: "flex flex-col gap-8 w-full max-w-5xl", onSubmit: handleSaveOrganization, autoComplete: "off" }, /* @__PURE__ */ React58.createElement(TextInput, { label: "Workspace Name", value: orgName, onChange: handleOrgNameChange, disabled: !canManage || isSavingOrg, placeholder: "Acme Corporation", maxLength: 50 }), /* @__PURE__ */ React58.createElement("div", { className: "space-y-1.5 relative w-full" }, /* @__PURE__ */ React58.createElement("label", { className: "text-xs text-stone-400 tracking-[0.2em] block" }, "Workspace Handle"), /* @__PURE__ */ React58.createElement("div", { className: "flex items-center relative w-full border-b border-stone-200 focus-within:border-black transition-all duration-300 overflow-hidden" }, /* @__PURE__ */ React58.createElement("input", { type: "text", value: orgSlug, disabled: !canManage || isSavingOrg, onChange: (e) => handleOrgSlugChange(e.target.value), spellCheck: "false", autoComplete: "off", className: "w-full pr-10 pl-0 py-3 text-sm bg-transparent text-black outline-none disabled:opacity-50 disabled:cursor-not-allowed", placeholder: "workspace-handle" }), /* @__PURE__ */ React58.createElement("div", { className: "absolute right-2 top-1/2 -translate-y-1/2" }, isCheckingSlug && /* @__PURE__ */ React58.createElement(InputSpinner4, null), !isCheckingSlug && canManage && orgSlug !== initialOrgSlug && orgSlug.length >= 3 && slugAvailable === false && /* @__PURE__ */ React58.createElement("span", { className: "inline-flex items-center justify-center w-4 h-4 rounded-full bg-[#d97757]/10" }, /* @__PURE__ */ React58.createElement("svg", { className: "w-2 h-2 text-[#d97757]", viewBox: "0 0 20 20", fill: "currentColor" }, /* @__PURE__ */ React58.createElement("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" }))), !isCheckingSlug && canManage && orgSlug !== initialOrgSlug && orgSlug.length >= 3 && slugAvailable === true && /* @__PURE__ */ React58.createElement("span", { className: "inline-flex items-center justify-center w-4 h-4 rounded-full bg-green-100" }, /* @__PURE__ */ React58.createElement("svg", { className: "w-2 h-2 text-green-600", viewBox: "0 0 20 20", fill: "currentColor" }, /* @__PURE__ */ React58.createElement("path", { fillRule: "evenodd", clipRule: "evenodd", d: "M16.707 5.293a1 1 0 00-1.414 0L8 12.586 4.707 9.293a1 1 0 10-1.414 1.414l4 4a1 1 0 001.414 0l8-8a1 1 0 000-1.414z" })))))), /* @__PURE__ */ React58.createElement("div", { className: "pt-8 mt-2 flex items-center gap-4" }, /* @__PURE__ */ React58.createElement(ThreeDActionButton, { type: "submit", disabled: isOrgSaveDisabled, isLoading: isSavingOrg, className: "min-w-32" }, "Save Changes"), hasOrgChanges && !isSavingOrg && canManage && /* @__PURE__ */ React58.createElement("button", { type: "button", onClick: () => {
|
|
7170
|
+
setOrgName(initialOrgName || "");
|
|
7171
|
+
setOrgSlug(initialOrgSlug || "");
|
|
7172
|
+
setOrgAvatarUrl(initialOrgAvatarUrl || "");
|
|
7173
|
+
setPendingOrgAvatar(null);
|
|
7174
|
+
}, className: "text-xs tracking-widest text-stone-400 hover:text-black transition-colors outline-none" }, "Cancel")))), activeTab === "ACCOUNT" && /* @__PURE__ */ React58.createElement("div", { className: "flex flex-col gap-6 animate-in fade-in duration-300" }, /* @__PURE__ */ React58.createElement("div", { className: "flex flex-col gap-8 rounded-2xl p-6 bg-white w-full" }, /* @__PURE__ */ React58.createElement("div", { className: "flex items-start justify-between gap-4" }, /* @__PURE__ */ React58.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ React58.createElement("div", { className: "relative group cursor-pointer shrink-0", onClick: () => !isSavingProfile ? userFileInputRef.current?.click() : void 0 }, /* @__PURE__ */ React58.createElement(MemberAvatar5, { src: avatarUrl, status: "ACTIVE", sizeClass: "w-14 h-14" }), /* @__PURE__ */ React58.createElement("div", { className: "absolute -bottom-1 -right-1 w-6 h-6 bg-white border border-stone-200 rounded-full flex items-center justify-center text-stone-500 group-hover:text-black transition-colors z-20" }, isUploadingUserAvatar ? /* @__PURE__ */ React58.createElement(HugeiconsIcon44, { icon: Loading03Icon32, size: 12, className: "animate-spin" }) : /* @__PURE__ */ React58.createElement(HugeiconsIcon44, { icon: CloudUploadIcon2, size: 14 })), /* @__PURE__ */ React58.createElement("input", { type: "file", ref: userFileInputRef, className: "hidden", accept: ".png, .jpg, .jpeg", onChange: (e) => handleFileSelect(e, "USER") })), /* @__PURE__ */ React58.createElement("div", null, /* @__PURE__ */ React58.createElement("h2", { className: "text-black text-xl mb-1 tracking-tight" }, "Personal Identity"), /* @__PURE__ */ React58.createElement("p", { className: "text-xs text-stone-500" }, "Update your system display name and contact email.")))), /* @__PURE__ */ React58.createElement("form", { className: "flex flex-col gap-6 w-full max-w-5xl", onSubmit: handleSaveProfile, autoComplete: "off" }, /* @__PURE__ */ React58.createElement("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-6" }, /* @__PURE__ */ React58.createElement(TextInput, { label: "First Name", value: firstName, onChange: (v) => setFirstName(v.replace(/[^a-zA-Z\s-]/g, "").substring(0, 50)), disabled: isSavingProfile, placeholder: "First name", maxLength: 50 }), /* @__PURE__ */ React58.createElement(TextInput, { label: "Last Name", value: lastName, onChange: (v) => setLastName(v.replace(/[^a-zA-Z\s-]/g, "").substring(0, 50)), disabled: isSavingProfile, placeholder: "Last name", maxLength: 50 })), /* @__PURE__ */ React58.createElement("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-6" }, /* @__PURE__ */ React58.createElement(TextInput, { label: "Job Title", value: jobTitle, onChange: (v) => setJobTitle(v.substring(0, 50)), disabled: isSavingProfile, placeholder: "e.g. HR Manager, CEO", maxLength: 50 }), /* @__PURE__ */ React58.createElement("div", { className: "space-y-1.5 w-full" }, /* @__PURE__ */ React58.createElement("label", { className: "text-xs text-stone-400 tracking-[0.2em] block" }, "Email Address"), /* @__PURE__ */ React58.createElement("input", { type: "email", value: initialEmail, disabled: true, className: "w-full pb-3 pt-3 text-sm bg-transparent text-stone-400 border-b border-stone-200 outline-none cursor-not-allowed" }))), /* @__PURE__ */ React58.createElement("div", { className: "space-y-1.5 w-full" }, /* @__PURE__ */ React58.createElement("label", { className: "text-xs text-stone-400 tracking-[0.2em] block" }, "About Me"), /* @__PURE__ */ React58.createElement(
|
|
7175
|
+
"textarea",
|
|
7176
|
+
{
|
|
7177
|
+
value: description,
|
|
7178
|
+
onChange: (e) => setDescription(e.target.value.substring(0, 300)),
|
|
7179
|
+
disabled: isSavingProfile,
|
|
7180
|
+
placeholder: "A short shout about yourself...",
|
|
7181
|
+
className: "w-full pb-3 pt-3 text-sm bg-transparent text-black border-b border-stone-200 outline-none focus:border-[#d97757] transition-all duration-300 resize-none h-20 custom-scrollbar",
|
|
7182
|
+
maxLength: 300
|
|
7183
|
+
}
|
|
7184
|
+
)), /* @__PURE__ */ React58.createElement("div", { className: "pt-4 flex items-center gap-4" }, /* @__PURE__ */ React58.createElement(ThreeDActionButton, { type: "submit", disabled: isProfileSaveDisabled, isLoading: isSavingProfile, className: "min-w-32" }, "Update Identity"))))));
|
|
7185
|
+
};
|
|
7186
|
+
|
|
7187
|
+
// src/components/UniversalDeveloperSettings.tsx
|
|
7188
|
+
import React59, { useState as useState43, useEffect as useEffect25 } from "react";
|
|
7189
|
+
import { toast as toast19 } from "react-hot-toast";
|
|
7190
|
+
import { HugeiconsIcon as HugeiconsIcon45 } from "@hugeicons/react";
|
|
7191
|
+
import { SidebarLeft01Icon as SidebarLeft01Icon4 } from "@hugeicons/core-free-icons";
|
|
7192
|
+
var UniversalDeveloperSettings = ({
|
|
7193
|
+
initialPublicKey,
|
|
7194
|
+
initialWebhookUrl,
|
|
7195
|
+
isReadOnly = false,
|
|
7196
|
+
onGenerateKeys,
|
|
7197
|
+
onSaveWebhook
|
|
7198
|
+
}) => {
|
|
7199
|
+
const [publicKey, setPublicKey] = useState43(initialPublicKey);
|
|
7200
|
+
const [webhookUrl, setWebhookUrl] = useState43(initialWebhookUrl);
|
|
7201
|
+
const [isGenerating, setIsGenerating] = useState43(false);
|
|
7202
|
+
const [isSavingWebhook, setIsSavingWebhook] = useState43(false);
|
|
7203
|
+
const [isRollModalOpen, setIsRollModalOpen] = useState43(false);
|
|
7204
|
+
useEffect25(() => {
|
|
7205
|
+
setPublicKey(initialPublicKey || "");
|
|
7206
|
+
setWebhookUrl(initialWebhookUrl || "");
|
|
7207
|
+
}, [initialPublicKey, initialWebhookUrl]);
|
|
7208
|
+
const handleWebhookChange = (val) => {
|
|
7209
|
+
setWebhookUrl(val.trim());
|
|
7210
|
+
};
|
|
7211
|
+
const downloadEnvironmentFile = (pubKey, secKey) => {
|
|
7212
|
+
const envContent = `AUDDITUR_PUBLIC_KEY="${pubKey}"
|
|
7213
|
+
AUDDITUR_SECRET_KEY="${secKey}"
|
|
7214
|
+
`;
|
|
7215
|
+
const blob = new Blob([envContent], { type: "text/plain" });
|
|
7216
|
+
const url = URL.createObjectURL(blob);
|
|
7217
|
+
const link = document.createElement("a");
|
|
7218
|
+
link.href = url;
|
|
7219
|
+
link.download = "audditur_credentials.txt";
|
|
7220
|
+
document.body.appendChild(link);
|
|
7221
|
+
link.click();
|
|
7222
|
+
document.body.removeChild(link);
|
|
7223
|
+
URL.revokeObjectURL(url);
|
|
7224
|
+
};
|
|
7225
|
+
const handleGenerateKeys = async () => {
|
|
7226
|
+
if (isGenerating || isReadOnly) return;
|
|
7227
|
+
setIsGenerating(true);
|
|
7228
|
+
try {
|
|
7229
|
+
const res = await onGenerateKeys();
|
|
7230
|
+
if (res.success && res.data) {
|
|
7231
|
+
setPublicKey(res.data.publicKey);
|
|
7232
|
+
downloadEnvironmentFile(res.data.publicKey, res.data.secretKey);
|
|
7233
|
+
toast19.success("Keys generated. Check your downloads folder.");
|
|
7234
|
+
setIsRollModalOpen(false);
|
|
7235
|
+
} else {
|
|
7236
|
+
toast19.error(res.error || "Uh oh! Something went wrong.");
|
|
7237
|
+
}
|
|
7238
|
+
} catch (error) {
|
|
7239
|
+
toast19.error("Uh oh! Something went wrong.");
|
|
7240
|
+
} finally {
|
|
7241
|
+
setIsGenerating(false);
|
|
7242
|
+
}
|
|
7243
|
+
};
|
|
7244
|
+
const handleSaveWebhook = async (e) => {
|
|
7245
|
+
e.preventDefault();
|
|
7246
|
+
if (isSavingWebhook || isReadOnly) return;
|
|
7247
|
+
setIsSavingWebhook(true);
|
|
7248
|
+
try {
|
|
7249
|
+
const res = await onSaveWebhook(webhookUrl);
|
|
7250
|
+
if (res.success && res.data) {
|
|
7251
|
+
setWebhookUrl(res.data.webhookUrl || "");
|
|
7252
|
+
toast19.success("Webhook URL updated.");
|
|
7253
|
+
} else {
|
|
7254
|
+
toast19.error(res.error || "Uh oh! Something went wrong.");
|
|
7255
|
+
}
|
|
7256
|
+
} catch (error) {
|
|
7257
|
+
toast19.error("Uh oh! Something went wrong.");
|
|
7258
|
+
} finally {
|
|
7259
|
+
setIsSavingWebhook(false);
|
|
7260
|
+
}
|
|
7261
|
+
};
|
|
7262
|
+
const hasWebhookChanges = webhookUrl !== initialWebhookUrl;
|
|
7263
|
+
const isWebhookSaveDisabled = isSavingWebhook || isReadOnly || !hasWebhookChanges;
|
|
7264
|
+
return /* @__PURE__ */ React59.createElement("div", { className: "flex flex-col max-w-3xl rounded-2xl p-6 bg-white gap-8 animate-in fade-in duration-300 min-h-full" }, /* @__PURE__ */ React59.createElement(ManagedToaster, null), /* @__PURE__ */ React59.createElement("div", { className: "flex flex-col sm:flex-row sm:items-start justify-between gap-3 sm:gap-4" }, /* @__PURE__ */ React59.createElement("div", { className: "flex flex-col min-w-0 gap-1" }, /* @__PURE__ */ React59.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React59.createElement(
|
|
7265
|
+
"button",
|
|
7266
|
+
{
|
|
7267
|
+
onClick: () => window.dispatchEvent(new Event("open-sidebar")),
|
|
7268
|
+
className: "md:hidden flex shrink-0 items-center justify-center w-7 h-7 bg-white rounded-full text-black transition-all duration-300 outline-none hover:bg-stone-50",
|
|
7269
|
+
"aria-label": "Open Menu"
|
|
7270
|
+
},
|
|
7271
|
+
/* @__PURE__ */ React59.createElement(HugeiconsIcon45, { icon: SidebarLeft01Icon4, size: 16 })
|
|
7272
|
+
), /* @__PURE__ */ React59.createElement("h1", { className: "font-serif text-xl text-black truncate tracking-tight" }, "Developer Settings")), /* @__PURE__ */ React59.createElement("p", { className: "text-xs text-neutral-500 truncate" }, "Manage your API credentials and webhook integrations.")), isReadOnly && /* @__PURE__ */ React59.createElement("span", { className: "px-3 py-1 bg-neutral-50 text-neutral-500 rounded-full text-[10px] tracking-[0.2em] shrink-0 w-fit sm:mt-1" }, "Read Only Access")), /* @__PURE__ */ React59.createElement("div", { className: "w-full max-w-2xl flex flex-col gap-12" }, /* @__PURE__ */ React59.createElement("div", { className: "flex flex-col gap-6" }, /* @__PURE__ */ React59.createElement("div", { className: "space-y-2 min-w-0" }, /* @__PURE__ */ React59.createElement(
|
|
7273
|
+
TextInput,
|
|
7274
|
+
{
|
|
7275
|
+
label: "Public Key",
|
|
7276
|
+
value: publicKey || "No key generated yet",
|
|
7277
|
+
onChange: () => {
|
|
7278
|
+
},
|
|
7279
|
+
disabled: true
|
|
7280
|
+
}
|
|
7281
|
+
), /* @__PURE__ */ React59.createElement("p", { className: "text-[10px] text-neutral-400 mt-1 leading-snug" }, "Your public key is used to identify your application. Your secret key will only be shown once upon generation.")), /* @__PURE__ */ React59.createElement("div", { className: "flex items-center gap-4" }, /* @__PURE__ */ React59.createElement(
|
|
7282
|
+
ThreeDActionButton,
|
|
7283
|
+
{
|
|
7284
|
+
onClick: () => {
|
|
7285
|
+
if (publicKey) setIsRollModalOpen(true);
|
|
7286
|
+
else handleGenerateKeys();
|
|
7287
|
+
},
|
|
7288
|
+
disabled: isGenerating || isReadOnly,
|
|
7289
|
+
isLoading: isGenerating,
|
|
7290
|
+
className: "w-fit"
|
|
7291
|
+
},
|
|
7292
|
+
publicKey ? "Roll API Keys" : "Generate Keys"
|
|
7293
|
+
))), /* @__PURE__ */ React59.createElement("form", { className: "flex flex-col gap-6 border-t border-neutral-100 pt-8", onSubmit: handleSaveWebhook, autoComplete: "off" }, /* @__PURE__ */ React59.createElement("div", { className: "space-y-2 min-w-0" }, /* @__PURE__ */ React59.createElement(
|
|
7294
|
+
TextInput,
|
|
7295
|
+
{
|
|
7296
|
+
label: "Webhook URL",
|
|
7297
|
+
value: webhookUrl,
|
|
7298
|
+
onChange: handleWebhookChange,
|
|
7299
|
+
disabled: isReadOnly || isSavingWebhook,
|
|
7300
|
+
placeholder: "https://your-domain.com/webhook",
|
|
7301
|
+
type: "url"
|
|
7302
|
+
}
|
|
7303
|
+
), /* @__PURE__ */ React59.createElement("p", { className: "text-[10px] text-neutral-400 mt-1 leading-snug" }, "We will send secure POST requests to this endpoint when significant events occur. Must use HTTPS.")), /* @__PURE__ */ React59.createElement("div", { className: "flex flex-col sm:flex-row sm:items-center justify-between mt-2 gap-6 sm:gap-4" }, /* @__PURE__ */ React59.createElement("div", { className: "flex items-center gap-6 min-w-0" }, /* @__PURE__ */ React59.createElement("div", { className: "min-w-0" }, /* @__PURE__ */ React59.createElement("span", { className: "text-[10px] text-neutral-400 tracking-[0.2em] block truncate uppercase" }, "Webhook Status"), /* @__PURE__ */ React59.createElement("span", { className: `text-xs block truncate ${webhookUrl ? "text-emerald-600" : "text-neutral-400"}` }, webhookUrl ? "Active" : "Inactive"))), /* @__PURE__ */ React59.createElement("div", { className: "flex flex-col-reverse sm:flex-row items-center gap-3 sm:gap-4 w-full sm:w-auto shrink-0" }, hasWebhookChanges && !isSavingWebhook && !isReadOnly && /* @__PURE__ */ React59.createElement(
|
|
7304
|
+
"button",
|
|
7305
|
+
{
|
|
7306
|
+
type: "button",
|
|
7307
|
+
onClick: () => setWebhookUrl(initialWebhookUrl),
|
|
7308
|
+
className: "text-[11px] tracking-widest text-neutral-500 hover:text-black transition-colors w-full sm:w-auto py-2 sm:py-0 outline-none"
|
|
7309
|
+
},
|
|
7310
|
+
"Cancel"
|
|
7311
|
+
), /* @__PURE__ */ React59.createElement(
|
|
7312
|
+
ThreeDActionButton,
|
|
7313
|
+
{
|
|
7314
|
+
type: "submit",
|
|
7315
|
+
disabled: isWebhookSaveDisabled,
|
|
7316
|
+
isLoading: isSavingWebhook,
|
|
7317
|
+
className: "min-w-32 w-full sm:w-auto"
|
|
7318
|
+
},
|
|
7319
|
+
"Save Webhook"
|
|
7320
|
+
))))), /* @__PURE__ */ React59.createElement(
|
|
7321
|
+
ConfirmationDialog,
|
|
7322
|
+
{
|
|
7323
|
+
isOpen: isRollModalOpen && !isReadOnly,
|
|
7324
|
+
title: "Roll API Keys",
|
|
7325
|
+
message: "Are you sure you want to roll your keys? This will permanently invalidate your current secret key and active MCP tokens.",
|
|
7326
|
+
confirmText: "Roll Keys",
|
|
7327
|
+
cancelText: "Cancel",
|
|
7328
|
+
isProcessing: isGenerating,
|
|
7329
|
+
isDestructive: true,
|
|
7330
|
+
onClose: () => !isGenerating && setIsRollModalOpen(false),
|
|
7331
|
+
onConfirm: handleGenerateKeys
|
|
7332
|
+
}
|
|
7333
|
+
));
|
|
7334
|
+
};
|
|
7335
|
+
|
|
7336
|
+
// src/components/UniversalApplicationPage2.tsx
|
|
7337
|
+
import React60, { useState as useState44, useRef as useRef18 } from "react";
|
|
7338
|
+
import { HugeiconsIcon as HugeiconsIcon46 } from "@hugeicons/react";
|
|
7339
|
+
import {
|
|
7340
|
+
Search01Icon as Search01Icon10,
|
|
7341
|
+
SearchList02Icon as SearchList02Icon5,
|
|
7342
|
+
SidebarLeft01Icon as SidebarLeft01Icon5
|
|
7343
|
+
} from "@hugeicons/core-free-icons";
|
|
7344
|
+
var UniversalApplicationPage2 = ({
|
|
7345
|
+
userRole = "MEMBER",
|
|
7346
|
+
applications,
|
|
7347
|
+
isLoading,
|
|
7348
|
+
currentPage,
|
|
7349
|
+
totalPages,
|
|
7350
|
+
onPageChange,
|
|
7351
|
+
searchQuery,
|
|
7352
|
+
onSearchChange,
|
|
7353
|
+
activeStatusFilter,
|
|
7354
|
+
onStatusFilterChange,
|
|
7355
|
+
onApplicationClick,
|
|
7356
|
+
onCreateApplication
|
|
7357
|
+
}) => {
|
|
7358
|
+
const canManage = userRole === "ADMIN" || userRole === "MANAGER" || userRole === "OWNER";
|
|
7359
|
+
const [showStatusModal, setShowStatusModal] = useState44(false);
|
|
7360
|
+
const [localSearchQuery, setLocalSearchQuery] = useState44(searchQuery);
|
|
7361
|
+
const typingTimer = useRef18(null);
|
|
7362
|
+
const handleSearchInput = (e) => {
|
|
7363
|
+
const val = e.target.value;
|
|
7364
|
+
setLocalSearchQuery(val);
|
|
7365
|
+
if (typingTimer.current) clearTimeout(typingTimer.current);
|
|
7366
|
+
typingTimer.current = setTimeout(() => {
|
|
7367
|
+
onSearchChange(val);
|
|
7368
|
+
}, 600);
|
|
7369
|
+
};
|
|
7370
|
+
const APPLICATION_STATUSES = [
|
|
7371
|
+
"ALL",
|
|
7372
|
+
"DRAFT",
|
|
7373
|
+
"COMPLETED",
|
|
7374
|
+
"PENDING",
|
|
7375
|
+
"REJECTED",
|
|
7376
|
+
"QUERIED",
|
|
7377
|
+
"AWAITING_PAYMENT"
|
|
7378
|
+
];
|
|
7379
|
+
return /* @__PURE__ */ React60.createElement("div", { className: "w-full max-w-3xl mx-auto flex flex-col animate-in fade-in duration-300 relative" }, /* @__PURE__ */ React60.createElement("div", { className: "flex flex-col gap-1 mb-8 px-1" }, /* @__PURE__ */ React60.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React60.createElement(
|
|
7380
|
+
"button",
|
|
7381
|
+
{
|
|
7382
|
+
onClick: () => window.dispatchEvent(new Event("open-sidebar")),
|
|
7383
|
+
className: "md:hidden flex shrink-0 items-center justify-center w-7 h-7 bg-white rounded-full text-black transition-all duration-300 outline-none hover:bg-stone-50",
|
|
7384
|
+
"aria-label": "Open Menu"
|
|
7385
|
+
},
|
|
7386
|
+
/* @__PURE__ */ React60.createElement(HugeiconsIcon46, { icon: SidebarLeft01Icon5, size: 16 })
|
|
7387
|
+
), /* @__PURE__ */ React60.createElement("h1", { className: "text-black text-xl tracking-tight" }, "Applications Directory")), /* @__PURE__ */ React60.createElement("p", { className: "text-xs text-stone-500" }, "Search, filter, and track all your organizational applications.")), /* @__PURE__ */ React60.createElement("div", { className: "flex flex-row flex-nowrap mb-2 items-center justify-between gap-4 w-full px-1" }, /* @__PURE__ */ React60.createElement("div", { className: "relative flex-1 min-w-0 max-w-full" }, /* @__PURE__ */ React60.createElement("div", { className: "absolute inset-y-0 left-0 pl-4 flex items-center pointer-events-none" }, /* @__PURE__ */ React60.createElement(HugeiconsIcon46, { icon: Search01Icon10, size: 16, className: "text-stone-400" })), /* @__PURE__ */ React60.createElement(
|
|
7388
|
+
"input",
|
|
7389
|
+
{
|
|
7390
|
+
type: "text",
|
|
7391
|
+
placeholder: "Search applications...",
|
|
7392
|
+
value: localSearchQuery,
|
|
7393
|
+
onChange: handleSearchInput,
|
|
7394
|
+
className: "w-full pl-10 pr-4 py-2.5 bg-white rounded-full text-sm text-black placeholder-stone-400 outline-none transition-colors focus:border-[#d97757] border border-transparent shadow-[0_2px_10px_rgba(0,0,0,0.02)]"
|
|
7395
|
+
}
|
|
7396
|
+
)), /* @__PURE__ */ React60.createElement("div", { className: "flex items-center gap-3 w-auto pb-0 shrink-0" }, /* @__PURE__ */ React60.createElement(
|
|
7397
|
+
"button",
|
|
7398
|
+
{
|
|
7399
|
+
onClick: () => setShowStatusModal(true),
|
|
7400
|
+
className: "flex items-center justify-center bg-white shadow-[0_2px_10px_rgba(0,0,0,0.02)] w-10 h-10 rounded-full text-stone-500 hover:text-black transition-colors outline-none relative"
|
|
7401
|
+
},
|
|
7402
|
+
/* @__PURE__ */ React60.createElement(HugeiconsIcon46, { icon: SearchList02Icon5, size: 18 }),
|
|
7403
|
+
activeStatusFilter !== "ALL" && /* @__PURE__ */ React60.createElement("span", { className: "absolute top-2 right-2 w-2 h-2 bg-[#d97757] rounded-full border border-white" })
|
|
7404
|
+
))), /* @__PURE__ */ React60.createElement("div", { className: "w-full mt-2" }, /* @__PURE__ */ React60.createElement(
|
|
7405
|
+
UniversalApplicationsPage,
|
|
7406
|
+
{
|
|
7407
|
+
headerTitle: "Recent Filings",
|
|
7408
|
+
headerDescription: "",
|
|
7409
|
+
applications,
|
|
7410
|
+
isLoading,
|
|
7411
|
+
currentPage,
|
|
7412
|
+
totalPages,
|
|
7413
|
+
onPageChange,
|
|
7414
|
+
onApplicationClick,
|
|
7415
|
+
onCreateApplication: canManage ? onCreateApplication : void 0
|
|
7416
|
+
}
|
|
7417
|
+
)), /* @__PURE__ */ React60.createElement(
|
|
7418
|
+
ReusableOptions,
|
|
7419
|
+
{
|
|
7420
|
+
isOpen: showStatusModal,
|
|
7421
|
+
onClose: () => setShowStatusModal(false),
|
|
7422
|
+
title: "Filter by Status",
|
|
7423
|
+
options: APPLICATION_STATUSES,
|
|
7424
|
+
selectedOption: activeStatusFilter,
|
|
7425
|
+
onSelect: (status) => {
|
|
7426
|
+
onStatusFilterChange(status);
|
|
7427
|
+
setShowStatusModal(false);
|
|
7428
|
+
}
|
|
7429
|
+
}
|
|
7430
|
+
));
|
|
7431
|
+
};
|
|
6400
7432
|
export {
|
|
6401
7433
|
AppBento2,
|
|
6402
7434
|
CardInfoDialog,
|
|
@@ -6426,15 +7458,20 @@ export {
|
|
|
6426
7458
|
PipleAuth,
|
|
6427
7459
|
PlatformFeatures,
|
|
6428
7460
|
PortfolioHero,
|
|
7461
|
+
RootSidebar,
|
|
6429
7462
|
TextInput,
|
|
6430
7463
|
ThreeDActionButton,
|
|
6431
7464
|
ThreeDButton,
|
|
7465
|
+
UniversalApplicationPage2,
|
|
7466
|
+
UniversalApplicationsPage,
|
|
6432
7467
|
UniversalBuyCryptoPage,
|
|
6433
7468
|
UniversalCardActionPage,
|
|
6434
7469
|
UniversalCardPage,
|
|
6435
7470
|
UniversalCreateHuddle,
|
|
7471
|
+
UniversalDeveloperSettings,
|
|
6436
7472
|
UniversalErrorView,
|
|
6437
7473
|
UniversalHome2,
|
|
7474
|
+
UniversalHome3,
|
|
6438
7475
|
UniversalHomeView,
|
|
6439
7476
|
UniversalHuddleDetails,
|
|
6440
7477
|
UniversalHuddlesPage,
|
|
@@ -6446,6 +7483,7 @@ export {
|
|
|
6446
7483
|
UniversalRewardPage,
|
|
6447
7484
|
UniversalSecurityPage,
|
|
6448
7485
|
UniversalSettings,
|
|
7486
|
+
UniversalSettings2,
|
|
6449
7487
|
UniversalSidebar,
|
|
6450
7488
|
UniversalTransactionPage,
|
|
6451
7489
|
UniversalVerificationPage,
|