Skip to content

Commit a524dc2

Browse files
committed
[Add] evaluation filter
1 parent e098fc1 commit a524dc2

File tree

3 files changed

+148
-0
lines changed

3 files changed

+148
-0
lines changed
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* 評価方法フィルターのコンポーネント
3+
*/
4+
5+
"use client";
6+
import React, { ReactNode } from "react";
7+
import { Evaluation } from "@/app/type";
8+
import Checkbox from "../UI/Checkbox";
9+
10+
const evaluations: Evaluation[] = ["試験", "レポート", "出席", "平常"];
11+
12+
/**
13+
* 評価方法フィルターのプロパティ
14+
*/
15+
interface EvaluationProp {
16+
evaluation_included?: Evaluation[];
17+
evaluation_excluded?: Evaluation[];
18+
setEvaluation: (
19+
evaluation_included: Evaluation[],
20+
evaluation_excluded: Evaluation[],
21+
) => void;
22+
}
23+
24+
/**
25+
* 評価方法フィルターのコンポーネント
26+
* @param prop 評価方法フィルターのプロパティ
27+
* @returns 評価方法フィルターのコンポーネント
28+
*/
29+
export const EvaluationFilter: React.FC<EvaluationProp> = (
30+
prop: EvaluationProp,
31+
) => {
32+
const slots: ReactNode[] = [];
33+
34+
slots.push(<div key={"void"} />);
35+
slots.push(<div key={"label_in"}>含む</div>);
36+
slots.push(<div key={"label_ex"}>除外</div>);
37+
38+
evaluations.map((ev) => {
39+
slots.push(<div key={ev + "header"}>{ev.substring(0, 2)}</div>);
40+
slots.push(
41+
<CheckboxInGrid
42+
isInclude={true}
43+
ev={ev}
44+
key={ev + "included"}
45+
prop={prop}
46+
/>,
47+
);
48+
slots.push(
49+
<CheckboxInGrid
50+
isInclude={false}
51+
ev={ev}
52+
key={ev + "excluded"}
53+
prop={prop}
54+
/>,
55+
);
56+
});
57+
58+
return <div className="grid grid-rows-3 grid-flow-col gap-2">{slots}</div>;
59+
};
60+
61+
/**
62+
* グリッド上に並べるチェックボックスのコンポーネント
63+
* @param param0 プロパティ
64+
* @param param0.isInclude このチェックボックスが、含めたい評価方法を示しているか否か
65+
* @param param0.ev 評価方法
66+
* @param param0.prop 評価方法のフィルターコンポーネントのプロパティ
67+
* @returns チェックボックスコンポーネント
68+
*/
69+
const CheckboxInGrid: React.FC<{
70+
isInclude: boolean;
71+
ev: Evaluation;
72+
prop: EvaluationProp;
73+
}> = ({ isInclude, ev, prop }) => {
74+
let evaluation_included = prop.evaluation_included ?? [];
75+
let evaluation_excluded = prop.evaluation_excluded ?? [];
76+
let myEvaluation = isInclude ? evaluation_included : evaluation_excluded;
77+
let otherEvaluation = isInclude ? evaluation_excluded : evaluation_included;
78+
79+
// クリックされたときの挙動
80+
const onClick = (ev: Evaluation) => {
81+
if (myEvaluation.includes(ev)) {
82+
// もともとチェックされていたボックスをクリックしたら、外す
83+
myEvaluation.splice(myEvaluation.indexOf(ev), 1);
84+
} else {
85+
// もともとチェックされていなかったボックスをクリックしたら
86+
const index = otherEvaluation.indexOf(ev); // 相方のチェックがされているかを確認
87+
if (index >= 0) otherEvaluation.splice(index, 1); // 相方のチェックを外す
88+
console.log(index);
89+
myEvaluation.push(ev); // 自分のボックスにチェックを入れる
90+
}
91+
92+
prop.setEvaluation(evaluation_included, evaluation_excluded);
93+
};
94+
95+
return (
96+
<Checkbox
97+
checked={myEvaluation.includes(ev)}
98+
onChange={(_) => onClick(ev)}
99+
/>
100+
);
101+
};

src/app/components/FilterUI/FilterUI.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { useState } from "react";
77
import { ClassType, Evaluation, Semester } from "@/app/type";
88
import { SemestersCheckbox } from "./FilterComponents/Semester";
99
import { FilterCard } from "./UI/FilterCard";
10+
import { EvaluationFilter } from "./FilterComponents/Evaluation";
1011

1112
/**
1213
* フィルタの型定義
@@ -39,6 +40,19 @@ export const FilterUI: React.FC = () => {
3940
}
4041
/>
4142
</FilterCard>
43+
44+
<FilterCard title={"評価方法"}>
45+
<EvaluationFilter
46+
evaluation_included={filter.evaluation_included}
47+
evaluation_excluded={filter.evaluation_excluded}
48+
setEvaluation={(
49+
evaluation_included: Evaluation[],
50+
evaluation_excluded,
51+
) =>
52+
setFilter({ ...filter, evaluation_included, evaluation_excluded })
53+
}
54+
/>
55+
</FilterCard>
4256
</div>
4357
);
4458
};
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
"use client";
2+
import React from "react";
3+
4+
type CheckboxProps = {
5+
checked: boolean; // チェック状態
6+
onChange: (checked: boolean) => void; // チェック状態が変化したときのコールバック
7+
className?: string;
8+
};
9+
10+
/**
11+
* チェックボックスコンポーネント
12+
* @param param0 チェックボックスのプロパティ
13+
* @param param0.checked チェック状態
14+
* @param param0.onChange チェック状態が変化したときのコールバック
15+
* @param param0.className tailwindcss
16+
* @returns チェックボックスコンポーネント
17+
*/
18+
const Checkbox: React.FC<CheckboxProps> = ({
19+
checked,
20+
onChange,
21+
className,
22+
}) => {
23+
return (
24+
<input
25+
type="checkbox"
26+
checked={checked}
27+
onChange={() => onChange(!checked)}
28+
className={"accent-primary w-6 h-6 " + className}
29+
/>
30+
);
31+
};
32+
33+
export default Checkbox;

0 commit comments

Comments
 (0)