feat: image preview
This commit is contained in:
@@ -0,0 +1,114 @@
|
|||||||
|
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>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,69 +1,10 @@
|
|||||||
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 { createFileRoute } from "@tanstack/react-router";
|
||||||
import type { ChangeEvent } from "react";
|
import { AddOrEditAnnouncement } from "../../components/AddOrEditAnnouncement";
|
||||||
|
|
||||||
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/")({
|
export const Route = createFileRoute("/add/")({
|
||||||
component: RouteComponent,
|
component: RouteComponent,
|
||||||
});
|
});
|
||||||
|
|
||||||
function RouteComponent() {
|
function RouteComponent() {
|
||||||
return (
|
return <AddOrEditAnnouncement />;
|
||||||
<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"></TextField>
|
|
||||||
<FormLabel>Text:</FormLabel>
|
|
||||||
<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>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user