commit 8cc5f679a14c03431f3ad105d7a37f96f2eb9060
parent b17b0efb37d9ed9de4ece0eb1d587998474b5c12
Author: Yuukin256 <Yuukin256@gmail.com>
Date: Thu, 10 Nov 2022 00:10:08 +0900
データフェッチに時間がかかった場合のみ読み込み画面表示
Diffstat:
5 files changed, 41 insertions(+), 19 deletions(-)
diff --git a/src/hooks/useDebouncedValue.ts b/src/hooks/useDebouncedValue.ts
@@ -0,0 +1,18 @@
+import { useState } from 'react';
+import { useDebounce } from 'react-use';
+
+const useDebouncedValue = <T>(val: T, delay?: number) => {
+ const [debouncedValue, setDebouncedValue] = useState<T>();
+
+ useDebounce(
+ () => {
+ setDebouncedValue(val);
+ },
+ delay ?? 2000,
+ [val]
+ );
+
+ return debouncedValue;
+};
+
+export default useDebouncedValue;
diff --git a/src/hooks/useRegisterDayTimetable.ts b/src/hooks/useRegisterDayTimetable.ts
@@ -69,13 +69,17 @@ const useRegisterDayTimetable = (): Result => {
enqueueSnackbar('正常に保存されました', { variant: 'success', autoHideDuration: 2000 });
queryClient.invalidateQueries(apiClient.timetables._grade(grade)._date(date.toJSON()).$path());
},
- onError: () => enqueueSnackbar('エラーが発生しました', { variant: 'error', autoHideDuration: 6000 }),
+ onError: () => {
+ enqueueSnackbar('エラーが発生しました', { variant: 'error', autoHideDuration: 6000 });
+ },
}
);
const submit = () => {
if (grade) {
dayTimetableMutation.mutate({ grade, date, body: timetable });
+ } else {
+ enqueueSnackbar('学年を選択してください', { variant: 'error', autoHideDuration: 6000 });
}
};
diff --git a/src/pages/console/standard.tsx b/src/pages/console/standard.tsx
@@ -7,6 +7,7 @@ import Breadcrumbs from '@mui/material/Breadcrumbs';
import CircularProgress from '@mui/material/CircularProgress';
import Container from '@mui/material/Container';
import FormControl from '@mui/material/FormControl';
+import FormHelperText from '@mui/material/FormHelperText';
import InputLabel from '@mui/material/InputLabel';
import MenuItem from '@mui/material/MenuItem';
import Paper from '@mui/material/Paper';
@@ -21,6 +22,7 @@ import TextField from '@mui/material/TextField';
import Typography from '@mui/material/Typography';
import Link from 'components/common/Link';
+import useDebouncedValue from 'hooks/useDebouncedValue';
import useRegisterStandardTimetable from 'hooks/useRegisterStandardTimetable';
import type { NextPage } from 'next';
@@ -145,9 +147,11 @@ const Page: NextPage = () => {
const { loading, sending, classes, classId, setClassId, standard, setStandard, submit } =
useRegisterStandardTimetable();
+ const debouncedLoading = useDebouncedValue(loading, 1000);
+
return (
<Container maxWidth='lg' component={Box} py={2}>
- <Backdrop open={loading}>
+ <Backdrop open={loading && !!debouncedLoading}>
<CircularProgress color='inherit' />
</Backdrop>
@@ -163,8 +167,8 @@ const Page: NextPage = () => {
</Typography>
</Breadcrumbs>
- <Box width='7rem' m={4}>
- <FormControl fullWidth disabled={loading}>
+ <Box width='8rem' m={4}>
+ <FormControl fullWidth required disabled={loading} error={typeof classId === 'undefined'}>
<InputLabel>クラス</InputLabel>
<Select value={classId ?? ''} label='クラス' onChange={(e) => setClassId(e.target.value as number)}>
{classes.map((c) => (
@@ -173,6 +177,7 @@ const Page: NextPage = () => {
</MenuItem>
))}
</Select>
+ {typeof classId === 'undefined' && <FormHelperText>選択してください</FormHelperText>}
</FormControl>
</Box>
diff --git a/src/pages/console/timetable.tsx b/src/pages/console/timetable.tsx
@@ -12,6 +12,7 @@ import Button from '@mui/material/Button';
import CircularProgress from '@mui/material/CircularProgress';
import Container from '@mui/material/Container';
import FormControl from '@mui/material/FormControl';
+import FormHelperText from '@mui/material/FormHelperText';
import IconButton from '@mui/material/IconButton';
import InputLabel from '@mui/material/InputLabel';
import MenuItem from '@mui/material/MenuItem';
@@ -29,6 +30,7 @@ import {
ABSTRACT_LESSON_NAME_MAP_EN_TO_JA,
ABSTRACT_LESSON_NAME_MAP_JA_TO_EN,
} from 'constant';
+import useDebouncedValue from 'hooks/useDebouncedValue';
import useRegisterDayTimetable from 'hooks/useRegisterDayTimetable';
import { dateToPlainDate, plainDateToDate } from 'utils';
@@ -72,11 +74,12 @@ const Page: NextPage = () => {
submit,
} = useRegisterDayTimetable();
+ const debouncedLoading = useDebouncedValue(loading, 1000);
+
// TODO: Temporal をそのまま扱える Adapter を用意する?
- // TODO: データフェッチに一定以上の時間がかかった場合のみ進捗表示を出す
return (
<Container maxWidth='lg' component={Box} py={2}>
- <Backdrop open={loading}>
+ <Backdrop open={loading && !!debouncedLoading}>
<CircularProgress color='inherit' />
</Backdrop>
@@ -93,8 +96,8 @@ const Page: NextPage = () => {
</Breadcrumbs>
<Stack direction={{ xs: 'column', sm: 'row' }} spacing={{ xs: 2, sm: 8 }} m={4}>
- <Box width='7rem'>
- <FormControl fullWidth required disabled={loading} size='small'>
+ <Box width='8rem'>
+ <FormControl fullWidth required disabled={loading} size='small' error={typeof grade === 'undefined'}>
<InputLabel>学年</InputLabel>
<Select value={grade ?? ''} label='学年' onChange={(e) => setGrade(e.target.value as number)}>
{grades.map((g) => (
@@ -103,10 +106,11 @@ const Page: NextPage = () => {
</MenuItem>
))}
</Select>
+ {typeof grade === 'undefined' && <FormHelperText>選択してください</FormHelperText>}
</FormControl>
</Box>
- <Stack direction='row' spacing={1}>
+ <Stack direction='row' spacing={1} alignItems='flex-start'>
<IconButton onClick={() => setDate((old) => old.subtract({ days: 1 }))}>
<ChevronLeftIcon />
</IconButton>
diff --git a/yarn.lock b/yarn.lock
@@ -96,16 +96,7 @@ __metadata:
languageName: node
linkType: hard
-"@babel/runtime@npm:^7.1.2":
- version: 7.20.0
- resolution: "@babel/runtime@npm:7.20.0"
- dependencies:
- regenerator-runtime: ^0.13.10
- checksum: 637fca51db34f3a59d329b7e0d01163769fe94915fdb04e4ac4ba62de9f1ca637ce3a564fe3b0166ccdd7f02f14b6a5707ee3e550b3e01c72327c6620d8e6a8b
- languageName: node
- linkType: hard
-
-"@babel/runtime@npm:^7.10.2, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.18.9, @babel/runtime@npm:^7.19.0, @babel/runtime@npm:^7.6.2, @babel/runtime@npm:^7.7.2":
+"@babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.2, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.18.9, @babel/runtime@npm:^7.19.0, @babel/runtime@npm:^7.6.2, @babel/runtime@npm:^7.7.2":
version: 7.20.1
resolution: "@babel/runtime@npm:7.20.1"
dependencies: