update database
This commit is contained in:
919
html/receivables-management.html
Normal file
919
html/receivables-management.html
Normal file
@@ -0,0 +1,919 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="vi">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Quản lý Công nợ - EuroTile Dealer</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<link rel="stylesheet" href="assets/css/style.css">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
<style>
|
||||
.receivables-container {
|
||||
min-height: calc(100vh - 120px);
|
||||
background: #f8f9fa;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.summary-cards {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||
gap: 15px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.summary-card {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border-radius: 16px;
|
||||
padding: 20px;
|
||||
color: white;
|
||||
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.2);
|
||||
}
|
||||
|
||||
.summary-card.warning {
|
||||
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
|
||||
}
|
||||
|
||||
.summary-card.success {
|
||||
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
|
||||
}
|
||||
|
||||
.summary-title {
|
||||
font-size: 0.9rem;
|
||||
opacity: 0.9;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.summary-amount {
|
||||
font-size: 1.8rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.summary-detail {
|
||||
font-size: 0.8rem;
|
||||
opacity: 0.8;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.filter-section {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.08);
|
||||
}
|
||||
|
||||
.filter-row {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 15px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.filter-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.filter-label {
|
||||
font-weight: 600;
|
||||
color: #374151;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.filter-select,
|
||||
.filter-input {
|
||||
padding: 10px 12px;
|
||||
border: 2px solid #e5e7eb;
|
||||
border-radius: 8px;
|
||||
font-size: 0.9rem;
|
||||
transition: border-color 0.3s ease;
|
||||
}
|
||||
|
||||
.filter-select:focus,
|
||||
.filter-input:focus {
|
||||
outline: none;
|
||||
border-color: #667eea;
|
||||
}
|
||||
|
||||
.receivables-list {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.08);
|
||||
}
|
||||
|
||||
.receivable-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
border-bottom: 1px solid #f3f4f6;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.receivable-item:hover {
|
||||
background: #f9fafb;
|
||||
}
|
||||
|
||||
.receivable-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.customer-avatar {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
font-weight: 700;
|
||||
font-size: 1.2rem;
|
||||
margin-right: 15px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.receivable-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.customer-name {
|
||||
font-weight: 700;
|
||||
color: #1f2937;
|
||||
margin-bottom: 5px;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.order-details {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 15px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.order-id {
|
||||
color: #6b7280;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.order-date {
|
||||
color: #9ca3af;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.payment-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.overdue-badge {
|
||||
background: #fee2e2;
|
||||
color: #dc2626;
|
||||
padding: 4px 8px;
|
||||
border-radius: 12px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.due-soon-badge {
|
||||
background: #fef3c7;
|
||||
color: #d97706;
|
||||
padding: 4px 8px;
|
||||
border-radius: 12px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.receivable-amount {
|
||||
text-align: right;
|
||||
margin-left: 15px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.amount-value {
|
||||
font-size: 1.2rem;
|
||||
font-weight: 700;
|
||||
color: #1f2937;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.amount-overdue {
|
||||
color: #dc2626;
|
||||
}
|
||||
|
||||
.amount-due-soon {
|
||||
color: #d97706;
|
||||
}
|
||||
|
||||
.due-date {
|
||||
font-size: 0.8rem;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
margin-left: 15px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.btn-action {
|
||||
padding: 8px 12px;
|
||||
border-radius: 6px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
font-size: 0.8rem;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.btn-remind {
|
||||
background: #eff6ff;
|
||||
color: #1d4ed8;
|
||||
}
|
||||
|
||||
.btn-remind:hover {
|
||||
background: #dbeafe;
|
||||
}
|
||||
|
||||
.btn-collect {
|
||||
background: #f0fdf4;
|
||||
color: #16a34a;
|
||||
}
|
||||
|
||||
.btn-collect:hover {
|
||||
background: #dcfce7;
|
||||
}
|
||||
|
||||
.btn-view {
|
||||
background: #f3f4f6;
|
||||
color: #374151;
|
||||
}
|
||||
|
||||
.btn-view:hover {
|
||||
background: #e5e7eb;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
padding: 60px 20px;
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
.empty-state i {
|
||||
font-size: 3rem;
|
||||
margin-bottom: 20px;
|
||||
color: #d1d5db;
|
||||
}
|
||||
|
||||
.floating-action {
|
||||
position: fixed;
|
||||
bottom: 90px;
|
||||
right: 20px;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
font-size: 1.5rem;
|
||||
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.4);
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.floating-action:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 12px 35px rgba(102, 126, 234, 0.5);
|
||||
}
|
||||
|
||||
.modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0,0,0,0.5);
|
||||
z-index: 1000;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.modal.show {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background: white;
|
||||
border-radius: 16px;
|
||||
width: 100%;
|
||||
max-width: 500px;
|
||||
max-height: 80vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
padding: 20px 20px 0;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
font-size: 1.2rem;
|
||||
font-weight: 700;
|
||||
color: #1f2937;
|
||||
}
|
||||
|
||||
.modal-close {
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 1.5rem;
|
||||
color: #6b7280;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
display: block;
|
||||
font-weight: 600;
|
||||
color: #374151;
|
||||
margin-bottom: 8px;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.form-input,
|
||||
.form-select,
|
||||
.form-textarea {
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
border: 2px solid #e5e7eb;
|
||||
border-radius: 8px;
|
||||
font-size: 0.9rem;
|
||||
transition: border-color 0.3s ease;
|
||||
}
|
||||
|
||||
.form-input:focus,
|
||||
.form-select:focus,
|
||||
.form-textarea:focus {
|
||||
outline: none;
|
||||
border-color: #667eea;
|
||||
}
|
||||
|
||||
.form-textarea {
|
||||
height: 100px;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
.modal-actions {
|
||||
padding: 0 20px 20px;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.btn-cancel {
|
||||
padding: 12px 20px;
|
||||
background: #f3f4f6;
|
||||
color: #374151;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.btn-submit {
|
||||
padding: 12px 20px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.receivables-container {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.summary-cards {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.filter-row {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.receivable-item {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.order-details {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.btn-action {
|
||||
font-size: 0.75rem;
|
||||
padding: 6px 8px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="page-wrapper">
|
||||
<!-- Header -->
|
||||
<div class="header">
|
||||
<a href="index.html" class="back-button">
|
||||
<i class="fas fa-arrow-left"></i>
|
||||
</a>
|
||||
<h1 class="header-title">Quản lý Công nợ</h1>
|
||||
<button class="icon-button" onclick="exportReceivables()">
|
||||
<i class="fas fa-download"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="receivables-container">
|
||||
<!-- Summary Cards -->
|
||||
<div class="summary-cards">
|
||||
<div class="summary-card">
|
||||
<div class="summary-title">Tổng công nợ</div>
|
||||
<div class="summary-amount">892.500.000đ</div>
|
||||
<div class="summary-detail">
|
||||
<i class="fas fa-users"></i>
|
||||
<span>45 khách hàng</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="summary-card warning">
|
||||
<div class="summary-title">Quá hạn thanh toán</div>
|
||||
<div class="summary-amount">156.000.000đ</div>
|
||||
<div class="summary-detail">
|
||||
<i class="fas fa-exclamation-triangle"></i>
|
||||
<span>12 đơn hàng</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="summary-card success">
|
||||
<div class="summary-title">Sắp đến hạn</div>
|
||||
<div class="summary-amount">234.750.000đ</div>
|
||||
<div class="summary-detail">
|
||||
<i class="fas fa-clock"></i>
|
||||
<span>18 đơn hàng (7 ngày tới)</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Filter Section -->
|
||||
<div class="filter-section">
|
||||
<div class="filter-row">
|
||||
<div class="filter-group">
|
||||
<label class="filter-label">Trạng thái</label>
|
||||
<select class="filter-select" id="statusFilter" onchange="filterReceivables()">
|
||||
<option value="">Tất cả</option>
|
||||
<option value="overdue">Quá hạn</option>
|
||||
<option value="due-soon">Sắp đến hạn</option>
|
||||
<option value="normal">Bình thường</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="filter-group">
|
||||
<label class="filter-label">Khoảng tiền</label>
|
||||
<select class="filter-select" id="amountFilter" onchange="filterReceivables()">
|
||||
<option value="">Tất cả</option>
|
||||
<option value="small">Dưới 10 triệu</option>
|
||||
<option value="medium">10 - 50 triệu</option>
|
||||
<option value="large">Trên 50 triệu</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="filter-group">
|
||||
<label class="filter-label">Tìm kiếm khách hàng</label>
|
||||
<input type="text" class="filter-input" id="searchInput" placeholder="Tên hoặc mã đơn hàng..." onkeyup="filterReceivables()">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Receivables List -->
|
||||
<div class="receivables-list" id="receivablesList">
|
||||
<!-- Receivable Items will be populated by JavaScript -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bottom Navigation -->
|
||||
<div class="bottom-nav">
|
||||
<a href="index.html" class="nav-item">
|
||||
<i class="fas fa-home"></i>
|
||||
<span>Trang chủ</span>
|
||||
</a>
|
||||
<a href="loyalty.html" class="nav-item">
|
||||
<i class="fas fa-star"></i>
|
||||
<span>Hội viên</span>
|
||||
</a>
|
||||
<a href="promotions.html" class="nav-item">
|
||||
<i class="fas fa-tags"></i>
|
||||
<span>Khuyến mãi</span>
|
||||
</a>
|
||||
<a href="notifications.html" class="nav-item">
|
||||
<i class="fas fa-bell"></i>
|
||||
<span>Thông báo</span>
|
||||
</a>
|
||||
<a href="account.html" class="nav-item active">
|
||||
<i class="fas fa-user"></i>
|
||||
<span>Cài đặt</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Floating Action Button -->
|
||||
<div class="floating-action" onclick="openAddReceivableModal()">
|
||||
<i class="fas fa-plus"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Reminder Modal -->
|
||||
<div class="modal" id="reminderModal">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">Gửi nhắc nợ</h3>
|
||||
<button class="modal-close" onclick="closeModal('reminderModal')">
|
||||
<i class="fas fa-times"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Khách hàng</label>
|
||||
<input type="text" class="form-input" id="reminderCustomer" readonly>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Số tiền nợ</label>
|
||||
<input type="text" class="form-input" id="reminderAmount" readonly>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Phương thức nhắc nhở</label>
|
||||
<select class="form-select" id="reminderMethod">
|
||||
<option value="sms">Tin nhắn SMS</option>
|
||||
<option value="call">Gọi điện thoại</option>
|
||||
<option value="email">Email</option>
|
||||
<option value="visit">Đến thăm trực tiếp</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Nội dung nhắc nhở</label>
|
||||
<textarea class="form-textarea" id="reminderMessage" placeholder="Nhập nội dung nhắc nở...">Kính chào anh/chị,
|
||||
|
||||
EuroTile xin nhắc nhở về việc thanh toán công nợ đơn hàng. Vui lòng liên hệ với chúng tôi để sắp xếp thanh toán.
|
||||
|
||||
Xin cảm ơn!</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-actions">
|
||||
<button class="btn-cancel" onclick="closeModal('reminderModal')">Hủy</button>
|
||||
<button class="btn-submit" onclick="sendReminder()">Gửi nhắc nhở</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Collection Modal -->
|
||||
<div class="modal" id="collectionModal">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">Thu tiền</h3>
|
||||
<button class="modal-close" onclick="closeModal('collectionModal')">
|
||||
<i class="fas fa-times"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Khách hàng</label>
|
||||
<input type="text" class="form-input" id="collectionCustomer" readonly>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Tổng số tiền nợ</label>
|
||||
<input type="text" class="form-input" id="collectionTotalAmount" readonly>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Số tiền thu</label>
|
||||
<input type="number" class="form-input" id="collectionAmount" placeholder="Nhập số tiền thu được...">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Phương thức thanh toán</label>
|
||||
<select class="form-select" id="paymentMethod">
|
||||
<option value="cash">Tiền mặt</option>
|
||||
<option value="transfer">Chuyển khoản</option>
|
||||
<option value="check">Séc</option>
|
||||
<option value="card">Thẻ tín dụng</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Ghi chú</label>
|
||||
<textarea class="form-textarea" id="collectionNote" placeholder="Ghi chú về việc thu tiền..."></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-actions">
|
||||
<button class="btn-cancel" onclick="closeModal('collectionModal')">Hủy</button>
|
||||
<button class="btn-submit" onclick="recordPayment()">Ghi nhận thanh toán</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Sample receivables data
|
||||
const receivablesData = [
|
||||
{
|
||||
id: 'DH001234',
|
||||
customer: 'Công ty TNHH Xây dựng Minh An',
|
||||
customerCode: 'KH001',
|
||||
phone: '0912345678',
|
||||
orderDate: '2023-10-15',
|
||||
dueDate: '2023-11-15',
|
||||
amount: 85000000,
|
||||
status: 'overdue',
|
||||
daysOverdue: 15
|
||||
},
|
||||
{
|
||||
id: 'DH001235',
|
||||
customer: 'Anh Nguyễn Văn Hùng',
|
||||
customerCode: 'KH002',
|
||||
phone: '0987654321',
|
||||
orderDate: '2023-11-20',
|
||||
dueDate: '2023-12-20',
|
||||
amount: 25750000,
|
||||
status: 'due-soon',
|
||||
daysOverdue: 0
|
||||
},
|
||||
{
|
||||
id: 'DH001236',
|
||||
customer: 'Chị Trần Thị Mai',
|
||||
customerCode: 'KH003',
|
||||
phone: '0923456789',
|
||||
orderDate: '2023-11-25',
|
||||
dueDate: '2023-12-25',
|
||||
amount: 12500000,
|
||||
status: 'normal',
|
||||
daysOverdue: 0
|
||||
},
|
||||
{
|
||||
id: 'DH001237',
|
||||
customer: 'Công ty CP Đầu tư Bất động sản ABC',
|
||||
customerCode: 'KH004',
|
||||
phone: '0945678912',
|
||||
orderDate: '2023-10-10',
|
||||
dueDate: '2023-11-10',
|
||||
amount: 156000000,
|
||||
status: 'overdue',
|
||||
daysOverdue: 20
|
||||
},
|
||||
{
|
||||
id: 'DH001238',
|
||||
customer: 'Anh Lê Minh Tuấn',
|
||||
customerCode: 'KH005',
|
||||
phone: '0934567890',
|
||||
orderDate: '2023-11-28',
|
||||
dueDate: '2023-12-28',
|
||||
amount: 18900000,
|
||||
status: 'due-soon',
|
||||
daysOverdue: 0
|
||||
}
|
||||
];
|
||||
|
||||
let filteredReceivables = [...receivablesData];
|
||||
|
||||
// Initialize page
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
renderReceivables();
|
||||
});
|
||||
|
||||
function renderReceivables() {
|
||||
const container = document.getElementById('receivablesList');
|
||||
|
||||
if (filteredReceivables.length === 0) {
|
||||
container.innerHTML = `
|
||||
<div class="empty-state">
|
||||
<i class="fas fa-receipt"></i>
|
||||
<h3>Không có công nợ nào</h3>
|
||||
<p>Không tìm thấy công nợ phù hợp với bộ lọc hiện tại</p>
|
||||
</div>
|
||||
`;
|
||||
return;
|
||||
}
|
||||
|
||||
container.innerHTML = filteredReceivables.map(receivable => `
|
||||
<div class="receivable-item" onclick="viewReceivableDetail('${receivable.id}')">
|
||||
<div class="customer-avatar">
|
||||
${receivable.customer.charAt(0).toUpperCase()}
|
||||
</div>
|
||||
|
||||
<div class="receivable-info">
|
||||
<div class="customer-name">${receivable.customer}</div>
|
||||
<div class="order-details">
|
||||
<span class="order-id">Đơn hàng: ${receivable.id}</span>
|
||||
<span class="order-date">Ngày đặt: ${formatDate(receivable.orderDate)}</span>
|
||||
</div>
|
||||
<div class="payment-info">
|
||||
${getStatusBadge(receivable.status, receivable.daysOverdue)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="receivable-amount">
|
||||
<div class="amount-value ${getAmountClass(receivable.status)}">
|
||||
${formatCurrency(receivable.amount)}
|
||||
</div>
|
||||
<div class="due-date">Hạn: ${formatDate(receivable.dueDate)}</div>
|
||||
</div>
|
||||
|
||||
<div class="action-buttons">
|
||||
<button class="btn-action btn-remind" onclick="event.stopPropagation(); openReminderModal('${receivable.id}')">
|
||||
<i class="fas fa-bell"></i>
|
||||
</button>
|
||||
<button class="btn-action btn-collect" onclick="event.stopPropagation(); openCollectionModal('${receivable.id}')">
|
||||
<i class="fas fa-money-bill-wave"></i>
|
||||
</button>
|
||||
<button class="btn-action btn-view" onclick="event.stopPropagation(); viewReceivableDetail('${receivable.id}')">
|
||||
<i class="fas fa-eye"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
}
|
||||
|
||||
function getStatusBadge(status, daysOverdue) {
|
||||
switch(status) {
|
||||
case 'overdue':
|
||||
return `<span class="overdue-badge">Quá hạn ${daysOverdue} ngày</span>`;
|
||||
case 'due-soon':
|
||||
return `<span class="due-soon-badge">Sắp đến hạn</span>`;
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
function getAmountClass(status) {
|
||||
switch(status) {
|
||||
case 'overdue':
|
||||
return 'amount-overdue';
|
||||
case 'due-soon':
|
||||
return 'amount-due-soon';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
function filterReceivables() {
|
||||
const statusFilter = document.getElementById('statusFilter').value;
|
||||
const amountFilter = document.getElementById('amountFilter').value;
|
||||
const searchTerm = document.getElementById('searchInput').value.toLowerCase();
|
||||
|
||||
filteredReceivables = receivablesData.filter(receivable => {
|
||||
// Status filter
|
||||
if (statusFilter && receivable.status !== statusFilter) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Amount filter
|
||||
if (amountFilter) {
|
||||
const amount = receivable.amount;
|
||||
if (amountFilter === 'small' && amount >= 10000000) return false;
|
||||
if (amountFilter === 'medium' && (amount < 10000000 || amount > 50000000)) return false;
|
||||
if (amountFilter === 'large' && amount <= 50000000) return false;
|
||||
}
|
||||
|
||||
// Search filter
|
||||
if (searchTerm) {
|
||||
const searchableText = `${receivable.customer} ${receivable.id}`.toLowerCase();
|
||||
if (!searchableText.includes(searchTerm)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
renderReceivables();
|
||||
}
|
||||
|
||||
function openReminderModal(receivableId) {
|
||||
const receivable = receivablesData.find(r => r.id === receivableId);
|
||||
if (!receivable) return;
|
||||
|
||||
document.getElementById('reminderCustomer').value = receivable.customer;
|
||||
document.getElementById('reminderAmount').value = formatCurrency(receivable.amount);
|
||||
document.getElementById('reminderModal').classList.add('show');
|
||||
}
|
||||
|
||||
function openCollectionModal(receivableId) {
|
||||
const receivable = receivablesData.find(r => r.id === receivableId);
|
||||
if (!receivable) return;
|
||||
|
||||
document.getElementById('collectionCustomer').value = receivable.customer;
|
||||
document.getElementById('collectionTotalAmount').value = formatCurrency(receivable.amount);
|
||||
document.getElementById('collectionAmount').value = '';
|
||||
document.getElementById('collectionModal').classList.add('show');
|
||||
}
|
||||
|
||||
function closeModal(modalId) {
|
||||
document.getElementById(modalId).classList.remove('show');
|
||||
}
|
||||
|
||||
function sendReminder() {
|
||||
const method = document.getElementById('reminderMethod').value;
|
||||
const message = document.getElementById('reminderMessage').value;
|
||||
|
||||
if (!message.trim()) {
|
||||
alert('Vui lòng nhập nội dung nhắc nhở');
|
||||
return;
|
||||
}
|
||||
|
||||
// Simulate sending reminder
|
||||
alert('Đã gửi nhắc nhở thành công!');
|
||||
closeModal('reminderModal');
|
||||
}
|
||||
|
||||
function recordPayment() {
|
||||
const amount = document.getElementById('collectionAmount').value;
|
||||
const method = document.getElementById('paymentMethod').value;
|
||||
|
||||
if (!amount || amount <= 0) {
|
||||
alert('Vui lòng nhập số tiền hợp lệ');
|
||||
return;
|
||||
}
|
||||
|
||||
// Simulate recording payment
|
||||
alert('Đã ghi nhận thanh toán thành công!');
|
||||
closeModal('collectionModal');
|
||||
|
||||
// Refresh the list (in a real app, this would update the backend)
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function viewReceivableDetail(receivableId) {
|
||||
// Navigate to receivable detail page
|
||||
alert(`Xem chi tiết công nợ ${receivableId}`);
|
||||
}
|
||||
|
||||
function openAddReceivableModal() {
|
||||
alert('Chức năng thêm công nợ mới sẽ được phát triển');
|
||||
}
|
||||
|
||||
function exportReceivables() {
|
||||
// Simulate export functionality
|
||||
alert('Đang xuất báo cáo công nợ...');
|
||||
}
|
||||
|
||||
// Utility functions
|
||||
function formatCurrency(amount) {
|
||||
return new Intl.NumberFormat('vi-VN', {
|
||||
style: 'currency',
|
||||
currency: 'VND',
|
||||
minimumFractionDigits: 0
|
||||
}).format(amount);
|
||||
}
|
||||
|
||||
function formatDate(dateString) {
|
||||
const date = new Date(dateString);
|
||||
return date.toLocaleDateString('vi-VN');
|
||||
}
|
||||
|
||||
// Close modals when clicking outside
|
||||
window.onclick = function(event) {
|
||||
const modals = document.querySelectorAll('.modal');
|
||||
modals.forEach(modal => {
|
||||
if (event.target === modal) {
|
||||
modal.classList.remove('show');
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user