All inner pages, seo selenium, sitemap, dynamic blog , contatc api integration are updated
This commit is contained in:
parent
7eee6d62d0
commit
345cef2e37
455
package-lock.json
generated
455
package-lock.json
generated
@ -8,14 +8,21 @@
|
||||
"name": "antalya-web",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"axios": "^1.13.2",
|
||||
"framer-motion": "^12.23.24",
|
||||
"next": "16.0.3",
|
||||
"react": "19.2.0",
|
||||
"react-dom": "19.2.0"
|
||||
"react-dom": "19.2.0",
|
||||
"react-google-recaptcha": "^3.1.0",
|
||||
"selenium-webdriver": "^4.38.0",
|
||||
"sitemap": "^9.0.0",
|
||||
"xml2js": "^0.6.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20",
|
||||
"@types/react": "^19",
|
||||
"@types/react-dom": "^19",
|
||||
"@types/react-google-recaptcha": "^2.1.9",
|
||||
"eslint": "^9",
|
||||
"eslint-config-next": "16.0.3",
|
||||
"typescript": "^5"
|
||||
@ -261,6 +268,12 @@
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@bazel/runfiles": {
|
||||
"version": "6.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@bazel/runfiles/-/runfiles-6.5.0.tgz",
|
||||
"integrity": "sha512-RzahvqTkfpY2jsDxo8YItPX+/iZ6hbiikw1YhE0bA9EKBR5Og8Pa6FHn9PO9M0zaXRVsr0GFQLKbB/0rzy9SzA==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@emnapi/core": {
|
||||
"version": "1.7.1",
|
||||
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.7.1.tgz",
|
||||
@ -1263,7 +1276,6 @@
|
||||
"version": "20.19.25",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.25.tgz",
|
||||
"integrity": "sha512-ZsJzA5thDQMSQO788d7IocwwQbI8B5OPzmqNvpf3NY/+MHDAS759Wo0gd2WQeXYt5AAAQjzcrTVC6SKCuYgoCQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.21.0"
|
||||
@ -1289,6 +1301,25 @@
|
||||
"@types/react": "^19.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-google-recaptcha": {
|
||||
"version": "2.1.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-google-recaptcha/-/react-google-recaptcha-2.1.9.tgz",
|
||||
"integrity": "sha512-nT31LrBDuoSZJN4QuwtQSF3O89FVHC4jLhM+NtKEmVF5R1e8OY0Jo4//x2Yapn2aNHguwgX5doAq8Zo+Ehd0ug==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/sax": {
|
||||
"version": "1.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.7.tgz",
|
||||
"integrity": "sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||
"version": "8.47.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.47.0.tgz",
|
||||
@ -1915,6 +1946,12 @@
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/arg": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
|
||||
"integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/argparse": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||
@ -2109,6 +2146,12 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/available-typed-arrays": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
|
||||
@ -2135,6 +2178,17 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.13.2",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz",
|
||||
"integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.6",
|
||||
"form-data": "^4.0.4",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/axobject-query": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
|
||||
@ -2243,7 +2297,6 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
|
||||
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
@ -2343,6 +2396,18 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
@ -2357,6 +2422,12 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/core-util-is": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
|
||||
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||
@ -2501,6 +2572,15 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/detect-libc": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
|
||||
@ -2528,7 +2608,6 @@
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.1",
|
||||
@ -2626,7 +2705,6 @@
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
||||
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
@ -2636,7 +2714,6 @@
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
||||
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
@ -2674,7 +2751,6 @@
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
|
||||
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0"
|
||||
@ -2687,7 +2763,6 @@
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
|
||||
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
@ -3302,6 +3377,26 @@
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.15.11",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
|
||||
"integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"debug": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/for-each": {
|
||||
"version": "0.3.5",
|
||||
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
|
||||
@ -3318,11 +3413,53 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "4.0.5",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
|
||||
"integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"es-set-tostringtag": "^2.1.0",
|
||||
"hasown": "^2.0.2",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/framer-motion": {
|
||||
"version": "12.23.24",
|
||||
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.23.24.tgz",
|
||||
"integrity": "sha512-HMi5HRoRCTou+3fb3h9oTLyJGBxHfW+HnNE25tAXOvVx/IvwMHK0cx7IR4a2ZU6sh3IX1Z+4ts32PcYBOqka8w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"motion-dom": "^12.23.23",
|
||||
"motion-utils": "^12.23.6",
|
||||
"tslib": "^2.4.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@emotion/is-prop-valid": "*",
|
||||
"react": "^18.0.0 || ^19.0.0",
|
||||
"react-dom": "^18.0.0 || ^19.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@emotion/is-prop-valid": {
|
||||
"optional": true
|
||||
},
|
||||
"react": {
|
||||
"optional": true
|
||||
},
|
||||
"react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/function-bind": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
@ -3383,7 +3520,6 @@
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
||||
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.2",
|
||||
@ -3408,7 +3544,6 @@
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"dunder-proto": "^1.0.1",
|
||||
@ -3496,7 +3631,6 @@
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
||||
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
@ -3568,7 +3702,6 @@
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
|
||||
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
@ -3581,7 +3714,6 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
||||
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"has-symbols": "^1.0.3"
|
||||
@ -3597,7 +3729,6 @@
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
||||
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"function-bind": "^1.1.2"
|
||||
@ -3623,6 +3754,15 @@
|
||||
"hermes-estree": "0.25.1"
|
||||
}
|
||||
},
|
||||
"node_modules/hoist-non-react-statics": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
|
||||
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"react-is": "^16.7.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ignore": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
||||
@ -3633,6 +3773,12 @@
|
||||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/immediate": {
|
||||
"version": "3.0.6",
|
||||
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
|
||||
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/import-fresh": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
|
||||
@ -3660,6 +3806,12 @@
|
||||
"node": ">=0.8.19"
|
||||
}
|
||||
},
|
||||
"node_modules/inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/internal-slot": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
|
||||
@ -4126,7 +4278,6 @@
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/js-yaml": {
|
||||
@ -4205,6 +4356,18 @@
|
||||
"node": ">=4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jszip": {
|
||||
"version": "3.10.1",
|
||||
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz",
|
||||
"integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==",
|
||||
"license": "(MIT OR GPL-3.0-or-later)",
|
||||
"dependencies": {
|
||||
"lie": "~3.3.0",
|
||||
"pako": "~1.0.2",
|
||||
"readable-stream": "~2.3.6",
|
||||
"setimmediate": "^1.0.5"
|
||||
}
|
||||
},
|
||||
"node_modules/keyv": {
|
||||
"version": "4.5.4",
|
||||
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
|
||||
@ -4249,6 +4412,15 @@
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lie": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
|
||||
"integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"immediate": "~3.0.5"
|
||||
}
|
||||
},
|
||||
"node_modules/locate-path": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
|
||||
@ -4276,7 +4448,6 @@
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||
@ -4299,7 +4470,6 @@
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
||||
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
@ -4329,6 +4499,27 @@
|
||||
"node": ">=8.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
@ -4352,6 +4543,21 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/motion-dom": {
|
||||
"version": "12.23.23",
|
||||
"resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.23.23.tgz",
|
||||
"integrity": "sha512-n5yolOs0TQQBRUFImrRfs/+6X4p3Q4n1dUEqt/H58Vx7OW6RF+foWEgmTVDhIWJIMXOuNNL0apKH2S16en9eiA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"motion-utils": "^12.23.6"
|
||||
}
|
||||
},
|
||||
"node_modules/motion-utils": {
|
||||
"version": "12.23.6",
|
||||
"resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.23.6.tgz",
|
||||
"integrity": "sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
@ -4463,7 +4669,6 @@
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
@ -4650,6 +4855,12 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/pako": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
|
||||
"integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
|
||||
"license": "(MIT AND Zlib)"
|
||||
},
|
||||
"node_modules/parent-module": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
||||
@ -4757,11 +4968,16 @@
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/process-nextick-args": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/prop-types": {
|
||||
"version": "15.8.1",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.4.0",
|
||||
@ -4769,6 +4985,12 @@
|
||||
"react-is": "^16.13.1"
|
||||
}
|
||||
},
|
||||
"node_modules/proxy-from-env": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/punycode": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||
@ -4809,6 +5031,19 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-async-script": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react-async-script/-/react-async-script-1.2.0.tgz",
|
||||
"integrity": "sha512-bCpkbm9JiAuMGhkqoAiC0lLkb40DJ0HOEJIku+9JDjxX3Rcs+ztEOG13wbrOskt3n2DTrjshhaQ/iay+SnGg5Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"hoist-non-react-statics": "^3.3.0",
|
||||
"prop-types": "^15.5.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.4.1"
|
||||
}
|
||||
},
|
||||
"node_modules/react-dom": {
|
||||
"version": "19.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz",
|
||||
@ -4821,11 +5056,44 @@
|
||||
"react": "^19.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-google-recaptcha": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/react-google-recaptcha/-/react-google-recaptcha-3.1.0.tgz",
|
||||
"integrity": "sha512-cYW2/DWas8nEKZGD7SCu9BSuVz8iOcOLHChHyi7upUuVhkpkhYG/6N3KDiTQ3XAiZ2UAZkfvYKMfAHOzBOcGEg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"prop-types": "^15.5.0",
|
||||
"react-async-script": "^1.2.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.4.1"
|
||||
}
|
||||
},
|
||||
"node_modules/react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/readable-stream": {
|
||||
"version": "2.3.8",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
|
||||
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"core-util-is": "~1.0.0",
|
||||
"inherits": "~2.0.3",
|
||||
"isarray": "~1.0.0",
|
||||
"process-nextick-args": "~2.0.0",
|
||||
"safe-buffer": "~5.1.1",
|
||||
"string_decoder": "~1.1.1",
|
||||
"util-deprecate": "~1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/readable-stream/node_modules/isarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/reflect.getprototypeof": {
|
||||
@ -4968,6 +5236,12 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/safe-push-apply": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz",
|
||||
@ -5003,12 +5277,43 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/sax": {
|
||||
"version": "1.4.3",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.4.3.tgz",
|
||||
"integrity": "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==",
|
||||
"license": "BlueOak-1.0.0"
|
||||
},
|
||||
"node_modules/scheduler": {
|
||||
"version": "0.27.0",
|
||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
|
||||
"integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/selenium-webdriver": {
|
||||
"version": "4.38.0",
|
||||
"resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.38.0.tgz",
|
||||
"integrity": "sha512-5/UXXFSQmn7FGQkbcpAqvfhzflUdMWtT7QqpEgkFD6Q6rDucxB5EUfzgjmr6JbUj30QodcW3mDXehzoeS/Vy5w==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/SeleniumHQ"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/selenium"
|
||||
}
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@bazel/runfiles": "^6.3.1",
|
||||
"jszip": "^3.10.1",
|
||||
"tmp": "^0.2.5",
|
||||
"ws": "^8.18.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 20.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
@ -5068,6 +5373,12 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/setimmediate": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
|
||||
"integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/sharp": {
|
||||
"version": "0.34.5",
|
||||
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz",
|
||||
@ -5225,6 +5536,40 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/sitemap": {
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/sitemap/-/sitemap-9.0.0.tgz",
|
||||
"integrity": "sha512-J/SU27FJ+I52TcDLKZzPRRVQUMj0Pp1i/HLb2lrkU+hrMLM+qdeRjdacrNxnSW48Waa3UcEOGOdX1+0Lob7TgA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "^24.9.2",
|
||||
"@types/sax": "^1.2.1",
|
||||
"arg": "^5.0.0",
|
||||
"sax": "^1.4.1"
|
||||
},
|
||||
"bin": {
|
||||
"sitemap": "dist/esm/cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.19.5",
|
||||
"npm": ">=10.8.2"
|
||||
}
|
||||
},
|
||||
"node_modules/sitemap/node_modules/@types/node": {
|
||||
"version": "24.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz",
|
||||
"integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~7.16.0"
|
||||
}
|
||||
},
|
||||
"node_modules/sitemap/node_modules/undici-types": {
|
||||
"version": "7.16.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
|
||||
"integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/source-map-js": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
|
||||
@ -5255,6 +5600,15 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/string_decoder": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"safe-buffer": "~5.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/string.prototype.includes": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz",
|
||||
@ -5488,6 +5842,15 @@
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/tmp": {
|
||||
"version": "0.2.5",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz",
|
||||
"integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=14.14"
|
||||
}
|
||||
},
|
||||
"node_modules/to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
@ -5698,7 +6061,6 @@
|
||||
"version": "6.21.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
|
||||
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/unrs-resolver": {
|
||||
@ -5777,6 +6139,12 @@
|
||||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||
@ -5892,6 +6260,49 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.18.3",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
|
||||
"integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": ">=5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/xml2js": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz",
|
||||
"integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"sax": ">=0.6.0",
|
||||
"xmlbuilder": "~11.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/xmlbuilder": {
|
||||
"version": "11.0.1",
|
||||
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
|
||||
"integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/yallist": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
|
||||
|
||||
12
package.json
12
package.json
@ -6,17 +6,25 @@
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "eslint"
|
||||
"lint": "eslint",
|
||||
"sitemap": "node scripts/generate-sitemap.cjs"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.13.2",
|
||||
"framer-motion": "^12.23.24",
|
||||
"next": "16.0.3",
|
||||
"react": "19.2.0",
|
||||
"react-dom": "19.2.0"
|
||||
"react-dom": "19.2.0",
|
||||
"react-google-recaptcha": "^3.1.0",
|
||||
"selenium-webdriver": "^4.38.0",
|
||||
"sitemap": "^9.0.0",
|
||||
"xml2js": "^0.6.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20",
|
||||
"@types/react": "^19",
|
||||
"@types/react-dom": "^19",
|
||||
"@types/react-google-recaptcha": "^2.1.9",
|
||||
"eslint": "^9",
|
||||
"eslint-config-next": "16.0.3",
|
||||
"typescript": "^5"
|
||||
|
||||
BIN
public/images/about-testimonial-bg.jpg
Normal file
BIN
public/images/about-testimonial-bg.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 356 KiB |
BIN
public/images/footer-bg.png
Normal file
BIN
public/images/footer-bg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 776 KiB |
BIN
public/images/section-bg.jpg
Normal file
BIN
public/images/section-bg.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 356 KiB |
6
public/robots.txt
Normal file
6
public/robots.txt
Normal file
@ -0,0 +1,6 @@
|
||||
# Allow all search engines to crawl all pages
|
||||
User-agent: *
|
||||
Disallow:
|
||||
|
||||
# Sitemap
|
||||
Sitemap: http://localhost:3000/sitemap.xml
|
||||
1
public/sitemap.xml
Normal file
1
public/sitemap.xml
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1"><url><loc>http://localhost:3000/</loc><changefreq>daily</changefreq><priority>1.0</priority></url><url><loc>http://localhost:3000/about/</loc><changefreq>monthly</changefreq><priority>0.5</priority></url><url><loc>http://localhost:3000/menu/</loc><changefreq>weekly</changefreq><priority>0.6</priority></url><url><loc>http://localhost:3000/gallery/</loc><changefreq>weekly</changefreq><priority>0.6</priority></url><url><loc>http://localhost:3000/contact/</loc><changefreq>weekly</changefreq><priority>0.6</priority></url><url><loc>http://localhost:3000/blog/</loc><changefreq>weekly</changefreq><priority>0.6</priority></url><url><loc>http://localhost:3000/blog/the-art-of-turkish-tea/</loc><changefreq>weekly</changefreq><priority>0.6</priority></url><url><loc>http://localhost:3000/blog/secrets-of-charcoal-grilling/</loc><changefreq>weekly</changefreq><priority>0.6</priority></url><url><loc>http://localhost:3000/blog/a-taste-of-sweet-legacy/</loc><changefreq>weekly</changefreq><priority>0.6</priority></url></urlset>
|
||||
66
scripts/generate-sitemap.cjs
Normal file
66
scripts/generate-sitemap.cjs
Normal file
@ -0,0 +1,66 @@
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const { SitemapStream, streamToPromise } = require("sitemap");
|
||||
const { pathToFileURL } = require("url");
|
||||
|
||||
const hostname = "http://localhost:3000"; // localhost for development
|
||||
const addTrailingSlash = true; // ✅ Set this true if your Next.js uses trailingSlash: true
|
||||
|
||||
// Utility to format URLs based on config
|
||||
const shouldAddSlash = (url) => {
|
||||
if (url === "/") return false;
|
||||
if (/\.[a-z0-9]{2,6}(\?.*)?$/i.test(url)) return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
const formatUrl = (url) => {
|
||||
if (!url.startsWith("/")) url = "/" + url;
|
||||
if (addTrailingSlash && shouldAddSlash(url) && !url.endsWith("/")) {
|
||||
return url + "/";
|
||||
}
|
||||
if (!addTrailingSlash && url.endsWith("/") && url !== "/") {
|
||||
return url.slice(0, -1);
|
||||
}
|
||||
return url;
|
||||
};
|
||||
|
||||
// ✅ Static pages
|
||||
const staticLinks = [
|
||||
{ url: '/', changefreq: 'daily', priority: 1.0 },
|
||||
{ url: '/about/', changefreq: 'monthly', priority: 0.5 },
|
||||
{ url: '/menu/', changefreq: 'weekly', priority: 0.6 },
|
||||
{ url: '/gallery/', changefreq: 'weekly', priority: 0.6 },
|
||||
{ url: '/contact/', changefreq: 'weekly', priority: 0.6 },
|
||||
{ url: '/blog/', changefreq: 'weekly', priority: 0.6 },
|
||||
];
|
||||
|
||||
// ✅ Dynamic blog posts (only URLs, no extra metadata needed beyond static format)
|
||||
const blogPosts = [
|
||||
{ slug: '/blog/the-art-of-turkish-tea' },
|
||||
{ slug: '/blog/secrets-of-charcoal-grilling/' },
|
||||
{ slug: '/blog/a-taste-of-sweet-legacy/' },
|
||||
];
|
||||
|
||||
const blogLinks = blogPosts.map(p => ({ url: p.slug, changefreq: 'weekly', priority: 0.6 }));
|
||||
|
||||
const allLinks = [...staticLinks, ...blogLinks].map(l => ({ ...l, url: formatUrl(l.url) }));
|
||||
|
||||
async function generateSitemap() {
|
||||
try {
|
||||
const sitemap = new SitemapStream({ hostname });
|
||||
const writeStream = fs.createWriteStream(path.resolve(__dirname, "../public/sitemap.xml"));
|
||||
sitemap.pipe(writeStream);
|
||||
console.log('📦 Writing URLs to sitemap:');
|
||||
allLinks.forEach(link => {
|
||||
console.log(' -', hostname + link.url);
|
||||
sitemap.write(link);
|
||||
});
|
||||
sitemap.end();
|
||||
await streamToPromise(sitemap);
|
||||
console.log('✅ sitemap.xml created successfully!');
|
||||
} catch (error) {
|
||||
console.error('❌ Error creating sitemap.xml:', error);
|
||||
}
|
||||
}
|
||||
|
||||
generateSitemap();
|
||||
10
scripts/image_alt_issues.csv
Normal file
10
scripts/image_alt_issues.csv
Normal file
@ -0,0 +1,10 @@
|
||||
Page URL,Image Src,Alt Text,Issue Type
|
||||
"http://localhost:3000/","","Antalya Restaurant","Duplicate Alt (2 times)"
|
||||
"http://localhost:3000/about/","","Antalya Restaurant","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/menu/","","Antalya Restaurant","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/gallery/","","Antalya Restaurant","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/contact/","","Antalya Restaurant","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/blog/","","Antalya Restaurant","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/blog/the-art-of-turkish-tea/","","Antalya Restaurant","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/blog/secrets-of-charcoal-grilling/","","Antalya Restaurant","Duplicate Alt (3 times)"
|
||||
"http://localhost:3000/blog/a-taste-of-sweet-legacy/","","Antalya Restaurant","Duplicate Alt (3 times)"
|
||||
|
244
scripts/seo-test-selenium.cjs
Normal file
244
scripts/seo-test-selenium.cjs
Normal file
@ -0,0 +1,244 @@
|
||||
const { Builder, By } = require("selenium-webdriver");
|
||||
const chrome = require("selenium-webdriver/chrome");
|
||||
const axios = require("axios");
|
||||
const xml2js = require("xml2js");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
// CSV file for Image Alt issues
|
||||
const csvPath = path.join(__dirname, "image_alt_issues.csv");
|
||||
fs.writeFileSync(csvPath, "Page URL,Image Src,Alt Text,Issue Type\n", "utf8");
|
||||
|
||||
// ==========================
|
||||
// 1️⃣ Fetch URLs from sitemap.xml
|
||||
// ==========================
|
||||
async function getUrlsFromSitemap(sitemapUrl) {
|
||||
try {
|
||||
const res = await axios.get(sitemapUrl);
|
||||
const parsed = await xml2js.parseStringPromise(res.data);
|
||||
return parsed.urlset.url.map((u) => u.loc[0]);
|
||||
} catch (err) {
|
||||
console.error("❌ Failed to load sitemap:", err.message);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================
|
||||
// 2️⃣ Check HTTP Status
|
||||
// ==========================
|
||||
async function checkLinkStatus(url) {
|
||||
try {
|
||||
const res = await axios.get(url, {
|
||||
timeout: 10000,
|
||||
validateStatus: () => true,
|
||||
});
|
||||
if (res.status === 200 && res.data.toLowerCase().includes("page not found")) {
|
||||
return "Soft 404";
|
||||
}
|
||||
return res.status;
|
||||
} catch (err) {
|
||||
return err.response ? err.response.status : "❌ No Response";
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================
|
||||
// 3️⃣ Main SEO + Accessibility + Image Alt Audit
|
||||
// ==========================
|
||||
async function checkSEO(url, siteDomain) {
|
||||
const options = new chrome.Options();
|
||||
options.addArguments("--headless", "--no-sandbox", "--disable-gpu");
|
||||
const driver = await new Builder()
|
||||
.forBrowser("chrome")
|
||||
.setChromeOptions(options)
|
||||
.build();
|
||||
|
||||
try {
|
||||
const pageStatus = await checkLinkStatus(url);
|
||||
if (pageStatus === 404 || pageStatus === "Soft 404") {
|
||||
console.log(`\n🚫 ${url} → ❌ Page not found (${pageStatus})`);
|
||||
return;
|
||||
}
|
||||
|
||||
await driver.get(url);
|
||||
const pageSource = await driver.getPageSource();
|
||||
|
||||
// Basic SEO Elements
|
||||
const title = await driver.getTitle();
|
||||
const descElem = await driver.findElements(By.css('meta[name="description"]'));
|
||||
const canonicalElem = await driver.findElements(By.css('link[rel="canonical"]'));
|
||||
const robotsElem = await driver.findElements(By.css('meta[name="robots"]'));
|
||||
const viewportElem = await driver.findElements(By.css('meta[name="viewport"]'));
|
||||
const charset = await driver.findElements(By.css('meta[charset]'));
|
||||
const htmlTag = await driver.findElement(By.css("html"));
|
||||
const langAttr = await htmlTag.getAttribute("lang").catch(() => "");
|
||||
const h1Tags = await driver.findElements(By.css("h1"));
|
||||
const h2Tags = await driver.findElements(By.css("h2"));
|
||||
|
||||
// Meta Description
|
||||
let descContent = descElem.length > 0 ? await descElem[0].getAttribute("content") : "";
|
||||
const descLength = descContent.length;
|
||||
const descStatus =
|
||||
descLength === 0
|
||||
? "❌ Missing"
|
||||
: descLength < 50
|
||||
? `⚠️ Too short (${descLength})`
|
||||
: descLength > 160
|
||||
? `⚠️ Too long (${descLength})`
|
||||
: "✅ Perfect";
|
||||
|
||||
// Title length check
|
||||
const titleLength = title.length;
|
||||
const titleStatus =
|
||||
titleLength === 0
|
||||
? "❌ Missing"
|
||||
: titleLength < 30
|
||||
? `⚠️ Too short (${titleLength})`
|
||||
: titleLength > 65
|
||||
? `⚠️ Too long (${titleLength})`
|
||||
: "✅ Perfect";
|
||||
|
||||
// Canonical
|
||||
const canonicalURL = canonicalElem.length > 0 ? await canonicalElem[0].getAttribute("href") : "❌ Missing";
|
||||
|
||||
// 🖼️ Image Accessibility Audit
|
||||
const imgs = await driver.findElements(By.css("img"));
|
||||
let missingAlt = 0;
|
||||
let emptyAlt = 0;
|
||||
let duplicateAlt = [];
|
||||
const altTextMap = new Map();
|
||||
|
||||
for (const img of imgs) {
|
||||
const src = await img.getAttribute("src");
|
||||
const alt = (await img.getAttribute("alt"))?.trim() ?? null;
|
||||
|
||||
if (alt === null) {
|
||||
missingAlt++;
|
||||
fs.appendFileSync(csvPath, `"${url}","${src}","","Missing Alt"\n`, "utf8");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (alt === "") {
|
||||
emptyAlt++;
|
||||
fs.appendFileSync(csvPath, `"${url}","${src}","(empty)","Empty Alt"\n`, "utf8");
|
||||
}
|
||||
|
||||
if (altTextMap.has(alt)) {
|
||||
altTextMap.set(alt, altTextMap.get(alt) + 1);
|
||||
} else {
|
||||
altTextMap.set(alt, 1);
|
||||
}
|
||||
}
|
||||
|
||||
for (const [altText, count] of altTextMap.entries()) {
|
||||
if (altText && count > 1) {
|
||||
duplicateAlt.push({ altText, count });
|
||||
fs.appendFileSync(
|
||||
csvPath,
|
||||
`"${url}","","${altText}","Duplicate Alt (${count} times)"\n`,
|
||||
"utf8"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Detect tracking & schema tags
|
||||
const hasGTM = pageSource.includes("googletagmanager.com/gtm.js");
|
||||
const hasClarity = pageSource.includes("clarity.ms/tag");
|
||||
const hasFBPixel = pageSource.includes("fbevents.js") || pageSource.includes("fbq(");
|
||||
const hasAnalytics = pageSource.includes("www.googletagmanager.com/gtag/js");
|
||||
|
||||
const ogTags = await driver.findElements(By.css("meta[property^='og:']"));
|
||||
const twitterTags = await driver.findElements(By.css("meta[name^='twitter:']"));
|
||||
const schemaScripts = await driver.findElements(By.css('script[type="application/ld+json"]'));
|
||||
|
||||
// Links check
|
||||
const anchorTags = await driver.findElements(By.css("a[href]"));
|
||||
const brokenLinks = [];
|
||||
for (const a of anchorTags) {
|
||||
const href = await a.getAttribute("href");
|
||||
if (!href || href.startsWith("#") || href.startsWith("mailto:")) continue;
|
||||
|
||||
const fullUrl = href.startsWith("http")
|
||||
? href
|
||||
: `${siteDomain}${href.startsWith("/") ? href : `/${href}`}`;
|
||||
|
||||
if (fullUrl.includes(siteDomain)) {
|
||||
const status = await checkLinkStatus(fullUrl);
|
||||
if (status === 404 || status === "Soft 404" || status === "❌ No Response") {
|
||||
brokenLinks.push({ link: fullUrl, status });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Lazy loading check
|
||||
const mediaElems = await driver.findElements(By.css("img, video, iframe"));
|
||||
const lazyLoadCount = await Promise.all(
|
||||
mediaElems.map(async (el) => {
|
||||
const loading = await el.getAttribute("loading");
|
||||
return loading === "lazy";
|
||||
})
|
||||
);
|
||||
const lazyLoaded = lazyLoadCount.filter((v) => v).length;
|
||||
|
||||
// Console Summary
|
||||
console.log(`\n🔍 Checking: ${url}`);
|
||||
console.log("-------------------------------------------");
|
||||
console.log("Title:", titleStatus);
|
||||
console.log("Meta Description:", descStatus);
|
||||
console.log("Canonical URL:", canonicalURL);
|
||||
console.log("Meta Robots:", robotsElem.length > 0 ? "✅ Found" : "⚠️ Missing");
|
||||
console.log("Viewport:", viewportElem.length > 0 ? "✅ Found" : "⚠️ Missing");
|
||||
console.log("Charset:", charset.length > 0 ? "✅ Found" : "❌ Missing");
|
||||
console.log("HTML lang:", langAttr ? `✅ ${langAttr}` : "⚠️ Missing");
|
||||
console.log("H1 Tags:", h1Tags.length > 0 ? `✅ ${h1Tags.length}` : "❌ Missing");
|
||||
console.log("H2 Tags:", h2Tags.length > 0 ? `ℹ️ ${h2Tags.length}` : "⚠️ None");
|
||||
console.log("Images:", imgs.length);
|
||||
console.log("Missing Alt:", missingAlt > 0 ? `❌ ${missingAlt}` : "✅ None");
|
||||
console.log("Empty Alt:", emptyAlt > 0 ? `⚠️ ${emptyAlt}` : "✅ None");
|
||||
console.log("Duplicate Alt:", duplicateAlt.length > 0 ? `⚠️ ${duplicateAlt.length}` : "✅ None");
|
||||
console.log("Lazy Loaded Images:", lazyLoaded > 0 ? `✅ ${lazyLoaded}` : "⚠️ None");
|
||||
console.log("Open Graph Tags:", ogTags.length > 0 ? "✅ Found" : "⚠️ Missing");
|
||||
console.log("Twitter Tags:", twitterTags.length > 0 ? "✅ Found" : "⚠️ Missing");
|
||||
console.log("Schema Markup:", schemaScripts.length > 0 ? "✅ Found" : "⚠️ Missing");
|
||||
console.log("Google Analytics:", hasAnalytics ? "✅ Found" : "⚠️ Missing");
|
||||
console.log("GTM:", hasGTM ? "✅ Found" : "⚠️ Missing");
|
||||
console.log("Clarity:", hasClarity ? "✅ Found" : "⚠️ Missing");
|
||||
console.log("Facebook Pixel:", hasFBPixel ? "✅ Found" : "⚠️ Missing");
|
||||
|
||||
if (brokenLinks.length > 0) {
|
||||
console.log("\n❌ Broken Links:");
|
||||
brokenLinks.forEach((b) => console.log(` → ${b.link} [${b.status}]`));
|
||||
} else {
|
||||
console.log("✅ No broken links found.");
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(`❌ Error on ${url}:`, err.message);
|
||||
} finally {
|
||||
await driver.quit();
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================
|
||||
// 4️⃣ Run Full Site Audit
|
||||
// ==========================
|
||||
(async () => {
|
||||
const sitemapUrl = "http://localhost:3000/sitemap.xml";
|
||||
const siteDomain = "http://localhost:3000";
|
||||
|
||||
console.log("📄 Fetching URLs from sitemap...");
|
||||
const urls = await getUrlsFromSitemap(sitemapUrl);
|
||||
|
||||
if (urls.length === 0) {
|
||||
console.error("❌ No URLs found in sitemap.");
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`✅ Found ${urls.length} URLs in sitemap.`);
|
||||
console.log("🚀 Starting Full SEO + Accessibility + Broken Link Audit...");
|
||||
|
||||
for (const url of urls) {
|
||||
await checkSEO(url, siteDomain);
|
||||
}
|
||||
|
||||
console.log("\n✅ Full SEO Audit Completed!");
|
||||
console.log(`📁 CSV Report: ${csvPath}`);
|
||||
})();
|
||||
575
src/app/about/about.module.css
Normal file
575
src/app/about/about.module.css
Normal file
@ -0,0 +1,575 @@
|
||||
.main {
|
||||
background-color: var(--color-dark);
|
||||
color: var(--color-text-light);
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.hero {
|
||||
padding: 10rem 2rem;
|
||||
background: linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.6)), url('/images/hero-1.png');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.heroContent {
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
.heroTitle {
|
||||
font-family: var(--font-playfair);
|
||||
font-size: 4rem;
|
||||
color: var(--color-gold);
|
||||
margin-bottom: 1rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
.breadcrumb {
|
||||
font-size: 1.1rem;
|
||||
color: #C5A059;
|
||||
font-family: var(--font-lato);
|
||||
}
|
||||
|
||||
.breadcrumb a {
|
||||
color: #fff;
|
||||
transition: color 0.3s;
|
||||
}
|
||||
|
||||
.breadcrumb a:hover {
|
||||
color: var(--color-gold);
|
||||
}
|
||||
|
||||
.section {
|
||||
padding: 80px 20px;
|
||||
background-color: #f5e6d3;
|
||||
}
|
||||
|
||||
.featuresSection {
|
||||
background-color: #3a0c08;
|
||||
background-image: url('/images/section-bg.jpg');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.testimonialsSection {
|
||||
background-color: #3a0c08;
|
||||
background-image: url('/images/about-testimonial-bg.jpg');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-repeat: repeat;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.textBlock {
|
||||
flex: 1;
|
||||
min-width: 300px;
|
||||
}
|
||||
|
||||
.imageBlock {
|
||||
flex: 1;
|
||||
min-width: 300px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.sectionTitle {
|
||||
font-family: var(--font-playfair);
|
||||
font-size: 3rem;
|
||||
color: #5d4037;
|
||||
margin-bottom: 1.5rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
.sectionTitleCenter {
|
||||
font-family: var(--font-playfair);
|
||||
font-size: 3.5rem;
|
||||
color: #C5A059;
|
||||
margin-bottom: 3rem;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
.text {
|
||||
font-size: 1.1rem;
|
||||
line-height: 1.8;
|
||||
color: #5d4037;
|
||||
margin-bottom: 1.5rem;
|
||||
opacity: 0.9;
|
||||
font-family: var(--font-lato);
|
||||
}
|
||||
|
||||
.image {
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
border: 4px solid #C5A059;
|
||||
}
|
||||
|
||||
.menuButton {
|
||||
display: inline-block;
|
||||
padding: 15px 40px;
|
||||
border: 2px solid #C5A059;
|
||||
color: #C5A059;
|
||||
font-family: var(--font-lato);
|
||||
font-size: 1.1rem;
|
||||
text-transform: uppercase;
|
||||
text-decoration: none;
|
||||
transition: all 0.3s ease;
|
||||
background: transparent;
|
||||
letter-spacing: 1px;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.menuButton:hover {
|
||||
background-color: #C5A059;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/* Features Section */
|
||||
.featuresGrid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 3rem;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.featureCard {
|
||||
background-color: #F5E6D3;
|
||||
padding: 2.5rem 2rem;
|
||||
text-align: center;
|
||||
border: 4px solid #C5A059;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.featureCard:hover {
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
|
||||
.featureImageWrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
margin-bottom: 1.5rem;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
border: 2px solid #C5A059;
|
||||
}
|
||||
|
||||
.featureImage {
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.featureTitle {
|
||||
font-family: var(--font-playfair);
|
||||
font-size: 1.8rem;
|
||||
color: #3e2723;
|
||||
margin-bottom: 1rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.featureDesc {
|
||||
font-family: var(--font-lato);
|
||||
font-size: 1rem;
|
||||
color: #5d4037;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* Testimonials Slider */
|
||||
.testimonialSlider {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 2rem;
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.sliderBtn {
|
||||
background: transparent;
|
||||
border: 2px solid #C5A059;
|
||||
color: #C5A059;
|
||||
font-size: 2.5rem;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.sliderBtn:hover {
|
||||
background-color: #C5A059;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.testimonialCard {
|
||||
background-color: #F5E6D3;
|
||||
padding: 3rem 2.5rem;
|
||||
border: 4px solid #C5A059;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2rem;
|
||||
flex: 1;
|
||||
min-height: 300px;
|
||||
}
|
||||
|
||||
.testimonialText {
|
||||
font-family: var(--font-lato);
|
||||
font-size: 1.3rem;
|
||||
color: #5d4037;
|
||||
line-height: 1.8;
|
||||
font-style: italic;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.testimonialAuthor {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.authorImageWrapper {
|
||||
position: relative;
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
border: 3px solid #C5A059;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.authorImage {
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.authorInfo {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.authorName {
|
||||
font-family: var(--font-playfair);
|
||||
font-size: 1.2rem;
|
||||
color: #3e2723;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.authorRole {
|
||||
font-family: var(--font-lato);
|
||||
font-size: 0.95rem;
|
||||
color: #836839;
|
||||
}
|
||||
|
||||
.sliderDots {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 1rem;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.dot {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
background: transparent;
|
||||
border: 2px solid #C5A059;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.dot:hover,
|
||||
.activeDot {
|
||||
background-color: #C5A059;
|
||||
}
|
||||
|
||||
/* Call to Action Section */
|
||||
.ctaSection {
|
||||
padding: 5rem 2rem;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.ctaOverlay {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
background: rgba(58, 12, 8, 0.9);
|
||||
padding: 4rem 2rem;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
border: 4px solid #C5A059;
|
||||
}
|
||||
|
||||
.ctaTitle {
|
||||
font-family: var(--font-playfair);
|
||||
font-size: 3rem;
|
||||
color: #C5A059;
|
||||
margin-bottom: 1rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
.ctaSubtitle {
|
||||
font-family: var(--font-lato);
|
||||
font-size: 1.3rem;
|
||||
color: #F5E6D3;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.ctaButton {
|
||||
display: inline-block;
|
||||
padding: 15px 40px;
|
||||
border: 2px solid #C5A059;
|
||||
color: #C5A059;
|
||||
font-family: var(--font-lato);
|
||||
font-size: 1.1rem;
|
||||
text-transform: uppercase;
|
||||
text-decoration: none;
|
||||
transition: all 0.3s ease;
|
||||
background: transparent;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.ctaButton:hover {
|
||||
background-color: #C5A059;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
.featuresGrid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.testimonialSlider {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.sliderBtn {
|
||||
order: 2;
|
||||
}
|
||||
|
||||
.testimonialCard {
|
||||
order: 1;
|
||||
}
|
||||
|
||||
.faqContainer {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 3rem;
|
||||
}
|
||||
|
||||
.faqImageBlock {
|
||||
min-height: 400px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.heroTitle {
|
||||
font-size: 3rem;
|
||||
}
|
||||
|
||||
.container {
|
||||
flex-direction: column;
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.section {
|
||||
padding: 60px 20px;
|
||||
}
|
||||
|
||||
.sectionTitleCenter {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.ctaTitle {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.sliderBtn {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.faqSection {
|
||||
padding: 60px 20px;
|
||||
}
|
||||
|
||||
.faqTitle {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.faqSubtitle {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.faqQuestion {
|
||||
padding: 1.2rem 1.5rem;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.faqAnswer {
|
||||
padding: 1.2rem 1.5rem;
|
||||
}
|
||||
|
||||
.faqImageBlock {
|
||||
min-height: 300px;
|
||||
}
|
||||
}
|
||||
|
||||
/* FAQ Section Styles */
|
||||
.faqSection {
|
||||
padding: 80px 20px;
|
||||
background-color: #F5E6D3;
|
||||
}
|
||||
|
||||
.faqContainer {
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 4rem;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.faqImageBlock {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 600px;
|
||||
}
|
||||
|
||||
.faqImage {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.faqContentBlock {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.faqTitle {
|
||||
font-family: var(--font-playfair);
|
||||
font-size: 2.5rem;
|
||||
color: #5d4037;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.faqSubtitle {
|
||||
font-family: var(--font-lato);
|
||||
font-size: 1.1rem;
|
||||
color: #836839;
|
||||
line-height: 1.6;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.faqAccordion {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.faqItem {
|
||||
background: #fff;
|
||||
border: 2px solid #C5A059;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.faqItem:hover {
|
||||
box-shadow: 0 4px 12px rgba(197, 160, 89, 0.2);
|
||||
}
|
||||
|
||||
.faqQuestion {
|
||||
width: 100%;
|
||||
padding: 1.5rem 2rem;
|
||||
background: transparent;
|
||||
border: none;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
font-family: var(--font-lato);
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
color: #5d4037;
|
||||
text-align: left;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.faqQuestion:hover {
|
||||
background-color: #faf6f0;
|
||||
}
|
||||
|
||||
.faqQuestionActive {
|
||||
background-color: #C5A059;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.faqIcon {
|
||||
font-size: 1.5rem;
|
||||
font-weight: bold;
|
||||
color: #C5A059;
|
||||
transition: transform 0.3s ease;
|
||||
flex-shrink: 0;
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
.faqQuestionActive .faqIcon {
|
||||
color: #fff;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.faqAnswer {
|
||||
padding: 1.5rem 2rem;
|
||||
border-top: 1px solid #e0d5c7;
|
||||
animation: slideDown 0.3s ease;
|
||||
}
|
||||
|
||||
.faqAnswer p {
|
||||
font-family: var(--font-lato);
|
||||
font-size: 1rem;
|
||||
color: #5d4037;
|
||||
line-height: 1.8;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@keyframes slideDown {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
770
src/app/about/about.module.css.backup
Normal file
770
src/app/about/about.module.css.backup
Normal file
@ -0,0 +1,770 @@
|
||||
.main {
|
||||
background-color: var(--color-dark);
|
||||
color: var(--color-text-light);
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.hero {
|
||||
padding: 10rem 2rem;
|
||||
background: linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.6)), url('/images/hero-1.png');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.heroContent {
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
.heroTitle {
|
||||
font-family: var(--font-playfair);
|
||||
font-size: 4rem;
|
||||
color: var(--color-gold);
|
||||
margin-bottom: 1rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
.breadcrumb {
|
||||
font-size: 1.1rem;
|
||||
color: #C5A059;
|
||||
font-family: var(--font-lato);
|
||||
}
|
||||
|
||||
.breadcrumb a {
|
||||
color: #fff;
|
||||
transition: color 0.3s;
|
||||
}
|
||||
|
||||
.breadcrumb a:hover {
|
||||
color: var(--color-gold);
|
||||
}
|
||||
|
||||
.section {
|
||||
padding: 80px 20px;
|
||||
background-color: #0a0a0a;
|
||||
}
|
||||
|
||||
.featuresSection {
|
||||
background-color: #3a0c08;
|
||||
background-image: url('/images/section-bg.jpg');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.testimonialsSection {
|
||||
background-color: #0a0a0a;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.textBlock {
|
||||
flex: 1;
|
||||
min-width: 300px;
|
||||
}
|
||||
|
||||
.imageBlock {
|
||||
flex: 1;
|
||||
min-width: 300px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.sectionTitle {
|
||||
font-family: var(--font-playfair);
|
||||
font-size: 3rem;
|
||||
color: #C5A059;
|
||||
margin-bottom: 1.5rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
.sectionTitleCenter {
|
||||
font-family: var(--font-playfair);
|
||||
font-size: 3.5rem;
|
||||
color: #C5A059;
|
||||
margin-bottom: 3rem;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
.text {
|
||||
font-size: 1.1rem;
|
||||
line-height: 1.8;
|
||||
color: #C5A059;
|
||||
margin-bottom: 1.5rem;
|
||||
opacity: 0.9;
|
||||
font-family: var(--font-lato);
|
||||
}
|
||||
|
||||
.image {
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
border: 4px solid #C5A059;
|
||||
}
|
||||
|
||||
.menuButton {
|
||||
display: inline-block;
|
||||
padding: 15px 40px;
|
||||
border: 2px solid #C5A059;
|
||||
color: #C5A059;
|
||||
font-family: var(--font-lato);
|
||||
font-size: 1.1rem;
|
||||
text-transform: uppercase;
|
||||
text-decoration: none;
|
||||
transition: all 0.3s ease;
|
||||
background: transparent;
|
||||
letter-spacing: 1px;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.menuButton:hover {
|
||||
background-color: #C5A059;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/* Features Section */
|
||||
.featuresGrid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 3rem;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.featureCard {
|
||||
background-color: #F5E6D3;
|
||||
padding: 2.5rem 2rem;
|
||||
text-align: center;
|
||||
border: 4px solid #C5A059;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.featureCard:hover {
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
|
||||
.featureImageWrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
margin-bottom: 1.5rem;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
border: 2px solid #C5A059;
|
||||
}
|
||||
|
||||
.featureImage {
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.featureTitle {
|
||||
font-family: var(--font-playfair);
|
||||
font-size: 1.8rem;
|
||||
color: #3e2723;
|
||||
margin-bottom: 1rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.featureDesc {
|
||||
font-family: var(--font-lato);
|
||||
font-size: 1rem;
|
||||
color: #5d4037;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* Testimonials Slider */
|
||||
.testimonialSlider {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 2rem;
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.sliderBtn {
|
||||
background: transparent;
|
||||
border: 2px solid #C5A059;
|
||||
color: #C5A059;
|
||||
font-size: 2.5rem;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.sliderBtn:hover {
|
||||
background-color: #C5A059;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.testimonialCard {
|
||||
background-color: #F5E6D3;
|
||||
padding: 3rem 2.5rem;
|
||||
border: 4px solid #C5A059;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2rem;
|
||||
flex: 1;
|
||||
min-height: 300px;
|
||||
}
|
||||
|
||||
.testimonialText {
|
||||
font-family: var(--font-lato);
|
||||
font-size: 1.3rem;
|
||||
color: #5d4037;
|
||||
line-height: 1.8;
|
||||
font-style: italic;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.testimonialAuthor {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.authorImageWrapper {
|
||||
position: relative;
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
border: 3px solid #C5A059;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.authorImage {
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.authorInfo {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.authorName {
|
||||
font-family: var(--font-playfair);
|
||||
font-size: 1.2rem;
|
||||
color: #3e2723;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.authorRole {
|
||||
font-family: var(--font-lato);
|
||||
font-size: 0.95rem;
|
||||
color: #836839;
|
||||
}
|
||||
|
||||
.sliderDots {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 1rem;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.dot {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
background: transparent;
|
||||
border: 2px solid #C5A059;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.dot:hover,
|
||||
.activeDot {
|
||||
background-color: #C5A059;
|
||||
}
|
||||
|
||||
/* Call to Action Section */
|
||||
.ctaSection {
|
||||
padding: 5rem 2rem;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.ctaOverlay {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
background: rgba(58, 12, 8, 0.9);
|
||||
padding: 4rem 2rem;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
border: 4px solid #C5A059;
|
||||
}
|
||||
|
||||
.ctaTitle {
|
||||
font-family: var(--font-playfair);
|
||||
font-size: 3rem;
|
||||
color: #C5A059;
|
||||
margin-bottom: 1rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
.ctaSubtitle {
|
||||
font-family: var(--font-lato);
|
||||
font-size: 1.3rem;
|
||||
color: #F5E6D3;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.ctaButton {
|
||||
display: inline-block;
|
||||
padding: 15px 40px;
|
||||
border: 2px solid #C5A059;
|
||||
color: #C5A059;
|
||||
font-family: var(--font-lato);
|
||||
font-size: 1.1rem;
|
||||
text-transform: uppercase;
|
||||
text-decoration: none;
|
||||
transition: all 0.3s ease;
|
||||
background: transparent;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.ctaButton:hover {
|
||||
background-color: #C5A059;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
.featuresGrid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.testimonialSlider {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.sliderBtn {
|
||||
order: 2;
|
||||
}
|
||||
|
||||
font-family: var(--font-playfair);
|
||||
font-size: 1.8rem;
|
||||
color: #3e2723;
|
||||
margin-bottom: 1rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.featureDesc {
|
||||
font-family: var(--font-lato);
|
||||
font-size: 1rem;
|
||||
color: #5d4037;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* Testimonials Slider */
|
||||
.testimonialSlider {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 2rem;
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.sliderBtn {
|
||||
background: transparent;
|
||||
border: 2px solid #C5A059;
|
||||
color: #C5A059;
|
||||
font-size: 2.5rem;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.sliderBtn:hover {
|
||||
background-color: #C5A059;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.testimonialCard {
|
||||
background-color: #F5E6D3;
|
||||
padding: 3rem 2.5rem;
|
||||
border: 4px solid #C5A059;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2rem;
|
||||
flex: 1;
|
||||
min-height: 300px;
|
||||
}
|
||||
|
||||
.testimonialText {
|
||||
font-family: var(--font-lato);
|
||||
font-size: 1.3rem;
|
||||
color: #5d4037;
|
||||
line-height: 1.8;
|
||||
font-style: italic;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.testimonialAuthor {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.authorImageWrapper {
|
||||
position: relative;
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
border: 3px solid #C5A059;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.authorImage {
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.authorInfo {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.authorName {
|
||||
font-family: var(--font-playfair);
|
||||
font-size: 1.2rem;
|
||||
color: #3e2723;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.authorRole {
|
||||
font-family: var(--font-lato);
|
||||
font-size: 0.95rem;
|
||||
color: #836839;
|
||||
}
|
||||
|
||||
.sliderDots {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 1rem;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.dot {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
background: transparent;
|
||||
border: 2px solid #C5A059;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.dot:hover,
|
||||
.activeDot {
|
||||
background-color: #C5A059;
|
||||
}
|
||||
|
||||
/* Call to Action Section */
|
||||
.ctaSection {
|
||||
padding: 5rem 2rem;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.ctaOverlay {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
background: rgba(58, 12, 8, 0.9);
|
||||
padding: 4rem 2rem;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
border: 4px solid #C5A059;
|
||||
}
|
||||
|
||||
.ctaTitle {
|
||||
font-family: var(--font-playfair);
|
||||
font-size: 3rem;
|
||||
color: #C5A059;
|
||||
margin-bottom: 1rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
.ctaSubtitle {
|
||||
font-family: var(--font-lato);
|
||||
font-size: 1.3rem;
|
||||
color: #F5E6D3;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.ctaButton {
|
||||
display: inline-block;
|
||||
padding: 15px 40px;
|
||||
border: 2px solid #C5A059;
|
||||
color: #C5A059;
|
||||
font-family: var(--font-lato);
|
||||
font-size: 1.1rem;
|
||||
text-transform: uppercase;
|
||||
text-decoration: none;
|
||||
transition: all 0.3s ease;
|
||||
background: transparent;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.ctaButton:hover {
|
||||
background-color: #C5A059;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
.featuresGrid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.testimonialSlider {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.sliderBtn {
|
||||
order: 2;
|
||||
}
|
||||
|
||||
.testimonialCard {
|
||||
order: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.heroTitle {
|
||||
font-size: 3rem;
|
||||
}
|
||||
|
||||
.container {
|
||||
flex-direction: column;
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.section {
|
||||
padding: 60px 20px;
|
||||
}
|
||||
|
||||
.sectionTitleCenter {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.ctaTitle {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.sliderBtn {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* FAQ Section Styles */
|
||||
.faqSection {
|
||||
padding: 80px 20px;
|
||||
background-color: #F5E6D3;
|
||||
}
|
||||
|
||||
.faqContainer {
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 4rem;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.faqImageBlock {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 600px;
|
||||
}
|
||||
|
||||
.faqImage {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.faqContentBlock {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.faqTitle {
|
||||
font-family: var(--font-playfair);
|
||||
font-size: 2.5rem;
|
||||
color: #5d4037;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.faqSubtitle {
|
||||
font-family: var(--font-lato);
|
||||
font-size: 1.1rem;
|
||||
color: #836839;
|
||||
line-height: 1.6;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.faqAccordion {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.faqItem {
|
||||
background: #fff;
|
||||
border: 2px solid #C5A059;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.faqItem:hover {
|
||||
box-shadow: 0 4px 12px rgba(197, 160, 89, 0.2);
|
||||
}
|
||||
|
||||
.faqQuestion {
|
||||
width: 100%;
|
||||
padding: 1.5rem 2rem;
|
||||
background: transparent;
|
||||
border: none;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
font-family: var(--font-lato);
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
color: #5d4037;
|
||||
text-align: left;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.faqQuestion:hover {
|
||||
background-color: #faf6f0;
|
||||
}
|
||||
|
||||
.faqQuestionActive {
|
||||
background-color: #C5A059;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.faqIcon {
|
||||
font-size: 1.5rem;
|
||||
font-weight: bold;
|
||||
color: #C5A059;
|
||||
transition: transform 0.3s ease;
|
||||
flex-shrink: 0;
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
.faqQuestionActive .faqIcon {
|
||||
color: #fff;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.faqAnswer {
|
||||
padding: 1.5rem 2rem;
|
||||
border-top: 1px solid #e0d5c7;
|
||||
animation: slideDown 0.3s ease;
|
||||
}
|
||||
|
||||
.faqAnswer p {
|
||||
font-family: var(--font-lato);
|
||||
font-size: 1rem;
|
||||
color: #5d4037;
|
||||
line-height: 1.8;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@keyframes slideDown {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
.faqContainer {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 3rem;
|
||||
}
|
||||
|
||||
.faqImageBlock {
|
||||
min-height: 400px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.faqSection {
|
||||
padding: 60px 20px;
|
||||
}
|
||||
|
||||
.faqTitle {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.faqSubtitle {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.faqQuestion {
|
||||
padding: 1.2rem 1.5rem;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.faqAnswer {
|
||||
padding: 1.2rem 1.5rem;
|
||||
}
|
||||
|
||||
.faqImageBlock {
|
||||
min-height: 300px;
|
||||
}
|
||||
}
|
||||
168
src/app/about/about_temp.css
Normal file
168
src/app/about/about_temp.css
Normal file
@ -0,0 +1,168 @@
|
||||
.main {
|
||||
background-color: var(--color-dark);
|
||||
color: var(--color-text-light);
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.hero {
|
||||
padding: 10rem 2rem;
|
||||
background: linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.6)), url('/images/hero-1.png');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.heroContent {
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
.heroTitle {
|
||||
font-family: var(--font-playfair);
|
||||
font-size: 4rem;
|
||||
color: var(--color-gold);
|
||||
margin-bottom: 1rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
.breadcrumb {
|
||||
font-size: 1.1rem;
|
||||
color: #C5A059;
|
||||
font-family: var(--font-lato);
|
||||
}
|
||||
|
||||
.breadcrumb a {
|
||||
color: #fff;
|
||||
transition: color 0.3s;
|
||||
}
|
||||
|
||||
.breadcrumb a:hover {
|
||||
color: var(--color-gold);
|
||||
}
|
||||
|
||||
.section {
|
||||
padding: 80px 20px;
|
||||
background-color: #f5e6d3;
|
||||
}
|
||||
|
||||
.featuresSection {
|
||||
background-color: #3a0c08;
|
||||
background-image: url('/images/section-bg.jpg');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.testimonialsSection {
|
||||
background-color: #0a0a0a;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.textBlock {
|
||||
flex: 1;
|
||||
min-width: 300px;
|
||||
}
|
||||
|
||||
.imageBlock {
|
||||
flex: 1;
|
||||
min-width: 300px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.sectionTitle {
|
||||
font-family: var(--font-playfair);
|
||||
font-size: 3rem;
|
||||
color: #C5A059;
|
||||
margin-bottom: 1.5rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
.sectionTitleCenter {
|
||||
font-family: var(--font-playfair);
|
||||
font-size: 3.5rem;
|
||||
color: #C5A059;
|
||||
margin-bottom: 3rem;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
.text {
|
||||
font-size: 1.1rem;
|
||||
line-height: 1.8;
|
||||
color: #C5A059;
|
||||
margin-bottom: 1.5rem;
|
||||
opacity: 0.9;
|
||||
font-family: var(--font-lato);
|
||||
}
|
||||
|
||||
.image {
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
border: 4px solid #C5A059;
|
||||
}
|
||||
|
||||
.menuButton {
|
||||
display: inline-block;
|
||||
padding: 15px 40px;
|
||||
border: 2px solid #C5A059;
|
||||
color: #C5A059;
|
||||
font-family: var(--font-lato);
|
||||
font-size: 1.1rem;
|
||||
text-transform: uppercase;
|
||||
text-decoration: none;
|
||||
transition: all 0.3s ease;
|
||||
background: transparent;
|
||||
letter-spacing: 1px;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.menuButton:hover {
|
||||
background-color: #C5A059;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/* Features Section */
|
||||
.featuresGrid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 3rem;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.featureCard {
|
||||
background-color: #F5E6D3;
|
||||
padding: 2.5rem 2rem;
|
||||
text-align: center;
|
||||
border: 4px solid #C5A059;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.featureCard:hover {
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
|
||||
.featureImageWrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
margin-bottom: 1.5rem;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
border: 2px solid #C5A059;
|
||||
}
|
||||
352
src/app/about/page.tsx
Normal file
352
src/app/about/page.tsx
Normal file
@ -0,0 +1,352 @@
|
||||
'use client'
|
||||
|
||||
import Navbar from "@/components/Navbar/Navbar";
|
||||
import Footer from "@/components/Footer/Footer";
|
||||
import FAQ from "@/components/FAQ/FAQ";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import styles from "./about.module.css";
|
||||
import { featuresData, testimonialData, ctaData, aboutFaqData } from "@/utils/constant";
|
||||
import { useState, useEffect } from "react";
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
|
||||
export default function AboutPage() {
|
||||
const [currentTestimonial, setCurrentTestimonial] = useState(0);
|
||||
|
||||
// Animation variants
|
||||
const fadeInUp = {
|
||||
hidden: { opacity: 0, y: 30 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
transition: {
|
||||
duration: 0.6
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const fadeIn = {
|
||||
hidden: { opacity: 0 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
transition: { duration: 0.8 }
|
||||
}
|
||||
};
|
||||
|
||||
const slideInLeft = {
|
||||
hidden: { opacity: 0, x: -50 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
x: 0,
|
||||
transition: {
|
||||
duration: 0.7
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const slideInRight = {
|
||||
hidden: { opacity: 0, x: 50 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
x: 0,
|
||||
transition: {
|
||||
duration: 0.7
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const staggerContainer = {
|
||||
hidden: { opacity: 0 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
transition: {
|
||||
staggerChildren: 0.2,
|
||||
delayChildren: 0.1
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Auto-slide testimonials
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
setCurrentTestimonial((prev) => (prev + 1) % testimonialData.length);
|
||||
}, 5000); // Change every 5 seconds
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
const nextTestimonial = () => {
|
||||
setCurrentTestimonial((prev) => (prev + 1) % testimonialData.length);
|
||||
};
|
||||
|
||||
const prevTestimonial = () => {
|
||||
setCurrentTestimonial((prev) => (prev - 1 + testimonialData.length) % testimonialData.length);
|
||||
};
|
||||
|
||||
return (
|
||||
<main className={styles.main}>
|
||||
<Navbar />
|
||||
|
||||
{/* Hero Banner */}
|
||||
<motion.section
|
||||
className={styles.hero}
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
variants={fadeIn}
|
||||
>
|
||||
<div className={styles.heroContent}>
|
||||
<h1 className={styles.heroTitle}>About Us</h1>
|
||||
<p className={styles.breadcrumb}>
|
||||
<Link href="/">Home</Link> / About
|
||||
</p>
|
||||
</div>
|
||||
</motion.section>
|
||||
|
||||
{/* About Section - No boxed structure */}
|
||||
<section className={styles.section}>
|
||||
<motion.div
|
||||
className={styles.container}
|
||||
initial="hidden"
|
||||
whileInView="visible"
|
||||
viewport={{ once: true, margin: "-100px" }}
|
||||
variants={staggerContainer}
|
||||
>
|
||||
<motion.div className={styles.textBlock} variants={slideInLeft}>
|
||||
<h2 className={styles.sectionTitle}>Our Story</h2>
|
||||
<p className={styles.text}>
|
||||
Founded in 2010, Antalya Restaurant began with a simple mission: to bring the authentic flavors of Turkey to our community.
|
||||
What started as a small family-run kitchen has grown into a beloved dining destination, known for its warm hospitality and traditional recipes passed down through generations.
|
||||
</p>
|
||||
<p className={styles.text}>
|
||||
Every dish we serve tells a story of tradition, passion, and dedication to the culinary arts. Our chefs use time-honored techniques combined with the freshest ingredients to create an unforgettable dining experience.
|
||||
</p>
|
||||
<Link href="/menu" className={styles.menuButton}>
|
||||
View Our Menu
|
||||
</Link>
|
||||
</motion.div>
|
||||
<motion.div className={styles.imageBlock} variants={slideInRight}>
|
||||
<Image src="/images/restaurant-interior.png" alt="Our Story" width={500} height={350} className={styles.image} />
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
</section>
|
||||
|
||||
{/* Features Section - With real images */}
|
||||
<section className={`${styles.section} ${styles.featuresSection}`}>
|
||||
<motion.h2
|
||||
className={styles.sectionTitleCenter}
|
||||
initial="hidden"
|
||||
whileInView="visible"
|
||||
viewport={{ once: true }}
|
||||
variants={fadeInUp}
|
||||
>
|
||||
What Makes Us Special
|
||||
</motion.h2>
|
||||
<motion.div
|
||||
className={styles.featuresGrid}
|
||||
initial="hidden"
|
||||
whileInView="visible"
|
||||
viewport={{ once: true, margin: "-100px" }}
|
||||
variants={staggerContainer}
|
||||
>
|
||||
{featuresData.map((feature) => (
|
||||
<motion.div
|
||||
key={feature.id}
|
||||
className={styles.featureCard}
|
||||
variants={fadeInUp}
|
||||
whileHover={{ y: -5, transition: { duration: 0.3 } }}
|
||||
>
|
||||
<div className={styles.featureImageWrapper}>
|
||||
<Image src={feature.image} alt={feature.title} fill className={styles.featureImage} />
|
||||
</div>
|
||||
<h3 className={styles.featureTitle}>{feature.title}</h3>
|
||||
<p className={styles.featureDesc}>{feature.description}</p>
|
||||
</motion.div>
|
||||
))}
|
||||
</motion.div>
|
||||
</section>
|
||||
|
||||
{/* Why Choose Us Section */}
|
||||
<section className={styles.section}>
|
||||
<motion.div
|
||||
className={styles.container}
|
||||
initial="hidden"
|
||||
whileInView="visible"
|
||||
viewport={{ once: true, margin: "-100px" }}
|
||||
variants={staggerContainer}
|
||||
>
|
||||
<motion.div className={styles.imageBlock} variants={slideInLeft}>
|
||||
<Image src="/images/hero-2.png" alt="Why Choose Us" width={500} height={350} className={styles.image} />
|
||||
</motion.div>
|
||||
<motion.div className={styles.textBlock} variants={slideInRight}>
|
||||
<h2 className={styles.sectionTitle}>Why Choose Us</h2>
|
||||
<p className={styles.text}>
|
||||
At Antalya Restaurant, we don't just serve food – we create experiences. Our commitment to authenticity means every spice, every ingredient, and every cooking method stays true to Turkish culinary traditions.
|
||||
</p>
|
||||
<p className={styles.text}>
|
||||
From our charcoal-grilled kebabs to our handmade baklava, we take pride in delivering dishes that transport you straight to the streets of Istanbul and the coasts of Antalya.
|
||||
</p>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
</section>
|
||||
|
||||
{/* Testimonials Section - Auto Slider */}
|
||||
<section className={`${styles.section} ${styles.testimonialsSection}`}>
|
||||
<motion.h2
|
||||
className={styles.sectionTitleCenter}
|
||||
initial="hidden"
|
||||
whileInView="visible"
|
||||
viewport={{ once: true }}
|
||||
variants={fadeInUp}
|
||||
>
|
||||
What Our Guests Say
|
||||
</motion.h2>
|
||||
<motion.div
|
||||
className={styles.testimonialSlider}
|
||||
initial="hidden"
|
||||
whileInView="visible"
|
||||
viewport={{ once: true }}
|
||||
variants={fadeIn}
|
||||
>
|
||||
<button className={styles.sliderBtn} onClick={prevTestimonial}>‹</button>
|
||||
|
||||
<AnimatePresence mode="wait">
|
||||
<motion.div
|
||||
key={currentTestimonial}
|
||||
className={styles.testimonialCard}
|
||||
initial={{ opacity: 0, x: 50 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
exit={{ opacity: 0, x: -50 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
>
|
||||
<p className={styles.testimonialText}>"{testimonialData[currentTestimonial].text}"</p>
|
||||
<div className={styles.testimonialAuthor}>
|
||||
<div className={styles.authorImageWrapper}>
|
||||
<Image
|
||||
src={testimonialData[currentTestimonial].image}
|
||||
alt={testimonialData[currentTestimonial].name}
|
||||
fill
|
||||
className={styles.authorImage}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.authorInfo}>
|
||||
<p className={styles.authorName}>{testimonialData[currentTestimonial].name}</p>
|
||||
<p className={styles.authorRole}>{testimonialData[currentTestimonial].role}</p>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</AnimatePresence>
|
||||
|
||||
<button className={styles.sliderBtn} onClick={nextTestimonial}>›</button>
|
||||
</motion.div>
|
||||
|
||||
{/* Slider dots */}
|
||||
<div className={styles.sliderDots}>
|
||||
{testimonialData.map((_, index) => (
|
||||
<button
|
||||
key={index}
|
||||
className={`${styles.dot} ${index === currentTestimonial ? styles.activeDot : ''}`}
|
||||
onClick={() => setCurrentTestimonial(index)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* FAQ Section - Image Left, FAQ Right */}
|
||||
<section className={styles.faqSection}>
|
||||
<motion.div
|
||||
className={styles.faqContainer}
|
||||
initial="hidden"
|
||||
whileInView="visible"
|
||||
viewport={{ once: true, margin: "-100px" }}
|
||||
variants={staggerContainer}
|
||||
>
|
||||
<motion.div className={styles.faqImageBlock} variants={slideInLeft}>
|
||||
<Image
|
||||
src="/images/restaurant-interior.png"
|
||||
alt="Frequently Asked Questions"
|
||||
width={600}
|
||||
height={700}
|
||||
className={styles.faqImage}
|
||||
/>
|
||||
</motion.div>
|
||||
<motion.div className={styles.faqContentBlock} variants={slideInRight}>
|
||||
<h2 className={styles.faqTitle}>Frequently Asked Questions</h2>
|
||||
<p className={styles.faqSubtitle}>
|
||||
Have questions about Antalya Restaurant? Find answers to our most commonly asked questions below.
|
||||
</p>
|
||||
<div className={styles.faqAccordion}>
|
||||
{aboutFaqData.map((faq, index) => (
|
||||
<FaqItem key={index} question={faq.q} answer={faq.a} />
|
||||
))}
|
||||
</div>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
</section>
|
||||
|
||||
{/* Call to Action */}
|
||||
<motion.section
|
||||
className={styles.ctaSection}
|
||||
style={{ backgroundImage: `url(${ctaData.backgroundImage})` }}
|
||||
initial="hidden"
|
||||
whileInView="visible"
|
||||
viewport={{ once: true }}
|
||||
variants={fadeIn}
|
||||
>
|
||||
<div className={styles.ctaOverlay}>
|
||||
<motion.h2
|
||||
className={styles.ctaTitle}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.6, delay: 0.2 }}
|
||||
>
|
||||
{ctaData.title}
|
||||
</motion.h2>
|
||||
<motion.p
|
||||
className={styles.ctaSubtitle}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.6, delay: 0.4 }}
|
||||
>
|
||||
{ctaData.subtitle}
|
||||
</motion.p>
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.6, delay: 0.6 }}
|
||||
>
|
||||
<Link href={ctaData.buttonLink} className={styles.ctaButton}>
|
||||
{ctaData.buttonText}
|
||||
</Link>
|
||||
</motion.div>
|
||||
</div>
|
||||
</motion.section>
|
||||
|
||||
<Footer />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
// FAQ Item Component
|
||||
function FaqItem({ question, answer }: { question: string; answer: string }) {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<div className={styles.faqItem}>
|
||||
<button
|
||||
className={`${styles.faqQuestion} ${isOpen ? styles.faqQuestionActive : ''}`}
|
||||
onClick={() => setIsOpen(!isOpen)}
|
||||
>
|
||||
<span>{question}</span>
|
||||
<span className={styles.faqIcon}>{isOpen ? '−' : '+'}</span>
|
||||
</button>
|
||||
{isOpen && (
|
||||
<div className={styles.faqAnswer}>
|
||||
<p>{answer}</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
310
src/app/blog/[id]/blogDetail.module.css
Normal file
310
src/app/blog/[id]/blogDetail.module.css
Normal file
@ -0,0 +1,310 @@
|
||||
.main {
|
||||
background-color: var(--color-dark);
|
||||
color: var(--color-text-light);
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.hero {
|
||||
padding: 10rem 2rem;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.heroContent {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.heroTitle {
|
||||
font-family: var(--font-playfair);
|
||||
font-size: 4rem;
|
||||
color: #C5A059;
|
||||
margin-bottom: 1rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
.breadcrumb {
|
||||
font-size: 1.1rem;
|
||||
color: #C5A059;
|
||||
font-family: var(--font-lato);
|
||||
}
|
||||
|
||||
.breadcrumb a {
|
||||
color: #fff;
|
||||
transition: color 0.3s;
|
||||
}
|
||||
|
||||
.breadcrumb a:hover {
|
||||
color: var(--color-gold);
|
||||
}
|
||||
|
||||
.article {
|
||||
background-color: #F5E6D3;
|
||||
padding: 60px 20px;
|
||||
}
|
||||
|
||||
.contentContainer {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
background: #fff;
|
||||
padding: 3rem;
|
||||
border: 4px solid #C5A059;
|
||||
}
|
||||
|
||||
.meta {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
margin-bottom: 2rem;
|
||||
flex-wrap: wrap;
|
||||
font-family: var(--font-lato);
|
||||
}
|
||||
|
||||
.category {
|
||||
background: #C5A059;
|
||||
color: #fff;
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 4px;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.date,
|
||||
.comments {
|
||||
color: #836839;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.separator {
|
||||
color: #d4c5b0;
|
||||
}
|
||||
|
||||
.featuredImage {
|
||||
width: 100%;
|
||||
height: 500px;
|
||||
position: relative;
|
||||
margin-bottom: 2.5rem;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
border: 3px solid #C5A059;
|
||||
}
|
||||
|
||||
.featuredImage img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.content {
|
||||
font-family: var(--font-lato);
|
||||
font-size: 1.1rem;
|
||||
line-height: 1.8;
|
||||
color: #5d4037;
|
||||
}
|
||||
|
||||
.content h2 {
|
||||
font-family: var(--font-playfair);
|
||||
font-size: 2rem;
|
||||
color: #5d4037;
|
||||
margin: 2rem 0 1rem;
|
||||
padding-bottom: 0.5rem;
|
||||
border-bottom: 2px solid #C5A059;
|
||||
}
|
||||
|
||||
.content h3 {
|
||||
font-family: var(--font-playfair);
|
||||
font-size: 1.6rem;
|
||||
color: #5d4037;
|
||||
margin: 1.5rem 0 1rem;
|
||||
}
|
||||
|
||||
.content h4 {
|
||||
font-family: var(--font-playfair);
|
||||
font-size: 1.3rem;
|
||||
color: #5d4037;
|
||||
margin: 1.2rem 0 0.8rem;
|
||||
}
|
||||
|
||||
.content p {
|
||||
margin-bottom: 1.2rem;
|
||||
}
|
||||
|
||||
.content ul {
|
||||
margin: 1.5rem 0;
|
||||
padding-left: 2rem;
|
||||
}
|
||||
|
||||
.content li {
|
||||
margin-bottom: 0.8rem;
|
||||
color: #5d4037;
|
||||
}
|
||||
|
||||
.content strong {
|
||||
color: #3e2723;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.content a {
|
||||
color: #C5A059;
|
||||
text-decoration: underline;
|
||||
transition: color 0.3s;
|
||||
}
|
||||
|
||||
.content a:hover {
|
||||
color: #b08f4a;
|
||||
}
|
||||
|
||||
.content .sec-title {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.content .mt-4 {
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
.content .list-style-two {
|
||||
list-style: none;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.content .list-style-two li {
|
||||
position: relative;
|
||||
padding-left: 2rem;
|
||||
}
|
||||
|
||||
.content .list-style-two li:before {
|
||||
content: "✓";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
color: #C5A059;
|
||||
font-weight: bold;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
/* Impressive Blockquote Styling */
|
||||
.content blockquote {
|
||||
text-align: center;
|
||||
background: linear-gradient(135deg, #faf6f0 0%, #f5ede0 100%);
|
||||
border-left: 6px solid #c5a059;
|
||||
/* border-right: 6px solid #c5a059; */
|
||||
/* max-width: 800px; */
|
||||
margin: 3rem 0px;
|
||||
padding: 10px 20px 10px 20px;
|
||||
position: relative;
|
||||
box-shadow: 0 8px 24px #c5a05926;
|
||||
}
|
||||
|
||||
.content blockquote p {
|
||||
font-family: var(--font-playfair);
|
||||
font-size: 1.4rem;
|
||||
font-style: italic;
|
||||
color: #5d4037;
|
||||
line-height: 1.8;
|
||||
margin: 0;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.content blockquote cite {
|
||||
display: block;
|
||||
margin-top: 1.5rem;
|
||||
font-family: var(--font-lato);
|
||||
font-size: 1rem;
|
||||
font-style: normal;
|
||||
color: #C5A059;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.content blockquote cite:before {
|
||||
content: "— ";
|
||||
}
|
||||
|
||||
.navigation {
|
||||
margin-top: 3rem;
|
||||
padding-top: 2rem;
|
||||
border-top: 2px solid #e0d5c7;
|
||||
}
|
||||
|
||||
.backButton {
|
||||
display: inline-block;
|
||||
padding: 12px 30px;
|
||||
background: transparent;
|
||||
border: 2px solid #C5A059;
|
||||
color: #C5A059;
|
||||
font-family: var(--font-lato);
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
transition: all 0.3s;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.backButton:hover {
|
||||
background: #C5A059;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.errorContainer {
|
||||
min-height: 60vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 4rem 2rem;
|
||||
}
|
||||
|
||||
.errorTitle {
|
||||
font-family: var(--font-playfair);
|
||||
font-size: 3rem;
|
||||
color: #C5A059;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.backLink {
|
||||
color: #C5A059;
|
||||
font-size: 1.2rem;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.heroTitle {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
|
||||
.contentContainer {
|
||||
padding: 2rem 1.5rem;
|
||||
}
|
||||
|
||||
.featuredImage {
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
.content {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.content h2 {
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
|
||||
.content h3 {
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
|
||||
.content blockquote {
|
||||
padding: 2rem 2rem;
|
||||
margin: 2rem auto;
|
||||
}
|
||||
|
||||
.content blockquote p {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.meta {
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
}
|
||||
94
src/app/blog/[id]/page.tsx
Normal file
94
src/app/blog/[id]/page.tsx
Normal file
@ -0,0 +1,94 @@
|
||||
'use client'
|
||||
|
||||
import { useParams } from 'next/navigation';
|
||||
import Navbar from "@/components/Navbar/Navbar";
|
||||
import Footer from "@/components/Footer/Footer";
|
||||
import FAQ from "@/components/FAQ/FAQ";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import styles from "./blogDetail.module.css";
|
||||
import { blogData } from "@/utils/constant";
|
||||
|
||||
export default function BlogDetailPage() {
|
||||
const params = useParams();
|
||||
const slug = params.id as string;
|
||||
const blog = blogData.find((b) => b.slug === slug);
|
||||
|
||||
if (!blog) {
|
||||
return (
|
||||
<main className={styles.main}>
|
||||
<Navbar />
|
||||
<div className={styles.errorContainer}>
|
||||
<h1 className={styles.errorTitle}>Blog Post Not Found</h1>
|
||||
<Link href="/blog" className={styles.backLink}>Back to Blog</Link>
|
||||
</div>
|
||||
<Footer />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<main className={styles.main}>
|
||||
<Navbar />
|
||||
|
||||
{/* Banner Section */}
|
||||
<section className={styles.hero} style={{ backgroundImage: `linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.6)), url(${blog.banner})` }}>
|
||||
<div className={styles.heroContent}>
|
||||
<h1 className={styles.heroTitle}>{blog.title}</h1>
|
||||
<p className={styles.breadcrumb}>
|
||||
<Link href="/">Home</Link> / <Link href="/blog">Blog</Link> / {blog.title}
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Blog Content */}
|
||||
<article className={styles.article}>
|
||||
<div className={styles.contentContainer}>
|
||||
{/* Meta Information */}
|
||||
|
||||
{/* Featured Image */}
|
||||
{blog.detailImage && (
|
||||
<div className={styles.featuredImage}>
|
||||
<Image
|
||||
src={blog.detailImage}
|
||||
alt={blog.title}
|
||||
width={1200}
|
||||
height={600}
|
||||
style={{ objectFit: 'cover' }}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className={styles.meta}>
|
||||
<span className={styles.category}>{blog.category}</span>
|
||||
<span className={styles.separator}>|</span>
|
||||
<span className={styles.date}>{blog.date}</span>
|
||||
<span className={styles.separator}>|</span>
|
||||
<span className={styles.comments}>{blog.comments}</span>
|
||||
</div>
|
||||
|
||||
|
||||
{/* Blog Content */}
|
||||
<div
|
||||
className={styles.content}
|
||||
dangerouslySetInnerHTML={{ __html: blog.content }}
|
||||
/>
|
||||
|
||||
{/* FAQ Section */}
|
||||
{blog.faqs && blog.faqs.length > 0 && (
|
||||
<FAQ faqs={blog.faqs} />
|
||||
)}
|
||||
|
||||
|
||||
{/* Navigation */}
|
||||
<div className={styles.navigation}>
|
||||
<Link href="/blog" className={styles.backButton}>← Back to All Blogs</Link>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
|
||||
<Footer />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
143
src/app/blog/blog.module.css
Normal file
143
src/app/blog/blog.module.css
Normal file
@ -0,0 +1,143 @@
|
||||
.main {
|
||||
background-color: var(--color-dark);
|
||||
color: var(--color-text-light);
|
||||
min-height: 100vh;
|
||||
background-color: #f5e6d3;
|
||||
}
|
||||
|
||||
.hero {
|
||||
padding: 10rem 2rem;
|
||||
background: linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.6)), url('/images/dish-2.png');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.heroContent {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.heroTitle {
|
||||
font-family: var(--font-playfair);
|
||||
font-size: 4rem;
|
||||
color: #C5A059;
|
||||
margin-bottom: 1rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
.breadcrumb {
|
||||
font-size: 1.1rem;
|
||||
color: #C5A059;
|
||||
font-family: var(--font-lato);
|
||||
}
|
||||
|
||||
.breadcrumb a {
|
||||
color: #fff;
|
||||
transition: color 0.3s;
|
||||
}
|
||||
|
||||
.breadcrumb a:hover {
|
||||
color: var(--color-gold);
|
||||
}
|
||||
|
||||
.blogSection {
|
||||
padding: 80px 20px;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
/* background-color: #0a0a0a; */
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.card {
|
||||
background-color: #F5E6D3;
|
||||
border: 4px solid #C5A059;
|
||||
overflow: hidden;
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
transform: translateY(-10px);
|
||||
box-shadow: 0 10px 30px rgba(197, 160, 89, 0.5);
|
||||
}
|
||||
|
||||
.imageContainer {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 250px;
|
||||
border-bottom: 1px solid #C5A059;
|
||||
}
|
||||
|
||||
.cardContent {
|
||||
padding: 1.5rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: calc(100% - 250px);
|
||||
}
|
||||
|
||||
.blogTitle {
|
||||
font-family: var(--font-playfair);
|
||||
font-size: 1.6rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.blogTitle a {
|
||||
color: #3e2723;
|
||||
transition: color 0.3s;
|
||||
}
|
||||
|
||||
.blogTitle a:hover {
|
||||
color: #C5A059;
|
||||
}
|
||||
|
||||
.date {
|
||||
font-size: 0.9rem;
|
||||
color: #836839;
|
||||
margin-bottom: 1rem;
|
||||
font-family: var(--font-lato);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.excerpt {
|
||||
font-size: 1rem;
|
||||
color: #5d4037;
|
||||
line-height: 1.6;
|
||||
margin-bottom: 1.5rem;
|
||||
flex-grow: 1;
|
||||
font-family: var(--font-lato);
|
||||
}
|
||||
|
||||
.button {
|
||||
display: inline-block;
|
||||
padding: 10px 25px;
|
||||
border: 2px solid #C5A059;
|
||||
color: #5d4037;
|
||||
text-align: center;
|
||||
transition: all 0.3s ease;
|
||||
align-self: flex-start;
|
||||
font-family: var(--font-lato);
|
||||
text-transform: uppercase;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
background-color: #C5A059;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.heroTitle {
|
||||
font-size: 3rem;
|
||||
}
|
||||
|
||||
.blogSection {
|
||||
padding: 60px 20px;
|
||||
}
|
||||
}
|
||||
110
src/app/blog/page.tsx
Normal file
110
src/app/blog/page.tsx
Normal file
@ -0,0 +1,110 @@
|
||||
'use client'
|
||||
|
||||
import Navbar from "@/components/Navbar/Navbar";
|
||||
import Footer from "@/components/Footer/Footer";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import styles from "./blog.module.css";
|
||||
import { blogData } from "@/utils/constant";
|
||||
import { motion } from "framer-motion";
|
||||
|
||||
export default function BlogPage() {
|
||||
// Animation variants
|
||||
const containerVariants = {
|
||||
hidden: { opacity: 0 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
transition: {
|
||||
staggerChildren: 0.15,
|
||||
delayChildren: 0.2
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const cardVariants = {
|
||||
hidden: {
|
||||
opacity: 0,
|
||||
y: 30
|
||||
},
|
||||
visible: {
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
transition: {
|
||||
duration: 0.6
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const heroVariants = {
|
||||
hidden: { opacity: 0, y: -20 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
transition: {
|
||||
duration: 0.8
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<main className={styles.main}>
|
||||
<Navbar />
|
||||
|
||||
<motion.section
|
||||
className={styles.hero}
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
variants={heroVariants}
|
||||
>
|
||||
<div className={styles.heroContent}>
|
||||
<h1 className={styles.heroTitle}>Our Blog</h1>
|
||||
<p className={styles.breadcrumb}>
|
||||
<Link href="/">Home</Link> / Blog
|
||||
</p>
|
||||
</div>
|
||||
</motion.section>
|
||||
|
||||
<section className={styles.blogSection}>
|
||||
<motion.div
|
||||
className={styles.grid}
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
variants={containerVariants}
|
||||
>
|
||||
{blogData.map((blog) => (
|
||||
<motion.div
|
||||
key={blog.id}
|
||||
className={styles.card}
|
||||
variants={cardVariants}
|
||||
whileHover={{
|
||||
y: -8,
|
||||
transition: { duration: 0.3 }
|
||||
}}
|
||||
>
|
||||
<div className={styles.imageContainer}>
|
||||
<Image
|
||||
src={blog.image}
|
||||
alt={blog.title}
|
||||
fill
|
||||
style={{ objectFit: 'cover' }}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.cardContent}>
|
||||
<h3 className={styles.blogTitle}>
|
||||
<Link href={`/blog/${blog.slug}`}>{blog.title}</Link>
|
||||
</h3>
|
||||
<p className={styles.date}>{blog.date}</p>
|
||||
<p className={styles.excerpt}>{blog.excerpt}</p>
|
||||
<Link href={`/blog/${blog.slug}`} className={styles.button}>
|
||||
Read More
|
||||
</Link>
|
||||
</div>
|
||||
</motion.div>
|
||||
))}
|
||||
</motion.div>
|
||||
</section>
|
||||
|
||||
<Footer />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
315
src/app/contact/contact.module.css
Normal file
315
src/app/contact/contact.module.css
Normal file
@ -0,0 +1,315 @@
|
||||
.main {
|
||||
background-color: var(--color-dark);
|
||||
color: var(--color-text-light);
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.hero {
|
||||
padding: 10rem 2rem;
|
||||
background: linear-gradient(rgba(0, 0, 0, 0.7), rgba(0, 0, 0, 0.7)), url('/images/hero-2.png');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.heroContent {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.heroTitle {
|
||||
font-family: var(--font-playfair);
|
||||
font-size: 4rem;
|
||||
color: #C5A059;
|
||||
margin-bottom: 1rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
.breadcrumb {
|
||||
font-size: 1.1rem;
|
||||
color: #C5A059;
|
||||
font-family: var(--font-lato);
|
||||
}
|
||||
|
||||
.breadcrumb a {
|
||||
color: #fff;
|
||||
transition: color 0.3s;
|
||||
}
|
||||
|
||||
.breadcrumb a:hover {
|
||||
color: var(--color-gold);
|
||||
}
|
||||
|
||||
.contactSection {
|
||||
padding: 80px 20px;
|
||||
background-color: #F5E6D3;
|
||||
/* background-image: url('/images/section-bg.jpg'); */
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 4rem;
|
||||
}
|
||||
|
||||
/* Left Side - Form Block */
|
||||
.formBlock {
|
||||
background-color: #F5E6D3;
|
||||
padding: 2.5rem;
|
||||
border: 4px solid #C5A059;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-family: var(--font-cinzel), serif;
|
||||
font-size: 2.5rem;
|
||||
color: #5d4037;
|
||||
margin-bottom: 1rem;
|
||||
font-weight: 600;
|
||||
border-bottom: 3px solid #C5A059;
|
||||
padding-bottom: 0.5rem;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 1rem;
|
||||
color: #5d4037;
|
||||
line-height: 1.6;
|
||||
margin-bottom: 2rem;
|
||||
font-family: var(--font-lato);
|
||||
}
|
||||
|
||||
.form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.formRow {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.formGroup {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.formLabel {
|
||||
font-family: var(--font-lato);
|
||||
color: #C5A059;
|
||||
font-size: 0.95rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.input,
|
||||
.textarea {
|
||||
background: #fff;
|
||||
border: 1px solid #d4c5b0;
|
||||
padding: 0.9rem;
|
||||
color: #C5A059;
|
||||
font-family: var(--font-lato);
|
||||
font-size: 0.95rem;
|
||||
transition: border-color 0.3s;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.input::placeholder,
|
||||
.textarea::placeholder {
|
||||
color: #a89b87;
|
||||
}
|
||||
|
||||
.input:focus,
|
||||
.textarea:focus {
|
||||
outline: none;
|
||||
border-color: #C5A059;
|
||||
}
|
||||
|
||||
.textarea {
|
||||
resize: vertical;
|
||||
min-height: 100px;
|
||||
}
|
||||
|
||||
.charCount {
|
||||
font-size: 0.85rem;
|
||||
color: #836839;
|
||||
text-align: right;
|
||||
font-family: var(--font-lato);
|
||||
}
|
||||
|
||||
.submitButton {
|
||||
background: #C5A059;
|
||||
border: none;
|
||||
color: #fff;
|
||||
padding: 15px 40px;
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
font-family: var(--font-lato);
|
||||
border-radius: 50px;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.submitButton:hover {
|
||||
background-color: #b08f4a;
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 12px rgba(197, 160, 89, 0.3);
|
||||
}
|
||||
|
||||
/* Alert Messages */
|
||||
.alert {
|
||||
padding: 1rem 1.5rem;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 1.5rem;
|
||||
font-family: var(--font-lato);
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.alertSuccess {
|
||||
background-color: #d4edda;
|
||||
color: #155724;
|
||||
border: 1px solid #c3e6cb;
|
||||
}
|
||||
|
||||
.alertDanger {
|
||||
background-color: #f8d7da;
|
||||
color: #721c24;
|
||||
border: 1px solid #f5c6cb;
|
||||
}
|
||||
|
||||
.errorText {
|
||||
color: #dc3545;
|
||||
font-size: 0.85rem;
|
||||
margin-top: 0.25rem;
|
||||
display: block;
|
||||
font-family: var(--font-lato);
|
||||
}
|
||||
|
||||
.recaptchaWrapper {
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
/* Right Side - Info Block */
|
||||
.infoBlock {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.locationCard {
|
||||
background: #F5E6D3;
|
||||
padding: 1.5rem;
|
||||
border: 4px solid #C5A059;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 1.5rem;
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
|
||||
.locationCard:hover {
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
|
||||
.iconWrapper {
|
||||
background: #C5A059;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.locationInfo {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.locationTitle {
|
||||
font-family: var(--font-cinzel), serif;
|
||||
font-size: 1.3rem;
|
||||
color: #5d4037;
|
||||
margin-bottom: 0.3rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.locationSubtitle {
|
||||
font-size: 0.9rem;
|
||||
color: #836839;
|
||||
margin-bottom: 0.5rem;
|
||||
font-family: var(--font-lato);
|
||||
}
|
||||
|
||||
.locationAddress,
|
||||
.locationPhone {
|
||||
font-size: 1rem;
|
||||
color: #5d4037;
|
||||
line-height: 1.6;
|
||||
font-family: var(--font-lato);
|
||||
}
|
||||
|
||||
.locationPhone {
|
||||
font-size: 1.2rem;
|
||||
font-weight: 600;
|
||||
color: #C5A059;
|
||||
}
|
||||
|
||||
.mapContainer {
|
||||
border: 4px solid #C5A059;
|
||||
overflow: hidden;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.mapContainer iframe {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
.container {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 3rem;
|
||||
}
|
||||
|
||||
.formRow {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.heroTitle {
|
||||
font-size: 3rem;
|
||||
}
|
||||
|
||||
.contactSection {
|
||||
padding: 60px 20px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.formRow {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.formBlock {
|
||||
padding: 2rem 1.5rem;
|
||||
}
|
||||
}
|
||||
384
src/app/contact/page.tsx
Normal file
384
src/app/contact/page.tsx
Normal file
@ -0,0 +1,384 @@
|
||||
'use client'
|
||||
|
||||
import { useState, useEffect } from "react";
|
||||
import ReCAPTCHA from "react-google-recaptcha";
|
||||
import axios from "axios";
|
||||
import Navbar from "@/components/Navbar/Navbar";
|
||||
import Footer from "@/components/Footer/Footer";
|
||||
import Link from "next/link";
|
||||
import styles from "./contact.module.css";
|
||||
import { motion } from "framer-motion";
|
||||
|
||||
interface FormErrors {
|
||||
name?: string;
|
||||
email?: string;
|
||||
phone?: string;
|
||||
date?: string;
|
||||
time?: string;
|
||||
captcha?: string;
|
||||
}
|
||||
|
||||
export default function ContactPage() {
|
||||
const [email, setEmail] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
const user = "info";
|
||||
const domain = "antalya-restaurant.com";
|
||||
setEmail(`${user}@${domain}`);
|
||||
}, []);
|
||||
|
||||
const [formData, setFormData] = useState({
|
||||
name: "",
|
||||
email: "",
|
||||
phone: "",
|
||||
guests: "2 Guests",
|
||||
date: "",
|
||||
time: "",
|
||||
requests: "",
|
||||
});
|
||||
|
||||
const [formErrors, setFormErrors] = useState<FormErrors>({});
|
||||
const [captchaToken, setCaptchaToken] = useState<string | null>(null);
|
||||
const [alert, setAlert] = useState({ show: false, type: "", message: "" });
|
||||
const [charCount, setCharCount] = useState(0);
|
||||
|
||||
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => {
|
||||
const { name, value } = e.target;
|
||||
setFormData((prev) => ({ ...prev, [name]: value }));
|
||||
|
||||
if (name === "requests") {
|
||||
setCharCount(value.length);
|
||||
}
|
||||
};
|
||||
|
||||
const handleCaptchaChange = (token: string | null) => {
|
||||
setCaptchaToken(token);
|
||||
};
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
|
||||
const errors: FormErrors = {};
|
||||
if (!formData.name.trim()) errors.name = "Name is required.";
|
||||
if (!formData.email.trim()) errors.email = "Email is required.";
|
||||
if (!formData.phone.trim()) errors.phone = "Phone is required.";
|
||||
if (!formData.date.trim()) errors.date = "Date is required.";
|
||||
if (!formData.time.trim()) errors.time = "Time is required.";
|
||||
if (!captchaToken) errors.captcha = "Please verify the CAPTCHA.";
|
||||
|
||||
setFormErrors(errors);
|
||||
if (Object.keys(errors).length > 0) return;
|
||||
|
||||
const emailData = {
|
||||
name: formData.name,
|
||||
phone: formData.phone,
|
||||
email: formData.email,
|
||||
subject: `Table Reservation - ${formData.guests} on ${formData.date}`,
|
||||
message: `
|
||||
<strong>Reservation Details:</strong><br/>
|
||||
Name: ${formData.name}<br/>
|
||||
Email: ${formData.email}<br/>
|
||||
Phone: ${formData.phone}<br/>
|
||||
Guests: ${formData.guests}<br/>
|
||||
Date: ${formData.date}<br/>
|
||||
Time: ${formData.time}<br/><br/>
|
||||
<strong>Special Requests:</strong><br/>
|
||||
${formData.requests || "None"}
|
||||
`,
|
||||
to: email,
|
||||
senderName: "Antalya Restaurant - Table Reservation",
|
||||
recaptchaToken: captchaToken,
|
||||
};
|
||||
|
||||
try {
|
||||
const res = await axios.post(
|
||||
"https://mailserver.metatronnest.com/send",
|
||||
emailData,
|
||||
{ headers: { "Content-Type": "application/json" } }
|
||||
);
|
||||
|
||||
setAlert({
|
||||
show: true,
|
||||
type: "success",
|
||||
message: res?.data?.message || "Reservation request sent successfully! We'll contact you soon.",
|
||||
});
|
||||
|
||||
setFormData({
|
||||
name: "",
|
||||
email: "",
|
||||
phone: "",
|
||||
guests: "2 Guests",
|
||||
date: "",
|
||||
time: "",
|
||||
requests: "",
|
||||
});
|
||||
setCaptchaToken(null);
|
||||
setFormErrors({});
|
||||
setCharCount(0);
|
||||
} catch (error) {
|
||||
setAlert({
|
||||
show: true,
|
||||
type: "danger",
|
||||
message: "Failed to send reservation request. Please try again later.",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (alert.show) {
|
||||
const timer = setTimeout(() => {
|
||||
setAlert((prev) => ({ ...prev, show: false }));
|
||||
}, 5000);
|
||||
return () => clearTimeout(timer);
|
||||
}
|
||||
}, [alert.show]);
|
||||
|
||||
return (
|
||||
<main className={styles.main}>
|
||||
<Navbar />
|
||||
|
||||
<motion.section
|
||||
className={styles.hero}
|
||||
initial={{ opacity: 0, y: -20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.8 }}
|
||||
>
|
||||
<div className={styles.heroContent}>
|
||||
<h1 className={styles.heroTitle}>Contact Us</h1>
|
||||
<p className={styles.breadcrumb}>
|
||||
<Link href="/">Home</Link> / Contact
|
||||
</p>
|
||||
</div>
|
||||
</motion.section>
|
||||
|
||||
<section className={styles.contactSection}>
|
||||
<motion.div
|
||||
className={styles.container}
|
||||
initial="hidden"
|
||||
whileInView="visible"
|
||||
viewport={{ once: true, margin: "-100px" }}
|
||||
transition={{ staggerChildren: 0.3 }}
|
||||
>
|
||||
{/* Left Side - Book a Table Form */}
|
||||
<motion.div
|
||||
className={styles.formBlock}
|
||||
initial={{ opacity: 0, x: -60 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.8 }}
|
||||
>
|
||||
<h2 className={styles.title}>Book a Table</h2>
|
||||
<p className={styles.subtitle}>
|
||||
Reserve your table for an unforgettable Turkish dining experience. We look forward to serving you our authentic cuisine.
|
||||
</p>
|
||||
|
||||
{alert.show && (
|
||||
<div className={`${styles.alert} ${styles[`alert${alert.type.charAt(0).toUpperCase() + alert.type.slice(1)}`]}`}>
|
||||
{alert.message}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<form className={styles.form} onSubmit={handleSubmit}>
|
||||
<div className={styles.formRow}>
|
||||
<div className={styles.formGroup}>
|
||||
<label htmlFor="name" className={styles.formLabel}>Name *</label>
|
||||
<input
|
||||
type="text"
|
||||
id="name"
|
||||
name="name"
|
||||
className={styles.input}
|
||||
placeholder="Your Full Name"
|
||||
value={formData.name}
|
||||
onChange={handleChange}
|
||||
required
|
||||
/>
|
||||
{formErrors.name && <small className={styles.errorText}>{formErrors.name}</small>}
|
||||
</div>
|
||||
|
||||
<div className={styles.formGroup}>
|
||||
<label htmlFor="email" className={styles.formLabel}>Email *</label>
|
||||
<input
|
||||
type="email"
|
||||
id="email"
|
||||
name="email"
|
||||
className={styles.input}
|
||||
placeholder="your@email.com"
|
||||
value={formData.email}
|
||||
onChange={handleChange}
|
||||
required
|
||||
/>
|
||||
{formErrors.email && <small className={styles.errorText}>{formErrors.email}</small>}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.formRow}>
|
||||
<div className={styles.formGroup}>
|
||||
<label htmlFor="phone" className={styles.formLabel}>Phone *</label>
|
||||
<input
|
||||
type="tel"
|
||||
id="phone"
|
||||
name="phone"
|
||||
className={styles.input}
|
||||
placeholder="(519) 000-0000"
|
||||
value={formData.phone}
|
||||
onChange={handleChange}
|
||||
required
|
||||
/>
|
||||
{formErrors.phone && <small className={styles.errorText}>{formErrors.phone}</small>}
|
||||
</div>
|
||||
|
||||
<div className={styles.formGroup}>
|
||||
<label htmlFor="guests" className={styles.formLabel}>Guests</label>
|
||||
<select
|
||||
id="guests"
|
||||
name="guests"
|
||||
className={styles.input}
|
||||
value={formData.guests}
|
||||
onChange={handleChange}
|
||||
>
|
||||
<option>1 Guest</option>
|
||||
<option>2 Guests</option>
|
||||
<option>3 Guests</option>
|
||||
<option>4 Guests</option>
|
||||
<option>5 Guests</option>
|
||||
<option>6+ Guests</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.formRow}>
|
||||
<div className={styles.formGroup}>
|
||||
<label htmlFor="date" className={styles.formLabel}>Date *</label>
|
||||
<input
|
||||
type="date"
|
||||
id="date"
|
||||
name="date"
|
||||
className={styles.input}
|
||||
value={formData.date}
|
||||
onChange={handleChange}
|
||||
required
|
||||
/>
|
||||
{formErrors.date && <small className={styles.errorText}>{formErrors.date}</small>}
|
||||
</div>
|
||||
|
||||
<div className={styles.formGroup}>
|
||||
<label htmlFor="time" className={styles.formLabel}>Time *</label>
|
||||
<input
|
||||
type="time"
|
||||
id="time"
|
||||
name="time"
|
||||
className={styles.input}
|
||||
value={formData.time}
|
||||
onChange={handleChange}
|
||||
required
|
||||
/>
|
||||
{formErrors.time && <small className={styles.errorText}>{formErrors.time}</small>}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.formGroup}>
|
||||
<label htmlFor="requests" className={styles.formLabel}>Special Requests</label>
|
||||
<textarea
|
||||
id="requests"
|
||||
name="requests"
|
||||
className={styles.textarea}
|
||||
placeholder="Any special dietary requirements or requests..."
|
||||
rows={4}
|
||||
maxLength={500}
|
||||
value={formData.requests}
|
||||
onChange={handleChange}
|
||||
></textarea>
|
||||
<span className={styles.charCount}>{charCount}/500 characters</span>
|
||||
</div>
|
||||
|
||||
<div className={styles.recaptchaWrapper}>
|
||||
<ReCAPTCHA
|
||||
sitekey="6Lckq9MrAAAAABjBD9rQYm19BMGFFWiwb9mPiw2K"
|
||||
onChange={handleCaptchaChange}
|
||||
/>
|
||||
{formErrors.captcha && <small className={styles.errorText}>{formErrors.captcha}</small>}
|
||||
</div>
|
||||
|
||||
<button type="submit" className={styles.submitButton}>
|
||||
Reserve Table
|
||||
</button>
|
||||
</form>
|
||||
</motion.div>
|
||||
|
||||
{/* Right Side - Location Info & Map */}
|
||||
<motion.div
|
||||
className={styles.infoBlock}
|
||||
initial={{ opacity: 0, x: 60 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.8 }}
|
||||
>
|
||||
{/* Location Cards */}
|
||||
<div className={styles.locationCard}>
|
||||
<div className={styles.iconWrapper}>
|
||||
<svg className={styles.icon} fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z" />
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 11a3 3 0 11-6 0 3 3 0 016 0z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div className={styles.locationInfo}>
|
||||
<h3 className={styles.locationTitle}>Kitchener Location</h3>
|
||||
<p className={styles.locationSubtitle}>Main Restaurant</p>
|
||||
<p className={styles.locationAddress}>
|
||||
1187 Fischer-Hallman Rd #411<br />
|
||||
Kitchener, ON N2T 4H2
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.locationCard}>
|
||||
<div className={styles.iconWrapper}>
|
||||
<svg className={styles.icon} fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z" />
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 11a3 3 0 11-6 0 3 3 0 016 0z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div className={styles.locationInfo}>
|
||||
<h3 className={styles.locationTitle}>Burlington Location</h3>
|
||||
<p className={styles.locationSubtitle}>Second Location</p>
|
||||
<p className={styles.locationAddress}>
|
||||
1860 Appleby Line<br />
|
||||
Burlington, ON L7L 7H7
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.locationCard}>
|
||||
<div className={styles.iconWrapper}>
|
||||
<svg className={styles.icon} fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div className={styles.locationInfo}>
|
||||
<h3 className={styles.locationTitle}>Call Us</h3>
|
||||
<p className={styles.locationSubtitle}>For reservations & inquiries</p>
|
||||
<p className={styles.locationPhone}>(519) 570-4848</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Map */}
|
||||
<div className={styles.mapContainer}>
|
||||
<iframe
|
||||
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d2895.8474424447677!2d-80.48089492346795!3d43.44826897111238!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x882b8b1e1e1e1e1e%3A0x1e1e1e1e1e1e1e1e!2s1187%20Fischer-Hallman%20Rd%2C%20Kitchener%2C%20ON!5e0!3m2!1sen!2sca!4v1234567890123!5m2!1sen!2sca"
|
||||
width="100%"
|
||||
height="300"
|
||||
style={{ border: 0 }}
|
||||
allowFullScreen
|
||||
loading="lazy"
|
||||
referrerPolicy="no-referrer-when-downgrade"
|
||||
title="Restaurant Location Map"
|
||||
></iframe>
|
||||
</div>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
</section>
|
||||
|
||||
<Footer />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
219
src/app/gallery/gallery.module.css
Normal file
219
src/app/gallery/gallery.module.css
Normal file
@ -0,0 +1,219 @@
|
||||
.main {
|
||||
background-color: var(--color-dark);
|
||||
color: var(--color-text-light);
|
||||
min-height: 100vh;
|
||||
background-color: #f5e6d3;
|
||||
}
|
||||
|
||||
.hero {
|
||||
padding: 10rem 2rem;
|
||||
background: linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.6)), url('/images/hero-2.png');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.heroContent {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.heroTitle {
|
||||
font-family: var(--font-playfair);
|
||||
font-size: 4rem;
|
||||
color: #C5A059;
|
||||
margin-bottom: 1rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
.breadcrumb {
|
||||
font-size: 1.1rem;
|
||||
color: #C5A059;
|
||||
font-family: var(--font-lato);
|
||||
}
|
||||
|
||||
.breadcrumb a {
|
||||
color: #fff;
|
||||
transition: color 0.3s;
|
||||
}
|
||||
|
||||
.breadcrumb a:hover {
|
||||
color: var(--color-gold);
|
||||
}
|
||||
|
||||
.section {
|
||||
padding: 80px 20px;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
/* background-color: #0a0a0a; */
|
||||
}
|
||||
|
||||
.tabs {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 1.5rem;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.tab {
|
||||
background: transparent;
|
||||
border: 2px solid #C5A059;
|
||||
color: #C5A059;
|
||||
padding: 12px 30px;
|
||||
font-size: 1rem;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
font-family: var(--font-lato);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tab:hover,
|
||||
.activeTab {
|
||||
background-color: #C5A059;
|
||||
color: #F5E6D3;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.imageWrapper {
|
||||
position: relative;
|
||||
aspect-ratio: 4/3;
|
||||
cursor: pointer;
|
||||
overflow: hidden;
|
||||
border: 4px solid #C5A059;
|
||||
}
|
||||
|
||||
.image {
|
||||
object-fit: cover;
|
||||
transition: transform 0.5s ease;
|
||||
}
|
||||
|
||||
.imageWrapper:hover .image {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(58, 12, 8, 0.7);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.imageWrapper:hover .overlay {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.viewText {
|
||||
color: #C5A059;
|
||||
font-size: 1.2rem;
|
||||
border: 2px solid #C5A059;
|
||||
padding: 0.5rem 1.5rem;
|
||||
font-family: var(--font-lato);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
/* Lightbox */
|
||||
.lightbox {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.95);
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.lightboxContent {
|
||||
position: relative;
|
||||
width: 90%;
|
||||
height: 80%;
|
||||
max-width: 1000px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.lightboxImageWrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.closeBtn {
|
||||
position: absolute;
|
||||
top: -40px;
|
||||
right: 0;
|
||||
background: none;
|
||||
border: none;
|
||||
color: #C5A059;
|
||||
font-size: 2.5rem;
|
||||
cursor: pointer;
|
||||
transition: color 0.3s;
|
||||
}
|
||||
|
||||
.closeBtn:hover {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.navBtn {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
background: rgba(197, 160, 89, 0.2);
|
||||
border: 2px solid #C5A059;
|
||||
color: #C5A059;
|
||||
font-size: 2rem;
|
||||
padding: 1rem;
|
||||
cursor: pointer;
|
||||
z-index: 10;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.navBtn:hover {
|
||||
background: rgba(197, 160, 89, 0.5);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.prevBtn {
|
||||
left: -60px;
|
||||
}
|
||||
|
||||
.nextBtn {
|
||||
right: -60px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.heroTitle {
|
||||
font-size: 3rem;
|
||||
}
|
||||
|
||||
.prevBtn {
|
||||
left: 10px;
|
||||
}
|
||||
|
||||
.nextBtn {
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
.tabs {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
209
src/app/gallery/page.tsx
Normal file
209
src/app/gallery/page.tsx
Normal file
@ -0,0 +1,209 @@
|
||||
'use client'
|
||||
|
||||
import { useState } from 'react';
|
||||
import Navbar from "@/components/Navbar/Navbar";
|
||||
import Footer from "@/components/Footer/Footer";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import styles from "./gallery.module.css";
|
||||
import { galleryData } from "@/utils/constant";
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
|
||||
const categories = ['All', 'Food', 'Interior'];
|
||||
|
||||
export default function GalleryPage() {
|
||||
const [activeTab, setActiveTab] = useState('All');
|
||||
const [lightboxOpen, setLightboxOpen] = useState(false);
|
||||
const [currentIndex, setCurrentIndex] = useState(0);
|
||||
|
||||
// Animation variants
|
||||
const heroVariants = {
|
||||
hidden: { opacity: 0, y: -20 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
transition: { duration: 0.8 }
|
||||
}
|
||||
};
|
||||
|
||||
const tabsVariants = {
|
||||
hidden: { opacity: 0, y: 20 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
transition: {
|
||||
duration: 0.6,
|
||||
staggerChildren: 0.1
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const tabVariants = {
|
||||
hidden: { opacity: 0, y: 10 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
transition: { duration: 0.4 }
|
||||
}
|
||||
};
|
||||
|
||||
const gridVariants = {
|
||||
hidden: { opacity: 0 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
transition: {
|
||||
staggerChildren: 0.08,
|
||||
delayChildren: 0.1
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const imageVariants = {
|
||||
hidden: { opacity: 0, scale: 0.9 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
scale: 1,
|
||||
transition: { duration: 0.5 }
|
||||
}
|
||||
};
|
||||
|
||||
const filteredImages = activeTab === 'All'
|
||||
? galleryData
|
||||
: galleryData.filter(img => img.category === activeTab);
|
||||
|
||||
const openLightbox = (index: number) => {
|
||||
setCurrentIndex(index);
|
||||
setLightboxOpen(true);
|
||||
};
|
||||
|
||||
const closeLightbox = () => {
|
||||
setLightboxOpen(false);
|
||||
};
|
||||
|
||||
const nextImage = (e: React.MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
setCurrentIndex((prev) => (prev + 1) % filteredImages.length);
|
||||
};
|
||||
|
||||
const prevImage = (e: React.MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
setCurrentIndex((prev) => (prev - 1 + filteredImages.length) % filteredImages.length);
|
||||
};
|
||||
|
||||
return (
|
||||
<main className={styles.main}>
|
||||
<Navbar />
|
||||
|
||||
<motion.section
|
||||
className={styles.hero}
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
variants={heroVariants}
|
||||
>
|
||||
<div className={styles.heroContent}>
|
||||
<h1 className={styles.heroTitle}>Our Gallery</h1>
|
||||
<p className={styles.breadcrumb}>
|
||||
<Link href="/">Home</Link> / Gallery
|
||||
</p>
|
||||
</div>
|
||||
</motion.section>
|
||||
|
||||
<section className={styles.section}>
|
||||
<motion.div
|
||||
className={styles.tabs}
|
||||
initial="hidden"
|
||||
whileInView="visible"
|
||||
viewport={{ once: true }}
|
||||
variants={tabsVariants}
|
||||
>
|
||||
{categories.map(category => (
|
||||
<motion.button
|
||||
key={category}
|
||||
className={`${styles.tab} ${activeTab === category ? styles.activeTab : ''}`}
|
||||
onClick={() => setActiveTab(category)}
|
||||
variants={tabVariants}
|
||||
whileHover={{ scale: 1.05 }}
|
||||
whileTap={{ scale: 0.95 }}
|
||||
>
|
||||
{category}
|
||||
</motion.button>
|
||||
))}
|
||||
</motion.div>
|
||||
|
||||
<motion.div
|
||||
className={styles.grid}
|
||||
key={activeTab}
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
variants={gridVariants}
|
||||
>
|
||||
{filteredImages.map((img, index) => (
|
||||
<motion.div
|
||||
key={img.id}
|
||||
className={styles.imageWrapper}
|
||||
onClick={() => openLightbox(index)}
|
||||
variants={imageVariants}
|
||||
whileHover={{
|
||||
scale: 1.05,
|
||||
transition: { duration: 0.3 }
|
||||
}}
|
||||
>
|
||||
<Image
|
||||
src={img.src}
|
||||
alt={img.alt}
|
||||
fill
|
||||
className={styles.image}
|
||||
/>
|
||||
<div className={styles.overlay}>
|
||||
<span className={styles.viewText}>View</span>
|
||||
</div>
|
||||
</motion.div>
|
||||
))}
|
||||
</motion.div>
|
||||
</section>
|
||||
|
||||
<AnimatePresence>
|
||||
{lightboxOpen && (
|
||||
<motion.div
|
||||
className={styles.lightbox}
|
||||
onClick={closeLightbox}
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
transition={{ duration: 0.3 }}
|
||||
>
|
||||
<motion.div
|
||||
className={styles.lightboxContent}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
initial={{ scale: 0.8, opacity: 0 }}
|
||||
animate={{ scale: 1, opacity: 1 }}
|
||||
exit={{ scale: 0.8, opacity: 0 }}
|
||||
transition={{ duration: 0.3 }}
|
||||
>
|
||||
<button className={styles.closeBtn} onClick={closeLightbox}>×</button>
|
||||
<button className={`${styles.navBtn} ${styles.prevBtn}`} onClick={prevImage}>‹</button>
|
||||
<motion.div
|
||||
className={styles.lightboxImageWrapper}
|
||||
key={currentIndex}
|
||||
initial={{ opacity: 0, x: 50 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
exit={{ opacity: 0, x: -50 }}
|
||||
transition={{ duration: 0.3 }}
|
||||
>
|
||||
<Image
|
||||
src={filteredImages[currentIndex].src}
|
||||
alt={filteredImages[currentIndex].alt}
|
||||
fill
|
||||
style={{ objectFit: 'contain' }}
|
||||
/>
|
||||
</motion.div>
|
||||
<button className={`${styles.navBtn} ${styles.nextBtn}`} onClick={nextImage}>›</button>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
|
||||
<Footer />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
@ -1,10 +1,11 @@
|
||||
:root {
|
||||
--color-gold: #bf9b30;
|
||||
--color-gold: #b28839;
|
||||
--color-dark: #0a0a0a;
|
||||
--color-input-bg: #e8e0d5;
|
||||
--color-text-light: #f5f5f5;
|
||||
--font-playfair: 'Playfair Display', serif;
|
||||
--font-lato: 'Lato', sans-serif;
|
||||
--font-cormorant: 'Cormorant Garamond', serif;
|
||||
}
|
||||
|
||||
* {
|
||||
@ -19,7 +20,8 @@ body {
|
||||
overflow-x: hidden;
|
||||
background-color: var(--color-dark);
|
||||
color: var(--color-text-light);
|
||||
font-family: var(--font-lato);
|
||||
font-family: var(--font-cormorant);
|
||||
font-weight: 300;
|
||||
/* Ensure default font is applied */
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import type { Metadata } from "next";
|
||||
import { Playfair_Display, Lato, Cinzel, Inter } from "next/font/google";
|
||||
import { Playfair_Display, Lato, Cinzel, Inter, Cormorant_Garamond } from "next/font/google";
|
||||
import "./globals.css";
|
||||
import ScrollToTop from "@/components/ScrollToTop/ScrollToTop";
|
||||
|
||||
@ -28,6 +28,13 @@ const inter = Inter({
|
||||
display: "swap",
|
||||
});
|
||||
|
||||
const cormorantGaramond = Cormorant_Garamond({
|
||||
weight: ["300", "400"],
|
||||
subsets: ["latin"],
|
||||
variable: "--font-cormorant",
|
||||
display: "swap",
|
||||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Antalya Restaurant - Book A Table",
|
||||
description: "Experience luxury dining at Antalya Restaurant.",
|
||||
@ -41,8 +48,8 @@ export default function RootLayout({
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
return (
|
||||
<html lang="en" className={`${playfair.variable} ${lato.variable} ${cinzel.variable} ${inter.variable}`}>
|
||||
<body className={lato.className}>
|
||||
<html lang="en" className={`${playfair.variable} ${lato.variable} ${cinzel.variable} ${inter.variable} ${cormorantGaramond.variable}`}>
|
||||
<body className={cormorantGaramond.className}>
|
||||
<Navbar />
|
||||
{children}
|
||||
<ScrollToTop />
|
||||
|
||||
289
src/app/menu/menu.module.css
Normal file
289
src/app/menu/menu.module.css
Normal file
@ -0,0 +1,289 @@
|
||||
.main {
|
||||
background-color: var(--color-dark);
|
||||
color: var(--color-text-light);
|
||||
min-height: 100vh;
|
||||
background-color: #f5e6d3;
|
||||
}
|
||||
|
||||
.hero {
|
||||
padding: 10rem 2rem;
|
||||
background: linear-gradient(rgba(0, 0, 0, 0.7), rgba(0, 0, 0, 0.7)), url('/images/hero-3.png');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-attachment: fixed;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.heroContent {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.heroTitle {
|
||||
font-family: var(--font-playfair);
|
||||
font-size: 4rem;
|
||||
color: #C5A059;
|
||||
margin-bottom: 1rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
.breadcrumb {
|
||||
font-size: 1.1rem;
|
||||
color: #C5A059;
|
||||
font-family: var(--font-lato);
|
||||
}
|
||||
|
||||
.breadcrumb a {
|
||||
color: #fff;
|
||||
transition: color 0.3s;
|
||||
}
|
||||
|
||||
.breadcrumb a:hover {
|
||||
color: var(--color-gold);
|
||||
}
|
||||
|
||||
.menuSection {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 60px 20px 80px;
|
||||
/* background-color: #0a0a0a; */
|
||||
}
|
||||
|
||||
/* Category Tabs */
|
||||
.tabs {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 1.5rem;
|
||||
margin-bottom: 3rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.tab {
|
||||
background: transparent;
|
||||
border: 2px solid #C5A059;
|
||||
color: #C5A059;
|
||||
padding: 12px 30px;
|
||||
font-size: 1rem;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
font-family: var(--font-playfair);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tab:hover,
|
||||
.activeTab {
|
||||
background-color: #C5A059;
|
||||
color: #F5E6D3;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.menuGrid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.menuCard {
|
||||
display: flex;
|
||||
gap: 1.2rem;
|
||||
background: #c5a059;
|
||||
padding: 1.2rem;
|
||||
border: 1px solid rgba(197, 160, 89, 0.2);
|
||||
transition: all 0.4s ease;
|
||||
animation: fadeInUp 0.6s ease forwards;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.menuCard:nth-child(1) {
|
||||
animation-delay: 0.1s;
|
||||
}
|
||||
|
||||
.menuCard:nth-child(2) {
|
||||
animation-delay: 0.2s;
|
||||
}
|
||||
|
||||
.menuCard:nth-child(3) {
|
||||
animation-delay: 0.3s;
|
||||
}
|
||||
|
||||
.menuCard:nth-child(4) {
|
||||
animation-delay: 0.4s;
|
||||
}
|
||||
|
||||
.menuCard:nth-child(5) {
|
||||
animation-delay: 0.5s;
|
||||
}
|
||||
|
||||
.menuCard:nth-child(6) {
|
||||
animation-delay: 0.6s;
|
||||
}
|
||||
|
||||
@keyframes fadeInUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.menuCard:hover {
|
||||
background: #c5a059;
|
||||
border-color: #F5E6D3;
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 10px 30px rgba(197, 160, 89, 0.2);
|
||||
}
|
||||
|
||||
.imageFrame {
|
||||
position: relative;
|
||||
width: 130px;
|
||||
height: 130px;
|
||||
flex-shrink: 0;
|
||||
padding: 6px;
|
||||
background: linear-gradient(135deg, rgba(197, 160, 89, 0.1), rgba(197, 160, 89, 0.05));
|
||||
}
|
||||
|
||||
.imageWrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 2px solid #F5E6D3;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.dishImage {
|
||||
object-fit: cover;
|
||||
transition: transform 0.5s ease;
|
||||
}
|
||||
|
||||
.menuCard:hover .dishImage {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
/* Corner decorations */
|
||||
.cornerTL,
|
||||
.cornerTR,
|
||||
.cornerBL,
|
||||
.cornerBR {
|
||||
position: absolute;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
border: 2px solid #F5E6D3;
|
||||
}
|
||||
|
||||
.cornerTL {
|
||||
top: 0;
|
||||
left: 0;
|
||||
border-right: none;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.cornerTR {
|
||||
top: 0;
|
||||
right: 0;
|
||||
border-left: none;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.cornerBL {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
border-right: none;
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.cornerBR {
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
border-left: none;
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.cardContent {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.cardHeader {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: baseline;
|
||||
margin-bottom: 0.6rem;
|
||||
}
|
||||
|
||||
.dishName {
|
||||
font-family: var(--font-playfair);
|
||||
font-size: 1.3rem;
|
||||
color: #F5E6D3;
|
||||
text-transform: capitalize;
|
||||
transition: color 0.3s;
|
||||
}
|
||||
|
||||
.menuCard:hover .dishName {
|
||||
color: #F5E6D3;
|
||||
}
|
||||
|
||||
.price {
|
||||
font-size: 1.2rem;
|
||||
color: #F5E6D3;
|
||||
font-weight: bold;
|
||||
font-family: var(--font-playfair);
|
||||
}
|
||||
|
||||
.description {
|
||||
font-size: 0.9rem;
|
||||
color: #F5E6D3;
|
||||
line-height: 1.6;
|
||||
font-family: var(--font-lato);
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
@media (max-width: 968px) {
|
||||
.menuGrid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.heroTitle {
|
||||
font-size: 3rem;
|
||||
}
|
||||
|
||||
.menuSection {
|
||||
padding: 40px 20px 60px;
|
||||
}
|
||||
|
||||
.tabs {
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.tab {
|
||||
padding: 10px 20px;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.menuCard {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.imageFrame {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
}
|
||||
|
||||
.cardHeader {
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
155
src/app/menu/page.tsx
Normal file
155
src/app/menu/page.tsx
Normal file
@ -0,0 +1,155 @@
|
||||
'use client'
|
||||
|
||||
import { useState } from 'react';
|
||||
import Navbar from "@/components/Navbar/Navbar";
|
||||
import Footer from "@/components/Footer/Footer";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import styles from "./menu.module.css";
|
||||
import { menuData } from "@/utils/constant";
|
||||
import { motion } from "framer-motion";
|
||||
|
||||
export default function MenuPage() {
|
||||
const [activeCategory, setActiveCategory] = useState(0);
|
||||
|
||||
// Animation variants
|
||||
const heroVariants = {
|
||||
hidden: { opacity: 0, y: -20 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
transition: { duration: 0.8 }
|
||||
}
|
||||
};
|
||||
|
||||
const tabsVariants = {
|
||||
hidden: { opacity: 0, y: 20 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
transition: {
|
||||
staggerChildren: 0.1,
|
||||
delayChildren: 0.2
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const tabVariants = {
|
||||
hidden: { opacity: 0, y: 10 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
transition: { duration: 0.4 }
|
||||
}
|
||||
};
|
||||
|
||||
const gridVariants = {
|
||||
hidden: { opacity: 0 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
transition: {
|
||||
staggerChildren: 0.1,
|
||||
delayChildren: 0.2
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const cardVariants = {
|
||||
hidden: { opacity: 0, y: 30 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
transition: { duration: 0.5 }
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<main className={styles.main}>
|
||||
<Navbar />
|
||||
|
||||
<motion.section
|
||||
className={styles.hero}
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
variants={heroVariants}
|
||||
>
|
||||
<div className={styles.heroContent}>
|
||||
<h1 className={styles.heroTitle}>Our Menu</h1>
|
||||
<p className={styles.breadcrumb}>
|
||||
<Link href="/">Home</Link> / Menu
|
||||
</p>
|
||||
</div>
|
||||
</motion.section>
|
||||
|
||||
<section className={styles.menuSection}>
|
||||
{/* Category Tabs */}
|
||||
<motion.div
|
||||
className={styles.tabs}
|
||||
initial="hidden"
|
||||
whileInView="visible"
|
||||
viewport={{ once: true }}
|
||||
variants={tabsVariants}
|
||||
>
|
||||
{menuData.map((section, index) => (
|
||||
<motion.button
|
||||
key={index}
|
||||
className={`${styles.tab} ${activeCategory === index ? styles.activeTab : ''}`}
|
||||
onClick={() => setActiveCategory(index)}
|
||||
variants={tabVariants}
|
||||
whileHover={{ scale: 1.05 }}
|
||||
whileTap={{ scale: 0.95 }}
|
||||
>
|
||||
{section.category}
|
||||
</motion.button>
|
||||
))}
|
||||
</motion.div>
|
||||
|
||||
{/* Menu Items Grid */}
|
||||
<motion.div
|
||||
className={styles.menuGrid}
|
||||
key={activeCategory}
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
variants={gridVariants}
|
||||
>
|
||||
{menuData[activeCategory].items.map((item, itemIndex) => (
|
||||
<motion.div
|
||||
key={itemIndex}
|
||||
className={styles.menuCard}
|
||||
variants={cardVariants}
|
||||
whileHover={{
|
||||
y: -8,
|
||||
transition: { duration: 0.3 }
|
||||
}}
|
||||
>
|
||||
<div className={styles.imageFrame}>
|
||||
<div className={styles.imageWrapper}>
|
||||
<Image
|
||||
src={item.image}
|
||||
alt={item.name}
|
||||
fill
|
||||
className={styles.dishImage}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.cornerTL}></div>
|
||||
<div className={styles.cornerTR}></div>
|
||||
<div className={styles.cornerBL}></div>
|
||||
<div className={styles.cornerBR}></div>
|
||||
</div>
|
||||
|
||||
<div className={styles.cardContent}>
|
||||
<div className={styles.cardHeader}>
|
||||
<h3 className={styles.dishName}>{item.name}</h3>
|
||||
<span className={styles.price}>{item.price}</span>
|
||||
</div>
|
||||
<p className={styles.description}>{item.description}</p>
|
||||
</div>
|
||||
</motion.div>
|
||||
))}
|
||||
</motion.div>
|
||||
</section>
|
||||
|
||||
<Footer />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
@ -1,4 +1,3 @@
|
||||
import Navbar from "@/components/Navbar/Navbar";
|
||||
import Hero from "@/components/Hero/Hero";
|
||||
import PopularDishes from "@/components/PopularDishes/PopularDishes";
|
||||
import About from "@/components/About/About";
|
||||
@ -11,7 +10,6 @@ import Footer from "@/components/Footer/Footer";
|
||||
export default function Home() {
|
||||
return (
|
||||
<main>
|
||||
<Navbar />
|
||||
<Hero />
|
||||
<PopularDishes />
|
||||
<About />
|
||||
|
||||
@ -1,20 +1,41 @@
|
||||
'use client'
|
||||
|
||||
import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
import styles from './About.module.css'
|
||||
import { motion } from 'framer-motion'
|
||||
|
||||
export default function About() {
|
||||
return (
|
||||
<section className={styles.section} id="about">
|
||||
<div className={styles.container}>
|
||||
<div className={styles.imageWrapper}>
|
||||
<motion.div
|
||||
className={styles.container}
|
||||
initial="hidden"
|
||||
whileInView="visible"
|
||||
viewport={{ once: true, margin: "-100px" }}
|
||||
transition={{ staggerChildren: 0.3 }}
|
||||
>
|
||||
<motion.div
|
||||
className={styles.imageWrapper}
|
||||
initial={{ opacity: 0, x: -60 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.8 }}
|
||||
>
|
||||
<Image
|
||||
src="/images/restaurant-interior.png"
|
||||
alt="About Antalya Interior"
|
||||
fill
|
||||
className={styles.image}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.content}>
|
||||
</motion.div>
|
||||
<motion.div
|
||||
className={styles.content}
|
||||
initial={{ opacity: 0, x: 60 }}
|
||||
whileInView={{ opacity: 1, x: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.8 }}
|
||||
>
|
||||
{/* Decorative Icon SVG */}
|
||||
<svg className={styles.icon} viewBox="0 0 100 100" fill="currentColor">
|
||||
<path d="M50 0 C60 20 80 40 100 50 C80 60 60 80 50 100 C40 80 20 60 0 50 C20 40 40 20 50 0 Z" />
|
||||
@ -31,8 +52,8 @@ export default function About() {
|
||||
<Link href="#about-more" className={styles.button}>
|
||||
Learn More
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
.section {
|
||||
padding: 80px 20px;
|
||||
background-color: #3a0c08;
|
||||
/* Dark red/brown background */
|
||||
background-image: url('/images/pattern-overlay.png');
|
||||
/* Optional pattern */
|
||||
background-image: url('/images/section-bg.jpg');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
@ -21,19 +21,12 @@
|
||||
.sliderContainer {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
padding: 0 40px;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 30px;
|
||||
max-width: 1400px;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
padding: 0 60px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.card {
|
||||
@ -46,7 +39,9 @@
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
transition: transform 0.3s ease;
|
||||
height: 100%;
|
||||
flex: 0 0 calc(33.333% - 30px);
|
||||
max-width: calc(33.333% - 30px);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
@ -103,20 +98,28 @@
|
||||
}
|
||||
|
||||
.arrow {
|
||||
background: none;
|
||||
border: none;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
color: #C5A059;
|
||||
font-size: 3rem;
|
||||
cursor: pointer;
|
||||
background: none;
|
||||
border: none;
|
||||
transition: transform 0.2s;
|
||||
padding: 0 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.arrow:hover {
|
||||
transform: scale(1.1);
|
||||
transform: translateY(-50%) scale(1.1);
|
||||
}
|
||||
|
||||
.prevArrow {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.nextArrow {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.viewMoreContainer {
|
||||
@ -127,15 +130,13 @@
|
||||
display: inline-block;
|
||||
padding: 15px 40px;
|
||||
border: 1px solid #C5A059;
|
||||
color: #C5A059;
|
||||
color: #fff;
|
||||
font-family: var(--font-inter), sans-serif;
|
||||
text-transform: uppercase;
|
||||
font-size: 1rem;
|
||||
text-decoration: none;
|
||||
transition: all 0.3s ease;
|
||||
background: transparent;
|
||||
border-radius: 5px;
|
||||
/* Slight radius as per some designs, or keep square */
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
@ -144,12 +145,88 @@
|
||||
color: #000;
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
.grid {
|
||||
grid-template-columns: 1fr;
|
||||
/* Responsive adjustments for different viewport sizes */
|
||||
@media (max-width: 1400px) {
|
||||
.sliderContainer {
|
||||
padding: 0 50px;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
font-size: 2.8rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
.sliderContainer {
|
||||
padding: 0 40px;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
.sliderContainer {
|
||||
padding: 0 30px;
|
||||
}
|
||||
|
||||
.card {
|
||||
flex: 0 0 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
/* Hide 2nd and 3rd cards on mobile, show only 1st */
|
||||
.card:nth-child(2),
|
||||
.card:nth-child(3) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
font-size: 2.2rem;
|
||||
}
|
||||
|
||||
.prevArrow {
|
||||
left: 5px;
|
||||
}
|
||||
|
||||
.nextArrow {
|
||||
right: 5px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.sliderContainer {
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.prevArrow {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.nextArrow {
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.sliderContainer {
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
@ -1,61 +1,73 @@
|
||||
'use client'
|
||||
|
||||
import { useState, useEffect } from 'react'
|
||||
import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
import styles from './Blogs.module.css'
|
||||
|
||||
const blogs = [
|
||||
{
|
||||
id: 1,
|
||||
title: 'The Art of Turkish Tea',
|
||||
image: '/images/dish-1.png', // Placeholder
|
||||
excerpt: 'Lorem ipsum dolor sit amet, tuem cergat imlpecion diirm, iadioc-ticid est nt eedrama inapat.'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Secrets of Charcoal Grilling',
|
||||
image: '/images/hero-3.png', // Placeholder
|
||||
excerpt: 'Lorem ipsum dolor sit amet, tuem cergat imlpecion diirm, iadioc-ticid est nt eedrama inapat.'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: 'A Taste of Sweet Legacy',
|
||||
image: '/images/dish-2.png', // Placeholder
|
||||
excerpt: 'Lorem ipsum dolor sit amet, tuem cergat imlpecion diirm, iadioc-ticid est nt eedrama inapat.'
|
||||
}
|
||||
]
|
||||
import { blogData } from '@/utils/constant'
|
||||
|
||||
export default function Blogs() {
|
||||
const [currentIndex, setCurrentIndex] = useState(0)
|
||||
|
||||
const nextSlide = () => {
|
||||
setCurrentIndex((prev) => (prev + 1) % blogData.length)
|
||||
}
|
||||
|
||||
const prevSlide = () => {
|
||||
setCurrentIndex((prev) => (prev === 0 ? blogData.length - 1 : prev - 1))
|
||||
}
|
||||
|
||||
// Auto-slide effect
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
setCurrentIndex((prev) => (prev + 1) % blogData.length)
|
||||
}, 5000) // Change slide every 5 seconds
|
||||
|
||||
return () => clearInterval(interval)
|
||||
}, [currentIndex])
|
||||
|
||||
// Get the 3 visible blogs
|
||||
const getVisibleBlogs = () => {
|
||||
const items = []
|
||||
for (let i = 0; i < 3; i++) {
|
||||
const index = (currentIndex + i) % blogData.length
|
||||
items.push(blogData[index])
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
||||
const visibleItems = getVisibleBlogs()
|
||||
|
||||
return (
|
||||
<section className={styles.section} id="blog">
|
||||
<h2 className={styles.title}>OUR BLOGS</h2>
|
||||
|
||||
<div className={styles.sliderContainer}>
|
||||
<button className={styles.arrow}>←</button>
|
||||
<button className={`${styles.arrow} ${styles.prevArrow}`} onClick={prevSlide}>←</button>
|
||||
|
||||
<div className={styles.grid}>
|
||||
{blogs.map((blog) => (
|
||||
<div key={blog.id} className={styles.card}>
|
||||
<div className={styles.imageContainer}>
|
||||
<Image
|
||||
src={blog.image}
|
||||
alt={blog.title}
|
||||
fill
|
||||
style={{ objectFit: 'cover' }}
|
||||
/>
|
||||
</div>
|
||||
<h3 className={styles.blogTitle}>{blog.title}</h3>
|
||||
<p className={styles.excerpt}>{blog.excerpt}</p>
|
||||
<Link href="#" className={styles.button}>
|
||||
View More
|
||||
</Link>
|
||||
{visibleItems.map((blog) => (
|
||||
<div key={blog.id} className={styles.card}>
|
||||
<div className={styles.imageContainer}>
|
||||
<Image
|
||||
src={blog.imageDetail}
|
||||
alt={blog.title}
|
||||
fill
|
||||
style={{ objectFit: 'cover' }}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<h3 className={styles.blogTitle}>{blog.title}</h3>
|
||||
<p className={styles.excerpt}>{blog.para}</p>
|
||||
<Link href={`/blog/${blog.slug}`} className={styles.button}>
|
||||
View More
|
||||
</Link>
|
||||
</div>
|
||||
))}
|
||||
|
||||
<button className={styles.arrow}>→</button>
|
||||
<button className={`${styles.arrow} ${styles.nextArrow}`} onClick={nextSlide}>→</button>
|
||||
</div>
|
||||
|
||||
<div className={styles.viewMoreContainer}>
|
||||
<Link href="#" className={styles.viewMoreButton}>
|
||||
<Link href="/blog" className={styles.viewMoreButton}>
|
||||
Read More Blogs
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
@ -62,16 +62,14 @@
|
||||
|
||||
.inputGroup {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-family: var(--font-playfair);
|
||||
color: var(--color-gold);
|
||||
width: 80px;
|
||||
font-size: 1.1rem;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.input,
|
||||
@ -83,7 +81,7 @@
|
||||
padding: 0.8rem 1rem;
|
||||
font-family: var(--font-lato);
|
||||
font-size: 1rem;
|
||||
color: #333;
|
||||
color: #757575;
|
||||
outline: none;
|
||||
transition: box-shadow 0.3s ease;
|
||||
}
|
||||
@ -107,7 +105,7 @@
|
||||
font-size: 1rem;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
align-self: flex-end;
|
||||
align-self: center;
|
||||
margin-top: 1rem;
|
||||
border-radius: 4px;
|
||||
}
|
||||
@ -124,6 +122,55 @@
|
||||
font-family: var(--font-lato);
|
||||
}
|
||||
|
||||
/* Alert styles */
|
||||
.alert {
|
||||
padding: 1rem;
|
||||
margin-bottom: 1.5rem;
|
||||
border-radius: 4px;
|
||||
font-family: var(--font-lato);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.alertSuccess {
|
||||
background-color: rgba(40, 167, 69, 0.2);
|
||||
color: #28a745;
|
||||
border: 1px solid #28a745;
|
||||
}
|
||||
|
||||
.alertDanger {
|
||||
background-color: rgba(220, 53, 69, 0.2);
|
||||
color: #dc3545;
|
||||
border: 1px solid #dc3545;
|
||||
}
|
||||
|
||||
/* Error text */
|
||||
.errorText {
|
||||
color: #dc3545;
|
||||
font-size: 0.875rem;
|
||||
margin-top: 0.25rem;
|
||||
display: block;
|
||||
font-family: var(--font-lato);
|
||||
}
|
||||
|
||||
/* Character count */
|
||||
.charCount {
|
||||
color: var(--color-gold);
|
||||
font-size: 0.875rem;
|
||||
margin-top: 0.25rem;
|
||||
display: block;
|
||||
text-align: right;
|
||||
font-family: var(--font-lato);
|
||||
}
|
||||
|
||||
/* ReCAPTCHA wrapper */
|
||||
.recaptchaWrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.imageContainer {
|
||||
display: block;
|
||||
|
||||
@ -1,32 +1,121 @@
|
||||
'use client'
|
||||
|
||||
import { useState } from 'react'
|
||||
import { useState, useEffect } from 'react'
|
||||
import Image from 'next/image'
|
||||
import ReCAPTCHA from "react-google-recaptcha"
|
||||
import axios from "axios"
|
||||
import styles from './BookTable.module.css'
|
||||
import { submitReservation } from '@/app/actions'
|
||||
|
||||
interface FormErrors {
|
||||
name?: string;
|
||||
phone?: string;
|
||||
date?: string;
|
||||
captcha?: string;
|
||||
}
|
||||
|
||||
export default function BookTable() {
|
||||
const [isSubmitting, setIsSubmitting] = useState(false)
|
||||
const [message, setMessage] = useState('')
|
||||
const [email, setEmail] = useState("");
|
||||
|
||||
async function handleSubmit(formData: FormData) {
|
||||
setIsSubmitting(true)
|
||||
setMessage('')
|
||||
useEffect(() => {
|
||||
const user = "info";
|
||||
const domain = "antalya-restaurant.com";
|
||||
setEmail(`${user}@${domain}`);
|
||||
}, []);
|
||||
|
||||
const [formData, setFormData] = useState({
|
||||
name: "",
|
||||
phone: "",
|
||||
date: "",
|
||||
message: "",
|
||||
});
|
||||
|
||||
const [formErrors, setFormErrors] = useState<FormErrors>({});
|
||||
const [captchaToken, setCaptchaToken] = useState<string | null>(null);
|
||||
const [alert, setAlert] = useState({ show: false, type: "", message: "" });
|
||||
const [charCount, setCharCount] = useState(0);
|
||||
|
||||
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
|
||||
const { name, value } = e.target;
|
||||
setFormData((prev) => ({ ...prev, [name]: value }));
|
||||
|
||||
if (name === "message") {
|
||||
setCharCount(value.length);
|
||||
}
|
||||
};
|
||||
|
||||
const handleCaptchaChange = (token: string | null) => {
|
||||
setCaptchaToken(token);
|
||||
};
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
|
||||
const errors: FormErrors = {};
|
||||
if (!formData.name.trim()) errors.name = "Name is required.";
|
||||
if (!formData.phone.trim()) errors.phone = "Phone is required.";
|
||||
if (!formData.date.trim()) errors.date = "Date is required.";
|
||||
if (!captchaToken) errors.captcha = "Please verify the CAPTCHA.";
|
||||
|
||||
setFormErrors(errors);
|
||||
if (Object.keys(errors).length > 0) return;
|
||||
|
||||
const emailData = {
|
||||
name: formData.name,
|
||||
phone: formData.phone,
|
||||
email: email,
|
||||
subject: `Table Reservation - ${formData.name} on ${formData.date}`,
|
||||
message: `
|
||||
<strong>Reservation Details:</strong><br/>
|
||||
Name: ${formData.name}<br/>
|
||||
Phone: ${formData.phone}<br/>
|
||||
Date: ${formData.date}<br/><br/>
|
||||
<strong>Message:</strong><br/>
|
||||
${formData.message || "None"}
|
||||
`,
|
||||
to: email,
|
||||
senderName: "Antalya Restaurant - Table Reservation",
|
||||
recaptchaToken: captchaToken,
|
||||
};
|
||||
|
||||
try {
|
||||
const result = await submitReservation(formData)
|
||||
if (result.success) {
|
||||
setMessage(result.message)
|
||||
const form = document.getElementById('reservation-form') as HTMLFormElement
|
||||
form?.reset()
|
||||
}
|
||||
const res = await axios.post(
|
||||
"https://mailserver.metatronnest.com/send",
|
||||
emailData,
|
||||
{ headers: { "Content-Type": "application/json" } }
|
||||
);
|
||||
|
||||
setAlert({
|
||||
show: true,
|
||||
type: "success",
|
||||
message: res?.data?.message || "Reservation request sent successfully! We'll contact you soon.",
|
||||
});
|
||||
|
||||
setFormData({
|
||||
name: "",
|
||||
phone: "",
|
||||
date: "",
|
||||
message: "",
|
||||
});
|
||||
setCaptchaToken(null);
|
||||
setFormErrors({});
|
||||
setCharCount(0);
|
||||
} catch (error) {
|
||||
console.error('Error submitting form:', error)
|
||||
setMessage('Something went wrong. Please try again.')
|
||||
} finally {
|
||||
setIsSubmitting(false)
|
||||
setAlert({
|
||||
show: true,
|
||||
type: "danger",
|
||||
message: "Failed to send reservation request. Please try again later.",
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (alert.show) {
|
||||
const timer = setTimeout(() => {
|
||||
setAlert((prev) => ({ ...prev, show: false }));
|
||||
}, 5000);
|
||||
return () => clearTimeout(timer);
|
||||
}
|
||||
}, [alert.show]);
|
||||
|
||||
return (
|
||||
<section className={styles.section} id="book">
|
||||
@ -44,65 +133,96 @@ export default function BookTable() {
|
||||
<div className={styles.content}>
|
||||
<h2 className={styles.title}>Book A Table</h2>
|
||||
|
||||
{alert.show && (
|
||||
<div className={`${styles.alert} ${styles[`alert${alert.type.charAt(0).toUpperCase() + alert.type.slice(1)}`]}`}>
|
||||
{alert.message}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<form
|
||||
id="reservation-form"
|
||||
action={handleSubmit}
|
||||
onSubmit={handleSubmit}
|
||||
className={styles.form}
|
||||
>
|
||||
{/* Name Input with Placeholder */}
|
||||
<div className={styles.inputGroup}>
|
||||
<label htmlFor="name" className={styles.label}>Name</label>
|
||||
<label htmlFor="name" className={styles.label}>Name *</label>
|
||||
<input
|
||||
type="text"
|
||||
id="name"
|
||||
name="name"
|
||||
required
|
||||
className={styles.input}
|
||||
placeholder="Your Full Name"
|
||||
value={formData.name}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
{formErrors.name && <small className={styles.errorText}>{formErrors.name}</small>}
|
||||
</div>
|
||||
|
||||
{/* Phone Input with Placeholder */}
|
||||
<div className={styles.inputGroup}>
|
||||
<label htmlFor="phone" className={styles.label}>Phone</label>
|
||||
<label htmlFor="phone" className={styles.label}>Phone *</label>
|
||||
<input
|
||||
type="tel"
|
||||
id="phone"
|
||||
name="phone"
|
||||
required
|
||||
className={styles.input}
|
||||
placeholder="(519) 000-0000"
|
||||
value={formData.phone}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
{formErrors.phone && <small className={styles.errorText}>{formErrors.phone}</small>}
|
||||
</div>
|
||||
|
||||
<div className={styles.inputGroup}>
|
||||
<label htmlFor="date" className={styles.label}>Date</label>
|
||||
<label htmlFor="date" className={styles.label}>Date *</label>
|
||||
<input
|
||||
type="date"
|
||||
id="date"
|
||||
name="date"
|
||||
required
|
||||
className={styles.input}
|
||||
value={formData.date}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
{formErrors.date && <small className={styles.errorText}>{formErrors.date}</small>}
|
||||
</div>
|
||||
|
||||
{/* Message Textarea with Placeholder */}
|
||||
<div className={styles.inputGroup}>
|
||||
<label htmlFor="message" className={styles.label}>Message</label>
|
||||
<textarea
|
||||
id="message"
|
||||
name="message"
|
||||
className={styles.textarea}
|
||||
placeholder="Any special requests..."
|
||||
maxLength={500}
|
||||
value={formData.message}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
<span className={styles.charCount}>{charCount}/500 characters</span>
|
||||
</div>
|
||||
|
||||
<button
|
||||
<button
|
||||
type="submit"
|
||||
disabled={isSubmitting}
|
||||
className={styles.submitButton}
|
||||
>
|
||||
{isSubmitting ? 'Submitting...' : 'Submit Reservation'}
|
||||
Submit Reservation
|
||||
</button>
|
||||
|
||||
{message && <p className={styles.successMessage}>{message}</p>}
|
||||
<div className={styles.recaptchaWrapper}>
|
||||
<ReCAPTCHA
|
||||
sitekey="6Lckq9MrAAAAABjBD9rQYm19BMGFFWiwb9mPiw2K"
|
||||
onChange={handleCaptchaChange}
|
||||
/>
|
||||
{formErrors.captcha && <small className={styles.errorText}>{formErrors.captcha}</small>}
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
}
|
||||
123
src/components/FAQ/FAQ.module.css
Normal file
123
src/components/FAQ/FAQ.module.css
Normal file
@ -0,0 +1,123 @@
|
||||
.faqSection {
|
||||
padding: 30px 20px 60px 20px;
|
||||
/* background-color: #F5E6D3; */
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.faqTitle {
|
||||
font-family: var(--font-playfair);
|
||||
font-size: 2.5rem;
|
||||
color: #5d4037;
|
||||
text-align: start;
|
||||
margin-bottom: 3rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
.faqContainer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.faqItem {
|
||||
background: #fff;
|
||||
border: 2px solid #C5A059;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.faqItem:hover {
|
||||
box-shadow: 0 4px 12px rgba(197, 160, 89, 0.2);
|
||||
}
|
||||
|
||||
.faqQuestion {
|
||||
width: 100%;
|
||||
padding: 1.5rem 2rem;
|
||||
background: transparent;
|
||||
border: none;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
font-family: var(--font-lato);
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
color: #5d4037;
|
||||
text-align: left;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.faqQuestion:hover {
|
||||
background-color: #faf6f0;
|
||||
}
|
||||
|
||||
.faqQuestion.active {
|
||||
background-color: #C5A059;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.icon {
|
||||
font-size: 1.5rem;
|
||||
font-weight: bold;
|
||||
color: #C5A059;
|
||||
transition: transform 0.3s ease;
|
||||
flex-shrink: 0;
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
.faqQuestion.active .icon {
|
||||
color: #fff;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.faqAnswer {
|
||||
max-height: 0;
|
||||
overflow: hidden;
|
||||
transition: max-height 0.4s ease, padding 0.4s ease;
|
||||
}
|
||||
|
||||
.faqAnswer.open {
|
||||
max-height: 1000px;
|
||||
padding: 1.5rem 2rem;
|
||||
border-top: 1px solid #e0d5c7;
|
||||
}
|
||||
|
||||
.faqContent {
|
||||
font-family: var(--font-lato);
|
||||
font-size: 1rem;
|
||||
color: #5d4037;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
.faqContent a {
|
||||
color: #C5A059;
|
||||
text-decoration: underline;
|
||||
transition: color 0.3s;
|
||||
}
|
||||
|
||||
.faqContent a:hover {
|
||||
color: #b08f4a;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.faqSection {
|
||||
padding: 40px 15px;
|
||||
}
|
||||
|
||||
.faqTitle {
|
||||
font-size: 2rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.faqQuestion {
|
||||
padding: 1.2rem 1.5rem;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.faqAnswer.open {
|
||||
padding: 1.2rem 1.5rem;
|
||||
}
|
||||
}
|
||||
46
src/components/FAQ/FAQ.tsx
Normal file
46
src/components/FAQ/FAQ.tsx
Normal file
@ -0,0 +1,46 @@
|
||||
'use client'
|
||||
|
||||
import { useState } from 'react';
|
||||
import styles from './FAQ.module.css';
|
||||
|
||||
interface FAQItem {
|
||||
q: string;
|
||||
a: string;
|
||||
}
|
||||
|
||||
interface FAQProps {
|
||||
faqs: FAQItem[];
|
||||
}
|
||||
|
||||
export default function FAQ({ faqs }: FAQProps) {
|
||||
const [openIndex, setOpenIndex] = useState<number | null>(null);
|
||||
|
||||
const toggleFAQ = (index: number) => {
|
||||
setOpenIndex(openIndex === index ? null : index);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.faqSection}>
|
||||
<h2 className={styles.faqTitle}>FAQs</h2>
|
||||
<div className={styles.faqContainer}>
|
||||
{faqs.map((faq, index) => (
|
||||
<div key={index} className={styles.faqItem}>
|
||||
<button
|
||||
className={`${styles.faqQuestion} ${openIndex === index ? styles.active : ''}`}
|
||||
onClick={() => toggleFAQ(index)}
|
||||
>
|
||||
<span>{faq.q}</span>
|
||||
<span className={styles.icon}>{openIndex === index ? '−' : '+'}</span>
|
||||
</button>
|
||||
<div className={`${styles.faqAnswer} ${openIndex === index ? styles.open : ''}`}>
|
||||
<div
|
||||
className={styles.faqContent}
|
||||
dangerouslySetInnerHTML={{ __html: faq.a }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
16
src/components/Footer.tsx
Normal file
16
src/components/Footer.tsx
Normal file
@ -0,0 +1,16 @@
|
||||
import React from 'react';
|
||||
import styles from '@/app/about/about.module.css'; // reuse styles or define minimal inline
|
||||
|
||||
export default function Footer() {
|
||||
return (
|
||||
<footer className={styles.footer || ''} style={{
|
||||
backgroundColor: 'var(--color-dark)',
|
||||
color: '#fff',
|
||||
textAlign: 'center',
|
||||
padding: '2rem 0',
|
||||
marginTop: '4rem',
|
||||
}}>
|
||||
<p>© 2025 Antalya Restaurant. All rights reserved.</p>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
.footer {
|
||||
background-color: #2a0a0a;
|
||||
background-image: url('/images/section-bg.jpg');
|
||||
/* Deep red/brown */
|
||||
color: #d4b060;
|
||||
/* Gold-ish text */
|
||||
@ -7,6 +8,21 @@
|
||||
border-top: 1px solid var(--color-gold);
|
||||
}
|
||||
|
||||
/* Add this (or adjust as needed) to Footer.module.css */
|
||||
|
||||
.logoImage {
|
||||
/* Style the Next.js Image component inside the logo container */
|
||||
width: auto;
|
||||
height: 100px;
|
||||
/* Example height - adjust this to your desired size */
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.logoa {
|
||||
/* Ensure the link container doesn't disrupt layout */
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
@ -57,7 +73,7 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #2a0a0a;
|
||||
color: #ffff;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
@ -1,15 +1,32 @@
|
||||
'use client'
|
||||
|
||||
import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
import styles from './Footer.module.css'
|
||||
|
||||
export default function Footer() {
|
||||
|
||||
const metatronCubeLink = "https://metatroncubesolutions.com/";
|
||||
|
||||
return (
|
||||
<footer className={styles.footer} id="contact">
|
||||
<div className={styles.container}>
|
||||
{/* Brand Column */}
|
||||
<div className={`${styles.column} ${styles.brandColumn}`}>
|
||||
{/* Logo updated to use Image and Link */}
|
||||
<div className={styles.logo}>
|
||||
ANTALYA<br />
|
||||
<span style={{ fontSize: '1rem', letterSpacing: '4px' }}>RESTAURANT</span>
|
||||
<Link href="/" onClick={() => window.scrollTo(0, 0)}>
|
||||
<Image
|
||||
src="/images/antalya-logo.png"
|
||||
alt="Antalya Restaurant"
|
||||
width={200}
|
||||
height={200}
|
||||
className={styles.logoImage} // Must be styled in Footer.module.css
|
||||
priority
|
||||
/>
|
||||
</Link>
|
||||
</div>
|
||||
{/* End of Logo update */}
|
||||
<p className={styles.description}>
|
||||
Discover the essence of fusion cuisine in the heart of Ontario at Antalya Restaurant.
|
||||
Our carefully curated menu offers a delicious selection from sizzling kebabs and succulent doners to authentic pides, sandwiches, and wraps.
|
||||
@ -24,14 +41,17 @@ export default function Footer() {
|
||||
{/* Quick Links Column */}
|
||||
<div className={styles.column}>
|
||||
<h3 className={styles.heading}>Quick Links</h3>
|
||||
{/* Removed the Bootstrap classes (row, col-lg-6) as this is a CSS Modules file and those classes are not defined. Reverting to a single list structure for stability. */}
|
||||
|
||||
<ul className={styles.linkList}>
|
||||
<li className={styles.linkItem}><a href="#" className={styles.link}>Home</a></li>
|
||||
<li className={styles.linkItem}><a href="#menu" className={styles.link}>Menu</a></li>
|
||||
<li className={styles.linkItem}><a href="#gallery" className={styles.link}>Gallery</a></li>
|
||||
<li className={styles.linkItem}><a href="#about" className={styles.link}>About</a></li>
|
||||
<li className={styles.linkItem}><a href="#blog" className={styles.link}>Blog</a></li>
|
||||
<li className={styles.linkItem}><a href="#contact" className={styles.link}>Contact</a></li>
|
||||
<li className={styles.linkItem}><a href="/" className={styles.link}>Home</a></li>
|
||||
<li className={styles.linkItem}><a href="/about" className={styles.link}>About</a></li>
|
||||
<li className={styles.linkItem}><a href="/gallery" className={styles.link}>Gallery</a></li>
|
||||
<li className={styles.linkItem}><a href="/menu" className={styles.link}>Menu</a></li>
|
||||
<li className={styles.linkItem}><a href="/blog" className={styles.link}>Blog</a></li>
|
||||
<li className={styles.linkItem}><a href="/contact" className={styles.link}>Contact</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
{/* Location Column */}
|
||||
@ -62,8 +82,16 @@ export default function Footer() {
|
||||
</div>
|
||||
|
||||
<div className={styles.copyright}>
|
||||
© Copyright 2025 Antalya Restaurant | Powered by MetatronCube All Rights Reserved
|
||||
© Copyright 2025 Antalya Restaurant | Powered by{' '}
|
||||
<a
|
||||
href={metatronCubeLink}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
MetatronCube
|
||||
</a>{' '}
|
||||
All Rights Reserved
|
||||
</div>
|
||||
</footer>
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,9 @@
|
||||
.section {
|
||||
padding: 6rem 2rem;
|
||||
background-color: #3a0c08;
|
||||
/* Very dark red/brown */
|
||||
background-image: url('/images/section-bg.jpg');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@ -62,7 +64,7 @@
|
||||
margin-top: 3rem;
|
||||
padding: 0.8rem 2rem;
|
||||
border: 1px solid var(--color-gold);
|
||||
color: var(--color-gold);
|
||||
color: #fff;
|
||||
font-family: var(--font-lato);
|
||||
text-transform: uppercase;
|
||||
text-decoration: none;
|
||||
@ -73,7 +75,7 @@
|
||||
|
||||
.button:hover {
|
||||
background-color: var(--color-gold);
|
||||
color: #000;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Lightbox */
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
import { useState } from 'react'
|
||||
import Image from 'next/image'
|
||||
import styles from './Gallery.module.css'
|
||||
import Link from 'next/link'
|
||||
|
||||
const images = [
|
||||
'/images/dish-1.png',
|
||||
@ -37,7 +38,7 @@ export default function Gallery() {
|
||||
}
|
||||
|
||||
return (
|
||||
<section className={styles.section} id="gallery">
|
||||
<section className={styles.section}>
|
||||
<h2 className={styles.title}>Gallery</h2>
|
||||
<div className={styles.grid}>
|
||||
{images.map((src, index) => (
|
||||
@ -55,7 +56,7 @@ export default function Gallery() {
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<button className={styles.button}>View More</button>
|
||||
<Link href="/gallery" className={styles.button}>View More</Link>
|
||||
|
||||
{lightboxOpen && (
|
||||
<div className={styles.lightbox} onClick={closeLightbox}>
|
||||
|
||||
@ -90,8 +90,9 @@
|
||||
|
||||
.btnPrimary {
|
||||
background-color: var(--color-gold);
|
||||
color: #000;
|
||||
color: #fff;
|
||||
border: 1px solid var(--color-gold);
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.btnPrimary:hover {
|
||||
@ -102,11 +103,12 @@
|
||||
.btnSecondary {
|
||||
background-color: transparent;
|
||||
color: #fff;
|
||||
border: 1px solid #fff;
|
||||
border: 3px solid #b28839;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.btnSecondary:hover {
|
||||
background-color: #fff;
|
||||
background-color: #b28839;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@ import { useState, useEffect } from 'react'
|
||||
import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
import styles from './Hero.module.css'
|
||||
import { motion, AnimatePresence } from 'framer-motion'
|
||||
|
||||
const slides = [
|
||||
{
|
||||
@ -38,34 +39,62 @@ export default function Hero() {
|
||||
|
||||
return (
|
||||
<section className={styles.hero}>
|
||||
{slides.map((slide, index) => (
|
||||
<div
|
||||
key={slide.id}
|
||||
className={`${styles.slide} ${index === currentSlide ? styles.active : ''}`}
|
||||
<AnimatePresence mode="wait">
|
||||
<motion.div
|
||||
key={currentSlide}
|
||||
className={`${styles.slide} ${styles.active}`}
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
transition={{ duration: 0.7 }}
|
||||
>
|
||||
<Image
|
||||
src={slide.image}
|
||||
alt={slide.title}
|
||||
src={slides[currentSlide].image}
|
||||
alt={slides[currentSlide].title}
|
||||
fill
|
||||
style={{ objectFit: 'cover' }}
|
||||
priority={index === 0}
|
||||
priority={currentSlide === 0}
|
||||
/>
|
||||
<div className={styles.overlay}>
|
||||
<div className={styles.content}>
|
||||
<h1 className={styles.title}>{slide.title}</h1>
|
||||
<p className={styles.subtitle}>{slide.subtitle}</p>
|
||||
<div className={styles.buttons}>
|
||||
<Link href="#menu" className={`${styles.btn} ${styles.btnPrimary}`}>
|
||||
<motion.div
|
||||
className={styles.content}
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.8, delay: 0.3 }}
|
||||
>
|
||||
<motion.h1
|
||||
className={styles.title}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.6, delay: 0.5 }}
|
||||
>
|
||||
{slides[currentSlide].title}
|
||||
</motion.h1>
|
||||
<motion.p
|
||||
className={styles.subtitle}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.6, delay: 0.7 }}
|
||||
>
|
||||
{slides[currentSlide].subtitle}
|
||||
</motion.p>
|
||||
<motion.div
|
||||
className={styles.buttons}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.6, delay: 0.9 }}
|
||||
>
|
||||
<Link href="/menu" className={`${styles.btn} ${styles.btnPrimary}`}>
|
||||
View Menu
|
||||
</Link>
|
||||
<Link href="#book" className={`${styles.btn} ${styles.btnSecondary}`}>
|
||||
<Link href="/contact" className={`${styles.btn} ${styles.btnSecondary}`}>
|
||||
Book A Table
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</motion.div>
|
||||
</AnimatePresence>
|
||||
|
||||
<div className={styles.dots}>
|
||||
{slides.map((_, index) => (
|
||||
|
||||
26
src/components/Navbar.tsx
Normal file
26
src/components/Navbar.tsx
Normal file
@ -0,0 +1,26 @@
|
||||
import React from 'react';
|
||||
import Link from 'next/link';
|
||||
import styles from '@/app/about/about.module.css'; // reuse existing styles if needed
|
||||
|
||||
export default function Navbar() {
|
||||
return (
|
||||
<nav className={styles.navbar || ''} style={{
|
||||
backgroundColor: 'var(--color-dark)',
|
||||
padding: '1rem 2rem',
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
color: '#fff',
|
||||
}}>
|
||||
<div style={{ fontFamily: 'var(--font-playfair)', fontSize: '1.5rem' }}>
|
||||
Antalya Restaurant
|
||||
</div>
|
||||
<ul style={{ listStyle: 'none', display: 'flex', gap: '1.5rem', margin: 0 }}>
|
||||
<li><Link href="/" style={{ color: '#fff', textDecoration: 'none' }}>Home</Link></li>
|
||||
<li><Link href="/about" style={{ color: '#fff', textDecoration: 'none' }}>About</Link></li>
|
||||
<li><Link href="/menu" style={{ color: '#fff', textDecoration: 'none' }}>Menu</Link></li>
|
||||
<li><Link href="/contact" style={{ color: '#fff', textDecoration: 'none' }}>Contact</Link></li>
|
||||
</ul>
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
@ -3,7 +3,7 @@
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 70px;
|
||||
height: 120px;
|
||||
background-color: rgba(26, 26, 26, 0.9);
|
||||
backdrop-filter: blur(10px);
|
||||
display: flex;
|
||||
@ -27,7 +27,7 @@
|
||||
}
|
||||
|
||||
.logoImage {
|
||||
height: 50px;
|
||||
height: 110px;
|
||||
width: auto;
|
||||
object-fit: contain;
|
||||
}
|
||||
@ -41,7 +41,7 @@
|
||||
.navLink {
|
||||
color: #C9A865;
|
||||
text-decoration: none;
|
||||
font-size: 1rem;
|
||||
font-size: 28px;
|
||||
font-weight: 400;
|
||||
letter-spacing: 0.5px;
|
||||
transition: all 0.3s ease;
|
||||
@ -154,4 +154,12 @@
|
||||
.navbar {
|
||||
padding: 0 20px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) and (min-width: 200px) {
|
||||
.logoImage {
|
||||
object-fit: contain;
|
||||
width: auto;
|
||||
height: 100px;
|
||||
}
|
||||
}
|
||||
@ -7,13 +7,14 @@ import styles from './Navbar.module.css'
|
||||
|
||||
const navLinks = [
|
||||
{ name: 'Home', href: '/' },
|
||||
{ name: 'About', href: '#about' },
|
||||
{ name: 'Gallery', href: '#gallery' },
|
||||
{ name: 'Menu', href: '#menu' },
|
||||
{ name: 'Blog', href: '#blog' },
|
||||
{ name: 'Contact', href: '#contact' },
|
||||
{ name: 'About', href: '/about' },
|
||||
{ name: 'Gallery', href: '/gallery' },
|
||||
{ name: 'Menu', href: '/menu' },
|
||||
{ name: 'Blog', href: '/blog' },
|
||||
{ name: 'Contact', href: '/contact' },
|
||||
]
|
||||
|
||||
|
||||
export default function Navbar() {
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
const [scrolled, setScrolled] = useState(false)
|
||||
@ -81,7 +82,7 @@ export default function Navbar() {
|
||||
src="/images/antalya-logo.png"
|
||||
alt="Antalya Restaurant"
|
||||
width={200}
|
||||
height={60}
|
||||
height={200}
|
||||
className={styles.logoImage}
|
||||
priority
|
||||
/>
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
.section {
|
||||
padding: 80px 20px;
|
||||
background-color: #3a0c08;
|
||||
/* Dark red/brown background */
|
||||
background-image: url('/images/pattern-overlay.png');
|
||||
/* Optional pattern */
|
||||
background-image: url('/images/section-bg.jpg');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
}
|
||||
@ -98,7 +98,7 @@
|
||||
display: inline-block;
|
||||
padding: 15px 40px;
|
||||
border: 1px solid #C5A059;
|
||||
color: #C5A059;
|
||||
color: #fff;
|
||||
font-family: var(--font-inter), sans-serif;
|
||||
text-transform: uppercase;
|
||||
font-size: 1rem;
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
'use client'
|
||||
|
||||
import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
import styles from './PopularDishes.module.css'
|
||||
import { motion } from 'framer-motion'
|
||||
|
||||
const dishes = [
|
||||
{
|
||||
@ -25,12 +28,54 @@ const dishes = [
|
||||
]
|
||||
|
||||
export default function PopularDishes() {
|
||||
const containerVariants = {
|
||||
hidden: { opacity: 0 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
transition: {
|
||||
staggerChildren: 0.2,
|
||||
delayChildren: 0.2
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const cardVariants = {
|
||||
hidden: { opacity: 0, y: 40 },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
transition: { duration: 0.6 }
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<section className={styles.section} id="menu">
|
||||
<h2 className={styles.title}>POPULAR DISHES</h2>
|
||||
<div className={styles.grid}>
|
||||
<motion.h2
|
||||
className={styles.title}
|
||||
initial={{ opacity: 0, y: 30 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.6 }}
|
||||
>
|
||||
POPULAR DISHES
|
||||
</motion.h2>
|
||||
<motion.div
|
||||
className={styles.grid}
|
||||
initial="hidden"
|
||||
whileInView="visible"
|
||||
viewport={{ once: true, margin: "-100px" }}
|
||||
variants={containerVariants}
|
||||
>
|
||||
{dishes.map((dish) => (
|
||||
<div key={dish.id} className={styles.card}>
|
||||
<motion.div
|
||||
key={dish.id}
|
||||
className={styles.card}
|
||||
variants={cardVariants}
|
||||
whileHover={{
|
||||
y: -10,
|
||||
transition: { duration: 0.3 }
|
||||
}}
|
||||
>
|
||||
<div className={styles.imageContainer}>
|
||||
<Image
|
||||
src={dish.image}
|
||||
@ -44,14 +89,20 @@ export default function PopularDishes() {
|
||||
<Link href="#menu" className={styles.button}>
|
||||
View More
|
||||
</Link>
|
||||
</div>
|
||||
</motion.div>
|
||||
))}
|
||||
</div>
|
||||
<div className={styles.viewMoreContainer}>
|
||||
</motion.div>
|
||||
<motion.div
|
||||
className={styles.viewMoreContainer}
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.6, delay: 0.4 }}
|
||||
>
|
||||
<Link href="#menu" className={styles.viewMoreButton}>
|
||||
View More
|
||||
</Link>
|
||||
</div>
|
||||
</motion.div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
@ -87,6 +87,19 @@
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
.authorImageWrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.authorImage {
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.name {
|
||||
font-family: var(--font-inter), sans-serif;
|
||||
/* Assuming Inter or similar */
|
||||
@ -129,11 +142,11 @@
|
||||
}
|
||||
|
||||
.prevArrow {
|
||||
left: -25px;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.nextArrow {
|
||||
right: -25px;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
/* Lanterns decoration placeholder */
|
||||
@ -146,20 +159,90 @@
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
/* Responsive adjustments for different viewport sizes */
|
||||
@media (max-width: 1400px) {
|
||||
.sliderContainer {
|
||||
padding: 0 50px;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
font-size: 2.8rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
.sliderContainer {
|
||||
padding: 0 40px;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
.track {
|
||||
flex-direction: column;
|
||||
transform: none !important;
|
||||
/* Disable slide on mobile if stacking */
|
||||
.sliderContainer {
|
||||
padding: 0 30px;
|
||||
}
|
||||
|
||||
.card {
|
||||
flex: 0 0 100%;
|
||||
max-width: 100%;
|
||||
margin: 0 0 20px 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Hide 2nd and 3rd cards on mobile, show only 1st */
|
||||
.card:nth-child(2),
|
||||
.card:nth-child(3) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
display: none;
|
||||
font-size: 2.2rem;
|
||||
}
|
||||
|
||||
.prevArrow {
|
||||
left: 5px;
|
||||
}
|
||||
|
||||
.nextArrow {
|
||||
right: 5px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.sliderContainer {
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.prevArrow {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.nextArrow {
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.sliderContainer {
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
@ -4,48 +4,47 @@ import { useState, useEffect } from 'react'
|
||||
import Image from 'next/image'
|
||||
import styles from './Testimonials.module.css'
|
||||
|
||||
// Placeholder data with 6 items
|
||||
const testimonials = [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Anya Petrova, [City]',
|
||||
name: 'Anya Petrova',
|
||||
image: '/images/avatar-anya.png',
|
||||
text: '“An unforgettable journey of flavors and warmth. The ambiance is exquisite is Turkish fusion dishes simply divine.”',
|
||||
text: '"An unforgettable journey of flavors and warmth. The ambiance is exquisite and the Turkish fusion dishes are simply divine."',
|
||||
rating: 5
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Tuest Khan, [City]',
|
||||
image: '/images/avatar-anya.png',
|
||||
text: '“An unforgettable journey of flavors and warmth. The ambiance is exquisite is Turkish fusion dishes simply divine.”',
|
||||
name: 'Tuest Khan',
|
||||
image: '/images/avatar-tuest.png',
|
||||
text: '"The best Turkish restaurant in town! Every dish is prepared with authentic spices and love. The staff made us feel like family."',
|
||||
rating: 5
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'Tariq Name, [City]',
|
||||
image: '/images/avatar-anya.png',
|
||||
text: '“An unforgettable journey of flavors and warmth. The ambiene exquisite, and Turkish fusion dishes simply divine.”',
|
||||
name: 'Tariq Ahmed',
|
||||
image: '/images/avatar-tariq.png',
|
||||
text: '"Exceptional quality and presentation. The kebabs were perfectly grilled and the baklava for dessert was heavenly!"',
|
||||
rating: 5
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: 'Sarah Jenkins, [City]',
|
||||
image: '/images/avatar-anya.png', // Reusing for now
|
||||
text: '“Amazing service and beautiful atmosphere. Highly recommend the mixed grill!”',
|
||||
name: 'Sarah Jenkins',
|
||||
image: '/images/avatar-sarah.png',
|
||||
text: '"Amazing service and beautiful atmosphere. The mixed grill platter is a must-try. Highly recommend for special occasions!"',
|
||||
rating: 5
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: 'Michael Chen, [City]',
|
||||
image: '/images/avatar-sarah.png', // Reusing for now
|
||||
text: '“A hidden gem! The fusion of flavors is incredible. Will definitely come back.”',
|
||||
name: 'Michael Chen',
|
||||
image: '/images/avatar-michael.png',
|
||||
text: '"A hidden gem! The fusion of traditional Turkish flavors with modern techniques is incredible. Will definitely come back soon."',
|
||||
rating: 5
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: 'Emily Davis, [City]',
|
||||
image: '/images/avatar-sarah.png', // Reusing for now
|
||||
text: '“The staff was so welcoming and the food was absolutely delicious. 10/10 experience.”',
|
||||
name: 'Emily Davis',
|
||||
image: '/images/avatar-emily.png',
|
||||
text: '"The staff was so welcoming and the food was absolutely delicious. From appetizers to dessert, everything was perfect. 10/10 experience!"',
|
||||
rating: 5
|
||||
}
|
||||
]
|
||||
@ -71,12 +70,6 @@ export default function Testimonials() {
|
||||
}, [])
|
||||
|
||||
// Get the 3 visible testimonials
|
||||
// Simple sliding window logic for 3 items
|
||||
// Note: This simple logic assumes we stop at the end or loop.
|
||||
// For a true infinite loop with 3 items visible, it's more complex.
|
||||
// Here we will just slide through the window.
|
||||
// Actually, let's do a simple modulo wrap for the window to always show 3.
|
||||
|
||||
const getVisibleTestimonials = () => {
|
||||
const items = []
|
||||
for (let i = 0; i < 3; i++) {
|
||||
@ -90,11 +83,6 @@ export default function Testimonials() {
|
||||
|
||||
return (
|
||||
<section className={styles.section}>
|
||||
{/* Decorative Lanterns - Placeholder Image */}
|
||||
{/* <div className={styles.lanterns}>
|
||||
<Image src="/images/lanterns.png" alt="Lanterns" width={150} height={200} />
|
||||
</div> */}
|
||||
|
||||
<h2 className={styles.title}>TESTIMONIALS</h2>
|
||||
|
||||
<div className={styles.sliderContainer}>
|
||||
@ -103,11 +91,14 @@ export default function Testimonials() {
|
||||
{visibleItems.map((item) => (
|
||||
<div key={item.id} className={styles.card}>
|
||||
<div className={styles.avatarContainer}>
|
||||
{/* Using a div fallback if image is missing, or standard img tag */}
|
||||
<div className={styles.avatar} style={{ overflow: 'hidden' }}>
|
||||
{/* Placeholder for avatar - using different colors to distinguish if needed, or just gray */}
|
||||
<div style={{ width: '100%', height: '100%', backgroundColor: '#ccc', display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#666' }}>
|
||||
{item.name.charAt(0)}
|
||||
<div className={styles.authorImageWrapper}>
|
||||
<Image
|
||||
src={item.image}
|
||||
alt={item.name}
|
||||
fill
|
||||
className={styles.authorImage}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
300
src/utils/constant.ts
Normal file
300
src/utils/constant.ts
Normal file
@ -0,0 +1,300 @@
|
||||
export const blogData = [
|
||||
{
|
||||
id: 1,
|
||||
slug: 'the-art-of-turkish-tea',
|
||||
title: 'The Art of Turkish Tea',
|
||||
metatitle: 'The Art of Turkish Tea - Antalya Restaurant',
|
||||
metadesc: 'Discover the rich history and tradition behind the perfect cup of Turkish tea at Antalya Restaurant.',
|
||||
category: 'Culture',
|
||||
date: 'October 15, 2025',
|
||||
comments: '12 Comments',
|
||||
author: 'Emre Yilmaz',
|
||||
para: 'Discover the rich history and tradition behind the perfect cup of Turkish tea.',
|
||||
image: '/images/dish-1.png',
|
||||
imageDetail: '/images/dish-1.png',
|
||||
banner: '/images/hero-1.png',
|
||||
detailImage: '/images/dish-1.png',
|
||||
excerpt: 'Discover the rich history and tradition behind the perfect cup of Turkish tea.',
|
||||
content: `
|
||||
<div class="sec-title new mt-4">
|
||||
<h2>The Rich Tradition of Turkish Tea</h2>
|
||||
</div>
|
||||
<p>Turkish tea, known as çay, is more than just a drink; it is a symbol of hospitality and friendship. Brewed in a unique two-stacked kettle called a çaydanlık, the tea is served in small, tulip-shaped glasses to showcase its deep red color.</p>
|
||||
|
||||
<div class="sec-title new mt-4">
|
||||
<h3>The History of Tea in Turkey</h3>
|
||||
</div>
|
||||
<p>While Turkey is famous for its coffee, tea has become the most consumed beverage in the country. The tea culture in Turkey began in the early 20th century when the government encouraged tea cultivation in the Black Sea region.</p>
|
||||
|
||||
<div class="sec-title new mt-4">
|
||||
<h3>How to Brew the Perfect Turkish Tea</h3>
|
||||
</div>
|
||||
<ul class="list-style-two">
|
||||
<li>Use a traditional çaydanlık (double teapot)</li>
|
||||
<li>Boil water in the lower pot</li>
|
||||
<li>Add loose tea leaves to the upper pot</li>
|
||||
<li>Pour boiling water over the leaves</li>
|
||||
<li>Let it steep for 10-15 minutes</li>
|
||||
<li>Serve in tulip-shaped glasses</li>
|
||||
</ul>
|
||||
|
||||
<p>At Antalya Restaurant, we serve authentic Turkish tea with every meal, continuing this beautiful tradition of hospitality.</p>
|
||||
|
||||
<blockquote>
|
||||
<p>Tea is not just a beverage in Turkey; it's a way of life, a symbol of hospitality, and a bridge between hearts.</p>
|
||||
<cite>Turkish Proverb</cite>
|
||||
</blockquote>
|
||||
|
||||
|
||||
`,
|
||||
faqs: [
|
||||
{
|
||||
q: "What makes Turkish tea different from other teas?",
|
||||
a: "Turkish tea is brewed using a special double teapot called a çaydanlık, which allows for a stronger, more flavorful brew. It's typically served in small tulip-shaped glasses and is known for its deep red color and robust taste."
|
||||
},
|
||||
{
|
||||
q: "Can I order Turkish tea at Antalya Restaurant?",
|
||||
a: "Yes! We serve authentic Turkish tea with every meal. It's complimentary with your dining experience and brewed fresh throughout the day using traditional methods."
|
||||
},
|
||||
{
|
||||
q: "Is Turkish tea caffeinated?",
|
||||
a: "Yes, Turkish tea contains caffeine as it's made from black tea leaves. However, the caffeine content can vary depending on how strong you prefer your tea."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
slug: 'secrets-of-charcoal-grilling',
|
||||
title: 'Secrets of Charcoal Grilling',
|
||||
metatitle: 'Secrets of Charcoal Grilling - Antalya Restaurant',
|
||||
metadesc: 'Why charcoal grilling is the heart of authentic Turkish cuisine and how we perfect it at Antalya.',
|
||||
category: 'Cooking',
|
||||
date: 'November 2, 2025',
|
||||
comments: '8 Comments',
|
||||
author: 'Chef Ahmet',
|
||||
para: 'Why charcoal grilling is the heart of authentic Turkish cuisine.',
|
||||
image: '/images/hero-3.png',
|
||||
imageDetail: '/images/hero-3.png',
|
||||
banner: '/images/hero-2.png',
|
||||
detailImage: '/images/hero-3.png',
|
||||
excerpt: 'Why charcoal grilling is the heart of authentic Turkish cuisine.',
|
||||
content: `
|
||||
<div class="sec-title new mt-4">
|
||||
<h2>The Art of Charcoal Grilling</h2>
|
||||
</div>
|
||||
<p>The smoky flavor of Turkish kebabs comes from the traditional method of charcoal grilling. Unlike gas grills, charcoal provides an intense heat that sears the meat while locking in the juices.</p>
|
||||
|
||||
<div class="sec-title new mt-4">
|
||||
<h3>Why Charcoal Makes a Difference</h3>
|
||||
</div>
|
||||
<p>Charcoal grilling isn't just about heat—it's about flavor. The smoke from natural charcoal infuses the meat with a distinctive taste that cannot be replicated with gas or electric grills.</p>
|
||||
|
||||
<ul class="list-style-two">
|
||||
<li>Higher cooking temperatures for perfect searing</li>
|
||||
<li>Natural smoke flavor enhancement</li>
|
||||
<li>Traditional cooking method passed down through generations</li>
|
||||
<li>Better moisture retention in the meat</li>
|
||||
</ul>
|
||||
|
||||
<p>At Antalya, our chefs master the art of the grill to bring you the most authentic flavors of Turkey.</p>
|
||||
`,
|
||||
faqs: [
|
||||
{
|
||||
q: "What type of charcoal do you use at Antalya?",
|
||||
a: "We use natural hardwood charcoal that burns hotter and cleaner than briquettes, providing the authentic smoky flavor that Turkish cuisine is known for."
|
||||
},
|
||||
{
|
||||
q: "How long does it take to grill kebabs over charcoal?",
|
||||
a: "Depending on the type of kebab, it typically takes 10-15 minutes over high heat. Our chefs monitor each skewer carefully to ensure perfect doneness."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
slug: 'a-taste-of-sweet-legacy',
|
||||
title: 'A Taste of Sweet Legacy',
|
||||
metatitle: 'Turkish Desserts: A Taste of Sweet Legacy',
|
||||
metadesc: 'Exploring the delicate layers of Baklava and other Turkish delights at Antalya Restaurant.',
|
||||
category: 'Desserts',
|
||||
date: 'November 20, 2025',
|
||||
comments: '15 Comments',
|
||||
author: 'Leyla Demir',
|
||||
para: 'Exploring the delicate layers of Baklava and other Turkish delights.',
|
||||
image: '/images/dish-2.png',
|
||||
imageDetail: '/images/dish-2.png',
|
||||
banner: '/images/hero-1.png',
|
||||
detailImage: '/images/dish-2.png',
|
||||
excerpt: 'Exploring the delicate layers of Baklava and other Turkish delights.',
|
||||
content: `
|
||||
<div class="sec-title new mt-4">
|
||||
<h2>The Sweet World of Turkish Desserts</h2>
|
||||
</div>
|
||||
<p>Baklava is perhaps the most famous Turkish dessert, but there is so much more to explore. From the creamy texture of Sütlaç (rice pudding) to the syrupy goodness of Künefe, Turkish desserts are a celebration of sweetness.</p>
|
||||
|
||||
<div class="sec-title new mt-4">
|
||||
<h3>Popular Turkish Desserts</h3>
|
||||
</div>
|
||||
<p><strong>Baklava</strong><br>
|
||||
Layers of thin filo pastry filled with chopped nuts and sweetened with syrup or honey.</p>
|
||||
|
||||
<p><strong>Künefe</strong><br>
|
||||
Shredded pastry soaked in sweet syrup, layered with cheese, and served hot.</p>
|
||||
|
||||
<p><strong>Turkish Delight (Lokum)</strong><br>
|
||||
Soft, chewy confection dusted with powdered sugar, available in various flavors.</p>
|
||||
|
||||
<p>In this post, we dive into the history of these treats and share some secrets on how we achieve the perfect balance of flaky pastry and rich filling.</p>
|
||||
`,
|
||||
faqs: [
|
||||
{
|
||||
q: "Is baklava made fresh at Antalya?",
|
||||
a: "Yes! Our baklava is made fresh daily using traditional recipes and the finest ingredients, including premium pistachios and honey."
|
||||
},
|
||||
{
|
||||
q: "Are Turkish desserts very sweet?",
|
||||
a: "Turkish desserts are known for their sweetness, but we balance the flavors carefully. Many of our desserts are served with unsweetened Turkish tea to complement the sweetness."
|
||||
},
|
||||
{
|
||||
q: "Can I order desserts for takeout?",
|
||||
a: "Absolutely! All our desserts are available for takeout. We package them carefully to maintain their freshness and quality."
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
export const galleryData = [
|
||||
{ id: 1, src: '/images/dish-1.png', category: 'Food', alt: 'Delicious Kebab' },
|
||||
{ id: 2, src: '/images/dish-2.png', category: 'Food', alt: 'Sweet Baklava' },
|
||||
{ id: 3, src: '/images/hero-1.png', category: 'Interior', alt: 'Restaurant Ambience' },
|
||||
{ id: 4, src: '/images/hero-2.png', category: 'Interior', alt: 'Dining Area' },
|
||||
{ id: 5, src: '/images/hero-3.png', category: 'Food', alt: 'Grilled Meat' },
|
||||
{ id: 6, src: '/images/restaurant-interior.png', category: 'Interior', alt: 'Cozy Seating' },
|
||||
];
|
||||
|
||||
export const menuData = [
|
||||
{
|
||||
category: 'Starters',
|
||||
image: '/images/dish-1.png',
|
||||
items: [
|
||||
{ name: 'Hummus', price: '$8', description: 'Creamy chickpea dip with tahini, lemon, and garlic.', image: '/images/dish-1.png' },
|
||||
{ name: 'Ezme', price: '$7', description: 'Spicy tomato and pepper salad with walnuts.', image: '/images/dish-2.png' },
|
||||
{ name: 'Cacik', price: '$6', description: 'Yogurt with cucumber, garlic, and mint.', image: '/images/hero-1.png' }
|
||||
]
|
||||
},
|
||||
{
|
||||
category: 'Main Courses',
|
||||
image: '/images/hero-3.png',
|
||||
items: [
|
||||
{ name: 'Adana Kebab', price: '$18', description: 'Spicy minced lamb grilled on a skewer.', image: '/images/hero-3.png' },
|
||||
{ name: 'Lamb Chops', price: '$24', description: 'Tender lamb chops grilled to perfection.', image: '/images/dish-1.png' },
|
||||
{ name: 'Chicken Shish', price: '$16', description: 'Marinated chicken cubes grilled on skewers.', image: '/images/hero-2.png' }
|
||||
]
|
||||
},
|
||||
{
|
||||
category: 'Desserts',
|
||||
image: '/images/dish-2.png',
|
||||
items: [
|
||||
{ name: 'Baklava', price: '$9', description: 'Layers of filo pastry filled with pistachios and syrup.', image: '/images/dish-2.png' },
|
||||
{ name: 'Künefe', price: '$10', description: 'Shredded pastry with cheese, soaked in syrup.', image: '/images/dish-1.png' },
|
||||
{ name: 'Turkish Delight', price: '$5', description: 'Assorted traditional gelatin sweets.', image: '/images/hero-1.png' }
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
export const testimonialData = [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Sarah Johnson',
|
||||
role: 'Food Critic',
|
||||
image: '/images/avatar-anya.png',
|
||||
text: 'The most authentic Turkish cuisine I have experienced outside of Turkey. Every dish is a masterpiece!'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Michael Chen',
|
||||
role: 'Regular Customer',
|
||||
image: '/images/avatar-emily.png',
|
||||
text: 'Antalya has become my favorite restaurant. The atmosphere is warm and the food is consistently excellent.'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'Emma Williams',
|
||||
role: 'Travel Blogger',
|
||||
image: '/images/avatar-emily.png',
|
||||
text: 'A hidden gem! The charcoal-grilled kebabs are to die for, and the service is impeccable.'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: 'Emma Williams',
|
||||
role: 'Travel Blogger',
|
||||
image: '/images/avatar-emily.png',
|
||||
text: 'A hidden gem! The charcoal-grilled kebabs are to die for, and the service is impeccable.'
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: 'Emma Williams',
|
||||
role: 'Travel Blogger',
|
||||
image: '/images/avatar-emily.png',
|
||||
text: 'A hidden gem! The charcoal-grilled kebabs are to die for, and the service is impeccable.'
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: 'Emma Williams',
|
||||
role: 'Travel Blogger',
|
||||
image: '/images/avatar-emily.png',
|
||||
text: 'A hidden gem! The charcoal-grilled kebabs are to die for, and the service is impeccable.'
|
||||
}
|
||||
];
|
||||
|
||||
export const featuresData = [
|
||||
{
|
||||
id: 1,
|
||||
title: 'Fresh Ingredients',
|
||||
description: 'We source only the finest, freshest ingredients from local suppliers daily.',
|
||||
image: '/images/dish-1.png'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Expert Chefs',
|
||||
description: 'Our chefs have decades of experience in traditional Turkish cuisine.',
|
||||
image: '/images/hero-3.png'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: 'Authentic Recipes',
|
||||
description: 'Traditional family recipes passed down through generations.',
|
||||
image: '/images/dish-2.png'
|
||||
}
|
||||
];
|
||||
|
||||
export const ctaData = {
|
||||
title: 'Experience the Flavors of Turkey',
|
||||
subtitle: 'Book your table today and embark on a culinary journey',
|
||||
buttonText: 'Reserve Now',
|
||||
buttonLink: '/contact',
|
||||
backgroundImage: '/images/hero-1.png'
|
||||
};
|
||||
|
||||
export const aboutFaqData = [
|
||||
{
|
||||
q: "What makes Antalya Restaurant authentic?",
|
||||
a: "We use traditional Turkish recipes passed down through generations, authentic cooking methods like charcoal grilling, and import specialty ingredients directly from Turkey to ensure the most authentic dining experience."
|
||||
},
|
||||
{
|
||||
q: "Do you offer vegetarian and vegan options?",
|
||||
a: "Yes! Turkish cuisine has a rich variety of vegetarian dishes. We offer numerous vegetarian options including mezze platters, stuffed vegetables, lentil soups, and fresh salads. Please ask our staff about vegan modifications."
|
||||
},
|
||||
{
|
||||
q: "Can you accommodate large groups or private events?",
|
||||
a: "Absolutely! We can accommodate groups of various sizes and offer private dining options for special occasions. Please contact us in advance to discuss your requirements and make arrangements."
|
||||
},
|
||||
{
|
||||
q: "What are your most popular dishes?",
|
||||
a: "Our signature dishes include Adana Kebab, Lamb Chops, handmade Baklava, and our traditional Turkish tea. The charcoal-grilled meats and fresh mezze platters are customer favorites."
|
||||
},
|
||||
{
|
||||
q: "Do you take reservations?",
|
||||
a: "Yes, we highly recommend making reservations, especially for weekends and special occasions. You can book a table through our website, by phone, or by visiting us in person."
|
||||
}
|
||||
];
|
||||
Loading…
x
Reference in New Issue
Block a user