partial update transaction work with stock product
This commit is contained in:
531
resources/views/back/master/work-products.blade.php
Normal file
531
resources/views/back/master/work-products.blade.php
Normal file
@@ -0,0 +1,531 @@
|
||||
@extends('layouts.backapp')
|
||||
|
||||
@section('content')
|
||||
|
||||
<div class="kt-portlet kt-portlet--mobile" id="kt_blockui_datatable">
|
||||
<div class="kt-portlet__head kt-portlet__head--lg">
|
||||
<div class="kt-portlet__head-label">
|
||||
<span class="kt-portlet__head-icon">
|
||||
<i class="kt-font-brand flaticon2-box"></i>
|
||||
</span>
|
||||
<h3 class="kt-portlet__head-title">
|
||||
Kelola Produk untuk Pekerjaan: {{ $work->name }}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="kt-portlet__head-toolbar">
|
||||
<div class="kt-portlet__head-wrapper">
|
||||
<div class="kt-portlet__head-actions">
|
||||
<a href="{{ route('work.index') }}" class="btn btn-secondary btn-sm mr-2">
|
||||
<i class="fa fa-arrow-left"></i> Kembali
|
||||
</a>
|
||||
<button type="button" class="btn btn-info btn-sm mr-2" id="showStockPrediction">
|
||||
<i class="fa fa-chart-line"></i> Prediksi Stock
|
||||
</button>
|
||||
@can('create', $menus['work.index'] ?? null)
|
||||
<button type="button" class="btn btn-bold btn-label-brand btn-sm" id="addWorkProduct">
|
||||
<i class="fa fa-plus"></i> Tambah Produk
|
||||
</button>
|
||||
@endcan
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="kt-portlet__body">
|
||||
<!-- Work Info -->
|
||||
<div class="card mb-4">
|
||||
<div class="card-header bg-primary text-white">
|
||||
<h5 class="card-title mb-0">
|
||||
<i class="fa fa-info-circle mr-2"></i>
|
||||
Informasi Pekerjaan
|
||||
</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="work-info-item mb-3">
|
||||
<label class="font-weight-bold text-muted mb-1">Nama Pekerjaan:</label>
|
||||
<div class="work-info-value">{{ $work->name }}</div>
|
||||
</div>
|
||||
<div class="work-info-item mb-3">
|
||||
<label class="font-weight-bold text-muted mb-1">Short Name:</label>
|
||||
<div class="work-info-value">{{ $work->shortname }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="work-info-item mb-3">
|
||||
<label class="font-weight-bold text-muted mb-1">Kategori:</label>
|
||||
<div class="work-info-value">
|
||||
@if($work->category)
|
||||
<span class="badge badge-info">{{ $work->category->name }}</span>
|
||||
@else
|
||||
<span class="text-muted">-</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="work-info-item mb-3">
|
||||
<label class="font-weight-bold text-muted mb-1">Deskripsi:</label>
|
||||
<div class="work-info-value">
|
||||
@if($work->desc)
|
||||
{{ $work->desc }}
|
||||
@else
|
||||
<span class="text-muted">Tidak ada deskripsi</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<!--begin: Datatable -->
|
||||
<table class="table table-striped table-bordered table-hover table-checkable" id="workProductsTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Kode Produk</th>
|
||||
<th>Nama Produk</th>
|
||||
<th>Kategori</th>
|
||||
<th>Satuan</th>
|
||||
<th>Qty Diperlukan</th>
|
||||
<th>Catatan</th>
|
||||
<th>Aksi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
<!--end: Datatable -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--begin::Modal-->
|
||||
<div class="modal fade" id="workProductModal" tabindex="-1" role="dialog" aria-labelledby="workProductModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered" role="document">
|
||||
<form id="workProductForm" class="kt-form">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="modalHeading">
|
||||
<i class="fa fa-plus mr-2"></i>
|
||||
Tambah Produk
|
||||
</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<input type="hidden" id="work_id" name="work_id" value="{{ $work->id }}">
|
||||
<input type="hidden" id="work_product_id" name="work_product_id">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<div class="form-group">
|
||||
<label for="product_id" class="font-weight-bold">
|
||||
<i class="fa fa-box mr-1"></i>
|
||||
Pilih Produk <span class="text-danger">*</span>
|
||||
</label>
|
||||
<select name="product_id" id="product_id" class="form-control select2" required>
|
||||
<option value="">-- Pilih Produk --</option>
|
||||
@foreach ($products as $product)
|
||||
<option value="{{ $product->id }}" data-code="{{ $product->code }}" data-unit="{{ $product->unit }}">
|
||||
{{ $product->code }} - {{ $product->name }} ({{ $product->unit }})
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="form-group">
|
||||
<label for="quantity_required" class="font-weight-bold">
|
||||
<i class="fa fa-calculator mr-1"></i>
|
||||
Jumlah Diperlukan <span class="text-danger">*</span>
|
||||
</label>
|
||||
<input type="number" class="form-control" id="quantity_required" name="quantity_required"
|
||||
placeholder="0.00" step="0.01" min="0.01" required>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="notes" class="font-weight-bold">
|
||||
<i class="fa fa-sticky-note mr-1"></i>
|
||||
Catatan
|
||||
</label>
|
||||
<textarea name="notes" id="notes" rows="3" class="form-control"
|
||||
placeholder="Catatan atau keterangan tambahan (opsional)"></textarea>
|
||||
</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" id="saveBtn">
|
||||
Simpan
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<!--end::Modal-->
|
||||
|
||||
<!-- Stock Prediction Modal -->
|
||||
<div class="modal fade" id="stockPredictionModal" tabindex="-1" role="dialog" aria-labelledby="stockPredictionModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Prediksi Penggunaan Stock</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label for="prediction_quantity">Jumlah Pekerjaan:</label>
|
||||
<div class="input-group">
|
||||
<input type="number" class="form-control" id="prediction_quantity" value="1" min="1">
|
||||
<div class="input-group-append">
|
||||
<button type="button" class="btn btn-primary" id="applyPrediction">
|
||||
Terapkan
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="stockPredictionContent">
|
||||
<!-- Content will be loaded via AJAX -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Tutup</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Hidden inputs for JavaScript -->
|
||||
<input type="hidden" name="work_id" value="{{ $work->id }}">
|
||||
<input type="hidden" name="index_url" value="{{ route('work.products.index', $work->id) }}">
|
||||
<input type="hidden" name="store_url" value="{{ route('work.products.store', $work->id) }}">
|
||||
<input type="hidden" name="stock_prediction_url" value="{{ route('work.products.stock-prediction', $work->id) }}">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||||
<input type="hidden" name="base_url" value="{{ route('work.products.index', $work->id) }}">
|
||||
<input type="hidden" name="show_url_template" value="{{ route('work.products.show', ['work' => $work->id, 'workProduct' => ':id']) }}">
|
||||
<input type="hidden" name="update_url_template" value="{{ route('work.products.update', ['work' => $work->id, 'workProduct' => ':id']) }}">
|
||||
<input type="hidden" name="destroy_url_template" value="{{ route('work.products.destroy', ['work' => $work->id, 'workProduct' => ':id']) }}">
|
||||
|
||||
@endsection
|
||||
|
||||
@section('javascripts')
|
||||
<script src="{{ url('js/pages/back/master/work-products.js') }}" type="text/javascript"></script>
|
||||
@endsection
|
||||
|
||||
@section('styles')
|
||||
<style>
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
.modal .close {
|
||||
cursor: pointer;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.modal .close:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.input-group-append .btn {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
/* Action button flex layout */
|
||||
.d-flex.flex-row.gap-1 {
|
||||
display: flex !important;
|
||||
flex-direction: row !important;
|
||||
gap: 0.25rem !important;
|
||||
align-items: center;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
.d-flex.flex-row.gap-1 .btn {
|
||||
white-space: nowrap;
|
||||
margin: 0;
|
||||
padding: 0.375rem 0.75rem;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.5;
|
||||
border-radius: 0.2rem;
|
||||
}
|
||||
|
||||
.d-flex.flex-row.gap-1 .btn i {
|
||||
margin-right: 0.25rem;
|
||||
}
|
||||
|
||||
/* Work Info Styling */
|
||||
.work-info-item {
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
padding-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.work-info-item:last-child {
|
||||
border-bottom: none;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.work-info-item label {
|
||||
font-size: 0.875rem;
|
||||
color: #6c757d;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.work-info-value {
|
||||
font-size: 1rem;
|
||||
color: #495057;
|
||||
font-weight: 500;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.card-header.bg-primary {
|
||||
background: linear-gradient(135deg, #007bff 0%, #0056b3 100%) !important;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.card-header.bg-primary h5 {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.badge.badge-info {
|
||||
background-color: #17a2b8;
|
||||
color: white;
|
||||
padding: 0.375rem 0.75rem;
|
||||
font-size: 0.875rem;
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
|
||||
/* Ensure DataTables doesn't break flex layout */
|
||||
.dataTables_wrapper .dataTables_scrollBody .d-flex {
|
||||
display: flex !important;
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 768px) {
|
||||
.d-flex.flex-row.gap-1 {
|
||||
flex-direction: column !important;
|
||||
gap: 0.125rem !important;
|
||||
}
|
||||
|
||||
.d-flex.flex-row.gap-1 .btn {
|
||||
width: 100%;
|
||||
margin-bottom: 0.125rem;
|
||||
}
|
||||
|
||||
.work-info-item {
|
||||
margin-bottom: 1rem !important;
|
||||
}
|
||||
|
||||
.card-body .row .col-md-6:first-child {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* Modal and Form Styling */
|
||||
.modal-header {
|
||||
border-bottom: 1px solid #dee2e6;
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
.modal-header h5 {
|
||||
font-weight: 600;
|
||||
color: #495057;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
font-size: 0.9rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.form-group label i {
|
||||
color: #6c757d;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
border-radius: 0.375rem;
|
||||
border: 1px solid #ced4da;
|
||||
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
|
||||
}
|
||||
|
||||
.form-control:focus {
|
||||
border-color: #007bff;
|
||||
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
|
||||
}
|
||||
|
||||
.btn {
|
||||
border-radius: 0.375rem;
|
||||
font-weight: 500;
|
||||
transition: all 0.15s ease-in-out;
|
||||
}
|
||||
|
||||
.btn i {
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
/* Required field indicator */
|
||||
.text-danger {
|
||||
color: #dc3545 !important;
|
||||
}
|
||||
|
||||
/* Placeholder styling */
|
||||
.form-control::placeholder {
|
||||
color: #6c757d;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
/* Select2 Styling */
|
||||
.select2-container--default .select2-selection--single {
|
||||
border: 1px solid #ced4da;
|
||||
border-radius: 0.375rem;
|
||||
height: 38px;
|
||||
line-height: 36px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-selection--single .select2-selection__rendered {
|
||||
line-height: 36px;
|
||||
padding-left: 12px;
|
||||
padding-right: 30px;
|
||||
color: #495057;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-selection--single .select2-selection__placeholder {
|
||||
color: #6c757d;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-selection--single .select2-selection__arrow {
|
||||
height: calc(1.5em + 0.75rem);
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-selection--single .select2-selection__clear {
|
||||
color: #6c757d;
|
||||
margin-right: 25px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-selection--single .select2-selection__clear:hover {
|
||||
color: #dc3545;
|
||||
}
|
||||
|
||||
.select2-container--default.select2-container--focus .select2-selection--single {
|
||||
border-color: #007bff;
|
||||
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
|
||||
}
|
||||
|
||||
.select2-dropdown {
|
||||
border: 1px solid #ced4da;
|
||||
border-radius: 0.375rem;
|
||||
box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-search--dropdown .select2-search__field {
|
||||
border: 1px solid #ced4da;
|
||||
border-radius: 0.25rem;
|
||||
padding: 8px 12px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-search--dropdown .select2-search__field:focus {
|
||||
border-color: #007bff;
|
||||
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-results__option {
|
||||
padding: 8px 12px;
|
||||
font-size: 14px;
|
||||
color: #495057;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-results__option--highlighted[aria-selected] {
|
||||
background-color: #007bff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-results__option[aria-selected=true] {
|
||||
background-color: #e9ecef;
|
||||
color: #495057;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-results__option[aria-selected=true]:hover {
|
||||
background-color: #007bff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.select2-container {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
/* Ensure Select2 works properly in modal */
|
||||
.modal .select2-container {
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.modal .select2-dropdown {
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
/* Fix Select2 height to match form controls */
|
||||
.select2-container--default .select2-selection--single {
|
||||
height: calc(1.5em + 0.75rem + 2px);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-selection--single .select2-selection__rendered {
|
||||
line-height: 1.5;
|
||||
padding-top: 0.375rem;
|
||||
padding-bottom: 0.375rem;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-selection--single .select2-selection__arrow {
|
||||
height: calc(1.5em + 0.75rem);
|
||||
top: 0;
|
||||
}
|
||||
|
||||
/* SweetAlert Icon Centering */
|
||||
.swal2-icon {
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
margin: 0 auto !important;
|
||||
}
|
||||
|
||||
.swal2-icon .swal2-icon-content {
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
}
|
||||
|
||||
.swal2-popup {
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
.swal2-title {
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
.swal2-content {
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
.swal2-actions {
|
||||
justify-content: center !important;
|
||||
}
|
||||
</style>
|
||||
@endsection
|
||||
@@ -6,6 +6,243 @@
|
||||
#nama{
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
/* Action button flex layout */
|
||||
.d-flex.flex-row.gap-1 {
|
||||
display: flex !important;
|
||||
flex-direction: row !important;
|
||||
gap: 0.25rem !important;
|
||||
align-items: center;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
.d-flex.flex-row.gap-1 .btn {
|
||||
white-space: nowrap;
|
||||
margin: 0;
|
||||
padding: 0.375rem 0.75rem;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.5;
|
||||
border-radius: 0.2rem;
|
||||
}
|
||||
|
||||
.d-flex.flex-row.gap-1 .btn i {
|
||||
margin-right: 0.25rem;
|
||||
}
|
||||
|
||||
/* Ensure DataTables doesn't break flex layout */
|
||||
.dataTables_wrapper .dataTables_scrollBody .d-flex {
|
||||
display: flex !important;
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 768px) {
|
||||
.d-flex.flex-row.gap-1 {
|
||||
flex-direction: column !important;
|
||||
gap: 0.125rem !important;
|
||||
}
|
||||
|
||||
.d-flex.flex-row.gap-1 .btn {
|
||||
width: 100%;
|
||||
margin-bottom: 0.125rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* Modal and Form Styling */
|
||||
.modal-header {
|
||||
border-bottom: 1px solid #dee2e6;
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
.modal-header h5 {
|
||||
font-weight: 600;
|
||||
color: #495057;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
font-size: 0.9rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.form-group label i {
|
||||
color: #6c757d;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
border-radius: 0.375rem;
|
||||
border: 1px solid #ced4da;
|
||||
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
|
||||
}
|
||||
|
||||
.form-control:focus {
|
||||
border-color: #007bff;
|
||||
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
|
||||
}
|
||||
|
||||
.btn {
|
||||
border-radius: 0.375rem;
|
||||
font-weight: 500;
|
||||
transition: all 0.15s ease-in-out;
|
||||
}
|
||||
|
||||
.btn i {
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
/* Required field indicator */
|
||||
.text-danger {
|
||||
color: #dc3545 !important;
|
||||
}
|
||||
|
||||
/* Placeholder styling */
|
||||
.form-control::placeholder {
|
||||
color: #6c757d;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
/* Select2 Styling */
|
||||
.select2-container--default .select2-selection--single {
|
||||
border: 1px solid #ced4da;
|
||||
border-radius: 0.375rem;
|
||||
height: 38px;
|
||||
line-height: 36px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-selection--single .select2-selection__rendered {
|
||||
line-height: 36px;
|
||||
padding-left: 12px;
|
||||
padding-right: 30px;
|
||||
color: #495057;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-selection--single .select2-selection__placeholder {
|
||||
color: #6c757d;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-selection--single .select2-selection__arrow {
|
||||
height: 36px;
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-selection--single .select2-selection__clear {
|
||||
color: #6c757d;
|
||||
margin-right: 25px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-selection--single .select2-selection__clear:hover {
|
||||
color: #dc3545;
|
||||
}
|
||||
|
||||
.select2-container--default.select2-container--focus .select2-selection--single {
|
||||
border-color: #007bff;
|
||||
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
|
||||
}
|
||||
|
||||
.select2-dropdown {
|
||||
border: 1px solid #ced4da;
|
||||
border-radius: 0.375rem;
|
||||
box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-search--dropdown .select2-search__field {
|
||||
border: 1px solid #ced4da;
|
||||
border-radius: 0.25rem;
|
||||
padding: 8px 12px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-search--dropdown .select2-search__field:focus {
|
||||
border-color: #007bff;
|
||||
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-results__option {
|
||||
padding: 8px 12px;
|
||||
font-size: 14px;
|
||||
color: #495057;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-results__option--highlighted[aria-selected] {
|
||||
background-color: #007bff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-results__option[aria-selected=true] {
|
||||
background-color: #e9ecef;
|
||||
color: #495057;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-results__option[aria-selected=true]:hover {
|
||||
background-color: #007bff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.select2-container {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
/* Ensure Select2 works properly in modal */
|
||||
.modal .select2-container {
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.modal .select2-dropdown {
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
/* Fix Select2 height to match form controls */
|
||||
.select2-container--default .select2-selection--single {
|
||||
height: calc(1.5em + 0.75rem + 2px);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-selection--single .select2-selection__rendered {
|
||||
line-height: 1.5;
|
||||
padding-top: 0.375rem;
|
||||
padding-bottom: 0.375rem;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-selection--single .select2-selection__arrow {
|
||||
height: calc(1.5em + 0.75rem);
|
||||
top: 0;
|
||||
}
|
||||
|
||||
/* SweetAlert Icon Centering */
|
||||
.swal2-icon {
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
margin: 0 auto !important;
|
||||
}
|
||||
|
||||
.swal2-icon .swal2-icon-content {
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
}
|
||||
|
||||
.swal2-popup {
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
.swal2-title {
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
.swal2-content {
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
.swal2-actions {
|
||||
justify-content: center !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="kt-portlet kt-portlet--mobile" id="kt_blockui_datatable">
|
||||
@@ -22,7 +259,7 @@
|
||||
<div class="kt-portlet__head-toolbar">
|
||||
<div class="kt-portlet__head-wrapper">
|
||||
<div class="kt-portlet__head-actions">
|
||||
<button type="button" class="btn btn-bold btn-label-brand btn-sm" id="addWork"> Tambah </button>
|
||||
<button type="button" class="btn btn-bold btn-label-brand" id="addWork"> Tambah </button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -52,41 +289,73 @@
|
||||
|
||||
<!--begin::Modal-->
|
||||
<div class="modal fade" id="workModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<form id="workForm" class="kt-form">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="modalHeading"></h5>
|
||||
<h5 class="modal-title" id="modalHeading">
|
||||
<i class="fa fa-plus mr-2"></i>
|
||||
Tambah Pekerjaan
|
||||
</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="kt-portlet__body">
|
||||
<div class="form-group">
|
||||
<label>Nama Pekerjaan</label>
|
||||
<input type="text" class="form-control inputUppercase" id="name" name="name" placeholder="Masukan Nama Pekerjaan" value="" required="" autocomplete="off" />
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="name" class="font-weight-bold">
|
||||
<i class="fa fa-tag mr-1"></i>
|
||||
Nama Pekerjaan <span class="text-danger">*</span>
|
||||
</label>
|
||||
<input type="text" class="form-control inputUppercase" id="name" name="name"
|
||||
placeholder="Masukan Nama Pekerjaan" value="" required="" autocomplete="off" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Short Name</label>
|
||||
<input type="text" class="form-control inputUppercase" id="shortname" name="shortname" placeholder="Masukan Short Name" value="" required="" autocomplete="off" />
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="shortname" class="font-weight-bold">
|
||||
<i class="fa fa-code mr-1"></i>
|
||||
Short Name <span class="text-danger">*</span>
|
||||
</label>
|
||||
<input type="text" class="form-control inputUppercase" id="shortname" name="shortname"
|
||||
placeholder="Masukan Short Name" value="" required="" autocomplete="off" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="category_id">Kategori</label>
|
||||
<select name="category_id" id="category_id" class="form-control">
|
||||
@foreach ($categories as $category)
|
||||
<option value="{{ $category->id }}">{{ $category->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="desc">Deskripsi Pekerjaan</label>
|
||||
<textarea name="desc" id="desc" rows="5" class="form-control"></textarea>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="category_id" class="font-weight-bold">
|
||||
<i class="fa fa-folder mr-1"></i>
|
||||
Kategori <span class="text-danger">*</span>
|
||||
</label>
|
||||
<select name="category_id" id="category_id" class="form-control select2" required>
|
||||
<option value="">-- Pilih Kategori --</option>
|
||||
@foreach ($categories as $category)
|
||||
<option value="{{ $category->id }}">{{ $category->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="desc" class="font-weight-bold">
|
||||
<i class="fa fa-align-left mr-1"></i>
|
||||
Deskripsi Pekerjaan
|
||||
</label>
|
||||
<textarea name="desc" id="desc" rows="4" class="form-control"
|
||||
placeholder="Masukan deskripsi pekerjaan (opsional)"></textarea>
|
||||
</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" id="saveBtn" value="create">Simpan</button>
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">
|
||||
Batal
|
||||
</button>
|
||||
<button type="submit" class="btn btn-primary" id="saveBtn" value="create">
|
||||
Simpan
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -111,8 +111,8 @@ License: You must have a valid license purchased only from themeforest(the above
|
||||
<!-- end::Scrolltop -->
|
||||
|
||||
<!--begin::Global Theme Bundle(used by all pages) -->
|
||||
<script src="{{ asset('js/bootstrap-datepicker.min.js') }}"></script>
|
||||
<script src="{{ asset('js/app.bundle.min.js') }}"></script>
|
||||
<script src="{{ asset('js/bootstrap-datepicker.min.js') }}"></script>
|
||||
<script src="//maps.google.com/maps/api/js?key=AIzaSyBTGnKT7dt597vo9QgeQ7BFhvSRP4eiMSM"></script>
|
||||
<!--end::Global Theme Bundle -->
|
||||
|
||||
|
||||
@@ -268,6 +268,65 @@ use Illuminate\Support\Facades\Auth;
|
||||
width: 100% !important;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
/* Style for placeholder options */
|
||||
select option[disabled] {
|
||||
color: #6c757d;
|
||||
font-style: italic;
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
/* Prevent auto-selection of first option */
|
||||
select:focus option:first-child {
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
/* Required field styling */
|
||||
.form-control[required]:not(:placeholder-shown):valid {
|
||||
border-color: #28a745;
|
||||
box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25);
|
||||
}
|
||||
|
||||
.form-control[required]:not(:placeholder-shown):invalid {
|
||||
border-color: #dc3545;
|
||||
box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);
|
||||
}
|
||||
|
||||
/* Required field indicator */
|
||||
.form-control[required]::placeholder {
|
||||
color: #6c757d;
|
||||
}
|
||||
|
||||
/* Service Advisor required styling */
|
||||
select[name="user_sa_id"][required] option:first-child {
|
||||
color: #6c757d;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* Required field labels */
|
||||
.form-group label:after {
|
||||
content: " *";
|
||||
color: #dc3545;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Required field focus styling */
|
||||
.form-control[required]:focus {
|
||||
border-color: #5d78ff;
|
||||
box-shadow: 0 0 0 0.2rem rgba(93, 120, 255, 0.25);
|
||||
}
|
||||
|
||||
/* Invalid field styling */
|
||||
.form-control.is-invalid {
|
||||
border-color: #dc3545;
|
||||
box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);
|
||||
}
|
||||
|
||||
/* Valid field styling */
|
||||
.form-control.is-valid {
|
||||
border-color: #28a745;
|
||||
box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25);
|
||||
}
|
||||
</style>
|
||||
@endsection
|
||||
|
||||
@@ -364,9 +423,31 @@ use Illuminate\Support\Facades\Auth;
|
||||
<input type="hidden" name="form" value="work">
|
||||
<input type="hidden" name="mechanic_id" value="{{ $mechanic->id }}">
|
||||
<input type="hidden" name="dealer_id" value="{{ $mechanic->dealer_id }}">
|
||||
|
||||
<!-- Stock Error Display -->
|
||||
@if($errors->has('stock'))
|
||||
<div class="alert alert-warning alert-dismissible fade show" role="alert">
|
||||
<strong><i class="fa fa-exclamation-triangle"></i> Peringatan Stock:</strong>
|
||||
<br>{!! $errors->first('stock') !!}
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if($errors->has('error'))
|
||||
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
||||
<strong><i class="fa fa-times-circle"></i> Error:</strong>
|
||||
{{ $errors->first('error') }}
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
@endif
|
||||
<div class="form-group row">
|
||||
<div class="col-6">
|
||||
<input type="text" name="spk_no" class="form-control @if(old('form') == 'work') @error('spk_no') is-invalid @enderror @endif" value="{{ old('spk_no') }}" placeholder="No. SPK">
|
||||
<label>No. SPK</label>
|
||||
<input type="text" name="spk_no" class="form-control @if(old('form') == 'work') @error('spk_no') is-invalid @enderror @endif" value="{{ old('spk_no') }}" placeholder="No. SPK" required>
|
||||
|
||||
@if(old('form') == 'work')
|
||||
@error('spk_no')
|
||||
@@ -377,7 +458,8 @@ use Illuminate\Support\Facades\Auth;
|
||||
@endif
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<input type="text" name="police_number" class="form-control @if(old('form') == 'work') @error('police_number') is-invalid @enderror" @endif value="{{ old('police_number') }}" placeholder="No. Polisi">
|
||||
<label>No. Polisi</label>
|
||||
<input type="text" name="police_number" class="form-control @if(old('form') == 'work') @error('police_number') is-invalid @enderror" @endif value="{{ old('police_number') }}" placeholder="No. Polisi" required>
|
||||
@if(old('form') == 'work')
|
||||
@error('police_number')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
@@ -389,6 +471,7 @@ use Illuminate\Support\Facades\Auth;
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-6">
|
||||
<label>Warranty</label>
|
||||
<select name="warranty" class="form-control @if(old('form') == 'work') @error('warranty') is-invalid @enderror @endif">
|
||||
<option selected>Warranty</option>
|
||||
<option value="1" @if(old('form') == 'work') @if(old('warranty') == 1) selected @endif @endif>Ya</option>
|
||||
@@ -403,6 +486,7 @@ use Illuminate\Support\Facades\Auth;
|
||||
@endif
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<label>Tanggal Pekerjaan</label>
|
||||
<input type="text" name="date" id="date-work" required class="form-control @if(old('form') == 'work') @error('date') is-invalid @enderror @endif" placeholder="Tanggal Pekerjaan">
|
||||
@if(old('form') == 'work')
|
||||
@error('date')
|
||||
@@ -414,7 +498,8 @@ use Illuminate\Support\Facades\Auth;
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group mt-4">
|
||||
<select name="user_sa_id" class="form-control @if(old('form') == 'work') @error('user_sa_id') is-invalid @enderror @endif">
|
||||
<label>Service Advisor</label>
|
||||
<select name="user_sa_id" class="form-control @if(old('form') == 'work') @error('user_sa_id') is-invalid @enderror @endif" required>
|
||||
<option value="" selected>Service Advisor</option>
|
||||
@foreach ($user_sas as $user_sa)
|
||||
<option @if(old('form') == 'work') @if($user_sa->id == old('user_sa_id')) selected @enderror @endif value="{{ $user_sa->id }}">{{ $user_sa->name }}</option>
|
||||
@@ -436,10 +521,10 @@ use Illuminate\Support\Facades\Auth;
|
||||
@for ($i = 0; $i < count(old('work_id')); $i++)
|
||||
<div class="form-group row" id="work_field{{ $i+1 }}">
|
||||
<div class="col-6">
|
||||
<select name="work_id[]" id="work_work{{ $i+1 }}" class="form-control @error('work_id.'.$i)" is-invalid @enderror>
|
||||
<option selected disabled>Pekerjaan</option>
|
||||
<select name="work_id[]" id="work_work{{ $i+1 }}" class="form-control @error('work_id.'.$i) is-invalid @enderror">
|
||||
<option value="" disabled>Pekerjaan</option>
|
||||
@foreach ($work_works as $work)
|
||||
<option value="{{ $work->id }}" @if($work->id == old('work_id.'.$i)) selected @endif>{{ $work->name }}</option>
|
||||
<option value="{{ $work->id }}" @if($work->id == old('work_id.'.$i)) selected @endif>{{ $work->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
|
||||
@@ -467,7 +552,7 @@ use Illuminate\Support\Facades\Auth;
|
||||
<div class="form-group row" id="work_field1">
|
||||
<div class="col-6">
|
||||
<select name="work_id[]" id="work_work1" class="form-control">
|
||||
<option selected disabled>Pekerjaan</option>
|
||||
<option value="" selected disabled>Pekerjaan</option>
|
||||
@foreach ($work_works as $work)
|
||||
<option value="{{ $work->id }}">{{ $work->name }}</option>
|
||||
@endforeach
|
||||
@@ -483,7 +568,7 @@ use Illuminate\Support\Facades\Auth;
|
||||
<div class="form-group row" id="work_field2">
|
||||
<div class="col-6">
|
||||
<select name="work_id[]" id="work_work2" class="form-control">
|
||||
<option selected disabled>Pekerjaan</option>
|
||||
<option value="" selected disabled>Pekerjaan</option>
|
||||
@foreach ($work_works as $work)
|
||||
<option value="{{ $work->id }}">{{ $work->name }}</option>
|
||||
@endforeach
|
||||
@@ -499,7 +584,7 @@ use Illuminate\Support\Facades\Auth;
|
||||
<div class="form-group row" id="work_field3">
|
||||
<div class="col-6">
|
||||
<select name="work_id[]" id="work_work3" class="form-control">
|
||||
<option selected disabled>Pekerjaan</option>
|
||||
<option value="" selected disabled>Pekerjaan</option>
|
||||
@foreach ($work_works as $work)
|
||||
<option value="{{ $work->id }}">{{ $work->name }}</option>
|
||||
@endforeach
|
||||
@@ -515,7 +600,7 @@ use Illuminate\Support\Facades\Auth;
|
||||
<div class="form-group row" id="work_field4">
|
||||
<div class="col-6">
|
||||
<select name="work_id[]" id="work_work4" class="form-control">
|
||||
<option selected disabled>Pekerjaan</option>
|
||||
<option value="" selected disabled>Pekerjaan</option>
|
||||
@foreach ($work_works as $work)
|
||||
<option value="{{ $work->id }}">{{ $work->name }}</option>
|
||||
@endforeach
|
||||
@@ -531,7 +616,7 @@ use Illuminate\Support\Facades\Auth;
|
||||
<div class="form-group row" id="work_field5">
|
||||
<div class="col-6">
|
||||
<select name="work_id[]" id="work_work5" class="form-control">
|
||||
<option selected disabled>Pekerjaan</option>
|
||||
<option value="" selected disabled>Pekerjaan</option>
|
||||
@foreach ($work_works as $work)
|
||||
<option value="{{ $work->id }}">{{ $work->name }}</option>
|
||||
@endforeach
|
||||
@@ -548,7 +633,7 @@ use Illuminate\Support\Facades\Auth;
|
||||
<div class="row">
|
||||
<div class="col-10"></div>
|
||||
<div class="col-2">
|
||||
<button class="btn mb-4 btn-sm btn-primary float-right btn-add-field-work" style="width: 100%;" onclick="addFormField('work'); return false;">+</button>
|
||||
<button class="btn mb-4 btn-sm btn-primary float-right btn-add-field-work" style="width: 100%;" onclick="addFormFieldWithStockCheck('work'); return false;">+</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -565,7 +650,8 @@ use Illuminate\Support\Facades\Auth;
|
||||
<input type="hidden" name="dealer_id" value="{{ $mechanic->dealer_id }}">
|
||||
<div class="form-group row">
|
||||
<div class="col-6">
|
||||
<input type="text" name="spk_no" class="form-control @if(old('form') == 'wash') @error('spk_no') is-invalid @enderror @endif" value="{{ old('spk_no') }}" placeholder="No. SPK">
|
||||
<label>No. SPK</label>
|
||||
<input type="text" name="spk_no" class="form-control @if(old('form') == 'wash') @error('spk_no') is-invalid @enderror @endif" value="{{ old('spk_no') }}" placeholder="No. SPK" required>
|
||||
@if(old('form') == 'wash')
|
||||
@error('spk_no')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
@@ -575,7 +661,8 @@ use Illuminate\Support\Facades\Auth;
|
||||
@endif
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<input type="text" name="police_number" class="form-control @if(old('form') == 'wash') @error('police_number') is-invalid @enderror @endif" value="{{ old('police_number') }}" placeholder="No. Polisi">
|
||||
<label>No. Polisi</label>
|
||||
<input type="text" name="police_number" class="form-control @if(old('form') == 'wash') @error('police_number') is-invalid @enderror @endif" value="{{ old('police_number') }}" placeholder="No. Polisi" required>
|
||||
@if(old('form') == 'wash')
|
||||
@error('police_number')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
@@ -587,6 +674,7 @@ use Illuminate\Support\Facades\Auth;
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-6">
|
||||
<label>Warranty</label>
|
||||
<select name="warranty" class="form-control @if(old('form') == 'wash') @error('warranty') is-invalid @enderror @endif">
|
||||
<option selected>Warranty</option>
|
||||
<option value="1" @if(old('form') == 'wash') @if(old('warranty') == 1) selected @endif @endif>Ya</option>
|
||||
@@ -599,7 +687,8 @@ use Illuminate\Support\Facades\Auth;
|
||||
@enderror
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<input type="text" id="date-wash" name="date" class="form-control @if(old('form') == 'wash') @error('date') is-invalid @enderror @endif" placeholder="Tanggal Pekerjaan">
|
||||
<label>Tanggal Pekerjaan</label>
|
||||
<input type="text" id="date-wash" name="date" class="form-control @if(old('form') == 'wash') @error('date') is-invalid @enderror @endif" placeholder="Tanggal Pekerjaan" required>
|
||||
@if(old('form') == 'wash')
|
||||
@error('date')
|
||||
<span class="invalid-feedback" role="alert">
|
||||
@@ -610,8 +699,9 @@ use Illuminate\Support\Facades\Auth;
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group mt-4">
|
||||
<select name="user_sa_id" class="form-control @if(old('form') == 'wash') @error('user_sa_id') is-invalid @enderror @endif">
|
||||
<option selected>Service Advisor</option>
|
||||
<label>Service Advisor</label>
|
||||
<select name="user_sa_id" class="form-control @if(old('form') == 'wash') @error('user_sa_id') is-invalid @enderror @endif" required>
|
||||
<option value="" selected>Service Advisor</option>
|
||||
@foreach ($user_sas as $user_sa)
|
||||
<option @if(old('form') == 'wash') @if($user_sa->id == old('user_sa_id')) selected @enderror @endif value="{{ $user_sa->id }}">{{ $user_sa->name }}</option>
|
||||
@endforeach
|
||||
@@ -896,7 +986,114 @@ use Illuminate\Support\Facades\Auth;
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Global variables for stock checking
|
||||
let dealerId = {{ $mechanic->dealer_id }};
|
||||
let stockWarnings = {};
|
||||
|
||||
// Function to check stock availability for selected work
|
||||
function checkStockAvailability(workId, quantity, callback) {
|
||||
if (!workId || !quantity || quantity < 1) {
|
||||
if (callback) callback(null);
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: "{{ route('transaction.check-stock') }}",
|
||||
method: 'POST',
|
||||
data: {
|
||||
work_id: workId,
|
||||
dealer_id: dealerId,
|
||||
quantity: quantity,
|
||||
_token: $('meta[name="csrf-token"]').attr('content')
|
||||
},
|
||||
success: function(response) {
|
||||
if (callback) callback(response.data);
|
||||
},
|
||||
error: function(xhr) {
|
||||
console.error('Error checking stock:', xhr);
|
||||
if (callback) callback(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Function to display stock warning
|
||||
function displayStockWarning(fieldId, stockData) {
|
||||
// Remove existing warning
|
||||
$(`#stock-warning-${fieldId}`).remove();
|
||||
|
||||
if (!stockData || stockData.available) {
|
||||
return; // No warning needed
|
||||
}
|
||||
|
||||
let warningHtml = `
|
||||
<div id="stock-warning-${fieldId}" class="alert alert-warning mt-2 mb-0" style="font-size: 12px;">
|
||||
<strong><i class="fa fa-exclamation-triangle"></i> Peringatan Stock:</strong> ${stockData.message}
|
||||
<ul class="mb-0 mt-1" style="font-size: 11px;">
|
||||
`;
|
||||
|
||||
stockData.details.forEach(function(detail) {
|
||||
if (!detail.is_available) {
|
||||
warningHtml += `
|
||||
<li>${detail.product_name}: Butuh ${detail.required_quantity}, Tersedia ${detail.available_stock}</li>
|
||||
`;
|
||||
}
|
||||
});
|
||||
|
||||
warningHtml += `
|
||||
</ul>
|
||||
</div>
|
||||
`;
|
||||
|
||||
$(`#work_field${fieldId.replace('work_work', '')}`).append(warningHtml);
|
||||
}
|
||||
|
||||
// Function to handle work selection change
|
||||
function handleWorkSelectionChange(selectElement) {
|
||||
let workId = $(selectElement).val();
|
||||
let fieldId = $(selectElement).attr('id');
|
||||
let quantityInput = $(selectElement).closest('.form-group').find('input[name="quantity[]"]');
|
||||
let quantity = parseInt(quantityInput.val()) || 1;
|
||||
|
||||
if (workId) {
|
||||
checkStockAvailability(workId, quantity, function(stockData) {
|
||||
displayStockWarning(fieldId, stockData);
|
||||
|
||||
// Store warning data for form submission validation
|
||||
if (stockData && !stockData.available) {
|
||||
stockWarnings[fieldId] = stockData;
|
||||
} else {
|
||||
delete stockWarnings[fieldId];
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// Remove warning when no work selected
|
||||
$(`#stock-warning-${fieldId}`).remove();
|
||||
delete stockWarnings[fieldId];
|
||||
}
|
||||
}
|
||||
|
||||
// Function to handle quantity change
|
||||
function handleQuantityChange(quantityInput) {
|
||||
let workSelect = $(quantityInput).closest('.form-group').find('select[name="work_id[]"]');
|
||||
let workId = workSelect.val();
|
||||
let quantity = parseInt($(quantityInput).val()) || 1;
|
||||
|
||||
if (workId && quantity > 0) {
|
||||
let fieldId = workSelect.attr('id');
|
||||
checkStockAvailability(workId, quantity, function(stockData) {
|
||||
displayStockWarning(fieldId, stockData);
|
||||
|
||||
// Store warning data for form submission validation
|
||||
if (stockData && !stockData.available) {
|
||||
stockWarnings[fieldId] = stockData;
|
||||
} else {
|
||||
delete stockWarnings[fieldId];
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function logout(event){
|
||||
event.preventDefault();
|
||||
@@ -973,23 +1170,296 @@ use Illuminate\Support\Facades\Auth;
|
||||
|
||||
function getWork(ajax_work_url, form, id) {
|
||||
$.get(ajax_work_url, function(res) {
|
||||
var $select = $(`#${form}_work${id}`);
|
||||
|
||||
// Clear existing options except the first one (placeholder)
|
||||
$select.find('option:not(:first)').remove();
|
||||
|
||||
// Add new options
|
||||
$.each(res.data, function (i, item) {
|
||||
$(`#${form}_work${id}`).append($('<option>', {
|
||||
$select.append($('<option>', {
|
||||
value: item.id,
|
||||
text : item.name
|
||||
}));
|
||||
});
|
||||
|
||||
// Ensure placeholder is still properly set
|
||||
var $placeholder = $select.find('option:first');
|
||||
if ($placeholder.length) {
|
||||
$placeholder.prop('disabled', true).prop('selected', true).val('');
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Add event listeners for existing fields
|
||||
$(document).ready(function() {
|
||||
// Initial fields (work1, work2, etc.)
|
||||
$('select[name="work_id[]"]').on('change', function() {
|
||||
handleWorkSelectionChange(this);
|
||||
});
|
||||
|
||||
$('input[name="quantity[]"]').on('input', function() {
|
||||
handleQuantityChange(this);
|
||||
});
|
||||
|
||||
// Check stock for pre-filled fields
|
||||
$('select[name="work_id[]"]').each(function() {
|
||||
if ($(this).val()) {
|
||||
handleWorkSelectionChange(this);
|
||||
}
|
||||
});
|
||||
|
||||
// Ensure placeholder options are properly disabled and not selectable
|
||||
$('select[name="work_id[]"]').each(function() {
|
||||
var $select = $(this);
|
||||
var $placeholder = $select.find('option:first');
|
||||
|
||||
// Make sure placeholder is disabled and has empty value
|
||||
if ($placeholder.length) {
|
||||
$placeholder.prop('disabled', true).prop('selected', true).val('');
|
||||
}
|
||||
|
||||
// Prevent auto-selection of first non-disabled option
|
||||
$select.on('focus', function() {
|
||||
if (!$(this).val()) {
|
||||
$(this).find('option:first').prop('selected', true);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Handle form errors - ensure work selections are maintained
|
||||
@if($errors->any() && (old('form') == 'work' || old('form') == 'wash'))
|
||||
// When there are form errors, ensure the correct work selections are maintained
|
||||
// The old values are already handled by the Blade template in the HTML
|
||||
// We just need to ensure proper placeholder handling
|
||||
$('select[name="work_id[]"]').each(function() {
|
||||
var $select = $(this);
|
||||
|
||||
// If no value is selected, ensure placeholder is selected
|
||||
if (!$select.val() || $select.val() === '') {
|
||||
var $placeholder = $select.find('option:first');
|
||||
if ($placeholder.length) {
|
||||
$placeholder.prop('selected', true);
|
||||
}
|
||||
} else {
|
||||
// Trigger change event to update any dependent fields
|
||||
$select.trigger('change');
|
||||
}
|
||||
});
|
||||
@endif
|
||||
});
|
||||
|
||||
// Override addFormField function to include event listeners
|
||||
function addFormFieldWithStockCheck(form) {
|
||||
addFormField(form); // Call original function
|
||||
|
||||
// Add event listeners to new field
|
||||
setTimeout(function() {
|
||||
var id = $(`.${form}_field_counter`).val();
|
||||
var $newSelect = $(`#${form}_work${id}`);
|
||||
|
||||
// Ensure placeholder is properly set
|
||||
var $placeholder = $newSelect.find('option:first');
|
||||
if ($placeholder.length) {
|
||||
$placeholder.prop('disabled', true).prop('selected', true).val('');
|
||||
}
|
||||
|
||||
$newSelect.on('change', function() {
|
||||
handleWorkSelectionChange(this);
|
||||
});
|
||||
|
||||
$newSelect.closest('.form-group').find('input[name="quantity[]"]').on('input', function() {
|
||||
handleQuantityChange(this);
|
||||
});
|
||||
|
||||
// Prevent auto-selection of first non-disabled option
|
||||
$newSelect.on('focus', function() {
|
||||
if (!$(this).val()) {
|
||||
$(this).find('option:first').prop('selected', true);
|
||||
}
|
||||
});
|
||||
}, 100);
|
||||
}
|
||||
|
||||
$("#workForm").submit(function(e) {
|
||||
$(".button-save").attr("disabled");
|
||||
// Validate required fields
|
||||
var spkNo = $('input[name="spk_no"]').val().trim();
|
||||
var policeNumber = $('input[name="police_number"]').val().trim();
|
||||
var userSaId = $('select[name="user_sa_id"]').val();
|
||||
var date = $('input[name="date"]').val().trim();
|
||||
|
||||
var errorMessages = [];
|
||||
|
||||
if (!spkNo) {
|
||||
errorMessages.push('No. SPK harus diisi');
|
||||
$('input[name="spk_no"]').addClass('is-invalid');
|
||||
} else {
|
||||
$('input[name="spk_no"]').removeClass('is-invalid');
|
||||
}
|
||||
|
||||
if (!policeNumber) {
|
||||
errorMessages.push('No. Polisi harus diisi');
|
||||
$('input[name="police_number"]').addClass('is-invalid');
|
||||
} else {
|
||||
$('input[name="police_number"]').removeClass('is-invalid');
|
||||
}
|
||||
|
||||
if (!userSaId || userSaId === '') {
|
||||
errorMessages.push('Service Advisor harus dipilih');
|
||||
$('select[name="user_sa_id"]').addClass('is-invalid');
|
||||
} else {
|
||||
$('select[name="user_sa_id"]').removeClass('is-invalid');
|
||||
}
|
||||
|
||||
if (!date) {
|
||||
errorMessages.push('Tanggal Pekerjaan harus diisi');
|
||||
$('input[name="date"]').addClass('is-invalid');
|
||||
} else {
|
||||
$('input[name="date"]').removeClass('is-invalid');
|
||||
}
|
||||
|
||||
if (errorMessages.length > 0) {
|
||||
e.preventDefault();
|
||||
Swal.fire({
|
||||
title: 'Validasi Gagal',
|
||||
html: `
|
||||
<div class="text-left">
|
||||
<p class="mb-3">Mohon lengkapi field berikut:</p>
|
||||
<ul class="text-left">
|
||||
${errorMessages.map(msg => '<li>' + msg + '</li>').join('')}
|
||||
</ul>
|
||||
</div>
|
||||
`,
|
||||
icon: 'warning',
|
||||
confirmButtonText: 'OK'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate that at least one work is selected
|
||||
var hasSelectedWork = false;
|
||||
$('select[name="work_id[]"]').each(function() {
|
||||
if ($(this).val() && $(this).val() !== '') {
|
||||
hasSelectedWork = true;
|
||||
return false; // break loop
|
||||
}
|
||||
});
|
||||
|
||||
if (!hasSelectedWork) {
|
||||
e.preventDefault();
|
||||
Swal.fire({
|
||||
title: 'Peringatan',
|
||||
text: 'Minimal pilih satu pekerjaan sebelum menyimpan!',
|
||||
icon: 'warning',
|
||||
confirmButtonText: 'OK'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if there are stock warnings
|
||||
if (Object.keys(stockWarnings).length > 0) {
|
||||
e.preventDefault();
|
||||
|
||||
let warningMessages = [];
|
||||
Object.values(stockWarnings).forEach(function(warning) {
|
||||
warningMessages.push(warning.message);
|
||||
warning.details.forEach(function(detail) {
|
||||
if (!detail.is_available) {
|
||||
warningMessages.push(`- ${detail.product_name}: Butuh ${detail.required_quantity}, Tersedia ${detail.available_stock}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Swal.fire({
|
||||
title: 'Peringatan Stock Tidak Mencukupi',
|
||||
html: `
|
||||
<div class="text-left">
|
||||
<p class="mb-3">Ada beberapa pekerjaan yang memerlukan produk dengan stock tidak mencukupi:</p>
|
||||
<div class="alert alert-warning text-left">
|
||||
${warningMessages.join('<br>')}
|
||||
</div>
|
||||
<p class="mb-0"><strong>Apakah Anda yakin ingin melanjutkan?</strong></p>
|
||||
<small class="text-muted">Transaksi akan tetap dibuat, namun stock akan menjadi negatif.</small>
|
||||
</div>
|
||||
`,
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#ffc107',
|
||||
cancelButtonColor: '#6c757d',
|
||||
confirmButtonText: 'Lanjutkan',
|
||||
cancelButtonText: 'Batal'
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
$(".button-save").attr("disabled", true);
|
||||
$(".button-save").addClass("disabled");
|
||||
$("#workForm")[0].submit(); // Submit the form
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$(".button-save").attr("disabled", true);
|
||||
$(".button-save").addClass("disabled");
|
||||
return true;
|
||||
})
|
||||
|
||||
$("#washForm").submit(function(e) {
|
||||
$(".button-save").attr("disabled");
|
||||
// Validate required fields
|
||||
var spkNo = $('input[name="spk_no"]').val().trim();
|
||||
var policeNumber = $('input[name="police_number"]').val().trim();
|
||||
var userSaId = $('select[name="user_sa_id"]').val();
|
||||
var date = $('input[name="date"]').val().trim();
|
||||
|
||||
var errorMessages = [];
|
||||
|
||||
if (!spkNo) {
|
||||
errorMessages.push('No. SPK harus diisi');
|
||||
$('input[name="spk_no"]').addClass('is-invalid');
|
||||
} else {
|
||||
$('input[name="spk_no"]').removeClass('is-invalid');
|
||||
}
|
||||
|
||||
if (!policeNumber) {
|
||||
errorMessages.push('No. Polisi harus diisi');
|
||||
$('input[name="police_number"]').addClass('is-invalid');
|
||||
} else {
|
||||
$('input[name="police_number"]').removeClass('is-invalid');
|
||||
}
|
||||
|
||||
if (!userSaId || userSaId === '') {
|
||||
errorMessages.push('Service Advisor harus dipilih');
|
||||
$('select[name="user_sa_id"]').addClass('is-invalid');
|
||||
} else {
|
||||
$('select[name="user_sa_id"]').removeClass('is-invalid');
|
||||
}
|
||||
|
||||
if (!date) {
|
||||
errorMessages.push('Tanggal Pekerjaan harus diisi');
|
||||
$('input[name="date"]').addClass('is-invalid');
|
||||
} else {
|
||||
$('input[name="date"]').removeClass('is-invalid');
|
||||
}
|
||||
|
||||
if (errorMessages.length > 0) {
|
||||
e.preventDefault();
|
||||
Swal.fire({
|
||||
title: 'Validasi Gagal',
|
||||
html: `
|
||||
<div class="text-left">
|
||||
<p class="mb-3">Mohon lengkapi field berikut:</p>
|
||||
<ul class="text-left">
|
||||
${errorMessages.map(msg => '<li>' + msg + '</li>').join('')}
|
||||
</ul>
|
||||
</div>
|
||||
`,
|
||||
icon: 'warning',
|
||||
confirmButtonText: 'OK'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
$(".button-save").attr("disabled", true);
|
||||
$(".button-save").addClass("disabled");
|
||||
return true;
|
||||
})
|
||||
@@ -1280,28 +1750,31 @@ use Illuminate\Support\Facades\Auth;
|
||||
}
|
||||
})
|
||||
|
||||
$("#date-work").datepicker({
|
||||
format: 'yyyy-mm-dd',
|
||||
autoclose: true,
|
||||
todayHighlight: true
|
||||
})
|
||||
$("#date-wash").datepicker({
|
||||
format: 'yyyy-mm-dd',
|
||||
autoclose: true,
|
||||
todayHighlight: true
|
||||
})
|
||||
$("#date-opname").datepicker({
|
||||
format: 'yyyy-mm-dd',
|
||||
autoclose: true,
|
||||
todayHighlight: true,
|
||||
startDate: '-30d',
|
||||
endDate: '+0d'
|
||||
})
|
||||
$("#date-mutasi").datepicker({
|
||||
format: 'yyyy-mm-dd',
|
||||
autoclose: true,
|
||||
todayHighlight: true
|
||||
})
|
||||
// Initialize datepickers when document is ready
|
||||
$(document).ready(function() {
|
||||
$("#date-work").datepicker({
|
||||
format: 'yyyy-mm-dd',
|
||||
autoclose: true,
|
||||
todayHighlight: true
|
||||
});
|
||||
$("#date-wash").datepicker({
|
||||
format: 'yyyy-mm-dd',
|
||||
autoclose: true,
|
||||
todayHighlight: true
|
||||
});
|
||||
$("#date-opname").datepicker({
|
||||
format: 'yyyy-mm-dd',
|
||||
autoclose: true,
|
||||
todayHighlight: true,
|
||||
startDate: '-30d',
|
||||
endDate: '+0d'
|
||||
});
|
||||
$("#date-mutasi").datepicker({
|
||||
format: 'yyyy-mm-dd',
|
||||
autoclose: true,
|
||||
todayHighlight: true
|
||||
});
|
||||
});
|
||||
|
||||
// Calculate difference for opname
|
||||
$(document).on('input change keyup', '.physical-stock', function() {
|
||||
@@ -1393,6 +1866,15 @@ use Illuminate\Support\Facades\Auth;
|
||||
$(this).removeClass('is-invalid');
|
||||
});
|
||||
|
||||
// Remove invalid styling when user starts typing in required fields
|
||||
$(document).on('input', 'input[name="spk_no"], input[name="police_number"], input[name="date"]', function() {
|
||||
$(this).removeClass('is-invalid');
|
||||
});
|
||||
|
||||
$(document).on('change', 'select[name="user_sa_id"]', function() {
|
||||
$(this).removeClass('is-invalid');
|
||||
});
|
||||
|
||||
// Handle server-side errors - scroll to first error and highlight
|
||||
$(document).ready(function() {
|
||||
// Set default date for opname if empty
|
||||
@@ -1431,6 +1913,18 @@ use Illuminate\Support\Facades\Auth;
|
||||
initReceiveMutationsTable();
|
||||
}, 200);
|
||||
}, 100);
|
||||
@elseif($errors->any() && old('form') == 'work')
|
||||
// Activate transaksi tab and form kerja sub-tab when there are work form errors
|
||||
$('.nav-link[href="#transaksi"]').tab('show');
|
||||
setTimeout(function() {
|
||||
$('.nav-link[href="#form-kerja"]').tab('show');
|
||||
}, 100);
|
||||
@elseif($errors->any() && old('form') == 'wash')
|
||||
// Activate transaksi tab and form cuci sub-tab when there are wash form errors
|
||||
$('.nav-link[href="#transaksi"]').tab('show');
|
||||
setTimeout(function() {
|
||||
$('.nav-link[href="#form-cuci"]').tab('show');
|
||||
}, 100);
|
||||
@endif
|
||||
@endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user