timetable-app

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

index.tsx (4221B)


      1 /** @jsxImportSource @emotion/react */
      2 import { useIsomorphicEffect } from '@mantine/hooks';
      3 import { GlobalStyles, Link, Alert as MUIAlert } from '@mui/material';
      4 import { css, styled } from '@mui/material/styles';
      5 import shuffle from 'lodash/shuffle';
      6 import { useState } from 'react';
      7 import { Autoplay, Pagination } from 'swiper/modules';
      8 import { Swiper, SwiperSlide } from 'swiper/react';
      9 import 'swiper/css';
     10 import 'swiper/css/autoplay';
     11 import 'swiper/css/pagination';
     12 
     13 import { BUG_REPORT_FORM_URL, FEEDBACK_FORM_URL } from 'common/constant';
     14 
     15 import type { AlertProps } from '@mui/material/Alert';
     16 import type { ReactNode } from 'react';
     17 
     18 const Alert = styled(MUIAlert)({
     19 	height: '100%',
     20 	paddingBottom: '22px', // ページネーション用の余白
     21 	borderRadius: 0,
     22 	verticalAlign: 'center',
     23 });
     24 
     25 const globalStyles = (
     26 	<GlobalStyles
     27 		styles={(theme) => css`
     28 			.swiper .swiper-slide {
     29 				height: auto;
     30 			}
     31 			.swiper .swiper-pagination-bullet {
     32 				background-color: ${theme.vars.palette.text.primary};
     33 				opacity: 0.3;
     34 			}
     35 			.swiper .swiper-pagination-bullet-active {
     36 				background-color: ${theme.vars.palette.primary.main};
     37 				opacity: 1;
     38 			}
     39 		`}
     40 	/>
     41 );
     42 
     43 type SlideData = {
     44 	id: number;
     45 	content: ReactNode;
     46 	severity?: AlertProps['severity'];
     47 	variant?: AlertProps['variant'];
     48 	icon?: AlertProps['icon'];
     49 };
     50 
     51 const prioritySlideData: SlideData[] = [
     52 	{
     53 		id: 11,
     54 		content: (
     55 			<>
     56 				情報の正確性を保証することはできませんので、参考程度にお使いください。時間割が間違っていた場合、学校・IT部は一切の責任を負いません。
     57 			</>
     58 		),
     59 		severity: 'warning',
     60 	},
     61 	{
     62 		id: 12,
     63 		content: (
     64 			<>臨時変更には対応していません。教室掲示のプリントで確認してください。</>
     65 		),
     66 		severity: 'warning',
     67 	},
     68 	{
     69 		id: 13,
     70 		content: (
     71 			<>
     72 				臨時変更の情報を入力する機能を追加しました!登録した臨時変更情報は他の利用者に共有されません。ご要望ありがとうございました。
     73 			</>
     74 		),
     75 	},
     76 ];
     77 
     78 const extraSlideData: SlideData[] = [
     79 	{
     80 		id: 101,
     81 		content: (
     82 			<>
     83 				このアプリはIT部が制作・運営しています。人手不足なので助けてください。
     84 				プログラミング経験者や開発に興味がある人はIT部まで!
     85 			</>
     86 		),
     87 	},
     88 	{
     89 		id: 102,
     90 		content: (
     91 			<>
     92 				IT部
     93 				部員募集中!ボカロ楽曲制作、プログラミング、動画制作などやってます。
     94 				毎週木・金曜日にLAN教室までお気軽にお越しください!
     95 			</>
     96 		),
     97 	},
     98 	{
     99 		id: 103,
    100 		content: (
    101 			<>
    102 				<Link href={FEEDBACK_FORM_URL} target='_blank' rel='noopener'>
    103 					フィードバックアンケート
    104 				</Link>
    105 				で、このアプリの評価にご協力お願いします。ご意見・ご要望もお待ちしております。
    106 			</>
    107 		),
    108 	},
    109 	{
    110 		id: 104,
    111 		content: (
    112 			<>
    113 				アプリの不具合や時間割情報の誤りを見つけた場合は、
    114 				<Link href={BUG_REPORT_FORM_URL} target='_blank' rel='noopener'>
    115 					Googleフォーム
    116 				</Link>
    117 				で報告お願いします。
    118 			</>
    119 		),
    120 	},
    121 	// {
    122 	// 	id: 105,
    123 	// 	content: (
    124 	// 		<>
    125 	// 			広告募集中!ここに文字広告を載せられます。木・金曜日にLAN教室にお越しになるか、お近くのIT部員にお声がけください。
    126 	// 		</>
    127 	// 	),
    128 	// },
    129 	{
    130 		id: 106,
    131 		content: (
    132 			<>
    133 				各時限の時間割をタップすると、授業場所、臨時変更入力機能、メモ機能などが表示されます。
    134 			</>
    135 		),
    136 	},
    137 ];
    138 
    139 export default function SlideFooter() {
    140 	const [slideData, setSlideData] = useState([...prioritySlideData]);
    141 	useIsomorphicEffect(
    142 		() => setSlideData([...prioritySlideData, ...shuffle(extraSlideData)]),
    143 		[],
    144 	);
    145 
    146 	return (
    147 		<Swiper
    148 			modules={[Autoplay, Pagination]}
    149 			autoplay={{ delay: 5000 }}
    150 			pagination={{ clickable: true }}
    151 			allowTouchMove={false}
    152 			loop
    153 		>
    154 			{globalStyles}
    155 			{slideData.map((data) => (
    156 				<SwiperSlide key={data.id}>
    157 					<Alert
    158 						severity={data.severity ?? 'info'}
    159 						variant={data.variant ?? 'standard'}
    160 					>
    161 						{data.content}
    162 					</Alert>
    163 				</SwiperSlide>
    164 			))}
    165 		</Swiper>
    166 	);
    167 }