diff --git a/frontend/src/components/WorkingGroupsSection.svelte b/frontend/src/components/WorkingGroupsSection.svelte index ba443c41..3aed360f 100644 --- a/frontend/src/components/WorkingGroupsSection.svelte +++ b/frontend/src/components/WorkingGroupsSection.svelte @@ -4,6 +4,7 @@ import { userStore } from '../lib/userStore.js'; import { stewardAPI } from '../lib/api.js'; import Avatar from './Avatar.svelte'; + import CategoryIcon from './portal/CategoryIcon.svelte'; import { showSuccess, showError } from '../lib/toastStore.js'; import { categoryTheme } from '../stores/category.js'; import { parseMarkdown } from '../lib/markdownLoader.js'; @@ -13,6 +14,10 @@ // Working groups state let workingGroups = $state([]); let loading = $state(true); + let expandedGroupIds = $state(new Set()); + let totalParticipantCount = $derived( + workingGroups.reduce((total, group) => total + memberCount(group), 0) + ); // Create/Edit modal state let showGroupModal = $state(false); @@ -56,8 +61,10 @@ ); workingGroups = detailedGroups; + expandedGroupIds = new Set(); } catch (err) { workingGroups = []; + expandedGroupIds = new Set(); } finally { loading = false; } @@ -199,177 +206,238 @@ searchResults = []; } }); + + function memberCount(group) { + return group?.participant_count || group?.participants?.length || 0; + } + + function participantName(participant) { + if (participant?.name) return participant.name; + if (participant?.address) return `${participant.address.slice(0, 6)}...${participant.address.slice(-4)}`; + return 'Unnamed member'; + } + + function openParticipant(participant) { + if (participant?.address) { + push(`/participant/${participant.address}`); + } + } + + function isGroupExpanded(groupId) { + return expandedGroupIds.has(groupId); + } + + function toggleGroup(groupId) { + const nextExpandedGroupIds = new Set(expandedGroupIds); + if (nextExpandedGroupIds.has(groupId)) { + nextExpandedGroupIds.delete(groupId); + } else { + nextExpandedGroupIds.add(groupId); + } + expandedGroupIds = nextExpandedGroupIds; + } - -
- -
-
-

- - - - Working Groups -

- {#if isSteward} - - {/if} +
+
+
+ +
+
+

Working Groups

+ + {workingGroups.length} groups + + + {totalParticipantCount} members + +
+

+ Focused steward groups with member rosters and private coordination links where available. +

+
+ + {#if isSteward} + + {/if}
- -
- -

- Specialized teams focused on different aspects of the GenLayer ecosystem. -

- - -
-

- ๐Ÿ’ก Interested in joining? Contact @ras on Discord to learn more. -

-
+
+ Contact @ras on + Discord + to join. +
- +
{#if loading} -
-
+
+ {#each [1, 2] as _} +
+
+
+
+
+
+
+
+ {/each}
- {:else if workingGroups.length === 0} -
- - - -

No working groups yet

+
+
+ +
+

No working groups yet

{#if isSteward} {/if}
- {:else} -
+
{#each workingGroups as group (group.id)} -
- -
-
- {group.icon || '๐Ÿ‘ฅ'} -

{group.name}

- - {group.participant_count || group.participants?.length || 0} members - -
- {#if isSteward} -
- - +
+
+
+
+
+ {#if group.icon} + + {:else} + + {/if} +
+
+
+

{group.name}

+ + {memberCount(group)} members + +
+ {#if group.description} +
+ {@html parseMarkdown(group.description)} +
+ {/if} +
+
+ +
+ {#if group.discord_url} + + + Discord + + {/if} + + {#if isSteward} + + + + {/if} +
- {/if} -
- - - {#if group.description} -
- {@html parseMarkdown(group.description)}
- {/if} +
- - {#if group.participants && group.participants.length > 0} -
- {#each group.participants as participant} -
-
-
- -
- -
-
-
+ {#if isGroupExpanded(group.id)} +
+ {#if group.participants && group.participants.length > 0} +
+ {#each group.participants as participant} +
+ {#if isSteward} {/if}
-
+ {/each}
- {/each} -
- {:else} -
- No members yet + {:else} +
+ No members yet +
+ {/if}
{/if} -
+
{/each}
{/if}
-
+
{#if showGroupModal} @@ -380,39 +448,43 @@
- +
- +
- +
- +
@@ -427,7 +499,7 @@ @@ -444,11 +516,12 @@

Add Participant

- + {#if searching} @@ -518,6 +591,59 @@ {/if}