Refactoring

This commit is contained in:
Darren Clarke 2024-04-29 17:27:25 +02:00
parent 39cfada3e8
commit dd14dfe72e
41 changed files with 866 additions and 742 deletions

View file

@ -0,0 +1,127 @@
import { FC, useState } from "react";
import {
TextField as InternalTextField,
Grid,
Box,
IconButton,
} from "@mui/material";
import {
AddCircle as AddCircleIcon,
RemoveCircle as RemoveCircleIcon,
} from "@mui/icons-material";
import { colors, typography } from "../styles/theme";
const TextField: FC<any> = (props) => {
return (
<InternalTextField
fullWidth
size="small"
InputProps={{
sx: {
backgroundColor: "#fff",
},
}}
{...props}
/>
);
};
type MultiValueFieldProps = {
name: string;
label: string;
formState: Record<string, any>;
helperText?: string;
};
export const MultiValueField: FC<MultiValueFieldProps> = ({
name,
label,
formState,
helperText,
}) => {
const { darkMediumGray, mediumBlue, brightRed } = colors;
const { body } = typography;
const value = formState.values[name] || {};
const [fields, setFields] = useState<any[]>(Object.entries(value));
const addField = () => {
setFields([...fields, ["", ""]]);
};
const removeField = (index: number) => {
const newFields = [...fields];
newFields.splice(index, 1);
setFields(newFields);
};
const updateField = (index: number, position: number, value: any) => {
const newFields = [...fields];
newFields[index][position] = value;
setFields(newFields);
// formState.values[name] = Object.fromEntries(newFields);
// console.log(formState.values);
};
return (
<Box component="fieldset" sx={{ border: `1px solid ${darkMediumGray}` }}>
<Box
component="input"
name={name}
value={JSON.stringify(Object.fromEntries(fields))}
readOnly
hidden
/>
<Box
component="legend"
sx={{ ...body, color: darkMediumGray, fontSize: 14 }}
>
{label}
</Box>
<Grid container direction="column" spacing={2}>
<Grid
item
container
xs={12}
direction="row"
justifyContent="space-between"
alignItems="center"
>
<Grid item xs={10}>
<Box sx={{ ...body, color: darkMediumGray }}> {helperText}</Box>
</Grid>
<Grid item>
<IconButton sx={{ color: mediumBlue }} onClick={addField}>
<AddCircleIcon />
</IconButton>
</Grid>
</Grid>
{fields.map(([key, value], index) => (
<Grid key={index} item container direction="row" xs={12} spacing={2}>
<Grid item xs={5}>
<TextField
label="Key"
defaultValue={key}
onChange={(e: any) => updateField(index, 0, e.target.value)}
/>
</Grid>
<Grid item xs={6}>
<TextField
label="Value"
defaultValue={value}
onChange={(e: any) => updateField(index, 1, e.target.value)}
/>
</Grid>
<Grid item xs={1} sx={{ textAlign: "right" }}>
<IconButton
sx={{ color: brightRed }}
onClick={() => removeField(index)}
>
<RemoveCircleIcon />
</IconButton>
</Grid>
</Grid>
))}
</Grid>
</Box>
);
};

View file

@ -1,31 +1,57 @@
import { FC } from "react";
import { Select as InternalSelect } from "@mui/material";
import { FC, useState, useEffect } from "react";
import { Select as InternalSelect, MenuItem } from "@mui/material";
export type SelectOption = {
value: string;
label: string;
};
type SelectProps = {
name: string;
label: string;
formState: Record<string, any>;
children: React.ReactNode;
required?: boolean;
getOptions?: (formState: any) => Promise<SelectOption[]>;
};
export const Select: FC<SelectProps> = ({
name,
label,
formState,
children,
}) => (
<InternalSelect
fullWidth
name={name}
label={label}
variant="outlined"
size="small"
inputProps={{ id: name }}
defaultValue={formState.values[name] || ""}
sx={{
backgroundColor: "#fff",
}}
>
{children}
</InternalSelect>
);
required = false,
getOptions,
}) => {
const [options, setOptions] = useState([] as SelectOption[]);
useEffect(() => {
const fetchData = async () => {
if (getOptions) {
const opts = await getOptions(formState);
setOptions(opts);
}
};
fetchData();
}, [getOptions, formState]);
return (
<InternalSelect
fullWidth
name={name}
label={label}
variant="outlined"
required={required}
size="small"
inputProps={{ id: name }}
defaultValue={formState.values[name] || ""}
sx={{
backgroundColor: "#fff",
}}
>
{options.map((option: SelectOption) => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</InternalSelect>
);
};

View file

@ -9,5 +9,6 @@ export { Button } from "./components/Button";
export { TextField } from "./components/TextField";
export { DisplayTextField } from "./components/DisplayTextField";
export { Select } from "./components/Select";
export { MultiValueField } from "./components/MultiValueField";
export { Dialog } from "./components/Dialog";
export { fonts, typography, colors } from "./styles/theme";

File diff suppressed because one or more lines are too long