diff --git a/.claude/settings.json b/.claude/settings.json
new file mode 100644
index 0000000..14a4516
--- /dev/null
+++ b/.claude/settings.json
@@ -0,0 +1,9 @@
+{
+ "env": {
+ "ANTHROPIC_DEFAULT_HAIKU_MODEL": "glm-4.6",
+ "ANTHROPIC_DEFAULT_SONNET_MODEL": "glm-4.6",
+ "ANTHROPIC_DEFAULT_OPUS_MODEL": "glm-4.6",
+ "ANTHROPIC_AUTH_TOKEN": "9f61bdd57b634f2693020b45f0ea198b.nQXOS8pGhmqXhiip",
+ "ANTHROPIC_BASE_URL": "https://api.z.ai/api/anthropic"
+ }
+ }
\ No newline at end of file
diff --git a/next.config.ts b/next.config.ts
index e9ffa30..adaeb8a 100644
--- a/next.config.ts
+++ b/next.config.ts
@@ -1,7 +1,22 @@
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
- /* config options here */
+ images: {
+ remotePatterns: [
+ {
+ protocol: 'https',
+ hostname: 'images.unsplash.com',
+ port: '',
+ pathname: '/**',
+ },
+ {
+ protocol: 'https',
+ hostname: 'picsum.photos',
+ port: '',
+ pathname: '/**',
+ },
+ ],
+ },
};
export default nextConfig;
diff --git a/package-lock.json b/package-lock.json
index a95f9ba..907130c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,6 +8,10 @@
"name": "hotels",
"version": "0.1.0",
"dependencies": {
+ "@gsap/react": "^2.1.2",
+ "@phosphor-icons/react": "^2.1.10",
+ "gsap": "^3.13.0",
+ "lucide-react": "^0.546.0",
"next": "15.5.5",
"react": "19.1.0",
"react-dom": "19.1.0"
@@ -208,6 +212,16 @@
"tslib": "^2.4.0"
}
},
+ "node_modules/@gsap/react": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/@gsap/react/-/react-2.1.2.tgz",
+ "integrity": "sha512-JqliybO1837UcgH2hVOM4VO+38APk3ECNrsuSM4MuXp+rbf+/2IG2K1YJiqfTcXQHH7XlA0m3ykniFYstfq0Iw==",
+ "license": "SEE LICENSE AT https://gsap.com/standard-license",
+ "peerDependencies": {
+ "gsap": "^3.12.5",
+ "react": ">=17"
+ }
+ },
"node_modules/@img/colour": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz",
@@ -833,6 +847,19 @@
"node": ">= 10"
}
},
+ "node_modules/@phosphor-icons/react": {
+ "version": "2.1.10",
+ "resolved": "https://registry.npmjs.org/@phosphor-icons/react/-/react-2.1.10.tgz",
+ "integrity": "sha512-vt8Tvq8GLjheAZZYa+YG/pW7HDbov8El/MANW8pOAz4eGxrwhnbfrQZq0Cp4q8zBEu8NIhHdnr+r8thnfRSNYA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "react": ">= 16.8",
+ "react-dom": ">= 16.8"
+ }
+ },
"node_modules/@swc/helpers": {
"version": "0.5.15",
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
@@ -1134,6 +1161,7 @@
"integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"csstype": "^3.0.2"
}
@@ -1222,6 +1250,13 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/gsap": {
+ "version": "3.13.0",
+ "resolved": "https://registry.npmjs.org/gsap/-/gsap-3.13.0.tgz",
+ "integrity": "sha512-QL7MJ2WMjm1PHWsoFrAQH/J8wUeqZvMtHO58qdekHpCfhvhSL4gSiz6vJf5EeMP0LOn3ZCprL2ki/gjED8ghVw==",
+ "license": "Standard 'no charge' license: https://gsap.com/standard-license.",
+ "peer": true
+ },
"node_modules/jiti": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz",
@@ -1471,6 +1506,15 @@
"url": "https://opencollective.com/parcel"
}
},
+ "node_modules/lucide-react": {
+ "version": "0.546.0",
+ "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.546.0.tgz",
+ "integrity": "sha512-Z94u6fKT43lKeYHiVyvyR8fT7pwCzDu7RyMPpTvh054+xahSgj4HFQ+NmflvzdXsoAjYGdCguGaFKYuvq0ThCQ==",
+ "license": "ISC",
+ "peerDependencies": {
+ "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
"node_modules/magic-string": {
"version": "0.30.19",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz",
@@ -1642,6 +1686,7 @@
"resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz",
"integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==",
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">=0.10.0"
}
@@ -1651,6 +1696,7 @@
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz",
"integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"scheduler": "^0.26.0"
},
diff --git a/package.json b/package.json
index 7f6e501..02d7a63 100644
--- a/package.json
+++ b/package.json
@@ -10,17 +10,21 @@
"format": "biome format --write"
},
"dependencies": {
+ "@gsap/react": "^2.1.2",
+ "@phosphor-icons/react": "^2.1.10",
+ "gsap": "^3.13.0",
+ "lucide-react": "^0.546.0",
+ "next": "15.5.5",
"react": "19.1.0",
- "react-dom": "19.1.0",
- "next": "15.5.5"
+ "react-dom": "19.1.0"
},
"devDependencies": {
- "typescript": "^5",
+ "@biomejs/biome": "2.2.0",
+ "@tailwindcss/postcss": "^4",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
- "@tailwindcss/postcss": "^4",
"tailwindcss": "^4",
- "@biomejs/biome": "2.2.0"
+ "typescript": "^5"
}
}
diff --git a/public/Fonts/blanka/Blanka-Regular.otf b/public/Fonts/blanka/Blanka-Regular.otf
new file mode 100644
index 0000000..60b18d7
Binary files /dev/null and b/public/Fonts/blanka/Blanka-Regular.otf differ
diff --git a/public/Fonts/blanka/Please Read This.rtf b/public/Fonts/blanka/Please Read This.rtf
new file mode 100644
index 0000000..007f41e
--- /dev/null
+++ b/public/Fonts/blanka/Please Read This.rtf
@@ -0,0 +1,15 @@
+{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
+{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\paperw11900\paperh16840\margl1440\margr1440\vieww10800\viewh8400\viewkind0
+\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural
+
+\f0\fs24 \cf0 Thanks for downloading BLANKA FONT !\
+\
+You can use it for free and commercial.\
+\
+Feedbacks are welcome !\
+\
+\'97\
+Emmeran RICHARD.\
+www.emmeranrichard.fr}
\ No newline at end of file
diff --git a/public/Fonts/figtree/figtree-italic.ttf b/public/Fonts/figtree/figtree-italic.ttf
new file mode 100644
index 0000000..968b606
Binary files /dev/null and b/public/Fonts/figtree/figtree-italic.ttf differ
diff --git a/public/Fonts/figtree/figtree.ttf b/public/Fonts/figtree/figtree.ttf
new file mode 100644
index 0000000..19c4a20
Binary files /dev/null and b/public/Fonts/figtree/figtree.ttf differ
diff --git a/public/Popular-Cities/faisal-masjid.svg b/public/Popular-Cities/faisal-masjid.svg
new file mode 100644
index 0000000..d5003ee
--- /dev/null
+++ b/public/Popular-Cities/faisal-masjid.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/Popular-Cities/k2-mountain.svg b/public/Popular-Cities/k2-mountain.svg
new file mode 100644
index 0000000..9849d69
--- /dev/null
+++ b/public/Popular-Cities/k2-mountain.svg
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/public/Popular-Cities/mazar-e-quaid.svg b/public/Popular-Cities/mazar-e-quaid.svg
new file mode 100644
index 0000000..702ba8f
--- /dev/null
+++ b/public/Popular-Cities/mazar-e-quaid.svg
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/public/Popular-Cities/minar-e-pakistan.svg b/public/Popular-Cities/minar-e-pakistan.svg
new file mode 100644
index 0000000..d316368
--- /dev/null
+++ b/public/Popular-Cities/minar-e-pakistan.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/arrow.png b/public/arrow.png
new file mode 100644
index 0000000..0c84ba8
Binary files /dev/null and b/public/arrow.png differ
diff --git a/public/badge-ticket.png b/public/badge-ticket.png
new file mode 100644
index 0000000..26526e5
Binary files /dev/null and b/public/badge-ticket.png differ
diff --git a/public/best-prices.png b/public/best-prices.png
new file mode 100644
index 0000000..233f390
Binary files /dev/null and b/public/best-prices.png differ
diff --git a/public/hotel-banner.png b/public/hotel-banner.png
new file mode 100644
index 0000000..c921dac
Binary files /dev/null and b/public/hotel-banner.png differ
diff --git a/public/logo.png b/public/logo.png
new file mode 100644
index 0000000..5f9ce50
Binary files /dev/null and b/public/logo.png differ
diff --git a/public/stars.jpg b/public/stars.jpg
new file mode 100644
index 0000000..4dd4673
Binary files /dev/null and b/public/stars.jpg differ
diff --git a/src/app/globals.css b/src/app/globals.css
index a2dc41e..3d552a6 100644
--- a/src/app/globals.css
+++ b/src/app/globals.css
@@ -1,26 +1,2 @@
@import "tailwindcss";
-:root {
- --background: #ffffff;
- --foreground: #171717;
-}
-
-@theme inline {
- --color-background: var(--background);
- --color-foreground: var(--foreground);
- --font-sans: var(--font-geist-sans);
- --font-mono: var(--font-geist-mono);
-}
-
-@media (prefers-color-scheme: dark) {
- :root {
- --background: #0a0a0a;
- --foreground: #ededed;
- }
-}
-
-body {
- background: var(--background);
- color: var(--foreground);
- font-family: Arial, Helvetica, sans-serif;
-}
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index f7fa87e..21333be 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -1,20 +1,9 @@
import type { Metadata } from "next";
-import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
-const geistSans = Geist({
- variable: "--font-geist-sans",
- subsets: ["latin"],
-});
-
-const geistMono = Geist_Mono({
- variable: "--font-geist-mono",
- subsets: ["latin"],
-});
-
export const metadata: Metadata = {
- title: "Create Next App",
- description: "Generated by create next app",
+ title: "Hotels",
+ description: "Hotels",
};
export default function RootLayout({
@@ -24,9 +13,7 @@ export default function RootLayout({
}>) {
return (
-
+
{children}
diff --git a/src/app/page.tsx b/src/app/page.tsx
index a932894..2b2d483 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -1,103 +1,22 @@
-import Image from "next/image";
-
+import Navigation from "@/components/common/navigation";
+import Hero from "@/components/landing/hero";
+import Search from "@/components/landing/search";
+import BestPrices from "@/components/landing/best-prices";
+import BrowseByCity from "@/components/landing/browse-by-city";
+import Review from "@/components/landing/review";
+import FAQs from "@/components/landing/faqs";
+import Footer from "@/components/landing/footer";
+import SearchBy from "@/components/search-results/search";
+import Results from "@/components/search-results/results";
+import Features from "@/components/details/features";
export default function Home() {
return (
-
-
-
-
-
- Get started by editing{" "}
-
- src/app/page.tsx
-
- .
-
-
- Save and see your changes instantly.
-
-
-
-
-
-
-
+ <>
+
+
+
+
+
+ >
);
}
diff --git a/src/components/common/navigation.tsx b/src/components/common/navigation.tsx
new file mode 100644
index 0000000..5c0f04f
--- /dev/null
+++ b/src/components/common/navigation.tsx
@@ -0,0 +1,62 @@
+'use client'
+import Image from "next/image";
+import gsap from "gsap";
+import { useRef } from "react";
+import { useGSAP } from "@gsap/react";
+import localFont from "next/font/local";
+import logo from '../../../public/logo.png';
+import { UserSquare } from "@phosphor-icons/react";
+
+
+
+
+const figtree = localFont({
+ src: [
+ {
+ path: '../../../public/Fonts/figtree/figtree.ttf',
+ },
+ ],
+})
+
+
+
+
+function Navigation() {
+
+ const navbarRef = useRef(null);
+
+ useGSAP(() => {
+ gsap.fromTo(navbarRef.current, {
+ y: -40,
+ opacity: 0,
+ }, {
+ y: 10,
+ opacity: 1,
+ duration: 1,
+ ease: "elastic.out(1,0.3)",
+ });
+ });
+
+ return (
+
+
+
+
+
+
Your Reservation
+ Book Now
+
+
+
+
+ List Your Property
+
+
+
+
+
+
+ )
+}
+
+export default Navigation;
\ No newline at end of file
diff --git a/src/components/details/features.tsx b/src/components/details/features.tsx
new file mode 100644
index 0000000..99cbbc8
--- /dev/null
+++ b/src/components/details/features.tsx
@@ -0,0 +1,464 @@
+"use client"
+
+import { Star, MapPin, Share, Heart, Wifi, Car, Utensils, Wind, Monitor, X, Waves, Dumbbell, Coffee, Briefcase, Droplets, Tv } from "lucide-react";
+import { useState, useEffect } from "react";
+import localFont from "next/font/local";
+import Image from "next/image";
+
+const figtree = localFont({
+ src: [
+ {
+ path: '../../../public/Fonts/figtree/figtree.ttf',
+ },
+ ],
+})
+
+const property = {
+ title: "Luxury Villa with Panoramic Mountain Views",
+ location: "Islamabad, Pakistan",
+ guests: 4,
+ bedrooms: 2,
+ beds: 2,
+ baths: 2,
+ rating: 4.81,
+ reviewCount: 5,
+ price: 25000,
+ description: "Experience the ultimate luxury in this stunning villa located in the heart of Islamabad. Featuring breathtaking mountain views, modern amenities, and a serene atmosphere, this is the perfect getaway for families and couples alike. The property boasts a spacious living area, a fully equipped kitchen, and a private garden.",
+ amenities: [
+ { icon: Wifi, label: "Fast Wifi", category: "Internet & Office" },
+ { icon: Monitor, label: "TV with Netflix", category: "Entertainment" },
+ { icon: Briefcase, label: "Dedicated workspace", category: "Internet & Office" },
+ { icon: Car, label: "Free Parking", category: "Parking & Facilities" },
+ { icon: Utensils, label: "Full Kitchen", category: "Kitchen" },
+ { icon: Coffee, label: "Coffee Maker", category: "Kitchen" },
+ { icon: Wind, label: "Air Conditioning", category: "Heating & Cooling" },
+ { icon: Waves, label: "Private Pool", category: "Parking & Facilities" },
+ { icon: Dumbbell, label: "Gym", category: "Parking & Facilities" },
+ { icon: Droplets, label: "Washer & Dryer", category: "Services" },
+ { icon: Tv, label: "HDTV", category: "Entertainment" }
+ ],
+ host: {
+ name: "John Doe",
+ image: "https://picsum.photos/100/100",
+ joined: "2020",
+ isSuperhost: true
+ },
+ images: [
+ "/hotel-banner.png",
+ "/hotel-banner.png",
+ "/hotel-banner.png",
+ "/hotel-banner.png",
+ "/hotel-banner.png"
+ ],
+ reviews: [
+ {
+ id: 1,
+ user: "Sarah Smith",
+ avatar: "https://picsum.photos/50/50?random=1",
+ date: "October 2023",
+ rating: 5,
+ comment: "Absolutely stunning property! The views are incredible and the host was very responsive. The villa was spotless and had everything we needed for a comfortable stay."
+ },
+ {
+ id: 2,
+ user: "Mike Johnson",
+ avatar: "https://picsum.photos/50/50?random=2",
+ date: "September 2023",
+ rating: 4.5,
+ comment: "Great location and amenities. The only minor issue was the wifi speed, but otherwise perfect. The pool was amazing and the kids loved it."
+ },
+ {
+ id: 3,
+ user: "Emily Davis",
+ avatar: "https://picsum.photos/50/50?random=3",
+ date: "August 2023",
+ rating: 5,
+ comment: "A perfect getaway! The attention to detail in the design is impressive. We will definitely be coming back next year."
+ },
+ {
+ id: 4,
+ user: "David Wilson",
+ avatar: "https://picsum.photos/50/50?random=4",
+ date: "July 2023",
+ rating: 4.8,
+ comment: "Beautiful location and very comfortable beds. The kitchen is well-stocked for cooking meals."
+ },
+ {
+ id: 5,
+ user: "Jessica Brown",
+ avatar: "https://picsum.photos/50/50?random=5",
+ date: "June 2023",
+ rating: 5,
+ comment: "Host was super helpful and gave great local recommendations. The house is even better than the photos."
+ }
+ ]
+}
+
+function Features() {
+ const [showAmenities, setShowAmenities] = useState(false);
+ const [showReviews, setShowReviews] = useState(false);
+
+ // Prevent body scroll when modal is open
+ useEffect(() => {
+ if (showAmenities || showReviews) {
+ document.body.style.overflow = 'hidden';
+ } else {
+ document.body.style.overflow = 'unset';
+ }
+ return () => {
+ document.body.style.overflow = 'unset';
+ };
+ }, [showAmenities, showReviews]);
+
+ return (
+
+ {/* Header Section */}
+
+
+
{property.title}
+
+
+
+
+ {property.rating} · {property.reviewCount} reviews
+
+ |
+
+
+ {property.location}
+
+
+
+
+
+ Share
+
+
+
+ Save
+
+
+
+
+
+
+ {/* Image Grid */}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Show all photos
+
+
+
+
+
+
+ {/* Main Content */}
+
+
+ {/* Left Column */}
+
+
+ {/* Host Info & Stats */}
+
+
+
Hosted by {property.host.name}
+
+ {property.guests} guests · {property.bedrooms} bedrooms · {property.beds} beds · {property.baths} baths
+
+
+
+
+
+
+
+ {/* Highlights */}
+
+
+
+
+
+
+
Top rated host
+
John has received 5-star ratings from 95% of recent guests.
+
+
+
+
+
+
+
+
Great location
+
100% of recent guests gave the location a 5-star rating.
+
+
+
+
+ {/* Description */}
+
+
About this place
+
+ {property.description}
+
+
+
+ {/* Amenities */}
+
+
What this place offers
+
+ {property.amenities.slice(0, 6).map((item, idx) => (
+
+
+ {item.label}
+
+ ))}
+
+
setShowAmenities(true)}
+ className="mt-6 px-6 py-3 border-2 border-black font-medium hover:bg-[#E7FE78] transition-colors"
+ >
+ Show all {property.amenities.length} amenities
+
+
+
+
+
+ {/* Right Column - Sticky Booking Card */}
+
+
+
+
+ ₨{property.price.toLocaleString()}
+ / night
+
+
+
+ {property.rating} · {property.reviewCount} reviews
+
+
+
+
+
+
+ Guests
+
+ 1 guest
+ 2 guests
+ 3 guests
+
+
+
+
+
+ Reserve
+
+
+
You won't be charged yet
+
+
+
+ ₨{property.price.toLocaleString()} x 5 nights
+ ₨{(property.price * 5).toLocaleString()}
+
+
+ Cleaning fee
+ ₨5,000
+
+
+ Service fee
+ ₨8,000
+
+
+ Total
+ ₨{(property.price * 5 + 13000).toLocaleString()}
+
+
+
+
+
+
+ {/* Reviews Section */}
+
+
+
+
{property.rating} · {property.reviewCount} reviews
+
+
+
+ {property.reviews.slice(0, 4).map((review) => (
+
+
+
+
+
{review.user}
+
{review.date}
+
+
+
+ "{review.comment}"
+
+
+ ))}
+
+
setShowReviews(true)}
+ className="mt-8 px-8 py-3 border-2 border-black font-medium hover:bg-[#E7FE78] transition-colors"
+ >
+ Show all {property.reviewCount} reviews
+
+
+
+ {/* Amenities Modal */}
+ {showAmenities && (
+
+
setShowAmenities(false)} />
+
+
+
What this place offers
+ setShowAmenities(false)}
+ className="p-2 hover:bg-gray-100 rounded-full transition-colors"
+ >
+
+
+
+
+
+ {Array.from(new Set(property.amenities.map(a => a.category))).map(category => (
+
+
{category}
+
+ {property.amenities.filter(a => a.category === category).map((item, idx) => (
+
+
+ {item.label}
+
+ ))}
+
+
+ ))}
+
+
+
+
+ )}
+
+ {/* Reviews Modal */}
+ {showReviews && (
+
+
setShowReviews(false)} />
+
+
+
+
+
{property.rating} · {property.reviewCount} reviews
+
+
setShowReviews(false)}
+ className="p-2 hover:bg-gray-100 rounded-full transition-colors"
+ >
+
+
+
+
+
+ {property.reviews.map((review) => (
+
+
+
+
+
{review.user}
+
{review.date}
+
+
+
+ {[...Array(5)].map((_, i) => (
+
+ ))}
+
+
+ {review.comment}
+
+
+ ))}
+
+
+
+
+ )}
+
+ )
+}
+
+export default Features;
\ No newline at end of file
diff --git a/src/components/landing/best-prices.tsx b/src/components/landing/best-prices.tsx
new file mode 100644
index 0000000..20afd80
--- /dev/null
+++ b/src/components/landing/best-prices.tsx
@@ -0,0 +1,33 @@
+import Image from "next/image";
+import BestPricesImage from '../../../public/best-prices.png'
+import hotelBanner from '../../../public/hotel-banner.png'
+import localFont from "next/font/local";
+
+
+const figtree = localFont({
+ src: [
+ {
+ path: '../../../public/Fonts/figtree/figtree.ttf',
+ },
+ ],
+})
+
+function BestPrices() {
+ return (
+
+
+
+
+
+
+
+
Consistent Service and Quality
+
1. Our listings are consistently rated highly for service and quality, ensuring you have a comfortable and enjoyable stay.
+
2. We make sure to offer the best prices for our listings, ensuring you get the best value for your money.
+
+
+
+ )
+}
+
+export default BestPrices;
\ No newline at end of file
diff --git a/src/components/landing/browse-by-city.tsx b/src/components/landing/browse-by-city.tsx
new file mode 100644
index 0000000..f796a67
--- /dev/null
+++ b/src/components/landing/browse-by-city.tsx
@@ -0,0 +1,246 @@
+'use client';
+
+import localFont from "next/font/local";
+import Image from "next/image";
+import { useState } from "react";
+
+const figtree = localFont({
+ src: [
+ {
+ path: '../../../public/Fonts/figtree/figtree.ttf',
+ },
+ ],
+})
+
+interface Property {
+ id: number;
+ image: string;
+ city: string;
+ price: number;
+ title: string;
+ rating: number;
+}
+
+const cities = ["Islamabad", "Karachi", "Lahore"];
+
+// Sample property data - you'll replace these with actual hotel images
+const propertiesByCity: Record
= {
+ "Islamabad": [
+ {
+ id: 1,
+ image: "/hotel-banner.png",
+ city: "ISLAMABAD, PAKISTAN",
+ price: 12500,
+ title: "Luxury hotel in Islamabad",
+ rating: 4.9
+ },
+ {
+ id: 2,
+ image: "/hotel-banner.png",
+ city: "ISLAMABAD, PAKISTAN",
+ price: 15000,
+ title: "Modern apartment near Faisal Masjid",
+ rating: 4.8
+ },
+ {
+ id: 3,
+ image: "/hotel-banner.png",
+ city: "ISLAMABAD, PAKISTAN",
+ price: 18000,
+ title: "Spacious villa with mountain view",
+ rating: 4.9
+ },
+ {
+ id: 4,
+ image: "/hotel-banner.png",
+ city: "ISLAMABAD, PAKISTAN",
+ price: 11000,
+ title: "Cozy studio in F-7 sector",
+ rating: 4.7
+ }
+ ],
+ "Karachi": [
+ {
+ id: 5,
+ image: "/hotel-banner.png",
+ city: "KARACHI, PAKISTAN",
+ price: 10000,
+ title: "Beachfront apartment in Clifton",
+ rating: 4.8
+ },
+ {
+ id: 6,
+ image: "/hotel-banner.png",
+ city: "KARACHI, PAKISTAN",
+ price: 13500,
+ title: "Luxury suite near Port Grand",
+ rating: 4.9
+ },
+ {
+ id: 7,
+ image: "/hotel-banner.png",
+ city: "KARACHI, PAKISTAN",
+ price: 9500,
+ title: "Modern flat in DHA",
+ rating: 4.7
+ },
+ {
+ id: 8,
+ image: "/hotel-banner.png",
+ city: "KARACHI, PAKISTAN",
+ price: 14000,
+ title: "Spacious penthouse with sea view",
+ rating: 4.9
+ }
+ ],
+ "Lahore": [
+ {
+ id: 9,
+ image: "/hotel-banner.png",
+ city: "LAHORE, PAKISTAN",
+ price: 11500,
+ title: "Heritage hotel near Badshahi Masjid",
+ rating: 4.8
+ },
+ {
+ id: 10,
+ image: "/hotel-banner.png",
+ city: "LAHORE, PAKISTAN",
+ price: 13000,
+ title: "Modern apartment in Gulberg",
+ rating: 4.9
+ },
+ {
+ id: 11,
+ image: "/hotel-banner.png",
+ city: "LAHORE, PAKISTAN",
+ price: 16000,
+ title: "Luxury villa in DHA",
+ rating: 4.9
+ },
+ {
+ id: 12,
+ image: "/hotel-banner.png",
+ city: "LAHORE, PAKISTAN",
+ price: 10500,
+ title: "Cozy stay near Minar-e-Pakistan",
+ rating: 4.7
+ }
+ ]
+};
+
+function BrowseByCity() {
+ const [selectedCity, setSelectedCity] = useState("Islamabad");
+
+ return (
+
+
+ {/* Section Header */}
+
+
+ Browse by city
+
+
+ Experience different cities and vibes by staying with PakStay
+
+
+
+ {/* City Tabs */}
+
+
+ {cities.map((city) => (
+ setSelectedCity(city)}
+ className={`${figtree.className} px-10 py-3 text-base font-bold transition-all duration-300 gap-2
+ ${selectedCity === city
+ ? 'bg-[#E7FE78] text-black uppercase'
+ : 'bg-transparent text-gray-700 hover:bg-[#E7FE78] uppercase'
+ }`}
+ >
+ {city}
+
+ ))}
+
+
+
+ {/* Property Cards Grid */}
+
+
+ {propertiesByCity[selectedCity].map((property) => (
+
+ {/* Image Container */}
+
+
+
+
+ {/* Property Details */}
+
+ {/* Location */}
+
+
+ {property.city}
+
+
+
+
+
+
+ {property.rating}
+
+
+
+
+ {/* Title */}
+
+ {property.title}
+
+
+ {/* Price */}
+
+ ₨{property.price.toLocaleString()}
+ night
+
+
+
+ ))}
+
+
+ {/* Navigation Arrows */}
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Pagination Dots */}
+
+ {[0, 1, 2, 3, 4, 5].map((dot, index) => (
+
+ ))}
+
+
+
+ )
+}
+
+export default BrowseByCity;
\ No newline at end of file
diff --git a/src/components/landing/faqs.tsx b/src/components/landing/faqs.tsx
new file mode 100644
index 0000000..3fed3c0
--- /dev/null
+++ b/src/components/landing/faqs.tsx
@@ -0,0 +1,128 @@
+"use client";
+
+import localFont from "next/font/local";
+import { useState } from "react";
+
+const figtree = localFont({
+ src: [
+ {
+ path: '../../../public/Fonts/figtree/figtree.ttf',
+ },
+ ],
+})
+
+interface FAQItem {
+ question: string;
+ answer: string;
+}
+
+const faqData: FAQItem[] = [
+ {
+ question: "How does PakStay work?",
+ answer: "The first step is to get in touch with us. They'll discuss with you what the best options are and proceed to calculate your potential earnings. If you're happy the next steps depend on whether you have a running set-up or starting from 0. We're familiar with both. Have a look at the onboarding process."
+ },
+ {
+ question: "What makes PakStay the right partner?",
+ answer: "Managing a vacation rental isn't easy. It's a balance of hosting, analyzing & managing a home that requires a lot of attention. We're there to take away that hassle for you because we're doing it anyways and we simply love what we're doing. We're set out on a mission to make vacation rental owners happy. Really happy."
+ },
+ {
+ question: "What happens if I'm not happy with PakStay's service?",
+ answer: ""
+ },
+ {
+ question: "How does the onboarding process work?",
+ answer: ""
+ },
+ {
+ question: "Do I have to sign a long-term contract?",
+ answer: ""
+ },
+ {
+ question: "Do I need a running business already?",
+ answer: ""
+ },
+ {
+ question: "What about legality? Isn't short-term rental illegal?",
+ answer: ""
+ },
+ {
+ question: "I dont own my apartments, I rent them. Does that work too?",
+ answer: ""
+ },
+ {
+ question: "Do I have a personal contact at PakStay?",
+ answer: ""
+ },
+ {
+ question: "Do you really guarantee customer satisfaction? How does that work?",
+ answer: ""
+ },
+ {
+ question: "I have apartments in a city you're not operating yet.",
+ answer: ""
+ }
+];
+
+function FAQs() {
+ const [openIndex, setOpenIndex] = useState(null);
+
+ const toggleFAQ = (index: number) => {
+ setOpenIndex(openIndex === index ? null : index);
+ };
+
+ return (
+
+
+
+ FAQs
+
+
+
+ {faqData.map((faq, index) => (
+
+
toggleFAQ(index)}
+ className="w-full flex items-center justify-between p-6 text-left focus:outline-none hover:bg-gray-50 transition-colors"
+ >
+
+ {faq.question}
+
+
+
+ {openIndex === index ? (
+
+ ) : (
+
+ )}
+
+
+
+
+ {openIndex === index && faq.answer && (
+
+ )}
+
+ ))}
+
+
+
+ )
+}
+
+export default FAQs;
\ No newline at end of file
diff --git a/src/components/landing/footer.tsx b/src/components/landing/footer.tsx
new file mode 100644
index 0000000..9f24514
--- /dev/null
+++ b/src/components/landing/footer.tsx
@@ -0,0 +1,32 @@
+import localFont from "next/font/local";
+import logo from '../../../public/logo.png';
+import Image from "next/image";
+
+const figtree = localFont({
+ src: [
+ {
+ path: '../../../public/Fonts/figtree/figtree.ttf',
+ },
+ ],
+})
+
+const InstagramLogo =
+
+function Footer() {
+ return (
+
+
+
+
{InstagramLogo}
+
+ Contact
+ T&Cs
+ Legal
+ Privacy
+
+
+
+ )
+}
+
+export default Footer;
\ No newline at end of file
diff --git a/src/components/landing/hero.tsx b/src/components/landing/hero.tsx
new file mode 100644
index 0000000..316ce71
--- /dev/null
+++ b/src/components/landing/hero.tsx
@@ -0,0 +1,36 @@
+import localFont from "next/font/local";
+import Image from "next/image";
+import badge from '../../../public/badge-ticket.png'
+import arrow from '../../../public/arrow.png'
+
+const figtree = localFont({
+ src: [
+ {
+ path: '../../../public/Fonts/figtree/figtree.ttf',
+ },
+ ],
+})
+
+
+function Hero() {
+ return (
+
+
+
+
Find Your PakStay Home in
+
+
+
+
Travel Karo, Tension Free!
+
+
+
+ )
+}
+
+export default Hero;
\ No newline at end of file
diff --git a/src/components/landing/review.tsx b/src/components/landing/review.tsx
new file mode 100644
index 0000000..ba316a9
--- /dev/null
+++ b/src/components/landing/review.tsx
@@ -0,0 +1,158 @@
+'use client';
+
+import localFont from "next/font/local";
+import { useState } from "react";
+import { ChevronLeft, ChevronRight, Star } from "lucide-react";
+
+const figtree = localFont({
+ src: [
+ {
+ path: '../../../public/Fonts/figtree/figtree.ttf',
+ },
+ ],
+})
+
+interface Review {
+ name: string;
+ date: string;
+ rating: number;
+ text: string;
+}
+
+const reviews: Review[] = [
+ {
+ name: "Ayesha Malik",
+ date: "October 2025",
+ rating: 4.81,
+ text: "Clean apartment in great location Positive: Nice apartment in a highly walkable location. We took the river walk to most of the main attractions, which was a scenic 20 minute walk full of outdoor restaurants that we really enjoyed. The apartment was clean and spacious. Highly recommend",
+ },
+ {
+ name: "Hassan Bilal",
+ date: "October 2025",
+ rating: 4.81,
+ text: "The place is great. All the appliances, furniture and bathroom fittings were new. Lots of crockery and cutlery making it very easy for us. Very accessible apartment and a lift is a great plus given that the apartment is on the 4th floor. The mattresses were just great...very comfortable. I highly recommend the place. Thank you Mai.",
+
+ },
+ {
+ name: "Javed Ali",
+ date: "October 2025",
+ rating: 4.81,
+ text: "I was traveling with my wife. We spent a couple of nights there. I totally recommend the apartment. It has everything one needs - utensils, kitchenware etc. Extremely clean. New. I had a feeling that we are the first guests there. Was really nice to come back to this cozy light apartment. Thanks to the great host :)",
+
+ },
+ {
+ name: "Sarah Raza",
+ date: "October 2025",
+ rating: 4.75,
+ text: "Amazing stay! The apartment exceeded our expectations. Great location, modern amenities, and the host was very responsive. Would definitely stay here again!",
+
+ },
+ {
+ name: "Shakeel Ahmed",
+ date: "October 2025",
+ rating: 4.90,
+ text: "Perfect apartment for our city break. Everything was spotless and well-maintained. The neighborhood is quiet yet close to all attractions. Highly recommended!"
+
+ }
+];
+
+function Review() {
+ const [currentIndex, setCurrentIndex] = useState(0);
+ const reviewsPerPage = 3;
+ const totalPages = Math.ceil(reviews.length / reviewsPerPage);
+
+ const nextSlide = () => {
+ setCurrentIndex((prev) => (prev + 1) % totalPages);
+ };
+
+ const prevSlide = () => {
+ setCurrentIndex((prev) => (prev - 1 + totalPages) % totalPages);
+ };
+
+ const getCurrentReviews = () => {
+ const start = currentIndex * reviewsPerPage;
+ return reviews.slice(start, start + reviewsPerPage);
+ };
+
+ return (
+
+
+
+ {/* Header */}
+
+
+ What others have to say about us
+
+
+ We have not only earned the trust of our customers but also of our highly valued service providers.
+
+
+
+ {/* Reviews Carousel */}
+
+ {/* Navigation Buttons */}
+
+
+
+
+
+
+
+
+ {/* Reviews Grid */}
+
+ {getCurrentReviews().map((review, index) => (
+
+ {/* Header */}
+
+
+
{review.name}
+
{review.date}
+
+
+
+ {review.rating}
+
+
+
+ {/* Review Text */}
+
+ {review.text}
+
+
+ ))}
+
+
+
+ {/* Pagination Dots */}
+
+ {Array.from({ length: totalPages }).map((_, index) => (
+ setCurrentIndex(index)}
+ className={`w-2 h-2 rounded-full transition-all ${
+ index === currentIndex
+ ? 'bg-black w-3 h-3'
+ : 'bg-gray-400'
+ }`}
+ aria-label={`Go to page ${index + 1}`}
+ />
+ ))}
+
+
+
+ )
+}
+
+export default Review;
\ No newline at end of file
diff --git a/src/components/landing/search.tsx b/src/components/landing/search.tsx
new file mode 100644
index 0000000..9346649
--- /dev/null
+++ b/src/components/landing/search.tsx
@@ -0,0 +1,78 @@
+'use client'
+import localFont from "next/font/local";
+import { Calendar, MagnifyingGlass, MapPin, User } from "@phosphor-icons/react";
+import arrow from '../../../public/arrow.png'
+import Image from "next/image";
+
+
+const figtree = localFont({
+ src: [
+ {
+ path: '../../../public/Fonts/figtree/figtree.ttf',
+ },
+ ],
+})
+
+function Search() {
+ return (
+
+
+
+
+
+
+
+ {/* First Column */}
+
+ {/* Separator */}
+
+ {/* Second Column */}
+
+ {/* Separator */}
+
+ {/* Third Column */}
+
+ {/* Separator */}
+
+ {/* Fourth Column */}
+
+ {/* Separator */}
+
+ {/* Fifth Column */}
+
+
+
+
+
+ )
+}
+
+export default Search;
\ No newline at end of file
diff --git a/src/components/search-results/results.tsx b/src/components/search-results/results.tsx
new file mode 100644
index 0000000..0ca56ce
--- /dev/null
+++ b/src/components/search-results/results.tsx
@@ -0,0 +1,221 @@
+'use client';
+
+import localFont from "next/font/local";
+import Image from "next/image";
+import { useState } from "react";
+
+const figtree = localFont({
+ src: [
+ {
+ path: '../../../public/Fonts/figtree/figtree.ttf',
+ },
+ ],
+})
+
+interface Property {
+ id: number;
+ image: string;
+ city: string;
+ price: number;
+ title: string;
+ rating: number;
+}
+
+// Sample property data - replace with actual API data
+const allProperties: Property[] = Array.from({ length: 120 }, (_, i) => ({
+ id: i + 1,
+ image: "/hotel-banner.png",
+ city: ["ISLAMABAD, PAKISTAN", "KARACHI, PAKISTAN", "LAHORE, PAKISTAN"][i % 3],
+ price: Math.floor(Math.random() * 10000) + 8000,
+ title: [
+ "Luxury hotel with modern amenities",
+ "Cozy apartment in city center",
+ "Spacious villa with garden view",
+ "Modern suite near landmark",
+ "Beachfront property with pool",
+ "Heritage hotel with traditional charm",
+ "Contemporary loft in downtown",
+ "Family-friendly resort"
+ ][i % 8],
+ rating: Number((4.5 + Math.random() * 0.5).toFixed(1))
+}));
+
+const PROPERTIES_PER_PAGE = 40; // 10 rows × 4 columns
+
+function Results() {
+ const [currentPage, setCurrentPage] = useState(1);
+
+ const totalPages = Math.ceil(allProperties.length / PROPERTIES_PER_PAGE);
+ const startIndex = (currentPage - 1) * PROPERTIES_PER_PAGE;
+ const endIndex = startIndex + PROPERTIES_PER_PAGE;
+ const currentProperties = allProperties.slice(startIndex, endIndex);
+
+ const goToPage = (page: number) => {
+ setCurrentPage(page);
+ window.scrollTo({ top: 0, behavior: 'smooth' });
+ };
+
+ const goToPreviousPage = () => {
+ if (currentPage > 1) {
+ goToPage(currentPage - 1);
+ }
+ };
+
+ const goToNextPage = () => {
+ if (currentPage < totalPages) {
+ goToPage(currentPage + 1);
+ }
+ };
+
+ // Generate page numbers to display
+ const getPageNumbers = () => {
+ const pages = [];
+ const maxPagesToShow = 5;
+
+ if (totalPages <= maxPagesToShow) {
+ for (let i = 1; i <= totalPages; i++) {
+ pages.push(i);
+ }
+ } else {
+ if (currentPage <= 3) {
+ for (let i = 1; i <= 4; i++) {
+ pages.push(i);
+ }
+ pages.push('...');
+ pages.push(totalPages);
+ } else if (currentPage >= totalPages - 2) {
+ pages.push(1);
+ pages.push('...');
+ for (let i = totalPages - 3; i <= totalPages; i++) {
+ pages.push(i);
+ }
+ } else {
+ pages.push(1);
+ pages.push('...');
+ pages.push(currentPage - 1);
+ pages.push(currentPage);
+ pages.push(currentPage + 1);
+ pages.push('...');
+ pages.push(totalPages);
+ }
+ }
+
+ return pages;
+ };
+
+ return (
+
+
+
+ {/* Property Cards Grid */}
+
+ {currentProperties.map((property) => (
+
+ {/* Image Container */}
+
+
+
+
+ {/* Property Details */}
+
+ {/* Location */}
+
+
+ {property.city}
+
+
+
+
+
+
+ {property.rating}
+
+
+
+
+ {/* Title */}
+
+ {property.title}
+
+
+ {/* Price */}
+
+ ₨{property.price.toLocaleString()}
+ night
+
+
+
+ ))}
+
+
+ {/* Pagination Controls */}
+
+ {/* Page Numbers */}
+
+ {/* Previous Button */}
+
+ Previous
+
+
+ {/* Page Numbers */}
+ {getPageNumbers().map((page, index) => (
+ typeof page === 'number' ? (
+ goToPage(page)}
+ className={`${figtree.className} w-10 h-10 border-2 border-black transition-all duration-300 ${
+ currentPage === page
+ ? 'bg-[#E7FE78] text-black font-bold'
+ : 'bg-white text-black hover:bg-[#E7FE78]'
+ }`}
+ >
+ {page}
+
+ ) : (
+
+ {page}
+
+ )
+ ))}
+
+ {/* Next Button */}
+
+ Next
+
+
+
+ {/* Page Info */}
+
+ Page {currentPage} of {totalPages}
+
+
+
+
+ )
+}
+
+export default Results;
diff --git a/src/components/search-results/search.tsx b/src/components/search-results/search.tsx
new file mode 100644
index 0000000..ecf2db1
--- /dev/null
+++ b/src/components/search-results/search.tsx
@@ -0,0 +1,115 @@
+import localFont from "next/font/local";
+import { CubeIcon } from "@phosphor-icons/react";
+import { SearchIcon } from "lucide-react";
+
+const figtree = localFont({
+ src: [
+ {
+ path: '../../../public/Fonts/figtree/figtree.ttf',
+ },
+ ],
+})
+
+const MapPinIcon = ({ className }: { className: string }) => {
+ return (
+
+ )
+}
+
+const ChevronDownIcon = ({ className }: { className: string }) => {
+ return (
+
+ )
+}
+
+const CalendarIcon = ({ className }: { className: string }) => {
+ return (
+
+ )
+}
+
+const UserIcon = ({ className }: { className: string }) => {
+ return (
+
+ )
+}
+
+function SearchBy() {
+ return (
+
+
+
+
Places to stay
+
+
+ {/* Location */}
+
+
+ {/* Check in/out */}
+
+
+
+
Fri, Nov 14
+
-
+
Sat, Nov 15
+
+
+
+
+
+
+ {/* Guests */}
+
+
+
+
2 Adults
+
.
+
1 Child
+
+
+
+
+
+
+ {/* Search */}
+
+
+ Search
+
+
+
+
+ {/* Filters */}
+
+
+
Filters:
+
+
+ Standard
+
+
+
+
+ {/* Sort by */}
+
+
Sort by:
+
+ Revelance
+
+
+
+
+
+
+ )
+}
+
+export default SearchBy;
\ No newline at end of file