904 lines
34 KiB
PHP
904 lines
34 KiB
PHP
@extends('admin.layouts.app')
|
|
|
|
@section('page-title', 'Edit Invoice')
|
|
|
|
@section('content')
|
|
<style>
|
|
:root {
|
|
--primary-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
--success-gradient: linear-gradient(135deg, #10b981 0%, #059669 100%);
|
|
--warning-gradient: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);
|
|
--danger-gradient: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
|
|
--glass-bg: rgba(255, 255, 255, 0.95);
|
|
--glass-border: rgba(255, 255, 255, 0.2);
|
|
--shadow-soft: 0 8px 32px rgba(0, 0, 0, 0.08);
|
|
--shadow-medium: 0 12px 48px rgba(0, 0, 0, 0.12);
|
|
--shadow-strong: 0 20px 60px rgba(0, 0, 0, 0.15);
|
|
--border-radius: 12px;
|
|
}
|
|
|
|
body {
|
|
background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
|
|
font-family: "Inter", "Segoe UI", system-ui, sans-serif;
|
|
}
|
|
|
|
@keyframes fadeUp {
|
|
0% {
|
|
opacity: 0;
|
|
transform: translateY(20px) scale(0.98);
|
|
}
|
|
100% {
|
|
opacity: 1;
|
|
transform: translateY(0) scale(1);
|
|
}
|
|
}
|
|
|
|
.glass-card {
|
|
background: var(--glass-bg);
|
|
backdrop-filter: blur(20px);
|
|
border-radius: var(--border-radius);
|
|
border: 1px solid var(--glass-border);
|
|
box-shadow: var(--shadow-strong);
|
|
position: relative;
|
|
overflow: hidden;
|
|
animation: fadeUp 0.6s ease;
|
|
margin-bottom: 1.5rem;
|
|
}
|
|
|
|
.glass-card::before {
|
|
content: "";
|
|
position: absolute;
|
|
inset: 0;
|
|
background: linear-gradient(
|
|
45deg,
|
|
rgba(102, 126, 234, 0.03),
|
|
rgba(118, 75, 162, 0.03) 50%,
|
|
rgba(16, 185, 129, 0.03)
|
|
);
|
|
pointer-events: none;
|
|
}
|
|
|
|
.card-header-compact {
|
|
background: var(--primary-gradient);
|
|
color: #fff;
|
|
padding: 1rem 1.5rem;
|
|
border: none;
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.card-header-compact h4 {
|
|
margin: 0;
|
|
font-weight: 700;
|
|
font-size: 1.3rem;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
|
}
|
|
|
|
.card-body-compact {
|
|
padding: 1.5rem;
|
|
background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
|
|
position: relative;
|
|
z-index: 1;
|
|
}
|
|
|
|
.form-grid-compact {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
|
gap: 1rem;
|
|
margin-bottom: 1.5rem;
|
|
}
|
|
|
|
.form-group-compact {
|
|
position: relative;
|
|
}
|
|
|
|
.form-label-compact {
|
|
font-weight: 600;
|
|
color: #374151;
|
|
margin-bottom: 8px;
|
|
font-size: 0.9rem;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
|
|
.form-control-compact,
|
|
.form-select-compact {
|
|
border: 2px solid #e2e8f0;
|
|
border-radius: 8px;
|
|
padding: 10px 12px;
|
|
font-size: 0.9rem;
|
|
transition: all 0.3s ease;
|
|
background: #ffffff;
|
|
width: 100%;
|
|
}
|
|
|
|
.form-control-compact:focus,
|
|
.form-select-compact:focus {
|
|
border-color: #667eea;
|
|
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
|
|
outline: none;
|
|
}
|
|
|
|
.btn-compact {
|
|
padding: 10px 20px;
|
|
border-radius: 8px;
|
|
font-weight: 600;
|
|
font-size: 0.9rem;
|
|
transition: all 0.3s ease;
|
|
border: none;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
text-decoration: none;
|
|
}
|
|
|
|
.btn-success-compact {
|
|
background: var(--success-gradient);
|
|
color: white;
|
|
box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3);
|
|
}
|
|
|
|
.btn-success-compact:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 6px 20px rgba(16, 185, 129, 0.4);
|
|
color: white;
|
|
}
|
|
|
|
.btn-primary-compact {
|
|
background: var(--primary-gradient);
|
|
color: white;
|
|
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
|
|
}
|
|
|
|
.btn-primary-compact:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
|
|
color: white;
|
|
}
|
|
|
|
.btn-danger-compact {
|
|
background: var(--danger-gradient);
|
|
color: white;
|
|
box-shadow: 0 4px 12px rgba(239, 68, 68, 0.3);
|
|
}
|
|
|
|
.btn-danger-compact:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 6px 20px rgba(239, 68, 68, 0.4);
|
|
color: white;
|
|
}
|
|
|
|
.summary-grid-compact {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
gap: 1rem;
|
|
margin-bottom: 1.5rem;
|
|
}
|
|
|
|
.summary-card-compact {
|
|
background: #ffffff;
|
|
padding: 1rem;
|
|
border-radius: 8px;
|
|
box-shadow: var(--shadow-soft);
|
|
border-left: 4px solid;
|
|
text-align: center;
|
|
}
|
|
|
|
.summary-card-compact.total {
|
|
border-left-color: #10b981;
|
|
}
|
|
|
|
.summary-card-compact.paid {
|
|
border-left-color: #3b82f6;
|
|
}
|
|
|
|
.summary-card-compact.remaining {
|
|
border-left-color: #f59e0b;
|
|
}
|
|
|
|
.summary-value-compact {
|
|
font-size: 1.5rem;
|
|
font-weight: 700;
|
|
margin-bottom: 0.25rem;
|
|
}
|
|
|
|
.summary-label-compact {
|
|
font-size: 0.8rem;
|
|
color: #64748b;
|
|
font-weight: 600;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.5px;
|
|
}
|
|
|
|
.amount-breakdown-compact {
|
|
background: #ffffff;
|
|
padding: 1rem;
|
|
border-radius: 8px;
|
|
box-shadow: var(--shadow-soft);
|
|
margin-bottom: 1.5rem;
|
|
}
|
|
|
|
.breakdown-row {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 0.5rem 0;
|
|
border-bottom: 1px solid #f1f5f9;
|
|
}
|
|
|
|
.breakdown-row:last-child {
|
|
border-bottom: none;
|
|
}
|
|
|
|
.breakdown-label {
|
|
font-weight: 600;
|
|
color: #374151;
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
.breakdown-value {
|
|
font-weight: 600;
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
.table-compact {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
margin-bottom: 0;
|
|
font-size: 0.85rem;
|
|
}
|
|
|
|
.table-compact thead th {
|
|
background: var(--primary-gradient);
|
|
color: #ffffff;
|
|
padding: 0.75rem 1rem;
|
|
font-weight: 600;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.5px;
|
|
font-size: 0.8rem;
|
|
border: none;
|
|
}
|
|
|
|
.table-compact tbody tr {
|
|
background: #ffffff;
|
|
transition: all 0.2s ease;
|
|
}
|
|
|
|
.table-compact tbody tr:hover {
|
|
background: #f8fafc;
|
|
}
|
|
|
|
.table-compact tbody td {
|
|
padding: 0.75rem 1rem;
|
|
border-bottom: 1px solid #e2e8f0;
|
|
vertical-align: middle;
|
|
}
|
|
|
|
.badge-compact {
|
|
padding: 0.25rem 0.75rem;
|
|
border-radius: 20px;
|
|
font-size: 0.75rem;
|
|
font-weight: 600;
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.glass-card {
|
|
margin: 0.5rem;
|
|
border-radius: 10px;
|
|
}
|
|
.card-body-compact {
|
|
padding: 1rem;
|
|
}
|
|
.form-grid-compact {
|
|
grid-template-columns: 1fr;
|
|
gap: 0.75rem;
|
|
}
|
|
.summary-grid-compact {
|
|
grid-template-columns: 1fr;
|
|
gap: 0.75rem;
|
|
}
|
|
.btn-compact {
|
|
width: 100%;
|
|
justify-content: center;
|
|
}
|
|
.table-compact {
|
|
font-size: 0.8rem;
|
|
}
|
|
}
|
|
</style>
|
|
|
|
<div class="container-fluid py-3">
|
|
{{-- Invoice Preview / Overview --}}
|
|
<div class="glass-card">
|
|
<div class="card-header-compact">
|
|
<h4>
|
|
<i class="fas fa-file-invoice me-2"></i>
|
|
Invoice Overview
|
|
</h4>
|
|
</div>
|
|
<div class="card-body-compact">
|
|
{{-- Read-only popup: items price/total cannot be edited here --}}
|
|
@include('admin.popup_invoice', ['invoice' => $invoice, 'shipment' => $shipment])
|
|
</div>
|
|
</div>
|
|
|
|
{{-- Edit Invoice Header Details (POST) --}}
|
|
<div class="glass-card">
|
|
<div class="card-header-compact">
|
|
<h4>
|
|
<i class="fas fa-edit me-2"></i>
|
|
Edit Invoice Details
|
|
</h4>
|
|
</div>
|
|
<div class="card-body-compact">
|
|
<form action="{{ route('admin.invoices.update', $invoice->id) }}" method="POST">
|
|
@csrf
|
|
|
|
<div class="form-grid-compact">
|
|
{{-- Invoice Date --}}
|
|
<div class="form-group-compact">
|
|
<label class="form-label-compact">
|
|
<i class="fas fa-calendar-day"></i> Invoice Date
|
|
</label>
|
|
<input type="date"
|
|
name="invoice_date"
|
|
class="form-control-compact"
|
|
value="{{ old('invoice_date', $invoice->invoice_date) }}"
|
|
required>
|
|
</div>
|
|
|
|
{{-- Due Date --}}
|
|
<div class="form-group-compact">
|
|
<label class="form-label-compact">
|
|
<i class="fas fa-clock"></i> Due Date
|
|
</label>
|
|
<input type="date"
|
|
name="due_date"
|
|
class="form-control-compact"
|
|
value="{{ old('due_date', $invoice->due_date) }}"
|
|
required>
|
|
</div>
|
|
|
|
{{-- Final Amount (Base) --}}
|
|
<div class="form-group-compact">
|
|
<label class="form-label-compact">
|
|
<i class="fas fa-money-bill-wave"></i> Final Amount (Before GST)
|
|
</label>
|
|
<input type="number"
|
|
step="0.01"
|
|
name="final_amount"
|
|
class="form-control-compact"
|
|
value="{{ old('final_amount', $invoice->final_amount) }}"
|
|
required>
|
|
</div>
|
|
|
|
{{-- Tax Type --}}
|
|
<div class="form-group-compact">
|
|
<label class="form-label-compact">
|
|
<i class="fas fa-receipt"></i> Tax Type
|
|
</label>
|
|
<div class="d-flex gap-3 mt-1">
|
|
<div class="form-check">
|
|
<input class="form-check-input"
|
|
type="radio"
|
|
name="tax_type"
|
|
value="gst"
|
|
{{ old('tax_type', $invoice->tax_type) === 'gst' ? 'checked' : '' }}>
|
|
<label class="form-check-label fw-semibold">GST (CGST + SGST)</label>
|
|
</div>
|
|
<div class="form-check">
|
|
<input class="form-check-input"
|
|
type="radio"
|
|
name="tax_type"
|
|
value="igst"
|
|
{{ old('tax_type', $invoice->tax_type) === 'igst' ? 'checked' : '' }}>
|
|
<label class="form-check-label fw-semibold">IGST</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- Tax Percentage --}}
|
|
<div class="form-group-compact">
|
|
<label class="form-label-compact">
|
|
<i class="fas fa-percentage"></i> Tax Percentage
|
|
</label>
|
|
<input type="number"
|
|
step="0.01"
|
|
min="0"
|
|
max="28"
|
|
name="tax_percent"
|
|
class="form-control-compact"
|
|
value="{{ old('tax_percent',
|
|
$invoice->tax_type === 'gst'
|
|
? ($invoice->cgst_percent + $invoice->sgst_percent)
|
|
: $invoice->igst_percent
|
|
) }}"
|
|
required>
|
|
</div>
|
|
|
|
{{-- Status --}}
|
|
<div class="form-group-compact">
|
|
<label class="form-label-compact">
|
|
<i class="fas fa-tasks"></i> Status
|
|
</label>
|
|
<select name="status" class="form-select-compact" required>
|
|
<option value="pending" {{ old('status', $invoice->status) === 'pending' ? 'selected' : '' }}>
|
|
Pending
|
|
</option>
|
|
<option value="paid" {{ old('status', $invoice->status) === 'paid' ? 'selected' : '' }}>
|
|
Paid
|
|
</option>
|
|
<option value="overdue" {{ old('status', $invoice->status) === 'overdue' ? 'selected' : '' }}>
|
|
Overdue
|
|
</option>
|
|
</select>
|
|
</div>
|
|
|
|
{{-- Notes --}}
|
|
<div class="form-group-compact" style="grid-column: 1 / -1;">
|
|
<label class="form-label-compact">
|
|
<i class="fas fa-sticky-note"></i> Notes
|
|
</label>
|
|
<textarea name="notes"
|
|
rows="3"
|
|
class="form-control-compact"
|
|
placeholder="Add any additional notes...">{{ old('notes', $invoice->notes) }}</textarea>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="text-end mt-3">
|
|
<button type="submit" class="btn-success-compact btn-compact">
|
|
<i class="fas fa-save me-2"></i>Update Invoice
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</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" id="baseAmount">
|
|
₹{{ 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" id="gstAmount">
|
|
₹{{ 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" id="totalInvoiceWithGst">
|
|
₹{{ 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" id="totalInvoiceWithGstCard">
|
|
₹{{ 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">
|
|
<h4 class="mb-0">
|
|
<i class="fas fa-credit-card me-2"></i>Installment Payments
|
|
</h4>
|
|
@if($remaining > 0)
|
|
<button id="toggleInstallmentForm" class="btn-primary-compact btn-compact">
|
|
<i class="fas fa-plus-circle me-2"></i>Add Installment
|
|
</button>
|
|
@endif
|
|
</div>
|
|
|
|
<div class="card-body-compact">
|
|
{{-- Installment Form --}}
|
|
<div id="installmentForm" class="d-none mb-3">
|
|
<div class="glass-card" style="background: rgba(248, 250, 252, 0.8);">
|
|
<div class="card-header-compact" style="background: var(--success-gradient);">
|
|
<h4 class="mb-0">
|
|
<i class="fas fa-plus-circle me-2"></i>Add New Installment
|
|
</h4>
|
|
</div>
|
|
<div class="card-body-compact">
|
|
<form id="installmentSubmitForm">
|
|
@csrf
|
|
|
|
<div class="form-grid-compact">
|
|
<div class="form-group-compact">
|
|
<label class="form-label-compact">
|
|
<i class="fas fa-calendar-day"></i> Installment Date
|
|
</label>
|
|
<input type="date"
|
|
name="installment_date"
|
|
class="form-control-compact"
|
|
required>
|
|
</div>
|
|
|
|
<div class="form-group-compact">
|
|
<label class="form-label-compact">
|
|
<i class="fas fa-credit-card"></i> Payment Method
|
|
</label>
|
|
<select name="payment_method"
|
|
class="form-select-compact"
|
|
required>
|
|
<option value="cash">Cash</option>
|
|
<option value="bank">Bank Transfer</option>
|
|
<option value="upi">UPI</option>
|
|
<option value="cheque">Cheque</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="form-group-compact">
|
|
<label class="form-label-compact">
|
|
<i class="fas fa-hashtag"></i> Reference No
|
|
</label>
|
|
<input type="text"
|
|
name="reference_no"
|
|
class="form-control-compact"
|
|
placeholder="Enter reference number">
|
|
</div>
|
|
|
|
<div class="form-group-compact">
|
|
<label class="form-label-compact">
|
|
<i class="fas fa-money-bill-wave"></i> Amount
|
|
</label>
|
|
<input type="number"
|
|
name="amount"
|
|
id="installmentAmount"
|
|
class="form-control-compact"
|
|
step="0.01"
|
|
min="1"
|
|
max="{{ $remaining }}"
|
|
required
|
|
placeholder="Enter installment amount">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="text-end mt-2">
|
|
<button type="submit"
|
|
class="btn-success-compact btn-compact"
|
|
id="installmentSubmitBtn">
|
|
<i class="fas fa-paper-plane me-2"></i>Submit Installment
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- Installment History --}}
|
|
<h6 class="fw-bold mb-2 text-dark">
|
|
<i class="fas fa-history me-2"></i>Installment History
|
|
</h6>
|
|
|
|
<div id="noInstallmentsMsg"
|
|
class="{{ $invoice->installments->count() ? 'd-none' : '' }} text-center text-muted fw-bold py-4">
|
|
No installments found. Click Add Installment to create one.
|
|
</div>
|
|
|
|
<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">
|
|
@foreach($invoice->installments as $i)
|
|
<tr data-id="{{ $i->id }}">
|
|
<td class="fw-bold text-muted">{{ $loop->iteration }}</td>
|
|
<td>{{ $i->installment_date }}</td>
|
|
<td>
|
|
<span class="badge-compact bg-primary bg-opacity-10 text-primary">
|
|
{{ strtoupper($i->payment_method) }}
|
|
</span>
|
|
</td>
|
|
<td>
|
|
@if($i->reference_no)
|
|
<span class="text-muted">{{ $i->reference_no }}</span>
|
|
@else
|
|
<span class="text-muted">-</span>
|
|
@endif
|
|
</td>
|
|
<td class="fw-bold text-success">
|
|
₹{{ number_format($i->amount, 2) }}
|
|
</td>
|
|
<td>
|
|
<button class="btn-danger-compact btn-compact btn-sm deleteInstallment">
|
|
<i class="fas fa-trash me-1"></i>Delete
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
@endforeach
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
document.addEventListener("DOMContentLoaded", function () {
|
|
const toggleBtn = document.getElementById("toggleInstallmentForm");
|
|
const formBox = document.getElementById("installmentForm");
|
|
|
|
if (toggleBtn && formBox) {
|
|
toggleBtn.addEventListener("click", function (e) {
|
|
e.preventDefault();
|
|
formBox.classList.toggle("d-none");
|
|
});
|
|
}
|
|
|
|
const submitForm = document.getElementById("installmentSubmitForm");
|
|
const submitBtn = document.getElementById("installmentSubmitBtn");
|
|
|
|
const formatINR = (amt) => {
|
|
return Number(amt).toLocaleString("en-IN", {
|
|
minimumFractionDigits: 2,
|
|
maximumFractionDigits: 2
|
|
});
|
|
};
|
|
|
|
if (submitForm && submitBtn) {
|
|
submitForm.addEventListener("submit", function (e) {
|
|
e.preventDefault();
|
|
|
|
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin me-2"></i>Processing...';
|
|
submitBtn.disabled = true;
|
|
|
|
fetch("{{ route('admin.invoice.installment.store', $invoice->id) }}", {
|
|
method: "POST",
|
|
headers: {
|
|
"X-CSRF-TOKEN": submitForm.querySelector('input[name="_token"]').value,
|
|
"Accept": "application/json",
|
|
},
|
|
body: new FormData(submitForm)
|
|
})
|
|
.then(res => res.json())
|
|
.then(data => {
|
|
submitBtn.innerHTML = '<i class="fas fa-paper-plane me-2"></i>Submit Installment';
|
|
submitBtn.disabled = false;
|
|
|
|
if (data.status === "error") {
|
|
alert(data.message);
|
|
return;
|
|
}
|
|
|
|
const table = document.getElementById("installmentTable");
|
|
const index = table.rows.length + 1;
|
|
|
|
document.getElementById("noInstallmentsMsg")?.classList.add("d-none");
|
|
|
|
table.insertAdjacentHTML("beforeend", `
|
|
<tr data-id="${data.installment.id}">
|
|
<td class="fw-bold text-muted">${index}</td>
|
|
<td>${data.installment.installment_date}</td>
|
|
<td>
|
|
<span class="badge-compact bg-primary bg-opacity-10 text-primary">
|
|
${data.installment.payment_method.toUpperCase()}
|
|
</span>
|
|
</td>
|
|
<td>
|
|
${data.installment.reference_no
|
|
? `<span class="text-muted">${data.installment.reference_no}</span>`
|
|
: '<span class="text-muted">-</span>'}
|
|
</td>
|
|
<td class="fw-bold text-success">
|
|
₹${formatINR(data.installment.amount)}
|
|
</td>
|
|
<td>
|
|
<button class="btn-danger-compact btn-compact btn-sm deleteInstallment">
|
|
<i class="fas fa-trash me-1"></i>Delete
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
`);
|
|
|
|
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);
|
|
}
|
|
|
|
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");
|
|
if (remainingCard) remainingCard.textContent = "₹" + formatINR(data.remaining);
|
|
|
|
submitForm.reset();
|
|
|
|
if (data.isCompleted && toggleBtn) {
|
|
toggleBtn.remove();
|
|
formBox.classList.add("d-none");
|
|
}
|
|
|
|
alert(data.message);
|
|
})
|
|
.catch(() => {
|
|
submitBtn.innerHTML = '<i class="fas fa-paper-plane me-2"></i>Submit Installment';
|
|
submitBtn.disabled = false;
|
|
alert("Something went wrong. Please try again.");
|
|
});
|
|
});
|
|
}
|
|
|
|
document.addEventListener("click", function (e) {
|
|
if (!e.target.classList.contains("deleteInstallment") &&
|
|
!e.target.closest(".deleteInstallment")) {
|
|
return;
|
|
}
|
|
e.preventDefault();
|
|
|
|
if (!confirm("Are you sure you want to delete this installment?")) {
|
|
return;
|
|
}
|
|
|
|
const btn = e.target.closest(".deleteInstallment");
|
|
const row = btn.closest("tr");
|
|
const id = row.getAttribute("data-id");
|
|
|
|
fetch("{{ url('admin/installment') }}/" + id, {
|
|
method: "DELETE",
|
|
headers: {
|
|
"X-CSRF-TOKEN": document.querySelector('meta[name="csrf-token"]').getAttribute("content"),
|
|
"Accept": "application/json",
|
|
},
|
|
})
|
|
.then(res => res.json())
|
|
.then(data => {
|
|
if (data.status === "success") {
|
|
row.style.opacity = 0;
|
|
setTimeout(() => row.remove(), 300);
|
|
|
|
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);
|
|
}
|
|
|
|
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");
|
|
if (remainingCard) remainingCard.textContent = "₹" + formatINR(data.remaining);
|
|
|
|
if (data.isZero) {
|
|
document.getElementById("noInstallmentsMsg")?.classList.remove("d-none");
|
|
}
|
|
|
|
alert(data.message);
|
|
} else {
|
|
alert(data.message || "Something went wrong. Please try again.");
|
|
}
|
|
})
|
|
.catch(() => {
|
|
alert("Something went wrong. Please try again.");
|
|
});
|
|
});
|
|
});
|
|
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const invoiceDateInput = document.querySelector('input[name="invoice_date"]');
|
|
const dueDateInput = document.querySelector('input[name="due_date"]');
|
|
|
|
if (invoiceDateInput && dueDateInput) {
|
|
invoiceDateInput.addEventListener('change', function() {
|
|
const selectedDate = new Date(this.value);
|
|
|
|
if (!isNaN(selectedDate.getTime())) {
|
|
// १० दिवस पुढे नेण्यासाठी logic
|
|
selectedDate.setDate(selectedDate.getDate() + 10);
|
|
|
|
// तारीख YYYY-MM-DD format मध्ये करण्यासाठी
|
|
const year = selectedDate.getFullYear();
|
|
const month = String(selectedDate.getMonth() + 1).padStart(2, '0');
|
|
const day = String(selectedDate.getDate()).padStart(2, '0');
|
|
|
|
dueDateInput.value = `${year}-${month}-${day}`;
|
|
}
|
|
});
|
|
}
|
|
});
|
|
</script>
|
|
@endsection
|