292 lines
9.0 KiB
PHP
292 lines
9.0 KiB
PHP
|
|
@extends('admin.layouts.app')
|
|||
|
|
|
|||
|
|
@section('page-title', 'Container Details')
|
|||
|
|
|
|||
|
|
@section('content')
|
|||
|
|
<style>
|
|||
|
|
.cm-detail-wrapper {
|
|||
|
|
padding: 10px 0 20px 0;
|
|||
|
|
}
|
|||
|
|
.cm-detail-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-detail-header-card .card-body {
|
|||
|
|
padding: 14px 18px;
|
|||
|
|
display:flex;
|
|||
|
|
justify-content:space-between;
|
|||
|
|
align-items:center;
|
|||
|
|
gap:10px;
|
|||
|
|
}
|
|||
|
|
.cm-detail-title {
|
|||
|
|
margin:0;
|
|||
|
|
font-size:20px;
|
|||
|
|
font-weight:600;
|
|||
|
|
}
|
|||
|
|
.cm-detail-sub {
|
|||
|
|
font-size:12px;
|
|||
|
|
opacity:0.9;
|
|||
|
|
}
|
|||
|
|
.cm-detail-main-card {
|
|||
|
|
border-radius:14px;
|
|||
|
|
border:none;
|
|||
|
|
box-shadow:0 6px 18px rgba(15,35,52,0.12);
|
|||
|
|
overflow:hidden;
|
|||
|
|
}
|
|||
|
|
.cm-detail-main-card .card-header {
|
|||
|
|
background:#ffffff;
|
|||
|
|
border-bottom:1px solid #edf0f5;
|
|||
|
|
padding:10px 18px;
|
|||
|
|
display:flex;
|
|||
|
|
justify-content:space-between;
|
|||
|
|
align-items:center;
|
|||
|
|
gap:10px;
|
|||
|
|
}
|
|||
|
|
.cm-detail-main-card .card-header h5 {
|
|||
|
|
margin:0;
|
|||
|
|
font-size:16px;
|
|||
|
|
font-weight:600;
|
|||
|
|
}
|
|||
|
|
.cm-info-label {
|
|||
|
|
font-size:12px;
|
|||
|
|
color:#6c757d;
|
|||
|
|
font-weight:500;
|
|||
|
|
}
|
|||
|
|
.cm-info-value {
|
|||
|
|
font-size:13px;
|
|||
|
|
font-weight:500;
|
|||
|
|
color:#343a40;
|
|||
|
|
}
|
|||
|
|
.cm-table-wrapper {
|
|||
|
|
position:relative;
|
|||
|
|
max-height: 520px;
|
|||
|
|
overflow:auto;
|
|||
|
|
border-top:1px solid #edf0f5;
|
|||
|
|
}
|
|||
|
|
.cm-table {
|
|||
|
|
font-size:11.5px;
|
|||
|
|
min-width: 1100px;
|
|||
|
|
}
|
|||
|
|
.cm-table thead th {
|
|||
|
|
position: sticky;
|
|||
|
|
top: 0;
|
|||
|
|
z-index: 2;
|
|||
|
|
background: #fff7e0;
|
|||
|
|
color:#495057;
|
|||
|
|
font-weight:600;
|
|||
|
|
border-bottom:1px solid #e0d2a4;
|
|||
|
|
white-space:nowrap;
|
|||
|
|
}
|
|||
|
|
.cm-table tbody tr:nth-child(even) {
|
|||
|
|
background:#fafbff;
|
|||
|
|
}
|
|||
|
|
.cm-table tbody tr:hover {
|
|||
|
|
background:#e9f3ff;
|
|||
|
|
}
|
|||
|
|
.cm-table td,
|
|||
|
|
.cm-table th {
|
|||
|
|
padding:4px 6px;
|
|||
|
|
vertical-align:middle;
|
|||
|
|
}
|
|||
|
|
.cm-table td {
|
|||
|
|
white-space:nowrap;
|
|||
|
|
}
|
|||
|
|
.cm-table-caption {
|
|||
|
|
font-size:11px;
|
|||
|
|
color:#868e96;
|
|||
|
|
padding:6px 18px 0 18px;
|
|||
|
|
}
|
|||
|
|
.cm-filter-bar {
|
|||
|
|
padding:8px 18px 0 18px;
|
|||
|
|
display:flex;
|
|||
|
|
justify-content:space-between;
|
|||
|
|
align-items:center;
|
|||
|
|
gap:10px;
|
|||
|
|
flex-wrap:wrap;
|
|||
|
|
}
|
|||
|
|
.cm-filter-input {
|
|||
|
|
max-width:240px;
|
|||
|
|
font-size:12px;
|
|||
|
|
border-radius:20px;
|
|||
|
|
padding:6px 10px;
|
|||
|
|
}
|
|||
|
|
.cm-edit-save-btn {
|
|||
|
|
font-size:12px;
|
|||
|
|
border-radius:20px;
|
|||
|
|
padding:6px 14px;
|
|||
|
|
}
|
|||
|
|
.cm-cell-input {
|
|||
|
|
width: 140px;
|
|||
|
|
min-width: 120px;
|
|||
|
|
max-width: 220px;
|
|||
|
|
font-size:11px;
|
|||
|
|
padding:3px 4px;
|
|||
|
|
height: 26px;
|
|||
|
|
}
|
|||
|
|
@media (max-width: 767px) {
|
|||
|
|
.cm-detail-header-card .card-body {
|
|||
|
|
flex-direction:column;
|
|||
|
|
align-items:flex-start;
|
|||
|
|
}
|
|||
|
|
.cm-table-wrapper {
|
|||
|
|
max-height:400px;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</style>
|
|||
|
|
|
|||
|
|
<div class="container-fluid cm-detail-wrapper">
|
|||
|
|
|
|||
|
|
{{-- TOP GRADIENT HEADER --}}
|
|||
|
|
<div class="card cm-detail-header-card">
|
|||
|
|
<div class="card-body">
|
|||
|
|
<div>
|
|||
|
|
<h4 class="cm-detail-title">
|
|||
|
|
Container: {{ $container->container_number }}
|
|||
|
|
</h4>
|
|||
|
|
<div class="cm-detail-sub">
|
|||
|
|
Edit loading list directly – scroll horizontally and vertically like Excel.
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<a href="{{ route('containers.index') }}" class="btn btn-light btn-sm">
|
|||
|
|
← Back to list
|
|||
|
|
</a>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{{-- MAIN CARD --}}
|
|||
|
|
<div class="card cm-detail-main-card">
|
|||
|
|
<div class="card-header">
|
|||
|
|
<h5>Container Information</h5>
|
|||
|
|
|
|||
|
|
@if(!$container->rows->isEmpty())
|
|||
|
|
{{-- Save button (submits form below) --}}
|
|||
|
|
<button type="submit"
|
|||
|
|
form="cm-edit-rows-form"
|
|||
|
|
class="btn btn-primary cm-edit-save-btn">
|
|||
|
|
💾 Save Changes
|
|||
|
|
</button>
|
|||
|
|
@endif
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="card-body pb-0">
|
|||
|
|
{{-- BASIC INFO --}}
|
|||
|
|
<div class="row g-3 mb-2">
|
|||
|
|
<div class="col-md-4">
|
|||
|
|
<div class="cm-info-label">Container</div>
|
|||
|
|
<div class="cm-info-value">{{ $container->container_name }}</div>
|
|||
|
|
</div>
|
|||
|
|
<div class="col-md-4">
|
|||
|
|
<div class="cm-info-label">Date</div>
|
|||
|
|
<div class="cm-info-value">
|
|||
|
|
{{ $container->container_date?->format('d-m-Y') }}
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<div class="col-md-4">
|
|||
|
|
<div class="cm-info-label">Excel File</div>
|
|||
|
|
@if($container->excel_file)
|
|||
|
|
<div class="cm-info-value">
|
|||
|
|
<a href="{{ \Illuminate\Support\Facades\Storage::url($container->excel_file) }}"
|
|||
|
|
target="_blank">
|
|||
|
|
Download / View Excel
|
|||
|
|
</a>
|
|||
|
|
</div>
|
|||
|
|
@else
|
|||
|
|
<div class="cm-info-value text-muted">Not uploaded</div>
|
|||
|
|
@endif
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
@if($container->rows->isEmpty())
|
|||
|
|
<div class="p-3">
|
|||
|
|
<p class="mb-0">No entries found for this container.</p>
|
|||
|
|
</div>
|
|||
|
|
@else
|
|||
|
|
@php
|
|||
|
|
// सर्व headings collect
|
|||
|
|
$allHeadings = [];
|
|||
|
|
foreach ($container->rows as $row) {
|
|||
|
|
if (is_array($row->data)) {
|
|||
|
|
$allHeadings = array_unique(array_merge($allHeadings, array_keys($row->data)));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
@endphp
|
|||
|
|
|
|||
|
|
{{-- FILTER BAR --}}
|
|||
|
|
<div class="cm-filter-bar">
|
|||
|
|
<div class="cm-table-caption">
|
|||
|
|
Total rows: {{ $container->rows->count() }} • Type to filter rows, edit cells then click "Save Changes".
|
|||
|
|
</div>
|
|||
|
|
<input type="text" id="cmRowSearch" class="form-control cm-filter-input"
|
|||
|
|
placeholder="Quick search in table..." onkeyup="cmFilterRows()">
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{{-- EDITABLE TABLE FORM --}}
|
|||
|
|
<form id="cm-edit-rows-form"
|
|||
|
|
action="{{ route('containers.rows.update', $container->id) }}"
|
|||
|
|
method="POST">
|
|||
|
|
@csrf
|
|||
|
|
|
|||
|
|
<div class="cm-table-wrapper mt-1">
|
|||
|
|
<table class="table table-bordered table-hover cm-table" id="cmExcelTable">
|
|||
|
|
<thead>
|
|||
|
|
<tr>
|
|||
|
|
@foreach($allHeadings as $heading)
|
|||
|
|
<th>{{ $heading }}</th>
|
|||
|
|
@endforeach
|
|||
|
|
</tr>
|
|||
|
|
</thead>
|
|||
|
|
<tbody>
|
|||
|
|
@foreach($container->rows as $row)
|
|||
|
|
<tr>
|
|||
|
|
@foreach($allHeadings as $heading)
|
|||
|
|
@php
|
|||
|
|
$value = $row->data[$heading] ?? '';
|
|||
|
|
@endphp
|
|||
|
|
<td>
|
|||
|
|
<input type="text"
|
|||
|
|
class="form-control form-control-sm cm-cell-input"
|
|||
|
|
name="rows[{{ $row->id }}][{{ $heading }}]"
|
|||
|
|
value="{{ $value }}">
|
|||
|
|
</td>
|
|||
|
|
@endforeach
|
|||
|
|
</tr>
|
|||
|
|
@endforeach
|
|||
|
|
</tbody>
|
|||
|
|
</table>
|
|||
|
|
</div>
|
|||
|
|
</form>
|
|||
|
|
@endif
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
{{-- SIMPLE FRONT‑END SEARCH --}}
|
|||
|
|
<script>
|
|||
|
|
function cmFilterRows() {
|
|||
|
|
const input = document.getElementById('cmRowSearch');
|
|||
|
|
if (!input) return;
|
|||
|
|
const filter = input.value.toLowerCase();
|
|||
|
|
const table = document.getElementById('cmExcelTable');
|
|||
|
|
if (!table) return;
|
|||
|
|
|
|||
|
|
const rows = table.getElementsByTagName('tr');
|
|||
|
|
for (let i = 1; i < rows.length; i++) { // skip header
|
|||
|
|
const cells = rows[i].getElementsByTagName('td');
|
|||
|
|
let match = false;
|
|||
|
|
for (let j = 0; j < cells.length; j++) {
|
|||
|
|
const txt = cells[j].textContent || cells[j].innerText;
|
|||
|
|
if (txt.toLowerCase().indexOf(filter) > -1) {
|
|||
|
|
match = true;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
rows[i].style.display = match ? '' : 'none';
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</script>
|
|||
|
|
@endsection
|