Giter VIP home page Giter VIP logo

livewire-calendar's Introduction

Livewire Calendar

This package allows you to build a Livewire monthly calendar grid to show events for each day. Events can be loaded from within the component and will be presented on each day depending on the date of the event.

Preview

preview

Installation

You can install the package via composer:

composer require asantibanez/livewire-calendar

Requirements

This package uses livewire/livewire (https://laravel-livewire.com/) under the hood.

It also uses TailwindCSS (https://tailwindcss.com/) for base styling.

Please make sure you include both of this dependencies before using this component.

Usage

In order to use this component, you must create a new Livewire component that extends from LivewireCalendar

You can use make:livewire to create a new component. For example.

php artisan make:livewire AppointmentsCalendar

In the AppointmentsCalendar class, instead of extending from the base Component Livewire class, extend from LivewireCalendar. Also, remove the render method. You'll have a class similar to this snippet.

class AppointmentsCalendar extends LivewireCalendar
{
    //
}

In this class, you must override the following method

public function events() : Collection
{
    // must return a Laravel collection
}

In the events() method, return a collection holding the events that will be displayed on the calendar. Events must be keyed arrays holding at least the following keys: id, title, description, date (date must be a Carbon\Carbon instance).

Example

public function events() : Collection
{
    return collect([
        [
            'id' => 1,
            'title' => 'Breakfast',
            'description' => 'Pancakes! 🥞',
            'date' => Carbon::today(),
        ],
        [
            'id' => 2,
            'title' => 'Meeting with Pamela',
            'description' => 'Work stuff',
            'date' => Carbon::tomorrow(),
        ],
    ]);
}

The date value will be used to determine to what day the event belongs to. To load values in the events() method, you can use the following component properties to filter your events.

  • startsAt: starting date of month
  • endsAt: ending date of month
  • gridStartsAt: starting date of calendar grid. Can be a date from the previous month.
  • endingStartsAt: ending date of calendar grid. Can be a date from the next month.

Example

public function events(): Collection
{
    return Model::query()
        ->whereDate('scheduled_at', '>=', $this->gridStartsAt)
        ->whereDate('scheduled_at', '<=', $this->gridEndsAt)
        ->get()
        ->map(function (Model $model) {
            return [
                'id' => $model->id,
                'title' => $model->title,
                'description' => $model->notes,
                'date' => $model->scheduled_at,
            ];
        });
}

Now, we can include our component in any view.

Example

<livewire:appointments-calendar/>

This will render a calendar grid.

example

By default, the component will render the current month. If you want to change the starting month, you can set the year and month props.

Example

<livewire:appointments-calendar
   year="2019"
   month="12"
/>

You should include scripts with @livewireCalendarScripts to enable drag and drop which is turned on by default. You must include them after @livewireScripts

@livewireScripts
@livewireCalendarScripts

The component has 3 public methods that can help navigate forward and backward through months:

  • goToPreviousMonth
  • goToNextMonth
  • goToCurrentMonth

You can use these methods on extra views using before-calendar-view or after-calendar-view explained below.

Advanced usage

Ui customization

You can customize the behavior of the component with the following properties when rendering on a view:

  • week-starts-at which can be a number from 0 to 6 according to Carbon days of week to indicate with which day of week the calendar should render first.

  • event-view which can be any blade.php view that will be used to render the event card. This view will be injected with a $event variable holding its data.

  • before-calendar-view and after-calendar-view can be any blade.php views that can be rendered before or after the calendar itself. These can be used to add extra features to your component using Livewire.

  • drag-and-drop-classes can be any css class used to render the hover effect when dragging an event over each day in the calendar. By default, this value is border border-blue-400 border-4

  • day-of-week-view which can be any blade.php view that will be used to render the header of each calendar day. This view will be injected the day property which is a Carbon instance of the day of the week.

<livewire:appointments-grid
    week-starts-at="0, 1, 2, 3, 4, 5 or 6. 0 stands for Sunday"
    event-view="path/to/view/starting/from/views/folder"
    day-of-week-view="path/to/view/starting/from/views/folder"
    before-calendar-view="path/to/view/starting/from/views/folder"
    after-calendar-view="path/to/view/starting/from/views/folder"
    drag-and-drop-classes="css classes"
/>

Advanced ui customization

(This options should be used using blade views based on the component default views)

To use these options, it is recommended to publish the base blade views used by the component and extend their behavior and styling to your liking. To do this, run php artisan vendor:publish and export the livewire-calendar tag.

  • calendar-view which can be any blade.php view that renders the whole component. It's advised to override this view with an altered copy of the base calendar-view eg adding a view next to the component.

  • day-view which can be any blade.php view that will be used to render each day of the month. This view will be injected with the following properties: componentId (id of the Livewire component) , day (day of the month as a Carbon instance) , dayInMonth (if the day is part of the month or not) , isToday (if the day is today's date) , events (events collection that correspond to this day)

Example

<livewire:appointments-grid
    calendar-view="path/to/view/starting/from/views/folder"
    day-view="path/to/view/starting/from/views/folder"
/>

Interaction customization

You can override the following methods to add interactivity to your component

public function onDayClick($year, $month, $day)
{
    // This event is triggered when a day is clicked
    // You will be given the $year, $month and $day for that day
}

public function onEventClick($eventId)
{
    // This event is triggered when an event card is clicked
    // You will be given the event id that was clicked 
}

public function onEventDropped($eventId, $year, $month, $day)
{
    // This event will fire when an event is dragged and dropped into another calendar day
    // You will get the event id, year, month and day where it was dragged to
}

Automatic polling

You can also add automatic polling if needed using pollMillis parameters. You can combo with pollAction in order to call a specific action in your component at the desired polling interval.

Disabling interactions

By default click and drag/drop events are enabled. To disable them you can use the following parameters when rendering the component

<livewire:appointments-grid
    :day-click-enabled="false"
    :event-click-enabled="false"
    :drag-and-drop-enabled="false"
/>

Testing

composer test

Changelog

Please see CHANGELOG for more information what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Security

If you discover any security related issues, please email [email protected] instead of using the issue tracker.

Credits

License

The MIT License (MIT). Please see License File for more information.

livewire-calendar's People

Contributors

asantibanez avatar barryvdh avatar da-sie avatar shanerbaner82 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

livewire-calendar's Issues

Day Height for Multiple Items

Hoping that someone has a quick fix for this as it isn't necessarily a bug. If I have multiple events on a day, the day scrolls, however, I would like to expand the day to show all events. I have been unable to change the CSS successfully in the view files. Any tips?

Feature request: isPast()

Would be nice to alter the display of a day providing it's in the current month, but in the past.

Have published vendor files for now and added

                                        'isToday' => $day->isToday(),
                                        'isPast' => $day->isPast(),
                                        'events' => $getEventsForDay($day, $events),

But this really is a nice bit of work! Thanks for sharing it!

Events that span multiple days

This isn't currently handled and would be extremely useful.
Perhaps check to see if current day is in start and end ranges and populate each day with the event item.

below is my attempt it uses a multiday bool on the event - if it's missing it will default to old behaviour

#20

public function getEventsForDay($day, Collection $events) : Collection
{
    return $events->filter(function ($event) use ($day)
    {
        if(isset($event['multiday']) && $event['multiday']===true)
        {
            return $day->between(Carbon::parse($event['date']), Carbon::parse($event['end']));
        }
        return Carbon::parse($event['date'])->isSameDay($day);
    });
}

In event.blade.php

  @if(!isset($event['multiday']) || $event['multiday']!== true)
            {{$event['date']->format('G:i')}} - {{$event['end']->format('G:i')}}
        @endif

events function not compatible

Hi, I want to implement livewire-calendar within my laravel project which it already leverages and livewire for other functions.

I am following the readme and in the LivewireCalendar class I have inserted the events () function as indicated in the guide.

My Visual Studio Code is reporting error to me because it says the events () method is not compatible with 'Asantibanez \ LivewireCalendar \ LivewireCalendar :: events ()

In the guide it is not specified but before the main component class I inserted this line to invoke the package
use Asantibanez \ LivewireCalendar \ LivewireCalendar;

What am I doing wrong?

Thanks to those who want to answer.

See you soon

LARAVEL 8 ISSUE

Return value of App\Http\Livewire\AppointmentsCalendar::events() must be an instance of Illuminate\Database\Eloquent\Collection, instance of Illuminate\Support\Collection returned (View: /Applications/MAMP/htdocs/todo/resources/views/vendor/jetstream/components/welcome.blade.php) (View: /Applications/MAMP/htdocs/todo/resources/views/vendor/jetstream/components/welcome.blade.php)

Class "Asantibanez\LivewireCalendar\LivewireCalendar" not found

I've done everything as said in the documentation, but this "Class "Asantibanez\LivewireCalendar\LivewireCalendar" not found" error shows up whenever I insert livewire:teacher-calendar/ in a blade file, teacherCalendar being the livewire component name. Any suggestions? I have Laravel 9 installed, and managed to install this plugin via a solution by some user that I found in a forum. Might that be the issue?

Could not install it on Laravel 9

Your requirements could not be resolved to an installable set of packages.

Problem 1
- Root composer.json requires asantibanez/livewire-calendar ^2.1 -> satisfiable by asantibanez/livewire-calendar[2.1.0].
- asantibanez/livewire-calendar 2.1.0 requires illuminate/support ^6.0|^7.0|^8.0 -> found illuminate/support[v6.0.0, ..., 6.x-dev, v7.0.0, ..., 7.x-dev, v8.0.0, ..., 8.x-dev] but these were not loaded, likely because it conflicts with another require.

Pulling in LivewireCalendar breaks Jetstream Livewire components

Hi there,

This is a hobby for me and infact, the first issue i've ever submitted on any public repo before, although i have tested this back and forth a few times.

System Versions (all at time of writing)
OS: MacOS using Valet
Laravel: Latest
Livewire: Latest

Replication

  • Brand new laravel app with --jet flag using latest laravel installer
  • No additional features added to jetstream in test app
  • Compile assets and migrate database
  • Load the "Profile" page from the dropdown to prove it works
  • Pull in livewire calendar as require from composer following readme
  • Try to reload the profile page

Thoughts
The error displayed in my app was different, it couldn't locate the declared Livewire Components from the jetstream package, although an error is still thrown with a fresh install
Although i'm not confident enough to make a Pull Request here, i have dismantled the package and made it local (out of the vendor DIR and with no ServiceProvider etc. and it all plays nicely.

Screenshot
jet-livewire-test livewire calendar breaking jetstream

Hope this is of some help to you!

Adding child livewire in view breaks

Trying to add a Livewire component to the day.blade.php file. Even a default livewire component echoing "hello world" breaks the calendar monthly view.

Installation error

I get this error when I try to install the package

Problem 1
- Root composer.json requires asantibanez/livewire-calendar ^2.1 -> satisfiable by asantibanez/livewire-calendar[2.1.0].
- asantibanez/livewire-calendar 2.1.0 requires illuminate/support ^6.0|^7.0|^8.0 -> found illuminate/support[v6.0.0, ..., 6.x-dev, v7.0.0, ..., 7.x-dev, v8.0.0, ..., 8.x-dev] but it conflicts with your root composer.json require (^9.28).

You can also try re-running composer require with an explicit version constraint, e.g. "composer require asantibanez/livewire-calendar:*" to figure out if any version is installable, or "composer require asantibanez/livewire-calendar:^2.1" if you know which you need.

Installation failed, reverting ./composer.json and ./composer.lock to their original content.

I have laravel version 9.19 and illuminate/support 9.28.
thank you in advance for your return.

getting ErrorException `Undefined variable: pollMillis`

Hi, I've followed the Readme file but it looks like I can't use the component. I'm on Laravel 8.13

as far as I understand this should be enough:

<?php

namespace App\Http\Livewire;
use Asantibanez\LivewireCalendar\LivewireCalendar;
use Illuminate\Support\Collection;
use Carbon\Carbon;

class AppointmentsCalendar extends LivewireCalendar
{

    public function events() : Collection
    {

        return collect([
            [
                'id' => 1,
                'title' => 'Breakfast',
                'description' => 'Pancakes! 🥞',
                'date' => Carbon::today(),
            ],
            [
                'id' => 2,
                'title' => 'Meeting with Pamela',
                'description' => 'Work stuff',
                'date' => Carbon::tomorrow(),
            ],
        ]);

    }
}

I'm then calling
<livewire:appointments-calendar />

on my view, but I receive this error

ErrorException
Undefined variable: pollMillis (View: [...]/vendor/asantibanez/livewire-calendar/resources/views/calendar.blade.php)

any idea what might be wrong?

bootstrap

Is it possible I use bootstrap instead of tailwind css? if so, which part should I change?

[App\Http\Livewire\AppointmentsCalendar] does not implement [LivewireUI\Modal\Contracts\ModalComponent] interface.

Good day,

I already ran this code composer require asantibanez/livewire-calendar to install this package

but the error Exception
[App\Http\Livewire\AppointmentsCalendar] does not implement [LivewireUI\Modal\Contracts\ModalComponent] interface.

even though I add the "Asantibanez\LivewireCalendar\": "vendor/asantibanez/livewire-calendar/src/" in the autoload

and I already added the Asantibanez\LivewireCalendar\LivewireCalendarServiceProvider::class, to the Package Service Providers

And 'LivewireCalendar' => \Asantibanez\LivewireCalendar\LivewireCalendarFacade::class, to the alias.

This is my Livewire:

use Livewire\Component;
use Illuminate\Support\Collection;
use Illuminate\Support\Carbon;
use Asantibanez\LivewireCalendar\LivewireCalendar;

class AppointmentsCalendar extends LivewireCalendar
{
public function events() : Collection
{
return collect([
[
'id' => 1,
'title' => 'Breakfast',
'description' => 'Pancakes! 🥞',
'date' => Carbon::today(),
],
[
'id' => 2,
'title' => 'Meeting with Pamela',
'description' => 'Work stuff',
'date' => Carbon::tomorrow(),
],
]);
}

Click event for edit an unschedules event does not work but works inside the calendar...

I added in unschedules events the edit button there but it does not work but in the calendar the same code works!

here the code

                    <button
                        wire:click.stop="editEvent({{ $event->id }})"
                        type="button"
                        class="mt-2 inline-flex items-center px-2 py-1 border border-transparent text-xs leading-4 font-medium rounded text-indigo-700 bg-indigo-100 hover:bg-indigo-50 focus:outline-none focus:border-indigo-300 focus:shadow-outline-indigo active:bg-indigo-200 transition ease-in-out duration-150">
                        {{ __('messages.edit') }} 
                    </button>
                    <button
                        wire:click.stop="deleteEvent({{ $event->id }})"
                        type="button"
                        class="mt-2 inline-flex items-center px-2 py-1 border border-transparent text-xs leading-4 font-medium rounded text-indigo-700 bg-indigo-100 hover:bg-indigo-50 focus:outline-none focus:border-indigo-300 focus:shadow-outline-indigo active:bg-indigo-200 transition ease-in-out duration-150">
                        {{ __('messages.delete') }} 
                    </button>

the editEvent function

    public function editEvent($eventId)
    {
        $this->selectedAppointment = PharmacyAppointments::find($eventId);
    }

Error

Call to a member function format() on null

Any ideas why it does not work in unschedules events but when moved into the calendar it works?
thanks

> Rather than forking it yourself, you may as well take advantage of someone else's fixed fork.

          > Rather than forking it yourself, you may as well take advantage of someone else's fixed fork.

In your composer.json add the following which will use the repository which @Butochnikov has already forked and updated to work with Laravel 9.

"repositories": [{ "type": "package", "canonical": false, "package": { "version": "master", "name": "asantibanez/livewire-calendar", "source": { "url": "https://github.com/Butochnikov/livewire-calendar.git", "type": "git", "reference": "master" } } }]

Then run composer require asantibanez/livewire-calendar:*

It'll then install for you.

Just remember to undo that and use the original when @asantibanez gets around to accepting the pull request.

In the terminal I had to use.

composer require asantibanez/livewire-calendar:dev-master

Originally posted by @grafxflow in #32 (comment)

Some difficulty in making it work

Hi, I have installed the package and made it work but I have some problems.
For example: drag and drop doesn't work. To test the package I installed laravel, liveware, tailwind css and then the calendar from scratch.
The display is correct but drag and drop does not work and neither do the onDayClick, onEventClick and onEventDropped functions.
I try to explain myself better: I move the appointment to another day, the square of the day lights up (it signals it to me) but releasing it does not move it, it returns to its original place.
Of course I added @livewireScripts and @livewireCalendarScripts.
Then the documentation is not clear. For example, I can't get the 3 methods goToPreviousMonth, goToNextMonth and goToCurrentMonth to go.
Also the doc talks about a livewire component: appointments-grid that doesn't seem to exist.
Another thing: is it possible to put appointments with several days in the calendar?
Thanks

livewire 3

Uncaught TypeError: Cannot read properties of undefined (reading 'events')

Exception Livewire Calendar not correctly configured. Check initial inputs.

Hello.

I'm ussing your calendar component and when show the october's calendar, show the exception "Livewire Calendar not correctly configured. Check initial inputs". I'd checked the code and when you calculate days in vendor/asantibanez/livewire-calendar/src/LivewireCalendar.php:179, the result is 36 because at end of october is the daylight saving time change and gridStartsAt is 2021-09-27 00:00:00.0 +02:00 and gridEndsAt is 2021-10-31 23:59:59.0 +01:00

Please, can you check this?

Timeline

Would be more awesome, if some kind of timeline pops up when pressing on a specific date . Because as we know there would alot of appointments lets say in 1 day .

Time complexity problem

hey, thank you for making this kind of package for livewire, I always made my own livewire calendar but really doesn't know how to make it reusable

I read some of your code and found the get event from day function is a bit clunky IMO

public function getEventsForDay($day, Collection $events): Collection
    {
        return $events
            ->filter(function ($event) use ($day) {
                return Carbon::parse($event['date'])->isSameDay($day);
            });
    }

I'm afraid this will do tons of repeated loops and might cause a problem if a certain month has tons of events. my suggestion is instead of doing it maybe you can encourage users to group the event by timestamp and create a hashmap, instead of getting it per day

Also maybe you can use carbon period CarbonPeriod::create to create a list of date

P.S. more like 35>42 repeated loop

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.