timetable-app

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

index.tsx (2631B)


      1 import { useDidUpdate } from '@mantine/hooks';
      2 import { Box, Stack } from '@mui/material';
      3 import { Provider, createStore } from 'jotai';
      4 import { useEffect, useMemo, useState } from 'react';
      5 import { Swiper, SwiperSlide } from 'swiper/react';
      6 
      7 import { classAtom, gradeAtom } from './atoms';
      8 import DatePicker from './components/DatePicker';
      9 import JumpToTodayFab from './components/JumpToTodayFab';
     10 import Lessons from './components/Lessons';
     11 import SetMyClassFab from './components/SetMyClassFab';
     12 import useIndexAndDate from './hooks/useIndexAndDate';
     13 
     14 import type { DayTimetable } from './types';
     15 import type { Class, Grade } from 'common/types';
     16 import type SwiperClass from 'swiper';
     17 
     18 import 'swiper/css';
     19 
     20 const store = createStore();
     21 
     22 type Props = {
     23 	calendar: [string, DayTimetable][];
     24 	grade: Grade;
     25 	class: Class;
     26 };
     27 
     28 // TODO: jotai atom でデータ受け渡し
     29 export default function DailyView(props: Props) {
     30 	const dateStrings = useMemo(
     31 		() => props.calendar.map(([date]) => date),
     32 		[props.calendar],
     33 	);
     34 	const [swiper, setSwiper] = useState<SwiperClass>();
     35 
     36 	const { dates, index, setDate, setIndex } = useIndexAndDate(dateStrings);
     37 
     38 	const [initialIndex] = useState(index);
     39 
     40 	const handleSlideChange = (swiper: SwiperClass) =>
     41 		setIndex(swiper.activeIndex);
     42 
     43 	// index が変わると swiper をスライド
     44 	useDidUpdate(() => {
     45 		if (swiper?.activeIndex !== index) {
     46 			swiper?.slideTo(index);
     47 		}
     48 	}, [index]);
     49 
     50 	// 学年、クラスの情報を提供
     51 	useEffect(() => {
     52 		store.set(gradeAtom, props.grade);
     53 		store.set(classAtom, props.class);
     54 	}, [props.class, props.grade]);
     55 
     56 	return (
     57 		<Provider store={store}>
     58 			<Stack direction='column' width={1} minHeight={1} spacing={1} py={2}>
     59 				<DatePicker
     60 					dates={dates}
     61 					index={index}
     62 					setDate={setDate}
     63 					setIndex={setIndex}
     64 				/>
     65 
     66 				<Box flexGrow={1}>
     67 					{index < 0 ? (
     68 						<Box sx={{ p: 2 }}>時間割がありません</Box>
     69 					) : (
     70 						<Swiper
     71 							centeredSlides={true}
     72 							spaceBetween={30}
     73 							initialSlide={initialIndex}
     74 							onSwiper={setSwiper}
     75 							onSlideChange={handleSlideChange}
     76 						>
     77 							{props.calendar.map(([d, lessons]) => (
     78 								<SwiperSlide key={d}>
     79 									<Lessons timetable={lessons} />
     80 								</SwiperSlide>
     81 							))}
     82 						</Swiper>
     83 					)}
     84 				</Box>
     85 
     86 				<Box
     87 					sx={{
     88 						position: 'sticky',
     89 						bottom: 16,
     90 						marginLeft: '16px',
     91 						marginRight: '16px',
     92 						zIndex: 100,
     93 					}}
     94 				>
     95 					<JumpToTodayFab
     96 						dateStrings={dateStrings}
     97 						index={index}
     98 						setIndex={setIndex}
     99 					/>
    100 					<SetMyClassFab />
    101 				</Box>
    102 			</Stack>
    103 		</Provider>
    104 	);
    105 }