351 lines
17 KiB
PHP
351 lines
17 KiB
PHP
<?php
|
|
|
|
namespace App\Providers\Filament;
|
|
|
|
use App\Filament\Pages\Auth\Login;
|
|
use App\Http\Middleware\SetLocale;
|
|
use BezhanSalleh\FilamentShield\FilamentShieldPlugin;
|
|
use Filament\Actions\Action;
|
|
use Filament\Http\Middleware\Authenticate;
|
|
use Filament\View\PanelsRenderHook;
|
|
use Filament\Http\Middleware\AuthenticateSession;
|
|
use Filament\Http\Middleware\DisableBladeIconComponents;
|
|
use Filament\Http\Middleware\DispatchServingFilamentEvent;
|
|
use Filament\Navigation\NavigationGroup;
|
|
use Filament\Panel;
|
|
use Filament\PanelProvider;
|
|
use Filament\Support\Colors\Color;
|
|
use Filament\Support\Enums\Width;
|
|
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
|
|
use Illuminate\Cookie\Middleware\EncryptCookies;
|
|
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;
|
|
use Illuminate\Routing\Middleware\SubstituteBindings;
|
|
use Illuminate\Session\Middleware\StartSession;
|
|
use Illuminate\View\Middleware\ShareErrorsFromSession;
|
|
|
|
class AdminPanelProvider extends PanelProvider
|
|
{
|
|
public function boot(): void
|
|
{
|
|
\Filament\Support\Facades\FilamentAsset::register([
|
|
\Filament\Support\Assets\Js::make('audio-speed', asset('js/audio-speed.js')),
|
|
]);
|
|
}
|
|
|
|
public function panel(Panel $panel): Panel
|
|
{
|
|
return $panel
|
|
->default()
|
|
->id('admin')
|
|
->path('admin')
|
|
->login(Login::class)
|
|
->colors([
|
|
'primary' => Color::Blue,
|
|
'orange' => Color::Orange,
|
|
])
|
|
->brandLogo(function () {
|
|
$key = app()->getLocale() === 'fa' ? 'listlogo_per.png' : 'listlogo_eng.png';
|
|
$attachment = \Illuminate\Support\Facades\Cache::remember(
|
|
'brand_logo_' . $key,
|
|
now()->addHours(24),
|
|
fn () => \App\Models\OsurgInitial::where('init_parameter', $key)->value('attachment')
|
|
);
|
|
return $attachment ? asset('storage/' . $attachment) : null;
|
|
})
|
|
->brandLogoHeight('1.75rem')
|
|
->brandName('')
|
|
->favicon(asset('favicon.svg'))
|
|
->font('Vazirmatn', url: \Illuminate\Support\Facades\Vite::asset('resources/css/vazirmatn.css'), provider: \Filament\FontProviders\LocalFontProvider::class)
|
|
->renderHook(
|
|
PanelsRenderHook::BODY_START,
|
|
fn (): string => <<<'HTML'
|
|
<script>
|
|
(function () {
|
|
if (localStorage.getItem('isOpen') === null) {
|
|
localStorage.setItem('isOpen', 'false');
|
|
}
|
|
if (localStorage.getItem('isOpenDesktop') === null) {
|
|
localStorage.setItem('isOpenDesktop', 'false');
|
|
}
|
|
})();
|
|
</script>
|
|
HTML,
|
|
)
|
|
->renderHook(
|
|
PanelsRenderHook::TOPBAR_LOGO_AFTER,
|
|
fn (): string => view('components.persian-datetime')->render(),
|
|
)
|
|
->renderHook(
|
|
PanelsRenderHook::GLOBAL_SEARCH_BEFORE,
|
|
fn (): string => \Blade::render('@livewire(\'settings-dropdown\')'),
|
|
)
|
|
->renderHook(
|
|
PanelsRenderHook::BODY_END,
|
|
fn (): string => <<<'HTML'
|
|
<script>
|
|
(function () {
|
|
var speeds = [0.5, 1, 1.5, 2];
|
|
document.addEventListener('click', function (e) {
|
|
var btn = e.target.closest('.filepond--media-player-button-playbackrate');
|
|
if (!btn) return;
|
|
var item = btn.closest('.filepond--item, .filepond--root');
|
|
if (!item) return;
|
|
var media = item.querySelector('audio, video');
|
|
if (!media) return;
|
|
var current = media.playbackRate || 1;
|
|
var idx = speeds.indexOf(current);
|
|
var next = speeds[(idx + 1) % speeds.length];
|
|
media.playbackRate = next;
|
|
btn.textContent = next + 'x';
|
|
});
|
|
})();
|
|
</script>
|
|
HTML,
|
|
)
|
|
->renderHook(
|
|
PanelsRenderHook::BODY_END,
|
|
fn (): string => <<<'HTML'
|
|
<div id="fi-lightbox">
|
|
<div id="fi-lb-wrap">
|
|
<img id="fi-lb-img" src="" alt="">
|
|
<button id="fi-lb-close" title="بستن">✕</button>
|
|
<button id="fi-lb-prev" title="قبلی">‹</button>
|
|
<button id="fi-lb-next" title="بعدی">›</button>
|
|
<div id="fi-lb-counter">1 / 1</div>
|
|
<div id="fi-lb-hint">اسکرول: زوم | دابلکلیک: ریست</div>
|
|
</div>
|
|
</div>
|
|
<script>
|
|
(function () {
|
|
'use strict';
|
|
|
|
var lb = document.getElementById('fi-lightbox');
|
|
var lbWrap = document.getElementById('fi-lb-wrap');
|
|
var lbImg = document.getElementById('fi-lb-img');
|
|
var lbCnt = document.getElementById('fi-lb-counter');
|
|
var lbPrev = document.getElementById('fi-lb-prev');
|
|
var lbNext = document.getElementById('fi-lb-next');
|
|
var lbClose = document.getElementById('fi-lb-close');
|
|
if (!lb) return;
|
|
|
|
var images = [], currentIdx = 0, zoom = 1;
|
|
var isPanning = false, panStartX = 0, panStartY = 0, panX = 0, panY = 0;
|
|
|
|
function applyTransform() {
|
|
lbImg.style.transform = 'scale(' + zoom + ') translate(' + panX + 'px, ' + panY + 'px)';
|
|
lbImg.classList.toggle('lb-zoomed', zoom > 1);
|
|
}
|
|
|
|
function showLightbox(imgs, idx) {
|
|
images = imgs;
|
|
currentIdx = idx;
|
|
zoom = 1; panX = 0; panY = 0;
|
|
applyTransform();
|
|
updateCounter();
|
|
loadImage();
|
|
lb.classList.add('lb-open');
|
|
document.addEventListener('keydown', onKey);
|
|
}
|
|
|
|
function hideLightbox() {
|
|
lb.classList.remove('lb-open');
|
|
document.removeEventListener('keydown', onKey);
|
|
lbImg.src = '';
|
|
}
|
|
|
|
function navigate(dir) {
|
|
if (images.length < 2) return;
|
|
currentIdx = (currentIdx + dir + images.length) % images.length;
|
|
zoom = 1; panX = 0; panY = 0;
|
|
applyTransform();
|
|
loadImage();
|
|
updateCounter();
|
|
}
|
|
|
|
function loadImage() {
|
|
lbImg.style.opacity = '0';
|
|
var src = images[currentIdx];
|
|
var tmp = new Image();
|
|
tmp.onload = function () { lbImg.src = src; lbImg.style.opacity = '1'; };
|
|
tmp.onerror = function () { lbImg.src = src; lbImg.style.opacity = '1'; };
|
|
tmp.src = src;
|
|
}
|
|
|
|
function updateCounter() {
|
|
lbCnt.textContent = (currentIdx + 1) + ' / ' + images.length;
|
|
var show = images.length > 1;
|
|
lbPrev.style.visibility = show ? '' : 'hidden';
|
|
lbNext.style.visibility = show ? '' : 'hidden';
|
|
}
|
|
|
|
function onKey(e) {
|
|
if (e.key === 'Escape') hideLightbox();
|
|
else if (e.key === 'ArrowLeft') navigate(-1);
|
|
else if (e.key === 'ArrowRight') navigate(1);
|
|
else if (e.key === '+' || e.key === '=') { zoom = Math.min(8, zoom + 0.2); applyTransform(); }
|
|
else if (e.key === '-') { zoom = Math.max(0.3, zoom - 0.2); if (zoom <= 1) { panX = 0; panY = 0; } applyTransform(); }
|
|
else if (e.key === '0') { zoom = 1; panX = 0; panY = 0; applyTransform(); }
|
|
}
|
|
|
|
lbWrap.addEventListener('wheel', function (e) {
|
|
e.preventDefault();
|
|
zoom = Math.max(0.3, Math.min(8, zoom + (e.deltaY < 0 ? 0.1 : -0.1)));
|
|
if (zoom <= 1) { panX = 0; panY = 0; }
|
|
applyTransform();
|
|
}, { passive: false });
|
|
|
|
lbImg.addEventListener('dblclick', function () {
|
|
zoom = 1; panX = 0; panY = 0; applyTransform();
|
|
});
|
|
|
|
lbImg.addEventListener('mousedown', function (e) {
|
|
if (zoom <= 1) return;
|
|
isPanning = true;
|
|
panStartX = e.clientX - panX * zoom;
|
|
panStartY = e.clientY - panY * zoom;
|
|
lbImg.classList.add('lb-dragging');
|
|
e.preventDefault();
|
|
});
|
|
document.addEventListener('mousemove', function (e) {
|
|
if (!isPanning) return;
|
|
panX = (e.clientX - panStartX) / zoom;
|
|
panY = (e.clientY - panStartY) / zoom;
|
|
lbImg.style.transform = 'scale(' + zoom + ') translate(' + panX + 'px, ' + panY + 'px)';
|
|
});
|
|
document.addEventListener('mouseup', function () {
|
|
if (isPanning) { isPanning = false; lbImg.classList.remove('lb-dragging'); }
|
|
});
|
|
|
|
lbWrap.addEventListener('click', function (e) { if (e.target === lbWrap) hideLightbox(); });
|
|
lbClose.addEventListener('click', hideLightbox);
|
|
lbPrev.addEventListener('click', function () { navigate(-1); });
|
|
lbNext.addEventListener('click', function () { navigate(1); });
|
|
|
|
document.addEventListener('click', function (e) {
|
|
var thumb = e.target.closest('[data-lb-src]');
|
|
if (!thumb) return;
|
|
e.preventDefault();
|
|
var group = thumb.getAttribute('data-lb-group');
|
|
var all = group
|
|
? Array.from(document.querySelectorAll('[data-lb-group="' + group + '"]'))
|
|
: [thumb];
|
|
var urls = all.map(function (el) { return el.getAttribute('data-lb-src'); });
|
|
var idx = all.indexOf(thumb);
|
|
showLightbox(urls, Math.max(0, idx));
|
|
});
|
|
|
|
document.addEventListener('click', function (e) {
|
|
var preview = e.target.closest('.filepond--image-preview-wrapper, .filepond--image-preview');
|
|
if (!preview) return;
|
|
|
|
var item = preview.closest('.filepond--item');
|
|
var root = item && item.closest('.filepond--root');
|
|
if (!item || !root) return;
|
|
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
|
|
var allItems = Array.from(root.querySelectorAll('.filepond--item'));
|
|
var clickedIdx = allItems.indexOf(item);
|
|
|
|
var pond = null;
|
|
var alpineEl = root.closest('[x-data]');
|
|
if (alpineEl && window.Alpine) {
|
|
try { var ad = Alpine.$data(alpineEl); if (ad && ad.pond) pond = ad.pond; } catch (e1) {}
|
|
}
|
|
if (!pond) {
|
|
var inp = root.querySelector('input[type="file"], input.filepond');
|
|
if (inp && inp._filepond) pond = inp._filepond;
|
|
}
|
|
if (pond) {
|
|
try {
|
|
var pondFiles = pond.getFiles();
|
|
var urls1 = [];
|
|
pondFiles.forEach(function (f) {
|
|
var sid = f.serverId;
|
|
if (!sid) return;
|
|
if (typeof sid !== 'string') { try { sid = JSON.parse(sid); } catch(pe) {} }
|
|
if (typeof sid === 'string') {
|
|
urls1.push(sid.startsWith('http') || sid.startsWith('/') ? sid : '/storage/' + sid);
|
|
}
|
|
});
|
|
if (urls1.length) { showLightbox(urls1, Math.min(clickedIdx, urls1.length - 1)); return; }
|
|
} catch (e2) {}
|
|
}
|
|
|
|
var wireInput = root.querySelector('input[wire\\:model], input[wire\\:model\\.live], input[wire\\:model\\.blur]');
|
|
var wireModel = wireInput && (wireInput.getAttribute('wire:model') || wireInput.getAttribute('wire:model.live') || wireInput.getAttribute('wire:model.blur'));
|
|
var wireEl = root.closest('[wire\\:id]');
|
|
var wireId = wireEl && wireEl.getAttribute('wire:id');
|
|
if (wireModel && wireId && window.Livewire) {
|
|
try {
|
|
var comp = window.Livewire.find(wireId);
|
|
var files = comp.$wire.get(wireModel);
|
|
if (files) {
|
|
var arr = Array.isArray(files) ? files : Object.values(files);
|
|
if (arr.length) {
|
|
showLightbox(arr.map(function (f) { return '/storage/' + f; }), Math.min(clickedIdx, arr.length - 1));
|
|
return;
|
|
}
|
|
}
|
|
} catch (e3) {}
|
|
}
|
|
|
|
var imgs = [], fbIdx = 0;
|
|
allItems.forEach(function (it) {
|
|
var canvas = it.querySelector('canvas');
|
|
if (canvas) {
|
|
try {
|
|
var src = canvas.toDataURL('image/jpeg', 0.95);
|
|
if (it === item) fbIdx = imgs.length;
|
|
imgs.push(src);
|
|
} catch (ex) {}
|
|
}
|
|
});
|
|
if (imgs.length) showLightbox(imgs, fbIdx);
|
|
}, true);
|
|
})();
|
|
</script>
|
|
HTML,
|
|
)
|
|
->userMenuItems([
|
|
Action::make('switch_language')
|
|
->label(fn () => app()->getLocale() === 'fa' ? 'English' : 'فارسی')
|
|
->icon('heroicon-o-language')
|
|
->url(fn () => route('locale.switch', app()->getLocale() === 'fa' ? 'en' : 'fa')),
|
|
])
|
|
->navigationGroups([
|
|
NavigationGroup::make('بیماران و ویزیت'),
|
|
NavigationGroup::make('بیماریها و روشهای درمان'),
|
|
NavigationGroup::make('اطلاعات کلینیک'),
|
|
NavigationGroup::make('تنظیمات'),
|
|
])
|
|
->sidebarFullyCollapsibleOnDesktop()
|
|
->maxContentWidth(Width::Full)
|
|
->viteTheme('resources/css/filament/admin/theme.css')
|
|
->discoverResources(in: app_path('Filament/Resources'), for: 'App\Filament\Resources')
|
|
->plugins([
|
|
FilamentShieldPlugin::make(),
|
|
])
|
|
->discoverPages(in: app_path('Filament/Pages'), for: 'App\Filament\Pages')
|
|
->pages([])
|
|
->discoverWidgets(in: app_path('Filament/Widgets'), for: 'App\Filament\Widgets')
|
|
->widgets([])
|
|
->middleware([
|
|
EncryptCookies::class,
|
|
AddQueuedCookiesToResponse::class,
|
|
StartSession::class,
|
|
AuthenticateSession::class,
|
|
ShareErrorsFromSession::class,
|
|
VerifyCsrfToken::class,
|
|
SubstituteBindings::class,
|
|
DisableBladeIconComponents::class,
|
|
DispatchServingFilamentEvent::class,
|
|
SetLocale::class,
|
|
])
|
|
->authMiddleware([
|
|
Authenticate::class,
|
|
]);
|
|
}
|
|
}
|