feat: Implement useImageStatus hook and enhance image loading status handling across various components to address cached images and loading timeouts.
This commit is contained in:
@@ -41,6 +41,7 @@ export function ConnectionCard({
|
||||
)}
|
||||
{avatar && !isPlaceholder && (
|
||||
<img
|
||||
ref={(el) => { if (el?.complete && el.naturalWidth > 0) setAvatarLoaded(true); }}
|
||||
src={avatar}
|
||||
alt={name}
|
||||
className={`absolute inset-0 w-full h-full object-cover rounded-full transition-opacity duration-300 ${avatarLoaded ? 'opacity-100' : 'opacity-0'}`}
|
||||
|
||||
@@ -55,6 +55,7 @@ export function InvitationCard({
|
||||
)}
|
||||
{avatar && !isPlaceholder && (
|
||||
<img
|
||||
ref={(el) => { if (el?.complete && el.naturalWidth > 0) setAvatarLoaded(true); }}
|
||||
src={avatar}
|
||||
alt={name}
|
||||
className={`absolute inset-0 w-full h-full object-cover rounded-full transition-opacity duration-300 ${avatarLoaded ? 'opacity-100' : 'opacity-0'}`}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { signIn } from 'next-auth/react';
|
||||
import Link from 'next/link';
|
||||
@@ -15,6 +15,12 @@ export default function LoginPage() {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [userType, setUserType] = useState<'USER' | 'ADMIN'>('USER');
|
||||
|
||||
// Clear logout flags on mount so API calls aren't blocked after redirect from logout
|
||||
useEffect(() => {
|
||||
localStorage.removeItem('isLoggingOut');
|
||||
resetLogoutState();
|
||||
}, []);
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setLoading(true);
|
||||
|
||||
@@ -291,6 +291,7 @@ export default function AgentProfileView() {
|
||||
)}
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
ref={(el) => { if (el?.complete) { if (el.naturalWidth > 0) setImageLoaded(true); else setImageError(true); } }}
|
||||
src={getProfileImageUrl()!}
|
||||
alt="Profile"
|
||||
className={`w-full h-full object-cover transition-opacity duration-300 ${imageLoaded ? 'opacity-100' : 'opacity-0'}`}
|
||||
|
||||
@@ -77,6 +77,7 @@ function ProfileImage({ src, alt, className }: { src: string | null; alt: string
|
||||
{src && status !== 'error' ? (
|
||||
/* eslint-disable-next-line @next/next/no-img-element */
|
||||
<img
|
||||
ref={(el) => { if (el?.complete) setStatus(el.naturalWidth > 0 ? 'loaded' : 'error'); }}
|
||||
src={src}
|
||||
alt={alt}
|
||||
className={`w-full h-full object-cover transition-opacity duration-300 ${status === 'loaded' ? 'opacity-100' : 'opacity-0'}`}
|
||||
|
||||
@@ -360,6 +360,7 @@ function SmartImage({
|
||||
)}
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
ref={(el) => { if (el?.complete) setStatus(el.naturalWidth > 0 ? 'loaded' : 'error'); }}
|
||||
src={src}
|
||||
alt={alt}
|
||||
className={`${className || ''} transition-opacity duration-300 ${status === 'loaded' ? 'opacity-100' : 'opacity-0'}`}
|
||||
@@ -393,6 +394,7 @@ function FeatureCard({ feature }: { feature: AboutFeaturesContent['features'][nu
|
||||
{feature.iconPath && iconStatus !== 'error' && (
|
||||
/* eslint-disable-next-line @next/next/no-img-element */
|
||||
<img
|
||||
ref={(el) => { if (el?.complete) setIconStatus(el.naturalWidth > 0 ? 'loaded' : 'error'); }}
|
||||
src={feature.iconPath}
|
||||
alt=""
|
||||
className={`w-[35px] h-[35px] object-contain transition-opacity duration-300 ${iconStatus === 'loaded' ? 'opacity-100' : 'opacity-0'}`}
|
||||
@@ -434,6 +436,7 @@ function TeamCard({ member }: { member: AboutTeamContent['members'][number] }) {
|
||||
{member.imageUrl && imgStatus !== 'error' && (
|
||||
/* eslint-disable-next-line @next/next/no-img-element */
|
||||
<img
|
||||
ref={(el) => { if (el?.complete) setImgStatus(el.naturalWidth > 0 ? 'loaded' : 'error'); }}
|
||||
src={member.imageUrl}
|
||||
alt={member.name}
|
||||
className={`w-full h-full object-cover transition-opacity duration-300 ${imgStatus === 'loaded' ? 'opacity-100' : 'opacity-0'}`}
|
||||
|
||||
@@ -35,6 +35,9 @@ export default function LogoutPage() {
|
||||
// Delete cookies again after signOut in case signOut recreated any
|
||||
await clearAuthCookies();
|
||||
|
||||
// Clear the logout flag before redirecting so it doesn't block API calls on public pages
|
||||
localStorage.removeItem('isLoggingOut');
|
||||
|
||||
// Redirect to login immediately
|
||||
window.location.href = '/login';
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user