Initial commit
This commit is contained in:
309
src/pages/HomePage.tsx
Normal file
309
src/pages/HomePage.tsx
Normal file
@@ -0,0 +1,309 @@
|
||||
import AboutFeaturesSplit from '@/components/sections/about/AboutFeaturesSplit';
|
||||
import ContactCta from '@/components/sections/contact/ContactCta';
|
||||
import FaqSimple from '@/components/sections/faq/FaqSimple';
|
||||
import FeaturesMediaCarousel from '@/components/sections/features/FeaturesMediaCarousel';
|
||||
import FeaturesRevealCardsBento from '@/components/sections/features/FeaturesRevealCardsBento';
|
||||
import HeroBillboardCarousel from '@/components/sections/hero/HeroBillboardCarousel';
|
||||
import MetricsMediaCards from '@/components/sections/metrics/MetricsMediaCards';
|
||||
import PricingMediaCards from '@/components/sections/pricing/PricingMediaCards';
|
||||
import { ShieldCheck, TrendingUp, Zap } from "lucide-react";
|
||||
import SectionErrorBoundary from "@/components/ui/SectionErrorBoundary";
|
||||
|
||||
export default function HomePage() {
|
||||
return (
|
||||
<>
|
||||
<div id="hero" data-section="hero">
|
||||
<SectionErrorBoundary name="hero">
|
||||
<HeroBillboardCarousel
|
||||
tag="PROFESSIONAL WEB DESIGN · MEXICO"
|
||||
title="YOUR BUSINESS NEEDS A WEB THAT [X] WORKS."
|
||||
description="Delivered in 7 days. No excuses."
|
||||
primaryButton={{
|
||||
text: "See packages",
|
||||
href: "#packages",
|
||||
}}
|
||||
secondaryButton={{
|
||||
text: "Talk to an expert",
|
||||
href: "#contact",
|
||||
}}
|
||||
items={[
|
||||
{
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/modern-geometrical-background-with-white-shapes_23-2148811532.jpg",
|
||||
},
|
||||
{
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/3d-abstract-creative-sphere_23-2150885414.jpg",
|
||||
},
|
||||
{
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/white-bokeh-effect-black-background_1017-2740.jpg",
|
||||
},
|
||||
{
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/3d-geometric-abstract-background_1048-10524.jpg",
|
||||
},
|
||||
{
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/3d-rendering-abstract-black-white_23-2150853563.jpg",
|
||||
},
|
||||
{
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/3d-geometric-abstract-background_1048-10385.jpg",
|
||||
},
|
||||
]}
|
||||
textAnimation="slide-up"
|
||||
/>
|
||||
</SectionErrorBoundary>
|
||||
</div>
|
||||
|
||||
<div id="guarantee" data-section="guarantee">
|
||||
<SectionErrorBoundary name="guarantee">
|
||||
<AboutFeaturesSplit
|
||||
tag="OUR PROMISE"
|
||||
title="PROFESSIONAL WEB IN 7 DAYS"
|
||||
description="Or you don't pay. That simple."
|
||||
items={[
|
||||
{
|
||||
icon: Zap,
|
||||
title: "SPEED",
|
||||
description: "Guaranteed delivery in 7 business days.",
|
||||
},
|
||||
{
|
||||
icon: TrendingUp,
|
||||
title: "RESULTS",
|
||||
description: "Design that converts visitors into clients.",
|
||||
},
|
||||
{
|
||||
icon: ShieldCheck,
|
||||
title: "SUPPORT",
|
||||
description: "Real support — not a ticket queue.",
|
||||
},
|
||||
]}
|
||||
textAnimation="fade-blur"
|
||||
imageSrc="http://img.b2bpic.net/free-photo/white-water-drop-background_23-2147787465.jpg"
|
||||
/>
|
||||
</SectionErrorBoundary>
|
||||
</div>
|
||||
|
||||
<div id="services" data-section="services">
|
||||
<SectionErrorBoundary name="services">
|
||||
<FeaturesMediaCarousel
|
||||
tag="WHAT WE BUILD"
|
||||
title="WEBSITES THAT DO [X] THE WORK."
|
||||
description="From custom design to SEO and automation."
|
||||
items={[
|
||||
{
|
||||
title: "Custom Web Design",
|
||||
description: "Tailored, high-conversion visual design.",
|
||||
buttonIcon: "ArrowRight",
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/light-prisms-colorful-effect_23-2148898178.jpg",
|
||||
},
|
||||
{
|
||||
title: "On-page SEO",
|
||||
description: "Ready to rank from day one.",
|
||||
buttonIcon: "ArrowRight",
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/empty-concrete-room-with-neon-lights_1048-12984.jpg",
|
||||
},
|
||||
{
|
||||
title: "Integrations",
|
||||
description: "WhatsApp, Forms, and GMB setup.",
|
||||
buttonIcon: "ArrowRight",
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/colorful-light-prisms-effect_23-2148898152.jpg",
|
||||
},
|
||||
{
|
||||
title: "Analytics",
|
||||
description: "Google Analytics and traffic reporting.",
|
||||
buttonIcon: "ArrowRight",
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/front-view-blue-white-bottle-designed-round-beautiful-white-wall_140725-11601.jpg",
|
||||
},
|
||||
{
|
||||
title: "Speed Optimization",
|
||||
description: "Performance focused architecture.",
|
||||
buttonIcon: "ArrowRight",
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/abstract-metallic-cube-shape_23-2150979663.jpg",
|
||||
},
|
||||
{
|
||||
title: "Ongoing Support",
|
||||
description: "We ensure your site stays up.",
|
||||
buttonIcon: "ArrowRight",
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/spiky-black-ferromagnetic-liquid-metal-with-copy-space_23-2148253673.jpg",
|
||||
},
|
||||
]}
|
||||
textAnimation="slide-up"
|
||||
/>
|
||||
</SectionErrorBoundary>
|
||||
</div>
|
||||
|
||||
<div id="packages" data-section="packages">
|
||||
<SectionErrorBoundary name="packages">
|
||||
<PricingMediaCards
|
||||
tag="PACKAGES"
|
||||
title="CHOOSE YOUR [X] LEVEL"
|
||||
description="Transparent pricing for complete solutions."
|
||||
plans={[
|
||||
{
|
||||
tag: "WEB X PRO",
|
||||
price: "$14,900",
|
||||
period: "MXN",
|
||||
features: [
|
||||
"10 pages",
|
||||
"On-page SEO",
|
||||
"Forms & WhatsApp",
|
||||
"GMB Premium",
|
||||
"1 month support",
|
||||
],
|
||||
primaryButton: {
|
||||
text: "Get Pro",
|
||||
href: "#contact",
|
||||
},
|
||||
imageSrc: "http://img.b2bpic.net/free-psd/start-up-landing-page-template_23-2148819558.jpg",
|
||||
},
|
||||
{
|
||||
tag: "WEB X DOMINATOR",
|
||||
price: "$24,900",
|
||||
period: "MXN",
|
||||
features: [
|
||||
"Everything in Pro",
|
||||
"Campaign Landing Page",
|
||||
"Google Analytics",
|
||||
"Traffic Report",
|
||||
"3 months support",
|
||||
],
|
||||
primaryButton: {
|
||||
text: "Get Dominator",
|
||||
href: "#contact",
|
||||
},
|
||||
imageSrc: "http://img.b2bpic.net/free-psd/business-corporation-template_23-2151402198.jpg",
|
||||
},
|
||||
]}
|
||||
textAnimation="fade-blur"
|
||||
/>
|
||||
</SectionErrorBoundary>
|
||||
</div>
|
||||
|
||||
<div id="comparison" data-section="comparison">
|
||||
<SectionErrorBoundary name="comparison">
|
||||
<FaqSimple
|
||||
tag="DETAILS"
|
||||
title="DETAILED COMPARISON"
|
||||
description="Understand what is included in each package."
|
||||
items={[
|
||||
{
|
||||
question: "What's the difference between Pro and Dominator?",
|
||||
answer: "Dominator includes a custom campaign landing page, advanced analytics setup, monthly reporting, and 3 months of support versus 1.",
|
||||
},
|
||||
{
|
||||
question: "Is hosting included?",
|
||||
answer: "Hosting is included during your support period. We also manage domain setup and technical configuration.",
|
||||
},
|
||||
{
|
||||
question: "How does the 7-day guarantee work?",
|
||||
answer: "If we don't deliver a functional site in 7 business days, you don't pay. Simple.",
|
||||
},
|
||||
]}
|
||||
textAnimation="slide-up"
|
||||
/>
|
||||
</SectionErrorBoundary>
|
||||
</div>
|
||||
|
||||
<div id="process" data-section="process">
|
||||
<SectionErrorBoundary name="process">
|
||||
<FeaturesRevealCardsBento
|
||||
tag="PROCESS"
|
||||
title="FROM ZERO TO LIVE IN 7 DAYS."
|
||||
description="A streamlined four-stage process for maximum efficiency."
|
||||
items={[
|
||||
{
|
||||
title: "Day 1-2: Brief",
|
||||
description: "Gather goals and objectives.",
|
||||
href: "#",
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/prism-dispersing-light-concept_23-2148599263.jpg",
|
||||
},
|
||||
{
|
||||
title: "Day 2-4: Design",
|
||||
description: "Structuring your brand identity.",
|
||||
href: "#",
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/3d-rendering-holographic-cube_23-2150979697.jpg",
|
||||
},
|
||||
{
|
||||
title: "Day 4-6: Development",
|
||||
description: "Coding and functionality.",
|
||||
href: "#",
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/lights-prisms-effect-close-up_23-2148917904.jpg",
|
||||
},
|
||||
{
|
||||
title: "Day 7: Delivery",
|
||||
description: "Live launch and final review.",
|
||||
href: "#",
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/abstract-metallic-cube-shape_23-2150979660.jpg",
|
||||
},
|
||||
{
|
||||
title: "Ongoing",
|
||||
description: "Post-launch maintenance.",
|
||||
href: "#",
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/flying-rings-geometric-shapes-background_23-2148772500.jpg",
|
||||
},
|
||||
{
|
||||
title: "Support",
|
||||
description: "3 months technical help.",
|
||||
href: "#",
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/colorful-light-prisms-reflection_23-2148898144.jpg",
|
||||
},
|
||||
{
|
||||
title: "Optimization",
|
||||
description: "SEO tuning and analytics.",
|
||||
href: "#",
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/flying-snake_488145-667.jpg",
|
||||
},
|
||||
]}
|
||||
textAnimation="fade-blur"
|
||||
/>
|
||||
</SectionErrorBoundary>
|
||||
</div>
|
||||
|
||||
<div id="stats" data-section="stats">
|
||||
<SectionErrorBoundary name="stats">
|
||||
<MetricsMediaCards
|
||||
tag="TRUST"
|
||||
title="PROVEN TRACK RECORD"
|
||||
description="Results that drive business growth."
|
||||
metrics={[
|
||||
{
|
||||
value: "+50",
|
||||
title: "Businesses",
|
||||
description: "Active digital presence.",
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/3d-geometric-abstract-background_1048-11112.jpg",
|
||||
},
|
||||
{
|
||||
value: "7",
|
||||
title: "Days",
|
||||
description: "Guaranteed delivery time.",
|
||||
imageSrc: "http://img.b2bpic.net/free-vector/ring-glowing-points-black_1217-1373.jpg",
|
||||
},
|
||||
{
|
||||
value: "100%",
|
||||
title: "Satisfaction",
|
||||
description: "Or you don't pay.",
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/closeup-shot-glass-marbles_53876-47208.jpg",
|
||||
},
|
||||
]}
|
||||
textAnimation="slide-up"
|
||||
/>
|
||||
</SectionErrorBoundary>
|
||||
</div>
|
||||
|
||||
<div id="contact" data-section="contact">
|
||||
<SectionErrorBoundary name="contact">
|
||||
<ContactCta
|
||||
tag="MAKE THE MOVE"
|
||||
text="READY TO GROW [X]?"
|
||||
primaryButton={{
|
||||
text: "I want my website",
|
||||
href: "#",
|
||||
}}
|
||||
secondaryButton={{
|
||||
text: "See packages",
|
||||
href: "#packages",
|
||||
}}
|
||||
textAnimation="fade-blur"
|
||||
/>
|
||||
</SectionErrorBoundary>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
14
src/pages/blog/BlogPage.tsx
Normal file
14
src/pages/blog/BlogPage.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import BlogSimpleCards from "@/components/sections/blog/BlogSimpleCards";
|
||||
|
||||
const BlogPage = () => {
|
||||
return (
|
||||
<BlogSimpleCards
|
||||
tag="Blog"
|
||||
title="Latest Articles"
|
||||
description="Stay updated with our latest insights and news"
|
||||
textAnimation="slide-up"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default BlogPage;
|
||||
50
src/pages/blog/BlogPostPage.tsx
Normal file
50
src/pages/blog/BlogPostPage.tsx
Normal file
@@ -0,0 +1,50 @@
|
||||
import { useParams, useNavigate } from "react-router-dom";
|
||||
import { Loader2 } from "lucide-react";
|
||||
import BlogArticle from "@/components/sections/blog/BlogArticle";
|
||||
import useBlogPost from "@/hooks/useBlogPost";
|
||||
|
||||
const BlogPostPage = () => {
|
||||
const { slug } = useParams<{ slug: string }>();
|
||||
const navigate = useNavigate();
|
||||
const { post, isLoading } = useBlogPost(slug || "");
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<section className="w-content-width mx-auto py-20">
|
||||
<div className="flex justify-center">
|
||||
<Loader2 className="size-8 animate-spin text-foreground" strokeWidth={1.5} />
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
if (!post || !post.content) {
|
||||
return (
|
||||
<section className="w-content-width mx-auto py-20 text-center">
|
||||
<p className="text-foreground mb-4">Post not found</p>
|
||||
<button onClick={() => navigate("/blog")} className="primary-button px-6 py-2 rounded-theme text-primary-cta-text">
|
||||
Back to Blog
|
||||
</button>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
const wordCount = post.content.replace(/<[^>]*>/g, " ").trim().split(/\s+/).length;
|
||||
const readingTime = `${Math.max(1, Math.round(wordCount / 200))} min read`;
|
||||
|
||||
return (
|
||||
<BlogArticle
|
||||
category={post.category}
|
||||
title={post.title}
|
||||
excerpt={post.excerpt}
|
||||
content={post.content}
|
||||
imageSrc={post.imageSrc}
|
||||
authorName={post.authorName}
|
||||
authorImageSrc={post.authorAvatar}
|
||||
date={post.date}
|
||||
readingTime={readingTime}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default BlogPostPage;
|
||||
79
src/pages/shop/ProductPage.tsx
Normal file
79
src/pages/shop/ProductPage.tsx
Normal file
@@ -0,0 +1,79 @@
|
||||
import { ReactLenis } from "lenis/react";
|
||||
import { useParams, useNavigate } from "react-router-dom";
|
||||
import { Loader2 } from "lucide-react";
|
||||
import ProductDetailCard from "@/components/ecommerce/ProductDetailCard";
|
||||
import ProductCart from "@/components/ecommerce/ProductCart";
|
||||
import useProductDetail from "@/hooks/useProductDetail";
|
||||
import useCart from "@/hooks/useCart";
|
||||
import useCheckout from "@/hooks/useCheckout";
|
||||
|
||||
const ProductPage = () => {
|
||||
const { id } = useParams<{ id: string }>();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const { product, isLoading, images, createCartItem, selectedQuantity } = useProductDetail(id || "");
|
||||
const { items: cartItems, isOpen: cartOpen, setIsOpen: setCartOpen, addItem, updateQuantity, removeItem, total: cartTotal, getCheckoutItems } = useCart();
|
||||
const { buyNow, checkout } = useCheckout();
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<section className="w-content-width mx-auto py-20">
|
||||
<div className="flex justify-center">
|
||||
<Loader2 className="size-8 animate-spin text-foreground" strokeWidth={1.5} />
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
if (!product) {
|
||||
return (
|
||||
<section className="w-content-width mx-auto py-20 text-center">
|
||||
<p className="text-foreground mb-4">Product not found</p>
|
||||
<button onClick={() => navigate("/shop")} className="primary-button px-6 py-2 rounded-theme text-primary-cta-text">
|
||||
Back to Shop
|
||||
</button>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
const handleAddToCart = () => {
|
||||
const item = createCartItem();
|
||||
if (item) addItem(item);
|
||||
};
|
||||
|
||||
const handleBuyNow = () => {
|
||||
buyNow(product, selectedQuantity);
|
||||
};
|
||||
|
||||
const handleCheckout = async () => {
|
||||
if (cartItems.length === 0) return;
|
||||
const url = new URL(window.location.href);
|
||||
url.searchParams.set("success", "true");
|
||||
await checkout(getCheckoutItems(), { successUrl: url.toString() });
|
||||
};
|
||||
|
||||
return (
|
||||
<ReactLenis root>
|
||||
<ProductDetailCard
|
||||
name={product.name}
|
||||
price={product.price}
|
||||
description={product.description}
|
||||
images={images.map((img) => img.src)}
|
||||
rating={product.rating}
|
||||
onAddToCart={handleAddToCart}
|
||||
onBuyNow={handleBuyNow}
|
||||
/>
|
||||
<ProductCart
|
||||
isOpen={cartOpen}
|
||||
onClose={() => setCartOpen(false)}
|
||||
items={cartItems}
|
||||
total={`$${cartTotal}`}
|
||||
onQuantityChange={updateQuantity}
|
||||
onRemove={removeItem}
|
||||
onCheckout={handleCheckout}
|
||||
/>
|
||||
</ReactLenis>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProductPage;
|
||||
31
src/pages/shop/ShopPage.tsx
Normal file
31
src/pages/shop/ShopPage.tsx
Normal file
@@ -0,0 +1,31 @@
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { Loader2 } from "lucide-react";
|
||||
import ProductCatalog from "@/components/ecommerce/ProductCatalog";
|
||||
import useProductCatalog from "@/hooks/useProductCatalog";
|
||||
|
||||
const ShopPage = () => {
|
||||
const navigate = useNavigate();
|
||||
const { products, isLoading, search, setSearch } = useProductCatalog({
|
||||
onProductClick: (productId) => navigate(`/shop/${productId}`),
|
||||
});
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<section className="w-content-width mx-auto py-20">
|
||||
<div className="flex justify-center">
|
||||
<Loader2 className="size-8 animate-spin text-foreground" strokeWidth={1.5} />
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<ProductCatalog
|
||||
products={products}
|
||||
searchValue={search}
|
||||
onSearchChange={setSearch}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default ShopPage;
|
||||
Reference in New Issue
Block a user