refactor(frontend): replace alert() with modern toast notifications
Replaced all alert() calls with react-hot-toast notifications for better user experience. Toast notifications are non-blocking, auto-dismiss, and provide visual feedback with icons based on message type. Changes: - EventChatPage: Match request success/error toasts - MatchChatPage: Video file selection and WebRTC connection error toasts - MatchesPage: Match accept/reject action toasts - RatePartnerPage: Rating submission and validation toasts - VerifyEmailPage: Email verification sent toast - ScheduleConfigSection: Schedule save success/error toasts - MatchingConfigSection: Deadline save success/error toasts All toast notifications use appropriate types (success, error, warning, info) for better visual distinction and user feedback.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { useState } from 'react';
|
||||
import toast from 'react-hot-toast';
|
||||
import { Video, Clock, Save, RefreshCw } from 'lucide-react';
|
||||
import { matchingAPI } from '../../services/api';
|
||||
|
||||
@@ -21,10 +22,11 @@ const MatchingConfigSection = ({ slug, event, onRefresh }) => {
|
||||
setSavingDeadline(true);
|
||||
const deadline = deadlineInput ? new Date(deadlineInput).toISOString() : null;
|
||||
await matchingAPI.setRegistrationDeadline(slug, deadline);
|
||||
toast.success('Deadline saved successfully');
|
||||
onRefresh?.();
|
||||
} catch (err) {
|
||||
console.error('Failed to save deadline:', err);
|
||||
alert('Nie udalo sie zapisac deadline');
|
||||
toast.error('Failed to save deadline');
|
||||
} finally {
|
||||
setSavingDeadline(false);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import toast from 'react-hot-toast';
|
||||
import { Layers, Plus, Trash2, Save, RefreshCw } from 'lucide-react';
|
||||
import { matchingAPI, divisionsAPI } from '../../services/api';
|
||||
|
||||
@@ -72,10 +73,11 @@ const ScheduleConfigSection = ({ slug, event, onRefresh }) => {
|
||||
? { slots: scheduleSlots.filter(s => s.divisionIds.length > 0) }
|
||||
: null;
|
||||
await matchingAPI.setScheduleConfig(slug, scheduleConfig);
|
||||
toast.success('Schedule saved successfully');
|
||||
onRefresh?.();
|
||||
} catch (err) {
|
||||
console.error('Failed to save schedule:', err);
|
||||
alert('Nie udalo sie zapisac harmonogramu');
|
||||
toast.error('Failed to save schedule');
|
||||
} finally {
|
||||
setSavingSchedule(false);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useState, useRef, useEffect } from 'react';
|
||||
import { useParams, useNavigate, useSearchParams, Link } from 'react-router-dom';
|
||||
import toast from 'react-hot-toast';
|
||||
import Layout from '../components/layout/Layout';
|
||||
import { useAuth } from '../contexts/AuthContext';
|
||||
import { Send, UserPlus, Loader2, LogOut, AlertTriangle, QrCode, Edit2, Filter, X, MessageSquare, Users, Video } from 'lucide-react';
|
||||
@@ -201,7 +202,7 @@ const EventChatPage = () => {
|
||||
const result = await matchesAPI.createMatch(userId, slug);
|
||||
|
||||
// Show success message
|
||||
alert(`Match request sent successfully! The user will be notified.`);
|
||||
toast.success('Match request sent successfully! The user will be notified.');
|
||||
|
||||
// Optional: Navigate to matches page or refresh matches list
|
||||
// For now, we just show a success message
|
||||
@@ -210,13 +211,13 @@ const EventChatPage = () => {
|
||||
|
||||
// Show appropriate error message
|
||||
if (error.status === 400 && error.message.includes('already exists')) {
|
||||
alert('You already have a match request with this user.');
|
||||
toast.error('You already have a match request with this user.');
|
||||
} else if (error.status === 403) {
|
||||
alert('You must be a participant of this event to send match requests.');
|
||||
toast.error('You must be a participant of this event to send match requests.');
|
||||
} else if (error.status === 404) {
|
||||
alert('Event not found.');
|
||||
toast.error('Event not found.');
|
||||
} else {
|
||||
alert('Failed to send match request. Please try again.');
|
||||
toast.error('Failed to send match request. Please try again.');
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -298,7 +299,7 @@ const EventChatPage = () => {
|
||||
navigate('/events');
|
||||
} catch (error) {
|
||||
console.error('Failed to leave event:', error);
|
||||
alert('Failed to leave event. Please try again.');
|
||||
toast.error('Failed to leave event. Please try again.');
|
||||
} finally {
|
||||
setIsLeaving(false);
|
||||
setShowLeaveModal(false);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useState, useRef, useEffect } from 'react';
|
||||
import { useParams, useNavigate, Link } from 'react-router-dom';
|
||||
import toast from 'react-hot-toast';
|
||||
import Layout from '../components/layout/Layout';
|
||||
import { useAuth } from '../contexts/AuthContext';
|
||||
import { matchesAPI } from '../services/api';
|
||||
@@ -73,7 +74,7 @@ const MatchChatPage = () => {
|
||||
setMatch(result.data);
|
||||
} catch (error) {
|
||||
console.error('Failed to load match:', error);
|
||||
alert('Failed to load match. Redirecting to matches page.');
|
||||
toast.error('Failed to load match. Redirecting to matches page.');
|
||||
navigate('/matches');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
@@ -97,7 +98,7 @@ const MatchChatPage = () => {
|
||||
if (file && file.type.startsWith('video/')) {
|
||||
setSelectedFile(file);
|
||||
} else {
|
||||
alert('Please select a video file');
|
||||
toast.error('Please select a video file');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -128,7 +129,7 @@ const MatchChatPage = () => {
|
||||
try {
|
||||
await waitForConnection;
|
||||
} catch (error) {
|
||||
alert('Failed to establish connection: ' + error.message);
|
||||
toast.error('Failed to establish connection: ' + error.message);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import toast from 'react-hot-toast';
|
||||
import Layout from '../components/layout/Layout';
|
||||
import { useAuth } from '../contexts/AuthContext';
|
||||
import { matchesAPI } from '../services/api';
|
||||
@@ -80,10 +81,10 @@ const MatchesPage = () => {
|
||||
await loadMatches();
|
||||
|
||||
// Show success message
|
||||
alert('Match accepted! You can now chat with your partner.');
|
||||
toast.success('Match accepted! You can now chat with your partner.');
|
||||
} catch (error) {
|
||||
console.error('Failed to accept match:', error);
|
||||
alert('Failed to accept match. Please try again.');
|
||||
toast.error('Failed to accept match. Please try again.');
|
||||
} finally {
|
||||
setProcessingMatchId(null);
|
||||
}
|
||||
@@ -102,7 +103,7 @@ const MatchesPage = () => {
|
||||
setMatches(prev => prev.filter(m => m.slug !== matchSlug));
|
||||
} catch (error) {
|
||||
console.error('Failed to reject match:', error);
|
||||
alert('Failed to reject match. Please try again.');
|
||||
toast.error('Failed to reject match. Please try again.');
|
||||
} finally {
|
||||
setProcessingMatchId(null);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
import toast from 'react-hot-toast';
|
||||
import Layout from '../components/layout/Layout';
|
||||
import { matchesAPI } from '../services/api';
|
||||
import { Star, Loader2 } from 'lucide-react';
|
||||
@@ -26,20 +27,20 @@ const RatePartnerPage = () => {
|
||||
|
||||
// Check if this match can be rated
|
||||
if (result.data.status !== MATCH_STATUS.ACCEPTED && result.data.status !== MATCH_STATUS.COMPLETED) {
|
||||
alert('This match must be accepted before rating.');
|
||||
toast.error('This match must be accepted before rating.');
|
||||
navigate('/matches');
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if user has already rated this match
|
||||
if (result.data.hasRated) {
|
||||
alert('You have already rated this match.');
|
||||
toast.info('You have already rated this match.');
|
||||
navigate('/matches');
|
||||
return;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load match:', error);
|
||||
alert('Failed to load match. Redirecting to matches page.');
|
||||
toast.error('Failed to load match. Redirecting to matches page.');
|
||||
navigate('/matches');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
@@ -53,7 +54,7 @@ const RatePartnerPage = () => {
|
||||
const handleSubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
if (rating === 0) {
|
||||
alert('Please select a rating (1-5 stars)');
|
||||
toast.warning('Please select a rating (1-5 stars)');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -66,14 +67,14 @@ const RatePartnerPage = () => {
|
||||
wouldCollaborateAgain,
|
||||
});
|
||||
|
||||
alert('Rating submitted successfully!');
|
||||
toast.success('Rating submitted successfully!');
|
||||
navigate('/matches');
|
||||
} catch (error) {
|
||||
console.error('Failed to submit rating:', error);
|
||||
if (error.message?.includes('already rated')) {
|
||||
alert('You have already rated this match.');
|
||||
toast.error('You have already rated this match.');
|
||||
} else {
|
||||
alert('Failed to submit rating. Please try again.');
|
||||
toast.error('Failed to submit rating. Please try again.');
|
||||
}
|
||||
} finally {
|
||||
setSubmitting(false);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useNavigate, useSearchParams, Link } from 'react-router-dom';
|
||||
import toast from 'react-hot-toast';
|
||||
import { authAPI } from '../services/api';
|
||||
import { useAuth } from '../contexts/AuthContext';
|
||||
import { Video, Mail, CheckCircle, XCircle, Loader2, ArrowRight } from 'lucide-react';
|
||||
@@ -91,7 +92,7 @@ const VerifyEmailPage = () => {
|
||||
|
||||
try {
|
||||
await authAPI.resendVerification(email);
|
||||
alert('Verification email sent! Please check your inbox.');
|
||||
toast.success('Verification email sent! Please check your inbox.');
|
||||
} catch (err) {
|
||||
setError(err.data?.error || 'Failed to resend verification email');
|
||||
} finally {
|
||||
|
||||
Reference in New Issue
Block a user