Documentation

Calendar Application

Calendar Application

Event management with FullCalendar integration, drag-and-drop functionality, and comprehensive scheduling features.

Route: /admin/apps/calendar

Overview

The Calendar application provides a complete event management system with multiple view options, drag-and-drop functionality, and comprehensive scheduling capabilities. It integrates with FullCalendar for a professional calendar experience.

Features

Core Calendar Features

  • Multiple Views - Month, week, day, and list views
  • Event Management - Create, edit, delete, and duplicate events
  • Drag & Drop - Move events between dates and times
  • Event Categories - Color-coded event types and categories
  • Recurring Events - Set up repeating events with various patterns
  • Event Details - Rich event information with descriptions and attendees
  • Time Zones - Support for multiple time zones
  • Event Search - Find events quickly with search functionality
  • Event Filtering - Filter events by category, date, or other criteria
  • Export/Import - Export calendar data and import from other sources

UI/UX Features

  • Responsive Design - Works on all devices
  • Dark/Light Mode - Automatic theme switching
  • Smooth Animations - Fluid transitions and interactions
  • Modern Interface - Clean, professional design
  • Accessibility - WCAG compliant with proper ARIA labels
  • Touch Support - Optimized for touch devices

Calendar Views

Month View

  • Grid Layout - Traditional monthly calendar grid
  • Event Display - Events shown as colored blocks
  • Navigation - Previous/next month navigation
  • Today Highlight - Current date highlighted
  • Event Overflow - Show "+X more" for days with many events

Week View

  • 7-Day Layout - Full week with time slots
  • Time Grid - Hourly time slots for precise scheduling
  • Event Positioning - Events positioned by time
  • Week Navigation - Navigate between weeks
  • Weekend Toggle - Show/hide weekends

Day View

  • Single Day - Focus on one day's events
  • Detailed Timeline - Hour-by-hour breakdown
  • Event Details - Full event information visible
  • Time Slots - Precise time management
  • Day Navigation - Navigate between days

List View

  • Event List - Chronological list of events
  • Upcoming Events - Focus on future events
  • Event Summary - Quick overview of all events
  • Search & Filter - Find specific events quickly
  • Bulk Actions - Manage multiple events at once

Event Management

Creating Events

  • Quick Create - Click on calendar to create event
  • Event Modal - Detailed event creation form
  • Event Details - Title, description, location, attendees
  • Time Selection - Start and end time pickers
  • All-Day Events - Toggle for all-day events
  • Recurring Options - Set up repeating events

Event Types

  • Meetings - Business meetings and appointments
  • Tasks - Personal tasks and to-dos
  • Deadlines - Project deadlines and milestones
  • Holidays - Company holidays and observances
  • Personal - Personal events and reminders
  • Custom - User-defined event types

Event Categories

  • Color Coding - Visual categorization with colors
  • Category Management - Create and manage categories
  • Category Filtering - Show/hide specific categories
  • Category Icons - Visual icons for categories
  • Category Rules - Automatic categorization rules

Integration Examples

Backend Integration

// Calendar Controller
class CalendarController extends Controller
{
    public function index()
    {
        $events = Event::where('user_id', auth()->id())
            ->orWhere('is_public', true)
            ->get();

        return view('admin.apps.calendar', compact('events'));
    }

    public function getEvents(Request $request)
    {
        $start = $request->start;
        $end = $request->end;

        $events = Event::where('user_id', auth()->id())
            ->whereBetween('start', [$start, $end])
            ->get()
            ->map(function($event) {
                return [
                    'id' => $event->id,
                    'title' => $event->title,
                    'start' => $event->start,
                    'end' => $event->end,
                    'color' => $event->color,
                    'allDay' => $event->all_day,
                    'extendedProps' => [
                        'description' => $event->description,
                        'location' => $event->location,
                        'attendees' => $event->attendees
                    ]
                ];
            });

        return response()->json($events);
    }

    public function store(Request $request)
    {
        $request->validate([
            'title' => 'required|string|max:255',
            'start' => 'required|date',
            'end' => 'nullable|date|after:start',
            'color' => 'nullable|string',
            'description' => 'nullable|string',
            'location' => 'nullable|string',
            'attendees' => 'nullable|array'
        ]);

        $event = Event::create([
            'user_id' => auth()->id(),
            'title' => $request->title,
            'start' => $request->start,
            'end' => $request->end,
            'color' => $request->color,
            'description' => $request->description,
            'location' => $request->location,
            'attendees' => $request->attendees,
            'all_day' => $request->boolean('all_day')
        ]);

        return response()->json($event);
    }

    public function update(Request $request, Event $event)
    {
        $this->authorize('update', $event);

        $request->validate([
            'title' => 'required|string|max:255',
            'start' => 'required|date',
            'end' => 'nullable|date|after:start'
        ]);

        $event->update($request->all());

        return response()->json($event);
    }

    public function destroy(Event $event)
    {
        $this->authorize('delete', $event);

        $event->delete();

        return response()->json(['success' => true]);
    }
}

Livewire Integration

// Calendar Livewire Component
class CalendarApp extends Component
{
    public $events = [];
    public $selectedEvent = null;
    public $showEventModal = false;
    public $eventTitle = '';
    public $eventStart = '';
    public $eventEnd = '';
    public $eventColor = '#3788d8';
    public $eventDescription = '';
    public $eventLocation = '';

    public function mount()
    {
        $this->loadEvents();
    }

    public function loadEvents()
    {
        $this->events = Event::where('user_id', auth()->id())
            ->get()
            ->map(function($event) {
                return [
                    'id' => $event->id,
                    'title' => $event->title,
                    'start' => $event->start,
                    'end' => $event->end,
                    'color' => $event->color,
                    'allDay' => $event->all_day
                ];
            })
            ->toArray();
    }

    public function selectDate($date)
    {
        $this->eventStart = $date;
        $this->eventEnd = $date;
        $this->showEventModal = true;
    }

    public function selectEvent($eventId)
    {
        $event = Event::find($eventId);
        $this->selectedEvent = $event;
        $this->eventTitle = $event->title;
        $this->eventStart = $event->start;
        $this->eventEnd = $event->end;
        $this->eventColor = $event->color;
        $this->eventDescription = $event->description;
        $this->eventLocation = $event->location;
        $this->showEventModal = true;
    }

    public function saveEvent()
    {
        $this->validate([
            'eventTitle' => 'required|string|max:255',
            'eventStart' => 'required|date',
            'eventEnd' => 'nullable|date|after:eventStart'
        ]);

        if ($this->selectedEvent) {
            $this->selectedEvent->update([
                'title' => $this->eventTitle,
                'start' => $this->eventStart,
                'end' => $this->eventEnd,
                'color' => $this->eventColor,
                'description' => $this->eventDescription,
                'location' => $this->eventLocation
            ]);
        } else {
            Event::create([
                'user_id' => auth()->id(),
                'title' => $this->eventTitle,
                'start' => $this->eventStart,
                'end' => $this->eventEnd,
                'color' => $this->eventColor,
                'description' => $this->eventDescription,
                'location' => $this->eventLocation
            ]);
        }

        $this->loadEvents();
        $this->closeEventModal();
    }

    public function deleteEvent()
    {
        if ($this->selectedEvent) {
            $this->selectedEvent->delete();
            $this->loadEvents();
            $this->closeEventModal();
        }
    }

    public function closeEventModal()
    {
        $this->showEventModal = false;
        $this->selectedEvent = null;
        $this->reset(['eventTitle', 'eventStart', 'eventEnd', 'eventColor', 'eventDescription', 'eventLocation']);
    }

    public function render()
    {
        return view('livewire.calendar-app');
    }
}

Google Calendar Integration

// Google Calendar Service
class GoogleCalendarService
{
    protected $client;

    public function __construct()
    {
        $this->client = new \Google_Client();
        $this->client->setAuthConfig(config('services.google.client_secret'));
        $this->client->addScope(\Google_Service_Calendar::CALENDAR);
    }

    public function syncEvents()
    {
        $service = new \Google_Service_Calendar($this->client);
        $calendarId = 'primary';

        $events = $service->events->listEvents($calendarId);

        foreach ($events->getItems() as $event) {
            Event::updateOrCreate([
                'google_id' => $event->getId()
            ], [
                'user_id' => auth()->id(),
                'title' => $event->getSummary(),
                'start' => $event->getStart()->getDateTime(),
                'end' => $event->getEnd()->getDateTime(),
                'description' => $event->getDescription(),
                'location' => $event->getLocation(),
                'color' => $this->getEventColor($event)
            ]);
        }
    }

    public function createEvent($eventData)
    {
        $service = new \Google_Service_Calendar($this->client);
        $calendarId = 'primary';

        $event = new \Google_Service_Calendar_Event([
            'summary' => $eventData['title'],
            'description' => $eventData['description'],
            'location' => $eventData['location'],
            'start' => [
                'dateTime' => $eventData['start'],
                'timeZone' => 'America/New_York'
            ],
            'end' => [
                'dateTime' => $eventData['end'],
                'timeZone' => 'America/New_York'
            ]
        ]);

        return $service->events->insert($calendarId, $event);
    }
}

Customization

Styling

// Custom calendar styles
.calendar-container {
    .fc {
        --fc-border-color: var(--border-color);
        --fc-button-bg-color: var(--primary-color);
        --fc-button-border-color: var(--primary-color);
        --fc-button-hover-bg-color: var(--primary-hover);
        --fc-button-hover-border-color: var(--primary-hover);
        --fc-button-active-bg-color: var(--primary-active);
        --fc-button-active-border-color: var(--primary-active);
        --fc-today-bg-color: var(--bg-today);
        --fc-event-bg-color: var(--event-bg);
        --fc-event-border-color: var(--event-border);
    }

    .fc-toolbar {
        margin-bottom: 1rem;

        .fc-toolbar-title {
            font-size: 1.5rem;
            font-weight: 600;
            color: var(--text-color);
        }
    }

    .fc-event {
        border-radius: 4px;
        border: none;
        padding: 2px 4px;
        font-size: 0.875rem;

        &:hover {
            opacity: 0.8;
        }
    }

    .fc-daygrid-event {
        margin: 1px 0;
    }

    .fc-timegrid-event {
        border-radius: 4px;
    }
}

JavaScript Functionality

// Calendar functionality
class CalendarApp {
    constructor() {
        this.calendar = null;
        this.initCalendar();
        this.initEventHandlers();
    }

    initCalendar() {
        const calendarEl = document.getElementById('calendar');

        this.calendar = new FullCalendar.Calendar(calendarEl, {
            initialView: 'dayGridMonth',
            headerToolbar: {
                left: 'prev,next today',
                center: 'title',
                right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
            },
            editable: true,
            selectable: true,
            selectMirror: true,
            dayMaxEvents: true,
            events: this.loadEvents.bind(this),
            select: this.handleDateSelect.bind(this),
            eventClick: this.handleEventClick.bind(this),
            eventDrop: this.handleEventDrop.bind(this),
            eventResize: this.handleEventResize.bind(this)
        });

        this.calendar.render();
    }

    loadEvents(info) {
        return fetch('/api/calendar/events', {
            method: 'GET',
            headers: {
                'Content-Type': 'application/json',
                'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
            }
        })
        .then(response => response.json())
        .then(events => {
            return events.map(event => ({
                id: event.id,
                title: event.title,
                start: event.start,
                end: event.end,
                color: event.color,
                allDay: event.allDay
            }));
        });
    }

    handleDateSelect(selectInfo) {
        const title = prompt('Enter event title:');
        if (title) {
            this.createEvent({
                title: title,
                start: selectInfo.startStr,
                end: selectInfo.endStr,
                allDay: selectInfo.allDay
            });
        }
        this.calendar.unselect();
    }

    handleEventClick(clickInfo) {
        const event = clickInfo.event;
        this.editEvent(event);
    }

    handleEventDrop(dropInfo) {
        this.updateEvent(dropInfo.event);
    }

    handleEventResize(resizeInfo) {
        this.updateEvent(resizeInfo.event);
    }

    createEvent(eventData) {
        fetch('/api/calendar/events', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
            },
            body: JSON.stringify(eventData)
        })
        .then(response => response.json())
        .then(event => {
            this.calendar.addEvent(event);
        });
    }

    updateEvent(event) {
        const eventData = {
            id: event.id,
            title: event.title,
            start: event.startStr,
            end: event.endStr,
            allDay: event.allDay
        };

        fetch(`/api/calendar/events/${event.id}`, {
            method: 'PUT',
            headers: {
                'Content-Type': 'application/json',
                'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
            },
            body: JSON.stringify(eventData)
        });
    }
}

Best Practices

  1. Performance: Implement event pagination and lazy loading
  2. Security: Validate all event data and implement proper authorization
  3. UX: Provide clear feedback for all user actions
  4. Mobile: Ensure touch-friendly interface on mobile devices
  5. Accessibility: Use proper ARIA labels and keyboard navigation
  6. Time Zones: Handle time zone conversions properly
  7. Recurring Events: Implement proper recurring event logic

Production Deployment

The Calendar application is ready for production use in both static HTML and Laravel Livewire editions. For production deployment:

  1. Database Setup - Create necessary tables for events and categories
  2. External Integrations - Set up Google Calendar, Outlook, or other calendar services
  3. File Storage - Configure attachment storage for event files
  4. Security - Implement proper authentication and authorization
  5. Performance - Set up caching for frequently accessed data
  6. Notifications - Configure email/SMS notifications for events