diff --git a/frontend/src/components/connections/ConnectionRequestCard.tsx b/frontend/src/components/connections/ConnectionRequestCard.tsx index 7ac76a8..a0b19bf 100644 --- a/frontend/src/components/connections/ConnectionRequestCard.tsx +++ b/frontend/src/components/connections/ConnectionRequestCard.tsx @@ -4,6 +4,7 @@ import { toast } from 'sonner'; import { formatDistanceToNow } from 'date-fns'; import { Button } from '@/components/ui/button'; import { useConnections } from '@/hooks/useConnections'; +import axios from 'axios'; import { getErrorMessage } from '@/lib/api'; import { cn } from '@/lib/utils'; import type { ConnectionRequest } from '@/types'; @@ -33,7 +34,13 @@ export default function ConnectionRequestCard({ request, direction }: Connection setResolved(true); toast.success(action === 'accept' ? 'Connection accepted' : 'Request declined'); } catch (err) { - toast.error(getErrorMessage(err, 'Failed to respond')); + // 409 means the request was already resolved (e.g. accepted via toast or notification center) + if (axios.isAxiosError(err) && err.response?.status === 409) { + setResolved(true); + toast.success(action === 'accept' ? 'Connection already accepted' : 'Request already resolved'); + } else { + toast.error(getErrorMessage(err, 'Failed to respond')); + } } }; diff --git a/frontend/src/components/notifications/NotificationToaster.tsx b/frontend/src/components/notifications/NotificationToaster.tsx index 89f2ac6..7792634 100644 --- a/frontend/src/components/notifications/NotificationToaster.tsx +++ b/frontend/src/components/notifications/NotificationToaster.tsx @@ -4,6 +4,7 @@ import { Check, X, Bell, UserPlus } from 'lucide-react'; import { useQueryClient } from '@tanstack/react-query'; import { useNotifications } from '@/hooks/useNotifications'; import { useConnections } from '@/hooks/useConnections'; +import axios from 'axios'; import { getErrorMessage } from '@/lib/api'; import type { AppNotification } from '@/types'; @@ -36,11 +37,10 @@ export default function NotificationToaster() { await respondRef.current({ requestId, action }); toast.dismiss(loadingId); toast.success(action === 'accept' ? 'Connection accepted' : 'Request declined'); - } catch (err: any) { + } catch (err) { toast.dismiss(loadingId); // 409 means the request was already resolved (e.g. accepted via notification center) - const status = err?.response?.status; - if (status === 409) { + if (axios.isAxiosError(err) && err.response?.status === 409) { toast.success(action === 'accept' ? 'Connection already accepted' : 'Request already resolved'); } else { toast.error(getErrorMessage(err, 'Failed to respond to request')); diff --git a/frontend/src/components/notifications/NotificationsPage.tsx b/frontend/src/components/notifications/NotificationsPage.tsx index 6ea9c09..9abd863 100644 --- a/frontend/src/components/notifications/NotificationsPage.tsx +++ b/frontend/src/components/notifications/NotificationsPage.tsx @@ -8,6 +8,7 @@ import { useNotifications } from '@/hooks/useNotifications'; import { useConnections } from '@/hooks/useConnections'; import { Button } from '@/components/ui/button'; import { cn } from '@/lib/utils'; +import axios from 'axios'; import { getErrorMessage } from '@/lib/api'; import { ListSkeleton } from '@/components/ui/skeleton'; import type { AppNotification } from '@/types'; @@ -31,7 +32,7 @@ export default function NotificationsPage() { deleteNotification, } = useNotifications(); - const { incomingRequests, respond, isResponding, isLoadingIncoming } = useConnections(); + const { incomingRequests, respond, isResponding } = useConnections(); const queryClient = useQueryClient(); const navigate = useNavigate(); const [filter, setFilter] = useState('all'); @@ -94,8 +95,10 @@ export default function NotificationsPage() { toast.success(action === 'accept' ? 'Connection accepted' : 'Request declined'); } catch (err) { // 409 means the request was already resolved (e.g. accepted via toast) - const status = (err as any)?.response?.status; - if (status === 409) { + if (axios.isAxiosError(err) && err.response?.status === 409) { + if (!notification.is_read) { + await markRead([notification.id]).catch(() => {}); + } toast.success(action === 'accept' ? 'Connection already accepted' : 'Request already resolved'); } else { toast.error(getErrorMessage(err, 'Failed to respond')); @@ -224,23 +227,22 @@ export default function NotificationsPage() { {/* Connection request actions (inline) */} {notification.type === 'connection_request' && notification.source_id && - !notification.is_read && - (isLoadingIncoming || pendingRequestIds.has(notification.source_id)) && ( + pendingRequestIds.has(notification.source_id) && (