From beb8ccbaeeb41e7420b14a2a85e4479ed4de88ae Mon Sep 17 00:00:00 2001 From: Rafiafrzl Date: Tue, 23 Dec 2025 22:10:11 +0700 Subject: [PATCH] feat: integration notification functionality and user history fetching --- src/api/notification.jsx | 12 +- .../component/ListNotification.jsx | 175 ++++++++++++------ .../IndexNotificationDetail.jsx | 105 +++++++---- 3 files changed, 199 insertions(+), 93 deletions(-) diff --git a/src/api/notification.jsx b/src/api/notification.jsx index 2e04cf8..67daa9a 100644 --- a/src/api/notification.jsx +++ b/src/api/notification.jsx @@ -46,10 +46,20 @@ const getNotificationLogByNotificationId = async (notificationId) => { return response.data; }; +// Resend notification to specific user +const resendNotificationToUser = async (notificationId, userId) => { + const response = await SendRequest({ + method: 'post', + prefix: `notification/${notificationId}/resend/${userId}`, + }); + return response.data; +}; + export { getAllNotification, getNotificationById, getNotificationDetail, createNotificationLog, - getNotificationLogByNotificationId + getNotificationLogByNotificationId, + resendNotificationToUser, }; diff --git a/src/pages/notification/component/ListNotification.jsx b/src/pages/notification/component/ListNotification.jsx index a959cd9..88df8de 100644 --- a/src/pages/notification/component/ListNotification.jsx +++ b/src/pages/notification/component/ListNotification.jsx @@ -38,7 +38,11 @@ import { SearchOutlined, } from '@ant-design/icons'; import { useNavigate, Link as RouterLink } from 'react-router-dom'; -import { getAllNotification, getNotificationLogByNotificationId } from '../../../api/notification'; +import { + getAllNotification, + getNotificationLogByNotificationId, + getNotificationDetail, +} from '../../../api/notification'; const { Text, Paragraph, Link: AntdLink } = Typography; @@ -77,31 +81,6 @@ const transformNotificationData = (apiData) => { })); }; -// Dummy data untuk user history -const userHistoryData = [ - { - id: '1', - name: 'John Doe', - phone: '081234567890', - status: 'Delivered', - timestamp: '04-11-2025 11:40 WIB', - }, - { - id: '2', - name: 'Jane Smith', - phone: '087654321098', - status: 'Delivered', - timestamp: '04-11-2025 11:41 WIB', - }, - { - id: '3', - name: 'Peter Jones', - phone: '082345678901', - status: 'Delivered', - timestamp: '04-11-2025 11:42 WIB', - }, -]; - const ListNotification = memo(function ListNotification(props) { const [notifications, setNotifications] = useState([]); const [activeTab, setActiveTab] = useState('all'); @@ -113,6 +92,8 @@ const ListNotification = memo(function ListNotification(props) { const [selectedNotification, setSelectedNotification] = useState(null); const [logHistoryData, setLogHistoryData] = useState([]); const [logLoading, setLogLoading] = useState(false); + const [userHistoryData, setUserHistoryData] = useState([]); + const [userLoading, setUserLoading] = useState(false); const [pagination, setPagination] = useState({ current_page: 1, current_limit: 10, @@ -290,6 +271,42 @@ const ListNotification = memo(function ListNotification(props) { } }; + // Fetch user history from API + const fetchUserHistory = async (notificationId) => { + try { + setUserLoading(true); + + const response = await getNotificationDetail(notificationId); + + if (response && response.data && response.data.users) { + // Transform API data to component format + const transformedUsers = response.data.users.map((user) => ({ + id: user.notification_error_user_id.toString(), + name: user.contact_name, + phone: user.contact_phone, + status: user.is_send ? 'Delivered' : 'Pending', + timestamp: user.created_at + ? new Date(user.created_at).toLocaleString('id-ID', { + day: '2-digit', + month: '2-digit', + year: 'numeric', + hour: '2-digit', + minute: '2-digit', + }) + ' WIB' + : 'N/A', + })); + setUserHistoryData(transformedUsers); + } else { + setUserHistoryData([]); + } + } catch (err) { + console.error('Error fetching user history:', err); + setUserHistoryData([]); // Set empty array on error + } finally { + setUserLoading(false); + } + }; + const tabButtonStyle = (isActive) => ({ padding: '12px 16px', border: 'none', @@ -467,8 +484,18 @@ const ListNotification = memo(function ListNotification(props) { border: '1px solid #1890ff', borderRadius: '4px', }} - onClick={(e) => { + onClick={async (e) => { e.stopPropagation(); + + setSelectedNotification(notification); + + // Extract notification ID from the notification object + const notificationId = + notification.id.split('-')[1]; + + // Fetch user history for the selected notification + await fetchUserHistory(notificationId); + setModalContent('user'); }} /> @@ -535,37 +562,69 @@ const ListNotification = memo(function ListNotification(props) { const renderUserHistory = () => ( <> - - {userHistoryData.map((user) => ( - - - - - {user.name} - | - - {user.phone} - - | - - - - - - - Success Delivered at {user.timestamp} - - - - - - - - - ))} - + {userLoading ? ( +
+ +
+ ) : ( + + {userHistoryData.map((user) => ( + + + + + {user.name} + | + + {user.phone} + + | + + + + + {user.status === 'Delivered' ? ( + + ) : ( + + )} + + {user.status === 'Delivered' + ? 'Success Delivered at' + : 'Status '}{' '} + {user.timestamp} + + + + + + + + + ))} + {userHistoryData.length === 0 && ( +
+ No user history available +
+ )} +
+ )} ); diff --git a/src/pages/notificationDetail/IndexNotificationDetail.jsx b/src/pages/notificationDetail/IndexNotificationDetail.jsx index 1a43f09..a3eb466 100644 --- a/src/pages/notificationDetail/IndexNotificationDetail.jsx +++ b/src/pages/notificationDetail/IndexNotificationDetail.jsx @@ -38,6 +38,7 @@ import { getNotificationDetail, createNotificationLog, getNotificationLogByNotificationId, + resendNotificationToUser, } from '../../api/notification'; const { Content } = Layout; @@ -94,38 +95,21 @@ const transformNotificationData = (apiData) => { device_location: apiData.device_location, brand_name: apiData.brand_name, }, + users: apiData.users || [], }; }; -// Dummy data baru untuk user history -const getDummyUsers = (notification) => { - if (!notification) return []; - return [ - { - id: '1', - name: 'John Doe', - phone: '081234567890', - status: 'delivered', - }, - { - id: '2', - name: 'Jane Smith', - phone: '082345678901', - status: 'sent', - }, - { - id: '3', - name: 'Bob Johnson', - phone: '083456789012', - status: 'failed', - }, - { - id: '4', - name: 'Alice Brown', - phone: '084567890123', - status: 'delivered', - }, - ]; +// Function to get actual users from notification data +const getUsersFromNotification = (notification) => { + if (!notification || !notification.users) return []; + + return notification.users.map((user) => ({ + id: user.notification_error_user_id.toString(), + name: user.contact_name, + phone: user.contact_phone, + status: user.is_send ? 'sent' : 'pending', + loading: user.loading || false, + })); }; const getStatusTag = (status) => { @@ -469,7 +453,7 @@ const NotificationDetailTab = (props) => { size={2} style={{ width: '100%' }} > - {getDummyUsers(notification).map((user) => ( + {getUsersFromNotification(notification).map((user) => ( { type="primary" icon={} size="small" - onClick={(e) => { + loading={user.loading} + onClick={async (e) => { e.stopPropagation(); - console.log( - `Resend to ${user.name}` - ); + const userId = parseInt(user.id); + try { + // Update user status to show loading + const updatedUsers = notification.users.map(u => + u.notification_error_user_id === userId + ? { ...u, loading: true } + : u + ); + setNotification({ + ...notification, + users: updatedUsers + }); + + // Call the resend API + const response = await resendNotificationToUser( + notification.notification_error_id, + userId + ); + + if (response && response.statusCode === 200) { + message.success(`Notification resent to ${user.name}`); + + // Update user status + const updatedUsersAfterSuccess = notification.users.map(u => + u.notification_error_user_id === userId + ? { + ...u, + is_send: true, + status: 'sent', + loading: false + } + : { ...u, loading: false } + ); + setNotification({ + ...notification, + users: updatedUsersAfterSuccess + }); + } else { + throw new Error(response?.message || 'Failed to resend notification'); + } + } catch (error) { + console.error('Error resending notification:', error); + message.error(error.message || 'Failed to resend notification'); + + // Reset loading state + const resetUsers = notification.users.map(u => + u.notification_error_user_id === userId + ? { ...u, loading: false } + : u + ); + setNotification({ + ...notification, + users: resetUsers + }); + } }} > Resend