MySubjectForm.tsx (2621B)
1 import { 2 Box, 3 FormControl, 4 Grid, 5 InputLabel, 6 MenuItem, 7 Select, 8 Stack, 9 TextField, 10 } from '@mui/material'; 11 import { useCallback, useState } from 'react'; 12 13 import useMyClass from 'client/hooks/useMyClass'; 14 import useMySubject from 'client/hooks/useMySubject'; 15 import { trpc } from 'client/utils/trpc'; 16 import { DAY_PERIOD_JA, GRADE_CLASSES } from 'common/constant'; 17 18 import type { SelectChangeEvent } from '@mui/material'; 19 import type { DayPeriodJa, GradeClass } from 'common/types'; 20 21 type SubjectInputFieldProps = { 22 gradeClass: GradeClass; 23 dayPeriod: DayPeriodJa; 24 defaultSubject: string; 25 }; 26 27 function SubjectInputField({ 28 gradeClass, 29 dayPeriod, 30 defaultSubject, 31 }: SubjectInputFieldProps) { 32 const [subject, setSubject, removeSubject] = useMySubject({ 33 gradeClass, 34 dayPeriod, 35 }); 36 const handleChange = (value: string) => { 37 if (value === '') { 38 removeSubject(); 39 } else { 40 setSubject(value); 41 } 42 }; 43 44 return ( 45 <TextField 46 label={dayPeriod} 47 value={subject ?? ''} 48 helperText={defaultSubject} 49 onChange={(e) => handleChange(e.target.value)} 50 variant='standard' 51 /> 52 ); 53 } 54 55 type SubjectInputGridProps = { 56 gradeClass: GradeClass; 57 }; 58 59 function SubjectInputGrid({ gradeClass }: SubjectInputGridProps) { 60 const { data } = trpc.classStandard.byGradeClass.useQuery({ gradeClass }); 61 62 return ( 63 <Grid container spacing={2} my={0.5}> 64 {DAY_PERIOD_JA.map((dayPeriod) => ( 65 <Grid width={150} key={dayPeriod}> 66 <SubjectInputField 67 gradeClass={gradeClass} 68 dayPeriod={dayPeriod} 69 defaultSubject={ 70 data?.standardTimetable[dayPeriod] 71 ?.map((c) => c.shortName) 72 .join('/') ?? '' 73 } 74 /> 75 </Grid> 76 ))} 77 </Grid> 78 ); 79 } 80 81 export default function MySubjectForm() { 82 const [myGradeClass] = useMyClass(); 83 84 const [selectedClass, setClass] = useState<GradeClass | ''>( 85 myGradeClass ?? '', 86 ); 87 const handleClassChange = useCallback( 88 (e: SelectChangeEvent<GradeClass | ''>) => 89 setClass(e.target.value as GradeClass | ''), 90 [setClass], 91 ); 92 93 return ( 94 <Stack> 95 <Box width='10rem'> 96 <FormControl fullWidth size='small'> 97 <InputLabel id='class-selection'>クラス</InputLabel> 98 <Select<GradeClass | ''> 99 labelId='class-selection' 100 label='クラス' 101 required 102 value={selectedClass} 103 onChange={handleClassChange} 104 > 105 {GRADE_CLASSES.map((g_c) => ( 106 <MenuItem value={g_c} key={g_c}> 107 {g_c} 108 </MenuItem> 109 ))} 110 </Select> 111 </FormControl> 112 </Box> 113 114 {selectedClass !== '' && ( 115 <SubjectInputGrid gradeClass={selectedClass} key={selectedClass} /> 116 )} 117 </Stack> 118 ); 119 }