metis/src/App.svelte

109 lines
2.9 KiB
Svelte

<script>
import { onMount } from 'svelte';
import { writable } from 'svelte/store';
import FullCalendar from 'svelte-fullcalendar';
import timeGridPlugin from '@fullcalendar/timegrid';
import adaptivePlugin from '@fullcalendar/adaptive';
import rrulePlugin from '@fullcalendar/rrule';
import dayGridPlugin from '@fullcalendar/daygrid';
import listPlugin from '@fullcalendar/list';
import frLocale from '@fullcalendar/core/locales/fr';
import EventModal from './EventModal.svelte';
import FilterBar from './FilterBar.svelte';
import { mkSource, calendarTree } from './calendar';
import { debounce } from 'lodash';
import 'bootstrap/dist/css/bootstrap.css';
import 'bootstrap-icons/font/bootstrap-icons.css';
import bootstrap5Plugin from '@fullcalendar/bootstrap5';
const event = writable(null);
let openModal = false;
const toggle = () => (openModal = !openModal);
const mobile = window.innerWidth < 765;
let calendar;
let options = writable({
initialView: mobile ? 'listWeek' : 'timeGridWeek',
plugins: [
timeGridPlugin,
dayGridPlugin,
rrulePlugin,
listPlugin,
adaptivePlugin,
bootstrap5Plugin
],
locale: frLocale,
allDayContent: '',
headerToolbar: {
left: mobile ? false : 'prev,next today',
center: 'title',
right: mobile
? 'prev,today,next dayGridMonth,timeGridWeek,listWeek'
: 'dayGridMonth,timeGridWeek,listWeek'
},
height: '100%',
schedulerLicenseKey: 'CC-Attribution-NonCommercial-NoDerivatives',
nowIndicator: true,
now: new Date(),
eventClick: info => {
openModal = true;
event.set(info.event);
},
titleFormat: {
year: mobile ? '2-digit' : 'numeric',
month: mobile ? 'numeric' : 'long',
day: 'numeric'
},
eventSources: [],
themeSystem: 'bootstrap5'
});
let selectedCalendars = [];
const updateEvents = debounce(calendars => {
options.update(opts => ({
...opts,
eventSources: selectedCalendars.map(mkSource).filter(x => !!x)
}));
}, 300);
$: updateEvents(selectedCalendars);
</script>
<div class="h-100 d-flex flex-column">
<h1 class="mt-3 title text-center">Calendrier de la vie étudiante à l'ENS</h1>
<FilterBar {calendarTree} bind:selected={selectedCalendars} />
<div class="h-100 d-flex">
<div class="flex-grow-1">
<FullCalendar bind:this={calendar} options={$options} />
</div>
</div>
<EventModal event={$event} open={openModal} {toggle} />
</div>
<div class="fc-toolbar-title" />
<style>
:global(.fc-event) {
cursor: pointer;
}
@media (max-width: 765px) {
:global(.fc-header-toolbar) {
flex-direction: column;
}
:global(.fc-toolbar-title) {
margin-bottom: 0.25em !important;
}
:global(.fc-toolbar-chunk) {
display: flex;
justify-content: space-evenly;
width: 100%;
}
}
</style>