Skip to content

Commit 889b3df

Browse files
Hide teams filter on dashboard for guest users (#807)
1 parent 24369f4 commit 889b3df

File tree

2 files changed

+98
-89
lines changed

2 files changed

+98
-89
lines changed

ui/src/pages/Dashboard.svelte

Lines changed: 93 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
RotateCcw,
2323
CheckCircle,
2424
} from 'lucide-svelte';
25+
import { validateUserIsRegistered } from '../validationUtils';
2526
2627
interface Props {
2728
xfetch: ApiClient;
@@ -49,6 +50,9 @@
4950
}
5051
5152
async function loadTeams() {
53+
if (!validateUserIsRegistered($user)) {
54+
return Promise.resolve();
55+
}
5256
try {
5357
xfetch(`/api/users/${$user.id}/teams`)
5458
.then(res => res.json())
@@ -172,112 +176,116 @@
172176
</p>
173177
</div>
174178

175-
<!-- Team Filter Dropdown -->
176-
<div class="flex-shrink-0 lg:mt-2">
177-
<div class="flex items-center space-x-4">
178-
<div class="flex items-center space-x-2">
179-
<Filter class="h-5 w-5 text-slate-500 dark:text-slate-400" />
180-
<span class="text-sm font-medium text-slate-700 dark:text-slate-300">{$LL.filterByTeam()}</span>
181-
</div>
182-
183-
<div class="relative">
184-
<button
185-
onclick={toggleTeamDropdown}
186-
class="inline-flex items-center justify-between rounded-xl bg-white dark:bg-slate-800 px-4 py-2.5 text-sm font-medium text-slate-700 dark:text-slate-300 shadow-sm ring-1 ring-slate-300 dark:ring-slate-600 hover:bg-slate-50 dark:hover:bg-slate-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 min-w-[200px]"
187-
>
188-
<div class="flex items-center space-x-2">
189-
<Users class="h-4 w-4" />
190-
<span>
191-
{selectedTeam ? selectedTeam.name : $LL.allTeams()}
192-
</span>
193-
</div>
194-
<ChevronDown
195-
class="h-4 w-4 ml-2 transition-transform duration-200 {showTeamDropdown ? 'rotate-180' : ''}"
196-
/>
197-
</button>
179+
{#if validateUserIsRegistered($user)}
180+
<!-- Team Filter Dropdown -->
181+
<div class="flex-shrink-0 lg:mt-2">
182+
<div class="flex items-center space-x-4">
183+
<div class="flex items-center space-x-2">
184+
<Filter class="h-5 w-5 text-slate-500 dark:text-slate-400" />
185+
<span class="text-sm font-medium text-slate-700 dark:text-slate-300">{$LL.filterByTeam()}</span>
186+
</div>
198187

199-
{#if showTeamDropdown}
200-
<div
201-
class="absolute right-0 mt-2 w-64 origin-top-right rounded-xl bg-white dark:bg-slate-800 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none z-50"
188+
<div class="relative">
189+
<button
190+
onclick={toggleTeamDropdown}
191+
class="inline-flex items-center justify-between rounded-xl bg-white dark:bg-slate-800 px-4 py-2.5 text-sm font-medium text-slate-700 dark:text-slate-300 shadow-sm ring-1 ring-slate-300 dark:ring-slate-600 hover:bg-slate-50 dark:hover:bg-slate-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 min-w-[200px]"
202192
>
203-
<div class="py-2">
204-
<button
205-
onclick={() => selectTeam(null)}
206-
class="flex w-full items-center px-4 py-2.5 text-sm text-slate-700 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-700 {!selectedTeam
207-
? 'bg-blue-50 dark:bg-blue-900/20 text-blue-700 dark:text-blue-300'
208-
: ''}"
209-
>
210-
<div class="flex items-center space-x-3">
211-
<div class="flex h-8 w-8 items-center justify-center rounded-lg bg-slate-100 dark:bg-slate-700">
212-
<Users class="h-4 w-4 text-slate-600 dark:text-slate-400" />
213-
</div>
214-
<div class="text-left">
215-
<div class="font-medium">{$LL.allTeams()}</div>
216-
<div class="text-xs text-slate-500 dark:text-slate-400">
217-
{$LL.showContentForAllTeams()}
218-
</div>
219-
</div>
220-
</div>
221-
</button>
193+
<div class="flex items-center space-x-2">
194+
<Users class="h-4 w-4" />
195+
<span>
196+
{selectedTeam ? selectedTeam.name : $LL.allTeams()}
197+
</span>
198+
</div>
199+
<ChevronDown
200+
class="h-4 w-4 ml-2 transition-transform duration-200 {showTeamDropdown ? 'rotate-180' : ''}"
201+
/>
202+
</button>
222203

223-
{#each teams as team}
204+
{#if showTeamDropdown}
205+
<div
206+
class="absolute right-0 mt-2 w-64 origin-top-right rounded-xl bg-white dark:bg-slate-800 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none z-50"
207+
>
208+
<div class="py-2">
224209
<button
225-
onclick={() => selectTeam(team)}
226-
class="flex w-full items-center px-4 py-2.5 text-sm text-slate-700 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-700 {selectedTeam?.id ===
227-
team.id
210+
onclick={() => selectTeam(null)}
211+
class="flex w-full items-center px-4 py-2.5 text-sm text-slate-700 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-700 {!selectedTeam
228212
? 'bg-blue-50 dark:bg-blue-900/20 text-blue-700 dark:text-blue-300'
229213
: ''}"
230214
>
231215
<div class="flex items-center space-x-3">
232216
<div
233-
class="flex h-8 w-8 items-center justify-center rounded-lg bg-emerald-100 dark:bg-emerald-900/30"
217+
class="flex h-8 w-8 items-center justify-center rounded-lg bg-slate-100 dark:bg-slate-700"
234218
>
235-
<Users class="h-4 w-4 text-emerald-600 dark:text-emerald-400" />
219+
<Users class="h-4 w-4 text-slate-600 dark:text-slate-400" />
236220
</div>
237221
<div class="text-left">
238-
<div class="font-medium">{team.name}</div>
222+
<div class="font-medium">{$LL.allTeams()}</div>
223+
<div class="text-xs text-slate-500 dark:text-slate-400">
224+
{$LL.showContentForAllTeams()}
225+
</div>
239226
</div>
240227
</div>
241228
</button>
242-
{/each}
229+
230+
{#each teams as team}
231+
<button
232+
onclick={() => selectTeam(team)}
233+
class="flex w-full items-center px-4 py-2.5 text-sm text-slate-700 dark:text-slate-300 hover:bg-slate-100 dark:hover:bg-slate-700 {selectedTeam?.id ===
234+
team.id
235+
? 'bg-blue-50 dark:bg-blue-900/20 text-blue-700 dark:text-blue-300'
236+
: ''}"
237+
>
238+
<div class="flex items-center space-x-3">
239+
<div
240+
class="flex h-8 w-8 items-center justify-center rounded-lg bg-emerald-100 dark:bg-emerald-900/30"
241+
>
242+
<Users class="h-4 w-4 text-emerald-600 dark:text-emerald-400" />
243+
</div>
244+
<div class="text-left">
245+
<div class="font-medium">{team.name}</div>
246+
</div>
247+
</div>
248+
</button>
249+
{/each}
250+
</div>
243251
</div>
244-
</div>
252+
{/if}
253+
</div>
254+
255+
{#if selectedTeam}
256+
<button
257+
onclick={() => selectTeam(null)}
258+
class="text-sm text-blue-600 dark:text-blue-400 hover:text-blue-700 dark:hover:text-blue-300 font-medium"
259+
>
260+
{$LL.clearFilter()}
261+
</button>
245262
{/if}
246263
</div>
247-
248264
{#if selectedTeam}
249-
<button
250-
onclick={() => selectTeam(null)}
251-
class="text-sm text-blue-600 dark:text-blue-400 hover:text-blue-700 dark:hover:text-blue-300 font-medium"
252-
>
253-
{$LL.clearFilter()}
254-
</button>
265+
{@const linkPrefix = selectedTeam.department_id
266+
? `/organization/${selectedTeam.organization_id}/department/${selectedTeam.department_id}/team/${selectedTeam.id}`
267+
: selectedTeam.organization_id
268+
? `/organization/${selectedTeam.organization_id}/team/${selectedTeam.id}`
269+
: `/team/${selectedTeam.id}`}
270+
<div class="flex flex-col sm:flex-row gap-3 mt-4 justify-end">
271+
<a
272+
href={linkPrefix}
273+
class="inline-flex items-center justify-center gap-2 px-4 py-2.5 text-sm font-medium text-white bg-gradient-to-r from-blue-600 to-blue-700 hover:from-blue-700 hover:to-blue-800 dark:from-blue-500 dark:to-blue-600 dark:hover:from-blue-600 dark:hover:to-blue-700 rounded-lg shadow-sm hover:shadow-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 dark:focus:ring-offset-slate-800 transition-all duration-200"
274+
>
275+
<Users class="h-4 w-4" />
276+
{$LL.teamPage()}
277+
</a>
278+
<a
279+
href="{linkPrefix}/checkin"
280+
class="inline-flex items-center justify-center gap-2 px-4 py-2.5 text-sm font-medium text-lime-700 dark:text-lime-300 bg-lime-50 hover:bg-lime-100 dark:bg-lime-900/20 dark:hover:bg-lime-900/30 border border-lime-200 dark:border-lime-700 hover:border-lime-300 dark:hover:border-lime-600 rounded-lg shadow-sm hover:shadow-md focus:outline-none focus:ring-2 focus:ring-lime-500 focus:ring-offset-2 dark:focus:ring-offset-slate-800 transition-all duration-200"
281+
>
282+
<CheckCircle class="h-4 w-4" />
283+
{$LL.teamCheckins()}
284+
</a>
285+
</div>
255286
{/if}
256287
</div>
257-
{#if selectedTeam}
258-
{@const linkPrefix = selectedTeam.department_id
259-
? `/organization/${selectedTeam.organization_id}/department/${selectedTeam.department_id}/team/${selectedTeam.id}`
260-
: selectedTeam.organization_id
261-
? `/organization/${selectedTeam.organization_id}/team/${selectedTeam.id}`
262-
: `/team/${selectedTeam.id}`}
263-
<div class="flex flex-col sm:flex-row gap-3 mt-4 justify-end">
264-
<a
265-
href={linkPrefix}
266-
class="inline-flex items-center justify-center gap-2 px-4 py-2.5 text-sm font-medium text-white bg-gradient-to-r from-blue-600 to-blue-700 hover:from-blue-700 hover:to-blue-800 dark:from-blue-500 dark:to-blue-600 dark:hover:from-blue-600 dark:hover:to-blue-700 rounded-lg shadow-sm hover:shadow-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 dark:focus:ring-offset-slate-800 transition-all duration-200"
267-
>
268-
<Users class="h-4 w-4" />
269-
{$LL.teamPage()}
270-
</a>
271-
<a
272-
href="{linkPrefix}/checkin"
273-
class="inline-flex items-center justify-center gap-2 px-4 py-2.5 text-sm font-medium text-lime-700 dark:text-lime-300 bg-lime-50 hover:bg-lime-100 dark:bg-lime-900/20 dark:hover:bg-lime-900/30 border border-lime-200 dark:border-lime-700 hover:border-lime-300 dark:hover:border-lime-600 rounded-lg shadow-sm hover:shadow-md focus:outline-none focus:ring-2 focus:ring-lime-500 focus:ring-offset-2 dark:focus:ring-offset-slate-800 transition-all duration-200"
274-
>
275-
<CheckCircle class="h-4 w-4" />
276-
{$LL.teamCheckins()}
277-
</a>
278-
</div>
279-
{/if}
280-
</div>
288+
{/if}
281289
</div>
282290
</div>
283291

ui/src/validationUtils.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ export const passMax = 72;
55
export const nameLenError = `Name must be between ${nameMin} and ${nameMax} characters.`;
66
export const passLenError = `Password must be between ${passMin} and ${passMax} characters.`;
77
export const passNotMatchError = `Password and Confirm Password do not match.`;
8+
import type { User } from './types/user';
89

9-
export const validatePasswords = (password1, password2) => {
10+
export const validatePasswords = (password1: string, password2: string) => {
1011
let valid = true;
1112
let error = '';
1213

@@ -26,7 +27,7 @@ export const validatePasswords = (password1, password2) => {
2627
};
2728
};
2829

29-
export const validateName = warriorName => {
30+
export const validateName = (warriorName: string) => {
3031
let valid = true;
3132
let error = '';
3233

@@ -41,10 +42,10 @@ export const validateName = warriorName => {
4142
};
4243
};
4344

44-
export const validateUserIsAdmin = user => {
45+
export const validateUserIsAdmin = (user: User) => {
4546
return user.rank === 'ADMIN' || user.rank === 'GENERAL';
4647
};
4748

48-
export const validateUserIsRegistered = user => {
49+
export const validateUserIsRegistered = (user: User) => {
4950
return user && user.rank !== 'GUEST' && user.rank !== 'PRIVATE';
5051
};

0 commit comments

Comments
 (0)