feature: affiliate-links page

This commit is contained in:
DeathKaioken 2025-10-03 20:30:55 +02:00
parent 37fbc6ae25
commit 42130be8e8
6 changed files with 388 additions and 261 deletions

View File

@ -0,0 +1,189 @@
import PageLayout from '../components/PageLayout';
const posts = [
{
id: 1,
title: 'TechInnovate Solutions',
href: 'https://example.com/affiliate/techinnovate',
description:
'Leading provider of innovative tech solutions for businesses. Earn commissions on referrals.',
imageUrl:
'https://images.unsplash.com/photo-1496128858413-b36217c2ce36?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=3603&q=80',
category: { title: 'Technology', href: '#' },
},
{
id: 2,
title: 'GreenEnergy Corp',
href: 'https://example.com/affiliate/greenenergy',
description:
'Sustainable energy products and services. Partner with us for eco-friendly commissions.',
imageUrl:
'https://images.unsplash.com/photo-1547586696-ea22b4d4235d?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=3270&q=80',
category: { title: 'Energy', href: '#' },
},
{
id: 3,
title: 'FinanceHub Advisors',
href: 'https://example.com/affiliate/financehub',
description:
'Expert financial advisory services. Get rewarded for every successful referral.',
imageUrl:
'https://images.unsplash.com/photo-1492724441997-5dc865305da7?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=3270&q=80',
category: { title: 'Finance', href: '#' },
},
{
id: 4,
title: 'HealthWell Clinics',
href: 'https://example.com/affiliate/healthwell',
description:
'Comprehensive healthcare solutions. Affiliate program with competitive payouts.',
imageUrl:
'https://images.unsplash.com/photo-1559136555-9303baea8ebd?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=3270&q=80',
category: { title: 'Healthcare', href: '#' },
},
{
id: 5,
title: 'EduLearn Academy',
href: 'https://example.com/affiliate/edulearn',
description:
'Online education platforms for all ages. Earn from educational referrals.',
imageUrl:
'https://images.unsplash.com/photo-1485217988980-11786ced9454?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=3270&q=80',
category: { title: 'Education', href: '#' },
},
{
id: 6,
title: 'TravelEase Agency',
href: 'https://example.com/affiliate/travelease',
description:
'Seamless travel booking services. Commissions on every trip booked through affiliates.',
imageUrl:
'https://images.unsplash.com/photo-1670272504528-790c24957dda?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=3270&q=80',
category: { title: 'Travel', href: '#' },
},
{
id: 7,
title: 'RetailMax Stores',
href: 'https://example.com/affiliate/retailmax',
description:
'Wide range of retail products. Join our affiliate network for sales commissions.',
imageUrl:
'https://images.unsplash.com/photo-1670272505284-8faba1c31f7d?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=3270&q=80',
category: { title: 'Retail', href: '#' },
},
{
id: 8,
title: 'BuildPro Contractors',
href: 'https://example.com/affiliate/buildpro',
description:
'Professional construction and renovation services. Affiliate rewards for leads.',
imageUrl:
'https://images.unsplash.com/photo-1557804506-669a67965ba0?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=3270&q=80',
category: { title: 'Construction', href: '#' },
},
{
id: 9,
title: 'FoodieDelight Catering',
href: 'https://example.com/affiliate/foodiedelight',
description:
'Delicious catering services for events. Earn commissions on catering bookings.',
imageUrl:
'https://images.unsplash.com/photo-1492724441997-5dc865305da7?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=3270&q=80',
category: { title: 'Food', href: '#' },
},
{
id: 10,
title: 'AutoCare Mechanics',
href: 'https://example.com/affiliate/autocare',
description:
'Reliable automotive repair and maintenance. Affiliate program with steady payouts.',
imageUrl:
'https://images.unsplash.com/photo-1547586696-ea22b4d4235d?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=3270&q=80',
category: { title: 'Automotive', href: '#' },
},
{
id: 11,
title: 'FashionForward Boutique',
href: 'https://example.com/affiliate/fashionforward',
description:
'Trendy fashion and accessories. Commissions on fashion sales through affiliates.',
imageUrl:
'https://images.unsplash.com/photo-1496128858413-b36217c2ce36?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=3270&q=80',
category: { title: 'Fashion', href: '#' },
},
{
id: 12,
title: 'PetCare Essentials',
href: 'https://example.com/affiliate/petcare',
description:
'Everything for your pets. Earn from pet product referrals.',
imageUrl:
'https://images.unsplash.com/photo-1559136555-9303baea8ebd?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=3270&q=80',
category: { title: 'Pets', href: '#' },
},
]
export default function AffiliateLinksPage() {
return (
<PageLayout>
<div className="bg-gray-900 py-24 sm:py-32">
<div className="mx-auto max-w-7xl px-6 lg:px-8">
<div className="mx-auto max-w-2xl text-center">
<h2 className="text-4xl font-semibold tracking-tight text-balance text-white sm:text-5xl">
Affiliate Partners
</h2>
<p className="mt-2 text-lg/8 text-gray-300">
Discover our trusted partners and earn commissions through affiliate
links.
</p>
</div>
<div className="mx-auto mt-16 grid max-w-2xl grid-cols-1 gap-x-8 gap-y-20 lg:mx-0 lg:max-w-none lg:grid-cols-3">
{posts.map((post) => (
<article key={post.id} className="flex flex-col items-start justify-between">
<div className="relative w-full">
<img
alt=""
src={post.imageUrl}
className="aspect-video w-full rounded-2xl bg-gray-800 object-cover sm:aspect-2/1 lg:aspect-3/2"
/>
<div className="absolute inset-0 rounded-2xl inset-ring inset-ring-white/10" />
</div>
<div className="flex max-w-xl grow flex-col justify-between">
<div className="mt-8 flex items-center gap-x-4 text-xs">
<a
href={post.category.href}
className="relative z-10 rounded-full bg-gray-800/60 px-3 py-1.5 font-medium text-gray-300 hover:bg-gray-800"
>
{post.category.title}
</a>
</div>
<div className="group relative grow">
<h3 className="mt-3 text-lg/6 font-semibold text-white group-hover:text-gray-300">
<a href={post.href} target="_blank" rel="noopener noreferrer">
<span className="absolute inset-0" />
{post.title}
</a>
</h3>
<p className="mt-5 line-clamp-3 text-sm/6 text-gray-400">
{post.description}
</p>
</div>
<div className="relative mt-8 flex items-center gap-x-4 justify-self-end">
<a
href={post.href}
target="_blank"
rel="noopener noreferrer"
className="text-sm font-semibold text-indigo-400 hover:text-indigo-300"
>
Visit Affiliate Link
</a>
</div>
</div>
</article>
))}
</div>
</div>
</div>
</PageLayout>
)
}

View File

@ -4,7 +4,7 @@ import { useTranslation } from '../i18n/useTranslation';
export default function Footer() { export default function Footer() {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<footer className="bg-[#0F172A] py-4 px-6 shadow-inner"> <footer className="relative z-50 w-full bg-[#0F172A] py-4 px-6 shadow-inner">
<div className="container mx-auto flex justify-between items-center"> <div className="container mx-auto flex justify-between items-center">
<div className="text-sm text-white/70"> <div className="text-sm text-white/70">
© {new Date().getFullYear()} {t('footer.company')} - {t('footer.rights')} © {new Date().getFullYear()} {t('footer.company')} - {t('footer.rights')}

View File

@ -25,7 +25,7 @@ export default function PageLayout({
const isMobile = isMobileDevice(); const isMobile = isMobileDevice();
return ( return (
<div className="min-h-screen w-full flex flex-col relative overflow-x-hidden bg-white"> <div className="min-h-screen w-full flex flex-col relative overflow-x-hidden bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 transition-colors">
{showHeader && ( {showHeader && (
<div className="relative z-50 w-full"> <div className="relative z-50 w-full">
@ -39,7 +39,7 @@ export default function PageLayout({
</div> </div>
{showFooter && ( {showFooter && (
<div className="relative z-20 w-full"> <div className="mt-auto relative z-50">
<Footer /> <Footer />
</div> </div>
)} )}

View File

@ -1,6 +1,6 @@
'use client' 'use client'
import { useState } from 'react' import { useState, useEffect, useCallback } from 'react'
import { useRouter } from 'next/navigation'; import { useRouter } from 'next/navigation';
import Image from 'next/image'; import Image from 'next/image';
import { import {
@ -21,7 +21,9 @@ import {
HomeIcon, HomeIcon,
UserCircleIcon, UserCircleIcon,
XMarkIcon, XMarkIcon,
ArrowRightOnRectangleIcon ArrowRightOnRectangleIcon,
MoonIcon,
SunIcon
} from '@heroicons/react/24/outline' } from '@heroicons/react/24/outline'
import { ChevronDownIcon } from '@heroicons/react/20/solid' import { ChevronDownIcon } from '@heroicons/react/20/solid'
import useAuthStore from '../../store/authStore'; import useAuthStore from '../../store/authStore';
@ -51,6 +53,7 @@ const products = [
export default function Header() { export default function Header() {
const [mobileMenuOpen, setMobileMenuOpen] = useState(false) const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
const [isDark, setIsDark] = useState(false)
const user = useAuthStore((s) => s.user); const user = useAuthStore((s) => s.user);
const logout = useAuthStore((s) => s.logout); const logout = useAuthStore((s) => s.logout);
const router = useRouter(); const router = useRouter();
@ -79,8 +82,34 @@ export default function Header() {
return 'U'; return 'U';
}; };
// Theme initialization & persistence
useEffect(() => {
const stored = localStorage.getItem('theme')
if (stored === 'dark' || (!stored && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
document.documentElement.classList.add('dark')
setIsDark(true)
} else {
document.documentElement.classList.remove('dark')
setIsDark(false)
}
}, [])
const toggleTheme = useCallback(() => {
setIsDark(prev => {
const next = !prev
if (next) {
document.documentElement.classList.add('dark')
localStorage.setItem('theme', 'dark')
} else {
document.documentElement.classList.remove('dark')
localStorage.setItem('theme', 'light')
}
return next
})
}, [])
return ( return (
<header className="relative isolate z-10 bg-gray-900"> <header className="relative isolate z-10 bg-white/85 dark:bg-gray-900/90 backdrop-blur supports-[backdrop-filter]:bg-white/60 dark:supports-[backdrop-filter]:bg-gray-900/70 border-b border-gray-200 dark:border-white/10 transition-colors">
<nav aria-label="Global" className="mx-auto flex max-w-7xl items-center justify-between p-6 lg:px-8"> <nav aria-label="Global" className="mx-auto flex max-w-7xl items-center justify-between p-6 lg:px-8">
<div className="flex lg:flex-1"> <div className="flex lg:flex-1">
<button <button
@ -109,31 +138,31 @@ export default function Header() {
</div> </div>
<PopoverGroup className="hidden lg:flex lg:gap-x-12"> <PopoverGroup className="hidden lg:flex lg:gap-x-12">
<Popover> <Popover>
<PopoverButton className="flex items-center gap-x-1 text-sm/6 font-semibold text-white"> <PopoverButton className="flex items-center gap-x-1 text-sm/6 font-semibold text-gray-900 dark:text-white">
Product Product
<ChevronDownIcon aria-hidden="true" className="size-5 flex-none text-gray-500" /> <ChevronDownIcon aria-hidden="true" className="size-5 flex-none text-gray-500" />
</PopoverButton> </PopoverButton>
<PopoverPanel <PopoverPanel
transition transition
className="absolute inset-x-0 top-16 bg-gray-900 transition data-closed:-translate-y-1 data-closed:opacity-0 data-enter:duration-200 data-enter:ease-out data-leave:duration-150 data-leave:ease-in" className="absolute inset-x-0 top-16 bg-white dark:bg-gray-900 transition data-closed:-translate-y-1 data-closed:opacity-0 data-enter:duration-200 data-enter:ease-out data-leave:duration-150 data-leave:ease-in"
> >
<div aria-hidden="true" className="absolute inset-0 top-1/2 bg-gray-900 ring-1 ring-white/15" /> <div aria-hidden="true" className="absolute inset-0 top-1/2 bg-white dark:bg-gray-900 ring-1 ring-black/5 dark:ring-white/15" />
<div className="relative bg-gray-900"> <div className="relative bg-white dark:bg-gray-900">
<div className="mx-auto grid max-w-7xl grid-cols-3 gap-x-4 px-6 py-10 lg:px-8 xl:gap-x-8"> <div className="mx-auto grid max-w-7xl grid-cols-3 gap-x-4 px-6 py-10 lg:px-8 xl:gap-x-8">
{products.map((item) => ( {products.map((item) => (
<div key={item.name} className="group relative rounded-lg p-6 text-sm/6 hover:bg-white/5"> <div key={item.name} className="group relative rounded-lg p-6 text-sm/6 hover:bg-gray-100/70 dark:hover:bg-white/5 transition-colors">
<div className="flex size-11 items-center justify-center rounded-lg bg-gray-700/50 group-hover:bg-gray-700"> <div className="flex size-11 items-center justify-center rounded-lg bg-gray-200/70 dark:bg-gray-700/50 group-hover:bg-gray-300 dark:group-hover:bg-gray-700">
<item.icon aria-hidden="true" className="size-6 text-gray-400 group-hover:text-white" /> <item.icon aria-hidden="true" className="size-6 text-gray-600 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white" />
</div> </div>
<button <button
onClick={() => router.push(item.href)} onClick={() => router.push(item.href)}
className="mt-6 block font-semibold text-white" className="mt-6 block font-semibold text-gray-900 dark:text-white"
> >
{item.name} {item.name}
<span className="absolute inset-0" /> <span className="absolute inset-0" />
</button> </button>
<p className="mt-1 text-gray-400">{item.description}</p> <p className="mt-1 text-gray-600 dark:text-gray-400">{item.description}</p>
</div> </div>
))} ))}
</div> </div>
@ -143,21 +172,21 @@ export default function Header() {
<button <button
onClick={() => router.push('/features')} onClick={() => router.push('/features')}
className="text-sm/6 font-semibold text-white hover:text-indigo-400 transition-colors" className="text-sm/6 font-semibold text-gray-900 dark:text-white hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors"
> >
Features Features
</button> </button>
<button <button
onClick={() => router.push('/marketplace')} onClick={() => router.push('/marketplace')}
className="text-sm/6 font-semibold text-white hover:text-indigo-400 transition-colors" className="text-sm/6 font-semibold text-gray-900 dark:text-white hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors"
> >
Marketplace Marketplace
</button> </button>
<button <button
onClick={() => router.push('/company')} onClick={() => router.push('/company')}
className="text-sm/6 font-semibold text-white hover:text-indigo-400 transition-colors" className="text-sm/6 font-semibold text-gray-900 dark:text-white hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors"
> >
Company Company
</button> </button>
@ -165,7 +194,7 @@ export default function Header() {
{/* Profile Dropdown - nur wenn eingeloggt */} {/* Profile Dropdown - nur wenn eingeloggt */}
{user && ( {user && (
<Popover> <Popover>
<PopoverButton className="flex items-center gap-x-1 text-sm/6 font-semibold text-white"> <PopoverButton className="flex items-center gap-x-1 text-sm/6 font-semibold text-gray-900 dark:text-white">
<Avatar <Avatar
src="" src=""
initials={getUserInitials()} initials={getUserInitials()}
@ -176,7 +205,7 @@ export default function Header() {
<PopoverPanel <PopoverPanel
transition transition
className="absolute right-0 top-16 w-64 bg-gray-900 ring-1 ring-white/15 transition data-closed:-translate-y-1 data-closed:opacity-0 data-enter:duration-200 data-enter:ease-out data-leave:duration-150 data-leave:ease-in" className="absolute right-0 top-16 w-64 bg-white dark:bg-gray-900 ring-1 ring-black/5 dark:ring-white/15 transition data-closed:-translate-y-1 data-closed:opacity-0 data-enter:duration-200 data-enter:ease-out data-leave:duration-150 data-leave:ease-in"
> >
<div className="p-4"> <div className="p-4">
<div className="flex flex-col border-b border-white/10 pb-4 mb-4"> <div className="flex flex-col border-b border-white/10 pb-4 mb-4">
@ -210,13 +239,21 @@ export default function Header() {
)} )}
</PopoverGroup> </PopoverGroup>
<div className="hidden lg:flex lg:flex-1 lg:justify-end lg:items-center lg:gap-x-4"> <div className="hidden lg:flex lg:flex-1 lg:justify-end lg:items-center lg:gap-x-4">
{/* Theme Toggle */}
<button
onClick={toggleTheme}
aria-label="Toggle theme"
className="p-2 rounded-md border border-gray-300 dark:border-white/10 bg-gray-100 hover:bg-gray-200 dark:bg-gray-800 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-200 transition-colors"
>
{isDark ? <SunIcon className="h-5 w-5" /> : <MoonIcon className="h-5 w-5" />}
</button>
{/* Language Switcher */} {/* Language Switcher */}
<LanguageSwitcher variant="dark" /> <LanguageSwitcher variant={isDark ? 'dark' : 'light'} />
{!user && ( {!user && (
<button <button
onClick={() => router.push('/login')} onClick={() => router.push('/login')}
className="text-sm/6 font-semibold text-white hover:text-indigo-400 transition-colors" className="text-sm/6 font-semibold text-gray-900 dark:text-white hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors"
> >
Log in <span aria-hidden="true">&rarr;</span> Log in <span aria-hidden="true">&rarr;</span>
</button> </button>
@ -225,7 +262,7 @@ export default function Header() {
</nav> </nav>
<Dialog open={mobileMenuOpen} onClose={setMobileMenuOpen} className="lg:hidden"> <Dialog open={mobileMenuOpen} onClose={setMobileMenuOpen} className="lg:hidden">
<div className="fixed inset-0 z-50" /> <div className="fixed inset-0 z-50" />
<DialogPanel className="fixed inset-y-0 right-0 z-50 w-full overflow-y-auto bg-gray-900 p-6 sm:max-w-sm sm:ring-1 sm:ring-gray-100/10"> <DialogPanel className="fixed inset-y-0 right-0 z-50 w-full overflow-y-auto bg-white dark:bg-gray-900 p-6 sm:max-w-sm sm:ring-1 sm:ring-black/10 dark:sm:ring-gray-100/10 transition-colors">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<button <button
onClick={() => router.push('/')} onClick={() => router.push('/')}
@ -250,12 +287,22 @@ export default function Header() {
</button> </button>
</div> </div>
<div className="mt-6 flow-root"> <div className="mt-6 flow-root">
<div className="-my-6 divide-y divide-white/10"> <div className="-my-6 divide-y divide-gray-200 dark:divide-white/10">
{/* Insert theme toggle in mobile */}
<div className="py-6">
<button
onClick={toggleTheme}
className="flex items-center gap-x-2 rounded-lg px-3 py-2.5 text-base/7 font-semibold text-gray-900 dark:text-white hover:bg-gray-100 dark:hover:bg-white/5 w-full"
>
{isDark ? <SunIcon className="h-5 w-5" /> : <MoonIcon className="h-5 w-5" />}
{isDark ? 'Light Mode' : 'Dark Mode'}
</button>
</div>
{user ? ( {user ? (
<> <>
<div className="space-y-2 py-6"> <div className="space-y-2 py-6">
<Disclosure as="div" className="-mx-3"> <Disclosure as="div" className="-mx-3">
<DisclosureButton className="group flex w-full items-center justify-between rounded-lg py-2 pr-3.5 pl-3 text-base/7 font-semibold text-white hover:bg-white/5"> <DisclosureButton className="group flex w-full items-center justify-between rounded-lg py-2 pr-3.5 pl-3 text-base/7 font-semibold text-gray-900 dark:text-white hover:bg-white/5">
Navigation Navigation
<ChevronDownIcon aria-hidden="true" className="size-5 flex-none group-data-open:rotate-180" /> <ChevronDownIcon aria-hidden="true" className="size-5 flex-none group-data-open:rotate-180" />
</DisclosureButton> </DisclosureButton>
@ -268,7 +315,7 @@ export default function Header() {
router.push(item.href); router.push(item.href);
setMobileMenuOpen(false); setMobileMenuOpen(false);
}} }}
className="block rounded-lg py-2 pr-3 pl-6 text-sm/7 font-semibold text-white hover:bg-white/5 w-full text-left" className="block rounded-lg py-2 pr-3 pl-6 text-sm/7 font-semibold text-gray-900 dark:text-white hover:bg-white/5 w-full text-left"
> >
{item.name} {item.name}
</DisclosureButton> </DisclosureButton>
@ -297,7 +344,7 @@ export default function Header() {
router.push('/profile'); router.push('/profile');
setMobileMenuOpen(false); setMobileMenuOpen(false);
}} }}
className="-mx-3 block rounded-lg px-3 py-2 text-base/7 font-semibold text-white hover:bg-white/5 w-full text-left" className="-mx-3 block rounded-lg px-3 py-2 text-base/7 font-semibold text-gray-900 dark:text-white hover:bg-white/5 w-full text-left"
> >
Profile Profile
</button> </button>
@ -306,7 +353,7 @@ export default function Header() {
handleLogout(); handleLogout();
setMobileMenuOpen(false); setMobileMenuOpen(false);
}} }}
className="-mx-3 block rounded-lg px-3 py-2 text-base/7 font-semibold text-white hover:bg-white/5 w-full text-left" className="-mx-3 block rounded-lg px-3 py-2 text-base/7 font-semibold text-gray-900 dark:text-white hover:bg-white/5 w-full text-left"
> >
Logout Logout
</button> </button>
@ -323,7 +370,7 @@ export default function Header() {
router.push('/login'); router.push('/login');
setMobileMenuOpen(false); setMobileMenuOpen(false);
}} }}
className="-mx-3 block rounded-lg px-3 py-2.5 text-base/7 font-semibold text-white hover:bg-white/5 w-full text-left" className="-mx-3 block rounded-lg px-3 py-2.5 text-base/7 font-semibold text-gray-900 dark:text-white hover:bg-white/5 w-full text-left"
> >
Log in Log in
</button> </button>

View File

@ -27,7 +27,7 @@ export default function RootLayout({
return ( return (
<html lang="en" > <html lang="en" >
<body <body
className={`${geistSans.variable} ${geistMono.variable} antialiased`} className={`${geistSans.variable} ${geistMono.variable} antialiased bg-white text-gray-900 dark:bg-gray-900 dark:text-gray-100 transition-colors`}
> >
<ClientWrapper> <ClientWrapper>
{children} {children}

View File

@ -1,250 +1,141 @@
'use client' import PageLayout from './components/PageLayout';
import { useState } from 'react'
import { Dialog, DialogPanel } from '@headlessui/react'
import { Bars3Icon, XMarkIcon, SunIcon, MoonIcon } from '@heroicons/react/24/outline'
const navigation = [
{ name: 'Shop', href: '/shop' },
{ name: 'Affiliate-Links', href: '#' },
{ name: 'Memberships', href: '#' },
{ name: 'About us', href: '#' },
]
export default function Example() {
const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
const [isDarkMode, setIsDarkMode] = useState(true)
const toggleTheme = () => {
setIsDarkMode(!isDarkMode)
}
export default function HomePage() {
return ( return (
<div className={isDarkMode ? "bg-gray-900" : "bg-white"}> <PageLayout>
<header className="absolute inset-x-0 top-0 z-50"> {/* Hero Section */}
<nav aria-label="Global" className="mx-auto flex max-w-7xl items-center justify-between p-6 lg:px-8"> <section
<div className="flex lg:flex-1"> id="hero"
<a href="/" className="-m-1.5 p-1.5"> className="relative isolate flex flex-col min-h-screen" // added min-h-screen to ensure full height and push footer to bottom
<span className="sr-only">Profit Planet</span> >
<img {/* ...existing code (pattern SVG + blurred polygon) ... */}
alt="Profit Planet" <svg
src={isDarkMode ? "/images/logos/pp_logo_gold_transparent.png" : "/images/logos/pp_logo_gold_transparent.png"} aria-hidden="true"
className={`h-18 w-auto ${isDarkMode ? '' : 'brightness-0'}`} className="absolute inset-x-0 top-0 -z-10 h-256 w-full mask-[radial-gradient(32rem_32rem_at_center,white,transparent)] stroke-gray-900/10 dark:stroke-white/10"
/> >
</a> <defs>
</div> <pattern
<div className="flex lg:hidden"> x="50%"
<button y={-1}
type="button" id="hero-pattern"
onClick={() => setMobileMenuOpen(true)} width={200}
className={`-m-2.5 inline-flex items-center justify-center rounded-md p-2.5 ${isDarkMode ? 'text-gray-200' : 'text-gray-700'}`} height={200}
patternUnits="userSpaceOnUse"
> >
<span className="sr-only">Open main menu</span> <path d="M.5 200V.5H200" fill="none" />
<Bars3Icon aria-hidden="true" className="size-6" /> </pattern>
</button> </defs>
</div> <svg x="50%" y={-1} className="overflow-visible fill-gray-100 dark:fill-gray-800">
<div className="hidden lg:flex lg:gap-x-12"> <path
{navigation.map((item) => ( d="M-200 0h201v201h-201Z M600 0h201v201h-201Z M-400 600h201v201h-201Z M200 800h201v201h-201Z"
<a key={item.name} href={item.href} className={`text-sm/6 font-semibold ${isDarkMode ? 'text-white' : 'text-gray-900'}`}> strokeWidth={0}
{item.name} />
</a> </svg>
))} <rect fill="url(#hero-pattern)" width="100%" height="100%" strokeWidth={0} />
</div> </svg>
<div className="hidden lg:flex lg:flex-1 lg:justify-end lg:items-center lg:gap-x-4"> <div
<button aria-hidden="true"
onClick={toggleTheme} className="absolute top-0 right-0 left-1/2 -z-10 -ml-24 transform-gpu overflow-hidden blur-3xl lg:ml-24 xl:ml-48"
className={`p-2 rounded-md ${isDarkMode ? 'text-gray-200 hover:bg-white/5' : 'text-gray-600 hover:bg-gray-100'}`} >
> <div
{isDarkMode ? ( style={{
<SunIcon className="h-5 w-5" /> clipPath:
) : ( 'polygon(63.1% 29.5%, 100% 17.1%, 76.6% 3%, 48.4% 0%, 44.6% 4.7%, 54.5% 25.3%, 59.8% 49%, 55.2% 57.8%, 44.4% 57.2%, 27.8% 47.9%, 35.1% 81.5%, 0% 97.7%, 39.2% 100%, 35.2% 81.4%, 97.2% 52.8%, 63.1% 29.5%)',
<MoonIcon className="h-5 w-5" /> }}
)} className="aspect-801/1036 w-200.25 bg-linear-to-tr from-[#ff80b5] to-[#9089fc] opacity-30 dark:opacity-30"
</button> />
<a href="#" className={`text-sm/6 font-semibold ${isDarkMode ? 'text-white' : 'text-gray-900'}`}> </div>
Log in <span aria-hidden="true">&rarr;</span>
</a> {/* Background layering */}
</div> <div className="relative flex-1 overflow-hidden flex">
</nav> {/* ...existing code (absolute layers) ... */}
<Dialog open={mobileMenuOpen} onClose={setMobileMenuOpen} className="lg:hidden"> <div className="absolute inset-0 -z-30 bg-white dark:bg-gray-950" />
<div className="fixed inset-0 z-50" /> <div className="absolute inset-0 -z-20 bg-gradient-to-b from-gray-900/95 via-gray-900/80 to-gray-900 dark:from-gray-900/95 dark:via-gray-900/80 dark:to-gray-900" />
<DialogPanel className={`fixed inset-y-0 right-0 z-50 w-full overflow-y-auto ${isDarkMode ? 'bg-gray-900' : 'bg-white'} p-6 sm:max-w-sm sm:ring-1 ${isDarkMode ? 'sm:ring-gray-100/10' : 'sm:ring-gray-900/10'}`}> <div className="pointer-events-none absolute inset-0 -z-10 bg-[radial-gradient(circle_at_30%_20%,rgba(255,255,255,0.18),transparent_65%)] dark:bg-[radial-gradient(circle_at_35%_25%,rgba(255,255,255,0.08),transparent_60%)]" />
<div className="flex items-center justify-between"> <div className="pointer-events-none absolute inset-0 -z-10 mix-blend-overlay [background-image:linear-gradient(rgba(255,255,255,0.04)_1px,transparent_1px),linear-gradient(90deg,rgba(255,255,255,0.04)_1px,transparent_1px)] bg-[size:40px_40px]" />
<a href="#" className="-m-1.5 p-1.5">
<span className="sr-only">Profit Planet</span> {/* Content wrapper now fills and centers vertically */}
<img <div className="mx-auto max-w-7xl px-6 py-20 lg:py-28 flex w-full items-center min-h-full">
alt="Profit Planet" <div className="mx-auto max-w-2xl gap-x-14 lg:mx-0 lg:flex lg:max-w-none lg:items-center">
src={isDarkMode ? "/images/logo/pp_logo_gold_transparent.png" : "/images/logo/pp_logo_gold_transparent.png"} <div className="relative w-full lg:max-w-xl lg:shrink-0 xl:max-w-2xl">
className={`h-8 w-auto ${isDarkMode ? '' : 'brightness-0'}`} <h1 className="text-5xl font-semibold tracking-tight text-pretty text-white sm:text-7xl">
/> Profit Planet
</a> </h1>
<button <p className="mt-4 text-xl italic text-gray-300 sm:text-2xl">
type="button" Building a Community that will bring change
onClick={() => setMobileMenuOpen(false)} </p>
className={`-m-2.5 rounded-md p-2.5 ${isDarkMode ? 'text-gray-200' : 'text-gray-700'}`} <p className="mt-8 text-lg font-medium text-pretty text-gray-400 sm:max-w-md sm:text-xl/8 lg:max-w-none">
> Profit Planet is a platform building a vibrant community where members access diverse services and products from within. Users enjoy benefits like cashback and discounts, fostering a smart, rewarding ecosystem.
<span className="sr-only">Close menu</span> </p>
<XMarkIcon aria-hidden="true" className="size-6" /> <div className="mt-10 flex items-center gap-x-6">
</button>
</div>
<div className="mt-6 flow-root">
<div className={`-my-6 divide-y ${isDarkMode ? 'divide-white/10' : 'divide-gray-500/10'}`}>
<div className="space-y-2 py-6">
{navigation.map((item) => (
<a
key={item.name}
href={item.href}
className={`-mx-3 block rounded-lg px-3 py-2 text-base/7 font-semibold ${isDarkMode ? 'text-white hover:bg-white/5' : 'text-gray-900 hover:bg-gray-50'}`}
>
{item.name}
</a>
))}
</div>
<div className="py-6 space-y-2">
<button
onClick={toggleTheme}
className={`-mx-3 flex w-full items-center rounded-lg px-3 py-2.5 text-base/7 font-semibold ${isDarkMode ? 'text-white hover:bg-white/5' : 'text-gray-900 hover:bg-gray-50'}`}
>
{isDarkMode ? (
<>
<SunIcon className="h-5 w-5 mr-2" />
Light Mode
</>
) : (
<>
<MoonIcon className="h-5 w-5 mr-2" />
Dark Mode
</>
)}
</button>
<a <a
href="#" href="/shop"
className={`-mx-3 block rounded-lg px-3 py-2.5 text-base/7 font-semibold ${isDarkMode ? 'text-white hover:bg-white/5' : 'text-gray-900 hover:bg-gray-50'}`} className="rounded-md bg-indigo-500 px-3.5 py-2.5 text-sm font-semibold text-white shadow-xs hover:bg-indigo-400 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500"
> >
Log in Shop
</a>
<a href="/login" className="text-sm/6 font-semibold text-white">
Login <span aria-hidden="true"></span>
</a> </a>
</div> </div>
</div> </div>
</div> {/* Removed sm:-mt-44 to prevent height reduction */}
</DialogPanel> <div className="mt-14 flex justify-end gap-8 sm:mt-14 sm:justify-start sm:pl-20 lg:mt-0 lg:pl-0">
</Dialog> {/* ...existing code (image stacks) ... */}
</header> <div className="ml-auto w-44 flex-none space-y-8 pt-32 sm:ml-0 sm:pt-80 lg:order-last lg:pt-36 xl:order-0 xl:pt-80">
<main> <div className="relative">
<div className="relative isolate"> <img
<svg alt=""
aria-hidden="true" src="https://images.unsplash.com/photo-1557804506-669a67965ba0?auto=format&fit=crop&h=528&q=80"
className={`absolute inset-x-0 top-0 -z-10 h-256 w-full mask-[radial-gradient(32rem_32rem_at_center,white,transparent)] ${isDarkMode ? 'stroke-white/10' : 'stroke-gray-900/10'}`} className="aspect-2/3 w-full rounded-xl bg-gray-700/5 object-cover shadow-lg"
> />
<defs> <div className="pointer-events-none absolute inset-0 rounded-xl ring-1 ring-white/10 ring-inset" />
<pattern
x="50%"
y={-1}
id="1f932ae7-37de-4c0a-a8b0-a6e3b4d44b84"
width={200}
height={200}
patternUnits="userSpaceOnUse"
>
<path d="M.5 200V.5H200" fill="none" />
</pattern>
</defs>
<svg x="50%" y={-1} className={`overflow-visible ${isDarkMode ? 'fill-gray-800' : 'fill-gray-100'}`}>
<path
d="M-200 0h201v201h-201Z M600 0h201v201h-201Z M-400 600h201v201h-201Z M200 800h201v201h-201Z"
strokeWidth={0}
/>
</svg>
<rect fill="url(#1f932ae7-37de-4c0a-a8b0-a6e3b4d44b84)" width="100%" height="100%" strokeWidth={0} />
</svg>
<div
aria-hidden="true"
className="absolute top-0 right-0 left-1/2 -z-10 -ml-24 transform-gpu overflow-hidden blur-3xl lg:ml-24 xl:ml-48"
>
<div
style={{
clipPath:
'polygon(63.1% 29.5%, 100% 17.1%, 76.6% 3%, 48.4% 0%, 44.6% 4.7%, 54.5% 25.3%, 59.8% 49%, 55.2% 57.8%, 44.4% 57.2%, 27.8% 47.9%, 35.1% 81.5%, 0% 97.7%, 39.2% 100%, 35.2% 81.4%, 97.2% 52.8%, 63.1% 29.5%)',
}}
className={`aspect-801/1036 w-200.25 ${isDarkMode ? 'bg-linear-to-tr from-[#ff80b5] to-[#9089fc] opacity-30' : 'bg-linear-to-tr from-[#fbbf24] to-[#3b82f6] opacity-20'}`}
/>
</div>
<div className="overflow-hidden">
<div className="mx-auto max-w-7xl px-6 pt-36 pb-32 sm:pt-60 lg:px-8 lg:pt-32">
<div className="mx-auto max-w-2xl gap-x-14 lg:mx-0 lg:flex lg:max-w-none lg:items-center">
<div className="relative w-full lg:max-w-xl lg:shrink-0 xl:max-w-2xl">
<h1 className={`text-5xl font-semibold tracking-tight text-pretty ${isDarkMode ? 'text-white' : 'text-gray-900'} sm:text-7xl`}>
Profit Planet
</h1>
<p className={`mt-4 text-xl italic ${isDarkMode ? 'text-gray-300' : 'text-gray-600'} sm:text-2xl`}>
Building a Community that will bring change
</p>
<p className={`mt-8 text-lg font-medium text-pretty ${isDarkMode ? 'text-gray-400' : 'text-gray-600'} sm:max-w-md sm:text-xl/8 lg:max-w-none`}>
Profit Planet is a platform building a vibrant community where members access diverse services and products from within. Users enjoy benefits like cashback and discounts, fostering a smart, rewarding ecosystem.
</p>
<div className="mt-10 flex items-center gap-x-6">
<a
href="/shop"
className="rounded-md bg-indigo-500 px-3.5 py-2.5 text-sm font-semibold text-white shadow-xs hover:bg-indigo-400 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500"
>
Shop
</a>
<a href="/login" className={`text-sm/6 font-semibold ${isDarkMode ? 'text-white' : 'text-gray-900'}`}>
Login <span aria-hidden="true"></span>
</a>
</div> </div>
</div> </div>
<div className="mt-14 flex justify-end gap-8 sm:-mt-44 sm:justify-start sm:pl-20 lg:mt-0 lg:pl-0"> <div className="mr-auto w-44 flex-none space-y-8 sm:mr-0 sm:pt-52 lg:pt-36">
<div className="ml-auto w-44 flex-none space-y-8 pt-32 sm:ml-0 sm:pt-80 lg:order-last lg:pt-36 xl:order-0 xl:pt-80"> <div className="relative">
<div className="relative"> <img
<img alt=""
alt="" src="https://images.unsplash.com/photo-1485217988980-11786ced9454?auto=format&fit=crop&h=528&q=80"
src="https://images.unsplash.com/photo-1557804506-669a67965ba0?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&h=528&q=80" className="aspect-2/3 w-full rounded-xl bg-gray-700/5 object-cover shadow-lg"
className="aspect-2/3 w-full rounded-xl bg-gray-700/5 object-cover shadow-lg" />
/> <div className="pointer-events-none absolute inset-0 rounded-xl ring-1 ring-white/10 ring-inset" />
<div className={`pointer-events-none absolute inset-0 rounded-xl ring-1 ${isDarkMode ? 'ring-white/10' : 'ring-gray-900/10'} ring-inset`} />
</div>
</div> </div>
<div className="mr-auto w-44 flex-none space-y-8 sm:mr-0 sm:pt-52 lg:pt-36"> <div className="relative">
<div className="relative"> <img
<img alt=""
alt="" src="https://images.unsplash.com/photo-1559136555-9303baea8ebd?auto=format&fit=crop&crop=focalpoint&fp-x=.4&w=396&h=528&q=80"
src="https://images.unsplash.com/photo-1485217988980-11786ced9454?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&h=528&q=80" className="aspect-2/3 w-full rounded-xl bg-gray-700/5 object-cover shadow-lg"
className="aspect-2/3 w-full rounded-xl bg-gray-700/5 object-cover shadow-lg" />
/> <div className="pointer-events-none absolute inset-0 rounded-xl ring-1 ring-white/10 ring-inset" />
<div className={`pointer-events-none absolute inset-0 rounded-xl ring-1 ${isDarkMode ? 'ring-white/10' : 'ring-gray-900/10'} ring-inset`} />
</div>
<div className="relative">
<img
alt=""
src="https://images.unsplash.com/photo-1559136555-9303baea8ebd?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&crop=focalpoint&fp-x=.4&w=396&h=528&q=80"
className="aspect-2/3 w-full rounded-xl bg-gray-700/5 object-cover shadow-lg"
/>
<div className={`pointer-events-none absolute inset-0 rounded-xl ring-1 ${isDarkMode ? 'ring-white/10' : 'ring-gray-900/10'} ring-inset`} />
</div>
</div> </div>
<div className="w-44 flex-none space-y-8 pt-32 sm:pt-0"> </div>
<div className="relative"> <div className="w-44 flex-none space-y-8 pt-32 sm:pt-0">
<img <div className="relative">
alt="" <img
src="https://images.unsplash.com/photo-1670272504528-790c24957dda?ixlib=rb-4.0.3&ixid=MnwxMjA3fDF8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&crop=left&w=400&h=528&q=80" alt=""
className="aspect-2/3 w-full rounded-xl bg-gray-700/5 object-cover shadow-lg" src="https://images.unsplash.com/photo-1670272504528-790c24957dda?auto=format&fit=crop&crop=left&w=400&h=528&q=80"
/> className="aspect-2/3 w-full rounded-xl bg-gray-700/5 object-cover shadow-lg"
<div className={`pointer-events-none absolute inset-0 rounded-xl ring-1 ${isDarkMode ? 'ring-white/10' : 'ring-gray-900/10'} ring-inset`} /> />
</div> <div className="pointer-events-none absolute inset-0 rounded-xl ring-1 ring-white/10 ring-inset" />
<div className="relative"> </div>
<img <div className="relative">
alt="" <img
src="https://images.unsplash.com/photo-1670272505284-8faba1c31f7d?ixlib=rb-4.0.3&ixid=MnwxMjA3fDF8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&h=528&q=80" alt=""
className="aspect-2/3 w-full rounded-xl bg-gray-700/5 object-cover shadow-lg" src="https://images.unsplash.com/photo-1670272505284-8faba1c31f7d?auto=format&fit=crop&h=528&q=80"
/> className="aspect-2/3 w-full rounded-xl bg-gray-700/5 object-cover shadow-lg"
<div className={`pointer-events-none absolute inset-0 rounded-xl ring-1 ${isDarkMode ? 'ring-white/10' : 'ring-gray-900/10'} ring-inset`} /> />
</div> <div className="pointer-events-none absolute inset-0 rounded-xl ring-1 ring-white/10 ring-inset" />
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
{/* Bottom fade (optional) */}
<div className="pointer-events-none absolute inset-x-0 bottom-0 h-24 bg-gradient-to-b from-transparent to-[#0F172A]" />
</div> </div>
</main> </section>
</div> </PageLayout>
) );
} }