diff --git a/backend/app/routers/connections.py b/backend/app/routers/connections.py index aa7de36..a566f27 100644 --- a/backend/app/routers/connections.py +++ b/backend/app/routers/connections.py @@ -184,7 +184,7 @@ async def send_connection_request( raise HTTPException(status_code=409, detail="A pending request already exists") # Per-receiver cap: max 5 pending requests within 10 minutes - ten_min_ago = datetime.now() - timedelta(minutes=10) + ten_min_ago = datetime.now(timezone.utc) - timedelta(minutes=10) pending_count = await db.scalar( select(func.count()) .select_from(ConnectionRequest) @@ -375,7 +375,7 @@ async def _respond_to_request_inner( db: AsyncSession, current_user: User, ) -> RespondAcceptResponse | RespondRejectResponse: - now = datetime.now() + now = datetime.now(timezone.utc) # Atomic update — only succeeds if status is still 'pending' and receiver is current user result = await db.execute( @@ -562,7 +562,7 @@ async def cancel_request( current_user: User = Depends(get_current_user), ): """Cancel an outgoing connection request. Atomic via UPDATE...WHERE status='pending'.""" - now = datetime.now() + now = datetime.now(timezone.utc) # Atomic update — only succeeds if sender is current user and status is still pending result = await db.execute( diff --git a/frontend/src/components/connections/ConnectionSearch.tsx b/frontend/src/components/connections/ConnectionSearch.tsx index 9dcf54f..40da4ae 100644 --- a/frontend/src/components/connections/ConnectionSearch.tsx +++ b/frontend/src/components/connections/ConnectionSearch.tsx @@ -14,6 +14,7 @@ import { Button } from '@/components/ui/button'; import { Label } from '@/components/ui/label'; import { useConnections } from '@/hooks/useConnections'; import { useSettings } from '@/hooks/useSettings'; +import axios from 'axios'; import { getErrorMessage } from '@/lib/api'; interface ConnectionSearchProps { @@ -24,7 +25,7 @@ interface ConnectionSearchProps { export default function ConnectionSearch({ open, onOpenChange, personId }: ConnectionSearchProps) { const { search, isSearching, sendRequest, isSending } = useConnections(); - const { settings } = useSettings(); + const { settings, isLoading: isLoadingSettings } = useSettings(); const navigate = useNavigate(); const [umbralName, setUmbralName] = useState(''); const [found, setFound] = useState(null); @@ -39,8 +40,12 @@ export default function ConnectionSearch({ open, onOpenChange, personId }: Conne try { const result = await search(umbralName.trim()); setFound(result.found); - } catch { - setFound(false); + } catch (err) { + if (axios.isAxiosError(err) && err.response?.status === 429) { + toast.error('Too many searches — please wait a moment and try again'); + } else { + setFound(false); + } } }; @@ -76,7 +81,9 @@ export default function ConnectionSearch({ open, onOpenChange, personId }: Conne
- {!acceptConnectionsEnabled ? ( + {isLoadingSettings ? ( +
+ ) : !acceptConnectionsEnabled ? (