Compare commits

...

12 Commits

Author SHA256 Message Date
Utkarsh Khedkar
8b6d3d5fad Account Changes 2025-12-27 11:15:00 +05:30
Utkarsh Khedkar
c89e5bdf7d changes 2025-12-25 18:11:33 +05:30
Utkarsh Khedkar
10af713fa1 Changes 2025-12-25 11:38:02 +05:30
Utkarsh Khedkar
ebb263cd36 Merge branch 'dev' of http://103.248.30.24:3000/kent-logistics/Kent-logistics-Laravel into dev 2025-12-25 10:22:36 +05:30
Utkarsh Khedkar
82d9c10130 Dashboard Changes 2025-12-25 10:22:20 +05:30
divya abdar
cb24cf575b changes in order,popup invoice ,invoice pdf,invoice edit,customer add,customer a 2025-12-25 10:19:20 +05:30
Utkarsh Khedkar
e4c07cb838 shipment Changes 2025-12-24 13:36:50 +05:30
Utkarsh Khedkar
f38a5afdd7 shipment Changes 2025-12-24 13:34:44 +05:30
divya abdar
9423c79c80 changes of dashboard and order , requests 2025-12-24 13:32:47 +05:30
divya abdar
8a958b9c48 dashboard order and request file changes 2025-12-24 10:47:20 +05:30
Utkarsh Khedkar
82882e859e changes 2025-12-23 13:09:33 +05:30
Utkarsh Khedkar
2d28e7c1d5 changes 2025-12-23 13:08:26 +05:30
46 changed files with 5004 additions and 3550 deletions

View File

@@ -9,6 +9,7 @@ use App\Models\InvoiceItem;
use Mpdf\Mpdf;
use App\Models\InvoiceInstallment;
use Illuminate\Support\Facades\Log;
use Barryvdh\DomPDF\Facade\Pdf;
class AdminInvoiceController extends Controller
{
@@ -43,7 +44,14 @@ class AdminInvoiceController extends Controller
$invoice = Invoice::with(['order.shipments'])->findOrFail($id);
$shipment = $invoice->order?->shipments?->first();
return view('admin.invoice_edit', compact('invoice', 'shipment'));
// ADD THIS SECTION: Calculate customer's total due across all invoices
$customerTotalDue = Invoice::where('customer_id', $invoice->customer_id)
->where('status', '!=', 'cancelled')
->where('status', '!=', 'void')
->sum('final_amount_with_gst');
// Pass the new variable to the view
return view('admin.invoice_edit', compact('invoice', 'shipment', 'customerTotalDue'));
}
// -------------------------------------------------------------
@@ -147,14 +155,9 @@ class AdminInvoiceController extends Controller
{
$invoice = Invoice::findOrFail($id);
// Generate PDF if missing
if (
!$invoice->pdf_path ||
!file_exists(public_path($invoice->pdf_path))
) {
// ALWAYS regenerate to reflect latest HTML/CSS
$this->generateInvoicePDF($invoice);
$invoice->refresh();
}
return response()->download(public_path($invoice->pdf_path));
}

View File

@@ -6,6 +6,7 @@
<meta name="csrf-token" content="{{ csrf_token() }}">
<style>
/* ---------- Base ---------- */
:root{
--primary-1:#1a2951;
--primary-2:#243a72;
@@ -37,7 +38,7 @@ body {
/* header */
.account-header {
margin-bottom: 18px;
background: linear-gradient(90deg,var(--primary-1),var(--primary-2));
background:linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding: 22px 26px;
border-radius: var(--rounded);
box-shadow: 0 6px 18px rgba(34,50,90,0.12);
@@ -62,7 +63,7 @@ body {
.btn {
display:inline-flex; align-items:center; justify-content:center; gap:8px;
background: linear-gradient(90deg,var(--primary-1),var(--primary-2));
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color:#fff; border:none; padding:10px 16px; border-radius:10px; font-weight:600;
cursor:pointer; transition: transform .15s ease, box-shadow .15s;
}
@@ -334,7 +335,7 @@ tr:hover td{ background:#fbfdff; }
display: flex;
align-items: center;
gap: 8px;
/* margin-right:-550px; */
margin-right:-550px;
}
@@ -342,7 +343,7 @@ tr:hover td{ background:#fbfdff; }
display: flex;
align-items: center;
gap: 8px;
margin-right:-550px;
margin-right:8=500px;
}
@@ -458,7 +459,7 @@ tr:hover td{ background:#fbfdff; }
filter: brightness(0) saturate(100%) invert(84%) sepia(8%) saturate(165%) hue-rotate(179deg) brightness(89%) contrast(86%);
}
/* ---------- Entry Details Modal (existing) ---------- */
/* ---------- Entry Details Modal (Enhanced) ---------- */
.modal-fade1 {
position:fixed;
inset:0;
@@ -484,12 +485,15 @@ tr:hover td{ background:#fbfdff; }
#entryOrdersModal {
z-index: 1300;
}
#entryOrdersModal {
z-index: 1300;
}
/* entry summary cards */
.entry-summary-cards {
display:flex;
gap:16px;
margin-bottom:20px;
margin-top:25px;
flex-wrap:wrap;
}
.entry-summary-card {
@@ -504,6 +508,184 @@ tr:hover td{ background:#fbfdff; }
.entry-summary-label{ font-size:12px; color:var(--muted); }
.entry-summary-value{ font-size:18px; font-weight:700; color:#253047; margin-top:6px; }
/* Enhanced dropdown */
.installment-status-dropdown {
cursor: pointer;
appearance: none;
width: 100%;
padding: 10px 40px 10px 12px;
border-radius: 8px;
border: 1.5px solid #e3eaf6;
background: white;
font-size: 13px;
font-weight: 500;
transition: all 0.2s ease;
background-image: url('data:image/svg+xml;charset=US-ASCII,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="%236b7280" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>');
background-repeat: no-repeat;
background-position: right 12px center;
min-width: 140px;
}
.installment-status-dropdown:hover {
border-color: #c2d1f0;
background-color: #f8fafc;
}
.installment-status-dropdown:focus {
outline: none;
border-color: var(--accent);
box-shadow: 0 0 0 3px rgba(39, 109, 234, 0.1);
}
/* Status-specific dropdown options */
.installment-status-dropdown option {
padding: 12px !important;
font-size: 13px;
font-weight: 500;
}
.installment-status-dropdown option[value="Pending"] {
color: #f59e0b;
}
.installment-status-dropdown option[value="Loading"] {
color: #3b82f6;
}
.installment-status-dropdown option[value="Packed"] {
color: #8b5cf6;
}
.installment-status-dropdown option[value="Dispatched"] {
color: #10b981;
}
.installment-status-dropdown option[value="Delivered"] {
color: #0c6b2e;
}
/* ---------- Entry Orders Modal (Enhanced) ---------- */
.entry-orders-modal .modal-box1 {
padding: 0 !important;
overflow: hidden;
border-radius: 16px;
box-shadow: 0 20px 60px rgba(18, 30, 60, 0.25);
}
.entry-orders-header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding: 24px 30px;
color: white;
border-radius: 16px 16px 0 0;
}
.entry-orders-header h2 {
margin: 0 0 8px 0;
font-size: 24px;
font-weight: 700;
color: white;
}
.entry-orders-header .subtitle {
font-size: 14px;
opacity: 0.9;
display: flex;
align-items: center;
gap: 8px;
}
.entry-orders-content {
padding: 30px;
max-height: 70vh;
overflow-y: auto;
}
/* Orders table in modal */
.orders-table-container {
max-height: 400px;
overflow-y: auto;
border: 1px solid #eef3fb;
border-radius: 12px;
margin: 20px 0;
}
.orders-table {
width: 100%;
border-collapse: collapse;
font-size: 14px;
}
.orders-table th {
background: linear-gradient(90deg, #f8fbff, #f5f9ff);
padding: 14px 16px;
text-align: left;
font-weight: 700;
color: var(--primary-1);
border-bottom: 2px solid #eef3fb;
position: sticky;
top: 0;
}
.orders-table td {
padding: 14px 16px;
border-bottom: 1px solid #f1f6ff;
}
.orders-table tr:hover {
background: #fbfdff;
}
.orders-table tr:last-child td {
border-bottom: none;
}
/* Order ID with badge style */
.order-id-badge {
display: inline-block;
background: linear-gradient(90deg, #f0f7ff, #e6f0ff);
color: var(--primary-1);
padding: 4px 10px;
border-radius: 6px;
font-weight: 600;
font-size: 12px;
border: 1px solid #dbe4f5;
}
/* Summary row */
.orders-summary-row {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px 20px;
background: linear-gradient(90deg, #e6ebf5 0%, #f9fbff 100%);
border-radius: 10px;
margin-top: 20px;
border: 1px solid #eef3fb;
}
.orders-summary-item {
display: flex;
flex-direction: column;
align-items: center;
flex: 1;
}
.orders-summary-value {
font-size: 20px;
font-weight: 800;
color: var(--primary-1);
}
.orders-summary-label {
font-size: 12px;
color: var(--muted);
margin-top: 4px;
text-transform: uppercase;
letter-spacing: 0.5px;
}
/* installment modal */
#installmentModal .modal-box1 { max-width:720px; min-width:380px; }
@@ -828,7 +1010,10 @@ tr:hover td{ background:#fbfdff; }
flex-wrap: wrap;
margin-bottom: 16px;
padding: 12px 14px;
background: linear-gradient(90deg, #f9fbff, #f7faff);
background:linear-gradient(90deg, #e6ebf5 0%, #f9fbff 100%);
border-radius: 8px;
border: 1px solid #eef3fb;
}
@@ -1110,6 +1295,40 @@ tr:hover td{ background:#fbfdff; }
.pagination-container {
margin-right: 0 !important;
}
/* Responsive modals */
.entry-details-modal .modal-box1,
.entry-orders-modal .modal-box1 {
margin: 10px;
border-radius: 12px;
}
.entry-details-header,
.entry-orders-header {
padding: 18px 20px;
}
.entry-details-content,
.entry-orders-content {
padding: 20px;
}
.entry-summary-cards {
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
gap: 12px;
}
.entry-summary-value {
font-size: 20px;
}
.orders-summary-row {
flex-direction: column;
gap: 15px;
text-align: center;
}
}
/* Zoom out specific fix */
@@ -1146,6 +1365,10 @@ tr:hover td{ background:#fbfdff; }
.pagination-info {
font-size: 12px;
}
.entry-summary-cards {
grid-template-columns: 1fr;
}
}
/* Prevent horizontal scroll on very small screens */
@@ -1178,6 +1401,7 @@ html, body {
</style>
<div class="account-container">
@@ -1323,7 +1547,7 @@ html, body {
<!-- 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="display:flex; align-items:center; justify-content:space-between; margin-bottom:16px; background:linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding:20px; border-radius:12px; color:white; margin-top:-20px; margin-left:-20px; margin-right:-15px; margin-top:-15px;">
<div style="font-size:20px; font-weight:800;">Create New Installment</div>
<button class="btn ghost" id="closeCreateModal" title="Close create form"></button>
</div>
@@ -1415,37 +1639,64 @@ html, body {
</div>
</div>
<!-- ENTRY DETAILS MODAL -->
<div class="modal-fade1" id="entryDetailsModal">
<div class="modal-box1 entry-details-modal">
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;">
<div>
<h2 style="margin:0;font-size:20px;color:#223256;font-weight:800">Entry Details <span id="entryDetailsId">-</span></h2>
<div style="font-size:13px;color:var(--muted)">Complete view of all installments for this entry.</div>
<!-- ENTRY DETAILS MODAL (Enhanced) -->
<div class="modal-fade1 entry-details-modal" id="entryDetailsModal">
<div class="modal-box1">
<div class="entry-details-header" >
<h2 >Entry Details</h2>
<div class="subtitle">
<span id="entryDetailsId">Loading...</span>
<span> Complete view of all installments for this entry</span>
</div>
<div><button class="btn ghost" onclick="closeEntryDetailsModal()">Close</button></div>
</div>
<div class="entry-details-content">
<div class="entry-summary-cards">
<div class="entry-summary-card">
<div class="entry-summary-label">Original Amount</div>
<div class="entry-summary-label">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 2v20M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"/>
</svg>
Original Amount
</div>
<div class="entry-summary-value" id="originalAmount">-</div>
</div>
<div class="entry-summary-card">
<div class="entry-summary-label">Total Processed</div>
<div class="entry-summary-label">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M22 12h-4l-3 9L9 3l-3 9H2"/>
</svg>
Total Processed
</div>
<div class="entry-summary-value" id="totalProcessed">-</div>
</div>
<div class="entry-summary-card">
<div class="entry-summary-label">Pending Balance</div>
<div class="entry-summary-label">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/>
</svg>
Pending Balance
</div>
<div class="entry-summary-value" id="pendingBalance">-</div>
</div>
<div class="entry-summary-card">
<div class="entry-summary-label">Total Installments</div>
<div class="entry-summary-label">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/>
</svg>
Total Installments
</div>
<div class="entry-summary-value" id="totalInstallments">-</div>
</div>
</div>
<table class="entry-installments-table" style="width:100%; border-collapse:collapse;">
<div style="margin-top: 30px;">
<h3 style="font-size: 18px; font-weight: 700; color: var(--primary-1); margin-bottom: 16px;">
Installment History
</h3>
<div class="orders-table-container">
<table class="entry-installments-table">
<thead>
<tr>
<th>Installment</th>
@@ -1460,36 +1711,40 @@ html, body {
<tr><td colspan="6" class="empty-state">No installments yet</td></tr>
</tbody>
</table>
</div>
</div>
</div>
<div style="display:flex; justify-content: flex-end; gap:12px; margin-top:16px;">
<button type="button" class="btn ghost" onclick="closeEntryDetailsModal()">Close</button>
<div style="padding: 20px 30px; border-top: 1px solid #eef3fb; display: flex; justify-content: space-between; align-items: center;">
<button type="button" class="btn ghost" onclick="closeEntryDetailsModal()">
Close
</button>
@can('account.add_installment')
<button type="button" class="btn" id="addInstallmentFromDetails">+ Add New Installment</button>
<button type="button" class="btn" id="addInstallmentFromDetails">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="margin-right: 6px;">
<line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/>
</svg>
Add New Installment
</button>
@endcan
</div>
</div>
</div>
<!-- ENTRY ORDERS MODAL -->
<div class="modal-fade1" id="entryOrdersModal">
<div class="modal-box1" style="max-width: 1000px;">
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:12px;">
<div>
<h2 style="margin:0;font-size:20px;color:#223256;font-weight:800;">
Entry Orders
<span id="entryOrdersEntryNo-span" style="font-size:14px;color:#6b7280;margin-left:8px;"></span>
</h2>
<div style="font-size:13px;color:#6f7b8f;">
All orders associated with this entry.
<!-- ENTRY ORDERS MODAL (Enhanced) -->
<div class="modal-fade1 entry-orders-modal" id="entryOrdersModal">
<div class="modal-box1">
<div class="entry-orders-header">
<h2>Entry Orders</h2>
<div class="subtitle">
<span id="entryOrdersEntryNo-span">Loading...</span>
<span> All orders associated with this entry</span>
</div>
</div>
<button class="btn ghost" type="button" onclick="closeEntryOrdersModal()">
Close
</button>
</div>
<div class="entry-orders-content">
<div class="orders-table-container">
<table class="orders-table" style="width:100%;border-collapse:collapse;font-size:13px;">
<table class="orders-table">
<thead>
<tr>
<th>Order ID</th>
@@ -1503,23 +1758,40 @@ html, body {
</thead>
<tbody id="entryOrdersTableBody">
<tr>
<td colspan="7" class="empty-state">No orders associated with this entry</td>
<td colspan="7" class="empty-state">Loading orders...</td>
</tr>
</tbody>
</table>
</div>
<div class="orders-summary-row">
<div class="orders-summary-item">
<div class="orders-summary-value" id="ordersTotalCount">0</div>
<div class="orders-summary-label">Total Orders</div>
</div>
<div class="orders-summary-item">
<div class="orders-summary-value" id="ordersTotalQuantity">0</div>
<div class="orders-summary-label">Total Quantity</div>
</div>
<div class="orders-summary-item">
<div class="orders-summary-value" id="ordersTotalAmount">₹0</div>
<div class="orders-summary-label">Total Amount</div>
</div>
</div>
</div>
<div style="padding: 20px 30px; border-top: 1px solid #eef3fb; display: flex; justify-content: flex-end;">
<button class="btn ghost" type="button" onclick="closeEntryOrdersModal()">
Close
</button>
</div>
</div>
</div>
<!-- Installment Modal -->
<div class="modal-fade1" id="installmentModal">
<div class="modal-box1" style="max-width:720px;">
<div style="display:flex;align-items:center; justify-content:space-between; margin-bottom:12px;">
<div style="display:flex;align-items:center; justify-content:space-between; margin-bottom:12px; background:linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding:16px; border-radius:8px; color:white; margin-top:-15px; margin-left:-20px; margin-right:-15px;">
<div style="font-size:18px;font-weight:800;color:#243a72;">+ Add New Installment</div>
<button class="btn ghost" onclick="closeInstallmentModal()"></button>
</div>
@@ -2785,8 +3057,15 @@ async function submitEditEntry(e) {
function openEntryOrdersModal(entryNo) {
// Set entry number in header
document.getElementById('entryOrdersEntryNo-span').textContent = `(${entryNo})`;
// Reset summary values
document.getElementById('ordersTotalCount').textContent = '0';
document.getElementById('ordersTotalQuantity').textContent = '0';
document.getElementById('ordersTotalAmount').textContent = '₹0';
// table loading state
const tbody = document.getElementById('entryOrdersTableBody');
tbody.innerHTML = `
<tr>
@@ -2794,6 +3073,7 @@ async function submitEditEntry(e) {
</tr>
`;
// API call: /admin/account/entry-orders/{entryno}
jsonFetch(`/admin/account/entry-orders/${encodeURIComponent(entryNo)}`, {
method: 'GET'
})
@@ -2819,29 +3099,44 @@ async function submitEditEntry(e) {
tbody.innerHTML = '';
let totalQuantity = 0;
let totalAmount = 0;
orders.forEach(order => {
const tr = document.createElement('tr');
const amountValue =
order.ttl_amount ??
order.ttlamount ??
order.total_amount ??
order.order_amount ??
order.amount ??
0;
const idString = (order.orderid ?? order.id ?? '').toString().trim();
const numericId = parseInt(idString, 10);
const formattedId = isNaN(numericId)
? escapeHtml(idString)
: 'KNT-25-' + String(numericId).padStart(8, '0');
// Calculate values for summary
const quantity = Number(order.qty || order.order_qty || 0);
const amountValue = Number(order.ttl_amount ?? order.ttlamount ?? order.total_amount ?? order.order_amount ?? order.amount ?? 0);
totalQuantity += quantity;
totalAmount += amountValue;
tr.innerHTML = `
<td>${escapeHtml(order.order_id)}</td>
<td>${escapeHtml(order.mark_no ?? '')}</td>
<td>
<span class="order-id-badge">${formattedId}</span>
</td>
<td>${escapeHtml(order.markno ?? order.mark_no ?? '')}</td>
<td>${escapeHtml(order.origin ?? '')}</td>
<td>${escapeHtml(order.destination ?? '')}</td>
<td>${escapeHtml(order.ctn ?? '')}</td>
<td>${escapeHtml(order.qty ?? '')}</td>
<td>${formatCurrency(amountValue)}</td>
<td><strong>${quantity}</strong></td>
<td><strong>${formatCurrency(amountValue)}</strong></td>
`;
tbody.appendChild(tr);
});
// Update summary
document.getElementById('ordersTotalCount').textContent = orders.length;
document.getElementById('ordersTotalQuantity').textContent = totalQuantity.toLocaleString();
document.getElementById('ordersTotalAmount').textContent = formatCurrency(totalAmount);
})
.catch(() => {
tbody.innerHTML = `
@@ -2854,7 +3149,6 @@ async function submitEditEntry(e) {
document.getElementById('entryOrdersModal').classList.add('modal-open');
}
function closeEntryOrdersModal() {
document.getElementById('entryOrdersModal').classList.remove('modal-open');
}
@@ -2989,7 +3283,7 @@ function handleSearch(){
updatePaginationControls();
}
/* ---------- Entry details & installments ---------- */
/* ---------- Entry details & installments (Enhanced) ---------- */
async function openEntryDetailsModal(entryNo) {
try {
const res = await jsonFetch('/admin/account/entry/' + encodeURIComponent(entryNo));
@@ -2999,58 +3293,109 @@ async function openEntryDetailsModal(entryNo) {
const entry = res.entry;
currentEntry = entry;
// Set header info
document.getElementById('entryDetailsId').textContent = entry.entry_no;
document.getElementById('originalAmount').textContent = formatCurrency(entry.amount);
const totalProcessed = Number(entry.amount) - Number(entry.pending_amount);
// Calculate values
const originalAmount = Number(entry.amount || 0);
const pendingAmount = Number(entry.pending_amount || 0);
const totalProcessed = originalAmount - pendingAmount;
// Update summary cards
document.getElementById('originalAmount').textContent = formatCurrency(originalAmount);
document.getElementById('totalProcessed').textContent = formatCurrency(totalProcessed);
document.getElementById('pendingBalance').textContent = formatCurrency(pendingAmount);
document.getElementById('totalInstallments').textContent = entry.installments?.length || 0;
document.getElementById('pendingBalance').textContent = formatCurrency(entry.pending_amount);
document.getElementById('totalInstallments').textContent = entry.installments.length;
// Render installments table
const tbody = document.getElementById('installmentsTableBody');
tbody.innerHTML = '';
if (!entry.installments || entry.installments.length === 0) {
tbody.innerHTML = `
<tr>
<td colspan="6" class="empty-state">
<div style="padding: 30px; text-align: center;">
<div style="font-size: 48px; color: #eef3fb; margin-bottom: 16px;">📋</div>
<div style="font-size: 16px; color: #6f7b8f; font-weight: 500;">
No installments found for this entry
</div>
<div style="font-size: 14px; color: #9ba5bb; margin-top: 8px;">
Add your first installment to get started
</div>
</div>
</td>
</tr>
`;
} else {
entry.installments.forEach((ins, idx) => {
const tr = document.createElement('tr');
tr.innerHTML = `
<td>${idx === 0 ? 'Original Entry' : 'Installment ' + idx}</td>
<td>${escapeHtml(ins.proc_date)}</td>
<td>${escapeHtml(ins.description)}</td>
<td>${escapeHtml(ins.region)}</td>
<td>${formatCurrency(ins.amount)}</td>
// Determine installment label
let installmentLabel = 'Original Entry';
if (idx > 0) {
installmentLabel = `Installment ${idx}`;
}
// Status dropdown options with colors
const statusOptions = [
{ value: 'Pending', label: '⏳ Pending', color: '#f59e0b' },
{ value: 'Loading', label: '📦 Loading', color: '#3b82f6' },
{ value: 'Packed', label: '📦 Packed', color: '#8b5cf6' },
{ value: 'Dispatched', label: '🚚 Dispatched', color: '#10b981' },
{ value: 'Delivered', label: '✅ Delivered', color: '#0c6b2e' }
];
let statusOptionsHtml = '';
statusOptions.forEach(opt => {
const selected = ins.status === opt.value ? 'selected' : '';
statusOptionsHtml += `<option value="${opt.value}" ${selected} style="color: ${opt.color}; font-weight: 500;">${opt.label}</option>`;
});
tr.innerHTML = `
<td>
<div style="display: flex; align-items: center; gap: 8px;">
<div style="width: 32px; height: 32px; border-radius: 8px; background: linear-gradient(135deg, #f0f7ff, #e6f0ff); display: flex; align-items: center; justify-content: center; font-weight: 700; color: var(--primary-1);">
${idx + 1}
</div>
<span style="font-weight: 600;">${installmentLabel}</span>
</div>
</td>
<td>
<div style="display: flex; align-items: center; gap: 6px;">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="3" y="4" width="18" height="18" rx="2" ry="2"/>
<line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/>
<line x1="3" y1="10" x2="21" y2="10"/>
</svg>
${escapeHtml(ins.proc_date || ins.date || '')}
</div>
</td>
<td>${escapeHtml(ins.description || '')}</td>
<td>
<span style="padding: 4px 8px; background: #f0f7ff; border-radius: 6px; font-size: 12px; font-weight: 600; color: var(--primary-1);">
${escapeHtml(ins.region || '')}
</span>
</td>
<td>
<span style="font-weight: 700; color: var(--primary-1);">
${formatCurrency(ins.amount || 0)}
</span>
</td>
<td>
<select class="installment-status-dropdown"
data-id="${ins.id}"
onchange="updateInstallmentStatus(${ins.id}, this.value)">
<option value="Pending" ${ins.status === 'Pending' ? 'selected' : ''}
style="color: #f59e0b; font-weight: 500; padding: 10px;">
Pending
</option>
<option value="Loading" ${ins.status === 'Loading' ? 'selected' : ''}
style="color: #3b82f6; font-weight: 500; padding: 10px;">
📦 Loading
</option>
<option value="Packed" ${ins.status === 'Packed' ? 'selected' : ''}
style="color: #8b5cf6; font-weight: 500; padding: 10px;">
📦 Packed
</option>
<option value="Dispatched" ${ins.status === 'Dispatched' ? 'selected' : ''}
style="color: #10b981; font-weight: 500; padding: 10px;">
🚚 Dispatched
</option>
<option value="Delivered" ${ins.status === 'Delivered' ? 'selected' : ''}
style="color: #0c6b2e; font-weight: 500; padding: 10px;">
Delivered
</option>
onchange="updateInstallmentStatus(${ins.id}, this.value)"
title="Update installment status">
${statusOptionsHtml}
</select>
</td>
`;
tbody.appendChild(tr);
});
}
// Show modal
document.getElementById('entryDetailsModal').classList.add('modal-open');
} catch (err) {

View File

@@ -830,6 +830,7 @@
<th class="table-header">Order Total</th>
<th class="table-header">Total Payable</th> {{-- NEW --}}
<th class="table-header">Remaining</th> {{-- NEW --}}
<th class="table-header">Paid Amount</th>
<th class="table-header">Create Date</th>
<th class="table-header">Status</th>
<th class="table-header" width="100">Actions</th>
@@ -907,8 +908,11 @@
@endif
</td>
<td class="total-column">
<span class="fw-bold text-success">
{{ number_format($totalPaid, 2) }}
</span>
</td>
<!-- Create Date -->

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -27,7 +27,7 @@
justify-content: space-between;
align-items: center;
border-radius: 17px 17px 0 0;
background: #fceeb8ff;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 54px;
padding: 15px 26px 10px 22px;
border-bottom: 1.4px solid #e8e2cf;
@@ -37,7 +37,7 @@
.invoice-management-title {
font-size: 1.32rem;
font-weight: 800;
color: #2451af;
color: #ffffffff;
letter-spacing: .08em;
display: flex;
align-items: center;
@@ -223,7 +223,7 @@
/* Center all table content */
.table thead tr {
background: #feebbe !important;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.table thead th:first-child {
@@ -237,7 +237,7 @@
background: transparent !important;
border: none;
font-weight: 700;
color: #343535;
color: #ffffffff;
letter-spacing: 0.02em;
font-size: 14px;
padding: 20px 15px;
@@ -259,24 +259,32 @@
/* Soft blue background for ALL table rows */
.table-striped tbody tr {
background: #f0f8ff !important;
transition: all 0.2s ease;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
transition: all 0.15s ease;
border-radius: 6px;
box-shadow: 0 1px 4px rgba(0,0,0,0.05);
}
.table-striped tbody tr td {
padding: 6px 10px;
font-size: 14px;
}
.table-striped tbody tr:hover {
background: #e6f3ff !important;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
transform: translateY(-1px);
box-shadow: 0 2px 6px rgba(0,0,0,0.08);
transform: translateY(-0.5px);
}
/* Remove striped pattern - all rows same soft blue */
.table-striped tbody tr:nth-of-type(odd),
.table-striped tbody tr:nth-of-type(even) {
background: #f0f8ff !important;
}
/* Center all table cells with proper spacing */
.table td {
padding: 18px 15px;
border: none;
@@ -291,7 +299,7 @@
font-weight: 400;
}
/* First and last cell rounded corners */
.table td:first-child {
padding-left: 30px;
font-weight: 600;
@@ -587,7 +595,7 @@
}
.date-separator {
color: #64748b;
color: #000000ff;
font-weight: 500;
font-family: 'Inter', sans-serif;
}

View File

@@ -274,6 +274,30 @@ body {
color: white;
}
.btn-info-compact {
background: linear-gradient(135deg, #06b6d4 0%, #0ea5e9 100%);
color: white;
box-shadow: 0 4px 12px rgba(6, 182, 212, 0.3);
}
.btn-info-compact:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(6, 182, 212, 0.4);
color: white;
}
.btn-warning-compact {
background: var(--warning-gradient);
color: white;
box-shadow: 0 4px 12px rgba(245, 158, 11, 0.3);
}
.btn-warning-compact:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(245, 158, 11, 0.4);
color: white;
}
/* --------------------------------------------------
COMPACT SUMMARY CARDS
-------------------------------------------------- */
@@ -316,7 +340,7 @@ body {
-------------------------------------------------- */
.amount-breakdown-compact {
background: white;
padding: 1rem;
padding: 1.5rem;
border-radius: 8px;
box-shadow: var(--shadow-soft);
margin-bottom: 1.5rem;
@@ -391,6 +415,15 @@ body {
font-weight: 600;
}
/* --------------------------------------------------
HEADER ACTION BUTTONS
-------------------------------------------------- */
.header-actions {
display: flex;
gap: 0.75rem;
align-items: center;
}
/* --------------------------------------------------
RESPONSIVE DESIGN
-------------------------------------------------- */
@@ -422,6 +455,13 @@ body {
.table-compact {
font-size: 0.8rem;
}
.header-actions {
flex-direction: column;
width: 100%;
gap: 0.5rem;
margin-top: 0.5rem;
}
}
@media print {
@@ -454,10 +494,21 @@ body {
<!-- Invoice Preview Section -->
<div class="glass-card">
<div class="card-header-compact">
<div class="card-header-compact d-flex justify-content-between align-items-center">
<h4>
<i class="fas fa-file-invoice me-2"></i>Invoice Overview
</h4>
<div class="header-actions">
<!-- Share Invoice -->
<button class="btn-info-compact btn-compact" id="shareInvoiceBtn">
<i class="fas fa-share-alt me-2"></i>Share Invoice
</button>
<!-- Download Invoice -->
<a href="{{ route('admin.invoices.download', $invoice->id) }}"
class="btn-warning-compact btn-compact" target="_blank">
<i class="fas fa-download me-2"></i>Download Invoice
</a>
</div>
</div>
<div class="card-body-compact invoice-preview-wrapper">
@include('admin.popup_invoice', [
@@ -468,6 +519,89 @@ body {
</div>
</div>
<!-- Amount Breakdown -->
<div class="glass-card">
<div class="card-header-compact">
<h4>
<i class="fas fa-calculator me-2"></i>Amount Breakdown
</h4>
</div>
<div class="card-body-compact">
<div class="amount-breakdown-compact">
@php
$totalPaid = $invoice->installments->sum('amount');
$remaining = $invoice->final_amount_with_gst - $totalPaid;
// Calculate GST/IGST percentage dynamically
$taxPercentage = $invoice->tax_type === 'gst'
? ($invoice->cgst_percent + $invoice->sgst_percent)
: $invoice->igst_percent;
@endphp
<div class="breakdown-row">
<span class="breakdown-label">Total Amount (Before Tax):</span>
<span class="breakdown-value">{{ number_format($invoice->final_amount, 2) }}</span>
</div>
<div class="breakdown-row">
<span class="breakdown-label">
@if($invoice->tax_type === 'gst')
GST ({{ number_format($taxPercentage, 2) }}%)
@else
IGST ({{ number_format($taxPercentage, 2) }}%)
@endif:
</span>
<span class="breakdown-value text-warning">{{ number_format($invoice->gst_amount, 2) }}</span>
</div>
<div class="breakdown-row" style="border-top: 2px solid #e2e8f0; padding-top: 0.75rem;">
<span class="breakdown-label fw-bold">Total Invoice Amount (Including GST):</span>
<span class="breakdown-value fw-bold text-dark">{{ number_format($invoice->final_amount_with_gst, 2) }}</span>
</div>
<div class="breakdown-row">
<span class="breakdown-label text-success">Total Paid:</span>
<span class="breakdown-value fw-bold text-success" id="paidAmount">{{ number_format($totalPaid, 2) }}</span>
</div>
<div class="breakdown-row" style="border-bottom: none;">
<span class="breakdown-label text-danger">Remaining:</span>
<span class="breakdown-value fw-bold text-danger" id="remainingAmount">{{ number_format($remaining, 2) }}</span>
</div>
<!-- NEW: Customer's Total Amount Due Across All Invoices -->
<div class="breakdown-row" style="border-top: 2px solid #3b82f6; background: rgba(59, 130, 246, 0.05);">
<span class="breakdown-label fw-bold text-primary">
<i class="fas fa-users me-1"></i>Total Amount Due (Including Tax):
<small class="d-block text-muted" style="font-size: 0.75rem; font-weight: normal;">
</small>
</span>
<span class="breakdown-value fw-bold text-primary" style="font-size: 1.1rem;">
{{ number_format($customerTotalDue, 2) }}
</span>
</div>
</div>
<!-- Installment Summary -->
<div class="summary-grid-compact mt-3">
<div class="summary-card-compact total">
<div class="summary-value-compact text-success">{{ number_format($invoice->final_amount_with_gst, 2) }}</div>
<div class="summary-label-compact">Total Amount</div>
</div>
<div class="summary-card-compact paid">
<div class="summary-value-compact text-primary">{{ number_format($totalPaid, 2) }}</div>
<div class="summary-label-compact">Total Paid</div>
</div>
<div class="summary-card-compact remaining">
<div class="summary-value-compact text-warning">{{ number_format($remaining, 2) }}</div>
<div class="summary-label-compact">Remaining</div>
</div>
</div>
</div>
</div>
<!-- Edit Invoice Form -->
<div class="glass-card">
<div class="card-header-compact">
@@ -577,81 +711,6 @@ body {
</div>
</div>
@php
$totalPaid = $invoice->installments->sum('amount');
$remaining = $invoice->final_amount_with_gst - $totalPaid;
@endphp
<!-- Amount Breakdown -->
<div class="amount-breakdown-compact">
<h6 class="fw-bold mb-3 text-dark">
<i class="fas fa-calculator me-2"></i>Amount Breakdown
</h6>
<div class="breakdown-row">
<span class="breakdown-label">Total Amount (Before Tax):</span>
<span class="breakdown-value">{{ number_format($invoice->final_amount, 2) }}</span>
</div>
<div class="breakdown-row">
<span class="breakdown-label">Tax Type:</span>
<span class="breakdown-value text-primary">
@if($invoice->tax_type === 'gst')
GST (CGST + SGST)
@else
IGST
@endif
</span>
</div>
<div class="breakdown-row">
<span class="breakdown-label">Tax Percentage:</span>
<span class="breakdown-value text-primary">
@if($invoice->tax_type === 'gst')
{{ $invoice->cgst_percent + $invoice->sgst_percent }}%
@else
{{ $invoice->igst_percent }}%
@endif
</span>
</div>
<div class="breakdown-row">
<span class="breakdown-label">GST Amount:</span>
<span class="breakdown-value text-warning">{{ number_format($invoice->gst_amount, 2) }}</span>
</div>
<div class="breakdown-row" style="border-top: 2px solid #e2e8f0; padding-top: 0.75rem;">
<span class="breakdown-label fw-bold">Total Invoice Amount (Including GST):</span>
<span class="breakdown-value fw-bold text-dark">{{ number_format($invoice->final_amount_with_gst, 2) }}</span>
</div>
<div class="breakdown-row">
<span class="breakdown-label text-success">Total Paid:</span>
<span class="breakdown-value fw-bold text-success" id="paidAmount">{{ number_format($totalPaid, 2) }}</span>
</div>
<div class="breakdown-row" style="border-bottom: none;">
<span class="breakdown-label text-danger">Remaining:</span>
<span class="breakdown-value fw-bold text-danger" id="remainingAmount">{{ number_format($remaining, 2) }}</span>
</div>
</div>
<!-- Installment Summary -->
<div class="summary-grid-compact">
<div class="summary-card-compact total">
<div class="summary-value-compact text-success">{{ number_format($invoice->final_amount_with_gst, 2) }}</div>
<div class="summary-label-compact">Total Amount</div>
</div>
<div class="summary-card-compact paid">
<div class="summary-value-compact text-primary">{{ number_format($totalPaid, 2) }}</div>
<div class="summary-label-compact">Total Paid</div>
</div>
<div class="summary-card-compact remaining">
<div class="summary-value-compact text-warning">{{ number_format($remaining, 2) }}</div>
<div class="summary-label-compact">Remaining</div>
</div>
</div>
<!-- Installment Management -->
<div class="glass-card">
<div class="card-header-compact d-flex justify-content-between align-items-center">
@@ -736,6 +795,7 @@ body {
<h6 class="fw-bold mb-2 text-dark">
<i class="fas fa-history me-2"></i>Installment History
</h6>
@if($invoice->installments->count() > 0)
<div class="table-responsive">
<table class="table-compact">
<thead>
@@ -776,24 +836,87 @@ body {
</tbody>
</table>
</div>
</div>
</div>
</div>
<!-- Add this just above the table -->
<div id="noInstallmentsMsg" class="d-none text-center text-muted fw-bold py-4">
@else
<div id="noInstallmentsMsg" class="text-center text-muted fw-bold py-4">
No installments found. Click "Add Installment" to create one.
</div>
<table ...>
<tbody id="installmentTable">
@foreach($invoice->installments as $i)
...
@endforeach
</tbody>
</table>
@endif
</div>
</div>
</div>
<script>
document.addEventListener("DOMContentLoaded", function () {
// Share Invoice Functionality
const shareInvoiceBtn = document.getElementById('shareInvoiceBtn');
if (shareInvoiceBtn) {
shareInvoiceBtn.addEventListener('click', function() {
const shareUrl = window.location.href;
const invoiceNo = "{{ $invoice->invoice_no }}";
const message = `Invoice #${invoiceNo} - Total: ₹{{ number_format($invoice->final_amount_with_gst, 2) }}\nView: ${shareUrl}`;
if (navigator.share) {
navigator.share({
title: `Invoice #${invoiceNo}`,
text: `Invoice #${invoiceNo} - Total: ₹{{ number_format($invoice->final_amount_with_gst, 2) }}`,
url: shareUrl
}).catch(console.error);
} else if (navigator.clipboard) {
navigator.clipboard.writeText(message)
.then(() => {
alert('Invoice link copied to clipboard!');
})
.catch(err => {
console.error('Failed to copy: ', err);
// Fallback to prompt
prompt('Copy this link to share:', shareUrl);
});
} else {
prompt('Copy this link to share:', shareUrl);
}
});
}
// Print Invoice Function
window.printInvoice = function() {
const printWindow = window.open('', '_blank');
const invoiceContent = document.querySelector('.invoice-preview-wrapper').innerHTML;
const printContent = `
<!DOCTYPE html>
<html>
<head>
<title>Invoice {{ $invoice->invoice_no }}</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
.invoice-container { max-width: 800px; margin: 0 auto; }
.text-end { text-align: right; }
.fw-bold { font-weight: bold; }
table { width: 100%; border-collapse: collapse; }
th, td { padding: 8px; border: 1px solid #ddd; }
th { background-color: #f8f9fa; }
.total-row { background-color: #f8f9fa; font-weight: bold; }
</style>
</head>
<body>
<div class="invoice-container">
${invoiceContent}
</div>
<script>
window.onload = function() {
window.print();
setTimeout(function() {
window.close();
}, 500);
};
<\/script>
</body>
</html>
`;
printWindow.document.write(printContent);
printWindow.document.close();
};
// Toggle Installment Form
const toggleBtn = document.getElementById("toggleInstallmentForm");
const formBox = document.getElementById("installmentForm");
@@ -814,6 +937,7 @@ document.addEventListener("DOMContentLoaded", function () {
maximumFractionDigits: 2
});
if (submitForm) {
submitForm.addEventListener("submit", function (e) {
e.preventDefault();
@@ -839,9 +963,40 @@ document.addEventListener("DOMContentLoaded", function () {
}
const table = document.querySelector("#installmentTable");
const index = table.rows.length + 1;
const noInstallmentsMsg = document.getElementById("noInstallmentsMsg");
table.insertAdjacentHTML("beforeend", `
if (noInstallmentsMsg) {
noInstallmentsMsg.classList.add("d-none");
}
if (!table) {
// Create table if it doesn't exist
const tableHTML = `
<div class="table-responsive">
<table class="table-compact">
<thead>
<tr>
<th>#</th>
<th>Date</th>
<th>Payment Method</th>
<th>Reference No</th>
<th>Amount</th>
<th>Action</th>
</tr>
</thead>
<tbody id="installmentTable">
</tbody>
</table>
</div>
`;
const parent = submitForm.closest('.card-body-compact');
parent.insertAdjacentHTML('beforeend', tableHTML);
}
const newTable = document.querySelector("#installmentTable");
const index = newTable.rows.length + 1;
newTable.insertAdjacentHTML("beforeend", `
<tr data-id="${data.installment.id}">
<td class="fw-bold text-muted">${index}</td>
<td>${data.installment.installment_date}</td>
@@ -860,15 +1015,11 @@ document.addEventListener("DOMContentLoaded", function () {
</tr>
`);
// Update all displayed values using GST fields!
// Update all displayed values
if (document.getElementById("paidAmount")) document.getElementById("paidAmount").textContent = formatINR(data.totalPaid);
if (document.getElementById("remainingAmount")) document.getElementById("remainingAmount").textContent = formatINR(data.remaining);
if (document.getElementById("baseAmount")) document.getElementById("baseAmount").textContent = formatINR(data.baseAmount);
if (document.getElementById("gstAmount")) document.getElementById("gstAmount").textContent = formatINR(data.gstAmount);
if (document.getElementById("totalInvoiceWithGst")) document.getElementById("totalInvoiceWithGst").textContent = formatINR(data.finalAmountWithGst);
if (document.getElementById("invoiceStatus")) document.getElementById("invoiceStatus").textContent = data.isCompleted ? "Paid" : "Pending";
// Update summary cards if used
// Update summary cards
const paidCard = document.querySelector(".summary-card-compact.paid .summary-value-compact");
if (paidCard) paidCard.textContent = formatINR(data.totalPaid);
const remainingCard = document.querySelector(".summary-card-compact.remaining .summary-value-compact");
@@ -890,6 +1041,7 @@ document.addEventListener("DOMContentLoaded", function () {
alert("Something went wrong. Please try again.");
});
});
}
// Delete Installment
document.addEventListener("click", function (e) {
@@ -911,15 +1063,27 @@ document.addEventListener("DOMContentLoaded", function () {
.then(data => {
if (data.status === "success") {
row.style.opacity = "0";
setTimeout(() => row.remove(), 300);
setTimeout(() => {
row.remove();
// Update all displayed values using GST fields!
// Update row numbers
const rows = document.querySelectorAll("#installmentTable tr");
rows.forEach((row, index) => {
row.querySelector("td:first-child").textContent = index + 1;
});
// Show no installments message if empty
if (rows.length === 0) {
const noInstallmentsMsg = document.getElementById("noInstallmentsMsg");
if (noInstallmentsMsg) {
noInstallmentsMsg.classList.remove("d-none");
}
}
}, 300);
// Update all displayed values
if (document.getElementById("paidAmount")) document.getElementById("paidAmount").textContent = formatINR(data.totalPaid);
if (document.getElementById("remainingAmount")) document.getElementById("remainingAmount").textContent = formatINR(data.remaining);
if (document.getElementById("baseAmount")) document.getElementById("baseAmount").textContent = formatINR(data.baseAmount);
if (document.getElementById("gstAmount")) document.getElementById("gstAmount").textContent = formatINR(data.gstAmount);
if (document.getElementById("totalInvoiceWithGst")) document.getElementById("totalInvoiceWithGst").textContent = formatINR(data.finalAmountWithGst);
if (document.getElementById("invoiceStatus")) document.getElementById("invoiceStatus").textContent = data.remaining === 0 ? "Paid" : "Pending";
// Update summary cards
const paidCard = document.querySelector(".summary-card-compact.paid .summary-value-compact");
@@ -927,7 +1091,15 @@ document.addEventListener("DOMContentLoaded", function () {
const remainingCard = document.querySelector(".summary-card-compact.remaining .summary-value-compact");
if (remainingCard) remainingCard.textContent = formatINR(data.remaining);
// Show add installment button if there's remaining amount
if (data.remaining > 0 && !document.getElementById("toggleInstallmentForm")) {
const header = document.querySelector(".glass-card .card-header-compact");
header.innerHTML += `
<button id="toggleInstallmentForm" class="btn-primary-compact btn-compact">
<i class="fas fa-plus-circle me-2"></i>Add Installment
</button>
`;
}
alert(data.message);
} else {
@@ -940,6 +1112,4 @@ document.addEventListener("DOMContentLoaded", function () {
});
});
</script>
@endsection

View File

@@ -12,6 +12,7 @@
padding: 0;
font-size: 15px;
}
.container {
max-width: 850px;
margin: 24px auto 0 auto;
@@ -20,49 +21,56 @@
box-shadow: 0 2px 14px rgba(40,105,160,0.08);
padding: 35px 32px 18px 32px;
}
/* ================= HEADER FIX ================= */
.header {
display: flex;
justify-content: space-between;
align-items: flex-start;
width: 100%;
overflow: hidden; /* clears floats */
border-bottom: 2px solid #E6EBF0;
padding-bottom: 13px;
}
/* LEFT SIDE */
.logo-company {
display: flex;
align-items: flex-start;
float: left;
width: 65%;
}
/* RIGHT SIDE */
.invoice-details {
float: right;
width: 35%;
text-align: right;
}
/* Logo */
.logo {
height: 50px;
margin-right: 13px;
margin-bottom: 6px;
}
/* Company text */
.company-details {
margin-top: 0;
font-size: 15px;
line-height: 1.55;
}
.company-title {
font-size: 21px;
font-weight: bold;
margin-bottom: 2px;
}
.company-sub {
font-size: 16px;
margin-bottom: 8px;
font-weight: 500;
}
.invoice-details {
text-align: right;
min-width: 220px;
margin-bottom: 4px;
}
/* Invoice */
.invoice-title {
font-weight: bold;
font-size: 23px;
letter-spacing: 0.5px;
margin-bottom: 2px;
}
.paid-label {
margin-top: 8px;
margin-bottom: 2px;
margin-bottom: 6px;
}
/* Paid / Status */
.paid-tag {
background: #23BF47;
color: #fff;
@@ -73,6 +81,7 @@
display: inline-block;
position: relative;
}
.paid-tag:before {
content: '';
position: absolute;
@@ -83,26 +92,29 @@
background: #fff;
border-radius: 50%;
}
.paid-date {
font-size: 14px;
color: #23BF47;
margin-top: 2px;
margin-top: 3px;
}
/* ================= REST ================= */
.bill-section {
background: #F3F7FB;
border-radius: 11px;
padding: 20px 18px 13px 18px;
margin: 28px 0 16px 0;
box-shadow: 0 0px 0px #0000;
}
.bill-title {
font-size: 17px;
font-weight: bold;
color: #23355D;
margin-bottom: 4px;
letter-spacing: 0.3px;
}
.bill-details {
font-size: 15px;
line-height: 1.6;
@@ -113,56 +125,27 @@
border-collapse: collapse;
margin-top: 9px;
margin-bottom: 13px;
background: #fff;
border-radius: 10px;
overflow: hidden;
}
th {
background: #F6F7F9;
padding: 10px 0;
font-size: 15px;
color: #6781A6;
font-weight: bold;
border: none;
text-align: left;
}
td {
padding: 7px 0;
color: #222;
font-size: 15px;
border: none;
text-align: left;
color: #222;
}
tbody tr:not(:last-child) td {
border-bottom: 1px solid #E6EBF0;
}
tbody tr:last-child td {
border-bottom: none;
}
.totals-row td {
font-weight: bold;
color: #23355D;
}
.gst-row td {
font-weight: 500;
color: #23BF47;
}
.total-row td {
font-weight: bold;
font-size: 17px;
color: #222;
}
.payment-info {
margin-top: 24px;
margin-bottom: 9px;
font-size: 15px;
}
.ref-number {
font-size: 14px;
color: #6781A6;
margin-bottom: 8px;
margin-top: 2px;
}
.footer {
border-top: 1.2px solid #E6EBF0;
margin-top: 25px;
@@ -171,10 +154,17 @@
color: #888;
text-align: center;
}
.footer strong {
color: #222;
.gst-row td {
color: #23BF47;
font-weight: 500;
}
.total-row td {
font-weight: bold;
font-size: 17px;
border-top: 2px solid #E6EBF0;
}
</style>
</head>
<body>
@@ -241,18 +231,47 @@
<td>{{ number_format($item->ttl_amount, 0) }}</td>
</tr>
@endforeach
{{-- SUBTOTAL --}}
<tr class="totals-row">
<td colspan="3" style="text-align:right;">Subtotal:</td>
<td>{{ number_format($invoice->subtotal, 0) }}</td>
<td colspan="3" style="text-align:right;">total</td>
<td style="text-align:right;">
{{ number_format($invoice->final_amount, 2) }}
</td>
</tr>
{{-- TAX --}}
@if($invoice->tax_type === 'gst' && $invoice->gst_amount > 0)
<tr class="gst-row">
<td colspan="3" style="text-align:right;">GST ({{ $invoice->gst_percent }}%):</td>
<td>{{ number_format($invoice->gst_amount, 0) }}</td>
<td colspan="3" style="text-align:right;">
GST ({{ $invoice->gst_percent }}%)
</td>
<td style="text-align:right;">
{{ number_format($invoice->gst_amount, 2) }}
</td>
</tr>
@elseif($invoice->tax_type === 'igst' && $invoice->gst_amount > 0)
<tr class="gst-row">
<td colspan="3" style="text-align:right;">
IGST ({{ $invoice->gst_percent }}%)
</td>
<td style="text-align:right;">
{{ number_format($invoice->gst_amount, 2) }}
</td>
</tr>
@endif
{{-- TOTAL --}}
<tr class="total-row">
<td colspan="3" style="text-align:right;">Total:</td>
<td>{{ number_format($invoice->final_amount_with_gst, 0) }}</td>
<td colspan="3" style="text-align:right;">Total Amount</td>
<td style="text-align:right;">
{{ number_format($invoice->final_amount_with_gst, 2) }}
</td>
</tr>
</tbody>
</table>
<!-- Payment Info & Reference -->

View File

@@ -7,6 +7,7 @@
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
<style>
/* ALL YOUR EXISTING CSS STAYS HERE - EXCEPT GST TOTALS SECTION REMOVED */
:root {
--primary: #2c3e50;
--secondary: #3498db;
@@ -284,6 +285,8 @@
flex-wrap: wrap;
}
/* GST Totals Section Styles - COMPLETELY REMOVED */
@media (max-width: 768px) {
.invoice-container {
margin: 1rem;
@@ -346,6 +349,17 @@
overflow-x: auto;
}
}
@media print {
body {
background-color: white;
}
.invoice-container {
box-shadow: none;
border: 1px solid #ddd;
}
}
</style>
</head>
<body>
@@ -356,6 +370,8 @@
============================ -->
@php
$showActions = $showActions ?? true;
// REMOVED GST CALCULATION LOGIC
@endphp
<div class="compact-header">
@@ -440,7 +456,6 @@
<div class="id-value">
@php
$shipmentId = 'N/A';
// Try multiple ways to get shipment ID
if($invoice->shipment && $invoice->shipment->shipment_id) {
$shipmentId = $invoice->shipment->shipment_id;
} elseif($invoice->shipment_id) {
@@ -550,62 +565,14 @@
</div>
</div>
@php
$totalAmount = $invoice->final_amount;
$gstAmount = $invoice->gst_amount;
$totalPayable = $invoice->final_amount_with_gst;
$paidAmount = $invoice->totalPaid();
$remaining = $invoice->remainingAmount();
@endphp
<div class="summary-container">
<div class="row justify-content-center">
<div class="col-lg-8">
<div class="amount-row">
<span>Total Amount</span>
<span class="fw-bold">{{ number_format($totalAmount,2) }}</span>
</div>
<div class="amount-row">
<span>GST Amount</span>
<span class="fw-bold text-danger">
+ {{ number_format($gstAmount,2) }}
</span>
</div>
<div class="amount-row border-top pt-2">
<span class="fw-bold">Total Payable</span>
<span class="fw-bold text-success">
{{ number_format($totalPayable,2) }}
</span>
</div>
<div class="amount-row">
<span>Paid Amount</span>
<span class="fw-bold text-primary">
{{ number_format($paidAmount,2) }}
</span>
</div>
<div class="amount-row border-top pt-2">
<span class="fw-bold text-danger">Remaining Amount</span>
<span class="fw-bold text-danger fs-5">
{{ number_format($remaining,2) }}
</span>
</div>
</div>
</div>
</div>
<!-- ============================
GST TOTALS SECTION - COMPLETELY REMOVED
============================ -->
<!-- ============================
FOOTER DOWNLOAD & SHARE
============================ -->
<div class="mt-4 pt-3 border-top text-center">
<!-- <div class="mt-4 pt-3 border-top text-center">
<a href="{{ route('admin.invoices.download', $invoice->id) }}"
class="btn btn-primary me-2">
<i class="fas fa-download me-1"></i> Download PDF
@@ -614,8 +581,7 @@
<button class="btn btn-success" onclick="shareInvoice()">
<i class="fas fa-share me-1"></i> Share
</button>
</div>
</div> -->
</div>
</div>
@@ -624,7 +590,7 @@
<!-- ============================
SHARE SCRIPT
============================ -->
<script>
<!-- <script>
function shareInvoice() {
const shareData = {
title: "Invoice {{ $invoice->invoice_number }}",
@@ -639,7 +605,12 @@
alert("Link copied! Sharing not supported on this browser.");
}
}
</script>
// Add print functionality
function printInvoice() {
window.print();
}
</script> -->
</body>
</html>

View File

@@ -22,7 +22,7 @@
.custom-table tbody tr:hover { background-color: #fffbea; transform: scale(1.01); box-shadow: 0 2px 6px rgba(0,0,0,0.05); }
.priority-badge {
display: inline-flex; align-items: center; font-size: 13.5px; padding: 6px 16px; border-radius: 12px; font-weight: 600;
box-shadow: 0 1px 2px 0 rgba(130,130,130,0.15); width: 90px; min-height: 28px; justify-content: center;
box-shadow: 0 1px 2px 0 rgba(230, 206, 206, 0.15); width: 90px; min-height: 28px; justify-content: center;
color: #fff; margin: 2px 0; transition: transform 0.2s ease-in-out;
}
.priority-badge:hover { transform: scale(1.08); }
@@ -30,8 +30,8 @@
.priority-medium { background: linear-gradient(135deg, #ffe390, #f5b041); }
.priority-low { background: linear-gradient(135deg, #b8f0c2, #1d8660); }
.custom-table thead th {
text-align: center; font-weight: 700; color: #000; padding: 14px; font-size: 17px; letter-spacing: 0.5px;
border-bottom: 2px solid #bfbfbf; background-color: #fde4b3;
text-align: center; font-weight: 700; color: #ffffffff; padding: 14px; font-size: 17px; letter-spacing: 0.5px;
border-bottom: 2px solid #bfbfbf; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);;
}
.custom-table thead tr:first-child th:first-child { border-top-left-radius: 12px; }
.custom-table thead tr:first-child th:last-child { border-top-right-radius: 12px; }
@@ -333,7 +333,11 @@ a.btn.btn-primary.position-relative .badge {
box-shadow: 0 0 0 2px #ffffff;
}
.custom-table th,
.custom-table td {
text-align: center;
vertical-align: middle;
}
</style>

File diff suppressed because it is too large Load Diff