This is what I have for now, it notable does not work, and I am really not sure how to tackle this at the moment. Basically I want it so when the user presses '8:00 AM' on the modal it aligns the text to the left and vice versa for '8:30 AM.' I am very inexperienced with dynamic styles and would love to get some insight on this
"use client";
import FullCalendar from "@fullcalendar/react";
import dayGridPlugin from "@fullcalendar/daygrid";
import interactionPlugin, {
Draggable,
DropArg,
} from "@fullcalendar/interaction";
import timeGridPlugin from "@fullcalendar/timegrid";
import { Fragment, useEffect, useState } from "react";
import { Dialog, Transition } from "@headlessui/react";
import { CheckIcon, ExclamationTriangleIcon } from "@heroicons/react/20/solid";
import { EventSourceInput } from "@fullcalendar/core/index.js";
import clsx from "clsx";
interface Event {
title: string;
start: Date | string;
allDay: boolean;
id: number;
alignClass: string;
}
export default function Home() {
const [events, setEvents] = useState([
{ title: "Employee 1", id: "1", alignClass: "align-left" },
{ title: "Employee 2", id: "2", alignClass: "align-left" },
{ title: "Employee 3", id: "3", alignClass: "align-left" },
{ title: "Employee 4", id: "4", alignClass: "align-left" },
{ title: "Employee 5", id: "5", alignClass: "align-left" },
]);
const [allEvents, setAllEvents] = useState<Event[]>([]);
const [showModal, setShowModal] = useState(false);
const [showDeleteModal, setShowDeleteModal] = useState(false);
const [showAlignModal, setShowAlignModal] = useState(false);
const [idToAlign, setIdToAlign] = useState<number | null>(null);
const [idToDelete, setIdToDelete] = useState<number | null>(null);
const [newEvent, setNewEvent] = useState<Event>({
title: "",
start: "",
allDay: false,
id: 0,
alignClass: "align-left",
});
useEffect(() => {
let draggableEl = document.getElementById("draggable-el");
if (draggableEl) {
new Draggable(draggableEl, {
itemSelector: ".fc-event",
eventData: function (eventEl) {
let title = eventEl.getAttribute("title");
let id = eventEl.getAttribute("data");
let start = eventEl.getAttribute("start");
return { title, id, start };
},
});
}
}, []);
function handleDateClick(arg: { date: Date; allDay: boolean }) {
setNewEvent({
...newEvent,
start: arg.date,
allDay: arg.allDay,
id: new Date().getTime(),
});
setShowModal(true);
}
function addEvent(data: DropArg) {
const event = {
...newEvent,
start: data.date.toISOString(),
title: data.draggedEl.innerText,
allDay: data.allDay,
id: new Date().getTime(),
alignClass: "align-left", // Default alignment when dragged
};
setAllEvents([...allEvents, event]);
}
function handleEditModal(data: { event: { id: string } }) {
setIdToAlign(Number(data.event.id));
setShowAlignModal(true);
}
function handleDelete() {
setAllEvents(
allEvents.filter((event) => Number(event.id) !== Number(idToDelete))
);
setShowDeleteModal(false);
setIdToDelete(null);
}
function alignEvent(alignClass: string) {
setAllEvents((prevEvents) =>
prevEvents.map((event) =>
Number(event.id) === Number(idToAlign)
? { ...event, alignClass: alignClass }
: event
)
);
setShowAlignModal(false);
setIdToAlign(null);
}
function handleCloseModal() {
setShowModal(false);
setNewEvent({
title: "",
start: "",
allDay: false,
id: 0,
alignClass: "",
});
setShowDeleteModal(false);
setIdToDelete(null);
}
const handleChange = (e: React.ChangeEvent<HTMLInputElement>): void => {
setNewEvent({
...newEvent,
title: e.target.value,
});
};
function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
setAllEvents([...allEvents, newEvent]);
setShowModal(false);
setNewEvent({
title: "",
start: "",
allDay: false,
id: 0,
alignClass: "align-left",
});
}
return (
<>
<nav className="flex justify-between mb-12 border-b border-violet-100 p-4">
<h1 className="font-bold text-2xl text-gray-700">Calendar</h1>
</nav>
<main className="flex min-h-screen flex-col items-center justify-between p-24">
<div className="grid grid-cols-10">
<div className="col-span-8">
<FullCalendar
plugins={[dayGridPlugin, interactionPlugin, timeGridPlugin]}
headerToolbar={{
left: "prev,next today",
center: "title",
right: "resourceTimelineWeek, dayGridMonth,timeGridWeek",
}}
hiddenDays={[0]}
events={allEvents as EventSourceInput}
nowIndicator={true}
editable={true}
droppable={true}
selectable={true}
selectMirror={true}
dateClick={handleDateClick}
drop={(data) => addEvent(data)}
eventClick={(data) => handleEditModal(data)}
/>
</div>
<div
id="draggable-el"
className="ml-8 w-full border-2 p-2 rounded-md mt-16 lg:h-1/2 bg-violet-50"
>
<h1 className="font-bold text-lg text-center">Drag Event</h1>
{events.map((event) => (
<div
className={clsx(
"fc-event border-2 p-1 m-2 w-full rounded-md ml-auto bg-white",
{
"text-right": event.alignClass === "align-right",
"text-left": event.alignClass === "align-left",
}
)}
title={event.title}
key={event.id}
>
{event.title}
</div>
))}
</div>
</div>
<Transition.Root show={showAlignModal} as={Fragment}>
<Dialog
as="div"
className="relative z-10"
onClose={setShowAlignModal}
>
<Transition.Child
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="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" />
</Transition.Child>
<div className="fixed inset-0 z-10 overflow-y-auto">
<div className="flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
enterTo="opacity-100 translate-y-0 sm:scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
>
<Dialog.Panel
className="relative transform overflow-hidden rounded-lg
bg-white text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-lg"
>
<div className="bg-white px-4 pb-4 pt-5 sm:p-6 sm:pb-4">
<div className="sm:flex sm:items-start">
<div
className="mx-auto flex h-12 w-12 flex-shrink-0 items-center
justify-center rounded-full bg-red-100 sm:mx-0 sm:h-10 sm:w-10"
>
<ExclamationTriangleIcon
className="h-6 w-6 text-red-600"
aria-hidden="true"
/>
</div>
<div className="mt-3 text-center sm:ml-4 sm:mt-0 sm:text-left">
<Dialog.Title
as="h3"
className="text-base font-semibold leading-6 text-gray-900"
>
Change Event
</Dialog.Title>
<div className="mt-2">
<p className="text-sm text-gray-500">
What time will this person start?
</p>
</div>
</div>
</div>
</div>
<div className="bg-gray-50 px-4 py-3 sm:flex sm:px-6">
<button
type="button"
className="ml-4 inline-flex justify-center rounded-md bg-blue-600 px-3 py-2 text-sm font-semibold text-white
shadow-sm hover:bg-blue-500 sm:ml-0 sm:w-auto"
onClick={() => alignEvent("align-left")}
>
8:00 AM
</button>
<button
type="button"
className="ml-8 inline-flex justify-center rounded-md bg-blue-600 px-3 py-2 text-sm font-semibold text-white
shadow-sm hover:bg-blue-500 sm:ml-2 sm:w-auto"
onClick={() => alignEvent("align-right")}
>
8:30 AM
</button>
<button
type="button"
className="inline-flex justify-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900
shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 sm:ml-10 sm:w-auto"
onClick={handleCloseModal}
>
Cancel
</button>
<button
type="button"
className="ml-4 inline-flex justify-center rounded-md bg-red-600 px-3 py-2 text-sm font-semibold text-white
shadow-sm hover:bg-red-500"
onClick={handleDelete}
>
Delete
</button>
</div>
</Dialog.Panel>
</Transition.Child>
</div>
</div>
</Dialog>
</Transition.Root>
<Transition.Root show={showModal} as={Fragment}>
<Dialog as="div" className="relative z-10" onClose={setShowModal}>
<Transition.Child
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="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" />
</Transition.Child>
<div className="fixed inset-0 z-10 overflow-y-auto">
<div className="flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
enterTo="opacity-100 translate-y-0 sm:scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
>
<Dialog.Panel className="relative transform overflow-hidden rounded-lg bg-white px-4 pb-4 pt-5 text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-lg sm:p-6">
<div>
<div className="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-green-100">
<CheckIcon
className="h-6 w-6 text-green-600"
aria-hidden="true"
/>
</div>
<div className="mt-3 text-center sm:mt-5">
<Dialog.Title
as="h3"
className="text-base font-semibold leading-6 text-gray-900"
>
Add Event
</Dialog.Title>
<form action="submit" onSubmit={handleSubmit}>
<div className="mt-2">
<input
type="text"
name="title"
className="block w-full rounded-md border-0 py-1.5 text-gray-900
shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400
focus:ring-2
focus:ring-inset focus:ring-violet-600
sm:text-sm sm:leading-6"
value={newEvent.title}
onChange={(e) => handleChange(e)}
placeholder="Title"
/>
</div>
<div className="mt-5 sm:mt-6 sm:grid sm:grid-flow-row-dense sm:grid-cols-2 sm:gap-3">
<button
type="submit"
className="inline-flex w-full justify-center rounded-md bg-violet-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-violet-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-violet-600 sm:col-start-2 disabled:opacity-25"
disabled={newEvent.title === ""}
>
Create
</button>
<button
type="button"
className="mt-3 inline-flex w-full justify-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 sm:col-start-1 sm:mt-0"
onClick={handleCloseModal}
>
Cancel
</button>
</div>
</form>
</div>
</div>
</Dialog.Panel>
</Transition.Child>
</div>
</div>
</Dialog>
</Transition.Root>
</main>
</>
);
}
I tried using clsx, but it doesn't work. I think this is honestly not possible.
className={clsx(
"fc-event border-2 p-1 m-2 w-full rounded-md ml-auto bg-white",
{
"text-right": event.alignClass === "align-right",
"text-left": event.alignClass === "align-left",
}
)}
title={event.title}
key={event.id}
>