Add project base

This commit is contained in:
Aj - Thomas
2022-04-25 00:11:32 +02:00
parent c2c4f3a9d1
commit 56b42668a8
11 changed files with 568 additions and 124 deletions

View File

@@ -0,0 +1,134 @@
import React, { useState } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import {
ActionIcon,
createStyles,
Grid,
Group,
Text,
Title,
Paper,
Tooltip,
Image,
ThemeIcon,
useMantineTheme,
Anchor,
Box,
Menu,
AspectRatio,
} from '@mantine/core';
import { ArrowBack, Trash } from 'tabler-icons-react';
const AppShelf = () => {
const Services = loadServices();
const [hovering, setHovering] = useState('none');
const theme = useMantineTheme();
return (
<Grid m={'xl'} gutter={'xl'}>
{Services.map((service, i) => (
<Grid.Col span={4} lg={2} sm={3} key={i}>
<motion.div
onHoverStart={(e) => {
setHovering(service.name);
}}
onHoverEnd={(e) => {
setHovering('none');
}}
>
<AspectRatio ratio={4 / 3}>
<Box
sx={(theme) => ({
backgroundColor:
theme.colorScheme === 'dark' ? theme.colors.dark[6] : theme.colors.gray[0],
textAlign: 'center',
padding: theme.spacing.xl,
borderRadius: theme.radius.md,
'&:hover': {
backgroundColor:
theme.colorScheme === 'dark' ? theme.colors.dark[5] : theme.colors.gray[1],
},
})}
>
<motion.div animate={{opacity: hovering == service.name ? 1 : 0}}>
<Menu sx={{ position: 'absolute', top: 3, right: 3 }}>
<Menu.Label>Settings</Menu.Label>
<Menu.Label>Danger zone</Menu.Label>
<Menu.Item color="red" icon={<Trash size={14} />}>
Delete
</Menu.Item>
</Menu>
</motion.div>
<Group position="center">
<Anchor href={service.url} target="_blank">
<motion.div whileHover={{ scale: 1.2 }}>
<Image height={60} src={service.icon} alt={service.name} />
</motion.div>
</Anchor>
<Text>{service.name}</Text>
</Group>
</Box>
</AspectRatio>
</motion.div>
</Grid.Col>
))}
</Grid>
);
};
export default AppShelf;
function loadServices() {
return [
{
name: 'Radarr',
icon: 'https://cdn.jsdelivr.net/gh/IceWhaleTech/CasaOS-AppStore@main/Apps/Radarr/icon.png',
url: 'http://server:7878/',
},
{
name: 'Sonarr',
icon: 'https://cdn.jsdelivr.net/gh/IceWhaleTech/CasaOS-AppStore@main/Apps/Sonarr/icon.png',
url: 'http://server:8989/',
},
{
name: 'Sonarr',
icon: 'https://cdn.jsdelivr.net/gh/IceWhaleTech/CasaOS-AppStore@main/Apps/Sonarr/icon.png',
url: 'http://server:8989/',
},
{
name: 'Sonarr',
icon: 'https://cdn.jsdelivr.net/gh/IceWhaleTech/CasaOS-AppStore@main/Apps/Sonarr/icon.png',
url: 'http://server:8989/',
},
{
name: 'Sonarr',
icon: 'https://cdn.jsdelivr.net/gh/IceWhaleTech/CasaOS-AppStore@main/Apps/Sonarr/icon.png',
url: 'http://server:8989/',
},
{
name: 'Sonarr',
icon: 'https://cdn.jsdelivr.net/gh/IceWhaleTech/CasaOS-AppStore@main/Apps/Sonarr/icon.png',
url: 'http://server:8989/',
},
{
name: 'Sonarr',
icon: 'https://cdn.jsdelivr.net/gh/IceWhaleTech/CasaOS-AppStore@main/Apps/Sonarr/icon.png',
url: 'http://server:8989/',
},
{
name: 'Sonarr',
icon: 'https://cdn.jsdelivr.net/gh/IceWhaleTech/CasaOS-AppStore@main/Apps/Sonarr/icon.png',
url: 'http://server:8989/',
},
{
name: 'Sonarr',
icon: 'https://cdn.jsdelivr.net/gh/IceWhaleTech/CasaOS-AppStore@main/Apps/Sonarr/icon.png',
url: 'http://server:8989/',
},
{
name: 'Sonarr',
icon: 'https://cdn.jsdelivr.net/gh/IceWhaleTech/CasaOS-AppStore@main/Apps/Sonarr/icon.png',
url: 'http://server:8989/',
},
];
}

View File

@@ -1,26 +1,28 @@
import { ActionIcon, Group, useMantineColorScheme } from '@mantine/core';
import { SunIcon, MoonIcon } from '@modulz/radix-icons';
import { ActionIcon, useMantineColorScheme } from '@mantine/core';
import { Sun, MoonStars } from 'tabler-icons-react';
import { motion } from 'framer-motion';
export function ColorSchemeToggle() {
const { colorScheme, toggleColorScheme } = useMantineColorScheme();
return (
<Group position="center" mt="xl">
<motion.div
whileHover={{ scale: 1.2, rotate: 90 }}
whileTap={{
scale: 0.8,
rotate: -90,
borderRadius: '100%',
}}
>
<ActionIcon
onClick={() => toggleColorScheme()}
size="xl"
sx={(theme) => ({
backgroundColor:
theme.colorScheme === 'dark' ? theme.colors.dark[6] : theme.colors.gray[0],
color: theme.colorScheme === 'dark' ? theme.colors.yellow[4] : theme.colors.blue[6],
})}
>
{colorScheme === 'dark' ? (
<SunIcon width={20} height={20} />
) : (
<MoonIcon width={20} height={20} />
)}
{colorScheme === 'dark' ? <Sun size={24} /> : <MoonStars size={24} />}
</ActionIcon>
</Group>
</motion.div>
);
}

View File

@@ -0,0 +1,82 @@
import React from 'react';
import { createStyles, Anchor, Text, Group, ActionIcon } from '@mantine/core';
import { BrandGithub, Phone, BrandGmail } from 'tabler-icons-react';
import { posix } from 'path';
const useStyles = createStyles((theme) => ({
footer: {
borderTop: `1px solid ${
theme.colorScheme === 'dark' ? theme.colors.dark[5] : theme.colors.gray[2]
}`,
},
inner: {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
padding: `${theme.spacing.md}px ${theme.spacing.md}px`,
[theme.fn.smallerThan('sm')]: {
flexDirection: 'column',
},
},
links: {
[theme.fn.smallerThan('sm')]: {
marginTop: theme.spacing.lg,
marginBottom: theme.spacing.sm,
},
},
}));
interface FooterCenteredProps {
links: { link: string; label: string }[];
}
export function Footer({ links }: FooterCenteredProps) {
const { classes } = useStyles();
const items = links.map((link) => (
<Anchor<'a'>
color="dimmed"
key={link.label}
href={link.link}
sx={{ lineHeight: 1 }}
onClick={(event) => event.preventDefault()}
size="sm"
>
{link.label}
</Anchor>
));
return (
<Group
sx={{
position: 'absolute',
bottom: 0,
right: 15,
}}
direction="row"
align="center"
mb={15}
>
<Group className={classes.links}>{items}</Group>
<Group spacing={'xs'} position="right" noWrap>
<ActionIcon<'a'> component="a" href={`https://github.com/ajnart/myhomepage`} size="lg">
<BrandGithub size={18} />
</ActionIcon>
</Group>
<Text
style={{
fontSize: '0.75rem',
textAlign: 'center',
color: '#a0aec0',
}}
>
Made with by @
<Anchor href="https://github.com/ajnart" style={{ color: 'inherit', fontStyle: 'inherit' }}>
ajnart
</Anchor>
</Text>
</Group>
);
}

View File

@@ -0,0 +1,146 @@
import React, { useState } from 'react';
import {
createStyles,
Header as Head,
Container,
Group,
Burger,
Paper,
Transition,
} from '@mantine/core';
import { useBooleanToggle } from '@mantine/hooks';
import { NextLink } from '@mantine/next';
import { Logo } from './Logo';
import { ColorSchemeToggle } from '../ColorSchemeToggle/ColorSchemeToggle';
const HEADER_HEIGHT = 60;
const useStyles = createStyles((theme) => ({
root: {
position: 'relative',
zIndex: 1,
},
dropdown: {
position: 'absolute',
top: HEADER_HEIGHT,
left: 0,
right: 0,
zIndex: 0,
borderTopRightRadius: 0,
borderTopLeftRadius: 0,
borderTopWidth: 0,
overflow: 'hidden',
[theme.fn.largerThan('sm')]: {
display: 'none',
},
},
header: {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
height: '100%',
},
links: {
[theme.fn.smallerThan('sm')]: {
display: 'none',
},
},
burger: {
[theme.fn.largerThan('sm')]: {
display: 'none',
},
},
link: {
display: 'block',
lineHeight: 1,
padding: '8px 12px',
borderRadius: theme.radius.sm,
textDecoration: 'none',
color: theme.colorScheme === 'dark' ? theme.colors.dark[0] : theme.colors.gray[7],
fontSize: theme.fontSizes.sm,
fontWeight: 500,
'&:hover': {
backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[6] : theme.colors.gray[0],
},
[theme.fn.smallerThan('sm')]: {
borderRadius: 0,
padding: theme.spacing.md,
},
},
linkActive: {
'&, &:hover': {
backgroundColor:
theme.colorScheme === 'dark'
? theme.fn.rgba(theme.colors[theme.primaryColor][9], 0.25)
: theme.colors[theme.primaryColor][0],
color: theme.colors[theme.primaryColor][theme.colorScheme === 'dark' ? 3 : 7],
},
},
}));
interface HeaderResponsiveProps {
links: { link: string; label: string }[];
}
export function Header({ links }: HeaderResponsiveProps) {
const [opened, toggleOpened] = useBooleanToggle(false);
const [active, setActive] = useState('/');
const { classes, cx } = useStyles();
const items = (
<>
{links.map((link) => (
<NextLink
key={link.label}
href={link.link}
className={cx(classes.link, { [classes.linkActive]: active === link.link })}
onClick={(event) => {
setActive(link.link);
toggleOpened(false);
}}
>
{link.label}
</NextLink>
))}
</>
);
return (
<Head height={HEADER_HEIGHT} mb={10} className={classes.root}>
<Container className={classes.header}>
<Group>
<ColorSchemeToggle />
<NextLink style={{ textDecoration: 'none' }} href="/">
<Logo style={{ fontSize: 22 }} />
</NextLink>
</Group>
<Group spacing={5} className={classes.links}>
{items}
</Group>
<Burger
opened={opened}
onClick={() => toggleOpened()}
className={classes.burger}
size="sm"
/>
<Transition transition="pop-top-right" duration={200} mounted={opened}>
{(styles) => (
<Paper className={classes.dropdown} withBorder style={{ zIndex: 99 }}>
{items}
</Paper>
)}
</Transition>
</Container>
</Head>
);
}

View File

@@ -0,0 +1,32 @@
import { AppShell, Center, createStyles } from '@mantine/core';
import { Header } from './Header';
import { Footer } from './Footer';
const useStyles = createStyles((theme) => ({
main: {
[theme.fn.smallerThan('md')]: {
maxWidth: '90vw',
},
[theme.fn.largerThan('md')]: {
width: 1200,
},
},
}));
export default function Layout({ children, style }: any) {
const { classes, cx } = useStyles();
return (
<AppShell header={<Header links={[]} />} footer={<Footer links={[]} />}>
<Center>
<main
className={cx(classes.main)}
style={{
...style,
}}
>
{children}
</main>
</Center>
</AppShell>
);
}

View File

@@ -0,0 +1,15 @@
import { Text } from '@mantine/core';
import * as React from 'react';
export function Logo({ style }: any) {
return (
<Text
sx={style}
weight="bold"
variant="gradient"
gradient={{ from: 'red', to: 'orange', deg: 145 }}
>
MyHomePage
</Text>
);
}