2022-05-24 20:15:07 +02:00
|
|
|
import { Text, Card, Anchor, AspectRatio, Image, Center, createStyles } from '@mantine/core';
|
2022-05-23 11:20:08 +02:00
|
|
|
import { motion } from 'framer-motion';
|
|
|
|
|
import { useState } from 'react';
|
|
|
|
|
import { useSortable } from '@dnd-kit/sortable';
|
|
|
|
|
import { CSS } from '@dnd-kit/utilities';
|
|
|
|
|
import { serviceItem } from '../../tools/types';
|
|
|
|
|
import PingComponent from '../modules/ping/PingModule';
|
|
|
|
|
import AppShelfMenu from './AppShelfMenu';
|
|
|
|
|
|
|
|
|
|
const useStyles = createStyles((theme) => ({
|
|
|
|
|
item: {
|
|
|
|
|
transition: 'box-shadow 150ms ease, transform 100ms ease',
|
|
|
|
|
|
|
|
|
|
'&:hover': {
|
|
|
|
|
boxShadow: `${theme.shadows.md} !important`,
|
|
|
|
|
transform: 'scale(1.05)',
|
|
|
|
|
},
|
2022-06-06 17:37:42 +02:00
|
|
|
[theme.fn.smallerThan('sm')]: {
|
|
|
|
|
WebkitUserSelect: 'none',
|
|
|
|
|
},
|
2022-05-23 11:20:08 +02:00
|
|
|
},
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
export function SortableAppShelfItem(props: any) {
|
|
|
|
|
const { attributes, listeners, setNodeRef, transform, transition } = useSortable({
|
|
|
|
|
id: props.id,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const style = {
|
|
|
|
|
transform: CSS.Transform.toString(transform),
|
|
|
|
|
transition,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div ref={setNodeRef} style={style} {...attributes} {...listeners}>
|
|
|
|
|
<AppShelfItem service={props.service} />
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function AppShelfItem(props: any) {
|
|
|
|
|
const { service }: { service: serviceItem } = props;
|
|
|
|
|
const [hovering, setHovering] = useState(false);
|
2022-06-06 17:37:42 +02:00
|
|
|
const { classes } = useStyles();
|
2022-05-23 11:20:08 +02:00
|
|
|
return (
|
|
|
|
|
<motion.div
|
|
|
|
|
animate={{
|
|
|
|
|
scale: [0.9, 1.06, 1],
|
|
|
|
|
rotate: [0, 5, 0],
|
|
|
|
|
}}
|
|
|
|
|
transition={{ duration: 0.6, type: 'spring', damping: 10, mass: 0.75, stiffness: 100 }}
|
|
|
|
|
key={service.name}
|
|
|
|
|
onHoverStart={() => {
|
|
|
|
|
setHovering(true);
|
|
|
|
|
}}
|
|
|
|
|
onHoverEnd={() => {
|
|
|
|
|
setHovering(false);
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<Card withBorder radius="lg" shadow="md" className={classes.item}>
|
|
|
|
|
<Card.Section>
|
|
|
|
|
<Anchor
|
|
|
|
|
target="_blank"
|
|
|
|
|
href={service.url}
|
|
|
|
|
style={{ color: 'inherit', fontStyle: 'inherit', fontSize: 'inherit' }}
|
|
|
|
|
>
|
|
|
|
|
<Text mt="sm" align="center" lineClamp={1} weight={550}>
|
|
|
|
|
{service.name}
|
|
|
|
|
</Text>
|
|
|
|
|
</Anchor>
|
|
|
|
|
<motion.div
|
|
|
|
|
style={{
|
|
|
|
|
position: 'absolute',
|
|
|
|
|
top: 15,
|
|
|
|
|
right: 15,
|
|
|
|
|
alignSelf: 'flex-end',
|
|
|
|
|
}}
|
|
|
|
|
animate={{
|
|
|
|
|
opacity: hovering ? 1 : 0,
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<AppShelfMenu service={service} />
|
|
|
|
|
</motion.div>
|
|
|
|
|
</Card.Section>
|
|
|
|
|
<Center>
|
|
|
|
|
<Card.Section>
|
|
|
|
|
<AspectRatio
|
|
|
|
|
ratio={3 / 5}
|
|
|
|
|
m="xl"
|
|
|
|
|
style={{
|
|
|
|
|
width: 150,
|
|
|
|
|
height: 90,
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<motion.i
|
|
|
|
|
whileHover={{
|
|
|
|
|
scale: 1.1,
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<Image
|
2022-06-01 19:53:57 +02:00
|
|
|
styles={{ root: { cursor: 'pointer' } }}
|
2022-05-23 11:20:08 +02:00
|
|
|
width={80}
|
|
|
|
|
height={80}
|
|
|
|
|
src={service.icon}
|
|
|
|
|
fit="contain"
|
|
|
|
|
onClick={() => {
|
2022-06-06 18:26:29 +02:00
|
|
|
if (service.openedUrl) window.open(service.openedUrl, '_blank');
|
|
|
|
|
else window.open(service.url);
|
2022-05-23 11:20:08 +02:00
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
</motion.i>
|
|
|
|
|
</AspectRatio>
|
|
|
|
|
<PingComponent url={service.url} />
|
|
|
|
|
</Card.Section>
|
|
|
|
|
</Center>
|
|
|
|
|
</Card>
|
|
|
|
|
</motion.div>
|
|
|
|
|
);
|
|
|
|
|
}
|