@elevasis/ui 2.17.0 → 2.18.0

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.
Files changed (37) hide show
  1. package/dist/charts/index.js +2 -2
  2. package/dist/{chunk-ABUDMATM.js → chunk-66VY5EMV.js} +4 -4
  3. package/dist/{chunk-2TDZBYXI.js → chunk-A2AZY5SF.js} +1 -1
  4. package/dist/{chunk-FNWWVX5N.js → chunk-B6FIIEFO.js} +245 -86
  5. package/dist/{chunk-MJ6YV2B5.js → chunk-DDZMBNTY.js} +1 -1
  6. package/dist/{chunk-R7GKX4HW.js → chunk-EY322HXF.js} +175 -78
  7. package/dist/{chunk-JU6UB4YA.js → chunk-FM6LSZ45.js} +3 -3
  8. package/dist/{chunk-OCCZRPER.js → chunk-I3LQGLUC.js} +1 -1
  9. package/dist/{chunk-MDO4UCEJ.js → chunk-LT33DSMO.js} +45 -80
  10. package/dist/{chunk-TP5NMF6K.js → chunk-P6TC4K7I.js} +3 -3
  11. package/dist/{chunk-TTP62HWW.js → chunk-SQPM2QDH.js} +7 -13
  12. package/dist/{chunk-S6CYH4RI.js → chunk-SS2UVUSG.js} +27 -5
  13. package/dist/{chunk-MUZIYL5Q.js → chunk-UA36WILN.js} +83 -310
  14. package/dist/{chunk-OXWQQCDR.js → chunk-WP3IYOVJ.js} +226 -211
  15. package/dist/components/index.d.ts +9 -4
  16. package/dist/components/index.js +32 -18
  17. package/dist/features/crm/index.js +5 -5
  18. package/dist/features/dashboard/index.js +6 -6
  19. package/dist/features/delivery/index.js +5 -5
  20. package/dist/features/lead-gen/index.d.ts +152 -16
  21. package/dist/features/lead-gen/index.js +9 -9
  22. package/dist/features/monitoring/index.js +7 -7
  23. package/dist/features/monitoring/requests/index.js +4 -4
  24. package/dist/features/operations/index.d.ts +1 -0
  25. package/dist/features/operations/index.js +8 -8
  26. package/dist/features/settings/index.js +5 -5
  27. package/dist/hooks/index.d.ts +359 -46
  28. package/dist/hooks/index.js +4 -4
  29. package/dist/hooks/published.d.ts +359 -46
  30. package/dist/hooks/published.js +4 -4
  31. package/dist/index.d.ts +359 -46
  32. package/dist/index.js +4 -4
  33. package/dist/provider/index.js +3 -3
  34. package/dist/provider/published.js +2 -2
  35. package/dist/types/index.d.ts +12 -6
  36. package/dist/zustand/index.js +2 -2
  37. package/package.json +3 -3
@@ -4,9 +4,9 @@ import { SubshellNavItem } from './chunk-CEWTOKE7.js';
4
4
  import { SubshellSidebarSection } from './chunk-IIMU5YAJ.js';
5
5
  import { FilterBar } from './chunk-PDHTXPSF.js';
6
6
  import { CustomModal } from './chunk-GBMNCNHX.js';
7
- import { useDealTasksDue, useDeals, useCreateDealTask, useDeleteDeal, useTableSort, sortData, usePaginationState, useTableSelection, useDealDetail, useCompany } from './chunk-R7GKX4HW.js';
7
+ import { useDealTasksDue, useDealsLookup, useCreateDealTask, useDealsSummary, useDeleteDeal, usePaginationState, useDeals, useTableSort, sortData, useTableSelection, useDealDetail, useCompany } from './chunk-EY322HXF.js';
8
8
  import { SubshellContentContainer } from './chunk-RX4UWZZR.js';
9
- import { CenteredErrorState, CardHeader, PageTitleCaption, EmptyState, ActivityTimeline } from './chunk-TTP62HWW.js';
9
+ import { CenteredErrorState, CardHeader, PageTitleCaption, EmptyState, ActivityTimeline } from './chunk-SQPM2QDH.js';
10
10
  import { useRouterContext } from './chunk-Q7DJKLEN.js';
11
11
  import { PAGE_SIZE_DEFAULT, formatTimeAgo } from './chunk-GCBWGGI6.js';
12
12
  import { useElevasisServices } from './chunk-IRW7JMQ4.js';
@@ -14,7 +14,7 @@ import { Box, Stack, Group, Text, Badge, Center, Loader, UnstyledButton, Button,
14
14
  import { IconLayoutGrid, IconColumns, IconFileInvoice, IconAddressBook, IconTrophy, IconClockExclamation, IconUser, IconPlus, IconChecklist, IconAlertCircle, IconHistory, IconSearch, IconTargetArrow, IconAlertTriangle, IconArrowLeft, IconFileText, IconTrash, IconX, IconBuilding, IconCheckbox, IconCalendar, IconMail, IconPhone, IconArrowRight, IconNote } from '@tabler/icons-react';
15
15
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
16
16
  import { useState, useMemo, useEffect } from 'react';
17
- import { useQuery, useQueryClient } from '@tanstack/react-query';
17
+ import { useQuery } from '@tanstack/react-query';
18
18
  import { useNavigate } from '@tanstack/react-router';
19
19
 
20
20
  var CrmSidebarTop = () => {
@@ -161,28 +161,29 @@ var KIND_OPTIONS = [
161
161
  { value: "meeting", label: "Meeting" },
162
162
  { value: "other", label: "Other" }
163
163
  ];
164
- function buildDealLabel(deal) {
165
- const contact = deal.contact;
166
- if (!contact) return `Deal ${deal.id.slice(0, 8)}`;
167
- const name = `${contact.first_name ?? ""} ${contact.last_name ?? ""}`.trim();
168
- const company = contact.company?.name ?? "\u2014";
169
- return name ? `${name} \u2013 ${company}` : `Deal ${deal.id.slice(0, 8)}`;
170
- }
171
164
  function QuickCreateActions({ showSectionLabel = true }) {
172
165
  const [open, setOpen] = useState(false);
173
166
  const [dealId, setDealId] = useState(null);
167
+ const [dealSearch, setDealSearch] = useState("");
174
168
  const [title, setTitle] = useState("");
175
169
  const [description, setDescription] = useState("");
176
170
  const [kind, setKind] = useState("other");
177
171
  const [dueAt, setDueAt] = useState("");
178
- const { data: deals } = useDeals();
172
+ const { data: deals, isLoading: isLoadingDeals } = useDealsLookup(
173
+ {
174
+ search: dealSearch || void 0,
175
+ limit: 25
176
+ },
177
+ { enabled: open }
178
+ );
179
179
  const createTask = useCreateDealTask();
180
180
  const dealOptions = (deals ?? []).map((deal) => ({
181
181
  value: deal.id,
182
- label: buildDealLabel(deal)
182
+ label: deal.displayLabel
183
183
  }));
184
184
  function resetForm() {
185
185
  setDealId(null);
186
+ setDealSearch("");
186
187
  setTitle("");
187
188
  setDescription("");
188
189
  setKind("other");
@@ -216,11 +217,15 @@ function QuickCreateActions({ showSectionLabel = true }) {
216
217
  Select,
217
218
  {
218
219
  label: "Deal",
219
- placeholder: "Select a deal",
220
+ placeholder: "Search deals",
220
221
  data: dealOptions,
221
222
  value: dealId,
222
223
  onChange: setDealId,
224
+ searchValue: dealSearch,
225
+ onSearchChange: setDealSearch,
223
226
  searchable: true,
227
+ nothingFoundMessage: dealSearch ? "No matching deals" : "No deals available",
228
+ disabled: isLoadingDeals,
224
229
  required: true
225
230
  }
226
231
  ),
@@ -319,32 +324,29 @@ var PIPELINE_FUNNEL_ORDER = [
319
324
  "closed_lost",
320
325
  "nurturing"
321
326
  ];
322
- var defaultValueOf = (deal) => deal.initial_fee ?? 0;
323
327
  function useCrmPipelineSummary(opts) {
324
- const getValue = opts?.getDealValue ?? defaultValueOf;
325
- const { data: deals, isLoading, error } = useDeals();
328
+ const { data: summary, isLoading, error } = useDealsSummary();
326
329
  const data = useMemo(() => {
327
- const dealList = deals ?? [];
328
330
  const stageMap = /* @__PURE__ */ new Map();
329
331
  for (const stage of PIPELINE_FUNNEL_ORDER) {
330
332
  stageMap.set(stage, { count: 0, totalValue: 0 });
331
333
  }
332
- for (const deal of dealList) {
333
- const stage = deal.cached_stage;
334
- if (!stage || !stageMap.has(stage)) continue;
334
+ for (const stageSummary of summary?.stageSummary ?? []) {
335
+ const stage = stageSummary.stage;
336
+ if (!stageMap.has(stage)) continue;
335
337
  const entry = stageMap.get(stage);
336
- entry.count += 1;
337
- entry.totalValue += getValue(deal);
338
+ entry.count = stageSummary.count;
339
+ entry.totalValue = typeof stageSummary.totalValue === "number" ? stageSummary.totalValue : 0;
338
340
  }
339
341
  return PIPELINE_FUNNEL_ORDER.map((stage) => {
340
342
  const entry = stageMap.get(stage);
341
343
  return { stage, count: entry.count, totalValue: entry.totalValue };
342
344
  });
343
- }, [deals, getValue]);
345
+ }, [summary, opts]);
344
346
  return { data, isLoading, error };
345
347
  }
346
- var CLOSED_STAGES = ["closed_won", "closed_lost"];
347
- var OPEN_EXCLUDED = CLOSED_STAGES;
348
+
349
+ // src/features/crm/overview/hooks/useCrmQuickMetrics.ts
348
350
  var ZERO_METRICS = {
349
351
  totalDeals: 0,
350
352
  openDeals: 0,
@@ -354,48 +356,15 @@ var ZERO_METRICS = {
354
356
  totalPipelineValue: 0
355
357
  };
356
358
  function useCrmQuickMetrics() {
357
- const { data: deals, isLoading, error } = useDeals();
358
- const data = useMemo(() => {
359
- const dealList = deals ?? [];
360
- if (dealList.length === 0) return ZERO_METRICS;
361
- let openDeals = 0;
362
- let wonDeals = 0;
363
- let lostDeals = 0;
364
- let wonFeeSum = 0;
365
- let wonFeeCount = 0;
366
- let pipelineValue = 0;
367
- for (const deal of dealList) {
368
- const stage = deal.cached_stage;
369
- const isOpen = !stage || !OPEN_EXCLUDED.includes(stage);
370
- const isWon = stage === "closed_won";
371
- const isLost = stage === "closed_lost";
372
- if (isOpen) {
373
- openDeals += 1;
374
- pipelineValue += deal.initial_fee ?? 0;
375
- }
376
- if (isWon) {
377
- wonDeals += 1;
378
- if (deal.initial_fee != null) {
379
- wonFeeSum += deal.initial_fee;
380
- wonFeeCount += 1;
381
- }
382
- }
383
- if (isLost) {
384
- lostDeals += 1;
385
- }
386
- }
387
- const winRateDenominator = wonDeals + lostDeals;
388
- const winRate = winRateDenominator === 0 ? 0 : wonDeals / winRateDenominator;
389
- const avgDealSize = wonFeeCount === 0 ? 0 : wonFeeSum / wonFeeCount;
390
- return {
391
- totalDeals: dealList.length,
392
- openDeals,
393
- wonDeals,
394
- winRate,
395
- avgDealSize,
396
- totalPipelineValue: pipelineValue
397
- };
398
- }, [deals]);
359
+ const { data: summary, isLoading, error } = useDealsSummary();
360
+ const data = summary ? {
361
+ totalDeals: summary.totalDeals,
362
+ openDeals: summary.openDeals,
363
+ wonDeals: summary.wonDeals,
364
+ winRate: summary.winRate,
365
+ avgDealSize: summary.avgDealSize,
366
+ totalPipelineValue: summary.totalPipelineValue
367
+ } : ZERO_METRICS;
399
368
  return { data, isLoading, error };
400
369
  }
401
370
  function useRecentCrmActivity(opts) {
@@ -736,28 +705,24 @@ var sortAccessors = {
736
705
  };
737
706
  function DealsListPage() {
738
707
  const navigate = useNavigate();
739
- const queryClient = useQueryClient();
740
708
  const deleteDeal = useDeleteDeal();
741
709
  const [stageFilter, setStageFilter] = useState(null);
742
710
  const [searchQuery, setSearchQuery] = useState("");
743
711
  const [showBatchDelete, setShowBatchDelete] = useState(false);
744
- const { data: deals, isLoading, error } = useDeals({
712
+ const pagination = usePaginationState(PAGE_SIZE_DEFAULT, [stageFilter, searchQuery]);
713
+ const { data: deals, total, isLoading, error } = useDeals({
745
714
  stage: stageFilter || void 0,
746
- search: searchQuery || void 0
715
+ search: searchQuery || void 0,
716
+ limit: PAGE_SIZE_DEFAULT,
717
+ offset: pagination.offset
747
718
  });
748
719
  const { sort, toggleSort } = useTableSort("updated");
749
720
  const sortedDeals = useMemo(() => sortData(deals ?? [], sort, sortAccessors), [deals, sort]);
750
- const pagination = usePaginationState(PAGE_SIZE_DEFAULT, [stageFilter, searchQuery], sortedDeals.length);
751
- const paginatedDeals = useMemo(
752
- () => sortedDeals.slice(pagination.offset, pagination.offset + PAGE_SIZE_DEFAULT),
753
- [sortedDeals, pagination.offset]
754
- );
755
- const selection = useTableSelection(paginatedDeals, sortedDeals);
721
+ const selection = useTableSelection(sortedDeals, sortedDeals);
756
722
  const handleDeleteSelected = async () => {
757
723
  await Promise.all([...selection.selectedIds].map((dealId) => deleteDeal.mutateAsync(dealId)));
758
724
  setShowBatchDelete(false);
759
725
  selection.clear();
760
- await queryClient.invalidateQueries({ queryKey: ["deals"] });
761
726
  };
762
727
  return /* @__PURE__ */ jsxs(SubshellContentContainer, { children: [
763
728
  /* @__PURE__ */ jsxs(PageContainer, { children: [
@@ -817,7 +782,7 @@ function DealsListPage() {
817
782
  /* @__PURE__ */ jsx(SortableHeader, { column: "stage", sort, onToggle: toggleSort, children: "Stage" }),
818
783
  /* @__PURE__ */ jsx(SortableHeader, { column: "updated", sort, onToggle: toggleSort, children: "Updated" })
819
784
  ] }) }),
820
- /* @__PURE__ */ jsx(Table.Tbody, { children: paginatedDeals.map((deal) => {
785
+ /* @__PURE__ */ jsx(Table.Tbody, { children: sortedDeals.map((deal) => {
821
786
  const discoveryData = deal.discovery_data;
822
787
  const companyName = deal.contact?.company?.name || discoveryData?.company || deal.contact_email?.split("@")[1] || "-";
823
788
  const contactName = [deal.contact?.first_name, deal.contact?.last_name].filter(Boolean).join(" ");
@@ -848,12 +813,12 @@ function DealsListPage() {
848
813
  );
849
814
  }) })
850
815
  ] }),
851
- sortedDeals.length > PAGE_SIZE_DEFAULT && /* @__PURE__ */ jsx(Group, { justify: "center", children: /* @__PURE__ */ jsx(
816
+ total > PAGE_SIZE_DEFAULT && /* @__PURE__ */ jsx(Group, { justify: "center", children: /* @__PURE__ */ jsx(
852
817
  Pagination,
853
818
  {
854
819
  value: pagination.page,
855
820
  onChange: pagination.setPage,
856
- total: pagination.totalPages(sortedDeals.length),
821
+ total: pagination.totalPages(total),
857
822
  size: "sm"
858
823
  }
859
824
  ) })
@@ -1,10 +1,10 @@
1
- import { CyberAreaChart, CostTrendChart, ActivityTrendChart } from './chunk-MJ6YV2B5.js';
1
+ import { CyberAreaChart, CostTrendChart, ActivityTrendChart } from './chunk-DDZMBNTY.js';
2
2
  import { AppShellLoader } from './chunk-M25JL54Z.js';
3
3
  import { FilterBar } from './chunk-PDHTXPSF.js';
4
4
  import { CustomModal } from './chunk-GBMNCNHX.js';
5
5
  import { formatDuration } from './chunk-E4WQGJNS.js';
6
- import { useResolveError, useResolveAllErrors, usePaginationState, useErrorDetails, useMarkAsRead, useExecutionLogsFilters, useExecutionLogs, useExecutionHealth, useErrorAnalysis, useTimeRangeDates, useErrorDetail, useResolveErrorsByExecution, useResources, useCostTrends, useCostSummary, useCostByModel, useCostBreakdown, useActivityFilters, useActivityTrend, useActivities, useNotifications, useMarkAllAsRead, useTestNotification } from './chunk-R7GKX4HW.js';
7
- import { CenteredErrorState, CardHeader, StatsCardSkeleton, TrendIndicator, DetailCardSkeleton, EmptyState, PageTitleCaption, JsonViewer } from './chunk-TTP62HWW.js';
6
+ import { useResolveError, useResolveAllErrors, usePaginationState, useErrorDetails, useMarkAsRead, useExecutionLogsFilters, useExecutionLogs, useExecutionHealth, useErrorAnalysis, useTimeRangeDates, useErrorDetail, useResolveErrorsByExecution, useResources, useCostTrends, useCostSummary, useCostByModel, useCostBreakdown, useActivityFilters, useActivityTrend, useActivities, useNotifications, useMarkAllAsRead, useTestNotification } from './chunk-EY322HXF.js';
7
+ import { CenteredErrorState, CardHeader, StatsCardSkeleton, TrendIndicator, DetailCardSkeleton, EmptyState, PageTitleCaption, JsonViewer } from './chunk-SQPM2QDH.js';
8
8
  import { useRouterContext } from './chunk-Q7DJKLEN.js';
9
9
  import { formatBucketTime, PAGE_SIZE_DEFAULT, getTimeRangeDates } from './chunk-GCBWGGI6.js';
10
10
  import { useState, useMemo, useCallback } from 'react';
@@ -302,8 +302,13 @@ function ContextNode({ data, depth }) {
302
302
  }
303
303
  return /* @__PURE__ */ jsx(Text, { size: "sm", children: String(data) });
304
304
  }
305
+ var ACRONYMS = ["AI", "URL", "UUID", "ID", "API", "HTTP", "JSON"];
305
306
  function formatLabel(key) {
306
- return key.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[_-]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
307
+ const titleCased = key.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[_-]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
308
+ return titleCased.replace(
309
+ new RegExp(`\\b(${ACRONYMS.map((a) => a[0] + a.slice(1).toLowerCase()).join("|")})\\b`, "g"),
310
+ (match) => match.toUpperCase()
311
+ );
307
312
  }
308
313
  function hasMarkdown(value) {
309
314
  return /(\*\*.+\*\*|^#{1,6}\s|^\s*[-*]\s|\[.+\]\(.+\)|^\|.+\|$|^>\s|```)/.test(value);
@@ -312,18 +317,7 @@ function NestedSection({ title, children }) {
312
317
  const [expanded, setExpanded] = useState(true);
313
318
  return /* @__PURE__ */ jsxs(Stack, { gap: 6, children: [
314
319
  /* @__PURE__ */ jsxs(Group, { gap: 4, style: { cursor: "pointer", userSelect: "none" }, onClick: () => setExpanded((v) => !v), children: [
315
- /* @__PURE__ */ jsx(
316
- IconChevronRight,
317
- {
318
- size: 14,
319
- color: "var(--color-primary)",
320
- style: {
321
- transition: "transform 150ms ease",
322
- transform: expanded ? "rotate(90deg)" : "rotate(0deg)",
323
- flexShrink: 0
324
- }
325
- }
326
- ),
320
+ expanded ? /* @__PURE__ */ jsx(IconChevronDown, { size: 14, color: "var(--color-primary)", style: { flexShrink: 0 } }) : /* @__PURE__ */ jsx(IconChevronRight, { size: 14, color: "var(--color-primary)", style: { flexShrink: 0 } }),
327
321
  /* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, style: { fontFamily: "var(--mantine-font-family-headings)" }, children: title })
328
322
  ] }),
329
323
  expanded && /* @__PURE__ */ jsx(Box, { pl: "sm", style: { borderLeft: "2px solid var(--color-border)" }, children })
@@ -2,14 +2,14 @@ import { AppShellLoader } from './chunk-M25JL54Z.js';
2
2
  import { FilterBar } from './chunk-PDHTXPSF.js';
3
3
  import { CustomModal } from './chunk-GBMNCNHX.js';
4
4
  import { useAvailablePresets } from './chunk-6RWMRQN5.js';
5
- import { useDeleteCredential, useCreateCredential, useCredentials, MEMBERSHIP_STATUS_COLORS, transformMembershipToTableRow, useUserMemberships, useUpdateWebhookEndpoint, useResources, useDeleteWebhookEndpoint, useCreateWebhookEndpoint, useListWebhookEndpoints, useUpdateMemberConfig, useOrganizationMembers, useUpdateCredential, CredentialSchemas } from './chunk-R7GKX4HW.js';
5
+ import { useDeleteCredential, useCreateCredential, useCredentials, MEMBERSHIP_STATUS_COLORS, transformMembershipToTableRow, useUserMemberships, useUpdateWebhookEndpoint, useResources, useDeleteWebhookEndpoint, useCreateWebhookEndpoint, useListWebhookEndpoints, useUpdateMemberConfig, useOrganizationMembers, useUpdateCredential, CredentialSchemas } from './chunk-EY322HXF.js';
6
6
  import { showErrorNotification } from './chunk-GRGRBWIO.js';
7
- import { ListSkeleton, EmptyState, PageTitleCaption, CardHeader, APIErrorAlert, StatCard } from './chunk-TTP62HWW.js';
7
+ import { ListSkeleton, EmptyState, PageTitleCaption, CardHeader, APIErrorAlert, StatCard } from './chunk-SQPM2QDH.js';
8
8
  import { formatDateTime, OAUTH_POPUP_CHECK_INTERVAL, OAUTH_FLOW_TIMEOUT } from './chunk-GCBWGGI6.js';
9
9
  import { useInitialization } from './chunk-DK2HVHCY.js';
10
10
  import { useElevasisServices } from './chunk-IRW7JMQ4.js';
11
11
  import { Table, Group, Text, Tooltip, ActionIcon, Stack, Title, Button, Select, TextInput, Alert, PasswordInput, Anchor, Paper, Card, Switch, Badge, Center, Loader, Box, Code, CopyButton, ThemeIcon, useMantineColorScheme, SimpleGrid, UnstyledButton, Divider, Textarea } from '@mantine/core';
12
- import { IconSettings, IconKey, IconCalendar, IconPencil, IconTrash, IconAlertTriangle, IconInfoCircle, IconExclamationMark, IconPlus, IconAlertCircle, IconUsers, IconSearch, IconBuilding, IconWebhook, IconCheck, IconCopy, IconUser, IconMail, IconRefresh, IconPalette, IconSun, IconEye, IconSparkles, IconTrendingUp, IconClock, IconPlayerPause, IconPlayerPlay, IconActivity, IconBrandDropbox, IconBrandGoogleDrive, IconPlug, IconMoon, IconDeviceDesktop } from '@tabler/icons-react';
12
+ import { IconSettings, IconKey, IconCalendar, IconPencil, IconTrash, IconAlertTriangle, IconInfoCircle, IconExclamationMark, IconPlus, IconAlertCircle, IconUsers, IconSearch, IconBuilding, IconWebhook, IconCheck, IconCopy, IconUser, IconMail, IconRefresh, IconPalette, IconSun, IconEye, IconSparkles, IconTrendingUp, IconClock, IconPlayerPause, IconPlayerPlay, IconActivity, IconBrandDropbox, IconBrandGoogleDrive, IconPlug, IconEdit, IconUserX, IconUserCheck, IconMoon, IconDeviceDesktop } from '@tabler/icons-react';
13
13
  import { z } from 'zod';
14
14
  import { useState, useEffect, useRef, useMemo, useCallback } from 'react';
15
15
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
@@ -547,7 +547,9 @@ function MembershipStatusBadge({ status, size = "sm", variant = "light" }) {
547
547
  function OrganizationMembershipsList({
548
548
  memberships,
549
549
  loading,
550
- error
550
+ error,
551
+ onEditRole,
552
+ onLeaveOrganization
551
553
  }) {
552
554
  const [searchTerm, setSearchTerm] = useState("");
553
555
  const [statusFilter, setStatusFilter] = useState("");
@@ -557,6 +559,26 @@ function OrganizationMembershipsList({
557
559
  const matchesStatus = !statusFilter || row.status === statusFilter;
558
560
  return matchesSearch && matchesStatus;
559
561
  });
562
+ const renderActions = (row) => {
563
+ if (!onEditRole && !onLeaveOrganization) {
564
+ return /* @__PURE__ */ jsx(ActionIcon, { variant: "light", size: "sm", color: "gray", title: "Configure member access", children: /* @__PURE__ */ jsx(IconSettings, { size: 14 }) });
565
+ }
566
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
567
+ row.canEdit && onEditRole && /* @__PURE__ */ jsx(
568
+ ActionIcon,
569
+ {
570
+ variant: "subtle",
571
+ size: "sm",
572
+ color: "blue",
573
+ onClick: () => onEditRole(row.id),
574
+ disabled: row.status !== "active",
575
+ children: /* @__PURE__ */ jsx(IconEdit, { size: 16 })
576
+ }
577
+ ),
578
+ row.canRemove && onLeaveOrganization && row.status === "active" && /* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", size: "sm", color: "red", onClick: () => onLeaveOrganization(row.id), children: /* @__PURE__ */ jsx(IconUserX, { size: 16 }) }),
579
+ row.status === "inactive" && /* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", size: "sm", color: "green", disabled: true, title: "Contact admin to reactivate", children: /* @__PURE__ */ jsx(IconUserCheck, { size: 16 }) })
580
+ ] });
581
+ };
560
582
  if (error) {
561
583
  return /* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsx(APIErrorAlert, { error, title: "Failed to load memberships" }) });
562
584
  }
@@ -622,7 +644,7 @@ function OrganizationMembershipsList({
622
644
  /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { variant: "light", color: "blue", size: "sm", children: row.role }) }),
623
645
  /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(MembershipStatusBadge, { status: row.status }) }),
624
646
  /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: row.joinedAt.toLocaleDateString() }) }),
625
- /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Group, { gap: "xs", children: /* @__PURE__ */ jsx(ActionIcon, { variant: "light", size: "sm", color: "gray", title: "Configure member access", children: /* @__PURE__ */ jsx(IconSettings, { size: 14 }) }) }) })
647
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Group, { gap: "xs", children: renderActions(row) }) })
626
648
  ] }, row.id)) })
627
649
  ] }) })
628
650
  ] })