partial update create kpi and progress bar
This commit is contained in:
252
resources/views/kpi/targets/create.blade.php
Normal file
252
resources/views/kpi/targets/create.blade.php
Normal file
@@ -0,0 +1,252 @@
|
||||
@extends('layouts.backapp')
|
||||
|
||||
@section('title', 'Tambah Target KPI')
|
||||
|
||||
@section('styles')
|
||||
<style>
|
||||
.select2-container .select2-selection {
|
||||
height: calc(1.5em + 0.75rem + 2px);
|
||||
padding: 0.375rem 0.75rem;
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
color: #495057;
|
||||
background-color: #fff;
|
||||
border: 1px solid #ced4da;
|
||||
border-radius: 0.25rem;
|
||||
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
|
||||
}
|
||||
|
||||
.select2-container.select2-container--focus .select2-selection {
|
||||
border-color: #80bdff;
|
||||
outline: 0;
|
||||
box-shadow: 0 0 0 0.2rem rgba(197, 214, 233, 0.25);
|
||||
}
|
||||
|
||||
.select2-container .select2-selection--single .select2-selection__rendered {
|
||||
padding-left: 0;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.select2-container .select2-selection--single .select2-selection__arrow {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.select2-results__option--highlighted[aria-selected] {
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Limit Select2 dropdown height */
|
||||
.select2-results__options {
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/* Style for Select2 results */
|
||||
.select2-results__option {
|
||||
padding: 8px 12px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.select2-results__option:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
/* Improve Select2 search box */
|
||||
.select2-search--dropdown .select2-search__field {
|
||||
padding: 8px 12px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
<div class="kt-content kt-grid__item kt-grid__item--fluid kt-grid kt-grid--hor" id="kt_content">
|
||||
<div class="kt-container kt-container--fluid kt-grid__item kt-grid__item--fluid">
|
||||
<div class="kt-portlet kt-portlet--mobile">
|
||||
<div class="kt-portlet__head kt-portlet__head--lg">
|
||||
<div class="kt-portlet__head-label">
|
||||
<h3 class="kt-portlet__head-title">
|
||||
Tambah Target KPI
|
||||
</h3>
|
||||
</div>
|
||||
<div class="kt-portlet__head-toolbar">
|
||||
<div class="kt-portlet__head-actions">
|
||||
<a href="{{ route('kpi.targets.index') }}" class="btn btn-secondary">
|
||||
<i class="fas fa-arrow-left"></i> Kembali
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="kt-portlet__body">
|
||||
<form id="kpi-form" method="POST" action="{{ route('kpi.targets.store') }}">
|
||||
@csrf
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="user_id" class="form-control-label">Mekanik <span class="text-danger">*</span></label>
|
||||
<select name="user_id" id="user_id" class="form-control select2" required>
|
||||
<option value="">Pilih Mekanik</option>
|
||||
@foreach($mechanics as $mechanic)
|
||||
<option value="{{ $mechanic->id }}" {{ old('user_id') == $mechanic->id ? 'selected' : '' }}>
|
||||
{{ $mechanic->name }} ({{ $mechanic->dealer->name ?? 'N/A' }})
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
@if($mechanics->isEmpty())
|
||||
<div class="alert alert-warning mt-2">
|
||||
<i class="fas fa-exclamation-triangle"></i>
|
||||
Tidak ada mekanik yang ditemukan. Pastikan ada user dengan role "mechanic" di sistem.
|
||||
</div>
|
||||
@else
|
||||
<small class="form-text text-muted">
|
||||
Ditemukan {{ $mechanics->count() }} mekanik.
|
||||
@if($mechanics->count() >= 50)
|
||||
Menampilkan 50 mekanik pertama. Gunakan pencarian untuk menemukan mekanik tertentu.
|
||||
@endif
|
||||
</small>
|
||||
@endif
|
||||
@error('user_id')
|
||||
<span class="text-danger">{{ $message }}</span>
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="target_value" class="form-control-label">Target Nilai <span class="text-danger">*</span></label>
|
||||
<input type="number" name="target_value" id="target_value" class="form-control"
|
||||
value="{{ old('target_value') }}" min="1" required>
|
||||
@error('target_value')
|
||||
<span class="text-danger">{{ $message }}</span>
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="form-group">
|
||||
<label for="description" class="form-control-label">Deskripsi</label>
|
||||
<textarea name="description" id="description" class="form-control" rows="3"
|
||||
placeholder="Deskripsi target (opsional)">{{ old('description') }}</textarea>
|
||||
@error('description')
|
||||
<span class="text-danger">{{ $message }}</span>
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input type="checkbox" name="is_active" id="is_active" class="custom-control-input"
|
||||
value="1" {{ old('is_active', true) ? 'checked' : '' }}>
|
||||
<label class="custom-control-label" for="is_active">
|
||||
Target Aktif
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="fas fa-save"></i> Simpan Target
|
||||
</button>
|
||||
<a href="{{ route('kpi.targets.index') }}" class="btn btn-secondary">Kembali</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@push('javascripts')
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Initialize Select2 with fallback
|
||||
try {
|
||||
// Initialize Select2 for mechanics with search limit
|
||||
$('#user_id').select2({
|
||||
theme: 'bootstrap4',
|
||||
width: '100%',
|
||||
placeholder: 'Pilih Mekanik',
|
||||
allowClear: true,
|
||||
minimumInputLength: 1,
|
||||
maximumInputLength: 50,
|
||||
maximumResultsForSearch: 10,
|
||||
language: {
|
||||
inputTooShort: function() {
|
||||
return "Masukkan minimal 1 karakter untuk mencari";
|
||||
},
|
||||
inputTooLong: function() {
|
||||
return "Maksimal 50 karakter";
|
||||
},
|
||||
noResults: function() {
|
||||
return "Tidak ada hasil ditemukan";
|
||||
},
|
||||
searching: function() {
|
||||
return "Mencari...";
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
} catch (error) {
|
||||
console.log('Select2 not available, using regular select');
|
||||
// Fallback: ensure regular select works
|
||||
$('.select2').removeClass('select2').addClass('form-control');
|
||||
}
|
||||
|
||||
// Form validation
|
||||
$('#kpi-form').on('submit', function(e) {
|
||||
var isValid = true;
|
||||
var errors = [];
|
||||
|
||||
// Clear previous errors
|
||||
$('.text-danger').remove();
|
||||
|
||||
// Validate required fields
|
||||
if (!$('#user_id').val()) {
|
||||
errors.push('Mekanik harus dipilih');
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
if (!$('#target_value').val() || $('#target_value').val() < 1) {
|
||||
errors.push('Target nilai harus diisi dan minimal 1');
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!isValid) {
|
||||
e.preventDefault();
|
||||
if (typeof Swal !== 'undefined') {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Validasi Gagal',
|
||||
html: errors.join('<br>'),
|
||||
confirmButtonText: 'OK'
|
||||
});
|
||||
} else {
|
||||
alert('Validasi Gagal:\n' + errors.join('\n'));
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
263
resources/views/kpi/targets/edit.blade.php
Normal file
263
resources/views/kpi/targets/edit.blade.php
Normal file
@@ -0,0 +1,263 @@
|
||||
@extends('layouts.backapp')
|
||||
|
||||
@section('title', 'Edit Target KPI')
|
||||
|
||||
@section('styles')
|
||||
<style>
|
||||
.select2-container .select2-selection {
|
||||
height: calc(1.5em + 0.75rem + 2px);
|
||||
padding: 0.375rem 0.75rem;
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
color: #495057;
|
||||
background-color: #fff;
|
||||
border: 1px solid #ced4da;
|
||||
border-radius: 0.25rem;
|
||||
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
|
||||
}
|
||||
|
||||
.select2-container.select2-container--focus .select2-selection {
|
||||
border-color: #80bdff;
|
||||
outline: 0;
|
||||
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
|
||||
}
|
||||
|
||||
.select2-container .select2-selection--single .select2-selection__rendered {
|
||||
padding-left: 0;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.select2-container .select2-selection--single .select2-selection__arrow {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.select2-results__option--highlighted[aria-selected] {
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Ensure Select2 is visible */
|
||||
.select2-container {
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.select2-dropdown {
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
/* Fix Select2 width */
|
||||
.select2-container--default .select2-selection--single {
|
||||
height: calc(1.5em + 0.75rem + 2px);
|
||||
padding: 0.375rem 0.75rem;
|
||||
}
|
||||
|
||||
/* Limit Select2 dropdown height */
|
||||
.select2-results__options {
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/* Style for Select2 results */
|
||||
.select2-results__option {
|
||||
padding: 8px 12px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.select2-results__option:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
/* Improve Select2 search box */
|
||||
.select2-search--dropdown .select2-search__field {
|
||||
padding: 8px 12px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
<div class="kt-content kt-grid__item kt-grid__item--fluid kt-grid kt-grid--hor" id="kt_content">
|
||||
<div class="kt-container kt-container--fluid kt-grid__item kt-grid__item--fluid">
|
||||
<div class="kt-portlet kt-portlet--mobile">
|
||||
<div class="kt-portlet__head kt-portlet__head--lg">
|
||||
<div class="kt-portlet__head-label">
|
||||
<h3 class="kt-portlet__head-title">
|
||||
Edit Target KPI
|
||||
</h3>
|
||||
</div>
|
||||
<div class="kt-portlet__head-toolbar">
|
||||
<div class="kt-portlet__head-actions">
|
||||
<a href="{{ route('kpi.targets.index') }}" class="btn btn-secondary">
|
||||
<i class="fas fa-arrow-left"></i> Kembali
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="kt-portlet__body">
|
||||
|
||||
<form id="kpi-form" method="POST" action="{{ route('kpi.targets.update', $target->id) }}">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="user_id" class="form-control-label">Mekanik <span class="text-danger">*</span></label>
|
||||
<select name="user_id" id="user_id" class="form-control select2" required>
|
||||
<option value="">Pilih Mekanik</option>
|
||||
@foreach($mechanics as $mechanic)
|
||||
@php
|
||||
$isSelected = old('user_id', $target->user_id) == $mechanic->id;
|
||||
@endphp
|
||||
<option value="{{ $mechanic->id }}"
|
||||
{{ $isSelected ? 'selected' : '' }}>
|
||||
{{ $mechanic->name }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
|
||||
@error('user_id')
|
||||
<span class="text-danger">{{ $message }}</span>
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="target_value" class="form-control-label">Target Nilai <span class="text-danger">*</span></label>
|
||||
<input type="number" name="target_value" id="target_value" class="form-control"
|
||||
value="{{ old('target_value', $target->target_value) }}" min="1" required>
|
||||
@error('target_value')
|
||||
<span class="text-danger">{{ $message }}</span>
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="form-group">
|
||||
<label for="description" class="form-control-label">Deskripsi</label>
|
||||
<textarea name="description" id="description" class="form-control" rows="3"
|
||||
placeholder="Deskripsi target (opsional)">{{ old('description', $target->description) }}</textarea>
|
||||
@error('description')
|
||||
<span class="text-danger">{{ $message }}</span>
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input type="checkbox" name="is_active" id="is_active" class="custom-control-input"
|
||||
value="1" {{ old('is_active', $target->is_active) ? 'checked' : '' }}>
|
||||
<label class="custom-control-label" for="is_active">
|
||||
Target Aktif
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<i class="fas fa-save"></i> Update Target
|
||||
</button>
|
||||
<a href="{{ route('kpi.targets.index') }}" class="btn btn-secondary">Kembali</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@push('javascripts')
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Initialize Select2 with fallback and delay
|
||||
setTimeout(function() {
|
||||
try {
|
||||
// Initialize Select2 for mechanics with search limit
|
||||
$('#user_id').select2({
|
||||
theme: 'bootstrap4',
|
||||
width: '100%',
|
||||
placeholder: 'Pilih Mekanik',
|
||||
allowClear: true,
|
||||
minimumInputLength: 1,
|
||||
maximumInputLength: 50,
|
||||
maximumResultsForSearch: 10,
|
||||
language: {
|
||||
inputTooShort: function() {
|
||||
return "Masukkan minimal 1 karakter untuk mencari";
|
||||
},
|
||||
inputTooLong: function() {
|
||||
return "Maksimal 50 karakter";
|
||||
},
|
||||
noResults: function() {
|
||||
return "Tidak ada hasil ditemukan";
|
||||
},
|
||||
searching: function() {
|
||||
return "Mencari...";
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
} catch (error) {
|
||||
console.log('Select2 not available, using regular select');
|
||||
// Fallback: ensure regular select works
|
||||
$('.select2').removeClass('select2').addClass('form-control');
|
||||
}
|
||||
}, 100);
|
||||
|
||||
// Form validation
|
||||
$('#kpi-form').on('submit', function(e) {
|
||||
var isValid = true;
|
||||
var errors = [];
|
||||
|
||||
// Clear previous errors
|
||||
$('.text-danger').remove();
|
||||
|
||||
// Validate required fields
|
||||
if (!$('#user_id').val()) {
|
||||
errors.push('Mekanik harus dipilih');
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
if (!$('#target_value').val() || $('#target_value').val() < 1) {
|
||||
errors.push('Target nilai harus diisi dan minimal 1');
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!isValid) {
|
||||
e.preventDefault();
|
||||
if (typeof Swal !== 'undefined') {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Validasi Gagal',
|
||||
html: errors.join('<br>'),
|
||||
confirmButtonText: 'OK'
|
||||
});
|
||||
} else {
|
||||
alert('Validasi Gagal:\n' + errors.join('\n'));
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
212
resources/views/kpi/targets/index.blade.php
Normal file
212
resources/views/kpi/targets/index.blade.php
Normal file
@@ -0,0 +1,212 @@
|
||||
@extends('layouts.backapp')
|
||||
|
||||
@section('content')
|
||||
<div class="kt-content kt-grid__item kt-grid__item--fluid kt-grid kt-grid--hor" id="kt_content">
|
||||
<div class="kt-container kt-container--fluid kt-grid__item kt-grid__item--fluid">
|
||||
<div class="kt-portlet kt-portlet--mobile">
|
||||
<div class="kt-portlet__head kt-portlet__head--lg">
|
||||
<div class="kt-portlet__head-label">
|
||||
<h3 class="kt-portlet__head-title">
|
||||
Manajemen Target KPI
|
||||
</h3>
|
||||
</div>
|
||||
<div class="kt-portlet__head-toolbar">
|
||||
<div class="kt-portlet__head-actions">
|
||||
<a href="{{ route('kpi.targets.create') }}" class="btn btn-primary">
|
||||
<i class="fas fa-plus"></i> Tambah Target
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="kt-portlet__body">
|
||||
@if(session('success'))
|
||||
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
||||
{{ session('success') }}
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if(session('error'))
|
||||
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
||||
{{ session('error') }}
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-bordered" id="kpiTargetsTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>No</th>
|
||||
<th>Mekanik</th>
|
||||
<th>Target</th>
|
||||
<th>Status</th>
|
||||
<th>Aksi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse($targets as $target)
|
||||
<tr>
|
||||
<td>{{ $loop->iteration }}</td>
|
||||
<td>{{ $target->user->name }}</td>
|
||||
<td>{{ number_format($target->target_value) }}</td>
|
||||
<td>
|
||||
@if($target->is_active)
|
||||
<span class="badge badge-success">Aktif</span>
|
||||
@else
|
||||
<span class="badge badge-secondary">Nonaktif</span>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-group" role="group">
|
||||
<a href="{{ route('kpi.targets.show', $target->id) }}"
|
||||
class="btn btn-sm btn-info" title="Detail">
|
||||
<i class="fas fa-eye"></i>
|
||||
</a>
|
||||
<a href="{{ route('kpi.targets.edit', $target->id) }}"
|
||||
class="btn btn-sm btn-warning" title="Edit">
|
||||
<i class="fas fa-edit"></i>
|
||||
</a>
|
||||
<button type="button"
|
||||
class="btn btn-sm btn-{{ $target->is_active ? 'warning' : 'success' }}"
|
||||
onclick="toggleStatus({{ $target->id }})"
|
||||
title="{{ $target->is_active ? 'Nonaktifkan' : 'Aktifkan' }}">
|
||||
<i class="fas fa-{{ $target->is_active ? 'pause' : 'play' }}"></i>
|
||||
</button>
|
||||
<form action="{{ route('kpi.targets.destroy', $target->id) }}"
|
||||
method="POST"
|
||||
style="display: inline;"
|
||||
onsubmit="return confirm('Yakin ingin menghapus target ini?')">
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button type="submit" class="btn btn-sm btn-danger" title="Hapus">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="5" class="text-center">Tidak ada data target KPI</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@if($targets->hasPages())
|
||||
<div class="d-flex justify-content-center">
|
||||
{{ $targets->links() }}
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Filter Modal -->
|
||||
<div class="modal fade" id="filterModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Filter Target KPI</h5>
|
||||
<button type="button" class="close" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="{{ route('kpi.targets.index') }}" method="GET">
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label>Mekanik</label>
|
||||
<select name="user_id" class="form-control">
|
||||
<option value="">Semua Mekanik</option>
|
||||
@foreach($mechanics as $mechanic)
|
||||
<option value="{{ $mechanic->id }}"
|
||||
{{ request('user_id') == $mechanic->id ? 'selected' : '' }}>
|
||||
{{ $mechanic->name }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Status</label>
|
||||
<select name="is_active" class="form-control">
|
||||
<option value="">Semua Status</option>
|
||||
<option value="1" {{ request('is_active') == '1' ? 'selected' : '' }}>Aktif</option>
|
||||
<option value="0" {{ request('is_active') == '0' ? 'selected' : '' }}>Nonaktif</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Batal</button>
|
||||
<button type="submit" class="btn btn-primary">Filter</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@push('javascripts')
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Initialize DataTable
|
||||
$('#kpiTargetsTable').DataTable({
|
||||
"pageLength": 25,
|
||||
"order": [[0, "asc"]],
|
||||
"language": {
|
||||
"url": "//cdn.datatables.net/plug-ins/1.10.24/i18n/Indonesian.json"
|
||||
}
|
||||
});
|
||||
|
||||
// Auto hide alerts after 5 seconds
|
||||
setTimeout(function() {
|
||||
$('.alert').fadeOut('slow');
|
||||
}, 5000);
|
||||
});
|
||||
|
||||
function toggleStatus(targetId) {
|
||||
if (confirm('Yakin ingin mengubah status target ini?')) {
|
||||
$.ajax({
|
||||
url: '{{ route("kpi.targets.toggle-status", ":id") }}'.replace(':id', targetId),
|
||||
type: 'POST',
|
||||
data: {
|
||||
_token: '{{ csrf_token() }}'
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Berhasil',
|
||||
text: response.message,
|
||||
timer: 2000,
|
||||
showConfirmButton: false
|
||||
}).then(function() {
|
||||
location.reload();
|
||||
});
|
||||
} else {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Error',
|
||||
text: response.message
|
||||
});
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Error',
|
||||
text: 'Terjadi kesalahan saat mengubah status'
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@endpush
|
||||
193
resources/views/kpi/targets/show.blade.php
Normal file
193
resources/views/kpi/targets/show.blade.php
Normal file
@@ -0,0 +1,193 @@
|
||||
@extends('layouts.backapp')
|
||||
|
||||
@section('content')
|
||||
<div class="kt-content kt-grid__item kt-grid__item--fluid kt-grid kt-grid--hor" id="kt_content">
|
||||
<div class="kt-container kt-container--fluid kt-grid__item kt-grid__item--fluid">
|
||||
<div class="kt-portlet kt-portlet--mobile">
|
||||
<div class="kt-portlet__head kt-portlet__head--lg">
|
||||
<div class="kt-portlet__head-label">
|
||||
<h3 class="kt-portlet__head-title">
|
||||
Detail Target KPI
|
||||
</h3>
|
||||
</div>
|
||||
<div class="kt-portlet__head-toolbar">
|
||||
<div class="kt-portlet__head-actions">
|
||||
<a href="{{ route('kpi.targets.edit', $target->id) }}" class="btn btn-warning">
|
||||
<i class="fas fa-edit"></i> Edit
|
||||
</a>
|
||||
<a href="{{ route('kpi.targets.index') }}" class="btn btn-secondary">
|
||||
<i class="fas fa-arrow-left"></i> Kembali
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="kt-portlet__body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="150"><strong>Mekanik</strong></td>
|
||||
<td>: {{ $target->user->name }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Email</strong></td>
|
||||
<td>: {{ $target->user->email }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Dealer</strong></td>
|
||||
<td>: {{ $target->user->dealer->name ?? 'N/A' }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Target Nilai</strong></td>
|
||||
<td>: {{ number_format($target->target_value) }} Pekerjaan</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Status</strong></td>
|
||||
<td>:
|
||||
@if($target->is_active)
|
||||
<span class="badge badge-success">Aktif</span>
|
||||
@else
|
||||
<span class="badge badge-secondary">Nonaktif</span>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<td width="150"><strong>Jenis Target</strong></td>
|
||||
<td>: <span class="badge badge-info">Target Permanen</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Berlaku Sejak</strong></td>
|
||||
<td>: {{ $target->created_at->format('d/m/Y') }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Dibuat</strong></td>
|
||||
<td>: {{ $target->created_at->format('d/m/Y H:i') }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Terakhir Update</strong></td>
|
||||
<td>: {{ $target->updated_at->format('d/m/Y H:i') }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Total Pencapaian</strong></td>
|
||||
<td>: {{ $target->achievements->count() }} Bulan</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if($target->description)
|
||||
<div class="row mt-3">
|
||||
<div class="col-12">
|
||||
<h6><strong>Deskripsi:</strong></h6>
|
||||
<p class="text-muted">{{ $target->description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<!-- Achievement History -->
|
||||
<div class="row mt-4">
|
||||
<div class="col-12">
|
||||
<h5><i class="fas fa-chart-line"></i> Riwayat Pencapaian Bulanan</h5>
|
||||
@if($target->achievements->count() > 0)
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Periode</th>
|
||||
<th>Target</th>
|
||||
<th>Aktual</th>
|
||||
<th>Pencapaian</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($target->achievements->sortByDesc('year')->sortByDesc('month') as $achievement)
|
||||
<tr>
|
||||
<td>{{ $achievement->getPeriodDisplayName() }}</td>
|
||||
<td>{{ number_format($achievement->target_value) }}</td>
|
||||
<td>{{ number_format($achievement->actual_value) }}</td>
|
||||
<td>{{ number_format($achievement->achievement_percentage, 1) }}%</td>
|
||||
<td>
|
||||
<span class="badge badge-{{ $achievement->status_color }}">
|
||||
@switch($achievement->status)
|
||||
@case('exceeded')
|
||||
Melebihi Target
|
||||
@break
|
||||
@case('good')
|
||||
Baik
|
||||
@break
|
||||
@case('fair')
|
||||
Cukup
|
||||
@break
|
||||
@case('poor')
|
||||
Kurang
|
||||
@break
|
||||
@default
|
||||
Tidak Diketahui
|
||||
@endswitch
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@else
|
||||
<div class="alert alert-info">
|
||||
<i class="fas fa-info-circle"></i> Belum ada data pencapaian untuk target ini.
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Summary Statistics -->
|
||||
@if($target->achievements->count() > 0)
|
||||
<div class="row mt-4">
|
||||
<div class="col-12">
|
||||
<h5><i class="fas fa-chart-bar"></i> Statistik Pencapaian</h5>
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<div class="card bg-primary text-white">
|
||||
<div class="card-body text-center">
|
||||
<h4>{{ $target->achievements->count() }}</h4>
|
||||
<small>Total Pencapaian</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card bg-success text-white">
|
||||
<div class="card-body text-center">
|
||||
<h4>{{ $target->achievements->where('achievement_percentage', '>=', 100)->count() }}</h4>
|
||||
<small>Target Tercapai</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card bg-info text-white">
|
||||
<div class="card-body text-center">
|
||||
<h4>{{ number_format($target->achievements->avg('achievement_percentage'), 1) }}%</h4>
|
||||
<small>Rata-rata Pencapaian</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card bg-warning text-white">
|
||||
<div class="card-body text-center">
|
||||
<h4>{{ number_format($target->achievements->max('achievement_percentage'), 1) }}%</h4>
|
||||
<small>Pencapaian Tertinggi</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
Reference in New Issue
Block a user