mirror of
https://github.com/ae-utbm/sith.git
synced 2025-07-11 12:29:24 +00:00
Room reservation form
This commit is contained in:
@ -1,6 +1,7 @@
|
||||
import { inheritHtmlElement, registerComponent } from "#core:utils/web-components";
|
||||
import {
|
||||
Calendar,
|
||||
type DateSelectArg,
|
||||
type EventDropArg,
|
||||
type EventSourceFuncArg,
|
||||
} from "@fullcalendar/core";
|
||||
@ -18,6 +19,7 @@ import {
|
||||
import { paginated } from "#core:utils/api";
|
||||
import interactionPlugin from "@fullcalendar/interaction";
|
||||
import resourceTimelinePlugin from "@fullcalendar/resource-timeline";
|
||||
import type { SlotSelectedEventArg } from "#reservation:reservation/types";
|
||||
|
||||
@registerComponent("room-scheduler")
|
||||
export class RoomScheduler extends inheritHtmlElement("div") {
|
||||
@ -26,6 +28,7 @@ export class RoomScheduler extends inheritHtmlElement("div") {
|
||||
private locale = "en";
|
||||
private canEditSlot = false;
|
||||
private canBookSlot = false;
|
||||
private canDeleteSlot = false;
|
||||
|
||||
attributeChangedCallback(name: string, _oldValue?: string, newValue?: string) {
|
||||
if (name === "locale") {
|
||||
@ -37,6 +40,9 @@ export class RoomScheduler extends inheritHtmlElement("div") {
|
||||
if (name === "can_create_slot") {
|
||||
this.canBookSlot = newValue.toLowerCase() === "true";
|
||||
}
|
||||
if (name === "can_delete_slot") {
|
||||
this.canDeleteSlot = newValue.toLowerCase() === "true";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -84,6 +90,18 @@ export class RoomScheduler extends inheritHtmlElement("div") {
|
||||
}
|
||||
}
|
||||
|
||||
selectFreeSlot(infos: DateSelectArg) {
|
||||
document.dispatchEvent(
|
||||
new CustomEvent<SlotSelectedEventArg>("timeSlotSelected", {
|
||||
detail: {
|
||||
ressource: Number.parseInt(infos.resource.id),
|
||||
start: infos.startStr,
|
||||
end: infos.endStr,
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
this.scheduler = new Calendar(this.node, {
|
||||
@ -109,6 +127,7 @@ export class RoomScheduler extends inheritHtmlElement("div") {
|
||||
resourceAreaWidth: "20%",
|
||||
resources: this.fetchResources,
|
||||
events: this.fetchEvents,
|
||||
select: this.selectFreeSlot,
|
||||
selectOverlap: false,
|
||||
selectable: this.canBookSlot,
|
||||
selectConstraint: { start: new Date() },
|
||||
|
@ -0,0 +1,23 @@
|
||||
import type { SlotSelectedEventArg } from "#reservation:reservation/types";
|
||||
|
||||
document.addEventListener("alpine:init", () => {
|
||||
Alpine.data("slotReservation", () => ({
|
||||
start: null as string,
|
||||
end: null as string,
|
||||
room: null as number,
|
||||
showForm: false,
|
||||
|
||||
init() {
|
||||
document.addEventListener(
|
||||
"timeSlotSelected",
|
||||
(event: CustomEvent<SlotSelectedEventArg>) => {
|
||||
this.start = event.detail.start.split("+")[0];
|
||||
this.end = event.detail.end.split("+")[0];
|
||||
this.room = event.detail.ressource;
|
||||
this.showForm = true;
|
||||
this.$nextTick(() => this.$el.scrollIntoView({ behavior: "smooth" })).then();
|
||||
},
|
||||
);
|
||||
},
|
||||
}));
|
||||
});
|
5
reservation/static/bundled/reservation/types.d.ts
vendored
Normal file
5
reservation/static/bundled/reservation/types.d.ts
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
export interface SlotSelectedEventArg {
|
||||
start: string;
|
||||
end: string;
|
||||
ressource: number;
|
||||
}
|
39
reservation/static/reservation/reservation.scss
Normal file
39
reservation/static/reservation/reservation.scss
Normal file
@ -0,0 +1,39 @@
|
||||
#slot-reservation {
|
||||
margin-top: 3em;
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
||||
h3 {
|
||||
display: block;
|
||||
margin: auto;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.alert, .error {
|
||||
display: block;
|
||||
margin: 1em auto auto;
|
||||
max-width: 400px;
|
||||
word-wrap: break-word;
|
||||
text-wrap: wrap;
|
||||
}
|
||||
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: .5em;
|
||||
justify-content: center;
|
||||
|
||||
.buttons-row {
|
||||
input[type="submit"], button {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
textarea {
|
||||
max-width: unset;
|
||||
width: 100%;
|
||||
margin-top: unset;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user