landing page + results + features

This commit is contained in:
2025-11-20 19:54:14 +00:00
parent 68d82aec3b
commit b7405d787c
32 changed files with 1697 additions and 145 deletions

9
.claude/settings.json Normal file
View File

@@ -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"
}
}

View File

@@ -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;

46
package-lock.json generated
View File

@@ -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"
},

View File

@@ -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"
}
}

Binary file not shown.

View File

@@ -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}

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" viewBox="0 0 138 172.5" enable-background="new 0 0 138 138" xml:space="preserve"><g><path d="M133,112.2753h-4.6799l-1.5-4.0903c0-0.1-0.0094-82.2253-0.04-76.9697l-3.6901-15.75c-0.11-0.4502-0.51-0.77-0.98-0.77 c-0.4601,0-0.86,0.3198-0.97,0.77c-3.1888,13.5886,0.3204-1.3831-3.7101,15.8198c-0.0484,0.2907-0.0095-3.7786-0.02,76.8999 l-0.4199,1.1401c-19.207-45.2834-10.0206-23.6252-12.61-29.73l-0.0033-0.0078c0.0036-49.7577,0.02-46.0838-0.0267-46.332 l-3.71-15.5703c-0.1-0.4497-0.51-0.77-0.9701-0.77c-0.46,0-0.8699,0.3203-0.97,0.77c-4.0472,16.9965-3.7251,15.5509-3.7373,15.8252 v39.7764C79.3386,64.0953,85.305,67.6052,69.7,58.4252l-0.001-0.0005V49.411c0-0.4678-0.3237-0.8721-0.7793-0.9756 c-0.4541-0.1016-0.9219,0.123-1.123,0.5449c-1.2627,2.6445-2.127,2.8501-2.3618,2.8501s-1.0991-0.2056-2.3613-2.8501 c-0.2007-0.4219-0.6665-0.647-1.123-0.5449c-0.4556,0.1035-0.7793,0.5078-0.7793,0.9756v9.333l-0.0012,0.001L39.7732,72.7533 c-0.0148-40.7379,0.0281-39.1466-0.0232-39.4585c0.1-0.0976-1.7207-7.2676-3.71-15.6099c-0.1101-0.4497-0.51-0.77-0.97-0.77 c-0.4701,0-0.8701,0.3203-0.9801,0.77c-3.866,16.3034-3.73,15.5853-3.73,15.8101c-0.0011,61.631-0.0008,42.5602-0.0009,46.3823 c-0.1349,0.3887-9.9724,28.7253-10.1191,29.1479c-0.0373-0.1045-0.3411-0.9546-0.3037-0.8501 c-0.0067-80.8159,0.0304-76.7123-0.0264-76.9102c-5.7261-24.3859-2.89-12.3077-3.71-15.7998c-0.1-0.4502-0.51-0.77-0.97-0.77 s-0.87,0.3198-0.97,0.77c-0.82,3.4924,2.0161-8.5861-3.71,15.7998c-0.0572,0.1994-0.0196-3.9033-0.0273,76.9126l-0.0027,0.0073 l-1.49,4.0903H5c-0.55,0-1,0.4497-1,1v9.0298c0,0.5503,0.45,1,1,1h128c0.55,0,1-0.4497,1-1v-9.0298 C134,112.725,133.55,112.2753,133,112.2753z M124.8201,107.3651h-5.4102V32.4852h5.4102V107.3651z M119.11,109.3651 c0.1485,0,5.9646,0,5.7101,0h0.2999l1.0699,2.9102c-0.2018,0-8.4729,0-7.9399,0l-0.11-0.2603L119.11,109.3651z M98.9905,112.1351 v-2.7695l2.6995,2.7695H98.9905z M96.9905,112.1449c-0.1515,0-7.9465,0-7.4277,0V99.6981 c1.6695,1.7115-4.1044-4.2076,7.5527,7.7427C97.0424,107.5799,97.0402,107.7732,96.9905,112.1449z M87.5627,112.1449h-8.8623 V88.5555c1.5918,1.633-4.2808-4.3918,8.863,9.0928C87.5635,97.6498,87.5629,108.9408,87.5627,112.1449z M76.7004,112.1449h-9.6821 V76.5731l0.0017,0.002L76.7,86.5052l0.0005,0.0005V112.1449z M65.0183,75.702v36.4429h-8.4526 c-0.1971-27.4216,0.4232-26.5403-0.47-27.1147c5.2586-5.5533,3.7372-3.9467,8.9343-9.4351l0.0127-0.0132 C65.0375,75.6229,65.0183,75.6595,65.0183,75.702z M54.5657,112.1449h-8.4993c0.0976-0.3929,0.0172,0.9472,0.0471-15.835 c0-0.2056-0.0769-0.3857-0.1833-0.5444c5.1095-5.3939,3.5826-3.782,8.6355-9.1162V112.1449z M44.1606,112.1449h-6.655 c-0.0921-6.5311,0.2102-6.6796-0.248-7.2168c0.1292-0.1366,6.9493-7.3456,6.8524-7.2432l0.0035-0.0039 C44.1437,113.1675,44.0604,111.7414,44.1606,112.1449z M35.5056,112.1449h-5.0857l5.0857-5.3647V112.1449z M122.11,20.0653 l2.4501,10.4199h-4.8901L122.11,20.0653z M102.3767,34.5052v43.148l-5.4141-3.1865V34.5052H102.3767z M99.6699,22.2352 c0.0235,0.0989-0.2807-1.181,2.4401,10.2646h-4.88C99.9504,21.0553,99.6464,22.3341,99.6699,22.2352z M102.37,79.975 l9.9366,23.4424L71.4983,61.8041L71.5,61.805L102.37,79.975z M65.4348,53.8304c0.7944,0,1.5454-0.355,2.2642-1.0767v4.4907 l-1.609-0.9497c-0.0199-0.0098-0.0499-0.0298-0.08-0.0396c-0.0195-0.0112-0.0414-0.0156-0.0615-0.0254 c-0.0439-0.0234-0.0895-0.041-0.137-0.0566c-0.1036-0.0347-0.2087-0.0581-0.3115-0.0581c-0.01,0-0.01,0-0.02,0s-0.01,0-0.02,0 c-0.0601,0-0.13,0.0098-0.1899,0.0298c-0.0601,0.0103-0.13,0.04-0.1901,0.0601c-0.0399,0.02-0.09,0.04-0.13,0.0703l-1.7788,1.1587 v-4.6797C63.8894,53.4754,64.6404,53.8304,65.4348,53.8304z M32.3591,34.5052h5.4141v39.5581 c-2.5336,1.6577-5.5383,3.6238-5.4141,3.5425V34.5052z M35.0701,22.2352c0.0235,0.0989-0.2807-1.181,2.4399,10.2646h-4.89 C35.3517,21.0553,35.0465,22.3341,35.0701,22.2352z M32.46,79.9252l27.12-17.7402l0.0052-0.0034 c-20.5908,22.8359-29.9177,33.2358-34.1536,38.0088C25.4677,100.0884,32.0855,81.0443,32.46,79.9252z M23.7064,105.1551 c1.6558-2,27.5276-30.7285,41.8241-46.5801l48.9121,49.8765l1.5374,3.6333l-0.02,0.0601h-11.47l-38.25-39.23 c-0.1899-0.1997-0.49-0.3096-0.72-0.2998c-0.27,0-0.53,0.1099-0.72,0.3101l-37.1201,39.2197H21.38l-0.05-0.1396L23.7064,105.1551z M12.5227,32.4901h5.4136v74.875h-5.4136V32.4901z M15.23,20.0653l2.4399,10.4199H12.78L15.23,20.0653z M12.22,109.3651h6.02 l0.97,2.6602l-0.09,0.25h-7.9601L12.22,109.3651z M132,121.305H6v-7.0298h3.38c0.2307,0.0924,11.4691,0.0924,11.7,0 c11.9348,0,27.2454,0,34.1884,0c0.2532,0.0803,0.3415,0.0803,0.5947,0c40.7713,0,70.813,0.0238,76.137,0V121.305z"/></g></svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="-5.0 -10.0 110.0 135.0">
<path d="m26.082 68.035-0.67578-1.4336-2.1875-2.0234h-4.1758v-1.6016l3-1.6016v-2.9453l3.0039-2.2773 3.3594 1.0977 3.3594 2.3594-2.3477-4.2969-3.1992-1.7695v-2.2773l-1.1719-2.1055 0.63281-4.5 0.011718-0.011718 5.6367 4.9648 0.058594-0.0625 0.51172 2.7266 3.3945 1.4336 5.8711 5.4766 1.7188 4.9141 2.4805 0.64453 0.87109-2.2148 3.3906 1.2344 2.0586 4.2695h2.5391l-1.2461-2.3633-1.6953-7.1133 1.9141-7.7109-1.9141-3.1133 2.6094-1.3828 4.8711 4.1602 1.9141 3.2539-0.69531-4.6016-5.0469-7.7539 0.4375-3.3711h2l3.3047 3.2578-0.86719-3.2578-2.6992-2.8047-1.3047-4.7188 0.17187-3.4844 0.26563-1.2852 14.078 17.551-0.375 4.4297 2.2812 1.7695 2.1562 7.7148v7.1172l6.5078 3.707h2.3672v-2.0273l-2.0898-3.7031-2.3477-2.5273-2.2188-4.8867 2.4766-1.5156 1.9609 2.4844-0.52344-4.8438-1.4375-2.0234-0.046875-1.3711 15.391 20.414h2.9141l-18.59-24.656-7.1094-2.1836-15.82-19.73-9.4023 11.309-3.7969 1.2266-11.414 12.242-5.8438-5.1484-9.3945 13.473-0.55859 0.64453-2.9336 1.0547-9.8086 11.77z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="-5.0 -10.0 110.0 135.0">
<path d="m91.105 89.289h-0.74219v-3.6523c0-1.4844-1.1953-2.6836-2.6836-2.6836h-2.1367l-1.9062-17.605c0-0.015625 0.015625-0.03125 0.015625-0.046875 0-0.046875-0.015625-0.074219-0.03125-0.12109l-3.3477-31.074c-0.15234-1.3633-1.2891-2.3945-2.668-2.3945h-6.668v-3.7578h2.2422c0.41016 0 0.72656-0.33203 0.72656-0.72656 0-0.41016-0.33203-0.72656-0.72656-0.72656h-2.2422c-0.16797-11.258-9.1836-20.426-20.395-20.805l0.003906-2.043c0-0.41016-0.33203-0.72656-0.72656-0.72656-0.41016 0-0.72656 0.33203-0.72656 0.72656v2.0469c-11.215 0.375-20.246 9.5273-20.41 20.801h-2.2422c-0.41016 0-0.72656 0.33203-0.72656 0.72656 0 0.41016 0.33203 0.72656 0.72656 0.72656h2.2422v3.7578h-6.2891c-1.3789 0-2.5156 1.0312-2.668 2.3945l-5.2578 48.848h-2.1523c-1.4844 0-2.6836 1.1953-2.6836 2.6836v3.6523h-0.73828c-1.4844 0-2.6836 1.1953-2.6836 2.6836v4.3789c0 0.41016 0.33203 0.72656 0.72656 0.72656h86.105c0.41016 0 0.72656-0.33203 0.72656-0.72656l0.003907-4.3828c0.015624-1.4844-1.1992-2.6797-2.668-2.6797zm-25.258-6.3359c-0.10547-2.5469-0.37891-5.1367-0.81641-7.7422h4.4531l-0.015625 7.7422zm-15.816 0h-0.03125-0.03125-14.727c0.10547-2.668 0.41016-5.4688 0.92578-8.3477 0.5625-3.2109 1.3164-6.2578 2.2422-9.0742 1.1211-3.4844 2.5-6.6055 3.9844-9.0312 0.16797-0.27344 0.34766-0.53125 0.51562-0.78906l0.089844-0.13672c1.5312-2.2578 3.9531-4.9531 6.832-4.9531 3.0469 0 5.5898 3 7.1953 5.5312l0.015625 0.015625v0.015625c0.074219 0.12109 0.15234 0.22656 0.22656 0.34766 1.4688 2.4102 2.8477 5.5312 3.9844 9.0312 0.92578 2.8633 1.6836 5.9102 2.2266 9.0742 0.5 2.8164 0.80469 5.6211 0.92578 8.3477h-14.375zm-33.105-9.1953 0.83203-7.7109h8.6367v7.7109zm1.8164-16.91h8.3477 0.015625 0.015625 5.1055l-0.015624 7.7109h-14.316zm0.98437-9.1641h6.6523v7.7109h-7.4844zm21.926 0v7.2578c-0.089844 0.15234-0.19531 0.30469-0.28906 0.45312h-8.2266c-0.046875-0.015625-0.089844-0.03125-0.15234-0.03125s-0.10547 0.015625-0.15234 0.03125h-4.9688v-7.7109zm1.0586-9.5625h-5.3789v-3.4688c0-1.4844 1.2109-2.6953 2.6953-2.6953s2.6953 1.2109 2.6953 2.6953l0.003906 3.4688zm0.72656 1.4688h5.832v6.6211h-9.9844v-6.6211zm19.23-1.4688h-5.3789v-3.4688c0-1.4844 1.2109-2.6953 2.6953-2.6953s2.6953 1.2109 2.6953 2.6953l0.003906 3.4688zm-6.1055 1.4688h4.168v6.6211h-9.9844v-6.6211zm23.711 8.0938 0.83203 7.7109h-7.4844v-7.7109zm2.8008 26.074h-9.4531v-7.7109h8.6367zm-18.285 0c-0.48437-2.668-1.1055-5.2578-1.8633-7.7109h3.9258c0.074219 0.015625 0.13672 0.046875 0.21094 0.046875s0.15234-0.015625 0.21094-0.046875h4.8789v7.7109zm-27.605-9.1836h-3.4844l0.015625-7.7109h6.8047c-1.2461 2.1992-2.3672 4.7891-3.3359 7.7109zm5.9219-16.891h13.789v5.7891c-2.2266-2.8164-4.6523-4.3164-7.0898-4.3164-2.332 0-4.5742 1.3047-6.7109 3.8477l-0.003906-5.3203zm19.348 16.891c-0.96875-2.9258-2.0898-5.5156-3.3047-7.7109h7.1953l-0.015625 7.7109zm5.3359 0 0.015626-7.7109h5.0625 0.015624 0.015626 8.3477l0.83203 7.7109zm4.3633-9.1797h-13.789v-7.7109h13.789zm-19.457-17.273h-5.3789v-3.4688c0-1.4844 1.2109-2.6953 2.6953-2.6953s2.6953 1.2109 2.6953 2.6953l0.003907 3.4688zm-24.848 27.91h8.8633c-0.74219 2.4258-1.3789 5.0156-1.8789 7.7109h-6.9844zm6.7266 9.1797c-0.42578 2.668-0.69531 5.2578-0.80469 7.7422h-3.2422l0.015625-7.7422zm36.379 0h1.8633c0.03125 0 0.046875 0.015624 0.0625 0.015624 0.03125 0 0.046875-0.015624 0.0625-0.015624h10.289l0.83203 7.7422h-13.121zm7.8633-40.938 1.2891 11.938h-17.91v-6.6211h2.6211c1.1836 0 2.2422-0.78906 2.5742-1.9258l1.0625-3.6055c0.15234-0.51562 0.63672-0.87891 1.168-0.87891h7.9844c0.62109 0.003906 1.1523 0.47266 1.2109 1.0938zm-29-27.137c10.742 0 19.484 8.6523 19.652 19.363h-39.316c0.17969-10.695 8.9219-19.363 19.664-19.363zm-19.68 20.816h39.348v3.7734c-1.1211 0.0625-2.1211 0.81641-2.4375 1.9102l-1.0625 3.6055c-0.15234 0.51562-0.63672 0.87891-1.168 0.87891h-0.68359v-3.4688c0-2.2891-1.8633-4.1523-4.1523-4.1523-2.2891 0-4.1523 1.8633-4.1523 4.1523v3.4688h-1.6836v-3.4688c0-2.2891-1.8633-4.1523-4.1523-4.1523-2.2891 0-4.1523 1.8633-4.1523 4.1523v3.4688h-1.6836v-3.4688c0-2.2891-1.8633-4.1523-4.1523-4.1523-2.2891 0-4.1523 1.8633-4.1523 4.1523v3.4688h-0.68359c-0.53125 0-1.0156-0.36328-1.168-0.87891l-1.0625-3.6055c-0.33203-1.1367-1.3945-1.9258-2.5742-1.9258h-0.24219zm-8.9531 6.3203c0.0625-0.62109 0.58984-1.0898 1.2109-1.0898h7.9844c0.53125 0 1.0156 0.36328 1.168 0.87891l1.0625 3.6055c0.33203 1.1367 1.3945 1.9258 2.5742 1.9258h2.6523v6.6211l-17.941-0.003906zm-4.4102 40.938h10.289c0.03125 0 0.046875 0.015624 0.0625 0.015624 0.03125 0 0.046875-0.015624 0.0625-0.015624h1.9102l-0.015625 7.7422h-13.137zm-5.668 10.426c0-0.66797 0.54688-1.2109 1.2109-1.2109h37.574c0.03125 0 0.0625 0.015625 0.10547 0.015625 0.03125 0 0.0625-0.015625 0.089844-0.015625h19.789c0.10547 0.046875 0.21094 0.089844 0.33203 0.089844 0.12109 0 0.22656-0.03125 0.33203-0.089844h17.137c0.66797 0 1.2109 0.54688 1.2109 1.2109v3.6523h-77.781zm81.211 9.9844h-84.633v-3.6523c0-0.66797 0.54688-1.2109 1.2109-1.2109h82.195c0.66797 0 1.2109 0.54688 1.2109 1.2109l0.003907 3.6523z"/>
</svg>

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" viewBox="0 0 138 172.5" enable-background="new 0 0 138 138" xml:space="preserve"><g><path d="M102.5823,132.1334c-0.0913-0.0522-9.1206-5.3164-9.4053-11.2856c-0.1172-2.4531,1.333-4.7695,4.3105-6.8838 c0.436-0.3096,0.5513-0.9072,0.2617-1.3569c-2-3.105-3.6826-4.2612-10.0176-1.1621c-0.6439-0.6006-1.3651-1.0811-2.1252-1.438 c-6.2313-19.8076-7.3215-55.6421-7.4576-61.3789c0.9941-0.4272,1.6927-1.4146,1.6927-2.5635c0-1.5322-1.2422-2.7778-2.772-2.7871 V32.9918c1.5329-0.0303,2.772-1.2813,2.772-2.8218c0-1.5586-1.2681-2.8271-2.8267-2.8271h-1.9785v-8.6494 c0-1.6426-0.8815-3.0728-2.1884-3.8755c-0.0842-2.1772-1.0211-4.2583-2.6168-5.7505V5.0001c0-0.5522-0.4478-1-1-1s-1,0.4478-1,1 v3.6455l-0.6177,0.7163c-1.3003,1.5073-2.0161,3.4341-2.0161,5.4253v0.0396c-1.298,0.8047-2.1719,2.231-2.1719,3.8667v8.6494 H61.447c-1.5586,0-2.8267,1.2686-2.8267,2.8271c0,1.5405,1.2391,2.7915,2.772,2.8218v10.2856 c-1.5298,0.0093-2.772,1.2549-2.772,2.7871c0,1.1582,0.7103,2.1528,1.7177,2.5737c0.4449,32.4902-4.4525,55.1226-6.0928,61.7407 c-0.3978,0.1738-0.795,0.3755-1.1894,0.6255c-2.9961-1.6753-6.2334-3.1528-12.4502,0.3013 c-0.3018,0.168-0.4951,0.4795-0.5127,0.8242c-0.0171,0.3447,0.145,0.6743,0.4282,0.8716c0.062,0.0435,6.2031,4.3789,5.666,9.4507 c-0.3794,3.582-3.9648,6.8203-10.6572,9.6255c-0.439,0.1841-0.6875,0.6528-0.5938,1.1196 c0.0942,0.4668,0.5044,0.8027,0.9805,0.8027c15.9972,0,53.7776,0,66.1665,0c0.4526,0,0.8491-0.3047,0.9663-0.7422 C103.1662,132.8204,102.9743,132.3595,102.5823,132.1334z M86.3658,112.9112c-0.7884,2.2769-2.8328,10.1733,2.6907,19.0889h-7.0731 c-5.6926-7.5669-3.2593-17.7671-2.9521-18.9399C80.9914,110.6139,84.1491,110.8398,86.3658,112.9112z M52.5935,132.0001 c4.3926-8.7612,2.0753-17.0625,1.3528-19.1802c2.9775-2.0112,5.1974-0.7876,6.5787,0.6987 c0.4417,1.2656,3.158,9.8564-0.6061,18.4814H52.5935z M60.614,84.8448h4.974c-0.3436,5.3413-0.8484,10.5688-1.5815,15.1675h-5.5643 C59.1786,95.8526,59.9502,90.7618,60.614,84.8448z M62.3445,48.8536h3.757c0.0818,2.9834,0.2192,9.542,0.1357,17.4326h-4.1718 C62.3114,60.8565,62.4242,55.0323,62.3445,48.8536z M81.0523,100.0123h-5.0203c-0.5893-4.6011-1.0296-9.8286-1.3561-15.1675h4.0002 C79.3035,89.9918,80.0828,95.1686,81.0523,100.0123z M74.5583,82.8448c-0.2772-4.9648-0.4622-9.959-0.5847-14.5586h3.1231 c0.3271,4.5405,0.7634,9.5078,1.3423,14.5586H74.5583z M68.1061,48.8536h3.6364c-0.0141,2.5132-0.0244,9.1958,0.1644,17.4326 h-3.6454C68.3409,58.4381,68.1954,51.9161,68.1061,48.8536z M71.9559,68.2862c0.1205,4.5942,0.3054,9.5811,0.5845,14.5586h-4.8056 c0.2841-4.9663,0.4332-9.9487,0.5013-14.5586H71.9559z M73.924,66.2862c-0.1939-8.2773-0.1904-14.9897-0.1801-17.4326h2.4077 c0.0552,2.4648,0.2457,9.082,0.806,17.4326H73.924z M61.9656,68.2862h4.2455c-0.0699,4.6182-0.2202,9.6035-0.5013,14.5586h-4.8791 C61.2945,78.4083,61.6911,73.5431,61.9656,68.2862z M67.6119,84.8448h5.0457c0.3262,5.3076,0.7659,10.5298,1.3575,15.1675h-7.9908 C66.7585,95.3658,67.2677,90.1529,67.6119,84.8448z M74.2857,102.0123c0.3973,2.7778,0.8553,5.3003,1.3846,7.4399 c-3.3447-1.7287-8.3292-1.6817-11.7422-0.0688c0.6853-2.1392,1.2668-4.6313,1.7589-7.3711H74.2857z M62.4988,113.1031 c1.1608-1.9072,4.3375-3.1011,7.9526-2.9224c5.6341,0.2802,6.3419,3.1103,6.4419,3.2065 c-0.6385,2.8945-1.9484,11.4224,2.6498,18.6128H62.0874C65.5235,123.3316,63.1834,115.1251,62.4988,113.1031z M78.191,111.0572 c-0.7465-2.3477-1.3692-5.4536-1.8871-9.0449h5.1628c0.557,2.583,1.1742,5.043,1.8524,7.3359 C81.3166,109.1153,79.5797,109.7582,78.191,111.0572z M75.0696,32.9972v10.2783H63.3923V32.9972H75.0696z M67.6311,14.1339 c0.1304-1.248,0.6309-2.4346,1.4429-3.4019c0.9072,0.9316,1.5039,2.1265,1.71,3.4019h-0.3047c-0.0009,0-0.0016,0-0.0024,0h-2.4917 c-0.0009,0-0.0016,0-0.0024,0H67.6311z M65.4255,18.6935c0-1.4102,1.1472-2.5581,2.5571-2.5596h2.4966 c1.4099,0.0015,2.5571,1.1494,2.5571,2.5596v8.6494h-7.6108V18.6935z M60.6203,30.17c0-0.4561,0.3706-0.8271,0.8267-0.8271h15.5679 c0.4561,0,0.8267,0.3711,0.8267,0.8271s-0.3706,0.8271-0.8267,0.8271H61.447C60.9909,30.9972,60.6203,30.6261,60.6203,30.17z M61.4089,45.2755h15.644c0.4351,0,0.7886,0.354,0.7886,0.7891s-0.3535,0.7891-0.7886,0.7891h-15.644 c-0.4351,0-0.7886-0.354-0.7886-0.7891S60.9739,45.2755,61.4089,45.2755z M58.0793,102.0123h5.5865 c-0.6774,3.7168-1.5262,6.917-2.5817,9.3052c-1.4126-1.1455-3.0042-1.6509-4.6436-1.5088 C56.8775,107.9684,57.4554,105.3463,58.0793,102.0123z M42.9294,112.3595c4.1964-1.9663,6.428-1.106,8.9138,0.2612 c-0.0367,0.5537,3.8446,9.7322-1.5269,19.3794H40.299C50.3531,126.4029,50.42,118.8185,42.9294,112.3595z M91.4441,132.0001 c-6.1392-8.938-3.7549-16.9043-3.1267-18.6108c4.9608-2.4834,6.1065-2.0522,7.2341-0.4751 c-7.637,6.0091-4.4846,13.2773,3.2573,19.0859H91.4441z"/></g></svg>

After

Width:  |  Height:  |  Size: 4.7 KiB

BIN
public/arrow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
public/badge-ticket.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

BIN
public/best-prices.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 272 KiB

BIN
public/hotel-banner.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

BIN
public/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

BIN
public/stars.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

View File

@@ -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;
}

View File

@@ -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 (
<html lang="en">
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
>
<body className="antialiased">
{children}
</body>
</html>

View File

@@ -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 (
<div className="font-sans grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20">
<main className="flex flex-col gap-[32px] row-start-2 items-center sm:items-start">
<Image
className="dark:invert"
src="/next.svg"
alt="Next.js logo"
width={180}
height={38}
priority
/>
<ol className="font-mono list-inside list-decimal text-sm/6 text-center sm:text-left">
<li className="mb-2 tracking-[-.01em]">
Get started by editing{" "}
<code className="bg-black/[.05] dark:bg-white/[.06] font-mono font-semibold px-1 py-0.5 rounded">
src/app/page.tsx
</code>
.
</li>
<li className="tracking-[-.01em]">
Save and see your changes instantly.
</li>
</ol>
<div className="flex gap-4 items-center flex-col sm:flex-row">
<a
className="rounded-full border border-solid border-transparent transition-colors flex items-center justify-center bg-foreground text-background gap-2 hover:bg-[#383838] dark:hover:bg-[#ccc] font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 sm:w-auto"
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
className="dark:invert"
src="/vercel.svg"
alt="Vercel logomark"
width={20}
height={20}
/>
Deploy now
</a>
<a
className="rounded-full border border-solid border-black/[.08] dark:border-white/[.145] transition-colors flex items-center justify-center hover:bg-[#f2f2f2] dark:hover:bg-[#1a1a1a] hover:border-transparent font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 w-full sm:w-auto md:w-[158px]"
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
Read our docs
</a>
</div>
</main>
<footer className="row-start-3 flex gap-[24px] flex-wrap items-center justify-center">
<a
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
aria-hidden
src="/file.svg"
alt="File icon"
width={16}
height={16}
/>
Learn
</a>
<a
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
aria-hidden
src="/window.svg"
alt="Window icon"
width={16}
height={16}
/>
Examples
</a>
<a
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
href="https://nextjs.org?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
aria-hidden
src="/globe.svg"
alt="Globe icon"
width={16}
height={16}
/>
Go to nextjs.org
</a>
</footer>
</div>
<>
<div>
<Navigation />
<Features />
<Footer />
</div>
</>
);
}

View File

@@ -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<HTMLDivElement>(null);
useGSAP(() => {
gsap.fromTo(navbarRef.current, {
y: -40,
opacity: 0,
}, {
y: 10,
opacity: 1,
duration: 1,
ease: "elastic.out(1,0.3)",
});
});
return (
<div ref={navbarRef} className="w-full border border-black border-4 h-18 rounded-lg my-auto mb-8">
<div className=" w-[98%] mx-auto">
<div className=" flex flex-row items-center justify-between">
<div className="flex items-center gap-4 justify-evenly">
<Image src={logo} alt="logo" width={200} height={200} className="hover:scale-105 transition-all duration-300 cursor-pointer" />
<h2 className={`${figtree.className} text-lg font-light italic hover:underline cursor-pointer`}>Your Reservation</h2>
<h2 className={`${figtree.className} text-lg font-light italic hover:underline cursor-pointer`}>Book Now</h2>
</div>
<div className="flex items-center gap-8 justify-around">
<div className="border border-black border-2 w-0 h-16"></div>
<button className={`${figtree.className} bg-[#E7FE78] text-black px-4 py-2 rounded-lg shadow-[2px_2px_0px_rgba(0,0,0,1)] font-light italic border-2 border-black hover:scale-105 transition-all duration-300 cursor-pointer hover:shadow-[10px_10px_0px_rgba(0,0,0,1]`}>
List Your Property
</button>
<UserSquare className={`w-14 h-14 hover:scale-110 transition-all duration-300 cursor-pointer`} />
</div>
</div>
</div>
</div>
)
}
export default Navigation;

View File

@@ -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 (
<div className={`w-full bg-white ${figtree.className}`}>
{/* Header Section */}
<div className="max-w-[95%] mx-auto pt-8 pb-6">
<div className="flex flex-col gap-4">
<h1 className="text-4xl font-medium uppercase tracking-tight">{property.title}</h1>
<div className="flex flex-row items-center justify-between w-full">
<div className="flex items-center gap-4 text-sm md:text-base">
<span className="flex items-center gap-1 font-medium underline cursor-pointer hover:text-gray-600">
<Star className="w-4 h-4 fill-black" />
{property.rating} · {property.reviewCount} reviews
</span>
<span className="hidden md:inline text-gray-400">|</span>
<span className="flex items-center gap-1 font-medium underline cursor-pointer hover:text-gray-600">
<MapPin className="w-4 h-4" />
{property.location}
</span>
</div>
<div className="flex items-center gap-4">
<button className="flex items-center gap-2 px-4 py-2 text-sm font-medium border-2 border-transparent hover:bg-gray-100 transition-colors rounded-full md:rounded-none md:border-black md:hover:bg-[#E7FE78]">
<Share className="w-4 h-4" />
<span className="hidden md:inline">Share</span>
</button>
<button className="flex items-center gap-2 px-4 py-2 text-sm font-medium border-2 border-transparent hover:bg-gray-100 transition-colors rounded-full md:rounded-none md:border-black md:hover:bg-[#E7FE78]">
<Heart className="w-4 h-4" />
<span className="hidden md:inline">Save</span>
</button>
</div>
</div>
</div>
</div>
{/* Image Grid */}
<div className="max-w-[95%] mx-auto mb-12">
<div className="grid grid-cols-1 md:grid-cols-4 gap-2 h-[400px] md:h-[500px] rounded-xl overflow-hidden md:rounded-none">
<div className="md:col-span-2 h-full relative border-2 border-black group overflow-hidden">
<Image
src={property.images[0]}
alt="Main view"
fill
className="object-cover group-hover:scale-105 transition-transform duration-500"
/>
</div>
<div className="hidden md:grid grid-cols-1 gap-2 h-full">
<div className="relative h-full border-2 border-black group overflow-hidden">
<Image
src={property.images[1]}
alt="View 2"
fill
className="object-cover group-hover:scale-105 transition-transform duration-500"
/>
</div>
<div className="relative h-full border-2 border-black group overflow-hidden">
<Image
src={property.images[2]}
alt="View 3"
fill
className="object-cover group-hover:scale-105 transition-transform duration-500"
/>
</div>
</div>
<div className="hidden md:grid grid-cols-1 gap-2 h-full">
<div className="relative h-full border-2 border-black group overflow-hidden">
<Image
src={property.images[3]}
alt="View 4"
fill
className="object-cover group-hover:scale-105 transition-transform duration-500"
/>
</div>
<div className="relative h-full border-2 border-black group overflow-hidden">
<Image
src={property.images[4]}
alt="View 5"
fill
className="object-cover group-hover:scale-105 transition-transform duration-500"
/>
<button className="absolute bottom-4 right-4 bg-white border-2 border-black px-4 py-2 text-sm font-medium hover:bg-[#E7FE78] transition-colors">
Show all photos
</button>
</div>
</div>
</div>
</div>
{/* Main Content */}
<div className="max-w-[95%] mx-auto grid grid-cols-1 lg:grid-cols-3 gap-12 mb-20">
{/* Left Column */}
<div className="lg:col-span-2 space-y-10">
{/* Host Info & Stats */}
<div className="flex items-center justify-between pb-8 border-b-2 border-gray-100">
<div>
<h2 className="text-2xl font-medium mb-1">Hosted by {property.host.name}</h2>
<p className="text-gray-600">
{property.guests} guests · {property.bedrooms} bedrooms · {property.beds} beds · {property.baths} baths
</p>
</div>
<div className="relative w-14 h-14 md:w-16 md:h-16">
<Image
src={property.host.image}
alt={property.host.name}
fill
className="rounded-full object-cover border-2 border-black"
/>
</div>
</div>
{/* Highlights */}
<div className="space-y-6 pb-8 border-b-2 border-gray-100">
<div className="flex gap-4 items-start">
<div className="p-2 border-2 border-black bg-[#E7FE78]">
<Star className="w-6 h-6" />
</div>
<div>
<h3 className="font-medium text-lg">Top rated host</h3>
<p className="text-gray-600 text-sm">John has received 5-star ratings from 95% of recent guests.</p>
</div>
</div>
<div className="flex gap-4 items-start">
<div className="p-2 border-2 border-black bg-white">
<MapPin className="w-6 h-6" />
</div>
<div>
<h3 className="font-medium text-lg">Great location</h3>
<p className="text-gray-600 text-sm">100% of recent guests gave the location a 5-star rating.</p>
</div>
</div>
</div>
{/* Description */}
<div className="pb-8 border-b-2 border-gray-100">
<h3 className="text-2xl font-medium mb-4">About this place</h3>
<p className="text-gray-700 leading-relaxed text-lg font-light">
{property.description}
</p>
</div>
{/* Amenities */}
<div className="pb-8 border-b-2 border-gray-100">
<h3 className="text-2xl font-medium mb-6">What this place offers</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
{property.amenities.slice(0, 6).map((item, idx) => (
<div key={idx} className="flex items-center gap-4 p-4 border-2 border-gray-100 hover:border-black transition-colors">
<item.icon className="w-6 h-6" />
<span className="text-lg font-light">{item.label}</span>
</div>
))}
</div>
<button
onClick={() => 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
</button>
</div>
</div>
{/* Right Column - Sticky Booking Card */}
<div className="relative">
<div className="sticky top-24 border-2 border-black p-6 bg-white shadow-[8px_8px_0px_0px_rgba(0,0,0,1)]">
<div className="flex items-end justify-between mb-6">
<div>
<span className="text-2xl font-bold">{property.price.toLocaleString()}</span>
<span className="text-gray-600"> / night</span>
</div>
<div className="flex items-center gap-1 text-sm font-medium">
<Star className="w-4 h-4 fill-black" />
{property.rating} · <span className="text-gray-500 underline">{property.reviewCount} reviews</span>
</div>
</div>
<div className="border-2 border-black mb-4">
<div className="grid grid-cols-2 border-b-2 border-black">
<div className="p-3 border-r-2 border-black">
<label className="block text-xs font-bold uppercase tracking-wider mb-1">Check-in</label>
<input type="date" className="w-full outline-none text-sm bg-transparent" />
</div>
<div className="p-3">
<label className="block text-xs font-bold uppercase tracking-wider mb-1">Check-out</label>
<input type="date" className="w-full outline-none text-sm bg-transparent" />
</div>
</div>
<div className="p-3">
<label className="block text-xs font-bold uppercase tracking-wider mb-1">Guests</label>
<select className="w-full outline-none text-sm bg-transparent">
<option>1 guest</option>
<option>2 guests</option>
<option>3 guests</option>
</select>
</div>
</div>
<button className="w-full py-4 bg-black text-white font-medium text-lg hover:bg-[#E7FE78] hover:text-black border-2 border-black transition-all duration-300 mb-4">
Reserve
</button>
<p className="text-center text-sm text-gray-500 mb-4">You won't be charged yet</p>
<div className="space-y-3 text-sm">
<div className="flex justify-between">
<span className="underline">₨{property.price.toLocaleString()} x 5 nights</span>
<span>₨{(property.price * 5).toLocaleString()}</span>
</div>
<div className="flex justify-between">
<span className="underline">Cleaning fee</span>
<span>₨5,000</span>
</div>
<div className="flex justify-between">
<span className="underline">Service fee</span>
<span>₨8,000</span>
</div>
<div className="pt-4 border-t-2 border-gray-100 flex justify-between font-bold text-lg">
<span>Total</span>
<span>₨{(property.price * 5 + 13000).toLocaleString()}</span>
</div>
</div>
</div>
</div>
</div>
{/* Reviews Section */}
<div className="max-w-[95%] mx-auto pb-20 border-t-2 border-gray-100 pt-12">
<div className="flex items-center gap-2 mb-8">
<Star className="w-6 h-6 fill-[#E7FE78] text-black" />
<h2 className="text-2xl font-medium">{property.rating} · {property.reviewCount} reviews</h2>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
{property.reviews.slice(0, 4).map((review) => (
<div key={review.id} className="p-6 border-2 border-black hover:bg-gray-50 transition-colors">
<div className="flex items-center gap-4 mb-4">
<Image
src={review.avatar}
alt={review.user}
width={48}
height={48}
className="rounded-full border border-black"
/>
<div>
<h4 className="font-medium">{review.user}</h4>
<p className="text-sm text-gray-500">{review.date}</p>
</div>
</div>
<p className="text-gray-700 font-light leading-relaxed">
"{review.comment}"
</p>
</div>
))}
</div>
<button
onClick={() => 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
</button>
</div>
{/* Amenities Modal */}
{showAmenities && (
<div className="fixed inset-0 z-50 flex items-center justify-center p-4">
<div className="absolute inset-0 bg-black/50 backdrop-blur-sm" onClick={() => setShowAmenities(false)} />
<div className="relative bg-white w-full max-w-2xl max-h-[85vh] rounded-xl shadow-2xl flex flex-col animate-in fade-in zoom-in duration-200">
<div className="flex items-center justify-between p-6 border-b">
<h2 className="text-2xl font-medium">What this place offers</h2>
<button
onClick={() => setShowAmenities(false)}
className="p-2 hover:bg-gray-100 rounded-full transition-colors"
>
<X className="w-5 h-5" />
</button>
</div>
<div className="p-6 overflow-y-auto flex-1">
<div className="space-y-8">
{Array.from(new Set(property.amenities.map(a => a.category))).map(category => (
<div key={category}>
<h3 className="font-medium text-lg mb-4">{category}</h3>
<div className="space-y-4">
{property.amenities.filter(a => a.category === category).map((item, idx) => (
<div key={idx} className="flex items-center gap-4 pb-4 border-b border-gray-50 last:border-0">
<item.icon className="w-6 h-6 text-gray-600" />
<span className="text-lg font-light">{item.label}</span>
</div>
))}
</div>
</div>
))}
</div>
</div>
</div>
</div>
)}
{/* Reviews Modal */}
{showReviews && (
<div className="fixed inset-0 z-50 flex items-center justify-center p-4">
<div className="absolute inset-0 bg-black/50 backdrop-blur-sm" onClick={() => setShowReviews(false)} />
<div className="relative bg-white w-full max-w-4xl max-h-[85vh] rounded-xl shadow-2xl flex flex-col animate-in fade-in zoom-in duration-200">
<div className="flex items-center justify-between p-6 border-b">
<div className="flex items-center gap-2">
<Star className="w-5 h-5 fill-black" />
<h2 className="text-2xl font-medium">{property.rating} · {property.reviewCount} reviews</h2>
</div>
<button
onClick={() => setShowReviews(false)}
className="p-2 hover:bg-gray-100 rounded-full transition-colors"
>
<X className="w-5 h-5" />
</button>
</div>
<div className="p-8 overflow-y-auto flex-1">
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
{property.reviews.map((review) => (
<div key={review.id} className="space-y-4">
<div className="flex items-center gap-3">
<Image
src={review.avatar}
alt={review.user}
width={48}
height={48}
className="rounded-full border border-gray-200"
/>
<div>
<h4 className="font-medium">{review.user}</h4>
<p className="text-sm text-gray-500">{review.date}</p>
</div>
</div>
<div className="flex gap-1">
{[...Array(5)].map((_, i) => (
<Star
key={i}
className={`w-4 h-4 ${i < Math.floor(review.rating) ? 'fill-black text-black' : 'text-gray-300'}`}
/>
))}
</div>
<p className="text-gray-700 leading-relaxed">
{review.comment}
</p>
</div>
))}
</div>
</div>
</div>
</div>
)}
</div>
)
}
export default Features;

View File

@@ -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 (
<div>
<div className="flex flex-row justify-center gap-10 overflow-visible mb-35">
<div className="flex flex-row items-center justify-around">
<Image src={BestPricesImage} alt="Best Prices" width={300} height={200} className="h-85 object-cover rounded-l-xl hover:scale-105 transition-all duration-300 cursor-pointer" />
<Image src={hotelBanner} alt="Hotel Banner" width={300} height={500} className="h-85 object-cover rounded-r-xl shadow-[8px_4px_0px_rgba(0,0,0,1)] hover:scale-105 transition-all duration-300 cursor-pointer" />
</div>
<div className="flex flex-col items-center justify-start w-100 h-85 border border-black border-2 rounded-xl p-4 gap-4 shadow-[8px_4px_0px_rgba(0,0,0,1)] hover:scale-105 transition-all duration-300 cursor-pointer">
<h2 className={`${figtree.className} text-4xl font-bold`}>Consistent Service and Quality</h2>
<p className={`${figtree.className} text-lg font-light`}> 1. Our listings are consistently rated highly for service and quality, ensuring you have a comfortable and enjoyable stay.</p>
<p className={`${figtree.className} text-lg font-light`}> 2. We make sure to offer the best prices for our listings, ensuring you get the best value for your money.</p>
</div>
</div>
</div>
)
}
export default BestPrices;

View File

@@ -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<string, Property[]> = {
"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 (
<div className="w-full py-16 px-8 bg-white">
<div className="max-w-7xl mx-auto">
{/* Section Header */}
<div className="text-center mb-8">
<h2 className={`${figtree.className} text-5xl font-semibold mb-4`}>
Browse by city
</h2>
<p className={`${figtree.className} text-lg text-gray-600`}>
Experience different cities and vibes by staying with PakStay
</p>
</div>
{/* City Tabs */}
<div className="flex justify-center mb-12">
<div className="inline-flex border-2 border-black p-2">
{cities.map((city) => (
<button
key={city}
onClick={() => 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}
</button>
))}
</div>
</div>
{/* Property Cards Grid */}
<div className="relative px-16">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
{propertiesByCity[selectedCity].map((property) => (
<div
key={property.id}
className="group cursor-pointer border border-black border-2 overflow-hidden"
>
{/* Image Container */}
<div className="relative aspect-[16/14] overflow-hidden">
<Image
src={property.image}
alt={property.title}
fill
className="object-cover group-hover:scale-105 transition-transform duration-300"
/>
</div>
{/* Property Details */}
<div className="space-y-1 p-4">
{/* Location */}
<div className="flex items-center justify-between">
<p className={`${figtree.className} text-xs font-semibold text-gray-700 tracking-wider`}>
{property.city}
</p>
<div className="flex items-center gap-1">
<svg className="w-4 h-4" viewBox="0 0 24 24" fill="currentColor">
<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/>
</svg>
<span className={`${figtree.className} text-sm font-medium`}>
{property.rating}
</span>
</div>
</div>
{/* Title */}
<h3 className={`${figtree.className} text-base font-normal text-gray-900`}>
{property.title}
</h3>
{/* Price */}
<p className={`${figtree.className} text-base`}>
<span className="font-semibold">{property.price.toLocaleString()}</span>
<span className="text-gray-600"> night</span>
</p>
</div>
</div>
))}
</div>
{/* Navigation Arrows */}
<button className="absolute left-0 top-1/2 -translate-y-1/2 w-10 h-10 bg-transparent rounded-full border border-black flex items-center justify-center transition-shadow">
<svg className="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
<path d="M15 18l-6-6 6-6"/>
</svg>
</button>
<button className="absolute right-0 top-1/2 -translate-y-1/2 w-10 h-10 bg-transparent rounded-full border border-black flex items-center justify-center transition-shadow">
<svg className="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
<path d="M9 18l6-6-6-6"/>
</svg>
</button>
</div>
{/* Pagination Dots */}
<div className="flex justify-center gap-2 mt-8">
{[0, 1, 2, 3, 4, 5].map((dot, index) => (
<button
key={dot}
className={`w-2 h-2 rounded-full transition-colors ${
index === 0 ? 'bg-gray-900' : 'bg-gray-300'
}`}
/>
))}
</div>
</div>
</div>
)
}
export default BrowseByCity;

View File

@@ -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<number | null>(null);
const toggleFAQ = (index: number) => {
setOpenIndex(openIndex === index ? null : index);
};
return (
<div className="w-full bg-gray-50 py-16 px-6">
<div className="max-w-4xl mx-auto">
<h1 className={`${figtree.className} text-4xl md:text-5xl font-bold text-center mb-12 text-gray-900`}>
FAQs
</h1>
<div className="space-y-4">
{faqData.map((faq, index) => (
<div
key={index}
className="bg-white border-2 border-gray-900 rounded-lg overflow-hidden shadow-sm hover:shadow-md transition-shadow"
>
<button
onClick={() => toggleFAQ(index)}
className="w-full flex items-center justify-between p-6 text-left focus:outline-none hover:bg-gray-50 transition-colors"
>
<span className={`${figtree.className} text-lg font-medium text-gray-900 pr-4`}>
{faq.question}
</span>
<span className={`flex-shrink-0 w-10 h-10 rounded-full flex items-center justify-center transition-all duration-200 ${
openIndex === index
? 'bg-red-500 text-white rotate-180'
: 'bg-lime-400 text-gray-900'
}`}>
<svg
className="w-5 h-5"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
{openIndex === index ? (
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2.5} d="M5 15l7-7 7 7" />
) : (
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2.5} d="M19 9l-7 7-7-7" />
)}
</svg>
</span>
</button>
{openIndex === index && faq.answer && (
<div className="px-6 pb-6">
<p className={`${figtree.className} text-gray-600 leading-relaxed`}>
{faq.answer}
</p>
</div>
)}
</div>
))}
</div>
</div>
</div>
)
}
export default FAQs;

View File

@@ -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 = <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M128,80a48,48,0,1,0,48,48A48.05,48.05,0,0,0,128,80Zm0,80a32,32,0,1,1,32-32A32,32,0,0,1,128,160ZM176,24H80A56.06,56.06,0,0,0,24,80v96a56.06,56.06,0,0,0,56,56h96a56.06,56.06,0,0,0,56-56V80A56.06,56.06,0,0,0,176,24Zm40,152a40,40,0,0,1-40,40H80a40,40,0,0,1-40-40V80A40,40,0,0,1,80,40h96a40,40,0,0,1,40,40ZM192,76a12,12,0,1,1-12-12A12,12,0,0,1,192,76Z"></path></svg>
function Footer() {
return (
<div>
<div className="flex flex-row items-center justify-around border border-black border-4">
<Image src={logo} alt="logo" width={200} height={200} />
<div className="hover:scale-105 transition-all duration-300 cursor-pointer">{InstagramLogo}</div>
<div className="flex flex-row items-center justify-evenly gap-4">
<button className={`${figtree.className} text-xs font-light hover:underline cursor-pointer`}>Contact</button>
<button className={`${figtree.className} text-xs font-light hover:underline cursor-pointer`}>T&Cs</button>
<button className={`${figtree.className} text-xs font-light hover:underline cursor-pointer`}>Legal</button>
<button className={`${figtree.className} text-xs font-light hover:underline cursor-pointer`}>Privacy</button>
</div>
</div>
</div>
)
}
export default Footer;

View File

@@ -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 (
<div>
<div className="flex flex-col w-full items-center justify-center mb-16">
<div className="flex flex-row items-center justify-between gap-4">
<h1 className={`${figtree.className} text-7xl font-medium`}>Find Your PakStay Home in</h1>
<div className="relative">
<Image src={badge} alt="badge" width={400} height={400} />
<div className="absolute top-1/2 left-[52%] transform -translate-x-1/2 -translate-y-1/2 rotate-[-8deg]">
<h2 className={`${figtree.className} text-6xl font-bold text-black uppercase`}>Karachi</h2>
</div>
</div>
</div>
<div>
<h3 className={`${figtree.className} text-xl font-bold`}>Travel Karo, Tension Free!</h3>
</div>
</div>
</div>
)
}
export default Hero;

View File

@@ -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 (
<section className={`${figtree.className} bg-[#E7FE78] py-16 px-4 md:px-8 lg:px-16 relative overflow-hidden`}>
<div className="max-w-7xl mx-auto">
{/* Header */}
<div className="text-center mb-12">
<h2 className="text-4xl md:text-5xl font-medium text-black mb-4">
What others have to say<br />about us
</h2>
<p className="text-lg text-black max-w-2xl mx-auto">
We have not only earned the trust of our customers but also of our highly valued service providers.
</p>
</div>
{/* Reviews Carousel */}
<div className="relative">
{/* Navigation Buttons */}
<button
onClick={prevSlide}
className="absolute left-0 top-1/2 -translate-y-1/2 -translate-x-4 lg:-translate-x-12 z-10 bg-white rounded-full p-3 shadow-lg hover:shadow-xl transition-shadow"
aria-label="Previous reviews"
>
<ChevronLeft className="w-6 h-6 text-black" />
</button>
<button
onClick={nextSlide}
className="absolute right-0 top-1/2 -translate-y-1/2 translate-x-4 lg:translate-x-12 z-10 bg-white rounded-full p-3 shadow-lg hover:shadow-xl transition-shadow"
aria-label="Next reviews"
>
<ChevronRight className="w-6 h-6 text-black" />
</button>
{/* Reviews Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 px-4">
{getCurrentReviews().map((review, index) => (
<div
key={`${review.name}-${review.date}-${index}`}
className="bg-white p-6 border border-black border-2"
>
{/* Header */}
<div className="flex justify-between items-start mb-2">
<div>
<h3 className="font-bold text-xl text-black">{review.name}</h3>
<p className="text-sm text-gray-600">{review.date}</p>
</div>
<div className="flex items-center gap-1">
<Star className="w-5 h-5 fill-black text-black" />
<span className="font-semibold text-black">{review.rating}</span>
</div>
</div>
{/* Review Text */}
<p className="text-gray-800 text-sm leading-relaxed mb-4">
{review.text}
</p>
</div>
))}
</div>
</div>
{/* Pagination Dots */}
<div className="flex justify-center gap-2 mt-8">
{Array.from({ length: totalPages }).map((_, index) => (
<button
key={index}
onClick={() => 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}`}
/>
))}
</div>
</div>
</section>
)
}
export default Review;

View File

@@ -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 (
<div className="mb-10">
<div className="absolute top-[40%] left-[0%]">
<Image src={arrow} alt="arrow" width={300} height={300} />
</div>
<div className="flex flex-col w-full items-center justify-center">
<div className="flex flex-row w-[60%] p-6 border border-black border-4 rounded-lg justify-evenly">
<div className="flex flex-row gap-11">
{/* First Column */}
<div className="flex flex-row items-center justify-center gap-2 hover:scale-105 transition-all duration-300 cursor-pointer">
<MapPin className="w-8 h-8" />
<div>
<p className={`${figtree.className} text-lg font-light`}>Location</p>
<h3 className={`${figtree.className} text-xl font-bold`}>Anywhere</h3>
</div>
</div>
{/* Separator */}
<div className="border border-black border-1 w-0 h-14"></div>
{/* Second Column */}
<div className="flex flex-row items-center justify-center gap-2 hover:scale-105 transition-all duration-300 cursor-pointer">
<Calendar className="w-8 h-8" />
<div>
<p className={`${figtree.className} text-lg font-light`}>Check in</p>
<h3 className={`${figtree.className} text-xl font-bold`}>Anytime</h3>
</div>
</div>
{/* Separator */}
<div className="border border-black border-1 w-0 h-14"></div>
{/* Third Column */}
<div className="flex flex-row items-center justify-center gap-2 hover:scale-105 transition-all duration-300 cursor-pointer">
<Calendar className="w-8 h-8" />
<div>
<p className={`${figtree.className} text-lg font-light`}>Check out</p>
<h3 className={`${figtree.className} text-xl font-bold`}>Anytime</h3>
</div>
</div>
{/* Separator */}
<div className="border border-black border-1 w-0 h-14"></div>
{/* Fourth Column */}
<div className="flex flex-row items-center justify-center gap-2 hover:scale-105 transition-all duration-300 cursor-pointer">
<User className="w-8 h-8" />
<div>
<p className={`${figtree.className} text-lg font-light`}>Guests</p>
<h3 className={`${figtree.className} text-xl font-bold`}>Add guests</h3>
</div>
</div>
{/* Separator */}
<div className="border border-black border-1 w-0 h-14"></div>
{/* Fifth Column */}
<div className="flex flex-row items-center justify-center gap-2 hover:scale-105 transition-all duration-300 cursor-pointer">
<div className="p-2 rounded-full bg-[#E7FE78]">
<MagnifyingGlass className="w-10 h-10" />
</div>
</div>
</div>
</div>
</div>
</div>
)
}
export default Search;

View File

@@ -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 (
<div className="w-full py-16 px-8 bg-white">
<div className="max-w-[95%] mx-auto">
{/* Property Cards Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-12">
{currentProperties.map((property) => (
<div
key={property.id}
className="group cursor-pointer border border-black border-2 overflow-hidden"
>
{/* Image Container */}
<div className="relative aspect-[16/14] overflow-hidden">
<Image
src={property.image}
alt={property.title}
fill
className="object-cover group-hover:scale-105 transition-transform duration-300"
/>
</div>
{/* Property Details */}
<div className="space-y-1 p-4">
{/* Location */}
<div className="flex items-center justify-between">
<p className={`${figtree.className} text-xs font-semibold text-gray-700 tracking-wider`}>
{property.city}
</p>
<div className="flex items-center gap-1">
<svg className="w-4 h-4" viewBox="0 0 24 24" fill="currentColor">
<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/>
</svg>
<span className={`${figtree.className} text-sm font-medium`}>
{property.rating}
</span>
</div>
</div>
{/* Title */}
<h3 className={`${figtree.className} text-base font-normal text-gray-900`}>
{property.title}
</h3>
{/* Price */}
<p className={`${figtree.className} text-base`}>
<span className="font-semibold">{property.price.toLocaleString()}</span>
<span className="text-gray-600"> night</span>
</p>
</div>
</div>
))}
</div>
{/* Pagination Controls */}
<div className="flex flex-col items-center gap-6">
{/* Page Numbers */}
<div className="flex items-center gap-2">
{/* Previous Button */}
<button
onClick={goToPreviousPage}
disabled={currentPage === 1}
className={`${figtree.className} px-4 py-2 border-2 border-black transition-all duration-300 ${
currentPage === 1
? 'bg-gray-200 text-gray-400 cursor-not-allowed'
: 'bg-white text-black hover:bg-[#E7FE78]'
}`}
>
Previous
</button>
{/* Page Numbers */}
{getPageNumbers().map((page, index) => (
typeof page === 'number' ? (
<button
key={index}
onClick={() => 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}
</button>
) : (
<span key={index} className={`${figtree.className} px-2 text-gray-500`}>
{page}
</span>
)
))}
{/* Next Button */}
<button
onClick={goToNextPage}
disabled={currentPage === totalPages}
className={`${figtree.className} px-4 py-2 border-2 border-black transition-all duration-300 ${
currentPage === totalPages
? 'bg-gray-200 text-gray-400 cursor-not-allowed'
: 'bg-white text-black hover:bg-[#E7FE78]'
}`}
>
Next
</button>
</div>
{/* Page Info */}
<p className={`${figtree.className} text-sm text-gray-600`}>
Page {currentPage} of {totalPages}
</p>
</div>
</div>
</div>
)
}
export default Results;

View File

@@ -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 (
<svg className={className} xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M184,72a56,56,0,1,0-64,55.42V232a8,8,0,0,0,16,0V127.42A56.09,56.09,0,0,0,184,72Zm-56,40a40,40,0,1,1,40-40A40,40,0,0,1,128,112Z"></path></svg>
)
}
const ChevronDownIcon = ({ className }: { className: string }) => {
return (
<svg className={className} xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z"></path></svg>
)
}
const CalendarIcon = ({ className }: { className: string }) => {
return (
<svg className={className} xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M208,32H184V24a8,8,0,0,0-16,0v8H88V24a8,8,0,0,0-16,0v8H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32ZM72,48v8a8,8,0,0,0,16,0V48h80v8a8,8,0,0,0,16,0V48h24V80H48V48ZM208,208H48V96H208V208Zm-96-88v64a8,8,0,0,1-16,0V132.94l-4.42,2.22a8,8,0,0,1-7.16-14.32l16-8A8,8,0,0,1,112,120Zm59.16,30.45L152,176h16a8,8,0,0,1,0,16H136a8,8,0,0,1-6.4-12.8l28.78-38.37A8,8,0,1,0,145.07,132a8,8,0,1,1-13.85-8A24,24,0,0,1,176,136,23.76,23.76,0,0,1,171.16,150.45Z"></path></svg>
)
}
const UserIcon = ({ className }: { className: string }) => {
return (
<svg className={className} xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M256,136a8,8,0,0,1-8,8H232v16a8,8,0,0,1-16,0V144H200a8,8,0,0,1,0-16h16V112a8,8,0,0,1,16,0v16h16A8,8,0,0,1,256,136Zm-57.87,58.85a8,8,0,0,1-12.26,10.3C165.75,181.19,138.09,168,108,168s-57.75,13.19-77.87,37.15a8,8,0,0,1-12.25-10.3c14.94-17.78,33.52-30.41,54.17-37.17a68,68,0,1,1,71.9,0C164.6,164.44,183.18,177.07,198.13,194.85ZM108,152a52,52,0,1,0-52-52A52.06,52.06,0,0,0,108,152Z"></path></svg>
)
}
function SearchBy() {
return (
<div>
<div className="flex flex-col justify-center p-4">
<div className="justify-center pb-4">
<h1 className={`${figtree.className} text-4xl font-medium`}>Places to stay</h1>
</div>
<div className="flex flex-row justify-center gap-4">
{/* Location */}
<div className="flex flex-row gap-2 border border-black border-2 py-2 w-[30%] items-center justify-between px-4">
<div className="flex flex-row gap-2 items-center justify-center">
<MapPinIcon className="w-6 h-6" />
<p className={`${figtree.className} text-lg font-medium`}>Karachi, Pakistan</p>
</div>
<div>
<ChevronDownIcon className="w-6 h-6" />
</div>
</div>
{/* Check in/out */}
<div className="flex flex-row gap-2 border border-black border-2 py-2 w-[30%] items-center justify-between px-4">
<div className="flex flex-row gap-2 items-center justify-center">
<CalendarIcon className="w-6 h-6" />
<p className={`${figtree.className} text-lg font-medium`}>Fri, Nov 14</p>
<p className={`${figtree.className} text-lg font-medium`}>-</p>
<p className={`${figtree.className} text-lg font-medium`}>Sat, Nov 15</p>
</div>
<div>
<ChevronDownIcon className="w-6 h-6" />
</div>
</div>
{/* Guests */}
<div className="flex flex-row gap-2 border border-black border-2 py-2 w-[30%] items-center justify-between px-4">
<div className="flex flex-row gap-2 items-center justify-center">
<UserIcon className="w-6 h-6" />
<p className={`${figtree.className} text-lg font-medium`}>2 Adults</p>
<p>.</p>
<p className={`${figtree.className} text-lg font-medium`}>1 Child</p>
</div>
<div>
<ChevronDownIcon className="w-6 h-6" />
</div>
</div>
{/* Search */}
<button className="flex flex-row gap-2 border border-black border-2 py-2 items-center justify-between px-4 bg-[#E7FE78]">
<SearchIcon className="w-6 h-6" />
<p className={`${figtree.className} text-lg font-medium`}>Search</p>
</button>
</div>
<div className="flex flex-row justify-between pt-4">
{/* Filters */}
<div className="flex flex-row items-center justify-center gap-2">
<h2 className={`${figtree.className} text-md font-medium text-gray-500`}>Filters:</h2>
<button className="flex flex-row items-center justify-between">
<p className={`${figtree.className} text-md font-medium`}>Standard</p>
</button>
<ChevronDownIcon className="w-3 h-3 mt-1" />
</div>
{/* Sort by */}
<div className="flex flex-row items-center justify-center gap-2">
<h2 className={`${figtree.className} text-md font-medium text-gray-500`}>Sort by:</h2>
<button className="flex flex-row items-center justify-between">
<p className={`${figtree.className} text-md font-medium`}>Revelance</p>
</button>
<ChevronDownIcon className="w-3 h-3 mt-1" />
</div>
</div>
</div>
</div>
)
}
export default SearchBy;