@@ -41,6 +41,7 @@ import {
4141 IconBrandTwitch ,
4242 IconUsers ,
4343 IconBrandGithub ,
44+ IconUser ,
4445} from '@tabler/icons'
4546import useAuthenticatedUser , { logUserOut } from 'src/hooks/auth/useAuthenticatedUser'
4647import { useQueryClient } from '@tanstack/react-query'
@@ -60,7 +61,7 @@ import { EMOTES } from 'src/assets/img/emotes'
6061import { ErrorPage } from 'src/components/ErrorPage/ErrorPage'
6162import HttpStatus from 'src/utils/httpStatus'
6263import BroadcasterTokenButton from 'src/components/BroadcasterTokenModal'
63- import { checkAuthorization , redirectToBroadcasterAuthLogin } from 'src/services/authorization'
64+ import { checkAuthorization , redirectToBroadcasterAuthLogin , redirectToUserAuthLogin } from 'src/services/authorization'
6465import BroadcasterTokenModal from 'src/components/BroadcasterTokenModal'
6566import banner from 'src/assets/img/banner-la-clipassa.png'
6667import homeBackground from 'src/assets/img/background-la-clipassa.jpg'
@@ -87,7 +88,8 @@ export default function Layout({ children }: LayoutProps) {
8788 const { user, isAuthenticating } = useAuthenticatedUser ( )
8889 const { colorScheme } = useMantineColorScheme ( ) // TODO: app logo useffect
8990 const { burgerOpened, setBurgerOpened } = useUISlice ( )
90- const [ broadcasterTokenOpened , { open : openBroadcasterToken , close : closeBroadcasterToken } ] = useDisclosure ( false )
91+ const [ broadcasterTokenModalOpened , { open : openBroadcasterTokenModal , close : closeBroadcasterTokenModal } ] =
92+ useDisclosure ( false )
9193 const notificationIdRef = useRef < string | null > ( null )
9294 const swRegistrationRef = useRef < ServiceWorkerRegistration | null > ( null )
9395
@@ -219,7 +221,7 @@ export default function Layout({ children }: LayoutProps) {
219221 ui . setIsLoggingOut ( false )
220222 }
221223
222- function renderAvatarOrLogin ( ) {
224+ function renderUserMenuButton ( ) {
223225 if ( ui . isLoggingOut || isAuthenticating )
224226 return (
225227 < Group gap = { 'md' } align = "center" >
@@ -228,18 +230,30 @@ export default function Layout({ children }: LayoutProps) {
228230 { ui . isLoggingOut && < Text > { t ( 'layout.loggingOut' ) } </ Text > }
229231 </ Group >
230232 )
231- return user ? (
233+
234+ return (
232235 < UnstyledButton className = { cx ( styles . user , { [ styles . userActive as string ] : userMenuOpened } ) } >
233236 < Group gap = { 'xs' } m = { 4 } align = "center" >
234- < Avatar alt = { user . displayName } radius = "xl" size = { 28 } src = { withBaseURL ( user . profileImage ) } />
235- < Text className = { styles . displayName } fw = { 500 } size = "sm" >
236- { user . displayName }
237- </ Text >
237+ { user ? (
238+ < Avatar alt = { user . displayName } radius = "xl" size = { 28 } src = { withBaseURL ( user . profileImage ) } />
239+ ) : (
240+ < >
241+ < Avatar radius = "xl" size = { 28 } >
242+ < IconUser size = { 16 } />
243+ </ Avatar >
244+ < Text className = { styles . displayName } fw = { 500 } size = "sm" >
245+ { t ( 'common.login' ) }
246+ </ Text >
247+ </ >
248+ ) }
249+ { user && (
250+ < Text className = { styles . displayName } fw = { 500 } size = "sm" >
251+ { user . displayName }
252+ </ Text >
253+ ) }
238254 < IconChevronDown size = { 12 } stroke = { 1.5 } />
239255 </ Group >
240256 </ UnstyledButton >
241- ) : (
242- < LoginButton />
243257 )
244258 }
245259
@@ -254,7 +268,7 @@ export default function Layout({ children }: LayoutProps) {
254268 < Banner />
255269 < AppShell
256270 style = { {
257- height : ` calc(100% - var(--header-height) - var(--footer-height))` ,
271+ height : ' calc(100% - var(--header-height) - var(--footer-height))' ,
258272 } }
259273 className = { styles . appShell }
260274 header = { { height : 'var(--header-height)' } }
@@ -306,65 +320,83 @@ export default function Layout({ children }: LayoutProps) {
306320 width = { 220 }
307321 position = "bottom-end"
308322 onClose = { ( ) => setUserMenuOpened ( false ) }
309- onOpen = { ( ) => {
310- if ( user ) setUserMenuOpened ( true )
311- } }
312- disabled = { ! user }
323+ onOpen = { ( ) => setUserMenuOpened ( true ) }
313324 >
314- < Menu . Target > { renderAvatarOrLogin ( ) } </ Menu . Target >
325+ < Menu . Target > { renderUserMenuButton ( ) } </ Menu . Target >
315326 < Menu . Dropdown classNames = { { dropdown : styles . menuDropdown } } >
316327 < Group justify = "center" >
317328 < LanguageToggle />
318329 </ Group >
319330 < Menu . Divider />
320331 < Menu . Label > { t ( 'common.theme' ) } </ Menu . Label >
321332 < ThemeSwitcher />
322- { checkAuthorization ( { user, requiredRole : 'ADMIN' } ) . authorized && (
323- < >
324- < Menu . Divider />
325- < Menu . Label > Admin</ Menu . Label >
326- < Menu . Item
327- component = "a"
328- color = {
329- window . location . href . includes ( uiPath ( '/admin/users-management' ) )
330- ? 'var(--mantine-primary-color-6)'
331- : 'inherit'
332- }
333- leftSection = { < IconUsers size = { 14 } stroke = { 1.5 } /> }
334- onClick = { ( ) => navigate ( uiPath ( '/admin/users-management' ) ) }
335- >
336- { t ( 'layout.userManagement' ) }
337- </ Menu . Item >
338- </ >
339- ) }
333+
334+ { user
335+ ? checkAuthorization ( { user, requiredRole : 'ADMIN' } ) . authorized && (
336+ < >
337+ < Menu . Divider />
338+ < Menu . Label > Admin</ Menu . Label >
339+ < Menu . Item
340+ component = "a"
341+ color = {
342+ window . location . href . includes ( uiPath ( '/admin/users-management' ) )
343+ ? 'var(--mantine-primary-color-6)'
344+ : 'inherit'
345+ }
346+ leftSection = { < IconUsers size = { 14 } stroke = { 1.5 } /> }
347+ onClick = { ( ) => navigate ( uiPath ( '/admin/users-management' ) ) }
348+ >
349+ { t ( 'layout.userManagement' ) }
350+ </ Menu . Item >
351+ </ >
352+ )
353+ : null }
354+
340355 < Menu . Divider />
341356 < Menu . Item
342357 leftSection = { < IconBrandGithub size = { 14 } stroke = { 1.5 } /> }
343358 onClick = { ( ) => window . open ( 'https://github.com/caliecode/la-clipasa' , '_blank' ) }
344359 >
345360 { t ( 'layout.contribute' ) }
346361 </ Menu . Item >
347- < Menu . Divider />
348- < Menu . Label > Settings</ Menu . Label >
349- < Menu . Item leftSection = { < IconSettings size = { 14 } stroke = { 1.5 } /> } >
350- { t ( 'layout.accountSettings' ) }
351- </ Menu . Item >
352- < Menu . Item
353- leftSection = { < IconDeviceDesktopAnalytics size = { 14 } stroke = { 1.5 } /> }
354- onClick = { ( ) => navigate ( uiPath ( '/settings/sessions' ) ) }
355- >
356- { t ( 'layout.sessionManagement' ) }
357- </ Menu . Item >
358- < Menu . Item
359- onClick = { ( ) => openBroadcasterToken ( ) }
360- leftSection = { < IconBrandTwitch size = { 14 } stroke = { 1.5 } /> }
361- >
362- { t ( 'layout.broadcasterToken' ) }
363- </ Menu . Item >
364- < Menu . Divider />
365- < Menu . Item leftSection = { < IconLogout size = { 14 } stroke = { 1.5 } /> } onClick = { onLogout } >
366- Logout
367- </ Menu . Item >
362+
363+ { user ? (
364+ < >
365+ < Menu . Divider />
366+ < Menu . Label > Settings</ Menu . Label >
367+ < Menu . Item leftSection = { < IconSettings size = { 14 } stroke = { 1.5 } /> } >
368+ { t ( 'layout.accountSettings' ) }
369+ </ Menu . Item >
370+ < Menu . Item
371+ leftSection = { < IconDeviceDesktopAnalytics size = { 14 } stroke = { 1.5 } /> }
372+ onClick = { ( ) => navigate ( uiPath ( '/settings/sessions' ) ) }
373+ >
374+ { t ( 'layout.sessionManagement' ) }
375+ </ Menu . Item >
376+ < Menu . Item
377+ onClick = { ( ) => openBroadcasterTokenModal ( ) }
378+ leftSection = { < IconBrandTwitch size = { 14 } stroke = { 1.5 } /> }
379+ >
380+ { t ( 'layout.broadcasterToken' ) }
381+ </ Menu . Item >
382+ < Menu . Divider />
383+ < Menu . Item leftSection = { < IconLogout size = { 14 } stroke = { 1.5 } /> } onClick = { onLogout } >
384+ { t ( 'common.logout' ) }
385+ </ Menu . Item >
386+ </ >
387+ ) : (
388+ < >
389+ < Menu . Divider />
390+ < Menu . Item
391+ leftSection = { < IconBrandTwitch size = { 14 } stroke = { 1.5 } /> }
392+ className = { styles . twitchLogin }
393+ onClick = { redirectToUserAuthLogin }
394+ >
395+ { t ( 'common.twitchLogin' ) }
396+ </ Menu . Item >
397+ </ >
398+ ) }
399+
368400 < Menu . Label c = "dimmed" style = { { display : 'none' } } >
369401 Version: { import . meta. env . VITE_BUILD_VERSION } (1)
370402 </ Menu . Label >
@@ -425,8 +457,8 @@ export default function Layout({ children }: LayoutProps) {
425457 </ Drawer >
426458 { /* <AppShell.Aside p="md">Aside</AppShell.Aside> */ }
427459 < BroadcasterTokenModal
428- isOpen = { broadcasterTokenOpened }
429- onClose = { closeBroadcasterToken }
460+ isOpen = { broadcasterTokenModalOpened }
461+ onClose = { closeBroadcasterTokenModal }
430462 onConfirm = { ( ) => redirectToBroadcasterAuthLogin ( ) }
431463 />
432464 < AppShell . Footer className = { styles . footer } >
@@ -497,13 +529,13 @@ function Banner() {
497529 alt = "la clipasa"
498530 src = { banner }
499531 onClick = { ( ) => navigate ( '/' ) }
500- className = { ` showOnLargeOnly` }
532+ className = { styles . showOnLargeOnly }
501533 style = { {
502534 cursor : 'pointer' ,
503535 height : 'var(--banner-height)' ,
504536 width : '100%' ,
505537 backgroundImage : `url(${ banner } )` ,
506- animation : ` slideIn 0.3s ease-in-out` ,
538+ animation : ' slideIn 0.3s ease-in-out' ,
507539 } }
508540 />
509541 )
@@ -515,9 +547,9 @@ function LiveAvatar({ streamTitle }) {
515547 return (
516548 < Group align = "center" >
517549 < Tooltip label = { streamTitle } >
518- < a href = { ` https://www.twitch.tv/caliebre` } target = "_blank" rel = "noopener noreferrer" >
550+ < a href = " https://www.twitch.tv/caliebre" target = "_blank" rel = "noopener noreferrer" >
519551 < div style = { { position : 'relative' } } >
520- < img src = { broadcasterIcon } alt = { ` caliebre` } height = { 40 } width = { 40 } className = { styles . avatar } />
552+ < img src = { broadcasterIcon } alt = " caliebre" height = { 40 } width = { 40 } className = { styles . avatar } />
521553 < Badge className = { styles . liveBadge } variant = "filled" radius = { 5 } size = "xs" >
522554 LIVE
523555 </ Badge >
0 commit comments