Implement the (mostly) functional side of things

This commit is contained in:
powermaker450 2024-08-29 03:19:21 +00:00
parent 0f4955c5b5
commit 40f4520458
3 changed files with 134 additions and 13 deletions

View file

@ -1,26 +1,112 @@
import { Alert, Collapse, Rating, Typography } from "@mui/material";
import "./App.css"; import "./App.css";
import ButtonRow, { ActionProps } from "./components/ButtonRow"; import ButtonRow, { ActionProps } from "./components/ButtonRow";
import ReviewField from "./components/ReviewField"; import ReviewField, { ReviewFieldProps } from "./components/ReviewField";
import { useState } from "react";
function App() { function App() {
const [rating, setNewRating] = useState<number | null>(0);
const [showAlert, changeAlert] = useState(false);
const [alertText, changeAlertText] = useState("");
const fields: ReviewFieldProps[] = [
{
name: "Name",
dynamicState: useState("")
},
{
name: "Title",
dynamicState: useState("")
},
{
name: "Content",
dynamicState: useState("")
}
];
const clearValues = () => {
fields.forEach((field) => {
field.dynamicState[1]("");
});
setNewRating(null);
}
const showThenHide = async () => {
const response = await fetch("http://localhost:8080/post", {
method: "POST",
body: JSON.stringify({
rating: rating,
username: fields[0].dynamicState[0],
title: fields[1].dynamicState[0],
content: fields[2].dynamicState[0]
})
}).then((response) => response.json());
response.error ? changeAlertText(`${response.error.type}: ${response.error.message}`) : changeAlertText(`Success: ${response.message}`);
if (showAlert) {
return;
}
changeAlert(true);
setTimeout(() => {
changeAlert(false);
}, 3000);
}
const buttons: ActionProps[] = [ const buttons: ActionProps[] = [
{ {
name: "Cancel", name: "Clear",
type: "outlined", type: "outlined",
action: clearValues
}, },
{ {
name: "Submit", name: "Submit",
type: "contained", type: "contained",
action: showThenHide
}, },
]; ];
const alert = (
<Alert severity="info">
{alertText}
</Alert>
);
return ( return (
<> <>
<ReviewField /> <Typography variant="h3">
Simple Review Client
</Typography>
<br />
<Rating
name="review-rating"
precision={0.5}
size="large"
value={rating}
onChange={(event, newRating) => {
setNewRating(newRating);
}}
/>
<br />
<br />
<ReviewField fields={fields} />
<br /> <br />
<ButtonRow buttons={buttons} /> <ButtonRow buttons={buttons} />
<br />
<Collapse in={showAlert}>
{alert}
</Collapse>
</> </>
); );
} }

View file

@ -4,6 +4,7 @@ import React, { ReactNode } from "react";
export interface ActionProps { export interface ActionProps {
name: string; name: string;
type: "outlined" | "text" | "contained"; type: "outlined" | "text" | "contained";
action?: () => void;
} }
interface ActionButtonProps { interface ActionButtonProps {
@ -14,7 +15,15 @@ const ButtonRow = ({ buttons }: ActionButtonProps) => {
return ( return (
<Grid2 container spacing={2}> <Grid2 container spacing={2}>
{buttons.map((button) => { {buttons.map((button) => {
return <Button variant={button.type}>{button.name}</Button>; return (
<Button
key={button.name}
variant={button.type}
onClick={button.action}
>
{button.name}
</Button>
);
})} })}
</Grid2> </Grid2>
); );

View file

@ -1,15 +1,41 @@
import { Box, Grid2, TextField } from "@mui/material"; import { Box, Stack, TextField } from "@mui/material";
import React from "react"; import React, { useState } from "react";
export interface ReviewFieldProps {
name: string;
dynamicState: [string, React.Dispatch<React.SetStateAction<string>>];
variant?: "outlined" | "filled" | "standard";
help?: string;
}
interface ReviewFieldOpts {
fields: ReviewFieldProps[];
}
const ReviewField = ({ fields }: ReviewFieldOpts) => {
const ReviewField = () => {
return ( return (
<Box component="form" noValidate autoComplete="off"> <Box component="form" noValidate autoComplete="off">
<Grid2 container spacing={4}> <Stack spacing={1}>
<TextField id="username" label="Username" variant="outlined" /> {
<TextField id="rating" label="Rating" variant="outlined" /> fields.map((field) => {
<TextField id="title" label="Title" variant="outlined" /> return (
<TextField id="content" label="Content" variant="outlined" /> <TextField
</Grid2> id={field.name}
key={field.name}
label={field.name}
value={field.dynamicState[0]}
onChange={(({ target }) => {
field.dynamicState[1](target.value);
})}
variant={field.variant ?? "outlined"}
helperText={field.help}
autoComplete="off"
/>
)
})
}
</Stack>
</Box> </Box>
); );
}; };