refactor: replace team member section with feature cards and add associated SVG icons

This commit is contained in:
pradeepkumar
2026-04-15 07:15:56 +05:30
parent 3897a47756
commit 5e787f2720
5 changed files with 85 additions and 53 deletions

View File

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="36" height="36" viewBox="0 0 24 24" fill="none" stroke="#e58625" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
<path d="M12 2l8 4v6c0 5-3.5 9-8 10-4.5-1-8-5-8-10V6l8-4z"/>
<path d="M9 12l2 2 4-4"/>
</svg>

After

Width:  |  Height:  |  Size: 277 B

View File

@@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" width="36" height="36" viewBox="0 0 24 24" fill="none" stroke="#e58625" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
<path d="M12 3v18"/>
<path d="M6 21h12"/>
<path d="M5 7l-3 7a4 4 0 0 0 6 0l-3-7z"/>
<path d="M19 7l-3 7a4 4 0 0 0 6 0l-3-7z"/>
<path d="M5 7h14"/>
</svg>

After

Width:  |  Height:  |  Size: 343 B

View File

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="36" height="36" viewBox="0 0 24 24" fill="none" stroke="#e58625" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
<path d="M3 4h18l-7 9v7l-4-2v-5L3 4z"/>
<line x1="3" y1="21" x2="21" y2="3"/>
</svg>

After

Width:  |  Height:  |  Size: 268 B

View File

@@ -55,10 +55,14 @@ export default function AboutPage() {
} }
break; break;
case 'team': case 'team':
if (Array.isArray(c.members) && c.members.length > 0) { if (c.title || c.subtitle || c.intro || (Array.isArray(c.cards) && c.cards.length > 0)) {
const teamData = c as unknown as AboutTeamContent; const teamData = c as unknown as AboutTeamContent;
for (const member of teamData.members) { if (Array.isArray(teamData.cards)) {
member.imageUrl = await resolveImageUrl(member.imageUrl); for (const card of teamData.cards) {
card.iconPath = await resolveImageUrl(card.iconPath);
}
} else {
teamData.cards = [];
} }
setTeam(teamData); setTeam(teamData);
} }
@@ -196,24 +200,32 @@ export default function AboutPage() {
)} )}
{/* Team Section */} {/* Team Section */}
{team && team.members.length > 0 && ( {team && (team.title || team.subtitle || team.intro || team.cards.length > 0) && (
<section className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 pb-16 lg:pb-20"> <section className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 pb-16 lg:pb-20">
<div className="text-center mb-12"> <div className="text-center mb-12">
<h2 className="font-fractul font-bold text-[30px] text-[#00293d] mb-3"> {team.title && (
{team.title} <h2 className="font-fractul font-bold text-[30px] text-[#00293d] mb-3">
</h2> {team.title}
<p className="font-serif text-[14px] text-[#00293d] max-w-[471px] mx-auto"> </h2>
{team.subtitle} )}
</p> {team.subtitle && (
<p className="font-serif text-[14px] text-[#00293d] max-w-[600px] mx-auto mt-4"> <p className="font-serif text-[14px] text-[#00293d] max-w-[471px] mx-auto">
RE-Quest is a unique platform in real estate where no agent can pay to be pushed to the top. RE-Quest elevates ethical, skilled, service-oriented professionals who genuinely care about their clients with no sponsorship tiers. With RE-Quest you receive: {team.subtitle}
</p> </p>
</div> )}
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 max-w-4xl mx-auto"> {team.intro && (
{team.members.map((member, index) => ( <p className="font-serif text-[14px] text-[#00293d] max-w-[600px] mx-auto mt-4 whitespace-pre-line">
<TeamCard key={index} member={member} /> {team.intro}
))} </p>
)}
</div> </div>
{team.cards.length > 0 && (
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 max-w-5xl mx-auto items-stretch">
{team.cards.map((card, index) => (
<TeamCard key={index} card={card} />
))}
</div>
)}
</section> </section>
)} )}
@@ -334,12 +346,14 @@ function AboutSkeleton() {
<div className="shimmer-loading h-[36px] w-[350px] max-w-full rounded-lg" /> <div className="shimmer-loading h-[36px] w-[350px] max-w-full rounded-lg" />
<div className="shimmer-loading h-[14px] w-[400px] max-w-full rounded-lg" /> <div className="shimmer-loading h-[14px] w-[400px] max-w-full rounded-lg" />
</div> </div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 max-w-4xl mx-auto"> <div className="grid grid-cols-1 md:grid-cols-3 gap-6 max-w-5xl mx-auto">
{[1, 2, 3].map((i) => ( {[1, 2, 3].map((i) => (
<div key={i} className="border border-[#00293d]/10 rounded-[15px] p-4 flex flex-col items-center gap-3"> <div key={i} className="border border-[#00293d]/10 rounded-[15px] p-6 flex flex-col items-center gap-3">
<div className="shimmer-loading w-full h-[211px] rounded-[15px]" /> <div className="shimmer-loading w-[36px] h-[36px] rounded-full" />
<div className="shimmer-loading h-[14px] w-[80px] rounded-lg" /> <div className="shimmer-loading h-[16px] w-[140px] rounded-lg" />
<div className="shimmer-loading h-[12px] w-[100px] rounded-lg" /> <div className="shimmer-loading h-[12px] w-full rounded-lg" />
<div className="shimmer-loading h-[12px] w-[90%] rounded-lg" />
<div className="shimmer-loading h-[12px] w-[80%] rounded-lg" />
</div> </div>
))} ))}
</div> </div>
@@ -436,38 +450,40 @@ function FeatureCard({ feature }: { feature: AboutFeaturesContent['features'][nu
// Team card — shimmer image while loading // Team card — shimmer image while loading
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
function TeamCard({ member }: { member: AboutTeamContent['members'][number] }) { function TeamCard({ card }: { card: AboutTeamContent['cards'][number] }) {
const [imgStatus, setImgStatus] = useState<'loading' | 'loaded' | 'error'>( const [iconStatus, setIconStatus] = useState<'loading' | 'loaded' | 'error'>(
member.imageUrl ? 'loading' : 'error' card.iconPath ? 'loading' : 'error'
); );
useEffect(() => { useEffect(() => {
setImgStatus(member.imageUrl ? 'loading' : 'error'); setIconStatus(card.iconPath ? 'loading' : 'error');
}, [member.imageUrl]); }, [card.iconPath]);
return ( return (
<div className="border border-[#00293d]/10 rounded-[15px] p-4 text-center"> <div className="border border-[#00293d]/10 rounded-[15px] p-6 text-center h-full flex flex-col">
<div className="w-full h-[211px] rounded-[15px] overflow-hidden mb-4 border border-[#00293d]/10 bg-gray-50"> <div className="flex items-center justify-center mb-4 h-[36px]">
{imgStatus === 'loading' && ( <div className="relative w-[36px] h-[36px]">
<div className="w-full h-full shimmer-loading rounded-[15px]" /> {iconStatus === 'loading' && (
)} <div className="absolute inset-0 rounded-full shimmer-loading" />
{member.imageUrl && imgStatus !== 'error' && ( )}
/* eslint-disable-next-line @next/next/no-img-element */ {card.iconPath && iconStatus !== 'error' && (
<img /* eslint-disable-next-line @next/next/no-img-element */
ref={(el) => { if (el?.complete) setImgStatus(el.naturalWidth > 0 ? 'loaded' : 'error'); }} <img
src={member.imageUrl} ref={(el) => { if (el?.complete) setIconStatus(el.naturalWidth > 0 ? 'loaded' : 'error'); }}
alt={member.name} src={card.iconPath}
className={`w-full h-full object-cover transition-opacity duration-300 ${imgStatus === 'loaded' ? 'opacity-100' : 'opacity-0'}`} alt=""
onLoad={() => setImgStatus('loaded')} className={`w-[36px] h-[36px] object-contain transition-opacity duration-300 ${iconStatus === 'loaded' ? 'opacity-100' : 'opacity-0'}`}
onError={() => setImgStatus('error')} onLoad={() => setIconStatus('loaded')}
/> onError={() => setIconStatus('error')}
)} />
)}
</div>
</div> </div>
<h3 className="font-fractul font-bold text-[14px] text-black"> <h3 className="font-fractul font-bold text-[16px] text-[#00293d] mb-3">
{member.name} {card.title}
</h3> </h3>
<p className="font-fractul font-light text-[14px] text-black"> <p className="font-serif text-[14px] text-[#00293d] leading-relaxed">
{member.role} {card.description}
</p> </p>
</div> </div>
); );

View File

@@ -95,16 +95,17 @@ export interface AboutFeaturesContent {
features: AboutFeatureItem[]; features: AboutFeatureItem[];
} }
export interface AboutTeamMember { export interface AboutTeamCard {
name: string; title: string;
role: string; description: string;
imageUrl: string; iconPath: string;
} }
export interface AboutTeamContent { export interface AboutTeamContent {
title: string; title: string;
subtitle: string; subtitle: string;
members: AboutTeamMember[]; intro: string;
cards: AboutTeamCard[];
} }
export interface AboutCtaContent { export interface AboutCtaContent {