refactor: remove hardcoded default content from components and update dashboard to conditionally render sections after CMS data loading

This commit is contained in:
pradeepkumar
2026-03-30 12:07:20 +05:30
parent 75994c09bd
commit daa0e3ff67
3 changed files with 53 additions and 83 deletions

View File

@@ -10,27 +10,34 @@ import type { HeroContent, FeaturesContent, TopProfessionalsContent, Testimonial
export default function UserDashboard() { export default function UserDashboard() {
const [cmsData, setCmsData] = useState<Record<string, unknown>>({}); const [cmsData, setCmsData] = useState<Record<string, unknown>>({});
const [cmsLoaded, setCmsLoaded] = useState(false);
useEffect(() => { useEffect(() => {
const fetchCms = async () => { const fetchCms = async () => {
const sections = await cmsService.getPageContent('landing'); try {
const data: Record<string, unknown> = {}; const sections = await cmsService.getPageContent('landing');
for (const s of sections) { const data: Record<string, unknown> = {};
const content = s.content as Record<string, unknown>; for (const s of sections) {
// Resolve S3 keys in image fields const content = s.content as Record<string, unknown>;
if (s.sectionKey === 'features' && Array.isArray(content.features)) { // Resolve S3 keys in image fields
for (const feat of content.features as { iconPath?: string }[]) { if (s.sectionKey === 'features' && Array.isArray(content.features)) {
if (feat.iconPath) feat.iconPath = await resolveImageUrl(feat.iconPath); for (const feat of content.features as { iconPath?: string }[]) {
if (feat.iconPath) feat.iconPath = await resolveImageUrl(feat.iconPath);
}
} }
} if (s.sectionKey === 'testimonials' && Array.isArray(content.stats)) {
if (s.sectionKey === 'testimonials' && Array.isArray(content.stats)) { for (const stat of content.stats as { iconPath?: string }[]) {
for (const stat of content.stats as { iconPath?: string }[]) { if (stat.iconPath) stat.iconPath = await resolveImageUrl(stat.iconPath);
if (stat.iconPath) stat.iconPath = await resolveImageUrl(stat.iconPath); }
} }
data[s.sectionKey] = content;
} }
data[s.sectionKey] = content; setCmsData(data);
} catch {
// Use default content on error
} finally {
setCmsLoaded(true);
} }
setCmsData(data);
}; };
fetchCms(); fetchCms();
}, []); }, []);
@@ -38,7 +45,7 @@ export default function UserDashboard() {
return ( return (
<div> <div>
<HeroSection content={cmsData.hero as HeroContent | undefined} /> <HeroSection content={cmsData.hero as HeroContent | undefined} />
<FeaturesSection content={cmsData.features as FeaturesContent | undefined} /> {cmsLoaded && <FeaturesSection content={cmsData.features as FeaturesContent | undefined} />}
<TopProfessionals content={cmsData.topProfessionals as TopProfessionalsContent | undefined} /> <TopProfessionals content={cmsData.topProfessionals as TopProfessionalsContent | undefined} />
<TestimonialsSection content={cmsData.testimonials as TestimonialsContent | undefined} /> <TestimonialsSection content={cmsData.testimonials as TestimonialsContent | undefined} />
</div> </div>

View File

@@ -5,37 +5,6 @@ import Image from 'next/image';
import type { FeaturesContent, FeaturedAgentItem } from '@/types/cms'; import type { FeaturesContent, FeaturedAgentItem } from '@/types/cms';
import { resolveImageUrl } from '@/services/cms.service'; import { resolveImageUrl } from '@/services/cms.service';
const defaultContent: FeaturesContent = {
title: 'Find Trusted Real Estate Professionals On Demand',
subtitle: 'Quickly connect with the right agents exactly when you need them.',
features: [
{
iconPath: '/assets/icons/hourglass-icon.svg',
title: 'Hire Quickly',
description: 'Connect with experienced local real estate agents who match your needs and preferences. Our simple process helps you get started quickly and move forward without delays or unnecessary complexity.',
},
{
iconPath: '/assets/icons/verified-badge-icon.svg',
title: 'Verified Agents',
description: 'All agents are carefully identity-verified and background-checked to ensure trust and safety. You can confidently work with professionals who meet quality and reliability standards.',
},
{
iconPath: '/assets/icons/star-orange-icon.svg',
title: 'Top Rated',
description: 'Work with highly rated agents known for strong expertise and positive client feedback. Their consistent performance helps you make informed and confident property decisions.',
},
{
iconPath: '/assets/icons/trusted-people-icon.svg',
title: 'Trusted by Thousands',
description: 'Thousands of buyers, sellers, and renters trust our platform to find reliable agents. Our professionals help people navigate property journeys with confidence and ease.',
},
],
featuredAgents: [
{ name: 'Anderson', role: 'Rental & Investment Consultant', rating: '4.9', location: 'New York', experience: '7+ years in the real estate industry.', imageUrl: '/assets/images/agent-anderson.jpg' },
{ name: 'Deepak', role: 'Rental & Investment Consultant', rating: '4.9', location: 'New York', experience: '7+ years in the real estate industry.', imageUrl: '/assets/images/agent-deepak.jpg' },
{ name: 'Daniel', role: 'Rental & Investment Consultant', rating: '4.9', location: 'New York', experience: '7+ years in the real estate industry.', imageUrl: '/assets/images/agent-daniel.jpg' },
],
};
function AgentCard({ agent, className = '' }: { agent: FeaturedAgentItem; className?: string }) { function AgentCard({ agent, className = '' }: { agent: FeaturedAgentItem; className?: string }) {
const [imgLoaded, setImgLoaded] = useState(false); const [imgLoaded, setImgLoaded] = useState(false);
@@ -100,7 +69,8 @@ function AgentCard({ agent, className = '' }: { agent: FeaturedAgentItem; classN
} }
export function FeaturesSection({ content }: { content?: FeaturesContent }) { export function FeaturesSection({ content }: { content?: FeaturesContent }) {
const data = content ?? defaultContent; if (!content) return null;
const data = content;
const agents = data.featuredAgents || []; const agents = data.featuredAgents || [];
const [activeCard, setActiveCard] = useState(0); const [activeCard, setActiveCard] = useState(0);

View File

@@ -3,32 +3,6 @@
import Image from 'next/image'; import Image from 'next/image';
import type { TestimonialsContent } from '@/types/cms'; import type { TestimonialsContent } from '@/types/cms';
const defaultTestimonials = [
{
id: '1',
rating: 5,
title: 'I have been working with Lorem ..',
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean commodo ligula eget dolor. Sed dignissim, nisl eget tincidunt vulputate, lacus justo bibendum ipsum, vitae tempus risus lorem at nunc. Integer sed arcu vitae risus feugiat vehicula. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.',
author: 'Conor Kenney',
role: 'Chief Operations Officer',
},
{
id: '2',
rating: 5,
title: 'I have been working with Lorem ..',
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean commodo ligula eget dolor. Sed dignissim, nisl eget tincidunt vulputate, lacus justo bibendum ipsum, vitae tempus risus lorem at nunc. Integer sed arcu vitae risus feugiat vehicula. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.',
author: 'Conor Kenney',
role: 'Chief Operations Officer',
},
{
id: '3',
rating: 5,
title: 'I have been working with Lorem ..',
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean commodo ligula eget dolor. Sed dignissim, nisl eget tincidunt vulputate, lacus justo bibendum ipsum, vitae tempus risus lorem at nunc. Integer sed arcu vitae risus feugiat vehicula. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.',
author: 'Conor Kenney',
role: 'Chief Operations Officer',
},
];
interface TestimonialCardProps { interface TestimonialCardProps {
title: string; title: string;
@@ -87,21 +61,40 @@ function TestimonialCard({ title, content, author, role, rating }: TestimonialCa
); );
} }
const defaultTestimonials = [
{
id: '1',
rating: 5,
title: 'I have been working with Lorem ..',
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean commodo ligula eget dolor. Sed dignissim, nisl eget tincidunt vulputate.',
author: 'Conor Kenney',
role: 'Chief Operations Officer',
},
{
id: '2',
rating: 5,
title: 'I have been working with Lorem ..',
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean commodo ligula eget dolor. Sed dignissim, nisl eget tincidunt vulputate.',
author: 'Conor Kenney',
role: 'Chief Operations Officer',
},
{
id: '3',
rating: 5,
title: 'I have been working with Lorem ..',
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean commodo ligula eget dolor. Sed dignissim, nisl eget tincidunt vulputate.',
author: 'Conor Kenney',
role: 'Chief Operations Officer',
},
];
const defaultContent: TestimonialsContent = { const defaultContent: TestimonialsContent = {
title: "Our Clients' Trust Is Our Foundation", title: "Our Clients' Trust Is Our Foundation",
subtitle: 'We help buyers, sellers, and investors close successful real estate deals with confidence in every transaction.', subtitle: 'We help buyers, sellers, and investors close successful real estate deals with confidence in every transaction.',
ratingInfo: 'Clients rate our real estate services 4.9 out of 5 on average, based on recent client reviews.', ratingInfo: 'Clients rate our real estate services 4.9 out of 5 on average, based on recent client reviews.',
stats: [ stats: [
{ { iconPath: '/assets/icons/cities-icon.svg', boldText: '25+ Cities &', normalText: 'neighborhoods served' },
iconPath: '/assets/icons/cities-icon.svg', { iconPath: '/assets/icons/properties-icon.svg', boldText: '1,000+ Properties', normalText: 'bought and sold for our clients.' },
boldText: '25+ Cities &',
normalText: 'neighborhoods served',
},
{
iconPath: '/assets/icons/properties-icon.svg',
boldText: '1,000+ Properties',
normalText: 'bought and sold for our clients.',
},
], ],
testimonials: defaultTestimonials, testimonials: defaultTestimonials,
}; };