Skip to content

Commit

Permalink
feat: use mantine
Browse files Browse the repository at this point in the history
* refactor: use mantine

* feat: add library page

* feat: add library

* fix: remove logging
  • Loading branch information
oae authored Oct 6, 2022
1 parent 90c831c commit 2ba146b
Show file tree
Hide file tree
Showing 41 changed files with 1,474 additions and 1,089 deletions.
3 changes: 2 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"plugin:react/jsx-runtime"
],
"rules": {
"react/jsx-props-no-spreading": "off",
"no-underscore-dangle": "off",
"import/extensions": [
"error",
Expand All @@ -32,4 +33,4 @@
}
]
}
}
}
2 changes: 1 addition & 1 deletion next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ function defineNextConfig(config) {
}

export default defineNextConfig({
reactStrictMode: true,
reactStrictMode: false,
swcMinify: true,
// Next.js i18n docs: https://nextjs.org/docs/advanced-features/i18n-routing
i18n: {
Expand Down
13 changes: 10 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,16 @@
"dependencies": {
"@bull-board/api": "^4.3.2",
"@bull-board/express": "^4.3.2",
"@elastic/datemath": "^5.0.3",
"@elastic/eui": "^68.0.0",
"@emotion/cache": "^11.10.3",
"@emotion/react": "^11.10.4",
"@emotion/server": "^11.10.0",
"@mantine/core": "^5.5.4",
"@mantine/form": "^5.5.4",
"@mantine/hooks": "^5.5.4",
"@mantine/modals": "^5.5.4",
"@mantine/next": "^5.5.4",
"@mantine/notifications": "^5.5.4",
"@mantine/nprogress": "^5.5.4",
"@mantine/spotlight": "^5.5.4",
"@prisma/client": "4.4.0",
"@tanstack/react-query": "^4.9.0",
"@trpc/client": "^10.0.0-proxy-beta.13",
Expand All @@ -59,6 +65,7 @@
"react-dom": "18.2.0",
"react-icons": "^4.4.0",
"react-no-ssr": "^1.1.0",
"sharp": "^0.31.1",
"superjson": "^1.10.0",
"yaml": "^2.1.2",
"zod": "^3.19.1"
Expand Down
2 changes: 1 addition & 1 deletion postcss.config.mjs → postcss.config.cjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export default {
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
Expand Down
Binary file removed prisma/kaizoku.db-journal
Binary file not shown.
9 changes: 0 additions & 9 deletions prisma/migrations/20221002232213_init/migration.sql

This file was deleted.

17 changes: 17 additions & 0 deletions prisma/migrations/20221006210146_init/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
-- CreateTable
CREATE TABLE "Library" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"path" TEXT NOT NULL
);

-- CreateTable
CREATE TABLE "Manga" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"title" TEXT NOT NULL,
"cover" TEXT NOT NULL,
"interval" TEXT NOT NULL,
"source" TEXT NOT NULL,
"query" TEXT NOT NULL,
"libraryId" INTEGER,
CONSTRAINT "Manga_libraryId_fkey" FOREIGN KEY ("libraryId") REFERENCES "Library" ("id") ON DELETE SET NULL ON UPDATE CASCADE
);
20 changes: 14 additions & 6 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,19 @@ datasource db {
url = "file:./kaizoku.db"
}

model Library {
id Int @id @default(autoincrement())
path String
mangas Manga[]
}

model Manga {
id Int @id @default(autoincrement())
title String
cover String
interval String
source String
query String
id Int @id @default(autoincrement())
title String
cover String
interval String
source String
query String
Library Library? @relation(fields: [libraryId], references: [id])
libraryId Int?
}
Binary file modified public/favicon.ico
Binary file not shown.
Binary file added public/kaizoku.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/ninja-naruto.regular.woff
Binary file not shown.
115 changes: 115 additions & 0 deletions src/components/addLibrary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { Box, Button, Code, LoadingOverlay, Text, TextInput } from '@mantine/core';
import { useForm } from '@mantine/form';
import { useModals } from '@mantine/modals';
import { showNotification } from '@mantine/notifications';
import { useState } from 'react';
import { IoCloseCircle } from 'react-icons/io5';
import { MdCheckCircleOutline, MdOutlineCreateNewFolder } from 'react-icons/md';
import { trpc } from '../utils/trpc';

function Form({ onClose }: { onClose: () => void }) {
const [visible, setVisible] = useState(false);

const libraryMutation = trpc.library.create.useMutation();

const form = useForm({
initialValues: {
library: {
path: '',
},
},
validate: {
library: {
path: (value) => (value.trim().length === 0 ? 'Path cannot be empty' : null),
},
},
});

return (
<form
onSubmit={form.onSubmit(async (values) => {
setVisible((v) => !v);
try {
await libraryMutation.mutateAsync({
path: values.library.path,
});
} catch (err) {
showNotification({
icon: <IoCloseCircle size={48} />,
color: 'red',
autoClose: true,
title: 'Library',
message: (
<Text>
Failed to create library. <Code color="red">{`${err}`}</Code>
</Text>
),
});

form.reset();
onClose();
setVisible((v) => !v);
return;
}
form.reset();
onClose();
setVisible((v) => !v);
showNotification({
icon: <MdCheckCircleOutline size={48} />,
color: 'teal',
autoClose: true,
title: 'Library',
message: (
<Text>
Library is created at <Code color="blue">{values.library.path}</Code>
</Text>
),
});
})}
>
<LoadingOverlay visible={visible} overlayBlur={2} />
<TextInput label="Library path" placeholder="./library" {...form.getInputProps('library.path')} />

<Box
sx={(theme) => ({
display: 'flex',
gap: theme.spacing.xs,
justifyContent: 'end',
marginTop: theme.spacing.md,
})}
>
<Button
variant="white"
color="red"
onClick={() => {
form.reset();
onClose();
}}
>
Cancel
</Button>
<Button type="submit" variant="light" color="cyan">
Create
</Button>
</Box>
</form>
);
}

export function AddLibrary() {
const modals = useModals();

const openCreateModal = () => {
const id = modals.openModal({
title: 'Create a Library',
centered: true,
children: <Form onClose={() => modals.closeModal(id)} />,
});
};

return (
<Button type="submit" onClick={openCreateModal} leftIcon={<MdOutlineCreateNewFolder size={20} />}>
Create a library
</Button>
);
}
29 changes: 29 additions & 0 deletions src/components/emptyPrompt.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Center, createStyles, Stack, Text, Title } from '@mantine/core';
import { BiBookContent } from 'react-icons/bi';
import { AddLibrary } from './addLibrary';

const useStyles = createStyles((theme) => ({
root: {
height: '100%',
},
description: {
color: theme.colors.gray[6],
},
}));

export function EmptyPrompt() {
const { classes } = useStyles();

return (
<Center className={classes.root}>
<Stack justify="center" align="center" spacing={10}>
<BiBookContent size={48} />
<Title>No library found</Title>
<Text size="sm" className={classes.description}>
To be able to add new manga, you need to create a library
</Text>
<AddLibrary />
</Stack>
</Center>
);
}
116 changes: 116 additions & 0 deletions src/components/header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import { Center, Container, createStyles, Group, Header, Menu, Title, UnstyledButton } from '@mantine/core';
import { NextLink } from '@mantine/next';
import Image from 'next/image';
import Link from 'next/link';
import { AiOutlineDown } from 'react-icons/ai';

const useStyles = createStyles((theme) => ({
header: {
backgroundColor: theme.colors.red[8],
borderBottom: 0,
boxShadow: theme.shadows.xl,
},

inner: {
height: 56,
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
},

title: {
fontFamily: 'Ninja Naruto Regular',
lineHeight: 56,
fontWeight: 300,
marginTop: 10,
color: theme.colors.gray[0],
},

links: {},

link: {
display: 'block',
lineHeight: 1,
padding: '8px 12px',
borderRadius: theme.radius.sm,
textDecoration: 'none',
color: theme.white,
fontSize: theme.fontSizes.sm,
fontWeight: 500,

'&:hover': {
backgroundColor: theme.fn.lighten(theme.colors.red[8], 0.2),
},
},

linkLabel: {
marginRight: 5,
},
}));

interface HeaderSearchProps {
links: { link: string; label: string; links?: { link: string; label: string }[] }[];
}

export function KaizokuHeader({ links }: HeaderSearchProps) {
const { classes } = useStyles();

const items = links.map((link) => {
const menuItems = link.links?.map((item) => <Menu.Item key={item.link}>{item.label}</Menu.Item>);

if (menuItems) {
return (
<Menu key={link.label} trigger="hover" exitTransitionDuration={0}>
<Menu.Target>
<a href={link.link} className={classes.link} onClick={(event) => event.preventDefault()}>
<Center>
<span className={classes.linkLabel}>{link.label}</span>
<AiOutlineDown size={12} strokeWidth={1.5} />
</Center>
</a>
</Menu.Target>
<Menu.Dropdown>{menuItems}</Menu.Dropdown>
</Menu>
);
}

return (
<NextLink target="_blank" key={link.label} href={link.link} className={classes.link}>
{link.label}
</NextLink>
);
});

return (
<Header height={56} className={classes.header} mb={120}>
<Container fluid>
<div className={classes.inner}>
<Link href="/">
<UnstyledButton component="a">
<Group spacing={10}>
<Image src="/kaizoku.png" height={48} width={48} />
<Title order={2} className={classes.title}>
Kaizoku
</Title>
</Group>
</UnstyledButton>
</Link>
<Group spacing={5} className={classes.links}>
{items}
</Group>
</div>
</Container>
</Header>
);
}

export const KaizokuLinks = [
{
link: '/admin/queues/queue/downloadQue?status=completed',
label: 'Downloads',
},
{
link: '/',
label: 'Settings',
},
];
Loading

0 comments on commit 2ba146b

Please sign in to comment.