Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
869 changes: 869 additions & 0 deletions src/app/(app)/settings/backoffice/events/page.tsx

Large diffs are not rendered by default.

17 changes: 13 additions & 4 deletions src/components/combobox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ interface ICustomCombobox {
setSelectedItem: (item: IItemProps | null) => void;
className?: string;
placeholder?: string;
disableFlip?: boolean;
required?: boolean;
}

export default function CustomCombobox({
Expand All @@ -25,6 +27,8 @@ export default function CustomCombobox({
setSelectedItem,
className,
placeholder,
disableFlip = false,
required = false,
}: ICustomCombobox) {
const [query, setQuery] = useState("");

Expand All @@ -47,8 +51,9 @@ export default function CustomCombobox({
placeholder={placeholder}
displayValue={(item: IItemProps) => item?.name || ""}
onChange={(event) => setQuery(event.target.value)}
required={required}
className={clsx(
"bg-muted border-dark/10 w-full rounded-lg border py-1.5 pr-8 pl-3 text-sm/6",
"bg-muted border-dark/10 w-full rounded-xl 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",
)}
/>
Expand All @@ -60,11 +65,15 @@ export default function CustomCombobox({
</ComboboxButton>
</div>
<ComboboxOptions
anchor="bottom"
anchor={disableFlip ? undefined : "bottom"}
transition
className={clsx(
"border-dark/5 bg-muted w-(--input-width) rounded-xl border p-1 [--anchor-gap:--spacing(1)] empty:invisible",
"transition duration-100 ease-in data-leave:data-closed:opacity-0",
"border-dark/5 bg-muted z-50 rounded-xl border p-1 empty:invisible",
"origin-top transition duration-150 ease-out",
"data-closed:scale-95 data-closed:opacity-0",
disableFlip
? "absolute top-full right-0 left-0 mt-1 max-h-60 overflow-auto"
: "w-(--input-width) [--anchor-gap:--spacing(1)]",
)}
>
{filteredItems.map((item) => (
Expand Down
7 changes: 2 additions & 5 deletions src/components/input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ interface IInputProps extends React.InputHTMLAttributes<HTMLInputElement> {
export default function Input({
type,
className,
value,
center_text,
min,
max,
Expand All @@ -27,18 +26,16 @@ export default function Input({
clsx(
className,
textAlignment,
"flex items-center rounded-xl border border-black/10 px-2 py-1.5 text-black outline-none md:px-3 md:py-2.5",
"flex w-full items-center rounded-xl border border-black/10 px-2 py-1.5 text-black outline-none md:px-3 md:py-2.5",
),
)}
>
<input
type={mutType}
value={value}
className={twMerge(
clsx(
className,
textAlignment,
"flex-1 bg-transparent text-black outline-none placeholder:text-black/30 invalid:border-red-500 invalid:text-red-600",
"w-full flex-1 bg-transparent text-black outline-none placeholder:text-black/30 invalid:border-red-500 invalid:text-red-600",
),
)}
min={type === "number" ? min : undefined}
Expand Down
65 changes: 65 additions & 0 deletions src/components/modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import {
Dialog,
DialogPanel,
Transition,
TransitionChild,
} from "@headlessui/react";
import clsx from "clsx";
import { Fragment } from "react";
import { twMerge } from "tailwind-merge";

interface IModalProps {
modalState: boolean;
onClose: () => void;
children: React.ReactNode;
className?: string;
}

export default function Modal({
modalState,
onClose,
children,
className,
}: IModalProps) {
return (
<Transition appear show={modalState} as={Fragment}>
<Dialog as="div" className="relative z-50" onClose={onClose}>
<TransitionChild
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="bg-dark/5 fixed inset-0 backdrop-blur-sm" />
</TransitionChild>
<div className="fixed inset-0 flex w-screen items-center justify-center p-4">
<TransitionChild
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 scale-95"
enterTo="opacity-100 scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95"
>
<DialogPanel
className={twMerge(
clsx(
"bg-muted/65 relative max-w-lg flex-1 space-y-4 rounded-2xl border border-black/10 p-6 shadow-xl focus:outline-0",
className,
),
)}
>
<div className="flex h-full w-full items-center justify-center">
{children}
</div>
</DialogPanel>
</TransitionChild>
</div>
</Dialog>
</Transition>
);
}
100 changes: 62 additions & 38 deletions src/components/sidebar-settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,50 +34,74 @@ export default function SidebarSettings() {
</SidebarItem>
</SidebarItemList>

{user.data && ["admin", "professor"].includes(user.data.type) && (
<>
<SidebarHeader>Backoffice</SidebarHeader>
{user.data &&
["admin", "professor", "department"].includes(user.data.type) && (
<>
<SidebarHeader>Backoffice</SidebarHeader>

<SidebarItemList>
<SidebarItem
id="configurations"
href="/settings/backoffice/configurations"
>
<SidebarItemLabel icon="settings" label="Configurations" />
</SidebarItem>
<SidebarItemList>
{["admin", "professor"].includes(user.data.type) && (
<>
<SidebarItem
id="configurations"
href="/settings/backoffice/configurations"
>
<SidebarItemLabel
icon="settings"
label="Configurations"
/>
</SidebarItem>

<SidebarItem id="exports" href="/settings/backoffice/exports">
<SidebarItemLabel icon="download" label="Export" />
</SidebarItem>
<SidebarItem
id="exports"
href="/settings/backoffice/exports"
>
<SidebarItemLabel icon="download" label="Export" />
</SidebarItem>

<SidebarItem id="jobs" href="/settings/backoffice/jobs">
<SidebarItemLabel icon="data_table" label="Jobs Monitor" />
</SidebarItem>
<SidebarItem id="jobs" href="/settings/backoffice/jobs">
<SidebarItemLabel
icon="data_table"
label="Jobs Monitor"
/>
</SidebarItem>

<SidebarItem
id="statistics"
href="/settings/backoffice/statistics"
>
<SidebarItemLabel icon="insights" label="Statistics" />
</SidebarItem>
<SidebarItem
id="statistics"
href="/settings/backoffice/statistics"
>
<SidebarItemLabel icon="insights" label="Statistics" />
</SidebarItem>
</>
)}

{user.data && user.data.type === "admin" && (
<>
<SidebarItem id="imports" href="/settings/backoffice/imports">
<SidebarItemLabel icon="upload" label="Import" />
</SidebarItem>
{user.data && user.data.type === "admin" && (
<>
<SidebarItem
id="imports"
href="/settings/backoffice/imports"
>
<SidebarItemLabel icon="upload" label="Import" />
</SidebarItem>

<SidebarItem
id="generator"
href="/settings/backoffice/generator"
>
<SidebarItemLabel icon="sdk" label="Schedule Generator" />
</SidebarItem>
</>
)}
</SidebarItemList>
</>
)}
<SidebarItem
id="generator"
href="/settings/backoffice/generator"
>
<SidebarItemLabel icon="sdk" label="Schedule Generator" />
</SidebarItem>
</>
)}

<SidebarItem id="events" href="/settings/backoffice/events">
<SidebarItemLabel
icon="event_upcoming"
label="Events & Categories"
/>
</SidebarItem>
</SidebarItemList>
</>
)}
</Sidebar>
</div>
);
Expand Down
61 changes: 61 additions & 0 deletions src/components/table.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import clsx from "clsx";

interface IParentProps {
children: React.ReactNode;
className?: string;
}

export function HeaderElement({
title,
className,
}: {
title: string;
className?: string;
}) {
return (
<th
className={clsx("text-dark/50 p-4 text-start font-semibold", className)}
>
{title}
</th>
);
}

export function TableHeader({ children, className }: IParentProps) {
return (
<thead className={clsx("sticky top-0 z-10 bg-white shadow-sm", className)}>
<tr>{children}</tr>
</thead>
);
}

export function TableContent({ children, className }: IParentProps) {
return (
<tbody
className={clsx("divide-dark/10 divide-y overflow-y-scroll", className)}
>
{children}
</tbody>
);
}

export function TableItemWrapper({ children, className }: IParentProps) {
return <tr className={clsx("", className)}>{children}</tr>;
}

export function TableCell({ children, className }: IParentProps) {
return <td className={clsx("p-4", className)}>{children}</td>;
}

export default function Table({ children, className }: IParentProps) {
return (
<div
className={clsx(
"border-dark/10 flex h-full min-h-0 flex-col overflow-auto rounded-xl border",
className,
)}
>
<table className="w-full">{children}</table>
</div>
);
}
12 changes: 2 additions & 10 deletions src/contexts/events-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
IEventCategory,
IEventResponse,
} from "@/lib/types";
import { getContrastColor } from "@/lib/utils";
import { getContrastColor, isAllDayEvent } from "@/lib/utils";
import moment from "moment";
import { createContext, useEffect, useState } from "react";

Expand Down Expand Up @@ -106,14 +106,6 @@ function formatEvents(events: IEventResponse[]) {
const start = moment.utc(event.start);
const end = moment.utc(event.end);

const startsAtMidnight =
start.hours() === 0 && start.minutes() === 0 && start.seconds() === 0;
const endsAtMidnight =
end.hours() === 0 && end.minutes() === 0 && end.seconds() === 0;
const allday =
(startsAtMidnight && endsAtMidnight) ||
end.diff(start, "days", true) >= 1;

return {
id: event.id,
title: event.title,
Expand All @@ -124,7 +116,7 @@ function formatEvents(events: IEventResponse[]) {
link: event.link,
eventColor: event.category.color,
textColor: getContrastColor(event.category.color, 5),
allDay: allday,
allDay: isAllDayEvent(start, end),
};
});
}
Expand Down
Loading