import React, { useState, useEffect } from 'react'; import { Table, Button, Avatar, Spin, Select, Input, message, Modal } from 'antd'; import { Link } from 'react-router-dom'; import { Plus, Edit, Trash2, Users, Gift, Heart, Search, Download } from 'react-feather'; import CustomPagination from '../../components/CustomPagination'; import { weddingGuestService } from '../../services/weddingGuestService'; const { Option } = Select; const { confirm } = Modal; const WeddingGuestList = () => { // State management const [guestData, setGuestData] = useState([]); const [loading, setLoading] = useState(false); const [selectedRowKeys, setSelectedRowKeys] = useState([]); // Pagination state const [currentPage, setCurrentPage] = useState(1); const [pageSize, setPageSize] = useState(10); const [totalCount, setTotalCount] = useState(0); const [totalPages, setTotalPages] = useState(1); // Filter states const [filterStatus, setFilterStatus] = useState('All Status'); const [filterUnit, setFilterUnit] = useState('All Units'); const [searchTerm, setSearchTerm] = useState(''); // Statistics and options const [statistics, setStatistics] = useState({ totalGuests: 0, confirmedGuests: 0, totalPeople: 0, totalGiftAmount: 0 }); // Mock data fallback for development/testing const mockGuestData = [ { id: '1', name: 'Nguyễn Văn An', unit: 'Công ty ABC', numberOfPeople: 2, giftAmount: 500000, status: 'Going', phone: '0901234567', relationship: 'Friend', address: '123 Lê Lợi, Q1, TP.HCM', notes: 'Bạn thân từ đại học', inviteDate: '2024-01-15T00:00:00Z', confirmDate: '2024-01-20T00:00:00Z', createdDate: '2024-01-10T00:00:00Z', isActive: true }, { id: '2', name: 'Trần Thị Bình', unit: 'Trường ĐH XYZ', numberOfPeople: 4, giftAmount: 1000000, status: 'Going', phone: '0912345678', relationship: 'Family', address: '456 Nguyễn Huệ, Q1, TP.HCM', notes: 'Chị gái', inviteDate: '2024-01-16T00:00:00Z', confirmDate: '2024-01-22T00:00:00Z', createdDate: '2024-01-11T00:00:00Z', isActive: true }, { id: '3', name: 'Lê Minh Cường', unit: 'Ngân hàng DEF', numberOfPeople: 1, giftAmount: 300000, status: 'NotGoing', phone: '0923456789', relationship: 'Colleague', address: '789 Đồng Khởi, Q1, TP.HCM', notes: 'Đồng nghiệp cũ', inviteDate: '2024-01-17T00:00:00Z', confirmDate: '2024-01-25T00:00:00Z', createdDate: '2024-01-12T00:00:00Z', isActive: true }, { id: '4', name: 'Phạm Thị Dung', unit: 'Bệnh viện GHI', numberOfPeople: 3, giftAmount: 800000, status: 'Going', phone: '0934567890', relationship: 'Friend', address: '321 Hai Bà Trưng, Q3, TP.HCM', notes: 'Bạn cùng lớp', inviteDate: '2024-01-18T00:00:00Z', confirmDate: '2024-01-28T00:00:00Z', createdDate: '2024-01-13T00:00:00Z', isActive: true }, { id: '5', name: 'Hoàng Văn Em', unit: 'Công ty JKL', numberOfPeople: 2, giftAmount: 600000, status: 'Pending', phone: '0945678901', relationship: 'Colleague', address: '654 Cách Mạng Tháng 8, Q10, TP.HCM', notes: 'Đồng nghiệp hiện tại', inviteDate: '2024-01-19T00:00:00Z', confirmDate: null, createdDate: '2024-01-14T00:00:00Z', isActive: true } ]; // Load wedding guests from API const loadGuests = async (page = 1, size = 10) => { console.log('🚀 Loading guests...', { page, size, searchTerm, filterStatus, filterUnit }); setLoading(true); try { const params = { page: page, pageSize: size, searchTerm: searchTerm || undefined, status: (filterStatus && filterStatus !== 'All Status') ? filterStatus : undefined, unit: (filterUnit && filterUnit !== 'All Units') ? filterUnit : undefined, sortBy: 'name', sortOrder: 'asc' }; console.log('📤 API Request params:', params); const response = await weddingGuestService.getWeddingGuests(params); console.log('📥 API Response:', response); if (response.success) { // Handle different API response structures let guests = []; let paginationInfo = null; // Check if response has pagination structure if (response.data && typeof response.data === 'object') { if (response.data.data && Array.isArray(response.data.data)) { // Structure: { data: [...], pagination: {...} } guests = response.data.data; paginationInfo = response.data.pagination; } else if (response.data.guests && Array.isArray(response.data.guests)) { // Structure: { guests: [...], pagination: {...} } guests = response.data.guests; paginationInfo = response.data.pagination; } else if (Array.isArray(response.data)) { // Structure: [...] guests = response.data; } else { // Fallback: try to extract array from response guests = Object.values(response.data).find(val => Array.isArray(val)) || []; } } console.log('👥 Setting guest data:', guests); setGuestData(guests); // Handle pagination info if (paginationInfo) { const totalCount = paginationInfo.totalCount || paginationInfo.total || 0; const totalPages = paginationInfo.totalPages || Math.ceil(totalCount / pageSize); setTotalCount(totalCount); setTotalPages(totalPages); console.log('📊 Pagination from API:', { paginationInfo, totalCount, totalPages, currentPage: page, pageSize }); } else { // Calculate pagination from array length const totalCount = guests.length; const totalPages = Math.ceil(totalCount / pageSize); setTotalCount(totalCount); setTotalPages(totalPages); console.log('📊 Calculated pagination:', { totalCount, totalPages, currentPage: page, pageSize, guestsLength: guests.length }); } } else { console.error('❌ API call failed:', response.message); console.log('🔄 Using mock data as fallback'); // Use mock data as fallback setGuestData(mockGuestData); setTotalCount(mockGuestData.length); setTotalPages(1); message.warning('Using demo data - API connection failed: ' + response.message); } } catch (error) { console.error('💥 Exception in loadGuests:', error); console.log('🔄 Using mock data as fallback due to exception'); // Use mock data as fallback setGuestData(mockGuestData); setTotalCount(mockGuestData.length); setTotalPages(1); message.warning('Using demo data - API connection error: ' + error.message); } finally { setLoading(false); console.log('✅ Loading complete'); } }; // Load statistics from API const loadStatistics = async () => { try { console.log('📊 Loading statistics...'); const response = await weddingGuestService.getWeddingGuestStatistics(); if (response.success) { setStatistics({ totalGuests: response.data.totalGuests || 0, confirmedGuests: response.data.confirmedGuests || 0, totalPeople: response.data.totalPeople || 0, totalGiftAmount: response.data.totalGiftAmount || 0 }); console.log('✅ Statistics loaded:', response.data); } else { console.log('🔄 Using mock statistics as fallback'); // Calculate mock statistics const mockStats = { totalGuests: mockGuestData.length, confirmedGuests: mockGuestData.filter(g => g.status === 'Going').length, totalPeople: mockGuestData.filter(g => g.status === 'Going').reduce((sum, g) => sum + g.numberOfPeople, 0), totalGiftAmount: mockGuestData.filter(g => g.status === 'Going').reduce((sum, g) => sum + g.giftAmount, 0) }; setStatistics(mockStats); console.log('📊 Mock statistics:', mockStats); } } catch (error) { console.error('Error loading statistics:', error); console.log('🔄 Using mock statistics as fallback due to exception'); // Calculate mock statistics const mockStats = { totalGuests: mockGuestData.length, confirmedGuests: mockGuestData.filter(g => g.status === 'Going').length, totalPeople: mockGuestData.filter(g => g.status === 'Going').reduce((sum, g) => sum + g.numberOfPeople, 0), totalGiftAmount: mockGuestData.filter(g => g.status === 'Going').reduce((sum, g) => sum + g.giftAmount, 0) }; setStatistics(mockStats); } }; // Load available units for filter const loadUnits = async () => { try { console.log('🏢 Loading units...'); const response = await weddingGuestService.getUnits(); if (response.success) { console.log('✅ Units loaded:', response.data); } else { console.log('🔄 Using mock units as fallback'); } } catch (error) { console.error('Error loading units:', error); console.log('🔄 Using mock units as fallback due to exception'); } }; // Handle delete guest const handleDeleteGuest = async (id) => { confirm({ title: 'Xác nhận xóa khách mời', content: 'Bạn có chắc chắn muốn xóa khách mời này không?', okText: 'Xóa', okType: 'danger', cancelText: 'Hủy', onOk: async () => { try { const response = await weddingGuestService.deleteWeddingGuest(id); if (response.success) { message.success('Xóa khách mời thành công'); loadGuests(currentPage, pageSize); loadStatistics(); } else { message.error(response.message || 'Failed to delete guest'); } } catch (error) { console.error('Error deleting guest:', error); message.error('An error occurred while deleting guest'); } } }); }; // Handle export guests const handleExportGuests = async () => { try { const response = await weddingGuestService.exportWeddingGuests('excel'); if (response.success) { message.success('Export completed successfully'); } else { message.error(response.message || 'Failed to export guests'); } } catch (error) { console.error('Error exporting guests:', error); message.error('An error occurred while exporting guests'); } }; // Get status configuration const getStatusConfig = (status) => { const statusConfigs = { 'Going': { color: '#52c41a', backgroundColor: 'rgba(82, 196, 26, 0.1)', borderColor: '#52c41a', textColor: '#52c41a', icon: '✅', label: 'Đi' }, 'NotGoing': { color: '#f5222d', backgroundColor: 'rgba(245, 34, 45, 0.1)', borderColor: '#f5222d', textColor: '#f5222d', icon: '❌', label: 'Không đi' }, 'Pending': { color: '#faad14', backgroundColor: 'rgba(250, 173, 20, 0.1)', borderColor: '#faad14', textColor: '#faad14', icon: '⏳', label: 'Chưa xác nhận' } }; return statusConfigs[status] || statusConfigs['Pending']; }; // Format currency const formatCurrency = (amount) => { return new Intl.NumberFormat('vi-VN', { style: 'currency', currency: 'VND' }).format(amount); }; // Load data on component mount useEffect(() => { loadGuests(); loadStatistics(); loadUnits(); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); // Reload data when filters change useEffect(() => { if (currentPage === 1) { loadGuests(1, pageSize); } else { setCurrentPage(1); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [filterStatus, filterUnit, searchTerm]); // Handle pagination change const handlePageChange = (page) => { setCurrentPage(page); loadGuests(page, pageSize); }; // Handle page size change const handlePageSizeChange = (newPageSize) => { setPageSize(newPageSize); setCurrentPage(1); loadGuests(1, newPageSize); }; // Handle search const handleSearch = (value) => { setSearchTerm(value); }; // Table columns configuration const columns = [ { title: 'Tên khách mời', dataIndex: 'name', key: 'name', render: (text, record) => (