mirror of
https://github.com/barthuijgen/factorio-sites.git
synced 2025-02-03 14:01:50 +02:00
This reverts commit a06c7533122cd7e663ceb49a08f351b24e4bff46.
This commit is contained in:
parent
a06c753312
commit
72c719e561
@ -1,93 +1,68 @@
|
||||
import { useState } from "react";
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
import styled from "@emotion/styled";
|
||||
import { css } from "@emotion/react";
|
||||
import { format } from "date-fns";
|
||||
import { Box, Text } from "@chakra-ui/react";
|
||||
import { MdFavorite, MdDeleteForever } from "react-icons/md";
|
||||
import { MdFavorite } from "react-icons/md";
|
||||
import { BlueprintPage } from "@factorio-sites/types";
|
||||
import { getLocaleDateFormat } from "@factorio-sites/web-utils";
|
||||
import clsx from "clsx";
|
||||
import { Button } from "./Button";
|
||||
|
||||
const StyledBlueprintLink = styled.div`
|
||||
display: flex;
|
||||
margin: 5px 0;
|
||||
const linkStyles = css`
|
||||
margin: 5px 10px 5px 0;
|
||||
background: #353535;
|
||||
|
||||
.link-box {
|
||||
width: 100%;
|
||||
height: 36px;
|
||||
margin-right: 5px;
|
||||
background-color: #313031;
|
||||
box-shadow: inset 3px 0 3px -3px #201815, inset 2px 0 2px -2px #201815,
|
||||
inset 1px 0 1px -1px #201815, inset 0 3px 3px -3px #8f8c8b, inset 0 2px 2px -2px #8f8c8b,
|
||||
inset 0 1px 1px -1px #8f8c8b, inset -3px 0 3px -3px #201815, inset -2px 0 2px -2px #201815,
|
||||
inset -2px 0 1px -1px #201815, inset 0 -3px 3px -3px #000, inset 0 -2px 2px -2px #000,
|
||||
inset 0 -1px 1px -1px #000, 0 0 2px 0 #201815, 0 0 4px 0 #201815;
|
||||
|
||||
.block {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.image {
|
||||
position: relative;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.details {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.title {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
a {
|
||||
display: block;
|
||||
padding: 5px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
background: #4c4c4c;
|
||||
}
|
||||
|
||||
&.tile {
|
||||
width: 210px;
|
||||
height: 232px;
|
||||
.block {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
.block {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.delete {
|
||||
padding: 2px;
|
||||
width: 36px;
|
||||
justify-content: center;
|
||||
.image {
|
||||
position: relative;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.details {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.title {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
a {
|
||||
display: block;
|
||||
padding: 5px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
background: #4c4c4c;
|
||||
}
|
||||
|
||||
&.tile {
|
||||
width: 210px;
|
||||
height: 232px;
|
||||
.block {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
interface BlueprintLinkProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
interface BlueprintLinkProps {
|
||||
blueprint: Pick<BlueprintPage, "id" | "title" | "image_hash" | "favorite_count" | "updated_at">;
|
||||
editLink?: boolean;
|
||||
type: "tile" | "row";
|
||||
onDelete?: (id: string) => void;
|
||||
disableDelete?: boolean;
|
||||
}
|
||||
|
||||
export const BlueprintLink: React.FC<BlueprintLinkProps> = ({
|
||||
blueprint,
|
||||
editLink,
|
||||
type = "tile",
|
||||
onDelete,
|
||||
disableDelete,
|
||||
className,
|
||||
}) => {
|
||||
const [imageError, setImageError] = useState(false);
|
||||
const onImageError = () => {
|
||||
@ -95,54 +70,44 @@ export const BlueprintLink: React.FC<BlueprintLinkProps> = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledBlueprintLink className={clsx("blueprint-link", type, className)}>
|
||||
<Box className="link-box">
|
||||
<Link
|
||||
href={editLink ? `/user/blueprint/${blueprint.id}` : `/blueprint/${blueprint.id}`}
|
||||
passHref
|
||||
>
|
||||
<a>
|
||||
<Box className="block">
|
||||
{type === "tile" && (
|
||||
<div className="image">
|
||||
{imageError ? (
|
||||
<div>The image is not generated yet, please be patient it will come soon.</div>
|
||||
) : (
|
||||
<Image
|
||||
loader={({ src }) => src}
|
||||
src={`https://storage.googleapis.com/blueprint-images/300/${blueprint.image_hash}.webp`}
|
||||
layout="fill"
|
||||
objectFit="contain"
|
||||
alt={blueprint.title}
|
||||
onError={onImageError}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<Box className="details">
|
||||
<Text css={{ display: "flex", alignItems: "center", marginRight: "1rem" }}>
|
||||
<MdFavorite css={{ marginRight: "5px" }} />
|
||||
{blueprint.favorite_count || "0"}
|
||||
</Text>
|
||||
<Text className="title">{blueprint.title}</Text>
|
||||
</Box>
|
||||
{type === "row" && (
|
||||
<Box>
|
||||
<Text>{format(blueprint.updated_at * 1000, getLocaleDateFormat(true))}</Text>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</a>
|
||||
</Link>
|
||||
</Box>
|
||||
<Button
|
||||
className="delete"
|
||||
danger
|
||||
disabled={disableDelete}
|
||||
onClick={() => onDelete?.(blueprint.id)}
|
||||
<div css={linkStyles} className={type}>
|
||||
<Link
|
||||
href={editLink ? `/user/blueprint/${blueprint.id}` : `/blueprint/${blueprint.id}`}
|
||||
passHref
|
||||
>
|
||||
<MdDeleteForever size={18} />
|
||||
</Button>
|
||||
</StyledBlueprintLink>
|
||||
<a>
|
||||
<Box className="block">
|
||||
{type === "tile" && (
|
||||
<div className="image">
|
||||
{imageError ? (
|
||||
<div>The image is not generated yet, please be patient it will come soon.</div>
|
||||
) : (
|
||||
<Image
|
||||
loader={({ src }) => src}
|
||||
src={`https://storage.googleapis.com/blueprint-images/300/${blueprint.image_hash}.webp`}
|
||||
layout="fill"
|
||||
objectFit="contain"
|
||||
alt={blueprint.title}
|
||||
onError={onImageError}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<Box className="details">
|
||||
<Text css={{ display: "flex", alignItems: "center", marginRight: "1rem" }}>
|
||||
<MdFavorite css={{ marginRight: "5px" }} />
|
||||
{blueprint.favorite_count || "0"}
|
||||
</Text>
|
||||
<Text className="title">{blueprint.title}</Text>
|
||||
</Box>
|
||||
{type === "row" && (
|
||||
<Box>
|
||||
<Text>{format(blueprint.updated_at * 1000, getLocaleDateFormat(true))}</Text>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -4,18 +4,11 @@ import clsx from "clsx";
|
||||
|
||||
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
primary?: boolean;
|
||||
danger?: boolean;
|
||||
}
|
||||
|
||||
export const Button: React.FC<ButtonProps> = ({
|
||||
primary,
|
||||
danger,
|
||||
className,
|
||||
children,
|
||||
...props
|
||||
}) => {
|
||||
export const Button: React.FC<ButtonProps> = ({ primary, className, children, ...props }) => {
|
||||
return (
|
||||
<StyledButton className={clsx({ primary, danger }, className)} {...props}>
|
||||
<StyledButton className={clsx({ primary }, className)} {...props}>
|
||||
{children}
|
||||
</StyledButton>
|
||||
);
|
||||
|
@ -1,33 +0,0 @@
|
||||
import { deleteBlueprintPage, getBlueprintPageById } from "@factorio-sites/database";
|
||||
import { parseDatabaseError } from "../../../../utils/api.utils";
|
||||
import { apiHandler } from "../../../../utils/api-handler";
|
||||
|
||||
const handler = apiHandler(async (req, res, { session }) => {
|
||||
if (req.method !== "DELETE") return res.status(400).json({ error: "method must be DELETE" });
|
||||
|
||||
if (!session) return res.status(401).json({ status: "Not authenticated" });
|
||||
|
||||
const { id } = req.query;
|
||||
if (!id) return res.status(400).json({ status: "ID is required" });
|
||||
|
||||
const existing = await getBlueprintPageById(String(id));
|
||||
if (existing?.user_id !== session.user_id)
|
||||
return res.status(403).json({ status: "Unauthorised" });
|
||||
|
||||
try {
|
||||
await deleteBlueprintPage(String(id));
|
||||
return res.status(201).json({ success: true, id });
|
||||
} catch (err) {
|
||||
const insert_errors = parseDatabaseError(err);
|
||||
if (insert_errors) {
|
||||
if (insert_errors.blueprint_id || insert_errors.blueprint_book_id) {
|
||||
insert_errors.string = "This string already exists";
|
||||
}
|
||||
return res.status(400).json({ errors: insert_errors });
|
||||
}
|
||||
}
|
||||
|
||||
res.status(500).json({ status: "Failed to delete blueprint" });
|
||||
});
|
||||
|
||||
export default handler;
|
@ -1,4 +1,4 @@
|
||||
import React, { useState } from "react";
|
||||
import React from "react";
|
||||
import { NextPage } from "next";
|
||||
import Link from "next/link";
|
||||
import { SimpleGrid, Box } from "@chakra-ui/react";
|
||||
@ -8,55 +8,32 @@ import { pageHandler } from "../../utils/page-handler";
|
||||
import { BlueprintLink } from "../../components/BlueprintLink";
|
||||
import { Panel } from "../../components/Panel";
|
||||
import { Button } from "../../components/Button";
|
||||
|
||||
interface UserBlueprintsProps {
|
||||
blueprints: BlueprintPage[];
|
||||
}
|
||||
|
||||
export const UserBlueprints: NextPage<UserBlueprintsProps> = ({ blueprints: blueprintsProp }) => {
|
||||
const [blueprints, setBlueprints] = useState<BlueprintPage[]>(blueprintsProp);
|
||||
const [deleteId, setDeleteId] = useState<string | null>(null);
|
||||
export const UserBlueprints: NextPage<UserBlueprintsProps> = ({ blueprints }) => {
|
||||
if (!blueprints) return null;
|
||||
|
||||
const deleteBlueprint = async (id: string) => {
|
||||
setDeleteId(id);
|
||||
try {
|
||||
await fetch(`/api/blueprint/delete/${id}`, { method: "DELETE" });
|
||||
setBlueprints((blueprints) => blueprints.filter((bp) => bp.id !== id));
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
setDeleteId(null);
|
||||
};
|
||||
|
||||
return (
|
||||
<SimpleGrid columns={1} margin="0 auto" maxWidth="800px">
|
||||
<Panel title="Blueprints">
|
||||
<Link href="/user/blueprint-create">
|
||||
<a>
|
||||
<Button primary>Create Blueprint</Button>
|
||||
</a>
|
||||
</Link>
|
||||
<hr
|
||||
<Box
|
||||
css={{
|
||||
border: "none",
|
||||
height: "2px",
|
||||
margin: "12px auto",
|
||||
boxShadow: "inset 0 1px 1px 0 #131313, inset 0 -1px 1px 0 #838383, 0 0 4px 0 #392f2e",
|
||||
display: "flex",
|
||||
borderBottom: "1px solid #b7b7b7",
|
||||
paddingBottom: "0.3rem",
|
||||
}}
|
||||
/>
|
||||
>
|
||||
<Link href="/user/blueprint-create">
|
||||
<a>
|
||||
<Button primary>Create Blueprint</Button>
|
||||
</a>
|
||||
</Link>
|
||||
</Box>
|
||||
<Box>
|
||||
{blueprints.length !== 0 ? (
|
||||
blueprints.map((bp) => (
|
||||
<BlueprintLink
|
||||
key={bp.id}
|
||||
blueprint={bp}
|
||||
editLink
|
||||
type="row"
|
||||
onDelete={deleteBlueprint}
|
||||
disableDelete={deleteId === bp.id}
|
||||
/>
|
||||
))
|
||||
blueprints.map((bp) => <BlueprintLink key={bp.id} blueprint={bp} editLink type="row" />)
|
||||
) : (
|
||||
<p css={{ marginTop: "10px" }}>You don't have any blueprints yet</p>
|
||||
)}
|
||||
|
@ -261,12 +261,3 @@ export async function editBlueprintPage(
|
||||
console.log(`Updated Blueprint Page`);
|
||||
return page;
|
||||
}
|
||||
|
||||
export async function deleteBlueprintPage(blueprintPageId: string) {
|
||||
console.log("deleteBlueprintPage");
|
||||
console.log(blueprintPageId);
|
||||
|
||||
const result = await prisma.blueprint_page.delete({ where: { id: blueprintPageId } });
|
||||
|
||||
return result;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user