import {useState} from 'react'; import ValidatingInputNumberField from "./validating-input-number-field.tsx"; import {actionLoadedMaze, actionLoadingFailed, actionStartedLoading} from "./state/action.ts"; import styles from "./input-form.module.css"; import "./input-form.css"; export default function InputForm({state, dispatch}) { const [width, setWidth] = useState(10); const [height, setHeight] = useState(10); const [id, setId] = useState(null as number); const [algorithm, setAlgorithm] = useState('wilson'); const handleSubmit = (e) => { e.preventDefault(); dispatch(actionStartedLoading()); const url = `https://manuel.friedli.info/labyrinth/create/json?w=${width}&h=${height}&id=${id || ''}&algorithm=${algorithm}`; fetch(url) .then(response => response.json()) // .then(result => new Promise(resolve => setTimeout(resolve, 600, result))) .then(result => { dispatch(actionLoadedMaze(result)); }) .catch(reason => { console.error("Failed to fetch maze data.", reason); dispatch(actionLoadingFailed(reason)); }); }; const validateWidthHeightInput = value => { if (isNaN(value) || "" === value || (Math.floor(value) !== Number(value))) { return { valid: false, message: "Must be an integer greater than 1.", value }; } if (value < 1) { return { valid: false, message: "Must be greater than 1.", value }; } return { valid: true, value }; }; const validateIdInput = value => { // FIXME doesn't handle strings with characters correctly (e.g. "asdf" yields an empty value, due to "type=number"). if (isNaN(value) || ("" !== value && ((Math.floor(value) !== Number(value))))) { return { valid: false, message: "Must be empty or an integer", value }; } return { valid: true, value } }; return ( <form onSubmit={handleSubmit}> <div className={styles.inputform}> <ValidatingInputNumberField id={"width"} label={"Width"} value={width} constraints={{ min: 2 }} validatorFn={validateWidthHeightInput} disabled={state.loading} onChange={setWidth} /> <ValidatingInputNumberField id={"height"} label={"Height"} value={height} constraints={{ min: 2 }} validatorFn={validateWidthHeightInput} disabled={state.loading} onChange={setHeight} /> <ValidatingInputNumberField id={"id"} label={"ID (optional)"} value={id} validatorFn={validateIdInput} disabled={state.loading} onChange={setId} /> <label htmlFor="algorithm">Algorithm:</label> <select id={"algorithm"} value={algorithm} disabled={state.loading} onChange={e => setAlgorithm(e.target.value)}> <option value="wilson">Wilson</option> <option value="random">Random Depth First</option> </select> </div> <button type={"submit"} disabled={state.loading || isNaN(width) || isNaN(height) } className={styles.submitbutton}>{state.loading ? "Loading ..." : "Create Maze!"} </button> </form> ); }