si-klinik/sk-klinik.my.id/resources/views/livewire/admin/service-manager.blade.php

193 lines
8.6 KiB
PHP

<div class="mx-auto">
{{-- HEADER --}}
<div class="flex justify-between items-center mb-8">
<div>
<flux:heading size="xl">Manajemen Layanan</flux:heading>
<flux:subheading>Kelola daftar layanan dan galeri foto klinik.</flux:subheading>
</div>
<flux:button wire:click="create" variant="primary" icon="plus">
Tambah Layanan
</flux:button>
</div>
{{-- FILTER --}}
<div class="flex gap-4 mb-6">
<div class="flex-1">
<flux:input wire:model.live="search" placeholder="Cari nama layanan..." icon="magnifying-glass" />
</div>
<div class="w-64">
<flux:select wire:model.live="filterCategory">
<option value="">Semua Kategori</option>
@foreach ($categories as $id => $name)
<option value="{{ $id }}">{{ $name }}</option>
@endforeach
</flux:select>
</div>
</div>
{{-- TABLE --}}
<flux:table>
<flux:table.columns>
<flux:table.column>Foto</flux:table.column>
<flux:table.column sortable>Nama Layanan</flux:table.column>
<flux:table.column>Kategori</flux:table.column>
<flux:table.column>Deskripsi</flux:table.column>
<flux:table.column align="end">Aksi</flux:table.column>
</flux:table.columns>
<flux:table.rows>
@forelse ($services as $s)
<flux:table.row :key="$s->id">
{{-- Avatar Stack untuk Foto --}}
<flux:table.cell>
<div class="flex -space-x-2 overflow-hidden">
@if ($s->photo && count($s->photo) > 0)
@foreach (array_slice($s->photo, 0, 3) as $img)
<img src="{{ asset('storage/' . $img) }}"
class="inline-block rounded-lg ring-2 ring-white w-10 h-10 object-cover">
@endforeach
@if (count($s->photo) > 3)
<div
class="flex justify-center items-center bg-gray-100 rounded-lg ring-2 ring-white w-10 h-10 font-medium text-[10px] text-gray-500">
+{{ count($s->photo) - 3 }}
</div>
@endif
@else
<div
class="flex justify-center items-center bg-gray-50 border border-gray-300 border-dashed rounded-lg w-10 h-10">
<flux:icon.photo class="w-5 h-5 text-gray-400" />
</div>
@endif
</div>
</flux:table.cell>
<flux:table.cell class="font-medium text-zinc-800">{{ $s->name }}</flux:table.cell>
<flux:table.cell>
<flux:badge size="sm" inset="top bottom">{{ $s->category->name }}</flux:badge>
</flux:table.cell>
<flux:table.cell>
<p class="text-zinc-600 text-sm">
{{ Str::limit(strip_tags($s->description), 50, '...') }}
</p>
</flux:table.cell>
<flux:table.cell align="end">
<div class="flex justify-end gap-1">
<flux:button wire:click="edit({{ $s->id }})" icon="pencil" variant="ghost"
size="sm" />
<flux:button wire:click="delete({{ $s->id }})"
wire:confirm="Apakah Anda yakin ingin menghapus layanan ini?" icon="trash"
variant="ghost" size="sm" class="text-red-600" />
</div>
</flux:table.cell>
</flux:table.row>
@empty
<flux:table.row>
<flux:table.cell colspan="4" class="py-10 text-zinc-400 text-center">
Tidak ada data layanan ditemukan.
</flux:table.cell>
</flux:table.row>
@endforelse
</flux:table.rows>
</flux:table>
<div class="mt-6">
{{ $services->links() }}
</div>
{{-- MODAL FORM --}}
<flux:modal wire:model="isModalOpen" class="space-y-6 md:w-[700px]">
<div>
<flux:heading size="lg">{{ $serviceId ? 'Edit' : 'Tambah' }} Layanan</flux:heading>
<flux:subheading>Isi informasi detail mengenai layanan klinik di bawah ini.</flux:subheading>
</div>
<form wire:submit.prevent="save" class="space-y-6">
<div class="gap-4 grid grid-cols-1 md:grid-cols-2">
<flux:input wire:model="name" label="Nama Layanan" placeholder="Contoh: Scaling Gigi" />
<flux:select wire:model="category_id" label="Kategori">
<option value="">Pilih Kategori</option>
@foreach ($categories as $id => $name)
<option value="{{ $id }}">{{ $name }}</option>
@endforeach
</flux:select>
</div>
<div class="space-y-2">
<flux:label for="description">Deskripsi Detail</flux:label>
<flux:textarea
id="description"
wire:model="description"
rows="8"
placeholder="Masukkan deskripsi detail..."
/>
@error('description')
<p class="mt-1 text-sm text-red-500">{{ $message }}</p>
@enderror
</div>
{{-- MULTIPLE PHOTO UPLOAD --}}
<div class="space-y-3">
<flux:label>Foto & Galeri (Multiple)</flux:label>
<flux:input type="file" wire:model="photos" multiple accept="image/*" />
<div wire:loading wire:target="photos">
<flux:subheading class="text-blue-600 animate-pulse">Sedang mengunggah foto...</flux:subheading>
</div>
{{-- Preview Foto yang Sudah Ada --}}
@if ($existingPhotos)
<div class="gap-3 grid grid-cols-4 md:grid-cols-6 bg-zinc-50 p-3 border border-zinc-100 rounded-xl">
@foreach ($existingPhotos as $index => $path)
<div class="group relative aspect-square">
<img src="{{ asset('storage/' . $path) }}"
class="shadow-sm border border-zinc-200 rounded-lg w-full h-full object-cover">
<button type="button" wire:click="removePhoto({{ $index }})"
class="-top-2 -right-2 absolute bg-red-500 shadow-lg p-1 rounded-full text-white hover:scale-110 transition-transform">
<flux:icon.x-mark variant="mini" />
</button>
</div>
@endforeach
</div>
@endif
{{-- Preview Foto Baru (Temporary) --}}
@if ($photos)
<div class="flex gap-3 pb-2 overflow-x-auto">
@foreach ($photos as $photo)
<div
class="relative flex-none shadow-md border-2 border-blue-400 rounded-lg overflow-hidden">
<img src="{{ $photo->temporaryUrl() }}" class="w-20 h-20 object-cover">
<div class="absolute inset-0 flex justify-center items-center bg-blue-500/20">
<flux:badge size="xs" variant="primary" class="opacity-90">Baru</flux:badge>
</div>
</div>
@endforeach
</div>
@endif
</div>
<div class="flex justify-end gap-3 pt-4 border-zinc-100 border-t">
<flux:modal.close>
<flux:button variant="ghost">Batal</flux:button>
</flux:modal.close>
<flux:button type="submit" variant="primary" wire:loading.attr="disabled">
<span wire:loading.remove wire:target="save">Simpan Perubahan</span>
<span wire:loading wire:target="save">Memproses...</span>
</flux:button>
</div>
</form>
</flux:modal>
</div>