Problem:
In the new version nothing happens if I click any item, the Select Menu stays open till I press escape or something.
Old version:
return(
<div>
<select
className="questionAnswer"
name={props.question.type}
id={props.question.id}
onChange={event => timeAnswerDbUpdate(Number(event.target.value))}
>
value=<TimeAnswerProperties
key={currentTimeAnswer}
timeUnit={{
time: currentTimeAnswer + "",
length: 15,
end: "24:00"
}}
/>
{timeUnitsToChoose}
</select>
</div>
New version:
const initialTimeUnitValue = <TimeUnitAnswer key={currentTimeAnswer} timeUnit={{
time: currentTimeAnswer + "",
length: 15,
end: "24:00"
}}
/>
return(
<FormControl>
<InputLabel>Time</InputLabel>
<Select
name={props.question.type}
id={props.question.id}
value={initialTimeUnitValue}
onChange={event => timeAnswerDbUpdate(Number(event.target.value))}
>
{filteredTimeUnitSelection}
</Select>
//this is a working test from the MaterialUI documentation
<Select
value={age}
onChange={event => setAge(event.target.value as string)}
>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
);
TimeUnitAnwer (new version), (old version is named ‘TimeAnswerProperties’ and with instead of :
import { TimeUnit } from "../service/models";
import { MenuItem } from '@mui/material';
interface AnswerProps {
timeUnit: TimeUnit
}
export default function TimeUnitAnswer(props: AnswerProps) {
return (
<MenuItem key={props.timeUnit.timeInMinutes} value={props.timeUnit.timeInMinutes}>{props.timeUnit.time}h</MenuItem>
)
}
full old version:
import {Question, TimeAnswer, TimeUnit, WorkdayAnswer} from "../service/models";
import {useEffect, useState} from "react";
import {getTimeUnitList, postTimeAnswer, postWorkdayAnswer} from "../service/apiService";
import TimeAnswerProperties from "./TimeAnswerProperties";
import "./QuestionComponent.css"
import {convertTimeUnitToMinutes} from "../utilities/Util"
interface QuestionProps {
question: Question
answers: Array<TimeAnswer>
answerCallback: () => void //refreshing site
}
export default function QuestionListComponent(props: QuestionProps) {
const [timeUnitList, setTimeUnitList] = useState<Array<TimeUnit>>([])
const [currentTimeAnswer, setCurrentTimeAnswer] = useState<string>()
const [workdays, setWorkdays] = useState<boolean[]>([true, true, true, true, true, false, false]);
const [errorMessage, setErrorMessage] = useState("")
const question = props.question
const answerCallback = props.answerCallback
useEffect(() => {
const workdayAnswerDbUpdate = () => {
const workdayAnswer: WorkdayAnswer = {
questionId: question.id,
question: question.question,
monday: workdays[0],
tuesday: workdays[1],
wednesday: workdays[2],
thursday: workdays[3],
friday: workdays[4],
saturday: workdays[5],
sunday: workdays[6],
};
postWorkdayAnswer(workdayAnswer)
.then(() => answerCallback()) // refreshing site
.catch(() => {
console.error("Error posting workday answer:", Error);
setErrorMessage("error posting answer");
});
};
workdayAnswerDbUpdate();
}, [answerCallback, question, workdays]);
useEffect(() => {
const loadTimeUnitList = async () => {
try {
const data = await getTimeUnitList();
setTimeUnitList(data);
} catch {
setErrorMessage("Failed to load time unit list")
}
};
loadTimeUnitList();
const currentAnswer = props.answers.find(answer => answer.questionId === props.question.id)
setCurrentTimeAnswer(currentAnswer ? currentAnswer.time : "00:00");
}, [props.answers, props.question.id])
const timeAnswerDbUpdate = (timeInMinutes: number) => {
const timeAnswer: TimeAnswer = {
questionId: props.question.id,
question: props.question.question,
timeInMinutes: timeInMinutes
}
postTimeAnswer(timeAnswer)
.then(() => props.answerCallback()) // refreshing site
.catch(() => {
console.error("Error posting time answer:", Error);
setErrorMessage("error posting answer");
})
};
const timeUnitsToChoose = timeUnitList
.filter(timeUnit => {
if (!props.question.previousQuestionId) {
return true;
} else {
const previousQuestionAnswer = props.answers.find(answer => answer.questionId === props.question.previousQuestionId)
if (previousQuestionAnswer) {
const currentTimeAnswerInMinutes = convertTimeUnitToMinutes(currentTimeAnswer);
return (
timeUnit.timeInMinutes! >= previousQuestionAnswer.timeInMinutes) &&
timeUnit.timeInMinutes !== currentTimeAnswerInMinutes;
} else {
return true;
}
}
})
.map(timeUnit => <TimeAnswerProperties key={timeUnit.id} timeUnit={timeUnit}/>)
const renderWorkdayCheckboxes = () => {
const days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
return days.map((day, index) => (
<span key={index}>
<input
type="checkbox"
id={`check${index}`}
checked={workdays[index]}
onChange={event => {
const newWorkdays = [...workdays];
newWorkdays[index] = event.target.checked;
setWorkdays(newWorkdays);
}}
/>
<label htmlFor={`check${index}`}>{day}</label>
</span>
));
};
const QuestionType = () => {
if (props.question.question === "On which days do you work ?") {
return (
<div>
{renderWorkdayCheckboxes()}
</div>
);
}
else{
return(
<div>
<select
className="questionAnswer"
name={props.question.type}
id={props.question.id}
onChange={event => timeAnswerDbUpdate(Number(event.target.value))}
>
value=<TimeAnswerProperties
key={currentTimeAnswer}
timeUnit={{
time: currentTimeAnswer + "",
length: 15,
end: "24:00"
}}
/>
{timeUnitsToChoose}
</select>
</div>
);
}
};
return (
<div className="question">
<p>{props.question.question}</p>
{errorMessage && <div>{errorMessage}</div>}
{QuestionType()}
</div>
);
}
full new version:
import {Question, TimeAnswer, TimeUnit, WorkdayAnswer} from "../service/models";
import {useEffect, useState} from "react";
import {getTimeUnitList, postTimeAnswer, postWorkdayAnswer} from "../service/apiService";
import TimeUnitAnswer from "../components/TimeUnitAnswer";
//import "./QuestionManager.css"
import {convertTimeUnitToMinutes} from "../utilities/Util"
import WorkdayCheckboxes from "../components/WorkdayCheckboxes";
import { Select, FormControl, Box, Typography, Grid2, Card, InputLabel, MenuItem, SelectChangeEvent } from '@mui/material';
interface QuestionProps {
question: Question
answers: Array<TimeAnswer>
answerCallback: () => void //refreshing site
}
export default function QuestionManager(props: QuestionProps) {
const [timeUnitList, setTimeUnitList] = useState<Array<TimeUnit>>([])
const [currentTimeAnswer, setCurrentTimeAnswer] = useState<string>()
const [workdays, setWorkdays] = useState<boolean[]>([true, true, true, true, true, false, false]);
const [errorMessage, setErrorMessage] = useState("")
const question = props.question
const answerCallback = props.answerCallback
useEffect(() => {
const workdayAnswerDbUpdate = () => {
const workdayAnswer: WorkdayAnswer = {
questionId: question.id,
question: question.question,
monday: workdays[0],
tuesday: workdays[1],
wednesday: workdays[2],
thursday: workdays[3],
friday: workdays[4],
saturday: workdays[5],
sunday: workdays[6],
};
postWorkdayAnswer(workdayAnswer)
.then(() => answerCallback()) // refreshing site
.catch(() => {
console.error("Error posting workday answer:", Error);
setErrorMessage("error posting answer");
});
};
workdayAnswerDbUpdate();
}, [answerCallback, question, workdays]);
useEffect(() => {
const loadTimeUnitList = async () => {
try {
const data = await getTimeUnitList();
setTimeUnitList(data);
} catch {
setErrorMessage("Failed to load time unit list")
}
};
loadTimeUnitList();
const currentAnswer = props.answers.find(answer => answer.questionId === props.question.id)
setCurrentTimeAnswer(currentAnswer ? currentAnswer.time : "00:00");
}, [props.answers, props.question.id])
const timeAnswerDbUpdate = (timeInMinutes: number) => {
const timeAnswer: TimeAnswer = {
questionId: props.question.id,
question: props.question.question,
timeInMinutes: timeInMinutes
}
postTimeAnswer(timeAnswer)
.then(() => props.answerCallback()) // refreshing site
.catch(() => {
console.error("Error posting time answer:", Error);
setErrorMessage("error posting answer");
})
};
const filteredTimeUnitSelection = timeUnitList
.filter(timeUnit => {
if (!props.question.previousQuestionId) {
return true;
} else {
const previousQuestionAnswer = props.answers.find(answer => answer.questionId === props.question.previousQuestionId)
if (previousQuestionAnswer) {
const currentTimeAnswerInMinutes = convertTimeUnitToMinutes(currentTimeAnswer);
return (
timeUnit.timeInMinutes! >= previousQuestionAnswer.timeInMinutes) &&
timeUnit.timeInMinutes !== currentTimeAnswerInMinutes;
} else {
return true;
}
}
})
.map(timeUnit => <TimeUnitAnswer key={timeUnit.id} timeUnit={timeUnit}/>)
const initialTimeUnitValue = <TimeUnitAnswer key={currentTimeAnswer} timeUnit={{
time: currentTimeAnswer + "",
length: 15,
end: "24:00"
}}
/>
const QuestionTypeResolver = () => {
if (props.question.question === "On which days do you work ?") {
return (
<div>
<WorkdayCheckboxes workdays={workdays} setWorkdays={setWorkdays} />
</div>
);
}
else{
return(
//create extra 'TimeSelection' component
<FormControl>
<InputLabel>Time</InputLabel>
<Select
name={props.question.type}
id={props.question.id}
value={initialTimeUnitValue}
onChange={event => timeAnswerDbUpdate(Number(event.target.value))}
>
{filteredTimeUnitSelection}
</Select>
<Select
value={age}
onChange={event => setAge(event.target.value as string)}
>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
);
}
};
const [age, setAge] =useState('');
const handleChange = (event: SelectChangeEvent) => {
setAge(event.target.value as string);
};
return (
<Grid2 size={8}>
<Card sx={{
backgroundColor: "primary.main",
marginTop:'40px'
}}>
<Box textAlign='center' >
<Typography>{props.question.question}</Typography>
{errorMessage && <div>{errorMessage}</div>}
{QuestionTypeResolver()}
</Box>
</Card>
</Grid2>
);
}
The copied test from the M-UI documentation is working completely fine.
I did try putting the “value={initialValue}” after the , like in the old version but it hasn’t changed anything.
Would it make sense to rather use https://mui.com/x/react-date-pickers/time-picker/ ?
3