Skip to content
This repository was archived by the owner on Apr 19, 2023. It is now read-only.

Commit ba1e1e1

Browse files
✨ Add group switcher
1 parent e426608 commit ba1e1e1

File tree

3 files changed

+103
-2
lines changed

3 files changed

+103
-2
lines changed

src/api.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -190,12 +190,16 @@ export const refresh = async () => {
190190
accessToken,
191191
refreshToken,
192192
}: { accessToken: string; refreshToken: string } = await res.json();
193+
const memberships = await api<any[]>({
194+
method: "GET",
195+
url: `/users/${loggedInUsers[index].details.id}/memberships`,
196+
});
193197
users.update((val) =>
194198
val.map((user, i) => {
195199
if (index === i) {
196200
return {
197201
details: user.details,
198-
memberships: user.memberships,
202+
memberships,
199203
auth: { accessToken, refreshToken },
200204
};
201205
}

src/components/Nav.svelte

+92
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
const { page } = stores();
1515
1616
let showUserDropdown = false;
17+
let showGroupDropdown = false;
1718
1819
const nav = [
1920
{
@@ -59,6 +60,97 @@
5960
<span class="ml-3 text-white font-medium">Staart UI</span>
6061
</a>
6162
</div>
63+
{#if navUsers.length && $page.path.startsWith('/groups/') && navUsers[userIndex].memberships.find((i) => String(i.group.id) === $page.path
64+
.split('/groups/')[1]
65+
.split('/')[0])}
66+
<div class="flex ml-10">
67+
<div class="relative z-20">
68+
<div>
69+
<button
70+
class="max-w-xs bg-gray-800 rounded flex items-center text-sm font-medium text-gray-300 transition motion-reduce:transition-none hover:text-white focus:bg-gray-700 focus:outline-none focus:text-white py-1"
71+
id="user-menu"
72+
aria-haspopup="true"
73+
on:click={() => (showGroupDropdown = true)}>
74+
<img
75+
class="h-8 w-8 rounded mr-3"
76+
src={`https://images.weserv.nl/?url=${encodeURIComponent(navUsers[userIndex].memberships.find((i) => String(i.group.id) === $page.path
77+
.split('/groups/')[1]
78+
.split('/')[0]).group.profilePictureUrl)}&w=64&h=64&fit=contain`}
79+
alt="" />
80+
<span>{navUsers[userIndex].memberships.find((i) => String(i.group.id) === $page.path
81+
.split('/groups/')[1]
82+
.split('/')[0]).group.name}</span>
83+
<svg
84+
class="-mr-1 ml-2 h-5 w-5"
85+
xmlns="http://www.w3.org/2000/svg"
86+
viewBox="0 0 20 20"
87+
fill="currentColor"
88+
aria-hidden="true">
89+
<path
90+
fill-rule="evenodd"
91+
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
92+
clip-rule="evenodd" />
93+
</svg>
94+
</button>
95+
</div>
96+
{#if showGroupDropdown}
97+
<div
98+
class="fixed left-0 right-0 top-0 bottom-0 z-40"
99+
on:click={() => (showGroupDropdown = false)} />
100+
<div
101+
transition:fadeScale={{ baseScale: 0.95, origin: 'top left' }}
102+
class="origin-top-right absolute left-0 mt-2 w-48 rounded-md shadow-lg py-1 bg-white ring-1 ring-black ring-opacity-5 divide-y divide-gray-100 z-50"
103+
role="menu"
104+
aria-orientation="vertical"
105+
aria-labelledby="user-menu"
106+
on:click={() => (showGroupDropdown = false)}>
107+
<div class="py-1">
108+
{#each navUsers[userIndex].memberships as membership}
109+
<a
110+
class="block w-full text-left px-4 py-2 text-sm text-gray-700 transition motion-reduce:transition-none hover:text-gray-900 hover:bg-gray-100 focus:bg-gray-100 focus:outline-none"
111+
href={$page.path.replace(navUsers[userIndex].memberships.find((i) => String(i.group.id) === $page.path
112+
.split('/groups/')[1]
113+
.split('/')[0]).group.id, membership.group.id)}
114+
role="menuitem">
115+
<div class="relative flex items-center">
116+
<img
117+
class="flex-shrink-0 h-6 w-6 rounded"
118+
src={`https://images.weserv.nl/?url=${encodeURIComponent(membership.group.profilePictureUrl)}&w=64&h=64&fit=contain`}
119+
alt="" />
120+
<span
121+
class={navUsers[userIndex].memberships.find((i) => String(i.group.id) === $page.path
122+
.split('/groups/')[1]
123+
.split(
124+
'/'
125+
)[0]).group.id === membership.group.id ? 'ml-3 block font-bold truncate pr-5' : 'ml-3 block font-normal truncate'}>
126+
{membership.group.name}
127+
</span>
128+
{#if navUsers[userIndex].memberships.find((i) => String(i.group.id) === $page.path
129+
.split('/groups/')[1]
130+
.split('/')[0]).group.id === membership.group.id}
131+
<span class="absolute inset-y-0 top-0 right-0 flex items-center">
132+
<svg
133+
class="h-5 w-5"
134+
xmlns="http://www.w3.org/2000/svg"
135+
viewBox="0 0 20 20"
136+
fill="currentColor"
137+
aria-hidden="true">
138+
<path
139+
fill-rule="evenodd"
140+
d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
141+
clip-rule="evenodd" />
142+
</svg>
143+
</span>
144+
{/if}
145+
</div>
146+
</a>
147+
{/each}
148+
</div>
149+
</div>
150+
{/if}
151+
</div>
152+
</div>
153+
{/if}
62154
{#if navUsers.length}
63155
<div class="hidden md:block">
64156
<div class="ml-10 flex items-baseline space-x-4">

src/stores.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@ export interface User {
44
auth: { accessToken: string; refreshToken: string };
55
memberships: {
66
id: number;
7-
group: { id: number; name: string; profilePicture: string; role: "ADMIN" | "OWNER" | "MEMBER" };
7+
group: {
8+
id: number;
9+
name: string;
10+
profilePictureUrl: string;
11+
role: "ADMIN" | "OWNER" | "MEMBER";
12+
};
813
}[];
914
details: {
1015
checkLocationOnLogin: boolean;

0 commit comments

Comments
 (0)