336 lines
8.6 KiB
TypeScript
336 lines
8.6 KiB
TypeScript
import { ReactNode } from 'react';
|
|
|
|
import {
|
|
Box,
|
|
Button,
|
|
ConditionalValue,
|
|
Flex,
|
|
HStack,
|
|
IconButton,
|
|
Span,
|
|
Text,
|
|
useBreakpointValue,
|
|
useDisclosure,
|
|
} from '@chakra-ui/react';
|
|
import {
|
|
LuAlignJustify,
|
|
LuArrowBigLeft,
|
|
LuCircleUserRound,
|
|
LuKeySquare,
|
|
LuLogIn,
|
|
LuLogOut,
|
|
LuMoon,
|
|
LuSettings,
|
|
LuSun,
|
|
} from 'react-icons/lu';
|
|
import {
|
|
MdHelp,
|
|
MdHome,
|
|
MdMore,
|
|
MdOutlinePlaylistPlay,
|
|
MdOutlineUploadFile,
|
|
MdRestartAlt,
|
|
MdSupervisedUserCircle,
|
|
} from 'react-icons/md';
|
|
import { useNavigate } from 'react-router-dom';
|
|
|
|
import { useColorMode, useColorModeValue } from '@/components/ui/color-mode';
|
|
import {
|
|
DrawerBody,
|
|
DrawerContent,
|
|
DrawerHeader,
|
|
DrawerRoot,
|
|
} from '@/components/ui/drawer';
|
|
import {
|
|
MenuContent,
|
|
MenuItem,
|
|
MenuRoot,
|
|
MenuTrigger,
|
|
} from '@/components/ui/menu';
|
|
import { useServiceContext } from '@/service/ServiceContext';
|
|
import { useSessionService } from '@/service/session';
|
|
import { colors } from '@/theme/colors';
|
|
import {
|
|
requestOpenSite,
|
|
requestSignIn,
|
|
requestSignOut,
|
|
requestSignUp,
|
|
} from '@/utils/sso';
|
|
|
|
export const TOP_BAR_HEIGHT = '50px';
|
|
|
|
export const BUTTON_TOP_BAR_PROPERTY = {
|
|
variant: 'ghost' as ConditionalValue<
|
|
'ghost' | 'outline' | 'solid' | 'subtle' | 'surface' | 'plain' | undefined
|
|
>,
|
|
//colorPalette: "brand",
|
|
fontSize: '20px',
|
|
textTransform: 'uppercase',
|
|
height: TOP_BAR_HEIGHT,
|
|
};
|
|
|
|
export type TopBarProps = {
|
|
children?: ReactNode;
|
|
title?: string;
|
|
titleLink?: string;
|
|
titleIcon?: ReactNode;
|
|
};
|
|
|
|
const ButtonMenuLeft = ({
|
|
dest,
|
|
title,
|
|
icon,
|
|
onClickEnd = () => {},
|
|
}: {
|
|
dest: string;
|
|
title: string;
|
|
icon: ReactNode;
|
|
onClickEnd?: () => void;
|
|
}) => {
|
|
const navigate = useNavigate();
|
|
return (
|
|
<>
|
|
<Button
|
|
background="#00000000"
|
|
borderRadius="0px"
|
|
onClick={() => {
|
|
navigate(dest);
|
|
onClickEnd();
|
|
}}
|
|
width="full"
|
|
{...BUTTON_TOP_BAR_PROPERTY}
|
|
>
|
|
<Box asChild style={{ width: '45px', height: '45px' }}>
|
|
{icon}
|
|
</Box>
|
|
<Text paddingLeft="3px" fontWeight="bold" marginRight="auto">
|
|
{title}
|
|
</Text>
|
|
</Button>
|
|
<Box marginY="5" marginX="10" height="2px" background="brand.600" />
|
|
</>
|
|
);
|
|
};
|
|
export const TopBar = ({
|
|
title,
|
|
titleLink,
|
|
titleIcon,
|
|
children,
|
|
}: TopBarProps) => {
|
|
const navigate = useNavigate();
|
|
const { colorMode, toggleColorMode } = useColorMode();
|
|
const { session } = useServiceContext();
|
|
const { clearToken, isConnected } = useSessionService();
|
|
const backColor = useColorModeValue('back.100', 'back.800');
|
|
const drawerDisclose = useDisclosure();
|
|
const isVisible = useBreakpointValue({ base: false, md: true });
|
|
const onOpenLeftMenu = () => {
|
|
if (!isConnected) {
|
|
onForceReload();
|
|
} else {
|
|
drawerDisclose.onOpen();
|
|
}
|
|
};
|
|
const onSignIn = (): void => {
|
|
clearToken();
|
|
requestSignIn();
|
|
};
|
|
const onSignUp = (): void => {
|
|
clearToken();
|
|
requestSignUp();
|
|
};
|
|
const onSignOut = (): void => {
|
|
clearToken();
|
|
requestSignOut();
|
|
};
|
|
const onKarso = (): void => {
|
|
requestOpenSite();
|
|
};
|
|
const onForceReload = (): void => {
|
|
// @ts-expect-error
|
|
window.location.reload(true);
|
|
};
|
|
return (
|
|
<Flex
|
|
minWidth="320px"
|
|
position="absolute"
|
|
top={0}
|
|
left={0}
|
|
right={0}
|
|
height={TOP_BAR_HEIGHT}
|
|
alignItems="center"
|
|
justifyContent="space-between"
|
|
backgroundColor={backColor}
|
|
gap="2"
|
|
px="2"
|
|
boxShadow={'0px 2px 4px ' + colors.back[900]}
|
|
zIndex={200}
|
|
>
|
|
<Button {...BUTTON_TOP_BAR_PROPERTY} onClick={onOpenLeftMenu}>
|
|
<HStack>
|
|
<LuAlignJustify />
|
|
{isVisible && (
|
|
<Text paddingLeft="3px" fontWeight="bold">
|
|
{environment.applName}
|
|
</Text>
|
|
)}
|
|
</HStack>
|
|
</Button>
|
|
{title && (
|
|
<Flex
|
|
truncate
|
|
fontSize="20px"
|
|
fontWeight="bold"
|
|
textTransform="uppercase"
|
|
marginRight="auto"
|
|
userSelect="none"
|
|
color="brand.500"
|
|
onClick={titleLink ? () => navigate(titleLink) : undefined}
|
|
>
|
|
<Flex gap="4px">
|
|
{titleIcon}
|
|
{title}
|
|
</Flex>
|
|
</Flex>
|
|
)}
|
|
{children}
|
|
<Flex right="0">
|
|
{!session?.isConnected && (
|
|
<>
|
|
<Button {...BUTTON_TOP_BAR_PROPERTY} onClick={onSignIn}>
|
|
<LuLogIn />
|
|
<Text paddingLeft="3px" fontWeight="bold">
|
|
Sign-in
|
|
</Text>
|
|
</Button>
|
|
<Button
|
|
{...BUTTON_TOP_BAR_PROPERTY}
|
|
onClick={onSignUp}
|
|
disabled={true}
|
|
>
|
|
<MdMore />
|
|
<Text paddingLeft="3px" fontWeight="bold">
|
|
Sign-up
|
|
</Text>
|
|
</Button>
|
|
</>
|
|
)}
|
|
{session?.isConnected && (
|
|
<MenuRoot>
|
|
<MenuTrigger asChild>
|
|
<IconButton {...BUTTON_TOP_BAR_PROPERTY} width={TOP_BAR_HEIGHT}>
|
|
<LuCircleUserRound />
|
|
</IconButton>
|
|
</MenuTrigger>
|
|
<MenuContent>
|
|
<MenuItem
|
|
value="user"
|
|
valueText="user"
|
|
color={useColorModeValue('brand.800', 'brand.200')}
|
|
>
|
|
<MdSupervisedUserCircle />
|
|
<Box flex="1">Sign in as {session?.login ?? 'Fail'}</Box>
|
|
</MenuItem>
|
|
<MenuItem
|
|
value="Settings"
|
|
valueText="Settings"
|
|
onClick={() => navigate('/settings')}
|
|
>
|
|
<LuSettings />
|
|
Settings
|
|
</MenuItem>
|
|
<MenuItem
|
|
value="Help"
|
|
valueText="Help"
|
|
onClick={() => navigate('/help')}
|
|
>
|
|
<MdHelp /> Help
|
|
</MenuItem>
|
|
<MenuItem
|
|
value="Sign-out"
|
|
valueText="Sign-out"
|
|
onClick={onSignOut}
|
|
>
|
|
<LuLogOut /> Sign-out
|
|
</MenuItem>
|
|
<MenuItem value="karso" valueText="Karso" onClick={onKarso}>
|
|
<LuKeySquare /> Karso (SSO)
|
|
</MenuItem>
|
|
<MenuItem
|
|
value="force_reload"
|
|
valueText="Karso"
|
|
onClick={onForceReload}
|
|
>
|
|
<MdRestartAlt /> force reload
|
|
</MenuItem>
|
|
{colorMode === 'light' ? (
|
|
<MenuItem
|
|
value="set-dark"
|
|
valueText="set-dark"
|
|
onClick={toggleColorMode}
|
|
>
|
|
<LuMoon /> Set dark mode
|
|
</MenuItem>
|
|
) : (
|
|
<MenuItem
|
|
value="set-light"
|
|
valueText="set-light"
|
|
onClick={toggleColorMode}
|
|
>
|
|
<LuSun /> Set light mode
|
|
</MenuItem>
|
|
)}
|
|
</MenuContent>
|
|
</MenuRoot>
|
|
)}
|
|
</Flex>
|
|
{session?.isConnected && (
|
|
<DrawerRoot
|
|
placement="start"
|
|
onOpenChange={drawerDisclose.onClose}
|
|
open={drawerDisclose.open}
|
|
data-testid="top-bar_drawer-root"
|
|
>
|
|
<DrawerContent data-testid="top-bar_drawer-content">
|
|
<DrawerHeader
|
|
paddingY="auto"
|
|
as="button"
|
|
onClick={drawerDisclose.onClose}
|
|
boxShadow={'0px 2px 4px ' + colors.back[900]}
|
|
backgroundColor={backColor}
|
|
color={useColorModeValue('brand.900', 'brand.50')}
|
|
textTransform="uppercase"
|
|
>
|
|
<HStack {...BUTTON_TOP_BAR_PROPERTY} cursor="pointer">
|
|
<LuArrowBigLeft />
|
|
<Span paddingLeft="3px">{environment.applName}</Span>
|
|
</HStack>
|
|
</DrawerHeader>
|
|
<DrawerBody paddingX="0px">
|
|
<Box marginY="3" />
|
|
<ButtonMenuLeft
|
|
onClickEnd={drawerDisclose.onClose}
|
|
dest="/"
|
|
title="Home"
|
|
icon={<MdHome />}
|
|
/>
|
|
<ButtonMenuLeft
|
|
onClickEnd={drawerDisclose.onClose}
|
|
dest="/on-air"
|
|
title="On air"
|
|
icon={<MdOutlinePlaylistPlay />}
|
|
/>
|
|
<ButtonMenuLeft
|
|
onClickEnd={drawerDisclose.onClose}
|
|
dest="/add"
|
|
title="Add Media"
|
|
icon={<MdOutlineUploadFile />}
|
|
/>
|
|
</DrawerBody>
|
|
</DrawerContent>
|
|
</DrawerRoot>
|
|
)}
|
|
</Flex>
|
|
);
|
|
};
|