first commit

This commit is contained in:
2026-06-16 13:02:08 +03:00
commit 76af0683fd
51 changed files with 12923 additions and 0 deletions
+96
View File
@@ -0,0 +1,96 @@
'use client';
import { useState, useEffect } from 'react';
import Image from 'next/image';
import { heroSlides } from '@/lib/data';
import { ChevronLeft, ChevronRight } from 'lucide-react';
import { Link } from '@/i18n/routing';
export function HeroSlider() {
const [current, setCurrent] = useState(0);
useEffect(() => {
const timer = setInterval(() => {
setCurrent((prev) => (prev === heroSlides.length - 1 ? 0 : prev + 1));
}, 5000);
return () => clearInterval(timer);
}, []);
const nextSlide = () => setCurrent(current === heroSlides.length - 1 ? 0 : current + 1);
const prevSlide = () => setCurrent(current === 0 ? heroSlides.length - 1 : current - 1);
return (
<div className="relative h-[80vh] min-h-[600px] w-full overflow-hidden group bg-deepblue-900">
{/* Decorative Aurora Gradients */}
<div className="absolute inset-0 overflow-hidden pointer-events-none z-10 opacity-60 mix-blend-screen">
<div className="absolute -top-[30%] -left-[10%] w-[60%] h-[60%] rounded-full bg-vibrantorange-500/30 blur-[120px] animate-pulse" style={{ animationDuration: '8s' }} />
<div className="absolute top-[20%] -right-[20%] w-[70%] h-[70%] rounded-full bg-turquoise-500/30 blur-[150px] animate-pulse" style={{ animationDuration: '12s' }} />
<div className="absolute -bottom-[40%] left-[20%] w-[80%] h-[80%] rounded-full bg-deepblue-900/40 blur-[100px] animate-pulse" style={{ animationDuration: '10s' }} />
</div>
{heroSlides.map((slide, index) => (
<div
key={index}
className={`absolute inset-0 transition-all duration-1000 ease-in-out ${
index === current ? 'opacity-100 z-10 scale-100' : 'opacity-0 z-0 scale-105'
}`}
>
<Image
src={slide}
alt={`Ölüdeniz Slider ${index + 1}`}
fill
className="object-cover mix-blend-overlay opacity-60"
priority={index === 0}
/>
{/* Overlay gradient for text readability and aurora blend */}
<div className="absolute inset-0 bg-gradient-to-t from-deepblue-900 via-deepblue-900/60 to-transparent" />
</div>
))}
{/* Content */}
<div className="absolute inset-0 z-20 flex flex-col items-center justify-center text-center px-4 pt-16">
<h1 className="text-5xl md:text-7xl lg:text-8xl font-extrabold text-white tracking-tight mb-6 animate-in fade-in slide-in-from-bottom-12 duration-1000 fill-mode-both drop-shadow-2xl">
ÖLÜDENİZ <span className="text-transparent bg-clip-text bg-gradient-to-r from-turquoise-500 to-vibrantorange-500">TOUR</span> TRAVELS
</h1>
<p className="text-xl md:text-3xl text-sandwhite-100 mb-12 max-w-4xl mx-auto font-medium animate-in fade-in slide-in-from-bottom-8 duration-1000 delay-300 fill-mode-both drop-shadow-lg">
Mavi Yolculuk, Günübirlik Turlar ve Unutulmaz Aktiviteler
</p>
<div className="flex flex-col sm:flex-row gap-6 animate-in fade-in slide-in-from-bottom-8 duration-1000 delay-700 fill-mode-both">
<Link href="/turlar" className="px-10 py-5 bg-gradient-to-r from-vibrantorange-500 to-orange-400 hover:from-orange-400 hover:to-vibrantorange-500 text-white rounded-2xl font-bold text-lg transition-all shadow-[0_0_30px_rgba(249,115,22,0.4)] hover:shadow-[0_0_50px_rgba(249,115,22,0.6)] hover:-translate-y-1">
Turları Keşfet
</Link>
<Link href="/aktiviteler" className="px-10 py-5 bg-white/10 hover:bg-white/20 backdrop-blur-md border border-white/20 text-white rounded-2xl font-bold text-lg transition-all shadow-lg hover:shadow-xl hover:-translate-y-1">
Aktiviteler
</Link>
</div>
</div>
{/* Controls */}
<button
onClick={prevSlide}
className="absolute left-4 top-1/2 -translate-y-1/2 z-30 w-12 h-12 bg-black/20 hover:bg-black/50 text-white rounded-full flex items-center justify-center opacity-0 group-hover:opacity-100 transition-all backdrop-blur-sm"
>
<ChevronLeft className="w-6 h-6" />
</button>
<button
onClick={nextSlide}
className="absolute right-4 top-1/2 -translate-y-1/2 z-30 w-12 h-12 bg-black/20 hover:bg-black/50 text-white rounded-full flex items-center justify-center opacity-0 group-hover:opacity-100 transition-all backdrop-blur-sm"
>
<ChevronRight className="w-6 h-6" />
</button>
{/* Indicators */}
<div className="absolute bottom-8 left-1/2 -translate-x-1/2 z-30 flex gap-2">
{heroSlides.map((_, index) => (
<button
key={index}
onClick={() => setCurrent(index)}
className={`w-3 h-3 rounded-full transition-all ${
index === current ? 'bg-white scale-125' : 'bg-white/50'
}`}
/>
))}
</div>
</div>
);
}
+54
View File
@@ -0,0 +1,54 @@
import { Link } from '@/i18n/routing';
import { siteInfo } from '@/lib/data';
import { Phone, Mail, MapPin } from 'lucide-react';
export function Footer() {
return (
<footer className="bg-deepblue-900 text-sandwhite-100 py-12">
<div className="container mx-auto px-4 grid grid-cols-1 md:grid-cols-3 gap-8">
<div>
<h3 className="font-bold text-xl mb-4 text-white">{siteInfo.name}</h3>
<p className="text-sm text-gray-300 max-w-sm">
{siteInfo.slogan}
</p>
</div>
<div>
<h4 className="font-semibold text-lg mb-4 text-white">Hızlı Linkler</h4>
<ul className="space-y-2 text-sm text-gray-300">
<li><Link href="/hakkimizda" className="hover:text-turquoise-500 transition-colors">Hakkımızda</Link></li>
<li><Link href="/turlar" className="hover:text-turquoise-500 transition-colors">Turlar</Link></li>
<li><Link href="/aktiviteler" className="hover:text-turquoise-500 transition-colors">Aktiviteler</Link></li>
<li><Link href="/tekne-turlari" className="hover:text-turquoise-500 transition-colors">Tekne Turları</Link></li>
<li><Link href="/iletisim" className="hover:text-turquoise-500 transition-colors">İletişim</Link></li>
</ul>
</div>
<div>
<h4 className="font-semibold text-lg mb-4 text-white">İletişim</h4>
<ul className="space-y-3 text-sm text-gray-300">
<li className="flex items-start gap-2">
<MapPin className="w-5 h-5 text-turquoise-500 shrink-0" />
<span>{siteInfo.address}</span>
</li>
<li className="flex items-center gap-2">
<Phone className="w-5 h-5 text-turquoise-500 shrink-0" />
<a href={siteInfo.phoneLink} className="hover:text-white transition-colors">{siteInfo.phone}</a>
</li>
<li className="flex items-center gap-2">
<Mail className="w-5 h-5 text-turquoise-500 shrink-0" />
<a href={`mailto:${siteInfo.email}`} className="hover:text-white transition-colors">{siteInfo.email}</a>
</li>
</ul>
</div>
</div>
<div className="container mx-auto px-4 mt-12 pt-8 border-t border-white/10 flex flex-col md:flex-row items-center justify-between text-sm text-gray-400">
<p>&copy; {new Date().getFullYear()} {siteInfo.name}. Tüm hakları saklıdır.</p>
<p className="mt-2 md:mt-0">
<a href="https://ayris.tech" target="_blank" rel="noreferrer" className="hover:text-white transition-colors">Created by ayris.tech</a>
</p>
</div>
</footer>
);
}
+62
View File
@@ -0,0 +1,62 @@
'use client';
import { Link } from '@/i18n/routing';
import { siteInfo } from '@/lib/data';
import { Phone, MapPin, Menu } from 'lucide-react';
import { useState } from 'react';
export function Navbar() {
const [isOpen, setIsOpen] = useState(false);
return (
<div className="fixed top-4 left-4 right-4 z-50">
<header className="container mx-auto bg-white/80 backdrop-blur-xl border border-white/20 shadow-lg rounded-2xl transition-all duration-300">
<div className="px-6 h-20 flex items-center justify-between">
<Link href="/" className="font-extrabold text-2xl text-deepblue-900 tracking-tighter flex items-center gap-2 hover:opacity-80 transition-opacity">
{siteInfo.name}
</Link>
{/* Desktop Nav */}
<nav className="hidden md:flex items-center gap-6">
<Link href="/" className="text-sm font-medium hover:text-turquoise-500 transition-colors">Ana Sayfa</Link>
<Link href="/hakkimizda" className="text-sm font-medium hover:text-turquoise-500 transition-colors">Hakkımızda</Link>
<Link href="/turlar" className="text-sm font-medium hover:text-turquoise-500 transition-colors">Turlar</Link>
<Link href="/aktiviteler" className="text-sm font-medium hover:text-turquoise-500 transition-colors">Aktiviteler</Link>
<Link href="/tekne-turlari" className="text-sm font-medium hover:text-turquoise-500 transition-colors">Tekne Turları</Link>
<Link href="/iletisim" className="text-sm font-medium hover:text-turquoise-500 transition-colors">İletişim</Link>
</nav>
<div className="hidden md:flex items-center gap-4">
<a href={siteInfo.phoneLink} className="flex items-center gap-2 text-sm font-semibold text-deepblue-900">
<Phone className="w-4 h-4 text-turquoise-500" />
{siteInfo.phone}
</a>
<a href={siteInfo.whatsappLink} target="_blank" rel="noreferrer" className="px-4 py-2 bg-vibrantorange-500 hover:bg-orange-600 text-white rounded-md text-sm font-medium transition-colors">
Rezervasyon
</a>
</div>
{/* Mobile Toggle */}
<button className="md:hidden p-2" onClick={() => setIsOpen(!isOpen)}>
<Menu className="w-6 h-6" />
</button>
</div>
{/* Mobile Nav */}
{isOpen && (
<div className="md:hidden border-t p-4 flex flex-col gap-4 bg-sandwhite-100">
<Link href="/" onClick={() => setIsOpen(false)} className="text-sm font-medium">Ana Sayfa</Link>
<Link href="/hakkimizda" onClick={() => setIsOpen(false)} className="text-sm font-medium">Hakkımızda</Link>
<Link href="/turlar" onClick={() => setIsOpen(false)} className="text-sm font-medium">Turlar</Link>
<Link href="/aktiviteler" onClick={() => setIsOpen(false)} className="text-sm font-medium">Aktiviteler</Link>
<Link href="/tekne-turlari" onClick={() => setIsOpen(false)} className="text-sm font-medium">Tekne Turları</Link>
<Link href="/iletisim" onClick={() => setIsOpen(false)} className="text-sm font-medium">İletişim</Link>
<a href={siteInfo.whatsappLink} className="mt-2 block text-center px-4 py-2 bg-vibrantorange-500 text-white rounded-md text-sm font-medium">
Rezervasyon
</a>
</div>
)}
</header>
</div>
);
}
+54
View File
@@ -0,0 +1,54 @@
'use client';
import Image from 'next/image';
import { Link } from '@/i18n/routing';
import { motion } from 'framer-motion';
import { ArrowRight } from 'lucide-react';
interface TourCardProps {
item: {
id: number;
slug: string;
title: string;
image: string;
price: string;
};
basePath: string; // e.g. "/turlar", "/aktiviteler"
index?: number;
}
export function TourCard({ item, basePath, index = 0 }: TourCardProps) {
return (
<motion.div
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: "-50px" }}
transition={{ duration: 0.5, delay: index * 0.1 }}
className="bg-white/80 backdrop-blur-md rounded-3xl overflow-hidden shadow-[0_8px_30px_rgb(0,0,0,0.04)] hover:shadow-[0_20px_40px_rgb(0,0,0,0.08)] transition-all duration-500 border border-white/50 flex flex-col group"
>
<div className="relative aspect-[4/3] w-full overflow-hidden">
<Image
src={item.image}
alt={item.title}
fill
className="object-cover group-hover:scale-110 transition-transform duration-700 ease-out"
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
/>
<div className="absolute inset-0 bg-gradient-to-t from-black/60 via-transparent to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500" />
<div className="absolute top-4 right-4 bg-white/90 backdrop-blur-md px-4 py-1.5 rounded-full text-sm font-extrabold text-vibrantorange-500 shadow-lg transform group-hover:scale-105 transition-transform duration-300">
{item.price}
</div>
</div>
<div className="p-6 flex flex-col flex-1 relative bg-gradient-to-b from-white/50 to-white">
<h3 className="font-bold text-xl mb-3 text-deepblue-900 line-clamp-2 flex-1 group-hover:text-turquoise-500 transition-colors">{item.title}</h3>
<Link
href={`${basePath}/${item.slug}`}
className="mt-4 flex items-center justify-center gap-2 w-full py-3 bg-gradient-to-r from-turquoise-500 to-deepblue-900 hover:from-deepblue-900 hover:to-turquoise-500 text-white font-semibold rounded-2xl transition-all duration-500 shadow-md hover:shadow-xl transform hover:-translate-y-1"
>
<span>Hemen İncele</span>
<ArrowRight className="w-4 h-4 group-hover:translate-x-1 transition-transform" />
</Link>
</div>
</motion.div>
);
}
+58
View File
@@ -0,0 +1,58 @@
import { Button as ButtonPrimitive } from "@base-ui/react/button"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
const buttonVariants = cva(
"group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/80",
outline:
"border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
secondary:
"bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
ghost:
"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",
destructive:
"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default:
"h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
lg: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
icon: "size-8",
"icon-xs":
"size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
"icon-sm":
"size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg",
"icon-lg": "size-9",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
)
function Button({
className,
variant = "default",
size = "default",
...props
}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {
return (
<ButtonPrimitive
data-slot="button"
className={cn(buttonVariants({ variant, size, className }))}
{...props}
/>
)
}
export { Button, buttonVariants }
+103
View File
@@ -0,0 +1,103 @@
import * as React from "react"
import { cn } from "@/lib/utils"
function Card({
className,
size = "default",
...props
}: React.ComponentProps<"div"> & { size?: "default" | "sm" }) {
return (
<div
data-slot="card"
data-size={size}
className={cn(
"group/card flex flex-col gap-(--card-spacing) overflow-hidden rounded-xl bg-card py-(--card-spacing) text-sm text-card-foreground ring-1 ring-foreground/10 [--card-spacing:--spacing(4)] has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:[--card-spacing:--spacing(3)] data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl",
className
)}
{...props}
/>
)
}
function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-header"
className={cn(
"group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-(--card-spacing) has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-(--card-spacing)",
className
)}
{...props}
/>
)
}
function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-title"
className={cn(
"font-heading text-base leading-snug font-medium group-data-[size=sm]/card:text-sm",
className
)}
{...props}
/>
)
}
function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-description"
className={cn("text-sm text-muted-foreground", className)}
{...props}
/>
)
}
function CardAction({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-action"
className={cn(
"col-start-2 row-span-2 row-start-1 self-start justify-self-end",
className
)}
{...props}
/>
)
}
function CardContent({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-content"
className={cn("px-(--card-spacing)", className)}
{...props}
/>
)
}
function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="card-footer"
className={cn(
"flex items-center rounded-b-xl border-t bg-muted/50 p-(--card-spacing)",
className
)}
{...props}
/>
)
}
export {
Card,
CardHeader,
CardFooter,
CardTitle,
CardAction,
CardDescription,
CardContent,
}
+20
View File
@@ -0,0 +1,20 @@
import * as React from "react"
import { Input as InputPrimitive } from "@base-ui/react/input"
import { cn } from "@/lib/utils"
function Input({ className, type, ...props }: React.ComponentProps<"input">) {
return (
<InputPrimitive
type={type}
data-slot="input"
className={cn(
"h-8 w-full min-w-0 rounded-lg border border-input bg-transparent px-2.5 py-1 text-base transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40",
className
)}
{...props}
/>
)
}
export { Input }