2026-02-27 10:51:26 +05:30
|
|
|
|
@extends('admin.layouts.app')
|
|
|
|
|
|
|
|
|
|
|
|
@section('page-title', 'Container Details')
|
|
|
|
|
|
|
|
|
|
|
|
@section('content')
|
|
|
|
|
|
<style>
|
|
|
|
|
|
@import url('https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&display=swap');
|
|
|
|
|
|
|
2026-03-09 10:24:44 +05:30
|
|
|
|
html, body {
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
overflow-x: hidden;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-27 10:51:26 +05:30
|
|
|
|
.cm-header-card {
|
|
|
|
|
|
background: linear-gradient(100deg, #4c6fff 0%, #8e54e9 100%);
|
|
|
|
|
|
border-radius: 14px;
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
box-shadow: 0 6px 24px rgba(76,111,255,0.22);
|
|
|
|
|
|
margin-bottom: 18px;
|
|
|
|
|
|
color: #fff;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-header-card .card-body {
|
|
|
|
|
|
padding: 14px 20px;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-header-title {
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
font-size: 19px;
|
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
|
letter-spacing: -0.3px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-header-sub {
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
opacity: 0.88;
|
|
|
|
|
|
margin-top: 2px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.cm-main-card {
|
|
|
|
|
|
border-radius: 14px;
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
box-shadow: 0 4px 20px rgba(15,35,52,0.10);
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
background: #fff;
|
2026-03-09 10:24:44 +05:30
|
|
|
|
position: relative;
|
2026-02-27 10:51:26 +05:30
|
|
|
|
}
|
|
|
|
|
|
.cm-main-card .card-header {
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
border-bottom: 1px solid #edf0f5;
|
|
|
|
|
|
padding: 12px 20px;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-main-card .card-header h5 {
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
font-size: 15px;
|
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
|
color: #1a2340;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-09 10:24:44 +05:30
|
|
|
|
.cm-info-cards-row {
|
|
|
|
|
|
display: grid;
|
|
|
|
|
|
grid-template-columns: repeat(3, minmax(0, 1fr)); /* 3 cards one row */
|
|
|
|
|
|
gap: 14px;
|
|
|
|
|
|
padding: 14px 18px 8px 18px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-info-card {
|
|
|
|
|
|
border-radius: 16px;
|
|
|
|
|
|
padding: 12px 14px;
|
2026-02-27 10:51:26 +05:30
|
|
|
|
display: flex;
|
2026-03-09 10:24:44 +05:30
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 10px;
|
|
|
|
|
|
box-shadow: 0 4px 16px rgba(15,35,52,0.12);
|
|
|
|
|
|
border: 1px solid rgba(148,163,184,0.25);
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
min-height: 70px;
|
2026-02-27 10:51:26 +05:30
|
|
|
|
}
|
2026-03-09 10:24:44 +05:30
|
|
|
|
.cm-info-card-icon {
|
|
|
|
|
|
width: 32px;
|
|
|
|
|
|
height: 32px;
|
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
color: #0f172a;
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
box-shadow: 0 3px 10px rgba(15,23,42,0.10);
|
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-info-card-body {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
gap: 3px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-info-card-label {
|
2026-02-27 10:51:26 +05:30
|
|
|
|
font-size: 11px;
|
|
|
|
|
|
text-transform: uppercase;
|
2026-03-09 10:24:44 +05:30
|
|
|
|
letter-spacing: 0.4px;
|
|
|
|
|
|
color: #64748b;
|
|
|
|
|
|
font-weight: 600;
|
2026-02-27 10:51:26 +05:30
|
|
|
|
}
|
2026-03-09 10:24:44 +05:30
|
|
|
|
.cm-info-card-value {
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
|
color: #0f172a;
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-card-container {
|
|
|
|
|
|
background: linear-gradient(135deg, #e0f2ff, #eef4ff);
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-card-container .cm-info-card-icon {
|
|
|
|
|
|
background: linear-gradient(135deg, #2563eb, #4f46e5);
|
|
|
|
|
|
color: #e5edff;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-card-date {
|
|
|
|
|
|
background: linear-gradient(135deg, #ecfdf3, #e0fbea);
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-card-date .cm-info-card-icon {
|
|
|
|
|
|
background: linear-gradient(135deg, #16a34a, #22c55e);
|
|
|
|
|
|
color: #ecfdf3;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-card-excel {
|
|
|
|
|
|
background: linear-gradient(135deg, #fff7ed, #fffbeb);
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-card-excel .cm-info-card-icon {
|
|
|
|
|
|
background: linear-gradient(135deg, #f97316, #fb923c);
|
|
|
|
|
|
color: #fff7ed;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* TOTAL BOXES */
|
|
|
|
|
|
.cm-total-cards-row {
|
|
|
|
|
|
display: grid;
|
|
|
|
|
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
|
|
|
|
gap: 14px;
|
|
|
|
|
|
padding: 4px 18px 14px 18px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-total-card {
|
|
|
|
|
|
border-radius: 18px;
|
|
|
|
|
|
padding: 12px 18px;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 10px;
|
|
|
|
|
|
box-shadow: 0 8px 30px rgba(15,23,42,0.08);
|
|
|
|
|
|
border: 1px solid rgba(148,163,184,0.25);
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-total-icon {
|
|
|
|
|
|
width: 34px;
|
|
|
|
|
|
height: 34px;
|
|
|
|
|
|
border-radius: 999px;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
font-size: 17px;
|
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
|
color: #0f172a;
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
box-shadow: 0 4px 14px rgba(15,23,42,0.15);
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-total-text {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
gap: 3px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-total-label {
|
|
|
|
|
|
font-size: 11px;
|
2026-02-27 10:51:26 +05:30
|
|
|
|
font-weight: 600;
|
2026-03-09 10:24:44 +05:30
|
|
|
|
color: #4b5563;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-total-value {
|
|
|
|
|
|
font-size: 18px;
|
|
|
|
|
|
font-weight: 800;
|
|
|
|
|
|
color: #111827;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-total-card-ctn {
|
|
|
|
|
|
background: linear-gradient(135deg, #e0f2ff, #eef2ff);
|
|
|
|
|
|
border-left: 4px solid #3b82f6;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-total-card-qty {
|
|
|
|
|
|
background: linear-gradient(135deg, #dcfce7, #ecfdf5);
|
|
|
|
|
|
border-left: 4px solid #22c55e;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-total-card-cbm {
|
|
|
|
|
|
background: linear-gradient(135deg, #fef9c3, #fffbeb);
|
|
|
|
|
|
border-left: 4px solid #f59e0b;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-total-card-kg {
|
|
|
|
|
|
background: linear-gradient(135deg, #fee2e2, #fef2f2);
|
|
|
|
|
|
border-left: 4px solid #ef4444;
|
2026-02-27 10:51:26 +05:30
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.cm-filter-bar {
|
2026-03-09 10:24:44 +05:30
|
|
|
|
padding: 4px 20px 0 20px;
|
2026-02-27 10:51:26 +05:30
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
gap: 10px;
|
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-row-count {
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
color: #8a93a6;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-filter-input {
|
|
|
|
|
|
max-width: 240px;
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
border-radius: 20px;
|
|
|
|
|
|
border: 1px solid #dde2ee;
|
|
|
|
|
|
padding: 6px 14px;
|
|
|
|
|
|
outline: none;
|
|
|
|
|
|
transition: border 0.2s;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-filter-input:focus {
|
|
|
|
|
|
border-color: #4c6fff;
|
|
|
|
|
|
box-shadow: 0 0 0 3px rgba(76,111,255,0.1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.cm-table-scroll-outer {
|
|
|
|
|
|
margin: 10px 14px 0 14px;
|
2026-03-09 10:24:44 +05:30
|
|
|
|
border-radius: 14px;
|
|
|
|
|
|
border: 1.5px solid #c9a359;
|
|
|
|
|
|
box-shadow: 0 4px 14px rgba(76,111,255,0.18);
|
|
|
|
|
|
overflow-x: auto;
|
|
|
|
|
|
overflow-y: hidden;
|
|
|
|
|
|
position: relative;
|
2026-02-27 10:51:26 +05:30
|
|
|
|
}
|
|
|
|
|
|
.cm-table-wrapper {
|
|
|
|
|
|
position: relative;
|
2026-03-09 10:24:44 +05:30
|
|
|
|
min-width: 1200px;
|
2026-02-27 10:51:26 +05:30
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.cm-table {
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
border-collapse: separate;
|
|
|
|
|
|
border-spacing: 0;
|
|
|
|
|
|
font-family: 'DM Sans', sans-serif;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-table thead tr th {
|
|
|
|
|
|
position: sticky;
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
z-index: 3;
|
2026-03-09 10:24:44 +05:30
|
|
|
|
background: linear-gradient(100deg, #fde4b3 0%, #fbd48a 100%);
|
|
|
|
|
|
color: #0c0909;
|
2026-02-27 10:51:26 +05:30
|
|
|
|
font-weight: 700;
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
padding: 11px 14px;
|
2026-03-09 10:24:44 +05:30
|
|
|
|
border-bottom: 2px solid rgba(255,255,255,0.15);
|
|
|
|
|
|
border-right: 1px solid rgba(255,255,255,0.18);
|
2026-02-27 10:51:26 +05:30
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
letter-spacing: 0.2px;
|
2026-03-09 10:24:44 +05:30
|
|
|
|
text-shadow: 0 1px 2px rgba(0,0,0,0.35);
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-table thead tr th:first-child {
|
|
|
|
|
|
border-top-left-radius: 10px;
|
2026-02-27 10:51:26 +05:30
|
|
|
|
}
|
|
|
|
|
|
.cm-table thead tr th:last-child {
|
2026-03-09 10:24:44 +05:30
|
|
|
|
border-top-right-radius: 10px;
|
2026-02-27 10:51:26 +05:30
|
|
|
|
border-right: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-table thead tr th:first-child,
|
|
|
|
|
|
.cm-table tbody tr td:first-child {
|
|
|
|
|
|
width: 46px;
|
|
|
|
|
|
min-width: 46px;
|
|
|
|
|
|
max-width: 46px;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-table tbody tr td {
|
|
|
|
|
|
padding: 8px 14px;
|
|
|
|
|
|
border-bottom: 1px solid #f0f3fb;
|
|
|
|
|
|
border-right: 1px solid #f0f3fb;
|
|
|
|
|
|
color: #2d3a55;
|
|
|
|
|
|
font-size: 12.5px;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
vertical-align: middle;
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
transition: background 0.15s;
|
2026-03-09 10:24:44 +05:30
|
|
|
|
white-space: nowrap;
|
2026-02-27 10:51:26 +05:30
|
|
|
|
}
|
|
|
|
|
|
.cm-table tbody tr td:last-child {
|
|
|
|
|
|
border-right: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-table tbody tr:nth-child(even) td {
|
|
|
|
|
|
background: #f8f9ff;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-table tbody tr:hover td {
|
|
|
|
|
|
background: #edf3ff !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-row-num {
|
|
|
|
|
|
color: #8a93a6;
|
|
|
|
|
|
font-size: 11px;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.cm-cell-input {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
min-width: 90px;
|
|
|
|
|
|
background: transparent;
|
|
|
|
|
|
border: 1.5px solid transparent;
|
|
|
|
|
|
border-radius: 5px;
|
|
|
|
|
|
font-size: 12.5px;
|
|
|
|
|
|
font-family: 'DM Sans', sans-serif;
|
|
|
|
|
|
color: #2d3a55;
|
|
|
|
|
|
padding: 3px 6px;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
transition: border 0.15s, background 0.15s, box-shadow 0.15s;
|
|
|
|
|
|
outline: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-cell-input:hover {
|
|
|
|
|
|
border-color: #c9d4f5;
|
|
|
|
|
|
background: #f5f8ff;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-cell-input:focus {
|
|
|
|
|
|
border-color: #4c6fff;
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
box-shadow: 0 0 0 3px rgba(76,111,255,0.12);
|
|
|
|
|
|
}
|
2026-03-09 10:24:44 +05:30
|
|
|
|
.cm-cell-readonly {
|
|
|
|
|
|
background: #f3f4ff;
|
|
|
|
|
|
cursor: not-allowed;
|
|
|
|
|
|
border-color: #e2e3ff;
|
|
|
|
|
|
}
|
2026-02-27 10:51:26 +05:30
|
|
|
|
|
2026-03-09 10:24:44 +05:30
|
|
|
|
.cm-save-btn-floating {
|
|
|
|
|
|
position: fixed;
|
|
|
|
|
|
right: 26px;
|
|
|
|
|
|
bottom: 22px;
|
|
|
|
|
|
z-index: 50;
|
|
|
|
|
|
font-size: 13px;
|
2026-02-27 10:51:26 +05:30
|
|
|
|
font-weight: 600;
|
2026-03-09 10:24:44 +05:30
|
|
|
|
border-radius: 22px;
|
|
|
|
|
|
padding: 8px 20px;
|
2026-02-27 10:51:26 +05:30
|
|
|
|
background: linear-gradient(90deg, #4c6fff, #8e54e9);
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
color: #fff;
|
2026-03-09 10:24:44 +05:30
|
|
|
|
box-shadow: 0 4px 16px rgba(76,111,255,0.35);
|
2026-02-27 10:51:26 +05:30
|
|
|
|
transition: opacity 0.2s, transform 0.15s;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
}
|
2026-03-09 10:24:44 +05:30
|
|
|
|
.cm-save-btn-floating:hover {
|
|
|
|
|
|
opacity: 0.94;
|
2026-02-27 10:51:26 +05:30
|
|
|
|
transform: translateY(-1px);
|
|
|
|
|
|
}
|
2026-03-09 10:24:44 +05:30
|
|
|
|
.cm-save-btn-floating.cm-disabled {
|
|
|
|
|
|
opacity: 0.6;
|
|
|
|
|
|
cursor: default;
|
|
|
|
|
|
pointer-events: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.cm-toast {
|
|
|
|
|
|
position: fixed;
|
|
|
|
|
|
right: 26px;
|
|
|
|
|
|
bottom: 70px;
|
|
|
|
|
|
background: #0f172a;
|
|
|
|
|
|
color: #f9fafb;
|
|
|
|
|
|
font-size: 12.5px;
|
|
|
|
|
|
padding: 8px 14px;
|
|
|
|
|
|
border-radius: 10px;
|
|
|
|
|
|
box-shadow: 0 8px 24px rgba(15,23,42,0.25);
|
|
|
|
|
|
opacity: 0;
|
|
|
|
|
|
pointer-events: none;
|
|
|
|
|
|
transition: opacity 0.25s, transform 0.2s;
|
|
|
|
|
|
transform: translateY(8px);
|
|
|
|
|
|
z-index: 60;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-toast.cm-show {
|
|
|
|
|
|
opacity: 1;
|
|
|
|
|
|
pointer-events: auto;
|
|
|
|
|
|
transform: translateY(0);
|
|
|
|
|
|
}
|
2026-02-27 10:51:26 +05:30
|
|
|
|
|
|
|
|
|
|
.cm-empty {
|
|
|
|
|
|
padding: 30px 20px;
|
|
|
|
|
|
color: #8a93a6;
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-09 10:24:44 +05:30
|
|
|
|
.cm-table-scroll-outer::-webkit-scrollbar {
|
|
|
|
|
|
height: 6px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-table-scroll-outer::-webkit-scrollbar-track {
|
|
|
|
|
|
background: #f0f3fb;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-table-scroll-outer::-webkit-scrollbar-thumb {
|
|
|
|
|
|
background: #c5cce8;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-table-scroll-outer::-webkit-scrollbar-thumb:hover {
|
|
|
|
|
|
background: #8a99d0;
|
|
|
|
|
|
}
|
2026-02-27 10:51:26 +05:30
|
|
|
|
|
2026-03-09 10:24:44 +05:30
|
|
|
|
@media (max-width: 991px) {
|
|
|
|
|
|
.cm-total-cards-row {
|
|
|
|
|
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-02-27 10:51:26 +05:30
|
|
|
|
@media (max-width: 767px) {
|
2026-03-09 10:24:44 +05:30
|
|
|
|
.cm-header-card .card-body {
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
align-items: flex-start;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-info-cards-row {
|
|
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-table-scroll-outer {
|
|
|
|
|
|
overflow-x: auto;
|
|
|
|
|
|
}
|
|
|
|
|
|
.cm-table-wrapper {
|
|
|
|
|
|
min-width: 900px;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
@media (max-width: 575px) {
|
|
|
|
|
|
.cm-total-cards-row {
|
|
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
|
|
}
|
2026-02-27 10:51:26 +05:30
|
|
|
|
}
|
|
|
|
|
|
</style>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="container-fluid cm-wrapper">
|
|
|
|
|
|
<div class="card cm-header-card">
|
|
|
|
|
|
<div class="card-body">
|
|
|
|
|
|
<div>
|
2026-03-09 10:24:44 +05:30
|
|
|
|
<h4 class="cm-header-title">Container {{ $container->container_number }}</h4>
|
2026-02-27 10:51:26 +05:30
|
|
|
|
<div class="cm-header-sub">
|
2026-03-09 10:24:44 +05:30
|
|
|
|
Edit loading list directly – like Excel. TT columns auto‑calculate from CTN, QTY, CBM, KG, PRICE.
|
2026-02-27 10:51:26 +05:30
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2026-03-09 10:24:44 +05:30
|
|
|
|
<div class="d-flex gap-2">
|
|
|
|
|
|
<a href="{{ route('containers.index') }}" class="btn btn-light btn-sm">Back to list</a>
|
|
|
|
|
|
|
|
|
|
|
|
<a href="{{ route('containers.download.pdf', $container->id) }}"
|
|
|
|
|
|
class="btn btn-sm btn-outline-primary">
|
|
|
|
|
|
Download PDF
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
<a href="{{ route('containers.download.excel', $container->id) }}"
|
|
|
|
|
|
class="btn btn-sm btn-outline-success">
|
|
|
|
|
|
Download Excel
|
|
|
|
|
|
</a>
|
|
|
|
|
|
</div>
|
2026-02-27 10:51:26 +05:30
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="card cm-main-card">
|
|
|
|
|
|
<div class="card-header">
|
|
|
|
|
|
<h5>Container Information</h5>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
2026-03-09 10:24:44 +05:30
|
|
|
|
{{-- 3 INFO CARDS IN SINGLE ROW --}}
|
|
|
|
|
|
<div class="cm-info-cards-row">
|
|
|
|
|
|
<div class="cm-info-card cm-card-container">
|
|
|
|
|
|
<div class="cm-info-card-icon">
|
|
|
|
|
|
<i class="bi bi-box-seam"></i>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="cm-info-card-body">
|
|
|
|
|
|
<div class="cm-info-card-label">Container</div>
|
|
|
|
|
|
<div class="cm-info-card-value">
|
|
|
|
|
|
{{ $container->container_name ?? $container->container_number }}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2026-02-27 10:51:26 +05:30
|
|
|
|
</div>
|
2026-03-09 10:24:44 +05:30
|
|
|
|
|
|
|
|
|
|
<div class="cm-info-card cm-card-date">
|
|
|
|
|
|
<div class="cm-info-card-icon">
|
|
|
|
|
|
<i class="bi bi-calendar-event"></i>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="cm-info-card-body">
|
|
|
|
|
|
<div class="cm-info-card-label">Date</div>
|
|
|
|
|
|
<div class="cm-info-card-value">
|
|
|
|
|
|
{{ $container->container_date ? $container->container_date->format('d-m-Y') : '' }}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2026-02-27 10:51:26 +05:30
|
|
|
|
</div>
|
2026-03-09 10:24:44 +05:30
|
|
|
|
|
|
|
|
|
|
<div class="cm-info-card cm-card-excel">
|
|
|
|
|
|
<div class="cm-info-card-icon">
|
|
|
|
|
|
<i class="bi bi-file-earmark-excel"></i>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="cm-info-card-body">
|
|
|
|
|
|
<div class="cm-info-card-label">Excel File</div>
|
|
|
|
|
|
<div class="cm-info-card-value">
|
|
|
|
|
|
@if($container->excel_file)
|
|
|
|
|
|
<a href="{{ url($container->excel_file) }}" target="_blank" style="color:#0f172a;text-decoration:none;">
|
|
|
|
|
|
Download / View
|
|
|
|
|
|
</a>
|
|
|
|
|
|
@else
|
|
|
|
|
|
<span style="color:#b0b8cc;">Not uploaded</span>
|
|
|
|
|
|
@endif
|
2026-02-27 10:51:26 +05:30
|
|
|
|
</div>
|
2026-03-09 10:24:44 +05:30
|
|
|
|
</div>
|
2026-02-27 10:51:26 +05:30
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
2026-03-09 10:24:44 +05:30
|
|
|
|
@php
|
|
|
|
|
|
$totalCtn = 0;
|
|
|
|
|
|
$totalQty = 0;
|
|
|
|
|
|
$totalCbm = 0.0;
|
|
|
|
|
|
$totalKg = 0.0;
|
|
|
|
|
|
|
|
|
|
|
|
if(!$container->rows->isEmpty()){
|
|
|
|
|
|
foreach ($container->rows as $row) {
|
|
|
|
|
|
if (!is_array($row->data)) continue;
|
|
|
|
|
|
foreach ($row->data as $h => $v) {
|
|
|
|
|
|
$norm = strtoupper(str_replace([' ', '/', '-', '.'],'', $h));
|
|
|
|
|
|
$val = is_numeric(str_replace([','], '', $v)) ? floatval(str_replace([','], '', $v)) : 0;
|
|
|
|
|
|
|
|
|
|
|
|
if (str_contains($norm, 'TOTALCTN') || $norm === 'CTN' || str_contains($norm,'TOTALCNTR') || str_contains($norm,'TOTALCARTON')) {
|
|
|
|
|
|
$totalCtn += $val;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
|
str_contains($norm,'TOTALQTY') ||
|
|
|
|
|
|
str_contains($norm,'ITLQTY') ||
|
|
|
|
|
|
str_contains($norm,'TTLQTY')
|
|
|
|
|
|
) {
|
|
|
|
|
|
$totalQty += $val;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
|
str_contains($norm,'TOTALCBM') ||
|
|
|
|
|
|
str_contains($norm,'TTLCBM') ||
|
|
|
|
|
|
str_contains($norm,'ITLCBM')
|
|
|
|
|
|
) {
|
|
|
|
|
|
$totalCbm += $val;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
|
str_contains($norm,'TOTALKG') ||
|
|
|
|
|
|
str_contains($norm,'TTKG')
|
|
|
|
|
|
) {
|
|
|
|
|
|
$totalKg += $val;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
@endphp
|
|
|
|
|
|
|
|
|
|
|
|
@if(!$container->rows->isEmpty())
|
|
|
|
|
|
<div class="cm-total-cards-row">
|
|
|
|
|
|
<div class="cm-total-card cm-total-card-ctn">
|
|
|
|
|
|
<div class="cm-total-icon">
|
|
|
|
|
|
<i class="bi bi-box"></i>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="cm-total-text">
|
|
|
|
|
|
<div class="cm-total-label">Total CTN</div>
|
|
|
|
|
|
<div class="cm-total-value">
|
|
|
|
|
|
{{ number_format($totalCtn, 0) }}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="cm-total-card cm-total-card-qty">
|
|
|
|
|
|
<div class="cm-total-icon">
|
|
|
|
|
|
<i class="bi bi-check-circle"></i>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="cm-total-text">
|
|
|
|
|
|
<div class="cm-total-label">Total QTY</div>
|
|
|
|
|
|
<div class="cm-total-value">
|
|
|
|
|
|
{{ number_format($totalQty, 0) }}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="cm-total-card cm-total-card-cbm">
|
|
|
|
|
|
<div class="cm-total-icon">
|
|
|
|
|
|
<i class="bi bi-border-width"></i>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="cm-total-text">
|
|
|
|
|
|
<div class="cm-total-label">Total CBM</div>
|
|
|
|
|
|
<div class="cm-total-value">
|
|
|
|
|
|
{{ number_format($totalCbm, 3) }}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="cm-total-card cm-total-card-kg">
|
|
|
|
|
|
<div class="cm-total-icon">
|
|
|
|
|
|
<i class="bi bi-exclamation-triangle"></i>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="cm-total-text">
|
|
|
|
|
|
<div class="cm-total-label">Total KG</div>
|
|
|
|
|
|
<div class="cm-total-value">
|
|
|
|
|
|
{{ number_format($totalKg, 2) }}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
@endif
|
|
|
|
|
|
|
2026-02-27 10:51:26 +05:30
|
|
|
|
@if($container->rows->isEmpty())
|
|
|
|
|
|
<div class="cm-empty">No entries found for this container.</div>
|
|
|
|
|
|
@else
|
|
|
|
|
|
@php
|
|
|
|
|
|
$allHeadings = [];
|
|
|
|
|
|
foreach ($container->rows as $row) {
|
|
|
|
|
|
if (is_array($row->data)) {
|
|
|
|
|
|
$allHeadings = array_unique(array_merge($allHeadings, array_keys($row->data)));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
@endphp
|
|
|
|
|
|
|
|
|
|
|
|
<div class="cm-filter-bar">
|
|
|
|
|
|
<span class="cm-row-count">
|
2026-03-09 10:24:44 +05:30
|
|
|
|
Total rows: {{ $container->rows->count() }} Edit cells then click "Save Changes".
|
2026-02-27 10:51:26 +05:30
|
|
|
|
</span>
|
2026-03-09 10:24:44 +05:30
|
|
|
|
<input type="text" id="cmRowSearch" class="cm-filter-input"
|
|
|
|
|
|
placeholder="Quick search..." onkeyup="cmFilterRows()">
|
2026-02-27 10:51:26 +05:30
|
|
|
|
</div>
|
|
|
|
|
|
|
2026-03-09 10:24:44 +05:30
|
|
|
|
<form id="cm-edit-rows-form" action="{{ route('containers.rows.update', $container->id) }}" method="POST">
|
2026-02-27 10:51:26 +05:30
|
|
|
|
@csrf
|
|
|
|
|
|
<div class="cm-table-scroll-outer">
|
2026-03-09 10:24:44 +05:30
|
|
|
|
<div class="cm-table-wrapper">
|
|
|
|
|
|
<table class="cm-table" id="cmExcelTable">
|
|
|
|
|
|
<thead>
|
2026-02-27 10:51:26 +05:30
|
|
|
|
<tr>
|
|
|
|
|
|
<th>#</th>
|
|
|
|
|
|
@foreach($allHeadings as $heading)
|
|
|
|
|
|
<th>{{ $heading }}</th>
|
|
|
|
|
|
@endforeach
|
|
|
|
|
|
</tr>
|
2026-03-09 10:24:44 +05:30
|
|
|
|
</thead>
|
|
|
|
|
|
<tbody>
|
2026-02-27 10:51:26 +05:30
|
|
|
|
@foreach($container->rows as $index => $row)
|
|
|
|
|
|
<tr>
|
|
|
|
|
|
<td class="cm-row-num">{{ $index + 1 }}</td>
|
|
|
|
|
|
@foreach($allHeadings as $heading)
|
2026-03-09 10:24:44 +05:30
|
|
|
|
@php
|
|
|
|
|
|
$value = $row->data[$heading] ?? '';
|
|
|
|
|
|
|
|
|
|
|
|
$norm = strtoupper(str_replace([' ', '/', '-', '.'],'', $heading));
|
|
|
|
|
|
|
|
|
|
|
|
$isCtn = str_contains($norm, 'CTN');
|
|
|
|
|
|
|
|
|
|
|
|
$isTotalQty = (
|
|
|
|
|
|
str_contains($norm, 'TOTALQTY') ||
|
|
|
|
|
|
str_contains($norm, 'ITLQTY') ||
|
|
|
|
|
|
str_contains($norm, 'TTLQTY')
|
|
|
|
|
|
);
|
|
|
|
|
|
$isQty = !$isTotalQty && (
|
|
|
|
|
|
str_contains($norm, 'QTY') ||
|
|
|
|
|
|
str_contains($norm, 'PCS') ||
|
|
|
|
|
|
str_contains($norm, 'PIECES')
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
$isTotalCbm = (
|
|
|
|
|
|
str_contains($norm, 'TOTALCBM') ||
|
|
|
|
|
|
str_contains($norm, 'TTLCBM') ||
|
|
|
|
|
|
str_contains($norm, 'ITLCBM')
|
|
|
|
|
|
);
|
|
|
|
|
|
$isCbm = !$isTotalCbm && str_contains($norm, 'CBM');
|
|
|
|
|
|
|
|
|
|
|
|
$isTotalKg = (
|
|
|
|
|
|
str_contains($norm, 'TOTALKG') ||
|
|
|
|
|
|
str_contains($norm, 'TTKG')
|
|
|
|
|
|
);
|
|
|
|
|
|
$isKg = !$isTotalKg && (str_contains($norm, 'KG') || str_contains($norm, 'WEIGHT'));
|
|
|
|
|
|
|
|
|
|
|
|
$isPrice = (str_contains($norm, 'PRICE') || str_contains($norm, 'RATE'));
|
|
|
|
|
|
|
|
|
|
|
|
$isAmount = (
|
|
|
|
|
|
str_contains($norm, 'AMOUNT') ||
|
|
|
|
|
|
str_contains($norm, 'TTLAMOUNT') ||
|
|
|
|
|
|
str_contains($norm, 'TOTALAMOUNT')
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
$isTotalColumn = $isTotalQty || $isTotalCbm || $isTotalKg || $isAmount;
|
2026-03-12 18:11:43 +05:30
|
|
|
|
// row index = headerRowIndex + 1 + offset — ContainerRow मध्ये row_index save आहे
|
|
|
|
|
|
$isLockedByInvoice = in_array($row->row_index, $lockedRowIndexes ?? []);
|
|
|
|
|
|
$isReadOnly = $isTotalColumn || $container->status !== 'pending' || $isLockedByInvoice;
|
|
|
|
|
|
@endphp
|
|
|
|
|
|
|
|
|
|
|
|
@if($loop->first && $isLockedByInvoice)
|
|
|
|
|
|
{{-- पहिल्या cell मध्ये lock icon --}}
|
|
|
|
|
|
@endif
|
|
|
|
|
|
|
2026-02-27 10:51:26 +05:30
|
|
|
|
<td>
|
2026-03-09 10:24:44 +05:30
|
|
|
|
<input
|
|
|
|
|
|
type="text"
|
2026-03-12 12:34:27 +05:30
|
|
|
|
class="cm-cell-input {{ $isReadOnly ? 'cm-cell-readonly' : '' }}"
|
2026-03-09 10:24:44 +05:30
|
|
|
|
name="rows[{{ $row->id }}][{{ $heading }}]"
|
|
|
|
|
|
value="{{ $value }}"
|
|
|
|
|
|
data-row-id="{{ $row->id }}"
|
|
|
|
|
|
data-col-key="{{ $heading }}"
|
|
|
|
|
|
data-ctn="{{ $isCtn ? '1' : '0' }}"
|
|
|
|
|
|
data-qty="{{ $isQty ? '1' : '0' }}"
|
|
|
|
|
|
data-ttlqty="{{ $isTotalQty ? '1' : '0' }}"
|
|
|
|
|
|
data-cbm="{{ $isCbm ? '1' : '0' }}"
|
|
|
|
|
|
data-ttlcbm="{{ $isTotalCbm ? '1' : '0' }}"
|
|
|
|
|
|
data-kg="{{ $isKg ? '1' : '0' }}"
|
|
|
|
|
|
data-ttlkg="{{ $isTotalKg ? '1' : '0' }}"
|
|
|
|
|
|
data-price="{{ $isPrice ? '1' : '0' }}"
|
|
|
|
|
|
data-amount="{{ $isAmount ? '1' : '0' }}"
|
2026-03-12 12:34:27 +05:30
|
|
|
|
{{ $isReadOnly ? 'readonly' : '' }}
|
2026-03-09 10:24:44 +05:30
|
|
|
|
>
|
2026-02-27 10:51:26 +05:30
|
|
|
|
</td>
|
|
|
|
|
|
@endforeach
|
2026-03-12 12:34:27 +05:30
|
|
|
|
|
2026-02-27 10:51:26 +05:30
|
|
|
|
</tr>
|
|
|
|
|
|
@endforeach
|
2026-03-09 10:24:44 +05:30
|
|
|
|
</tbody>
|
|
|
|
|
|
</table>
|
|
|
|
|
|
</div>
|
2026-02-27 10:51:26 +05:30
|
|
|
|
</div>
|
|
|
|
|
|
</form>
|
|
|
|
|
|
@endif
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
2026-03-09 10:24:44 +05:30
|
|
|
|
@if(!$container->rows->isEmpty())
|
2026-03-12 12:34:27 +05:30
|
|
|
|
<button
|
|
|
|
|
|
id="cmSaveBtnFloating"
|
|
|
|
|
|
class="cm-save-btn-floating {{ $container->status !== 'pending' ? 'cm-disabled' : '' }}"
|
|
|
|
|
|
{{ $container->status !== 'pending' ? 'disabled' : '' }}
|
|
|
|
|
|
>
|
|
|
|
|
|
Save Changes
|
|
|
|
|
|
</button>
|
2026-03-09 10:24:44 +05:30
|
|
|
|
@endif
|
|
|
|
|
|
|
2026-03-12 12:34:27 +05:30
|
|
|
|
|
2026-02-27 10:51:26 +05:30
|
|
|
|
<script>
|
2026-03-12 12:34:27 +05:30
|
|
|
|
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++) {
|
|
|
|
|
|
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;
|
2026-02-27 10:51:26 +05:30
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-03-12 12:34:27 +05:30
|
|
|
|
rows[i].style.display = match ? '' : 'none';
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
|
|
|
|
const form = document.getElementById('cm-edit-rows-form');
|
|
|
|
|
|
const btn = document.getElementById('cmSaveBtnFloating');
|
|
|
|
|
|
const toast = document.getElementById('cmToast');
|
|
|
|
|
|
const table = document.getElementById('cmExcelTable');
|
|
|
|
|
|
|
|
|
|
|
|
function showToast(message, isError = false) {
|
|
|
|
|
|
if (!toast) return;
|
|
|
|
|
|
toast.textContent = message;
|
|
|
|
|
|
toast.style.background = isError ? '#b91c1c' : '#0f172a';
|
|
|
|
|
|
toast.classList.add('cm-show');
|
|
|
|
|
|
setTimeout(() => toast.classList.remove('cm-show'), 2500);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function parseNumber(str) {
|
|
|
|
|
|
if (!str) return 0;
|
|
|
|
|
|
const cleaned = String(str).replace(/,/g, '').trim();
|
|
|
|
|
|
const val = parseFloat(cleaned);
|
|
|
|
|
|
return isNaN(val) ? 0 : val;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function formatNumber(val, decimals) {
|
|
|
|
|
|
if (isNaN(val)) val = 0;
|
|
|
|
|
|
return val.toFixed(decimals);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function recalcRow(row) {
|
|
|
|
|
|
const inputs = row.querySelectorAll('.cm-cell-input');
|
|
|
|
|
|
|
|
|
|
|
|
let ctn = 0, qty = 0, ttlQty = 0;
|
|
|
|
|
|
let cbm = 0, ttlCbm = 0;
|
|
|
|
|
|
let kg = 0, ttlKg = 0;
|
|
|
|
|
|
let price = 0, amount = 0;
|
|
|
|
|
|
|
|
|
|
|
|
let ctnInput = null,
|
|
|
|
|
|
qtyInput = null,
|
|
|
|
|
|
ttlQtyInput = null,
|
|
|
|
|
|
cbmInput = null,
|
|
|
|
|
|
ttlCbmInput = null,
|
|
|
|
|
|
kgInput = null,
|
|
|
|
|
|
ttlKgInput = null,
|
|
|
|
|
|
priceInput = null,
|
|
|
|
|
|
amountInput = null;
|
|
|
|
|
|
|
|
|
|
|
|
inputs.forEach(inp => {
|
|
|
|
|
|
const val = parseNumber(inp.value);
|
|
|
|
|
|
|
|
|
|
|
|
if (inp.dataset.ctn === '1') {
|
|
|
|
|
|
ctn = val;
|
|
|
|
|
|
ctnInput = inp;
|
|
|
|
|
|
} else if (inp.dataset.qty === '1') {
|
|
|
|
|
|
qty = val;
|
|
|
|
|
|
qtyInput = inp;
|
|
|
|
|
|
} else if (inp.dataset.ttlqty === '1') {
|
|
|
|
|
|
ttlQty = val;
|
|
|
|
|
|
ttlQtyInput = inp;
|
|
|
|
|
|
} else if (inp.dataset.cbm === '1') {
|
|
|
|
|
|
cbm = val;
|
|
|
|
|
|
cbmInput = inp;
|
|
|
|
|
|
} else if (inp.dataset.ttlcbm === '1') {
|
|
|
|
|
|
ttlCbm = val;
|
|
|
|
|
|
ttlCbmInput = inp;
|
|
|
|
|
|
} else if (inp.dataset.kg === '1') {
|
|
|
|
|
|
kg = val;
|
|
|
|
|
|
kgInput = inp;
|
|
|
|
|
|
} else if (inp.dataset.ttlkg === '1') {
|
|
|
|
|
|
ttlKg = val;
|
|
|
|
|
|
ttlKgInput = inp;
|
|
|
|
|
|
} else if (inp.dataset.price === '1') {
|
|
|
|
|
|
price = val;
|
|
|
|
|
|
priceInput = inp;
|
|
|
|
|
|
} else if (inp.dataset.amount === '1') {
|
|
|
|
|
|
amount = val;
|
|
|
|
|
|
amountInput = inp;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2026-03-09 10:24:44 +05:30
|
|
|
|
|
2026-03-12 12:34:27 +05:30
|
|
|
|
if (ttlQtyInput && ctnInput && qtyInput) {
|
|
|
|
|
|
const newTtlQty = ctn * qty;
|
|
|
|
|
|
ttlQtyInput.value = formatNumber(newTtlQty, 0);
|
|
|
|
|
|
ttlQty = newTtlQty;
|
2026-03-09 10:24:44 +05:30
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-12 12:34:27 +05:30
|
|
|
|
if (ttlCbmInput && cbmInput && ctnInput) {
|
|
|
|
|
|
const newTtlCbm = cbm * ctn;
|
|
|
|
|
|
ttlCbmInput.value = formatNumber(newTtlCbm, 3);
|
|
|
|
|
|
ttlCbm = newTtlCbm;
|
2026-03-09 10:24:44 +05:30
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-12 12:34:27 +05:30
|
|
|
|
if (ttlKgInput && kgInput && ctnInput) {
|
|
|
|
|
|
const newTtlKg = kg * ctn;
|
|
|
|
|
|
ttlKgInput.value = formatNumber(newTtlKg, 2);
|
|
|
|
|
|
ttlKg = newTtlKg;
|
2026-03-09 10:24:44 +05:30
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-12 12:34:27 +05:30
|
|
|
|
if (amountInput && priceInput && ttlQtyInput) {
|
|
|
|
|
|
const newAmount = price * ttlQty;
|
|
|
|
|
|
amountInput.value = formatNumber(newAmount, 2);
|
|
|
|
|
|
amount = newAmount;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-03-09 10:24:44 +05:30
|
|
|
|
|
2026-03-12 12:34:27 +05:30
|
|
|
|
if (table) {
|
|
|
|
|
|
table.addEventListener('input', function (e) {
|
|
|
|
|
|
const target = e.target;
|
|
|
|
|
|
if (!target.classList.contains('cm-cell-input')) return;
|
2026-03-09 10:24:44 +05:30
|
|
|
|
|
2026-03-12 12:34:27 +05:30
|
|
|
|
// readonly / non-pending cells साठी block
|
|
|
|
|
|
if (target.classList.contains('cm-cell-readonly') || target.hasAttribute('readonly')) {
|
|
|
|
|
|
target.blur();
|
|
|
|
|
|
return;
|
2026-03-09 10:24:44 +05:30
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-12 12:34:27 +05:30
|
|
|
|
const row = target.closest('tr');
|
|
|
|
|
|
if (row) {
|
|
|
|
|
|
recalcRow(row);
|
2026-03-09 10:24:44 +05:30
|
|
|
|
}
|
2026-03-12 12:34:27 +05:30
|
|
|
|
});
|
|
|
|
|
|
}
|
2026-03-09 10:24:44 +05:30
|
|
|
|
|
2026-03-12 12:34:27 +05:30
|
|
|
|
if (form && btn) {
|
|
|
|
|
|
btn.addEventListener('click', function () {
|
|
|
|
|
|
// जर बटण आधीच disabled असेल (non-pending status किंवा processing)
|
|
|
|
|
|
if (btn.classList.contains('cm-disabled') || btn.hasAttribute('disabled')) {
|
|
|
|
|
|
return;
|
2026-03-09 10:24:44 +05:30
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-12 12:34:27 +05:30
|
|
|
|
btn.classList.add('cm-disabled');
|
|
|
|
|
|
const formData = new FormData(form);
|
|
|
|
|
|
|
|
|
|
|
|
fetch(form.action, {
|
|
|
|
|
|
method: 'POST',
|
|
|
|
|
|
headers: {
|
|
|
|
|
|
'X-Requested-With': 'XMLHttpRequest',
|
|
|
|
|
|
'X-CSRF-TOKEN': document.querySelector('input[name="_token"]').value
|
|
|
|
|
|
},
|
|
|
|
|
|
body: formData
|
|
|
|
|
|
})
|
|
|
|
|
|
.then(async res => {
|
|
|
|
|
|
if (!res.ok) {
|
|
|
|
|
|
const text = await res.text();
|
|
|
|
|
|
throw new Error(text || 'Failed to save');
|
|
|
|
|
|
}
|
|
|
|
|
|
return res.json().catch(() => ({}));
|
2026-03-09 10:24:44 +05:30
|
|
|
|
})
|
2026-03-12 12:34:27 +05:30
|
|
|
|
.then(() => {
|
|
|
|
|
|
showToast('Changes saved successfully.');
|
|
|
|
|
|
})
|
|
|
|
|
|
.catch(() => {
|
|
|
|
|
|
showToast('Error while saving changes.', true);
|
|
|
|
|
|
})
|
|
|
|
|
|
.finally(() => {
|
|
|
|
|
|
btn.classList.remove('cm-disabled');
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
2026-02-27 10:51:26 +05:30
|
|
|
|
</script>
|
2026-03-12 12:34:27 +05:30
|
|
|
|
|
2026-02-27 10:51:26 +05:30
|
|
|
|
@endsection
|