[DEV] test step between receipice and direct managemnt
This commit is contained in:
parent
91defa42c2
commit
d52052de90
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"display": "2025-01-13",
|
"display": "2025-01-14",
|
||||||
"version": "0.0.1-dev\n - 2025-01-13T21:39:39+01:00",
|
"version": "0.0.1-dev\n - 2025-01-14T20:19:20+01:00",
|
||||||
"commit": "0.0.1-dev\n",
|
"commit": "0.0.1-dev\n",
|
||||||
"date": "2025-01-13T21:39:39+01:00"
|
"date": "2025-01-14T20:19:20+01:00"
|
||||||
}
|
}
|
@ -38,9 +38,10 @@
|
|||||||
"css-mediaquery": "0.1.2",
|
"css-mediaquery": "0.1.2",
|
||||||
"dayjs": "1.11.13",
|
"dayjs": "1.11.13",
|
||||||
"history": "5.3.0",
|
"history": "5.3.0",
|
||||||
|
"next-themes": "^0.4.4",
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
"react-error-boundary": "5.0.0",
|
|
||||||
"react-dom": "18.3.1",
|
"react-dom": "18.3.1",
|
||||||
|
"react-error-boundary": "5.0.0",
|
||||||
"react-icons": "5.4.0",
|
"react-icons": "5.4.0",
|
||||||
"react-router-dom": "7.1.1",
|
"react-router-dom": "7.1.1",
|
||||||
"react-select": "5.9.0",
|
"react-select": "5.9.0",
|
||||||
|
14
front/pnpm-lock.yaml
generated
14
front/pnpm-lock.yaml
generated
@ -35,6 +35,9 @@ importers:
|
|||||||
history:
|
history:
|
||||||
specifier: 5.3.0
|
specifier: 5.3.0
|
||||||
version: 5.3.0
|
version: 5.3.0
|
||||||
|
next-themes:
|
||||||
|
specifier: ^0.4.4
|
||||||
|
version: 0.4.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
react:
|
react:
|
||||||
specifier: 18.3.1
|
specifier: 18.3.1
|
||||||
version: 18.3.1
|
version: 18.3.1
|
||||||
@ -3820,6 +3823,12 @@ packages:
|
|||||||
resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==}
|
resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==}
|
||||||
engines: {node: '>= 0.4.0'}
|
engines: {node: '>= 0.4.0'}
|
||||||
|
|
||||||
|
next-themes@0.4.4:
|
||||||
|
resolution: {integrity: sha512-LDQ2qIOJF0VnuVrrMSMLrWGjRMkq+0mpgl6e0juCLqdJ+oo8Q84JRWT6Wh11VDQKkMMe+dVzDKLWs5n87T+PkQ==}
|
||||||
|
peerDependencies:
|
||||||
|
react: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc
|
||||||
|
react-dom: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc
|
||||||
|
|
||||||
node-domexception@1.0.0:
|
node-domexception@1.0.0:
|
||||||
resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
|
resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
|
||||||
engines: {node: '>=10.5.0'}
|
engines: {node: '>=10.5.0'}
|
||||||
@ -9838,6 +9847,11 @@ snapshots:
|
|||||||
|
|
||||||
netmask@2.0.2: {}
|
netmask@2.0.2: {}
|
||||||
|
|
||||||
|
next-themes@0.4.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
||||||
|
dependencies:
|
||||||
|
react: 18.3.1
|
||||||
|
react-dom: 18.3.1(react@18.3.1)
|
||||||
|
|
||||||
node-domexception@1.0.0: {}
|
node-domexception@1.0.0: {}
|
||||||
|
|
||||||
node-eval@2.0.0:
|
node-eval@2.0.0:
|
||||||
|
@ -17,7 +17,6 @@ import {
|
|||||||
SelectValueText,
|
SelectValueText,
|
||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
defaultSystem,
|
|
||||||
useDisclosure,
|
useDisclosure,
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
|
|
||||||
@ -26,6 +25,7 @@ import { App as SpaApp } from '@/scene/App';
|
|||||||
import { USERS, USERS_COLLECTION } from '@/service/session';
|
import { USERS, USERS_COLLECTION } from '@/service/session';
|
||||||
import { hashLocalData } from '@/utils/sso';
|
import { hashLocalData } from '@/utils/sso';
|
||||||
import { Toaster } from './components/ui/toaster';
|
import { Toaster } from './components/ui/toaster';
|
||||||
|
import { systemTheme } from './theme/theme';
|
||||||
|
|
||||||
const AppEnvHint = () => {
|
const AppEnvHint = () => {
|
||||||
const dialog = useDisclosure();
|
const dialog = useDisclosure();
|
||||||
@ -120,8 +120,9 @@ const AppEnvHint = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ChakraProvider value={defaultSystem}>
|
<ChakraProvider value={systemTheme}>
|
||||||
<AppEnvHint />
|
<AppEnvHint />
|
||||||
<SpaApp />
|
<SpaApp />
|
||||||
<Toaster />
|
<Toaster />
|
||||||
|
@ -2,6 +2,7 @@ import { SyntheticEvent, useEffect, useRef, useState } from 'react';
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
|
Button,
|
||||||
Flex,
|
Flex,
|
||||||
IconButton,
|
IconButton,
|
||||||
Slider,
|
Slider,
|
||||||
@ -31,8 +32,9 @@ import { useSpecificArtists } from '@/service/Artist';
|
|||||||
import { useSpecificGender } from '@/service/Gender';
|
import { useSpecificGender } from '@/service/Gender';
|
||||||
import { useSpecificTrack } from '@/service/Track';
|
import { useSpecificTrack } from '@/service/Track';
|
||||||
import { DataUrlAccess } from '@/utils/data-url-access';
|
import { DataUrlAccess } from '@/utils/data-url-access';
|
||||||
import { useThemeMode } from '@/utils/theme-tools';
|
import { useColorModeValue } from '@/components/ui/color-mode';
|
||||||
import { isNullOrUndefined } from '@/utils/validator';
|
import { isNullOrUndefined } from '@/utils/validator';
|
||||||
|
import { Icon } from './Icon';
|
||||||
|
|
||||||
export enum PlayMode {
|
export enum PlayMode {
|
||||||
PLAY_ONE,
|
PLAY_ONE,
|
||||||
@ -62,7 +64,6 @@ const formatTime = (time) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const AudioPlayer = ({ }: AudioPlayerProps) => {
|
export const AudioPlayer = ({ }: AudioPlayerProps) => {
|
||||||
const { mode } = useThemeMode();
|
|
||||||
const { playTrackList, trackOffset, previous, next, first } =
|
const { playTrackList, trackOffset, previous, next, first } =
|
||||||
useActivePlaylistService();
|
useActivePlaylistService();
|
||||||
const audioRef = useRef<HTMLAudioElement>(null);
|
const audioRef = useRef<HTMLAudioElement>(null);
|
||||||
@ -85,7 +86,7 @@ export const AudioPlayer = ({ }: AudioPlayerProps) => {
|
|||||||
: ''
|
: ''
|
||||||
);
|
);
|
||||||
}, [dataTrack, setMediaSource]);
|
}, [dataTrack, setMediaSource]);
|
||||||
const backColor = mode('back.100', 'back.800');
|
const backColor = useColorModeValue('back.100', 'back.800');
|
||||||
const configButton = {
|
const configButton = {
|
||||||
borderRadius: 'full',
|
borderRadius: 'full',
|
||||||
backgroundColor: '#00000000',
|
backgroundColor: '#00000000',
|
||||||
@ -93,6 +94,9 @@ export const AudioPlayer = ({ }: AudioPlayerProps) => {
|
|||||||
boxShadow: 'outline-over',
|
boxShadow: 'outline-over',
|
||||||
bgColor: 'brand.500',
|
bgColor: 'brand.500',
|
||||||
},
|
},
|
||||||
|
width: "50px",
|
||||||
|
height: "50px",
|
||||||
|
padding: "5px",
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -285,11 +289,11 @@ export const AudioPlayer = ({ }: AudioPlayerProps) => {
|
|||||||
aria-label={'Play'}
|
aria-label={'Play'}
|
||||||
onClick={onPlay}
|
onClick={onPlay}
|
||||||
>
|
>
|
||||||
isPlaying ? (
|
{isPlaying ? (
|
||||||
<MdPause size="30px" />
|
<MdPause size="30px" />
|
||||||
) : (
|
) : (
|
||||||
<MdPlayArrow size="30px" />
|
<MdPlayArrow size="30px" />
|
||||||
)
|
)}
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<IconButton
|
<IconButton
|
||||||
{...configButton}
|
{...configButton}
|
||||||
@ -311,18 +315,18 @@ export const AudioPlayer = ({ }: AudioPlayerProps) => {
|
|||||||
{...configButton}
|
{...configButton}
|
||||||
aria-label={'jump 15sec in future'}
|
aria-label={'jump 15sec in future'}
|
||||||
onClick={onFastForward}
|
onClick={onFastForward}
|
||||||
><MdFastForward size="30px" /></IconButton>
|
><MdFastForward style={{ width: "100%", height: "100%" }} /></IconButton>
|
||||||
<IconButton
|
<IconButton
|
||||||
{...configButton}
|
{...configButton}
|
||||||
aria-label={'Next track'}
|
aria-label={'Next track'}
|
||||||
marginRight="auto"
|
marginRight="auto"
|
||||||
onClick={onNavigateNext}
|
onClick={onNavigateNext}
|
||||||
><MdNavigateNext size="30px" /></IconButton>
|
><MdNavigateNext style={{ width: "100%", height: "100%" }} /></IconButton>
|
||||||
<IconButton
|
<IconButton
|
||||||
{...configButton}
|
{...configButton}
|
||||||
aria-label={'continue to the end'}
|
aria-label={'continue to the end'}
|
||||||
onClick={onTypePlay}
|
onClick={onTypePlay}
|
||||||
>playModeIcon[playingMode]</IconButton>
|
>{playModeIcon[playingMode]}</IconButton>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
)}
|
)}
|
||||||
|
@ -5,7 +5,7 @@ import { useLocation } from 'react-router-dom';
|
|||||||
|
|
||||||
import { PageLayout } from '@/components/Layout/PageLayout';
|
import { PageLayout } from '@/components/Layout/PageLayout';
|
||||||
import { colors } from '@/theme/foundations/colors';
|
import { colors } from '@/theme/foundations/colors';
|
||||||
import { useThemeMode } from '@/utils/theme-tools';
|
import { useColorModeValue } from '@/components/ui/color-mode';
|
||||||
|
|
||||||
export type LayoutProps = FlexProps & {
|
export type LayoutProps = FlexProps & {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
@ -22,7 +22,6 @@ export const PageLayoutInfoCenter = ({
|
|||||||
window.scrollTo(0, 0);
|
window.scrollTo(0, 0);
|
||||||
}, [pathname]);
|
}, [pathname]);
|
||||||
|
|
||||||
const { mode } = useThemeMode();
|
|
||||||
return (
|
return (
|
||||||
<PageLayout>
|
<PageLayout>
|
||||||
<Flex
|
<Flex
|
||||||
@ -34,7 +33,7 @@ export const PageLayoutInfoCenter = ({
|
|||||||
borderRadius="8px"
|
borderRadius="8px"
|
||||||
padding="10px"
|
padding="10px"
|
||||||
boxShadow={'0px 0px 16px ' + colors.back[900]}
|
boxShadow={'0px 0px 16px ' + colors.back[900]}
|
||||||
backgroundColor={mode('#FFFFFF', '#000000')}
|
backgroundColor={useColorModeValue('#FFFFFF', '#000000')}
|
||||||
{...rest}
|
{...rest}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
@ -2,12 +2,6 @@ import { ReactNode } from 'react';
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Button,
|
|
||||||
Drawer,
|
|
||||||
DrawerBody,
|
|
||||||
DrawerContent,
|
|
||||||
DrawerHeader,
|
|
||||||
DrawerRoot,
|
|
||||||
Flex,
|
Flex,
|
||||||
HStack,
|
HStack,
|
||||||
IconButton,
|
IconButton,
|
||||||
@ -29,15 +23,22 @@ import { useServiceContext } from '@/service/ServiceContext';
|
|||||||
import { SessionState } from '@/service/SessionState';
|
import { SessionState } from '@/service/SessionState';
|
||||||
import { colors } from '@/theme/foundations/colors';
|
import { colors } from '@/theme/foundations/colors';
|
||||||
import { requestSignIn, requestSignOut, requestSignUp } from '@/utils/sso';
|
import { requestSignIn, requestSignOut, requestSignUp } from '@/utils/sso';
|
||||||
import { useThemeMode } from '@/utils/theme-tools';
|
|
||||||
import { useSessionService } from '@/service/session';
|
import { useSessionService } from '@/service/session';
|
||||||
import { MdHelp, MdHome, MdMore, MdOutlinePlaylistPlay, MdOutlineUploadFile, MdSupervisedUserCircle } from 'react-icons/md';
|
import { MdHelp, MdHome, MdMore, MdOutlinePlaylistPlay, MdOutlineUploadFile, MdSupervisedUserCircle } from 'react-icons/md';
|
||||||
import { MenuContent, MenuItem, MenuRoot, MenuTrigger } from '../ui/menu';
|
import { MenuContent, MenuItem, MenuRoot, MenuTrigger } from '@/components/ui/menu';
|
||||||
|
import { useColorMode, useColorModeValue } from '@/components/ui/color-mode';
|
||||||
|
import {
|
||||||
|
DrawerBody,
|
||||||
|
DrawerContent,
|
||||||
|
DrawerHeader,
|
||||||
|
DrawerRoot,
|
||||||
|
} from '@/components/ui/drawer';
|
||||||
|
import { Button } from '../ui/themed';
|
||||||
|
|
||||||
export const TOP_BAR_HEIGHT = '50px';
|
export const TOP_BAR_HEIGHT = '50px';
|
||||||
|
|
||||||
export const BUTTON_TOP_BAR_PROPERTY = {
|
export const BUTTON_TOP_BAR_PROPERTY = {
|
||||||
colorPalette: '@menu',
|
theme: '@menu',
|
||||||
height: TOP_BAR_HEIGHT,
|
height: TOP_BAR_HEIGHT,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -47,11 +48,11 @@ export type TopBarProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const TopBar = ({ title, children }: TopBarProps) => {
|
export const TopBar = ({ title, children }: TopBarProps) => {
|
||||||
const { mode, colorMode, toggleColorMode } = useThemeMode();
|
const { colorMode, toggleColorMode } = useColorMode();
|
||||||
const { clearToken } = useSessionService();
|
const { clearToken } = useSessionService();
|
||||||
|
|
||||||
const { session } = useServiceContext();
|
const { session } = useServiceContext();
|
||||||
const backColor = mode('back.100', 'back.800');
|
const backColor = useColorModeValue('back.100', 'back.800');
|
||||||
const drawerDisclose = useDisclosure();
|
const drawerDisclose = useDisclosure();
|
||||||
const onChangeTheme = () => {
|
const onChangeTheme = () => {
|
||||||
drawerDisclose.onOpen();
|
drawerDisclose.onOpen();
|
||||||
@ -120,7 +121,7 @@ export const TopBar = ({ title, children }: TopBarProps) => {
|
|||||||
<Flex right="0">
|
<Flex right="0">
|
||||||
{session?.state !== SessionState.CONNECTED && (
|
{session?.state !== SessionState.CONNECTED && (
|
||||||
<>
|
<>
|
||||||
<Button {...BUTTON_TOP_BAR_PROPERTY} onClick={onSignIn}>
|
<Button {...BUTTON_TOP_BAR_PROPERTY} theme="@primary" onClick={onSignIn}>
|
||||||
<LuLogIn />
|
<LuLogIn />
|
||||||
<Text paddingLeft="3px" fontWeight="bold">
|
<Text paddingLeft="3px" fontWeight="bold">
|
||||||
Sign-in
|
Sign-in
|
||||||
@ -149,7 +150,7 @@ export const TopBar = ({ title, children }: TopBarProps) => {
|
|||||||
><MdSupervisedUserCircle /></IconButton>
|
><MdSupervisedUserCircle /></IconButton>
|
||||||
</MenuTrigger>
|
</MenuTrigger>
|
||||||
<MenuContent>
|
<MenuContent>
|
||||||
<MenuItem value="user" valueText="user" _hover={{}} color={mode('brand.800', 'brand.200')}>
|
<MenuItem value="user" valueText="user" _hover={{}} color={useColorModeValue('brand.800', 'brand.200')}>
|
||||||
<MdSupervisedUserCircle />
|
<MdSupervisedUserCircle />
|
||||||
<Box flex="1">Sign in as {session?.login ?? 'Fail'}</Box>
|
<Box flex="1">Sign in as {session?.login ?? 'Fail'}</Box>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
@ -171,71 +172,69 @@ export const TopBar = ({ title, children }: TopBarProps) => {
|
|||||||
</MenuRoot>
|
</MenuRoot>
|
||||||
)}
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
<Drawer.Root
|
<DrawerRoot
|
||||||
placement="start"
|
placement="start"
|
||||||
onOpenChange={drawerDisclose.onClose}
|
onOpenChange={drawerDisclose.onClose}
|
||||||
open={drawerDisclose.open}
|
open={drawerDisclose.open}
|
||||||
data-testid="top-bar_drawer-root"
|
data-testid="top-bar_drawer-root"
|
||||||
>
|
>
|
||||||
<Drawer.Positioner>
|
<DrawerContent
|
||||||
<Drawer.Content
|
data-testid="top-bar_drawer-content">
|
||||||
data-testid="top-bar_drawer-content">
|
<DrawerHeader
|
||||||
<Drawer.Header
|
paddingY="auto"
|
||||||
paddingY="auto"
|
as="button"
|
||||||
as="button"
|
onClick={drawerDisclose.onClose}
|
||||||
onClick={drawerDisclose.onClose}
|
boxShadow={'0px 2px 4px ' + colors.back[900]}
|
||||||
boxShadow={'0px 2px 4px ' + colors.back[900]}
|
backgroundColor={backColor}
|
||||||
backgroundColor={backColor}
|
color={useColorModeValue('brand.900', 'brand.50')}
|
||||||
color={mode('brand.900', 'brand.50')}
|
textTransform="uppercase"
|
||||||
textTransform="uppercase"
|
>
|
||||||
|
<HStack height={TOP_BAR_HEIGHT}>
|
||||||
|
<LuArrowBigLeft />
|
||||||
|
<Text as="span" paddingLeft="3px">
|
||||||
|
Karusic
|
||||||
|
</Text>
|
||||||
|
</HStack>
|
||||||
|
</DrawerHeader>
|
||||||
|
<DrawerBody paddingX="0px">
|
||||||
|
<Button
|
||||||
|
background="#00000000"
|
||||||
|
borderRadius="0px"
|
||||||
|
onClick={onSelectHome}
|
||||||
|
width="full"
|
||||||
>
|
>
|
||||||
<HStack height={TOP_BAR_HEIGHT}>
|
<MdHome />
|
||||||
<LuArrowBigLeft />
|
<Text paddingLeft="3px" fontWeight="bold" marginRight="auto">
|
||||||
<Text as="span" paddingLeft="3px">
|
Home
|
||||||
Karusic
|
</Text>
|
||||||
</Text>
|
</Button>
|
||||||
</HStack>
|
<hr />
|
||||||
</Drawer.Header>
|
<Button
|
||||||
<Drawer.Body paddingX="0px">
|
background="#00000000"
|
||||||
<Button
|
borderRadius="0px"
|
||||||
background="#00000000"
|
onClick={onSelectOnAir}
|
||||||
borderRadius="0px"
|
width="full"
|
||||||
onClick={onSelectHome}
|
>
|
||||||
width="full"
|
<MdOutlinePlaylistPlay />
|
||||||
>
|
<Text paddingLeft="3px" fontWeight="bold" marginRight="auto">
|
||||||
<MdHome />
|
On air
|
||||||
<Text paddingLeft="3px" fontWeight="bold" marginRight="auto">
|
</Text>
|
||||||
Home
|
</Button>
|
||||||
</Text>
|
<hr />
|
||||||
</Button>
|
<Button
|
||||||
<hr />
|
background="#00000000"
|
||||||
<Button
|
borderRadius="0px"
|
||||||
background="#00000000"
|
onClick={onSelectAdd}
|
||||||
borderRadius="0px"
|
width="full"
|
||||||
onClick={onSelectOnAir}
|
>
|
||||||
width="full"
|
<MdOutlineUploadFile />
|
||||||
>
|
<Text paddingLeft="3px" fontWeight="bold" marginRight="auto">
|
||||||
<MdOutlinePlaylistPlay />
|
Add Media
|
||||||
<Text paddingLeft="3px" fontWeight="bold" marginRight="auto">
|
</Text>
|
||||||
On air
|
</Button>
|
||||||
</Text>
|
</DrawerBody>
|
||||||
</Button>
|
</DrawerContent>
|
||||||
<hr />
|
</DrawerRoot>
|
||||||
<Button
|
|
||||||
background="#00000000"
|
|
||||||
borderRadius="0px"
|
|
||||||
onClick={onSelectAdd}
|
|
||||||
width="full"
|
|
||||||
>
|
|
||||||
<MdOutlineUploadFile />
|
|
||||||
<Text paddingLeft="3px" fontWeight="bold" marginRight="auto">
|
|
||||||
Add Media
|
|
||||||
</Text>
|
|
||||||
</Button>
|
|
||||||
</Drawer.Body>
|
|
||||||
</Drawer.Content>
|
|
||||||
</Drawer.Positioner>
|
|
||||||
</Drawer.Root>
|
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -5,6 +5,8 @@ import {
|
|||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import { LuMenu } from 'react-icons/lu';
|
import { LuMenu } from 'react-icons/lu';
|
||||||
import { MenuContent, MenuItem, MenuRoot, MenuTrigger } from '../ui/menu';
|
import { MenuContent, MenuItem, MenuRoot, MenuTrigger } from '../ui/menu';
|
||||||
|
import { Button } from '../ui/themed';
|
||||||
|
import { customVariant } from '@/theme/recipes/button';
|
||||||
|
|
||||||
export type MenuElement = {
|
export type MenuElement = {
|
||||||
name: string;
|
name: string;
|
||||||
@ -15,6 +17,21 @@ export type ContextMenuProps = {
|
|||||||
elements?: MenuElement[];
|
elements?: MenuElement[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const theme = {
|
||||||
|
plop: {
|
||||||
|
bg: { _light: 'red', _dark: 'brand.300', _pink: "orange" },
|
||||||
|
_hover: { bg: { _light: 'green', _dark: 'brand.400', _pink: "black" } },
|
||||||
|
// bg: { _light: 'brand.600', _dark: 'brand.300' },
|
||||||
|
// _hover: { bg: { _light: 'brand.700', _dark: 'brand.400' } },
|
||||||
|
/*
|
||||||
|
bgActive: { _light: 'brand.600', _dark: 'brand.300' },
|
||||||
|
color: { _light: 'white', _dark: 'brand.900' },
|
||||||
|
colorHover: { _light: 'brand.800', _dark: 'brand.100' },
|
||||||
|
boxShadowHover: 'outline-over'
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const ContextMenu = ({ elements }: ContextMenuProps) => {
|
export const ContextMenu = ({ elements }: ContextMenuProps) => {
|
||||||
if (!elements) {
|
if (!elements) {
|
||||||
return <></>;
|
return <></>;
|
||||||
@ -25,9 +42,9 @@ export const ContextMenu = ({ elements }: ContextMenuProps) => {
|
|||||||
<MenuTrigger asChild
|
<MenuTrigger asChild
|
||||||
data-testid="context-menu_trigger">
|
data-testid="context-menu_trigger">
|
||||||
{/* This is very stupid, we need to set as span to prevent a button in button... WTF */}
|
{/* This is very stupid, we need to set as span to prevent a button in button... WTF */}
|
||||||
<IconButton as='span'>
|
<Button {...theme.plop} /*theme="@primary"*/>
|
||||||
<LuMenu />
|
<LuMenu />
|
||||||
</IconButton>
|
</Button>
|
||||||
</MenuTrigger>
|
</MenuTrigger>
|
||||||
<MenuContent
|
<MenuContent
|
||||||
data-testid="context-menu_content">
|
data-testid="context-menu_content">
|
||||||
@ -38,6 +55,6 @@ export const ContextMenu = ({ elements }: ContextMenuProps) => {
|
|||||||
</MenuItem>
|
</MenuItem>
|
||||||
))}
|
))}
|
||||||
</MenuContent>
|
</MenuContent>
|
||||||
</MenuRoot>
|
</MenuRoot >
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,17 +1,9 @@
|
|||||||
import { useRef, useState } from 'react';
|
import { useRef, useState } from 'react';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
|
||||||
Flex,
|
Flex,
|
||||||
Dialog,
|
|
||||||
DialogBody,
|
|
||||||
DialogContent,
|
|
||||||
DialogFooter,
|
|
||||||
DialogHeader,
|
|
||||||
Text,
|
Text,
|
||||||
useDisclosure,
|
useDisclosure,
|
||||||
DialogRoot,
|
|
||||||
DialogCloseTrigger,
|
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import {
|
import {
|
||||||
MdAdminPanelSettings,
|
MdAdminPanelSettings,
|
||||||
@ -32,6 +24,8 @@ import { useAlbumService, useSpecificAlbum } from '@/service/Album';
|
|||||||
import { useServiceContext } from '@/service/ServiceContext';
|
import { useServiceContext } from '@/service/ServiceContext';
|
||||||
import { useCountTracksWithAlbumId } from '@/service/Track';
|
import { useCountTracksWithAlbumId } from '@/service/Track';
|
||||||
import { isNullOrUndefined } from '@/utils/validator';
|
import { isNullOrUndefined } from '@/utils/validator';
|
||||||
|
import { DialogBody, DialogContent, DialogFooter, DialogHeader, DialogRoot } from '@/components/ui/dialog';
|
||||||
|
import { Button } from '../ui/themed';
|
||||||
|
|
||||||
export type AlbumEditPopUpProps = {};
|
export type AlbumEditPopUpProps = {};
|
||||||
|
|
||||||
@ -174,7 +168,7 @@ export const AlbumEditPopUp = ({ }: AlbumEditPopUpProps) => {
|
|||||||
<Button
|
<Button
|
||||||
onClick={disclosure.onOpen}
|
onClick={disclosure.onOpen}
|
||||||
marginRight="auto"
|
marginRight="auto"
|
||||||
colorPalette="red"
|
theme="@danger"
|
||||||
disabled={countTracksOfAnAlbum !== 0}
|
disabled={countTracksOfAnAlbum !== 0}
|
||||||
>
|
>
|
||||||
<MdDeleteForever /> Remove Media
|
<MdDeleteForever /> Remove Media
|
||||||
|
@ -1,17 +1,11 @@
|
|||||||
import { useRef, useState } from 'react';
|
import { useRef, useState } from 'react';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
|
||||||
Flex,
|
Flex,
|
||||||
Dialog,
|
|
||||||
DialogBody,
|
|
||||||
DialogContent,
|
|
||||||
DialogFooter,
|
|
||||||
DialogHeader,
|
|
||||||
Text,
|
Text,
|
||||||
useDisclosure,
|
useDisclosure,
|
||||||
DialogRoot,
|
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
|
import { DialogBody, DialogContent, DialogFooter, DialogHeader, DialogRoot } from '@/components/ui/dialog';
|
||||||
import {
|
import {
|
||||||
MdAdminPanelSettings,
|
MdAdminPanelSettings,
|
||||||
MdDeleteForever,
|
MdDeleteForever,
|
||||||
@ -31,6 +25,7 @@ import { useArtistService, useSpecificArtist } from '@/service/Artist';
|
|||||||
import { useServiceContext } from '@/service/ServiceContext';
|
import { useServiceContext } from '@/service/ServiceContext';
|
||||||
import { useCountTracksOfAnArtist } from '@/service/Track';
|
import { useCountTracksOfAnArtist } from '@/service/Track';
|
||||||
import { isNullOrUndefined } from '@/utils/validator';
|
import { isNullOrUndefined } from '@/utils/validator';
|
||||||
|
import { Button } from '../ui/themed';
|
||||||
|
|
||||||
export type ArtistEditPopUpProps = {};
|
export type ArtistEditPopUpProps = {};
|
||||||
|
|
||||||
@ -171,7 +166,7 @@ export const ArtistEditPopUp = ({ }: ArtistEditPopUpProps) => {
|
|||||||
<Button
|
<Button
|
||||||
onClick={disclosure.onOpen}
|
onClick={disclosure.onOpen}
|
||||||
marginRight="auto"
|
marginRight="auto"
|
||||||
colorPalette="red"
|
theme="@danger"
|
||||||
disabled={countTracksOnAnArtist !== 0}
|
disabled={countTracksOnAnArtist !== 0}
|
||||||
>
|
>
|
||||||
<MdDeleteForever /> Remove Media
|
<MdDeleteForever /> Remove Media
|
||||||
|
@ -2,14 +2,10 @@ import { useRef } from 'react';
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
DialogBody,
|
|
||||||
DialogContent,
|
|
||||||
DialogFooter,
|
|
||||||
DialogHeader,
|
|
||||||
DialogRoot,
|
|
||||||
UseDisclosureReturn,
|
UseDisclosureReturn,
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
|
|
||||||
|
import { DialogBody, DialogContent, DialogFooter, DialogHeader, DialogRoot } from '@/components/ui/dialog';
|
||||||
export type ConfirmPopUpProps = {
|
export type ConfirmPopUpProps = {
|
||||||
title: string;
|
title: string;
|
||||||
body: string;
|
body: string;
|
||||||
|
@ -1,16 +1,9 @@
|
|||||||
import { useRef, useState } from 'react';
|
import { useRef, useState } from 'react';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
|
||||||
Flex,
|
Flex,
|
||||||
Dialog,
|
|
||||||
DialogBody,
|
|
||||||
DialogContent,
|
|
||||||
DialogFooter,
|
|
||||||
DialogHeader,
|
|
||||||
Text,
|
Text,
|
||||||
useDisclosure,
|
useDisclosure,
|
||||||
DialogRoot,
|
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import {
|
import {
|
||||||
MdAdminPanelSettings,
|
MdAdminPanelSettings,
|
||||||
@ -18,6 +11,8 @@ import {
|
|||||||
MdEdit,
|
MdEdit,
|
||||||
MdWarning,
|
MdWarning,
|
||||||
} from 'react-icons/md';
|
} from 'react-icons/md';
|
||||||
|
|
||||||
|
import { DialogBody, DialogContent, DialogFooter, DialogHeader, DialogRoot } from '@/components/ui/dialog';
|
||||||
import { useNavigate, useParams } from 'react-router-dom';
|
import { useNavigate, useParams } from 'react-router-dom';
|
||||||
|
|
||||||
import { Gender, GenderResource } from '@/back-api';
|
import { Gender, GenderResource } from '@/back-api';
|
||||||
@ -31,6 +26,7 @@ import { useGenderService, useSpecificGender } from '@/service/Gender';
|
|||||||
import { useServiceContext } from '@/service/ServiceContext';
|
import { useServiceContext } from '@/service/ServiceContext';
|
||||||
import { useCountTracksOfAGender } from '@/service/Track';
|
import { useCountTracksOfAGender } from '@/service/Track';
|
||||||
import { isNullOrUndefined } from '@/utils/validator';
|
import { isNullOrUndefined } from '@/utils/validator';
|
||||||
|
import { Button } from '../ui/themed';
|
||||||
|
|
||||||
export type GenderEditPopUpProps = {};
|
export type GenderEditPopUpProps = {};
|
||||||
|
|
||||||
@ -170,7 +166,7 @@ export const GenderEditPopUp = ({ }: GenderEditPopUpProps) => {
|
|||||||
<Button
|
<Button
|
||||||
onClick={disclosure.onOpen}
|
onClick={disclosure.onOpen}
|
||||||
marginRight="auto"
|
marginRight="auto"
|
||||||
colorPalette="red"
|
theme="@danger"
|
||||||
disabled={countTracksOnAGender !== 0}
|
disabled={countTracksOnAGender !== 0}
|
||||||
>
|
>
|
||||||
<MdDeleteForever /> Remove gender
|
<MdDeleteForever /> Remove gender
|
||||||
|
@ -1,37 +1,13 @@
|
|||||||
import { ReactElement, useRef, useState } from 'react';
|
import { useRef } from 'react';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
|
||||||
Flex,
|
Flex,
|
||||||
Dialog,
|
|
||||||
DialogBody,
|
|
||||||
DialogContent,
|
|
||||||
DialogFooter,
|
|
||||||
DialogHeader,
|
|
||||||
Progress,
|
Progress,
|
||||||
Text,
|
Text,
|
||||||
useDisclosure,
|
|
||||||
DialogRoot,
|
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import {
|
|
||||||
MdAdminPanelSettings,
|
|
||||||
MdDeleteForever,
|
|
||||||
MdEdit,
|
|
||||||
MdWarning,
|
|
||||||
} from 'react-icons/md';
|
|
||||||
import { useNavigate, useParams } from 'react-router-dom';
|
|
||||||
|
|
||||||
import { Artist, ArtistResource } from '@/back-api';
|
import { DialogBody, DialogContent, DialogFooter, DialogHeader, DialogRoot } from '@/components/ui/dialog';
|
||||||
import { FormCovers } from '@/components/form/FormCovers';
|
import { Button } from '../ui/themed';
|
||||||
import { FormGroup } from '@/components/form/FormGroup';
|
|
||||||
import { FormInput } from '@/components/form/FormInput';
|
|
||||||
import { FormTextarea } from '@/components/form/FormTextarea';
|
|
||||||
import { useFormidable } from '@/components/form/Formidable';
|
|
||||||
import { ConfirmPopUp } from '@/components/popup/ConfirmPopUp';
|
|
||||||
import { useArtistService, useSpecificArtist } from '@/service/Artist';
|
|
||||||
import { useServiceContext } from '@/service/ServiceContext';
|
|
||||||
import { useCountTracksOfAnArtist } from '@/service/Track';
|
|
||||||
import { isNullOrUndefined } from '@/utils/validator';
|
|
||||||
|
|
||||||
export type PopUpUploadProgressProps = {
|
export type PopUpUploadProgressProps = {
|
||||||
title: string;
|
title: string;
|
||||||
@ -112,7 +88,7 @@ export const PopUpUploadProgress = ({
|
|||||||
</DialogBody>
|
</DialogBody>
|
||||||
<DialogFooter>
|
<DialogFooter>
|
||||||
{isFinished ? (
|
{isFinished ? (
|
||||||
<Button onClick={onClose} colorPalette="@success">
|
<Button onClick={onClose} theme="@success">
|
||||||
Ok
|
Ok
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
|
@ -1,15 +1,12 @@
|
|||||||
import { useRef, useState } from 'react';
|
import { useRef, useState } from 'react';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
|
||||||
DialogBody,
|
|
||||||
DialogContent,
|
|
||||||
DialogFooter,
|
|
||||||
DialogHeader,
|
|
||||||
DialogRoot,
|
|
||||||
Text,
|
Text,
|
||||||
useDisclosure,
|
useDisclosure,
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
|
|
||||||
|
import { DialogBody, DialogContent, DialogFooter, DialogHeader, DialogRoot } from '@/components/ui/dialog';
|
||||||
|
|
||||||
import { MdAdminPanelSettings, MdDeleteForever, MdEdit } from 'react-icons/md';
|
import { MdAdminPanelSettings, MdDeleteForever, MdEdit } from 'react-icons/md';
|
||||||
import { useNavigate, useParams } from 'react-router-dom';
|
import { useNavigate, useParams } from 'react-router-dom';
|
||||||
|
|
||||||
@ -28,6 +25,7 @@ import { useOrderedGenders } from '@/service/Gender';
|
|||||||
import { useServiceContext } from '@/service/ServiceContext';
|
import { useServiceContext } from '@/service/ServiceContext';
|
||||||
import { useSpecificTrack, useTrackService } from '@/service/Track';
|
import { useSpecificTrack, useTrackService } from '@/service/Track';
|
||||||
import { isNullOrUndefined } from '@/utils/validator';
|
import { isNullOrUndefined } from '@/utils/validator';
|
||||||
|
import { Button } from '../ui/themed';
|
||||||
|
|
||||||
export type TrackEditPopUpProps = {};
|
export type TrackEditPopUpProps = {};
|
||||||
|
|
||||||
@ -115,7 +113,7 @@ export const TrackEditPopUp = ({ }: TrackEditPopUpProps) => {
|
|||||||
<Button
|
<Button
|
||||||
onClick={disclosure.onOpen}
|
onClick={disclosure.onOpen}
|
||||||
marginRight="auto"
|
marginRight="auto"
|
||||||
colorPalette="@danger"
|
theme="@danger"
|
||||||
>
|
>
|
||||||
<MdDeleteForever /> Remove Media
|
<MdDeleteForever /> Remove Media
|
||||||
</Button>
|
</Button>
|
||||||
|
17
front/src/components/ui/close-button.tsx
Normal file
17
front/src/components/ui/close-button.tsx
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import type { ButtonProps } from "@chakra-ui/react"
|
||||||
|
import { IconButton as ChakraIconButton } from "@chakra-ui/react"
|
||||||
|
import * as React from "react"
|
||||||
|
import { LuX } from "react-icons/lu"
|
||||||
|
|
||||||
|
export type CloseButtonProps = ButtonProps
|
||||||
|
|
||||||
|
export const CloseButton = React.forwardRef<
|
||||||
|
HTMLButtonElement,
|
||||||
|
CloseButtonProps
|
||||||
|
>(function CloseButton(props, ref) {
|
||||||
|
return (
|
||||||
|
<ChakraIconButton variant="ghost" aria-label="Close" ref={ref} {...props}>
|
||||||
|
{props.children ?? <LuX />}
|
||||||
|
</ChakraIconButton>
|
||||||
|
)
|
||||||
|
})
|
29
front/src/components/ui/color-mode.tsx
Normal file
29
front/src/components/ui/color-mode.tsx
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import { ThemeProvider, useTheme, ThemeProviderProps } from "next-themes"
|
||||||
|
|
||||||
|
export interface ColorModeProviderProps extends ThemeProviderProps { }
|
||||||
|
|
||||||
|
export function ColorModeProvider(props: ColorModeProviderProps) {
|
||||||
|
return (
|
||||||
|
<ThemeProvider attribute="class" themes={['pink', 'dark', 'light']} disableTransitionOnChange {...props} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useColorMode() {
|
||||||
|
const { resolvedTheme, setTheme } = useTheme()
|
||||||
|
const toggleColorMode = () => {
|
||||||
|
console.log(`plop: ${resolvedTheme}`);
|
||||||
|
setTheme(resolvedTheme === "light" ? "pink" : resolvedTheme === "pink" ? "dark" : "light")
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
colorMode: resolvedTheme,
|
||||||
|
setColorMode: setTheme,
|
||||||
|
toggleColorMode,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useColorModeValue<T>(light: T, dark: T) {
|
||||||
|
const { colorMode } = useColorMode()
|
||||||
|
return colorMode === "light" ? light : dark
|
||||||
|
}
|
62
front/src/components/ui/dialog.tsx
Normal file
62
front/src/components/ui/dialog.tsx
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
import { Dialog as ChakraDialog, Portal } from "@chakra-ui/react"
|
||||||
|
import { CloseButton } from "./close-button"
|
||||||
|
import * as React from "react"
|
||||||
|
|
||||||
|
interface DialogContentProps extends ChakraDialog.ContentProps {
|
||||||
|
portalled?: boolean
|
||||||
|
portalRef?: React.RefObject<HTMLElement>
|
||||||
|
backdrop?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DialogContent = React.forwardRef<
|
||||||
|
HTMLDivElement,
|
||||||
|
DialogContentProps
|
||||||
|
>(function DialogContent(props, ref) {
|
||||||
|
const {
|
||||||
|
children,
|
||||||
|
portalled = true,
|
||||||
|
portalRef,
|
||||||
|
backdrop = true,
|
||||||
|
...rest
|
||||||
|
} = props
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Portal disabled={!portalled} container={portalRef}>
|
||||||
|
{backdrop && <ChakraDialog.Backdrop />}
|
||||||
|
<ChakraDialog.Positioner>
|
||||||
|
<ChakraDialog.Content ref={ref} {...rest} asChild={false}>
|
||||||
|
{children}
|
||||||
|
</ChakraDialog.Content>
|
||||||
|
</ChakraDialog.Positioner>
|
||||||
|
</Portal>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
export const DialogCloseTrigger = React.forwardRef<
|
||||||
|
HTMLButtonElement,
|
||||||
|
ChakraDialog.CloseTriggerProps
|
||||||
|
>(function DialogCloseTrigger(props, ref) {
|
||||||
|
return (
|
||||||
|
<ChakraDialog.CloseTrigger
|
||||||
|
position="absolute"
|
||||||
|
top="2"
|
||||||
|
insetEnd="2"
|
||||||
|
{...props}
|
||||||
|
asChild
|
||||||
|
>
|
||||||
|
<CloseButton size="sm" ref={ref}>
|
||||||
|
{props.children}
|
||||||
|
</CloseButton>
|
||||||
|
</ChakraDialog.CloseTrigger>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
export const DialogRoot = ChakraDialog.Root
|
||||||
|
export const DialogFooter = ChakraDialog.Footer
|
||||||
|
export const DialogHeader = ChakraDialog.Header
|
||||||
|
export const DialogBody = ChakraDialog.Body
|
||||||
|
export const DialogBackdrop = ChakraDialog.Backdrop
|
||||||
|
export const DialogTitle = ChakraDialog.Title
|
||||||
|
export const DialogDescription = ChakraDialog.Description
|
||||||
|
export const DialogTrigger = ChakraDialog.Trigger
|
||||||
|
export const DialogActionTrigger = ChakraDialog.ActionTrigger
|
52
front/src/components/ui/drawer.tsx
Normal file
52
front/src/components/ui/drawer.tsx
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import { Drawer as ChakraDrawer, Portal } from "@chakra-ui/react"
|
||||||
|
import { CloseButton } from "./close-button"
|
||||||
|
import * as React from "react"
|
||||||
|
|
||||||
|
interface DrawerContentProps extends ChakraDrawer.ContentProps {
|
||||||
|
portalled?: boolean
|
||||||
|
portalRef?: React.RefObject<HTMLElement>
|
||||||
|
offset?: ChakraDrawer.ContentProps["padding"]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DrawerContent = React.forwardRef<
|
||||||
|
HTMLDivElement,
|
||||||
|
DrawerContentProps
|
||||||
|
>(function DrawerContent(props, ref) {
|
||||||
|
const { children, portalled = true, portalRef, offset, ...rest } = props
|
||||||
|
return (
|
||||||
|
<Portal disabled={!portalled} container={portalRef}>
|
||||||
|
<ChakraDrawer.Positioner padding={offset}>
|
||||||
|
<ChakraDrawer.Content ref={ref} {...rest} asChild={false}>
|
||||||
|
{children}
|
||||||
|
</ChakraDrawer.Content>
|
||||||
|
</ChakraDrawer.Positioner>
|
||||||
|
</Portal>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
export const DrawerCloseTrigger = React.forwardRef<
|
||||||
|
HTMLButtonElement,
|
||||||
|
ChakraDrawer.CloseTriggerProps
|
||||||
|
>(function DrawerCloseTrigger(props, ref) {
|
||||||
|
return (
|
||||||
|
<ChakraDrawer.CloseTrigger
|
||||||
|
position="absolute"
|
||||||
|
top="2"
|
||||||
|
insetEnd="2"
|
||||||
|
{...props}
|
||||||
|
asChild
|
||||||
|
>
|
||||||
|
<CloseButton size="sm" ref={ref} />
|
||||||
|
</ChakraDrawer.CloseTrigger>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
export const DrawerTrigger = ChakraDrawer.Trigger
|
||||||
|
export const DrawerRoot = ChakraDrawer.Root
|
||||||
|
export const DrawerFooter = ChakraDrawer.Footer
|
||||||
|
export const DrawerHeader = ChakraDrawer.Header
|
||||||
|
export const DrawerBody = ChakraDrawer.Body
|
||||||
|
export const DrawerBackdrop = ChakraDrawer.Backdrop
|
||||||
|
export const DrawerDescription = ChakraDrawer.Description
|
||||||
|
export const DrawerTitle = ChakraDrawer.Title
|
||||||
|
export const DrawerActionTrigger = ChakraDrawer.ActionTrigger
|
0
front/src/components/ui/index.ts
Normal file
0
front/src/components/ui/index.ts
Normal file
7
front/src/components/ui/themed.tsx
Normal file
7
front/src/components/ui/themed.tsx
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
import buttonRecipe from '@/theme/recipes/button';
|
||||||
|
import { chakra } from '@chakra-ui/react';
|
||||||
|
|
||||||
|
// we export the element with the application recipe theme.
|
||||||
|
// cf doc: https://www.chakra-ui.com/docs/theming/recipes
|
||||||
|
export const Button = chakra("button", buttonRecipe)
|
@ -1,12 +1,10 @@
|
|||||||
import React, { FC } from 'react';
|
import React, { FC } from 'react';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Alert,
|
|
||||||
AlertDescription,
|
AlertDescription,
|
||||||
AlertRoot,
|
AlertRoot,
|
||||||
AlertTitle,
|
AlertTitle,
|
||||||
Box,
|
Box,
|
||||||
Button,
|
|
||||||
Collapsible,
|
Collapsible,
|
||||||
useDisclosure,
|
useDisclosure,
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
@ -14,7 +12,8 @@ import {
|
|||||||
FallbackProps,
|
FallbackProps,
|
||||||
ErrorBoundary as ReactErrorBoundary,
|
ErrorBoundary as ReactErrorBoundary,
|
||||||
} from 'react-error-boundary';
|
} from 'react-error-boundary';
|
||||||
import { LuChevronDown, LuChevronUp } from 'react-icons/lu';
|
import { Button } from '@/components/ui/themed';
|
||||||
|
import { LuChevronUp, LuChevronDown } from 'react-icons/lu';
|
||||||
|
|
||||||
const ErrorFallback = ({ error }: FallbackProps) => {
|
const ErrorFallback = ({ error }: FallbackProps) => {
|
||||||
const { open, onToggle } = useDisclosure();
|
const { open, onToggle } = useDisclosure();
|
||||||
@ -26,13 +25,12 @@ const ErrorFallback = ({ error }: FallbackProps) => {
|
|||||||
<AlertTitle>An unexpected error has occurred.</AlertTitle>
|
<AlertTitle>An unexpected error has occurred.</AlertTitle>
|
||||||
<AlertDescription display="block" lineHeight="1.4">
|
<AlertDescription display="block" lineHeight="1.4">
|
||||||
<Button
|
<Button
|
||||||
colorPalette="link"
|
theme="@secondary"
|
||||||
color="red.800"
|
color="red.800"
|
||||||
size="sm"
|
//size="sm"
|
||||||
//rightIcon={open ? <LuChevronUp /> : <LuChevronDown />}
|
|
||||||
onClick={onToggle}
|
onClick={onToggle}
|
||||||
>
|
>
|
||||||
Show details
|
Show details {open ? <LuChevronUp /> : <LuChevronDown />}
|
||||||
</Button>
|
</Button>
|
||||||
<Collapsible.Root open={open}>
|
<Collapsible.Root open={open}>
|
||||||
<Collapsible.Content>
|
<Collapsible.Content>
|
||||||
|
@ -3,6 +3,7 @@ import { StrictMode } from 'react';
|
|||||||
import ReactDOM from 'react-dom/client';
|
import ReactDOM from 'react-dom/client';
|
||||||
|
|
||||||
import App from '@/App';
|
import App from '@/App';
|
||||||
|
import { ColorModeProvider } from './components/ui/color-mode';
|
||||||
|
|
||||||
// Render the app
|
// Render the app
|
||||||
const rootElement = document.getElementById('root');
|
const rootElement = document.getElementById('root');
|
||||||
@ -10,7 +11,9 @@ if (rootElement && !rootElement.innerHTML) {
|
|||||||
const root = ReactDOM.createRoot(rootElement);
|
const root = ReactDOM.createRoot(rootElement);
|
||||||
root.render(
|
root.render(
|
||||||
<StrictMode>
|
<StrictMode>
|
||||||
<App />
|
<ColorModeProvider>
|
||||||
|
<App />
|
||||||
|
</ColorModeProvider>
|
||||||
</StrictMode>
|
</StrictMode>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -15,13 +15,12 @@ import { DisplayTrackFull } from '@/components/track/DisplayTrackFull';
|
|||||||
import { useActivePlaylistService } from '@/service/ActivePlaylist';
|
import { useActivePlaylistService } from '@/service/ActivePlaylist';
|
||||||
import { useSpecificAlbum } from '@/service/Album';
|
import { useSpecificAlbum } from '@/service/Album';
|
||||||
import { useTracksOfAnAlbum } from '@/service/Track';
|
import { useTracksOfAnAlbum } from '@/service/Track';
|
||||||
import { useThemeMode } from '@/utils/theme-tools';
|
import { useColorModeValue } from '@/components/ui/color-mode';
|
||||||
import { BASE_WRAP_SPACING } from '@/constants/genericSpacing';
|
import { BASE_WRAP_SPACING } from '@/constants/genericSpacing';
|
||||||
|
|
||||||
export const AlbumDetailPage = () => {
|
export const AlbumDetailPage = () => {
|
||||||
const { albumId } = useParams();
|
const { albumId } = useParams();
|
||||||
const albumIdInt = albumId ? parseInt(albumId, 10) : undefined;
|
const albumIdInt = albumId ? parseInt(albumId, 10) : undefined;
|
||||||
const { mode } = useThemeMode();
|
|
||||||
const { playInList } = useActivePlaylistService();
|
const { playInList } = useActivePlaylistService();
|
||||||
const { dataAlbum } = useSpecificAlbum(albumIdInt);
|
const { dataAlbum } = useSpecificAlbum(albumIdInt);
|
||||||
const { tracksOnAnAlbum } = useTracksOfAnAlbum(albumIdInt);
|
const { tracksOnAnAlbum } = useTracksOfAnAlbum(albumIdInt);
|
||||||
@ -107,13 +106,13 @@ export const AlbumDetailPage = () => {
|
|||||||
//height="60px"
|
//height="60px"
|
||||||
border="1px"
|
border="1px"
|
||||||
borderColor="brand.900"
|
borderColor="brand.900"
|
||||||
backgroundColor={mode('#FFFFFF88', '#00000088')}
|
backgroundColor={useColorModeValue('#FFFFFF88', '#00000088')}
|
||||||
key={data.id}
|
key={data.id}
|
||||||
padding="5px"
|
padding="5px"
|
||||||
as="button"
|
as="button"
|
||||||
_hover={{
|
_hover={{
|
||||||
boxShadow: 'outline-over',
|
boxShadow: 'outline-over',
|
||||||
bgColor: mode('#FFFFFFF7', '#000000F7'),
|
bgColor: useColorModeValue('#FFFFFFF7', '#000000F7'),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<DisplayTrackFull
|
<DisplayTrackFull
|
||||||
|
@ -9,14 +9,13 @@ import { SearchInput } from '@/components/SearchInput';
|
|||||||
import { TopBar } from '@/components/TopBar/TopBar';
|
import { TopBar } from '@/components/TopBar/TopBar';
|
||||||
import { DisplayAlbum } from '@/components/album/DisplayAlbum';
|
import { DisplayAlbum } from '@/components/album/DisplayAlbum';
|
||||||
import { useOrderedAlbums } from '@/service/Album';
|
import { useOrderedAlbums } from '@/service/Album';
|
||||||
import { useThemeMode } from '@/utils/theme-tools';
|
import { useColorModeValue } from '@/components/ui/color-mode';
|
||||||
import { BASE_WRAP_SPACING, BASE_WRAP_WIDTH, BASE_WRAP_HEIGHT } from '@/constants/genericSpacing';
|
import { BASE_WRAP_SPACING, BASE_WRAP_WIDTH, BASE_WRAP_HEIGHT } from '@/constants/genericSpacing';
|
||||||
import { Flex, HStack } from '@chakra-ui/react';
|
import { Flex, HStack } from '@chakra-ui/react';
|
||||||
|
|
||||||
export const AlbumsPage = () => {
|
export const AlbumsPage = () => {
|
||||||
const [filterTitle, setFilterTitle] = useState<string | undefined>(undefined);
|
const [filterTitle, setFilterTitle] = useState<string | undefined>(undefined);
|
||||||
const { isLoading, dataAlbums } = useOrderedAlbums(filterTitle);
|
const { isLoading, dataAlbums } = useOrderedAlbums(filterTitle);
|
||||||
const { mode } = useThemeMode();
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const onSelectItem = (albumId: number) => {
|
const onSelectItem = (albumId: number) => {
|
||||||
navigate(`/album/${albumId}`);
|
navigate(`/album/${albumId}`);
|
||||||
@ -44,13 +43,13 @@ export const AlbumsPage = () => {
|
|||||||
height={BASE_WRAP_HEIGHT}
|
height={BASE_WRAP_HEIGHT}
|
||||||
border="1px"
|
border="1px"
|
||||||
borderColor="brand.900"
|
borderColor="brand.900"
|
||||||
backgroundColor={mode('#FFFFFF88', '#00000088')}
|
backgroundColor={useColorModeValue('#FFFFFF88', '#00000088')}
|
||||||
key={data.id}
|
key={data.id}
|
||||||
padding="5px"
|
padding="5px"
|
||||||
as="button"
|
as="button"
|
||||||
_hover={{
|
_hover={{
|
||||||
boxShadow: 'outline-over',
|
boxShadow: 'outline-over',
|
||||||
bgColor: mode('#FFFFFFF7', '#000000F7'),
|
bgColor: useColorModeValue('#FFFFFFF7', '#000000F7'),
|
||||||
}}
|
}}
|
||||||
onClick={() => onSelectItem(data.id)}
|
onClick={() => onSelectItem(data.id)}
|
||||||
>
|
>
|
||||||
|
@ -15,13 +15,12 @@ import { useActivePlaylistService } from '@/service/ActivePlaylist';
|
|||||||
import { useSpecificAlbum } from '@/service/Album';
|
import { useSpecificAlbum } from '@/service/Album';
|
||||||
import { useSpecificArtist } from '@/service/Artist';
|
import { useSpecificArtist } from '@/service/Artist';
|
||||||
import { useTracksOfAnAlbum } from '@/service/Track';
|
import { useTracksOfAnAlbum } from '@/service/Track';
|
||||||
import { useThemeMode } from '@/utils/theme-tools';
|
import { useColorModeValue } from '@/components/ui/color-mode';
|
||||||
|
|
||||||
export const ArtistAlbumDetailPage = () => {
|
export const ArtistAlbumDetailPage = () => {
|
||||||
const { artistId, albumId } = useParams();
|
const { artistId, albumId } = useParams();
|
||||||
const artistIdInt = artistId ? parseInt(artistId, 10) : undefined;
|
const artistIdInt = artistId ? parseInt(artistId, 10) : undefined;
|
||||||
const albumIdInt = albumId ? parseInt(albumId, 10) : undefined;
|
const albumIdInt = albumId ? parseInt(albumId, 10) : undefined;
|
||||||
const { mode } = useThemeMode();
|
|
||||||
const { playInList } = useActivePlaylistService();
|
const { playInList } = useActivePlaylistService();
|
||||||
const { dataArtist } = useSpecificArtist(artistIdInt);
|
const { dataArtist } = useSpecificArtist(artistIdInt);
|
||||||
const { dataAlbum } = useSpecificAlbum(albumIdInt);
|
const { dataAlbum } = useSpecificAlbum(albumIdInt);
|
||||||
@ -124,13 +123,13 @@ export const ArtistAlbumDetailPage = () => {
|
|||||||
height="60px"
|
height="60px"
|
||||||
border="1px"
|
border="1px"
|
||||||
borderColor="brand.900"
|
borderColor="brand.900"
|
||||||
backgroundColor={mode('#FFFFFF88', '#00000088')}
|
backgroundColor={useColorModeValue('#FFFFFF88', '#00000088')}
|
||||||
key={data.id}
|
key={data.id}
|
||||||
padding="5px"
|
padding="5px"
|
||||||
as="button"
|
as="button"
|
||||||
_hover={{
|
_hover={{
|
||||||
boxShadow: 'outline-over',
|
boxShadow: 'outline-over',
|
||||||
bgColor: mode('#FFFFFFF7', '#000000F7'),
|
bgColor: useColorModeValue('#FFFFFFF7', '#000000F7'),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<DisplayTrack
|
<DisplayTrack
|
||||||
|
@ -12,13 +12,12 @@ import { DisplayAlbumId } from '@/components/album/DisplayAlbumId';
|
|||||||
import { ArtistEditPopUp } from '@/components/popup/ArtistEditPopUp';
|
import { ArtistEditPopUp } from '@/components/popup/ArtistEditPopUp';
|
||||||
import { useSpecificArtist } from '@/service/Artist';
|
import { useSpecificArtist } from '@/service/Artist';
|
||||||
import { useAlbumIdsOfAnArtist } from '@/service/Track';
|
import { useAlbumIdsOfAnArtist } from '@/service/Track';
|
||||||
import { useThemeMode } from '@/utils/theme-tools';
|
import { useColorModeValue } from '@/components/ui/color-mode';
|
||||||
import { BASE_WRAP_HEIGHT, BASE_WRAP_SPACING, BASE_WRAP_WIDTH } from '@/constants/genericSpacing';
|
import { BASE_WRAP_HEIGHT, BASE_WRAP_SPACING, BASE_WRAP_WIDTH } from '@/constants/genericSpacing';
|
||||||
|
|
||||||
export const ArtistDetailPage = () => {
|
export const ArtistDetailPage = () => {
|
||||||
const { artistId } = useParams();
|
const { artistId } = useParams();
|
||||||
const artistIdInt = artistId ? parseInt(artistId, 10) : undefined;
|
const artistIdInt = artistId ? parseInt(artistId, 10) : undefined;
|
||||||
const { mode } = useThemeMode();
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const onSelectItem = (albumId: number) => {
|
const onSelectItem = (albumId: number) => {
|
||||||
navigate(`/artist/${artistIdInt}/album/${albumId}`);
|
navigate(`/artist/${artistIdInt}/album/${albumId}`);
|
||||||
@ -96,13 +95,13 @@ export const ArtistDetailPage = () => {
|
|||||||
height={BASE_WRAP_HEIGHT}
|
height={BASE_WRAP_HEIGHT}
|
||||||
border="1px"
|
border="1px"
|
||||||
borderColor="brand.900"
|
borderColor="brand.900"
|
||||||
backgroundColor={mode('#FFFFFF88', '#00000088')}
|
backgroundColor={useColorModeValue('#FFFFFF88', '#00000088')}
|
||||||
key={data}
|
key={data}
|
||||||
padding="5px"
|
padding="5px"
|
||||||
as="button"
|
as="button"
|
||||||
_hover={{
|
_hover={{
|
||||||
boxShadow: 'outline-over',
|
boxShadow: 'outline-over',
|
||||||
bgColor: mode('#FFFFFFF7', '#000000F7'),
|
bgColor: useColorModeValue('#FFFFFFF7', '#000000F7'),
|
||||||
}}
|
}}
|
||||||
onClick={() => onSelectItem(data)}
|
onClick={() => onSelectItem(data)}
|
||||||
>
|
>
|
||||||
|
@ -11,7 +11,7 @@ import { PageLayout } from '@/components/Layout/PageLayout';
|
|||||||
import { SearchInput } from '@/components/SearchInput';
|
import { SearchInput } from '@/components/SearchInput';
|
||||||
import { BUTTON_TOP_BAR_PROPERTY, TopBar } from '@/components/TopBar/TopBar';
|
import { BUTTON_TOP_BAR_PROPERTY, TopBar } from '@/components/TopBar/TopBar';
|
||||||
import { useOrderedArtists } from '@/service/Artist';
|
import { useOrderedArtists } from '@/service/Artist';
|
||||||
import { useThemeMode } from '@/utils/theme-tools';
|
import { useColorModeValue } from '@/components/ui/color-mode';
|
||||||
import { BASE_WRAP_HEIGHT, BASE_WRAP_ICON_SIZE, BASE_WRAP_SPACING, BASE_WRAP_WIDTH } from '@/constants/genericSpacing';
|
import { BASE_WRAP_HEIGHT, BASE_WRAP_ICON_SIZE, BASE_WRAP_SPACING, BASE_WRAP_WIDTH } from '@/constants/genericSpacing';
|
||||||
import { MdOutlineForkRight } from 'react-icons/md';
|
import { MdOutlineForkRight } from 'react-icons/md';
|
||||||
import { useActivePlaylistService } from '@/service/ActivePlaylist';
|
import { useActivePlaylistService } from '@/service/ActivePlaylist';
|
||||||
@ -21,7 +21,6 @@ import { DataTools, TypeCheck } from '@/utils/data-tools';
|
|||||||
const LIMIT_RANDOM_VALUES = 25;
|
const LIMIT_RANDOM_VALUES = 25;
|
||||||
|
|
||||||
export const ArtistsPage = () => {
|
export const ArtistsPage = () => {
|
||||||
const { mode } = useThemeMode();
|
|
||||||
const [filterName, setFilterName] = useState<string | undefined>(undefined);
|
const [filterName, setFilterName] = useState<string | undefined>(undefined);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { playInList } = useActivePlaylistService();
|
const { playInList } = useActivePlaylistService();
|
||||||
@ -72,13 +71,13 @@ export const ArtistsPage = () => {
|
|||||||
height={BASE_WRAP_HEIGHT}
|
height={BASE_WRAP_HEIGHT}
|
||||||
border="1px"
|
border="1px"
|
||||||
borderColor="brand.900"
|
borderColor="brand.900"
|
||||||
backgroundColor={mode('#FFFFFF88', '#00000088')}
|
backgroundColor={useColorModeValue('#FFFFFF88', '#00000088')}
|
||||||
key={data.id}
|
key={data.id}
|
||||||
padding="5px"
|
padding="5px"
|
||||||
as="button"
|
as="button"
|
||||||
_hover={{
|
_hover={{
|
||||||
boxShadow: 'outline-over',
|
boxShadow: 'outline-over',
|
||||||
bgColor: mode('#FFFFFFF7', '#000000F7'),
|
bgColor: useColorModeValue('#FFFFFFF7', '#000000F7'),
|
||||||
}}
|
}}
|
||||||
onClick={() => onSelectItem(data)}
|
onClick={() => onSelectItem(data)}
|
||||||
>
|
>
|
||||||
|
@ -16,12 +16,11 @@ import { useActivePlaylistService } from '@/service/ActivePlaylist';
|
|||||||
import { useSpecificGender } from '@/service/Gender';
|
import { useSpecificGender } from '@/service/Gender';
|
||||||
import { useTracksOfAGender } from '@/service/Track';
|
import { useTracksOfAGender } from '@/service/Track';
|
||||||
//import { useTracksOfAGender } from '@/service/Track';
|
//import { useTracksOfAGender } from '@/service/Track';
|
||||||
import { useThemeMode } from '@/utils/theme-tools';
|
import { useColorModeValue } from '@/components/ui/color-mode';
|
||||||
|
|
||||||
export const GenderDetailPage = () => {
|
export const GenderDetailPage = () => {
|
||||||
const { genderId } = useParams();
|
const { genderId } = useParams();
|
||||||
const genderIdInt = genderId ? parseInt(genderId, 10) : undefined;
|
const genderIdInt = genderId ? parseInt(genderId, 10) : undefined;
|
||||||
const { mode } = useThemeMode();
|
|
||||||
const { playInList } = useActivePlaylistService();
|
const { playInList } = useActivePlaylistService();
|
||||||
const { dataGender } = useSpecificGender(genderIdInt);
|
const { dataGender } = useSpecificGender(genderIdInt);
|
||||||
const { tracksOnAGender } = useTracksOfAGender(genderIdInt);
|
const { tracksOnAGender } = useTracksOfAGender(genderIdInt);
|
||||||
@ -102,13 +101,13 @@ export const GenderDetailPage = () => {
|
|||||||
//height="60px"
|
//height="60px"
|
||||||
border="1px"
|
border="1px"
|
||||||
borderColor="brand.900"
|
borderColor="brand.900"
|
||||||
backgroundColor={mode('#FFFFFF88', '#00000088')}
|
backgroundColor={useColorModeValue('#FFFFFF88', '#00000088')}
|
||||||
key={data.id}
|
key={data.id}
|
||||||
padding="5px"
|
padding="5px"
|
||||||
as="button"
|
as="button"
|
||||||
_hover={{
|
_hover={{
|
||||||
boxShadow: 'outline-over',
|
boxShadow: 'outline-over',
|
||||||
bgColor: mode('#FFFFFFF7', '#000000F7'),
|
bgColor: useColorModeValue('#FFFFFFF7', '#000000F7'),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<DisplayTrackFull
|
<DisplayTrackFull
|
||||||
|
@ -9,13 +9,12 @@ import { SearchInput } from '@/components/SearchInput';
|
|||||||
import { TopBar } from '@/components/TopBar/TopBar';
|
import { TopBar } from '@/components/TopBar/TopBar';
|
||||||
import { DisplayGender } from '@/components/gender/DisplayGender';
|
import { DisplayGender } from '@/components/gender/DisplayGender';
|
||||||
import { useOrderedGenders } from '@/service/Gender';
|
import { useOrderedGenders } from '@/service/Gender';
|
||||||
import { useThemeMode } from '@/utils/theme-tools';
|
import { useColorModeValue } from '@/components/ui/color-mode';
|
||||||
import { Flex, HStack } from '@chakra-ui/react';
|
import { Flex, HStack } from '@chakra-ui/react';
|
||||||
|
|
||||||
export const GendersPage = () => {
|
export const GendersPage = () => {
|
||||||
const [filterTitle, setFilterTitle] = useState<string | undefined>(undefined);
|
const [filterTitle, setFilterTitle] = useState<string | undefined>(undefined);
|
||||||
const { isLoading, dataGenders } = useOrderedGenders(filterTitle);
|
const { isLoading, dataGenders } = useOrderedGenders(filterTitle);
|
||||||
const { mode } = useThemeMode();
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const onSelectItem = (genderId: number) => {
|
const onSelectItem = (genderId: number) => {
|
||||||
navigate(`/gender/${genderId}`);
|
navigate(`/gender/${genderId}`);
|
||||||
@ -43,13 +42,13 @@ export const GendersPage = () => {
|
|||||||
height="120px"
|
height="120px"
|
||||||
border="1px"
|
border="1px"
|
||||||
borderColor="brand.900"
|
borderColor="brand.900"
|
||||||
backgroundColor={mode('#FFFFFF88', '#00000088')}
|
backgroundColor={useColorModeValue('#FFFFFF88', '#00000088')}
|
||||||
key={data.id}
|
key={data.id}
|
||||||
padding="5px"
|
padding="5px"
|
||||||
as="button"
|
as="button"
|
||||||
_hover={{
|
_hover={{
|
||||||
boxShadow: 'outline-over',
|
boxShadow: 'outline-over',
|
||||||
bgColor: mode('#FFFFFFF7', '#000000F7'),
|
bgColor: useColorModeValue('#FFFFFFF7', '#000000F7'),
|
||||||
}}
|
}}
|
||||||
onClick={() => onSelectItem(data.id)}
|
onClick={() => onSelectItem(data.id)}
|
||||||
>
|
>
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { useCallback, useState } from 'react';
|
import { useCallback, useState } from 'react';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
|
||||||
Flex,
|
Flex,
|
||||||
Input,
|
Input,
|
||||||
Table,
|
Table,
|
||||||
@ -32,6 +31,7 @@ import { useGenderService, useOrderedGenders } from '@/service/Gender';
|
|||||||
import { useServiceContext } from '@/service/ServiceContext';
|
import { useServiceContext } from '@/service/ServiceContext';
|
||||||
import { useTrackService } from '@/service/Track';
|
import { useTrackService } from '@/service/Track';
|
||||||
import { isNullOrUndefined } from '@/utils/validator';
|
import { isNullOrUndefined } from '@/utils/validator';
|
||||||
|
import { Button } from '@/components/ui/themed';
|
||||||
|
|
||||||
export class ElementList {
|
export class ElementList {
|
||||||
constructor(
|
constructor(
|
||||||
@ -540,7 +540,7 @@ export const AddPage = () => {
|
|||||||
</Table.Root>
|
</Table.Root>
|
||||||
<Flex marginY="15px">
|
<Flex marginY="15px">
|
||||||
<Button
|
<Button
|
||||||
colorPalette="@primary"
|
theme="@primary"
|
||||||
onClick={sendFile}
|
onClick={sendFile}
|
||||||
disabled={!needSend}
|
disabled={!needSend}
|
||||||
marginLeft="auto"
|
marginLeft="auto"
|
||||||
|
@ -7,7 +7,8 @@ import { useNavigate } from 'react-router-dom';
|
|||||||
|
|
||||||
import { PageLayout } from '@/components/Layout/PageLayout';
|
import { PageLayout } from '@/components/Layout/PageLayout';
|
||||||
import { TopBar } from '@/components/TopBar/TopBar';
|
import { TopBar } from '@/components/TopBar/TopBar';
|
||||||
import { useThemeMode } from '@/utils/theme-tools';
|
|
||||||
|
import { useColorModeValue } from '@/components/ui/color-mode';
|
||||||
|
|
||||||
type HomeListType = {
|
type HomeListType = {
|
||||||
id: number;
|
id: number;
|
||||||
@ -19,37 +20,36 @@ const homeList: HomeListType[] = [
|
|||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
name: 'Genders',
|
name: 'Genders',
|
||||||
icon: <LuCrown size="60%" height="full" />,
|
icon: <LuCrown style={{ width: "100px", height: "100px" }} />,
|
||||||
to: 'gender',
|
to: 'gender',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 2,
|
id: 2,
|
||||||
name: 'Artists',
|
name: 'Artists',
|
||||||
icon: <MdGroup size="60%" height="full" />,
|
icon: <MdGroup style={{ width: "100px", height: "100px" }} />,
|
||||||
to: 'artist',
|
to: 'artist',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 3,
|
id: 3,
|
||||||
name: 'Albums',
|
name: 'Albums',
|
||||||
icon: <LuDisc3 size="60%" height="full" />,
|
icon: <LuDisc3 style={{ width: "100px", height: "100px" }} />,
|
||||||
to: 'album',
|
to: 'album',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 4,
|
id: 4,
|
||||||
name: 'Tracks',
|
name: 'Tracks',
|
||||||
icon: <LuFileAudio size="60%" height="full" />,
|
icon: <LuFileAudio style={{ width: "100px", height: "100px" }} />,
|
||||||
to: 'track',
|
to: 'track',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 5,
|
id: 5,
|
||||||
name: 'Playlists',
|
name: 'Playlists',
|
||||||
icon: <LuEar size="60%" height="full" />,
|
icon: <LuEar style={{ width: "100px", height: "100px" }} />,
|
||||||
to: 'playlists',
|
to: 'playlists',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const HomePage = () => {
|
export const HomePage = () => {
|
||||||
const { mode } = useThemeMode();
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const onSelectItem = (data: HomeListType) => {
|
const onSelectItem = (data: HomeListType) => {
|
||||||
navigate(data.to);
|
navigate(data.to);
|
||||||
@ -65,13 +65,13 @@ export const HomePage = () => {
|
|||||||
height="190px"
|
height="190px"
|
||||||
border="1px"
|
border="1px"
|
||||||
borderColor="brand.900"
|
borderColor="brand.900"
|
||||||
backgroundColor={mode('#FFFFFF88', '#00000088')}
|
backgroundColor={useColorModeValue('#FFFFFF88', '#00000088')}
|
||||||
key={data.id}
|
key={data.id}
|
||||||
padding="5px"
|
padding="5px"
|
||||||
as="button"
|
as="button"
|
||||||
_hover={{
|
_hover={{
|
||||||
boxShadow: 'outline-over',
|
boxShadow: 'outline-over',
|
||||||
bgColor: mode('#FFFFFFF7', '#000000F7'),
|
bgColor: useColorModeValue('#FFFFFFF7', '#000000F7'),
|
||||||
}}
|
}}
|
||||||
onClick={() => onSelectItem(data)}
|
onClick={() => onSelectItem(data)}
|
||||||
>
|
>
|
||||||
|
@ -1,26 +1,18 @@
|
|||||||
import { Box, Button, Flex, Text } from '@chakra-ui/react';
|
import { Box, Flex, Text } from '@chakra-ui/react';
|
||||||
import { LuDisc3 } from 'react-icons/lu';
|
import { Route, Routes, useNavigate } from 'react-router-dom';
|
||||||
import { MdEdit } from 'react-icons/md';
|
|
||||||
import { Route, Routes, useNavigate, useParams } from 'react-router-dom';
|
|
||||||
|
|
||||||
import { Covers } from '@/components/Cover';
|
|
||||||
import { EmptyEnd } from '@/components/EmptyEnd';
|
import { EmptyEnd } from '@/components/EmptyEnd';
|
||||||
import { PageLayout } from '@/components/Layout/PageLayout';
|
import { PageLayout } from '@/components/Layout/PageLayout';
|
||||||
import { PageLayoutInfoCenter } from '@/components/Layout/PageLayoutInfoCenter';
|
import { PageLayoutInfoCenter } from '@/components/Layout/PageLayoutInfoCenter';
|
||||||
import { BUTTON_TOP_BAR_PROPERTY, TopBar } from '@/components/TopBar/TopBar';
|
import { TopBar } from '@/components/TopBar/TopBar';
|
||||||
import { AlbumEditPopUp } from '@/components/popup/AlbumEditPopUp';
|
import { AlbumEditPopUp } from '@/components/popup/AlbumEditPopUp';
|
||||||
import { TrackEditPopUp } from '@/components/popup/TrackEditPopUp';
|
import { TrackEditPopUp } from '@/components/popup/TrackEditPopUp';
|
||||||
import { DisplayTrack } from '@/components/track/DisplayTrack';
|
|
||||||
import { DisplayTrackFull } from '@/components/track/DisplayTrackFull';
|
|
||||||
import { useActivePlaylistService } from '@/service/ActivePlaylist';
|
import { useActivePlaylistService } from '@/service/ActivePlaylist';
|
||||||
import { useSpecificAlbum } from '@/service/Album';
|
import { useColorModeValue } from '@/components/ui/color-mode';
|
||||||
import { useTracksOfAnAlbum } from '@/service/Track';
|
|
||||||
import { useThemeMode } from '@/utils/theme-tools';
|
|
||||||
import { BASE_WRAP_SPACING } from '@/constants/genericSpacing';
|
import { BASE_WRAP_SPACING } from '@/constants/genericSpacing';
|
||||||
import { DisplayTrackFullId } from '@/components/track/DisplayTrackFullId';
|
import { DisplayTrackFullId } from '@/components/track/DisplayTrackFullId';
|
||||||
|
|
||||||
export const OnAirPage = () => {
|
export const OnAirPage = () => {
|
||||||
const { mode } = useThemeMode();
|
|
||||||
const { playInList } = useActivePlaylistService();
|
const { playInList } = useActivePlaylistService();
|
||||||
const { playTrackList, trackOffset, setNewPlaylist } = useActivePlaylistService();
|
const { playTrackList, trackOffset, setNewPlaylist } = useActivePlaylistService();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@ -92,13 +84,13 @@ export const OnAirPage = () => {
|
|||||||
//height="60px"
|
//height="60px"
|
||||||
border="1px"
|
border="1px"
|
||||||
borderColor="brand.900"
|
borderColor="brand.900"
|
||||||
backgroundColor={mode('#FFFFFF88', '#00000088')}
|
backgroundColor={useColorModeValue('#FFFFFF88', '#00000088')}
|
||||||
key={data}
|
key={data}
|
||||||
padding="5px"
|
padding="5px"
|
||||||
as="button"
|
as="button"
|
||||||
_hover={{
|
_hover={{
|
||||||
boxShadow: 'outline-over',
|
boxShadow: 'outline-over',
|
||||||
bgColor: mode('#FFFFFFF7', '#000000F7'),
|
bgColor: useColorModeValue('#FFFFFFF7', '#000000F7'),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<DisplayTrackFullId
|
<DisplayTrackFullId
|
||||||
|
@ -6,7 +6,7 @@ import { useNavigate } from 'react-router-dom';
|
|||||||
import { PageLayout } from '@/components/Layout/PageLayout';
|
import { PageLayout } from '@/components/Layout/PageLayout';
|
||||||
import { TopBar } from '@/components/TopBar/TopBar';
|
import { TopBar } from '@/components/TopBar/TopBar';
|
||||||
import { DataTools, TypeCheck } from '@/utils/data-tools';
|
import { DataTools, TypeCheck } from '@/utils/data-tools';
|
||||||
import { useThemeMode } from '@/utils/theme-tools';
|
import { useColorModeValue } from '@/components/ui/color-mode';
|
||||||
|
|
||||||
export const alphabet = [
|
export const alphabet = [
|
||||||
'a',
|
'a',
|
||||||
@ -39,7 +39,6 @@ export const alphabet = [
|
|||||||
const possibilities = [...alphabet, '^^'];
|
const possibilities = [...alphabet, '^^'];
|
||||||
|
|
||||||
export const TrackSelectionPage = () => {
|
export const TrackSelectionPage = () => {
|
||||||
const { mode } = useThemeMode();
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const onSelectItem = (data: string) => {
|
const onSelectItem = (data: string) => {
|
||||||
navigate(`/track/${data}`);
|
navigate(`/track/${data}`);
|
||||||
@ -55,13 +54,13 @@ export const TrackSelectionPage = () => {
|
|||||||
height="75px"
|
height="75px"
|
||||||
border="1px"
|
border="1px"
|
||||||
borderColor="brand.900"
|
borderColor="brand.900"
|
||||||
backgroundColor={mode('#FFFFFF88', '#00000088')}
|
backgroundColor={useColorModeValue('#FFFFFF88', '#00000088')}
|
||||||
key={data}
|
key={data}
|
||||||
padding="5px"
|
padding="5px"
|
||||||
as="button"
|
as="button"
|
||||||
_hover={{
|
_hover={{
|
||||||
boxShadow: 'outline-over',
|
boxShadow: 'outline-over',
|
||||||
bgColor: mode('#FFFFFFF7', '#000000F7'),
|
bgColor: useColorModeValue('#FFFFFFF7', '#000000F7'),
|
||||||
}}
|
}}
|
||||||
onClick={() => onSelectItem(data)}
|
onClick={() => onSelectItem(data)}
|
||||||
>
|
>
|
||||||
|
@ -1,22 +1,20 @@
|
|||||||
import { ReactElement } from 'react';
|
import { ReactElement } from 'react';
|
||||||
|
|
||||||
import { Box, Flex, Text } from '@chakra-ui/react';
|
import { Box, Flex } from '@chakra-ui/react';
|
||||||
import { useNavigate, useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
|
|
||||||
import { EmptyEnd } from '@/components/EmptyEnd';
|
import { EmptyEnd } from '@/components/EmptyEnd';
|
||||||
import { PageLayout } from '@/components/Layout/PageLayout';
|
import { PageLayout } from '@/components/Layout/PageLayout';
|
||||||
import { TopBar } from '@/components/TopBar/TopBar';
|
import { TopBar } from '@/components/TopBar/TopBar';
|
||||||
import { DisplayTrack } from '@/components/track/DisplayTrack';
|
|
||||||
import { DisplayTrackFull } from '@/components/track/DisplayTrackFull';
|
import { DisplayTrackFull } from '@/components/track/DisplayTrackFull';
|
||||||
import { DisplayTrackSkeleton } from '@/components/track/DisplayTrackSkeleton';
|
import { DisplayTrackSkeleton } from '@/components/track/DisplayTrackSkeleton';
|
||||||
import { alphabet } from '@/scene/track/TrackSelectionPage';
|
import { alphabet } from '@/scene/track/TrackSelectionPage';
|
||||||
import { useActivePlaylistService } from '@/service/ActivePlaylist';
|
import { useActivePlaylistService } from '@/service/ActivePlaylist';
|
||||||
import { useTrackService, useTracksWithStartName } from '@/service/Track';
|
import { useTracksWithStartName } from '@/service/Track';
|
||||||
import { useThemeMode } from '@/utils/theme-tools';
|
import { useColorModeValue } from '@/components/ui/color-mode';
|
||||||
|
|
||||||
export const TracksStartLetterDetailPage = () => {
|
export const TracksStartLetterDetailPage = () => {
|
||||||
const { startLetter } = useParams();
|
const { startLetter } = useParams();
|
||||||
const { mode } = useThemeMode();
|
|
||||||
const { isLoading, tracksStartsWith } = useTracksWithStartName(
|
const { isLoading, tracksStartsWith } = useTracksWithStartName(
|
||||||
startLetter !== '^^'
|
startLetter !== '^^'
|
||||||
? startLetter
|
? startLetter
|
||||||
@ -63,13 +61,13 @@ export const TracksStartLetterDetailPage = () => {
|
|||||||
//height="60px"
|
//height="60px"
|
||||||
border="1px"
|
border="1px"
|
||||||
borderColor="brand.900"
|
borderColor="brand.900"
|
||||||
backgroundColor={mode('#FFFFFF88', '#00000088')}
|
backgroundColor={useColorModeValue('#FFFFFF88', '#00000088')}
|
||||||
key={data}
|
key={data}
|
||||||
padding="5px"
|
padding="5px"
|
||||||
as="button"
|
as="button"
|
||||||
_hover={{
|
_hover={{
|
||||||
boxShadow: 'outline-over',
|
boxShadow: 'outline-over',
|
||||||
bgColor: mode('#FFFFFFF7', '#000000F7'),
|
bgColor: useColorModeValue('#FFFFFFF7', '#000000F7'),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<DisplayTrackSkeleton />
|
<DisplayTrackSkeleton />
|
||||||
@ -82,13 +80,13 @@ export const TracksStartLetterDetailPage = () => {
|
|||||||
//height="60px"
|
//height="60px"
|
||||||
border="1px"
|
border="1px"
|
||||||
borderColor="brand.900"
|
borderColor="brand.900"
|
||||||
backgroundColor={mode('#FFFFFF88', '#00000088')}
|
backgroundColor={useColorModeValue('#FFFFFF88', '#00000088')}
|
||||||
key={data.id}
|
key={data.id}
|
||||||
padding="5px"
|
padding="5px"
|
||||||
as="button"
|
as="button"
|
||||||
_hover={{
|
_hover={{
|
||||||
boxShadow: 'outline-over',
|
boxShadow: 'outline-over',
|
||||||
bgColor: mode('#FFFFFFF7', '#000000F7'),
|
bgColor: useColorModeValue('#FFFFFFF7', '#000000F7'),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<DisplayTrackFull
|
<DisplayTrackFull
|
||||||
|
9
front/src/theme/foundations/index.ts
Normal file
9
front/src/theme/foundations/index.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { colors } from './colors';
|
||||||
|
import { shadows } from './shadows';
|
||||||
|
|
||||||
|
const foundations = {
|
||||||
|
colors,
|
||||||
|
shadows,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default foundations;
|
21
front/src/theme/foundations/shadows.ts
Normal file
21
front/src/theme/foundations/shadows.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { colors } from './colors';
|
||||||
|
|
||||||
|
const createOutline = (colorScheme = 'gray') =>
|
||||||
|
`0 0 0 3px ${colorScheme}.500/3`;
|
||||||
|
|
||||||
|
export const shadows = {
|
||||||
|
outline: createOutline('brand'),
|
||||||
|
'outline-brand': '0 0 0 1px brand.900',
|
||||||
|
'outline-gray': createOutline('gray'),
|
||||||
|
'outline-over': `4px 4px 5px #00000088`,
|
||||||
|
'outline-darkgray': `0 0 0 3px gray.500/8`,
|
||||||
|
'outline-success': createOutline('success'),
|
||||||
|
'outline-warning': createOutline('warning'),
|
||||||
|
'outline-error': createOutline('error'),
|
||||||
|
'outline-doing': createOutline('doing'),
|
||||||
|
'outline-paused': createOutline('paused'),
|
||||||
|
layout: '0 0 24px 1px rgba(0, 0, 0, 0.05)',
|
||||||
|
smooth: 'inset 0px 0px 16px rgba(0, 0, 0, 0.05)',
|
||||||
|
// smooth-light is used for dark backgrounds
|
||||||
|
'smooth-light': 'inset 0px 0px 16px rgba(255, 255, 255, 0.1)',
|
||||||
|
};
|
24
front/src/theme/recipes/badge.ts
Normal file
24
front/src/theme/recipes/badge.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
export default {
|
||||||
|
sizes: {
|
||||||
|
'2xs': {
|
||||||
|
fontSize: '0.5em',
|
||||||
|
},
|
||||||
|
xs: {
|
||||||
|
fontSize: '0.6em',
|
||||||
|
},
|
||||||
|
sm: {
|
||||||
|
fontSize: '0.7em',
|
||||||
|
},
|
||||||
|
md: {
|
||||||
|
fontSize: '0.8em',
|
||||||
|
textTransform: 'none',
|
||||||
|
},
|
||||||
|
lg: {
|
||||||
|
fontSize: '0.9em',
|
||||||
|
textTransform: 'none',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defaultProps: {
|
||||||
|
size: 'md',
|
||||||
|
},
|
||||||
|
};
|
109
front/src/theme/recipes/button.ts
Normal file
109
front/src/theme/recipes/button.ts
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
import { defineRecipe, defineStyle, RecipeVariantRecord, SystemStyleObject } from '@chakra-ui/react';
|
||||||
|
|
||||||
|
// https://medium.com/@a.heydari.dev/simplifying-chakra-ui-v3-recipes-vs-chakra-factory-a-developers-perspective-4020b62f1b4d
|
||||||
|
|
||||||
|
// const shimmer = keyframes`
|
||||||
|
// 100% {
|
||||||
|
// transform: translateX(100%);
|
||||||
|
// }
|
||||||
|
// `;
|
||||||
|
|
||||||
|
export const customVariant = ({ bg, bgHover, bgActive, color, colorHover, boxShadowHover }) => {
|
||||||
|
return defineStyle({
|
||||||
|
bg,
|
||||||
|
color,
|
||||||
|
border: '1px solid transparent',
|
||||||
|
_focus: {
|
||||||
|
border: '1px solid',
|
||||||
|
borderColor: 'black',
|
||||||
|
},
|
||||||
|
_hover: {
|
||||||
|
bg: bgHover,
|
||||||
|
color: colorHover,
|
||||||
|
boxShadow: boxShadowHover,
|
||||||
|
_disabled: {
|
||||||
|
bg,
|
||||||
|
boxShadow: 'none',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
_active: {
|
||||||
|
bg: bgActive,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const buttonRecipe = defineRecipe({
|
||||||
|
variants: {
|
||||||
|
theme: {
|
||||||
|
"@primary":
|
||||||
|
customVariant({
|
||||||
|
bg: { _light: 'brand.600', _dark: 'brand.300' },
|
||||||
|
bgHover: { _light: 'brand.700', _dark: 'brand.400' },
|
||||||
|
bgActive: { _light: 'brand.600', _dark: 'brand.300' },
|
||||||
|
color: { _light: 'white', _dark: 'brand.900' },
|
||||||
|
colorHover: { _light: 'brand.800', _dark: 'brand.100' },
|
||||||
|
boxShadowHover: 'outline-over'
|
||||||
|
}),
|
||||||
|
"@secondary":
|
||||||
|
customVariant({
|
||||||
|
bg: { _light: 'brand.100', _dark: 'brand.900' },
|
||||||
|
bgHover: { _light: 'brand.200', _dark: 'brand.800' },
|
||||||
|
bgActive: { _light: 'brand.300', _dark: 'brand.700' },
|
||||||
|
color: { _light: 'brand.700', _dark: 'brand.50' },
|
||||||
|
colorHover: { _light: 'brand.800', _dark: 'brand.100' },
|
||||||
|
boxShadowHover: 'outline-over',
|
||||||
|
}),
|
||||||
|
"@danger":
|
||||||
|
customVariant({
|
||||||
|
bg: { _light: 'error.600', _dark: 'error.600' },
|
||||||
|
bgHover: { _light: 'error.700', _dark: 'error.500' },
|
||||||
|
bgActive: { _light: 'error.600', _dark: 'error.500' },
|
||||||
|
color: { _light: 'white', _dark: 'error.900' },
|
||||||
|
colorHover: { _light: 'error.700', _dark: 'error.900' },
|
||||||
|
boxShadowHover: 'outline-over',
|
||||||
|
}),
|
||||||
|
"@success":
|
||||||
|
customVariant({
|
||||||
|
bg: { _light: 'green.300', _dark: 'green.300' },
|
||||||
|
bgHover: { _light: 'green.400', _dark: 'green.400' },
|
||||||
|
bgActive: { _light: 'green.500', _dark: 'green.400' },
|
||||||
|
color: { _light: 'white', _dark: 'green.900' },
|
||||||
|
colorHover: { _light: 'green.500', _dark: 'green.900' },
|
||||||
|
boxShadowHover: 'outline-over',
|
||||||
|
}),
|
||||||
|
|
||||||
|
"@progress":
|
||||||
|
defineStyle({
|
||||||
|
bg: { _light: `brand.500`, _dark: `brand.300` },
|
||||||
|
overflow: 'hidden',
|
||||||
|
/*
|
||||||
|
_after: !props.isLoading
|
||||||
|
? {
|
||||||
|
content: '""',
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
left: 0,
|
||||||
|
transform: 'translateX(-100%)',
|
||||||
|
bgGradient: `linear(90deg, brand.100/0 0%, brand.100/2 20%, brand.100/5 60%, v.100/0`,
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
|
*/
|
||||||
|
}),
|
||||||
|
|
||||||
|
"@menu": defineStyle({
|
||||||
|
bg: 'back.100',
|
||||||
|
color: 'brand.900',
|
||||||
|
borderRadius: 0,
|
||||||
|
border: 0,
|
||||||
|
_hover: { background: 'back.300' },
|
||||||
|
_focus: { border: 'none' },
|
||||||
|
fontSize: '20px',
|
||||||
|
textTransform: 'uppercase',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default buttonRecipe;
|
5
front/src/theme/recipes/checkbox.ts
Normal file
5
front/src/theme/recipes/checkbox.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export default {
|
||||||
|
defaultProps: {
|
||||||
|
colorScheme: 'brand',
|
||||||
|
},
|
||||||
|
};
|
29
front/src/theme/recipes/drawer.ts
Normal file
29
front/src/theme/recipes/drawer.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import { defineRecipe } from '@chakra-ui/react';
|
||||||
|
|
||||||
|
const drawerRecipe = defineRecipe({
|
||||||
|
base: {
|
||||||
|
bg: { _light: 'white', _dark: 'gray.800' },
|
||||||
|
color: { _light: 'gray.900', _dark: 'whiteAlpha.900' },
|
||||||
|
boxShadow: { _light: 'lg', _dark: 'dark-lg' },
|
||||||
|
padding: 4,
|
||||||
|
borderRadius: 'md',
|
||||||
|
},
|
||||||
|
variants: {
|
||||||
|
variant: {
|
||||||
|
solid: {
|
||||||
|
bg: { _light: 'blue.500', _dark: 'blue.300' },
|
||||||
|
color: 'white',
|
||||||
|
},
|
||||||
|
outline: {
|
||||||
|
border: '1px solid',
|
||||||
|
borderColor: { _light: 'gray.300', _dark: 'whiteAlpha.300' },
|
||||||
|
bg: { _light: 'white', _dark: 'gray.900' },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
defaultVariants: {
|
||||||
|
variant: 'solid',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default drawerRecipe;
|
20
front/src/theme/recipes/flex.ts
Normal file
20
front/src/theme/recipes/flex.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { defineRecipe } from '@chakra-ui/react';
|
||||||
|
|
||||||
|
|
||||||
|
const flexTheme = defineRecipe({
|
||||||
|
variants: {
|
||||||
|
variant: {
|
||||||
|
'@menu': {
|
||||||
|
bg: { _light: 'back.100', _dark: 'back.800' },
|
||||||
|
color: { _light: 'brand.900', _dark: 'brand.100' },
|
||||||
|
borderRadius: 0,
|
||||||
|
border: 0,
|
||||||
|
_hover: { background: { _light: 'back.300', _dark: 'back.600' } },
|
||||||
|
_focus: { border: 'none' },
|
||||||
|
fontSize: '20px',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default flexTheme;
|
13
front/src/theme/recipes/index.ts
Normal file
13
front/src/theme/recipes/index.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
export { default as Badge } from './badge';
|
||||||
|
export { default as Button } from './button';
|
||||||
|
export { default as Checkbox } from './checkbox';
|
||||||
|
export { default as Input } from './input';
|
||||||
|
//export { default as NumberInput } from './numberInput.ts_';
|
||||||
|
export { default as Popover } from './popover';
|
||||||
|
export { default as Radio } from './radio';
|
||||||
|
export { default as Select } from './select';
|
||||||
|
export { default as Switch } from './switch';
|
||||||
|
export { default as Textarea } from './textarea';
|
||||||
|
//export { default as Modal } from './modal';
|
||||||
|
export { default as Flex } from './flex';
|
||||||
|
export { default as Drawer } from './drawer';
|
21
front/src/theme/recipes/input.ts
Normal file
21
front/src/theme/recipes/input.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { defineRecipe } from '@chakra-ui/react';
|
||||||
|
|
||||||
|
const inputTheme = defineRecipe({
|
||||||
|
variants: {
|
||||||
|
variant: {
|
||||||
|
outline: {
|
||||||
|
field: {
|
||||||
|
bg: { _light: 'gray.50', _dark: 'whiteAlpha.50' },
|
||||||
|
borderColor: { _light: 'gray.200', _dark: 'whiteAlpha.100' },
|
||||||
|
color: { _light: 'gray.800', _dark: 'gray.50' },
|
||||||
|
_focus: {
|
||||||
|
borderColor: { _light: 'gray.800', _dark: 'gray.50' },
|
||||||
|
boxShadow: `0 0 0 1px gray.800`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default inputTheme;
|
17
front/src/theme/recipes/modal.ts__
Normal file
17
front/src/theme/recipes/modal.ts__
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { modalAnatomy as parts } from '@chakra-ui/anatomy';
|
||||||
|
import { createMultiStyleConfigHelpers } from '@chakra-ui/react';
|
||||||
|
|
||||||
|
const { definePartsStyle, defineMultiStyleConfig } =
|
||||||
|
createMultiStyleConfigHelpers(parts.keys);
|
||||||
|
|
||||||
|
const baseStyle = definePartsStyle({
|
||||||
|
header: {
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const modalTheme = defineMultiStyleConfig({
|
||||||
|
baseStyle,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default modalTheme;
|
27
front/src/theme/recipes/numberInput.ts_
Normal file
27
front/src/theme/recipes/numberInput.ts_
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { numberInputAnatomy } from '@chakra-ui/anatomy';
|
||||||
|
import { createMultiStyleConfigHelpers } from '@chakra-ui/react';
|
||||||
|
import { getColor, mode } from '@chakra-ui/theme-tools';
|
||||||
|
|
||||||
|
const { definePartsStyle, defineMultiStyleConfig } =
|
||||||
|
createMultiStyleConfigHelpers(numberInputAnatomy.keys);
|
||||||
|
|
||||||
|
const baseStyle = definePartsStyle((props) => {
|
||||||
|
|
||||||
|
return {
|
||||||
|
field: {
|
||||||
|
border: 0,
|
||||||
|
_focusVisible: {
|
||||||
|
borderColor: {_light:'brand.500', _dark:'brand.300'},
|
||||||
|
boxShadow: `0 0 0 1px 'brand.500'`,
|
||||||
|
ring: '1px',
|
||||||
|
ringColor: {_light:'brand.500', _dark:'brand.300'},
|
||||||
|
ringOffset: '1px',
|
||||||
|
ringOffsetColor: {_light:'brand.500', _dark:'brand.300'},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
export default defineMultiStyleConfig({
|
||||||
|
baseStyle,
|
||||||
|
});
|
77
front/src/theme/recipes/popover.ts
Normal file
77
front/src/theme/recipes/popover.ts
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
export default {
|
||||||
|
sizes: {
|
||||||
|
'3xs': {
|
||||||
|
content: {
|
||||||
|
width: '3xs',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'2xs': {
|
||||||
|
content: {
|
||||||
|
width: '2xs',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
xs: {
|
||||||
|
content: {
|
||||||
|
width: 'xs',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
sm: {
|
||||||
|
content: {
|
||||||
|
width: 'sm',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
md: {
|
||||||
|
content: {
|
||||||
|
width: 'md',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
lg: {
|
||||||
|
content: {
|
||||||
|
width: 'lg',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
xl: {
|
||||||
|
content: {
|
||||||
|
width: 'xl',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'2xl': {
|
||||||
|
content: {
|
||||||
|
width: '2xl',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'3xl': {
|
||||||
|
content: {
|
||||||
|
width: '3xl',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'4xl': {
|
||||||
|
content: {
|
||||||
|
width: '4xl',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'5xl': {
|
||||||
|
content: {
|
||||||
|
width: '5xl',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'6xl': {
|
||||||
|
content: {
|
||||||
|
width: '6xl',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'7xl': {
|
||||||
|
content: {
|
||||||
|
width: '7xl',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'8xl': {
|
||||||
|
content: {
|
||||||
|
width: '8xl',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defaultProps: {
|
||||||
|
size: 'xs',
|
||||||
|
},
|
||||||
|
};
|
5
front/src/theme/recipes/radio.ts
Normal file
5
front/src/theme/recipes/radio.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export default {
|
||||||
|
defaultProps: {
|
||||||
|
colorScheme: 'brand',
|
||||||
|
},
|
||||||
|
};
|
20
front/src/theme/recipes/select.ts
Normal file
20
front/src/theme/recipes/select.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { defineRecipe } from '@chakra-ui/react';
|
||||||
|
|
||||||
|
const selectTheme = defineRecipe({
|
||||||
|
variants: {
|
||||||
|
variant: {
|
||||||
|
outline: {
|
||||||
|
field: {
|
||||||
|
bg: { _light: 'gray.50', _dark: 'whiteAlpha.50' },
|
||||||
|
borderColor: { _light: 'blackAlpha.100', _dark: 'whiteAlpha.100' },
|
||||||
|
_focus: {
|
||||||
|
borderColor: { _light: 'brand.500', _dark: 'brand.300' },
|
||||||
|
boxShadow: `0 0 0 1px black`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default selectTheme;
|
5
front/src/theme/recipes/switch.ts
Normal file
5
front/src/theme/recipes/switch.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export default {
|
||||||
|
defaultProps: {
|
||||||
|
colorScheme: 'brand',
|
||||||
|
},
|
||||||
|
};
|
18
front/src/theme/recipes/textarea.ts
Normal file
18
front/src/theme/recipes/textarea.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { defineRecipe } from '@chakra-ui/react';
|
||||||
|
|
||||||
|
|
||||||
|
const textAreaTheme = defineRecipe({
|
||||||
|
variants: {
|
||||||
|
variant: {
|
||||||
|
outline: {
|
||||||
|
bg: { _light: 'gray.50', _dark: 'whiteAlpha.50' },
|
||||||
|
borderColor: { _light: 'blackAlpha.100', _dark: 'whiteAlpha.100' },
|
||||||
|
_focus: {
|
||||||
|
borderColor: { _light: 'brand.500', _dark: 'brand.300' },
|
||||||
|
boxShadow: `0 0 0 1px brand.500`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
export default textAreaTheme;
|
@ -1,4 +1,4 @@
|
|||||||
import { Button, Group, IconButton, VStack } from '@chakra-ui/react';
|
import { Group, VStack } from '@chakra-ui/react';
|
||||||
import { HiMinus, HiPlus } from 'react-icons/hi';
|
import { HiMinus, HiPlus } from 'react-icons/hi';
|
||||||
|
|
||||||
const meta = {
|
const meta = {
|
||||||
@ -19,8 +19,8 @@ export const Default = {
|
|||||||
export const Primary = {
|
export const Primary = {
|
||||||
render: () => (
|
render: () => (
|
||||||
<Group>
|
<Group>
|
||||||
<Button colorPalette="@primary">Primary Button</Button>
|
<Button theme="@primary">Primary Button</Button>
|
||||||
<IconButton colorPalette="@primary" aria-label="Add" ><HiPlus /></IconButton>
|
<IconButton theme="@primary" aria-label="Add" ><HiPlus /></IconButton>
|
||||||
</Group>
|
</Group>
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
@ -28,8 +28,8 @@ export const Primary = {
|
|||||||
export const Secondary = {
|
export const Secondary = {
|
||||||
render: () => (
|
render: () => (
|
||||||
<Group>
|
<Group>
|
||||||
<Button colorPalette="@secondary">Secondary Button</Button>
|
<Button theme="@secondary">Secondary Button</Button>
|
||||||
<IconButton colorPalette="@secondary" aria-label="Add" ><HiPlus /></IconButton>
|
<IconButton theme="@secondary" aria-label="Add" ><HiPlus /></IconButton>
|
||||||
</Group>
|
</Group>
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
@ -37,8 +37,8 @@ export const Secondary = {
|
|||||||
export const Danger = {
|
export const Danger = {
|
||||||
render: () => (
|
render: () => (
|
||||||
<Group>
|
<Group>
|
||||||
<Button colorPalette="@danger">Danger Button</Button>
|
<Button theme="@danger">Danger Button</Button>
|
||||||
<IconButton colorPalette="@danger" aria-label="Remove"><HiMinus /></IconButton>
|
<IconButton theme="@danger" aria-label="Remove"><HiMinus /></IconButton>
|
||||||
</Group>
|
</Group>
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
@ -58,7 +58,7 @@ export const Progress = {
|
|||||||
</Button>
|
</Button>
|
||||||
<IconButton
|
<IconButton
|
||||||
variant="solid"
|
variant="solid"
|
||||||
colorPalette="red"
|
theme="@danger"
|
||||||
aria-label="Remove"
|
aria-label="Remove"
|
||||||
><HiMinus /></IconButton>
|
><HiMinus /></IconButton>
|
||||||
</VStack>
|
</VStack>
|
||||||
|
@ -1,13 +1,4 @@
|
|||||||
// import { Styles } from '@chakra-ui/theme-tools';
|
import { Styles } from '@chakra-ui/theme-tools';
|
||||||
// import { mode } from '@chakra-ui/theme-tools';
|
|
||||||
|
|
||||||
// export const styles: Styles = {
|
export const styles: Styles = {
|
||||||
// global: (props) => ({
|
};
|
||||||
// body: {
|
|
||||||
// overflowY: 'none',
|
|
||||||
// bg: mode('back.50', 'back.700')(props),
|
|
||||||
// color: mode('text.900', 'text.50')(props),
|
|
||||||
// fontFamily: 'Roboto, Helvetica, Arial, "sans-serif"',
|
|
||||||
// },
|
|
||||||
// }),
|
|
||||||
// };
|
|
||||||
|
@ -1,9 +1,23 @@
|
|||||||
|
import * as recipes from './recipes';
|
||||||
import { createSystem, defaultConfig } from "@chakra-ui/react"
|
import { createSystem, defaultConfig, mergeConfigs, SystemConfig } from "@chakra-ui/react"
|
||||||
import { colors } from "./foundations/colors"
|
import { colors } from "./foundations/colors"
|
||||||
|
|
||||||
export const system = createSystem(defaultConfig, {
|
const baseTheme: SystemConfig = {
|
||||||
|
globalCss: {
|
||||||
|
body: {
|
||||||
|
overflowY: 'none',
|
||||||
|
bg: { _light: 'back.50', _dark: 'back.700' },
|
||||||
|
color: { _light: 'text.900', _dark: 'text.50' },
|
||||||
|
fontFamily: 'Roboto, Helvetica, Arial, "sans-serif"',
|
||||||
|
},
|
||||||
|
svg: {
|
||||||
|
width: "32px",
|
||||||
|
height: "32px",
|
||||||
|
aspectRatio: "square",
|
||||||
|
}
|
||||||
|
},
|
||||||
theme: {
|
theme: {
|
||||||
|
...recipes,
|
||||||
tokens: {
|
tokens: {
|
||||||
fonts: {
|
fonts: {
|
||||||
heading: { value: `Roboto, Helvetica, Arial, "sans-serif"` },
|
heading: { value: `Roboto, Helvetica, Arial, "sans-serif"` },
|
||||||
@ -25,4 +39,6 @@ export const system = createSystem(defaultConfig, {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
};
|
||||||
|
const config = mergeConfigs(defaultConfig, baseTheme);
|
||||||
|
export const systemTheme = createSystem(config);
|
@ -1,20 +0,0 @@
|
|||||||
import { useCallback } from 'react';
|
|
||||||
|
|
||||||
export const useThemeMode = () => {
|
|
||||||
//const { colorMode, toggleColorMode, setColorMode } = useColorMode();
|
|
||||||
const colorMode = "dark";
|
|
||||||
const toggleColorMode = () => { }
|
|
||||||
const setColorMode = (_value: string) => { }
|
|
||||||
|
|
||||||
const mode = useCallback(
|
|
||||||
(lightValue, darkValue) => (colorMode === 'dark' ? darkValue : lightValue),
|
|
||||||
[colorMode]
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
toggleColorMode,
|
|
||||||
setColorMode,
|
|
||||||
mode,
|
|
||||||
colorMode,
|
|
||||||
};
|
|
||||||
};
|
|
@ -38,7 +38,9 @@
|
|||||||
"include": [
|
"include": [
|
||||||
"next-env.d.ts",
|
"next-env.d.ts",
|
||||||
"src/**/*.ts",
|
"src/**/*.ts",
|
||||||
"src/**/*.tsx"
|
"src/**/*.tsx",
|
||||||
|
"src/theme/recipes/numberInput.ts_",
|
||||||
|
"src/theme/recipes/modal.ts__"
|
||||||
],
|
],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"node_modules"
|
"node_modules"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user