-
- Generate new schedule
- Trigger the schedule generator with a few clicks
-
+
+
+
+
+ Generate new schedule
+ Trigger the schedule generator with a few clicks
+
-
-
-
+
+
+
-
-
Semester
-
({
- id: `semester-${semester}`,
- name: semester.toString(),
- }))}
- selectedItem={selectedSemester}
- setSelectedItem={setSelectedSemester}
- />
+
+
Semester
+
({
+ id: `semester-${semester}`,
+ name: semester.toString(),
+ }))}
+ selectedItem={selectedSemester}
+ setSelectedItem={setSelectedSemester}
+ />
+
-
-
+
- {generateSchedule.isPending && (
- Pending...
- )}
+ {generateSchedule.isPending && (
+ Pending...
+ )}
- {generateSchedule.isSuccess && (
-
- {generateSchedule.data.message}
-
- )}
+ {generateSchedule.isSuccess && (
+
+ {generateSchedule.data.message}
+
+ )}
- {generateSchedule.isError && (
-
- {generateSchedule.error.message}
-
- )}
-
-
-
+ {generateSchedule.isError && (
+
+ {generateSchedule.error.message}
+
+ )}
+
+
+
+
);
}
diff --git a/src/app/(app)/settings/connections/page.tsx b/src/app/(app)/settings/connections/page.tsx
deleted file mode 100644
index 97064ab..0000000
--- a/src/app/(app)/settings/connections/page.tsx
+++ /dev/null
@@ -1,14 +0,0 @@
-import SettingsWrapper from "@/components/settings-wrapper";
-import { Metadata } from "next";
-
-export const metadata: Metadata = {
- title: "Pombo | Connections",
-};
-
-export default function Connections() {
- return (
-
- Connections Page
-
- );
-}
diff --git a/src/app/(app)/settings/notifications/page.tsx b/src/app/(app)/settings/notifications/page.tsx
deleted file mode 100644
index 05ae2c7..0000000
--- a/src/app/(app)/settings/notifications/page.tsx
+++ /dev/null
@@ -1,14 +0,0 @@
-import SettingsWrapper from "@/components/settings-wrapper";
-import { Metadata } from "next";
-
-export const metadata: Metadata = {
- title: "Pombo | Notifications",
-};
-
-export default function Notifications() {
- return (
-
- Notifications Page
-
- );
-}
diff --git a/src/app/(app)/settings/preferences/page.tsx b/src/app/(app)/settings/preferences/page.tsx
deleted file mode 100644
index f8da506..0000000
--- a/src/app/(app)/settings/preferences/page.tsx
+++ /dev/null
@@ -1,14 +0,0 @@
-import SettingsWrapper from "@/components/settings-wrapper";
-import { Metadata } from "next";
-
-export const metadata: Metadata = {
- title: "Pombo | Preferences",
-};
-
-export default function Preferences() {
- return (
-
- Preferences Page
-
- );
-}
diff --git a/src/app/(app)/settings/privacy/page.tsx b/src/app/(app)/settings/privacy/page.tsx
deleted file mode 100644
index e1bbd53..0000000
--- a/src/app/(app)/settings/privacy/page.tsx
+++ /dev/null
@@ -1,14 +0,0 @@
-import SettingsWrapper from "@/components/settings-wrapper";
-import { Metadata } from "next";
-
-export const metadata: Metadata = {
- title: "Pombo | Privacy",
-};
-
-export default function Privacy() {
- return (
-
- Privacy Page
-
- );
-}
diff --git a/src/components/calendar/event-card.tsx b/src/components/calendar/event-card.tsx
index 87859aa..f6fcd13 100644
--- a/src/components/calendar/event-card.tsx
+++ b/src/components/calendar/event-card.tsx
@@ -2,8 +2,8 @@ import { EventProps } from "react-big-calendar";
import { editColor } from "@/lib/utils";
export default function EventCard({ event }: EventProps) {
- const building = event.resource?.building || "";
- const room = event.resource?.room || "";
+ const building = event.resource?.building;
+ const room = event.resource?.room;
const textColor = event.resource?.textColor;
const location = `${building} - ${room}`;
@@ -26,9 +26,9 @@ export default function EventCard({ event }: EventProps) {
>
{event.title}
-
- {location || "No location"}
-
+ {building && room && (
+
{location}
+ )}
);
diff --git a/src/components/calendar/event-modal.tsx b/src/components/calendar/event-modal.tsx
index 2a27b75..8c40330 100644
--- a/src/components/calendar/event-modal.tsx
+++ b/src/components/calendar/event-modal.tsx
@@ -152,11 +152,13 @@ export default function EventModal({
/>
)}
void;
+ className?: string;
+}
+
+export default function CustomCombobox({
+ items,
+ selectedItem,
+ setSelectedItem,
+ className,
+}: ICustomCombobox) {
+ const [query, setQuery] = useState("");
+
+ const filteredItems =
+ query === ""
+ ? items
+ : Object.values(items).filter((item) => {
+ return item.name.toLowerCase().includes(query.toLowerCase());
+ });
+
+ return (
+ setQuery("")}
+ >
+
+ item?.name || ""}
+ onChange={(event) => setQuery(event.target.value)}
+ className={clsx(
+ "bg-muted border-dark/10 w-full rounded-lg border py-1.5 pr-8 pl-3 text-sm/6",
+ "focus:not-data-focus:outline-none data-focus:outline-2 data-focus:-outline-offset-2 data-focus:outline-white/25",
+ )}
+ />
+
+
+
+ keyboard_arrow_down
+
+
+
+
+ {filteredItems.map((item) => (
+
+
+ check
+
+ {item.name}
+
+ ))}
+
+
+ );
+}
diff --git a/src/components/exchange/cards-section.tsx b/src/components/exchange/cards-section.tsx
index 4a8c537..c36eb52 100644
--- a/src/components/exchange/cards-section.tsx
+++ b/src/components/exchange/cards-section.tsx
@@ -33,10 +33,14 @@ export default function CardsSection({
const { data: exchangeDate } = useGetExchangeDate();
const now = new Date();
- const opening = new Date(exchangeDate?.data?.start ?? "");
- const deadline = new Date(exchangeDate?.data?.end ?? "");
+ const opening = new Date(exchangeDate?.data?.start);
+ const deadline = new Date(exchangeDate?.data?.end);
console.log({ now, opening, deadline });
- const hasExchangeDateClosed = now > deadline || now < opening;
+ const hasExchangeDateClosed =
+ now > deadline ||
+ now < opening ||
+ !exchangeDate?.data?.end ||
+ !exchangeDate?.data?.start;
return (
diff --git a/src/components/select.tsx b/src/components/select.tsx
index 9bb8472..8256b25 100644
--- a/src/components/select.tsx
+++ b/src/components/select.tsx
@@ -1,3 +1,4 @@
+import { IItemProps } from "@/lib/types";
import {
Listbox,
ListboxButton,
@@ -6,11 +7,6 @@ import {
} from "@headlessui/react";
import clsx from "clsx";
-interface IItemProps {
- id: string;
- name: string;
-}
-
interface ICustomSelectProps {
items: IItemProps[];
selectedItem: IItemProps;
diff --git a/src/components/sidebar-settings.tsx b/src/components/sidebar-settings.tsx
index b4975e5..6e742e1 100644
--- a/src/components/sidebar-settings.tsx
+++ b/src/components/sidebar-settings.tsx
@@ -32,10 +32,6 @@ export default function SidebarSettings() {
-
-
-
-
{user.data && ["admin", "professor"].includes(user.data.type) && (
diff --git a/src/contexts/schedule-provider.tsx b/src/contexts/schedule-provider.tsx
index 2207ca9..ecd2a56 100644
--- a/src/contexts/schedule-provider.tsx
+++ b/src/contexts/schedule-provider.tsx
@@ -171,11 +171,12 @@ function extractShifts(courses: ICourse[]): IShift[] {
end: shift.end,
shiftType: convertShiftType(shiftGroup.type),
shiftNumber: shiftGroup.number,
- building:
- Number(shift.building) <= 3
+ building: shift.building
+ ? Number(shift.building) <= 3
? `CP${shift.building}`
- : `Building ${shift.building}`,
- room: shift.room,
+ : `Building ${shift.building}`
+ : null,
+ room: shift.room || null,
year: course.year,
semester: course.semester,
eventColor: "#C3E5F9",
diff --git a/src/lib/backoffice.ts b/src/lib/backoffice.ts
index d17ecfb..56c976f 100644
--- a/src/lib/backoffice.ts
+++ b/src/lib/backoffice.ts
@@ -32,3 +32,25 @@ export async function generateSchedule(params: {
);
}
}
+
+export async function exportShiftGroups(course_id: string) {
+ try {
+ const res = await api.get(`/export/blackboard/${course_id}/groups`);
+ return res.data;
+ } catch {
+ throw new Error("Failed to export Shift Groups. Please try again later.");
+ }
+}
+
+export async function exportGroupEnrollments(course_id: string) {
+ try {
+ const res = await api.get(
+ `/export/blackboard/${course_id}/group_enrollments`,
+ );
+ return res.data;
+ } catch {
+ throw new Error(
+ "Failed to export Group Enrollment. Please try again later.",
+ );
+ }
+}
diff --git a/src/lib/queries/backoffice.ts b/src/lib/queries/backoffice.ts
index 2f930ec..d1aee26 100644
--- a/src/lib/queries/backoffice.ts
+++ b/src/lib/queries/backoffice.ts
@@ -1,5 +1,10 @@
import { useQuery } from "@tanstack/react-query";
-import { getDegrees, listJobs } from "../backoffice";
+import {
+ exportGroupEnrollments,
+ exportShiftGroups,
+ getDegrees,
+ listJobs,
+} from "../backoffice";
export function useListJobs() {
return useQuery({
@@ -15,3 +20,19 @@ export function useGetDegrees() {
queryFn: getDegrees,
});
}
+
+export function useExportShiftGroups(courseId: string) {
+ return useQuery({
+ queryKey: ["shift-groups-export"],
+ queryFn: () => exportShiftGroups(courseId),
+ enabled: false,
+ });
+}
+
+export function useExportGroupEnrollments(courseId: string) {
+ return useQuery({
+ queryKey: ["group-enrollments-export"],
+ queryFn: () => exportGroupEnrollments(courseId),
+ enabled: false,
+ });
+}
diff --git a/src/lib/types.ts b/src/lib/types.ts
index 7639fec..0a64a15 100644
--- a/src/lib/types.ts
+++ b/src/lib/types.ts
@@ -16,8 +16,8 @@ export interface ITimeSlot {
start: string;
end: string;
weekday: string;
- room: string;
- building: string;
+ room: string | null;
+ building: string | null;
}
export interface IShiftResponse {
@@ -51,8 +51,8 @@ export interface IShift {
end: string; // hour only
shiftType: "T" | "TP" | "PL" | "OL";
shiftNumber: number;
- building: string;
- room: string;
+ building: string | null;
+ room: string | null;
year: number;
semester: number;
eventColor: string;
@@ -101,3 +101,8 @@ export interface IJobProps {
inserted_at: Date;
user_id: string;
}
+
+export interface IItemProps {
+ id: string;
+ name: string;
+}