|
| 1 | +"use client"; |
| 2 | + |
1 | 3 | import { AuthCheck } from "@/components/auth-check";
|
| 4 | +import CustomCombobox from "@/components/combobox"; |
2 | 5 | import SettingsWrapper from "@/components/settings-wrapper";
|
3 |
| -import { Metadata } from "next"; |
| 6 | +import { |
| 7 | + useExportGroupEnrollments, |
| 8 | + useExportShiftGroups, |
| 9 | +} from "@/lib/queries/backoffice"; |
| 10 | +import { useGetAllCourses } from "@/lib/queries/courses"; |
| 11 | +import { ICourse } from "@/lib/types"; |
| 12 | +import clsx from "clsx"; |
| 13 | +import { useState } from "react"; |
| 14 | +import { twMerge } from "tailwind-merge"; |
| 15 | + |
| 16 | +function downloadFile({ |
| 17 | + data, |
| 18 | + fileName, |
| 19 | + fileType, |
| 20 | +}: { |
| 21 | + data: string; |
| 22 | + fileName: string; |
| 23 | + fileType: string; |
| 24 | +}) { |
| 25 | + const blob = new Blob([data], { type: fileType }); |
| 26 | + |
| 27 | + const a = document.createElement("a"); |
| 28 | + a.download = fileName; |
| 29 | + a.href = window.URL.createObjectURL(blob); |
| 30 | + const clickEvt = new MouseEvent("click", { |
| 31 | + view: window, |
| 32 | + bubbles: true, |
| 33 | + cancelable: true, |
| 34 | + }); |
| 35 | + a.dispatchEvent(clickEvt); |
| 36 | + a.remove(); |
| 37 | +} |
| 38 | + |
| 39 | +function formatCourses(courses: ICourse[] | undefined) { |
| 40 | + if (!courses) return []; |
4 | 41 |
|
5 |
| -export const metadata: Metadata = { |
6 |
| - title: "Pombo | Exports", |
7 |
| -}; |
| 42 | + return courses.map((course) => { |
| 43 | + return { id: course.id, name: course.name }; |
| 44 | + }); |
| 45 | +} |
8 | 46 |
|
9 | 47 | export default function Exports() {
|
| 48 | + const [selectedCourse, setSelectedCourse] = useState<{ |
| 49 | + id: string; |
| 50 | + name: string; |
| 51 | + } | null>(null); |
| 52 | + |
| 53 | + const { data: allCourses } = useGetAllCourses(); |
| 54 | + const { refetch: getShiftGroups, isError: exportShiftsGroupError } = |
| 55 | + useExportShiftGroups(selectedCourse?.id || ""); |
| 56 | + const { refetch: getGroupEnrollment, isError: exportGroupEnrollmentsError } = |
| 57 | + useExportGroupEnrollments(selectedCourse?.id || ""); |
| 58 | + |
| 59 | + const formattedCourses = formatCourses(allCourses); |
| 60 | + |
| 61 | + const handleShiftsGroupExport = async () => { |
| 62 | + const result = await getShiftGroups(); |
| 63 | + downloadFile({ |
| 64 | + data: result.data, |
| 65 | + fileName: `${selectedCourse?.name}-turmas.csv`, |
| 66 | + fileType: "text/csv", |
| 67 | + }); |
| 68 | + }; |
| 69 | + |
| 70 | + const handleGroupEnrollmentsExport = async () => { |
| 71 | + const result = await getGroupEnrollment(); |
| 72 | + downloadFile({ |
| 73 | + data: result.data, |
| 74 | + fileName: `${selectedCourse?.name}-inscrições.csv`, |
| 75 | + fileType: "text/csv", |
| 76 | + }); |
| 77 | + }; |
| 78 | + |
| 79 | + const validCourse = selectedCourse !== null; |
| 80 | + |
10 | 81 | return (
|
11 | 82 | <AuthCheck userTypes={["admin", "professor"]}>
|
12 |
| - <SettingsWrapper title="Export data"> |
13 |
| - <div>Exports Page</div> |
| 83 | + <title>Pombo | Exports</title> |
| 84 | + |
| 85 | + <SettingsWrapper title="Schedule Generator"> |
| 86 | + <div className="flex h-full flex-col gap-8"> |
| 87 | + <section className="space-y-2"> |
| 88 | + <h2 className="text-2xl font-semibold">Generate new schedule</h2> |
| 89 | + <p>Trigger the schedule generator with a few clicks</p> |
| 90 | + </section> |
| 91 | + |
| 92 | + <section className="space-y-6"> |
| 93 | + <div className="max-w-2xl space-y-6"> |
| 94 | + <div className="space-y-1"> |
| 95 | + <p className="pl-2 font-semibold select-none">Courses</p> |
| 96 | + <CustomCombobox |
| 97 | + items={formattedCourses} |
| 98 | + selectedItem={selectedCourse} |
| 99 | + setSelectedItem={setSelectedCourse} |
| 100 | + /> |
| 101 | + </div> |
| 102 | + </div> |
| 103 | + |
| 104 | + <div className="mt-6 inline-flex w-full max-w-2xl items-center gap-4"> |
| 105 | + <button |
| 106 | + disabled={!validCourse} |
| 107 | + onClick={handleShiftsGroupExport} |
| 108 | + className={twMerge( |
| 109 | + clsx( |
| 110 | + "w-1/2 rounded-lg px-4 py-2 text-sm font-semibold text-white transition-all duration-200 md:text-base", |
| 111 | + !validCourse |
| 112 | + ? "cursor-not-allowed bg-gray-400" |
| 113 | + : "bg-primary-400 hover:bg-primary-400/95 cursor-pointer hover:scale-98", |
| 114 | + ), |
| 115 | + )} |
| 116 | + > |
| 117 | + Shift Groups |
| 118 | + </button> |
| 119 | + |
| 120 | + <span className="text-dark/80 font-semibold">or</span> |
| 121 | + |
| 122 | + <button |
| 123 | + disabled={!validCourse} |
| 124 | + onClick={handleGroupEnrollmentsExport} |
| 125 | + className={twMerge( |
| 126 | + clsx( |
| 127 | + "w-1/2 rounded-lg px-4 py-2 text-sm font-semibold text-white transition-all duration-200 md:text-base", |
| 128 | + !validCourse |
| 129 | + ? "cursor-not-allowed bg-gray-400" |
| 130 | + : "bg-primary-400 hover:bg-primary-400/95 cursor-pointer hover:scale-98", |
| 131 | + ), |
| 132 | + )} |
| 133 | + > |
| 134 | + Group Enrollments |
| 135 | + </button> |
| 136 | + </div> |
| 137 | + |
| 138 | + {exportShiftsGroupError && ( |
| 139 | + <p className="text-dark/50 font-semibold"> |
| 140 | + Failed to download Shifts Group! |
| 141 | + </p> |
| 142 | + )} |
| 143 | + |
| 144 | + {exportGroupEnrollmentsError && ( |
| 145 | + <p className="text-dark/50 font-semibold"> |
| 146 | + Failed to download Group Enrollment! |
| 147 | + </p> |
| 148 | + )} |
| 149 | + </section> |
| 150 | + </div> |
14 | 151 | </SettingsWrapper>
|
15 | 152 | </AuthCheck>
|
16 | 153 | );
|
|
0 commit comments