115 lines
2.7 KiB
TypeScript
115 lines
2.7 KiB
TypeScript
import CloudUploadIcon from "@mui/icons-material/CloudUpload";
|
|
import {
|
|
Button,
|
|
FormLabel,
|
|
TextareaAutosize,
|
|
TextField,
|
|
Typography,
|
|
} from "@mui/material";
|
|
import { Box, styled } from "@mui/system";
|
|
import { DatePicker } from "@mui/x-date-pickers";
|
|
import { type ChangeEvent, useState } from "react";
|
|
import type { Announcement } from "../services";
|
|
|
|
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 interface AddOrEditAnnouncementProps {
|
|
announcement?: Announcement;
|
|
}
|
|
|
|
function blobToDataURL(blob: Blob): Promise<string> {
|
|
return new Promise<string>((resolve, reject) => {
|
|
const reader = new FileReader();
|
|
reader.onload = (_e) => resolve(reader.result as string);
|
|
reader.onerror = (_e) => reject(reader.error);
|
|
reader.onabort = (_e) => reject(new Error("Read aborted"));
|
|
reader.readAsDataURL(blob);
|
|
});
|
|
}
|
|
|
|
export function AddOrEditAnnouncement({
|
|
announcement,
|
|
}: AddOrEditAnnouncementProps) {
|
|
const [currentImageUrl, setCurrentImageUrl] = useState<string | undefined>(
|
|
undefined,
|
|
);
|
|
|
|
return (
|
|
<Box
|
|
component="form"
|
|
encType="multipart/form-data"
|
|
action="/api/announcements"
|
|
method="POST"
|
|
sx={{
|
|
display: "flex",
|
|
flexDirection: "column",
|
|
"& > :not(style)": { m: 1, width: "25ch" },
|
|
}}
|
|
noValidate
|
|
autoComplete="off"
|
|
>
|
|
<TextField
|
|
name="title"
|
|
label="Title"
|
|
defaultValue={announcement?.title}
|
|
></TextField>
|
|
<FormLabel>Text:</FormLabel>
|
|
<TextareaAutosize
|
|
name="text"
|
|
minRows={6}
|
|
defaultValue={announcement?.text}
|
|
/>
|
|
<FormLabel>Publication Date:</FormLabel>
|
|
<DatePicker
|
|
name="publication_date"
|
|
defaultValue={
|
|
announcement ? new Date(announcement.publication_date) : undefined
|
|
}
|
|
/>
|
|
<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);
|
|
const file =
|
|
event.target.files && event.target.files.length > 0
|
|
? event.target.files[0]
|
|
: undefined;
|
|
if (file === undefined) {
|
|
setCurrentImageUrl(undefined);
|
|
return;
|
|
}
|
|
blobToDataURL(file).then(setCurrentImageUrl).catch(console.error);
|
|
}}
|
|
/>
|
|
</Button>
|
|
<Typography>Current image:</Typography>
|
|
{currentImageUrl ? (
|
|
<img src={currentImageUrl} alt="Current" />
|
|
) : (
|
|
<Typography>None</Typography>
|
|
)}
|
|
<Button variant="contained" type="submit">
|
|
Submit
|
|
</Button>
|
|
</Box>
|
|
);
|
|
}
|