Skip to content

Commit

Permalink
Merge pull request #1210 from Shelf-nu/1203-bug-styling-of-calendar-e…
Browse files Browse the repository at this point in the history
…vents-is-broken

fix: styling of calendar events is broken
  • Loading branch information
DonKoko authored Jul 26, 2024
2 parents cff60fb + d4f92be commit b05997e
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 79 deletions.
2 changes: 1 addition & 1 deletion app/components/shared/user-badge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const UserBadge = ({
imgClassName,
name,
}: UserBadgeProps) => (
<div className="max-w-[250px]">
<div className="h-6 max-w-[250px]">
<span
className={tw(
"ml-1 inline-flex w-max items-center rounded-2xl bg-gray-100 px-2 py-0.5",
Expand Down
137 changes: 66 additions & 71 deletions app/routes/_layout+/calendar.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { useState, useRef, useCallback } from "react";
import type { EventHoveringArg } from "@fullcalendar/core/index.js";
import type {
EventContentArg,
EventHoveringArg,
} from "@fullcalendar/core/index.js";
import dayGridPlugin from "@fullcalendar/daygrid";
import listPlugin from "@fullcalendar/list";
import FullCalendar from "@fullcalendar/react";
Expand All @@ -9,7 +12,6 @@ import { ChevronLeftIcon, ChevronRightIcon } from "@radix-ui/react-icons";
import type { LoaderFunctionArgs, MetaFunction } from "@remix-run/node";
import { json } from "@remix-run/node";
import { Link, useLoaderData } from "@remix-run/react";
import { format } from "date-fns";
import { ClientOnly } from "remix-utils/client-only";
import FallbackLoading from "~/components/dashboard/fallback-loading";
import { ArrowRightIcon } from "~/components/icons/library";
Expand All @@ -25,10 +27,11 @@ import {
} from "~/components/shared/hover-card";
import { Spinner } from "~/components/shared/spinner";
import { UserBadge } from "~/components/shared/user-badge";
import When from "~/components/when/when";
import { useViewportHeight } from "~/hooks/use-viewport-height";
import calendarStyles from "~/styles/layout/calendar.css?url";
import { appendToMetaTitle } from "~/utils/append-to-meta-title";
import { statusClassesOnHover } from "~/utils/calendar";
import { isOneDayEvent, statusClassesOnHover } from "~/utils/calendar";
import { getWeekStartingAndEndingDates } from "~/utils/date-fns";
import { makeShelfError } from "~/utils/error";
import { data, error } from "~/utils/http.server";
Expand All @@ -37,6 +40,7 @@ import {
PermissionEntity,
} from "~/utils/permissions/permission.data";
import { requirePermission } from "~/utils/roles.server";
import { tw } from "~/utils/tw";
import { bookingStatusColorMap } from "./bookings";

export function links() {
Expand Down Expand Up @@ -102,7 +106,7 @@ export const DATE_FORMAT_OPTIONS = {
} as const;

// Calendar Component
const Calendar = () => {
export default function Calendar() {
const { title } = useLoaderData<typeof loader>();
const { isMd } = useViewportHeight();
const [startingDay, endingDay] = getWeekStartingAndEndingDates(new Date());
Expand Down Expand Up @@ -245,71 +249,7 @@ const Calendar = () => {
eventMouseEnter={handleEventMouseEnter}
eventMouseLeave={handleEventMouseLeave}
windowResize={handleWindowResize}
eventContent={(args) => {
const hoveredBooking = args.event
.extendedProps as CalendarExtendedProps;

const startTime = format(
new Date(hoveredBooking.start),
"hh:mm"
);

return (
<HoverCard openDelay={0} closeDelay={0}>
<HoverCardTrigger className="inline-block w-full truncate">
{startTime} | {args.event.title}
</HoverCardTrigger>

<HoverCardPortal>
<HoverCardContent
className="pointer-events-none md:w-96"
side="top"
>
<div className="flex w-full items-center gap-x-2 text-xs text-gray-600">
<DateS
date={hoveredBooking.start}
options={DATE_FORMAT_OPTIONS}
/>
<ArrowRightIcon className="size-3 text-gray-600" />
<DateS
date={hoveredBooking.end}
options={DATE_FORMAT_OPTIONS}
/>
</div>

<p className="mb-3 text-sm font-medium">
{hoveredBooking.name}
</p>

<div className="mb-3 flex items-center gap-2">
<Badge
color={bookingStatusColorMap[hoveredBooking.status]}
>
<span className="block lowercase first-letter:uppercase">
{hoveredBooking.status}
</span>
</Badge>

<UserBadge
imgClassName="rounded-full"
name={hoveredBooking.custodian.name}
img={
hoveredBooking?.custodian.image ??
"/static/images/default_pfp.jpg"
}
/>
</div>

{hoveredBooking.description ? (
<div className="wordwrap rounded border border-gray-200 bg-gray-25 p-2 text-gray-500">
{hoveredBooking.description}
</div>
) : null}
</HoverCardContent>
</HoverCardPortal>
</HoverCard>
);
}}
eventContent={renderEventCard}
eventTimeFormat={{
hour: "numeric",
minute: "2-digit",
Expand All @@ -323,6 +263,61 @@ const Calendar = () => {
</div>
</>
);
};
}

const renderEventCard = (args: EventContentArg) => {
const event = args.event;
const booking = event.extendedProps as CalendarExtendedProps;
const _isOneDayEvent = isOneDayEvent(booking.start, booking.end);

return (
<HoverCard openDelay={0} closeDelay={0}>
<HoverCardTrigger asChild>
<div className={tw("inline-block truncate bg-transparent")}>
<When truthy={_isOneDayEvent}>
<div className="fc-daygrid-event-dot inline-block" />
</When>
<DateS
date={booking.start}
options={{
timeStyle: "short",
}}
/>{" "}
| {args.event.title}
</div>
</HoverCardTrigger>

<HoverCardPortal>
<HoverCardContent className="pointer-events-none md:w-96" side="top">
<div className="flex w-full items-center gap-x-2 text-xs text-gray-600">
<DateS date={booking.start} options={DATE_FORMAT_OPTIONS} />
<ArrowRightIcon className="size-3 text-gray-600" />
<DateS date={booking.end} options={DATE_FORMAT_OPTIONS} />
</div>

<div className="mb-3 mt-1 text-sm font-medium">{booking.name}</div>

<div className="mb-3 flex items-center gap-2">
<Badge color={bookingStatusColorMap[booking.status]}>
<span className="block lowercase first-letter:uppercase">
{booking.status}
</span>
</Badge>

export default Calendar;
<UserBadge
imgClassName="rounded-full"
name={booking.custodian.name}
img={booking?.custodian.image ?? "/static/images/default_pfp.jpg"}
/>
</div>

{booking.description ? (
<div className="wordwrap rounded border border-gray-200 bg-gray-25 p-2 text-gray-500">
{booking.description}
</div>
) : null}
</HoverCardContent>
</HoverCardPortal>
</HoverCard>
);
};
1 change: 1 addition & 0 deletions app/styles/layout/calendar.css
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

.fc-event-main {
color: inherit !important;
/* @apply !max-h-[20px]; */
}
.fc-event-title {
font-weight: inherit !important;
Expand Down
15 changes: 8 additions & 7 deletions app/utils/calendar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ export function getStatusClasses(
"!font-normal",
"py-[2px] px-[5px]",
"hover:cursor-pointer",
"max-h-[24px]",
];
if (oneDayEvent) {
classes.push(" [&>.fc-event-title]:!truncate bg-transparent");
classes.push(" [&>.fc-event-title]:!truncate !bg-transparent");
}
let statusClasses: string[] = [];
switch (status) {
Expand All @@ -25,7 +26,7 @@ export function getStatusClasses(
"md:!text-gray-700",
"md:bg-gray-50",
"md:border-gray-200",
"[&>div.fc-daygrid-event-dot]:!border-gray-700",
"[&_.fc-daygrid-event-dot]:!border-gray-700",
"[&_.fc-list-event-dot]:!border-gray-700",
"md:focus:!bg-gray-100",
];
Expand All @@ -35,7 +36,7 @@ export function getStatusClasses(
"md:!text-blue-700",
"md:bg-blue-50",
"md:border-blue-200",
"[&>div.fc-daygrid-event-dot]:!border-blue-700",
"[&_.fc-daygrid-event-dot]:!border-blue-700",
"[&_.fc-list-event-dot]:!border-blue-700",
"md:focus:!bg-blue-100",
];
Expand All @@ -45,7 +46,7 @@ export function getStatusClasses(
"md:!text-purple-700",
"md:bg-purple-50",
"md:border-purple-200",
"[&>div.fc-daygrid-event-dot]:!border-purple-700",
"[&_.fc-daygrid-event-dot]:!border-purple-700",
"[&_.fc-list-event-dot]:!border-purple-700",
"md:focus:!bg-purple-100",
];
Expand All @@ -55,7 +56,7 @@ export function getStatusClasses(
"md:!text-warning-700",
"md:bg-warning-50",
"md:border-warning-200",
"[&>div.fc-daygrid-event-dot]:!border-warning-700",
"[&_.fc-daygrid-event-dot]:!border-warning-700",
"[&_.fc-list-event-dot]:!border-warning-700",
"md:focus:!bg-warning-100",
];
Expand All @@ -65,7 +66,7 @@ export function getStatusClasses(
"md:!text-success-700",
"md:bg-success-50",
"md:border-success-200",
"[&>div.fc-daygrid-event-dot]:!border-success-700",
"[&_.fc-daygrid-event-dot]:!border-success-700",
"[&_.fc-list-event-dot]:!border-success-700",
"md:focus:!bg-success-100",
];
Expand All @@ -86,7 +87,7 @@ export const statusClassesOnHover: Record<BookingStatus, string> = {
COMPLETE: "md:!bg-success-100",
};

export function isOneDayEvent(from: Date, to: Date) {
export function isOneDayEvent(from: Date | string, to: Date | string) {
const start = new Date(from);
const end = new Date(to);

Expand Down

0 comments on commit b05997e

Please sign in to comment.