More picklists

This commit is contained in:
padamsen_fisker
2024-03-05 16:31:08 -05:00
parent f3b56c0e55
commit 8f011d11f2
7 changed files with 406 additions and 130 deletions

View File

@@ -291,11 +291,11 @@ export const VehicleProvider = ({ children }) => {
}
};
const getAllFlashpacks = async (options, token) => {
const getAllFlashpacks = async (model, trim, year, options, token) => {
try {
setBusy(true);
const result = await api.getAllFlashpacks(options, token);
const result = await api.getAllFlashpacks(model, trim, year, options, token);
if (result.error) {
throw new Error(`Get all flashpacks error. ${result.message}`);
}

View File

@@ -24,138 +24,175 @@ exports[`FlashpackAdd Render 1`] = `
>
<div>
<div
class="MuiFormControl-root MuiTextField-root MuiFormControl-marginNormal MuiFormControl-fullWidth"
class="MuiFormControl-root MuiFormControl-marginNormal MuiFormControl-fullWidth"
>
<label
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-outlined Mui-required Mui-required"
data-shrink="false"
for="carModel"
id="carModel-label"
class="MuiFormLabel-root MuiInputLabel-root makeStyles-whiteBackground-0 MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-outlined MuiFormLabel-filled"
data-shrink="true"
>
Model
<span
aria-hidden="true"
class="MuiFormLabel-asterisk MuiInputLabel-asterisk"
>
*
</span>
</label>
<div
class="MuiInputBase-root MuiOutlinedInput-root MuiInputBase-fullWidth MuiInputBase-formControl"
>
<input
aria-invalid="false"
class="MuiInputBase-input MuiOutlinedInput-input"
id="carModel"
maxlength="255"
name="carModel"
class="MuiInputBase-root MuiOutlinedInput-root MuiInputBase-formControl"
required=""
type="text"
value=""
>
<select
aria-invalid="false"
class="MuiSelect-root MuiSelect-select MuiSelect-outlined MuiInputBase-input MuiOutlinedInput-input"
required=""
>
<option
value="Ocean"
>
Ocean
</option>
</select>
<svg
aria-hidden="true"
class="MuiSvgIcon-root MuiSelect-icon MuiSelect-iconOutlined"
focusable="false"
viewBox="0 0 24 24"
>
<path
d="M7 10l5 5 5-5z"
/>
</svg>
<fieldset
aria-hidden="true"
class="PrivateNotchedOutline-root-0 MuiOutlinedInput-notchedOutline"
style="padding-left: 8px;"
>
<legend
class="PrivateNotchedOutline-legendLabelled-0"
class="PrivateNotchedOutline-legend-0"
style="width: 0.01px;"
>
<span>
Model
 *
</span>
</legend>
</fieldset>
</div>
</div>
<div
class="MuiFormControl-root MuiTextField-root MuiFormControl-marginNormal MuiFormControl-fullWidth"
class="MuiFormControl-root MuiFormControl-marginNormal MuiFormControl-fullWidth"
>
<label
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-outlined Mui-required Mui-required"
data-shrink="false"
for="carTrim"
id="carTrim-label"
class="MuiFormLabel-root MuiInputLabel-root makeStyles-whiteBackground-0 MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-outlined MuiFormLabel-filled"
data-shrink="true"
>
Trim
<span
aria-hidden="true"
class="MuiFormLabel-asterisk MuiInputLabel-asterisk"
>
*
</span>
</label>
<div
class="MuiInputBase-root MuiOutlinedInput-root MuiInputBase-fullWidth MuiInputBase-formControl"
>
<input
aria-invalid="false"
class="MuiInputBase-input MuiOutlinedInput-input"
id="carTrim"
maxlength="255"
name="carTrim"
class="MuiInputBase-root MuiOutlinedInput-root MuiInputBase-formControl"
required=""
type="text"
value=""
>
<select
aria-invalid="false"
class="MuiSelect-root MuiSelect-select MuiSelect-outlined MuiInputBase-input MuiOutlinedInput-input"
required=""
>
<option
value="Base"
>
Base
</option>
<option
value="Sport"
>
Sport
</option>
<option
value="Ocean One"
>
Ocean One
</option>
<option
value="Ultra"
>
Ultra
</option>
<option
value="Extreme"
>
Extreme
</option>
</select>
<svg
aria-hidden="true"
class="MuiSvgIcon-root MuiSelect-icon MuiSelect-iconOutlined"
focusable="false"
viewBox="0 0 24 24"
>
<path
d="M7 10l5 5 5-5z"
/>
</svg>
<fieldset
aria-hidden="true"
class="PrivateNotchedOutline-root-0 MuiOutlinedInput-notchedOutline"
style="padding-left: 8px;"
>
<legend
class="PrivateNotchedOutline-legendLabelled-0"
class="PrivateNotchedOutline-legend-0"
style="width: 0.01px;"
>
<span>
Trim
 *
</span>
</legend>
</fieldset>
</div>
</div>
<div
class="MuiFormControl-root MuiTextField-root MuiFormControl-marginNormal MuiFormControl-fullWidth"
class="MuiFormControl-root MuiFormControl-marginNormal MuiFormControl-fullWidth"
>
<label
class="MuiFormLabel-root MuiInputLabel-root MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-outlined Mui-required Mui-required"
data-shrink="false"
for="carYear"
id="carYear-label"
class="MuiFormLabel-root MuiInputLabel-root makeStyles-whiteBackground-0 MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-outlined MuiFormLabel-filled"
data-shrink="true"
>
Year
<span
aria-hidden="true"
class="MuiFormLabel-asterisk MuiInputLabel-asterisk"
>
*
</span>
</label>
<div
class="MuiInputBase-root MuiOutlinedInput-root MuiInputBase-fullWidth MuiInputBase-formControl"
>
<input
aria-invalid="false"
class="MuiInputBase-input MuiOutlinedInput-input"
id="carYear"
maxlength="255"
name="carYear"
class="MuiInputBase-root MuiOutlinedInput-root MuiInputBase-formControl"
required=""
type="number"
value=""
>
<select
aria-invalid="false"
class="MuiSelect-root MuiSelect-select MuiSelect-outlined MuiInputBase-input MuiOutlinedInput-input"
required=""
>
<option
value="2023"
>
2023
</option>
<option
value="2024"
>
2024
</option>
</select>
<svg
aria-hidden="true"
class="MuiSvgIcon-root MuiSelect-icon MuiSelect-iconOutlined"
focusable="false"
viewBox="0 0 24 24"
>
<path
d="M7 10l5 5 5-5z"
/>
</svg>
<fieldset
aria-hidden="true"
class="PrivateNotchedOutline-root-0 MuiOutlinedInput-notchedOutline"
style="padding-left: 8px;"
>
<legend
class="PrivateNotchedOutline-legendLabelled-0"
class="PrivateNotchedOutline-legend-0"
style="width: 0.01px;"
>
<span>
Year
 *
</span>
</legend>
</fieldset>

View File

@@ -12,7 +12,10 @@ import { logger } from "../../../services/monitoring";
import { useStatusContext } from "../../Contexts/StatusContext";
import { useVehicleContext, VehicleProvider } from "../../Contexts/VehicleContext";
import { useUserContext } from "../../Contexts/UserContext";
import { useLocalStorage } from "../../useLocalStorage";
import useStyles from "../../useStyles";
import { DropDownList } from "../../Controls/DropDownList";
import modelsTrimsYears from '.././modelsTrimsYears.json';
const MainForm = () => {
const {
@@ -23,9 +26,11 @@ const MainForm = () => {
const classes = useStyles();
const [redirect, setRedirect] = useState(null);
const { setMessage, setTitle, setSitePath } = useStatusContext();
const [carModel, setCarModel] = useState("");
const [carTrim, setCarTrim] = useState("");
const [carYear, setCarYear] = useState();
const [carModel, setCarModel] = useLocalStorage("FLASHPACK_ADD_MODEL", "Ocean");
const [carTrim, setCarTrim] = useLocalStorage("FLASHPACK_ADD_TRIM", "Base");
const [carYear, setCarYear] = useLocalStorage("FLASHPACK_ADD_YEAR", 2024);
const [trims, setTrims] = useLocalStorage("FLASHPACK_ADD_TRIMS", modelsTrimsYears.oceanTrims);
const [years, setYears] = useLocalStorage("FLASHPACK_ADD_YEARS", modelsTrimsYears.oceanYears);
const [flashpack, setFlashpack] = useState();
const [mappingInputs, setMappingInputs] = useState([{ ecuName: "", ecuVersion: "" }]);
const {
@@ -52,15 +57,30 @@ const MainForm = () => {
}, []);
const onCarModelChange = (event) => {
setCarModel(event.target.value);
let newModel = event.target.value
setCarModel(newModel)
switch (newModel) {
case "Ocean":
setTrims(modelsTrimsYears.oceanTrims);
setYears(modelsTrimsYears.oceanYears);
break;
default:
break;
}
}
const onCarTrimChange = (event) => {
setCarTrim(event.target.value);
let newTrim = event.target.value
setCarTrim(newTrim)
}
const onCarYearChange = (event) => {
setCarYear(event.target.value);
let newYear = event.target.value
setCarYear(newYear)
}
const onFlashpackChange = (event) => {
@@ -119,51 +139,9 @@ const MainForm = () => {
<div className={classes.paper}>
<form className={classes.form} noValidate action="{onSubmit}">
<div>
<TextField
id="carModel"
name="carModel"
label="Model"
variant="outlined"
margin="normal"
inputProps={{
maxLength: "255",
}}
required
fullWidth
value={carModel}
onChange={onCarModelChange}
type="text"
/>
<TextField
id="carTrim"
name="carTrim"
label="Trim"
variant="outlined"
margin="normal"
inputProps={{
maxLength: "255",
}}
required
fullWidth
value={carTrim}
onChange={onCarTrimChange}
type="text"
/>
<TextField
id="carYear"
name="carYear"
label="Year"
variant="outlined"
margin="normal"
inputProps={{
maxLength: "255",
}}
required
fullWidth
value={carYear}
onChange={onCarYearChange}
type="number"
/>
<DropDownList fullWidth required label="Model" data={modelsTrimsYears.models} classes={classes} onChange={onCarModelChange} value={carModel} />
<DropDownList fullWidth required label="Trim" data={trims} disabled={!carModel || !trims} classes={classes} onChange={onCarTrimChange} value={carTrim} />
<DropDownList fullWidth required label="Year" data={years} disabled={!carModel || !years} classes={classes} onChange={onCarYearChange} value={carYear} />
<TextField
id="flashpack"
name="flashpack"

View File

@@ -15,6 +15,175 @@ exports[`Flashpack Render 1`] = `
data-testid="mocked-vehicleprovider"
>
<div>
<div
class="MuiFormControl-root MuiFormControl-marginNormal"
>
<label
class="MuiFormLabel-root MuiInputLabel-root makeStyles-whiteBackground-0 MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-outlined MuiFormLabel-filled"
data-shrink="true"
>
Model
</label>
<div
class="MuiInputBase-root MuiOutlinedInput-root MuiInputBase-formControl"
>
<select
aria-invalid="false"
class="MuiSelect-root MuiSelect-select MuiSelect-outlined MuiInputBase-input MuiOutlinedInput-input"
>
<option
value="Ocean"
>
Ocean
</option>
</select>
<svg
aria-hidden="true"
class="MuiSvgIcon-root MuiSelect-icon MuiSelect-iconOutlined"
focusable="false"
viewBox="0 0 24 24"
>
<path
d="M7 10l5 5 5-5z"
/>
</svg>
<fieldset
aria-hidden="true"
class="PrivateNotchedOutline-root-0 MuiOutlinedInput-notchedOutline"
style="padding-left: 8px;"
>
<legend
class="PrivateNotchedOutline-legend-0"
style="width: 0.01px;"
>
<span>
</span>
</legend>
</fieldset>
</div>
</div>
<div
class="MuiFormControl-root MuiFormControl-marginNormal"
>
<label
class="MuiFormLabel-root MuiInputLabel-root makeStyles-whiteBackground-0 MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-outlined MuiFormLabel-filled"
data-shrink="true"
>
Trim
</label>
<div
class="MuiInputBase-root MuiOutlinedInput-root MuiInputBase-formControl"
>
<select
aria-invalid="false"
class="MuiSelect-root MuiSelect-select MuiSelect-outlined MuiInputBase-input MuiOutlinedInput-input"
>
<option
value="Base"
>
Base
</option>
<option
value="Sport"
>
Sport
</option>
<option
value="Ocean One"
>
Ocean One
</option>
<option
value="Ultra"
>
Ultra
</option>
<option
value="Extreme"
>
Extreme
</option>
</select>
<svg
aria-hidden="true"
class="MuiSvgIcon-root MuiSelect-icon MuiSelect-iconOutlined"
focusable="false"
viewBox="0 0 24 24"
>
<path
d="M7 10l5 5 5-5z"
/>
</svg>
<fieldset
aria-hidden="true"
class="PrivateNotchedOutline-root-0 MuiOutlinedInput-notchedOutline"
style="padding-left: 8px;"
>
<legend
class="PrivateNotchedOutline-legend-0"
style="width: 0.01px;"
>
<span>
</span>
</legend>
</fieldset>
</div>
</div>
<div
class="MuiFormControl-root MuiFormControl-marginNormal"
>
<label
class="MuiFormLabel-root MuiInputLabel-root makeStyles-whiteBackground-0 MuiInputLabel-formControl MuiInputLabel-animated MuiInputLabel-shrink MuiInputLabel-outlined MuiFormLabel-filled"
data-shrink="true"
>
Year
</label>
<div
class="MuiInputBase-root MuiOutlinedInput-root MuiInputBase-formControl"
>
<select
aria-invalid="false"
class="MuiSelect-root MuiSelect-select MuiSelect-outlined MuiInputBase-input MuiOutlinedInput-input"
>
<option
value="2023"
>
2023
</option>
<option
value="2024"
>
2024
</option>
</select>
<svg
aria-hidden="true"
class="MuiSvgIcon-root MuiSelect-icon MuiSelect-iconOutlined"
focusable="false"
viewBox="0 0 24 24"
>
<path
d="M7 10l5 5 5-5z"
/>
</svg>
<fieldset
aria-hidden="true"
class="PrivateNotchedOutline-root-0 MuiOutlinedInput-notchedOutline"
style="padding-left: 8px;"
>
<legend
class="PrivateNotchedOutline-legend-0"
style="width: 0.01px;"
>
<span>
</span>
</legend>
</fieldset>
</div>
</div>
<div
class="MuiGrid-root makeStyles-root-0 MuiGrid-container MuiGrid-spacing-xs-2"
>

View File

@@ -21,7 +21,9 @@ import TableHeaderSortable from "../Table/HeaderSortable";
import { useLocalStorage } from "../useLocalStorage";
import DeleteConfirmation from "../DeleteConfirmation";
import { RoleWrap } from "../Controls/RoleWrap";
import { DropDownList } from "../Controls/DropDownList";
import useStyles from "../useStyles";
import modelsTrimsYears from './modelsTrimsYears.json';
const tableColumns = [
{
@@ -55,6 +57,11 @@ const MainForm = () => {
const [pageIndex, setPageIndex] = useState(0);
const [showDeleteModal, setShowDeleteModal] = useState(false);
const [rowToDelete, setRowToDelete] = useState({});
const [model, setModel] = useLocalStorage("FLASHPACKS_MODEL", "Ocean");
const [trim, setTrim] = useLocalStorage("FLASHPACKS_TRIM", "Base");
const [year, setYear] = useLocalStorage("FLASHPACKS_YEAR", 2024);
const [trims, setTrims] = useLocalStorage("FLASHPACKS_TRIMS", modelsTrimsYears.oceanTrims);
const [years, setYears] = useLocalStorage("FLASHPACKS_YEARS", modelsTrimsYears.oceanYears);
const {
getAllFlashpacks,
flashpacks,
@@ -84,14 +91,17 @@ const MainForm = () => {
}, []);
useEffect(() => {
loadFlashpacks();
loadFlashpacks(model, trim, year);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [token, pageIndex, pageSize]);
const loadFlashpacks = async () => {
const loadFlashpacks = async (model, trim, year) => {
try {
if (!token) return;
await getAllFlashpacks(
model,
trim,
year,
{
limit: pageSize,
offset: pageSize * pageIndex,
@@ -104,6 +114,45 @@ const MainForm = () => {
}
};
const onModelChange = (event) => {
let newModel = event.target.value
setModel(newModel)
switch (newModel) {
case "Ocean":
setTrims(modelsTrimsYears.oceanTrims);
setYears(modelsTrimsYears.oceanYears);
break;
default:
break;
}
if (trim && year) {
loadFlashpacks(newModel, trim, year)
}
};
const onTrimChange = (event) => {
let newTrim = event.target.value
setTrim(newTrim)
if (model && year) {
loadFlashpacks(model, newTrim, year)
}
};
const onYearChange = (event) => {
let newYear = event.target.value
setYear(newYear)
if (model && trim) {
loadFlashpacks(model, trim, newYear)
}
};
const handleChangePageIndex = (event, newIndex) => {
setPageIndex(newIndex);
};
@@ -125,7 +174,7 @@ const MainForm = () => {
if (!result || result.error) return;
setMessage(`Deleted ${rowToDelete.car_year} ${rowToDelete.car_model} ${rowToDelete.car_trim} ${rowToDelete.flashpack}`);
loadFlashpacks();
loadFlashpacks(model, trim, year);
} catch (e) {
setMessage(e.message);
logger.warn(e.stack);
@@ -135,6 +184,9 @@ const MainForm = () => {
return (
<div>
<DropDownList label="Model" data={modelsTrimsYears.models} classes={classes} onChange={onModelChange} value={model} />
<DropDownList label="Trim" data={trims} disabled={!model || !trims} classes={classes} onChange={onTrimChange} value={trim} />
<DropDownList label="Year" data={years} disabled={!model || !years} classes={classes} onChange={onYearChange} value={year} />
<Grid container className={classes.root} spacing={2}>
<Grid item md={4} className={clsx(classes.textJustifyAlign, classes.actionsBar)}>
<Link to={`/tools/flashpack/add`} className={classes.labelInline}>

View File

@@ -0,0 +1,40 @@
{
"models": [
{
"value": "Ocean",
"label": "Ocean"
}
],
"oceanTrims": [
{
"value": "Base",
"label": "Base"
},
{
"value": "Sport",
"label": "Sport"
},
{
"value": "Ocean One",
"label": "Ocean One"
},
{
"value": "Ultra",
"label": "Ultra"
},
{
"value": "Extreme",
"label": "Extreme"
}
],
"oceanYears": [
{
"value": 2023,
"label": "2023"
},
{
"value": 2024,
"label": "2024"
}
]
}

View File

@@ -261,8 +261,8 @@ const vehiclesAPI = {
.catch(errorHandler)
},
getAllFlashpacks: async (options, token) => {
return fetch(addQueryParams(`${API_ENDPOINT}/flashpack_versions`, options), {
getAllFlashpacks: async (model, trim, year, options, token) => {
return fetch(addQueryParams(`${API_ENDPOINT}/flashpack_versions/${model}/${trim}/${year}`, options), {
method: "GET",
headers: Object.assign(
{ "Content-Type": "application/json" },