1888 lines
73 KiB
PHP
1888 lines
73 KiB
PHP
@extends('layouts.app')
|
|
|
|
@section('title', 'Manajemen Prestasi')
|
|
|
|
@push('styles')
|
|
<style>
|
|
/* Manajemen Prestasi Container */
|
|
.manajemen-prestasi-container {
|
|
max-width: 1400px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
/* Page Header */
|
|
.page-header {
|
|
padding: 20px 0;
|
|
}
|
|
|
|
.page-title {
|
|
font-family: 'Poppins', sans-serif;
|
|
font-weight: 700;
|
|
font-size: 2rem;
|
|
color: var(--dark);
|
|
margin-bottom: 0.5rem;
|
|
}
|
|
|
|
.page-subtitle {
|
|
color: #6c757d;
|
|
font-size: 1.1rem;
|
|
margin: 0;
|
|
}
|
|
|
|
/* Statistics Cards */
|
|
.stat-card {
|
|
background: white;
|
|
border-radius: var(--border-radius);
|
|
padding: 25px;
|
|
box-shadow: var(--shadow);
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 20px;
|
|
transition: var(--transition);
|
|
border-left: 4px solid transparent;
|
|
}
|
|
|
|
.stat-card:hover {
|
|
transform: translateY(-3px);
|
|
box-shadow: var(--shadow-lg);
|
|
}
|
|
|
|
.stat-card.primary {
|
|
border-left-color: var(--primary);
|
|
}
|
|
|
|
.stat-card.success {
|
|
border-left-color: #28a745;
|
|
}
|
|
|
|
.stat-card.warning {
|
|
border-left-color: #ffc107;
|
|
}
|
|
|
|
.stat-card.info {
|
|
border-left-color: #17a2b8;
|
|
}
|
|
|
|
.stat-icon {
|
|
width: 60px;
|
|
height: 60px;
|
|
border-radius: 15px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 1.5rem;
|
|
color: white;
|
|
}
|
|
|
|
.stat-card.primary .stat-icon {
|
|
background: var(--gradient);
|
|
}
|
|
|
|
.stat-card.success .stat-icon {
|
|
background: linear-gradient(135deg, #28a745, #20c997);
|
|
}
|
|
|
|
.stat-card.warning .stat-icon {
|
|
background: linear-gradient(135deg, #ffc107, #fd7e14);
|
|
}
|
|
|
|
.stat-card.info .stat-icon {
|
|
background: linear-gradient(135deg, #17a2b8, #6f42c1);
|
|
}
|
|
|
|
.stat-content {
|
|
flex: 1;
|
|
}
|
|
|
|
.stat-value {
|
|
font-family: 'Poppins', sans-serif;
|
|
font-weight: 700;
|
|
font-size: 2rem;
|
|
color: var(--dark);
|
|
margin: 0;
|
|
line-height: 1;
|
|
}
|
|
|
|
.stat-label {
|
|
color: #6c757d;
|
|
font-size: 0.9rem;
|
|
margin: 5px 0 0 0;
|
|
font-weight: 500;
|
|
}
|
|
|
|
/* Prestasi Grid Card */
|
|
.prestasi-grid-card {
|
|
background: white;
|
|
border-radius: var(--border-radius);
|
|
box-shadow: var(--shadow);
|
|
transition: var(--transition);
|
|
border: 1px solid rgba(0, 0, 0, 0.05);
|
|
}
|
|
|
|
.prestasi-grid-card:hover {
|
|
box-shadow: var(--shadow-lg);
|
|
}
|
|
|
|
.prestasi-grid-card .card-header {
|
|
padding: 25px 30px 0;
|
|
border: none;
|
|
background: none;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
flex-wrap: wrap;
|
|
gap: 20px;
|
|
}
|
|
|
|
.prestasi-grid-card .card-body {
|
|
padding: 25px 30px 30px;
|
|
}
|
|
|
|
.header-content {
|
|
display: flex;
|
|
align-items: center;
|
|
flex: 1;
|
|
}
|
|
|
|
.header-icon {
|
|
font-size: 1.8rem;
|
|
color: var(--primary);
|
|
margin-right: 15px;
|
|
width: 50px;
|
|
height: 50px;
|
|
background: linear-gradient(135deg, var(--primary-light), var(--primary));
|
|
border-radius: 12px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: white;
|
|
}
|
|
|
|
.card-title {
|
|
font-family: 'Poppins', sans-serif;
|
|
font-weight: 600;
|
|
font-size: 1.3rem;
|
|
color: var(--dark);
|
|
margin: 0;
|
|
}
|
|
|
|
.card-subtitle {
|
|
color: #6c757d;
|
|
font-size: 0.9rem;
|
|
margin: 5px 0 0 0;
|
|
}
|
|
|
|
/* Header Actions */
|
|
.header-actions {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 15px;
|
|
}
|
|
|
|
/* View Toggle */
|
|
.view-toggle {
|
|
display: flex;
|
|
gap: 5px;
|
|
background: #f8f9fa;
|
|
padding: 5px;
|
|
border-radius: 8px;
|
|
}
|
|
|
|
.view-btn {
|
|
width: 40px;
|
|
height: 40px;
|
|
border: none;
|
|
background: transparent;
|
|
border-radius: 6px;
|
|
color: #6c757d;
|
|
transition: var(--transition);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.view-btn:hover {
|
|
background: white;
|
|
color: var(--primary);
|
|
}
|
|
|
|
.view-btn.active {
|
|
background: var(--primary);
|
|
color: white;
|
|
}
|
|
|
|
/* Search Box */
|
|
.search-box {
|
|
position: relative;
|
|
min-width: 250px;
|
|
}
|
|
|
|
.search-box i {
|
|
position: absolute;
|
|
left: 15px;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
color: #6c757d;
|
|
}
|
|
|
|
.search-box input {
|
|
width: 100%;
|
|
padding: 12px 15px 12px 45px;
|
|
border: 2px solid #e9ecef;
|
|
border-radius: 8px;
|
|
font-size: 0.95rem;
|
|
transition: var(--transition);
|
|
}
|
|
|
|
.search-box input:focus {
|
|
border-color: var(--primary);
|
|
box-shadow: 0 0 0 0.2rem rgba(0, 102, 204, 0.1);
|
|
outline: none;
|
|
}
|
|
|
|
/* Prestasi Grid */
|
|
.prestasi-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
|
|
gap: 25px;
|
|
}
|
|
|
|
.prestasi-card {
|
|
background: white;
|
|
border-radius: var(--border-radius);
|
|
box-shadow: var(--shadow);
|
|
transition: var(--transition);
|
|
overflow: hidden;
|
|
border: 1px solid rgba(0, 0, 0, 0.05);
|
|
}
|
|
|
|
.prestasi-card:hover {
|
|
transform: translateY(-5px);
|
|
box-shadow: var(--shadow-lg);
|
|
}
|
|
|
|
.prestasi-image {
|
|
position: relative;
|
|
height: 220px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.prestasi-image img {
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: cover;
|
|
transition: var(--transition);
|
|
}
|
|
|
|
.prestasi-card:hover .prestasi-image img {
|
|
transform: scale(1.05);
|
|
}
|
|
|
|
.prestasi-overlay {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
background: rgba(0, 0, 0, 0.7);
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
opacity: 0;
|
|
transition: var(--transition);
|
|
overflow-y: auto;
|
|
padding: 20px;
|
|
text-align: center;
|
|
color: white;
|
|
z-index: 2;
|
|
}
|
|
|
|
.prestasi-card:hover .prestasi-overlay {
|
|
opacity: 1;
|
|
}
|
|
|
|
.prestasi-overlay::-webkit-scrollbar {
|
|
width: 6px;
|
|
}
|
|
|
|
.prestasi-overlay::-webkit-scrollbar-track {
|
|
background: rgba(0, 0, 0, 0.2);
|
|
}
|
|
|
|
.prestasi-overlay::-webkit-scrollbar-thumb {
|
|
background: rgba(255, 255, 255, 0.3);
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.prestasi-overlay::-webkit-scrollbar-thumb:hover {
|
|
background: rgba(255, 255, 255, 0.5);
|
|
}
|
|
|
|
.prestasi-badges {
|
|
position: absolute;
|
|
top: 10px;
|
|
left: 10px;
|
|
display: flex;
|
|
gap: 5px;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.badge {
|
|
padding: 4px 8px;
|
|
border-radius: 12px;
|
|
font-size: 0.7rem;
|
|
font-weight: 600;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.5px;
|
|
}
|
|
|
|
.badge-urutan {
|
|
background: rgba(0, 0, 0, 0.8);
|
|
color: white;
|
|
}
|
|
|
|
.badge-active {
|
|
background: linear-gradient(135deg, #28a745, #20c997);
|
|
color: white;
|
|
}
|
|
|
|
.badge-inactive {
|
|
background: #6c757d;
|
|
color: white;
|
|
}
|
|
|
|
/* Prestasi Content */
|
|
.prestasi-content {
|
|
padding: 20px;
|
|
}
|
|
|
|
.prestasi-title {
|
|
font-weight: 600;
|
|
color: var(--dark);
|
|
margin: 0 0 15px 0;
|
|
font-size: 1.1rem;
|
|
line-height: 1.4;
|
|
height: 3em;
|
|
overflow: hidden;
|
|
display: -webkit-box;
|
|
-webkit-line-clamp: 2;
|
|
line-clamp: 2;
|
|
-webkit-box-orient: vertical;
|
|
}
|
|
|
|
.prestasi-info {
|
|
margin-bottom: 15px;
|
|
}
|
|
|
|
.info-item {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
margin-bottom: 8px;
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
.info-item i {
|
|
width: 16px;
|
|
color: var(--primary);
|
|
text-align: center;
|
|
}
|
|
|
|
.info-item span {
|
|
color: #6c757d;
|
|
}
|
|
|
|
.prestasi-actions {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
border-top: 1px solid #e9ecef;
|
|
padding-top: 15px;
|
|
}
|
|
|
|
/* Form Switch */
|
|
.form-check.form-switch {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
margin: 0;
|
|
}
|
|
|
|
.form-check-input {
|
|
width: 3em;
|
|
height: 1.5em;
|
|
margin: 0;
|
|
}
|
|
|
|
.form-check-label {
|
|
font-size: 0.9rem;
|
|
color: var(--dark);
|
|
font-weight: 500;
|
|
}
|
|
|
|
/* Action Buttons */
|
|
.action-buttons {
|
|
display: flex;
|
|
gap: 8px;
|
|
}
|
|
|
|
.action-buttons .btn {
|
|
width: 36px;
|
|
height: 36px;
|
|
padding: 0;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border-radius: 8px;
|
|
border: 2px solid;
|
|
transition: var(--transition);
|
|
}
|
|
|
|
.btn-edit {
|
|
color: var(--primary);
|
|
border-color: var(--primary) !important;
|
|
background: transparent;
|
|
}
|
|
|
|
.btn-edit:hover {
|
|
background: var(--primary);
|
|
color: white;
|
|
transform: translateY(-2px);
|
|
}
|
|
|
|
.btn-view {
|
|
color: #17a2b8;
|
|
border-color: #17a2b8 !important;
|
|
background: transparent;
|
|
}
|
|
|
|
.btn-view:hover {
|
|
background: #17a2b8;
|
|
color: white;
|
|
transform: translateY(-2px);
|
|
}
|
|
|
|
.btn-delete {
|
|
color: #dc3545;
|
|
border-color: #dc3545 !important;
|
|
background: transparent;
|
|
}
|
|
|
|
.btn-delete:hover {
|
|
background: #dc3545;
|
|
color: white;
|
|
transform: translateY(-2px);
|
|
}
|
|
|
|
/* Prestasi List View */
|
|
.prestasi-list .prestasi-thumb {
|
|
width: 80px;
|
|
height: 60px;
|
|
border-radius: 8px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.prestasi-list .prestasi-thumb img {
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: cover;
|
|
}
|
|
|
|
.prestasi-list .prestasi-info-list h6 {
|
|
margin: 0;
|
|
font-weight: 600;
|
|
font-size: 0.95rem;
|
|
}
|
|
|
|
.student-info {
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
.achievement-info {
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
.urutan-badge {
|
|
background: var(--primary);
|
|
color: white;
|
|
padding: 4px 8px;
|
|
border-radius: 12px;
|
|
font-size: 0.8rem;
|
|
font-weight: 600;
|
|
}
|
|
|
|
/* Empty State */
|
|
.empty-state {
|
|
padding: 60px 20px;
|
|
text-align: center;
|
|
}
|
|
|
|
.empty-state h4 {
|
|
color: var(--dark);
|
|
margin-bottom: 10px;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.empty-state p {
|
|
color: #6c757d;
|
|
max-width: 400px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
/* Modal Styles */
|
|
.modal-content {
|
|
border: none;
|
|
border-radius: var(--border-radius);
|
|
box-shadow: var(--shadow-xl);
|
|
}
|
|
|
|
.modal-header {
|
|
border-bottom: 1px solid #e9ecef;
|
|
padding: 25px 30px 20px;
|
|
}
|
|
|
|
.modal-title {
|
|
font-family: 'Poppins', sans-serif;
|
|
font-weight: 600;
|
|
color: var(--dark);
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.modal-body {
|
|
padding: 25px 30px;
|
|
}
|
|
|
|
.modal-footer {
|
|
border-top: 1px solid #e9ecef;
|
|
padding: 20px 30px 25px;
|
|
}
|
|
|
|
/* Prestasi Upload Area */
|
|
.prestasi-upload-area {
|
|
position: relative;
|
|
}
|
|
|
|
.upload-wrapper {
|
|
border: 2px dashed #dee2e6;
|
|
border-radius: var(--border-radius);
|
|
padding: 40px 20px;
|
|
text-align: center;
|
|
cursor: pointer;
|
|
transition: var(--transition);
|
|
background: #f8f9fa;
|
|
}
|
|
|
|
.upload-wrapper:hover {
|
|
border-color: var(--primary);
|
|
background: #f0f4ff;
|
|
}
|
|
|
|
.upload-wrapper.dragover {
|
|
border-color: var(--primary);
|
|
background: #e3f2fd;
|
|
}
|
|
|
|
.upload-placeholder i {
|
|
font-size: 3rem;
|
|
color: #6c757d;
|
|
margin-bottom: 15px;
|
|
}
|
|
|
|
.upload-placeholder p {
|
|
font-weight: 600;
|
|
color: var(--dark);
|
|
margin: 0 0 10px 0;
|
|
}
|
|
|
|
.upload-placeholder small {
|
|
color: #6c757d;
|
|
line-height: 1.4;
|
|
}
|
|
|
|
.upload-input {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
opacity: 0;
|
|
cursor: pointer;
|
|
}
|
|
|
|
/* Image Preview */
|
|
.image-preview {
|
|
position: relative;
|
|
border: 2px solid #e9ecef;
|
|
border-radius: var(--border-radius);
|
|
overflow: hidden;
|
|
margin-top: 15px;
|
|
}
|
|
|
|
.image-preview img {
|
|
width: 100%;
|
|
height: 200px;
|
|
object-fit: cover;
|
|
}
|
|
|
|
.btn-remove-preview {
|
|
position: absolute;
|
|
top: 10px;
|
|
right: 10px;
|
|
width: 30px;
|
|
height: 30px;
|
|
border: none;
|
|
background: rgba(220, 53, 69, 0.9);
|
|
color: white;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 0.8rem;
|
|
transition: var(--transition);
|
|
}
|
|
|
|
.btn-remove-preview:hover {
|
|
background: #dc3545;
|
|
transform: scale(1.1);
|
|
}
|
|
|
|
/* Current Image Preview */
|
|
.current-image-preview {
|
|
border: 2px solid #e9ecef;
|
|
border-radius: var(--border-radius);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.current-image-preview img {
|
|
width: 100%;
|
|
height: 150px;
|
|
object-fit: cover;
|
|
}
|
|
|
|
/* Prestasi Detail View */
|
|
.prestasi-detail-image img {
|
|
width: 100%;
|
|
height: 300px;
|
|
object-fit: cover;
|
|
}
|
|
|
|
.prestasi-detail-info {
|
|
padding: 20px 0;
|
|
}
|
|
|
|
.detail-item {
|
|
margin-bottom: 15px;
|
|
}
|
|
|
|
.detail-label {
|
|
font-weight: 600;
|
|
color: var(--dark);
|
|
display: block;
|
|
margin-bottom: 5px;
|
|
}
|
|
|
|
.detail-content {
|
|
color: #6c757d;
|
|
margin: 0;
|
|
}
|
|
|
|
/* Form Styles */
|
|
.form-group {
|
|
margin-bottom: 1.5rem;
|
|
}
|
|
|
|
.form-label {
|
|
font-weight: 600;
|
|
color: var(--dark);
|
|
margin-bottom: 8px;
|
|
display: block;
|
|
}
|
|
|
|
.form-control {
|
|
border: 2px solid #e9ecef;
|
|
border-radius: 8px;
|
|
padding: 12px 15px;
|
|
transition: var(--transition);
|
|
font-size: 0.95rem;
|
|
}
|
|
|
|
.form-control:focus {
|
|
border-color: var(--primary);
|
|
box-shadow: 0 0 0 0.2rem rgba(0, 102, 204, 0.1);
|
|
}
|
|
|
|
textarea.form-control {
|
|
resize: vertical;
|
|
min-height: 100px;
|
|
}
|
|
|
|
.form-text {
|
|
font-size: 0.85rem;
|
|
}
|
|
|
|
/* Buttons */
|
|
.btn {
|
|
padding: 12px 25px;
|
|
border-radius: 8px;
|
|
font-weight: 500;
|
|
transition: var(--transition);
|
|
border: none;
|
|
}
|
|
|
|
.btn-primary {
|
|
background: var(--gradient);
|
|
border: none;
|
|
}
|
|
|
|
.btn-primary:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 5px 15px rgba(0, 102, 204, 0.3);
|
|
}
|
|
|
|
.btn-secondary {
|
|
background: #6c757d;
|
|
border: none;
|
|
}
|
|
|
|
.btn-secondary:hover {
|
|
background: #5a6268;
|
|
transform: translateY(-2px);
|
|
}
|
|
|
|
/* Loading State */
|
|
.btn-loading {
|
|
position: relative;
|
|
color: transparent !important;
|
|
}
|
|
|
|
.btn-loading::after {
|
|
content: '';
|
|
position: absolute;
|
|
width: 20px;
|
|
height: 20px;
|
|
top: 50%;
|
|
left: 50%;
|
|
margin-left: -10px;
|
|
margin-top: -10px;
|
|
border: 2px solid #ffffff;
|
|
border-radius: 50%;
|
|
border-top-color: transparent;
|
|
animation: spin 1s ease-in-out infinite;
|
|
}
|
|
|
|
@keyframes spin {
|
|
to {
|
|
transform: rotate(360deg);
|
|
}
|
|
}
|
|
|
|
/* Responsive Design */
|
|
@media (max-width: 991.98px) {
|
|
.page-header {
|
|
padding: 15px 0;
|
|
}
|
|
|
|
.page-title {
|
|
font-size: 1.7rem;
|
|
}
|
|
|
|
.stat-card {
|
|
padding: 20px;
|
|
}
|
|
|
|
.stat-value {
|
|
font-size: 1.7rem;
|
|
}
|
|
|
|
.prestasi-grid {
|
|
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
|
gap: 20px;
|
|
}
|
|
|
|
.prestasi-grid-card .card-header {
|
|
padding: 20px 25px 0;
|
|
flex-direction: column;
|
|
align-items: flex-start;
|
|
gap: 15px;
|
|
}
|
|
|
|
.header-content {
|
|
width: 100%;
|
|
}
|
|
|
|
.header-actions {
|
|
width: 100%;
|
|
justify-content: space-between;
|
|
}
|
|
|
|
.search-box {
|
|
min-width: 200px;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 767.98px) {
|
|
.prestasi-grid {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
.modal-body {
|
|
padding: 20px 25px;
|
|
}
|
|
|
|
.modal-header,
|
|
.modal-footer {
|
|
padding: 20px 25px;
|
|
}
|
|
|
|
.prestasi-list .table-responsive {
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
.header-actions {
|
|
flex-direction: column;
|
|
gap: 10px;
|
|
align-items: stretch;
|
|
}
|
|
|
|
.search-box {
|
|
min-width: 100%;
|
|
}
|
|
|
|
.prestasi-detail-info {
|
|
padding: 15px 0 0 0;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 575.98px) {
|
|
.manajemen-prestasi-container {
|
|
padding: 0 15px;
|
|
}
|
|
|
|
.page-title {
|
|
font-size: 1.5rem;
|
|
}
|
|
|
|
.stat-card {
|
|
flex-direction: column;
|
|
text-align: center;
|
|
gap: 15px;
|
|
}
|
|
|
|
.upload-placeholder {
|
|
padding: 30px 15px;
|
|
}
|
|
|
|
.upload-placeholder i {
|
|
font-size: 2.5rem;
|
|
}
|
|
|
|
.modal-body .row {
|
|
flex-direction: column;
|
|
}
|
|
|
|
.modal-body .col-md-6 {
|
|
width: 100%;
|
|
}
|
|
|
|
.action-buttons {
|
|
justify-content: center;
|
|
}
|
|
|
|
.prestasi-title {
|
|
height: auto;
|
|
-webkit-line-clamp: 3;
|
|
line-clamp: 3;
|
|
}
|
|
}
|
|
</style>
|
|
@endpush
|
|
|
|
@section('content')
|
|
<link rel="stylesheet" href="{{ asset('css/manajemen-prestasi.css') }}">
|
|
|
|
<div class="manajemen-prestasi-container">
|
|
<div class="page-header mb-4">
|
|
<div class="row align-items-center">
|
|
<div class="col">
|
|
<h1 class="page-title">Manajemen Prestasi</h1>
|
|
<p class="page-subtitle">Kelola data prestasi siswa SMK Muhammadiyah 1 Berbek</p>
|
|
</div>
|
|
<div class="col-auto">
|
|
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#tambahPrestasiModal">
|
|
<i class="fas fa-plus me-2"></i>Tambah Prestasi
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row mb-4">
|
|
<div class="col-md-3">
|
|
<div class="stat-card primary">
|
|
<div class="stat-icon">
|
|
<i class="fas fa-trophy"></i>
|
|
</div>
|
|
<div class="stat-content">
|
|
<h3 class="stat-value">{{ $prestasis->count() }}</h3>
|
|
<p class="stat-label">Total Prestasi</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="stat-card success">
|
|
<div class="stat-icon">
|
|
<i class="fas fa-check-circle"></i>
|
|
</div>
|
|
<div class="stat-content">
|
|
<h3 class="stat-value">{{ $prestasis->where('status', true)->count() }}</h3>
|
|
<p class="stat-label">Prestasi Aktif</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="stat-card warning">
|
|
<div class="stat-icon">
|
|
<i class="fas fa-clock"></i>
|
|
</div>
|
|
<div class="stat-content">
|
|
<h3 class="stat-value">{{ $prestasis->where('status', false)->count() }}</h3>
|
|
<p class="stat-label">Prestasi Nonaktif</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="stat-card info">
|
|
<div class="stat-icon">
|
|
<i class="fas fa-sort-amount-down"></i>
|
|
</div>
|
|
<div class="stat-content">
|
|
<h3 class="stat-value">{{ $prestasis->max('urutan') ?? 0 }}</h3>
|
|
<p class="stat-label">Urutan Tertinggi</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="prestasi-grid-card">
|
|
<div class="card-header">
|
|
<div class="header-content">
|
|
<i class="fas fa-award header-icon"></i>
|
|
<div>
|
|
<h3 class="card-title">Daftar Prestasi Siswa</h3>
|
|
<p class="card-subtitle">Kelola urutan dan tampilan prestasi di halaman utama</p>
|
|
</div>
|
|
</div>
|
|
<div class="header-actions">
|
|
<div class="view-toggle">
|
|
<button class="view-btn active" data-view="grid">
|
|
<i class="fas fa-th-large"></i>
|
|
</button>
|
|
<button class="view-btn" data-view="list">
|
|
<i class="fas fa-list"></i>
|
|
</button>
|
|
</div>
|
|
<div class="search-box">
|
|
<i class="fas fa-search"></i>
|
|
<input type="text" id="searchInput" placeholder="Cari prestasi...">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
@if ($prestasis->isEmpty())
|
|
<div class="empty-state">
|
|
<i class="fas fa-trophy fa-4x text-muted mb-4"></i>
|
|
<h4>Belum ada data prestasi</h4>
|
|
<p class="text-muted">Tambahkan data prestasi pertama untuk ditampilkan di website.</p>
|
|
<button class="btn btn-primary mt-3" data-bs-toggle="modal" data-bs-target="#tambahPrestasiModal">
|
|
<i class="fas fa-plus me-2"></i>Tambah Prestasi Pertama
|
|
</button>
|
|
</div>
|
|
@else
|
|
<div class="prestasi-grid" id="prestasiGridView">
|
|
@foreach ($prestasis as $item)
|
|
<div class="prestasi-card" data-prestasi-id="{{ $item->id }}">
|
|
<div class="prestasi-image">
|
|
<img src="{{ $item->foto_prestasi_url }}" class="card-img-top"
|
|
alt="{{ $item->nama_prestasi }}"
|
|
onerror="this.onerror=null;this.src='{{ asset('images/default-img.png') }}'">
|
|
<div class="prestasi-overlay">
|
|
<div class="action-buttons">
|
|
<button class="btn btn-sm btn-edit" onclick="editPrestasi({{ $item->id }})"
|
|
title="Edit Prestasi">
|
|
<i class="fas fa-edit"></i>
|
|
</button>
|
|
<button class="btn btn-sm btn-view" onclick="viewPrestasi({{ $item->id }})"
|
|
title="Lihat Detail">
|
|
<i class="fas fa-eye"></i>
|
|
</button>
|
|
<button class="btn btn-sm btn-delete"
|
|
onclick="deletePrestasi({{ $item->id }})" title="Hapus Prestasi">
|
|
<i class="fas fa-trash"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="prestasi-badges">
|
|
<span class="badge badge-urutan">#{{ $item->urutan }}</span>
|
|
@if ($item->status)
|
|
<span class="badge badge-active">Aktif</span>
|
|
@else
|
|
<span class="badge badge-inactive">Nonaktif</span>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
<div class="prestasi-content">
|
|
<h6 class="prestasi-title">{{ $item->nama_prestasi }}</h6>
|
|
<div class="student-info">
|
|
<div class="info-item">
|
|
<i class="fas fa-user"></i>
|
|
<span>{{ $item->nama_siswa }}</span>
|
|
</div>
|
|
<div class="info-item">
|
|
<i class="fas fa-graduation-cap"></i>
|
|
<span>{{ $item->jurusan->nama_jurusan ?? '-' }}</span>
|
|
</div>
|
|
<div class="info-item">
|
|
<i class="fas fa-calendar-alt"></i>
|
|
<span>Tahun {{ $item->tahun_prestasi }}</span>
|
|
</div>
|
|
</div>
|
|
<div class="prestasi-actions">
|
|
<div class="form-check form-switch">
|
|
<input class="form-check-input status-toggle" type="checkbox"
|
|
data-prestasi-id="{{ $item->id }}"
|
|
{{ $item->status ? 'checked' : '' }}>
|
|
<label class="form-check-label">Status Aktif</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
|
|
<div class="prestasi-list d-none" id="prestasiListView">
|
|
<div class="table-responsive">
|
|
<table class="table">
|
|
<thead>
|
|
<tr>
|
|
<th>Foto</th>
|
|
<th>Nama Siswa & Jurusan</th>
|
|
<th>Nama Prestasi</th>
|
|
<th>Peringkat & Tahun</th>
|
|
<th>Status</th>
|
|
<th>Urutan</th>
|
|
<th class="text-center">Aksi</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@foreach ($prestasis as $item)
|
|
<tr data-prestasi-id="{{ $item->id }}">
|
|
<td>
|
|
<div class="prestasi-img-wrapper">
|
|
<img src="{{ $item->foto_prestasi_url }}" class="prestasi-img"
|
|
alt="{{ $item->nama_prestasi }}"
|
|
onerror="this.onerror=null;this.src='{{ asset('images/default-img.png') }}'">
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<div class="student-info">
|
|
<strong>{{ $item->nama_siswa }}</strong>
|
|
<br>
|
|
<small
|
|
class="text-muted">{{ $item->jurusan->nama_jurusan ?? '-' }}</small>
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<div class="prestasi-name">{{ $item->nama_prestasi }}</div>
|
|
</td>
|
|
<td>
|
|
<div class="achievement-info">
|
|
<span class="badge bg-warning">{{ $item->peringkat }}</span>
|
|
<br>
|
|
<small class="text-muted">{{ $item->tahun_prestasi }}</small>
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<div class="form-check form-switch">
|
|
<input class="form-check-input status-toggle" type="checkbox"
|
|
data-prestasi-id="{{ $item->id }}"
|
|
{{ $item->status ? 'checked' : '' }}>
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<span class="urutan-badge">#{{ $item->urutan }}</span>
|
|
</td>
|
|
<td>
|
|
<div class="action-buttons">
|
|
<button class="btn btn-sm btn-edit"
|
|
onclick="editPrestasi({{ $item->id }})"
|
|
title="Edit Prestasi">
|
|
<i class="fas fa-edit"></i>
|
|
</button>
|
|
<button class="btn btn-sm btn-view"
|
|
onclick="viewPrestasi({{ $item->id }})" title="Lihat Detail">
|
|
<i class="fas fa-eye"></i>
|
|
</button>
|
|
<button class="btn btn-sm btn-delete"
|
|
onclick="deletePrestasi({{ $item->id }})"
|
|
title="Hapus Prestasi">
|
|
<i class="fas fa-trash"></i>
|
|
</button>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
@endforeach
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal Tambah Prestasi -->
|
|
<div class="modal fade" id="tambahPrestasiModal" tabindex="-1" aria-labelledby="tambahPrestasiModalLabel"
|
|
aria-hidden="true">
|
|
<div class="modal-dialog modal-lg">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="tambahPrestasiModalLabel">
|
|
<i class="fas fa-plus me-2"></i>Tambah Prestasi Siswa
|
|
</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<form id="tambahPrestasiForm" enctype="multipart/form-data">
|
|
@csrf
|
|
<div class="modal-body">
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label for="tambahNamaSiswa" class="form-label">Nama Siswa *</label>
|
|
<input type="text" class="form-control" id="tambahNamaSiswa" name="nama_siswa"
|
|
placeholder="Masukkan nama siswa" required>
|
|
<div class="invalid-feedback" id="tambahNamaSiswa_error"></div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="tambahJurusan" class="form-label">Jurusan *</label>
|
|
<select class="form-select" id="tambahJurusan" name="jurusan_id" required>
|
|
<option value="">Pilih Jurusan</option>
|
|
@foreach ($jurusans as $j)
|
|
<option value="{{ $j->id }}">{{ $j->nama_jurusan }}</option>
|
|
@endforeach
|
|
</select>
|
|
<div class="invalid-feedback" id="tambahJurusan_id_error"></div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="tambahNamaPrestasi" class="form-label">Nama Prestasi *</label>
|
|
<input type="text" class="form-control" id="tambahNamaPrestasi"
|
|
name="nama_prestasi" placeholder="Contoh: Juara 1 LKS Tingkat Provinsi" required>
|
|
<div class="invalid-feedback" id="tambahNamaPrestasi_error"></div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label for="tambahPeringkat" class="form-label">Peringkat *</label>
|
|
<input type="text" class="form-control" id="tambahPeringkat"
|
|
name="peringkat" placeholder="Contoh: Juara 1" required>
|
|
<div class="invalid-feedback" id="tambahPeringkat_error"></div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label for="tambahTahunPrestasi" class="form-label">Tahun *</label>
|
|
<input type="number" class="form-control" id="tambahTahunPrestasi"
|
|
name="tahun_prestasi" value="{{ date('Y') }}" min="2000"
|
|
max="{{ date('Y') + 1 }}" required>
|
|
<div class="invalid-feedback" id="tambahTahunPrestasi_error"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label for="tambahFotoPrestasi" class="form-label">Foto Prestasi *</label>
|
|
<div class="prestasi-upload-area">
|
|
<div class="upload-wrapper" id="tambahUploadWrapper">
|
|
<div class="upload-placeholder" id="tambahUploadPreview">
|
|
<i class="fas fa-cloud-upload-alt"></i>
|
|
<p>Klik atau drag foto di sini</p>
|
|
<small>Maksimal 5MB (JPG, PNG, WEBP)</small>
|
|
</div>
|
|
<input type="file" name="foto_prestasi" id="tambahFotoPrestasi"
|
|
class="upload-input" accept="image/*" required>
|
|
</div>
|
|
<div class="image-preview d-none" id="tambahImagePreview">
|
|
<img src="" alt="Preview" id="tambahPreviewImage">
|
|
<button type="button" class="btn-remove-preview"
|
|
onclick="removePreview('tambah')">
|
|
<i class="fas fa-times"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div class="invalid-feedback" id="tambahFotoPrestasi_error"></div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label for="tambahUrutan" class="form-label">Urutan Tampil</label>
|
|
<input type="number" class="form-control" id="tambahUrutan" name="urutan"
|
|
value="{{ $prestasi->max('urutan') + 1 }}" min="0" readonly>
|
|
<div class="invalid-feedback" id="tambahUrutan_error"></div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label class="form-label">Status</label>
|
|
<div class="form-check form-switch">
|
|
<input class="form-check-input" type="checkbox" id="tambahStatus"
|
|
name="status" checked>
|
|
<label class="form-check-label" for="tambahStatus">Aktif</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Batal</button>
|
|
<button type="submit" class="btn btn-primary" id="tambahPrestasiBtn">
|
|
<i class="fas fa-save me-2"></i>Simpan Prestasi
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal Edit Prestasi -->
|
|
<div class="modal fade" id="editPrestasiModal" tabindex="-1" aria-labelledby="editPrestasiModalLabel"
|
|
aria-hidden="true">
|
|
<div class="modal-dialog modal-lg">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="editPrestasiModalLabel">
|
|
<i class="fas fa-edit me-2"></i>Edit Prestasi Siswa
|
|
</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<form id="editPrestasiForm" enctype="multipart/form-data">
|
|
@csrf
|
|
@method('PUT')
|
|
<input type="hidden" id="editPrestasiId" name="id">
|
|
<div class="modal-body">
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label for="editNamaSiswa" class="form-label">Nama Siswa *</label>
|
|
<input type="text" class="form-control" id="editNamaSiswa" name="nama_siswa"
|
|
placeholder="Masukkan nama siswa" required>
|
|
<div class="invalid-feedback" id="editNamaSiswa_error"></div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="editJurusan" class="form-label">Jurusan *</label>
|
|
<select class="form-select" id="editJurusan" name="jurusan_id" required>
|
|
<option value="">Pilih Jurusan</option>
|
|
@foreach ($jurusans as $j)
|
|
<option value="{{ $j->id }}">{{ $j->nama_jurusan }}</option>
|
|
@endforeach
|
|
</select>
|
|
<div class="invalid-feedback" id="editJurusan_id_error"></div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="editNamaPrestasi" class="form-label">Nama Prestasi *</label>
|
|
<input type="text" class="form-control" id="editNamaPrestasi"
|
|
name="nama_prestasi" placeholder="Contoh: Juara 1 LKS Tingkat Provinsi" required>
|
|
<div class="invalid-feedback" id="editNamaPrestasi_error"></div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label for="editPeringkat" class="form-label">Peringkat *</label>
|
|
<input type="text" class="form-control" id="editPeringkat"
|
|
name="peringkat" placeholder="Contoh: Juara 1" required>
|
|
<div class="invalid-feedback" id="editPeringkat_error"></div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label for="editTahunPrestasi" class="form-label">Tahun *</label>
|
|
<input type="number" class="form-control" id="editTahunPrestasi"
|
|
name="tahun_prestasi" min="2000" max="{{ date('Y') + 1 }}" required>
|
|
<div class="invalid-feedback" id="editTahunPrestasi_error"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label class="form-label">Foto Saat Ini</label>
|
|
<div class="current-image-preview">
|
|
<img src="" alt="Current Prestasi" id="editCurrentImage"
|
|
onerror="this.onerror=null;this.src='{{ asset('images/default-img.png') }}'">
|
|
</div>
|
|
<div class="prestasi-upload-area mt-3">
|
|
<div class="upload-wrapper" id="editUploadWrapper">
|
|
<div class="upload-placeholder" id="editUploadPreview">
|
|
<i class="fas fa-camera"></i>
|
|
<p>Klik untuk ubah foto</p>
|
|
</div>
|
|
<input type="file" name="foto_prestasi" id="editFotoPrestasi"
|
|
class="upload-input" accept="image/*">
|
|
</div>
|
|
<div class="image-preview d-none" id="editImagePreview">
|
|
<img src="" alt="Preview" id="editPreviewImage">
|
|
<button type="button" class="btn-remove-preview"
|
|
onclick="removePreview('edit')">
|
|
<i class="fas fa-times"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<small class="text-muted">Biarkan kosong jika tidak ingin mengubah foto</small>
|
|
<div class="invalid-feedback" id="editFotoPrestasi_error"></div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label for="editUrutan" class="form-label">Urutan Tampil</label>
|
|
<input type="number" class="form-control" id="editUrutan" name="urutan"
|
|
min="0" readonly>
|
|
<div class="invalid-feedback" id="editUrutan_error"></div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label class="form-label">Status</label>
|
|
<div class="form-check form-switch">
|
|
<input class="form-check-input" type="checkbox" id="editStatus"
|
|
name="status" value="1">
|
|
<label class="form-check-label" for="editStatus">Aktif</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Batal</button>
|
|
<button type="submit" class="btn btn-primary" id="editPrestasiBtn">
|
|
<i class="fas fa-save me-2"></i>Simpan Perubahan
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal View Prestasi -->
|
|
<div class="modal fade" id="viewPrestasiModal" tabindex="-1" aria-labelledby="viewPrestasiModalLabel"
|
|
aria-hidden="true">
|
|
<div class="modal-dialog modal-lg">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="viewPrestasiModalLabel">
|
|
<i class="fas fa-eye me-2"></i>Detail Prestasi Siswa
|
|
</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="row">
|
|
<div class="col-md-5">
|
|
<div class="view-image-container">
|
|
<img src="" alt="Prestasi Detail" id="viewPrestasiImage"
|
|
class="img-fluid rounded shadow-sm"
|
|
onerror="this.onerror=null;this.src='{{ asset('images/default-img.png') }}'">
|
|
</div>
|
|
</div>
|
|
<div class="col-md-7">
|
|
<div class="view-details">
|
|
<h4 id="viewPrestasiTitle" class="mb-3"></h4>
|
|
<div class="detail-item">
|
|
<label class="detail-label">Nama Siswa:</label>
|
|
<p id="viewPrestasiSiswa" class="detail-content"></p>
|
|
</div>
|
|
<div class="detail-item">
|
|
<label class="detail-label">Jurusan:</label>
|
|
<p id="viewPrestasiJurusan" class="detail-content"></p>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-6">
|
|
<div class="detail-item">
|
|
<label class="detail-label">Peringkat:</label>
|
|
<p id="viewPrestasiPeringkat" class="detail-content"></p>
|
|
</div>
|
|
</div>
|
|
<div class="col-6">
|
|
<div class="detail-item">
|
|
<label class="detail-label">Tahun:</label>
|
|
<p id="viewPrestasiTahun" class="detail-content"></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="detail-item">
|
|
<label class="detail-label">Urutan Tampil:</label>
|
|
<p id="viewPrestasiUrutan" class="detail-content"></p>
|
|
</div>
|
|
<div class="row mt-3">
|
|
<div class="col-6">
|
|
<small class="text-muted d-block">Dibuat pada:</small>
|
|
<small id="viewPrestasiCreated" class="fw-bold"></small>
|
|
</div>
|
|
<div class="col-6">
|
|
<small class="text-muted d-block">Terakhir diupdate:</small>
|
|
<small id="viewPrestasiUpdated" class="fw-bold"></small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Tutup</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
initManajemenPrestasi();
|
|
});
|
|
|
|
function initManajemenPrestasi() {
|
|
initUploadPreview();
|
|
initFormSubmissions();
|
|
initViewToggle();
|
|
initStatusToggles();
|
|
initSearch();
|
|
}
|
|
|
|
function initUploadPreview() {
|
|
const tambahInput = document.getElementById('tambahFotoPrestasi');
|
|
const tambahUploadWrapper = document.getElementById('tambahUploadWrapper');
|
|
const tambahImagePreview = document.getElementById('tambahImagePreview');
|
|
const tambahPreviewImage = document.getElementById('tambahPreviewImage');
|
|
|
|
if (tambahInput) {
|
|
tambahInput.addEventListener('change', function() {
|
|
handleFileSelect(this, tambahUploadWrapper, tambahImagePreview, tambahPreviewImage);
|
|
});
|
|
}
|
|
|
|
const editInput = document.getElementById('editFotoPrestasi');
|
|
const editUploadWrapper = document.getElementById('editUploadWrapper');
|
|
const editImagePreview = document.getElementById('editImagePreview');
|
|
const editPreviewImage = document.getElementById('editPreviewImage');
|
|
|
|
if (editInput) {
|
|
editInput.addEventListener('change', function() {
|
|
handleFileSelect(this, editUploadWrapper, editImagePreview, editPreviewImage);
|
|
});
|
|
}
|
|
}
|
|
|
|
function handleFileSelect(input, wrapper, preview, img) {
|
|
const file = input.files[0];
|
|
if (file) {
|
|
const reader = new FileReader();
|
|
reader.onload = function(e) {
|
|
img.src = e.target.result;
|
|
wrapper.classList.add('d-none');
|
|
preview.classList.remove('d-none');
|
|
}
|
|
reader.readAsDataURL(file);
|
|
}
|
|
}
|
|
|
|
function removePreview(type) {
|
|
const wrapper = document.getElementById(`${type}UploadWrapper`);
|
|
const preview = document.getElementById(`${type}ImagePreview`);
|
|
const input = document.getElementById(`${type}FotoPrestasi`);
|
|
|
|
if (wrapper) wrapper.classList.remove('d-none');
|
|
if (preview) preview.classList.add('d-none');
|
|
if (input) input.value = '';
|
|
}
|
|
|
|
function initViewToggle() {
|
|
const viewBtns = document.querySelectorAll('.view-btn');
|
|
const gridView = document.getElementById('prestasiGridView');
|
|
const listView = document.getElementById('prestasiListView');
|
|
|
|
viewBtns.forEach(btn => {
|
|
btn.addEventListener('click', function() {
|
|
const view = this.getAttribute('data-view');
|
|
viewBtns.forEach(b => b.classList.remove('active'));
|
|
this.classList.add('active');
|
|
|
|
if (view === 'grid') {
|
|
gridView.classList.remove('d-none');
|
|
listView.classList.add('d-none');
|
|
} else {
|
|
gridView.classList.add('d-none');
|
|
listView.classList.remove('d-none');
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
function initStatusToggles() {
|
|
const toggles = document.querySelectorAll('.status-toggle');
|
|
toggles.forEach(toggle => {
|
|
toggle.addEventListener('change', function() {
|
|
const id = this.getAttribute('data-prestasi-id');
|
|
const status = this.checked;
|
|
updateStatus(id, status);
|
|
});
|
|
});
|
|
}
|
|
|
|
function initSearch() {
|
|
const searchInput = document.getElementById('searchInput');
|
|
if (!searchInput) return;
|
|
|
|
searchInput.addEventListener('input', function() {
|
|
const term = this.value.toLowerCase();
|
|
const cards = document.querySelectorAll('.prestasi-card');
|
|
const rows = document.querySelectorAll('tbody tr');
|
|
|
|
cards.forEach(card => {
|
|
const text = card.textContent.toLowerCase();
|
|
card.style.display = text.includes(term) ? '' : 'none';
|
|
});
|
|
|
|
rows.forEach(row => {
|
|
const text = row.textContent.toLowerCase();
|
|
row.style.display = text.includes(term) ? '' : 'none';
|
|
});
|
|
});
|
|
}
|
|
|
|
function initFormSubmissions() {
|
|
const tambahForm = document.getElementById('tambahPrestasiForm');
|
|
if (tambahForm) {
|
|
tambahForm.addEventListener('submit', function(e) {
|
|
e.preventDefault();
|
|
storePrestasi();
|
|
});
|
|
}
|
|
|
|
const editForm = document.getElementById('editPrestasiForm');
|
|
if (editForm) {
|
|
editForm.addEventListener('submit', function(e) {
|
|
e.preventDefault();
|
|
updatePrestasi();
|
|
});
|
|
}
|
|
}
|
|
|
|
function storePrestasi() {
|
|
const form = document.getElementById('tambahPrestasiForm');
|
|
const formData = new FormData(form);
|
|
const submitBtn = document.getElementById('tambahPrestasiBtn');
|
|
clearErrors('tambah');
|
|
submitBtn.classList.add('btn-loading');
|
|
submitBtn.disabled = true;
|
|
|
|
fetch('{{ route('admin.manajemen-prestasi.store') }}', {
|
|
method: 'POST',
|
|
body: formData,
|
|
headers: {
|
|
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
|
|
'Accept': 'application/json'
|
|
}
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
Swal.fire({
|
|
icon: 'success',
|
|
title: 'Berhasil!',
|
|
text: data.message,
|
|
timer: 2000,
|
|
showConfirmButton: false
|
|
}).then(() => {
|
|
window.location.reload();
|
|
});
|
|
} else {
|
|
showErrors(data.errors, 'tambah');
|
|
if (data.message && !data.errors) {
|
|
Swal.fire({
|
|
icon: 'error',
|
|
title: 'Gagal!',
|
|
text: data.message
|
|
});
|
|
}
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
Swal.fire({
|
|
icon: 'error',
|
|
title: 'Error!',
|
|
text: 'Terjadi kesalahan sistem.'
|
|
});
|
|
})
|
|
.finally(() => {
|
|
submitBtn.classList.remove('btn-loading');
|
|
submitBtn.disabled = false;
|
|
});
|
|
}
|
|
|
|
function editPrestasi(prestasiId) {
|
|
const editPrestasiBtn = document.getElementById('editPrestasiBtn');
|
|
editPrestasiBtn.classList.add('btn-loading');
|
|
editPrestasiBtn.disabled = true;
|
|
|
|
fetch(`/admin/manajemen-prestasi/${prestasiId}`, {
|
|
headers: {
|
|
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
|
|
'Accept': 'application/json'
|
|
}
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
const prestasi = data.prestasi;
|
|
document.getElementById('editPrestasiId').value = prestasi.id;
|
|
document.getElementById('editNamaSiswa').value = prestasi.nama_siswa;
|
|
document.getElementById('editJurusan').value = prestasi.jurusan_id;
|
|
document.getElementById('editNamaPrestasi').value = prestasi.nama_prestasi;
|
|
document.getElementById('editPeringkat').value = prestasi.peringkat;
|
|
document.getElementById('editTahunPrestasi').value = prestasi.tahun_prestasi;
|
|
document.getElementById('editUrutan').value = prestasi.urutan;
|
|
document.getElementById('editStatus').checked = prestasi.status;
|
|
document.getElementById('editCurrentImage').src = prestasi.foto_prestasi_url;
|
|
removePreview('edit');
|
|
const modal = new bootstrap.Modal(document.getElementById('editPrestasiModal'));
|
|
modal.show();
|
|
} else {
|
|
Swal.fire({
|
|
icon: 'error',
|
|
title: 'Error!',
|
|
text: 'Gagal memuat data prestasi.'
|
|
});
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
Swal.fire({
|
|
icon: 'error',
|
|
title: 'Error!',
|
|
text: 'Terjadi kesalahan saat memuat data prestasi.'
|
|
});
|
|
})
|
|
.finally(() => {
|
|
editPrestasiBtn.classList.remove('btn-loading');
|
|
editPrestasiBtn.disabled = false;
|
|
});
|
|
}
|
|
|
|
function viewPrestasi(prestasiId) {
|
|
fetch(`/admin/manajemen-prestasi/${prestasiId}`, {
|
|
headers: {
|
|
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
|
|
'Accept': 'application/json'
|
|
}
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
const prestasi = data.prestasi;
|
|
|
|
document.getElementById('viewPrestasiImage').src = prestasi.foto_prestasi_url;
|
|
document.getElementById('viewPrestasiTitle').textContent = prestasi.nama_prestasi;
|
|
document.getElementById('viewPrestasiSiswa').textContent = prestasi.nama_siswa;
|
|
document.getElementById('viewPrestasiJurusan').textContent = prestasi.nama_jurusan;
|
|
document.getElementById('viewPrestasiPeringkat').textContent = prestasi.peringkat;
|
|
document.getElementById('viewPrestasiTahun').textContent = prestasi.tahun_prestasi;
|
|
document.getElementById('viewPrestasiUrutan').textContent = '#' + prestasi.urutan;
|
|
document.getElementById('viewPrestasiCreated').textContent = prestasi.created_at;
|
|
document.getElementById('viewPrestasiUpdated').textContent = prestasi.updated_at;
|
|
|
|
const modal = new bootstrap.Modal(document.getElementById('viewPrestasiModal'));
|
|
modal.show();
|
|
} else {
|
|
Swal.fire({
|
|
icon: 'error',
|
|
title: 'Error!',
|
|
text: 'Gagal memuat data prestasi.'
|
|
});
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
Swal.fire({
|
|
icon: 'error',
|
|
title: 'Error!',
|
|
text: 'Terjadi kesalahan saat memuat data prestasi.'
|
|
});
|
|
});
|
|
}
|
|
|
|
function updatePrestasi() {
|
|
const form = document.getElementById('editPrestasiForm');
|
|
const formData = new FormData(form);
|
|
const id = document.getElementById('editPrestasiId').value;
|
|
const submitBtn = document.getElementById('editPrestasiBtn');
|
|
clearErrors('edit');
|
|
submitBtn.classList.add('btn-loading');
|
|
submitBtn.disabled = true;
|
|
|
|
fetch(`/admin/manajemen-prestasi/${id}`, {
|
|
method: 'POST',
|
|
body: formData,
|
|
headers: {
|
|
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
|
|
'X-HTTP-Method-Override': 'PUT',
|
|
'Accept': 'application/json'
|
|
}
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
Swal.fire({
|
|
icon: 'success',
|
|
title: 'Berhasil!',
|
|
text: data.message,
|
|
timer: 2000,
|
|
showConfirmButton: false
|
|
}).then(() => {
|
|
window.location.reload();
|
|
});
|
|
} else {
|
|
showErrors(data.errors, 'edit');
|
|
if (data.message && !data.errors) {
|
|
Swal.fire({
|
|
icon: 'error',
|
|
title: 'Gagal!',
|
|
text: data.message
|
|
});
|
|
}
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
Swal.fire({
|
|
icon: 'error',
|
|
title: 'Error!',
|
|
text: 'Terjadi kesalahan saat memperbarui prestasi.'
|
|
});
|
|
})
|
|
.finally(() => {
|
|
submitBtn.classList.remove('btn-loading');
|
|
submitBtn.disabled = false;
|
|
});
|
|
}
|
|
|
|
function updateStatus(id, status) {
|
|
fetch(`/admin/manajemen-prestasi/${id}/status`, {
|
|
method: 'PATCH',
|
|
body: JSON.stringify({
|
|
status: status
|
|
}),
|
|
headers: {
|
|
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
|
|
'Content-Type': 'application/json',
|
|
'Accept': 'application/json'
|
|
}
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (!data.success) {
|
|
Swal.fire({
|
|
icon: 'error',
|
|
title: 'Gagal!',
|
|
text: data.message
|
|
});
|
|
window.location.reload();
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
window.location.reload();
|
|
});
|
|
}
|
|
|
|
function deletePrestasi(id) {
|
|
Swal.fire({
|
|
title: 'Hapus Prestasi?',
|
|
text: "Data yang dihapus tidak dapat dikembalikan!",
|
|
icon: 'warning',
|
|
showCancelButton: true,
|
|
confirmButtonColor: '#d33',
|
|
cancelButtonColor: '#3085d6',
|
|
confirmButtonText: 'Ya, Hapus!',
|
|
cancelButtonText: 'Batal'
|
|
}).then((result) => {
|
|
if (result.isConfirmed) {
|
|
fetch(`/admin/manajemen-prestasi/${id}`, {
|
|
method: 'DELETE',
|
|
headers: {
|
|
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute(
|
|
'content'),
|
|
'Accept': 'application/json'
|
|
}
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
Swal.fire({
|
|
icon: 'success',
|
|
title: 'Berhasil!',
|
|
text: data.message,
|
|
timer: 2000,
|
|
showConfirmButton: false
|
|
}).then(() => {
|
|
window.location.reload();
|
|
});
|
|
} else {
|
|
Swal.fire({
|
|
icon: 'error',
|
|
title: 'Gagal!',
|
|
text: data.message
|
|
});
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
function showErrors(errors, type) {
|
|
for (const key in errors) {
|
|
// Map validation fields to element IDs
|
|
let field = key;
|
|
if (key === 'jurusan_id') field = 'jurusan';
|
|
if (key === 'foto_prestasi') field = 'fotoPrestasi';
|
|
if (key === 'nama_siswa') field = 'namaSiswa';
|
|
if (key === 'nama_prestasi') field = 'namaPrestasi';
|
|
if (key === 'tahun_prestasi') field = 'tahunPrestasi';
|
|
|
|
const id = type + field.charAt(0).toUpperCase() + field.slice(1);
|
|
const input = document.getElementById(id);
|
|
const errorEl = document.getElementById(id + '_error');
|
|
|
|
if (input) input.classList.add('is-invalid');
|
|
if (errorEl) errorEl.textContent = errors[key][0];
|
|
}
|
|
}
|
|
|
|
function clearErrors(type) {
|
|
const inputs = document.querySelectorAll(
|
|
`#${type}PrestasiForm .form-control, #${type}PrestasiForm .form-select`);
|
|
const errors = document.querySelectorAll(`#${type}PrestasiForm .invalid-feedback`);
|
|
|
|
inputs.forEach(input => input.classList.remove('is-invalid'));
|
|
errors.forEach(error => error.textContent = '');
|
|
}
|
|
|
|
window.editPrestasi = editPrestasi;
|
|
window.viewPrestasi = viewPrestasi;
|
|
window.deletePrestasi = deletePrestasi;
|
|
window.removePreview = removePreview;
|
|
</script>
|
|
@endsection
|