pnp-chatbot-admin-v1 / components /SemesterFilter.tsx
FauziIsyrinApridal
perbaikan semester filter dan jurusan scrap tambahkan beatifulsoup
050f867
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>
);
}