labyrinth-frontend/src/InputForm.js

109 lines
4.1 KiB
JavaScript
Raw Normal View History

import React, {useState} from 'react';
import ValidatingInputNumberField from "./ValidatingInputNumberField";
export default function InputForm({handleResult}) {
const [width, setWidth] = useState(10);
const [height, setHeight] = useState(10);
const [id, setId] = useState(null);
2023-04-16 04:04:00 +02:00
const [status, setStatus] = useState("ready"); // "ready", "submitting"
if (status === "submitted") {
return <span/>;
}
const callAPI = () => {
2023-04-16 04:04:00 +02:00
handleResult({});
const url = `https://manuel.friedli.info/labyrinth/create/json?w=${width}&h=${height}&id=${id || ''}`;
fetch(url)
.then(response => response.json())
2023-04-16 04:04:00 +02:00
// .then(result => new Promise(resolve => setTimeout(resolve, 600, result)))
.then(result => {
handleResult(result);
setId(_ => result.id);
})
.catch(reason => {
console.error("Failed to fetch maze data.", reason);
// FIXME alert is not user friendly
2023-04-16 04:04:00 +02:00
alert(`Failed to fetch maze data: ${reason}`);
})
.finally(() => {
2023-04-16 04:04:00 +02:00
setStatus("ready");
});
};
const handleSubmit = (e) => {
e.preventDefault();
setStatus("submitting");
callAPI();
};
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}>
<ValidatingInputNumberField id={"width"}
label={"Width"}
2023-04-16 01:01:23 +02:00
value={width}
constraints={{
min: 2
}}
validatorFn={validateWidthHeightInput}
disabled={status === "submitting"}
onChange={setWidth}
/><br/>
<ValidatingInputNumberField id={"height"}
label={"Height"}
2023-04-16 01:01:23 +02:00
value={height}
constraints={{
min: 2
}}
validatorFn={validateWidthHeightInput}
disabled={status === "submitting"}
onChange={setHeight}
/><br/>
<ValidatingInputNumberField id={"id"}
label={"ID (optional)"}
2023-04-16 01:01:23 +02:00
value={id}
validatorFn={validateIdInput}
disabled={status === "submitting"}
onChange={setId}
/><br/>
<button type={"submit"}
disabled={status === "submitting"
|| isNaN(width)
|| isNaN(height)
2023-04-16 04:04:00 +02:00
}>{status === "ready" ? "Create" : "Loading ..."}
</button>
</form>
);
}