update point
This commit is contained in:
@@ -8,78 +8,6 @@
|
||||
<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">
|
||||
</head>
|
||||
<style>
|
||||
.modal-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0,0,0,0.5);
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
width: 100%;
|
||||
max-width: 500px;
|
||||
animation: slideUp 0.3s ease;
|
||||
}
|
||||
|
||||
@keyframes slideUp {
|
||||
from { transform: translateY(20px); opacity: 0; }
|
||||
to { transform: translateY(0); opacity: 1; }
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
padding: 20px;
|
||||
border-bottom: 1px solid #e5e7eb;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
padding: 20px;
|
||||
border-top: 1px solid #e5e7eb;
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.modal-close {
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 20px;
|
||||
color: #6b7280;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.document-card {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.download-btn {
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-item.active {
|
||||
background: var(--primary-blue);
|
||||
color: var(--white);
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div class="page-wrapper">
|
||||
<!-- Header -->
|
||||
@@ -88,15 +16,12 @@
|
||||
<i class="fas fa-arrow-left"></i>
|
||||
</a>
|
||||
<h1 class="header-title">Lịch sử điểm</h1>
|
||||
<!--<div style="width: 32px;"></div>-->
|
||||
<button class="back-button" onclick="openInfoModal()">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
</button>
|
||||
<div style="width: 32px;"></div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<!-- Filter Section -->
|
||||
<!--<div class="card mb-3">
|
||||
<div class="card mb-3">
|
||||
<div class="d-flex justify-between align-center">
|
||||
<h3 class="card-title">Bộ lọc</h3>
|
||||
<i class="fas fa-filter" style="color: var(--primary-blue);"></i>
|
||||
@@ -104,185 +29,222 @@
|
||||
<p class="text-muted" style="font-size: 12px; margin-top: 8px;">
|
||||
Thời gian hiệu lực: 01/01/2023 - 31/12/2023
|
||||
</p>
|
||||
</div>-->
|
||||
</div>
|
||||
|
||||
<!-- Points History List -->
|
||||
<div class="points-history-list">
|
||||
<!-- Transaction Item 1 -->
|
||||
<div class="card mb-3">
|
||||
<div class="d-flex justify-between align-start mb-2">
|
||||
<div style="flex: 1;">
|
||||
<h4 style="color: var(--primary-blue); font-weight: 500; margin-bottom: 4px;">
|
||||
Giao dịch mua hàng 00083
|
||||
</h4>
|
||||
<p class="text-muted" style="font-size: 12px;">
|
||||
Thời gian: 28/09/2023 17:23:18
|
||||
</p>
|
||||
<p class="text-muted" style="font-size: 12px;">
|
||||
Giao dịch: 100.000.000 VND
|
||||
</p>
|
||||
</div>
|
||||
<button class="btn-complaint" onclick="openComplaint(this)">
|
||||
Khiếu nại
|
||||
</button>
|
||||
<!-- Transaction Card 1 -->
|
||||
<div class="transaction-card">
|
||||
<div class="card-header">
|
||||
<span class="transaction-code">GD-00083</span>
|
||||
<span class="transaction-date">28/09/2023</span>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-end align-center" style="margin-top: 12px;">
|
||||
<div style="text-align: right;">
|
||||
<div style="color: var(--success-color); font-weight: 500;">+3</div>
|
||||
<div style="color: var(--primary-blue); font-size: 12px;">Điểm mới: 604</div>
|
||||
<div class="card-content">
|
||||
<div class="transaction-desc">
|
||||
<div style="font-weight: 600; color: #333; margin-bottom: 4px;">Giao dịch mua hàng</div>
|
||||
<div style="font-size: 13px; color: #999;">Mã tham chiếu: #HD-2023-00083</div>
|
||||
</div>
|
||||
<div class="transaction-points positive">
|
||||
+3 điểm
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<span class="balance-after">Số dư sau: <strong>604 điểm</strong></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Transaction Item 2 -->
|
||||
<div class="card mb-3">
|
||||
<div class="d-flex justify-between align-start mb-2">
|
||||
<div style="flex: 1;">
|
||||
<h4 style="color: var(--primary-blue); font-weight: 500; margin-bottom: 4px;">
|
||||
Giao dịch mua hàng 00081
|
||||
</h4>
|
||||
<p class="text-muted" style="font-size: 12px;">
|
||||
Thời gian: 27/09/2023 17:23:18
|
||||
</p>
|
||||
<p class="text-muted" style="font-size: 12px;">
|
||||
Giao dịch: 200.000.000 VND
|
||||
</p>
|
||||
</div>
|
||||
<button class="btn-complaint" onclick="openComplaint(this)">
|
||||
Khiếu nại
|
||||
</button>
|
||||
<!-- Transaction Card 2 -->
|
||||
<div class="transaction-card">
|
||||
<div class="card-header">
|
||||
<span class="transaction-code">GD-00081</span>
|
||||
<span class="transaction-date">27/09/2023</span>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-end align-center" style="margin-top: 12px;">
|
||||
<div style="text-align: right;">
|
||||
<div style="color: var(--text-dark); font-weight: 500;">0</div>
|
||||
<div style="color: var(--primary-blue); font-size: 12px;">Điểm mới: 604</div>
|
||||
<div class="card-content">
|
||||
<div class="transaction-desc">
|
||||
<div style="font-weight: 600; color: #333; margin-bottom: 4px;">Giao dịch mua hàng</div>
|
||||
<div style="font-size: 13px; color: #999;">Mã tham chiếu: #HD-2023-00081</div>
|
||||
</div>
|
||||
<div class="transaction-points neutral">
|
||||
0 điểm
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<span class="balance-after">Số dư sau: <strong>601 điểm</strong></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Transaction Item 3 -->
|
||||
<div class="card mb-3">
|
||||
<div class="d-flex justify-between align-start mb-2">
|
||||
<div style="flex: 1;">
|
||||
<h4 style="color: var(--primary-blue); font-weight: 500; margin-bottom: 4px;">
|
||||
Điểm thưởng hết hạn
|
||||
</h4>
|
||||
<p class="text-muted" style="font-size: 12px;">
|
||||
Thời gian: 20/09/2023 17:23:18
|
||||
</p>
|
||||
</div>
|
||||
<button class="btn-complaint" onclick="openComplaint(this)">
|
||||
Khiếu nại
|
||||
</button>
|
||||
<!-- Transaction Card 3 -->
|
||||
<div class="transaction-card">
|
||||
<div class="card-header">
|
||||
<span class="transaction-code">EXP-2023-001</span>
|
||||
<span class="transaction-date">20/09/2023</span>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-end align-center" style="margin-top: 12px;">
|
||||
<div style="text-align: right;">
|
||||
<div style="color: var(--danger-color); font-weight: 500;">-5</div>
|
||||
<div style="color: var(--primary-blue); font-size: 12px;">Điểm mới: 604</div>
|
||||
<div class="card-content">
|
||||
<div class="transaction-desc">
|
||||
<div style="font-weight: 600; color: #333; margin-bottom: 4px;">Điểm thưởng hết hạn</div>
|
||||
<div style="font-size: 13px; color: #999;">Hết hạn sử dụng</div>
|
||||
</div>
|
||||
<div class="transaction-points negative">
|
||||
-5 điểm
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<span class="balance-after">Số dư sau: <strong>601 điểm</strong></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Transaction Item 4 -->
|
||||
<div class="card mb-3">
|
||||
<div class="d-flex justify-between align-start mb-2">
|
||||
<div style="flex: 1;">
|
||||
<h4 style="color: var(--primary-blue); font-weight: 500; margin-bottom: 4px;">
|
||||
Đổi Voucher HSG
|
||||
</h4>
|
||||
<p class="text-muted" style="font-size: 12px;">
|
||||
Thời gian: 19/09/2023 17:23:18
|
||||
</p>
|
||||
</div>
|
||||
<button class="btn-complaint" onclick="openComplaint(this)">
|
||||
Khiếu nại
|
||||
</button>
|
||||
<!-- Transaction Card 4 -->
|
||||
<div class="transaction-card">
|
||||
<div class="card-header">
|
||||
<span class="transaction-code">RDM-2023-042</span>
|
||||
<span class="transaction-date">19/09/2023</span>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-end align-center" style="margin-top: 12px;">
|
||||
<div style="text-align: right;">
|
||||
<div style="color: var(--danger-color); font-weight: 500;">-500</div>
|
||||
<div style="color: var(--primary-blue); font-size: 12px;">Điểm mới: 604</div>
|
||||
<div class="card-content">
|
||||
<div class="transaction-desc">
|
||||
<div style="font-weight: 600; color: #333; margin-bottom: 4px;">Đổi Voucher giảm giá</div>
|
||||
<div style="font-size: 13px; color: #999;">Voucher 5.000.000đ - HSG</div>
|
||||
</div>
|
||||
<div class="transaction-points negative">
|
||||
-500 điểm
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<span class="balance-after">Số dư sau: <strong>606 điểm</strong></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Transaction Item 5 -->
|
||||
<div class="card mb-3">
|
||||
<div class="d-flex justify-between align-start mb-2">
|
||||
<div style="flex: 1;">
|
||||
<h4 style="color: var(--primary-blue); font-weight: 500; margin-bottom: 4px;">
|
||||
Giới thiệu người dùng
|
||||
</h4>
|
||||
<p class="text-muted" style="font-size: 12px;">
|
||||
Thời gian: 10/09/2023 17:23:18
|
||||
</p>
|
||||
</div>
|
||||
<button class="btn-complaint" onclick="openComplaint(this)">
|
||||
Khiếu nại
|
||||
</button>
|
||||
<!-- Transaction Card 5 -->
|
||||
<div class="transaction-card">
|
||||
<div class="card-header">
|
||||
<span class="transaction-code">REF-2023-128</span>
|
||||
<span class="transaction-date">10/09/2023</span>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-end align-center" style="margin-top: 12px;">
|
||||
<div style="text-align: right;">
|
||||
<div style="color: var(--success-color); font-weight: 500;">+5</div>
|
||||
<div style="color: var(--primary-blue); font-size: 12px;">Điểm mới: 604</div>
|
||||
<div class="card-content">
|
||||
<div class="transaction-desc">
|
||||
<div style="font-weight: 600; color: #333; margin-bottom: 4px;">Giới thiệu thành công</div>
|
||||
<div style="font-size: 13px; color: #999;">Giới thiệu: Nguyễn Văn A</div>
|
||||
</div>
|
||||
<div class="transaction-points positive">
|
||||
+5 điểm
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<span class="balance-after">Số dư sau: <strong>1.106 điểm</strong></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Transaction Item 6 -->
|
||||
<div class="card mb-3">
|
||||
<div class="d-flex justify-between align-start mb-2">
|
||||
<div style="flex: 1;">
|
||||
<h4 style="color: var(--primary-blue); font-weight: 500; margin-bottom: 4px;">
|
||||
Đổi quà
|
||||
</h4>
|
||||
<p class="text-muted" style="font-size: 12px;">
|
||||
Thời gian: 19/09/2023 17:23:18
|
||||
</p>
|
||||
</div>
|
||||
<button class="btn-complaint" onclick="openComplaint(this)">
|
||||
Khiếu nại
|
||||
</button>
|
||||
<!-- Transaction Card 6 -->
|
||||
<div class="transaction-card">
|
||||
<div class="card-header">
|
||||
<span class="transaction-code">RDM-2023-038</span>
|
||||
<span class="transaction-date">05/09/2023</span>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-end align-center" style="margin-top: 12px;">
|
||||
<div style="text-align: right;">
|
||||
<div style="color: var(--danger-color); font-weight: 500;">-200</div>
|
||||
<div style="color: var(--primary-blue); font-size: 12px;">Điểm mới: 604</div>
|
||||
<div class="card-content">
|
||||
<div class="transaction-desc">
|
||||
<div style="font-weight: 600; color: #333; margin-bottom: 4px;">Đổi quà tặng</div>
|
||||
<div style="font-size: 13px; color: #999;">Tai nghe Bluetooth Sony WH-1000XM4</div>
|
||||
</div>
|
||||
<div class="transaction-points negative">
|
||||
-200 điểm
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Info Modal -->
|
||||
<div id="infoModal" class="modal-overlay" style="display: none;">
|
||||
<div class="modal-content info-modal">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title" style="font-weight: bold;">Hướng dẫn sử dụng</h3>
|
||||
<button class="modal-close" onclick="closeInfoModal()">
|
||||
<i class="fas fa-times"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Đây là nội dung hướng dẫn sử dụng cho tính năng Lịch sử điểm:</p>
|
||||
<ul class="list-disc ml-6 mt-3">
|
||||
<li>Đây là sao kê chi tiết tất cả các giao dịch cộng/trừ điểm của bạn.</li>
|
||||
<li>Bạn có thể kiểm tra điểm được cộng từ đơn hàng, từ việc đăng ký công trình, hoặc điểm bị trừ khi đổi quà.</li>
|
||||
<li>Nếu phát hiện giao dịch bị sai sót, hãy bấm nút "Khiếu nại" trên dòng giao dịch đó để gửi yêu cầu hỗ trợ.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-primary" onclick="closeInfoModal()">Đóng</button>
|
||||
<div class="card-footer">
|
||||
<span class="balance-after">Số dư sau: <strong>1.101 điểm</strong></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
/* Modern Transaction Card Styles */
|
||||
.transaction-card {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||||
margin-bottom: 12px;
|
||||
overflow: hidden;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.transaction-card:hover {
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.transaction-card .card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 12px 16px;
|
||||
background: #f9fafb;
|
||||
border-bottom: 1px solid #e5e7eb;
|
||||
}
|
||||
|
||||
.transaction-code {
|
||||
font-weight: 700;
|
||||
font-size: 14px;
|
||||
color: #005B9A;
|
||||
}
|
||||
|
||||
.transaction-date {
|
||||
font-size: 12px;
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
.transaction-card .card-content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.transaction-desc {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.transaction-points {
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
text-align: right;
|
||||
margin-left: 16px;
|
||||
}
|
||||
|
||||
.transaction-points.positive {
|
||||
color: #059669;
|
||||
}
|
||||
|
||||
.transaction-points.negative {
|
||||
color: #dc2626;
|
||||
}
|
||||
|
||||
.transaction-points.neutral {
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.transaction-card .card-footer {
|
||||
padding: 10px 16px;
|
||||
background: #fafafa;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.balance-after {
|
||||
font-size: 13px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.balance-after strong {
|
||||
color: #005B9A;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.transaction-points {
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
function openComplaint(buttonElement) {
|
||||
// Get transaction info from the card
|
||||
@@ -302,21 +264,6 @@
|
||||
|
||||
window.location.href = `point-complaint.html?${params.toString()}`;
|
||||
}
|
||||
|
||||
function openInfoModal() {
|
||||
document.getElementById('infoModal').style.display = 'flex';
|
||||
}
|
||||
|
||||
function closeInfoModal() {
|
||||
document.getElementById('infoModal').style.display = 'none';
|
||||
}
|
||||
|
||||
// Close modal when clicking outside
|
||||
document.addEventListener('click', function(e) {
|
||||
if (e.target.classList.contains('modal-overlay')) {
|
||||
e.target.style.display = 'none';
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -319,7 +319,124 @@
|
||||
color: #0369a1;
|
||||
}
|
||||
|
||||
.product-row {
|
||||
background: #f8f9fa;
|
||||
border: 2px solid var(--border-color);
|
||||
border-radius: 12px;
|
||||
padding: 16px;
|
||||
margin-bottom: 12px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.product-row-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 1px dashed #ddd;
|
||||
}
|
||||
|
||||
.product-row-title {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
.btn-remove-product {
|
||||
background: #fee2e2;
|
||||
color: #dc2626;
|
||||
border: none;
|
||||
padding: 6px 12px;
|
||||
border-radius: 6px;
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.btn-remove-product:hover {
|
||||
background: #fecaca;
|
||||
}
|
||||
|
||||
.product-input-group {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 12px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.product-input-full {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
.product-label {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: var(--text-primary);
|
||||
margin-bottom: 6px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.product-label.required::after {
|
||||
content: " *";
|
||||
color: var(--danger-color);
|
||||
}
|
||||
|
||||
.product-subtotal {
|
||||
background: #eff6ff;
|
||||
border: 2px dashed #005B9A;
|
||||
border-radius: 8px;
|
||||
padding: 12px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.product-subtotal-label {
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.product-subtotal-value {
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
color: #005B9A;
|
||||
}
|
||||
|
||||
.btn-add-product {
|
||||
width: 100%;
|
||||
background: white;
|
||||
border: 2px dashed var(--primary-color);
|
||||
color: var(--primary-color);
|
||||
padding: 14px;
|
||||
border-radius: 12px;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.btn-add-product:hover {
|
||||
background: #eff6ff;
|
||||
border-color: var(--primary-dark);
|
||||
}
|
||||
|
||||
.summary-card {
|
||||
background: linear-gradient(135deg, #eff6ff, #dbeafe);
|
||||
border: 2px solid #005B9A;
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.product-input-group {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.content {
|
||||
padding: 0.75rem;
|
||||
}
|
||||
@@ -403,44 +520,9 @@
|
||||
placeholder="Nhập số hóa đơn (nếu có)"
|
||||
onchange="validateForm()">
|
||||
</div>
|
||||
|
||||
<!-- Total Amount -->
|
||||
<div class="form-group">
|
||||
<label class="form-label required">Tổng giá trị đơn hàng (VNĐ)</label>
|
||||
<input type="number"
|
||||
class="form-input"
|
||||
id="totalAmount"
|
||||
placeholder="0"
|
||||
min="0"
|
||||
step="1000"
|
||||
required
|
||||
oninput="calculatePoints(); validateForm()">
|
||||
</div>
|
||||
|
||||
<!-- Points Estimate -->
|
||||
<!--<div class="points-estimate" id="pointsEstimate">
|
||||
<div class="estimate-title">Điểm dự kiến nhận được</div>
|
||||
<div class="estimate-text" id="estimateText">0 điểm</div>
|
||||
</div>-->
|
||||
|
||||
<!-- Products Purchased -->
|
||||
<!--<div class="form-group">
|
||||
<label class="form-label">Sản phẩm đã mua</label>
|
||||
<textarea class="form-input form-textarea"
|
||||
id="products"
|
||||
placeholder="Mô tả các sản phẩm đã mua (tùy chọn)"
|
||||
rows="3"></textarea>
|
||||
</div>-->
|
||||
|
||||
<!-- Points Estimate -->
|
||||
<div class="points-estimate" id="pointsEstimate">
|
||||
<div class="estimate-title">Điểm dự kiến nhận được</div>
|
||||
<div class="estimate-text" id="estimateText">0 điểm</div>
|
||||
</div>
|
||||
|
||||
<!-- Company Information -->
|
||||
<div class="form-group">
|
||||
<label class="form-label">Tên công ty</label>
|
||||
<label class="form-label">Tên đơn vị mua hàng</label>
|
||||
<input type="text"
|
||||
class="form-input"
|
||||
id="companyName"
|
||||
@@ -454,26 +536,41 @@
|
||||
id="taxCode"
|
||||
placeholder="Nhập mã số thuế (nếu có)">
|
||||
</div>
|
||||
|
||||
<!-- Dynamic Product List -->
|
||||
<div class="form-group">
|
||||
<label class="form-label">Số lượng (m²) đã mua</label>
|
||||
<input type="number"
|
||||
class="form-input"
|
||||
id="squareMeters"
|
||||
placeholder="0"
|
||||
min="0"
|
||||
step="0.01">
|
||||
<label class="form-label required">Danh sách sản phẩm</label>
|
||||
<div id="productsList">
|
||||
<!-- Product rows will be added here dynamically -->
|
||||
</div>
|
||||
<button type="button" onclick="addProductRow()" class="btn-add-product">
|
||||
<i class="fas fa-plus-circle"></i>
|
||||
Thêm sản phẩm
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Products Purchased -->
|
||||
<div class="form-group">
|
||||
<label class="form-label">Sản phẩm đã mua</label>
|
||||
<textarea class="form-input form-textarea"
|
||||
id="products"
|
||||
placeholder="Mô tả các sản phẩm đã mua (tùy chọn)"
|
||||
rows="3"></textarea>
|
||||
<!-- Order Summary (Auto-calculated) -->
|
||||
<div class="summary-card">
|
||||
<h3 style="font-size: 16px; font-weight: 600; color: #333; margin-bottom: 16px;">
|
||||
<i class="fas fa-calculator" style="color: #005B9A; margin-right: 8px;"></i>
|
||||
Tổng kết đơn hàng
|
||||
</h3>
|
||||
<div style="display: flex; flex-direction: column; gap: 12px;">
|
||||
<div style="display: flex; justify-content: space-between; padding-bottom: 12px; border-bottom: 1px dashed #e5e7eb;">
|
||||
<span style="color: #666; font-size: 15px;">Tổng số lượng:</span>
|
||||
<span id="totalSquareMeters" style="color: #333; font-weight: 600; font-size: 15px;">0 m²</span>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: space-between;">
|
||||
<span style="color: #666; font-size: 15px;">Tổng giá trị đơn hàng:</span>
|
||||
<span id="totalAmount" style="color: #005B9A; font-weight: 700; font-size: 18px;">0 đ</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Points Estimate -->
|
||||
<div class="points-estimate" id="pointsEstimate">
|
||||
<div class="estimate-title">Điểm dự kiến nhận được</div>
|
||||
<div class="estimate-text" id="estimateText">0 điểm</div>
|
||||
</div>
|
||||
|
||||
<!-- Invoice Images -->
|
||||
<div class="form-group">
|
||||
@@ -504,13 +601,13 @@
|
||||
</div>
|
||||
|
||||
<!-- Additional Notes -->
|
||||
<div class="form-group">
|
||||
<!--<div class="form-group">
|
||||
<label class="form-label">Ghi chú thêm</label>
|
||||
<textarea class="form-input form-textarea"
|
||||
id="notes"
|
||||
placeholder="Ghi chú thêm về đơn hàng (tùy chọn)"
|
||||
rows="3"></textarea>
|
||||
</div>
|
||||
</div>-->
|
||||
|
||||
<!-- Submit Button -->
|
||||
<button type="submit" class="submit-button" id="submitButton" disabled>
|
||||
@@ -523,26 +620,153 @@
|
||||
|
||||
<script>
|
||||
let selectedFiles = [];
|
||||
let productCounter = 0;
|
||||
let products = [];
|
||||
|
||||
// Set max date to today
|
||||
document.getElementById('purchaseDate').max = new Date().toISOString().split('T')[0];
|
||||
|
||||
// Add first product row on page load
|
||||
window.addEventListener('DOMContentLoaded', function() {
|
||||
addProductRow();
|
||||
});
|
||||
|
||||
function goBack() {
|
||||
window.history.back();
|
||||
}
|
||||
|
||||
function addProductRow() {
|
||||
productCounter++;
|
||||
const productsList = document.getElementById('productsList');
|
||||
|
||||
const productRow = document.createElement('div');
|
||||
productRow.className = 'product-row';
|
||||
productRow.id = `product-${productCounter}`;
|
||||
productRow.innerHTML = `
|
||||
<div class="product-row-header">
|
||||
<span class="product-row-title">
|
||||
<i class="fas fa-box"></i> Sản phẩm #${productCounter}
|
||||
</span>
|
||||
<button type="button" onclick="removeProductRow(${productCounter})" class="btn-remove-product">
|
||||
<i class="fas fa-trash"></i> Xóa
|
||||
</button>
|
||||
</div>
|
||||
<div class="product-input-full">
|
||||
<label class="product-label required">Tên sản phẩm</label>
|
||||
<input type="text"
|
||||
class="form-input"
|
||||
id="productName-${productCounter}"
|
||||
placeholder="Ví dụ: Gạch Granite 60x60"
|
||||
required
|
||||
onchange="updateCalculations()">
|
||||
</div>
|
||||
<div class="product-input-group">
|
||||
<div>
|
||||
<label class="product-label required">Số lượng (m²)</label>
|
||||
<input type="number"
|
||||
class="form-input"
|
||||
id="productQty-${productCounter}"
|
||||
placeholder="0"
|
||||
min="0"
|
||||
step="0.01"
|
||||
required
|
||||
oninput="updateCalculations()">
|
||||
</div>
|
||||
<div>
|
||||
<label class="product-label required">Đơn giá (VNĐ/m²)</label>
|
||||
<input type="number"
|
||||
class="form-input"
|
||||
id="productPrice-${productCounter}"
|
||||
placeholder="0"
|
||||
min="0"
|
||||
step="1000"
|
||||
required
|
||||
oninput="updateCalculations()">
|
||||
</div>
|
||||
</div>
|
||||
<div class="product-subtotal">
|
||||
<div class="product-subtotal-label">Thành tiền</div>
|
||||
<div class="product-subtotal-value" id="productSubtotal-${productCounter}">0 đ</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
productsList.appendChild(productRow);
|
||||
products.push(productCounter);
|
||||
updateCalculations();
|
||||
}
|
||||
|
||||
function removeProductRow(id) {
|
||||
if (products.length <= 1) {
|
||||
alert('Cần ít nhất một sản phẩm!');
|
||||
return;
|
||||
}
|
||||
|
||||
const row = document.getElementById(`product-${id}`);
|
||||
if (row) {
|
||||
row.remove();
|
||||
products = products.filter(p => p !== id);
|
||||
updateCalculations();
|
||||
}
|
||||
}
|
||||
|
||||
function updateCalculations() {
|
||||
let totalQty = 0;
|
||||
let totalValue = 0;
|
||||
|
||||
products.forEach(id => {
|
||||
const qtyInput = document.getElementById(`productQty-${id}`);
|
||||
const priceInput = document.getElementById(`productPrice-${id}`);
|
||||
const subtotalEl = document.getElementById(`productSubtotal-${id}`);
|
||||
|
||||
if (qtyInput && priceInput && subtotalEl) {
|
||||
const qty = parseFloat(qtyInput.value) || 0;
|
||||
const price = parseFloat(priceInput.value) || 0;
|
||||
const subtotal = qty * price;
|
||||
|
||||
totalQty += qty;
|
||||
totalValue += subtotal;
|
||||
|
||||
subtotalEl.textContent = formatCurrency(subtotal);
|
||||
}
|
||||
});
|
||||
|
||||
// Update summary
|
||||
document.getElementById('totalSquareMeters').textContent = totalQty.toFixed(2) + ' m²';
|
||||
document.getElementById('totalAmount').textContent = formatCurrency(totalValue);
|
||||
|
||||
// Calculate points
|
||||
calculatePoints(totalValue);
|
||||
validateForm();
|
||||
}
|
||||
|
||||
function formatCurrency(value) {
|
||||
return new Intl.NumberFormat('vi-VN', {
|
||||
style: 'currency',
|
||||
currency: 'VND',
|
||||
minimumFractionDigits: 0
|
||||
}).format(value);
|
||||
}
|
||||
|
||||
function validateForm() {
|
||||
const purchaseDate = document.getElementById('purchaseDate').value;
|
||||
const storeLocation = document.getElementById('storeLocation').value;
|
||||
const totalAmount = document.getElementById('totalAmount').value;
|
||||
const hasFiles = selectedFiles.length > 0;
|
||||
|
||||
const isValid = purchaseDate && storeLocation && totalAmount && hasFiles;
|
||||
// Check if at least one product is filled
|
||||
let hasValidProduct = false;
|
||||
products.forEach(id => {
|
||||
const name = document.getElementById(`productName-${id}`).value;
|
||||
const qty = document.getElementById(`productQty-${id}`).value;
|
||||
const price = document.getElementById(`productPrice-${id}`).value;
|
||||
if (name && qty && price) {
|
||||
hasValidProduct = true;
|
||||
}
|
||||
});
|
||||
|
||||
const isValid = purchaseDate && hasValidProduct && hasFiles;
|
||||
document.getElementById('submitButton').disabled = !isValid;
|
||||
}
|
||||
|
||||
function calculatePoints() {
|
||||
const totalAmount = document.getElementById('totalAmount').value;
|
||||
function calculatePoints(totalAmount) {
|
||||
const pointsEstimate = document.getElementById('pointsEstimate');
|
||||
const estimateText = document.getElementById('estimateText');
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import 'package:worker/features/chat/presentation/pages/chat_list_page.dart';
|
||||
import 'package:worker/features/favorites/presentation/pages/favorites_page.dart';
|
||||
import 'package:worker/features/loyalty/presentation/pages/loyalty_page.dart';
|
||||
import 'package:worker/features/loyalty/presentation/pages/points_history_page.dart';
|
||||
import 'package:worker/features/loyalty/presentation/pages/points_record_create_page.dart';
|
||||
import 'package:worker/features/loyalty/presentation/pages/points_records_page.dart';
|
||||
import 'package:worker/features/loyalty/presentation/pages/rewards_page.dart';
|
||||
import 'package:worker/features/main/presentation/pages/main_scaffold.dart';
|
||||
@@ -323,6 +324,14 @@ final routerProvider = Provider<GoRouter>((ref) {
|
||||
MaterialPage(key: state.pageKey, child: const PointsRecordsPage()),
|
||||
),
|
||||
|
||||
// Points Record Create Route
|
||||
GoRoute(
|
||||
path: RouteNames.pointsRecordCreate,
|
||||
name: 'loyalty_points_record_create',
|
||||
pageBuilder: (context, state) =>
|
||||
MaterialPage(key: state.pageKey, child: const PointsRecordCreatePage()),
|
||||
),
|
||||
|
||||
// Orders Route
|
||||
GoRoute(
|
||||
path: RouteNames.orders,
|
||||
@@ -651,6 +660,7 @@ class RouteNames {
|
||||
static const String rewards = '$loyalty/rewards';
|
||||
static const String pointsHistory = '$loyalty/points-history';
|
||||
static const String pointsRecords = '$loyalty/points-records';
|
||||
static const String pointsRecordCreate = '$loyalty/points-records/create';
|
||||
static const String myGifts = '$loyalty/gifts';
|
||||
static const String referral = '$loyalty/referral';
|
||||
|
||||
|
||||
@@ -8,11 +8,9 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:worker/core/widgets/loading_indicator.dart';
|
||||
import 'package:worker/core/constants/ui_constants.dart';
|
||||
import 'package:worker/core/database/models/enums.dart';
|
||||
import 'package:worker/core/theme/colors.dart';
|
||||
import 'package:worker/features/loyalty/data/datasources/points_history_local_datasource.dart';
|
||||
import 'package:worker/core/widgets/loading_indicator.dart';
|
||||
import 'package:worker/features/loyalty/data/models/loyalty_point_entry_model.dart';
|
||||
import 'package:worker/features/loyalty/presentation/providers/points_history_provider.dart';
|
||||
|
||||
@@ -20,9 +18,8 @@ import 'package:worker/features/loyalty/presentation/providers/points_history_pr
|
||||
///
|
||||
/// Features:
|
||||
/// - Filter section with date range
|
||||
/// - List of transaction cards
|
||||
/// - Each card shows: description, date, amount, points change, new balance
|
||||
/// - Complaint button for each transaction
|
||||
/// - List of transaction cards with new design
|
||||
/// - Each card shows: code, date, description, reference, points change, balance after
|
||||
class PointsHistoryPage extends ConsumerWidget {
|
||||
const PointsHistoryPage({super.key});
|
||||
|
||||
@@ -57,22 +54,19 @@ class PointsHistoryPage extends ConsumerWidget {
|
||||
return _buildEmptyState(colorScheme);
|
||||
}
|
||||
|
||||
return SingleChildScrollView(
|
||||
return ListView(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Filter Section
|
||||
_buildFilterSection(colorScheme),
|
||||
children: [
|
||||
// Filter Section
|
||||
_buildFilterSection(colorScheme),
|
||||
|
||||
const SizedBox(height: 16),
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// Transaction List
|
||||
...entries.map(
|
||||
(entry) => _buildTransactionCard(context, ref, entry, colorScheme),
|
||||
),
|
||||
],
|
||||
),
|
||||
// Transaction List
|
||||
...entries.map(
|
||||
(entry) => _buildTransactionCard(context, entry, colorScheme),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
loading: () => const CustomLoadingIndicator(),
|
||||
@@ -89,12 +83,12 @@ class PointsHistoryPage extends ConsumerWidget {
|
||||
margin: EdgeInsets.zero,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Bộ lọc',
|
||||
@@ -104,159 +98,162 @@ class PointsHistoryPage extends ConsumerWidget {
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
FaIcon(FontAwesomeIcons.sliders, color: colorScheme.primary, size: 18),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
'Thời gian hiệu lực: 01/01/2023 - 31/12/2023',
|
||||
style: TextStyle(fontSize: 12, color: colorScheme.onSurfaceVariant),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'Thời gian hiệu lực: 01/01/2023 - 31/12/2023',
|
||||
style: TextStyle(fontSize: 12, color: colorScheme.onSurfaceVariant),
|
||||
),
|
||||
FaIcon(FontAwesomeIcons.filter, color: colorScheme.primary, size: 18),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Build transaction card
|
||||
/// Build transaction card with new design
|
||||
Widget _buildTransactionCard(
|
||||
BuildContext context,
|
||||
WidgetRef ref,
|
||||
LoyaltyPointEntryModel entry,
|
||||
ColorScheme colorScheme,
|
||||
) {
|
||||
final dateFormatter = DateFormat('dd/MM/yyyy HH:mm:ss');
|
||||
final currencyFormatter = NumberFormat.currency(
|
||||
locale: 'vi_VN',
|
||||
symbol: 'VND',
|
||||
decimalDigits: 0,
|
||||
);
|
||||
final dateFormatter = DateFormat('dd/MM/yyyy');
|
||||
|
||||
// Get transaction amount if it's a purchase
|
||||
final datasource = ref.read(pointsHistoryLocalDataSourceProvider);
|
||||
final transactionAmount = datasource.getTransactionAmount(
|
||||
entry.description,
|
||||
);
|
||||
// Determine points color
|
||||
Color pointsColor;
|
||||
String pointsPrefix;
|
||||
if (entry.points > 0) {
|
||||
pointsColor = AppColors.success;
|
||||
pointsPrefix = '+';
|
||||
} else if (entry.points < 0) {
|
||||
pointsColor = AppColors.danger;
|
||||
pointsPrefix = '';
|
||||
} else {
|
||||
pointsColor = colorScheme.onSurfaceVariant;
|
||||
pointsPrefix = '';
|
||||
}
|
||||
|
||||
return Card(
|
||||
elevation: 1,
|
||||
margin: const EdgeInsets.only(bottom: 12),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Top row: Description and Complaint button
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: Column(
|
||||
children: [
|
||||
// Header: Code and Date
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
decoration: BoxDecoration(
|
||||
color: colorScheme.surfaceContainerHighest.withValues(alpha: 0.5),
|
||||
border: Border(
|
||||
bottom: BorderSide(
|
||||
color: colorScheme.outlineVariant,
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
entry.entryId,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: colorScheme.primary,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
dateFormatter.format(entry.timestamp),
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// Content: Description and Points
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
// Description
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Description
|
||||
Text(
|
||||
entry.description,
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: colorScheme.primary,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
|
||||
// Timestamp
|
||||
Text(
|
||||
'Thời gian: ${dateFormatter.format(entry.timestamp)}',
|
||||
'Mã tham chiếu: #${entry.entryId}',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontSize: 13,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
|
||||
// Transaction amount (if purchase)
|
||||
if (transactionAmount != null) ...[
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
'Giao dịch: ${currencyFormatter.format(transactionAmount)}',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(width: 12),
|
||||
const SizedBox(width: 16),
|
||||
|
||||
// Complaint button
|
||||
OutlinedButton(
|
||||
onPressed: () {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Chức năng khiếu nại đang phát triển'),
|
||||
),
|
||||
);
|
||||
},
|
||||
style: OutlinedButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 6,
|
||||
),
|
||||
side: BorderSide(color: colorScheme.onSurfaceVariant),
|
||||
foregroundColor: colorScheme.onSurface,
|
||||
textStyle: const TextStyle(fontSize: 12),
|
||||
minimumSize: const Size(0, 32),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
),
|
||||
// Points
|
||||
Text(
|
||||
'$pointsPrefix${entry.points} điểm',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: pointsColor,
|
||||
),
|
||||
child: const Text('Khiếu nại'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: 12),
|
||||
|
||||
// Bottom row: Points change and new balance
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
// Footer: Balance After
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
decoration: BoxDecoration(
|
||||
color: colorScheme.surfaceContainerLowest,
|
||||
border: Border(
|
||||
top: BorderSide(
|
||||
color: colorScheme.outlineVariant.withValues(alpha: 0.5),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
// Points change
|
||||
Text(
|
||||
entry.points > 0 ? '+${entry.points}' : '${entry.points}',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: entry.points > 0
|
||||
? AppColors.success
|
||||
: entry.points < 0
|
||||
? AppColors.danger
|
||||
: colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
|
||||
// New balance
|
||||
Text(
|
||||
'Điểm mới: ${entry.balanceAfter}',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: colorScheme.primary,
|
||||
),
|
||||
),
|
||||
],
|
||||
Text(
|
||||
'Số dư sau: ',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'${entry.balanceAfter} điểm',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: colorScheme.primary,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -293,7 +290,6 @@ class PointsHistoryPage extends ConsumerWidget {
|
||||
|
||||
/// Build error state
|
||||
Widget _buildErrorState(Object error, ColorScheme colorScheme) {
|
||||
print(error.toString());
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,9 +8,10 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:worker/core/widgets/loading_indicator.dart';
|
||||
import 'package:worker/core/constants/ui_constants.dart';
|
||||
import 'package:worker/core/router/app_router.dart';
|
||||
import 'package:worker/core/theme/colors.dart';
|
||||
import 'package:worker/core/widgets/loading_indicator.dart';
|
||||
import 'package:worker/features/loyalty/domain/entities/points_record.dart';
|
||||
import 'package:worker/features/loyalty/presentation/providers/points_records_provider.dart';
|
||||
|
||||
@@ -47,13 +48,12 @@ class PointsRecordsPage extends ConsumerWidget {
|
||||
color: colorScheme.onSurface,
|
||||
size: 20,
|
||||
),
|
||||
onPressed: () {
|
||||
// TODO: Navigate to points record create page
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Tính năng tạo ghi nhận điểm sẽ được cập nhật'),
|
||||
),
|
||||
);
|
||||
onPressed: () async {
|
||||
final result = await context.push<bool>(RouteNames.pointsRecordCreate);
|
||||
if (result == true) {
|
||||
// Refresh list after successful creation
|
||||
ref.invalidate(allPointsRecordsProvider);
|
||||
}
|
||||
},
|
||||
),
|
||||
const SizedBox(width: AppSpacing.sm),
|
||||
|
||||
Reference in New Issue
Block a user