feat(frontend): add toast notifications for dashboard actions
- Install react-hot-toast library - Add Toaster component to App.jsx - Show success/error toasts for match accept/reject/cancel - Show toasts for real-time match events - Update tests with toast mocks
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useNavigate, Link } from 'react-router-dom';
|
||||
import toast from 'react-hot-toast';
|
||||
import Layout from '../components/layout/Layout';
|
||||
import { useAuth } from '../contexts/AuthContext';
|
||||
import { dashboardAPI, matchesAPI } from '../services/api';
|
||||
@@ -39,8 +40,8 @@ const DashboardPage = () => {
|
||||
|
||||
const socket = getSocket();
|
||||
if (socket) {
|
||||
socket.on('match_request_received', handleRealtimeUpdate);
|
||||
socket.on('match_accepted', handleRealtimeUpdate);
|
||||
socket.on('match_request_received', handleMatchRequest);
|
||||
socket.on('match_accepted', handleMatchAccepted);
|
||||
socket.on('match_cancelled', handleRealtimeUpdate);
|
||||
socket.on('new_message', handleRealtimeUpdate);
|
||||
}
|
||||
@@ -49,8 +50,8 @@ const DashboardPage = () => {
|
||||
return () => {
|
||||
const socket = getSocket();
|
||||
if (socket) {
|
||||
socket.off('match_request_received', handleRealtimeUpdate);
|
||||
socket.off('match_accepted', handleRealtimeUpdate);
|
||||
socket.off('match_request_received', handleMatchRequest);
|
||||
socket.off('match_accepted', handleMatchAccepted);
|
||||
socket.off('match_cancelled', handleRealtimeUpdate);
|
||||
socket.off('new_message', handleRealtimeUpdate);
|
||||
}
|
||||
@@ -58,6 +59,20 @@ const DashboardPage = () => {
|
||||
};
|
||||
}, [user]);
|
||||
|
||||
const handleMatchRequest = (data) => {
|
||||
toast.success(`New match request from ${data.requesterUsername || 'someone'}!`, {
|
||||
icon: '📨',
|
||||
});
|
||||
loadDashboard();
|
||||
};
|
||||
|
||||
const handleMatchAccepted = (data) => {
|
||||
toast.success('Match accepted! You can now chat.', {
|
||||
icon: '🎉',
|
||||
});
|
||||
loadDashboard();
|
||||
};
|
||||
|
||||
const loadDashboard = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
@@ -79,10 +94,11 @@ const DashboardPage = () => {
|
||||
try {
|
||||
setProcessingMatchId(matchSlug);
|
||||
await matchesAPI.acceptMatch(matchSlug);
|
||||
toast.success('Match accepted! You can now chat.', { icon: '🎉' });
|
||||
await loadDashboard();
|
||||
} catch (err) {
|
||||
console.error('Failed to accept match:', err);
|
||||
alert('Failed to accept match. Please try again.');
|
||||
toast.error('Failed to accept match. Please try again.');
|
||||
} finally {
|
||||
setProcessingMatchId(null);
|
||||
}
|
||||
@@ -94,10 +110,11 @@ const DashboardPage = () => {
|
||||
try {
|
||||
setProcessingMatchId(matchSlug);
|
||||
await matchesAPI.deleteMatch(matchSlug);
|
||||
toast.success('Request declined.');
|
||||
await loadDashboard();
|
||||
} catch (err) {
|
||||
console.error('Failed to reject match:', err);
|
||||
alert('Failed to decline request. Please try again.');
|
||||
toast.error('Failed to decline request. Please try again.');
|
||||
} finally {
|
||||
setProcessingMatchId(null);
|
||||
}
|
||||
@@ -109,10 +126,11 @@ const DashboardPage = () => {
|
||||
try {
|
||||
setProcessingMatchId(matchSlug);
|
||||
await matchesAPI.deleteMatch(matchSlug);
|
||||
toast.success('Request cancelled.');
|
||||
await loadDashboard();
|
||||
} catch (err) {
|
||||
console.error('Failed to cancel request:', err);
|
||||
alert('Failed to cancel request. Please try again.');
|
||||
toast.error('Failed to cancel request. Please try again.');
|
||||
} finally {
|
||||
setProcessingMatchId(null);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user