setup intl for multi language website and make hero and services and projects components in home dynamic and optimized
This commit is contained in:
@@ -1,8 +1,26 @@
|
||||
import type { NextConfig } from "next";
|
||||
const createNextIntlPlugin = require("next-intl/plugin");
|
||||
|
||||
const nextConfig: NextConfig = {
|
||||
output: "standalone",
|
||||
const withNextIntl = createNextIntlPlugin("./src/i18n.ts");
|
||||
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
images: {
|
||||
unoptimized: true,
|
||||
remotePatterns: [
|
||||
{
|
||||
protocol: "http",
|
||||
hostname: "127.0.0.1", // Changed from localhost
|
||||
port: "4000",
|
||||
pathname: "/uploads/**",
|
||||
},
|
||||
{
|
||||
protocol: "http",
|
||||
hostname: "localhost",
|
||||
port: "4000", // Updated to match your environment variables
|
||||
pathname: "/uploads/**",
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
export default nextConfig;
|
||||
|
||||
module.exports = withNextIntl(nextConfig);
|
||||
|
||||
710
package-lock.json
generated
710
package-lock.json
generated
@@ -10,6 +10,7 @@
|
||||
"dependencies": {
|
||||
"lucide-react": "^1.8.0",
|
||||
"next": "16.2.4",
|
||||
"next-intl": "^4.9.1",
|
||||
"react": "19.2.4",
|
||||
"react-dom": "19.2.4"
|
||||
},
|
||||
@@ -68,6 +69,7 @@
|
||||
"integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.29.0",
|
||||
"@babel/generator": "^7.29.0",
|
||||
@@ -454,6 +456,36 @@
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@formatjs/fast-memoize": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://mirror-npm.runflare.com/@formatjs/fast-memoize/-/fast-memoize-3.1.2.tgz",
|
||||
"integrity": "sha512-vPnriihkfK0lzoQGaXq+qXH23VsYyansRTkTgo2aTG0k1NjLFyZimFVdfj4C9JkSE5dm7CEngcQ5TTc1yAyBfQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@formatjs/icu-messageformat-parser": {
|
||||
"version": "3.5.4",
|
||||
"resolved": "https://mirror-npm.runflare.com/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-3.5.4.tgz",
|
||||
"integrity": "sha512-JVY39ROgLt+pIYngo6piyj4OVfZmXs/2FkC4wLS+ql1Eig/sGJKB7YwDO/5bkJFkfwaFAeIpgEiJc8hiYxNalw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@formatjs/icu-skeleton-parser": "2.1.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@formatjs/icu-skeleton-parser": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://mirror-npm.runflare.com/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-2.1.4.tgz",
|
||||
"integrity": "sha512-8bSFZbrlvGX11ywMZxtgkPBt5Q8/etyts7j7j+GWpOVK1g43zwMIH3LZxk43HAtEP7L/jtZ+OZaMiFTOiBj9CA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@formatjs/intl-localematcher": {
|
||||
"version": "0.8.3",
|
||||
"resolved": "https://mirror-npm.runflare.com/@formatjs/intl-localematcher/-/intl-localematcher-0.8.3.tgz",
|
||||
"integrity": "sha512-pHUjWb9NuhnMs8+PxQdzBtZRFJHlGhrURGAbm6Ltwl82BFajeuiIR3jblSa7ia3r62rXe/0YtVpUG3xWr5bFCA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@formatjs/fast-memoize": "3.1.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@humanfs/core": {
|
||||
"version": "0.19.2",
|
||||
"resolved": "https://mirror-npm.runflare.com/@humanfs/core/-/core-0.19.2.tgz",
|
||||
@@ -1241,6 +1273,313 @@
|
||||
"node": ">=12.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher": {
|
||||
"version": "2.5.6",
|
||||
"resolved": "https://mirror-npm.runflare.com/@parcel/watcher/-/watcher-2.5.6.tgz",
|
||||
"integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"detect-libc": "^2.0.3",
|
||||
"is-glob": "^4.0.3",
|
||||
"node-addon-api": "^7.0.0",
|
||||
"picomatch": "^4.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@parcel/watcher-android-arm64": "2.5.6",
|
||||
"@parcel/watcher-darwin-arm64": "2.5.6",
|
||||
"@parcel/watcher-darwin-x64": "2.5.6",
|
||||
"@parcel/watcher-freebsd-x64": "2.5.6",
|
||||
"@parcel/watcher-linux-arm-glibc": "2.5.6",
|
||||
"@parcel/watcher-linux-arm-musl": "2.5.6",
|
||||
"@parcel/watcher-linux-arm64-glibc": "2.5.6",
|
||||
"@parcel/watcher-linux-arm64-musl": "2.5.6",
|
||||
"@parcel/watcher-linux-x64-glibc": "2.5.6",
|
||||
"@parcel/watcher-linux-x64-musl": "2.5.6",
|
||||
"@parcel/watcher-win32-arm64": "2.5.6",
|
||||
"@parcel/watcher-win32-ia32": "2.5.6",
|
||||
"@parcel/watcher-win32-x64": "2.5.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-android-arm64": {
|
||||
"version": "2.5.6",
|
||||
"resolved": "https://mirror-npm.runflare.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz",
|
||||
"integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-darwin-arm64": {
|
||||
"version": "2.5.6",
|
||||
"resolved": "https://mirror-npm.runflare.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz",
|
||||
"integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-darwin-x64": {
|
||||
"version": "2.5.6",
|
||||
"resolved": "https://mirror-npm.runflare.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz",
|
||||
"integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-freebsd-x64": {
|
||||
"version": "2.5.6",
|
||||
"resolved": "https://mirror-npm.runflare.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz",
|
||||
"integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-linux-arm-glibc": {
|
||||
"version": "2.5.6",
|
||||
"resolved": "https://mirror-npm.runflare.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz",
|
||||
"integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-linux-arm-musl": {
|
||||
"version": "2.5.6",
|
||||
"resolved": "https://mirror-npm.runflare.com/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz",
|
||||
"integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-linux-arm64-glibc": {
|
||||
"version": "2.5.6",
|
||||
"resolved": "https://mirror-npm.runflare.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz",
|
||||
"integrity": "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-linux-arm64-musl": {
|
||||
"version": "2.5.6",
|
||||
"resolved": "https://mirror-npm.runflare.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz",
|
||||
"integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-linux-x64-glibc": {
|
||||
"version": "2.5.6",
|
||||
"resolved": "https://mirror-npm.runflare.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz",
|
||||
"integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-linux-x64-musl": {
|
||||
"version": "2.5.6",
|
||||
"resolved": "https://mirror-npm.runflare.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz",
|
||||
"integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-win32-arm64": {
|
||||
"version": "2.5.6",
|
||||
"resolved": "https://mirror-npm.runflare.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz",
|
||||
"integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-win32-ia32": {
|
||||
"version": "2.5.6",
|
||||
"resolved": "https://mirror-npm.runflare.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz",
|
||||
"integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-win32-x64": {
|
||||
"version": "2.5.6",
|
||||
"resolved": "https://mirror-npm.runflare.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz",
|
||||
"integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher/node_modules/picomatch": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://mirror-npm.runflare.com/picomatch/-/picomatch-4.0.4.tgz",
|
||||
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/@rtsao/scc": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://mirror-npm.runflare.com/@rtsao/scc/-/scc-1.1.0.tgz",
|
||||
@@ -1248,6 +1587,210 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@schummar/icu-type-parser": {
|
||||
"version": "1.21.5",
|
||||
"resolved": "https://mirror-npm.runflare.com/@schummar/icu-type-parser/-/icu-type-parser-1.21.5.tgz",
|
||||
"integrity": "sha512-bXHSaW5jRTmke9Vd0h5P7BtWZG9Znqb8gSDxZnxaGSJnGwPLDPfS+3g0BKzeWqzgZPsIVZkM7m2tbo18cm5HBw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@swc/core-darwin-arm64": {
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://mirror-npm.runflare.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.15.30.tgz",
|
||||
"integrity": "sha512-VvpP+vq08HmGYewMWvrdsxh9s2lthz/808zXm8Yu5kaqeR8Yia2b0eYXleHQ3VAjoStUDk6LzTheBW9KXYQdMA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "Apache-2.0 AND MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-darwin-x64": {
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://mirror-npm.runflare.com/@swc/core-darwin-x64/-/core-darwin-x64-1.15.30.tgz",
|
||||
"integrity": "sha512-WiJA0hiZI3nwQAO6mu5RqigtWGDtth4Hiq6rbZxAaQyhIcqKIg5IoMRc1Y071lrNJn29eEDMC86Rq58xgUxlDg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "Apache-2.0 AND MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-arm-gnueabihf": {
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://mirror-npm.runflare.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.15.30.tgz",
|
||||
"integrity": "sha512-YANuFUo48kIT6plJgCD0keae9HFXfjxsbvsgevqc0hr/07X/p7sAWTFOGYEc2SXcASaK7UvuQqzlbW8pr7R79g==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-arm64-gnu": {
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://mirror-npm.runflare.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.15.30.tgz",
|
||||
"integrity": "sha512-VndG8jaR4ugY6u+iVOT0Q+d2fZd7sLgjPgN8W/Le+3EbZKl+cRfFxV7Eoz4gfLqhmneZPdcIzf9T3LkgkmqNLg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "Apache-2.0 AND MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-arm64-musl": {
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://mirror-npm.runflare.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.15.30.tgz",
|
||||
"integrity": "sha512-1SYGs2l0Yyyi0pR/P/NKz/x0kqxkoiw+BXeJjLUdecSk/KasncWlJrc6hOvFSgKHOBrzgM5jwuluKtlT8dnrcA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "Apache-2.0 AND MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-ppc64-gnu": {
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://mirror-npm.runflare.com/@swc/core-linux-ppc64-gnu/-/core-linux-ppc64-gnu-1.15.30.tgz",
|
||||
"integrity": "sha512-TXREtiXeRhbfDFbmhnkIsXpKfzbfT73YkV2ZF6w0sfxgjC5zI2ZAbaCOq25qxvegofj2K93DtOpm9RLaBgqR2g==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"license": "Apache-2.0 AND MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-s390x-gnu": {
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://mirror-npm.runflare.com/@swc/core-linux-s390x-gnu/-/core-linux-s390x-gnu-1.15.30.tgz",
|
||||
"integrity": "sha512-DCR2YYeyd6DQE4OuDhImouuNcjXEiEdnn1Y0DyGteugPEDvVuvYk8Xddi+4o2SgWH6jiW8/I+3emZvbep1NC+g==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"license": "Apache-2.0 AND MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-x64-gnu": {
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://mirror-npm.runflare.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.15.30.tgz",
|
||||
"integrity": "sha512-5Pizw3NgfOJ5BJOBK8TIRa59xFW2avESTOBDPTAYwZYa1JNDs+KMF9lUfjJiJLM5HiMs/wPheA9eiT0q9m2AoA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "Apache-2.0 AND MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-x64-musl": {
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://mirror-npm.runflare.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.15.30.tgz",
|
||||
"integrity": "sha512-qyqydP/wyH8alcIP4a2hnGSjHLJjm9H7yDFup+CPy9oTahFgLLwnNcv5UHXqO2Qs3AIND+cls5f/Bb6hqpxdgA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "Apache-2.0 AND MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-win32-arm64-msvc": {
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://mirror-npm.runflare.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.15.30.tgz",
|
||||
"integrity": "sha512-CaQENgDHVGOg1mSF5sQVgvfFHG9kjMor2rkLMLeLOkfZYNj13ppnJ9+lfaBZLZUMMbnlGQnavCJb8PVBUOso7Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "Apache-2.0 AND MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-win32-ia32-msvc": {
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://mirror-npm.runflare.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.15.30.tgz",
|
||||
"integrity": "sha512-30VdLeGk6fugiUs/kUdJ/pAg7z/zpvVbR11RH60jZ0Z42WIeIniYx0rLEWN7h/pKJ3CopqsQ3RsogCAkRKiA2g==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"license": "Apache-2.0 AND MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-win32-x64-msvc": {
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://mirror-npm.runflare.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.15.30.tgz",
|
||||
"integrity": "sha512-4iObHPR+Q4oDY110EF5SF5eIaaVJNpMdG9C0q3Q92BsJ5y467uHz7sYQhP60WYlLFsLQ1el2YrIPUItUAQGOKg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "Apache-2.0 AND MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/counter": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://mirror-npm.runflare.com/@swc/counter/-/counter-0.1.3.tgz",
|
||||
"integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@swc/helpers": {
|
||||
"version": "0.5.15",
|
||||
"resolved": "https://mirror-npm.runflare.com/@swc/helpers/-/helpers-0.5.15.tgz",
|
||||
@@ -1257,6 +1800,15 @@
|
||||
"tslib": "^2.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/types": {
|
||||
"version": "0.1.26",
|
||||
"resolved": "https://mirror-npm.runflare.com/@swc/types/-/types-0.1.26.tgz",
|
||||
"integrity": "sha512-lyMwd7WGgG79RS7EERZV3T8wMdmPq3xwyg+1nmAM64kIhx5yl+juO2PYIHb7vTiPgPCj8LYjsNV2T5wiQHUEaw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@swc/counter": "^0.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/node": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://mirror-npm.runflare.com/@tailwindcss/node/-/node-4.2.2.tgz",
|
||||
@@ -1640,6 +2192,7 @@
|
||||
"integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"csstype": "^3.2.2"
|
||||
}
|
||||
@@ -1699,6 +2252,7 @@
|
||||
"integrity": "sha512-/Zb/xaIDfxeJnvishjGdcR4jmr7S+bda8PKNhRGdljDM+elXhlvN0FyPSsMnLmJUrVG9aPO6dof80wjMawsASg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "8.58.2",
|
||||
"@typescript-eslint/types": "8.58.2",
|
||||
@@ -2224,6 +2778,7 @@
|
||||
"integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
@@ -2567,6 +3122,7 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"baseline-browser-mapping": "^2.10.12",
|
||||
"caniuse-lite": "^1.0.30001782",
|
||||
@@ -2866,7 +3422,6 @@
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://mirror-npm.runflare.com/detect-libc/-/detect-libc-2.1.2.tgz",
|
||||
"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
|
||||
"devOptional": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
@@ -3134,6 +3689,7 @@
|
||||
"integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.8.0",
|
||||
"@eslint-community/regexpp": "^4.12.1",
|
||||
@@ -3319,6 +3875,7 @@
|
||||
"integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@rtsao/scc": "^1.1.0",
|
||||
"array-includes": "^3.1.9",
|
||||
@@ -3980,6 +4537,21 @@
|
||||
"hermes-estree": "0.25.1"
|
||||
}
|
||||
},
|
||||
"node_modules/icu-minify": {
|
||||
"version": "4.9.1",
|
||||
"resolved": "https://mirror-npm.runflare.com/icu-minify/-/icu-minify-4.9.1.tgz",
|
||||
"integrity": "sha512-6NkfF9GHHFouqnz+wuiLjCWQiyxoEyJ5liUv4Jxxo/8wyhV7MY0L0iTEGDAVEa4aAD58WqTxFMa20S5nyMjwNw==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/amannn"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@formatjs/icu-messageformat-parser": "^3.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ignore": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://mirror-npm.runflare.com/ignore/-/ignore-5.3.2.tgz",
|
||||
@@ -4032,6 +4604,16 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/intl-messageformat": {
|
||||
"version": "11.2.1",
|
||||
"resolved": "https://mirror-npm.runflare.com/intl-messageformat/-/intl-messageformat-11.2.1.tgz",
|
||||
"integrity": "sha512-1gAVEUt3wEPvTqML4Fsw9klZV5j0vszQxayP/fi6gUroAc8AUHiNaisBKLWxybL1AdWq1mP07YV1q8v4N92ilQ==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@formatjs/fast-memoize": "3.1.2",
|
||||
"@formatjs/icu-messageformat-parser": "3.5.4"
|
||||
}
|
||||
},
|
||||
"node_modules/is-array-buffer": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://mirror-npm.runflare.com/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
|
||||
@@ -4194,7 +4776,6 @@
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://mirror-npm.runflare.com/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
@@ -4240,7 +4821,6 @@
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://mirror-npm.runflare.com/is-glob/-/is-glob-4.0.3.tgz",
|
||||
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-extglob": "^2.1.1"
|
||||
@@ -5047,6 +5627,15 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/negotiator": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://mirror-npm.runflare.com/negotiator/-/negotiator-1.0.0.tgz",
|
||||
"integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/next": {
|
||||
"version": "16.2.4",
|
||||
"resolved": "https://mirror-npm.runflare.com/next/-/next-16.2.4.tgz",
|
||||
@@ -5100,6 +5689,83 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/next-intl": {
|
||||
"version": "4.9.1",
|
||||
"resolved": "https://mirror-npm.runflare.com/next-intl/-/next-intl-4.9.1.tgz",
|
||||
"integrity": "sha512-N7ga0CjtYcdxNvaKNIi6eJ2mmatlHK5hp8rt0YO2Omoc1m0gean242/Ukdj6+gJNiReBVcYIjK0HZeNx7CV1ug==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/amannn"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@formatjs/intl-localematcher": "^0.8.1",
|
||||
"@parcel/watcher": "^2.4.1",
|
||||
"@swc/core": "^1.15.2",
|
||||
"icu-minify": "^4.9.1",
|
||||
"negotiator": "^1.0.0",
|
||||
"next-intl-swc-plugin-extractor": "^4.9.1",
|
||||
"po-parser": "^2.1.1",
|
||||
"use-intl": "^4.9.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"next": "^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0",
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/next-intl-swc-plugin-extractor": {
|
||||
"version": "4.9.1",
|
||||
"resolved": "https://mirror-npm.runflare.com/next-intl-swc-plugin-extractor/-/next-intl-swc-plugin-extractor-4.9.1.tgz",
|
||||
"integrity": "sha512-8whJJ6oxJz8JqkHarggmmuEDyXgC7nEnaPhZD91CJwEWW4xp0AST3Mw17YxvHyP2vAF3taWfFbs1maD+WWtz3w==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/next-intl/node_modules/@swc/core": {
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://mirror-npm.runflare.com/@swc/core/-/core-1.15.30.tgz",
|
||||
"integrity": "sha512-R8VQbQY1BZcbIF2p3gjlTCwAQzx1A194ugWfwld5y+WgVVWqVKm7eURGGOVbQVubgKWzidP2agomBbg96rZilQ==",
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@swc/counter": "^0.1.3",
|
||||
"@swc/types": "^0.1.26"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/swc"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@swc/core-darwin-arm64": "1.15.30",
|
||||
"@swc/core-darwin-x64": "1.15.30",
|
||||
"@swc/core-linux-arm-gnueabihf": "1.15.30",
|
||||
"@swc/core-linux-arm64-gnu": "1.15.30",
|
||||
"@swc/core-linux-arm64-musl": "1.15.30",
|
||||
"@swc/core-linux-ppc64-gnu": "1.15.30",
|
||||
"@swc/core-linux-s390x-gnu": "1.15.30",
|
||||
"@swc/core-linux-x64-gnu": "1.15.30",
|
||||
"@swc/core-linux-x64-musl": "1.15.30",
|
||||
"@swc/core-win32-arm64-msvc": "1.15.30",
|
||||
"@swc/core-win32-ia32-msvc": "1.15.30",
|
||||
"@swc/core-win32-x64-msvc": "1.15.30"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@swc/helpers": ">=0.5.17"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@swc/helpers": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/next/node_modules/postcss": {
|
||||
"version": "8.4.31",
|
||||
"resolved": "https://mirror-npm.runflare.com/postcss/-/postcss-8.4.31.tgz",
|
||||
@@ -5128,6 +5794,12 @@
|
||||
"node": "^10 || ^12 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/node-addon-api": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://mirror-npm.runflare.com/node-addon-api/-/node-addon-api-7.1.1.tgz",
|
||||
"integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/node-exports-info": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://mirror-npm.runflare.com/node-exports-info/-/node-exports-info-1.6.0.tgz",
|
||||
@@ -5404,6 +6076,12 @@
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/po-parser": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://mirror-npm.runflare.com/po-parser/-/po-parser-2.1.1.tgz",
|
||||
"integrity": "sha512-ECF4zHLbUItpUgE3OTtLKlPjeBN+fKEczj2zYjDfCGOzicNs0GK3Vg2IoAYwx7LH/XYw43fZQP6xnZ4TkNxSLQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/possible-typed-array-names": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://mirror-npm.runflare.com/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
|
||||
@@ -5501,6 +6179,7 @@
|
||||
"resolved": "https://mirror-npm.runflare.com/react/-/react-19.2.4.tgz",
|
||||
"integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@@ -5510,6 +6189,7 @@
|
||||
"resolved": "https://mirror-npm.runflare.com/react-dom/-/react-dom-19.2.4.tgz",
|
||||
"integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"scheduler": "^0.27.0"
|
||||
},
|
||||
@@ -6201,6 +6881,7 @@
|
||||
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@@ -6363,6 +7044,7 @@
|
||||
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
@@ -6497,6 +7179,27 @@
|
||||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/use-intl": {
|
||||
"version": "4.9.1",
|
||||
"resolved": "https://mirror-npm.runflare.com/use-intl/-/use-intl-4.9.1.tgz",
|
||||
"integrity": "sha512-iGVV/xFYlhe3btafRlL8RPLD2Jsuet4yqn9DR6LWWbMhULsJnXgLonDkzDmsAIBIwFtk02oJuX/Ox2vwHKF+UQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/amannn"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@formatjs/fast-memoize": "^3.1.0",
|
||||
"@schummar/icu-type-parser": "1.21.5",
|
||||
"icu-minify": "^4.9.1",
|
||||
"intl-messageformat": "^11.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/which": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://mirror-npm.runflare.com/which/-/which-2.0.2.tgz",
|
||||
@@ -6638,6 +7341,7 @@
|
||||
"integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/colinhacks"
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
"dependencies": {
|
||||
"lucide-react": "^1.8.0",
|
||||
"next": "16.2.4",
|
||||
"next-intl": "^4.9.1",
|
||||
"react": "19.2.4",
|
||||
"react-dom": "19.2.4"
|
||||
},
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
}
|
||||
|
||||
body {
|
||||
direction: rtl;
|
||||
background-color: var(--background);
|
||||
color: var(--foreground);
|
||||
}
|
||||
40
src/app/[locale]/layout.tsx
Normal file
40
src/app/[locale]/layout.tsx
Normal file
@@ -0,0 +1,40 @@
|
||||
import type { Metadata } from "next";
|
||||
import "./globals.css";
|
||||
import localFont from "next/font/local";
|
||||
import { NextIntlClientProvider } from "next-intl";
|
||||
import { getMessages } from "next-intl/server";
|
||||
import Navbar from "@/components/shared/Navbar";
|
||||
import { notFound } from "next/navigation";
|
||||
|
||||
const modam = localFont({
|
||||
src: "../../../public/fonts/ModamWeb-Bold.woff2",
|
||||
weight: "100 900",
|
||||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "رایین شبکه | توسعه نرمافزار",
|
||||
description: "ساخت اپلیکیشنهای وب مدرن و سیستمهای سازمانی",
|
||||
};
|
||||
|
||||
const locales = ["fa", "en", "ar"];
|
||||
|
||||
export default async function LocaleLayout({ children, params }: { children: React.ReactNode; params: Promise<{ locale: string }> }) {
|
||||
const { locale } = await params;
|
||||
|
||||
if (!locales.includes(locale)) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
const messages = await getMessages({ locale });
|
||||
|
||||
return (
|
||||
<html lang={locale} dir={locale === "en" ? "ltr" : "rtl"}>
|
||||
<body className={`${modam.className} flex flex-col min-h-screen bg-bg text-foreground`}>
|
||||
<NextIntlClientProvider messages={messages}>
|
||||
<Navbar />
|
||||
{children}
|
||||
</NextIntlClientProvider>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
@@ -1,24 +1,28 @@
|
||||
import BentoServices from "@/components/home/BentoServices";
|
||||
import HomeAcademy from "@/components/home/HomeAcademy";
|
||||
import HomeHero from "@/components/home/HomeHero";
|
||||
import HomeProjects from "@/components/home/HomeProjects";
|
||||
import TechMarquee from "@/components/home/TechMarquee";
|
||||
import Hero from "@/components/home/hero/Hero";
|
||||
import Consultation from "@/components/network/Consultation";
|
||||
import ContactFooter from "@/components/network/ContactFooter";
|
||||
import Services from "@/components/home/Services";
|
||||
import Projects from "@/components/home/Projects";
|
||||
import { BACKEND_URL_LOCAL } from "@/utilities/constants/urls.constant";
|
||||
import { Portfolio } from "@/utilities/types/portfolio.type";
|
||||
|
||||
export default async function HomePage({ params }: { params: Promise<{ locale: string }> }) {
|
||||
const { locale } = await params;
|
||||
|
||||
const latestPortfolios: Portfolio[] = await fetch(`${BACKEND_URL_LOCAL}/portfolios/latest/${locale}`)
|
||||
.then((res) => res.json())
|
||||
.then((res) => res.data);
|
||||
|
||||
export default function HomePage() {
|
||||
return (
|
||||
<div className="min-h-screen bg-[#0B1120] text-white font-sans selection:bg-orange-500/30 rtl" dir="rtl">
|
||||
{/* Background Glow */}
|
||||
<div className="min-h-screen bg-[#0B1120] text-white font-sans selection:bg-orange-500/30">
|
||||
<div className="fixed top-0 inset-x-0 h-[500px] bg-gradient-to-b from-orange-500/5 via-transparent to-transparent pointer-events-none -z-10"></div>
|
||||
|
||||
<main className="flex flex-col gap-24 pt-32 pb-12">
|
||||
<HomeHero />
|
||||
<TechMarquee />
|
||||
|
||||
<Hero />
|
||||
<div className="w-full px-4 mx-auto space-y-32 max-w-7xl sm:px-6 lg:px-8">
|
||||
<BentoServices />
|
||||
<HomeProjects />
|
||||
<Services />
|
||||
<Projects data={latestPortfolios} />
|
||||
<HomeAcademy />
|
||||
<div>
|
||||
<Consultation />
|
||||
@@ -1,29 +0,0 @@
|
||||
import type { Metadata } from "next";
|
||||
import "./globals.css";
|
||||
import localFont from "next/font/local";
|
||||
import Navbar from "@/components/shared/Navbar";
|
||||
|
||||
const modam = localFont({
|
||||
src: "../../public/fonts/ModamWeb-Bold.woff2",
|
||||
weight: "100 900",
|
||||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "رایین شبکه | توسعه نرمافزار",
|
||||
description: "ساخت اپلیکیشنهای وب مدرن و سیستمهای سازمانی",
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: Readonly<{
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
return (
|
||||
<html lang="fa-ir" className={modam.className}>
|
||||
<body className="flex flex-col min-h-screen bg-bg text-foreground">
|
||||
<Navbar />
|
||||
{children}
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
import React from "react";
|
||||
import { ChevronLeft } from "lucide-react";
|
||||
|
||||
export default function HomeHero() {
|
||||
return (
|
||||
<section className="flex flex-col items-center justify-center max-w-4xl px-4 mx-auto text-center">
|
||||
{/* Top Badge */}
|
||||
<div className="inline-flex items-center gap-2 px-4 py-2 mb-8 text-sm text-orange-400 border rounded-full border-orange-500/20 bg-orange-500/10">
|
||||
<span className="w-2 h-2 bg-orange-500 rounded-full animate-pulse"></span>
|
||||
معماری سیستمهای مقیاسپذیر
|
||||
</div>
|
||||
|
||||
{/* Main Title */}
|
||||
<h1 className="mb-6 text-5xl font-bold leading-tight md:text-7xl">
|
||||
ما گرههای فنی شما را
|
||||
<br />
|
||||
باز میکنیم
|
||||
</h1>
|
||||
|
||||
{/* Subtitle */}
|
||||
<p className="max-w-2xl mb-10 text-lg leading-relaxed text-gray-400 md:text-xl">
|
||||
ترکیبی از اقتدار مهندسی در زیرساخت و نوآوری مدرن در توسعه نرمافزار، از راهاندازی شبکههای پیچیده تا توسعه پلتفرمهای ابری سفارشی.
|
||||
</p>
|
||||
|
||||
{/* CTA Buttons */}
|
||||
<div className="flex flex-col items-center gap-4 sm:flex-row">
|
||||
<button className="flex items-center justify-center w-full gap-2 px-8 py-3 font-medium text-white transition-colors bg-orange-600 rounded-lg sm:w-auto hover:bg-orange-500">
|
||||
دریافت مشاوره رایگان
|
||||
<ChevronLeft className="w-4 h-4" />
|
||||
</button>
|
||||
<button className="flex items-center justify-center w-full px-8 py-3 font-medium text-white transition-colors border rounded-lg sm:w-auto border-slate-700 bg-slate-800/50 hover:bg-slate-800">
|
||||
مشاهده نمونهکارها
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState } from "react";
|
||||
import { ArrowUpLeft, FolderKanban } from "lucide-react";
|
||||
|
||||
const projectsData = [
|
||||
{
|
||||
id: 1,
|
||||
title: "ارتقای زیرساخت شبکه هلدینگ دارویی",
|
||||
category: "شبکه",
|
||||
description: "طراحی مجدد توپولوژی شبکه و پیادهسازی فایروالهای سختافزاری برای امنیت حداکثری.",
|
||||
image: "bg-slate-800", // در پروژه واقعی از آدرس تصویر استفاده کنید
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: "پلتفرم مدیریت منابع انسانی (HRM)",
|
||||
category: "نرمافزار",
|
||||
description: "توسعه سیستم جامع مدیریت پرسنل با استفاده از Next.js و .NET Core.",
|
||||
image: "bg-slate-800",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: "طراحی هویت بصری استارتاپ فینتک",
|
||||
category: "برندینگ",
|
||||
description: "طراحی کامل UI/UX اپلیکیشن موبایل و دیزاین سیستم سازمانی.",
|
||||
image: "bg-slate-800",
|
||||
},
|
||||
];
|
||||
|
||||
const tabs = ["همه", "شبکه", "نرمافزار", "برندینگ"];
|
||||
|
||||
export default function HomeProjects() {
|
||||
const [activeTab, setActiveTab] = useState("همه");
|
||||
|
||||
const filteredProjects = projectsData.filter((project) => (activeTab === "همه" ? true : project.category === activeTab));
|
||||
|
||||
return (
|
||||
<section className="py-12 border-t border-slate-800/50">
|
||||
<div className="flex flex-col justify-between gap-6 mb-12 md:flex-row md:items-end">
|
||||
<div>
|
||||
<h2 className="flex items-center gap-3 mb-4 text-3xl font-bold text-white">
|
||||
<FolderKanban className="text-orange-500" />
|
||||
پروژههای منتخب
|
||||
</h2>
|
||||
<p className="text-gray-400">گزیدهای از چالشهایی که با موفقیت پشت سر گذاشتیم.</p>
|
||||
</div>
|
||||
|
||||
{/* Tabs */}
|
||||
<div className="flex flex-wrap items-center gap-2 p-1 border bg-slate-900/50 rounded-xl border-slate-800 w-fit">
|
||||
{tabs.map((tab) => (
|
||||
<button
|
||||
key={tab}
|
||||
onClick={() => setActiveTab(tab)}
|
||||
className={`px-4 py-2 rounded-lg text-sm font-medium transition-colors ${
|
||||
activeTab === tab ? "bg-orange-500 text-white shadow-lg shadow-orange-500/20" : "text-gray-400 hover:text-white hover:bg-slate-800/50"
|
||||
}`}
|
||||
>
|
||||
{tab}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
|
||||
{filteredProjects.map((project) => (
|
||||
<div
|
||||
key={project.id}
|
||||
className="overflow-hidden transition-all duration-300 border cursor-pointer group bg-slate-900/30 border-slate-800 rounded-2xl hover:border-orange-500/50"
|
||||
>
|
||||
{/* Image placeholder */}
|
||||
<div className={`h-48 w-full ${project.image} relative overflow-hidden`}>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-slate-900 via-transparent to-transparent opacity-80"></div>
|
||||
<div className="absolute px-3 py-1 text-xs text-gray-300 border rounded-full top-4 right-4 bg-black/50 backdrop-blur-sm border-slate-700">
|
||||
{project.category}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="p-6">
|
||||
<h3 className="mb-2 text-xl font-bold text-white transition-colors group-hover:text-orange-500">{project.title}</h3>
|
||||
<p className="mb-6 text-sm text-gray-400 line-clamp-2">{project.description}</p>
|
||||
|
||||
<div className="flex items-center justify-between text-sm font-medium text-orange-500">
|
||||
<span>مشاهده پروژه</span>
|
||||
<ArrowUpLeft className="w-5 h-5 transition-transform group-hover:-translate-y-1 group-hover:translate-x-1" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
89
src/components/home/Projects.tsx
Normal file
89
src/components/home/Projects.tsx
Normal file
@@ -0,0 +1,89 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { ArrowUpLeft, ArrowUpRight, FolderKanban } from "lucide-react";
|
||||
import { Portfolio } from "@/utilities/types/portfolio.type";
|
||||
import { useTranslations, useLocale } from "next-intl";
|
||||
import Image from "next/image";
|
||||
import { BACKEND_URL } from "@/utilities/constants/urls.constant";
|
||||
|
||||
const tabs = ["all", "software", "network"] as const;
|
||||
|
||||
export default function Projects({ data }: { data: Portfolio[] }) {
|
||||
const [activeTab, setActiveTab] = useState<string>("all");
|
||||
const t = useTranslations("home.projects");
|
||||
const locale = useLocale();
|
||||
|
||||
const filteredPortfolios = data.filter((p) => (activeTab === "all" ? true : p.category === activeTab));
|
||||
|
||||
const ArrowIcon = locale === "en" ? ArrowUpRight : ArrowUpLeft;
|
||||
|
||||
return (
|
||||
<section className="py-12 border-t border-slate-800/50" id="portfolios_form">
|
||||
<div className="flex flex-col justify-between gap-6 mb-12 md:flex-row md:items-end">
|
||||
<div>
|
||||
<h2 className="flex items-center gap-3 mb-4 text-3xl font-bold text-white">
|
||||
<FolderKanban className="text-orange-500" />
|
||||
{t("title")}
|
||||
</h2>
|
||||
<p className="text-gray-400">{t("subtitle")}</p>
|
||||
</div>
|
||||
|
||||
{/* Tabs */}
|
||||
<div className="flex flex-wrap items-center gap-2 p-1 border bg-slate-900/50 rounded-xl border-slate-800 w-fit">
|
||||
{tabs.map((tab) => (
|
||||
<button
|
||||
key={tab}
|
||||
onClick={() => setActiveTab(tab)}
|
||||
className={`px-4 py-2 rounded-lg text-sm font-medium transition-colors ${
|
||||
activeTab === tab ? "bg-orange-500 text-white shadow-lg shadow-orange-500/20" : "text-gray-400 hover:text-white hover:bg-slate-800/50"
|
||||
}`}
|
||||
>
|
||||
{t(`tabs.${tab}`)}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
|
||||
{filteredPortfolios.map((p) => (
|
||||
<div
|
||||
key={p.id}
|
||||
className="flex flex-col h-full overflow-hidden transition-all duration-300 border cursor-pointer group bg-slate-900/30 border-slate-800 rounded-2xl hover:border-orange-500/50"
|
||||
>
|
||||
{/* Image placeholder */}
|
||||
<div className="relative w-full h-48 overflow-hidden shrink-0">
|
||||
<Image
|
||||
src={`${BACKEND_URL}/uploads/${p.featuredImage}`}
|
||||
fill
|
||||
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
|
||||
className="object-cover transition-transform duration-500 group-hover:scale-105"
|
||||
alt={`تصویر ${p.title}`}
|
||||
/>
|
||||
<div className="absolute px-3 py-1 text-xs text-gray-300 border rounded-full top-4 right-4 rtl:right-auto rtl:left-4 bg-black/50 backdrop-blur-sm border-slate-700">
|
||||
{t(`tabs.${p.category}`)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Content wrapper taking remaining height */}
|
||||
<div className="flex flex-col flex-1 p-6">
|
||||
{/* Title & Desc wrapper pushed to top */}
|
||||
<div className="mb-auto">
|
||||
<h3 className="mb-2 text-xl font-bold text-white transition-colors group-hover:text-orange-500 line-clamp-2">{p.title}</h3>
|
||||
<p className="mb-6 text-sm text-gray-400 line-clamp-2">{p.description}</p>
|
||||
</div>
|
||||
|
||||
{/* View Project button pushed to bottom */}
|
||||
<div className="flex items-center justify-between mt-4 text-sm font-medium text-orange-500">
|
||||
<span>{t("view_project")}</span>
|
||||
<ArrowIcon
|
||||
className={`w-5 h-5 transition-transform group-hover:-translate-y-1 ${locale === "en" ? "group-hover:translate-x-1" : "group-hover:-translate-x-1"}`}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -1,12 +1,16 @@
|
||||
import React from "react";
|
||||
import { Network, Code, PenTool, GraduationCap } from "lucide-react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import Link from "next/link";
|
||||
|
||||
export default function Services() {
|
||||
const t = useTranslations("home.services");
|
||||
|
||||
export default function BentoServices() {
|
||||
return (
|
||||
<section>
|
||||
<div className="mb-12 text-center">
|
||||
<h2 className="mb-4 text-3xl font-bold text-white">راهکارهای یکپارچه</h2>
|
||||
<p className="text-gray-400">خدمات ما پازلهای تکمیلکننده کسبوکار شما هستند.</p>
|
||||
<h2 className="mb-4 text-3xl font-bold text-white">{t("title")}</h2>
|
||||
<p className="text-gray-400">{t("subtitle")}</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 gap-6 lg:grid-cols-2">
|
||||
@@ -17,11 +21,9 @@ export default function BentoServices() {
|
||||
<div className="p-3 text-orange-500 bg-slate-800 rounded-xl">
|
||||
<Network className="w-6 h-6" />
|
||||
</div>
|
||||
<h3 className="text-2xl font-bold">زیرساخت و امنیت شبکه</h3>
|
||||
<h3 className="text-2xl font-bold">{t("network.title")}</h3>
|
||||
</div>
|
||||
<p className="max-w-md leading-relaxed text-gray-400">
|
||||
طراحی، پیادهسازی و ایمنسازی شبکههای پیچیده. از کانفیگ روترهای سختافزاری تا مانیتورینگ لایه هفت.
|
||||
</p>
|
||||
<p className="max-w-md leading-relaxed text-gray-400">{t("network.desc")}</p>
|
||||
</div>
|
||||
<div className="relative w-full h-32 mt-8 overflow-hidden border bg-slate-800/50 rounded-xl border-slate-700/50">
|
||||
{/* Decorative element representing network */}
|
||||
@@ -40,9 +42,9 @@ export default function BentoServices() {
|
||||
<div className="p-2 text-orange-500 rounded-lg bg-slate-800">
|
||||
<Code className="w-5 h-5" />
|
||||
</div>
|
||||
<h3 className="text-xl font-bold">توسعه نرمافزار اختصاصی</h3>
|
||||
<h3 className="text-xl font-bold">{t("software.title")}</h3>
|
||||
</div>
|
||||
<p className="text-sm text-gray-400">ساخت پلتفرمهای ابری قدرتمند و اتوماسیون فرآیندهای سازمانی.</p>
|
||||
<p className="text-sm text-gray-400">{t("software.desc")}</p>
|
||||
</div>
|
||||
|
||||
{/* Bottom Two Cards */}
|
||||
@@ -51,19 +53,22 @@ export default function BentoServices() {
|
||||
<div className="flex flex-col justify-between p-6 transition-colors border bg-slate-900/40 border-slate-800 rounded-2xl hover:border-orange-500/50">
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<PenTool className="w-5 h-5 text-orange-500" />
|
||||
<h3 className="text-lg font-bold">هویت بصری</h3>
|
||||
<h3 className="text-lg font-bold">{t("branding.title")}</h3>
|
||||
</div>
|
||||
<p className="mt-2 text-xs text-gray-400">طراحی رابط کاربری (UI/UX) و برندینگ مدرن.</p>
|
||||
<p className="mt-2 text-xs text-gray-400">{t("branding.desc")}</p>
|
||||
</div>
|
||||
|
||||
{/* Academy Card */}
|
||||
<div className="relative flex flex-col items-center justify-center p-6 overflow-hidden text-center transition-colors border bg-gradient-to-br from-slate-900 to-slate-800 border-slate-700 rounded-2xl hover:border-orange-500/50">
|
||||
<div className="absolute inset-0 bg-orange-500/5"></div>
|
||||
<GraduationCap className="relative z-10 w-8 h-8 mb-3 text-orange-500" />
|
||||
<h3 className="relative z-10 mb-3 text-lg font-bold">آکادمی</h3>
|
||||
<button className="relative z-10 px-6 py-2 text-sm text-white transition-colors border rounded-lg bg-slate-800 hover:bg-slate-700 border-slate-600">
|
||||
ورود
|
||||
</button>
|
||||
<h3 className="relative z-10 mb-3 text-lg font-bold">{t("academy.title")}</h3>
|
||||
<Link
|
||||
href={"/academy"}
|
||||
className="relative z-10 px-6 py-2 text-sm text-white transition-colors border rounded-lg bg-slate-800 hover:bg-slate-700 border-slate-600"
|
||||
>
|
||||
{t("academy.btn_enter")}
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
35
src/components/home/hero/Hero.tsx
Normal file
35
src/components/home/hero/Hero.tsx
Normal file
@@ -0,0 +1,35 @@
|
||||
import { useTranslations } from "next-intl";
|
||||
import HeroButtons from "./HeroButtons";
|
||||
import HeroTech from "./HeroTech";
|
||||
|
||||
export default function Hero() {
|
||||
const t = useTranslations("home.hero");
|
||||
|
||||
return (
|
||||
<>
|
||||
<section className="flex flex-col items-center justify-center max-w-4xl px-4 mx-auto text-center">
|
||||
{/* Top Badge */}
|
||||
<div className="inline-flex items-center gap-2 px-4 py-2 mb-8 text-sm text-orange-400 border rounded-full border-orange-500/20 bg-orange-500/10">
|
||||
<span className="w-2 h-2 bg-orange-500 rounded-full animate-pulse"></span>
|
||||
{t("badge")}
|
||||
</div>
|
||||
|
||||
{/* Main Title */}
|
||||
<h1 className="mb-6 text-5xl font-bold leading-tight md:text-7xl">
|
||||
{t("title1")}
|
||||
<br />
|
||||
{t("title2")}
|
||||
</h1>
|
||||
|
||||
{/* Subtitle */}
|
||||
<p className="max-w-2xl mb-10 text-lg leading-relaxed text-gray-400 md:text-xl">{t("subtitle")}</p>
|
||||
|
||||
{/* CTA Buttons */}
|
||||
<div className="flex flex-col items-center gap-4 sm:flex-row">
|
||||
<HeroButtons />
|
||||
</div>
|
||||
</section>
|
||||
<HeroTech />
|
||||
</>
|
||||
);
|
||||
}
|
||||
31
src/components/home/hero/HeroButtons.tsx
Normal file
31
src/components/home/hero/HeroButtons.tsx
Normal file
@@ -0,0 +1,31 @@
|
||||
"use client";
|
||||
|
||||
import { handleScrollToId } from "@/utilities/lib/scroll";
|
||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||
import { useTranslations, useLocale } from "next-intl";
|
||||
|
||||
export default function HeroButtons() {
|
||||
const t = useTranslations("home.hero");
|
||||
const locale = useLocale();
|
||||
|
||||
// Choose the right chevron based on text direction
|
||||
const isRtl = locale === "fa" || locale === "ar";
|
||||
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
onClick={() => handleScrollToId("portfolios_form")}
|
||||
className="flex items-center justify-center w-full px-8 py-3 font-medium text-white transition-colors border rounded-lg sm:w-auto border-slate-700 bg-slate-800/50 hover:bg-slate-800"
|
||||
>
|
||||
{t("btn_portfolio")}
|
||||
</button>
|
||||
<button
|
||||
onClick={() => handleScrollToId("contact_form")}
|
||||
className="flex items-center justify-center w-full gap-2 px-8 py-3 font-medium text-white transition-colors bg-orange-600 rounded-lg sm:w-auto hover:bg-orange-500"
|
||||
>
|
||||
{t("btn_consulting")}
|
||||
{isRtl ? <ChevronLeft className="w-4 h-4" /> : <ChevronRight className="w-4 h-4" />}
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,14 +1,12 @@
|
||||
export default function TechMarquee() {
|
||||
export default function HeroTech() {
|
||||
const techs = ["Node.js", "Next.js", "MikroTik", "Figma", "Ollama AI", "Docker & Coolify", ".NET"];
|
||||
|
||||
return (
|
||||
<div className="relative w-full py-4 overflow-hidden border-y border-slate-800/50 bg-slate-900/20">
|
||||
{/* Gradient masks for fading edges */}
|
||||
<div className="absolute inset-y-0 right-0 w-32 bg-gradient-to-l from-[#0B1120] to-transparent z-10"></div>
|
||||
<div className="absolute inset-y-0 left-0 w-32 bg-gradient-to-r from-[#0B1120] to-transparent z-10"></div>
|
||||
|
||||
<div className="flex flex-wrap justify-center gap-12 px-4 opacity-50 whitespace-nowrap">
|
||||
{/* In a real app, you'd use a CSS animation here for infinite scrolling */}
|
||||
{techs.map((tech, index) => (
|
||||
<div key={index} className="flex items-center gap-2 text-lg font-medium text-gray-400">
|
||||
<span className="flex items-center justify-center w-6 h-6 text-xs border rounded bg-slate-800 border-slate-700"></span>
|
||||
@@ -1,6 +1,6 @@
|
||||
export default function Consultation() {
|
||||
return (
|
||||
<div className="w-full max-w-6xl px-5 mx-auto mt-10">
|
||||
<div className="w-full max-w-6xl px-5 mx-auto mt-10" id="contact_form">
|
||||
<div className="relative grid grid-cols-1 gap-10 p-10 overflow-hidden border border-b-0 shadow-2xl bg-panel border-border rounded-t-3xl lg:grid-cols-2">
|
||||
<div className="absolute -top-12 left-1/2 -translate-x-1/2 w-[80%] h-[100px] bg-[radial-gradient(ellipse,rgba(199,92,67,0.15),transparent_70%)] pointer-events-none" />
|
||||
|
||||
|
||||
@@ -1,34 +1,78 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import Link from "next/link";
|
||||
import { useTranslations, useLocale } from "next-intl";
|
||||
import { usePathname, useRouter } from "next/navigation";
|
||||
|
||||
export default function Navbar() {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const t = useTranslations("navbar");
|
||||
const locale = useLocale();
|
||||
const pathname = usePathname();
|
||||
const router = useRouter();
|
||||
|
||||
const languages = [
|
||||
{ code: "fa", flag: "🇮🇷", label: "فارسی" },
|
||||
{ code: "en", flag: "🇬🇧", label: "English" },
|
||||
{ code: "ar", flag: "🇸🇦", label: "العربية" },
|
||||
];
|
||||
|
||||
const handleLanguageChange = (newLocale: string) => {
|
||||
// Replace the current locale in the URL path with the new one
|
||||
const newPath = pathname.replace(new RegExp(`^/${locale}`), `/${newLocale}`);
|
||||
router.replace(newPath);
|
||||
};
|
||||
|
||||
return (
|
||||
<header className="sticky top-0 z-50 border-b backdrop-blur-lg bg-bg/80 border-white/5">
|
||||
<div className="flex items-center justify-between px-6 py-4 mx-auto max-w-7xl">
|
||||
{/* Logo */}
|
||||
<div className="text-xl font-bold">
|
||||
رابین <span className="text-accent">شبکه</span>
|
||||
</div>
|
||||
<Link href={`/${locale}`} className="text-xl font-bold">
|
||||
{t("logo1")} <span className="text-accent">{t("logo2")}</span>
|
||||
</Link>
|
||||
|
||||
{/* Desktop Navigation */}
|
||||
<nav className="hidden md:block">
|
||||
<ul className="flex gap-8 text-sm text-muted">
|
||||
<li className="transition cursor-pointer hover:text-foreground">صفحه اصلی</li>
|
||||
<li className="transition cursor-pointer hover:text-foreground">خدمات</li>
|
||||
<li className="transition cursor-pointer hover:text-foreground">تکنولوژی</li>
|
||||
<li className="transition cursor-pointer hover:text-foreground">فرآیند</li>
|
||||
<li className="transition cursor-pointer hover:text-foreground">پروژهها</li>
|
||||
<li>
|
||||
<Link href={`/${locale}`} className="transition cursor-pointer hover:text-foreground">
|
||||
{t("home")}
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href={`/${locale}/software`} className="transition cursor-pointer hover:text-foreground">
|
||||
{t("software")}
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href={`/${locale}/network`} className="transition cursor-pointer hover:text-foreground">
|
||||
{t("network")}
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href={`/${locale}/academy`} className="transition cursor-pointer hover:text-foreground">
|
||||
{t("academy")}
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
{/* Desktop Actions & Mobile Menu Toggle */}
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="hidden gap-3 md:flex">
|
||||
<button className="border border-border px-3 py-1.5 rounded-md text-sm hover:bg-card transition">EN</button>
|
||||
<button className="border border-border px-3 py-1.5 rounded-md text-sm hover:bg-card transition">☾</button>
|
||||
<div className="hidden gap-2 md:flex">
|
||||
{languages.map((language) => (
|
||||
<button
|
||||
key={language.code}
|
||||
onClick={() => handleLanguageChange(language.code)}
|
||||
className={`border px-3 py-1.5 rounded-md text-sm transition ${
|
||||
locale === language.code ? "border-accent bg-accent/10" : "border-border hover:bg-card"
|
||||
}`}
|
||||
title={language.label}
|
||||
>
|
||||
{language.flag}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Mobile Menu Button */}
|
||||
@@ -51,17 +95,41 @@ export default function Navbar() {
|
||||
<div className="border-t md:hidden border-white/5 bg-bg/95 backdrop-blur-lg">
|
||||
<nav className="px-6 py-4">
|
||||
<ul className="flex flex-col gap-4 text-sm text-muted">
|
||||
<li className="transition cursor-pointer hover:text-foreground">صفحه اصلی</li>
|
||||
<li className="transition cursor-pointer hover:text-foreground">خدمات</li>
|
||||
<li className="transition cursor-pointer hover:text-foreground">تکنولوژی</li>
|
||||
<li className="transition cursor-pointer hover:text-foreground">فرآیند</li>
|
||||
<li className="transition cursor-pointer hover:text-foreground">پروژهها</li>
|
||||
<li>
|
||||
<Link href={`/${locale}`} className="transition cursor-pointer hover:text-foreground" onClick={() => setIsOpen(false)}>
|
||||
{t("home")}
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href={`/${locale}/software`} className="transition cursor-pointer hover:text-foreground" onClick={() => setIsOpen(false)}>
|
||||
{t("software")}
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href={`/${locale}/network`} className="transition cursor-pointer hover:text-foreground" onClick={() => setIsOpen(false)}>
|
||||
{t("network")}
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href={`/${locale}/academy`} className="transition cursor-pointer hover:text-foreground" onClick={() => setIsOpen(false)}>
|
||||
{t("academy")}
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
{/* Mobile Actions */}
|
||||
<div className="flex gap-3 pt-4 mt-6 border-t border-white/5">
|
||||
<button className="border border-border px-3 py-1.5 rounded-md text-sm hover:bg-card transition flex-1">EN</button>
|
||||
<button className="border border-border px-3 py-1.5 rounded-md text-sm hover:bg-card transition flex-1">☾</button>
|
||||
{/* Mobile Language Switcher */}
|
||||
<div className="flex gap-2 pt-4 mt-6 border-t border-white/5">
|
||||
{languages.map((language) => (
|
||||
<button
|
||||
key={language.code}
|
||||
onClick={() => handleLanguageChange(language.code)}
|
||||
className={`border px-3 py-1.5 rounded-md text-sm transition flex-1 ${
|
||||
locale === language.code ? "border-accent bg-accent/10" : "border-border hover:bg-card"
|
||||
}`}
|
||||
>
|
||||
{language.flag} {language.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
18
src/i18n.ts
Normal file
18
src/i18n.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
// src/i18n.ts
|
||||
import { getRequestConfig } from "next-intl/server";
|
||||
import { notFound } from "next/navigation";
|
||||
|
||||
const locales = ["fa", "en", "ar"];
|
||||
|
||||
export default getRequestConfig(async ({ requestLocale }) => {
|
||||
let locale = await requestLocale;
|
||||
|
||||
if (!locale || !locales.includes(locale as string)) {
|
||||
locale = "fa";
|
||||
}
|
||||
|
||||
return {
|
||||
locale,
|
||||
messages: (await import(`./messages/${locale}.json`)).default,
|
||||
};
|
||||
});
|
||||
50
src/messages/ar.json
Normal file
50
src/messages/ar.json
Normal file
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"navbar": {
|
||||
"home": "الرئيسية",
|
||||
"software": "برمجة",
|
||||
"network": "شبكة",
|
||||
"academy": "أكاديمية",
|
||||
"logo1": "رابين",
|
||||
"logo2": "شبكة"
|
||||
},
|
||||
"home": {
|
||||
"hero": {
|
||||
"badge": "هندسة الأنظمة القابلة للتطوير",
|
||||
"title1": "نحن نفك عقدك",
|
||||
"title2": "التقنية",
|
||||
"subtitle": "مزيج من السلطة الهندسية في البنية التحتية والابتكار الحديث في تطوير البرمجيات، من إعداد الشبكات المعقدة إلى تطوير منصات سحابية مخصصة.",
|
||||
"btn_consulting": "احصل على استشارة مجانية",
|
||||
"btn_portfolio": "عرض الأعمال"
|
||||
},
|
||||
"services": {
|
||||
"title": "حلول متكاملة",
|
||||
"subtitle": "خدماتنا هي القطع المكملة للغز عملك.",
|
||||
"network": {
|
||||
"title": "البنية التحتية وأمن الشبكات",
|
||||
"desc": "تصميم وتنفيذ وتأمين الشبكات المعقدة. من تكوين أجهزة التوجيه إلى مراقبة الطبقة السابعة."
|
||||
},
|
||||
"software": {
|
||||
"title": "تطوير برمجيات مخصصة",
|
||||
"desc": "بناء منصات سحابية قوية وأتمتة العمليات المؤسسية."
|
||||
},
|
||||
"branding": {
|
||||
"title": "الهوية البصرية",
|
||||
"desc": "تصميم واجهة المستخدم (UI/UX) والعلامات التجارية الحديثة."
|
||||
},
|
||||
"academy": {
|
||||
"title": "أكاديمية",
|
||||
"btn_enter": "مشاهدة"
|
||||
}
|
||||
},
|
||||
"projects": {
|
||||
"title": "مشاريع مختارة",
|
||||
"subtitle": "مجموعة مختارة من التحديات التي تغلبنا عليها بنجاح.",
|
||||
"view_project": "عرض المشروع",
|
||||
"tabs": {
|
||||
"all": "الكل",
|
||||
"software": "برمجيات",
|
||||
"network": "شبكات"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
50
src/messages/en.json
Normal file
50
src/messages/en.json
Normal file
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"navbar": {
|
||||
"home": "Home",
|
||||
"software": "Software",
|
||||
"network": "Network",
|
||||
"academy": "Academy",
|
||||
"logo1": "Robin",
|
||||
"logo2": "Network"
|
||||
},
|
||||
"home": {
|
||||
"hero": {
|
||||
"badge": "Scalable Systems Architecture",
|
||||
"title1": "We untangle your",
|
||||
"title2": "technical knots",
|
||||
"subtitle": "A combination of engineering authority in infrastructure and modern innovation in software development, from setting up complex networks to developing custom cloud platforms.",
|
||||
"btn_consulting": "Get Free Consultation",
|
||||
"btn_portfolio": "View Portfolio"
|
||||
},
|
||||
"services": {
|
||||
"title": "Integrated Solutions",
|
||||
"subtitle": "Our services are the missing pieces of your business puzzle.",
|
||||
"network": {
|
||||
"title": "Network Infrastructure & Security",
|
||||
"desc": "Designing, implementing, and securing complex networks. From hardware router configuration to Layer 7 monitoring."
|
||||
},
|
||||
"software": {
|
||||
"title": "Custom Software Development",
|
||||
"desc": "Building powerful cloud platforms and enterprise process automation."
|
||||
},
|
||||
"branding": {
|
||||
"title": "Visual Identity",
|
||||
"desc": "Modern UI/UX design and branding."
|
||||
},
|
||||
"academy": {
|
||||
"title": "Academy",
|
||||
"btn_enter": "View"
|
||||
}
|
||||
},
|
||||
"projects": {
|
||||
"title": "Featured Projects",
|
||||
"subtitle": "A selection of challenges we have successfully overcome.",
|
||||
"view_project": "View Project",
|
||||
"tabs": {
|
||||
"all": "All",
|
||||
"software": "Software",
|
||||
"network": "Network"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
50
src/messages/fa.json
Normal file
50
src/messages/fa.json
Normal file
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"navbar": {
|
||||
"home": "صفحه اصلی",
|
||||
"software": "نرم افزار",
|
||||
"network": "شبکه",
|
||||
"academy": "آکادمی",
|
||||
"logo1": "رابین",
|
||||
"logo2": "شبکه"
|
||||
},
|
||||
"home": {
|
||||
"hero": {
|
||||
"badge": "معماری سیستمهای مقیاسپذیر",
|
||||
"title1": "ما گرههای فنی شما را",
|
||||
"title2": "باز میکنیم",
|
||||
"subtitle": "ترکیبی از اقتدار مهندسی در زیرساخت و نوآوری مدرن در توسعه نرمافزار، از راهاندازی شبکههای پیچیده تا توسعه پلتفرمهای ابری سفارشی.",
|
||||
"btn_consulting": "دریافت مشاوره رایگان",
|
||||
"btn_portfolio": "مشاهده نمونهکارها"
|
||||
},
|
||||
"services": {
|
||||
"title": "راهکارهای یکپارچه",
|
||||
"subtitle": "خدمات ما پازلهای تکمیلکننده کسبوکار شما هستند.",
|
||||
"network": {
|
||||
"title": "زیرساخت و امنیت شبکه",
|
||||
"desc": "طراحی، پیادهسازی و ایمنسازی شبکههای پیچیده. از کانفیگ روترهای سختافزاری تا مانیتورینگ لایه هفت."
|
||||
},
|
||||
"software": {
|
||||
"title": "توسعه نرمافزار اختصاصی",
|
||||
"desc": "ساخت پلتفرمهای ابری قدرتمند و اتوماسیون فرآیندهای سازمانی."
|
||||
},
|
||||
"branding": {
|
||||
"title": "هویت بصری",
|
||||
"desc": "طراحی رابط کاربری (UI/UX) و برندینگ مدرن."
|
||||
},
|
||||
"academy": {
|
||||
"title": "آکادمی",
|
||||
"btn_enter": "مشاهده"
|
||||
}
|
||||
},
|
||||
"projects": {
|
||||
"title": "پروژههای منتخب",
|
||||
"subtitle": "گزیدهای از چالشهایی که با موفقیت پشت سر گذاشتیم.",
|
||||
"view_project": "مشاهده پروژه",
|
||||
"tabs": {
|
||||
"all": "همه",
|
||||
"software": "نرمافزار",
|
||||
"network": "شبکه"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
12
src/middleware.ts
Normal file
12
src/middleware.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
// src/middleware.ts
|
||||
import createMiddleware from "next-intl/middleware";
|
||||
|
||||
export default createMiddleware({
|
||||
locales: ["fa", "en", "ar"],
|
||||
defaultLocale: "fa",
|
||||
localePrefix: "always",
|
||||
});
|
||||
|
||||
export const config = {
|
||||
matcher: ["/", "/(fa|en|ar)/:path*", "/((?!_next|_vercel|.*\\..*).*)"],
|
||||
};
|
||||
2
src/utilities/constants/urls.constant.ts
Normal file
2
src/utilities/constants/urls.constant.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export const BACKEND_URL = process.env.NEXT_PUBLIC_BACKEND_URL;
|
||||
export const BACKEND_URL_LOCAL = process.env.NEXT_PUBLIC_BACKEND_URL_LOCAL;
|
||||
10
src/utilities/lib/scroll.ts
Normal file
10
src/utilities/lib/scroll.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
export const handleScrollToId = (id: string) => {
|
||||
const target = document.getElementById(id);
|
||||
|
||||
if (target) {
|
||||
target.scrollIntoView({
|
||||
behavior: "smooth",
|
||||
block: "center",
|
||||
});
|
||||
}
|
||||
};
|
||||
13
src/utilities/types/portfolio.type.ts
Normal file
13
src/utilities/types/portfolio.type.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
export interface Portfolio {
|
||||
id: string;
|
||||
category: PortfolioCategoryType;
|
||||
externalLink: string;
|
||||
featuredImage: string;
|
||||
gallery: string[];
|
||||
href: string;
|
||||
title: string;
|
||||
description: string;
|
||||
employer: string;
|
||||
}
|
||||
|
||||
export type PortfolioCategoryType = "network" | "software";
|
||||
Reference in New Issue
Block a user