refactor: standardize auth cookie configuration and improve logout reliability by explicitly expiring session tokens
This commit is contained in:
@@ -84,8 +84,6 @@ export default function AgentDashboard() {
|
||||
const [testimonials, setTestimonials] = useState<{ id: string; text: string; author: string; role: string; rating: number }[]>([]);
|
||||
const [isSubmittingVerification, setIsSubmittingVerification] = useState(false);
|
||||
|
||||
const defaultImage = '/assets/demo_images/8f017153a7b4a239a4f0691234ef97dd55092282.jpg';
|
||||
|
||||
// Helper to check if avatar is an S3 key (not a full URL or local path)
|
||||
const isS3Key = (avatar: string | null | undefined): boolean => {
|
||||
if (!avatar) return false;
|
||||
@@ -220,20 +218,15 @@ export default function AgentDashboard() {
|
||||
window.dispatchEvent(new Event('profile-updated'));
|
||||
};
|
||||
|
||||
const getProfileImageUrl = () => {
|
||||
// If image failed to load, return default
|
||||
if (imageError) {
|
||||
return defaultImage;
|
||||
}
|
||||
|
||||
const getProfileImageUrl = (): string | null => {
|
||||
// If we have a presigned URL from S3, use it
|
||||
if (avatarUrl) {
|
||||
return avatarUrl;
|
||||
}
|
||||
|
||||
// Check for null, undefined, or empty string
|
||||
// No avatar set
|
||||
if (!agentProfile?.avatar || agentProfile.avatar.trim() === '') {
|
||||
return defaultImage;
|
||||
return null;
|
||||
}
|
||||
|
||||
// For relative paths (local assets), return as-is
|
||||
@@ -241,8 +234,8 @@ export default function AgentDashboard() {
|
||||
return agentProfile.avatar;
|
||||
}
|
||||
|
||||
// Default fallback
|
||||
return defaultImage;
|
||||
// No URL resolvable
|
||||
return null;
|
||||
};
|
||||
|
||||
if (loading) {
|
||||
@@ -371,22 +364,25 @@ export default function AgentDashboard() {
|
||||
{/* Profile Image */}
|
||||
<div className="relative w-[200px] lg:w-[260px]">
|
||||
<div className="w-[200px] h-[200px] lg:w-[260px] lg:h-[260px] rounded-[15px] overflow-hidden relative">
|
||||
{/* Shimmer while loading, initials only on error */}
|
||||
{imageError ? (
|
||||
<div className="absolute inset-0 bg-[#c4d9d4] flex items-center justify-center rounded-[15px]">
|
||||
<span className="font-bold text-[#00293d] text-[80px]">{agentProfile?.firstName?.[0]?.toUpperCase() || '?'}</span>
|
||||
</div>
|
||||
) : !imageLoaded ? (
|
||||
{/* Initials fallback as base layer */}
|
||||
<div className="absolute inset-0 bg-[#c4d9d4] flex items-center justify-center rounded-[15px]">
|
||||
<span className="font-bold text-[#00293d] text-[80px]">{agentProfile?.firstName?.[0]?.toUpperCase() || '?'}</span>
|
||||
</div>
|
||||
{/* Shimmer while loading (only if we have a real image to load) */}
|
||||
{getProfileImageUrl() && !imageLoaded && !imageError && (
|
||||
<div className="absolute inset-0 shimmer-loading rounded-[15px]" />
|
||||
) : null}
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
src={getProfileImageUrl()}
|
||||
alt="Profile"
|
||||
className={`absolute inset-0 w-full h-full object-cover transition-opacity duration-300 ${imageLoaded ? 'opacity-100' : 'opacity-0'}`}
|
||||
onLoad={() => setImageLoaded(true)}
|
||||
onError={() => setImageError(true)}
|
||||
/>
|
||||
)}
|
||||
{/* Image overlay — only render if we have a URL */}
|
||||
{getProfileImageUrl() && !imageError && (
|
||||
/* eslint-disable-next-line @next/next/no-img-element */
|
||||
<img
|
||||
src={getProfileImageUrl()!}
|
||||
alt="Profile"
|
||||
className={`absolute inset-0 w-full h-full object-cover transition-opacity duration-300 ${imageLoaded ? 'opacity-100' : 'opacity-0'}`}
|
||||
onLoad={() => setImageLoaded(true)}
|
||||
onError={() => setImageError(true)}
|
||||
/>
|
||||
)}
|
||||
{/* Gradient Overlay */}
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/50 via-black/20 to-transparent pointer-events-none" />
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user