demo.html

12.16 KB • 23/12/2025 15:22:21 • HTML

Tải về
demo.html
Html
<!DOCTYPE html>
<html lang="vi">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Demo Hệ Thống Duyệt Nạp Tiền TRON</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
</head>
<body class="bg-gray-100 p-10 font-sans">

    <div class="max-w-4xl mx-auto bg-white shadow-lg rounded-lg overflow-hidden">
        <div class="bg-blue-600 p-4 text-white flex justify-between items-center">
            <h1 class="text-xl font-bold"><i class="fas fa-users-cog mr-2"></i>Danh sách Khách hàng</h1>
            <span class="text-sm bg-blue-500 px-2 py-1 rounded">Role: Support</span>
        </div>

        <table class="w-full text-left border-collapse">
            <thead>
                <tr class="bg-gray-200 text-gray-700 uppercase text-sm leading-normal">
                    <th class="py-3 px-6">ID</th>
                    <th class="py-3 px-6">Tên Khách Hàng</th>
                    <th class="py-3 px-6">Email</th>
                    <th class="py-3 px-6 text-right">Số dư (USDT)</th>
                    <th class="py-3 px-6 text-center">Hành động</th>
                </tr>
            </thead>
            <tbody id="customer-list" class="text-gray-600 text-sm font-light">
                </tbody>
        </table>
    </div>

    <div id="topup-modal" class="fixed inset-0 bg-gray-900 bg-opacity-50 hidden flex items-center justify-center z-50">
        <div class="bg-white rounded-lg shadow-xl w-full max-w-lg mx-4 overflow-hidden transform transition-all">
            
            <div class="bg-gray-50 px-4 py-3 border-b flex justify-between items-center">
                <h3 class="text-lg font-semibold text-gray-800">
                    <i class="fas fa-wallet text-blue-500 mr-2"></i>Duyệt nạp USDT
                </h3>
                <button onclick="closeModal()" class="text-gray-400 hover:text-gray-600">&times;</button>
            </div>

            <div class="p-6 space-y-4">
                <div class="bg-blue-50 text-blue-800 text-xs p-2 rounded border border-blue-200">
                    <strong>Support chú ý:</strong> Hệ thống sẽ tự động check trên Tronscan.
                    <br> - Copy mã <b>VALID_123</b> để test trường hợp thành công.
                    <br> - Copy mã <b>USED_456</b> để test trường hợp trùng lặp.
                </div>

                <div>
                    <label class="block text-sm font-medium text-gray-700 mb-1">Đang nạp cho:</label>
                    <input type="text" id="modal-customer-name" class="w-full bg-gray-100 border border-gray-300 rounded px-3 py-2 text-gray-500" disabled>
                    <input type="hidden" id="modal-customer-id">
                </div>

                <div>
                    <label class="block text-sm font-medium text-gray-700 mb-1">Mã giao dịch (TXID):</label>
                    <div class="flex gap-2">
                        <input type="text" id="tx-input" placeholder="Dán mã giao dịch vào đây..." class="flex-1 border border-gray-300 rounded px-3 py-2 focus:outline-none focus:border-blue-500">
                        <button onclick="checkTransaction()" class="bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded shadow transition">
                            <i class="fas fa-search mr-1"></i> Kiểm tra
                        </button>
                    </div>
                </div>

                <div id="result-area" class="hidden border rounded p-3 mt-2">
                    </div>
            </div>

            <div class="bg-gray-50 px-4 py-3 flex justify-end gap-2">
                <button onclick="closeModal()" class="px-4 py-2 bg-gray-300 text-gray-700 rounded hover:bg-gray-400">Hủy bỏ</button>
                <button id="btn-confirm" onclick="confirmTopUp()" disabled class="px-4 py-2 bg-green-600 text-white rounded opacity-50 cursor-not-allowed hover:bg-green-700 transition">
                    <i class="fas fa-check-circle mr-1"></i> Duyệt Nạp
                </button>
            </div>
        </div>
    </div>

    <script>
        // 1. DỮ LIỆU GIẢ LẬP (MOCK DATA)
        const customers = [
            { id: 101, name: "Nguyễn Văn A", email: "a.nguyen@example.com", balance: 0 },
            { id: 102, name: "Trần Thị B", email: "b.tran@gmail.com", balance: 50 },
            { id: 103, name: "Lê Văn C", email: "c.le@yahoo.com", balance: 1200 }
        ];

        // Giả lập Database chứa các mã đã dùng
        const usedTransactionsInDB = ["USED_456", "OLD_TX_789"];

        // 2. RENDER GIAO DIỆN
        function renderCustomers() {
            const tbody = document.getElementById('customer-list');
            tbody.innerHTML = '';
            customers.forEach(cus => {
                const tr = document.createElement('tr');
                tr.className = "border-b border-gray-200 hover:bg-gray-100";
                tr.innerHTML = `
                    <td class="py-3 px-6 whitespace-nowrap font-medium">${cus.id}</td>
                    <td class="py-3 px-6">${cus.name}</td>
                    <td class="py-3 px-6">${cus.email}</td>
                    <td class="py-3 px-6 text-right font-bold text-green-600">$${cus.balance.toLocaleString()}</td>
                    <td class="py-3 px-6 text-center">
                        <button onclick="openModal(${cus.id})" class="bg-blue-500 hover:bg-blue-600 text-white py-1 px-3 rounded text-xs shadow">
                            <i class="fas fa-plus-circle"></i> Nạp USDT
                        </button>
                    </td>
                `;
                tbody.appendChild(tr);
            });
        }

        // Khởi chạy lần đầu
        renderCustomers();

        // 3. XỬ LÝ MODAL
        let currentCustomerId = null;

        function openModal(id) {
            const customer = customers.find(c => c.id === id);
            if(!customer) return;

            currentCustomerId = id;
            document.getElementById('modal-customer-name').value = customer.name;
            document.getElementById('modal-customer-id').value = customer.id;
            
            // Reset form
            document.getElementById('tx-input').value = '';
            document.getElementById('result-area').classList.add('hidden');
            document.getElementById('btn-confirm').disabled = true;
            document.getElementById('btn-confirm').classList.add('opacity-50', 'cursor-not-allowed');

            document.getElementById('topup-modal').classList.remove('hidden');
        }

        function closeModal() {
            document.getElementById('topup-modal').classList.add('hidden');
        }

        // 4. LOGIC CHECK GIAO DỊCH (CORE FEATURE)
        function checkTransaction() {
            const txInput = document.getElementById('tx-input').value.trim();
            const resultArea = document.getElementById('result-area');
            const btnConfirm = document.getElementById('btn-confirm');
            
            // Reset trạng thái
            resultArea.classList.remove('hidden', 'bg-red-50', 'border-red-200', 'bg-green-50', 'border-green-200', 'bg-yellow-50', 'border-yellow-200');
            resultArea.innerHTML = '<div class="text-center text-gray-500"><i class="fas fa-spinner fa-spin"></i> Đang kết nối Tronscan...</div>';
            btnConfirm.disabled = true;
            btnConfirm.classList.add('opacity-50', 'cursor-not-allowed');

            // Giả lập độ trễ mạng (1 giây)
            setTimeout(() => {
                // --- KỊCH BẢN 1: GIAO DỊCH ĐÃ DÙNG (DUPLICATE) ---
                if (usedTransactionsInDB.includes(txInput)) {
                    showResult('DUPLICATE', {
                        hash: txInput,
                        amount: 100,
                        time: '2023-10-10 15:30:00',
                        usedBy: 'Khách hàng ID #999'
                    });
                }
                // --- KỊCH BẢN 2: GIAO DỊCH HỢP LỆ (SUCCESS) ---
                else if (txInput === 'VALID_123') {
                    showResult('SUCCESS', {
                        hash: txInput,
                        amount: 500, // Số tiền giả lập lấy từ API
                        time: new Date().toLocaleString(),
                        from: 'T_KHACH_HANG_ABCXYZ'
                    });
                }
                // --- KỊCH BẢN 3: KHÔNG TÌM THẤY (NOT FOUND) ---
                else {
                    showResult('NOT_FOUND');
                }
            }, 800);
        }

        // Hàm hiển thị kết quả check
        let currentTransactionAmount = 0; // Lưu tạm số tiền để nạp

        function showResult(type, data) {
            const resultArea = document.getElementById('result-area');
            const btnConfirm = document.getElementById('btn-confirm');

            if (type === 'SUCCESS') {
                currentTransactionAmount = data.amount;
                resultArea.className = "border rounded p-3 mt-2 bg-green-50 border-green-200 text-green-800";
                resultArea.innerHTML = `
                    <div class="font-bold mb-1"><i class="fas fa-check-circle"></i> Giao dịch Hợp lệ</div>
                    <ul class="text-sm list-disc pl-5 space-y-1">
                        <li><strong>Số tiền:</strong> ${data.amount} USDT</li>
                        <li><strong>Thời gian:</strong> ${data.time}</li>
                        <li><strong>Từ ví:</strong> ${data.from}</li>
                        <li><strong>Trạng thái:</strong> Chưa sử dụng</li>
                    </ul>
                `;
                // Mở khóa nút nạp
                btnConfirm.disabled = false;
                btnConfirm.classList.remove('opacity-50', 'cursor-not-allowed');
                
            } else if (type === 'DUPLICATE') {
                resultArea.className = "border rounded p-3 mt-2 bg-red-50 border-red-200 text-red-800";
                resultArea.innerHTML = `
                    <div class="font-bold mb-1"><i class="fas fa-exclamation-triangle"></i> CẢNH BÁO: Đã sử dụng</div>
                    <div class="text-sm">Mã giao dịch này đã được nạp trước đó!</div>
                    <ul class="text-sm list-disc pl-5 mt-1">
                        <li><strong>Số tiền:</strong> ${data.amount} USDT</li>
                        <li><strong>Đã nạp lúc:</strong> ${data.time}</li>
                        <li><strong>Người nạp:</strong> ${data.usedBy}</li>
                    </ul>
                `;
            } else {
                resultArea.className = "border rounded p-3 mt-2 bg-yellow-50 border-yellow-200 text-yellow-800";
                resultArea.innerHTML = `
                    <div class="font-bold mb-1"><i class="fas fa-times-circle"></i> Không tìm thấy</div>
                    <div class="text-sm">Không tìm thấy giao dịch này trên Blockchain hoặc Tronscan chưa cập nhật. Vui lòng kiểm tra lại mã.</div>
                `;
            }
        }

        // 5. XÁC NHẬN NẠP TIỀN
        function confirmTopUp() {
            const customer = customers.find(c => c.id === currentCustomerId);
            if (customer) {
                // Cộng tiền
                customer.balance += currentTransactionAmount;
                
                // Cập nhật giao diện
                renderCustomers();
                closeModal();
                
                // Thông báo (Alert đơn giản)
                alert(`Đã nạp thành công ${currentTransactionAmount} USDT cho khách hàng ${customer.name}`);
                
                // (Trong thực tế: Gọi API lưu vào DB để đánh dấu mã này đã dùng)
                usedTransactionsInDB.push(document.getElementById('tx-input').value);
            }
        }
    </script>
</body>
</html>

Số dòng: 241