Criando um Calendário com persistência, AJAX e com Laravel
Olá, mundo!
Tudo bem?
Hoje venho trazer um outro exemplo com a simplicidade de integração com componentes de bibliotecas Javascript com Laravel.
Vamos ao trabalho//
Vamos criar um novo projeto com Laravel. Estou usando a Versão 8.1 do PHP e o Laravel 9, no entanto funciona com a versão 7.4 do PHP e o Laravel 8.
composer create-project laravel/laravel laravel_cal
Com o projeto criado, vamos a configuração inicial de nosso arquivo .env na pasta raiz do projeto:
.env
DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=laravel_cal DB_USERNAME=<usuário> DB_PASSWORD=<senha>
Agora vamos criar na pasta de nosso projeto, nossa migration:
php artisan make:migration create_eventos_table
database/migrations/2022_12_05_132037_create_eventos_table.php
<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('eventos', function (Blueprint $table) { $table->id(); $table->string('titulo'); $table->date('inicio'); $table->date('fim'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('eventos'); } };
Vamos criar nosso banco de dados:
create database laravel_cal;
Pronto, agora vamos rodar nossa migration:
php artisan migrate
criaremos nossa classe model:
php artisan make:model Evento
<?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class Evento extends Model { use HasFactory; protected $fillable = [ 'titulo', 'inicio', 'fim' ]; }
Agora criaremos nosso controller, que terá dois métodos: um que pegará as informações persistentes no banco, e outro que fará requisições assíncronas, utilizando JQuery e o FullCalendar, para que realize inserção, alteração e exclusão de maneira reativa:
php artisan make:controller CalendarioController
CalendarioController.php
<?php namespace App\Http\Controllers; use App\Models\Evento; use Illuminate\Http\Request; class CalendarioController extends Controller { public function index(Request $request) { if($request->ajax()) { $data = Evento::whereDate('inicio', '>=', $request->inicio) ->whereDate('fim', '<=', $request->fim) ->get(['id', 'titulo', 'inicio', 'fim']); return response()->json($data); } return view('calendario'); } /** * Write code on Method * * @return response() */ public function ajax(Request $request) { switch ($request->type) { case 'add': $evento = Evento::create([ 'titulo' => $request->titulo, 'inicio' => $request->inicio, 'fim' => $request->fim, ]); return response()->json($evento); break; case 'update': $evento = Evento::find($request->id)->update([ 'titulo' => $request->titulo, 'inicio' => $request->inicio, 'fim' => $request->fim, ]); return response()->json($evento); break; case 'delete': $evento = Evento::find($request->id)->delete(); return response()->json($evento); break; default: # break; } } }
Como podemos observar nosso Controller, no método index() que já faz requisições ajax, através da injeção de dependência Request do Laravel, já no método ajax() temos a condição de cada função de adição, remoção, atualização que faremos a chamada em nossa view, através do JQuery.
Criaremos agora nossa view, resources/view/calendario.blade.php
<!DOCTYPE html> <html> <head> <title>Calendário com Laravel</title> <meta name="csrf-token" content="{{ csrf_token() }}"> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" /> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.9.0/fullcalendar.css" /> <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.9.0/fullcalendar.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.9.0/locale/pt-br.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css" /> </head> <body> <div class="container"> <h1>Calendário com Laravel e JQuery</h1> <div id='calendar'></div> </div> <script> $(document).ready(function () { var SITEURL = "{{ url('/') }}"; $.ajaxSetup({ headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') } }); var calendar = $('#calendar').fullCalendar({ editable: true, events: SITEURL + "/calendario", displayEventTime: false, editable: true, eventRender: function (event, element, view) { if (event.allDay === 'true') { event.allDay = true; } else { event.allDay = false; } }, selectable: true, selectHelper: true, select: function (start, end, allDay) { var title = prompt('Título do Evento:'); if (title) { var start = $.fullCalendar.formatDate(start, "Y-MM-DD"); var end = $.fullCalendar.formatDate(end, "Y-MM-DD"); $.ajax({ url: SITEURL + "/calendarioAjax", data: { title: title, start: start, end: end, type: 'add' }, type: "POST", success: function (data) { displayMessage("Evento criado com Sucesso"); calendar.fullCalendar('renderEvent', { id: data.id, title: title, start: start, end: end, allDay: allDay },true); calendar.fullCalendar('unselect'); } }); } }, eventDrop: function (event, delta) { var start = $.fullCalendar.formatDate(event.start, "Y-MM-DD"); var end = $.fullCalendar.formatDate(event.end, "Y-MM-DD"); $.ajax({ url: SITEURL + '/calendarioAjax', data: { title: event.title, start: start, end: end, id: event.id, type: 'update' }, type: "POST", success: function (response) { displayMessage("Evento Atualizado com Sucesso!"); } }); }, eventClick: function (event) { var deleteMsg = confirm("Você deseja apagar este evento?"); if (deleteMsg) { $.ajax({ type: "POST", url: SITEURL + '/calendarioAjax', data: { id: event.id, type: 'delete' }, success: function (response) { calendar.fullCalendar('removeEvents', event.id); displayMessage("Evento Apagado com Sucesso"); } }); } } }); }); function displayMessage(message) { toastr.success(message, 'Evento'); } </script> </body> </html>
routes/web.php
Route::get('calendario', [CalendarioController::class, 'index']); Route::post('calendarioAjax', [CalendarioController::class, 'ajax']);
agora vamos rodar a aplicação:
php artisan serve
A biblioteca Fullcalendar tem uma ampla documentação para se customizar conforme a necessidade de seu negócio.
Código fonte no Github.
Estudem seus homens com tanto cuidado quanto um cirurgião
estuda um caso difícil. E, quando tiverem certeza do diagnóstico,
apliquem o remédio. Lembrem-se de que vocês aplicam o remédio
para efetuar uma cura, não para ver a vítima contorcer-se. Pode ser
necessário cortar fundo, mas, quando estiverem satisfeitos com o
diagnóstico, não se desviem do objetivo por alguma falsa simpatia
pelo paciente. – O Manuscrito Original – Napoleon Hill