172 lines
12 KiB
PHP
172 lines
12 KiB
PHP
<x-master-page
|
|
title="Program Keahlian"
|
|
description="Kelola master jurusan atau program keahlian sekolah."
|
|
action-label="Tambah Program Keahlian"
|
|
:action-url="route('departments.create')"
|
|
>
|
|
<x-master-card title="Import Program Keahlian" subtitle="Upload Excel/CSV untuk menambah atau memperbarui data program keahlian secara massal.">
|
|
<form method="POST" action="{{ route('departments.import.preview') }}" enctype="multipart/form-data" class="space-y-5">
|
|
@csrf
|
|
<div>
|
|
<label for="import_file" class="mb-2 block text-sm font-medium text-slate-700">File Excel / CSV</label>
|
|
<input id="import_file" name="import_file" type="file" accept=".xlsx,.csv,.txt" class="block w-full rounded-2xl border border-slate-200 bg-white px-4 py-3 text-sm text-slate-700 file:mr-4 file:rounded-xl file:border-0 file:bg-indigo-50 file:px-4 file:py-2 file:font-semibold file:text-indigo-700 hover:file:bg-indigo-100">
|
|
<p class="mt-2 text-xs text-slate-500">Gunakan template agar format kolom sesuai. Import ini akan update data lama jika kode atau nama program keahlian sudah ada.</p>
|
|
</div>
|
|
|
|
<div class="flex flex-wrap items-center gap-3">
|
|
<button type="submit" class="inline-flex items-center rounded-2xl bg-indigo-600 px-5 py-3 text-sm font-semibold text-white shadow-lg shadow-indigo-200 transition hover:bg-indigo-700">Preview Import</button>
|
|
<a href="{{ route('departments.import.template') }}" class="inline-flex items-center rounded-2xl border border-emerald-200 bg-emerald-50 px-5 py-3 text-sm font-semibold text-emerald-700 transition hover:bg-emerald-100">Download Template</a>
|
|
</div>
|
|
</form>
|
|
|
|
@if (!empty($importPreview))
|
|
<div class="mt-6 rounded-3xl border border-slate-200 bg-white p-5">
|
|
<div class="mb-5 grid grid-cols-1 gap-4 md:grid-cols-4">
|
|
<div class="rounded-3xl border border-slate-200 bg-slate-50 px-5 py-4">
|
|
<div class="text-xs font-semibold uppercase tracking-[0.18em] text-slate-500">Total Baris</div>
|
|
<div class="mt-2 text-3xl font-bold text-slate-800">{{ $importPreview['summary']['total_rows'] }}</div>
|
|
</div>
|
|
<div class="rounded-3xl border border-emerald-200 bg-emerald-50 px-5 py-4">
|
|
<div class="text-xs font-semibold uppercase tracking-[0.18em] text-emerald-600">Valid</div>
|
|
<div class="mt-2 text-3xl font-bold text-emerald-700">{{ $importPreview['summary']['valid_rows'] }}</div>
|
|
</div>
|
|
<div class="rounded-3xl border border-sky-200 bg-sky-50 px-5 py-4">
|
|
<div class="text-xs font-semibold uppercase tracking-[0.18em] text-sky-600">Insert Baru</div>
|
|
<div class="mt-2 text-3xl font-bold text-sky-700">{{ $importPreview['summary']['insert_rows'] }}</div>
|
|
</div>
|
|
<div class="rounded-3xl border border-amber-200 bg-amber-50 px-5 py-4">
|
|
<div class="text-xs font-semibold uppercase tracking-[0.18em] text-amber-600">Update Data</div>
|
|
<div class="mt-2 text-3xl font-bold text-amber-700">{{ $importPreview['summary']['update_rows'] }}</div>
|
|
</div>
|
|
</div>
|
|
|
|
@if (!empty($importPreview['errors']))
|
|
<div class="mb-5 rounded-2xl border border-rose-200 bg-rose-50 px-5 py-4 text-sm text-rose-700">
|
|
<div class="font-semibold">Ada baris yang belum valid.</div>
|
|
<ul class="mt-2 list-disc space-y-1 pl-5">
|
|
@foreach (array_slice($importPreview['errors'], 0, 10) as $error)
|
|
<li>{{ $error }}</li>
|
|
@endforeach
|
|
</ul>
|
|
</div>
|
|
@endif
|
|
|
|
<div class="overflow-x-auto rounded-3xl border border-slate-200">
|
|
<table class="min-w-full divide-y divide-slate-200 text-sm">
|
|
<thead class="bg-slate-50">
|
|
<tr>
|
|
<th class="px-4 py-3 text-left text-xs font-semibold uppercase tracking-[0.16em] text-slate-500">Baris</th>
|
|
<th class="px-4 py-3 text-left text-xs font-semibold uppercase tracking-[0.16em] text-slate-500">Kode</th>
|
|
<th class="px-4 py-3 text-left text-xs font-semibold uppercase tracking-[0.16em] text-slate-500">Nama</th>
|
|
<th class="px-4 py-3 text-left text-xs font-semibold uppercase tracking-[0.16em] text-slate-500">Status</th>
|
|
<th class="px-4 py-3 text-left text-xs font-semibold uppercase tracking-[0.16em] text-slate-500">Aksi</th>
|
|
<th class="px-4 py-3 text-left text-xs font-semibold uppercase tracking-[0.16em] text-slate-500">Validasi</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="divide-y divide-slate-100 bg-white">
|
|
@foreach ($importPreview['rows'] as $row)
|
|
<tr class="align-top {{ $row['is_valid'] ? '' : 'bg-rose-50/50' }}">
|
|
<td class="px-4 py-4 font-semibold text-slate-700">{{ $row['row_number'] }}</td>
|
|
<td class="px-4 py-4 text-slate-700">{{ $row['data']['code'] ?: '-' }}</td>
|
|
<td class="px-4 py-4 text-slate-700">
|
|
<div class="font-medium">{{ $row['data']['name'] ?: '-' }}</div>
|
|
<div class="text-xs text-slate-400">{{ $row['data']['description'] ?: 'Tanpa deskripsi' }}</div>
|
|
</td>
|
|
<td class="px-4 py-4 text-slate-600">{{ ($row['data']['is_active'] ?? false) ? 'Aktif' : 'Nonaktif' }}</td>
|
|
<td class="px-4 py-4">
|
|
<span class="rounded-full px-3 py-1 text-xs font-semibold {{ $row['action'] === 'update' ? 'bg-amber-100 text-amber-700' : 'bg-sky-100 text-sky-700' }}">{{ $row['action'] === 'update' ? 'Update' : 'Insert' }}</span>
|
|
</td>
|
|
<td class="px-4 py-4 text-sm">
|
|
@if ($row['is_valid'])
|
|
<span class="rounded-full bg-emerald-100 px-3 py-1 text-xs font-semibold text-emerald-700">Valid</span>
|
|
@else
|
|
<div class="space-y-1 text-rose-700">
|
|
<div class="inline-flex rounded-full bg-rose-100 px-3 py-1 text-xs font-semibold">Perlu perbaikan</div>
|
|
<ul class="list-disc pl-4 text-xs">
|
|
@foreach ($row['errors'] as $error)
|
|
<li>{{ $error }}</li>
|
|
@endforeach
|
|
</ul>
|
|
</div>
|
|
@endif
|
|
</td>
|
|
</tr>
|
|
@endforeach
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
@if ($importPreview['summary']['valid_rows'] > 0)
|
|
<form method="POST" action="{{ route('departments.import') }}" class="mt-6 flex flex-wrap items-center gap-3">
|
|
@csrf
|
|
<input type="hidden" name="preview_token" value="{{ $importPreview['token'] }}">
|
|
<button type="submit" class="inline-flex items-center rounded-2xl bg-emerald-600 px-5 py-3 text-sm font-semibold text-white shadow-lg shadow-emerald-200 transition hover:bg-emerald-700">Konfirmasi Import ke Database</button>
|
|
<span class="text-sm text-slate-500">Hanya baris valid yang akan diproses.</span>
|
|
</form>
|
|
@endif
|
|
</div>
|
|
@endif
|
|
</x-master-card>
|
|
<x-master-card title="Filter Data" subtitle="Cari berdasarkan kode, nama, atau deskripsi program keahlian.">
|
|
<form method="GET" action="{{ route('departments.index') }}" class="flex flex-col gap-4 md:flex-row md:items-end">
|
|
<div class="md:flex-1">
|
|
<x-form-input name="search" label="Pencarian" :value="$search" placeholder="Cari program keahlian..." />
|
|
</div>
|
|
<div class="flex items-end gap-3">
|
|
<button type="submit" class="rounded-2xl bg-slate-900 px-5 py-3 text-sm font-semibold text-white transition hover:bg-slate-800">Cari</button>
|
|
<a href="{{ route('departments.index') }}" class="rounded-2xl border border-slate-200 px-5 py-3 text-sm font-semibold text-slate-700 transition hover:bg-slate-50">Reset</a>
|
|
</div>
|
|
</form>
|
|
</x-master-card>
|
|
|
|
<x-data-table :headers="['Kode', 'Nama', 'Dipakai', 'Deskripsi', 'Status', 'Aksi']">
|
|
@forelse ($departments as $department)
|
|
<tr>
|
|
<td class="px-6 py-4 text-sm font-semibold text-slate-800">{{ $department->code }}</td>
|
|
<td class="px-6 py-4 text-sm text-slate-700">{{ $department->name }}</td>
|
|
<td class="px-6 py-4">
|
|
<div class="flex flex-wrap gap-2">
|
|
<span class="rounded-full bg-sky-100 px-3 py-1 text-xs font-semibold text-sky-700">Kelas: {{ $department->classes_count }}</span>
|
|
<span class="rounded-full bg-indigo-100 px-3 py-1 text-xs font-semibold text-indigo-700">Siswa: {{ $department->students_count }}</span>
|
|
</div>
|
|
</td>
|
|
<td class="px-6 py-4 text-sm text-slate-500">{{ $department->description ?: '-' }}</td>
|
|
<td class="px-6 py-4">
|
|
@if ($department->is_active)
|
|
<span class="rounded-full bg-emerald-100 px-3 py-1 text-xs font-semibold text-emerald-700">Aktif</span>
|
|
@else
|
|
<span class="rounded-full bg-slate-100 px-3 py-1 text-xs font-semibold text-slate-600">Nonaktif</span>
|
|
@endif
|
|
</td>
|
|
<td class="px-6 py-4">
|
|
<div class="flex flex-wrap items-center gap-2">
|
|
<a href="{{ route('departments.edit', $department) }}" class="rounded-xl border border-slate-200 px-3 py-2 text-xs font-semibold text-slate-700 transition hover:bg-slate-50">Edit</a>
|
|
@php
|
|
$canDelete = $department->classes_count === 0 && $department->students_count === 0;
|
|
@endphp
|
|
@if ($canDelete)
|
|
<form action="{{ route('departments.destroy', $department) }}" method="POST" class="delete-form" data-entity="program keahlian {{ $department->name }}">
|
|
@csrf
|
|
@method('DELETE')
|
|
<button type="submit" class="rounded-xl border border-rose-200 px-3 py-2 text-xs font-semibold text-rose-600 transition hover:bg-rose-50">Hapus</button>
|
|
</form>
|
|
@else
|
|
<button type="button" disabled class="cursor-not-allowed rounded-xl border border-slate-200 bg-slate-100 px-3 py-2 text-xs font-semibold text-slate-400" title="Tidak bisa dihapus karena masih dipakai data lain">
|
|
Dipakai
|
|
</button>
|
|
@endif
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
@empty
|
|
<tr>
|
|
<td colspan="6" class="px-6 py-10 text-center text-sm text-slate-500">Belum ada data program keahlian.</td>
|
|
</tr>
|
|
@endforelse
|
|
</x-data-table>
|
|
|
|
<div>
|
|
{{ $departments->links() }}
|
|
</div>
|
|
</x-master-page>
|