Spaces:
Running
Running
File size: 5,289 Bytes
050f867 17fabdd 050f867 17fabdd 050f867 17fabdd 050f867 17fabdd 050f867 17fabdd 050f867 17fabdd 050f867 17fabdd 050f867 17fabdd 050f867 17fabdd 050f867 17fabdd 050f867 17fabdd 050f867 17fabdd |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
import { useState } from "react";
import { ChevronDown, Filter, Calendar } from "lucide-react";
interface SemesterFilterProps {
dates: string[];
onFilterChange?: (semesterId: string) => void;
}
interface SemesterOption {
id: string;
label: string;
description: string;
}
export default function SemesterFilter({
dates,
onFilterChange,
}: SemesterFilterProps) {
const [semesterFilter, setSemesterFilter] = useState("all");
const [isFilterOpen, setIsFilterOpen] = useState(false);
// Extract unique academic years from dates
const extractAcademicYears = (dates: string[]): string[] => {
const yearSet = new Set<string>();
dates.forEach((dateStr) => {
const date = new Date(dateStr);
const year = date.getFullYear();
const month = date.getMonth() + 1;
let startYear: number;
if (month >= 9) {
// Odd semester: starts in September
startYear = year;
} else {
// Even semester: January–August of next year
startYear = year - 1;
}
const academicYear = `${startYear}/${startYear + 1}`;
yearSet.add(academicYear);
});
if (yearSet.size === 0) {
const currentYear = new Date().getFullYear();
yearSet.add(`${currentYear - 2}/${currentYear - 1}`);
yearSet.add(`${currentYear - 1}/${currentYear}`);
yearSet.add(`${currentYear}/${currentYear + 1}`);
}
return Array.from(yearSet).sort((a, b) => (a > b ? -1 : 1));
};
const academicYears = extractAcademicYears(dates);
// Generate semester options
const semesterOptions: SemesterOption[] = [];
academicYears.forEach((academicYear) => {
const [startYear, endYear] = academicYear.split("/");
semesterOptions.push({
id: `odd-${academicYear}`,
label: `Ganjil ${academicYear}`,
description: `September ${startYear} - January ${endYear}`,
});
semesterOptions.push({
id: `even-${academicYear}`,
label: `Genap ${academicYear}`,
description: `February - August ${endYear}`,
});
});
const handleFilterClick = () => {
setIsFilterOpen(!isFilterOpen);
};
const handleSemesterSelect = (semesterId: string) => {
setSemesterFilter(semesterId);
setIsFilterOpen(false);
if (onFilterChange) {
onFilterChange(semesterId);
}
};
const getCurrentFilterText = () => {
if (semesterFilter === "all") return "All Semesters";
const selectedSemester = semesterOptions.find(
(option) => option.id === semesterFilter,
);
return selectedSemester ? selectedSemester.label : "All Semesters";
};
return (
<div className="relative">
{/* Filter Button */}
<button
onClick={handleFilterClick}
className="flex items-center gap-2 rounded-md border border-gray-300 bg-white px-3 py-2 text-sm shadow-sm hover:bg-gray-50"
>
<Filter className="h-4 w-4" />
<Calendar className="h-4 w-4" />
<span>{getCurrentFilterText()}</span>
<ChevronDown className="h-4 w-4" />
</button>
{/* Dropdown Menu */}
{isFilterOpen && (
<div className="absolute z-50 mt-2 min-w-[240px] rounded-md border border-gray-200 bg-white shadow-lg">
<div className="py-1">
{/* All Semesters */}
<div
onClick={() => handleSemesterSelect("all")}
className={`cursor-pointer px-4 py-2 hover:bg-gray-100 ${
semesterFilter === "all" ? "bg-blue-50 text-blue-600" : ""
}`}
>
All Semesters
</div>
<div className="my-1 border-t border-gray-200" />
{/* Semester Options Grouped by Academic Year */}
{academicYears.map((year, yearIndex) => (
<div key={year}>
{yearIndex > 0 && (
<div className="my-1 border-t border-gray-200" />
)}
<div className="px-4 py-2 text-xs font-semibold text-gray-500">
Academic Year {year}
</div>
{/* Odd Semester */}
<div
onClick={() => handleSemesterSelect(`odd-${year}`)}
className={`cursor-pointer px-4 py-2 hover:bg-gray-100 ${
semesterFilter === `odd-${year}`
? "bg-blue-50 text-blue-600"
: ""
}`}
>
<div className="font-medium">Ganjil {year}</div>
<div className="text-xs text-gray-500">
September - January
</div>
</div>
{/* Even Semester */}
<div
onClick={() => handleSemesterSelect(`even-${year}`)}
className={`cursor-pointer px-4 py-2 hover:bg-gray-100 ${
semesterFilter === `even-${year}`
? "bg-blue-50 text-blue-600"
: ""
}`}
>
<div className="font-medium">Genap {year}</div>
<div className="text-xs text-gray-500">February - August</div>
</div>
</div>
))}
</div>
</div>
)}
</div>
);
}
|