first commit

This commit is contained in:
akash 2025-11-24 20:45:13 +05:30
commit 6d89e2702c
48 changed files with 8580 additions and 0 deletions

41
.gitignore vendored Normal file
View File

@ -0,0 +1,41 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# env files (can opt-in for committing if needed)
.env*
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts

36
README.md Normal file
View File

@ -0,0 +1,36 @@
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
## Getting Started
First, run the development server:
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.

18
eslint.config.mjs Normal file
View File

@ -0,0 +1,18 @@
import { defineConfig, globalIgnores } from "eslint/config";
import nextVitals from "eslint-config-next/core-web-vitals";
import nextTs from "eslint-config-next/typescript";
const eslintConfig = defineConfig([
...nextVitals,
...nextTs,
// Override default ignores of eslint-config-next.
globalIgnores([
// Default ignores of eslint-config-next:
".next/**",
"out/**",
"build/**",
"next-env.d.ts",
]),
]);
export default eslintConfig;

7
next.config.ts Normal file
View File

@ -0,0 +1,7 @@
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
/* config options here */
};
export default nextConfig;

5939
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

24
package.json Normal file
View File

@ -0,0 +1,24 @@
{
"name": "antalya-web",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "eslint"
},
"dependencies": {
"next": "16.0.3",
"react": "19.2.0",
"react-dom": "19.2.0"
},
"devDependencies": {
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"eslint": "^9",
"eslint-config-next": "16.0.3",
"typescript": "^5"
}
}

1
public/file.svg Normal file
View File

@ -0,0 +1 @@
<svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 13.5V5.41a1 1 0 0 0-.3-.7L9.8.29A1 1 0 0 0 9.08 0H1.5v13.5A2.5 2.5 0 0 0 4 16h8a2.5 2.5 0 0 0 2.5-2.5m-1.5 0v-7H8v-5H3v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1M9.5 5V2.12L12.38 5zM5.13 5h-.62v1.25h2.12V5zm-.62 3h7.12v1.25H4.5zm.62 3h-.62v1.25h7.12V11z" clip-rule="evenodd" fill="#666" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 391 B

1
public/globe.svg Normal file
View File

@ -0,0 +1 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M10.27 14.1a6.5 6.5 0 0 0 3.67-3.45q-1.24.21-2.7.34-.31 1.83-.97 3.1M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16m.48-1.52a7 7 0 0 1-.96 0H7.5a4 4 0 0 1-.84-1.32q-.38-.89-.63-2.08a40 40 0 0 0 3.92 0q-.25 1.2-.63 2.08a4 4 0 0 1-.84 1.31zm2.94-4.76q1.66-.15 2.95-.43a7 7 0 0 0 0-2.58q-1.3-.27-2.95-.43a18 18 0 0 1 0 3.44m-1.27-3.54a17 17 0 0 1 0 3.64 39 39 0 0 1-4.3 0 17 17 0 0 1 0-3.64 39 39 0 0 1 4.3 0m1.1-1.17q1.45.13 2.69.34a6.5 6.5 0 0 0-3.67-3.44q.65 1.26.98 3.1M8.48 1.5l.01.02q.41.37.84 1.31.38.89.63 2.08a40 40 0 0 0-3.92 0q.25-1.2.63-2.08a4 4 0 0 1 .85-1.32 7 7 0 0 1 .96 0m-2.75.4a6.5 6.5 0 0 0-3.67 3.44 29 29 0 0 1 2.7-.34q.31-1.83.97-3.1M4.58 6.28q-1.66.16-2.95.43a7 7 0 0 0 0 2.58q1.3.27 2.95.43a18 18 0 0 1 0-3.44m.17 4.71q-1.45-.12-2.69-.34a6.5 6.5 0 0 0 3.67 3.44q-.65-1.27-.98-3.1" fill="#666"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
public/images/dish-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

BIN
public/images/dish-2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

BIN
public/images/hero-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 991 KiB

BIN
public/images/hero-2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 944 KiB

BIN
public/images/hero-3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 836 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
public/images/marble-bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 729 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 765 KiB

1
public/next.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

1
public/vercel.svg Normal file
View File

@ -0,0 +1 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1155 1000"><path d="m577.3 0 577.4 1000H0z" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 128 B

1
public/window.svg Normal file
View File

@ -0,0 +1 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 2.5h13v10a1 1 0 0 1-1 1h-11a1 1 0 0 1-1-1zM0 1h16v11.5a2.5 2.5 0 0 1-2.5 2.5h-11A2.5 2.5 0 0 1 0 12.5zm3.75 4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5M7 4.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0m1.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5" fill="#666"/></svg>

After

Width:  |  Height:  |  Size: 385 B

18
src/app/actions.ts Normal file
View File

@ -0,0 +1,18 @@
'use server'
export async function submitReservation(formData: FormData) {
const rawFormData = {
name: formData.get('name'),
phone: formData.get('phone'),
date: formData.get('date'),
message: formData.get('message'),
}
// Simulate server-side processing
console.log('Reservation received:', rawFormData)
// In a real app, you would save to DB or send email here
await new Promise(resolve => setTimeout(resolve, 1000))
return { success: true, message: 'Reservation submitted successfully!' }
}

BIN
src/app/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

31
src/app/globals.css Normal file
View File

@ -0,0 +1,31 @@
:root {
--color-gold: #bf9b30;
--color-dark: #0a0a0a;
--color-input-bg: #e8e0d5;
--color-text-light: #f5f5f5;
--font-playfair: 'Playfair Display', serif;
--font-lato: 'Lato', sans-serif;
}
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
html,
body {
max-width: 100vw;
overflow-x: hidden;
background-color: var(--color-dark);
color: var(--color-text-light);
font-family: var(--font-lato);
/* Ensure default font is applied */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
a {
color: inherit;
text-decoration: none;
}

52
src/app/layout.tsx Normal file
View File

@ -0,0 +1,52 @@
import type { Metadata } from "next";
import { Playfair_Display, Lato, Cinzel, Inter } from "next/font/google";
import "./globals.css";
import ScrollToTop from "@/components/ScrollToTop/ScrollToTop";
const playfair = Playfair_Display({
subsets: ["latin"],
variable: "--font-playfair",
display: "swap",
});
const lato = Lato({
weight: ["300", "400", "700"],
subsets: ["latin"],
variable: "--font-lato",
display: "swap",
});
const cinzel = Cinzel({
subsets: ["latin"],
variable: "--font-cinzel",
display: "swap",
});
const inter = Inter({
subsets: ["latin"],
variable: "--font-inter",
display: "swap",
});
export const metadata: Metadata = {
title: "Antalya Restaurant - Book A Table",
description: "Experience luxury dining at Antalya Restaurant.",
};
import Navbar from '@/components/Navbar/Navbar'
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en" className={`${playfair.variable} ${lato.variable} ${cinzel.variable} ${inter.variable}`}>
<body className={lato.className}>
<Navbar />
{children}
<ScrollToTop />
</body>
</html>
)
}

141
src/app/page.module.css Normal file
View File

@ -0,0 +1,141 @@
.page {
--background: #fafafa;
--foreground: #fff;
--text-primary: #000;
--text-secondary: #666;
--button-primary-hover: #383838;
--button-secondary-hover: #f2f2f2;
--button-secondary-border: #ebebeb;
display: flex;
min-height: 100vh;
align-items: center;
justify-content: center;
font-family: var(--font-geist-sans);
background-color: var(--background);
}
.main {
display: flex;
min-height: 100vh;
width: 100%;
max-width: 800px;
flex-direction: column;
align-items: flex-start;
justify-content: space-between;
background-color: var(--foreground);
padding: 120px 60px;
}
.intro {
display: flex;
flex-direction: column;
align-items: flex-start;
text-align: left;
gap: 24px;
}
.intro h1 {
max-width: 320px;
font-size: 40px;
font-weight: 600;
line-height: 48px;
letter-spacing: -2.4px;
text-wrap: balance;
color: var(--text-primary);
}
.intro p {
max-width: 440px;
font-size: 18px;
line-height: 32px;
text-wrap: balance;
color: var(--text-secondary);
}
.intro a {
font-weight: 500;
color: var(--text-primary);
}
.ctas {
display: flex;
flex-direction: row;
width: 100%;
max-width: 440px;
gap: 16px;
font-size: 14px;
}
.ctas a {
display: flex;
justify-content: center;
align-items: center;
height: 40px;
padding: 0 16px;
border-radius: 128px;
border: 1px solid transparent;
transition: 0.2s;
cursor: pointer;
width: fit-content;
font-weight: 500;
}
a.primary {
background: var(--text-primary);
color: var(--background);
gap: 8px;
}
a.secondary {
border-color: var(--button-secondary-border);
}
/* Enable hover only on non-touch devices */
@media (hover: hover) and (pointer: fine) {
a.primary:hover {
background: var(--button-primary-hover);
border-color: transparent;
}
a.secondary:hover {
background: var(--button-secondary-hover);
border-color: transparent;
}
}
@media (max-width: 600px) {
.main {
padding: 48px 24px;
}
.intro {
gap: 16px;
}
.intro h1 {
font-size: 32px;
line-height: 40px;
letter-spacing: -1.92px;
}
}
@media (prefers-color-scheme: dark) {
.logo {
filter: invert();
}
.page {
--background: #000;
--foreground: #000;
--text-primary: #ededed;
--text-secondary: #999;
--button-primary-hover: #ccc;
--button-secondary-hover: #1a1a1a;
--button-secondary-border: #1a1a1a;
}
}

25
src/app/page.tsx Normal file
View File

@ -0,0 +1,25 @@
import Header from "@/components/Header/Header";
import Hero from "@/components/Hero/Hero";
import PopularDishes from "@/components/PopularDishes/PopularDishes";
import About from "@/components/About/About";
import Gallery from "@/components/Gallery/Gallery";
import Testimonials from "@/components/Testimonials/Testimonials";
import Blogs from "@/components/Blogs/Blogs";
import BookTable from "@/components/BookTable/BookTable";
import Footer from "@/components/Footer/Footer";
export default function Home() {
return (
<main>
<Header />
<Hero />
<PopularDishes />
<About />
<Gallery />
<Testimonials />
<Blogs />
<BookTable />
<Footer />
</main>
);
}

View File

@ -0,0 +1,134 @@
.section {
padding: 80px 20px;
background-color: #0a0a0a;
/* Dark background matching the theme */
display: flex;
justify-content: center;
align-items: center;
}
.container {
max-width: 1400px;
width: 100%;
display: flex;
border: 4px solid #C5A059;
/* Main Gold Border */
position: relative;
background-color: #111;
/* Inner border effect handled by padding + background or pseudo-element if needed,
but image shows a solid border containing both image and text */
}
/* Inner decorative border offset */
.container::after {
content: '';
position: absolute;
top: 10px;
left: 10px;
right: 10px;
bottom: 10px;
border: 1px solid rgba(197, 160, 89, 0.3);
pointer-events: none;
z-index: 10;
}
.imageWrapper {
flex: 1;
position: relative;
min-height: 600px;
/* Ensure substantial height */
}
.image {
object-fit: cover;
width: 100%;
height: 100%;
}
.content {
flex: 1;
padding: 80px 60px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
background-image: url('/images/pattern-overlay.png');
/* Optional pattern overlay if available, else dark bg */
background-color: #151515;
position: relative;
}
.icon {
width: 60px;
height: auto;
margin-bottom: 30px;
color: #C5A059;
}
.title {
font-family: var(--font-cinzel), serif;
font-size: 3.5rem;
color: #C5A059;
margin-bottom: 10px;
text-transform: uppercase;
letter-spacing: 2px;
line-height: 1.2;
}
.subtitle {
font-family: var(--font-cinzel), serif;
font-size: 1.4rem;
color: #e0e0e0;
margin-bottom: 40px;
font-weight: 400;
}
.text {
font-family: var(--font-inter), sans-serif;
/* Or specific font from image */
color: #C5A059;
/* Goldish text color as seen in image */
line-height: 1.8;
margin-bottom: 50px;
max-width: 80%;
font-size: 1rem;
opacity: 0.8;
}
.button {
display: inline-block;
padding: 15px 40px;
border: 2px solid #C5A059;
color: #C5A059;
font-family: var(--font-cinzel), serif;
font-size: 1.1rem;
text-transform: uppercase;
text-decoration: none;
transition: all 0.3s ease;
background: transparent;
cursor: pointer;
}
.button:hover {
background-color: #C5A059;
color: #000;
}
@media (max-width: 1024px) {
.container {
flex-direction: column;
}
.imageWrapper {
min-height: 400px;
}
.content {
padding: 60px 30px;
}
.title {
font-size: 2.5rem;
}
}

View File

@ -0,0 +1,38 @@
import Image from 'next/image'
import Link from 'next/link'
import styles from './About.module.css'
export default function About() {
return (
<section className={styles.section} id="about">
<div className={styles.container}>
<div className={styles.imageWrapper}>
<Image
src="/images/restaurant-interior.png"
alt="About Antalya Interior"
fill
className={styles.image}
/>
</div>
<div className={styles.content}>
{/* Decorative Icon SVG */}
<svg className={styles.icon} viewBox="0 0 100 100" fill="currentColor">
<path d="M50 0 C60 20 80 40 100 50 C80 60 60 80 50 100 C40 80 20 60 0 50 C20 40 40 20 50 0 Z" />
<circle cx="50" cy="50" r="10" />
</svg>
<h2 className={styles.title}>ABOUT ANTALYA</h2>
<h3 className={styles.subtitle}>Experience Unforgettable Turkish Fusion</h3>
<p className={styles.text}>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</p>
<Link href="#about-more" className={styles.button}>
Learn More
</Link>
</div>
</div>
</section>
)
}

View File

@ -0,0 +1,155 @@
.section {
padding: 80px 20px;
background-color: #2a0a0a;
/* Dark red/brown background */
background-image: url('/images/pattern-overlay.png');
/* Optional pattern */
text-align: center;
position: relative;
overflow: hidden;
}
.title {
font-family: var(--font-cinzel), serif;
font-size: 3.5rem;
color: #C5A059;
margin-bottom: 60px;
text-transform: uppercase;
letter-spacing: 2px;
}
.sliderContainer {
display: flex;
justify-content: center;
align-items: center;
gap: 20px;
max-width: 1400px;
margin: 0 auto;
position: relative;
padding: 0 40px;
}
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 30px;
width: 100%;
}
.card {
background-color: #F5E6D3;
/* Cream background */
padding: 20px;
border: 4px solid #C5A059;
/* Gold border */
display: flex;
flex-direction: column;
align-items: center;
transition: transform 0.3s ease;
height: 100%;
}
.card:hover {
transform: translateY(-10px);
}
.imageContainer {
position: relative;
width: 100%;
height: 250px;
margin-bottom: 25px;
border: 1px solid #C5A059;
/* Inner border for image */
}
.blogTitle {
font-family: var(--font-cinzel), serif;
font-size: 1.5rem;
color: #3e2723;
/* Dark brown text */
margin-bottom: 15px;
font-weight: 600;
line-height: 1.3;
}
.excerpt {
font-family: var(--font-cinzel), serif;
font-size: 0.95rem;
color: #5d4037;
margin-bottom: 25px;
line-height: 1.6;
max-width: 90%;
opacity: 0.8;
}
.button {
display: inline-block;
padding: 10px 25px;
border: 2px solid #C5A059;
color: #5d4037;
font-family: var(--font-inter), sans-serif;
text-transform: uppercase;
font-size: 0.85rem;
text-decoration: none;
transition: all 0.3s ease;
background: transparent;
font-weight: 600;
margin-top: auto;
}
.button:hover {
background-color: #C5A059;
color: #fff;
}
.arrow {
background: none;
border: none;
color: #C5A059;
font-size: 3rem;
cursor: pointer;
transition: transform 0.2s;
padding: 0 10px;
display: flex;
align-items: center;
justify-content: center;
}
.arrow:hover {
transform: scale(1.1);
}
.viewMoreContainer {
margin-top: 60px;
}
.viewMoreButton {
display: inline-block;
padding: 15px 40px;
border: 1px solid #C5A059;
color: #C5A059;
font-family: var(--font-inter), sans-serif;
text-transform: uppercase;
font-size: 1rem;
text-decoration: none;
transition: all 0.3s ease;
background: transparent;
border-radius: 5px;
/* Slight radius as per some designs, or keep square */
border-radius: 8px;
}
.viewMoreButton:hover {
background-color: #C5A059;
color: #000;
}
@media (max-width: 1024px) {
.grid {
grid-template-columns: 1fr;
}
.arrow {
display: none;
}
}

View File

@ -0,0 +1,64 @@
import Image from 'next/image'
import Link from 'next/link'
import styles from './Blogs.module.css'
const blogs = [
{
id: 1,
title: 'The Art of Turkish Tea',
image: '/images/dish-1.png', // Placeholder
excerpt: 'Lorem ipsum dolor sit amet, tuem cergat imlpecion diirm, iadioc-ticid est nt eedrama inapat.'
},
{
id: 2,
title: 'Secrets of Charcoal Grilling',
image: '/images/hero-3.png', // Placeholder
excerpt: 'Lorem ipsum dolor sit amet, tuem cergat imlpecion diirm, iadioc-ticid est nt eedrama inapat.'
},
{
id: 3,
title: 'A Taste of Sweet Legacy',
image: '/images/dish-2.png', // Placeholder
excerpt: 'Lorem ipsum dolor sit amet, tuem cergat imlpecion diirm, iadioc-ticid est nt eedrama inapat.'
}
]
export default function Blogs() {
return (
<section className={styles.section} id="blog">
<h2 className={styles.title}>OUR BLOGS</h2>
<div className={styles.sliderContainer}>
<button className={styles.arrow}></button>
<div className={styles.grid}>
{blogs.map((blog) => (
<div key={blog.id} className={styles.card}>
<div className={styles.imageContainer}>
<Image
src={blog.image}
alt={blog.title}
fill
style={{ objectFit: 'cover' }}
/>
</div>
<h3 className={styles.blogTitle}>{blog.title}</h3>
<p className={styles.excerpt}>{blog.excerpt}</p>
<Link href="#" className={styles.button}>
View More
</Link>
</div>
))}
</div>
<button className={styles.arrow}></button>
</div>
<div className={styles.viewMoreContainer}>
<Link href="#" className={styles.viewMoreButton}>
Read More Blogs
</Link>
</div>
</section>
)
}

View File

@ -0,0 +1,131 @@
.section {
display: flex;
min-height: 50vh;
width: 100%;
background-color: var(--color-dark);
}
.imageContainer {
flex: 1;
position: relative;
display: none;
}
.formContainer {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 4rem 2rem;
background-image: url('/images/marble-bg.png');
background-size: cover;
background-position: center;
position: relative;
}
/* Overlay to darken the marble background slightly if needed */
.formContainer::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.4);
z-index: 1;
}
.content {
position: relative;
z-index: 2;
width: 100%;
max-width: 500px;
}
.title {
font-family: var(--font-playfair);
color: var(--color-gold);
font-size: 3rem;
text-align: center;
margin-bottom: 3rem;
font-weight: 400;
letter-spacing: 2px;
text-transform: uppercase;
}
.form {
display: flex;
flex-direction: column;
gap: 1.5rem;
}
.inputGroup {
display: flex;
align-items: center;
gap: 1rem;
}
.label {
font-family: var(--font-playfair);
color: var(--color-gold);
width: 80px;
font-size: 1.1rem;
text-align: right;
}
.input,
.textarea {
flex: 1;
background-color: var(--color-input-bg);
border: none;
border-radius: 4px;
padding: 0.8rem 1rem;
font-family: var(--font-lato);
font-size: 1rem;
color: #333;
outline: none;
transition: box-shadow 0.3s ease;
}
.input:focus,
.textarea:focus {
box-shadow: 0 0 0 2px var(--color-gold);
}
.textarea {
resize: vertical;
min-height: 100px;
}
.submitButton {
background: transparent;
border: 1px solid var(--color-gold);
color: var(--color-text-light);
padding: 0.8rem 2rem;
font-family: var(--font-lato);
font-size: 1rem;
cursor: pointer;
transition: all 0.3s ease;
align-self: flex-end;
margin-top: 1rem;
border-radius: 4px;
}
.submitButton:hover {
background-color: var(--color-gold);
color: var(--color-dark);
}
.successMessage {
color: var(--color-gold);
text-align: center;
margin-top: 1rem;
font-family: var(--font-lato);
}
@media (min-width: 768px) {
.imageContainer {
display: block;
}
}

View File

@ -0,0 +1,108 @@
'use client'
import { useState } from 'react'
import Image from 'next/image'
import styles from './BookTable.module.css'
import { submitReservation } from '@/app/actions'
export default function BookTable() {
const [isSubmitting, setIsSubmitting] = useState(false)
const [message, setMessage] = useState('')
async function handleSubmit(formData: FormData) {
setIsSubmitting(true)
setMessage('')
try {
const result = await submitReservation(formData)
if (result.success) {
setMessage(result.message)
const form = document.getElementById('reservation-form') as HTMLFormElement
form?.reset()
}
} catch (error) {
console.error('Error submitting form:', error)
setMessage('Something went wrong. Please try again.')
} finally {
setIsSubmitting(false)
}
}
return (
<section className={styles.section} id="book">
<div className={styles.imageContainer}>
<Image
src="/images/restaurant-interior.png"
alt="Luxury Restaurant Interior"
fill
style={{ objectFit: 'cover' }}
priority
/>
</div>
<div className={styles.formContainer}>
<div className={styles.content}>
<h2 className={styles.title}>Book A Table</h2>
<form
id="reservation-form"
action={handleSubmit}
className={styles.form}
>
<div className={styles.inputGroup}>
<label htmlFor="name" className={styles.label}>Name</label>
<input
type="text"
id="name"
name="name"
required
className={styles.input}
/>
</div>
<div className={styles.inputGroup}>
<label htmlFor="phone" className={styles.label}>Phone</label>
<input
type="tel"
id="phone"
name="phone"
required
className={styles.input}
/>
</div>
<div className={styles.inputGroup}>
<label htmlFor="date" className={styles.label}>Date</label>
<input
type="date"
id="date"
name="date"
required
className={styles.input}
/>
</div>
<div className={styles.inputGroup}>
<label htmlFor="message" className={styles.label}>Message</label>
<textarea
id="message"
name="message"
className={styles.textarea}
/>
</div>
<button
type="submit"
disabled={isSubmitting}
className={styles.submitButton}
>
{isSubmitting ? 'Submitting...' : 'Submit Reservation'}
</button>
{message && <p className={styles.successMessage}>{message}</p>}
</form>
</div>
</div>
</section>
)
}

View File

@ -0,0 +1,111 @@
.footer {
background-color: #2a0a0a;
/* Deep red/brown */
color: #d4b060;
/* Gold-ish text */
padding: 4rem 2rem 1rem;
border-top: 1px solid var(--color-gold);
}
.container {
max-width: 1200px;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
gap: 3rem;
}
.column {
flex: 1;
min-width: 250px;
}
.brandColumn {
display: flex;
flex-direction: column;
align-items: flex-start;
}
.logo {
font-family: var(--font-playfair);
font-size: 2rem;
color: var(--color-gold);
margin-bottom: 1rem;
text-transform: uppercase;
letter-spacing: 2px;
}
.description {
font-family: var(--font-lato);
font-size: 0.9rem;
line-height: 1.6;
margin-bottom: 1.5rem;
color: #ccb;
}
.socialIcons {
display: flex;
gap: 1rem;
}
.icon {
width: 30px;
height: 30px;
border-radius: 50%;
background-color: var(--color-gold);
display: flex;
align-items: center;
justify-content: center;
color: #2a0a0a;
font-weight: bold;
}
.heading {
font-family: var(--font-playfair);
font-size: 1.2rem;
margin-bottom: 1.5rem;
color: var(--color-gold);
}
.linkList {
list-style: none;
padding: 0;
}
.linkItem {
margin-bottom: 0.8rem;
}
.link {
font-family: var(--font-lato);
color: #ccb;
transition: color 0.3s ease;
}
.link:hover {
color: var(--color-gold);
}
.contactInfo {
font-family: var(--font-lato);
color: #ccb;
font-size: 0.9rem;
line-height: 1.8;
}
.contactRow {
display: flex;
gap: 0.5rem;
margin-bottom: 0.5rem;
}
.copyright {
text-align: center;
margin-top: 4rem;
padding-top: 1rem;
border-top: 1px solid rgba(191, 155, 48, 0.3);
font-family: var(--font-lato);
font-size: 0.8rem;
color: #887;
}

View File

@ -0,0 +1,69 @@
import styles from './Footer.module.css'
export default function Footer() {
return (
<footer className={styles.footer} id="contact">
<div className={styles.container}>
{/* Brand Column */}
<div className={`${styles.column} ${styles.brandColumn}`}>
<div className={styles.logo}>
ANTALYA<br />
<span style={{ fontSize: '1rem', letterSpacing: '4px' }}>RESTAURANT</span>
</div>
<p className={styles.description}>
Discover the essence of fusion cuisine in the heart of Ontario at Antalya Restaurant.
Our carefully curated menu offers a delicious selection from sizzling kebabs and succulent doners to authentic pides, sandwiches, and wraps.
</p>
<div className={styles.socialIcons}>
<div className={styles.icon}>f</div>
<div className={styles.icon}>t</div>
<div className={styles.icon}>in</div>
</div>
</div>
{/* Quick Links Column */}
<div className={styles.column}>
<h3 className={styles.heading}>Quick Links</h3>
<ul className={styles.linkList}>
<li className={styles.linkItem}><a href="#" className={styles.link}>Home</a></li>
<li className={styles.linkItem}><a href="#menu" className={styles.link}>Menu</a></li>
<li className={styles.linkItem}><a href="#gallery" className={styles.link}>Gallery</a></li>
<li className={styles.linkItem}><a href="#about" className={styles.link}>About</a></li>
<li className={styles.linkItem}><a href="#blog" className={styles.link}>Blog</a></li>
<li className={styles.linkItem}><a href="#contact" className={styles.link}>Contact</a></li>
</ul>
</div>
{/* Location Column */}
<div className={styles.column}>
<h3 className={styles.heading}>Location</h3>
<div className={styles.contactInfo}>
<p style={{ marginBottom: '1rem' }}>
1187 Fischer-Hallman Rd #435, Kitchener, ON N2E 4H9<br />
1860 Appleby Line, Burlington, ON L7L 7H7
</p>
<div className={styles.contactRow}>
<span>📞</span> <span>Kitchener: 519-581-6363</span>
</div>
<div className={styles.contactRow}>
<span>📞</span> <span>Burlington: 289-313-9838</span>
</div>
<div className={styles.contactRow}>
<span></span> <span>hello@antalyarestaurant.ca</span>
</div>
<h3 className={styles.heading} style={{ marginTop: '1.5rem' }}>Opening Hours</h3>
<p>
Sunday-Thursday 11am-10pm<br />
Friday-Saturday 11am-11pm
</p>
</div>
</div>
</div>
<div className={styles.copyright}>
© Copyright 2025 Antalya Restaurant | Powered by MetatronCube All Rights Reserved
</div>
</footer>
)
}

View File

@ -0,0 +1,144 @@
.section {
padding: 6rem 2rem;
background-color: #150505;
/* Very dark red/brown */
text-align: center;
}
.title {
font-family: var(--font-playfair);
font-size: 2.5rem;
color: var(--color-gold);
margin-bottom: 4rem;
text-transform: uppercase;
letter-spacing: 2px;
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 1.5rem;
max-width: 1200px;
margin: 0 auto;
}
.imageWrapper {
position: relative;
height: 300px;
cursor: pointer;
overflow: hidden;
border: 1px solid var(--color-gold);
transition: transform 0.3s ease;
}
.imageWrapper:hover {
transform: scale(1.02);
}
.imageWrapper:hover::after {
content: 'View';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0, 0, 0, 0.7);
color: var(--color-gold);
padding: 0.5rem 1.5rem;
border: 1px solid var(--color-gold);
font-family: var(--font-lato);
text-transform: uppercase;
pointer-events: none;
}
.button {
display: inline-block;
margin-top: 3rem;
padding: 0.8rem 2rem;
border: 1px solid var(--color-gold);
color: var(--color-gold);
font-family: var(--font-lato);
text-transform: uppercase;
text-decoration: none;
transition: all 0.3s ease;
background: transparent;
cursor: pointer;
}
.button:hover {
background-color: var(--color-gold);
color: #000;
}
/* Lightbox */
.lightbox {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.95);
z-index: 2000;
display: flex;
justify-content: center;
align-items: center;
}
.lightboxContent {
position: relative;
width: 90%;
max-width: 1000px;
height: 80vh;
}
.closeBtn {
position: absolute;
top: -40px;
right: 0;
background: none;
border: none;
color: #fff;
font-size: 2rem;
cursor: pointer;
}
.navBtn {
position: absolute;
top: 50%;
transform: translateY(-50%);
background: rgba(0, 0, 0, 0.5);
border: 1px solid var(--color-gold);
color: var(--color-gold);
width: 50px;
height: 50px;
border-radius: 50%;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.5rem;
transition: all 0.3s ease;
z-index: 10;
}
.navBtn:hover {
background: var(--color-gold);
color: #000;
}
.prevBtn {
left: -70px;
}
.nextBtn {
right: -70px;
}
@media (max-width: 768px) {
.prevBtn {
left: 10px;
}
.nextBtn {
right: 10px;
}
}

View File

@ -0,0 +1,77 @@
'use client'
import { useState } from 'react'
import Image from 'next/image'
import styles from './Gallery.module.css'
const images = [
'/images/dish-1.png',
'/images/dish-2.png',
'/images/hero-1.png',
'/images/hero-2.png',
'/images/hero-3.png',
'/images/restaurant-interior.png'
]
export default function Gallery() {
const [lightboxOpen, setLightboxOpen] = useState(false)
const [currentIndex, setCurrentIndex] = useState(0)
const openLightbox = (index: number) => {
setCurrentIndex(index)
setLightboxOpen(true)
}
const closeLightbox = () => {
setLightboxOpen(false)
}
const nextImage = (e: React.MouseEvent) => {
e.stopPropagation()
setCurrentIndex((prev) => (prev + 1) % images.length)
}
const prevImage = (e: React.MouseEvent) => {
e.stopPropagation()
setCurrentIndex((prev) => (prev - 1 + images.length) % images.length)
}
return (
<section className={styles.section} id="gallery">
<h2 className={styles.title}>Gallery</h2>
<div className={styles.grid}>
{images.map((src, index) => (
<div
key={index}
className={styles.imageWrapper}
onClick={() => openLightbox(index)}
>
<Image
src={src}
alt={`Gallery image ${index + 1}`}
fill
style={{ objectFit: 'cover' }}
/>
</div>
))}
</div>
<button className={styles.button}>View More</button>
{lightboxOpen && (
<div className={styles.lightbox} onClick={closeLightbox}>
<div className={styles.lightboxContent} onClick={(e) => e.stopPropagation()}>
<button className={styles.closeBtn} onClick={closeLightbox}>×</button>
<button className={`${styles.navBtn} ${styles.prevBtn}`} onClick={prevImage}></button>
<Image
src={images[currentIndex]}
alt="Gallery Preview"
fill
style={{ objectFit: 'contain' }}
/>
<button className={`${styles.navBtn} ${styles.nextBtn}`} onClick={nextImage}></button>
</div>
</div>
)}
</section>
)
}

View File

@ -0,0 +1,80 @@
.header {
position: fixed;
top: 0;
left: 0;
width: 100%;
z-index: 1000;
background-color: rgba(10, 10, 10, 0.95);
border-bottom: 1px solid rgba(191, 155, 48, 0.3);
padding: 1rem 0;
transition: all 0.3s ease;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 2rem;
display: flex;
justify-content: space-between;
align-items: center;
}
.logo {
display: flex;
align-items: center;
gap: 0.5rem;
text-decoration: none;
}
.logoText {
font-family: var(--font-playfair);
font-size: 1.5rem;
color: #fff;
letter-spacing: 1px;
}
.logoText span {
color: var(--color-gold);
}
.nav {
display: none;
}
.navList {
display: flex;
gap: 2rem;
list-style: none;
}
.navLink {
font-family: var(--font-lato);
color: var(--color-text-light);
font-size: 0.9rem;
text-transform: uppercase;
letter-spacing: 1px;
transition: color 0.3s ease;
}
.navLink:hover {
color: var(--color-gold);
}
.mobileMenuBtn {
display: block;
background: none;
border: none;
color: var(--color-gold);
font-size: 1.5rem;
cursor: pointer;
}
@media (min-width: 768px) {
.nav {
display: block;
}
.mobileMenuBtn {
display: none;
}
}

View File

@ -0,0 +1,30 @@
import Link from 'next/link'
import styles from './Header.module.css'
export default function Header() {
return (
<header className={styles.header}>
<div className={styles.container}>
<Link href="/" className={styles.logo}>
{/* Placeholder for logo icon if needed */}
<div className={styles.logoText}>
ANTALYA <span>RESTAURANT</span>
</div>
</Link>
<nav className={styles.nav}>
<ul className={styles.navList}>
<li><Link href="/" className={styles.navLink}>Home</Link></li>
<li><Link href="#about" className={styles.navLink}>About</Link></li>
<li><Link href="#gallery" className={styles.navLink}>Gallery</Link></li>
<li><Link href="#menu" className={styles.navLink}>Menu</Link></li>
<li><Link href="#blog" className={styles.navLink}>Blog</Link></li>
<li><Link href="#contact" className={styles.navLink}>Contact</Link></li>
</ul>
</nav>
<button className={styles.mobileMenuBtn}></button>
</div>
</header>
)
}

View File

@ -0,0 +1,141 @@
.hero {
position: relative;
height: 70vh;
width: 100%;
overflow: hidden;
margin-top: 0;
/* Header is fixed overlay */
}
.slide {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
transition: opacity 1s ease-in-out;
}
.slide.active {
opacity: 1;
z-index: 1;
}
.overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
z-index: 2;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
padding: 0 2rem;
}
.content {
max-width: 800px;
animation: fadeInUp 1s ease-out 0.5s forwards;
opacity: 0;
transform: translateY(20px);
}
@keyframes fadeInUp {
to {
opacity: 1;
transform: translateY(0);
}
}
.title {
font-family: var(--font-playfair);
font-size: 3.5rem;
color: #fff;
margin-bottom: 1rem;
line-height: 1.2;
}
.subtitle {
font-family: var(--font-playfair);
font-size: 1.5rem;
color: var(--color-gold);
margin-bottom: 2rem;
font-style: italic;
}
.buttons {
display: flex;
gap: 1.5rem;
justify-content: center;
}
.btn {
padding: 1rem 2rem;
font-family: var(--font-lato);
font-size: 1rem;
text-transform: uppercase;
letter-spacing: 1px;
cursor: pointer;
transition: all 0.3s ease;
text-decoration: none;
}
.btnPrimary {
background-color: var(--color-gold);
color: #000;
border: 1px solid var(--color-gold);
}
.btnPrimary:hover {
background-color: transparent;
color: var(--color-gold);
}
.btnSecondary {
background-color: transparent;
color: #fff;
border: 1px solid #fff;
}
.btnSecondary:hover {
background-color: #fff;
color: #000;
}
.dots {
position: absolute;
bottom: 2rem;
left: 50%;
transform: translateX(-50%);
z-index: 3;
display: flex;
gap: 1rem;
}
.dot {
width: 12px;
height: 12px;
border-radius: 50%;
background-color: rgba(255, 255, 255, 0.5);
cursor: pointer;
transition: background-color 0.3s ease;
}
.dot.active {
background-color: var(--color-gold);
}
@media (max-width: 768px) {
.title {
font-size: 2.5rem;
}
.subtitle {
font-size: 1.2rem;
}
}

View File

@ -0,0 +1,81 @@
'use client'
import { useState, useEffect } from 'react'
import Image from 'next/image'
import Link from 'next/link'
import styles from './Hero.module.css'
const slides = [
{
id: 1,
image: '/images/hero-1.png',
title: 'Experience Turkish Fusion at Antalya',
subtitle: 'An authentic obsession. kebabs, grill & more.'
},
{
id: 2,
image: '/images/hero-2.png',
title: 'Luxury Dining Atmosphere',
subtitle: 'Where tradition meets elegance.'
},
{
id: 3,
image: '/images/hero-3.png',
title: 'Masterfully Crafted Flavors',
subtitle: 'Taste the essence of Anatolia.'
}
]
export default function Hero() {
const [currentSlide, setCurrentSlide] = useState(0)
useEffect(() => {
const interval = setInterval(() => {
setCurrentSlide((prev) => (prev + 1) % slides.length)
}, 5000)
return () => clearInterval(interval)
}, [])
return (
<section className={styles.hero}>
{slides.map((slide, index) => (
<div
key={slide.id}
className={`${styles.slide} ${index === currentSlide ? styles.active : ''}`}
>
<Image
src={slide.image}
alt={slide.title}
fill
style={{ objectFit: 'cover' }}
priority={index === 0}
/>
<div className={styles.overlay}>
<div className={styles.content}>
<h1 className={styles.title}>{slide.title}</h1>
<p className={styles.subtitle}>{slide.subtitle}</p>
<div className={styles.buttons}>
<Link href="#menu" className={`${styles.btn} ${styles.btnPrimary}`}>
View Menu
</Link>
<Link href="#book" className={`${styles.btn} ${styles.btnSecondary}`}>
Book A Table
</Link>
</div>
</div>
</div>
</div>
))}
<div className={styles.dots}>
{slides.map((_, index) => (
<div
key={index}
className={`${styles.dot} ${index === currentSlide ? styles.active : ''}`}
onClick={() => setCurrentSlide(index)}
/>
))}
</div>
</section>
)
}

View File

@ -0,0 +1,154 @@
.navbar {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 80px;
background-color: #0a0a0a;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 40px;
z-index: 1000;
transition: all 0.3s ease;
}
.navbarScrolled {
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.8);
background-color: rgba(10, 10, 10, 0.95);
backdrop-filter: blur(10px);
}
.logoContainer {
display: flex;
align-items: center;
height: 100%;
z-index: 1002;
}
.logoImage {
height: 60px;
width: auto;
object-fit: contain;
}
.desktopMenu {
display: flex;
gap: 30px;
}
.navLink {
color: #fff;
text-decoration: none;
font-size: 0.95rem;
font-weight: 500;
text-transform: uppercase;
transition: all 0.3s ease;
position: relative;
}
.navLink:hover {
color: #C5A059;
}
.navLink::after {
content: '';
position: absolute;
bottom: -4px;
left: 0;
width: 0;
height: 2px;
background-color: #C5A059;
transition: width 0.3s;
}
.navLink:hover::after {
width: 100%;
}
/* Hamburger */
.hamburger {
display: none;
background: none;
border: none;
cursor: pointer;
flex-direction: column;
gap: 6px;
z-index: 1003;
padding: 10px;
}
.bar {
width: 30px;
height: 3px;
background-color: #C5A059;
transition: all 0.3s ease;
}
/* Hamburger to X animation */
.hamburgerOpen .bar:nth-child(1) {
transform: translateY(9px) rotate(45deg);
}
.hamburgerOpen .bar:nth-child(2) {
opacity: 0;
}
.hamburgerOpen .bar:nth-child(3) {
transform: translateY(-9px) rotate(-45deg);
}
/* Mobile Menu */
.mobileMenuOverlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
background-color: #0a0a0a;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 28px;
transform: translateY(-100%);
transition: all 0.45s ease;
z-index: 1001;
padding-top: 80px;
}
.mobileMenuOpen {
transform: translateY(0);
}
.mobileNavLink {
color: #fff;
font-size: 1.8rem;
text-decoration: none;
text-transform: uppercase;
opacity: 0;
transform: translateY(-20px);
transition: opacity 0.4s ease, transform 0.4s ease;
}
/* Animate when menu open */
.mobileMenuOpen .mobileNavLink {
opacity: 1;
transform: translateY(0);
}
.mobileNavLink:hover {
color: #C5A059;
}
@media (max-width: 1024px) {
.desktopMenu {
display: none;
}
.hamburger {
display: flex;
}
.navbar {
padding: 0 20px;
}
}

View File

@ -0,0 +1,130 @@
'use client'
import { useState, useEffect, useRef } from 'react'
import Image from 'next/image'
import Link from 'next/link'
import styles from './Navbar.module.css'
const navLinks = [
{ name: 'Home', href: '/' },
{ name: 'About', href: '#about' },
{ name: 'Services', href: '#services' },
{ name: 'Menu', href: '#menu' },
{ name: 'Gallery', href: '#gallery' },
{ name: 'Contact', href: '#contact' },
]
export default function Navbar() {
const [isOpen, setIsOpen] = useState(false)
const [scrolled, setScrolled] = useState(false)
const menuRef = useRef<HTMLDivElement>(null)
const hamburgerRef = useRef<HTMLButtonElement>(null)
const toggleMenu = () => {
setIsOpen(!isOpen)
}
const closeMenu = () => {
setIsOpen(false)
}
// Handle scroll for shadow effect
useEffect(() => {
const handleScroll = () => {
if (window.scrollY > 50) {
setScrolled(true)
} else {
setScrolled(false)
}
}
window.addEventListener('scroll', handleScroll)
return () => {
window.removeEventListener('scroll', handleScroll)
}
}, [])
// Close menu when clicking outside
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (
isOpen &&
menuRef.current &&
!menuRef.current.contains(event.target as Node) &&
hamburgerRef.current &&
!hamburgerRef.current.contains(event.target as Node)
) {
closeMenu()
}
}
document.addEventListener('mousedown', handleClickOutside)
return () => {
document.removeEventListener('mousedown', handleClickOutside)
}
}, [isOpen])
// Prevent scrolling when mobile menu is open
useEffect(() => {
if (isOpen) {
document.body.style.overflow = 'hidden'
} else {
document.body.style.overflow = 'unset'
}
}, [isOpen])
return (
<nav className={`${styles.navbar} ${scrolled ? styles.navbarScrolled : ''}`}>
<div className={styles.logoContainer}>
<Link href="/" onClick={closeMenu}>
<Image
src="/images/logo-header.png"
alt="Antalya Restaurant"
width={200}
height={60}
className={styles.logoImage}
priority
/>
</Link>
</div>
{/* Desktop Menu */}
<div className={styles.desktopMenu}>
{navLinks.map((link) => (
<Link key={link.name} href={link.href} className={styles.navLink}>
{link.name}
</Link>
))}
</div>
{/* Hamburger Button */}
<button
ref={hamburgerRef}
className={`${styles.hamburger} ${isOpen ? styles.hamburgerOpen : ''}`}
onClick={toggleMenu}
aria-label="Toggle menu"
>
<span className={styles.bar}></span>
<span className={styles.bar}></span>
<span className={styles.bar}></span>
</button>
{/* Mobile Menu Overlay */}
<div
ref={menuRef}
className={`${styles.mobileMenuOverlay} ${isOpen ? styles.mobileMenuOpen : ''}`}
>
{navLinks.map((link) => (
<Link
key={link.name}
href={link.href}
className={styles.mobileNavLink}
onClick={closeMenu}
>
{link.name}
</Link>
))}
</div>
</nav>
)
}

View File

@ -0,0 +1,123 @@
.section {
padding: 80px 20px;
background-color: #2a0a0a;
/* Dark red/brown background */
background-image: url('/images/pattern-overlay.png');
/* Optional pattern */
text-align: center;
position: relative;
}
.title {
font-family: var(--font-cinzel), serif;
font-size: 3.5rem;
color: #C5A059;
margin-bottom: 60px;
text-transform: uppercase;
letter-spacing: 2px;
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
gap: 40px;
max-width: 1400px;
margin: 0 auto;
padding: 0 20px;
}
.card {
background-color: #F5E6D3;
/* Cream background */
padding: 20px;
border: 4px solid #C5A059;
/* Gold border */
display: flex;
flex-direction: column;
align-items: center;
transition: transform 0.3s ease;
}
.card:hover {
transform: translateY(-10px);
}
.imageContainer {
position: relative;
width: 100%;
height: 300px;
margin-bottom: 25px;
border: 1px solid #C5A059;
/* Inner border for image */
}
.dishName {
font-family: var(--font-cinzel), serif;
font-size: 1.8rem;
color: #3e2723;
/* Dark brown text */
margin-bottom: 15px;
font-weight: 600;
}
.description {
font-family: var(--font-cinzel), serif;
/* Using serif as per image look */
font-size: 1rem;
color: #5d4037;
margin-bottom: 30px;
line-height: 1.6;
max-width: 90%;
opacity: 0.8;
}
.button {
display: inline-block;
padding: 12px 30px;
border: 2px solid #C5A059;
color: #5d4037;
font-family: var(--font-inter), sans-serif;
text-transform: uppercase;
font-size: 0.9rem;
text-decoration: none;
transition: all 0.3s ease;
background: transparent;
font-weight: 600;
}
.button:hover {
background-color: #C5A059;
color: #fff;
}
.viewMoreContainer {
margin-top: 60px;
}
.viewMoreButton {
display: inline-block;
padding: 15px 40px;
border: 1px solid #C5A059;
color: #C5A059;
font-family: var(--font-inter), sans-serif;
text-transform: uppercase;
font-size: 1rem;
text-decoration: none;
transition: all 0.3s ease;
background: transparent;
}
.viewMoreButton:hover {
background-color: #C5A059;
color: #000;
}
@media (max-width: 768px) {
.grid {
grid-template-columns: 1fr;
}
.title {
font-size: 2.5rem;
}
}

View File

@ -0,0 +1,57 @@
import Image from 'next/image'
import Link from 'next/link'
import styles from './PopularDishes.module.css'
const dishes = [
{
id: 1,
name: 'Adana Kebab',
image: '/images/dish-1.png',
description: 'Lorem ipsum dolor sit amet, tuem cergat imlpecion diirm, iadioc-ticid est nt eedrama inapat.'
},
{
id: 2,
name: 'Mixed Grill',
image: '/images/dish-2.png',
description: 'Lorem ipsum dolor sit amet, tuem cergat imlpecion diirm, iadioc-ticid est nt eedrama inapat.'
},
{
id: 3,
name: 'Baklava',
// Reusing dish-1 as placeholder since generation limit reached
image: '/images/dish-1.png',
description: 'Lorem ipsum dolor sit amet, tuem cergat imlpecion diirm, iadioc-ticid est nt eedrama inapat.'
}
]
export default function PopularDishes() {
return (
<section className={styles.section} id="menu">
<h2 className={styles.title}>POPULAR DISHES</h2>
<div className={styles.grid}>
{dishes.map((dish) => (
<div key={dish.id} className={styles.card}>
<div className={styles.imageContainer}>
<Image
src={dish.image}
alt={dish.name}
fill
style={{ objectFit: 'cover' }}
/>
</div>
<h3 className={styles.dishName}>{dish.name}</h3>
<p className={styles.description}>{dish.description}</p>
<Link href="#menu" className={styles.button}>
View More
</Link>
</div>
))}
</div>
<div className={styles.viewMoreContainer}>
<Link href="#menu" className={styles.viewMoreButton}>
View More
</Link>
</div>
</section>
)
}

View File

@ -0,0 +1,39 @@
.scrollToTopBtn {
position: fixed;
bottom: 2rem;
right: 2rem;
width: 3.5rem;
height: 3.5rem;
border-radius: 50%;
background-color: #C5A059;
/* Gold color matching the theme */
color: #fff;
border: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
opacity: 0;
visibility: hidden;
transform: translateY(20px);
transition: all 0.3s ease-in-out;
z-index: 50;
}
.scrollToTopBtn:hover {
background-color: #b08d45;
transform: translateY(0) scale(1.1);
}
.visible {
opacity: 1;
visibility: visible;
transform: translateY(0);
}
.icon {
width: 24px;
height: 24px;
stroke-width: 2.5;
}

View File

@ -0,0 +1,51 @@
'use client'
import { useState, useEffect } from 'react'
import styles from './ScrollToTop.module.css'
export default function ScrollToTop() {
const [isVisible, setIsVisible] = useState(false)
const toggleVisibility = () => {
if (window.scrollY > 200) {
setIsVisible(true)
} else {
setIsVisible(false)
}
}
const scrollToTop = () => {
window.scrollTo({
top: 0,
behavior: 'smooth',
})
}
useEffect(() => {
window.addEventListener('scroll', toggleVisibility)
return () => {
window.removeEventListener('scroll', toggleVisibility)
}
}, [])
return (
<button
type="button"
onClick={scrollToTop}
className={`${styles.scrollToTopBtn} ${isVisible ? styles.visible : ''}`}
aria-label="Scroll to top"
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
className={styles.icon}
>
<path d="M18 15l-6-6-6 6" />
</svg>
</button>
)
}

View File

@ -0,0 +1,166 @@
.section {
position: relative;
padding: 80px 20px;
background-color: #0a0a0a;
/* Fallback dark background */
background-image: url('/images/testimonial-bg-luxury.png');
/* Placeholder */
background-size: cover;
background-position: center;
color: #fff;
overflow: hidden;
min-height: 800px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.title {
font-family: var(--font-cinzel), serif;
/* Assuming Cinzel is available or similar serif */
font-size: 3.5rem;
color: #C5A059;
text-align: center;
margin-bottom: 60px;
letter-spacing: 2px;
text-transform: uppercase;
font-weight: 400;
}
.sliderContainer {
display: flex;
justify-content: center;
gap: 30px;
max-width: 1400px;
width: 100%;
position: relative;
padding: 0 60px;
/* Space for arrows */
}
.track {
display: flex;
transition: transform 0.5s ease-in-out;
width: 100%;
}
.card {
background: #1a1a1a;
border: 3px solid #C5A059;
border-radius: 30px;
padding: 40px 30px;
text-align: center;
position: relative;
/* Flex basis for 3 items: 100% / 3 = 33.333% */
flex: 0 0 33.333%;
max-width: 33.333%;
display: flex;
flex-direction: column;
align-items: center;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
box-sizing: border-box;
margin: 0 15px;
/* Visual gap */
/* Adjust flex basis to account for margin: calc(33.333% - 30px) */
flex: 0 0 calc(33.333% - 30px);
max-width: calc(33.333% - 30px);
}
.avatarContainer {
width: 120px;
height: 120px;
margin: 0 auto 20px;
position: relative;
border-radius: 50%;
padding: 4px;
background: linear-gradient(to bottom, #C5A059, #8A6E36);
/* Gold gradient border effect */
}
.avatar {
width: 100%;
height: 100%;
border-radius: 50%;
object-fit: cover;
border: 4px solid #1a1a1a;
/* Inner border to separate from gold */
background-color: #333;
}
.name {
font-family: var(--font-inter), sans-serif;
/* Assuming Inter or similar */
font-size: 1.1rem;
color: #C5A059;
margin-bottom: 30px;
font-weight: 500;
}
.text {
font-family: var(--font-cinzel), serif;
font-size: 1.2rem;
line-height: 1.6;
color: #e0e0e0;
margin-bottom: 30px;
font-style: italic;
}
.stars {
color: #C5A059;
font-size: 1.5rem;
letter-spacing: 5px;
}
.arrow {
position: absolute;
top: 50%;
transform: translateY(-50%);
color: #C5A059;
font-size: 3rem;
cursor: pointer;
background: none;
border: none;
transition: transform 0.2s;
z-index: 10;
}
.arrow:hover {
transform: translateY(-50%) scale(1.1);
}
.prevArrow {
left: -25;
}
.nextArrow {
right: -25;
}
/* Lanterns decoration placeholder */
.lanterns {
position: absolute;
top: 0;
right: 50px;
width: 150px;
height: auto;
z-index: 5;
}
@media (max-width: 1024px) {
.track {
flex-direction: column;
transform: none !important;
/* Disable slide on mobile if stacking */
}
.card {
flex: 0 0 100%;
max-width: 100%;
margin: 0 0 20px 0;
}
.arrow {
display: none;
}
}

View File

@ -0,0 +1,126 @@
'use client'
import { useState, useEffect } from 'react'
import Image from 'next/image'
import styles from './Testimonials.module.css'
// Placeholder data with 6 items
const testimonials = [
{
id: 1,
name: 'Anya Petrova, [City]',
image: '/images/avatar-anya.png',
text: '“An unforgettable journey of flavors and warmth. The ambiance is exquisite is Turkish fusion dishes simply divine.”',
rating: 5
},
{
id: 2,
name: 'Tuest Khan, [City]',
image: '/images/avatar-tuest.png',
text: '“An unforgettable journey of flavors and warmth. The ambiance is exquisite is Turkish fusion dishes simply divine.”',
rating: 5
},
{
id: 3,
name: 'Tariq Name, [City]',
image: '/images/avatar-tariq.png',
text: '“An unforgettable journey of flavors and warmth. The ambiene exquisite, and Turkish fusion dishes simply divine.”',
rating: 5
},
{
id: 4,
name: 'Sarah Jenkins, [City]',
image: '/images/avatar-anya.png', // Reusing for now
text: '“Amazing service and beautiful atmosphere. Highly recommend the mixed grill!”',
rating: 5
},
{
id: 5,
name: 'Michael Chen, [City]',
image: '/images/avatar-tuest.png', // Reusing for now
text: '“A hidden gem! The fusion of flavors is incredible. Will definitely come back.”',
rating: 5
},
{
id: 6,
name: 'Emily Davis, [City]',
image: '/images/avatar-tariq.png', // Reusing for now
text: '“The staff was so welcoming and the food was absolutely delicious. 10/10 experience.”',
rating: 5
}
]
export default function Testimonials() {
const [currentIndex, setCurrentIndex] = useState(0)
const nextSlide = () => {
setCurrentIndex((prev) => (prev + 1) % (testimonials.length - 2))
}
const prevSlide = () => {
setCurrentIndex((prev) => (prev === 0 ? testimonials.length - 3 : prev - 1))
}
// Auto-slide effect
useEffect(() => {
const interval = setInterval(() => {
nextSlide()
}, 5000) // Change slide every 5 seconds
return () => clearInterval(interval)
}, [])
// Get the 3 visible testimonials
// Simple sliding window logic for 3 items
// Note: This simple logic assumes we stop at the end or loop.
// For a true infinite loop with 3 items visible, it's more complex.
// Here we will just slide through the window.
// Actually, let's do a simple modulo wrap for the window to always show 3.
const getVisibleTestimonials = () => {
const items = []
for (let i = 0; i < 3; i++) {
const index = (currentIndex + i) % testimonials.length
items.push(testimonials[index])
}
return items
}
const visibleItems = getVisibleTestimonials()
return (
<section className={styles.section}>
{/* Decorative Lanterns - Placeholder Image */}
{/* <div className={styles.lanterns}>
<Image src="/images/lanterns.png" alt="Lanterns" width={150} height={200} />
</div> */}
<h2 className={styles.title}>TESTIMONIALS</h2>
<div className={styles.sliderContainer}>
<button className={`${styles.arrow} ${styles.prevArrow}`} onClick={prevSlide}></button>
{visibleItems.map((item) => (
<div key={item.id} className={styles.card}>
<div className={styles.avatarContainer}>
{/* Using a div fallback if image is missing, or standard img tag */}
<div className={styles.avatar} style={{ overflow: 'hidden' }}>
{/* Placeholder for avatar - using different colors to distinguish if needed, or just gray */}
<div style={{ width: '100%', height: '100%', backgroundColor: '#ccc', display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#666' }}>
{item.name.charAt(0)}
</div>
</div>
</div>
<h3 className={styles.name}> {item.name}</h3>
<p className={styles.text}>{item.text}</p>
<div className={styles.stars}>
{'★'.repeat(item.rating)}
</div>
</div>
))}
<button className={`${styles.arrow} ${styles.nextArrow}`} onClick={nextSlide}></button>
</div>
</section>
)
}

34
tsconfig.json Normal file
View File

@ -0,0 +1,34 @@
{
"compilerOptions": {
"target": "ES2017",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "react-jsx",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./src/*"]
}
},
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts",
".next/dev/types/**/*.ts",
"**/*.mts"
],
"exclude": ["node_modules"]
}