feat: Improve avatar loading experience by displaying placeholders until images are fully loaded across various components.
This commit is contained in:
@@ -50,6 +50,14 @@ export function ProfileCard({
|
||||
const router = useRouter();
|
||||
const pathname = usePathname();
|
||||
const [isUnlinking, setIsUnlinking] = useState(false);
|
||||
const [showLocationModal, setShowLocationModal] = useState(false);
|
||||
|
||||
// Split location into parts and limit display
|
||||
const locationParts = location.split(',').map(s => s.trim()).filter(Boolean);
|
||||
const maxVisibleLocations = 4;
|
||||
const visibleLocations = locationParts.slice(0, maxVisibleLocations).join(', ');
|
||||
const hasMoreLocations = locationParts.length > maxVisibleLocations;
|
||||
const remainingCount = locationParts.length - maxVisibleLocations;
|
||||
|
||||
// Handle unlink click
|
||||
const handleUnlinkClick = async () => {
|
||||
@@ -113,26 +121,35 @@ export function ProfileCard({
|
||||
)}
|
||||
</div>
|
||||
<p className="text-[#00293d] text-sm mb-2 font-fractul">{title}</p>
|
||||
<div className="flex items-center justify-center lg:justify-start gap-4 text-sm text-[#00293d] font-fractul">
|
||||
<div className="flex flex-wrap items-center justify-center lg:justify-start gap-x-4 gap-y-1 text-sm text-[#00293d] font-fractul">
|
||||
<span className="flex items-center gap-1">
|
||||
<Image
|
||||
src="/assets/icons/location-pin-icon.svg"
|
||||
alt="Location"
|
||||
width={21}
|
||||
height={19}
|
||||
className="flex-shrink-0"
|
||||
/>
|
||||
<span className="text-[14px] font-bold text-[#00293D] font-serif leading-[19px]">
|
||||
{location}
|
||||
{visibleLocations}
|
||||
{hasMoreLocations && (
|
||||
<button
|
||||
onClick={() => setShowLocationModal(true)}
|
||||
className="ml-1 text-[#e58625] hover:underline cursor-pointer"
|
||||
>
|
||||
+{remainingCount} more
|
||||
</button>
|
||||
)}
|
||||
</span>
|
||||
</span>
|
||||
<span className="flex items-center gap-1">
|
||||
<span className="flex items-center gap-1 flex-shrink-0">
|
||||
<Image
|
||||
src="/assets/icons/calendar-icon.svg"
|
||||
alt="Calendar"
|
||||
width={23}
|
||||
height={21}
|
||||
/>
|
||||
<span className="text-[13px] font-medium text-[#00293D] font-serif leading-[18px]">
|
||||
<span className="text-[13px] font-medium text-[#00293D] font-serif leading-[18px] whitespace-nowrap">
|
||||
Member Since {memberSince}
|
||||
</span>
|
||||
</span>
|
||||
@@ -260,6 +277,33 @@ export function ProfileCard({
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Location Modal */}
|
||||
{showLocationModal && (
|
||||
<div className="fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4" onClick={() => setShowLocationModal(false)}>
|
||||
<div className="bg-white rounded-[20px] p-6 max-w-[400px] w-full max-h-[80vh] overflow-y-auto" onClick={e => e.stopPropagation()}>
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h3 className="font-fractul font-bold text-[18px] text-[#00293D]">Service Areas</h3>
|
||||
<button
|
||||
onClick={() => setShowLocationModal(false)}
|
||||
className="text-[#00293D]/50 hover:text-[#00293D] text-[20px] leading-none cursor-pointer"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
</div>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{locationParts.map((loc, idx) => (
|
||||
<span
|
||||
key={idx}
|
||||
className="px-3 py-1.5 bg-[#e8e8e8] rounded-[10px] text-[13px] font-serif text-[#00293D]"
|
||||
>
|
||||
{loc}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user