- useContext from parent page for form fields
This commit is contained in:
1 parent
8292654d27
commit
5045eafb8e
3 files changed
+80
-96
No files matched your search
@@ -5,23 +5,13 @@ import { useTheme } from "@emotion/react";
|
||||
import TabPanel from "@mui/lab/TabPanel";
|
||||
import { publicPageGeneralSettingsValidation } from "../../../Validation/validation";
|
||||
import { buildErrors } from "../../../Validation/error";
|
||||
import { hasValidationErrors } from "../../../Validation/error";
|
||||
import Card from "./Card";
|
||||
import update from "immutability-helper";
|
||||
import Checkbox from "../../Inputs/Checkbox";
|
||||
|
||||
const ContentPanel = () => {
|
||||
const ContentPanel = ({errors, setErrors}) => {
|
||||
const theme = useTheme();
|
||||
const [errors, setErrors] = useState({});
|
||||
// Local state for form data, errors, and file handling
|
||||
const [localData, setLocalData] = useState({
|
||||
monitors: [],
|
||||
showUptimePercentage: false,
|
||||
showBarcode: false
|
||||
|
||||
});
|
||||
|
||||
const [cards, setCards] = useState(localData.monitors);
|
||||
const [cards, setCards] = useState(form.monitors);
|
||||
|
||||
// Clears specific error from errors state
|
||||
const clearError = (err) => {
|
||||
@@ -50,7 +40,7 @@ const ContentPanel = () => {
|
||||
const handleChange = (event) => {
|
||||
event.preventDefault();
|
||||
const { value, id } = event.target;
|
||||
setLocalData((prev) => ({
|
||||
setForm((prev) => ({
|
||||
...prev,
|
||||
[id]: value,
|
||||
}));
|
||||
@@ -66,13 +56,6 @@ const ContentPanel = () => {
|
||||
setCards(update(cards, { $splice: [[idx, 1, x]] }));
|
||||
} else setCards(update(cards, { $push: [{ id: id, url: value }] }));
|
||||
}
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (hasValidationErrors(localData, publicPageGeneralSettingsValidation, setErrors)) {
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
const handleAddNew = () => {
|
||||
setCards([...cards, { id: "" + Math.random() }]);
|
||||
};
|
||||
@@ -190,34 +173,19 @@ const ContentPanel = () => {
|
||||
<Checkbox
|
||||
id="show-barcode"
|
||||
label={`Show Barcode`}
|
||||
isChecked={localData.showBarcode}
|
||||
value={"localData.showBarcode"}
|
||||
isChecked={form.showBarcode}
|
||||
onChange={handleChange}
|
||||
onBlur={handleBlur}
|
||||
/>
|
||||
<Checkbox
|
||||
id="show-uptime-percentage"
|
||||
label={`Show Uptime Percentage`}
|
||||
isChecked={localData.showUptimePercentage}
|
||||
value={"localData.showUptimePercentage"}
|
||||
isChecked={form.showUptimePercentage}
|
||||
onChange={handleChange}
|
||||
onBlur={handleBlur}
|
||||
/>
|
||||
</Stack>
|
||||
</ConfigBox>
|
||||
|
||||
<Stack
|
||||
direction="row"
|
||||
justifyContent="flex-end"
|
||||
>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={handleSubmit}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</TabPanel>
|
||||
);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useState, useRef } from "react";
|
||||
import { useState, useRef, useContext } from "react";
|
||||
import { Button, Box, Stack, Typography } from "@mui/material";
|
||||
import { ConfigBox } from "../../../Pages/Settings/styled";
|
||||
import Checkbox from "../../Inputs/Checkbox";
|
||||
@@ -18,23 +18,15 @@ import ProgressUpload from "../../ProgressBars";
|
||||
import ImageIcon from "@mui/icons-material/Image";
|
||||
import { HttpAdornment } from "../../Inputs/TextInput/Adornments";
|
||||
import { hasValidationErrors } from "../../../Validation/error";
|
||||
import { StatusFormContext } from "../../../Pages/Status/TabContext";
|
||||
|
||||
const GeneralSettingsPanel = () => {
|
||||
const theme = useTheme();
|
||||
const [errors, setErrors] = useState({});
|
||||
const GeneralSettingsPanel = ({errors, setErrors}) => {
|
||||
const theme = useTheme();
|
||||
const [logo, setLogo] = useState();
|
||||
const { form, setForm } = useContext(StatusFormContext);
|
||||
const [progress, setProgress] = useState({ value: 0, isLoading: false });
|
||||
const intervalRef = useRef(null);
|
||||
// Local state for form data, errors, and file handling
|
||||
const [localData, setLocalData] = useState({
|
||||
companyName: "",
|
||||
url: "",
|
||||
timezone: "America/Toronto",
|
||||
color: "#4169E1",
|
||||
//which fields matching below?
|
||||
publish: false,
|
||||
logo: null,
|
||||
});
|
||||
|
||||
// Clears specific error from errors state
|
||||
const clearError = (err) => {
|
||||
setErrors((prev) => {
|
||||
@@ -46,7 +38,7 @@ const GeneralSettingsPanel = () => {
|
||||
const removeLogo = () => {
|
||||
errors["logo"] && clearError("logo");
|
||||
setLogo({});
|
||||
setLocalData((prev) => ({
|
||||
setForm((prev) => ({
|
||||
...prev,
|
||||
logo: logo?.src,
|
||||
}));
|
||||
@@ -58,27 +50,12 @@ const GeneralSettingsPanel = () => {
|
||||
const handleChange = (event) => {
|
||||
event.preventDefault();
|
||||
const { value, id } = event.target;
|
||||
setLocalData((prev) => ({
|
||||
setForm((prev) => ({
|
||||
...prev,
|
||||
[id]: value,
|
||||
}));
|
||||
};
|
||||
|
||||
const handleSubmit = () => {
|
||||
//validate rest of the form
|
||||
delete localData.logo;
|
||||
if (hasValidationErrors(localData, publicPageGeneralSettingsValidation, setErrors)) {
|
||||
return;
|
||||
}
|
||||
//validate image field
|
||||
let error = validateField(
|
||||
{ type: logo?.type ?? null, size: logo?.size ?? null },
|
||||
logoImageValidation
|
||||
);
|
||||
if (error) return;
|
||||
localData.logo = { ...logo, size: formatBytes(logo?.size) };
|
||||
};
|
||||
|
||||
const handleBlur = (event) => {
|
||||
event.preventDefault();
|
||||
const { value, id } = event.target;
|
||||
@@ -159,7 +136,7 @@ const GeneralSettingsPanel = () => {
|
||||
<Checkbox
|
||||
id="published-to-public"
|
||||
label={`Published and visible to the public`}
|
||||
isChecked={localData.publish}
|
||||
isChecked={form.publish}
|
||||
onChange={handleChange}
|
||||
onBlur={handleBlur}
|
||||
/>
|
||||
@@ -180,7 +157,7 @@ const GeneralSettingsPanel = () => {
|
||||
id="companyName"
|
||||
type="text"
|
||||
label="Company name"
|
||||
value={localData.companyName}
|
||||
value={form.companyName}
|
||||
onChange={handleChange}
|
||||
onBlur={handleBlur}
|
||||
helperText={errors["companyName"]}
|
||||
@@ -190,7 +167,7 @@ const GeneralSettingsPanel = () => {
|
||||
id="url"
|
||||
type="url"
|
||||
label="SubURL"
|
||||
value={localData.url}
|
||||
value={form.url}
|
||||
startAdornment={<HttpAdornment prefix = {"http://uptimegenie.com/"} https={false} />}
|
||||
onChange={handleChange}
|
||||
onBlur={handleBlur}
|
||||
@@ -212,7 +189,7 @@ const GeneralSettingsPanel = () => {
|
||||
<Select
|
||||
id="display-timezone"
|
||||
label="Display timezone"
|
||||
value={localData.timezone}
|
||||
value={form.timezone}
|
||||
onChange={handleChange}
|
||||
onBlur={handleBlur}
|
||||
items={timezones}
|
||||
@@ -220,7 +197,7 @@ const GeneralSettingsPanel = () => {
|
||||
/>
|
||||
<ImageField
|
||||
id="logo"
|
||||
src={localData.logo?.src ?? logo?.src}
|
||||
src={form.logo?.src ?? logo?.src}
|
||||
loading={progress.isLoading && progress.value !== 100}
|
||||
onChange={handleLogo}
|
||||
isRound={false}
|
||||
@@ -240,25 +217,13 @@ const GeneralSettingsPanel = () => {
|
||||
<TextInput
|
||||
id="color"
|
||||
label="Color"
|
||||
value={localData.color}
|
||||
value={form.color}
|
||||
error={errors["color"]}
|
||||
onChange={handleChange}
|
||||
onBlur={handleBlur}
|
||||
/>
|
||||
</Stack>
|
||||
</ConfigBox>
|
||||
<Stack
|
||||
direction="row"
|
||||
justifyContent="flex-end"
|
||||
>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={handleSubmit}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</TabPanel>
|
||||
);
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
import PropTypes from "prop-types";
|
||||
import { useNavigate } from "react-router";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Box, Tab, useTheme } from "@mui/material";
|
||||
import { Box, Tab, useTheme, Stack, Button } from "@mui/material";
|
||||
import TabContext from "@mui/lab/TabContext";
|
||||
import TabList from "@mui/lab/TabList";
|
||||
import GeneralSettingsPanel from "../../../Components/TabPanels/Status/GeneralSettingsPanel";
|
||||
import {
|
||||
capitalizeFirstLetter,
|
||||
toLowerCaseFirstLetter,
|
||||
} from "../../../Utils/stringUtils";
|
||||
import ContentPanel from "../../../Components/TabPanels/Status/ContentPanel";
|
||||
import {
|
||||
publicPageGeneralSettingsValidation,
|
||||
} from "../../../Validation/validation";
|
||||
import { hasValidationErrors } from "../../../Validation/error";
|
||||
import { StatusFormProvider } from "../TabContext"
|
||||
|
||||
/**
|
||||
* CreateStatus page renders a page with tabs for general settings and contents.
|
||||
@@ -19,22 +22,47 @@ import ContentPanel from "../../../Components/TabPanels/Status/ContentPanel";
|
||||
|
||||
const CreateStatus = ({ open = "general-settings" }) => {
|
||||
const theme = useTheme();
|
||||
const navigate = useNavigate();
|
||||
let tabList = ["General Settings", "Contents"];
|
||||
const [errors, setErrors] = useState({});
|
||||
const tab = open
|
||||
.split("-")
|
||||
.map((a) => capitalizeFirstLetter(a))
|
||||
.join(" ");
|
||||
|
||||
|
||||
const [tabIdx, setTabIdx] = useState(tabList.indexOf(tab));
|
||||
|
||||
const handleTabChange = (event, newTab) => {
|
||||
let toNavString = newTab.split(" ").map((a) => toLowerCaseFirstLetter(a));
|
||||
setTabIdx(tabList.indexOf(newTab));
|
||||
toNavString = toNavString.join("-");
|
||||
navigate(`/status/${toNavString}`);
|
||||
};
|
||||
|
||||
const [form, setForm] = useState({
|
||||
companyName: "",
|
||||
url: "",
|
||||
timezone: "America/Toronto",
|
||||
color: "#4169E1",
|
||||
//which fields matching below?
|
||||
publish: false,
|
||||
logo: null,
|
||||
monitors: [],
|
||||
showUptimePercentage: false,
|
||||
showBarcode: false
|
||||
});
|
||||
|
||||
const handleSubmit = () => {
|
||||
//validate rest of the form
|
||||
delete form.logo;
|
||||
if (hasValidationErrors(form, publicPageGeneralSettingsValidation, setErrors)) {
|
||||
return;
|
||||
}
|
||||
// //validate image field, double check if it is required
|
||||
// let error = validateField(
|
||||
// { type: logo?.type ?? null, size: logo?.size ?? null },
|
||||
// logoImageValidation
|
||||
// );
|
||||
if (error) return;
|
||||
form.logo = { ...logo, size: formatBytes(logo?.size) };
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setTabIdx(tabList.indexOf(tab));
|
||||
}, [tab]);
|
||||
@@ -49,7 +77,7 @@ const CreateStatus = ({ open = "general-settings" }) => {
|
||||
borderRadius={theme.shape.borderRadius}
|
||||
backgroundColor={theme.palette.background.main}
|
||||
>
|
||||
<TabContext value={tab}>
|
||||
<TabContext value={tabList[tabIdx]}>
|
||||
<Box
|
||||
sx={{
|
||||
borderBottom: 1,
|
||||
@@ -84,8 +112,31 @@ const CreateStatus = ({ open = "general-settings" }) => {
|
||||
))}
|
||||
</TabList>
|
||||
</Box>
|
||||
{tabIdx == 0 ? <GeneralSettingsPanel /> : <ContentPanel />}
|
||||
<StatusFormProvider>
|
||||
{tabIdx == 0 ? (
|
||||
<GeneralSettingsPanel
|
||||
errors={errors}
|
||||
setErrors={setErrors}/>
|
||||
) : (
|
||||
<ContentPanel
|
||||
ss errors={errors}
|
||||
setErrors={setErrors}
|
||||
/>
|
||||
)}
|
||||
</StatusFormProvider>
|
||||
</TabContext>
|
||||
<Stack
|
||||
direction="row"
|
||||
justifyContent="flex-end"
|
||||
>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={handleSubmit}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</Stack>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user