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>
);
};