402 lines
12 KiB
TypeScript
402 lines
12 KiB
TypeScript
/**
|
|
* Content Components Example
|
|
* Demonstrates how to use the content components with WordPress data
|
|
*/
|
|
|
|
import React from 'react';
|
|
import {
|
|
Hero,
|
|
Section,
|
|
SectionHeader,
|
|
SectionContent,
|
|
SectionGrid,
|
|
FeaturedImage,
|
|
ContentRenderer,
|
|
Breadcrumbs,
|
|
ContentBlock,
|
|
RichText,
|
|
Avatar,
|
|
ImageGallery,
|
|
} from './index';
|
|
import { Button, Card, CardHeader, CardBody, CardFooter, Grid } from '../ui';
|
|
import { Page, Post, Product, getMediaById } from '../../lib/data';
|
|
|
|
// Example: Hero component with WordPress data
|
|
export const ExampleHero: React.FC<{
|
|
page: Page;
|
|
}> = ({ page }) => {
|
|
const featuredMedia = page.featuredImage ? getMediaById(page.featuredImage) : null;
|
|
|
|
return (
|
|
<Hero
|
|
title={page.title}
|
|
subtitle={page.excerptHtml ? page.excerptHtml.replace(/<[^>]*>/g, '') : undefined}
|
|
backgroundImage={featuredMedia?.localPath}
|
|
backgroundAlt={featuredMedia?.alt || page.title}
|
|
height="lg"
|
|
variant="dark"
|
|
overlay={true}
|
|
overlayOpacity={0.6}
|
|
ctaText="Learn More"
|
|
ctaLink="#content"
|
|
/>
|
|
);
|
|
};
|
|
|
|
// Example: Section component for content blocks
|
|
export const ExampleSection: React.FC<{
|
|
title: string;
|
|
content: string;
|
|
background?: 'default' | 'light' | 'dark';
|
|
}> = ({ title, content, background = 'default' }) => {
|
|
return (
|
|
<Section background={background} padding="xl">
|
|
<SectionHeader title={title} align="center" />
|
|
<SectionContent>
|
|
<ContentRenderer content={content} />
|
|
</SectionContent>
|
|
</Section>
|
|
);
|
|
};
|
|
|
|
// Example: Featured content grid
|
|
export const ExampleContentGrid: React.FC<{
|
|
posts: Post[];
|
|
}> = ({ posts }) => {
|
|
return (
|
|
<Section background="light" padding="xl">
|
|
<SectionHeader
|
|
title="Latest News"
|
|
subtitle="Stay updated with our latest developments"
|
|
align="center"
|
|
/>
|
|
<SectionGrid cols={3} gap="md">
|
|
{posts.map((post) => {
|
|
const featuredMedia = post.featuredImage ? getMediaById(post.featuredImage) : null;
|
|
return (
|
|
<Card key={post.id} variant="elevated">
|
|
{featuredMedia && (
|
|
<div className="relative h-48">
|
|
<FeaturedImage
|
|
src={featuredMedia.localPath}
|
|
alt={featuredMedia.alt || post.title}
|
|
size="full"
|
|
aspectRatio="16:9"
|
|
/>
|
|
</div>
|
|
)}
|
|
<CardHeader>
|
|
<h3 className="text-xl font-bold">{post.title}</h3>
|
|
<small className="text-gray-500">
|
|
{new Date(post.datePublished).toLocaleDateString()}
|
|
</small>
|
|
</CardHeader>
|
|
<CardBody>
|
|
<RichText
|
|
html={post.excerptHtml}
|
|
className="text-gray-600 line-clamp-3"
|
|
/>
|
|
</CardBody>
|
|
<CardFooter>
|
|
<Button variant="primary" size="sm">
|
|
Read More
|
|
</Button>
|
|
</CardFooter>
|
|
</Card>
|
|
);
|
|
})}
|
|
</SectionGrid>
|
|
</Section>
|
|
);
|
|
};
|
|
|
|
// Example: Product showcase
|
|
export const ExampleProductShowcase: React.FC<{
|
|
product: Product;
|
|
}> = ({ product }) => {
|
|
const images = product.images.map((img) => ({
|
|
src: img,
|
|
alt: product.name,
|
|
}));
|
|
|
|
return (
|
|
<Section padding="xl">
|
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
|
{/* Product Images */}
|
|
<div>
|
|
{product.featuredImage && (
|
|
<FeaturedImage
|
|
src={product.featuredImage}
|
|
alt={product.name}
|
|
size="full"
|
|
aspectRatio="4:3"
|
|
priority
|
|
/>
|
|
)}
|
|
{images.length > 1 && (
|
|
<div className="mt-4">
|
|
<ImageGallery images={images.slice(1)} cols={3} />
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* Product Info */}
|
|
<div className="space-y-6">
|
|
<div>
|
|
<h1 className="text-3xl md:text-4xl font-bold mb-2">{product.name}</h1>
|
|
<div className="flex items-center gap-3">
|
|
<span className="text-2xl font-bold text-primary">
|
|
{product.regularPrice} {product.currency}
|
|
</span>
|
|
{product.salePrice && (
|
|
<span className="text-lg text-gray-500 line-through">
|
|
{product.salePrice} {product.currency}
|
|
</span>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
<RichText html={product.descriptionHtml} />
|
|
|
|
{product.categories.length > 0 && (
|
|
<div>
|
|
<strong>Categories:</strong>
|
|
<div className="flex flex-wrap gap-2 mt-2">
|
|
{product.categories.map((cat) => (
|
|
<span key={cat.id} className="px-3 py-1 bg-gray-100 rounded-full text-sm">
|
|
{cat.name}
|
|
</span>
|
|
))}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
<div className="flex gap-3">
|
|
<Button variant="primary" size="lg">
|
|
Add to Cart
|
|
</Button>
|
|
<Button variant="outline" size="lg">
|
|
Contact Sales
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</Section>
|
|
);
|
|
};
|
|
|
|
// Example: Breadcrumbs with WordPress page structure
|
|
export const ExampleBreadcrumbs: React.FC<{
|
|
page: Page;
|
|
ancestors?: Page[];
|
|
}> = ({ page, ancestors = [] }) => {
|
|
const items = [
|
|
...ancestors.map((p) => ({
|
|
label: p.title,
|
|
href: `/${p.locale}${p.path}`,
|
|
})),
|
|
{
|
|
label: page.title,
|
|
},
|
|
];
|
|
|
|
return <Breadcrumbs items={items} />;
|
|
};
|
|
|
|
// Example: Full page layout with all components
|
|
export const ExamplePageLayout: React.FC<{
|
|
page: Page;
|
|
relatedPosts?: Post[];
|
|
}> = ({ page, relatedPosts = [] }) => {
|
|
const featuredMedia = page.featuredImage ? getMediaById(page.featuredImage) : null;
|
|
|
|
return (
|
|
<div className="min-h-screen">
|
|
{/* Hero Section */}
|
|
<Hero
|
|
title={page.title}
|
|
subtitle={page.excerptHtml ? page.excerptHtml.replace(/<[^>]*>/g, '') : undefined}
|
|
backgroundImage={featuredMedia?.localPath}
|
|
backgroundAlt={featuredMedia?.alt || page.title}
|
|
height="md"
|
|
variant="dark"
|
|
overlay
|
|
overlayOpacity={0.5}
|
|
/>
|
|
|
|
{/* Breadcrumbs */}
|
|
<Breadcrumbs
|
|
items={[
|
|
{ label: 'Home', href: '/' },
|
|
{ label: page.title },
|
|
]}
|
|
/>
|
|
|
|
{/* Main Content */}
|
|
<Section padding="xl">
|
|
<div className="max-w-4xl mx-auto">
|
|
<ContentRenderer content={page.contentHtml} />
|
|
</div>
|
|
</Section>
|
|
|
|
{/* Related Posts */}
|
|
{relatedPosts.length > 0 && (
|
|
<Section background="light" padding="xl">
|
|
<SectionHeader title="Related Content" align="center" />
|
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
|
{relatedPosts.map((post) => (
|
|
<Card key={post.id} variant="bordered">
|
|
<CardBody>
|
|
<h3 className="text-lg font-bold mb-2">{post.title}</h3>
|
|
<RichText
|
|
html={post.excerptHtml}
|
|
className="text-gray-600 text-sm line-clamp-2"
|
|
/>
|
|
</CardBody>
|
|
<CardFooter>
|
|
<Button variant="ghost" size="sm">
|
|
Read More
|
|
</Button>
|
|
</CardFooter>
|
|
</Card>
|
|
))}
|
|
</div>
|
|
</Section>
|
|
)}
|
|
|
|
{/* CTA Section */}
|
|
<Section background="primary" padding="xl">
|
|
<div className="text-center text-white">
|
|
<h2 className="text-3xl font-bold mb-4">Ready to Get Started?</h2>
|
|
<p className="text-xl mb-6 opacity-90">
|
|
Contact us today for more information about our products and services.
|
|
</p>
|
|
<div className="flex justify-center gap-3">
|
|
<Button variant="secondary" size="lg">
|
|
Contact Us
|
|
</Button>
|
|
<Button variant="ghost" size="lg" className="text-white border-white hover:bg-white/10">
|
|
View Products
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</Section>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
// Example: Blog post layout
|
|
export const ExampleBlogPost: React.FC<{
|
|
post: Post;
|
|
author?: {
|
|
name: string;
|
|
avatar?: string;
|
|
};
|
|
}> = ({ post, author }) => {
|
|
const featuredMedia = post.featuredImage ? getMediaById(post.featuredImage) : null;
|
|
|
|
return (
|
|
<article className="max-w-4xl mx-auto">
|
|
{/* Header */}
|
|
<header className="mb-8 text-center">
|
|
<h1 className="text-4xl md:text-5xl font-bold mb-4">{post.title}</h1>
|
|
<div className="flex items-center justify-center gap-4 text-gray-600">
|
|
<time dateTime={post.datePublished}>
|
|
{new Date(post.datePublished).toLocaleDateString('en-US', {
|
|
year: 'numeric',
|
|
month: 'long',
|
|
day: 'numeric',
|
|
})}
|
|
</time>
|
|
{author && (
|
|
<div className="flex items-center gap-2">
|
|
{author.avatar && <Avatar src={author.avatar} alt={author.name} size="sm" />}
|
|
<span>{author.name}</span>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</header>
|
|
|
|
{/* Featured Image */}
|
|
{featuredMedia && (
|
|
<div className="mb-8">
|
|
<FeaturedImage
|
|
src={featuredMedia.localPath}
|
|
alt={featuredMedia.alt || post.title}
|
|
size="full"
|
|
aspectRatio="16:9"
|
|
priority
|
|
/>
|
|
</div>
|
|
)}
|
|
|
|
{/* Content */}
|
|
<div className="prose prose-lg max-w-none">
|
|
<ContentRenderer content={post.contentHtml} />
|
|
</div>
|
|
</article>
|
|
);
|
|
};
|
|
|
|
// Example: Product category grid
|
|
export const ExampleProductGrid: React.FC<{
|
|
products: Product[];
|
|
category?: string;
|
|
}> = ({ products, category }) => {
|
|
return (
|
|
<Section padding="xl">
|
|
<SectionHeader
|
|
title={category ? `${category} Products` : 'Our Products'}
|
|
subtitle="Explore our range of high-quality products"
|
|
align="center"
|
|
/>
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
{products.map((product) => {
|
|
const image = product.featuredImage || product.images[0];
|
|
return (
|
|
<Card key={product.id} variant="elevated" className="flex flex-col">
|
|
{image && (
|
|
<div className="relative">
|
|
<FeaturedImage
|
|
src={image}
|
|
alt={product.name}
|
|
size="full"
|
|
aspectRatio="4:3"
|
|
/>
|
|
</div>
|
|
)}
|
|
<CardHeader>
|
|
<h3 className="text-lg font-bold">{product.name}</h3>
|
|
<div className="text-primary font-semibold text-lg">
|
|
{product.regularPrice} {product.currency}
|
|
</div>
|
|
</CardHeader>
|
|
<CardBody>
|
|
<RichText
|
|
html={product.shortDescriptionHtml}
|
|
className="text-gray-600 text-sm line-clamp-2"
|
|
/>
|
|
</CardBody>
|
|
<CardFooter className="mt-auto">
|
|
<Button variant="primary" size="sm" fullWidth>
|
|
View Details
|
|
</Button>
|
|
</CardFooter>
|
|
</Card>
|
|
);
|
|
})}
|
|
</div>
|
|
</Section>
|
|
);
|
|
};
|
|
|
|
export default {
|
|
ExampleHero,
|
|
ExampleSection,
|
|
ExampleContentGrid,
|
|
ExampleProductShowcase,
|
|
ExampleBreadcrumbs,
|
|
ExamplePageLayout,
|
|
ExampleBlogPost,
|
|
ExampleProductGrid,
|
|
}; |