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 }