326 lines
13 KiB
PHP
326 lines
13 KiB
PHP
|
|
@extends('admin.layouts.app')
|
||
|
|
|
||
|
|
@section('page-title', 'Add Container')
|
||
|
|
|
||
|
|
@section('content')
|
||
|
|
<style>
|
||
|
|
.cm-add-wrapper { padding: 10px 0 20px 0; }
|
||
|
|
.cm-add-header-card {
|
||
|
|
border-radius: 14px;
|
||
|
|
border: none;
|
||
|
|
margin-bottom: 18px;
|
||
|
|
background: linear-gradient(90deg,#4c6fff,#8e54e9);
|
||
|
|
box-shadow: 0 6px 18px rgba(15,35,52,0.18);
|
||
|
|
color: #ffffff;
|
||
|
|
}
|
||
|
|
.cm-add-header-card .card-body {
|
||
|
|
padding: 14px 18px;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: space-between;
|
||
|
|
gap: 10px;
|
||
|
|
}
|
||
|
|
.cm-add-title { margin: 0; font-size: 20px; font-weight: 600; }
|
||
|
|
.cm-add-sub { font-size: 12px; opacity: 0.9; }
|
||
|
|
|
||
|
|
.cm-add-main-card {
|
||
|
|
border-radius: 14px;
|
||
|
|
border: none;
|
||
|
|
box-shadow: 0 6px 18px rgba(15,35,52,0.12);
|
||
|
|
}
|
||
|
|
.cm-add-main-card .card-header {
|
||
|
|
background:#ffffff;
|
||
|
|
border-bottom: 1px solid #edf0f5;
|
||
|
|
padding: 10px 18px;
|
||
|
|
}
|
||
|
|
.cm-add-main-card .card-header h5 {
|
||
|
|
margin: 0;
|
||
|
|
font-size: 16px;
|
||
|
|
font-weight: 600;
|
||
|
|
}
|
||
|
|
|
||
|
|
.cm-form-label { font-size: 13px; font-weight: 500; color:#495057; margin-bottom: 4px; }
|
||
|
|
.cm-form-control {
|
||
|
|
font-size: 13px;
|
||
|
|
border-radius: 10px;
|
||
|
|
border:1px solid #d0d7e2;
|
||
|
|
padding: 8px 11px;
|
||
|
|
}
|
||
|
|
.cm-form-control:focus {
|
||
|
|
border-color:#4c6fff;
|
||
|
|
box-shadow:0 0 0 0.15rem rgba(76,111,255,.25);
|
||
|
|
}
|
||
|
|
|
||
|
|
.cm-help-text { font-size: 11px; color:#868e96; margin-top: 2px; }
|
||
|
|
.cm-btn-primary { border-radius: 20px; padding: 6px 22px; font-size: 13px; font-weight: 500; }
|
||
|
|
.cm-btn-secondary { border-radius: 20px; padding: 6px 18px; font-size: 13px; }
|
||
|
|
|
||
|
|
.error-card {
|
||
|
|
border-radius: 12px;
|
||
|
|
border: 1px solid #f5c2c7;
|
||
|
|
box-shadow: 0 4px 12px rgba(0,0,0,0.06);
|
||
|
|
}
|
||
|
|
|
||
|
|
.error-row-box {
|
||
|
|
border: 1px solid #e9ecef;
|
||
|
|
border-radius: 8px;
|
||
|
|
padding: 10px;
|
||
|
|
margin-bottom: 10px;
|
||
|
|
background: #f8f9fa;
|
||
|
|
}
|
||
|
|
|
||
|
|
.error-title {
|
||
|
|
font-weight: 600;
|
||
|
|
font-size: 13px;
|
||
|
|
margin-bottom: 6px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.error-item {
|
||
|
|
font-size: 12px;
|
||
|
|
margin-left: 10px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.error-item span {
|
||
|
|
font-weight: 500;
|
||
|
|
}
|
||
|
|
</style>
|
||
|
|
|
||
|
|
<div class="container-fluid cm-add-wrapper">
|
||
|
|
|
||
|
|
<div class="card cm-add-header-card">
|
||
|
|
<div class="card-body">
|
||
|
|
<div>
|
||
|
|
<h4 class="cm-add-title">Create New Container</h4>
|
||
|
|
<div class="cm-add-sub">
|
||
|
|
Add container details and upload Kent loading list Excel file.
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<a href="{{ route('containers.index') }}" class="btn btn-light btn-sm">
|
||
|
|
Back to Containers
|
||
|
|
</a>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="card cm-add-main-card">
|
||
|
|
<div class="card-header">
|
||
|
|
<h5>Add Container</h5>
|
||
|
|
</div>
|
||
|
|
<div class="card-body">
|
||
|
|
|
||
|
|
{{-- SUCCESS --}}
|
||
|
|
@if (session('success'))
|
||
|
|
<div class="alert alert-success">
|
||
|
|
{{ session('success') }}
|
||
|
|
</div>
|
||
|
|
@endif
|
||
|
|
|
||
|
|
{{-- VALIDATION --}}
|
||
|
|
@if ($errors->any())
|
||
|
|
<div class="alert alert-danger">
|
||
|
|
<ul class="mb-0">
|
||
|
|
@foreach ($errors->all() as $error)
|
||
|
|
<li>{{ $error }}</li>
|
||
|
|
@endforeach
|
||
|
|
</ul>
|
||
|
|
</div>
|
||
|
|
@endif
|
||
|
|
|
||
|
|
{{-- COMBINED ERROR PANEL (summary text) --}}
|
||
|
|
@if(session('formula_errors') || session('mark_errors'))
|
||
|
|
|
||
|
|
<div class="card error-card mb-3">
|
||
|
|
<div class="card-header bg-danger text-white small">
|
||
|
|
⚠ Excel Validation Issues Found
|
||
|
|
</div>
|
||
|
|
<div class="card-body">
|
||
|
|
<div class="small mb-1">
|
||
|
|
Some rows in your Excel file have formula or mark issues.
|
||
|
|
See the table below, and detailed messages after the table.
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{{-- 1) Excel-style table at top --}}
|
||
|
|
@php
|
||
|
|
$formulaErrors = session('formula_errors') ?? [];
|
||
|
|
$markErrors = session('mark_errors') ?? [];
|
||
|
|
|
||
|
|
$allRowsData = [];
|
||
|
|
|
||
|
|
foreach ($formulaErrors as $fe) {
|
||
|
|
if (!empty($fe['data'] ?? null)) {
|
||
|
|
$allRowsData[] = $fe['data'];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
foreach ($markErrors as $me) {
|
||
|
|
if (!empty($me['data'] ?? null)) {
|
||
|
|
$allRowsData[] = $me['data'];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
$headings = [];
|
||
|
|
if (!empty($allRowsData)) {
|
||
|
|
$headings = array_keys($allRowsData[0]);
|
||
|
|
}
|
||
|
|
@endphp
|
||
|
|
|
||
|
|
@if(!empty($headings))
|
||
|
|
<div class="card mb-3">
|
||
|
|
<div class="card-header small">
|
||
|
|
Error rows in Excel view
|
||
|
|
</div>
|
||
|
|
<div class="card-body p-2">
|
||
|
|
<div class="table-responsive" style="max-height:260px; overflow:auto;">
|
||
|
|
<table class="table table-sm table-bordered mb-0" style="font-size:11.5px;">
|
||
|
|
<thead class="table-light">
|
||
|
|
<tr>
|
||
|
|
<th>Excel Row</th>
|
||
|
|
<th>Mark No</th>
|
||
|
|
@foreach($headings as $head)
|
||
|
|
<th>{{ $head }}</th>
|
||
|
|
@endforeach
|
||
|
|
</tr>
|
||
|
|
</thead>
|
||
|
|
<tbody>
|
||
|
|
{{-- Formula error rows --}}
|
||
|
|
@foreach($formulaErrors as $fe)
|
||
|
|
@php
|
||
|
|
$rowData = $fe['data'] ?? [];
|
||
|
|
@endphp
|
||
|
|
@if(!empty($rowData))
|
||
|
|
<tr class="table-danger">
|
||
|
|
<td>{{ $fe['excel_row'] }}</td>
|
||
|
|
<td>{{ $fe['mark_no'] }}</td>
|
||
|
|
@foreach($headings as $head)
|
||
|
|
<td>{{ $rowData[$head] ?? '' }}</td>
|
||
|
|
@endforeach
|
||
|
|
</tr>
|
||
|
|
@endif
|
||
|
|
@endforeach
|
||
|
|
|
||
|
|
{{-- Mark error rows --}}
|
||
|
|
@foreach($markErrors as $me)
|
||
|
|
@php
|
||
|
|
$rowData = $me['data'] ?? [];
|
||
|
|
@endphp
|
||
|
|
@if(!empty($rowData))
|
||
|
|
<tr class="table-warning">
|
||
|
|
<td>{{ $me['excel_row'] }}</td>
|
||
|
|
<td>{{ $me['mark_no'] }}</td>
|
||
|
|
@foreach($headings as $head)
|
||
|
|
<td>{{ $rowData[$head] ?? '' }}</td>
|
||
|
|
@endforeach
|
||
|
|
</tr>
|
||
|
|
@endif
|
||
|
|
@endforeach
|
||
|
|
</tbody>
|
||
|
|
</table>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
@endif
|
||
|
|
|
||
|
|
{{-- 2) Detailed per-row error boxes BELOW the table --}}
|
||
|
|
<div class="card error-card mb-3">
|
||
|
|
<div class="card-header bg-light small">
|
||
|
|
Detailed error messages
|
||
|
|
</div>
|
||
|
|
<div class="card-body">
|
||
|
|
|
||
|
|
{{-- Formula Errors (detailed) --}}
|
||
|
|
@if(session('formula_errors'))
|
||
|
|
@foreach(session('formula_errors') as $fe)
|
||
|
|
<div class="error-row-box">
|
||
|
|
<div class="error-title">
|
||
|
|
Row {{ $fe['excel_row'] }}
|
||
|
|
@if($fe['mark_no']) | Mark: {{ $fe['mark_no'] }} @endif
|
||
|
|
@if($fe['description']) | {{ $fe['description'] }} @endif
|
||
|
|
</div>
|
||
|
|
|
||
|
|
@foreach($fe['errors'] as $field => $detail)
|
||
|
|
<div class="error-item text-danger">
|
||
|
|
❌ <span>{{ $field }}</span> →
|
||
|
|
Expected: {{ number_format($detail['expected'],4) }}
|
||
|
|
| Got: {{ number_format($detail['actual'],4) }}
|
||
|
|
</div>
|
||
|
|
@endforeach
|
||
|
|
</div>
|
||
|
|
@endforeach
|
||
|
|
@endif
|
||
|
|
|
||
|
|
{{-- Mark Errors (detailed) --}}
|
||
|
|
@if(session('mark_errors'))
|
||
|
|
@foreach(session('mark_errors') as $me)
|
||
|
|
<div class="error-row-box bg-warning bg-opacity-10 border-warning">
|
||
|
|
<div class="error-title">
|
||
|
|
Row {{ $me['excel_row'] }}
|
||
|
|
</div>
|
||
|
|
<div class="error-item text-warning">
|
||
|
|
❌ Mark <strong>{{ $me['mark_no'] }}</strong> not found in database
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
@endforeach
|
||
|
|
@endif
|
||
|
|
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
@endif
|
||
|
|
|
||
|
|
{{-- FORM --}}
|
||
|
|
@if (!session('formula_errors') && !session('mark_errors'))
|
||
|
|
<form action="{{ route('containers.store') }}" method="POST" enctype="multipart/form-data" class="mt-3">
|
||
|
|
@csrf
|
||
|
|
|
||
|
|
<div class="row g-3">
|
||
|
|
<div class="col-md-6">
|
||
|
|
<label class="cm-form-label">Container Name</label>
|
||
|
|
<input type="text" name="container_name"
|
||
|
|
class="form-control cm-form-control"
|
||
|
|
value="{{ old('container_name') }}"
|
||
|
|
placeholder="Enter container name">
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="col-md-6">
|
||
|
|
<label class="cm-form-label">Container Number</label>
|
||
|
|
<input type="text" name="container_number"
|
||
|
|
class="form-control cm-form-control"
|
||
|
|
value="{{ old('container_number') }}"
|
||
|
|
placeholder="Enter container number">
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="col-md-6">
|
||
|
|
<label class="cm-form-label">Container Date</label>
|
||
|
|
<input type="date" name="container_date"
|
||
|
|
class="form-control cm-form-control"
|
||
|
|
value="{{ old('container_date') }}">
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="col-md-6">
|
||
|
|
<label class="cm-form-label">Loading List Excel</label>
|
||
|
|
<input type="file" name="excel_file"
|
||
|
|
class="form-control cm-form-control"
|
||
|
|
accept=".xls,.xlsx">
|
||
|
|
<div class="cm-help-text">
|
||
|
|
Upload Kent loading list Excel file (.xls / .xlsx).
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="mt-4 d-flex gap-2">
|
||
|
|
<button type="submit" class="btn btn-primary cm-btn-primary">
|
||
|
|
Save Container
|
||
|
|
</button>
|
||
|
|
<a href="{{ route('containers.index') }}" class="btn btn-outline-secondary cm-btn-secondary">
|
||
|
|
Cancel
|
||
|
|
</a>
|
||
|
|
</div>
|
||
|
|
</form>
|
||
|
|
@endif
|
||
|
|
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
@endsection
|