feat: move old components to __old__ dir
This commit is contained in:
@@ -0,0 +1,130 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import HERO_STATS from '@/data/hero-stats.json';
|
||||||
|
import { Button, SparklesIcon } from '@components';
|
||||||
|
import { motion } from 'framer-motion';
|
||||||
|
import Image from 'next/image';
|
||||||
|
import { Fragment, useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
export function Hero() {
|
||||||
|
const [scrollY, setScrollY] = useState(0);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handleScroll = () => {
|
||||||
|
setScrollY(window.scrollY);
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('scroll', handleScroll);
|
||||||
|
return () => window.removeEventListener('scroll', handleScroll);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="relative w-full py-20 md:py-32 lg:py-40 overflow-hidden">
|
||||||
|
<div className="absolute inset-0 -z-10 overflow-hidden">
|
||||||
|
<div className="absolute top-0 left-0 w-full h-full bg-gradient-to-b from-background to-background/50" />
|
||||||
|
<div
|
||||||
|
className="absolute top-1/4 -left-20 w-80 h-80 rounded-full bg-gradient-to-r from-primary/20 to-blue-400/20 blur-3xl"
|
||||||
|
style={{
|
||||||
|
transform: `translate(${scrollY * 0.1}px, ${scrollY * -0.05}px)`,
|
||||||
|
opacity: Math.max(0.2, 1 - scrollY * 0.001),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
className="absolute bottom-1/3 -right-20 w-80 h-80 rounded-full bg-gradient-to-r from-blue-400/20 to-primary/20 blur-3xl"
|
||||||
|
style={{
|
||||||
|
transform: `translate(${scrollY * -0.1}px, ${scrollY * 0.05}px)`,
|
||||||
|
opacity: Math.max(0.2, 1 - scrollY * 0.001),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div className="absolute inset-0 bg-[linear-gradient(rgba(59,130,246,0.05)_1px,transparent_1px),linear-gradient(to_right,rgba(59,130,246,0.05)_1px,transparent_1px)] bg-[size:40px_40px]" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="container px-4 md:px-6 relative">
|
||||||
|
<div className="grid gap-6 lg:grid-cols-2 lg:gap-12 items-center">
|
||||||
|
<motion.div
|
||||||
|
className="flex flex-col justify-center space-y-8"
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
animate={{ opacity: 1, y: 0 }}
|
||||||
|
transition={{ duration: 0.5 }}
|
||||||
|
>
|
||||||
|
<div className="inline-flex items-center rounded-full border px-3 py-1 text-sm w-fit">
|
||||||
|
<SparklesIcon className="mr-1 h-3.5 w-3.5 text-primary" />
|
||||||
|
<span>Komunitas Programmer Indonesia</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-4">
|
||||||
|
<h1 className="text-4xl md:text-5xl lg:text-6xl xl:text-7xl font-bold tracking-tighter bg-clip-text text-transparent bg-gradient-to-r from-foreground via-foreground to-foreground/70">
|
||||||
|
Programmer Handal, <br />
|
||||||
|
<span className="bg-clip-text text-transparent bg-gradient-to-r from-primary to-blue-400">
|
||||||
|
Tanpa Ribet
|
||||||
|
</span>
|
||||||
|
</h1>
|
||||||
|
<p className="max-w-[600px] text-muted-foreground md:text-xl">
|
||||||
|
Temukan potensi programming Anda bersama komunitas yang
|
||||||
|
mendukung, tutorial interaktif, dan sumber daya berkualitas
|
||||||
|
tinggi.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col sm:flex-row gap-4 w-full sm:w-auto">
|
||||||
|
<Button
|
||||||
|
size="lg"
|
||||||
|
className="group relative w-full sm:w-auto bg-gradient-to-r from-primary to-blue-600 hover:from-primary/90 hover:to-blue-600/90 transition-all duration-300 font-bold text-white hover:text-white/90 shadow-lg cursor-pointer"
|
||||||
|
onClick={() =>
|
||||||
|
window.open(
|
||||||
|
'https://facebook.com/groups/programmerhandal',
|
||||||
|
'_blank'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Mulai Belajar
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
size="lg"
|
||||||
|
variant="outline"
|
||||||
|
className="w-full sm:w-auto group relative overflow-hidden border-primary"
|
||||||
|
onClick={() =>
|
||||||
|
window.open('https://discord.com/invite/imphnen', '_blank')
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<span className="absolute inset-0 bg-gradient-to-r from-primary/10 to-blue-400/10 translate-y-full group-hover:translate-y-0 transition-transform duration-300" />
|
||||||
|
<span className="relative">Gabung Discord</span>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-wrap justify-center md:justify-start gap-6 sm:gap-8">
|
||||||
|
{HERO_STATS.map(({ value, label }, i) => (
|
||||||
|
<Fragment key={i}>
|
||||||
|
<div className="flex flex-col items-center">
|
||||||
|
<div className="text-2xl font-bold bg-clip-text text-transparent bg-gradient-to-r from-primary to-blue-400">
|
||||||
|
{value}
|
||||||
|
</div>
|
||||||
|
<div className="text-xs text-muted-foreground">{label}</div>
|
||||||
|
</div>
|
||||||
|
{i < HERO_STATS.length - 1 && (
|
||||||
|
<div className="hidden sm:block h-10 border-r border-border mx-4" />
|
||||||
|
)}
|
||||||
|
</Fragment>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
<motion.div
|
||||||
|
className="relative w-full lg:w-auto mx-auto lg:ml-auto"
|
||||||
|
initial={{ opacity: 0, scale: 0.9 }}
|
||||||
|
animate={{ opacity: 1, scale: 1 }}
|
||||||
|
transition={{ duration: 0.5, delay: 0.2 }}
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
src="/logo.webp"
|
||||||
|
alt="logo"
|
||||||
|
width={600}
|
||||||
|
height={500}
|
||||||
|
className="w-full h-auto object-cover"
|
||||||
|
/>
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,12 +1,15 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import HERO_STATS from '@/data/hero-stats.json';
|
import HERO_STATS from '@/data/hero-stats.json';
|
||||||
import { Button, SparklesIcon } from '@components';
|
import { Button } from '@components';
|
||||||
import { motion } from 'framer-motion';
|
import { motion } from 'framer-motion';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
|
import { useRouter } from 'next/navigation';
|
||||||
import { Fragment, useEffect, useState } from 'react';
|
import { Fragment, useEffect, useState } from 'react';
|
||||||
|
|
||||||
export function Hero() {
|
export function Hero() {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
const [scrollY, setScrollY] = useState(0);
|
const [scrollY, setScrollY] = useState(0);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -47,48 +50,35 @@ export function Hero() {
|
|||||||
animate={{ opacity: 1, y: 0 }}
|
animate={{ opacity: 1, y: 0 }}
|
||||||
transition={{ duration: 0.5 }}
|
transition={{ duration: 0.5 }}
|
||||||
>
|
>
|
||||||
<div className="inline-flex items-center rounded-full border px-3 py-1 text-sm w-fit">
|
<span className="inline-flex items-center rounded-full border px-3 py-1 text-sm w-fit">
|
||||||
<SparklesIcon className="mr-1 h-3.5 w-3.5 text-primary" />
|
Komunitas Programmer Indonesia
|
||||||
<span>Komunitas Programmer Indonesia</span>
|
</span>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<h1 className="text-4xl md:text-5xl lg:text-6xl xl:text-7xl font-bold tracking-tighter bg-clip-text text-transparent bg-gradient-to-r from-foreground via-foreground to-foreground/70">
|
<h1 className="text-4xl md:text-5xl lg:text-6xl xl:text-7xl font-bold tracking-tighter bg-clip-text text-transparent bg-gradient-to-r from-foreground via-foreground to-foreground/70">
|
||||||
Programmer Handal, <br />
|
Programmer Handal <br />
|
||||||
<span className="bg-clip-text text-transparent bg-gradient-to-r from-primary to-blue-400">
|
<span className="bg-clip-text bg-gradient-to-r text-primary-500">
|
||||||
Tanpa Ribet
|
Enggan Ngoding
|
||||||
</span>
|
</span>
|
||||||
</h1>
|
</h1>
|
||||||
<p className="max-w-[600px] text-muted-foreground md:text-xl">
|
<p className="max-w-[600px] text-muted-foreground md:text-xl">
|
||||||
Temukan potensi programming Anda bersama komunitas yang
|
Komunitas programmer terbesar di indonesia, tempat berbagi meme,
|
||||||
mendukung, tutorial interaktif, dan sumber daya berkualitas
|
tutorial, pengalaman dan yapping
|
||||||
tinggi.
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col sm:flex-row gap-4 w-full sm:w-auto">
|
<div className="flex flex-col sm:flex-row gap-4 w-full sm:w-auto">
|
||||||
<Button
|
<Button size="lg" onClick={() => router.push('#komunitas')}>
|
||||||
size="lg"
|
Join Komunitas
|
||||||
className="group relative w-full sm:w-auto bg-gradient-to-r from-primary to-blue-600 hover:from-primary/90 hover:to-blue-600/90 transition-all duration-300 font-bold text-white hover:text-white/90 shadow-lg cursor-pointer"
|
|
||||||
onClick={() =>
|
|
||||||
window.open(
|
|
||||||
'https://facebook.com/groups/programmerhandal',
|
|
||||||
'_blank'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
Mulai Belajar
|
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
size="lg"
|
size="lg"
|
||||||
variant="outline"
|
variant="bordered"
|
||||||
className="w-full sm:w-auto group relative overflow-hidden border-primary"
|
className="w-full sm:w-auto group relative overflow-hidden"
|
||||||
onClick={() =>
|
onClick={() => router.push('/events')}
|
||||||
window.open('https://discord.com/invite/imphnen', '_blank')
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<span className="absolute inset-0 bg-gradient-to-r from-primary/10 to-blue-400/10 translate-y-full group-hover:translate-y-0 transition-transform duration-300" />
|
<span className="absolute inset-0 bg-gradient-to-r from-primary/10 to-blue-400/10 translate-y-full group-hover:translate-y-0 transition-transform duration-300" />
|
||||||
<span className="relative">Gabung Discord</span>
|
<span className="relative">Explore Event</span>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -96,7 +86,7 @@ export function Hero() {
|
|||||||
{HERO_STATS.map(({ value, label }, i) => (
|
{HERO_STATS.map(({ value, label }, i) => (
|
||||||
<Fragment key={i}>
|
<Fragment key={i}>
|
||||||
<div className="flex flex-col items-center">
|
<div className="flex flex-col items-center">
|
||||||
<div className="text-2xl font-bold bg-clip-text text-transparent bg-gradient-to-r from-primary to-blue-400">
|
<div className="text-2xl font-bold bg-clip-text text-primary-500">
|
||||||
{value}
|
{value}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-xs text-muted-foreground">{label}</div>
|
<div className="text-xs text-muted-foreground">{label}</div>
|
||||||
|
|||||||
@@ -1,19 +1,9 @@
|
|||||||
import { CallToAction } from './_components/call-to-action';
|
|
||||||
import { Community } from './_components/community';
|
|
||||||
import { Features } from './_components/features';
|
|
||||||
import { Hero } from './_components/hero';
|
import { Hero } from './_components/hero';
|
||||||
import { LearningResources } from './_components/learning-resources';
|
|
||||||
import { Testimonials } from './_components/testimonials';
|
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Hero />
|
<Hero />
|
||||||
<Features />
|
|
||||||
<Community />
|
|
||||||
<LearningResources />
|
|
||||||
<Testimonials />
|
|
||||||
<CallToAction />
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import Image from 'next/image';
|
|||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { ThemeToggle } from './theme-toggle';
|
|
||||||
|
|
||||||
export function Header() {
|
export function Header() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -82,18 +81,11 @@ export function Header() {
|
|||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div className="flex items-center gap-x-2">
|
<div className="flex items-center gap-x-2">
|
||||||
<ThemeToggle />
|
<Button onClick={() => router.push('/signin')}>Login</Button>
|
||||||
|
|
||||||
<Button
|
|
||||||
className="group relative w-full sm:w-auto bg-gradient-to-r from-primary to-blue-600 hover:from-primary/90 hover:to-blue-600/90 transition-all duration-300 font-bold text-white hover:text-white/90 shadow-lg cursor-pointer"
|
|
||||||
onClick={() => router.push('/signin')}
|
|
||||||
>
|
|
||||||
Login
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
{/* Mobile Menu Button */}
|
{/* Mobile Menu Button */}
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="secondary"
|
||||||
size="icon"
|
size="icon"
|
||||||
className="md:hidden"
|
className="md:hidden"
|
||||||
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
|
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
|
||||||
@@ -140,12 +132,7 @@ export function Header() {
|
|||||||
Testimoni
|
Testimoni
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<Button
|
<Button onClick={() => router.push('/signin')}>Login</Button>
|
||||||
onClick={() => router.push('/signin')}
|
|
||||||
className="group relative w-full sm:w-auto bg-gradient-to-r from-primary to-blue-600 hover:from-primary/90 hover:to-blue-600/90 transition-all duration-300 font-bold text-white hover:text-white/90 shadow-lg cursor-pointer"
|
|
||||||
>
|
|
||||||
Login
|
|
||||||
</Button>
|
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export function ThemeToggle() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="bordered"
|
||||||
size="icon"
|
size="icon"
|
||||||
onClick={toggleTheme}
|
onClick={toggleTheme}
|
||||||
className="focus-visible:ring-0 cursor-pointer"
|
className="focus-visible:ring-0 cursor-pointer"
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { baiJamjureeFont } from '@/lib/fonts';
|
import { baiJamjureeFont } from '@/lib/fonts';
|
||||||
import '@/styles/globals.css';
|
import '@/styles/globals.css';
|
||||||
|
import { cn } from '@utils';
|
||||||
import { type Metadata } from 'next';
|
import { type Metadata } from 'next';
|
||||||
import { Providers } from './_components/providers';
|
import { Providers } from './_components/providers';
|
||||||
|
|
||||||
@@ -15,7 +16,7 @@ export default function RootLayout({
|
|||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<html lang="id" suppressHydrationWarning>
|
<html lang="id" suppressHydrationWarning>
|
||||||
<body className={baiJamjureeFont.className}>
|
<body className={cn(baiJamjureeFont.className, 'antialiased')}>
|
||||||
<Providers
|
<Providers
|
||||||
attribute="class"
|
attribute="class"
|
||||||
defaultTheme="system"
|
defaultTheme="system"
|
||||||
|
|||||||
Reference in New Issue
Block a user