feat: add entries
This commit is contained in:
@@ -1,6 +1,27 @@
|
||||
import { Box, FormLabel, TextareaAutosize, TextField } from "@mui/material";
|
||||
import CloudUploadIcon from "@mui/icons-material/CloudUpload";
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
FormLabel,
|
||||
styled,
|
||||
TextareaAutosize,
|
||||
TextField,
|
||||
} from "@mui/material";
|
||||
import { DatePicker } from "@mui/x-date-pickers";
|
||||
import { createFileRoute } from "@tanstack/react-router";
|
||||
import type { ChangeEvent } from "react";
|
||||
|
||||
const VisuallyHiddenInput = styled("input")({
|
||||
clip: "rect(0 0 0 0)",
|
||||
clipPath: "inset(50%)",
|
||||
height: 1,
|
||||
overflow: "hidden",
|
||||
position: "absolute",
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
whiteSpace: "nowrap",
|
||||
width: 1,
|
||||
});
|
||||
|
||||
export const Route = createFileRoute("/add/")({
|
||||
component: RouteComponent,
|
||||
@@ -10,6 +31,9 @@ function RouteComponent() {
|
||||
return (
|
||||
<Box
|
||||
component="form"
|
||||
enctype="multipart/form-data"
|
||||
action="/api/announcements/add"
|
||||
method="POST"
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
@@ -18,10 +42,28 @@ function RouteComponent() {
|
||||
noValidate
|
||||
autoComplete="off"
|
||||
>
|
||||
<TextField label="Title"></TextField>
|
||||
<TextField name="title" label="Title"></TextField>
|
||||
<FormLabel>Text:</FormLabel>
|
||||
<TextareaAutosize minRows={6}></TextareaAutosize>
|
||||
<DatePicker />
|
||||
<TextareaAutosize name="text" minRows={6}></TextareaAutosize>
|
||||
<DatePicker name="publication_date" />
|
||||
<Button
|
||||
component="label"
|
||||
variant="contained"
|
||||
tabIndex={-1}
|
||||
startIcon={<CloudUploadIcon />}
|
||||
>
|
||||
Upload files
|
||||
<VisuallyHiddenInput
|
||||
type="file"
|
||||
name="image"
|
||||
onChange={(event: ChangeEvent<HTMLInputElement>) =>
|
||||
console.log(event.target.files)
|
||||
}
|
||||
/>
|
||||
</Button>
|
||||
<Button variant="contained" type="submit">
|
||||
Submit
|
||||
</Button>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ export interface AnnouncementTable {
|
||||
title: string;
|
||||
text: string;
|
||||
image: string;
|
||||
publication_date: Date;
|
||||
publication_date: string;
|
||||
}
|
||||
|
||||
export type Announcement = Selectable<AnnouncementTable>;
|
||||
|
||||
@@ -1,13 +1,44 @@
|
||||
import express from "express";
|
||||
import multer from "multer";
|
||||
import ViteExpress from "vite-express";
|
||||
import z from "zod";
|
||||
import { db } from "./db/database.js";
|
||||
|
||||
const upload = multer({
|
||||
dest: "uploads/",
|
||||
});
|
||||
|
||||
const app = express();
|
||||
|
||||
const AddInput = z.object({
|
||||
file: z.object({ filename: z.string() }),
|
||||
body: z.object({
|
||||
publication_date: z.coerce
|
||||
.date()
|
||||
.transform((x) => new Date(x).toISOString()),
|
||||
title: z.string().nonempty(),
|
||||
text: z.string().nonempty(),
|
||||
}),
|
||||
});
|
||||
|
||||
app.get("/hello", (_, res) => {
|
||||
res.send("Hello Vite + React + TypeScript!");
|
||||
});
|
||||
|
||||
app.post("/api/announcements/add", upload.single("image"), async (req, res) => {
|
||||
const addInput = AddInput.parse(req);
|
||||
await db
|
||||
.insertInto("announcements")
|
||||
.values({
|
||||
title: addInput.body.title,
|
||||
text: addInput.body.text,
|
||||
publication_date: addInput.body.publication_date,
|
||||
image: addInput.file.filename,
|
||||
})
|
||||
.execute();
|
||||
res.redirect("/");
|
||||
});
|
||||
|
||||
app.get("/api/announcements", async (_, res) => {
|
||||
// await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
const announcements = await db
|
||||
|
||||
Reference in New Issue
Block a user