Merge version_3 into main #4
222
src/app/blog/[slug]/page.tsx
Normal file
222
src/app/blog/[slug]/page.tsx
Normal file
@@ -0,0 +1,222 @@
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import { useParams } from "next/navigation";
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import NavbarStyleApple from "@/components/navbar/NavbarStyleApple/NavbarStyleApple";
|
||||
import FooterLogoReveal from "@/components/sections/footer/FooterLogoReveal";
|
||||
|
||||
export default function ArticlePage() {
|
||||
const params = useParams();
|
||||
const slug = params?.slug as string;
|
||||
|
||||
const navItems = [
|
||||
{ name: "Shop", id: "shop" },
|
||||
{ name: "How It Works", id: "how-it-works" },
|
||||
{ name: "About", id: "about" },
|
||||
{ name: "Reviews", id: "reviews" },
|
||||
{ name: "Blog", id: "/blog" },
|
||||
];
|
||||
|
||||
const articles: Record<string, any> = {
|
||||
"1": {
|
||||
id: "1", category: "Preparedness", title: "The Complete Guide to Family Emergency Planning", excerpt: "Learn the essential steps to create a comprehensive emergency plan that protects your entire family during any crisis.", authorName: "Sarah Johnson", authorAvatar: "http://img.b2bpic.net/free-photo/side-view-beautiful-woman-with-folded-arms-looking-camera_23-2147876783.jpg?_wi=1", date: "15 Jan 2025", content: `
|
||||
<h2>Introduction</h2>
|
||||
<p>Creating an emergency plan is one of the most important steps you can take to protect your family. This comprehensive guide will walk you through each stage of the process, ensuring everyone in your household knows what to do when disaster strikes.</p>
|
||||
|
||||
<h2>Step 1: Gather Your Family</h2>
|
||||
<p>The first step is to bring everyone together and discuss emergency preparedness. Make sure all family members, including children, understand the importance of having a plan.</p>
|
||||
<ul>
|
||||
<li>Schedule a family meeting</li>
|
||||
<li>Explain emergency scenarios in age-appropriate language</li>
|
||||
<li>Listen to everyone's concerns</li>
|
||||
<li>Assign roles based on abilities</li>
|
||||
</ul>
|
||||
|
||||
<h2>Step 2: Identify Potential Hazards</h2>
|
||||
<p>Different regions face different risks. Consider what types of emergencies are most likely to affect your area:</p>
|
||||
<ul>
|
||||
<li>Natural disasters (hurricanes, earthquakes, floods)</li>
|
||||
<li>Severe weather (blizzards, tornadoes)</li>
|
||||
<li>Utility failures (power outages, water shortage)</li>
|
||||
<li>Medical emergencies</li>
|
||||
</ul>
|
||||
|
||||
<h2>Step 3: Create Communication Plans</h2>
|
||||
<p>During an emergency, normal communication methods might not work. Establish backup communication methods:</p>
|
||||
<ul>
|
||||
<li>Designate an out-of-area contact person</li>
|
||||
<li>Share important phone numbers with all family members</li>
|
||||
<li>Practice using emergency communication methods</li>
|
||||
<li>Keep written copies in multiple locations</li>
|
||||
</ul>
|
||||
|
||||
<h2>Step 4: Prepare Your Home</h2>
|
||||
<p>Make your home as safe as possible before an emergency occurs. This includes securing heavy furniture, knowing how to shut off utilities, and identifying safe rooms.</p>
|
||||
|
||||
<h2>Step 5: Build Your Emergency Kit</h2>
|
||||
<p>Stock your home with essential supplies like water, food, first aid items, and medications. SafeHome kits are specifically designed to meet these needs.</p>
|
||||
|
||||
<h2>Conclusion</h2>
|
||||
<p>By following these steps and regularly practicing your plan, your family will be prepared to handle any emergency with confidence and safety.</p>
|
||||
`,
|
||||
tags: ["family", "planning", "preparedness", "emergency"],
|
||||
},
|
||||
"2": {
|
||||
id: "2", category: "Safety Tips", title: "5 Essential Items Every Emergency Kit Needs", excerpt: "Discover the critical supplies that should be in every family emergency kit and why they matter for survival.", authorName: "Michael Chen", authorAvatar: "http://img.b2bpic.net/free-photo/portrait-handsome-man-sitting-sofa_329181-2737.jpg?_wi=1", date: "12 Jan 2025", content: `
|
||||
<h2>Why Emergency Kits Matter</h2>
|
||||
<p>In any emergency, having the right supplies can mean the difference between discomfort and survival. Here are the five essential items that should be in every emergency kit.</p>
|
||||
|
||||
<h2>1. Water - The Most Critical Resource</h2>
|
||||
<p>Clean drinking water is essential for survival. The general rule is one gallon per person per day for at least three days.</p>
|
||||
<p><strong>Why it matters:</strong> Dehydration sets in quickly, and contaminated water can cause serious illness during emergencies when medical help may not be available.</p>
|
||||
|
||||
<h2>2. Food - Sustenance That Keeps</h2>
|
||||
<p>Non-perishable, high-calorie food items that don't require cooking are ideal for emergency situations.</p>
|
||||
<p><strong>Best options:</strong> Granola bars, canned beans, peanut butter, crackers, and dried fruits.</p>
|
||||
|
||||
<h2>3. First Aid Kit - Immediate Medical Response</h2>
|
||||
<p>A comprehensive first aid kit enables you to treat minor injuries and manage medical situations until professional help arrives.</p>
|
||||
|
||||
<h2>4. Flashlight and Batteries - Light in Darkness</h2>
|
||||
<p>Power outages are common during emergencies. A reliable flashlight with extra batteries is crucial for safety and navigation.</p>
|
||||
|
||||
<h2>5. Emergency Communication - Staying Connected</h2>
|
||||
<p>A battery-powered or hand-crank radio allows you to receive emergency broadcasts and stay informed about the situation.</p>
|
||||
|
||||
<h2>Beyond These Five</h2>
|
||||
<p>While these are the essentials, SafeHome kits include additional items like blankets, hygiene supplies, and multi-tools to ensure comprehensive preparedness.</p>
|
||||
`,
|
||||
tags: ["essentials", "supplies", "survival", "preparedness"],
|
||||
},
|
||||
};
|
||||
|
||||
const article = articles[slug] || null;
|
||||
|
||||
if (!article) {
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="icon-arrow"
|
||||
defaultTextAnimation="entrance-slide"
|
||||
borderRadius="rounded"
|
||||
contentWidth="compact"
|
||||
sizing="largeSizeMediumTitles"
|
||||
background="blurBottom"
|
||||
cardStyle="soft-shadow"
|
||||
primaryButtonStyle="flat"
|
||||
secondaryButtonStyle="solid"
|
||||
headingFontWeight="medium"
|
||||
>
|
||||
<div id="nav" data-section="nav">
|
||||
<NavbarStyleApple brandName="SafeHome" navItems={navItems} />
|
||||
</div>
|
||||
<div className="py-20 md:py-32">
|
||||
<div className="mx-auto px-4 md:px-6 text-center">
|
||||
<h1 className="text-4xl font-bold mb-4">Article Not Found</h1>
|
||||
<p className="text-lg text-muted-foreground mb-8">The article you're looking for doesn't exist.</p>
|
||||
<Link href="/blog" className="text-primary-cta hover:underline">
|
||||
Back to Blog
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
<div id="footer" data-section="footer">
|
||||
<FooterLogoReveal
|
||||
logoText="SafeHome"
|
||||
leftLink={{ text: "Privacy Policy", href: "/privacy" }}
|
||||
rightLink={{ text: "Terms of Service", href: "/terms" }}
|
||||
/>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="icon-arrow"
|
||||
defaultTextAnimation="entrance-slide"
|
||||
borderRadius="rounded"
|
||||
contentWidth="compact"
|
||||
sizing="largeSizeMediumTitles"
|
||||
background="blurBottom"
|
||||
cardStyle="soft-shadow"
|
||||
primaryButtonStyle="flat"
|
||||
secondaryButtonStyle="solid"
|
||||
headingFontWeight="medium"
|
||||
>
|
||||
<div id="nav" data-section="nav">
|
||||
<NavbarStyleApple brandName="SafeHome" navItems={navItems} />
|
||||
</div>
|
||||
|
||||
<article className="py-20 md:py-32">
|
||||
<div className="mx-auto px-4 md:px-6 max-w-3xl">
|
||||
<div className="mb-8">
|
||||
<Link href="/blog" className="text-primary-cta hover:underline text-sm font-medium mb-4 inline-block">
|
||||
← Back to Blog
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<div className="mb-8">
|
||||
<div className="flex items-center gap-2 mb-4">
|
||||
<span className="px-3 py-1 bg-primary-cta text-primary-foreground text-xs font-semibold rounded-full">
|
||||
{article.category}
|
||||
</span>
|
||||
</div>
|
||||
<h1 className="text-4xl md:text-5xl font-bold mb-6">{article.title}</h1>
|
||||
<p className="text-xl text-muted-foreground mb-8">{article.excerpt}</p>
|
||||
|
||||
<div className="flex items-center gap-4 py-6 border-t border-b border-accent/20">
|
||||
<img
|
||||
src={article.authorAvatar}
|
||||
alt={article.authorName}
|
||||
className="w-12 h-12 rounded-full object-cover"
|
||||
/>
|
||||
<div>
|
||||
<p className="font-semibold text-foreground">{article.authorName}</p>
|
||||
<p className="text-sm text-muted-foreground">{article.date}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="prose prose-lg dark:prose-invert max-w-none mb-12 space-y-6"
|
||||
dangerouslySetInnerHTML={{ __html: article.content }}
|
||||
/>
|
||||
|
||||
<div className="mt-12 pt-8 border-t border-accent/20">
|
||||
<div className="mb-6">
|
||||
<h3 className="text-sm font-semibold text-muted-foreground mb-3">Tags</h3>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{article.tags.map((tag: string) => (
|
||||
<Link
|
||||
key={tag}
|
||||
href={`/blog?tag=${tag}`}
|
||||
className="px-3 py-1 bg-card text-foreground text-sm rounded-full hover:bg-accent transition-colors"
|
||||
>
|
||||
#{tag}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-12">
|
||||
<Link
|
||||
href="/blog"
|
||||
className="inline-block px-6 py-3 bg-primary-cta text-primary-foreground font-semibold rounded-lg hover:bg-primary-cta/90 transition-colors"
|
||||
>
|
||||
Read More Articles
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<div id="footer" data-section="footer">
|
||||
<FooterLogoReveal
|
||||
logoText="SafeHome"
|
||||
leftLink={{ text: "Privacy Policy", href: "/privacy" }}
|
||||
rightLink={{ text: "Terms of Service", href: "/terms" }}
|
||||
/>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
"use client";
|
||||
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import Link from "next/link";
|
||||
import { useState } from "react";
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import NavbarStyleApple from "@/components/navbar/NavbarStyleApple/NavbarStyleApple";
|
||||
import BlogCardOne from "@/components/sections/blog/BlogCardOne";
|
||||
import FooterLogoReveal from "@/components/sections/footer/FooterLogoReveal";
|
||||
|
||||
export default function BlogPage() {
|
||||
@@ -11,112 +13,35 @@ export default function BlogPage() {
|
||||
{ name: "How It Works", id: "how-it-works" },
|
||||
{ name: "About", id: "about" },
|
||||
{ name: "Reviews", id: "reviews" },
|
||||
{ name: "Contact", id: "contact" },
|
||||
{ name: "Blog", id: "/blog" },
|
||||
];
|
||||
|
||||
const blogCategories = [
|
||||
const [searchQuery, setSearchQuery] = useState("");
|
||||
const [selectedCategory, setSelectedCategory] = useState("all");
|
||||
|
||||
const blogPosts = [
|
||||
{
|
||||
id: "emergency-prep",
|
||||
name: "Emergency Preparedness",
|
||||
slug: "emergency-preparedness",
|
||||
description: "Learn best practices for family emergency planning",
|
||||
},
|
||||
id: "1", category: "Preparedness", title: "The Complete Guide to Family Emergency Planning", excerpt: "Learn the essential steps to create a comprehensive emergency plan that protects your entire family during any crisis.", imageSrc: "http://img.b2bpic.net/free-photo/affectionate-little-girl-with-eyes-closed-embracing-her-father-home-mother-is-background_637285-3199.jpg?_wi=1", imageAlt: "Family emergency planning guide", authorName: "Sarah Johnson", authorAvatar: "http://img.b2bpic.net/free-photo/side-view-beautiful-woman-with-folded-arms-looking-camera_23-2147876783.jpg?_wi=1", date: "15 Jan 2025"},
|
||||
{
|
||||
id: "product-guides",
|
||||
name: "Product Guides",
|
||||
slug: "product-guides",
|
||||
description: "Deep dives into emergency kit components and uses",
|
||||
},
|
||||
id: "2", category: "Safety Tips", title: "5 Essential Items Every Emergency Kit Needs", excerpt: "Discover the critical supplies that should be in every family emergency kit and why they matter for survival.", imageSrc: "http://img.b2bpic.net/free-photo/high-view-father-son-playing-with-toys_23-2148500810.jpg?_wi=1", imageAlt: "Emergency kit essentials", authorName: "Michael Chen", authorAvatar: "http://img.b2bpic.net/free-photo/portrait-handsome-man-sitting-sofa_329181-2737.jpg?_wi=1", date: "12 Jan 2025"},
|
||||
{
|
||||
id: "household-scenarios",
|
||||
name: "Household Scenarios",
|
||||
slug: "household-scenarios",
|
||||
description: "Preparedness tips for specific situations and emergencies",
|
||||
},
|
||||
id: "3", category: "Preparedness", title: "How to Prepare Your Home for Natural Disasters", excerpt: "Practical steps to weatherproof your home and create a safe haven for your family during severe weather events.", imageSrc: "http://img.b2bpic.net/free-photo/young-family-enjoying-trips_23-2149176539.jpg?_wi=1", imageAlt: "Home disaster preparation", authorName: "Emily Rodriguez", authorAvatar: "http://img.b2bpic.net/free-photo/young-female-blazer-beauty-blonde_1139-773.jpg?_wi=1", date: "10 Jan 2025"},
|
||||
{
|
||||
id: "food-water",
|
||||
name: "Food & Water",
|
||||
slug: "food-water",
|
||||
description: "Nutrition, hydration, and food storage for emergencies",
|
||||
},
|
||||
id: "4", category: "Safety Tips", title: "Emergency Communication Plans for Families", excerpt: "Stay connected when it matters most. Learn how to establish reliable communication channels during emergencies.", imageSrc: "http://img.b2bpic.net/free-photo/luggage-seen-from-rear-car-window_23-2150934321.jpg?_wi=1", imageAlt: "Family communication planning", authorName: "David Park", authorAvatar: "http://img.b2bpic.net/free-photo/man-looks-seriously-has-strict-expression-gazes-directly-camera-wears-blue-velvet-shirt-smirks-face-isolated-beige_273609-54464.jpg?_wi=1", date: "8 Jan 2025"},
|
||||
{
|
||||
id: "wellness",
|
||||
name: "Wellness & Mental Health",
|
||||
slug: "wellness",
|
||||
description: "Mental preparedness and coping with uncertainty",
|
||||
},
|
||||
id: "5", category: "Nutrition", title: "Long-Term Food Storage Best Practices", excerpt: "Master the art of storing emergency food supplies safely. Learn shelf life, rotation methods, and storage techniques.", imageSrc: "http://img.b2bpic.net/free-photo/top-view-storage-devices-glasses_23-2149319333.jpg?_wi=1", imageAlt: "Food storage organization", authorName: "Lisa Warren", authorAvatar: "http://img.b2bpic.net/free-photo/side-view-beautiful-woman-with-folded-arms-looking-camera_23-2147876783.jpg?_wi=1", date: "5 Jan 2025"},
|
||||
{
|
||||
id: "6", category: "Preparedness", title: "Teaching Kids About Emergency Preparedness", excerpt: "Age-appropriate ways to educate children about safety and emergency response without creating anxiety.", imageSrc: "http://img.b2bpic.net/free-photo/portrait-woman-home-yawning_23-2148923998.jpg?_wi=1", imageAlt: "Children safety education", authorName: "Jennifer Lee", authorAvatar: "http://img.b2bpic.net/free-photo/young-female-blazer-beauty-blonde_1139-773.jpg?_wi=1", date: "2 Jan 2025"},
|
||||
];
|
||||
|
||||
const blogArticles = [
|
||||
{
|
||||
id: "blog-1",
|
||||
title: "The Complete Guide to Building a 72-Hour Emergency Kit",
|
||||
slug: "complete-guide-72-hour-kit",
|
||||
excerpt: "Everything you need to know about assembling a functional 72-hour emergency kit for your household",
|
||||
category: "emergency-prep",
|
||||
readTime: "8 min",
|
||||
},
|
||||
{
|
||||
id: "blog-2",
|
||||
title: "Water Storage & Purification for Emergency Preparedness",
|
||||
slug: "water-storage-purification",
|
||||
excerpt: "Critical water preparation strategies and which purification methods work best",
|
||||
category: "food-water",
|
||||
readTime: "6 min",
|
||||
},
|
||||
{
|
||||
id: "blog-3",
|
||||
title: "Power Outage Preparedness: What Every Family Should Know",
|
||||
slug: "power-outage-preparedness",
|
||||
excerpt: "Essential steps to protect your family during extended power outages",
|
||||
category: "household-scenarios",
|
||||
readTime: "7 min",
|
||||
},
|
||||
{
|
||||
id: "blog-4",
|
||||
title: "Shelf-Stable Nutrition: Choosing High-Quality Emergency Food",
|
||||
slug: "shelf-stable-nutrition",
|
||||
excerpt: "How to select nutritious, long-lasting foods that your family will actually eat",
|
||||
category: "food-water",
|
||||
readTime: "6 min",
|
||||
},
|
||||
{
|
||||
id: "blog-5",
|
||||
title: "Managing Emergency Anxiety: A Mental Health Perspective",
|
||||
slug: "managing-emergency-anxiety",
|
||||
excerpt: "Psychological insights on preparing for emergencies without becoming overwhelmed",
|
||||
category: "wellness",
|
||||
readTime: "5 min",
|
||||
},
|
||||
{
|
||||
id: "blog-6",
|
||||
title: "First Aid Essentials: What Every Kit Must Include",
|
||||
slug: "first-aid-essentials",
|
||||
excerpt: "Medical supplies and first aid knowledge every household needs",
|
||||
category: "product-guides",
|
||||
readTime: "7 min",
|
||||
},
|
||||
{
|
||||
id: "blog-7",
|
||||
title: "Natural Disaster Preparedness by Region",
|
||||
slug: "natural-disaster-preparedness",
|
||||
excerpt: "Tailored emergency preparation strategies for earthquakes, hurricanes, tornadoes, and floods",
|
||||
category: "household-scenarios",
|
||||
readTime: "9 min",
|
||||
},
|
||||
{
|
||||
id: "blog-8",
|
||||
title: "Teaching Children About Emergency Preparedness",
|
||||
slug: "teaching-children-preparedness",
|
||||
excerpt: "Age-appropriate ways to involve kids in family emergency planning",
|
||||
category: "wellness",
|
||||
readTime: "5 min",
|
||||
},
|
||||
];
|
||||
const categories = ["all", "Preparedness", "Safety Tips", "Nutrition"];
|
||||
|
||||
const getCategoryName = (categoryId: string) => {
|
||||
return blogCategories.find(cat => cat.id === categoryId)?.name || categoryId;
|
||||
};
|
||||
const filteredPosts = blogPosts.filter((post) => {
|
||||
const matchesCategory = selectedCategory === "all" || post.category === selectedCategory;
|
||||
const matchesSearch = post.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||
post.excerpt.toLowerCase().includes(searchQuery.toLowerCase());
|
||||
return matchesCategory && matchesSearch;
|
||||
});
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
@@ -135,74 +60,57 @@ export default function BlogPage() {
|
||||
<NavbarStyleApple brandName="SafeHome" navItems={navItems} />
|
||||
</div>
|
||||
|
||||
<div id="blog-hero" data-section="blog-hero" className="py-16 md:py-24 mx-auto px-4 md:px-6">
|
||||
<div className="max-w-3xl">
|
||||
<h1 className="text-5xl md:text-6xl font-bold text-foreground mb-4">
|
||||
Emergency Preparedness Blog
|
||||
</h1>
|
||||
<p className="text-lg md:text-xl text-foreground/80">
|
||||
Expert insights and practical guides to help your family prepare for any emergency with confidence.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="py-20 md:py-32">
|
||||
<div className="mx-auto px-4 md:px-6 max-w-4xl">
|
||||
<div className="mb-12">
|
||||
<h1 className="text-4xl md:text-5xl font-bold mb-4">SafeHome Blog</h1>
|
||||
<p className="text-lg text-muted-foreground mb-8">Expert tips, guides, and stories on emergency preparedness</p>
|
||||
|
||||
<div id="blog-categories" data-section="blog-categories" className="py-12 md:py-16 mx-auto px-4 md:px-6">
|
||||
<div className="flex flex-wrap gap-3">
|
||||
{blogCategories.map((category) => (
|
||||
<Link
|
||||
key={category.id}
|
||||
href={`/blog/category/${category.slug}`}
|
||||
className="px-4 py-2 bg-accent/20 text-accent hover:bg-accent hover:text-white rounded-full font-medium transition-colors"
|
||||
>
|
||||
{category.name}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="blog-articles" data-section="blog-articles" className="py-20 md:py-32 mx-auto px-4 md:px-6">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
{blogArticles.map((article) => (
|
||||
<Link
|
||||
key={article.id}
|
||||
href={`/blog/${article.slug}`}
|
||||
className="group bg-card rounded-lg overflow-hidden shadow-sm hover:shadow-lg transition-shadow p-6"
|
||||
>
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<span className="text-xs font-semibold text-accent uppercase tracking-wider">
|
||||
{getCategoryName(article.category)}
|
||||
</span>
|
||||
<span className="text-xs text-foreground/60">{article.readTime}</span>
|
||||
<div className="space-y-6">
|
||||
<div className="relative">
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search articles..."
|
||||
value={searchQuery}
|
||||
onChange={(e) => setSearchQuery(e.target.value)}
|
||||
className="w-full px-4 py-2 border border-input rounded-lg bg-background text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-primary-cta"
|
||||
/>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-foreground mb-3 group-hover:text-accent transition-colors line-clamp-2">
|
||||
{article.title}
|
||||
</h3>
|
||||
<p className="text-foreground/70 text-sm line-clamp-3 mb-4">
|
||||
{article.excerpt}
|
||||
</p>
|
||||
<div className="flex items-center text-accent font-medium text-sm group-hover:gap-2 transition-all">
|
||||
Read More →
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="blog-cta" data-section="blog-cta" className="py-20 md:py-32 mx-auto px-4 md:px-6 bg-accent/10 rounded-lg">
|
||||
<div className="max-w-2xl mx-auto text-center">
|
||||
<h2 className="text-4xl md:text-5xl font-bold text-foreground mb-4">
|
||||
Ready to Prepare?
|
||||
</h2>
|
||||
<p className="text-lg text-foreground/80 mb-8">
|
||||
Use the knowledge from our blog to build the perfect emergency kit for your family.
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row gap-4 justify-center">
|
||||
<Link href="/kit-builder" className="inline-block px-8 py-3 bg-primary-cta text-primary-cta-text rounded-lg font-medium hover:opacity-90 transition-opacity">
|
||||
Build Your Kit
|
||||
</Link>
|
||||
<Link href="/" className="inline-block px-8 py-3 border-2 border-primary-cta text-primary-cta rounded-lg font-medium hover:bg-primary-cta/5 transition-colors">
|
||||
Back to Home
|
||||
</Link>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{categories.map((category) => (
|
||||
<button
|
||||
key={category}
|
||||
onClick={() => setSelectedCategory(category)}
|
||||
className={`px-4 py-2 rounded-lg font-medium transition-colors ${
|
||||
selectedCategory === category
|
||||
? "bg-primary-cta text-primary-foreground"
|
||||
: "bg-card text-foreground hover:bg-accent"
|
||||
}`}
|
||||
>
|
||||
{category.charAt(0).toUpperCase() + category.slice(1)}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="blog-posts" data-section="blog-posts" className="mb-12">
|
||||
{filteredPosts.length > 0 ? (
|
||||
<BlogCardOne
|
||||
blogs={filteredPosts}
|
||||
title=""
|
||||
description=""
|
||||
textboxLayout="default"
|
||||
useInvertedBackground={false}
|
||||
animationType="slide-up"
|
||||
carouselMode="buttons"
|
||||
/>
|
||||
) : (
|
||||
<div className="text-center py-12">
|
||||
<p className="text-lg text-muted-foreground">No articles found matching your search.</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,45 +1,61 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import NavbarStyleApple from '@/components/navbar/NavbarStyleApple/NavbarStyleApple';
|
||||
import NavbarStyleApple from "@/components/navbar/NavbarStyleApple/NavbarStyleApple";
|
||||
import MediaAbout from "@/components/sections/about/MediaAbout";
|
||||
import FooterLogoReveal from "@/components/sections/footer/FooterLogoReveal";
|
||||
import Link from "next/link";
|
||||
import { Trash2, Plus, Minus, ShoppingCart } from "lucide-react";
|
||||
|
||||
interface CartItem {
|
||||
id: string;
|
||||
name: string;
|
||||
price: number;
|
||||
quantity: number;
|
||||
variant: string;
|
||||
imageSrc: string;
|
||||
image: string;
|
||||
}
|
||||
|
||||
export default function CartPage() {
|
||||
// Mock cart data
|
||||
const cartItems: CartItem[] = [
|
||||
const [cartItems, setCartItems] = useState<CartItem[]>([
|
||||
{
|
||||
id: "kit-4p-24h",
|
||||
name: "4-Person 24-Hour Kit",
|
||||
price: 149,
|
||||
id: "kit-4p-24h", name: "4-Person 24-Hour Kit", price: 149,
|
||||
quantity: 1,
|
||||
variant: "Families with Children",
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/young-family-enjoying-trips_23-2149176539.jpg?_wi=6"
|
||||
},
|
||||
image: "http://img.b2bpic.net/free-photo/young-family-enjoying-trips_23-2149176539.jpg?_wi=1"},
|
||||
{
|
||||
id: "kit-2p-24h",
|
||||
name: "2-Person 24-Hour Kit",
|
||||
price: 89,
|
||||
quantity: 2,
|
||||
variant: "Couples & Small Households",
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/sporty-girl-packing-bag-training-sports-girl-going-training-preparing-training_169016-67560.jpg?_wi=5"
|
||||
}
|
||||
id: "kit-4p-72h-ext", name: "4-Person 72-Hour Extension", price: 150,
|
||||
quantity: 1,
|
||||
image: "http://img.b2bpic.net/free-photo/luggage-seen-from-rear-car-window_23-2150934321.jpg?_wi=1"},
|
||||
]);
|
||||
|
||||
const navItems = [
|
||||
{ name: "Shop", id: "/shop" },
|
||||
{ name: "How It Works", id: "how-it-works" },
|
||||
{ name: "About", id: "about" },
|
||||
{ name: "Reviews", id: "reviews" },
|
||||
{ name: "Contact", id: "contact" },
|
||||
];
|
||||
|
||||
const subtotal = cartItems.reduce((acc, item) => acc + (item.price * item.quantity), 0);
|
||||
const shipping = subtotal > 0 ? 12.99 : 0;
|
||||
const tax = subtotal * 0.08;
|
||||
const subtotal = cartItems.reduce((acc, item) => acc + item.price * item.quantity, 0);
|
||||
const shipping = 15;
|
||||
const tax = Math.round(subtotal * 0.1 * 100) / 100;
|
||||
const total = subtotal + shipping + tax;
|
||||
|
||||
const updateQuantity = (id: string, newQuantity: number) => {
|
||||
if (newQuantity <= 0) {
|
||||
setCartItems(cartItems.filter((item) => item.id !== id));
|
||||
} else {
|
||||
setCartItems(
|
||||
cartItems.map((item) =>
|
||||
item.id === id ? { ...item, quantity: newQuantity } : item
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const removeItem = (id: string) => {
|
||||
setCartItems(cartItems.filter((item) => item.id !== id));
|
||||
};
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="icon-arrow"
|
||||
@@ -54,197 +70,115 @@ export default function CartPage() {
|
||||
headingFontWeight="medium"
|
||||
>
|
||||
<div id="nav" data-section="nav">
|
||||
<NavbarStyleApple
|
||||
brandName="SafeHome"
|
||||
navItems={[
|
||||
{ name: "Shop", id: "/shop" },
|
||||
{ name: "How It Works", id: "/how-it-works" },
|
||||
{ name: "About", id: "/about" },
|
||||
{ name: "Reviews", id: "/reviews" },
|
||||
{ name: "Contact", id: "/contact" }
|
||||
]}
|
||||
/>
|
||||
<NavbarStyleApple brandName="SafeHome" navItems={navItems} />
|
||||
</div>
|
||||
|
||||
<div className="min-h-screen bg-[#e3deea]">
|
||||
{/* Cart Header */}
|
||||
<div id="cart-header" data-section="cart-header" className="py-16 md:py-20">
|
||||
<div className="mx-auto px-4 md:px-6 max-w-6xl">
|
||||
<div className="flex items-center gap-3 mb-6">
|
||||
<ShoppingCart className="w-8 h-8 text-[#c68a62]" />
|
||||
<h1 className="text-4xl md:text-5xl font-medium text-[#27231f]">Your Shopping Cart</h1>
|
||||
</div>
|
||||
<p className="text-lg text-[#27231f] opacity-75">Review your items before proceeding to checkout</p>
|
||||
</div>
|
||||
</div>
|
||||
<div id="cart" data-section="cart" className="py-20 md:py-32">
|
||||
<div className="mx-auto px-4 md:px-6 w-full max-w-5xl">
|
||||
<h1 className="text-4xl md:text-5xl font-bold mb-12">Shopping Cart</h1>
|
||||
|
||||
{/* Cart Items Section */}
|
||||
<div id="cart-items" data-section="cart-items" className="py-12 md:py-16">
|
||||
<div className="mx-auto px-4 md:px-6 max-w-6xl">
|
||||
{cartItems.length === 0 ? (
|
||||
<div className="bg-card rounded-lg p-8 text-center">
|
||||
<p className="text-lg text-foreground mb-6">Your cart is empty</p>
|
||||
<Link
|
||||
href="/shop"
|
||||
className="inline-block bg-primary-cta text-white px-6 py-3 rounded-lg hover:opacity-90 transition-opacity"
|
||||
>
|
||||
Continue Shopping
|
||||
</Link>
|
||||
</div>
|
||||
) : (
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
||||
{/* Items List */}
|
||||
<div className="lg:col-span-2">
|
||||
<div className="bg-white rounded-2xl shadow-sm p-6 md:p-8">
|
||||
<h2 className="text-2xl font-medium text-[#27231f] mb-6">Items</h2>
|
||||
|
||||
{cartItems.length === 0 ? (
|
||||
<div className="text-center py-12">
|
||||
<p className="text-[#27231f] opacity-60">Your cart is empty</p>
|
||||
<Link href="/shop" className="mt-4 inline-block px-6 py-2 bg-[#27231f] text-[#e3deea] rounded-lg">
|
||||
Continue Shopping
|
||||
</Link>
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-6">
|
||||
{cartItems.map((item, index) => (
|
||||
<div key={item.id} className={`flex gap-6 ${index > 0 ? 'border-t border-gray-200 pt-6' : ''}`}>
|
||||
<div className="w-24 h-24 flex-shrink-0 bg-gray-100 rounded-lg overflow-hidden">
|
||||
<img
|
||||
src={item.imageSrc}
|
||||
alt={item.name}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex-grow">
|
||||
<h3 className="text-lg font-medium text-[#27231f] mb-1">{item.name}</h3>
|
||||
<p className="text-sm text-[#27231f] opacity-60 mb-3">{item.variant}</p>
|
||||
<p className="text-lg font-medium text-[#c68a62]">${item.price.toFixed(2)}</p>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col items-end justify-between">
|
||||
<button className="text-red-500 hover:text-red-700 transition-colors">
|
||||
<Trash2 className="w-5 h-5" />
|
||||
<div className="space-y-4">
|
||||
{cartItems.map((item) => (
|
||||
<div key={item.id} className="bg-card rounded-lg p-6 flex gap-6 items-start">
|
||||
<img
|
||||
src={item.image}
|
||||
alt={item.name}
|
||||
className="w-24 h-24 object-cover rounded-lg flex-shrink-0"
|
||||
/>
|
||||
<div className="flex-1">
|
||||
<h3 className="font-bold text-lg mb-2">{item.name}</h3>
|
||||
<p className="text-foreground/70 mb-4">${item.price.toFixed(2)}</p>
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="flex items-center border border-accent rounded-lg">
|
||||
<button
|
||||
onClick={() => updateQuantity(item.id, item.quantity - 1)}
|
||||
className="px-3 py-2 hover:bg-accent/10"
|
||||
>
|
||||
−
|
||||
</button>
|
||||
<span className="px-4 py-2">{item.quantity}</span>
|
||||
<button
|
||||
onClick={() => updateQuantity(item.id, item.quantity + 1)}
|
||||
className="px-3 py-2 hover:bg-accent/10"
|
||||
>
|
||||
+
|
||||
</button>
|
||||
|
||||
<div className="flex items-center gap-2 bg-gray-100 rounded-lg p-1">
|
||||
<button className="p-1 hover:bg-gray-200 rounded">
|
||||
<Minus className="w-4 h-4 text-[#27231f]" />
|
||||
</button>
|
||||
<span className="w-6 text-center text-[#27231f] font-medium">{item.quantity}</span>
|
||||
<button className="p-1 hover:bg-gray-200 rounded">
|
||||
<Plus className="w-4 h-4 text-[#27231f]" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => removeItem(item.id)}
|
||||
className="text-red-500 hover:text-red-700 text-sm font-medium"
|
||||
>
|
||||
Remove
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<p className="font-bold text-lg">${(item.price * item.quantity).toFixed(2)}</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Order Summary */}
|
||||
<div className="lg:col-span-1">
|
||||
<div className="bg-white rounded-2xl shadow-sm p-6 md:p-8 sticky top-20">
|
||||
<h2 className="text-2xl font-medium text-[#27231f] mb-6">Order Summary</h2>
|
||||
|
||||
<div className="space-y-4 border-b border-gray-200 pb-6 mb-6">
|
||||
<div className="flex justify-between text-[#27231f]">
|
||||
<div className="bg-card rounded-lg p-6 sticky top-24">
|
||||
<h2 className="text-xl font-bold mb-6">Order Summary</h2>
|
||||
<div className="space-y-3 mb-6 pb-6 border-b border-accent/20">
|
||||
<div className="flex justify-between">
|
||||
<span>Subtotal</span>
|
||||
<span>${subtotal.toFixed(2)}</span>
|
||||
<span className="font-medium">${subtotal.toFixed(2)}</span>
|
||||
</div>
|
||||
<div className="flex justify-between text-[#27231f]">
|
||||
<div className="flex justify-between">
|
||||
<span>Shipping</span>
|
||||
<span>${shipping.toFixed(2)}</span>
|
||||
<span className="font-medium">${shipping.toFixed(2)}</span>
|
||||
</div>
|
||||
<div className="flex justify-between text-[#27231f]">
|
||||
<div className="flex justify-between">
|
||||
<span>Tax</span>
|
||||
<span>${tax.toFixed(2)}</span>
|
||||
<span className="font-medium">${tax.toFixed(2)}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-between mb-8">
|
||||
<span className="text-lg font-medium text-[#27231f]">Total</span>
|
||||
<span className="text-xl font-medium text-[#c68a62]">${total.toFixed(2)}</span>
|
||||
<div className="flex justify-between mb-6 text-lg font-bold">
|
||||
<span>Total</span>
|
||||
<span>${total.toFixed(2)}</span>
|
||||
</div>
|
||||
|
||||
<Link
|
||||
href="/checkout"
|
||||
className="w-full block text-center bg-[#27231f] text-[#e3deea] py-3 rounded-lg font-medium hover:opacity-90 transition-opacity mb-3"
|
||||
className="w-full inline-block text-center bg-primary-cta text-white px-6 py-3 rounded-lg hover:opacity-90 transition-opacity font-medium mb-3"
|
||||
>
|
||||
Proceed to Checkout
|
||||
</Link>
|
||||
|
||||
<Link
|
||||
href="/shop"
|
||||
className="w-full block text-center border border-[#27231f] text-[#27231f] py-3 rounded-lg font-medium hover:bg-gray-50 transition-colors"
|
||||
className="w-full inline-block text-center bg-secondary-cta text-foreground px-6 py-3 rounded-lg hover:opacity-90 transition-opacity font-medium border border-accent"
|
||||
>
|
||||
Continue Shopping
|
||||
</Link>
|
||||
|
||||
{/* Trust Badges */}
|
||||
<div className="mt-8 pt-8 border-t border-gray-200 space-y-3 text-sm text-[#27231f] opacity-70">
|
||||
<div className="flex items-start gap-2">
|
||||
<span className="text-[#c68a62] mt-1">✓</span>
|
||||
<span>30-day money-back guarantee</span>
|
||||
</div>
|
||||
<div className="flex items-start gap-2">
|
||||
<span className="text-[#c68a62] mt-1">✓</span>
|
||||
<span>Free shipping on orders over $150</span>
|
||||
</div>
|
||||
<div className="flex items-start gap-2">
|
||||
<span className="text-[#c68a62] mt-1">✓</span>
|
||||
<span>Trusted by 15,000+ families</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Recommended Products */}
|
||||
<div id="recommended" data-section="recommended" className="py-16 md:py-20">
|
||||
<div className="mx-auto px-4 md:px-6 max-w-6xl">
|
||||
<h2 className="text-3xl font-medium text-[#27231f] mb-4">Recommended Add-ons</h2>
|
||||
<p className="text-lg text-[#27231f] opacity-60 mb-8">Complete your emergency kit</p>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
{[
|
||||
{ name: "First Aid Refill Kit", price: "$29", variant: "Essential medical supplies" },
|
||||
{ name: "Water Purification Pack", price: "$34", variant: "Clean drinking water for 6 people" },
|
||||
{ name: "Food Extension Bundle", price: "$45", variant: "Additional 48-hour food supply" }
|
||||
].map((product, idx) => (
|
||||
<div key={idx} className="bg-white rounded-2xl shadow-sm p-6 hover:shadow-md transition-shadow">
|
||||
<div className="w-full h-40 bg-gray-100 rounded-lg mb-4"></div>
|
||||
<h3 className="text-lg font-medium text-[#27231f] mb-2">{product.name}</h3>
|
||||
<p className="text-sm text-[#27231f] opacity-60 mb-4">{product.variant}</p>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-lg font-medium text-[#c68a62]">{product.price}</span>
|
||||
<button className="bg-[#27231f] text-[#e3deea] px-4 py-2 rounded-lg hover:opacity-90 transition-opacity text-sm">
|
||||
Add to Cart
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Footer */}
|
||||
<div id="footer" data-section="footer" className="py-12 bg-white border-t border-gray-200">
|
||||
<div className="mx-auto px-4 md:px-6 max-w-6xl">
|
||||
<div className="flex flex-col md:flex-row justify-between items-center">
|
||||
<div className="text-center md:text-left mb-6 md:mb-0">
|
||||
<Link href="/" className="text-2xl font-medium text-[#27231f] hover:opacity-75 transition-opacity">
|
||||
SafeHome
|
||||
</Link>
|
||||
</div>
|
||||
<div className="flex gap-8">
|
||||
<Link href="/privacy" className="text-[#27231f] hover:text-[#c68a62] transition-colors">
|
||||
Privacy Policy
|
||||
</Link>
|
||||
<Link href="/terms" className="text-[#27231f] hover:text-[#c68a62] transition-colors">
|
||||
Terms of Service
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
<div className="border-t border-gray-200 mt-8 pt-8 text-center text-sm text-[#27231f] opacity-60">
|
||||
<p>© 2025 SafeHome Emergency Preparedness. All rights reserved.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="footer" data-section="footer">
|
||||
<FooterLogoReveal
|
||||
logoText="SafeHome"
|
||||
leftLink={{ text: "Privacy Policy", href: "/privacy" }}
|
||||
rightLink={{ text: "Terms of Service", href: "/terms" }}
|
||||
/>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
|
||||
231
src/app/dashboard/page.tsx
Normal file
231
src/app/dashboard/page.tsx
Normal file
@@ -0,0 +1,231 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import Link from "next/link";
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import NavbarStyleApple from "@/components/navbar/NavbarStyleApple/NavbarStyleApple";
|
||||
import FooterLogoReveal from "@/components/sections/footer/FooterLogoReveal";
|
||||
|
||||
interface Kit {
|
||||
id: string;
|
||||
name: string;
|
||||
size: string;
|
||||
duration: string;
|
||||
purchaseDate: string;
|
||||
expiryDate: string;
|
||||
status: "active" | "expiring-soon" | "expired";
|
||||
}
|
||||
|
||||
export default function DashboardPage() {
|
||||
const [activeTab, setActiveTab] = useState<"overview" | "kits" | "orders" | "subscriptions">("overview");
|
||||
const [kits, setKits] = useState<Kit[]>([
|
||||
{
|
||||
id: "kit-1", name: "4-Person 24-Hour Kit", size: "4 Person", duration: "24 Hours", purchaseDate: "2025-01-15", expiryDate: "2030-01-15", status: "active"},
|
||||
{
|
||||
id: "kit-2", name: "4-Person 72-Hour Kit", size: "4 Person", duration: "72 Hours", purchaseDate: "2025-02-10", expiryDate: "2028-02-10", status: "expiring-soon"},
|
||||
]);
|
||||
|
||||
const navItems = [
|
||||
{ name: "Shop", id: "shop" },
|
||||
{ name: "How It Works", id: "how-it-works" },
|
||||
{ name: "About", id: "about" },
|
||||
{ name: "Reviews", id: "reviews" },
|
||||
{ name: "Contact", id: "contact" },
|
||||
];
|
||||
|
||||
const getStatusColor = (status: string) => {
|
||||
switch (status) {
|
||||
case "active":
|
||||
return "bg-accent/10 text-accent border-accent/30";
|
||||
case "expiring-soon":
|
||||
return "bg-orange-500/10 text-orange-500 border-orange-500/30";
|
||||
case "expired":
|
||||
return "bg-red-500/10 text-red-500 border-red-500/30";
|
||||
default:
|
||||
return "bg-foreground/5 text-foreground border-foreground/10";
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="icon-arrow"
|
||||
defaultTextAnimation="entrance-slide"
|
||||
borderRadius="rounded"
|
||||
contentWidth="compact"
|
||||
sizing="largeSizeMediumTitles"
|
||||
background="blurBottom"
|
||||
cardStyle="soft-shadow"
|
||||
primaryButtonStyle="flat"
|
||||
secondaryButtonStyle="solid"
|
||||
headingFontWeight="medium"
|
||||
>
|
||||
<div id="nav" data-section="nav">
|
||||
<NavbarStyleApple brandName="SafeHome" navItems={navItems} />
|
||||
</div>
|
||||
|
||||
<div className="min-h-screen py-12 md:py-24">
|
||||
<div className="mx-auto px-4 md:px-6 max-w-6xl">
|
||||
{/* Header */}
|
||||
<div className="flex justify-between items-start mb-12">
|
||||
<div>
|
||||
<h1 className="text-4xl md:text-5xl font-semibold mb-2">Account Dashboard</h1>
|
||||
<p className="text-foreground/75">Welcome back! Manage your emergency kits and subscriptions</p>
|
||||
</div>
|
||||
<div className="flex gap-3">
|
||||
<Link
|
||||
href="/kit-builder"
|
||||
className="px-6 py-3 bg-primary-cta text-background font-medium rounded-theme hover:opacity-90 transition-opacity"
|
||||
>
|
||||
New Kit
|
||||
</Link>
|
||||
<button className="px-6 py-3 bg-secondary-cta text-foreground font-medium rounded-theme hover:opacity-80 transition-opacity">
|
||||
Settings
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Tab Navigation */}
|
||||
<div className="flex gap-2 mb-8 border-b border-foreground/10">
|
||||
{(["overview", "kits", "orders", "subscriptions"] as const).map((tab) => (
|
||||
<button
|
||||
key={tab}
|
||||
onClick={() => setActiveTab(tab)}
|
||||
className={`px-6 py-4 font-medium border-b-2 transition-colors capitalize ${
|
||||
activeTab === tab
|
||||
? "border-primary-cta text-primary-cta"
|
||||
: "border-transparent text-foreground/60 hover:text-foreground"
|
||||
}`}
|
||||
>
|
||||
{tab.replace("-", " ")}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Overview Tab */}
|
||||
{activeTab === "overview" && (
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-12">
|
||||
<div className="bg-card rounded-theme p-6 shadow-soft-shadow">
|
||||
<p className="text-foreground/60 text-sm mb-2">Active Kits</p>
|
||||
<p className="text-4xl font-semibold">{kits.length}</p>
|
||||
<p className="text-foreground/60 text-sm mt-4">All kits accounted for</p>
|
||||
</div>
|
||||
<div className="bg-card rounded-theme p-6 shadow-soft-shadow">
|
||||
<p className="text-foreground/60 text-sm mb-2">Total Spent</p>
|
||||
<p className="text-4xl font-semibold">$438</p>
|
||||
<p className="text-foreground/60 text-sm mt-4">2 kits purchased</p>
|
||||
</div>
|
||||
<div className="bg-card rounded-theme p-6 shadow-soft-shadow">
|
||||
<p className="text-foreground/60 text-sm mb-2">Renewal Status</p>
|
||||
<p className="text-2xl font-semibold text-orange-500">1 Expiring</p>
|
||||
<p className="text-foreground/60 text-sm mt-4">Action needed soon</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Kits Tab */}
|
||||
{activeTab === "kits" && (
|
||||
<div className="space-y-4">
|
||||
{kits.map((kit) => (
|
||||
<div key={kit.id} className="bg-card rounded-theme p-6 shadow-soft-shadow">
|
||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-4 items-center">
|
||||
<div>
|
||||
<h3 className="font-semibold text-lg mb-1">{kit.name}</h3>
|
||||
<p className="text-foreground/60 text-sm">
|
||||
{kit.size} • {kit.duration}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-foreground/60 text-xs mb-1">Purchased</p>
|
||||
<p className="font-medium">{new Date(kit.purchaseDate).toLocaleDateString()}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-foreground/60 text-xs mb-1">Expires</p>
|
||||
<p className="font-medium">{new Date(kit.expiryDate).toLocaleDateString()}</p>
|
||||
</div>
|
||||
<div className="flex justify-between items-center gap-2">
|
||||
<div className={`px-4 py-2 rounded-theme border text-sm font-medium ${getStatusColor(kit.status)}`}>
|
||||
{kit.status === "active" ? "✓ Active" : kit.status === "expiring-soon" ? "⚠ Expiring Soon" : "✕ Expired"}
|
||||
</div>
|
||||
<button className="px-4 py-2 bg-secondary-cta text-foreground rounded-theme hover:opacity-80 transition-opacity text-sm font-medium">
|
||||
Details
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Orders Tab */}
|
||||
{activeTab === "orders" && (
|
||||
<div className="bg-card rounded-theme p-8 shadow-soft-shadow text-center">
|
||||
<p className="text-foreground/60 mb-4">Order History</p>
|
||||
<table className="w-full">
|
||||
<thead>
|
||||
<tr className="border-b border-foreground/10">
|
||||
<th className="text-left py-3 px-4 font-medium text-foreground/60 text-sm">Order ID</th>
|
||||
<th className="text-left py-3 px-4 font-medium text-foreground/60 text-sm">Date</th>
|
||||
<th className="text-left py-3 px-4 font-medium text-foreground/60 text-sm">Total</th>
|
||||
<th className="text-left py-3 px-4 font-medium text-foreground/60 text-sm">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr className="border-b border-foreground/5 hover:bg-background transition-colors">
|
||||
<td className="py-3 px-4">#ORD-2025-001</td>
|
||||
<td className="py-3 px-4">Feb 10, 2025</td>
|
||||
<td className="py-3 px-4">$149.00</td>
|
||||
<td className="py-3 px-4"><span className="bg-accent/10 text-accent px-3 py-1 rounded-full text-sm">Delivered</span></td>
|
||||
</tr>
|
||||
<tr className="border-b border-foreground/5 hover:bg-background transition-colors">
|
||||
<td className="py-3 px-4">#ORD-2025-002</td>
|
||||
<td className="py-3 px-4">Jan 15, 2025</td>
|
||||
<td className="py-3 px-4">$289.00</td>
|
||||
<td className="py-3 px-4"><span className="bg-accent/10 text-accent px-3 py-1 rounded-full text-sm">Delivered</span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Subscriptions Tab */}
|
||||
{activeTab === "subscriptions" && (
|
||||
<div className="space-y-4">
|
||||
<div className="bg-card rounded-theme p-6 shadow-soft-shadow">
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 items-center">
|
||||
<div>
|
||||
<h3 className="font-semibold text-lg mb-1">Food Renewal Subscription</h3>
|
||||
<p className="text-foreground/60 text-sm">4-Person Kit • Monthly</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-foreground/60 text-xs mb-1">Next Renewal</p>
|
||||
<p className="font-medium">March 15, 2025</p>
|
||||
</div>
|
||||
<div className="flex gap-2 justify-end">
|
||||
<button className="px-4 py-2 bg-secondary-cta text-foreground rounded-theme hover:opacity-80 transition-opacity text-sm font-medium">
|
||||
Manage
|
||||
</button>
|
||||
<button className="px-4 py-2 bg-red-500/10 text-red-500 rounded-theme hover:opacity-80 transition-opacity text-sm font-medium border border-red-500/30">
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-background-accent/30 border border-foreground/10 rounded-theme p-6">
|
||||
<p className="text-foreground/60 text-sm mb-4">💡 Tip</p>
|
||||
<p className="text-foreground text-sm">Subscriptions help you stay prepared by automatically renewing perishable items before expiration. You'll receive email reminders 30 days before renewal.</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="footer" data-section="footer">
|
||||
<FooterLogoReveal
|
||||
logoText="SafeHome"
|
||||
leftLink={{ text: "Privacy Policy", href: "/privacy" }}
|
||||
rightLink={{ text: "Terms of Service", href: "/terms" }}
|
||||
/>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
@@ -1,24 +1,124 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useMemo } from "react";
|
||||
import Link from "next/link";
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import NavbarStyleApple from "@/components/navbar/NavbarStyleApple/NavbarStyleApple";
|
||||
import HeroLogoBillboardSplit from "@/components/sections/hero/HeroLogoBillboardSplit";
|
||||
import FeatureCardTwentyOne from "@/components/sections/feature/FeatureCardTwentyOne";
|
||||
import MediaAbout from "@/components/sections/about/MediaAbout";
|
||||
import ProductCardFour from "@/components/sections/product/ProductCardFour";
|
||||
import SocialProofOne from "@/components/sections/socialProof/SocialProofOne";
|
||||
import FooterLogoReveal from "@/components/sections/footer/FooterLogoReveal";
|
||||
import Link from "next/link";
|
||||
import { ChevronDown, Plus, Minus, Check } from "lucide-react";
|
||||
|
||||
interface KitItem {
|
||||
id: string;
|
||||
name: string;
|
||||
category: "shared" | "consumable";
|
||||
basePrice: number;
|
||||
scalesByPerson: boolean;
|
||||
duration: "24h" | "48h" | "72h" | null;
|
||||
}
|
||||
|
||||
const BASE_ITEMS: KitItem[] = [
|
||||
{ id: "radio", name: "Emergency Radio", category: "shared", basePrice: 25, scalesByPerson: false, duration: null },
|
||||
{ id: "flashlight", name: "LED Flashlight", category: "shared", basePrice: 15, scalesByPerson: false, duration: null },
|
||||
{ id: "firstaid", name: "First Aid Kit", category: "shared", basePrice: 30, scalesByPerson: false, duration: null },
|
||||
{ id: "whistle", name: "Emergency Whistle", category: "shared", basePrice: 5, scalesByPerson: false, duration: null },
|
||||
{ id: "multitool", name: "Multi-Tool", category: "shared", basePrice: 20, scalesByPerson: false, duration: null },
|
||||
];
|
||||
|
||||
const DURATION_ITEMS: Record<string, KitItem[]> = {
|
||||
"24h": [
|
||||
{ id: "water-24h", name: "Drinking Water (1L per person)", category: "consumable", basePrice: 3, scalesByPerson: true, duration: "24h" },
|
||||
{ id: "food-24h", name: "Shelf-Stable Food Ration", category: "consumable", basePrice: 12, scalesByPerson: true, duration: "24h" },
|
||||
{ id: "hygiene-24h", name: "Hygiene Kit", category: "consumable", basePrice: 8, scalesByPerson: true, duration: "24h" },
|
||||
{ id: "blanket-24h", name: "Emergency Blanket", category: "consumable", basePrice: 10, scalesByPerson: true, duration: "24h" },
|
||||
],
|
||||
"48h": [
|
||||
{ id: "water-48h", name: "Drinking Water (2L per person)", category: "consumable", basePrice: 6, scalesByPerson: true, duration: "48h" },
|
||||
{ id: "food-48h", name: "Shelf-Stable Food Bundle", category: "consumable", basePrice: 24, scalesByPerson: true, duration: "48h" },
|
||||
{ id: "filter-48h", name: "Water Filter", category: "consumable", basePrice: 15, scalesByPerson: true, duration: "48h" },
|
||||
{ id: "hygiene-48h", name: "Extended Hygiene Kit", category: "consumable", basePrice: 12, scalesByPerson: true, duration: "48h" },
|
||||
{ id: "blanket-48h", name: "Heavy-Duty Emergency Blanket", category: "consumable", basePrice: 18, scalesByPerson: true, duration: "48h" },
|
||||
],
|
||||
"72h": [
|
||||
{ id: "water-72h", name: "Drinking Water (3L per person)", category: "consumable", basePrice: 9, scalesByPerson: true, duration: "72h" },
|
||||
{ id: "food-72h", name: "Complete Food Supply", category: "consumable", basePrice: 36, scalesByPerson: true, duration: "72h" },
|
||||
{ id: "filter-72h", name: "Advanced Water Filter", category: "consumable", basePrice: 20, scalesByPerson: true, duration: "72h" },
|
||||
{ id: "hygiene-72h", name: "Complete Hygiene Kit", category: "consumable", basePrice: 15, scalesByPerson: true, duration: "72h" },
|
||||
{ id: "shelter-72h", name: "Emergency Shelter Kit", category: "consumable", basePrice: 25, scalesByPerson: true, duration: "72h" },
|
||||
{ id: "medical-72h", name: "Extended Medical Kit", category: "consumable", basePrice: 40, scalesByPerson: true, duration: "72h" },
|
||||
],
|
||||
};
|
||||
|
||||
export default function KitBuilderPage() {
|
||||
const [personCount, setPersonCount] = useState(2);
|
||||
const [selectedDurations, setSelectedDurations] = useState<Set<string>>(new Set(["24h"]));
|
||||
|
||||
const KitBuilderPage = () => {
|
||||
const navItems = [
|
||||
{ name: "Shop", id: "shop" },
|
||||
{ name: "How It Works", id: "how-it-works" },
|
||||
{ name: "About", id: "about" },
|
||||
{ name: "Reviews", id: "reviews" },
|
||||
{ name: "Contact", id: "contact" }
|
||||
{ name: "Contact", id: "contact" },
|
||||
];
|
||||
|
||||
const toggleDuration = (duration: string) => {
|
||||
const newDurations = new Set(selectedDurations);
|
||||
if (newDurations.has(duration)) {
|
||||
newDurations.delete(duration);
|
||||
} else {
|
||||
newDurations.add(duration);
|
||||
}
|
||||
setSelectedDurations(newDurations);
|
||||
};
|
||||
|
||||
const kitItems = useMemo(() => {
|
||||
const items: KitItem[] = [...BASE_ITEMS];
|
||||
const seenIds = new Set(items.map((item) => item.id));
|
||||
|
||||
const durationArray = Array.from(selectedDurations).sort((a, b) => {
|
||||
const orderMap = { "24h": 0, "48h": 1, "72h": 2 };
|
||||
return (orderMap[a as keyof typeof orderMap] || 999) - (orderMap[b as keyof typeof orderMap] || 999);
|
||||
});
|
||||
|
||||
durationArray.forEach((duration) => {
|
||||
const durationItems = DURATION_ITEMS[duration] || [];
|
||||
durationItems.forEach((item) => {
|
||||
if (!seenIds.has(item.id)) {
|
||||
items.push(item);
|
||||
seenIds.add(item.id);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return items;
|
||||
}, [selectedDurations]);
|
||||
|
||||
const totalPrice = useMemo(() => {
|
||||
return kitItems.reduce((sum, item) => {
|
||||
const multiplier = item.scalesByPerson ? personCount : 1;
|
||||
return sum + item.basePrice * multiplier;
|
||||
}, 0);
|
||||
}, [kitItems, personCount]);
|
||||
|
||||
const kitSummary = useMemo(() => {
|
||||
const sharedCount = kitItems.filter((item) => item.category === "shared").length;
|
||||
const consumableCount = kitItems.filter((item) => item.category === "consumable").length;
|
||||
const selectedDurationLabel = Array.from(selectedDurations)
|
||||
.sort((a, b) => {
|
||||
const orderMap = { "24h": 0, "48h": 1, "72h": 2 };
|
||||
return (orderMap[a as keyof typeof orderMap] || 999) - (orderMap[b as keyof typeof orderMap] || 999);
|
||||
})
|
||||
.join(" + ");
|
||||
|
||||
return {
|
||||
people: personCount,
|
||||
duration: selectedDurationLabel || "No duration selected", sharedItems: sharedCount,
|
||||
consumableItems: consumableCount,
|
||||
total: kitItems.length,
|
||||
};
|
||||
}, [personCount, selectedDurations, kitItems]);
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="icon-arrow"
|
||||
@@ -33,232 +133,198 @@ const KitBuilderPage = () => {
|
||||
headingFontWeight="medium"
|
||||
>
|
||||
<div id="nav" data-section="nav">
|
||||
<NavbarStyleApple
|
||||
brandName="SafeHome"
|
||||
navItems={navItems}
|
||||
/>
|
||||
<NavbarStyleApple brandName="SafeHome" navItems={navItems} />
|
||||
</div>
|
||||
|
||||
<div id="kit-builder-hero" data-section="kit-builder-hero" className="py-20 md:py-32">
|
||||
<div id="hero" data-section="hero" className="py-20 md:py-32">
|
||||
<div className="mx-auto px-4 md:px-6">
|
||||
<HeroLogoBillboardSplit
|
||||
logoText="SafeHome"
|
||||
description="Build your perfect emergency kit in four simple steps. Customize by family size, duration, and specific needs. Our intelligent system ensures you never buy duplicate items."
|
||||
logoText="SafeHome Kit Builder"
|
||||
description="Customize your emergency kit by family size and duration. Our intelligent system prevents duplicate purchases when you expand—buy only what you need."
|
||||
background={{ variant: "radial-gradient" }}
|
||||
buttons={[
|
||||
{
|
||||
text: "Start Building",
|
||||
href: "/kit-builder"
|
||||
},
|
||||
{
|
||||
text: "View Completed Kits",
|
||||
href: "/shop"
|
||||
}
|
||||
{ text: "Back to Home", href: "/" },
|
||||
{ text: "View All Kits", href: "/shop" },
|
||||
]}
|
||||
buttonAnimation="slide-up"
|
||||
layoutOrder="default"
|
||||
imageSrc="http://img.b2bpic.net/free-photo/affectionate-little-girl-with-eyes-closed-embracing-her-father-home-mother-is-background_637285-3199.jpg?_wi=3"
|
||||
imageAlt="family emergency preparedness kit home"
|
||||
imageSrc="http://img.b2bpic.net/free-photo/affectionate-little-girl-with-eyes-closed-embracing-her-father-home-mother-is-background_637285-3199.jpg?_wi=1"
|
||||
imageAlt="Family using SafeHome Kit Builder"
|
||||
frameStyle="card"
|
||||
mediaAnimation="opacity"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="builder-steps" data-section="builder-steps" className="py-20 md:py-32">
|
||||
<div className="mx-auto px-4 md:px-6">
|
||||
<FeatureCardTwentyOne
|
||||
title="Four Steps to Your Perfect Kit"
|
||||
description="Our guided process ensures you build a kit tailored to your household. No overwhelm, no guesswork—just practical preparedness."
|
||||
tag="Build Your Kit"
|
||||
accordionItems={[
|
||||
{
|
||||
id: "1",
|
||||
title: "Step 1: Select Family Size",
|
||||
content: "Choose your household composition: 1-person solo, 2-person couple, 4-person family, or 5+ person household. Each option includes precisely scaled quantities of food, water, and supplies."
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
title: "Step 2: Choose Duration",
|
||||
content: "Select 24-hour, 48-hour, or 72-hour preparedness levels. Higher durations include more food, water filters, and medical supplies. All durations include essential shared tools."
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
title: "Step 3: Add Extensions",
|
||||
content: "Extend your kit without waste. Add 48-hour or 72-hour extensions and pay only for new consumables. Your shared items (radio, flashlight, first aid) stay with you."
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
title: "Step 4: Review & Order",
|
||||
content: "See your complete kit breakdown with total costs, individual items, and shared components clearly labeled. Choose standard purchase or subscription renewal for food items."
|
||||
}
|
||||
]}
|
||||
imageSrc="http://img.b2bpic.net/free-photo/high-view-father-son-playing-with-toys_23-2148500810.jpg?_wi=3"
|
||||
imageAlt="step by step instruction guide visual"
|
||||
mediaAnimation="slide-up"
|
||||
useInvertedBackground={false}
|
||||
mediaPosition="right"
|
||||
buttons={[
|
||||
{
|
||||
text: "Begin Building",
|
||||
href: "/kit-builder"
|
||||
}
|
||||
]}
|
||||
buttonAnimation="slide-up"
|
||||
/>
|
||||
<div id="builder" data-section="builder" className="py-20 md:py-32">
|
||||
<div className="mx-auto px-4 md:px-6 max-w-4xl">
|
||||
<div className="bg-card rounded-lg p-8 shadow-lg">
|
||||
<h2 className="text-3xl font-bold mb-8">Build Your Perfect Kit</h2>
|
||||
|
||||
<div className="grid md:grid-cols-2 gap-8 mb-8">
|
||||
{/* Person Count Selector */}
|
||||
<div>
|
||||
<label className="block text-lg font-semibold mb-4">Family Size</label>
|
||||
<div className="flex items-center gap-4">
|
||||
<button
|
||||
onClick={() => setPersonCount(Math.max(1, personCount - 1))}
|
||||
className="p-2 rounded-lg bg-secondary-button hover:opacity-80 transition-opacity"
|
||||
aria-label="Decrease person count"
|
||||
>
|
||||
<Minus size={20} />
|
||||
</button>
|
||||
<div className="flex-1 bg-background rounded-lg p-4 text-center">
|
||||
<span className="text-2xl font-bold">{personCount}</span>
|
||||
<span className="text-sm opacity-70 ml-2">people</span>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => setPersonCount(Math.min(8, personCount + 1))}
|
||||
className="p-2 rounded-lg bg-secondary-button hover:opacity-80 transition-opacity"
|
||||
aria-label="Increase person count"
|
||||
>
|
||||
<Plus size={20} />
|
||||
</button>
|
||||
</div>
|
||||
<p className="text-sm opacity-70 mt-2">1-8 people (8+ coming soon)</p>
|
||||
</div>
|
||||
|
||||
{/* Duration Selector */}
|
||||
<div>
|
||||
<label className="block text-lg font-semibold mb-4">Duration</label>
|
||||
<div className="space-y-2">
|
||||
{["24h", "48h", "72h"].map((duration) => (
|
||||
<button
|
||||
key={duration}
|
||||
onClick={() => toggleDuration(duration)}
|
||||
className={`w-full p-3 rounded-lg border-2 transition-all flex items-center justify-between ${
|
||||
selectedDurations.has(duration)
|
||||
? "border-primary-cta bg-primary-cta bg-opacity-10"
|
||||
: "border-card bg-background hover:border-accent"
|
||||
}`}
|
||||
>
|
||||
<span className="font-medium">
|
||||
{duration === "24h" && "24-Hour Kit"}
|
||||
{duration === "48h" && "48-Hour Extension"}
|
||||
{duration === "72h" && "72-Hour Extension"}
|
||||
</span>
|
||||
{selectedDurations.has(duration) && <Check size={20} className="text-primary-cta" />}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Kit Summary */}
|
||||
<div className="bg-background rounded-lg p-6 mb-8">
|
||||
<h3 className="text-xl font-semibold mb-4">Your Kit Summary</h3>
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
||||
<div>
|
||||
<p className="text-sm opacity-70">People</p>
|
||||
<p className="text-2xl font-bold">{kitSummary.people}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm opacity-70">Duration</p>
|
||||
<p className="text-sm font-semibold">{kitSummary.duration}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm opacity-70">Shared Items</p>
|
||||
<p className="text-2xl font-bold">{kitSummary.sharedItems}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm opacity-70">Consumables</p>
|
||||
<p className="text-2xl font-bold">{kitSummary.consumableItems}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Kit Items Breakdown */}
|
||||
<div className="mb-8">
|
||||
<h3 className="text-xl font-semibold mb-4">What's in Your Kit</h3>
|
||||
<div className="space-y-2">
|
||||
{kitItems.map((item) => {
|
||||
const multiplier = item.scalesByPerson ? personCount : 1;
|
||||
const itemPrice = item.basePrice * multiplier;
|
||||
return (
|
||||
<div key={item.id} className="flex justify-between items-center p-3 bg-background rounded-lg border border-card">
|
||||
<div className="flex items-start gap-3 flex-1">
|
||||
<div className="mt-1">
|
||||
{item.category === "shared" ? (
|
||||
<div className="w-4 h-4 rounded-full bg-accent" title="Shared item - not duplicated"></div>
|
||||
) : (
|
||||
<div className="w-4 h-4 rounded-full bg-accent opacity-50" title="Per-person item"></div>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<p className="font-medium">{item.name}</p>
|
||||
{item.scalesByPerson && (
|
||||
<p className="text-xs opacity-60">× {personCount} person{personCount !== 1 ? "s" : ""}</p>
|
||||
)}
|
||||
{item.category === "shared" && <p className="text-xs opacity-60">Shared (one-time)</p>}
|
||||
</div>
|
||||
</div>
|
||||
<p className="font-semibold whitespace-nowrap ml-4">${itemPrice.toFixed(2)}</p>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Pricing and CTA */}
|
||||
<div className="border-t border-card pt-8">
|
||||
<div className="flex justify-between items-center mb-6">
|
||||
<span className="text-2xl font-bold">Total Price:</span>
|
||||
<span className="text-3xl font-bold text-primary-cta">${totalPrice.toFixed(2)}</span>
|
||||
</div>
|
||||
<div className="flex gap-4">
|
||||
<Link
|
||||
href="/checkout"
|
||||
className="flex-1 bg-primary-cta text-white py-3 px-6 rounded-lg font-semibold text-center hover:opacity-90 transition-opacity"
|
||||
>
|
||||
Proceed to Checkout
|
||||
</Link>
|
||||
<Link
|
||||
href="/"
|
||||
className="flex-1 border-2 border-secondary-cta text-foreground py-3 px-6 rounded-lg font-semibold text-center hover:bg-background transition-colors"
|
||||
>
|
||||
Continue Shopping
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Info Box */}
|
||||
<div className="mt-8 p-4 bg-accent bg-opacity-10 rounded-lg border border-accent border-opacity-30">
|
||||
<p className="text-sm">
|
||||
<span className="font-semibold">Smart Deduplication:</span> When you select multiple durations, shared items (radio, flashlight, first-aid kit) are included only once. You're only paying for what you need.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="popular-builds" data-section="popular-builds" className="py-20 md:py-32">
|
||||
<div className="mx-auto px-4 md:px-6">
|
||||
<ProductCardFour
|
||||
title="Popular Kit Configurations"
|
||||
description="Start with one of our most popular builds and customize from there"
|
||||
tag="Quick Start"
|
||||
products={[
|
||||
{
|
||||
id: "build-2p-24h",
|
||||
name: "2-Person 24-Hour Kit",
|
||||
price: "$89",
|
||||
variant: "Perfect for couples",
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/sporty-girl-packing-bag-training-sports-girl-going-training-preparing-training_169016-67560.jpg?_wi=3",
|
||||
imageAlt: "compact emergency kit organized supplies"
|
||||
},
|
||||
{
|
||||
id: "build-4p-24h",
|
||||
name: "4-Person 24-Hour Kit",
|
||||
price: "$149",
|
||||
variant: "Ideal for families",
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/young-family-enjoying-trips_23-2149176539.jpg?_wi=4",
|
||||
imageAlt: "family emergency kit four people"
|
||||
},
|
||||
{
|
||||
id: "build-4p-72h",
|
||||
name: "4-Person 72-Hour Kit",
|
||||
price: "$299",
|
||||
variant: "Extended family protection",
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/luggage-seen-from-rear-car-window_23-2150934321.jpg?_wi=3",
|
||||
imageAlt: "72 hour emergency kit family"
|
||||
},
|
||||
{
|
||||
id: "build-1p-ext",
|
||||
name: "1-Person Extended Bundle",
|
||||
price: "$179",
|
||||
variant: "Expandable solo kit",
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/top-view-storage-devices-glasses_23-2149319333.jpg?_wi=3",
|
||||
imageAlt: "individual emergency kit one person"
|
||||
}
|
||||
]}
|
||||
gridVariant="uniform-all-items-equal"
|
||||
animationType="slide-up"
|
||||
useInvertedBackground={false}
|
||||
textboxLayout="default"
|
||||
buttons={[
|
||||
{
|
||||
text: "Start Customizing",
|
||||
href: "/kit-builder"
|
||||
}
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="how-modularity-works" data-section="how-modularity-works" className="py-20 md:py-32">
|
||||
<div className="mx-auto px-4 md:px-6">
|
||||
<FeatureCardTwentyOne
|
||||
title="Smart Modular Design Explained"
|
||||
description="Our intelligent system prevents duplicate items when you expand your kit. See exactly what you're buying and why."
|
||||
tag="Smart Expansion"
|
||||
accordionItems={[
|
||||
{
|
||||
id: "1",
|
||||
title: "Shared Items (Purchased Once)",
|
||||
content: "Every kit includes essential shared tools: emergency radio, flashlight with batteries, multi-tool, emergency whistle, first-aid kit, and emergency blankets. When you upgrade or extend, these aren't duplicated."
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
title: "Per-Person Consumables (Scale by Size)",
|
||||
content: "Food, water, and hygiene items scale with household size. A 2-person kit has exactly half the consumables of a 4-person kit. Pay only for what your family needs."
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
title: "Duration Add-Ons (Incremental Extensions)",
|
||||
content: "Going from 24 to 72 hours? Add extension packages that include only additional food, water filters, and supplies. Your shared tools remain unchanged."
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
title: "Transparent Pricing & Breakdown",
|
||||
content: "Your order shows shared items, per-person supplies, and extensions separately. You'll know exactly what you're buying and see the cost breakdown before checkout."
|
||||
}
|
||||
]}
|
||||
imageSrc="http://img.b2bpic.net/free-psd/origami-poster-template-theme_23-2148584260.jpg?_wi=2"
|
||||
imageAlt="product components breakdown diagram"
|
||||
mediaAnimation="opacity"
|
||||
useInvertedBackground={false}
|
||||
mediaPosition="left"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="builder-benefits" data-section="builder-benefits" className="py-20 md:py-32">
|
||||
<div id="cta-section" data-section="cta-section" className="py-20 md:py-32">
|
||||
<div className="mx-auto px-4 md:px-6">
|
||||
<MediaAbout
|
||||
title="Why Use SafeHome's Kit Builder"
|
||||
description="Our builder eliminates guesswork and ensures you get exactly what your family needs—no more, no less. Customize with confidence."
|
||||
tag="Why Build Custom"
|
||||
imageSrc="http://img.b2bpic.net/free-photo/portrait-woman-home-yawning_23-2148923998.jpg?_wi=3"
|
||||
imageAlt="family feeling safe secure prepared"
|
||||
useInvertedBackground={true}
|
||||
title="Questions About Your Kit?"
|
||||
description="Our team is here to help you build the perfect emergency kit for your family. Contact us for personalized recommendations."
|
||||
imageSrc="http://img.b2bpic.net/free-photo/parents-little-daughters-with-documents_1398-4944.jpg?_wi=1"
|
||||
imageAlt="SafeHome customer support"
|
||||
useInvertedBackground={false}
|
||||
buttons={[
|
||||
{
|
||||
text: "Start Building Now",
|
||||
href: "/kit-builder"
|
||||
}
|
||||
{ text: "Contact Support", href: "#contact" },
|
||||
{ text: "View FAQ", href: "/#faq" },
|
||||
]}
|
||||
buttonAnimation="slide-up"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="trust-builders" data-section="trust-builders" className="py-20 md:py-32">
|
||||
<div className="mx-auto px-4 md:px-6">
|
||||
<SocialProofOne
|
||||
title="Trusted by Thousands of Builders"
|
||||
description="Families across the country use SafeHome's Kit Builder to create their perfect emergency preparedness solution"
|
||||
tag="Building Community"
|
||||
textboxLayout="default"
|
||||
useInvertedBackground={true}
|
||||
names={[
|
||||
"Family Safety First",
|
||||
"Emergency Ready",
|
||||
"Home Protection",
|
||||
"Peace of Mind",
|
||||
"Prepared Families",
|
||||
"Trust & Security",
|
||||
"Ready & Resilient",
|
||||
"Safe Households"
|
||||
]}
|
||||
speed={40}
|
||||
showCard={true}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="footer" data-section="footer">
|
||||
<FooterLogoReveal
|
||||
logoText="SafeHome"
|
||||
leftLink={{
|
||||
text: "Privacy Policy",
|
||||
href: "/privacy"
|
||||
}}
|
||||
rightLink={{
|
||||
text: "Terms of Service",
|
||||
href: "/terms"
|
||||
}}
|
||||
leftLink={{ text: "Privacy Policy", href: "/privacy" }}
|
||||
rightLink={{ text: "Terms of Service", href: "/terms" }}
|
||||
/>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default KitBuilderPage;
|
||||
}
|
||||
159
src/app/login/page.tsx
Normal file
159
src/app/login/page.tsx
Normal file
@@ -0,0 +1,159 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import Link from "next/link";
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import NavbarStyleApple from "@/components/navbar/NavbarStyleApple/NavbarStyleApple";
|
||||
import FooterLogoReveal from "@/components/sections/footer/FooterLogoReveal";
|
||||
|
||||
export default function LoginPage() {
|
||||
const [formData, setFormData] = useState({
|
||||
email: "", password: "", rememberMe: false,
|
||||
});
|
||||
const [error, setError] = useState("");
|
||||
const [success, setSuccess] = useState(false);
|
||||
|
||||
const navItems = [
|
||||
{ name: "Shop", id: "shop" },
|
||||
{ name: "How It Works", id: "how-it-works" },
|
||||
{ name: "About", id: "about" },
|
||||
{ name: "Reviews", id: "reviews" },
|
||||
{ name: "Contact", id: "contact" },
|
||||
];
|
||||
|
||||
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const { name, value, type, checked } = e.target;
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
[name]: type === "checkbox" ? checked : value,
|
||||
}));
|
||||
setError("");
|
||||
};
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
|
||||
if (!formData.email || !formData.password) {
|
||||
setError("Email and password are required");
|
||||
return;
|
||||
}
|
||||
|
||||
setSuccess(true);
|
||||
setFormData({
|
||||
email: "", password: "", rememberMe: false,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="icon-arrow"
|
||||
defaultTextAnimation="entrance-slide"
|
||||
borderRadius="rounded"
|
||||
contentWidth="compact"
|
||||
sizing="largeSizeMediumTitles"
|
||||
background="blurBottom"
|
||||
cardStyle="soft-shadow"
|
||||
primaryButtonStyle="flat"
|
||||
secondaryButtonStyle="solid"
|
||||
headingFontWeight="medium"
|
||||
>
|
||||
<div id="nav" data-section="nav">
|
||||
<NavbarStyleApple brandName="SafeHome" navItems={navItems} />
|
||||
</div>
|
||||
|
||||
<div className="min-h-screen py-20 md:py-32">
|
||||
<div className="mx-auto px-4 md:px-6 max-w-md">
|
||||
<div className="bg-card rounded-theme p-8 shadow-soft-shadow">
|
||||
<h1 className="text-3xl md:text-4xl font-semibold mb-2">Sign In</h1>
|
||||
<p className="text-foreground/75 mb-8">Access your SafeHome account and manage your emergency kits</p>
|
||||
|
||||
{success && (
|
||||
<div className="bg-accent/10 border border-accent rounded-theme p-4 mb-6">
|
||||
<p className="text-accent font-medium">✓ Login successful! Redirecting to dashboard...</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{error && (
|
||||
<div className="bg-red-500/10 border border-red-500 rounded-theme p-4 mb-6">
|
||||
<p className="text-red-500 text-sm">{error}</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<form onSubmit={handleSubmit} className="space-y-5">
|
||||
<div>
|
||||
<label htmlFor="email" className="block text-sm font-medium mb-2">
|
||||
Email Address
|
||||
</label>
|
||||
<input
|
||||
type="email"
|
||||
id="email"
|
||||
name="email"
|
||||
value={formData.email}
|
||||
onChange={handleChange}
|
||||
placeholder="your@email.com"
|
||||
className="w-full px-4 py-2 rounded-theme bg-background border border-foreground/10 text-foreground placeholder:text-foreground/50 focus:outline-none focus:ring-2 focus:ring-primary-cta"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="flex justify-between items-center mb-2">
|
||||
<label htmlFor="password" className="block text-sm font-medium">
|
||||
Password
|
||||
</label>
|
||||
<Link href="/forgot-password" className="text-xs text-primary-cta hover:underline">
|
||||
Forgot password?
|
||||
</Link>
|
||||
</div>
|
||||
<input
|
||||
type="password"
|
||||
id="password"
|
||||
name="password"
|
||||
value={formData.password}
|
||||
onChange={handleChange}
|
||||
placeholder="Enter your password"
|
||||
className="w-full px-4 py-2 rounded-theme bg-background border border-foreground/10 text-foreground placeholder:text-foreground/50 focus:outline-none focus:ring-2 focus:ring-primary-cta"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="rememberMe"
|
||||
name="rememberMe"
|
||||
checked={formData.rememberMe}
|
||||
onChange={handleChange}
|
||||
className="w-4 h-4 rounded border-foreground/20"
|
||||
/>
|
||||
<label htmlFor="rememberMe" className="ml-3 text-sm">
|
||||
Remember me on this device
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
className="w-full bg-primary-cta text-background font-medium py-3 rounded-theme hover:opacity-90 transition-opacity"
|
||||
>
|
||||
Sign In
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<p className="text-center text-sm text-foreground/75 mt-6">
|
||||
Don't have an account?{" "}
|
||||
<Link href="/register" className="text-primary-cta hover:underline font-medium">
|
||||
Create Account
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="footer" data-section="footer">
|
||||
<FooterLogoReveal
|
||||
logoText="SafeHome"
|
||||
leftLink={{ text: "Privacy Policy", href: "/privacy" }}
|
||||
rightLink={{ text: "Terms of Service", href: "/terms" }}
|
||||
/>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
@@ -67,7 +67,8 @@ export default function HomePage() {
|
||||
textboxLayout="default"
|
||||
useInvertedBackground={true}
|
||||
names={[
|
||||
"Family Safety First", "Emergency Ready", "Home Protection", "Peace of Mind", "Prepared Families", "Trust & Security", "Ready & Resilient", "Safe Households"]}
|
||||
"Family Safety First", "Emergency Ready", "Home Protection", "Peace of Mind", "Prepared Families", "Trust & Security", "Ready & Resilient", "Safe Households"
|
||||
]}
|
||||
speed={40}
|
||||
showCard={true}
|
||||
/>
|
||||
@@ -82,13 +83,17 @@ export default function HomePage() {
|
||||
tag="How It Works"
|
||||
accordionItems={[
|
||||
{
|
||||
id: "1", title: "Select Your Family Size", content: "Choose from 1-person to 5+ household options. Our kits are designed for your specific family composition, ensuring everyone has what they need."},
|
||||
id: "1", title: "Select Your Family Size", content: "Choose from 1-person to 5+ household options. Our kits are designed for your specific family composition, ensuring everyone has what they need."
|
||||
},
|
||||
{
|
||||
id: "2", title: "Pick Your Duration", content: "Start with 24-hour, 48-hour, or 72-hour kits. Each duration includes carefully curated items - food, water, first aid, shelter essentials, and tools."},
|
||||
id: "2", title: "Pick Your Duration", content: "Start with 24-hour, 48-hour, or 72-hour kits. Each duration includes carefully curated items - food, water, first aid, shelter essentials, and tools."
|
||||
},
|
||||
{
|
||||
id: "3", title: "Expand Modularly", content: "Add 48-hour or 72-hour extensions without duplicating shared items like radios or first-aid kits. Only new supplies are added to your kit."},
|
||||
id: "3", title: "Expand Modularly", content: "Add 48-hour or 72-hour extensions without duplicating shared items like radios or first-aid kits. Only new supplies are added to your kit."
|
||||
},
|
||||
{
|
||||
id: "4", title: "Set & Forget with Subscriptions", content: "Activate food renewal subscriptions to automatically refresh perishables. We notify you before expiration dates and handle the rest."},
|
||||
id: "4", title: "Set & Forget with Subscriptions", content: "Activate food renewal subscriptions to automatically refresh perishables. We notify you before expiration dates and handle the rest."
|
||||
},
|
||||
]}
|
||||
imageSrc="http://img.b2bpic.net/free-photo/high-view-father-son-playing-with-toys_23-2148500810.jpg?_wi=1"
|
||||
imageAlt="SafeHome kit customization process"
|
||||
@@ -112,18 +117,21 @@ export default function HomePage() {
|
||||
textboxLayout="default"
|
||||
products={[
|
||||
{
|
||||
id: "kit-2p-24h", name: "2-Person 24-Hour Kit", price: "$89", variant: "Couples & Small Households", imageSrc: "http://img.b2bpic.net/free-photo/sporty-girl-packing-bag-training-sports-girl-going-training-preparing-training_169016-67560.jpg?_wi=1", imageAlt: "2-person 24-hour emergency kit"},
|
||||
id: "kit-2p-24h", name: "2-Person 24-Hour Kit", price: "$89", variant: "Couples & Small Households", imageSrc: "http://img.b2bpic.net/free-photo/sporty-girl-packing-bag-training-sports-girl-going-training-preparing-training_169016-67560.jpg?_wi=1", imageAlt: "2-person 24-hour emergency kit"
|
||||
},
|
||||
{
|
||||
id: "kit-4p-24h", name: "4-Person 24-Hour Kit", price: "$149", variant: "Families with Children", imageSrc: "http://img.b2bpic.net/free-photo/young-family-enjoying-trips_23-2149176539.jpg?_wi=1", imageAlt: "4-person 24-hour emergency kit"},
|
||||
id: "kit-4p-24h", name: "4-Person 24-Hour Kit", price: "$149", variant: "Families with Children", imageSrc: "http://img.b2bpic.net/free-photo/young-family-enjoying-trips_23-2149176539.jpg?_wi=1", imageAlt: "4-person 24-hour emergency kit"
|
||||
},
|
||||
{
|
||||
id: "kit-4p-72h", name: "4-Person 72-Hour Kit", price: "$299", variant: "Complete Family Preparedness", imageSrc: "http://img.b2bpic.net/free-photo/luggage-seen-from-rear-car-window_23-2150934321.jpg?_wi=1", imageAlt: "4-person 72-hour emergency kit"},
|
||||
id: "kit-4p-72h", name: "4-Person 72-Hour Kit", price: "$299", variant: "Complete Family Preparedness", imageSrc: "http://img.b2bpic.net/free-photo/luggage-seen-from-rear-car-window_23-2150934321.jpg?_wi=1", imageAlt: "4-person 72-hour emergency kit"
|
||||
},
|
||||
{
|
||||
id: "kit-1p-extended", name: "1-Person Extended Bundle", price: "$179", variant: "Individual with Expandability", imageSrc: "http://img.b2bpic.net/free-photo/top-view-storage-devices-glasses_23-2149319333.jpg?_wi=1", imageAlt: "1-person extended emergency kit"},
|
||||
id: "kit-1p-extended", name: "1-Person Extended Bundle", price: "$179", variant: "Individual with Expandability", imageSrc: "http://img.b2bpic.net/free-photo/top-view-storage-devices-glasses_23-2149319333.jpg?_wi=1", imageAlt: "1-person extended emergency kit"
|
||||
},
|
||||
]}
|
||||
gridVariant="uniform-all-items-equal"
|
||||
animationType="slide-up"
|
||||
useInvertedBackground={false}
|
||||
cardClassName="ring-2 ring-blue-500 ring-offset-2"
|
||||
buttons={[
|
||||
{ text: "View All Kits", href: "/shop" },
|
||||
]}
|
||||
@@ -156,13 +164,17 @@ export default function HomePage() {
|
||||
tag="Smart Expansion"
|
||||
accordionItems={[
|
||||
{
|
||||
id: "1", title: "Shared Items (One-Time Purchase)", content: "Each kit includes essential tools shared by everyone: emergency radio, flashlight with batteries, first-aid kit, emergency whistle, and multi-tool. When you expand, these aren't duplicated."},
|
||||
id: "1", title: "Shared Items (One-Time Purchase)", content: "Each kit includes essential tools shared by everyone: emergency radio, flashlight with batteries, first-aid kit, emergency whistle, and multi-tool. When you expand, these aren't duplicated."
|
||||
},
|
||||
{
|
||||
id: "2", title: "Per-Person Consumables (Scale by Family Size)", content: "Food, water, and hygiene items scale with your household. A 24-hour kit for 2 people has half the consumables of a 4-person kit. Pay only for what you need."},
|
||||
id: "2", title: "Per-Person Consumables (Scale by Family Size)", content: "Food, water, and hygiene items scale with your household. A 24-hour kit for 2 people has half the consumables of a 4-person kit. Pay only for what you need."
|
||||
},
|
||||
{
|
||||
id: "3", title: "Duration Extensions (Add Incrementally)", content: "Extend from 24 to 48 hours, or 48 to 72 hours. Extensions add only additional food, water filters, and supplies—never duplicate the shared items you already have."},
|
||||
id: "3", title: "Duration Extensions (Add Incrementally)", content: "Extend from 24 to 48 hours, or 48 to 72 hours. Extensions add only additional food, water filters, and supplies—never duplicate the shared items you already have."
|
||||
},
|
||||
{
|
||||
id: "4", title: "Transparent Kit Breakdown", content: "Every product page shows exactly what's shared and what's per-person. You'll know precisely what you're buying and why, with zero guesswork."},
|
||||
id: "4", title: "Transparent Kit Breakdown", content: "Every product page shows exactly what's shared and what's per-person. You'll know precisely what you're buying and why, with zero guesswork."
|
||||
},
|
||||
]}
|
||||
imageSrc="http://img.b2bpic.net/free-psd/origami-poster-template-theme_23-2148584260.jpg?_wi=1"
|
||||
imageAlt="SafeHome modular kit component breakdown"
|
||||
@@ -182,16 +194,20 @@ export default function HomePage() {
|
||||
testimonials={[
|
||||
{
|
||||
id: "1", name: "Michelle Rodriguez", role: "Mother of Two", company: "Colorado", rating: 5,
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/side-view-beautiful-woman-with-folded-arms-looking-camera_23-2147876783.jpg?_wi=1", imageAlt: "woman portrait confident mother"},
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/side-view-beautiful-woman-with-folded-arms-looking-camera_23-2147876783.jpg?_wi=1", imageAlt: "woman portrait confident mother"
|
||||
},
|
||||
{
|
||||
id: "2", name: "David Chen", role: "Homeowner", company: "California", rating: 5,
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/portrait-handsome-man-sitting-sofa_329181-2737.jpg?_wi=1", imageAlt: "man portrait confident homeowner"},
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/portrait-handsome-man-sitting-sofa_329181-2737.jpg?_wi=1", imageAlt: "man portrait confident homeowner"
|
||||
},
|
||||
{
|
||||
id: "3", name: "Sarah Williams", role: "Family of Four", company: "Texas", rating: 5,
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/young-female-blazer-beauty-blonde_1139-773.jpg?_wi=1", imageAlt: "woman portrait family mother"},
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/young-female-blazer-beauty-blonde_1139-773.jpg?_wi=1", imageAlt: "woman portrait family mother"
|
||||
},
|
||||
{
|
||||
id: "4", name: "James Park", role: "Apartment Dweller", company: "New York", rating: 5,
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/man-looks-seriously-has-strict-expression-gazes-directly-camera-wears-blue-velvet-shirt-smirks-face-isolated-beige_273609-54464.jpg?_wi=1", imageAlt: "man portrait urban apartment dweller"},
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/man-looks-seriously-has-strict-expression-gazes-directly-camera-wears-blue-velvet-shirt-smirks-face-isolated-beige_273609-54464.jpg?_wi=1", imageAlt: "man portrait urban apartment dweller"
|
||||
},
|
||||
]}
|
||||
kpiItems={[
|
||||
{ value: "15,000+", label: "Families Prepared" },
|
||||
@@ -216,21 +232,29 @@ export default function HomePage() {
|
||||
faqsAnimation="slide-up"
|
||||
faqs={[
|
||||
{
|
||||
id: "1", title: "What's included in a SafeHome kit?", content: "Every kit includes water (1 liter per person per day), shelf-stable food, first-aid supplies, emergency radio, flashlight, batteries, whistle, multi-tool, emergency blanket, hygiene items, and instructional materials. Exact contents vary by duration (24/48/72 hours)."},
|
||||
id: "1", title: "What's included in a SafeHome kit?", content: "Every kit includes water (1 liter per person per day), shelf-stable food, first-aid supplies, emergency radio, flashlight, batteries, whistle, multi-tool, emergency blanket, hygiene items, and instructional materials. Exact contents vary by duration (24/48/72 hours)."
|
||||
},
|
||||
{
|
||||
id: "2", title: "Can I customize my kit?", content: "Yes! Use our Kit Builder to select family size, duration, and add extensions. You can also add individual items from our product catalog to tailor your kit to your family's specific needs."},
|
||||
id: "2", title: "Can I customize my kit?", content: "Yes! Use our Kit Builder to select family size, duration, and add extensions. You can also add individual items from our product catalog to tailor your kit to your family's specific needs."
|
||||
},
|
||||
{
|
||||
id: "3", title: "How does the no-duplicate system work?", content: "When you extend your kit (e.g., from 24 to 72 hours), we only add additional consumables and expansion items. Shared items like your radio and first-aid kit aren't duplicated—you keep the ones you have."},
|
||||
id: "3", title: "How does the no-duplicate system work?", content: "When you extend your kit (e.g., from 24 to 72 hours), we only add additional consumables and expansion items. Shared items like your radio and first-aid kit aren't duplicated—you keep the ones you have."
|
||||
},
|
||||
{
|
||||
id: "4", title: "What's the subscription service?", content: "Our subscription automatically renews perishable food items before expiration. You set the frequency, we handle the shipping. Plus, get notifications about upcoming expiration dates and renewal shipments."},
|
||||
id: "4", title: "What's the subscription service?", content: "Our subscription automatically renews perishable food items before expiration. You set the frequency, we handle the shipping. Plus, get notifications about upcoming expiration dates and renewal shipments."
|
||||
},
|
||||
{
|
||||
id: "5", title: "How long do supplies last?", content: "Most items have 5-10 year shelf lives. Our subscription service ensures you refresh food items regularly. We include expiration dates on all products and guide you on proper storage."},
|
||||
id: "5", title: "How long do supplies last?", content: "Most items have 5-10 year shelf lives. Our subscription service ensures you refresh food items regularly. We include expiration dates on all products and guide you on proper storage."
|
||||
},
|
||||
{
|
||||
id: "6", title: "Do you offer international shipping?", content: "Currently, we ship to all US addresses. International orders coming soon. Sign up for our newsletter to be notified when we expand."},
|
||||
id: "6", title: "Do you offer international shipping?", content: "Currently, we ship to all US addresses. International orders coming soon. Sign up for our newsletter to be notified when we expand."
|
||||
},
|
||||
{
|
||||
id: "7", title: "What's your return policy?", content: "30-day money-back guarantee on all kits. If you're not satisfied for any reason, contact our support team for a full refund. No questions asked."},
|
||||
id: "7", title: "What's your return policy?", content: "30-day money-back guarantee on all kits. If you're not satisfied for any reason, contact our support team for a full refund. No questions asked."
|
||||
},
|
||||
{
|
||||
id: "8", title: "How do I track expiration dates?", content: "Your SafeHome dashboard shows all items with expiration dates. Get email reminders 30 days before expiration. Activate subscriptions to auto-renew without thinking about it."},
|
||||
id: "8", title: "How do I track expiration dates?", content: "Your SafeHome dashboard shows all items with expiration dates. Get email reminders 30 days before expiration. Activate subscriptions to auto-renew without thinking about it."
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
202
src/app/register/page.tsx
Normal file
202
src/app/register/page.tsx
Normal file
@@ -0,0 +1,202 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import Link from "next/link";
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import NavbarStyleApple from "@/components/navbar/NavbarStyleApple/NavbarStyleApple";
|
||||
import FooterLogoReveal from "@/components/sections/footer/FooterLogoReveal";
|
||||
import MediaAbout from "@/components/sections/about/MediaAbout";
|
||||
|
||||
export default function RegisterPage() {
|
||||
const [formData, setFormData] = useState({
|
||||
name: "", email: "", password: "", confirmPassword: "", agreeTerms: false,
|
||||
});
|
||||
const [error, setError] = useState("");
|
||||
const [success, setSuccess] = useState(false);
|
||||
|
||||
const navItems = [
|
||||
{ name: "Shop", id: "shop" },
|
||||
{ name: "How It Works", id: "how-it-works" },
|
||||
{ name: "About", id: "about" },
|
||||
{ name: "Reviews", id: "reviews" },
|
||||
{ name: "Contact", id: "contact" },
|
||||
];
|
||||
|
||||
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const { name, value, type, checked } = e.target;
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
[name]: type === "checkbox" ? checked : value,
|
||||
}));
|
||||
setError("");
|
||||
};
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
|
||||
if (!formData.name || !formData.email || !formData.password) {
|
||||
setError("All fields are required");
|
||||
return;
|
||||
}
|
||||
|
||||
if (formData.password !== formData.confirmPassword) {
|
||||
setError("Passwords do not match");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!formData.agreeTerms) {
|
||||
setError("You must agree to the terms and conditions");
|
||||
return;
|
||||
}
|
||||
|
||||
setSuccess(true);
|
||||
setFormData({
|
||||
name: "", email: "", password: "", confirmPassword: "", agreeTerms: false,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="icon-arrow"
|
||||
defaultTextAnimation="entrance-slide"
|
||||
borderRadius="rounded"
|
||||
contentWidth="compact"
|
||||
sizing="largeSizeMediumTitles"
|
||||
background="blurBottom"
|
||||
cardStyle="soft-shadow"
|
||||
primaryButtonStyle="flat"
|
||||
secondaryButtonStyle="solid"
|
||||
headingFontWeight="medium"
|
||||
>
|
||||
<div id="nav" data-section="nav">
|
||||
<NavbarStyleApple brandName="SafeHome" navItems={navItems} />
|
||||
</div>
|
||||
|
||||
<div className="min-h-screen py-20 md:py-32">
|
||||
<div className="mx-auto px-4 md:px-6 max-w-md">
|
||||
<div className="bg-card rounded-theme p-8 shadow-soft-shadow">
|
||||
<h1 className="text-3xl md:text-4xl font-semibold mb-2">Create Account</h1>
|
||||
<p className="text-foreground/75 mb-8">Join SafeHome and start preparing for emergencies</p>
|
||||
|
||||
{success && (
|
||||
<div className="bg-accent/10 border border-accent rounded-theme p-4 mb-6">
|
||||
<p className="text-accent font-medium">✓ Account created successfully! Redirecting to login...</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{error && (
|
||||
<div className="bg-red-500/10 border border-red-500 rounded-theme p-4 mb-6">
|
||||
<p className="text-red-500 text-sm">{error}</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<form onSubmit={handleSubmit} className="space-y-5">
|
||||
<div>
|
||||
<label htmlFor="name" className="block text-sm font-medium mb-2">
|
||||
Full Name
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="name"
|
||||
name="name"
|
||||
value={formData.name}
|
||||
onChange={handleChange}
|
||||
placeholder="Your full name"
|
||||
className="w-full px-4 py-2 rounded-theme bg-background border border-foreground/10 text-foreground placeholder:text-foreground/50 focus:outline-none focus:ring-2 focus:ring-primary-cta"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label htmlFor="email" className="block text-sm font-medium mb-2">
|
||||
Email Address
|
||||
</label>
|
||||
<input
|
||||
type="email"
|
||||
id="email"
|
||||
name="email"
|
||||
value={formData.email}
|
||||
onChange={handleChange}
|
||||
placeholder="your@email.com"
|
||||
className="w-full px-4 py-2 rounded-theme bg-background border border-foreground/10 text-foreground placeholder:text-foreground/50 focus:outline-none focus:ring-2 focus:ring-primary-cta"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label htmlFor="password" className="block text-sm font-medium mb-2">
|
||||
Password
|
||||
</label>
|
||||
<input
|
||||
type="password"
|
||||
id="password"
|
||||
name="password"
|
||||
value={formData.password}
|
||||
onChange={handleChange}
|
||||
placeholder="Create a strong password"
|
||||
className="w-full px-4 py-2 rounded-theme bg-background border border-foreground/10 text-foreground placeholder:text-foreground/50 focus:outline-none focus:ring-2 focus:ring-primary-cta"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label htmlFor="confirmPassword" className="block text-sm font-medium mb-2">
|
||||
Confirm Password
|
||||
</label>
|
||||
<input
|
||||
type="password"
|
||||
id="confirmPassword"
|
||||
name="confirmPassword"
|
||||
value={formData.confirmPassword}
|
||||
onChange={handleChange}
|
||||
placeholder="Confirm your password"
|
||||
className="w-full px-4 py-2 rounded-theme bg-background border border-foreground/10 text-foreground placeholder:text-foreground/50 focus:outline-none focus:ring-2 focus:ring-primary-cta"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="agreeTerms"
|
||||
name="agreeTerms"
|
||||
checked={formData.agreeTerms}
|
||||
onChange={handleChange}
|
||||
className="w-4 h-4 rounded border-foreground/20"
|
||||
/>
|
||||
<label htmlFor="agreeTerms" className="ml-3 text-sm">
|
||||
I agree to the{" "}
|
||||
<Link href="/terms" className="text-primary-cta hover:underline">
|
||||
Terms of Service
|
||||
</Link>{" "}
|
||||
and{" "}
|
||||
<Link href="/privacy" className="text-primary-cta hover:underline">
|
||||
Privacy Policy
|
||||
</Link>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
className="w-full bg-primary-cta text-background font-medium py-3 rounded-theme hover:opacity-90 transition-opacity"
|
||||
>
|
||||
Create Account
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<p className="text-center text-sm text-foreground/75 mt-6">
|
||||
Already have an account?{" "}
|
||||
<Link href="/login" className="text-primary-cta hover:underline font-medium">
|
||||
Sign In
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="footer" data-section="footer">
|
||||
<FooterLogoReveal
|
||||
logoText="SafeHome"
|
||||
leftLink={{ text: "Privacy Policy", href: "/privacy" }}
|
||||
rightLink={{ text: "Terms of Service", href: "/terms" }}
|
||||
/>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
138
src/app/shop/[productId]/page.tsx
Normal file
138
src/app/shop/[productId]/page.tsx
Normal file
@@ -0,0 +1,138 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import NavbarStyleApple from "@/components/navbar/NavbarStyleApple/NavbarStyleApple";
|
||||
import ProductDetailCard from "@/components/ecommerce/productDetail/ProductDetailCard";
|
||||
import FooterLogoReveal from "@/components/sections/footer/FooterLogoReveal";
|
||||
|
||||
const productDatabase: Record<string, any> = {
|
||||
"kit-2p-24h": {
|
||||
name: "2-Person 24-Hour Kit", price: "$89.00", rating: 4.8,
|
||||
description: "Perfect for couples or two individuals. Includes everything needed for 24 hours: water, food, first aid, and emergency tools.", images: [
|
||||
{ src: "http://img.b2bpic.net/free-photo/sporty-girl-packing-bag-training-sports-girl-going-training-preparing-training_169016-67560.jpg?_wi=1", alt: "2-Person 24-Hour Kit - Front View" },
|
||||
{ src: "http://img.b2bpic.net/free-photo/young-family-enjoying-trips_23-2149176539.jpg?_wi=1", alt: "2-Person 24-Hour Kit - Contents" },
|
||||
],
|
||||
},
|
||||
"kit-4p-24h": {
|
||||
name: "4-Person 24-Hour Kit", price: "$149.00", rating: 4.9,
|
||||
description: "Ideal for families with children. Comprehensive 24-hour emergency kit for four people with age-appropriate items.", images: [
|
||||
{ src: "http://img.b2bpic.net/free-photo/young-family-enjoying-trips_23-2149176539.jpg?_wi=1", alt: "4-Person 24-Hour Kit - Front View" },
|
||||
{ src: "http://img.b2bpic.net/free-photo/luggage-seen-from-rear-car-window_23-2150934321.jpg?_wi=1", alt: "4-Person 24-Hour Kit - Contents" },
|
||||
],
|
||||
},
|
||||
"kit-4p-72h": {
|
||||
name: "4-Person 72-Hour Kit", price: "$299.00", rating: 4.9,
|
||||
description: "Extended family preparedness for 72 hours. Complete coverage for four people with enhanced supplies and variety.", images: [
|
||||
{ src: "http://img.b2bpic.net/free-photo/luggage-seen-from-rear-car-window_23-2150934321.jpg?_wi=1", alt: "4-Person 72-Hour Kit - Front View" },
|
||||
{ src: "http://img.b2bpic.net/free-photo/top-view-storage-devices-glasses_23-2149319333.jpg?_wi=1", alt: "4-Person 72-Hour Kit - Contents" },
|
||||
],
|
||||
},
|
||||
"kit-1p-extended": {
|
||||
name: "1-Person Extended Bundle", price: "$179.00", rating: 4.7,
|
||||
description: "Solo survival bundle with modular expansion capability. Start with 24-hour coverage and expand as needed.", images: [
|
||||
{ src: "http://img.b2bpic.net/free-photo/top-view-storage-devices-glasses_23-2149319333.jpg?_wi=1", alt: "1-Person Extended Bundle - Front View" },
|
||||
{ src: "http://img.b2bpic.net/free-photo/sporty-girl-packing-bag-training-sports-girl-going-training-preparing-training_169016-67560.jpg?_wi=1", alt: "1-Person Extended Bundle - Contents" },
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
export default function ProductDetailPage({ params }: { params: { productId: string } }) {
|
||||
const product = productDatabase[params.productId];
|
||||
const navItems = [
|
||||
{ name: "Shop", id: "/shop" },
|
||||
{ name: "How It Works", id: "how-it-works" },
|
||||
{ name: "About", id: "about" },
|
||||
{ name: "Reviews", id: "reviews" },
|
||||
{ name: "Contact", id: "contact" },
|
||||
];
|
||||
|
||||
const [selectedSize, setSelectedSize] = useState("M");
|
||||
const [selectedQuantity, setSelectedQuantity] = useState("1");
|
||||
|
||||
if (!product) {
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="icon-arrow"
|
||||
defaultTextAnimation="entrance-slide"
|
||||
borderRadius="rounded"
|
||||
contentWidth="compact"
|
||||
sizing="largeSizeMediumTitles"
|
||||
background="blurBottom"
|
||||
cardStyle="soft-shadow"
|
||||
primaryButtonStyle="flat"
|
||||
secondaryButtonStyle="solid"
|
||||
headingFontWeight="medium"
|
||||
>
|
||||
<div id="nav" data-section="nav">
|
||||
<NavbarStyleApple brandName="SafeHome" navItems={navItems} />
|
||||
</div>
|
||||
<div className="py-20 text-center">
|
||||
<p>Product not found</p>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="icon-arrow"
|
||||
defaultTextAnimation="entrance-slide"
|
||||
borderRadius="rounded"
|
||||
contentWidth="compact"
|
||||
sizing="largeSizeMediumTitles"
|
||||
background="blurBottom"
|
||||
cardStyle="soft-shadow"
|
||||
primaryButtonStyle="flat"
|
||||
secondaryButtonStyle="solid"
|
||||
headingFontWeight="medium"
|
||||
>
|
||||
<div id="nav" data-section="nav">
|
||||
<NavbarStyleApple brandName="SafeHome" navItems={navItems} />
|
||||
</div>
|
||||
|
||||
<div id="product-detail" data-section="product-detail" className="py-20 md:py-32">
|
||||
<div className="mx-auto px-4 md:px-6">
|
||||
<ProductDetailCard
|
||||
layout="page"
|
||||
name={product.name}
|
||||
price={product.price}
|
||||
rating={product.rating}
|
||||
description={product.description}
|
||||
images={product.images}
|
||||
variants={[
|
||||
{
|
||||
label: "Size", options: ["S", "M", "L", "XL"],
|
||||
selected: selectedSize,
|
||||
onChange: setSelectedSize,
|
||||
},
|
||||
]}
|
||||
quantity={{
|
||||
label: "Quantity", options: ["1", "2", "3", "4", "5"],
|
||||
selected: selectedQuantity,
|
||||
onChange: setSelectedQuantity,
|
||||
}}
|
||||
buttons={[
|
||||
{
|
||||
text: "Add to Cart", onClick: () => {
|
||||
console.log(`Added ${selectedQuantity}x ${product.name} (Size: ${selectedSize})`);
|
||||
alert(`Added to cart: ${product.name}`);
|
||||
},
|
||||
},
|
||||
{
|
||||
text: "Continue Shopping", href: "/shop"},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="footer" data-section="footer">
|
||||
<FooterLogoReveal
|
||||
logoText="SafeHome"
|
||||
leftLink={{ text: "Privacy Policy", href: "/privacy" }}
|
||||
rightLink={{ text: "Terms of Service", href: "/terms" }}
|
||||
/>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
@@ -1,22 +1,43 @@
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import { useState } from "react";
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import NavbarStyleApple from "@/components/navbar/NavbarStyleApple/NavbarStyleApple";
|
||||
import HeroLogoBillboardSplit from "@/components/sections/hero/HeroLogoBillboardSplit";
|
||||
import ProductCardFour from "@/components/sections/product/ProductCardFour";
|
||||
import FaqBase from "@/components/sections/faq/FaqBase";
|
||||
import FooterLogoReveal from "@/components/sections/footer/FooterLogoReveal";
|
||||
|
||||
export default function ShopPage() {
|
||||
const navItems = [
|
||||
{ name: "Shop", id: "shop" },
|
||||
{ name: "Shop", id: "/shop" },
|
||||
{ name: "How It Works", id: "how-it-works" },
|
||||
{ name: "About", id: "about" },
|
||||
{ name: "Reviews", id: "reviews" },
|
||||
{ name: "Contact", id: "contact" },
|
||||
];
|
||||
|
||||
const [selectedCategory, setSelectedCategory] = useState<string>("all");
|
||||
|
||||
const allProducts = [
|
||||
{
|
||||
id: "kit-2p-24h", name: "2-Person 24-Hour Kit", price: "$89", variant: "Couples & Small Households", imageSrc: "http://img.b2bpic.net/free-photo/sporty-girl-packing-bag-training-sports-girl-going-training-preparing-training_169016-67560.jpg?_wi=1", imageAlt: "2-person 24-hour emergency kit", category: "24-hour"},
|
||||
{
|
||||
id: "kit-4p-24h", name: "4-Person 24-Hour Kit", price: "$149", variant: "Families with Children", imageSrc: "http://img.b2bpic.net/free-photo/young-family-enjoying-trips_23-2149176539.jpg?_wi=1", imageAlt: "4-person 24-hour emergency kit", category: "24-hour"},
|
||||
{
|
||||
id: "kit-4p-72h", name: "4-Person 72-Hour Kit", price: "$299", variant: "Complete Family Preparedness", imageSrc: "http://img.b2bpic.net/free-photo/luggage-seen-from-rear-car-window_23-2150934321.jpg?_wi=1", imageAlt: "4-person 72-hour emergency kit", category: "72-hour"},
|
||||
{
|
||||
id: "kit-1p-extended", name: "1-Person Extended Bundle", price: "$179", variant: "Individual with Expandability", imageSrc: "http://img.b2bpic.net/free-photo/top-view-storage-devices-glasses_23-2149319333.jpg?_wi=1", imageAlt: "1-person extended emergency kit", category: "bundles"},
|
||||
{
|
||||
id: "kit-1p-24h", name: "1-Person 24-Hour Kit", price: "$49", variant: "Solo Travelers & Individuals", imageSrc: "http://img.b2bpic.net/free-photo/top-view-storage-devices-glasses_23-2149319333.jpg?_wi=1", imageAlt: "1-person 24-hour emergency kit", category: "24-hour"},
|
||||
{
|
||||
id: "kit-6p-72h", name: "6-Person 72-Hour Kit", price: "$449", variant: "Extended Family Coverage", imageSrc: "http://img.b2bpic.net/free-photo/luggage-seen-from-rear-car-window_23-2150934321.jpg?_wi=1", imageAlt: "6-person 72-hour emergency kit", category: "72-hour"},
|
||||
];
|
||||
|
||||
const filteredProducts =
|
||||
selectedCategory === "all"
|
||||
? allProducts
|
||||
: allProducts.filter((p: any) => p.category === selectedCategory);
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="icon-arrow"
|
||||
@@ -34,149 +55,93 @@ export default function ShopPage() {
|
||||
<NavbarStyleApple brandName="SafeHome" navItems={navItems} />
|
||||
</div>
|
||||
|
||||
<div id="shop-hero" data-section="shop-hero" className="py-20 md:py-32">
|
||||
<div id="hero" data-section="hero" className="py-20 md:py-32">
|
||||
<div className="mx-auto px-4 md:px-6">
|
||||
<HeroLogoBillboardSplit
|
||||
logoText="Shop All Kits"
|
||||
description="Choose the perfect emergency kit for your family. Browse by household size and preparedness duration. Every kit is thoughtfully designed and ready to ship."
|
||||
logoText="Shop SafeHome Kits"
|
||||
description="Browse our complete collection of modular emergency kits. Find the perfect kit for your family size and preparedness level."
|
||||
background={{ variant: "radial-gradient" }}
|
||||
buttons={[
|
||||
{ text: "Build Custom Kit", href: "/kit-builder" },
|
||||
{ text: "Learn More", href: "/" },
|
||||
{ text: "View All", href: "#products" },
|
||||
]}
|
||||
buttonAnimation="slide-up"
|
||||
layoutOrder="default"
|
||||
imageSrc="http://img.b2bpic.net/free-photo/young-family-enjoying-trips_23-2149176539.jpg?_wi=2"
|
||||
imageAlt="Shop SafeHome emergency kits"
|
||||
imageSrc="http://img.b2bpic.net/free-photo/affectionate-little-girl-with-eyes-closed-embracing-her-father-home-mother-is-background_637285-3199.jpg?_wi=1"
|
||||
imageAlt="SafeHome product collection"
|
||||
frameStyle="card"
|
||||
mediaAnimation="opacity"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="all-products" data-section="all-products" className="py-20 md:py-32">
|
||||
<div id="products" data-section="products" className="py-20 md:py-32">
|
||||
<div className="mx-auto px-4 md:px-6">
|
||||
<div className="mb-12">
|
||||
<div className="flex flex-wrap gap-2 md:gap-4 justify-center">
|
||||
<button
|
||||
onClick={() => setSelectedCategory("all")}
|
||||
className={`px-4 py-2 rounded-full font-medium transition-colors ${
|
||||
selectedCategory === "all"
|
||||
? "bg-primary-cta text-white"
|
||||
: "bg-card text-foreground border border-accent hover:border-primary-cta"
|
||||
}`}
|
||||
>
|
||||
All Products
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setSelectedCategory("24-hour")}
|
||||
className={`px-4 py-2 rounded-full font-medium transition-colors ${
|
||||
selectedCategory === "24-hour"
|
||||
? "bg-primary-cta text-white"
|
||||
: "bg-card text-foreground border border-accent hover:border-primary-cta"
|
||||
}`}
|
||||
>
|
||||
24-Hour Kits
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setSelectedCategory("72-hour")}
|
||||
className={`px-4 py-2 rounded-full font-medium transition-colors ${
|
||||
selectedCategory === "72-hour"
|
||||
? "bg-primary-cta text-white"
|
||||
: "bg-card text-foreground border border-accent hover:border-primary-cta"
|
||||
}`}
|
||||
>
|
||||
72-Hour Kits
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setSelectedCategory("bundles")}
|
||||
className={`px-4 py-2 rounded-full font-medium transition-colors ${
|
||||
selectedCategory === "bundles"
|
||||
? "bg-primary-cta text-white"
|
||||
: "bg-card text-foreground border border-accent hover:border-primary-cta"
|
||||
}`}
|
||||
>
|
||||
Bundles
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ProductCardFour
|
||||
title="Complete Kit Selection"
|
||||
description="All SafeHome kits include essential supplies, can be expanded modularly, and are backed by our 30-day satisfaction guarantee"
|
||||
tag="Complete Catalog"
|
||||
textboxLayout="default"
|
||||
products={[
|
||||
{
|
||||
id: "kit-1p-24h",
|
||||
name: "1-Person 24-Hour Kit",
|
||||
price: "$59",
|
||||
variant: "Solo Preparedness",
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/top-view-storage-devices-glasses_23-2149319333.jpg?_wi=2",
|
||||
imageAlt: "1-person 24-hour emergency kit",
|
||||
title="Emergency Kits"
|
||||
description="Choose from our curated selection of emergency kits or customize your own"
|
||||
products={filteredProducts.map((p: any) => ({
|
||||
id: p.id,
|
||||
name: p.name,
|
||||
price: p.price,
|
||||
variant: p.variant,
|
||||
imageSrc: p.imageSrc,
|
||||
imageAlt: p.imageAlt,
|
||||
onProductClick: () => {
|
||||
window.location.href = `/shop/${p.id}`;
|
||||
},
|
||||
{
|
||||
id: "kit-2p-24h",
|
||||
name: "2-Person 24-Hour Kit",
|
||||
price: "$89",
|
||||
variant: "Couples & Small Households",
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/sporty-girl-packing-bag-training-sports-girl-going-training-preparing-training_169016-67560.jpg?_wi=2",
|
||||
imageAlt: "2-person 24-hour emergency kit",
|
||||
},
|
||||
{
|
||||
id: "kit-3p-24h",
|
||||
name: "3-Person 24-Hour Kit",
|
||||
price: "$119",
|
||||
variant: "Small Family",
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/high-view-father-son-playing-with-toys_23-2148500810.jpg?_wi=2",
|
||||
imageAlt: "3-person 24-hour emergency kit",
|
||||
},
|
||||
{
|
||||
id: "kit-4p-24h",
|
||||
name: "4-Person 24-Hour Kit",
|
||||
price: "$149",
|
||||
variant: "Families with Children",
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/young-family-enjoying-trips_23-2149176539.jpg?_wi=3",
|
||||
imageAlt: "4-person 24-hour emergency kit",
|
||||
},
|
||||
{
|
||||
id: "kit-2p-48h",
|
||||
name: "2-Person 48-Hour Kit",
|
||||
price: "$149",
|
||||
variant: "Extended 2-Day",
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/luggage-seen-from-rear-car-window_23-2150934321.jpg?_wi=2",
|
||||
imageAlt: "2-person 48-hour emergency kit",
|
||||
},
|
||||
{
|
||||
id: "kit-4p-48h",
|
||||
name: "4-Person 48-Hour Kit",
|
||||
price: "$229",
|
||||
variant: "Extended Family",
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/affectionate-little-girl-with-eyes-closed-embracing-her-father-home-mother-is-background_637285-3199.jpg?_wi=2",
|
||||
imageAlt: "4-person 48-hour emergency kit",
|
||||
},
|
||||
{
|
||||
id: "kit-2p-72h",
|
||||
name: "2-Person 72-Hour Kit",
|
||||
price: "$199",
|
||||
variant: "Complete 3-Day",
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/portrait-woman-home-yawning_23-2148923998.jpg?_wi=2",
|
||||
imageAlt: "2-person 72-hour emergency kit",
|
||||
},
|
||||
{
|
||||
id: "kit-4p-72h",
|
||||
name: "4-Person 72-Hour Kit",
|
||||
price: "$299",
|
||||
variant: "Complete Family Preparedness",
|
||||
imageSrc: "http://img.b2bpic.net/free-photo/side-view-beautiful-woman-with-folded-arms-looking-camera_23-2147876783.jpg?_wi=2",
|
||||
imageAlt: "4-person 72-hour emergency kit",
|
||||
},
|
||||
]}
|
||||
}))}
|
||||
gridVariant="uniform-all-items-equal"
|
||||
animationType="slide-up"
|
||||
useInvertedBackground={false}
|
||||
buttons={[
|
||||
{ text: "View Collections", href: "/" },
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="shop-faq" data-section="shop-faq" className="py-20 md:py-32">
|
||||
<div className="mx-auto px-4 md:px-6">
|
||||
<FaqBase
|
||||
title="Shopping & Ordering"
|
||||
description="Get answers to common questions about ordering, shipping, and our kits"
|
||||
tag="Help"
|
||||
textboxLayout="default"
|
||||
useInvertedBackground={true}
|
||||
faqsAnimation="slide-up"
|
||||
faqs={[
|
||||
{
|
||||
id: "1",
|
||||
title: "How do I choose the right kit size?",
|
||||
content: "Select based on your household size (1-5+ people). Each kit includes enough supplies for that many people for the specified duration (24/48/72 hours). Our kit builder can help guide your selection.",
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
title: "Can I add items to my kit after purchase?",
|
||||
content: "Yes! After purchase, you can add individual items from our catalog, or upgrade to a larger duration kit. Any shared items you already own won't be duplicated.",
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
title: "How quickly does my order ship?",
|
||||
content: "Orders typically ship within 1-2 business days. Standard shipping is 5-7 business days. Expedited and overnight options are available at checkout.",
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
title: "What if my kit arrives damaged?",
|
||||
content: "We'll replace it immediately at no cost. Contact our support team with photos, and we'll arrange a replacement or full refund within 24 hours.",
|
||||
},
|
||||
{
|
||||
id: "5",
|
||||
title: "Are there bulk discounts for organizations?",
|
||||
content: "Yes! Schools, nonprofits, and businesses can inquire about volume pricing. Contact our B2B team at corporate@safehome.com for custom quotes.",
|
||||
},
|
||||
{
|
||||
id: "6",
|
||||
title: "Can I return or exchange an unopened kit?",
|
||||
content: "Absolutely. We offer 30-day returns and exchanges with no questions asked. Just contact support to initiate the process.",
|
||||
},
|
||||
buttons={[
|
||||
{ text: "View Comparison", href: "#compare" },
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -10,15 +10,15 @@
|
||||
--accent: #ffffff;
|
||||
--background-accent: #ffffff; */
|
||||
|
||||
--background: #e3deea;
|
||||
--card: #ffffff;
|
||||
--foreground: #27231f;
|
||||
--primary-cta: #27231f;
|
||||
--background: #ffffff;
|
||||
--card: #f9f9f9;
|
||||
--foreground: #0a3a1f;
|
||||
--primary-cta: #0a7039;
|
||||
--primary-cta-text: #e3deea;
|
||||
--secondary-cta: #ffffff;
|
||||
--secondary-cta: #f9f9f9;
|
||||
--secondary-cta-text: #27231f;
|
||||
--accent: #c68a62;
|
||||
--background-accent: #c68a62;
|
||||
--accent: #106EFB;
|
||||
--background-accent: #ff8c42;
|
||||
|
||||
/* text sizing - set by ThemeProvider */
|
||||
/* --text-2xs: clamp(0.465rem, 0.62vw, 0.62rem);
|
||||
|
||||
Reference in New Issue
Block a user