Skip to content

Calendar Page

  • File: src/pages/private/calendar/index.svelte

Overview

The calendar page makes use of made with svelte's Event Calendar component, which is a powerful tool built on top of the renowned FullCalendar package. This integration offers users a highly functional and intuitive calendar experience with a range of enhanced features.

Developed specifically for Svelte, the Event Calendar component provides seamless integration and efficient event management. Users can easily create, edit, and remove events, taking advantage of the rich customization options available in the FullCalendar package.

The component's user interface is designed to be user-friendly, ensuring smooth navigation and a visually appealing layout. With various view options, such as daily, weekly, monthly, and agenda views, users can effortlessly switch between different perspectives to suit their scheduling needs.

By utilizing the Event Calendar component from made with svelte, the calendar page becomes a dynamic and interactive platform, offering an enhanced and modern calendar experience for effectively organizing events and schedules.

Data Interfaces

Event Interfaces

ts
interface IFetchInfo {
  start: Date;
  end: Date;
  startStr: string;
  endStr: string;
}

interface IEvent {
  id: string;
  allDay: boolean;
  start: Date;
  end: Date;
  title: string;
  editable?: boolean;
  startEditable?: boolean;
  durationEditable?: boolean;
  display: "auto" | "background" | "ghost" | "preview" | "pointer";
}

Calendar Configuration

Plugins

svelte
let plugins = [TimeGrid, DayGrid, Interaction, List];

Calendar options

svelte
const options = {
  view: "listWeek",
  height: `${height}px`,
  headerToolbar: {
    start: "prev,next today",
    center: "title",
    end: "dayGridMonth,timeGridWeek,timeGridDay,listWeek"
  },
  scrollTime: "07:00:00",
  views: {
    timeGridWeek: { pointer: true }
  },
  editable: true,
  dayMaxEvents: true,
  nowIndicator: true,
  eventStartEditable: true,
  eventDurationEditable: true
};

Event Management

1. Event Fetching

svelte
async function getEvents(startTime: Date, endTime: Date) {
  const { data } = await query(`
    query ($startTime: DateTime!, $endTime: DateTime!) {
      xs: events(where: {
        startTime: { gte: $startTime, lt: $endTime },
        isSecuredCameraSession: { eq: false }
      }) {
        items {
          id, title, allDay, startDate, endDate,
          notes, participants { ... }
        }
      }
    }
  `);

  return processEventData(data.xs.items);
}

2. Event Creation

svelte
async function createEvent(payload) {
  const ret = await tryMutate(`
    mutation ($payload: CreateEventCommandInput!) {
      x: createEvent(payload: $payload) {
        success, message, data
      }
    }
  `, { payload });
  return ret;
}

3. Event Modification

svelte
async function resizeEvent(command: {
  eventId: number;
  start: Date;
  end: Date;
  timeZoneOffset: number;
}) {
  const ret = await runCommand<{ ret: CallResult }>(
    "resizeEvent",
    "ResizeEvent",
    command
  );
  return ret;
}

Event Handlers

1. Event Click

svelte
function eventClick(eventClickInfo) {
  activeEvent = {
    title: eventClickInfo.event.title,
    id: eventClickInfo.event.id
  };
  showDetailsModal = true;
}

2. Date Click

svelte
function dateClick(dateClickInfo) {
  if (!hasPermission(Permissions.manageEvents)) return;
  eventStartDate = dateClickInfo.date;
  showNewEventForm = true;
}

3. Event Drag & Drop

svelte
async function eventDrop({ delta, event, revert }) {
  const { id, start, end } = event;
  const timeZoneOffset = new Date().getTimezoneOffset() / -60;

  const ret = await resizeEvent({
    eventId: +id,
    start,
    end,
    timeZoneOffset
  });

  if (!ret.success) {
    revert();
    showError(ret.message);
  }
}

UI Components

1. Calendar Layout

svelte
<div class="h-full w-full flex flex-col">
  <!-- Toolbar -->
  <div class="py-2 content-between flex">
    <button on:click={() => showNewEventForm = true}>
      Add event
    </button>
    <button on:click={() => calendar?.refetchEvents()}>
      <Icon src={Refresh}/>
    </button>
  </div>

  <!-- Calendar -->
  <div class="flex-grow" bind:clientHeight={height}>
    <Calendar bind:this={calendar} {plugins} {options} />
  </div>
</div>

2. Event Modal

svelte
<!-- Event Details Modal -->
<Modal title={activeEvent.title}>
  <EventDetails
    activeEventId={activeEvent.id}
    on:editEvent={editEvent}
    on:deleted={() => {
      showDetailsModal = false;
      activeEvent = null;
      calendar?.refetchEvents();
    }}
  />
</Modal>

<!-- New Event Modal -->
<Modal title={edit ? "Update Event" : "New Event"}>
  <EventForm
    startNow={false}
    on:change={onEventFormChange}
    date={eventStartDate}
    activeEventId={activeEvent?.id}
    intentionalStartTime={true}
    intentionalEndTime={true}
  />
</Modal>

Event Content Customization

svelte
function eventContent(info: {
  event: any;
  timeText: string;
  view: any
}) {
  // Different layouts for different views
  switch (info.view.type) {
    case "listWeek":
      return listViewContent(info);
    case "timeGridDay":
    case "timeGridWeek":
      return timeGridContent(info);
    default:
      return defaultContent(info);
  }
}

Permission Management

svelte
// View-level permissions
{#if hasPermission(Permissions.manageEvents)}
  <button on:click={() => showNewEventForm = true}>
    Add event
  </button>
{/if}

// Action-level permissions
function dateClick(dateClickInfo) {
  if (!hasPermission(Permissions.manageEvents)) return;
  // Handle date click
}

Usage

svelte
<script>
    import Calendar from '@event-calendar/core';
    import TimeGrid from '@event-calendar/time-grid';

    let plugins = [TimeGrid];
    let options = {
        view: 'timeGridWeek',
        events: [
            // your list of events
        ]
    };
</script>

  <Calendar {plugins} {options} />

Released under the MIT License.