frontend Order Section Update
This commit is contained in:
@@ -29,7 +29,7 @@ body {
|
||||
/* container */
|
||||
.account-container {
|
||||
padding: 28px 34px;
|
||||
max-width:1300px;
|
||||
max-width:1400px;
|
||||
margin: 18px auto;
|
||||
box-sizing:border-box;
|
||||
}
|
||||
@@ -70,29 +70,128 @@ body {
|
||||
.btn:hover{ transform: translateY(-3px); box-shadow: 0 8px 26px rgba(36,58,114,0.12); }
|
||||
|
||||
/* account panels */
|
||||
.account-panels { display:flex; gap:22px; align-items:flex-start; flex-wrap:wrap; }
|
||||
.account-panels {
|
||||
display:flex;
|
||||
gap:22px;
|
||||
align-items:flex-start;
|
||||
flex-wrap:wrap;
|
||||
}
|
||||
.panel-card {
|
||||
background: var(--card-bg); border-radius:12px; box-shadow:0 8px 20px rgba(25,40,80,0.06);
|
||||
flex:1; min-width:48%; padding:18px; box-sizing:border-box; overflow-x:auto; transition: transform .12s, box-shadow .12s;
|
||||
background: var(--card-bg);
|
||||
border-radius:12px;
|
||||
box-shadow:0 8px 20px rgba(25,40,80,0.06);
|
||||
flex:1;
|
||||
min-width:48%;
|
||||
padding:22px;
|
||||
box-sizing:border-box;
|
||||
overflow-x:auto;
|
||||
transition: transform .12s, box-shadow .12s;
|
||||
min-height: 480px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.panel-card:hover{ transform: translateY(-4px); box-shadow:0 12px 28px rgba(25,40,80,0.08); }
|
||||
.panel-title { font-weight:700; font-size:16px; color:var(--primary-1); margin-bottom:12px; display:flex; align-items:center; justify-content:space-between; }
|
||||
.panel-title {
|
||||
font-weight:700;
|
||||
font-size:16px;
|
||||
color:var(--primary-1);
|
||||
margin-bottom:16px;
|
||||
display:flex;
|
||||
align-items:center;
|
||||
justify-content:space-between;
|
||||
}
|
||||
|
||||
/* table */
|
||||
table { width:100%; border-collapse:collapse; min-width:720px; font-size:14px; }
|
||||
th, td { padding:10px 12px; text-align:left; border-bottom:1px solid #eef3fb; white-space:nowrap; color:#2d3b53; }
|
||||
th { background: linear-gradient(90deg,#f6f9ff,#fbfdff); color:#4a5570; font-weight:700; font-size:13px; }
|
||||
table {
|
||||
width:100%;
|
||||
border-collapse:collapse;
|
||||
min-width:720px;
|
||||
font-size:14px;
|
||||
flex:1;
|
||||
}
|
||||
th, td {
|
||||
padding:12px 14px;
|
||||
text-align:left;
|
||||
border-bottom:1px solid #eef3fb;
|
||||
white-space:nowrap;
|
||||
color:#2d3b53;
|
||||
}
|
||||
th {
|
||||
background: linear-gradient(90deg,#f6f9ff,#fbfdff);
|
||||
color:#4a5570;
|
||||
font-weight:700;
|
||||
font-size:13px;
|
||||
}
|
||||
tr:hover td{ background:#fbfdff; }
|
||||
.entry-link{ color:var(--accent); text-decoration:underline; cursor:pointer; font-weight:700; }
|
||||
|
||||
/* badges */
|
||||
.status-badge { display:inline-block; padding:6px 12px; border-radius:20px; color:#fff; font-size:13px; font-weight:600; }
|
||||
.status-unpaid{ background:var(--danger); }
|
||||
.status-paid{ background:var(--success); }
|
||||
.status-loading{ background:#509cf8; }
|
||||
.status-dispatched{ background:#20c5c7; }
|
||||
.pending-badge-red{ background:var(--danger); }
|
||||
.pending-badge-green{ background:var(--success); }
|
||||
|
||||
/* === Modern Status Badges === */
|
||||
.status-badge {
|
||||
display: inline-block;
|
||||
padding: 6px 16px;
|
||||
border-radius: 999px;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
min-width: 76px;
|
||||
text-align: center;
|
||||
box-shadow: 0 2px 8px rgba(33, 43, 90, 0.07);
|
||||
letter-spacing: 0.1px;
|
||||
background: #6b7280; /* fallback */
|
||||
transition: box-shadow 0.22s, transform 0.17s, background 0.22s;
|
||||
vertical-align: middle;
|
||||
margin: 3px 2px;
|
||||
cursor: default;
|
||||
/* subtle glass effect */
|
||||
backdrop-filter: blur(2px);
|
||||
width: 99px;
|
||||
}
|
||||
|
||||
.status-badge:hover {
|
||||
transform: translateY(-3px) scale(1.045);
|
||||
box-shadow: 0 4px 16px rgba(33, 43, 90, 0.16);
|
||||
opacity: 0.96;
|
||||
}
|
||||
|
||||
/* High-impact, soft gradients for each status */
|
||||
.status-unpaid {
|
||||
background: linear-gradient(90deg, #ff5959, #dc3545);
|
||||
border: 1.5px solid #d42c3f21;
|
||||
width: 95px;
|
||||
}
|
||||
.status-paid {
|
||||
background: linear-gradient(90deg, #36d399 0%, #4ade80 100%);
|
||||
border: 1.5px solid #31b47a1a;
|
||||
width: 95px;
|
||||
}
|
||||
.status-loading {
|
||||
background: linear-gradient(90deg, #509cf8 0%, #3f79d3 100%);
|
||||
border: 1.5px solid #1665c320;
|
||||
width: 95px;
|
||||
}
|
||||
.status-dispatched {
|
||||
background: linear-gradient(90deg, #9775fa 0%, #845ef7 100%);
|
||||
border: 1.5px solid #9775fa40;
|
||||
width: 95px;
|
||||
}
|
||||
.pending-badge-red {
|
||||
background: linear-gradient(90deg, #f43f5e, #ef4444);
|
||||
border: 1.5px solid #f43f5e41;
|
||||
width: 95px;
|
||||
}
|
||||
.pending-badge-green {
|
||||
background: linear-gradient(90deg, #10b981 0%, #22d3ee 100%);
|
||||
border: 1.5px solid #10b98141;
|
||||
width: 95px;
|
||||
}
|
||||
|
||||
.status-delivered {
|
||||
background: linear-gradient(90deg, #22c55e 0%, #16a34a 100%);
|
||||
border: 1.5px solid #22c55e44;
|
||||
width: 95px;
|
||||
}
|
||||
|
||||
/* 3-state toggle */
|
||||
.toggle-switch-btn {
|
||||
@@ -140,48 +239,237 @@ tr:hover td{ background:#fbfdff; }
|
||||
transform: translateX(38px);
|
||||
}
|
||||
|
||||
|
||||
/* plus button */
|
||||
.plus-btn { display:inline-block; width:36px; height:36px; border-radius:10px; background:#fff; color:var(--primary-1); border:1.5px solid #e6edf8; font-size:1.15rem; font-weight:700; text-align:center; line-height:34px; cursor:pointer; transition: transform .12s; }
|
||||
.plus-btn {
|
||||
display:inline-block;
|
||||
width:36px;
|
||||
height:36px;
|
||||
border-radius:10px;
|
||||
background:#fff;
|
||||
color:var(--primary-1);
|
||||
border:1.5px solid #e6edf8;
|
||||
font-size:1.15rem;
|
||||
font-weight:700;
|
||||
text-align:center;
|
||||
line-height:34px;
|
||||
cursor:pointer;
|
||||
transition: transform .12s;
|
||||
}
|
||||
.plus-btn:hover{ transform: translateY(-3px); box-shadow:0 8px 16px rgba(33,47,90,0.04); }
|
||||
|
||||
/* ---------- Expandable Create Order Card (Option D) ---------- */
|
||||
.create-card {
|
||||
margin: 10px 0 18px 0;
|
||||
border-radius: 12px;
|
||||
background: linear-gradient(180deg,#ffffff,#fbfdff);
|
||||
box-shadow:0 10px 30px rgba(20,40,80,0.04);
|
||||
overflow: hidden; transition: max-height .28s ease, padding .22s ease;
|
||||
max-height: 0; padding: 0 18px; opacity:0; pointer-events:none;
|
||||
/* ---------- Create Order Popup Modal ---------- */
|
||||
.create-order-modal {
|
||||
position:fixed;
|
||||
inset:0;
|
||||
background:rgba(16,24,50,0.44);
|
||||
display:none;
|
||||
align-items:center;
|
||||
justify-content:center;
|
||||
z-index:1200;
|
||||
padding:18px;
|
||||
}
|
||||
.create-order-modal.modal-open { display:flex; }
|
||||
.create-order-modal .modal-box {
|
||||
background:#fff;
|
||||
border-radius:12px;
|
||||
padding:20px 24px;
|
||||
box-shadow:0 14px 40px rgba(18,30,60,0.12);
|
||||
max-width:1200px;
|
||||
width:100%;
|
||||
max-height:92vh;
|
||||
overflow:auto;
|
||||
}
|
||||
.create-card.open { max-height: 1500px; padding: 18px; opacity:1; pointer-events:auto; }
|
||||
.create-card .create-inner { display:flex; gap:14px; flex-direction:column; }
|
||||
.create-card .create-grid { display:grid; grid-template-columns: 1fr 1fr; gap:12px; align-items:start; }
|
||||
.create-card label{ font-weight:700; color:#28384f; margin-bottom:6px; font-size:13px; }
|
||||
.input, select { width:100%; padding:10px 12px; border-radius:8px; border:1.3px solid #e3eaf6; background:#fff; font-size:14px; box-sizing:border-box; }
|
||||
.create-actions { display:flex; gap:10px; justify-content:flex-end; margin-top:12px; }
|
||||
|
||||
/* consolidated orders area */
|
||||
.consolidate-area {
|
||||
background: linear-gradient(90deg,#fbfbff,#f9fcff);
|
||||
border:1px solid #eef5ff; padding:10px; border-radius:10px; box-shadow: inset 0 1px 0 rgba(255,255,255,0.6);
|
||||
margin-top:8px; overflow:auto;
|
||||
border:1px solid #eef5ff;
|
||||
padding:14px;
|
||||
border-radius:10px;
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,0.6);
|
||||
margin-top:12px;
|
||||
overflow:auto;
|
||||
min-height: 400px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.consolidate-toggle { display:flex; gap:10px; align-items:center; margin-bottom:8px; }
|
||||
.consolidate-tab-btn { background:#fff; border:1px solid #e6edf9; padding:8px 10px; border-radius:8px; font-weight:700; cursor:pointer; }
|
||||
.consolidate-tab-btn.active { background:linear-gradient(90deg,var(--primary-1),var(--primary-2)); color:#fff; border-color:transparent; box-shadow:0 6px 18px rgba(36,58,114,0.08); }
|
||||
|
||||
/* compact table in consolidate */
|
||||
#consolidateOrdersTable th, #consolidateOrdersTable td { padding:8px 9px; font-size:13px; border-bottom:1px solid #f1f6ff; }
|
||||
#consolidateOrdersTable th, #consolidateOrdersTable td { padding:10px 12px; font-size:13px; border-bottom:1px solid #f1f6ff; }
|
||||
|
||||
/* ---------- Pagination Styles ---------- */
|
||||
.pagination-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 15px;
|
||||
padding: 12px 0;
|
||||
border-top: 1px solid #eef3fb;
|
||||
}
|
||||
|
||||
.pagination-info {
|
||||
font-size: 13px;
|
||||
color: var(--muted);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.pagination-controls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.pagination-btn {
|
||||
background: #fff;
|
||||
border: 1px solid #e3eaf6;
|
||||
color: var(--primary-1);
|
||||
padding: 8px 12px;
|
||||
border-radius: 6px;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 40px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.pagination-btn:hover:not(:disabled) {
|
||||
background: var(--primary-1);
|
||||
color: white;
|
||||
border-color: var(--primary-1);
|
||||
}
|
||||
|
||||
.pagination-btn:disabled {
|
||||
background: #f8fafc;
|
||||
color: #cbd5e0;
|
||||
border-color: #e2e8f0;
|
||||
cursor: not-allowed;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.pagination-page-btn {
|
||||
background: #fff;
|
||||
border: 1px solid #e3eaf6;
|
||||
color: var(--primary-1);
|
||||
padding: 6px 12px;
|
||||
border-radius: 6px;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
min-width: 36px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.pagination-page-btn:hover {
|
||||
background: var(--primary-1);
|
||||
color: white;
|
||||
border-color: var(--primary-1);
|
||||
}
|
||||
|
||||
.pagination-page-btn.active {
|
||||
background: var(--primary-1);
|
||||
color: white;
|
||||
border-color: var(--primary-1);
|
||||
}
|
||||
|
||||
.pagination-pages {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.pagination-ellipsis {
|
||||
color: var(--muted);
|
||||
font-size: 13px;
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
/* Image-based pagination buttons */
|
||||
.pagination-img-btn {
|
||||
background: #fff;
|
||||
border: 1px solid #e3eaf6;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 40px;
|
||||
height: 32px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.pagination-img-btn:hover:not(:disabled) {
|
||||
background: var(--primary-1);
|
||||
border-color: var(--primary-1);
|
||||
}
|
||||
|
||||
.pagination-img-btn:disabled {
|
||||
background: #f8fafc;
|
||||
border-color: #e2e8f0;
|
||||
cursor: not-allowed;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.pagination-img-btn img {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
filter: brightness(0) saturate(100%) invert(26%) sepia(89%) saturate(748%) hue-rotate(201deg) brightness(93%) contrast(89%);
|
||||
transition: filter 0.3s ease;
|
||||
}
|
||||
|
||||
.pagination-img-btn:hover:not(:disabled) img {
|
||||
filter: brightness(0) saturate(100%) invert(100%) sepia(100%) saturate(0%) hue-rotate(288deg) brightness(106%) contrast(101%);
|
||||
}
|
||||
|
||||
.pagination-img-btn:disabled img {
|
||||
filter: brightness(0) saturate(100%) invert(84%) sepia(8%) saturate(165%) hue-rotate(179deg) brightness(89%) contrast(86%);
|
||||
}
|
||||
|
||||
/* ---------- Entry Details Modal (existing) ---------- */
|
||||
.modal-fade1 { position:fixed; inset:0; background:rgba(16,24,50,0.44); display:none; align-items:center; justify-content:center; z-index:1200; padding:18px; }
|
||||
.modal-fade1 {
|
||||
position:fixed;
|
||||
inset:0;
|
||||
background:rgba(16,24,50,0.44);
|
||||
display:none;
|
||||
align-items:center;
|
||||
justify-content:center;
|
||||
z-index:1200;
|
||||
padding:18px;
|
||||
}
|
||||
.modal-fade1.modal-open { display:flex; }
|
||||
.modal-box1 { background:#fff; border-radius:12px; padding:16px 18px; box-shadow:0 14px 40px rgba(18,30,60,0.12); max-width:1100px; width:100%; max-height:92vh; overflow:auto; }
|
||||
.modal-box1 {
|
||||
background:#fff;
|
||||
border-radius:12px;
|
||||
padding:20px 24px;
|
||||
box-shadow:0 14px 40px rgba(18,30,60,0.12);
|
||||
max-width:1200px;
|
||||
width:100%;
|
||||
max-height:92vh;
|
||||
overflow:auto;
|
||||
min-height: 500px;
|
||||
}
|
||||
|
||||
/* entry summary cards */
|
||||
.entry-summary-cards { display:flex; gap:12px; margin-bottom:14px; flex-wrap:wrap; }
|
||||
.entry-summary-card { background:#fbfdff; border:1px solid #eef6ff; padding:12px; border-radius:10px; min-width:160px; box-shadow:0 6px 18px rgba(22,36,72,0.03); }
|
||||
.entry-summary-cards {
|
||||
display:flex;
|
||||
gap:16px;
|
||||
margin-bottom:20px;
|
||||
flex-wrap:wrap;
|
||||
}
|
||||
.entry-summary-card {
|
||||
background:#fbfdff;
|
||||
border:1px solid #eef6ff;
|
||||
padding:16px;
|
||||
border-radius:10px;
|
||||
min-width:180px;
|
||||
box-shadow:0 6px 18px rgba(22,36,72,0.03);
|
||||
flex:1;
|
||||
}
|
||||
.entry-summary-label{ font-size:12px; color:var(--muted); }
|
||||
.entry-summary-value{ font-size:18px; font-weight:700; color:#253047; margin-top:6px; }
|
||||
|
||||
@@ -193,11 +481,47 @@ tr:hover td{ background:#fbfdff; }
|
||||
.empty-state{ padding:18px; text-align:center; color:#6f7b8f; }
|
||||
.kv { font-weight:700; color:#26364f; }
|
||||
|
||||
/* form styles */
|
||||
.input, select {
|
||||
width:100%;
|
||||
padding:12px 14px;
|
||||
border-radius:8px;
|
||||
border:1.3px solid #e3eaf6;
|
||||
background:#fff;
|
||||
font-size:14px;
|
||||
box-sizing:border-box;
|
||||
}
|
||||
.create-grid {
|
||||
display:grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap:16px;
|
||||
align-items:start;
|
||||
margin-bottom:16px;
|
||||
}
|
||||
.create-actions {
|
||||
display:flex;
|
||||
gap:12px;
|
||||
justify-content:flex-end;
|
||||
margin-top:16px;
|
||||
}
|
||||
|
||||
/* responsive */
|
||||
@media (max-width:980px){
|
||||
.create-card .create-grid { grid-template-columns: 1fr; }
|
||||
.create-grid { grid-template-columns: 1fr; }
|
||||
.panel-card { min-width:100%; }
|
||||
.search-row input{ width:220px; }
|
||||
.pagination-container { flex-direction: column; gap: 10px; align-items: stretch; }
|
||||
.pagination-controls { justify-content: center; }
|
||||
.account-container { padding: 20px; }
|
||||
.panel-card { padding: 18px; }
|
||||
}
|
||||
|
||||
@media (max-width:768px){
|
||||
.account-header { padding: 18px; }
|
||||
.top-actions { flex-direction: column; align-items: stretch; }
|
||||
.top-actions .left { justify-content: center; }
|
||||
.entry-summary-cards { gap: 12px; }
|
||||
.entry-summary-card { min-width: 140px; }
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -216,7 +540,7 @@ tr:hover td{ background:#fbfdff; }
|
||||
<button class="btn ghost" id="searchBtn">Search</button>
|
||||
</div>
|
||||
<div style="display:flex; align-items:center; gap:8px; margin-left:6px;">
|
||||
<button class="btn" id="toggleCreateBtn" aria-expanded="false">+ Create New Order</button>
|
||||
<button class="btn" id="openCreateModalBtn">+ Create New Order</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -225,83 +549,6 @@ tr:hover td{ background:#fbfdff; }
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Expandable Create Order Card (Option D) -->
|
||||
<div class="create-card" id="createCard">
|
||||
<div class="create-inner">
|
||||
<div style="display:flex; align-items:center; justify-content:space-between;">
|
||||
<div style="font-size:18px; font-weight:800; color:var(--primary-1)">Create New Order</div>
|
||||
<button class="consolidate-tab-btn" id="closeCreateInline" title="Close create form">✕</button>
|
||||
</div>
|
||||
|
||||
<form id="createOrderInlineForm" autocomplete="off">
|
||||
<div class="create-grid" style="margin-top:6px;">
|
||||
<div>
|
||||
<label for="inline_description">Description *</label>
|
||||
<input class="input" type="text" id="inline_description" name="description" required placeholder="Short description for consolidated entry">
|
||||
</div>
|
||||
<div>
|
||||
<label for="inline_region">Region *</label>
|
||||
<select id="inline_region" name="region" class="input" required>
|
||||
<option value="China">China</option>
|
||||
<option value="Europe">Europe</option>
|
||||
<option value="US">US</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="inline_amount">Total Amount (₹) *</label>
|
||||
<input class="input" type="number" id="inline_amount" name="amount" min="0" required>
|
||||
</div>
|
||||
<div>
|
||||
<label for="inline_entry_date">Entry Date *</label>
|
||||
<input class="input" type="date" id="inline_entry_date" name="entry_date" value="{{ date('Y-m-d') }}" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-top:10px;">
|
||||
<div class="consolidate-toggle">
|
||||
<button type="button" id="toggleConsolidatedBtn" class="consolidate-tab-btn active">Hide Orders</button>
|
||||
<div style="font-weight:700; color:#233063; margin-left:6px;">Consolidated Orders</div>
|
||||
<div style="margin-left:auto; font-size:13px; color:var(--muted);">Select orders to include in the consolidated entry</div>
|
||||
</div>
|
||||
|
||||
<div class="consolidate-area" id="consolidateArea">
|
||||
<table id="consolidateOrdersTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Order ID</th>
|
||||
<th>Mark No</th>
|
||||
<th>Origin</th>
|
||||
<th>Destination</th>
|
||||
<th>CTN</th>
|
||||
<th>QTY</th>
|
||||
<th>TTL/QTY</th>
|
||||
<th>Total Amount (₹)</th>
|
||||
<th>CBM</th>
|
||||
<th>TTL CBM</th>
|
||||
<th>KG</th>
|
||||
<th>TTL KG</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="consolidateOrdersBody">
|
||||
<tr><td colspan="14" class="empty-state">Loading available orders...</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="create-actions">
|
||||
<button type="button" class="btn ghost" id="cancelCreateInline">Cancel</button>
|
||||
<button type="submit" class="btn">Create Order</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="helper-note">Tip: Select orders from the list to include them in this consolidated entry. You can also search orders above.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Panels -->
|
||||
<div class="account-panels" id="account-panels">
|
||||
<div class="panel-card">
|
||||
@@ -343,6 +590,103 @@ tr:hover td{ background:#fbfdff; }
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- CREATE ORDER POPUP MODAL -->
|
||||
<div class="create-order-modal" id="createOrderModal">
|
||||
<div class="modal-box">
|
||||
<div style="display:flex; align-items:center; justify-content:space-between; margin-bottom:16px;">
|
||||
<div style="font-size:20px; font-weight:800; color:var(--primary-1)">Create New Order</div>
|
||||
<button class="btn ghost" id="closeCreateModal" title="Close create form">✕</button>
|
||||
</div>
|
||||
|
||||
<form id="createOrderInlineForm" autocomplete="off">
|
||||
<div class="create-grid">
|
||||
<div>
|
||||
<label for="inline_description">Description *</label>
|
||||
<input class="input" type="text" id="inline_description" name="description" required placeholder="Short description for consolidated entry">
|
||||
</div>
|
||||
<div>
|
||||
<label for="inline_region">Region *</label>
|
||||
<select id="inline_region" name="region" class="input" required>
|
||||
<option value="China">China</option>
|
||||
<option value="Europe">Europe</option>
|
||||
<option value="US">US</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="inline_amount">Total Amount (₹) *</label>
|
||||
<input class="input" type="number" id="inline_amount" name="amount" min="0" required>
|
||||
</div>
|
||||
<div>
|
||||
<label for="inline_entry_date">Entry Date *</label>
|
||||
<input class="input" type="date" id="inline_entry_date" name="entry_date" value="{{ date('Y-m-d') }}" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-top:16px;">
|
||||
<div style="display:flex; align-items:center; margin-bottom:8px;">
|
||||
<div style="font-weight:700; color:#233063; margin-right:6px;">Consolidated Orders</div>
|
||||
<div style="margin-left:auto; font-size:13px; color:var(--muted);">Select orders to include in the consolidated entry</div>
|
||||
</div>
|
||||
|
||||
<div class="consolidate-area" id="consolidateArea">
|
||||
<table id="consolidateOrdersTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Order ID</th>
|
||||
<th>Mark No</th>
|
||||
<th>Origin</th>
|
||||
<th>Destination</th>
|
||||
<th>CTN</th>
|
||||
<th>QTY</th>
|
||||
<th>TTL/QTY</th>
|
||||
<th>Total Amount (₹)</th>
|
||||
<th>CBM</th>
|
||||
<th>TTL CBM</th>
|
||||
<th>KG</th>
|
||||
<th>TTL KG</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="consolidateOrdersBody">
|
||||
<tr><td colspan="14" class="empty-state">Loading available orders...</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Pagination Controls -->
|
||||
<div class="pagination-container">
|
||||
<div class="pagination-info" id="pageInfo">Showing 1 to 10 of 0 entries</div>
|
||||
<div class="pagination-controls">
|
||||
<button class="pagination-img-btn" id="prevPageBtn" title="Previous page">
|
||||
<!-- Left arrow SVG -->
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10 12L6 8L10 4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</button>
|
||||
<div class="pagination-pages" id="paginationPages">
|
||||
<!-- Page numbers will be inserted here -->
|
||||
</div>
|
||||
<button class="pagination-img-btn" id="nextPageBtn" title="Next page">
|
||||
<!-- Right arrow SVG -->
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6 4L10 8L6 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="create-actions">
|
||||
<button type="button" class="btn ghost" id="cancelCreateModal">Cancel</button>
|
||||
<button type="submit" class="btn">Create Order</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="helper-note">Tip: Select orders from the list to include them in this consolidated entry. You can also search orders above.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ENTRY DETAILS MODAL -->
|
||||
<div class="modal-fade1" id="entryDetailsModal">
|
||||
<div class="modal-box1 entry-details-modal">
|
||||
@@ -389,7 +733,6 @@ tr:hover td{ background:#fbfdff; }
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
<div style="display:flex; justify-content: flex-end; gap:12px; margin-top:16px;">
|
||||
<button type="button" class="btn ghost" onclick="closeEntryDetailsModal()">Close</button>
|
||||
<button type="button" class="btn" id="addInstallmentFromDetails">+ Add New Installment</button>
|
||||
@@ -402,7 +745,7 @@ tr:hover td{ background:#fbfdff; }
|
||||
<div class="modal-box1" style="max-width:720px;">
|
||||
<div style="display:flex;align-items:center; justify-content:space-between; margin-bottom:12px;">
|
||||
<div style="font-size:18px;font-weight:800;color:#243a72;">+ Add New Installment</div>
|
||||
<button class="consolidate-tab-btn" onclick="closeInstallmentModal()">✕</button>
|
||||
<button class="btn ghost" onclick="closeInstallmentModal()">✕</button>
|
||||
</div>
|
||||
|
||||
<div style="font-size:14px;color:#6f7b8f;margin-bottom:14px;">Create a new processing entry for the remaining pending amount</div>
|
||||
@@ -453,6 +796,10 @@ let entries = [];
|
||||
let availableOrders = [];
|
||||
let currentEntry = null;
|
||||
|
||||
/* Pagination state */
|
||||
let currentPage = 1;
|
||||
const ordersPerPage = 10;
|
||||
|
||||
/* small util */
|
||||
function escapeHtml(s){ if(s === null || s === undefined) return ''; return String(s).replace(/[&<>"']/g, m => ({'&':'&','<':'<','>':'>','"':'"',"'":"'"}[m])); }
|
||||
function formatCurrency(v){ return '₹' + Number(v || 0).toLocaleString(undefined, { minimumFractionDigits:0, maximumFractionDigits:2 }); }
|
||||
@@ -471,17 +818,21 @@ function statusClass(status){
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
bindUI();
|
||||
loadDashboard();
|
||||
loadAvailableOrders();
|
||||
});
|
||||
|
||||
/* ---------- UI binding ---------- */
|
||||
function bindUI(){
|
||||
document.getElementById('toggleCreateBtn').addEventListener('click', toggleCreateCard);
|
||||
document.getElementById('closeCreateInline').addEventListener('click', () => closeCreateCard());
|
||||
document.getElementById('cancelCreateInline').addEventListener('click', () => closeCreateCard());
|
||||
// Create Order Modal
|
||||
document.getElementById('openCreateModalBtn').addEventListener('click', openCreateOrderModal);
|
||||
document.getElementById('closeCreateModal').addEventListener('click', closeCreateOrderModal);
|
||||
document.getElementById('cancelCreateModal').addEventListener('click', closeCreateOrderModal);
|
||||
document.getElementById('createOrderInlineForm').addEventListener('submit', submitCreateOrderInline);
|
||||
document.getElementById('refreshBtn').addEventListener('click', () => { loadDashboard(); loadAvailableOrders(); });
|
||||
document.getElementById('toggleConsolidatedBtn').addEventListener('click', toggleConsolidateVisibility);
|
||||
|
||||
// Pagination buttons
|
||||
document.getElementById('prevPageBtn').addEventListener('click', goToPreviousPage);
|
||||
document.getElementById('nextPageBtn').addEventListener('click', goToNextPage);
|
||||
|
||||
document.getElementById('refreshBtn').addEventListener('click', () => { loadDashboard(); });
|
||||
document.getElementById('searchBtn').addEventListener('click', handleSearch);
|
||||
document.getElementById('addInstallmentFromDetails').addEventListener('click', () => {
|
||||
if(!currentEntry) return;
|
||||
@@ -493,29 +844,100 @@ function bindUI(){
|
||||
document.getElementById('installmentForm').addEventListener('submit', submitInstallment);
|
||||
}
|
||||
|
||||
/* ---------- Toggle create inline ---------------- */
|
||||
function toggleCreateCard(){
|
||||
const card = document.getElementById('createCard');
|
||||
const btn = document.getElementById('toggleCreateBtn');
|
||||
if(card.classList.contains('open')){
|
||||
closeCreateCard();
|
||||
} else {
|
||||
openCreateCard();
|
||||
}
|
||||
/* ---------- Pagination Functions ---------- */
|
||||
function goToPreviousPage() {
|
||||
if (currentPage > 1) {
|
||||
currentPage--;
|
||||
renderConsolidateOrders(availableOrders);
|
||||
updatePaginationControls();
|
||||
}
|
||||
}
|
||||
function openCreateCard(){
|
||||
const card = document.getElementById('createCard');
|
||||
card.classList.add('open');
|
||||
document.getElementById('toggleCreateBtn').setAttribute('aria-expanded','true');
|
||||
// refresh orders
|
||||
|
||||
function goToNextPage() {
|
||||
const totalPages = Math.ceil(availableOrders.length / ordersPerPage);
|
||||
if (currentPage < totalPages) {
|
||||
currentPage++;
|
||||
renderConsolidateOrders(availableOrders);
|
||||
updatePaginationControls();
|
||||
}
|
||||
}
|
||||
|
||||
function updatePaginationControls() {
|
||||
const totalPages = Math.ceil(availableOrders.length / ordersPerPage);
|
||||
const prevBtn = document.getElementById('prevPageBtn');
|
||||
const nextBtn = document.getElementById('nextPageBtn');
|
||||
const pageInfo = document.getElementById('pageInfo');
|
||||
const paginationPages = document.getElementById('paginationPages');
|
||||
|
||||
prevBtn.disabled = currentPage === 1;
|
||||
nextBtn.disabled = currentPage === totalPages || totalPages === 0;
|
||||
|
||||
// Update page info text
|
||||
const startIndex = (currentPage - 1) * ordersPerPage + 1;
|
||||
const endIndex = Math.min(currentPage * ordersPerPage, availableOrders.length);
|
||||
pageInfo.textContent = `Showing ${startIndex} to ${endIndex} of ${availableOrders.length} entries`;
|
||||
|
||||
// Generate page numbers
|
||||
paginationPages.innerHTML = '';
|
||||
|
||||
if (totalPages <= 7) {
|
||||
// Show all pages
|
||||
for (let i = 1; i <= totalPages; i++) {
|
||||
addPageButton(i, paginationPages);
|
||||
}
|
||||
} else {
|
||||
// Show first page, current page range, and last page
|
||||
addPageButton(1, paginationPages);
|
||||
|
||||
if (currentPage > 3) {
|
||||
paginationPages.innerHTML += '<span class="pagination-ellipsis">...</span>';
|
||||
}
|
||||
|
||||
const start = Math.max(2, currentPage - 1);
|
||||
const end = Math.min(totalPages - 1, currentPage + 1);
|
||||
|
||||
for (let i = start; i <= end; i++) {
|
||||
addPageButton(i, paginationPages);
|
||||
}
|
||||
|
||||
if (currentPage < totalPages - 2) {
|
||||
paginationPages.innerHTML += '<span class="pagination-ellipsis">...</span>';
|
||||
}
|
||||
|
||||
addPageButton(totalPages, paginationPages);
|
||||
}
|
||||
}
|
||||
|
||||
function addPageButton(pageNumber, container) {
|
||||
const button = document.createElement('button');
|
||||
button.className = 'pagination-page-btn';
|
||||
if (pageNumber === currentPage) {
|
||||
button.classList.add('active');
|
||||
}
|
||||
button.textContent = pageNumber;
|
||||
button.addEventListener('click', () => {
|
||||
currentPage = pageNumber;
|
||||
renderConsolidateOrders(availableOrders);
|
||||
updatePaginationControls();
|
||||
});
|
||||
container.appendChild(button);
|
||||
}
|
||||
|
||||
/* ---------- Create Order Modal Functions ---------- */
|
||||
function openCreateOrderModal(){
|
||||
const modal = document.getElementById('createOrderModal');
|
||||
modal.classList.add('modal-open');
|
||||
loadAvailableOrders();
|
||||
// focus first input
|
||||
setTimeout(()=> document.getElementById('inline_description').focus(), 220);
|
||||
}
|
||||
function closeCreateCard(){
|
||||
const card = document.getElementById('createCard');
|
||||
card.classList.remove('open');
|
||||
document.getElementById('toggleCreateBtn').setAttribute('aria-expanded','false');
|
||||
|
||||
function closeCreateOrderModal(){
|
||||
const modal = document.getElementById('createOrderModal');
|
||||
modal.classList.remove('modal-open');
|
||||
// reset form and pagination
|
||||
document.getElementById('createOrderInlineForm').reset();
|
||||
currentPage = 1;
|
||||
}
|
||||
|
||||
/* ---------- Loaders ---------- */
|
||||
@@ -540,16 +962,19 @@ function loadDashboard(){
|
||||
|
||||
function loadAvailableOrders(){
|
||||
const tbody = document.getElementById('consolidateOrdersBody');
|
||||
tbody.innerHTML = '<tr><td colspan="10" class="empty-state">Loading available orders...</td></tr>';
|
||||
tbody.innerHTML = '<tr><td colspan="14" class="empty-state">Loading available orders...</td></tr>';
|
||||
jsonFetch('/admin/account/available-orders')
|
||||
.then(res => {
|
||||
if(!res.success) throw new Error(res.message || 'Failed to load orders');
|
||||
availableOrders = res.orders || [];
|
||||
currentPage = 1; // Reset to first page when loading new orders
|
||||
renderConsolidateOrders(availableOrders);
|
||||
updatePaginationControls();
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
tbody.innerHTML = '<tr><td colspan="10" class="empty-state">Unable to load orders</td></tr>';
|
||||
tbody.innerHTML = '<tr><td colspan="14" class="empty-state">Unable to load orders</td></tr>';
|
||||
updatePaginationControls();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -619,11 +1044,18 @@ function renderOrderTable(list){
|
||||
function renderConsolidateOrders(list){
|
||||
const body = document.getElementById('consolidateOrdersBody');
|
||||
body.innerHTML = '';
|
||||
|
||||
if(!list || list.length === 0){
|
||||
body.innerHTML = '<tr><td colspan="10" class="empty-state">No available orders</td></tr>';
|
||||
body.innerHTML = '<tr><td colspan="14" class="empty-state">No available orders</td></tr>';
|
||||
return;
|
||||
}
|
||||
list.forEach(order => {
|
||||
|
||||
// Calculate pagination
|
||||
const startIndex = (currentPage - 1) * ordersPerPage;
|
||||
const endIndex = startIndex + ordersPerPage;
|
||||
const paginatedOrders = list.slice(startIndex, endIndex);
|
||||
|
||||
paginatedOrders.forEach(order => {
|
||||
const tr = document.createElement('tr');
|
||||
tr.innerHTML = `
|
||||
<td><input type="checkbox" value="${order.id}"></td>
|
||||
@@ -639,13 +1071,11 @@ function renderConsolidateOrders(list){
|
||||
<td>${order.ttl_cbm ?? ''}</td>
|
||||
<td>${order.kg ?? ''}</td>
|
||||
<td>${order.ttl_kg ?? ''}</td>
|
||||
|
||||
`;
|
||||
body.appendChild(tr);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function setToggleVisual(btn, pos) {
|
||||
btn.classList.remove('mid', 'checked');
|
||||
|
||||
@@ -686,9 +1116,7 @@ function cycleToggle(btn) {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ---------- Create Order Inline (Option D) ---------- */
|
||||
/* ---------- Create Order Inline (Now in Popup) ---------- */
|
||||
async function submitCreateOrderInline(e){
|
||||
e.preventDefault();
|
||||
const form = e.target;
|
||||
@@ -714,9 +1142,8 @@ async function submitCreateOrderInline(e){
|
||||
if(!res.success) throw new Error(res.message || 'Create failed');
|
||||
// success
|
||||
form.reset();
|
||||
closeCreateCard();
|
||||
closeCreateOrderModal();
|
||||
loadDashboard();
|
||||
loadAvailableOrders();
|
||||
} catch(err){
|
||||
alert(err.message || 'Failed to create order');
|
||||
console.error(err);
|
||||
@@ -726,19 +1153,6 @@ async function submitCreateOrderInline(e){
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------- Consolidate toggle ---------- */
|
||||
function toggleConsolidateVisibility(){
|
||||
const btn = document.getElementById('toggleConsolidatedBtn');
|
||||
const area = document.getElementById('consolidateArea');
|
||||
if(btn.classList.contains('active')){
|
||||
btn.classList.remove('active'); btn.textContent = 'Show Orders';
|
||||
area.style.display = 'none';
|
||||
} else {
|
||||
btn.classList.add('active'); btn.textContent = 'Hide Orders';
|
||||
area.style.display = 'block';
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------- Search ---------- */
|
||||
function handleSearch(){
|
||||
const q = document.getElementById('main-search').value.trim().toLowerCase();
|
||||
@@ -810,8 +1224,6 @@ function closeEntryDetailsModal() {
|
||||
document.getElementById('entryDetailsModal').classList.remove('modal-open');
|
||||
}
|
||||
|
||||
|
||||
|
||||
async function updateInstallmentStatus(id, status) {
|
||||
try {
|
||||
const res = await jsonFetch('/admin/account/installment/update-status', {
|
||||
@@ -833,7 +1245,6 @@ async function updateInstallmentStatus(id, status) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ---------- Installment modal ---------- */
|
||||
function openInstallmentModal(entryNo, desc, region, pending){
|
||||
currentEntry = { entry_no: entryNo, description: desc, region: region, pending_amount: pending };
|
||||
@@ -884,4 +1295,4 @@ async function submitInstallment(e){
|
||||
document.addEventListener('DOMContentLoaded', () => { document.getElementById('consolidateArea').style.display = 'block'; });
|
||||
</script>
|
||||
|
||||
@endsection
|
||||
@endsection
|
||||
Reference in New Issue
Block a user