diff --git a/web/app/globals.css b/web/app/globals.css index d0c12603..b4c8ea0d 100644 --- a/web/app/globals.css +++ b/web/app/globals.css @@ -8,6 +8,10 @@ max-height: 450px; } +.btn { + @apply font-normal; +} + .cm-li-btn { @apply no-animation h-auto w-full justify-start rounded-none border-none bg-white px-6 py-4 text-left font-normal text-base shadow-none hover:bg-zinc-100 focus:bg-zinc-300; } @@ -16,3 +20,11 @@ .cm-pb-footer { padding-bottom: calc(3rem + env(safe-area-inset-bottom)); } + +.scrollbar-hide::-webkit-scrollbar { + display: none; +} +.scrollbar-hide { + -ms-overflow-style: none; + scrollbar-width: none; +} diff --git a/web/components/course/components/CourseRegisterConfirmDialog.tsx b/web/components/course/components/CourseRegisterConfirmDialog.tsx index 074c480c..bdbc9b0c 100644 --- a/web/components/course/components/CourseRegisterConfirmDialog.tsx +++ b/web/components/course/components/CourseRegisterConfirmDialog.tsx @@ -46,9 +46,7 @@ export default function CourseRegisterConfirmDialog({ return (
-

- {mode === "add" ? "変更" : "削除"}の確認 -

+

{mode === "add" ? "変更" : "削除"}の確認

{mode === "add" ? "次のように変更" : "次の授業を削除"} します。よろしいですか? diff --git a/web/components/course/components/SelectCourseDialog.tsx b/web/components/course/components/SelectCourseDialog.tsx index 52f5dafa..38dfa20a 100644 --- a/web/components/course/components/SelectCourseDialog.tsx +++ b/web/components/course/components/SelectCourseDialog.tsx @@ -1,9 +1,57 @@ import { DAY_TO_JAPANESE_MAP } from "common/consts"; import type { Course, Day } from "common/types"; import { useEffect, useState } from "react"; +import { MdClose, MdSearch } from "react-icons/md"; import courseApi from "~/api/course"; import CourseRegisterConfirmDialog from "./CourseRegisterConfirmDialog"; +import TagFilter from "./TagFilter"; +const faculties = [ + "all", + "zenki", + "law", + "medicine", + "engineering", + "arts", + "science", + "agriculture", + "economics", + "liberal-arts", + "education", + "pharmacy", +] as const; +export type FacultyKey = (typeof faculties)[number]; +const facultyRegExMap = new Map([ + ["all", /.*/], + ["zenki", /^[34].*/], + ["law", /^01.*/], + ["medicine", /^02.*/], + ["engineering", /^FEN.*/], + ["arts", /^04.*/], + ["science", /^05.*/], + ["agriculture", /^06.*/], + ["economics", /^07.*/], + ["liberal-arts", /^08.*/], + ["education", /^09.*/], + ["pharmacy", /^10.*/], +]); + +const facultyNameMap = new Map([ + ["all", "全て"], + ["zenki", "前期教養"], + ["law", "法"], + ["medicine", "医"], + ["engineering", "工"], + ["arts", "文"], + ["science", "理"], + ["agriculture", "農"], + ["economics", "経済"], + ["liberal-arts", "後期教養"], + ["education", "教育"], + ["pharmacy", "薬"], +]); + +// TODO: フィルタのロジックが異様にばらけているのでリファクタしよう・・ export default function SelectCourseDialog({ open, onClose, @@ -21,6 +69,7 @@ export default function SelectCourseDialog({ }) { const [availableCourses, setAvailableCourses] = useState([]); const [searchText, setSearchText] = useState(""); + const [selectedFaculty, setSelectedFaculty] = useState("all"); const [filteredAvailableCourses, setFilteredAvailableCourses] = useState< Course[] >([]); @@ -45,7 +94,7 @@ export default function SelectCourseDialog({ return ( // biome-ignore lint/a11y/useKeyWithClickEvents:

e.stopPropagation()} >
@@ -62,40 +111,42 @@ export default function SelectCourseDialog({
-

- {currentEdit - ? `${DAY_TO_JAPANESE_MAP.get(currentEdit.columnName)}曜${ - currentEdit.rowIndex + 1 - }限の授業を選択` - : "授業を選択"} -

- +
+

+ {currentEdit + ? `${DAY_TO_JAPANESE_MAP.get(currentEdit.columnName)}曜${ + currentEdit.rowIndex + 1 + }限の授業を編集中` + : "編集"} +

+ +
-

現在の授業

+

現在の授業

{currentEdit?.course ? ( -
+

{currentEdit?.course?.name ?? "-"}

-

{`${ - currentEdit?.course?.teacher ?? "-" - } / ${currentEdit?.course?.id ?? "-"}`}

+

{`${currentEdit?.course?.teacher ?? "-"} / ${ + currentEdit?.course?.id ?? "-" + }`}

- - { - const text = e.target.value.trim(); - setSearchText(text); - const newFilteredCourses = availableCourses.filter((course) => - course.name.includes(text), - ); - setFilteredAvailableCourses(newFilteredCourses); - }} - /> + +
+ { + setSelectedFaculty((prev) => (prev === tag ? "all" : tag)); + }} + /> +
{filteredAvailableCourses.length === 0 ? (

条件に当てはまる授業はありません。

) : (
    - {filteredAvailableCourses.map((course) => ( -
  • - -
  • - ))} + {filteredAvailableCourses + .filter((course) => + facultyRegExMap.get(selectedFaculty)?.test(course.id), + ) + .map((course) => ( +
  • + +
  • + ))}
)}
diff --git a/web/components/course/components/TagFilter.tsx b/web/components/course/components/TagFilter.tsx new file mode 100644 index 00000000..926641bf --- /dev/null +++ b/web/components/course/components/TagFilter.tsx @@ -0,0 +1,34 @@ +type Props = { + keyNameMap: Map; + selectedTag: T; + onTagChange: (tag: T) => void; +}; + +export default function TagFilter({ + keyNameMap, + selectedTag, + onTagChange, +}: Props) { + const tags = Array.from(keyNameMap.keys()); + return ( +
+ {tags.map((tag) => ( +
+ onTagChange(tag)} + /> + +
+ ))} +
+ ); +}