first change
This commit is contained in:
569
Modules/Admin/resources/views/calendar/index.blade.php
Normal file
569
Modules/Admin/resources/views/calendar/index.blade.php
Normal file
@@ -0,0 +1,569 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<div class="page-content">
|
||||
<div class="container-fluid">
|
||||
|
||||
<!-- start page title -->
|
||||
@include('layouts.partials.breadcrumb', ['title' => $title])
|
||||
<!-- end page title -->
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="row">
|
||||
<div class="col-xl-3">
|
||||
|
||||
<div class="card" style="height: 30%">
|
||||
<div class="card-header align-items-center d-flex">
|
||||
<h4 class="card-title flex-grow-1 mb-0">Content Schedule</h4>
|
||||
</div><!-- end card header -->
|
||||
|
||||
<div class="card-body p-0">
|
||||
<div data-simplebar="init" style="max-height: 200px;" class="simplebar-scrollable-y">
|
||||
<div class="simplebar-wrapper" style="margin: 0px;">
|
||||
<div class="simplebar-height-auto-observer-wrapper">
|
||||
<div class="simplebar-height-auto-observer"></div>
|
||||
</div>
|
||||
<div class="simplebar-mask">
|
||||
<div class="simplebar-offset" style="right: 0px; bottom: 0px;">
|
||||
<div class="simplebar-content-wrapper" tabindex="0" role="region"
|
||||
aria-label="scrollable content"
|
||||
style="height: auto; overflow: hidden scroll;">
|
||||
<div class="simplebar-content" style="padding: 0px;">
|
||||
<ul class="list-group list-group-flush border-dashed px-3">
|
||||
@forelse ($contents as $content)
|
||||
<li class="list-group-item ps-0">
|
||||
<a href="javascript:void(0)"
|
||||
class="content-edit-btn"
|
||||
data-link="{{ route('content.partials.edit', $content->id) }}"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#contentModal">
|
||||
<div class="d-flex mb-3">
|
||||
<div class="flex-grow-1"><i
|
||||
class="mdi mdi-checkbox-blank-circle text-success me-2"></i><span
|
||||
class="fw-medium">{{ $content->release_date?->format('d M, Y') }}</span>
|
||||
</div>
|
||||
<div class="flex-shrink-0"><small
|
||||
class="badge bg-primary-subtle text-primary ms-auto">{{ $content->release_time?->format('h:i A') }}</small>
|
||||
</div>
|
||||
</div>
|
||||
<h6 class="card-title fs-12">
|
||||
{{ $content->title }}
|
||||
</h6>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
@empty
|
||||
<h6 class="text-dark my-5 text-center">No upcoming
|
||||
schedule</h6>
|
||||
@endforelse
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="simplebar-placeholder" style="width: 655px; height: 268px;"></div>
|
||||
</div>
|
||||
<div class="simplebar-track simplebar-horizontal" style="visibility: hidden;">
|
||||
<div class="simplebar-scrollbar" style="width: 0px; display: none;"></div>
|
||||
</div>
|
||||
<div class="simplebar-track simplebar-vertical" style="visibility: visible;">
|
||||
<div class="simplebar-scrollbar"
|
||||
style="height: 178px; transform: translate3d(0px, 41px, 0px); display: block;">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- end card body -->
|
||||
</div>
|
||||
|
||||
<div class="card" style="height: 30%">
|
||||
<div class="card-header align-items-center d-flex">
|
||||
<h4 class="card-title flex-grow-1 mb-0">Events</h4>
|
||||
|
||||
<div class="flex-shrink-0">
|
||||
<button type="button" class="btn btn-sm btn-primary" data-bs-toggle="modal"
|
||||
data-bs-target="#eventModal">
|
||||
<i class="ri-add-line me-1 align-middle"></i>
|
||||
Add Event</button>
|
||||
</div>
|
||||
</div><!-- end card header -->
|
||||
|
||||
<div class="card-body p-0">
|
||||
<div data-simplebar="init" style="max-height: 200px;" class="simplebar-scrollable-y">
|
||||
<div class="simplebar-wrapper" style="margin: 0px;">
|
||||
<div class="simplebar-height-auto-observer-wrapper">
|
||||
<div class="simplebar-height-auto-observer"></div>
|
||||
</div>
|
||||
<div class="simplebar-mask">
|
||||
<div class="simplebar-offset" style="right: 0px; bottom: 0px;">
|
||||
<div class="simplebar-content-wrapper" tabindex="0" role="region"
|
||||
aria-label="scrollable content"
|
||||
style="height: auto; overflow: hidden scroll;">
|
||||
<div class="simplebar-content" style="padding: 0px;">
|
||||
<ul class="list-group list-group-flush border-dashed px-3">
|
||||
@foreach ($events as $event)
|
||||
<li class="list-group-item ps-0">
|
||||
<div class="d-flex mb-3">
|
||||
<div class="flex-grow-1"><i
|
||||
class="mdi mdi-checkbox-blank-circle text-primary me-2"></i><span
|
||||
class="fw-medium">{{ $event->start_date?->format('d M, Y') }}
|
||||
@if ($event->end_date)
|
||||
<span>to
|
||||
{{ $event->end_date?->format('d M, Y') }}</span>
|
||||
@endif
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex-shrink-0"><small
|
||||
class="badge bg-primary-subtle text-primary ms-auto">{{ $event->start_time?->format('h:i A') }}</small>
|
||||
</div>
|
||||
</div>
|
||||
<h6 class="card-title fs-12">{{ $event->title }}
|
||||
</h6>
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="simplebar-placeholder" style="width: 655px; height: 350px;"></div>
|
||||
</div>
|
||||
<div class="simplebar-track simplebar-horizontal" style="visibility: hidden;">
|
||||
<div class="simplebar-scrollbar" style="width: 0px; display: none;"></div>
|
||||
</div>
|
||||
<div class="simplebar-track simplebar-vertical" style="visibility: visible;">
|
||||
<div class="simplebar-scrollbar"
|
||||
style="height: 178px; transform: translate3d(0px, 41px, 0px); display: block;">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div><!-- end card body -->
|
||||
</div>
|
||||
|
||||
<div class="card" style="height: 30%">
|
||||
<div class="card-header align-items-center d-flex">
|
||||
<h4 class="card-title flex-grow-1 mb-0">Meetings</h4>
|
||||
|
||||
<div class="flex-shrink-0">
|
||||
<button type="button" class="btn btn-sm btn-warning" data-bs-toggle="modal"
|
||||
data-bs-target="#meetingModal"><i class="ri-add-line me-1 align-middle"></i>
|
||||
Add Meeting</button>
|
||||
</div>
|
||||
</div><!-- end card header -->
|
||||
|
||||
<div class="card-body p-0">
|
||||
<div data-simplebar="init" style="max-height: 200px;" class="simplebar-scrollable-y">
|
||||
<div class="simplebar-wrapper" style="margin: 0px;">
|
||||
<div class="simplebar-height-auto-observer-wrapper">
|
||||
<div class="simplebar-height-auto-observer"></div>
|
||||
</div>
|
||||
<div class="simplebar-mask">
|
||||
<div class="simplebar-offset" style="right: 0px; bottom: 0px;">
|
||||
<div class="simplebar-content-wrapper" tabindex="0" role="region"
|
||||
aria-label="scrollable content"
|
||||
style="height: auto; overflow: hidden scroll;">
|
||||
<div class="simplebar-content" style="padding: 0px;">
|
||||
<ul class="list-group list-group-flush border-dashed px-3">
|
||||
@foreach ($meetings as $meeting)
|
||||
<li class="list-group-item ps-0">
|
||||
<div class="d-flex mb-3">
|
||||
<div class="flex-grow-1"><i
|
||||
class="mdi mdi-checkbox-blank-circle text-warning me-2"></i><span
|
||||
class="fw-medium">{{ $meeting->date?->format('d M, Y') }}</span>
|
||||
</div>
|
||||
<div class="flex-shrink-0"><small
|
||||
class="badge bg-primary-subtle text-primary ms-auto">{{ $meeting->start_time?->format('h:i A') }}</small>
|
||||
</div>
|
||||
</div>
|
||||
<h6 class="card-title fs-12">{{ $meeting->title }}
|
||||
</h6>
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="simplebar-placeholder" style="width: 655px; height: 268px;"></div>
|
||||
</div>
|
||||
<div class="simplebar-track simplebar-horizontal" style="visibility: hidden;">
|
||||
<div class="simplebar-scrollbar" style="width: 0px; display: none;"></div>
|
||||
</div>
|
||||
<div class="simplebar-track simplebar-vertical" style="visibility: visible;">
|
||||
<div class="simplebar-scrollbar"
|
||||
style="height: 178px; transform: translate3d(0px, 41px, 0px); display: block;">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- end card body -->
|
||||
</div>
|
||||
</div>
|
||||
<!-- end col-->
|
||||
|
||||
<div class="col-xl-9">
|
||||
<div class="card">
|
||||
<div class="card-header border-bottom-dashed">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="flex-grow-1">
|
||||
<h6 class="card-title mb-0">Filter</h6>
|
||||
</div>
|
||||
<div class="flex-shrink-0">
|
||||
<ul class="list-inline card-toolbar-menu d-flex align-items-center mb-0">
|
||||
<li class="list-inline-item">
|
||||
<a class="minimize-card align-middle" data-bs-toggle="collapse"
|
||||
href="#collapseExample2" role="button" aria-expanded="false"
|
||||
aria-controls="collapseExample2">
|
||||
<i class="mdi mdi-plus plus align-middle"></i>
|
||||
<i class="mdi mdi-minus minus align-middle"></i>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div @class(['card-body collapse', 'show' => request()->has('product_id')]) id="collapseExample2">
|
||||
{{ html()->form('GET')->id('filter-form')->open() }}
|
||||
<div class="row justify-content-between align-items-center">
|
||||
<div class="col-md-4">
|
||||
{{ html()->select('product_id', $productOptions, request('product_id'))->placeholder('By Product')->value(request('product_id'))->class('form-control select2') }}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="d-flex list-grid-nav hstack mt-2 gap-1">
|
||||
<button type="submit" class="btn btn-sm btn-success">Filter</button>
|
||||
<a href="{{ route(Route::currentRouteName()) }}"
|
||||
class="btn btn-danger btn-sm reset-filter">Reset</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{ html()->form()->close() }}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="card card-h-100">
|
||||
<div class="card-body">
|
||||
<div id="calendar"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- end col -->
|
||||
</div>
|
||||
<!--end row-->
|
||||
</div>
|
||||
</div> <!-- end row-->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="viewModal" class="modal fade" tabindex="-1" aria-labelledby="viewModalLabel" aria-hidden="true"
|
||||
style="display: none;">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<p class="modal-title" id="viewModalLabel">Detail</p>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
</div>
|
||||
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
||||
|
||||
<div id="eventModal" class="modal fade" tabindex="-1" aria-labelledby="eventModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<p class="modal-title" id="viewModalLabel">Event Form</p>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"> </button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
{{ html()->form('POST')->route('event.store')->class(['needs-validation eventForm'])->attributes(['novalidate'])->open() }}
|
||||
@include('admin::calendar.partials.event-form')
|
||||
{{ html()->form()->close() }}
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
||||
|
||||
<div id="contentModal" class="modal fade" tabindex="-1" aria-labelledby="contentModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<p class="modal-title" id="viewModalLabel">Schedule Update Form</p>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body" id="js-content-partial-target">
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
||||
|
||||
<div id="meetingModal" class="modal fade" tabindex="-1" aria-labelledby="meetingModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="viewModalLabel">Meeting Form</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"> </button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
{{ html()->form('POST')->route('meeting.store')->class(['needs-validation meetingForm'])->attributes(['novalidate'])->open() }}
|
||||
@include('admin::calendar.partials.meeting-form')
|
||||
{{ html()->form()->close() }}
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
||||
@endsection
|
||||
|
||||
@push('js')
|
||||
<script src="{{ asset('assets/js/pages/form-validation.init.js') }}"></script>
|
||||
<script src='https://cdn.jsdelivr.net/npm/fullcalendar@6.1.11/index.global.min.js'></script>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var calendarEl = document.getElementById('calendar');
|
||||
$.ajaxSetup({
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
|
||||
}
|
||||
});
|
||||
|
||||
var currentDate = new Date().toISOString().split('T')[0];
|
||||
var calendar = new FullCalendar.Calendar(calendarEl, {
|
||||
headerToolbar: {
|
||||
left: 'prev,next today',
|
||||
center: 'title',
|
||||
right: 'dayGridMonth,timeGridWeek,timeGridDay,listMonth'
|
||||
},
|
||||
initialDate: currentDate,
|
||||
navLinks: true, // can click day/week names to navigate views
|
||||
businessHours: true, // display business hours
|
||||
editable: false,
|
||||
selectable: false,
|
||||
dayMaxEvents: true,
|
||||
events: {
|
||||
url: `${base_url}/admin/calendarByAjax`,
|
||||
method: 'GET',
|
||||
extraParams: function() {
|
||||
return {
|
||||
product_id: $('#filter-form #product_id').val()
|
||||
};
|
||||
}
|
||||
},
|
||||
selectMirror: true,
|
||||
select: function(arg) {
|
||||
var title = prompt('Event Title:');
|
||||
if (title) {
|
||||
calendar.addEvent({
|
||||
title: title,
|
||||
start: arg.start,
|
||||
end: arg.end,
|
||||
allDay: arg.allDay
|
||||
})
|
||||
}
|
||||
calendar.unselect()
|
||||
},
|
||||
eventClick: function(arg) {
|
||||
|
||||
if (arg.event.extendedProps.type == 'content schedule') {
|
||||
$('#contentModal').modal('show');
|
||||
const url = "{{ route('content.partials.edit', ':id') }}".replace(':id', arg.event.id);
|
||||
let target = document.querySelector('#js-content-partial-target');
|
||||
target.innerHTML = "<h5 class='text-center my-5'>Loading...</h5>";
|
||||
fetch(url)
|
||||
.then(response => response.text())
|
||||
.then(html => {
|
||||
target.innerHTML = html;
|
||||
});
|
||||
} else {
|
||||
|
||||
let html = `<tr class="mb-1">`;
|
||||
html += `<td class="text-bold">Title: </td>`;
|
||||
html += `<td>${arg.event.title}</td>`;
|
||||
html += `</tr>`;
|
||||
|
||||
html += `<tr class="mb-1">`;
|
||||
html += `<td class="text-bold">Type: </td>`;
|
||||
html += `<td>${arg.event.extendedProps.type}</td>`;
|
||||
html += `</tr>`;
|
||||
|
||||
html += `<tr class="mb-1">`;
|
||||
html += `<td class="text-bold">Start: </td>`;
|
||||
html += `<td>${new Date(arg.event.start).toLocaleString()}</td>`;
|
||||
html += `</tr>`;
|
||||
|
||||
if (arg.event.end) {
|
||||
html += `<tr class="mb-1">`;
|
||||
html += `<td class="text-bold">End: </td>`;
|
||||
html += `<td>${new Date(arg.event.end).toLocaleString()}</td>`;
|
||||
html += `</tr>`;
|
||||
}
|
||||
|
||||
html += `<tr>`;
|
||||
html += `<td class="text-bold">Location: </td>`;
|
||||
html += `<td>${arg.event.extendedProps.location ?? 'No Location'}</td>`;
|
||||
html += `</tr>`;
|
||||
|
||||
html += `<tr class="mb-1">`;
|
||||
html += `<td class="text-bold">Description: </td>`;
|
||||
html += `<td>${arg.event.extendedProps.desc ?? 'No Description'}</td>`;
|
||||
html += `</tr>`;
|
||||
|
||||
const modal = $('#viewModal');
|
||||
modal.find('.modal-body').html(html);
|
||||
$('#viewModal').modal('show');
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
calendar.render();
|
||||
|
||||
$('#filter-form').on('submit', function(e) {
|
||||
calendar.refetchEvents();
|
||||
})
|
||||
|
||||
$("body").on('submit', '.eventForm', function(e) {
|
||||
e.preventDefault();
|
||||
let form = $('.eventForm')[0];
|
||||
let formData = new FormData(form);
|
||||
param = {
|
||||
url: '{{ route('event.store') }}',
|
||||
type: 'event'
|
||||
}
|
||||
formSubmit(param, formData)
|
||||
window.location.href = "{{ route('calendar.index') }}";
|
||||
})
|
||||
|
||||
$("body").on('submit', '#contentForm', function(e) {
|
||||
e.preventDefault();
|
||||
let form = $('#contentForm')[0];
|
||||
let formData = new FormData(form);
|
||||
const url = $(this).attr('action');
|
||||
const button = $('#contentForm #submit');
|
||||
button.text('Scheduling...');
|
||||
button.prop('disabled', true);
|
||||
|
||||
$.ajax({
|
||||
url: url,
|
||||
type: 'POST',
|
||||
processData: false,
|
||||
contentType: false,
|
||||
data: formData,
|
||||
success: function(response) {
|
||||
$(`#contentModal`).modal('hide');
|
||||
flasher.success(response.msg);
|
||||
window.location.reload();
|
||||
},
|
||||
|
||||
error: function(xhr) {
|
||||
if (xhr.responseJSON) {
|
||||
var errors = xhr.responseJSON;
|
||||
for (var key in errors) {
|
||||
if (errors.hasOwnProperty(key)) {
|
||||
var errorMessages = errors[key];
|
||||
for (var i = 0; i < errorMessages.length; i++) {
|
||||
flasher.error(errorMessages[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
flasher.error("An error occurred while processing your request.");
|
||||
}
|
||||
},
|
||||
|
||||
complete: function() {
|
||||
button.text('Schedule');
|
||||
button.prop('disabled', false);
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
$("body").on('click', '.content-edit-btn', function(e) {
|
||||
e.preventDefault();
|
||||
const url = $(this).attr('data-link');
|
||||
|
||||
let target = document.querySelector('#js-content-partial-target');
|
||||
target.innerHTML = "<h5 class='text-center my-5'>Loading...</h5>";
|
||||
fetch(url)
|
||||
.then(response => response.text())
|
||||
.then(html => {
|
||||
target.innerHTML = html;
|
||||
})
|
||||
})
|
||||
|
||||
$("body").on('submit', '.meetingForm', function(e) {
|
||||
e.preventDefault();
|
||||
let form = $('.meetingForm')[0];
|
||||
let formData = new FormData(form);
|
||||
param = {
|
||||
url: '{{ route('meeting.store') }}',
|
||||
type: 'meeting'
|
||||
}
|
||||
formSubmit(param, formData)
|
||||
window.location.href = "{{ route('calendar.index') }}";
|
||||
})
|
||||
|
||||
const formSubmit = (param, formData) => {
|
||||
let type = param.type
|
||||
$.ajax({
|
||||
url: param.url,
|
||||
type: 'POST',
|
||||
processData: false,
|
||||
contentType: false,
|
||||
data: formData,
|
||||
success: function(response) {
|
||||
if (response.status == true) {
|
||||
eventData = response.data
|
||||
addEvent(eventData, type);
|
||||
}
|
||||
$(`#${param.type}Modal`).modal('hide');
|
||||
flasher.success(response.msg);
|
||||
$(`.${param.type}Form`)[0].reset()
|
||||
|
||||
},
|
||||
error: function(xhr) {
|
||||
if (xhr.responseJSON) {
|
||||
var errors = xhr.responseJSON;
|
||||
for (var key in errors) {
|
||||
if (errors.hasOwnProperty(key)) {
|
||||
var errorMessages = errors[key];
|
||||
for (var i = 0; i < errorMessages.length; i++) {
|
||||
flasher.error(errorMessages[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
flasher.error("An error occurred while processing your request.");
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const addEvent = (data, type) => {
|
||||
className = '';
|
||||
console.log(data, type);
|
||||
if (type == 'event') {
|
||||
className = 'bg-primary-subtle'
|
||||
} else if (type == 'meeting') {
|
||||
className = 'bg-warning-subtle'
|
||||
} else if (type == 'meeting') {
|
||||
className = 'bg-success-subtle'
|
||||
}
|
||||
|
||||
calendar.addEvent({
|
||||
title: data.title,
|
||||
start: data.start_date,
|
||||
end: data.end_date,
|
||||
desc: data.description,
|
||||
location: data.location,
|
||||
className: className,
|
||||
allDay: true
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
</script>
|
||||
@endpush
|
Reference in New Issue
Block a user