feat(api): image favoriting (#67)
This commit is contained in:
parent
53c53c009e
commit
e8b82ffe62
8 changed files with 66 additions and 12 deletions
|
@ -10,7 +10,6 @@
|
|||
"start": "node server",
|
||||
"lint": "next lint",
|
||||
"ts-node": "ts-node --compiler-options \"{\\\"module\\\":\\\"commonjs\\\"}\" --transpile-only",
|
||||
"create-all-migrations": "node scripts/create-migrations",
|
||||
"semantic-release": "semantic-release"
|
||||
},
|
||||
"dependencies": {
|
||||
|
|
2
prisma/migrations/20210827202147_favorite/migration.sql
Normal file
2
prisma/migrations/20210827202147_favorite/migration.sql
Normal file
|
@ -0,0 +1,2 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "Image" ADD COLUMN "favorite" BOOLEAN NOT NULL DEFAULT false;
|
|
@ -42,6 +42,7 @@ model Image {
|
|||
mimetype String @default("image/png")
|
||||
created_at DateTime @default(now())
|
||||
views Int @default(0)
|
||||
favorite Boolean @default(false)
|
||||
invisible InvisibleImage?
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
userId Int
|
||||
|
|
|
@ -16,7 +16,7 @@ export default function Image({ image, updateImages }) {
|
|||
|
||||
const handleDelete = async () => {
|
||||
const res = await useFetch('/api/user/images', 'DELETE', { id: image.id });
|
||||
if (!res.error) updateImages();
|
||||
if (!res.error) updateImages(true);
|
||||
|
||||
setAnchorEl(null);
|
||||
};
|
||||
|
@ -26,6 +26,11 @@ export default function Image({ image, updateImages }) {
|
|||
setAnchorEl(null);
|
||||
};
|
||||
|
||||
const handleFavorite = async () => {
|
||||
const data = await useFetch('/api/user/images', 'PATCH', { id: image.id, favorite: !image.favorite });
|
||||
if (!data.error) updateImages(true);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Card sx={{ maxWidth: '100%' }}>
|
||||
|
@ -54,6 +59,7 @@ export default function Image({ image, updateImages }) {
|
|||
<ButtonGroup variant='contained'>
|
||||
<Button onClick={handleDelete} color='primary'>Delete</Button>
|
||||
<Button onClick={handleCopy} color='primary'>Copy URL</Button>
|
||||
<Button onClick={handleFavorite} color='primary'>{image.favorite ? 'Unfavorite' : 'Favorite'}</Button>
|
||||
</ButtonGroup>
|
||||
</Popover>
|
||||
</>
|
||||
|
|
|
@ -97,7 +97,7 @@ export default function Dashboard() {
|
|||
const imgs = await useFetch('/api/user/images');
|
||||
const stts = await useFetch('/api/stats');
|
||||
setImages(imgs);
|
||||
setStats(stts);console.log(stts);
|
||||
setStats(stts);
|
||||
|
||||
setApiLoading(false);
|
||||
};
|
||||
|
|
|
@ -1,30 +1,37 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { Grid, Pagination, Box, Typography } from '@material-ui/core';
|
||||
import { Grid, Pagination, Box, Typography, Accordion, AccordionSummary, AccordionDetails } from '@material-ui/core';
|
||||
|
||||
import Backdrop from 'components/Backdrop';
|
||||
import ZiplineImage from 'components/Image';
|
||||
import useFetch from 'hooks/useFetch';
|
||||
import { ExpandMore } from '@material-ui/icons';
|
||||
|
||||
export default function Upload() {
|
||||
const [pages, setPages] = useState([]);
|
||||
const [page, setPage] = useState(1);
|
||||
const [favoritePages, setFavoritePages] = useState([]);
|
||||
const [favoritePage, setFavoritePage] = useState(1);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
const updatePages = async () => {
|
||||
const updatePages = async favorite => {
|
||||
setLoading(true);
|
||||
const pages = await useFetch('/api/user/images?paged=true&filter=image');
|
||||
if (favorite) {
|
||||
const fPages = await useFetch('/api/user/images?paged=true&favorite=true');
|
||||
setFavoritePages(fPages);
|
||||
}
|
||||
setPages(pages);
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
updatePages();
|
||||
updatePages(true);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Backdrop open={loading}/>
|
||||
{!pages.length && (
|
||||
{!pages.length ? (
|
||||
<Box
|
||||
display='flex'
|
||||
justifyContent='center'
|
||||
|
@ -34,7 +41,33 @@ export default function Upload() {
|
|||
>
|
||||
<Typography variant='h4'>No Images</Typography>
|
||||
</Box>
|
||||
)}
|
||||
) : <Typography variant='h4'>Images</Typography>}
|
||||
{favoritePages.length ? (
|
||||
<Accordion sx={{ my: 2, border: 1, borderColor: t => t.palette.divider }} elevation={0}>
|
||||
<AccordionSummary expandIcon={<ExpandMore />}>
|
||||
<Typography variant='h4'>Favorite Images</Typography>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<Grid container spacing={2}>
|
||||
{favoritePages.length ? favoritePages[(favoritePage - 1) ?? 0].map(image => (
|
||||
<Grid item xs={12} sm={3} key={image.id}>
|
||||
<ZiplineImage image={image} updateImages={() => updatePages(true)} />
|
||||
</Grid>
|
||||
)) : null}
|
||||
</Grid>
|
||||
{favoritePages.length ? (
|
||||
<Box
|
||||
display='flex'
|
||||
justifyContent='center'
|
||||
alignItems='center'
|
||||
pt={2}
|
||||
>
|
||||
<Pagination count={favoritePages.length} page={favoritePage} onChange={(_, v) => setFavoritePage(v)}/>
|
||||
</Box>
|
||||
) : null}
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
) : null}
|
||||
<Grid container spacing={2}>
|
||||
{pages.length ? pages[(page - 1) ?? 0].map(image => (
|
||||
<Grid item xs={12} sm={3} key={image.id}>
|
||||
|
@ -42,7 +75,6 @@ export default function Upload() {
|
|||
</Grid>
|
||||
)) : null}
|
||||
</Grid>
|
||||
|
||||
{pages.length ? (
|
||||
<Box
|
||||
display='flex'
|
||||
|
|
|
@ -142,7 +142,6 @@ export default function Manage() {
|
|||
setLoading(true);
|
||||
|
||||
const newUser = await useFetch('/api/user', 'PATCH', { customTheme: values });
|
||||
console.log(newUser);
|
||||
|
||||
if (newUser.error) {
|
||||
setLoading(false);
|
||||
|
|
|
@ -23,17 +23,32 @@ async function handler(req: NextApiReq, res: NextApiRes) {
|
|||
|
||||
Logger.get('image').info(`User ${user.username} (${user.id}) deleted an image ${image.file} (${image.id})`);
|
||||
|
||||
return res.json(image);
|
||||
} else if (req.method === 'PATCH') {
|
||||
if (!req.body.id) return res.error('no file id');
|
||||
|
||||
let image;
|
||||
|
||||
if (req.body.favorite !== null) image = await prisma.image.update({
|
||||
where: { id: req.body.id },
|
||||
data: {
|
||||
favorite: req.body.favorite
|
||||
}
|
||||
});
|
||||
|
||||
return res.json(image);
|
||||
} else {
|
||||
let images = await prisma.image.findMany({
|
||||
where: {
|
||||
userId: user.id
|
||||
userId: user.id,
|
||||
favorite: !!req.query.favorite
|
||||
},
|
||||
select: {
|
||||
created_at: true,
|
||||
file: true,
|
||||
mimetype: true,
|
||||
id: true
|
||||
id: true,
|
||||
favorite: true
|
||||
}
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue