Enhance UI components and animations: Introduce a shimmer animation effect in globals.css, refactor FeedbackPageClient, LoginPage, RegisterPage, and AdminPanel components to utilize new UI components for improved consistency and maintainability. Update event and feedback handling in EventsPageSection and FeedbackModal, ensuring a cohesive user experience across the application.
This commit is contained in:
70
components/ui/Avatar.tsx
Normal file
70
components/ui/Avatar.tsx
Normal file
@@ -0,0 +1,70 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect, useRef } from "react";
|
||||
import { normalizeAvatarUrl } from "@/lib/avatars";
|
||||
|
||||
interface AvatarProps {
|
||||
src: string | null | undefined;
|
||||
username: string;
|
||||
size?: "xs" | "sm" | "md" | "lg" | "xl" | "2xl";
|
||||
className?: string;
|
||||
borderClassName?: string;
|
||||
fallbackText?: string;
|
||||
}
|
||||
|
||||
const sizeClasses = {
|
||||
xs: "w-6 h-6 text-[8px]",
|
||||
sm: "w-8 h-8 text-[10px]",
|
||||
md: "w-10 h-10 text-xs",
|
||||
lg: "w-16 h-16 sm:w-20 sm:h-20 text-xl sm:text-2xl",
|
||||
xl: "w-24 h-24 text-4xl",
|
||||
"2xl": "w-32 h-32 text-4xl",
|
||||
};
|
||||
|
||||
export default function Avatar({
|
||||
src,
|
||||
username,
|
||||
size = "md",
|
||||
className = "",
|
||||
borderClassName = "",
|
||||
fallbackText,
|
||||
}: AvatarProps) {
|
||||
const [avatarError, setAvatarError] = useState(false);
|
||||
const prevSrcRef = useRef<string | null | undefined>(undefined);
|
||||
|
||||
// Reset error state when src changes
|
||||
useEffect(() => {
|
||||
if (src !== prevSrcRef.current) {
|
||||
prevSrcRef.current = src;
|
||||
// Reset error when src changes to allow retry
|
||||
// eslint-disable-next-line react-hooks/set-state-in-effect
|
||||
setAvatarError(false);
|
||||
}
|
||||
}, [src]);
|
||||
|
||||
const sizeClass = sizeClasses[size];
|
||||
const normalizedSrc = normalizeAvatarUrl(src);
|
||||
const displaySrc = normalizedSrc && !avatarError ? normalizedSrc : null;
|
||||
const initial = fallbackText || username.charAt(0).toUpperCase();
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`${sizeClass} rounded-full border overflow-hidden bg-black/60 flex items-center justify-center relative ${className} ${borderClassName}`}
|
||||
>
|
||||
{displaySrc ? (
|
||||
<img
|
||||
key={displaySrc}
|
||||
src={displaySrc}
|
||||
alt={username}
|
||||
className="w-full h-full object-cover absolute inset-0"
|
||||
onError={() => setAvatarError(true)}
|
||||
/>
|
||||
) : null}
|
||||
<span
|
||||
className={`text-pixel-gold font-bold ${displaySrc ? "hidden" : ""}`}
|
||||
>
|
||||
{initial}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user