Files
autocrm/resources/views/filament/tenant/pages/calendar.blade.php
T
Vasyka c84ef5d9bd fix: calendar collapses to plain text after first render
FullCalendar mounts into a Livewire-managed subtree. The first
$wire.getEvents() response triggered a Livewire DOM morph that reverted
#autocrm-calendar to its empty server HTML, destroying the rendered grid
(~1s after load it became unstyled text).

Wrap the calendar container in wire:ignore so Livewire's morphdom skips it.
The quick-create modal stays outside wire:ignore to keep its form reactive.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 22:58:55 +00:00

144 lines
6.4 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<x-filament-panels::page>
{{-- FullCalendar v6 ships CSS bundled in JS no separate stylesheet needed --}}
<script src="https://cdn.jsdelivr.net/npm/fullcalendar@6.1.15/index.global.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/fullcalendar@6.1.15/locales/ro.global.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/fullcalendar@6.1.15/locales/ru.global.min.js"></script>
<style>
.cal-wrap {
background: #fff; border: 1px solid #e5e7eb; border-radius: 10px;
padding: 16px;
}
.dark .cal-wrap { background: #1f2937; border-color: #374151; }
.fc { font-size: 13px; }
.fc .fc-toolbar-title { font-size: 16px; }
.fc-event { cursor: move; padding: 2px 4px; font-size: 11px; }
.fc-event:hover { opacity: 0.85; }
.fc-daygrid-event-dot { display: none; }
#cal-modal-bg {
position: fixed; top: 0; left: 0; right: 0; bottom: 0;
background: rgba(0,0,0,0.5); z-index: 9998;
display: none; align-items: center; justify-content: center;
}
#cal-modal-bg.open { display: flex; }
#cal-modal {
background: #fff; border-radius: 10px; padding: 20px;
max-width: 520px; width: 90%; max-height: 88vh; overflow: auto;
z-index: 9999;
}
.dark #cal-modal { background: #1f2937; color: #f9fafb; }
.cal-modal-head {
display: flex; justify-content: space-between; align-items: center;
margin-bottom: 16px;
}
.cal-modal-head h2 { font-size: 16px; font-weight: 600; margin: 0; }
.cal-close {
background: none; border: none; font-size: 22px; cursor: pointer; color: #9ca3af;
}
</style>
<div
x-data="{
calendar: null,
init() {
this.$nextTick(() => this.mount());
window.addEventListener('events-changed', () => this.calendar?.refetchEvents());
},
mount() {
const el = document.getElementById('autocrm-calendar');
if (!el) return;
this.calendar = new FullCalendar.Calendar(el, {
locale: 'ro',
initialView: 'timeGridWeek',
firstDay: 1,
height: 'auto',
nowIndicator: true,
slotMinTime: '07:00:00',
slotMaxTime: '21:00:00',
slotDuration: '00:30:00',
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'timeGridDay,timeGridWeek,dayGridMonth'
},
buttonText: {
today: 'Azi', month: 'Lună', week: 'Săpt.', day: 'Zi'
},
editable: true,
selectable: true,
selectMirror: true,
eventTimeFormat: { hour: '2-digit', minute: '2-digit', hour12: false },
events: async (info, success, fail) => {
try {
const events = await $wire.getEvents(
info.startStr.substring(0, 10),
info.endStr.substring(0, 10)
);
success(events);
} catch (e) { fail(e); }
},
eventDrop: (info) => {
$wire.moveEvent(
parseInt(info.event.id),
info.event.startStr,
info.event.endStr || info.event.startStr
);
},
eventResize: (info) => {
$wire.moveEvent(
parseInt(info.event.id),
info.event.startStr,
info.event.endStr
);
},
select: (info) => {
$wire.quickCreate(info.startStr, info.endStr);
},
eventClick: (info) => {
const e = info.event;
const props = e.extendedProps;
const ok = confirm(
`${e.title}\n` +
`${props.vehicle ?? ''} ${props.plate ? '['+props.plate+']' : ''}\n` +
`Maistru: ${props.master ?? '—'}\n` +
`Pod: ${props.post ?? '—'}\n\n` +
`Șterge programarea?`
);
if (ok) $wire.deleteEvent(parseInt(e.id));
}
});
this.calendar.render();
}
}"
x-on:open-create-modal.window="document.getElementById('cal-modal-bg').classList.add('open')"
x-on:close-create-modal.window="document.getElementById('cal-modal-bg').classList.remove('open')"
>
{{-- wire:ignore: keep Livewire's DOM-morph away from the FullCalendar
subtree, otherwise the first $wire.getEvents response reverts the
container to its empty server HTML and the calendar collapses. --}}
<div class="cal-wrap" wire:ignore>
<div id="autocrm-calendar"></div>
</div>
{{-- Quick-create modal --}}
<div id="cal-modal-bg" @click.self="$el.classList.remove('open')">
<div id="cal-modal">
<div class="cal-modal-head">
<h2>Programare nouă</h2>
<button class="cal-close" @click="document.getElementById('cal-modal-bg').classList.remove('open')">×</button>
</div>
<form wire:submit="saveCreate">
{{ $this->createForm }}
<div style="margin-top: 16px; display: flex; gap: 8px; justify-content: flex-end;">
<x-filament::button color="gray" type="button"
x-on:click="document.getElementById('cal-modal-bg').classList.remove('open')">
Anulează
</x-filament::button>
<x-filament::button type="submit">Salvează</x-filament::button>
</div>
</form>
</div>
</div>
</div>
</x-filament-panels::page>