354 lines
8.9 KiB
TypeScript
354 lines
8.9 KiB
TypeScript
import { ActionIcon, Box, Button, Group, Overlay, Stack, Text } from '@mantine/core';
|
|
import { useDisclosure } from '@mantine/hooks';
|
|
import { useCommonHooks, useMutationAPI } from 'hooks';
|
|
import { useState } from 'react';
|
|
import { FiEdit, FiShuffle, FiTrash, FiX } from 'react-icons/fi';
|
|
import { actionIconClasses } from 'styles';
|
|
import type { ThemePlaylist } from 'types';
|
|
import DeleteItemModal from '../Shared/DeleteItemModal';
|
|
|
|
function ThemeCard({ cardTheme, handleOpen, allThemes, themePlaylists }: any) {
|
|
const [hover, setHover] = useState(false);
|
|
const [shiftEdit, setShiftEdit] = useState<number>(0);
|
|
const [shiftShuffle, setShiftShuffle] = useState<number>(0);
|
|
const { mutateAsync } = useMutationAPI();
|
|
const [modalOpened, { open: openModal, close: closeModal }] = useDisclosure(false);
|
|
const {
|
|
handleThemeChange,
|
|
currentTheme,
|
|
setCurrentTheme,
|
|
theme,
|
|
currentThemePlaylist,
|
|
setCurrentThemePlaylist,
|
|
handleDelete,
|
|
} = useCommonHooks();
|
|
|
|
return (
|
|
<Group
|
|
gap={0}
|
|
align='center'
|
|
justify='center'
|
|
display={'grid'}
|
|
pos={'relative'}
|
|
onMouseEnter={() => setHover(true)}
|
|
onMouseLeave={() => setHover(false)}
|
|
>
|
|
<DeleteItemModal
|
|
modalOpened={modalOpened}
|
|
handleClose={closeModal}
|
|
title={'Delete Theme'}
|
|
body={
|
|
<Stack gap={0} w={'100%'} h={'150px'} align='center'>
|
|
<Text>Are you sure you want to delete this theme?</Text>
|
|
<Text
|
|
style={{
|
|
fontWeight: 'bold',
|
|
fontSize: '20px',
|
|
padding: '8px',
|
|
margin: '8px',
|
|
borderRadius: '10px',
|
|
backgroundColor: 'var(--color-text-acc)',
|
|
color: 'var(--color-background)',
|
|
}}
|
|
>{`"${cardTheme.name}"`}</Text>
|
|
<Text c='red'>This action cannot be undone!</Text>
|
|
<Group pos={'absolute'} bottom={8}>
|
|
<Button
|
|
color={'red'}
|
|
styles={{ label: { color: 'black' } }}
|
|
onClick={() => {
|
|
handleDelete(cardTheme, 'api/themes');
|
|
closeModal();
|
|
}}
|
|
>
|
|
Delete
|
|
</Button>
|
|
<Button
|
|
color={'grey'}
|
|
styles={{ label: { color: 'black' } }}
|
|
onClick={() => {
|
|
closeModal();
|
|
}}
|
|
>
|
|
Cancel
|
|
</Button>
|
|
</Group>
|
|
</Stack>
|
|
}
|
|
/>
|
|
<Text
|
|
style={{
|
|
position: 'absolute',
|
|
top: -10,
|
|
left: 6,
|
|
paddingRight: 4,
|
|
paddingLeft: 4,
|
|
backgroundColor: cardTheme.borderColor,
|
|
borderRadius: '4px',
|
|
color:
|
|
cardTheme.borderColor === cardTheme.primaryColor
|
|
? cardTheme.accentColor
|
|
: cardTheme.primaryColor,
|
|
zIndex: 3,
|
|
}}
|
|
>
|
|
{cardTheme.name}
|
|
</Text>
|
|
<Button
|
|
w={'275px'}
|
|
h={'115px'}
|
|
disabled={currentTheme === 'random'}
|
|
style={{
|
|
background: `linear-gradient(${cardTheme.backgroundColor}33, ${cardTheme.backgroundColor}33), no-repeat center url(/backgrounds/${cardTheme.backgroundImage})`,
|
|
backgroundSize: 'cover',
|
|
backgroundColor: cardTheme.backgroundColor,
|
|
border: `solid ${cardTheme.borderColor}`,
|
|
filter: cardTheme.randomEnabled === 0 ? 'saturate(0)' : undefined,
|
|
}}
|
|
onClick={() => {
|
|
setCurrentTheme(cardTheme.name);
|
|
setCurrentThemePlaylist('All');
|
|
}}
|
|
>
|
|
{hover && currentTheme !== 'random' && <Overlay opacity={0.5} zIndex={1} />}
|
|
<Group w={'100%'} gap={0} display={'flex'} align='center' justify='center'>
|
|
<Stack align='center'>
|
|
<Box
|
|
style={{
|
|
height: '10px',
|
|
width: '100px',
|
|
backgroundColor: cardTheme.searchColor,
|
|
borderRadius: '4px',
|
|
borderBottom: `solid 1px ${cardTheme.borderColor}`,
|
|
}}
|
|
/>
|
|
<Group justify='space-between'>
|
|
<Box
|
|
style={{
|
|
height: '8px',
|
|
width: '100px',
|
|
backgroundColor: cardTheme.accentColor,
|
|
borderRadius: '4px',
|
|
}}
|
|
/>
|
|
<Box
|
|
style={{
|
|
height: '8px',
|
|
width: '50px',
|
|
backgroundColor: cardTheme.primaryColor,
|
|
borderRadius: '4px',
|
|
}}
|
|
/>
|
|
</Group>
|
|
<Group w={'100%'}>
|
|
<Box
|
|
style={{
|
|
height: '5px',
|
|
width: '40px',
|
|
backgroundColor: cardTheme.primaryColor,
|
|
borderRadius: '4px',
|
|
}}
|
|
/>
|
|
</Group>
|
|
<Group w={'100%'}>
|
|
<Box
|
|
style={{
|
|
height: '10px',
|
|
width: '40px',
|
|
borderRadius: '4px',
|
|
backdropFilter: 'blur(10px) brightness(1.5)',
|
|
fontSize: '6px',
|
|
justifyContent: 'center',
|
|
alignContent: 'center',
|
|
color: cardTheme.primaryColor,
|
|
}}
|
|
>
|
|
lorem ipsum
|
|
</Box>
|
|
<Box
|
|
style={{
|
|
height: '10px',
|
|
width: '40px',
|
|
borderRadius: '4px',
|
|
backdropFilter: 'blur(10px) brightness(1.5)',
|
|
fontSize: '6px',
|
|
justifyContent: 'center',
|
|
alignContent: 'center',
|
|
color: cardTheme.primaryColor,
|
|
}}
|
|
>
|
|
lorem ipsum
|
|
</Box>
|
|
<Box
|
|
style={{
|
|
height: '10px',
|
|
width: '40px',
|
|
borderRadius: '4px',
|
|
backdropFilter: 'blur(10px) brightness(1.5)',
|
|
fontSize: '6px',
|
|
justifyContent: 'center',
|
|
alignContent: 'center',
|
|
color: cardTheme.primaryColor,
|
|
}}
|
|
>
|
|
lorem ipsum
|
|
</Box>
|
|
</Group>
|
|
</Stack>
|
|
</Group>
|
|
</Button>
|
|
{currentTheme === 'random' && cardTheme.name === theme.name ? (
|
|
<Group>
|
|
<Group
|
|
onMouseEnter={() => {
|
|
setShiftEdit(2);
|
|
}}
|
|
onMouseLeave={() => {
|
|
setShiftEdit(0);
|
|
}}
|
|
onClick={() => {
|
|
setShiftEdit(0);
|
|
}}
|
|
gap={0}
|
|
style={{
|
|
zIndex: 300,
|
|
position: 'absolute',
|
|
left: 0,
|
|
top: 27 - shiftEdit,
|
|
backgroundColor: shiftEdit === 0 ? 'white' : 'var(--color-background)',
|
|
borderRadius: '50%',
|
|
padding: '8px',
|
|
margin: '4px',
|
|
border: 'solid 2px',
|
|
borderColor: shiftEdit === 0 ? 'black' : 'var(--color-text-pri)',
|
|
transition: 'all 0.2s',
|
|
}}
|
|
>
|
|
<FiEdit
|
|
onClick={() => {
|
|
handleOpen(cardTheme);
|
|
}}
|
|
style={{
|
|
fontSize: '2em',
|
|
fontWeight: 'bold',
|
|
color: shiftEdit === 0 ? 'black' : 'var(--color-text-pri)',
|
|
}}
|
|
/>
|
|
</Group>
|
|
<Group
|
|
onMouseEnter={() => {
|
|
setShiftShuffle(2);
|
|
}}
|
|
onMouseLeave={() => {
|
|
setShiftShuffle(0);
|
|
}}
|
|
onClick={() => {
|
|
setShiftShuffle(0);
|
|
}}
|
|
gap={0}
|
|
style={{
|
|
zIndex: 300,
|
|
position: 'absolute',
|
|
right: 0,
|
|
top: 27 - shiftShuffle,
|
|
backgroundColor: shiftShuffle === 0 ? 'white' : 'var(--color-background)',
|
|
borderRadius: '50%',
|
|
padding: '8px',
|
|
margin: '4px',
|
|
border: 'solid 2px',
|
|
borderColor: shiftShuffle === 0 ? 'black' : 'var(--color-text-pri)',
|
|
transition: 'all 0.2s',
|
|
}}
|
|
>
|
|
<FiShuffle
|
|
onClick={() => {
|
|
const themeList = JSON.parse(
|
|
themePlaylists.find(
|
|
(t: ThemePlaylist) => t.name === currentThemePlaylist,
|
|
).themeList,
|
|
);
|
|
const filteredThemes = allThemes.filter((t: any) =>
|
|
themeList.includes(t.id),
|
|
);
|
|
handleThemeChange(filteredThemes, false);
|
|
}}
|
|
style={{
|
|
fontSize: '2em',
|
|
fontWeight: 'bold',
|
|
color: shiftShuffle === 0 ? 'black' : 'var(--color-text-pri)',
|
|
}}
|
|
/>
|
|
</Group>
|
|
</Group>
|
|
) : (
|
|
<Stack
|
|
gap={0}
|
|
style={{
|
|
zIndex: 2,
|
|
padding: '4px',
|
|
paddingRight: '0px',
|
|
position: 'absolute',
|
|
right: 3,
|
|
backgroundColor: '#ffffff88',
|
|
borderTopLeftRadius: '10px',
|
|
borderBottomLeftRadius: '10px',
|
|
}}
|
|
align='center'
|
|
justify='center'
|
|
display={
|
|
currentTheme === 'random' && cardTheme.name === theme.name ? 'none' : 'flex'
|
|
}
|
|
>
|
|
<ActionIcon
|
|
style={{
|
|
background: cardTheme.randomEnabled
|
|
? 'rgba(255,255,255,1)'
|
|
: 'rgba(255,255,255,0.5)',
|
|
margin: '2px',
|
|
}}
|
|
styles={{
|
|
root: {
|
|
height: '10px',
|
|
width: '10px',
|
|
},
|
|
icon: {
|
|
height: '20px',
|
|
width: '20px',
|
|
fontSize: '24px',
|
|
margin: 0,
|
|
padding: 0,
|
|
},
|
|
}}
|
|
onClick={() => {
|
|
mutateAsync({
|
|
method: 'PATCH',
|
|
endpoint: 'api/themes',
|
|
body: { ...cardTheme, randomEnabled: !cardTheme.randomEnabled },
|
|
});
|
|
}}
|
|
>
|
|
{cardTheme.randomEnabled ? <FiShuffle color='green' /> : <FiX color='red' />}
|
|
</ActionIcon>
|
|
<ActionIcon
|
|
className={actionIconClasses.themeEditButton}
|
|
classNames={actionIconClasses}
|
|
onClick={() => handleOpen(cardTheme)}
|
|
mb={2}
|
|
>
|
|
<FiEdit color='green' />
|
|
</ActionIcon>
|
|
<ActionIcon
|
|
className={actionIconClasses.themeEditButton}
|
|
classNames={actionIconClasses}
|
|
onClick={openModal}
|
|
>
|
|
<FiTrash color='red' />
|
|
</ActionIcon>
|
|
</Stack>
|
|
)}
|
|
</Group>
|
|
);
|
|
}
|
|
|
|
export default ThemeCard;
|