Guava Calendar for Filament PHP

repository·main·Indexed 43 days ago

https://github.com/guavacz/calendar

A calendar widget for Filament PHP panels powered by vkurko/calendar. It supports multiple event models, Filament Resource integration, context menus, and drag-and-drop event manipulation. Compatible with Filament 3.x (plugin 1.x), 4.x (plugin 2.x), and 5.x (plugin 3.x).

Tokens
18.1K
Snippets
76
Records
90
Agent score
56%

What's inside Guava Calendar

  1. Overview of the Guavacz Calendar widget

    main

    Guavacz Calendar is a widget designed for Filament PHP panels. It is powered by vkurko/calendar and provides advanced calendar functionality within the Filament ecosystem.

    Key features include:

    • Support for multiple event models.
    • Integration with Filament Resources.
    • Context menus.
    • Drag & drop event manipulation.
  2. Lock individual events from being edited

    main

    Enabling $eventDragEnabled or $eventResizeEnabled applies the behavior to all events globally. To prevent specific events from being moved or resized, configure the editing behavior on the individual event object using the following properties:

    • editable: Controls overall editability.
    • startEditable: Controls if the start of the event can be dragged.
    • durationEditable: Controls if the duration of the event can be resized.
  3. How schema discovery works in Guava Calendar

    main

    Guava Calendar automatically attempts to discover and reuse your existing Filament resource schemas for create, view, and edit actions.

    • create and edit actions: Use your Filament resource's form schema.
    • view actions: Use your Filament resource's infolist schema. If no infolist is defined, it falls back to the form schema.

    If auto-discovery works for your setup, no additional configuration is required. If you need custom schemas, you can define them globally via a default schema or specifically for individual models.

  4. Access contextual information in actions

    main

    Calendar actions can automatically inject contextual information via type-hinting. This allows you to react to how the user interacted with the calendar (e.g., clicking a date vs. clicking an event).

    Supported injectable parameters:

    ParameterDescription
    ContextThe current context enum, or null if not in a calendar context
    ContextualInfoThe info object of the current context
    DateClickInfoThe info of a date click, otherwise null
    DateSelectInfoThe info of a date selection, otherwise null
    EventClickInfoThe info of an event click, otherwise null
    NoEventsClickInfoThe info of a no-events click, otherwise null

    Example: Prefilling a form based on a date click or hiding an action based on context:

    use Guava\Calendar\Contracts\ContextualInfo;
    use Guava\Calendar\Enums\Context;
    use Guava\Calendar\ValueObjects\DateClickInfo;
    use Guava\Calendar\ValueObjects\DateSelectInfo;
    
    public function createFooAction(): CreateAction
    {
        return $this->createAction(Foo::class)
            ->mountUsing(function (?ContextualInfo $info) {
                if ($info instanceof DateClickInfo) {
                    // logic for date click
                }
    
                if ($info->getContext() === Context::DateSelect) {
                    // logic for date select
                }
            })
            // Or direct type-hinting:
            ->mountUsing(fn (?DateClickInfo $dateClick, ?DateSelectInfo $dateSelect) => /* ... */);
    }
    
    // Example: Hiding an action based on context
    $this->createAction(Foo::class)
        ->hidden(fn (?ContextualInfo $info) => $info?->getContext() === Context::DateClick);
  5. How custom event content works

    main

    By default, the calendar package uses a standard view for events. To gain full control over the HTML markup, you can provide custom content via the eventContent method.

    Crucial Performance Note: To maintain high performance, event content is rendered once on the server and then reused for every event. Because of this, you cannot access specific event data directly within Blade or PHP during the initial render.

    To display dynamic data (like titles or custom properties), you must use AlpineJS to access the event data exposed by the wrapper component. All data passed to the event via extendedProps is accessible via the event.extendedProps object in AlpineJS.

    <div class="flex flex-col items-start">
        <span x-text="event.title"></span>
        <template x-for="user in event.extendedProps.users">
            <span x-text="user.name"></span>
        </template>
    </div>
  6. Distinguish between $record and $eventRecord

    main

    When using a calendar widget on a Filament resource page, be aware of the distinction between these two variables:

    • $record: Refers to the record of the currently opened Filament resource page.
    • $eventRecord: Refers to the specific record of the calendar event you are interacting with.
  7. How to use the CalendarWidget

    main
    The CalendarWidget class is the primary entry point for this package. To use it in a Filament project, you must extend the CalendarWidget class, then add your new widget class to any Filament page. Configuration is handled by overriding the class's properties and methods.
  8. How to provide events to the calendar

    main

    To display data on the calendar, you must provide events using the getEvents method on your widget. You can supply events in two ways:

    1. Eloquent Models: Pass your Eloquent models directly to the method.
    2. CalendarEvent Objects: Manually construct CalendarEvent objects for more control over the event data.

    Detailed implementation details for each method and the available event options are covered in the specific event documentation pages.

    // Conceptual usage within a widget
    public function getEvents(): array
    {
        // Option 1: Returning Eloquent models
        return EventModel::all()->toArray();
    
        // Option 2: Returning custom CalendarEvent objects
        // return [new CalendarEvent(...), ...];
    }
  9. How resources work in the calendar

    main

    Resources allow you to group events into rows or columns. A common use case is grouping lessons (events) by the rooms (resources) in which they are held.

    Note: Resources are only visible when using Resource* calendar views. Ensure your widget is configured to use one of these specific view types to see resource grouping in action.

  10. Add resources from an array or collection

    main

    If you are not using Eloquent models, you can return an array or collection of CalendarResource objects directly from getResources. Each resource must have a unique ID provided via CalendarResource::make($id).

    use Guava\Calendar\ValueObjects\CalendarResource;
    
    protected function getResources(): array
    {
        return [
            CalendarResource::make('baz') // 'baz' is the unique ID
                ->title('My resource'),
        ];
    }
  11. Use Guava Calendar Actions instead of Filament Actions

    main

    To ensure actions work correctly within the calendar context, you must use the CalendarAction trait. The package provides drop-in replacements for standard Filament actions that include necessary setUp calls.

    Important: Always import these actions from the Guava\Calendar\Filament\Actions namespace rather than the standard Filament namespace.

    Available replacements:

    • Guava\Calendar\Filament\Actions\CreateAction
    • Guava\Calendar\Filament\Actions\ViewAction
    • Guava\Calendar\Filament\Actions\EditAction
    • Guava\Calendar\Filament\Actions\DeleteAction
    use Guava\Calendar\Filament\Actions\CreateAction;
  12. Link events to resources

    main

    To ensure events appear within specific resource views, you must associate them with a resource ID. Use the resourceId() method on your CalendarEvent object. This can be done within your widget's getEvents method or inside a model's toCalendarEvent method. An event can be linked to multiple resources.

    CalendarEvent::make($this)
        ->title($this->name)
        ->start($this->starts_at)
        ->end($this->ends_at)
        ->resourceId($this->room_id); // Links the event to the resource ID