diff --git a/.env b/.env deleted file mode 100644 index 73e3914..0000000 --- a/.env +++ /dev/null @@ -1,3 +0,0 @@ -SERVER_PREFIX=us8 -LIST_ID=f835096de2 -API_KEY=b8465dc10bd77a2f3ad24c2802fd5bbb-us8 \ No newline at end of file diff --git a/.env.vault b/.env.vault new file mode 100644 index 0000000..d65dfe2 --- /dev/null +++ b/.env.vault @@ -0,0 +1,25 @@ +#/-------------------.env.vault---------------------/ +#/ cloud-agnostic vaulting standard / +#/ [how it works](https://dotenv.org/env-vault) / +#/--------------------------------------------------/ + +# development +DOTENV_VAULT_DEVELOPMENT="M49oz3Z8F0q7Zsdi4BnOMs1rfOLhsgT5DW4yZ6thRof5vd5bf8edegHQyz77/odOlIv5D+Rwhq1bLhmrOXRnENpQUlqOfkt/sHzdACnoQjvTeO2m40PZS4DxNrzzuD8+94l3MPGAvLi0gX40eq7/eW2RJw8FJortgG6G8wIRXj3/THJ05ZC+hvZu3aROMFhagLT8KlmqOgDyoaRzEXpxb3P6Os5IgPF08EkmE4F0t9K/t/qbvvjhIzHck8DlLONlvx3QjIUDdQ==" +DOTENV_VAULT_DEVELOPMENT_VERSION=4 + +# ci +DOTENV_VAULT_CI="EYxK+yoakCKI0xgLaJfRoPuiHaClGwhNh6Vmur/+xdA3hckBeOnPGgE5l6CnvB2oQFnw2q3oTnInsgMPckXmPOBDiQOkYOQQgDPpV2QKHfg09kuo/2tvDATVgwISjBt67og9UtcOf6vAFP+S9BPSJmTZxQifEPeKqi8HLbBBkfM+mwLPU4PXDWnJ6LFwvPj4ft7LEhzc6vb7J9s2ynPsX0KjVD7ZZEm0IIoQRq2At1EAHju2kwqHNRjfP/eHYG4AhzK0pJGP779l6kPo" +DOTENV_VAULT_CI_VERSION=9 + +# staging +DOTENV_VAULT_STAGING="M+mX60q13lZA68jxmixDmextcqcS4GWVQrZfUgbkAbsFRdnf590SumvVEd/CvdLIdfF1FEMfDF/GXhg61QHOzsMX7oOrbX3eFL3uA5h8IQSD0EZyftA5M2mtIjwXmodslohyUjKDSiWA4aU1RVtjwps/Sx0=" +DOTENV_VAULT_STAGING_VERSION=3 + +# production +DOTENV_VAULT_PRODUCTION="Rxzz3jlI1Z9RaekljcubcMt8KsXrUdvMa5yey3O1ScFRsJHaWUjvoAv3DT6VsQy0WNlveeom91r70Pj1JVFyacCtEPa+3qD0QwpdRf27LqwjC5GZX/O1zX3H0wgaMPeHiEkVHDX5rELAT3i2/TqvIeSOwVU=" +DOTENV_VAULT_PRODUCTION_VERSION=3 + +#/----------------settings/metadata-----------------/ +DOTENV_VAULT="vlt_877c8269e6bac5a3a76def26cf15dee3b17f5fd18f9690f5cba86417599f4611" +DOTENV_API_URL="https://vault.dotenv.org" +DOTENV_CLI="npx dotenv-vault@latest" diff --git a/.github/workflows/actions.yml b/.github/workflows/actions.yml index 7207c1e..4dd5513 100644 --- a/.github/workflows/actions.yml +++ b/.github/workflows/actions.yml @@ -27,6 +27,8 @@ jobs: - name: Deploy 🚀 uses: JamesIves/github-pages-deploy-action@4.1.0 + env: + DOTENV_KEY: ${{ secrets.DOTENV_KEY }} with: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} BRANCH: gh-pages # The branch the action should deploy to. diff --git a/.gitignore b/.gitignore index 12a22b9..2717c5d 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,8 @@ yarn-error.log* # typescript *.tsbuildinfo + +.env* +.flaskenv* +!.env.project +!.env.vault \ No newline at end of file diff --git a/next.config.js b/next.config.js index 6eebe10..249ccd2 100644 --- a/next.config.js +++ b/next.config.js @@ -8,6 +8,32 @@ const nextConfig = { loader: 'akamai', path: '', }, + webpack(config, options) { + config.module.rules.push({ + test: /\.svg$/i, + issuer: /\.[jt]sx?$/, + use: [ + { + loader: '@svgr/webpack', + options: { + icon: true, + // svgoConfig: { + // plugins: [ + // { + // name: 'preset-default', + // params: { + // overrides: { removeViewBox: false }, + // }, + // }, + // ], + // }, + }, + }, + ], + }); + + return config; + }, }; module.exports = nextConfig; diff --git a/package-lock.json b/package-lock.json index a4d7214..d7380f4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,18 +8,22 @@ "name": "uddug", "version": "0.1.0", "dependencies": { - "@mailchimp/mailchimp_marketing": "^3.0.75", + "@sendgrid/mail": "^8.1.1", + "@splinetool/react-spline": "^2.2.6", + "@splinetool/runtime": "^1.0.54", "classnames": "^2.3.1", + "dotenv": "^16.4.5", "framer-motion": "6.2.4", + "lottie-react": "^2.4.0", "next": "12.1.0", "react": "17.0.2", "react-dom": "17.0.2", "react-scroll": "^1.8.7", - "react-use": "^17.3.2" + "react-use": "^17.3.2", + "swiper": "^11.0.6" }, "devDependencies": { "@svgr/webpack": "^6.2.1", - "@types/mailchimp__mailchimp_marketing": "^3.0.5", "@types/node": "17.0.22", "@types/react": "17.0.41", "@types/react-scroll": "^1.8.3", @@ -2210,18 +2214,6 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "node_modules/@mailchimp/mailchimp_marketing": { - "version": "3.0.78", - "resolved": "https://registry.npmjs.org/@mailchimp/mailchimp_marketing/-/mailchimp_marketing-3.0.78.tgz", - "integrity": "sha512-LAerA09fQ7opelydPolYez12mZ+TLQ+zDvHzweeAk9S+yI1bqBpuOvJVbe+3G0fsOqSbDTEUUBwUlncdAmShRA==", - "dependencies": { - "dotenv": "^8.2.0", - "superagent": "3.8.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/@next/env": { "version": "12.1.0", "resolved": "https://registry.npmjs.org/@next/env/-/env-12.1.0.tgz", @@ -2442,6 +2434,64 @@ "integrity": "sha512-LwzQKA4vzIct1zNZzBmRKI9QuNpLgTQMEjsQLf3BXuGYb3QPTP4Yjf6mkdX+X1mYttZ808QpOwAzZjv28kq7DA==", "dev": true }, + "node_modules/@sendgrid/client": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@sendgrid/client/-/client-8.1.1.tgz", + "integrity": "sha512-pg0gYhAdyQil3Aga7/xHVcZFpvDAjAQMNBgMy5njTSkjACoWHmpSi1nWBZM7nIH/ptcRNMpnBbm9B5EvQ8fX2w==", + "dependencies": { + "@sendgrid/helpers": "^8.0.0", + "axios": "^1.6.4" + }, + "engines": { + "node": ">=12.*" + } + }, + "node_modules/@sendgrid/helpers": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@sendgrid/helpers/-/helpers-8.0.0.tgz", + "integrity": "sha512-Ze7WuW2Xzy5GT5WRx+yEv89fsg/pgy3T1E3FS0QEx0/VvRmigMZ5qyVGhJz4SxomegDkzXv/i0aFPpHKN8qdAA==", + "dependencies": { + "deepmerge": "^4.2.2" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/@sendgrid/mail": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@sendgrid/mail/-/mail-8.1.1.tgz", + "integrity": "sha512-tNtmgWLtBA7ZxKtPuEGOaIdEZP1vZSXsj5zg9iuoDBPVj/fNz+7LWzndvTcKumHk5eaDrS0UPXJqBm61m3+H1A==", + "dependencies": { + "@sendgrid/client": "^8.1.1", + "@sendgrid/helpers": "^8.0.0" + }, + "engines": { + "node": ">=12.*" + } + }, + "node_modules/@splinetool/react-spline": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/@splinetool/react-spline/-/react-spline-2.2.6.tgz", + "integrity": "sha512-y9L2VEbnC6FNZZu8XMmWM9YTTTWal6kJVfP05Amf0QqDNzCSumKsJxZyGUODvuCmiAvy0PfIfEsiVKnSxvhsDw==", + "dependencies": { + "lodash.debounce": "^4.0.8", + "react-merge-refs": "^2.0.1" + }, + "peerDependencies": { + "@splinetool/runtime": "*", + "react": ">=17.0.0", + "react-dom": ">=17.0.0" + } + }, + "node_modules/@splinetool/runtime": { + "version": "1.0.54", + "resolved": "https://registry.npmjs.org/@splinetool/runtime/-/runtime-1.0.54.tgz", + "integrity": "sha512-Oc5R4oUoLiinYSSrbRTVnIM5iz7twgJAStUD4AObD2MLHZzjKnrcTaBMVb++magr/Y9vnLuVGhBGECNbeL/M2A==", + "dependencies": { + "on-change": "^4.0.0", + "semver-compare": "^1.0.0" + } + }, "node_modules/@svgr/babel-plugin-add-jsx-attribute": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.3.1.tgz", @@ -2717,12 +2767,6 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, - "node_modules/@types/mailchimp__mailchimp_marketing": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/mailchimp__mailchimp_marketing/-/mailchimp__mailchimp_marketing-3.0.5.tgz", - "integrity": "sha512-dayrFlKc/rIiMMH3MdQg8fZlu77PSjYzL56Cp+KczBtqjSWHxLt+rXOk2px86rKn7X8GIHnIIJdOGSiyy7Oy/w==", - "dev": true - }, "node_modules/@types/node": { "version": "17.0.22", "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.22.tgz", @@ -3082,6 +3126,29 @@ "node": ">=4" } }, + "node_modules/axios": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", + "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", + "dependencies": { + "follow-redirects": "^1.15.4", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axios/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/axobject-query": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", @@ -3202,6 +3269,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, "dependencies": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" @@ -3300,11 +3368,6 @@ "node": ">= 10" } }, - "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -3320,11 +3383,6 @@ "safe-buffer": "~5.1.1" } }, - "node_modules/cookiejar": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz", - "integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ==" - }, "node_modules/copy-to-clipboard": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.2.tgz", @@ -3367,11 +3425,6 @@ "url": "https://opencollective.com/core-js" } }, - "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==" - }, "node_modules/cosmiconfig": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", @@ -3574,7 +3627,6 @@ "version": "4.2.2", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -3692,11 +3744,14 @@ } }, "node_modules/dotenv": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", - "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", "engines": { - "node": ">=10" + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" } }, "node_modules/electron-to-chromium": { @@ -4352,11 +4407,6 @@ "node": ">=0.10.0" } }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -4464,26 +4514,23 @@ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", "dev": true }, - "node_modules/form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, + "node_modules/follow-redirects": { + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", + "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], "engines": { - "node": ">= 0.12" - } - }, - "node_modules/formidable": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", - "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==", - "deprecated": "Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau", - "funding": { - "url": "https://ko-fi.com/tunnckoCore/commissions" + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } } }, "node_modules/fraction.js": { @@ -4535,7 +4582,8 @@ "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true }, "node_modules/function.prototype.name": { "version": "1.1.5", @@ -4583,6 +4631,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", + "dev": true, "dependencies": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -4673,6 +4722,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, "dependencies": { "function-bind": "^1.1.1" }, @@ -4714,6 +4764,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -4793,7 +4844,8 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true }, "node_modules/inline-style-prefixer": { "version": "6.0.1", @@ -5017,11 +5069,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -5150,8 +5197,7 @@ "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" }, "node_modules/lodash.merge": { "version": "4.6.2", @@ -5175,6 +5221,23 @@ "loose-envify": "cli.js" } }, + "node_modules/lottie-react": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/lottie-react/-/lottie-react-2.4.0.tgz", + "integrity": "sha512-pDJGj+AQlnlyHvOHFK7vLdsDcvbuqvwPZdMlJ360wrzGFurXeKPr8SiRCjLf3LrNYKANQtSsh5dz9UYQHuqx4w==", + "dependencies": { + "lottie-web": "^5.10.2" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/lottie-web": { + "version": "5.12.2", + "resolved": "https://registry.npmjs.org/lottie-web/-/lottie-web-5.12.2.tgz", + "integrity": "sha512-uvhvYPC8kGPjXT3MyKMrL3JitEAmDMp30lVkuq/590Mw9ok6pWcFCwXJveo0t5uqYw1UREQHofD+jVpdjBv8wg==" + }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -5201,14 +5264,6 @@ "node": ">= 8" } }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", @@ -5222,17 +5277,6 @@ "node": ">=8.6" } }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -5273,7 +5317,8 @@ "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, "node_modules/nano-css": { "version": "5.3.5", @@ -5416,6 +5461,7 @@ "version": "1.12.2", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -5508,6 +5554,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/on-change": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/on-change/-/on-change-4.0.2.tgz", + "integrity": "sha512-cMtCyuJmTx/bg2HCpHo3ZLeF7FZnBOapLqZHr2AlLeJ5Ul0Zu2mUJJz051Fdwu/Et2YW04ZD+TtU+gVy0ACNCA==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/on-change?sponsor=1" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -6230,11 +6287,6 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "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==" - }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -6245,6 +6297,11 @@ "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==" + }, "node_modules/punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -6254,20 +6311,6 @@ "node": ">=6" } }, - "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -6318,6 +6361,15 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "node_modules/react-merge-refs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/react-merge-refs/-/react-merge-refs-2.1.1.tgz", + "integrity": "sha512-jLQXJ/URln51zskhgppGJ2ub7b2WFKGq3cl3NYKtlHoTG+dN2q7EzWrn3hN3EgPsTMvpR9tpq5ijdp7YwFZkag==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, "node_modules/react-scroll": { "version": "1.8.7", "resolved": "https://registry.npmjs.org/react-scroll/-/react-scroll-1.8.7.tgz", @@ -6365,20 +6417,6 @@ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "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/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -6574,7 +6612,8 @@ "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==" + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true }, "node_modules/scheduler": { "version": "0.20.2", @@ -6605,6 +6644,11 @@ "semver": "bin/semver.js" } }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==" + }, "node_modules/set-harmonic-interval": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/set-harmonic-interval/-/set-harmonic-interval-1.0.1.tgz", @@ -6638,6 +6682,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, "dependencies": { "call-bind": "^1.0.0", "get-intrinsic": "^1.0.2", @@ -6724,14 +6769,6 @@ "stacktrace-gps": "^3.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==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/string.prototype.matchall": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz", @@ -6845,35 +6882,6 @@ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.1.1.tgz", "integrity": "sha512-lVrM/bNdhVX2OgBFNa2YJ9Lxj7kPzylieHd3TNjuGE0Re9JB7joL5VUKOVH1kdNNJTgGPpT8hmwIAPLaSyEVFQ==" }, - "node_modules/superagent": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.1.tgz", - "integrity": "sha512-VMBFLYgFuRdfeNQSMLbxGSLfmXL/xc+OO+BZp41Za/NRDBet/BNbkRJrYzCUu0u4GU0i/ml2dtT8b9qgkw9z6Q==", - "deprecated": "Please upgrade to v7.0.2+ of superagent. We have fixed numerous issues with streams, form-data, attach(), filesystem errors not bubbling up (ENOENT on attach()), and all tests are now passing. See the releases tab for more information at .", - "dependencies": { - "component-emitter": "^1.2.0", - "cookiejar": "^2.1.0", - "debug": "^3.1.0", - "extend": "^3.0.0", - "form-data": "^2.3.1", - "formidable": "^1.1.1", - "methods": "^1.1.1", - "mime": "^1.4.1", - "qs": "^6.5.1", - "readable-stream": "^2.0.5" - }, - "engines": { - "node": ">= 4.0" - } - }, - "node_modules/superagent/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dependencies": { - "ms": "^2.1.1" - } - }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -6925,6 +6933,24 @@ "node": ">=10.13.0" } }, + "node_modules/swiper": { + "version": "11.0.6", + "resolved": "https://registry.npmjs.org/swiper/-/swiper-11.0.6.tgz", + "integrity": "sha512-W/Me7MQl5rNgdM5x9i3Gll76WsyVpnHn91GhBOyL7RCFUeg62aVnflzlVfIpXzZ/87FtJOfAoDH79ZH2Yq76zA==", + "funding": [ + { + "type": "patreon", + "url": "https://www.patreon.com/swiperjs" + }, + { + "type": "open_collective", + "url": "http://opencollective.com/swiper" + } + ], + "engines": { + "node": ">= 4.7.0" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -7161,7 +7187,8 @@ "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==" + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true }, "node_modules/v8-compile-cache": { "version": "2.3.0", @@ -8689,15 +8716,6 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "@mailchimp/mailchimp_marketing": { - "version": "3.0.78", - "resolved": "https://registry.npmjs.org/@mailchimp/mailchimp_marketing/-/mailchimp_marketing-3.0.78.tgz", - "integrity": "sha512-LAerA09fQ7opelydPolYez12mZ+TLQ+zDvHzweeAk9S+yI1bqBpuOvJVbe+3G0fsOqSbDTEUUBwUlncdAmShRA==", - "requires": { - "dotenv": "^8.2.0", - "superagent": "3.8.1" - } - }, "@next/env": { "version": "12.1.0", "resolved": "https://registry.npmjs.org/@next/env/-/env-12.1.0.tgz", @@ -8810,6 +8828,50 @@ "integrity": "sha512-LwzQKA4vzIct1zNZzBmRKI9QuNpLgTQMEjsQLf3BXuGYb3QPTP4Yjf6mkdX+X1mYttZ808QpOwAzZjv28kq7DA==", "dev": true }, + "@sendgrid/client": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@sendgrid/client/-/client-8.1.1.tgz", + "integrity": "sha512-pg0gYhAdyQil3Aga7/xHVcZFpvDAjAQMNBgMy5njTSkjACoWHmpSi1nWBZM7nIH/ptcRNMpnBbm9B5EvQ8fX2w==", + "requires": { + "@sendgrid/helpers": "^8.0.0", + "axios": "^1.6.4" + } + }, + "@sendgrid/helpers": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@sendgrid/helpers/-/helpers-8.0.0.tgz", + "integrity": "sha512-Ze7WuW2Xzy5GT5WRx+yEv89fsg/pgy3T1E3FS0QEx0/VvRmigMZ5qyVGhJz4SxomegDkzXv/i0aFPpHKN8qdAA==", + "requires": { + "deepmerge": "^4.2.2" + } + }, + "@sendgrid/mail": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@sendgrid/mail/-/mail-8.1.1.tgz", + "integrity": "sha512-tNtmgWLtBA7ZxKtPuEGOaIdEZP1vZSXsj5zg9iuoDBPVj/fNz+7LWzndvTcKumHk5eaDrS0UPXJqBm61m3+H1A==", + "requires": { + "@sendgrid/client": "^8.1.1", + "@sendgrid/helpers": "^8.0.0" + } + }, + "@splinetool/react-spline": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/@splinetool/react-spline/-/react-spline-2.2.6.tgz", + "integrity": "sha512-y9L2VEbnC6FNZZu8XMmWM9YTTTWal6kJVfP05Amf0QqDNzCSumKsJxZyGUODvuCmiAvy0PfIfEsiVKnSxvhsDw==", + "requires": { + "lodash.debounce": "^4.0.8", + "react-merge-refs": "^2.0.1" + } + }, + "@splinetool/runtime": { + "version": "1.0.54", + "resolved": "https://registry.npmjs.org/@splinetool/runtime/-/runtime-1.0.54.tgz", + "integrity": "sha512-Oc5R4oUoLiinYSSrbRTVnIM5iz7twgJAStUD4AObD2MLHZzjKnrcTaBMVb++magr/Y9vnLuVGhBGECNbeL/M2A==", + "requires": { + "on-change": "^4.0.0", + "semver-compare": "^1.0.0" + } + }, "@svgr/babel-plugin-add-jsx-attribute": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.3.1.tgz", @@ -8959,12 +9021,6 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, - "@types/mailchimp__mailchimp_marketing": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/mailchimp__mailchimp_marketing/-/mailchimp__mailchimp_marketing-3.0.5.tgz", - "integrity": "sha512-dayrFlKc/rIiMMH3MdQg8fZlu77PSjYzL56Cp+KczBtqjSWHxLt+rXOk2px86rKn7X8GIHnIIJdOGSiyy7Oy/w==", - "dev": true - }, "@types/node": { "version": "17.0.22", "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.22.tgz", @@ -9208,6 +9264,28 @@ "integrity": "sha512-32+ub6kkdhhWick/UjvEwRchgoetXqTK14INLqbGm5U2TzBkBNF3nQtLYm8ovxSkQWArjEQvftCKryjZaATu3w==", "dev": true }, + "axios": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", + "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", + "requires": { + "follow-redirects": "^1.15.4", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + }, + "dependencies": { + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } + } + }, "axobject-query": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", @@ -9300,6 +9378,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, "requires": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" @@ -9367,11 +9446,6 @@ "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", "dev": true }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" - }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -9387,11 +9461,6 @@ "safe-buffer": "~5.1.1" } }, - "cookiejar": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz", - "integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ==" - }, "copy-to-clipboard": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.2.tgz", @@ -9424,11 +9493,6 @@ "integrity": "sha512-IeHpLwk3uoci37yoI2Laty59+YqH9x5uR65/yiA0ARAJrTrN4YU0rmauLWfvqOuk77SlNJXj2rM6oT/dBD87+A==", "dev": true }, - "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==" - }, "cosmiconfig": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", @@ -9565,8 +9629,7 @@ "deepmerge": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==" }, "define-properties": { "version": "1.1.4", @@ -9647,9 +9710,9 @@ } }, "dotenv": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", - "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==" + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==" }, "electron-to-chromium": { "version": "1.4.239", @@ -10145,11 +10208,6 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -10244,20 +10302,10 @@ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", "dev": true }, - "form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "formidable": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", - "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==" + "follow-redirects": { + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", + "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==" }, "fraction.js": { "version": "4.2.0", @@ -10295,7 +10343,8 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true }, "function.prototype.name": { "version": "1.1.5", @@ -10331,6 +10380,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", + "dev": true, "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -10394,6 +10444,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -10422,7 +10473,8 @@ "has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true }, "has-tostringtag": { "version": "1.0.0", @@ -10478,7 +10530,8 @@ "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true }, "inline-style-prefixer": { "version": "6.0.1", @@ -10630,11 +10683,6 @@ "call-bind": "^1.0.2" } }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -10739,8 +10787,7 @@ "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" }, "lodash.merge": { "version": "4.6.2", @@ -10761,6 +10808,19 @@ "js-tokens": "^3.0.0 || ^4.0.0" } }, + "lottie-react": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/lottie-react/-/lottie-react-2.4.0.tgz", + "integrity": "sha512-pDJGj+AQlnlyHvOHFK7vLdsDcvbuqvwPZdMlJ360wrzGFurXeKPr8SiRCjLf3LrNYKANQtSsh5dz9UYQHuqx4w==", + "requires": { + "lottie-web": "^5.10.2" + } + }, + "lottie-web": { + "version": "5.12.2", + "resolved": "https://registry.npmjs.org/lottie-web/-/lottie-web-5.12.2.tgz", + "integrity": "sha512-uvhvYPC8kGPjXT3MyKMrL3JitEAmDMp30lVkuq/590Mw9ok6pWcFCwXJveo0t5uqYw1UREQHofD+jVpdjBv8wg==" + }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -10781,11 +10841,6 @@ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" - }, "micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", @@ -10796,11 +10851,6 @@ "picomatch": "^2.3.1" } }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" - }, "mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -10832,7 +10882,8 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, "nano-css": { "version": "5.3.5", @@ -10924,7 +10975,8 @@ "object-inspect": { "version": "1.12.2", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", - "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==" + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "dev": true }, "object-keys": { "version": "1.1.1", @@ -10987,6 +11039,11 @@ "es-abstract": "^1.19.1" } }, + "on-change": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/on-change/-/on-change-4.0.2.tgz", + "integrity": "sha512-cMtCyuJmTx/bg2HCpHo3ZLeF7FZnBOapLqZHr2AlLeJ5Ul0Zu2mUJJz051Fdwu/Et2YW04ZD+TtU+gVy0ACNCA==" + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -11418,11 +11475,6 @@ "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", "dev": true }, - "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==" - }, "prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -11433,20 +11485,17 @@ "react-is": "^16.13.1" } }, + "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==" + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true }, - "qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "requires": { - "side-channel": "^1.0.4" - } - }, "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -11477,6 +11526,11 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "react-merge-refs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/react-merge-refs/-/react-merge-refs-2.1.1.tgz", + "integrity": "sha512-jLQXJ/URln51zskhgppGJ2ub7b2WFKGq3cl3NYKtlHoTG+dN2q7EzWrn3hN3EgPsTMvpR9tpq5ijdp7YwFZkag==" + }, "react-scroll": { "version": "1.8.7", "resolved": "https://registry.npmjs.org/react-scroll/-/react-scroll-1.8.7.tgz", @@ -11513,20 +11567,6 @@ "tslib": "^2.1.0" } }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "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" - } - }, "regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -11667,7 +11707,8 @@ "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==" + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true }, "scheduler": { "version": "0.20.2", @@ -11689,6 +11730,11 @@ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, + "semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==" + }, "set-harmonic-interval": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/set-harmonic-interval/-/set-harmonic-interval-1.0.1.tgz", @@ -11713,6 +11759,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, "requires": { "call-bind": "^1.0.0", "get-intrinsic": "^1.0.2", @@ -11785,14 +11832,6 @@ "stacktrace-gps": "^3.0.4" } }, - "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==", - "requires": { - "safe-buffer": "~5.1.0" - } - }, "string.prototype.matchall": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz", @@ -11872,33 +11911,6 @@ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.1.1.tgz", "integrity": "sha512-lVrM/bNdhVX2OgBFNa2YJ9Lxj7kPzylieHd3TNjuGE0Re9JB7joL5VUKOVH1kdNNJTgGPpT8hmwIAPLaSyEVFQ==" }, - "superagent": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.1.tgz", - "integrity": "sha512-VMBFLYgFuRdfeNQSMLbxGSLfmXL/xc+OO+BZp41Za/NRDBet/BNbkRJrYzCUu0u4GU0i/ml2dtT8b9qgkw9z6Q==", - "requires": { - "component-emitter": "^1.2.0", - "cookiejar": "^2.1.0", - "debug": "^3.1.0", - "extend": "^3.0.0", - "form-data": "^2.3.1", - "formidable": "^1.1.1", - "methods": "^1.1.1", - "mime": "^1.4.1", - "qs": "^6.5.1", - "readable-stream": "^2.0.5" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "requires": { - "ms": "^2.1.1" - } - } - } - }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -11935,6 +11947,11 @@ "stable": "^0.1.8" } }, + "swiper": { + "version": "11.0.6", + "resolved": "https://registry.npmjs.org/swiper/-/swiper-11.0.6.tgz", + "integrity": "sha512-W/Me7MQl5rNgdM5x9i3Gll76WsyVpnHn91GhBOyL7RCFUeg62aVnflzlVfIpXzZ/87FtJOfAoDH79ZH2Yq76zA==" + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -12107,7 +12124,8 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true }, "v8-compile-cache": { "version": "2.3.0", diff --git a/package.json b/package.json index 7f103aa..4a1d665 100644 --- a/package.json +++ b/package.json @@ -3,25 +3,29 @@ "version": "0.1.0", "private": true, "scripts": { - "dev": "next dev", - "build": "next build", - "export": "next export", - "start": "next start", + "dev": "node -r dotenv/config node_modules/next/dist/bin/next", + "build": "node -r dotenv/config node_modules/next/dist/bin/next build", + "export": "node -r dotenv/config node_modules/next/dist/bin/next export", + "start": "node -r dotenv/config node_modules/next/dist/bin/next start", "lint": "next lint" }, "dependencies": { - "@mailchimp/mailchimp_marketing": "^3.0.75", + "@sendgrid/mail": "^8.1.1", + "@splinetool/react-spline": "^2.2.6", + "@splinetool/runtime": "^1.0.54", "classnames": "^2.3.1", + "dotenv": "^16.4.5", "framer-motion": "6.2.4", + "lottie-react": "^2.4.0", "next": "12.1.0", "react": "17.0.2", "react-dom": "17.0.2", "react-scroll": "^1.8.7", - "react-use": "^17.3.2" + "react-use": "^17.3.2", + "swiper": "^11.0.6" }, "devDependencies": { "@svgr/webpack": "^6.2.1", - "@types/mailchimp__mailchimp_marketing": "^3.0.5", "@types/node": "17.0.22", "@types/react": "17.0.41", "@types/react-scroll": "^1.8.3", diff --git a/public/icons/agente.svg b/public/icons/agente.svg new file mode 100644 index 0000000..10274a8 --- /dev/null +++ b/public/icons/agente.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/public/icons/arrow.svg b/public/icons/arrow.svg index cc38fa9..d08d896 100644 --- a/public/icons/arrow.svg +++ b/public/icons/arrow.svg @@ -1,3 +1,3 @@ - + diff --git a/public/icons/arsnl.svg b/public/icons/arsnl.svg new file mode 100644 index 0000000..825dfe4 --- /dev/null +++ b/public/icons/arsnl.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/clouds-badge.svg b/public/icons/clouds-badge.svg new file mode 100644 index 0000000..d56d839 --- /dev/null +++ b/public/icons/clouds-badge.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/consulting-badge.svg b/public/icons/consulting-badge.svg new file mode 100644 index 0000000..8ceb345 --- /dev/null +++ b/public/icons/consulting-badge.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/icons/cross.svg b/public/icons/cross.svg new file mode 100644 index 0000000..61f8808 --- /dev/null +++ b/public/icons/cross.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/defi-badge.svg b/public/icons/defi-badge.svg new file mode 100644 index 0000000..c75578b --- /dev/null +++ b/public/icons/defi-badge.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/discord.svg b/public/icons/discord.svg index 0ecec2c..8df4ac5 100644 --- a/public/icons/discord.svg +++ b/public/icons/discord.svg @@ -1,3 +1,3 @@ - + diff --git a/public/icons/facebook.svg b/public/icons/facebook.svg index 2c8f4c1..3231585 100644 --- a/public/icons/facebook.svg +++ b/public/icons/facebook.svg @@ -1,3 +1,3 @@ - - + + diff --git a/public/icons/ffconsulting.svg b/public/icons/ffconsulting.svg new file mode 100644 index 0000000..259e3fd --- /dev/null +++ b/public/icons/ffconsulting.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/final01.svg b/public/icons/final01.svg new file mode 100644 index 0000000..48e6322 --- /dev/null +++ b/public/icons/final01.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/icons/gateway.svg b/public/icons/gateway.svg new file mode 100644 index 0000000..27c6195 --- /dev/null +++ b/public/icons/gateway.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/github.svg b/public/icons/github.svg index 093dfe5..90d6bc2 100644 --- a/public/icons/github.svg +++ b/public/icons/github.svg @@ -1,3 +1,3 @@ - - + + diff --git a/public/icons/holygate.svg b/public/icons/holygate.svg new file mode 100644 index 0000000..7246f81 --- /dev/null +++ b/public/icons/holygate.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/public/icons/linkedIn.svg b/public/icons/linkedIn.svg index 316d0a1..ddf689b 100644 --- a/public/icons/linkedIn.svg +++ b/public/icons/linkedIn.svg @@ -1,4 +1,4 @@ - - - + + + diff --git a/public/icons/medium.svg b/public/icons/medium.svg new file mode 100644 index 0000000..b30ebda --- /dev/null +++ b/public/icons/medium.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/ml-ai-badge.svg b/public/icons/ml-ai-badge.svg new file mode 100644 index 0000000..2a6c812 --- /dev/null +++ b/public/icons/ml-ai-badge.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/nft-badge.svg b/public/icons/nft-badge.svg new file mode 100644 index 0000000..82432b7 --- /dev/null +++ b/public/icons/nft-badge.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/popup-success.svg b/public/icons/popup-success.svg new file mode 100644 index 0000000..8431150 --- /dev/null +++ b/public/icons/popup-success.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/icons/project-badge-web3.svg b/public/icons/project-badge-web3.svg new file mode 100644 index 0000000..25fac12 --- /dev/null +++ b/public/icons/project-badge-web3.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons/revitt.svg b/public/icons/revitt.svg new file mode 100644 index 0000000..d3154e8 --- /dev/null +++ b/public/icons/revitt.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/icons/snarkart.svg b/public/icons/snarkart.svg new file mode 100644 index 0000000..a496ded --- /dev/null +++ b/public/icons/snarkart.svg @@ -0,0 +1,11 @@ + + + + + + + + + + diff --git a/public/icons/tick.svg b/public/icons/tick.svg new file mode 100644 index 0000000..02589d8 --- /dev/null +++ b/public/icons/tick.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/public/icons/trinity.svg b/public/icons/trinity.svg new file mode 100644 index 0000000..c09f0f4 --- /dev/null +++ b/public/icons/trinity.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/twitter.svg b/public/icons/twitter.svg index 4356cfc..4fe412a 100644 --- a/public/icons/twitter.svg +++ b/public/icons/twitter.svg @@ -1,3 +1,3 @@ - - + + diff --git a/public/icons/web3-badge.svg b/public/icons/web3-badge.svg index 8edc988..1464069 100644 --- a/public/icons/web3-badge.svg +++ b/public/icons/web3-badge.svg @@ -1,49 +1,3 @@ - - web3 foundation grants - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + diff --git a/public/images/main-block-bg--desktop-compressed.png b/public/images/main-block-bg--desktop-compressed.png new file mode 100644 index 0000000..e447795 Binary files /dev/null and b/public/images/main-block-bg--desktop-compressed.png differ diff --git a/public/images/main-block-bg--desktop.png b/public/images/main-block-bg--desktop.png new file mode 100644 index 0000000..1df2492 Binary files /dev/null and b/public/images/main-block-bg--desktop.png differ diff --git a/public/images/main-block-bg--mobile-compressed.png b/public/images/main-block-bg--mobile-compressed.png new file mode 100644 index 0000000..b3be801 Binary files /dev/null and b/public/images/main-block-bg--mobile-compressed.png differ diff --git a/public/images/main-block-bg--mobile.png b/public/images/main-block-bg--mobile.png new file mode 100644 index 0000000..f4aa2fa Binary files /dev/null and b/public/images/main-block-bg--mobile.png differ diff --git a/public/team/andrew.png b/public/team/andrew.png index 7d9a192..6f8dd4b 100644 Binary files a/public/team/andrew.png and b/public/team/andrew.png differ diff --git a/public/team/mike.png b/public/team/mike.png index 0604e19..a697235 100644 Binary files a/public/team/mike.png and b/public/team/mike.png differ diff --git a/public/team/pavel.png b/public/team/pavel.png index ce851ec..8ec5f3a 100644 Binary files a/public/team/pavel.png and b/public/team/pavel.png differ diff --git a/public/team/solovov.png b/public/team/solovov.png index 7ddc201..c6bba64 100644 Binary files a/public/team/solovov.png and b/public/team/solovov.png differ diff --git a/src/components/general/Bullets/Bullets.module.css b/src/components/general/Bullets/Bullets.module.css new file mode 100644 index 0000000..3ffd877 --- /dev/null +++ b/src/components/general/Bullets/Bullets.module.css @@ -0,0 +1,121 @@ +.bullets { + position: relative; + background-color: var(--background); +} + +.inner { + padding: 33px 0 61px; + + @media (--tablet-vertical) { + padding: 73px 0 66px; + } + + @media (--desktop) { + padding: 14px 0 66px; + } +} + +.list { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 20px; + margin: 0; + padding: 0; + + @media (--desktop) { + grid-template-columns: repeat(auto-fill, minmax(14%, 1fr)); + } +} + +.item { + position: relative; + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 32px; + padding: 19px 22px; + background: var(--tranparent-grey); + border-radius: 16px; + transition: background 0.4s; + + &:active { + background: var(--card-hover-gradient); + } + + @media (hover: hover) { + &:hover, + &:focus { + background: var(--card-hover-gradient); + } + } + + @media (--tablet-vertical) { + flex-direction: row; + align-items: center; + padding: 32px 29px; + gap: 37px; + } + + @media (--desktop) { + padding: 34px 22px; + flex-direction: column; + align-items: flex-start; + gap: 63px; + } +} + +.title { + z-index: 1; + color: var(--white); + font-size: 15px; + line-height: 160%; + padding-left: 4px; + + @media (----tablet-vertical) { + padding-left: 0; + font-size: 18px; + } + + @media (----tablet-vertical) { + padding-left: 6px; + } +} + +.ico { + z-index: 1; + display: flex; + justify-content: center; + align-items: center; + width: 38px; + height: 38px; + background-size: contain; + background-position: center; + background-repeat: no-repeat; + + @media (--tablet-vertical) { + width: 46px; + height: 46px; + } +} + +.backgroundCircle { + top: 185px; + left: auto; + right: -420px; + transform: translate3d(0, 0, 0) rotate(-30deg); + + @media (--desktop) { + top: 45px; + right: -260px; + } +} + +.backgroundCircleSecond { + top: 0; + left: 0; + transform: translate3d(0, 0, 0) rotate(-30deg); + + @media (--tablet-vertical) { + display: none; + } +} diff --git a/src/components/general/Bullets/Bullets.tsx b/src/components/general/Bullets/Bullets.tsx new file mode 100644 index 0000000..7cc84b4 --- /dev/null +++ b/src/components/general/Bullets/Bullets.tsx @@ -0,0 +1,40 @@ +import React, { FC } from 'react'; + +import Wrapper from 'components/layout/Wrapper'; +import BackgroundCircle from 'components/ui/BackgroundCircle'; + +import styles from './Bullets.module.css'; + +interface IBulletProps { + bullets: { title: string; ico: string }[]; +} + +const Bullets: FC = ({ bullets }) => { + return ( +
+ +
+ +
+ + + + + ); +}; + +export default React.memo(Bullets); diff --git a/src/components/general/Bullets/index.ts b/src/components/general/Bullets/index.ts new file mode 100644 index 0000000..6fac23c --- /dev/null +++ b/src/components/general/Bullets/index.ts @@ -0,0 +1,3 @@ +import Bullets from './Bullets'; + +export default Bullets; diff --git a/src/components/general/Careers/Careers.module.css b/src/components/general/Careers/Careers.module.css index 8ab44d4..af43b07 100644 --- a/src/components/general/Careers/Careers.module.css +++ b/src/components/general/Careers/Careers.module.css @@ -1,79 +1,62 @@ .root { + background-color: var(--background); +} + +.inner { position: relative; - overflow-x: hidden; display: flex; flex-direction: column; align-items: center; - padding: 80px 20px; - background-color: var(--light); - @media (--tablet-vertical) { - padding: 100px 32px; - } - - @media (--tablet-landscape) { - padding: 100px 60px; - } + padding: 61px 0 71px; - @media (--tablet-landscape) { - padding: 100px 120px; + @media (--tablet-vertical) { + padding: 66px 0 80px; } } .header { z-index: 1; - font-weight: 700; - font-size: 24px; - line-height: 133%; text-align: center; - color: var(--dark); + margin: 0 auto 36px; + max-width: 360px; @media (--tablet-vertical) { - font-size: 32px; - line-height: 125%; + margin: 0 auto 48px; + max-width: 524px; } @media (--tablet-landscape) { - font-size: 42px; - line-height: 133%; + max-width: 1000px; } } -.description { - margin-top: 16px; - font-style: normal; - font-weight: 400; - font-size: 16px; - line-height: 138%; - text-align: center; - color: var(--dark); - opacity: .6; - max-width: 320px; +.title { + margin-bottom: 16px; @media (--tablet-vertical) { - font-size: 18px; - line-height: 156%; - margin-top: 16px; - max-width: 656px; + margin-bottom: 24px; } +} +.description { @media (--tablet-landscape) { - margin-top: 24px; + margin: 0 auto; max-width: 710px; } } .vacationsList { position: relative; - margin-top: 32px; display: flex; flex-direction: column; - row-gap: 12px; + row-gap: 24px; width: 100%; align-items: center; + margin-bottom: 34px; @media (--tablet-vertical) { - row-gap: 16px; + margin-bottom: 40px; } } @@ -81,13 +64,12 @@ z-index: 1; max-width: 1200px; width: 100%; - background: white; - border: 1px solid var(--grey); + background: transparent; + border: 1px solid var(--card-border); border-radius: 16px; display: grid; - grid-row-gap: 8px; - padding: 20px 20px 24px; - transition: .3s; + grid-row-gap: 20px; + padding: 42px 30px; cursor: pointer; grid-template-areas: 'n a' @@ -95,29 +77,35 @@ 'p p' 't t' 'ts ts'; + transition: all 0.2s; - & .arrow path { - transition: .3s; + &:active { + background: var(--card-hover-gradient); + + .arrow { + opacity: 1; + } } + @media (hover: hover) { + &:hover, + &:focus { + background: var(--card-hover-gradient); - @media (--desktop) { - &:hover { - border-color: var(--purple); - - & .arrow path { - fill: var(--purple); + .arrow { + opacity: 1; } } } @media (--tablet-vertical) { - grid-row-gap: 0; + grid-row-gap: 20px; grid-template-columns: repeat(3, 1fr); grid-template-areas: 'n n a' 's p t' 'ts ts ts'; + padding: 32px 40px; } @media (--tablet-landscape) { @@ -125,13 +113,27 @@ grid-template-areas: 'n n n a' 's p t ts'; + padding: 24px 40px; } @media (--desktop) { grid-template-columns: 5fr repeat(3, 4fr) 9fr; - grid-template-areas: - 'n s p t ts a'; - align-items: center; + grid-template-areas: 'n s p t ts a'; + align-items: start; + } +} + +.arrow { + width: 24px; + height: 24px; + grid-area: a; + justify-self: end; + color: var(--white); + opacity: 0.2; + transition: all 0.2s; + + @media (--desktop) { + align-self: center; } } @@ -139,19 +141,17 @@ font-weight: 700; font-size: 18px; line-height: 133%; - color: var(--dark); + color: var(--white); grid-area: n; + margin-bottom: 20px; @media (--tablet-vertical) { font-size: 20px; } -} -.arrow { - width: 24px; - height: 24px; - grid-area: a; - justify-self: end; + @media (--desktop) { + margin: 0; + } } .attributeValue { @@ -159,16 +159,15 @@ font-weight: 500; font-size: 12px; line-height: 133%; - color: var(--dark); - opacity: .4; + color: var(--light-grey); + margin-bottom: 4px; } & .value { font-weight: 500; font-size: 16px; line-height: 138%; - color: var(--dark); - margin-top: 4px; + color: var(--white); } } @@ -189,19 +188,32 @@ } .contactsText { - margin-top: 24px; - font-weight: 700; - font-size: 20px; - line-height: 140%; + font-weight: 500; + font-size: 16px; + line-height: 160%; text-align: center; - color: var(--dark); + color: var(--white); @media (--tablet-vertical) { - margin-top: 40px; - font-size: 24px; + font-size: 16px; + line-height: 200%; } } .links { cursor: pointer; -} \ No newline at end of file +} + +.backgroundCircle { + top: 40px; + left: -190px; + transform: translate3d(0, 0, 0) rotate(-16deg); + + @media (--tablet-vertical) { + top: 200px; + } + + @media (--desktop) { + top: 80px; + } +} diff --git a/src/components/general/Careers/Careers.tsx b/src/components/general/Careers/Careers.tsx index fcd143d..a0ac4b5 100644 --- a/src/components/general/Careers/Careers.tsx +++ b/src/components/general/Careers/Careers.tsx @@ -1,9 +1,11 @@ import { motion } from 'framer-motion'; -import React from 'react'; +import React, { FC } from 'react'; import classNames from 'classnames'; -import { useScrollState } from 'contexts/scrollStateContext'; -import { useScreenSize } from 'hooks/useScreenSize'; +import Wrapper from 'components/layout/Wrapper'; +import Title, { TitleSizes } from 'components/ui/Title'; +import Subtitle from 'components/ui/Subtitle'; +import BackgroundCircle from 'components/ui/BackgroundCircle'; import Icon from 'components/general/Icon'; import styles from './Careers.module.css'; @@ -89,67 +91,60 @@ const VacationCard: React.VFC = props => { ); }; -const Careers = () => { - const { - refs: { careers }, - } = useScrollState(); - - const screenSize = useScreenSize(); - const isWide = screenSize === 'desktop' || screenSize === 'tablet-landscape'; - +const Careers: FC = () => { return ( -
- - - We are hiring professionals for our{' '} - team - - - "Uddug" has enjoyed steady, solid growth in its years of - business, and talented, productive people made it possible. Please check - the open positions - - - {vacations.map(vacation => ( - - ))} -
- +
+ +
+ + + <span className='accentSecondaryText'>We are hiring</span>{' '} + professionals for our team + + + "Uddúg" has enjoyed steady, solid growth in its years of + business, and talented, productive people made it possible. Please + check the open positions + + + + {vacations.map(vacation => ( + + ))} + + + Send your CV to{' '} + + hr@uddug.com + {' '} + or{' '} + + LinkedIn + + +
- - - Send your CV to{' '} - - hr@uddug.com - {' '} - or{' '} - - LinkedIn - - +
); }; diff --git a/src/components/general/ContactForm/ContactForm.module.css b/src/components/general/ContactForm/ContactForm.module.css new file mode 100644 index 0000000..1ac72bb --- /dev/null +++ b/src/components/general/ContactForm/ContactForm.module.css @@ -0,0 +1,162 @@ +.form { + width: 100%; + display: flex; + flex-direction: column; + gap: 14px; +} + +.fields { + display: flex; + flex-direction: column; + gap: 14px; +} + +.fieldWrapper { + position: relative; + + width: 100%; +} + +.charactersLimit { + position: absolute; + top: 6px; + right: 30px; + font-weight: 300; + font-size: 12px; + line-height: 160%; + color: var(--light-grey); + transition: all 0.2s; +} + +.field { + width: 100%; + padding: 18px 31px; + background: transparent; + border: 1px solid rgba(255, 255, 255, 0.1); + border-radius: 100px; + outline: none; + font-weight: 400; + font-size: 16px; + line-height: 160%; + color: var(--white); + transition: all 0.2s; + &:hover, + &:focus { + border-color: var(--white); + } + + &:hover ~ .charactersLimit, + &:focus ~ .charactersLimit { + color: var(--white); + } +} + +.button { + transition: 0.5s; +} + +.errorField { + & .field { + border-color: var(--error) !important; + } + + &:after { + position: absolute; + top: 6px; + right: 30px; + font-weight: 500; + font-size: 12px; + line-height: 133%; + color: var(--error); + } + + &.invalidField:after { + content: 'Invalid'; + } + + &.requiredField:after { + content: 'Required'; + } +} + +.hide { + display: none !important; +} + +.submitButton { + position: relative; + z-index: 1; +} + +.popup { + z-index: 3; + position: fixed; + display: none; + top: 0; + bottom: 0; + left: 0; + right: 0; + justify-content: center; + align-items: center; + backdrop-filter: blur(20px); + transition: all 0.3s; +} + +.popupOpened { + display: flex; +} + +.popupInner { + padding: 26px 20px 37px; + background-color: var(--white); + border-radius: 20px; + max-width: 355px; + text-align: center; + + @media (--tablet-vertical) { + max-width: 410px; + } +} + +.image { + display: flex; + justify-content: center; + align-items: center; + width: 238px; + height: 218px; + margin: 0 auto 12px; + + @media (--tablet-vertical) { + width: 257px; + height: 237px; + } +} + +.icon { + width: 96px; + height: 96px; + margin: 0 auto 12px; + + @media (--tablet-vertical) { + width: 124px; + height: 124px; + } +} + +.popupTitle { + font-size: 22px; + line-height: 140%; + margin: 0 0 10px; + color: var(--background); + + @media (--tablet-vertical) { + font-size: 30px; + } +} + +.popupText { + font-size: 14px; + line-height: 160%; + color: var(--light-grey); + margin: 0 0 24px; +} diff --git a/src/components/general/ContactForm/ContactForm.tsx b/src/components/general/ContactForm/ContactForm.tsx index 0b4eedf..2fcf3fd 100644 --- a/src/components/general/ContactForm/ContactForm.tsx +++ b/src/components/general/ContactForm/ContactForm.tsx @@ -1,36 +1,133 @@ import React, { useEffect, useRef, useState } from 'react'; +import { motion } from 'framer-motion'; import classNames from 'classnames'; -import Icon from 'components/general/Icon'; -import styles from 'components/general/Footer/Footer.module.css'; +import PopupSuccessSVG from 'public/icons/popup-success.svg'; +import Button from 'components/ui/Button'; + +import styles from './ContactForm.module.css'; interface ContactFormProps { className?: string; onFormSend?: () => void; } +interface IPopupProps { + isOpened: boolean; + closePopup: () => void; +} + +const Popup: React.VFC = ({ isOpened, closePopup }) => { + return ( + +
+
+ +
+

Thanks for submitting!

+

+ We will contact you +
+ within 10 minutes +

+ +
+
+ ); +}; + const ContactForm: React.VFC = ({ onFormSend, className, }) => { - const submitRef = useRef(null); - - const [email, setEmail] = useState(''); const [name, setName] = useState(''); + const [email, setEmail] = useState(''); const [text, setText] = useState(''); const [emailError, setEmailError] = useState( null ); - const [nameError, setNameError] = useState(null); + const [nameError, setNameError] = useState( + null + ); const [isFormSent, setIsFormSent] = useState(false); + const [isShowPopup, setIsShowPopup] = useState(false); + + const validateName = (value: string) => { + if (value.length === 0) { + setNameError('required'); + return false; + } + + if (value.length < 2) { + setNameError('invalid'); + return false; + } + + return true; + }; + + const validateEmail = (value: string) => { + if (value.length === 0) { + setEmailError('required'); + return false; + } + + if (value.length < 6) { + setEmailError('invalid'); + return false; + } + + if (!value.includes('.') && !value.includes('@')) { + setEmailError('invalid'); + return false; + } + + return true; + }; + + const handleSendForm = async () => { + const result = await fetch('/api/sendgrid', { + body: JSON.stringify({ + name: name, + email: email, + text: text, + }), + headers: { + 'Content-Type': 'application/json', + }, + method: 'POST', + }); + + const { error } = await result.json(); + + if (error) { + console.log(error); + return; + } + if (result.ok && result.status >= 200 && result.status < 300) { + setIsShowPopup(true); + document.body.style.overflow = 'hidden'; + } + }; const submitHandler = async () => { setEmailError(null); setNameError(null); if (isFormSent) return; - if (email.length === 0) return setEmailError('required'); - if (name.length === 0) return setNameError('required'); - submitRef.current?.click(); + + const isNameValid = validateName(name); + const isEmailValid = validateEmail(email); + + if (!isNameValid || !isEmailValid) { + return; + } + handleSendForm(); setIsFormSent(true); setTimeout(() => { @@ -38,15 +135,6 @@ const ContactForm: React.VFC = ({ }, 3000); }; - const handleSendForm = () => { - setEmail(''); - setName(''); - setText(''); - setEmailError(null); - setNameError(null); - if (onFormSend) onFormSend(); - }; - useEffect(() => { if (onFormSend) { window.addEventListener('blur', handleSendForm); @@ -55,69 +143,44 @@ const ContactForm: React.VFC = ({ }, []); return ( -
-
-
-

Subscribe

-
Write to us
-
- * indicates required +
+ +
+
+ setName(e.currentTarget.value)} + required + placeholder='Name' + />
- setEmail(e.currentTarget.value)} - name='EMAIL' - className={classNames('required email', styles.field)} - id='mce-EMAIL' required placeholder='E-mail' /> -
-
- - setName(e.currentTarget.value)} - name='FNAME' - className={classNames(styles.field)} - id='mce-FNAME' - placeholder='Name' - /> - -
-
- +
= ({ if (e.currentTarget.value.length > 100) return; setText(e.currentTarget.value); }} - name='MMERGE6' className={styles.field} - id='mce-MMERGE6' placeholder='Your message here' /> {text.length} / 100 - -
-
-
-
-
-
-
-
-
- +
+ -

- - - -

+ Send message +
-
+ { + setIsShowPopup(false); + document.body.style.overflow = 'auto'; + }} + /> +
); }; diff --git a/src/components/general/ContactUs/ContactUs.module.css b/src/components/general/ContactUs/ContactUs.module.css new file mode 100644 index 0000000..854d9df --- /dev/null +++ b/src/components/general/ContactUs/ContactUs.module.css @@ -0,0 +1,72 @@ +.root { + background-color: var(--background); +} + +.inner { + padding: 61px 0 61px; + position: relative; + + @media (--tablet-vertical) { + padding: 66px 0 66px; + } +} + +.card { + display: grid; + gap: 36px; + + background-color: var(--tranparent-grey); + border-radius: 16px; + padding: 54px 20px; + + @media (--tablet-vertical) { + border-radius: 20px; + padding: 74px 60px 66px; + gap: 56px; + } + + @media (--tablet-landscape) { + padding: 74px 60px 66px; + grid-template-columns: repeat(2, 1fr); + align-items: center; + gap: 30px; + } + + @media (--desktop) { + padding: 74px 146px 66px 120px; + } +} + +.header { + text-align: center; + + @media (--tablet-landscape) { + text-align: start; + max-width: 300px; + } +} + +.title { + margin-bottom: 16px; + + @media (--tablet-vertical) { + margin-bottom: 24px; + } +} + +.backgroundCircleFirst { + top: -400px; + left: auto; + right: -337px; + transform: translate3d(0, 0, 0) rotate(-30deg); +} + +.backgroundCircleSecond { + top: auto; + bottom: -350px; + left: -188px; + + @media (--desktop) { + left: -350px; + } +} diff --git a/src/components/general/ContactUs/ContactUs.tsx b/src/components/general/ContactUs/ContactUs.tsx new file mode 100644 index 0000000..e7cea85 --- /dev/null +++ b/src/components/general/ContactUs/ContactUs.tsx @@ -0,0 +1,48 @@ +import React, { FC } from 'react'; +import { motion } from 'framer-motion'; + +import Wrapper from 'components/layout/Wrapper'; +import Title, { TitleSizes } from 'components/ui/Title'; +import Subtitle from 'components/ui/Subtitle'; +import ContactForm from 'components/general/ContactForm'; +import BackgroundCircle from 'components/ui/BackgroundCircle'; + +import styles from './ContactUs.module.css'; + +const ContactUs: FC = () => { + return ( +
+ +
+
+ + + Let’s discuss your project + + + Contact us - we will be glad +
+ to dive into your project +
+
+ + + +
+ + +
+
+
+ ); +}; + +export default React.memo(ContactUs); diff --git a/src/components/general/ContactUs/index.ts b/src/components/general/ContactUs/index.ts new file mode 100644 index 0000000..b46e5e1 --- /dev/null +++ b/src/components/general/ContactUs/index.ts @@ -0,0 +1,3 @@ +import ContactUs from './ContactUs'; + +export default ContactUs; diff --git a/src/components/general/Footer/Footer.module.css b/src/components/general/Footer/Footer.module.css index 09848b9..86c7cb5 100644 --- a/src/components/general/Footer/Footer.module.css +++ b/src/components/general/Footer/Footer.module.css @@ -51,9 +51,9 @@ font-weight: 400; font-size: 16px; line-height: 138%; - opacity: .6; + opacity: 0.6; max-width: 275px; - + @media (--tablet-vertical) { font-size: 18px; max-width: 656px; @@ -88,7 +88,7 @@ height: 28px; & path { - transition: .3s; + transition: 0.3s; } &:hover path { @@ -124,8 +124,8 @@ .infoLink { cursor: pointer; - opacity: .6; - transition: .3s; + opacity: 0.6; + transition: 0.3s; &:hover { opacity: 1; } @@ -139,12 +139,6 @@ gap: 24px; } -.formHeader { - font-weight: 700; - font-size: 32px; - line-height: 125%; -} - .fields { display: flex; flex-direction: column; @@ -190,7 +184,7 @@ } .button { - transition: .5s; + transition: 0.5s; } .errorField { @@ -235,7 +229,7 @@ color: white; cursor: pointer; - transition: .3s; + transition: 0.3s; &:hover { background-color: var(--purple-hover); @@ -274,4 +268,4 @@ .hide { display: none !important; -} \ No newline at end of file +} diff --git a/src/components/general/Footer/Footer.tsx b/src/components/general/Footer/Footer.tsx index b2d57d4..403a378 100644 --- a/src/components/general/Footer/Footer.tsx +++ b/src/components/general/Footer/Footer.tsx @@ -1,28 +1,23 @@ import { motion } from 'framer-motion'; -import React from 'react'; +import React, { FC } from 'react'; import classNames from 'classnames'; -import { Element } from 'react-scroll'; -import { useScrollState } from 'contexts/scrollStateContext'; import Icon from 'components/general/Icon'; import ContactForm from 'components/general/ContactForm'; import styles from './Footer.module.css'; -const Footer = () => { - const { - refs: { contactUs }, - } = useScrollState(); - +const Footer: FC = () => { return ( - +
-
+
+ className={styles.contactInfo} + initial={{ opacity: 0 }} + whileInView={{ opacity: 1 }} + >
Contact us
Write about your idea concept or ask a question via the feedback @@ -58,9 +53,10 @@ const Footer = () => {
+ className={styles.footerInfo} + initial={{ opacity: 0 }} + whileInView={{ opacity: 1 }} + > -
Uddug © 2013
+
Uddúg © 2013
@@ -79,7 +75,7 @@ const Footer = () => {
- +
); }; diff --git a/src/components/general/Icon/Icon.tsx b/src/components/general/Icon/Icon.tsx index ba48632..87f7204 100644 --- a/src/components/general/Icon/Icon.tsx +++ b/src/components/general/Icon/Icon.tsx @@ -1,32 +1,40 @@ -import React, { cloneElement, SVGProps, useEffect, useState } from 'react'; -import { useAsync } from 'react-use'; +import React, { useEffect, useState } from 'react'; -export interface IconProps extends SVGProps { +export interface IconProps extends React.SVGProps { name: 'logotype' | string; } -const Icon: React.VFC = props => { - const { name, ...restProps } = props; +const Icon: React.VFC = ({ name, ...restProps }) => { + const [iconComponent, setIconComponent] = useState + > | null>(null); - const [iconModule, setIconModule] = useState(() => ); - - useAsync(async () => { - const module = await import(`@svgr/webpack!public/icons/${name}.svg`).catch( - () => console.error(`Icon with name: ${name} not found!`) - ); + useEffect(() => { + const importIcon = async () => { + try { + const { default: IconComponent } = await import( + `@svgr/webpack!public/icons/${name}.svg` + ); + setIconComponent(() => IconComponent); + } catch (error) { + console.error(`Icon with name: ${name} not found!`, error); + } + }; - if (module) { - setIconModule(module.ReactComponent({})); - } - }, [name]); + importIcon(); - useEffect(() => { return () => { - setIconModule(<>); + setIconComponent(null); }; - }, []); + }, [name]); + + if (!iconComponent) { + return null; + } + + const IconComponent = iconComponent; - return cloneElement(iconModule, { ...restProps }); + return ; }; export default Icon; diff --git a/src/components/general/Internship/Internship.tsx b/src/components/general/Internship/Internship.tsx index 82b5634..a301547 100644 --- a/src/components/general/Internship/Internship.tsx +++ b/src/components/general/Internship/Internship.tsx @@ -1,34 +1,19 @@ import { motion } from 'framer-motion'; -import React from 'react'; -import * as Scroll from 'react-scroll'; +import React, { FC } from 'react'; -import { useScrollState } from 'contexts/scrollStateContext'; import Icon from 'components/general/Icon'; import styles from './Internship.module.css'; -const { scroller } = Scroll; - -const Internship = () => { - const { - refs: { internship }, - } = useScrollState(); - - const smoothScrollToTheContactUs = () => { - scroller.scrollTo('contactUs', { - duration: 1000, - containerId: 'home-page', - smooth: true, - }); - }; - +const Internship: FC = () => { return ( -
+ className={styles.wrapper} + id='internship' + initial={{ opacity: 0 }} + whileInView={{ opacity: 1 }} + > +
Internship with us
@@ -36,12 +21,7 @@ const Internship = () => { invite talented interns who want to gain experience in the commercial development of our own high-tech open source projects
-
- Contact us -
+
Contact us
diff --git a/src/components/general/MainBlock/MainBlock.module.css b/src/components/general/MainBlock/MainBlock.module.css index 7856c90..67f3939 100644 --- a/src/components/general/MainBlock/MainBlock.module.css +++ b/src/components/general/MainBlock/MainBlock.module.css @@ -1,190 +1,124 @@ .root { - background: var(--vertical-linear-gradient); - padding: 0 20px 58px; - height: calc(100vh - 58px); - color: var(--light); display: flex; flex-direction: column; - align-items: center; - justify-content: center; - text-align: center; + justify-content: flex-end; + background-color: var(--background); + background-image: url('/images/main-block-bg--mobile-compressed.png'); + background-repeat: no-repeat; + background-position: center; + background-size: cover; + height: 100vh; position: relative; - overflow-x: hidden; - - @media (--tablet-vertical) { - padding: 0 32px 72px; - height: calc(100vh - 72px); - } - @media (--tablet-landscape) { - padding: 0 60px 72px; + &::after { + content: ''; + position: absolute; + bottom: 0; + left: 0; + right: 0; + height: 192px; + background: linear-gradient( + to bottom, + rgba(1, 3, 5, 0) 0%, + rgba(1, 3, 5, 0.91) 60%, + rgba(1, 3, 5, 1) 100% + ); } - @media (--desktop) { - padding: 0 233px 72px; - } -} - -.mainLabel { - font-weight: 700; - font-size: 32px; - line-height: 125%; - letter-spacing: 0.02em; - max-width: 320px; - @media (--tablet-vertical) { - font-size: 42px; - max-width: 656px; + &::after { + height: 421px; + } } @media (--tablet-landscape) { - font-size: 64px; - max-width: 904px; + &::after { + height: 192px; + } } @media (--desktop) { - max-width: 960px; + background-image: url('/images/main-block-bg--desktop-compressed.png'); } } -.descriptionText { - margin-top: 16px; - font-weight: 400; - font-size: 16px; - line-height: 138%; - max-width: 320px; - - @media (--tablet-vertical) { - margin-top: 20px; - font-size: 18px; - max-width: 487px; - } - - @media (--tablet-landscape) { - margin-top: 32px; - font-size: 20px; - max-width: 750px; - } +.spline { + position: absolute; + z-index: 0; + top: 0; + bottom: 0; + left: 0; + right: 0; } -.directionsList { - margin-top: 33px; - display: grid; - grid-gap: 22px; - font-size: 14px; - grid-template-areas: - 't f' - 'b s' - 'c c' - 'm m'; +.spline canvas { + /* width: 50% !important; + height: 50% !important; + transform: scale(300%); */ - @media (--tablet-vertical) { - margin-top: 48px; - font-size: 16px; - grid-template-areas: - 't b f' - 'm c s'; - grid-row-gap: 30px; - grid-column-gap: 50px; - } - - @media (--tablet-landscape) { - margin-top: 56px; - font-size: 18px; - grid-template-areas: - 't b m' - 'c f s'; - } + /* @media (--desktop) { + width: 100% !important; + height: 100% !important; + transform: none; + } */ } -.icon { - width: 24px; - height: 24px; - margin-right: 8px; - - @media (--tablet-vertical) { - width: 32px; - height: 32px; - } -} - -.gridElement { +.inner { + pointer-events: none; + z-index: 1; + position: relative; display: flex; + flex-direction: column; align-items: center; justify-content: center; -} + align-items: flex-start; + padding-bottom: 130px; -.technicalConsulting { - grid-area: t; - - @media (--tablet-landscape) { - margin-right: 34px; + @media (--tablet-vertical) { + padding-bottom: 100px; } -} -.finTech { - grid-area: f; -} - -.blockchain { - grid-area: b; - - @media (--tablet-landscape) { - margin-right: 20px; + @media (--desktop) { + padding-bottom: 157px; } } -.startups { - grid-area: s; +.title { + white-space: pre-wrap; + margin-bottom: 16px; - @media (--tablet-landscape) { - justify-content: start; + @media (--tablet-vertical) { + margin-bottom: 28px; } } -.cloud { - grid-area: c; +.subtitle { + margin-bottom: 36px; + max-width: 529px; - @media (--tablet-landscape) { - justify-content: end; + @media (--tablet-vertical) { + margin-bottom: 54px; } } -.machine { - grid-area: m; +.button { + pointer-events: auto; + text-align: start; + border-radius: 100px; + max-width: 295px; - @media (--tablet-landscape) { - margin-left: 34px; + @media (--tablet-vertical) { + max-width: max-content; } } -.partners { - position: absolute; - bottom: 0; - width: 1440px; -} - -.arrowScroll { - position: absolute; - width: 46px; - height: 20px; - bottom: 18px; - left: calc(50% - 23px); - cursor: pointer; - - & path { - transition: .3s; - } +.backgroundCircle { + display: none; @media (--desktop) { - &:hover path { - fill: var(--orange); - } + display: block; + transform: translate3d(0, 0, 0) rotate(-30deg); + top: 50px; + left: -160px; } } - -.grid { - bottom: 0; - position: absolute; - opacity: .3; -} \ No newline at end of file diff --git a/src/components/general/MainBlock/MainBlock.tsx b/src/components/general/MainBlock/MainBlock.tsx index 21600cd..f150b16 100644 --- a/src/components/general/MainBlock/MainBlock.tsx +++ b/src/components/general/MainBlock/MainBlock.tsx @@ -1,143 +1,124 @@ -import { motion } from 'framer-motion'; -import React, { useEffect, useRef } from 'react'; -import classNames from 'classnames'; -import * as Scroll from 'react-scroll'; - -const { scroller } = Scroll; +import React, { useEffect, useState, useRef } from 'react'; +import Spline from '@splinetool/react-spline'; +import { Application } from '@splinetool/runtime'; +import Link from 'next/link'; +import Wrapper from 'components/layout/Wrapper'; import { useScreenSize } from 'hooks/useScreenSize'; -import { useScrollState } from 'contexts/scrollStateContext'; -import Icon from 'components/general/Icon'; +import Title, { TitleSizes } from 'components/ui/Title'; +import Subtitle from 'components/ui/Subtitle'; +import Button from 'components/ui/Button'; +import BackgroundCircle from 'components/ui/BackgroundCircle'; import styles from './MainBlock.module.css'; +const setWideScreenPosition = (groupToMove: any, pxToMove: number) => { + groupToMove.position.x += pxToMove; +}; + +const setDefaultPosition = (groupToMove: any, pxToMove: number) => { + groupToMove.position.x -= pxToMove; +}; + const MainBlock: React.VFC = () => { - const screenSize = useScreenSize(); - const isMobile = screenSize === 'mobile'; + // const spline = useRef(null); + const splineContainer = useRef(null); + // const screenSize = useScreenSize(); + // const [isFirstLoad, setIsFirstLoad] = useState(true); + // const [isSplineLoaded, setIsSplineLoaded] = useState(false); + // const [isWide, setIsWide] = useState(screenSize === 'desktop'); - const rootRef = useRef(null); + // const pxToMove = 0; - const scrollToPartners = () => { - scroller.scrollTo('partners', { - duration: 1500, - containerId: 'home-page', - smooth: true, - }); + const onLoad = (splineApp: Application) => { + // spline.current = splineApp; + // setIsSplineLoaded(true); + if (splineContainer.current) { + splineContainer.current.style.opacity = '0'; + setTimeout(() => { + if (splineContainer.current) { + splineContainer.current.style.opacity = '1'; + } + }, 100); + } }; - useEffect(() => { - const resizeHandler = () => { - if (rootRef.current) - rootRef.current.style.height = - document.documentElement.clientHeight - 58 + 'px'; - }; + // useEffect(() => { + // if (!isSplineLoaded) { + // return; + // } + + // setIsFirstLoad(prevIsFirstLoad => { + // let groupToMove; + + // if (prevIsFirstLoad && !isWide) { + // return false; + // } + + // if (spline && spline.current) { + // groupToMove = spline.current.findObjectById( + // 'cc1a3bc8-a4a6-430d-91e6-9bcc7409697b' + // ); + // } + + // if (isWide) { + // setWideScreenPosition(groupToMove, pxToMove); + // } else { + // setDefaultPosition(groupToMove, pxToMove); + // } - window.addEventListener('resize', resizeHandler); - window.addEventListener('orientationchange', resizeHandler); + // if (prevIsFirstLoad) { + // return false; + // } - resizeHandler(); - return () => { - window.removeEventListener('resize', resizeHandler); - window.removeEventListener('orientationchange', resizeHandler); - }; - }, []); + // return prevIsFirstLoad; + // }); + // }, [isSplineLoaded, isWide]); + + // useEffect(() => { + // const resizeHandler = () => { + // setIsWide(screenSize === 'desktop'); + // }; + + // window.addEventListener('resize', resizeHandler); + // window.addEventListener('orientationchange', resizeHandler); + + // resizeHandler(); + // return () => { + // window.removeEventListener('resize', resizeHandler); + // window.removeEventListener('orientationchange', resizeHandler); + // }; + // }, [screenSize]); return ( -
- - We are{isMobile ?
: ' '}production-focused{' '} - development team -
- - Team has deep industry IT expertise in the development of startups, - independent private projects, public business. - - -
- - Technical Consulting -
-
- - FinTech -
-
- - Blockchain and NFT -
-
- - Startups -
-
- - Cloud architecture -
-
- - Machine Learning +
+
+ +
+ +
+ + We are{'\n'}production-focused{'\n'}development team + + + Supercharge your product with our team of experts who are passionate + about blockchain + + + +
- - - -
+ + + ); }; diff --git a/src/components/general/Partners/Partners.module.css b/src/components/general/Partners/Partners.module.css index 384c7b7..dd30b84 100644 --- a/src/components/general/Partners/Partners.module.css +++ b/src/components/general/Partners/Partners.module.css @@ -1,85 +1,127 @@ .root { - display: flex; - flex-direction: column; - align-items: center; - padding: 60px 20px; - background-color: white; + z-index: 1; + position: relative; +} - @media (--tablet-landscape) { - padding: 60px; - } +.inner { + padding: 61px 0 61px; - @media (--desktop) { - padding: 60px 120px; + @media (--tablet-vertical) { + padding: 66px 0 66px; } } -.header { - font-weight: 700; - font-size: 24px; - line-height: 125%; - color: var(--dark); - text-align: center; +.partnersCard { + background-color: var(--tranparent-grey); + border-radius: 20px; + padding: 54px 20px; @media (--tablet-vertical) { - font-size: 32px; + padding: 66px 120px 58px; + } + + @media (--tablet-landscape) { + padding: 66px 54px 58px; } } -.partners { - margin-top: 16px; +.header { + text-align: center; + margin-bottom: 40px; +} + +.logoContainer { + cursor: pointer; display: flex; - flex-wrap: wrap; justify-content: center; - row-gap: 16px; + align-items: center; + border-radius: 14px; + border: 1px solid var(--card-border); + padding: 22px 20px; + height: 82px; + + &:active { + background: linear-gradient( + to right, + rgba(43, 54, 64, 1), + rgba(43, 54, 64, 0) + ); + } + + &:active .logo { + color: var(--white); + } @media (--tablet-vertical) { - margin-top: 40px; - width: 680px; - row-gap: 32px; + height: 107px; } - @media (--tablet-landscape) { - width: 100%; - justify-content: space-between; + @media (hover: hover) { + &:hover, + &:focus { + background: linear-gradient( + 20deg, + rgba(13, 17, 22, 1) 0%, + rgba(13, 17, 22, 0) 100% + ); + } + + &:hover .logo, + &:focus .logo { + color: var(--white); + } } +} + +.logo { + width: 100%; + height: 100%; + color: #293552; + transition: all 0.2s; +} - @media (--desktop) { - width: 1200px; - justify-content: center; +.swiper { + margin-bottom: 63px; + + @media (--tablet-vertical) { + margin-bottom: 53px; } } -.iconWrapper { - width: 160px; - height: 88px; +.pagination { + position: static; display: flex; - align-items: center; justify-content: center; + gap: 1px; +} - @media (--desktop) { - margin: 0 30px; +.slide { + @media (--tablet-vertical) { + margin-bottom: 10px; } } -.togglePartnersVisibilityButton { - margin-top: 40px; - background: white; - border: 1px solid var(--grey); - border-radius: 8px; - padding: 9px 16px; - display: flex; - align-items: center; - justify-content: center; - font-weight: 600; - font-size: 16px; - line-height: 138%; - cursor: pointer; - transition: .3s; +.bullet { + position: relative; + width: 51px; + height: 5px; + border-radius: 10px; + background: var(--dark--grey); + opacity: 1; - @media (--desktop) { - &:hover { - border-color: var(--purple); + &::after { + content: ''; + display: block; + border-radius: 10px; + width: 0%; + height: 100%; + background: var(--accent-secondary-color); + } + + &.active { + &::after { + transition: inherit; + width: 100%; } } -} \ No newline at end of file +} diff --git a/src/components/general/Partners/Partners.tsx b/src/components/general/Partners/Partners.tsx index b12c53e..892d075 100644 --- a/src/components/general/Partners/Partners.tsx +++ b/src/components/general/Partners/Partners.tsx @@ -1,141 +1,203 @@ import { motion } from 'framer-motion'; -import React, { useMemo, useState } from 'react'; +import React, { FC, useRef } from 'react'; +import { Swiper as SwiperClass } from 'swiper'; +import { Swiper, SwiperSlide } from 'swiper/react'; +import { Grid, Autoplay, Pagination } from 'swiper/modules'; -import Icon from 'components/general/Icon'; -import { useScreenSize } from 'hooks/useScreenSize'; -import { useScrollState } from 'contexts/scrollStateContext'; +import 'swiper/css'; +import 'swiper/css/autoplay'; +import 'swiper/css/grid'; +import 'swiper/css/pagination'; +import Wrapper from 'components/layout/Wrapper'; +import Title, { TitleSizes } from 'components/ui/Title'; +import PartnerLogo, { PartnersIconsList } from 'components/ui/PartnerLogo'; import styles from './Partners.module.css'; -interface Partner { +interface IPartnerProps { name: string; + logo: React.ReactNode; url: string | null; } -const partners: Partner[] = [ +const partners: IPartnerProps[] = [ { - name: 'partner1', - url: 'https://lime-expo.ru/', + name: 'gateway', + logo: ( + + ), + url: 'https://gateway.fm/', }, { - name: 'partner12', - url: 'http://holygate.com', + name: 'arsnl', + logo: ( + + ), + url: 'https://arsnl.art/', }, { - name: 'partner4', + name: 'holygate', + logo: ( + + ), url: null, }, { - name: 'partner5', - url: null, - }, - { - name: 'partner7', - url: null, + name: 'revitt', + logo: ( + + ), + url: 'https://revitt.consulting/', }, { - name: 'partner8', - url: 'https://snark.art/', + name: 'ffconsulting', + logo: ( + + ), + url: 'https://www.ffconsulting.org', }, { - name: 'partner9', + name: 'agente', + logo: ( + + ), url: null, }, { - name: 'partner10', - url: 'https://revitt.consulting/', - }, - { - name: 'partner11', - url: 'https://www.final01.agency/', - }, - { - name: 'partner2', - url: 'https://macbio.ru/', + name: 'final01', + logo: ( + + ), + url: 'https://www.final01.com', }, { - name: 'partner3', - url: 'https://spamorez.ru/', + name: 'trinity', + logo: ( + + ), + url: 'https://trinitymonsters.com', }, { - name: 'partner6', - url: null, + name: 'snarkart', + logo: ( + + ), + url: 'https://snark.art', }, ]; -const Partners = () => { - const { - refs: { partners: partnersRef }, - } = useScrollState(); - - const [isAllPartnersOpen, setIsAllPartnersOpen] = useState(false); - const [hoverState, setHoverState] = useState(() => - new Array(partners.length).fill(false) - ); - - const screenSize = useScreenSize(); - const isDesktop = screenSize === 'desktop'; - const isWide = isDesktop || screenSize === 'tablet-landscape'; +const breakpoints = { + 1024: { + slidesPerView: 5, + spaceBetween: 20, + grid: { + rows: 1, + }, + }, +}; - const visiblePartners = useMemo( - () => (isAllPartnersOpen ? partners : partners.slice(0, isWide ? 8 : 7)), - [isAllPartnersOpen, isWide] - ); - const handleMouseOverPartnerLogo = (index: number) => { - if (!isDesktop) return; - setHoverState(hoverState.map((status, i) => i === index)); - }; - const handleMouseLeavePartnerLogo = () => { - if (!isDesktop) return; - setHoverState(new Array(partners.length).fill(false)); - }; - const handleTogglePartnersVisibilityButtonClick = () => { - setIsAllPartnersOpen(!isAllPartnersOpen); - }; +const Partners: FC = () => { + const swiperRef = useRef(null); + const swiperDelay = 3000; return ( -
- - Trusted development partners - - - {visiblePartners.map((partner, index) => ( -
- { - if (!partner.url) e.preventDefault(); - }} +
+ +
+
+ - + Trusted development{' '} + partners + + + { + swiperRef.current = swiper; + }} + pagination={{ + clickable: true, + bulletActiveClass: styles.active, + renderBullet: function (index: number, className: string) { + return ``; + }, + }} + breakpoints={breakpoints} + slidesPerView={2} + spaceBetween={20} + autoplay={{ delay: swiperDelay }} + onSwiper={() => { + if (swiperRef.current) { + swiperRef.current.pagination.el.classList.add( + styles.pagination + ); } - style={{ - cursor: 'pointer', - }} - onMouseOver={() => handleMouseOverPartnerLogo(index)} - onMouseLeave={handleMouseLeavePartnerLogo} - /> - + }} + > + {partners && + partners.length && + partners.map((partner, index) => ( + + {partner.url ? ( + { + if (!partner.url) e.preventDefault(); + }} + > +
+ {partner.logo} +
+
+ ) : ( +
{partner.logo}
+ )} +
+ ))} +
- ))} - -
- {isAllPartnersOpen ? 'Roll Up' : 'Open all partners'} -
-
+
+ + ); }; diff --git a/src/components/general/Projects/Projects.module.css b/src/components/general/Projects/Projects.module.css index 3972c8e..00993b9 100644 --- a/src/components/general/Projects/Projects.module.css +++ b/src/components/general/Projects/Projects.module.css @@ -1,38 +1,26 @@ .root { - z-index: 1; - background-color: var(--light); - padding: 80px 18px 20px; + background-color: var(--background); +} + +.inner { display: flex; flex-direction: column; align-items: center; position: relative; + padding: 61px 0 61px; @media (--tablet-vertical) { - padding: 100px 30px 20px; - } - - @media (--tablet-landscape) { - padding: 100px 60px 20px; - } - - @media (--desktop) { - padding: 100px 120px 20px; + padding: 66px 0 66px; } } .header { - font-weight: 700; - font-size: 24px; - line-height: 133%; - color: var(--dark); - margin-bottom: 20px; z-index: 0; - @media (--tablet-vertical) { - font-size: 32px; - } + text-align: center; + margin-bottom: 36px; - @media (--tablet-landscape) { - font-size: 42px; + @media (--tablet-vertical) { + margin-bottom: 60px; } } @@ -65,38 +53,45 @@ .card { position: relative; z-index: 2; - background: white; - border: 1px solid var(--grey); + background: transparent; + border: 1px solid var(--card-border); border-radius: 16px; width: 100%; display: grid; - padding: 20px 20px 4px; + padding: 42px 20px; grid-gap: 16px; align-items: start; - transition: .3s; max-width: 1200px; overflow: hidden; grid-template-areas: 'h' 'd' - 't' 'l' + 't' 'o'; + transition: background 0.2s; - &:hover { - border-color: var(--purple); + &:active { + background: var(--card-hover-gradient); - & .cardHeader { - color: var(--purple); + .arrow { + opacity: 1; } } - @media (--tablet-vertical) { - padding: 32px 32px 16px; + @media (hover: hover) { + &:hover, + &:focus { + background: var(--card-hover-gradient); + + .arrow { + opacity: 1; + } + } } - @media (--tablet-landscape) { - padding: 32px 40px 16px; + @media (--tablet-vertical) { + padding: 32px 40px; } @media (--desktop) { @@ -137,9 +132,7 @@ font-weight: 700; font-size: 18px; line-height: 133%; - color: var(--dark); - - transition: color, .3s; + color: var(--white); @media (--tablet-vertical) { font-size: 20px; @@ -154,8 +147,7 @@ font-weight: 400; font-size: 14px; line-height: 157%; - color: var(--dark); - opacity: .6; + color: var(--light-grey); @media (--desktop) { grid-area: d; @@ -177,7 +169,6 @@ flex-wrap: wrap; gap: 10px; max-height: max-content; - } .technology { @@ -185,58 +176,68 @@ justify-content: center; align-items: center; padding: 4px 12px; - background: white; - border: 1px solid var(--grey); + background: #06090c; border-radius: 8px; font-weight: 500; font-size: 14px; line-height: 157%; - color: var(--dark); + color: var(--white); } .otherTechnologies { font-weight: 400; font-size: 14px; line-height: 157%; - color: var(--dark); + color: var(--white); } .otherTechnologiesLabel { - opacity: .6; + color: var(--light-grey); } .projectLink { font-weight: 500; font-size: 14px; line-height: 157%; + grid-area: l; @media (--desktop) { margin-top: 20px; } } +.partner { + width: 170px; + height: 50px; + color: var(--light-grey); +} + +.arrow { + position: absolute; + top: 42px; + right: 20px; + width: 24px; + height: 24px; + color: var(--white); + opacity: 0.2; + transition: all 0.2s; + + @media (--tablet-vertical) { + top: 50%; + transform: translateY(-50%); + } +} + .projectsVisibilityButton { margin-top: 40px; display: flex; justify-content: center; align-items: center; padding: 9px 16px; - background: white; - border: 1px solid var(--grey); - border-radius: 8px; - font-weight: 600; - font-size: 16px; - line-height: 138%; - color: var(--dark); - cursor: pointer; - transition: .3s; + border: 1px solid var(--card-border); + color: var(--white); z-index: 1; - - @media (--desktop) { - &:hover { - border-color: var(--purple); - } - } + background: transparent; } .badge { @@ -244,6 +245,8 @@ width: 100%; margin-left: -80px; margin-top: -50px; + color: var(--white); + @media (--desktop) { position: absolute; top: -10px; @@ -256,4 +259,23 @@ display: flex; justify-content: flex-end; } -} \ No newline at end of file +} + +.badgeLogo { + width: 300px; + height: 120px; +} + +.badgeLogo path { + fill: currentColor; +} + +.BackgroundCircle { + top: 40px; + left: -190px; + transform: translate3d(0, 0, 0) rotate(-16deg); + + @media (--tablet-vertical) { + top: 250px; + } +} diff --git a/src/components/general/Projects/Projects.tsx b/src/components/general/Projects/Projects.tsx index 0882be2..25dd23e 100644 --- a/src/components/general/Projects/Projects.tsx +++ b/src/components/general/Projects/Projects.tsx @@ -1,14 +1,20 @@ import { motion } from 'framer-motion'; -import React, { RefObject, useMemo, useRef, useState } from 'react'; +import React, { FC, RefObject, useMemo, useRef, useState } from 'react'; import classNames from 'classnames'; -import { useScrollState } from 'contexts/scrollStateContext'; -import Icon from 'components/general/Icon'; +import ProjectBadgeWEB3 from '/public/icons/project-badge-web3.svg'; +import ArrowSVG from '/public/icons/arrow.svg'; + +import Title, { TitleSizes } from 'components/ui/Title'; +import BackgroundCircle from 'components/ui/BackgroundCircle'; +import Wrapper from 'components/layout/Wrapper'; import { useScreenSize } from 'hooks/useScreenSize'; import { Project, projects, } from 'components/general/Projects/projects.constants'; +import Button from 'components/ui/Button/'; +import PartnerLogo, { PartnersIconsList } from 'components/ui/PartnerLogo'; import styles from './Projects.module.css'; @@ -23,14 +29,14 @@ const ProjectLink: React.VFC = props => { if (link === null) return ( -
+
Currently working on
); return ( -
- Visit Home page +
+ Finished project
); }; @@ -40,9 +46,15 @@ interface ProjectProps extends Project { } const ProjectCard: React.VFC = props => { - const { name, description, otherTechnologies, technologies, link, myRef } = - props; - + const { + name, + description, + otherTechnologies, + technologies, + link, + partner, + myRef, + } = props; const isDesktop = useScreenSize() === 'desktop'; return ( @@ -78,12 +90,19 @@ const ProjectCard: React.VFC = props => {
)}
+ {partner ? ( + + ) : null} {!isDesktop && } {name === 'Juni::Db' && (
- +
)} +
); }; @@ -106,10 +125,7 @@ const ProjectCardWrapper: React.VFC = props => { return ; }; -const Projects = () => { - const { - refs: { projects: projectsRef }, - } = useScrollState(); +const Projects: FC = () => { const projectToScroll = useRef(); const [isAllProjectsOpen, setIsAllProjectsOpen] = useState(false); @@ -134,38 +150,38 @@ const Projects = () => { }; return ( -
- - - Our projects and{' '} - technologies - -
- {visibleProjects.map((project, index) => ( - - ))} -
- +
+ +
+ + + Our projects and technologies + + +
+ {visibleProjects.map((project, index) => ( + + ))} +
+ +
-
-
- {isAllProjectsOpen ? 'Roll Up' : 'See All Projects'} -
-
+ + ); }; -export default Projects; +export default React.memo(Projects); diff --git a/src/components/general/Projects/projects.constants.ts b/src/components/general/Projects/projects.constants.ts index fed7bb7..f3894d3 100644 --- a/src/components/general/Projects/projects.constants.ts +++ b/src/components/general/Projects/projects.constants.ts @@ -1,16 +1,20 @@ +import { PartnersIconsList } from 'components/ui/PartnerLogo'; + export interface Project { name: string; description: string; technologies: string[]; otherTechnologies?: string[]; + partner?: string | null; link?: string | null; } export const projects: Project[] = [ { - link: 'https://infinex.io', + partner: PartnersIconsList.GATEWAY, + link: 'https://infinex.io', description: - 'In collaboration with Gateway.fm, we have developed an optimized and efficient API tailored for Synthetix PerpsV3 DEX to improve the trading experience by providing high-speed data access and seamless integration with PerpsV3 contracts.', + 'In collaboration with Gateway.fm & Infinex, we developed the new Infinex HFT API, a bespoke solution meticulously engineered for the Synthetix PerpsV3 DEX. This advanced API enhances the trading platform by offering rapid data access and flawless integration with PerpsV3 contracts, significantly elevating the trading experience through its optimized performance.', technologies: [ 'Go', 'Optimism', @@ -19,12 +23,29 @@ export const projects: Project[] = [ 'ScyllaDB', 'PostgreSql', 'Swagger', - 'Ethereum', + ], + otherTechnologies: ['Microservices', 'Redis', 'Nomad', 'Protobuff'], + name: 'Infinex HFT API', + }, + { + partner: PartnersIconsList.GATEWAY, + link: null, + description: + "We are delighted to announce the launch of Wirex Pay, a pioneering venture undertaken in partnership with Gateway.fm. This decentralized payment network, WPay, is the fruit of integrating Gateway.fm's PaaS Presto, which is underpinned by Polygon's CDK. This integration not only facilitates Layer 2 solutions but also introduces private zkEVM rollups, markedly enhancing scalability and cost-effectiveness while alleviating the load on the Ethereum mainnet. This initiative is a significant step forward in refining Wirex card services, seamlessly merging a blockchain-based system with the established KYC and processing frameworks, setting a new benchmark for the future of financial services.", + technologies: [ + 'Go', + 'Python', + 'Solidity', + 'React', + 'zkEVM Rollup', + 'Hardhat', + 'GRPC', 'Swagger', - ], - otherTechnologies: ['Microservices', 'Redis', 'Nomad', 'Web3.js'], - name: 'Infinex HFT API', - }, + 'Polygon СDK', + ], + otherTechnologies: ['Microservices', 'Nomad', 'ethers.js', 'Protobuff', 'Redis', 'Next.js'], + name: 'Wirex Pay', + }, { link: null, description: @@ -45,9 +66,9 @@ export const projects: Project[] = [ name: 'GitSEC', }, { - link: 'http://arsnl.art/nascent', + link: 'http://arsnl.art/nascent', description: -'An NFT Drama in Four Acts… Nascent consists of fifteen unique diptychs and an open-edition NFT theatrical performance starring “Happiness Pills.” Through thought-provoking visuals and layered symbolism, artworks serves as a mirror that reveals the complex interplay between digital consumption and true happiness.', + 'An NFT Drama in Four Acts… Nascent consists of fifteen unique diptychs and an open-edition NFT theatrical performance starring “Happiness Pills.” Through thought-provoking visuals and layered symbolism, artworks serves as a mirror that reveals the complex interplay between digital consumption and true happiness.', technologies: [ 'Go', 'Ethereum', @@ -56,14 +77,23 @@ export const projects: Project[] = [ 'PostgreSql', 'Swagger', 'EKS', - ], - otherTechnologies: ['Microservices', 'Ether.js', 'Stripe', 'Hardhat', 'Redis', 'AWS', 'S3', 'Docker'], - name: 'Ash Thorp: Nascent', - }, + ], + otherTechnologies: [ + 'Microservices', + 'Ether.js', + 'Stripe', + 'Hardhat', + 'Redis', + 'AWS', + 'S3', + 'Docker', + ], + name: 'Ash Thorp: Nascent', + }, { - link: 'https://arsnl.art/geometries', + link: 'https://arsnl.art/geometries', description: -'Each NFT is the culmination of a decades-long exploration of computation, painting, and physical space by one of the most legendary living artists. Owners may 3D print their NFTs as physical objects for personal use, display them in virtual and augmented realities, or remix them into something new.', + 'Each NFT is the culmination of a decades-long exploration of computation, painting, and physical space by one of the most legendary living artists. Owners may 3D print their NFTs as physical objects for personal use, display them in virtual and augmented realities, or remix them into something new.', technologies: [ 'Go', 'Ethereum', @@ -73,14 +103,25 @@ export const projects: Project[] = [ 'Swagger', 'React', 'EKS', - ], - otherTechnologies: ['Node.js', 'Microservices', 'Redis', 'AWS', 'Kubernetes', 'S3', 'Docker', 'Next.js', 'Web3.js', 'Stripe'], - name: 'Frank Stella: Geometries', - }, + ], + otherTechnologies: [ + 'Node.js', + 'Microservices', + 'Redis', + 'AWS', + 'Kubernetes', + 'S3', + 'Docker', + 'Next.js', + 'ethers.js', + 'Stripe', + ], + name: 'Frank Stella: Geometries', + }, { - link: 'https://arsnl.art/for-a-limited-time', + link: 'https://arsnl.art/for-a-limited-time', description: - 'Algorithms generate collages that every 15 min. transform images of current events into works. A new work is created every 10 - 15 minutes. A collector can claim the work, cementing the art and their personal connection with time onto the blockchain. Only 750 of 35k artworks be "curated" by collectors at their choosing over the course of the year.', + 'Algorithms generate collages that every 15 min. transform images of current events into works. A new work is created every 10 - 15 minutes. A collector can claim the work, cementing the art and their personal connection with time onto the blockchain. Only 750 of 35k artworks be "curated" by collectors at their choosing over the course of the year.', technologies: [ 'Go', 'Ethereum', @@ -89,10 +130,19 @@ export const projects: Project[] = [ 'PostgreSql', 'Swagger', 'EKS', - ], - otherTechnologies: ['Microservices', 'Redis', 'AWS', 'Kubernetes', 'S3', 'Docker', 'Web3.js', 'Stripe'], - name: 'Siebren Versteeg: For a limited time', - }, + ], + otherTechnologies: [ + 'Microservices', + 'Redis', + 'AWS', + 'Kubernetes', + 'S3', + 'Docker', + 'ethers.js', + 'Stripe', + ], + name: 'Siebren Versteeg: For a limited time', + }, { link: null, description: diff --git a/src/components/general/Team/Team.module.css b/src/components/general/Team/Team.module.css index 55dddae..f6ad405 100644 --- a/src/components/general/Team/Team.module.css +++ b/src/components/general/Team/Team.module.css @@ -1,183 +1,133 @@ -.wrapper { - display: flex; - align-items: center; - justify-content: center; - width: 100%; - background-color: var(--dark); -} +.inner { + position: relative; + padding: 61px 0 61px; -.root { - box-sizing: content-box; - width: 100%; - max-width: 1200px; - display: grid; - padding: 80px 20px; - grid-row-gap: 24px; - grid-template-areas: - 'h1 h1' - 'f1 f2' - 'h2 h2' - 'c1 c1' - 'c2 c2'; @media (--tablet-vertical) { - padding: 100px 32px; - grid-row-gap: 32px; - grid-template-areas: - 'h1 h1' - 'f1 f2' - 'h2 h2' - 'c1 c2'; + padding: 66px 0 66px; } +} - @media (--tablet-landscape) { - grid-row-gap: 40px; - padding: 120px 60px; - } +.title { + z-index: 1; + position: relative; + text-align: center; + margin-bottom: 24px; - @media (--desktop) { - padding: 120px 120px; - grid-row-gap: 60px; - grid-template-areas: - 'h1 f1 f2' - 'h2 c1 c2'; + @media (--tablet-vertical) { + margin-bottom: 30px; } } -.header { - font-style: normal; - font-weight: 700; - font-size: 24px; - line-height: 133%; - color: white; +.coloredSpan { + display: block; @media (--tablet-landscape) { - font-size: 32px; + display: unset; } +} - @media (--tablet-landscape) { - font-size: 42px; - } +.tabs { + z-index: 1; + position: relative; } -.founders { - margin-top: 24px; - width: 100%; +.slide { display: flex; - gap: 20px; + justify-content: center; +} - @media (--tablet-vertical) { - gap: 28px; - } +.pagination { + position: static; + display: flex; + justify-content: center; + gap: 1px; +} - @media (--tablet-landscape) { - gap: 152px; +.bullet { + position: relative; + width: 51px; + height: 5px; + border-radius: 10px; + background: var(--dark--grey); + opacity: 1; + margin-top: 42px !important; + + &:only-child { + margin-top: 0 !important; } - @media (--desktop) { - margin-top: 0; - gap: 104px; + &::after { + content: ''; + display: block; + border-radius: 10px; + width: 0%; + height: 100%; + background: var(--accent-secondary-color); } -} -.founder { - display: flex; - flex-direction: column; - width: 150px; + &.active { + &::after { + transition: inherit; + width: 100%; + } + } @media (--tablet-vertical) { - width: 310px; + margin-top: 63px !important; } } -.name { - margin-top: 12px; - font-weight: 700; - font-size: 18px; - line-height: 133%; - color: white; -} - -.position { - font-weight: 400; - font-size: 14px; - line-height: 157%; - color: white; - opacity: .6; - margin-top: 2px; +.backgroundCircle { + top: 87px; + right: -400px; + transform: translate3d(0, 0, 0) rotate(-30deg); } -.socialLinks { - margin-top: 10px; +.teamMore { display: flex; - gap: 18px; - - & path { - fill: white; - fill-opacity: .3; - } -} - -.founderImageWrapper { + background-color: var(--tranparent-grey); border-radius: 16px; - overflow: hidden; - width: 150px; - height: 150px; - - @media (--tablet-vertical) { - width: 300px; - height: 300px; - } -} - -.socialLink { - width: 24px; - height: 24px; - cursor: pointer; - - & path { - transition: .3s; - } + width: 100%; + max-width: 280px; + transition: background 0.2s; - &:hover path { - fill: var(--purple); + &:active { + background: var(--card-hover-gradient); } -} -.team { - display: grid; - grid-template-columns: 1fr; - grid-column-gap: 40px; - grid-row-gap: 32px; - margin-top: 32px; - - @media (--tablet-vertical) { - grid-template-columns: 1fr 1fr; + @media (hover: hover) { + &:hover, + &:focus { + background: var(--card-hover-gradient); + } } } -.teamMember { +.teamMoreInner { display: flex; - gap: 24px; -} - -.teamMemberName { - margin-top: 0; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 7px; + padding: 38px 22px 22px; + min-height: 352px; + width: fit-content; + min-width: 100%; } -.teamMemberImageWrapper { - width: 82px; - height: 82px; - border-radius: 16px; - overflow: hidden; +.teamMoreTitle { + color: var(--white); + font-size: 22px; + line-height: 160%; + text-align: center; + margin: 0; } -.teamMemberInfos { - display: flex; - flex-direction: column; +.teamMoreText { + color: var(--white); + font-size: 14px; + line-height: 160%; + text-align: center; + opacity: 0.6; + margin: 0; } - -.teamColumn { - display: flex; - flex-direction: column; - grid-row-gap: 24px; -} \ No newline at end of file diff --git a/src/components/general/Team/Team.tsx b/src/components/general/Team/Team.tsx index d823df7..0e98288 100644 --- a/src/components/general/Team/Team.tsx +++ b/src/components/general/Team/Team.tsx @@ -1,199 +1,214 @@ -import { motion } from 'framer-motion'; -import React from 'react'; -import Image from 'next/image'; +import React, { FC, useRef } from 'react'; import classNames from 'classnames'; +import { Swiper as SwiperClass } from 'swiper'; +import { Swiper, SwiperSlide } from 'swiper/react'; +import { Autoplay, Pagination } from 'swiper/modules'; -import { useScrollState } from 'contexts/scrollStateContext'; -import Icon from 'components/general/Icon'; +import 'swiper/css'; +import 'swiper/css/pagination'; +import Wrapper from 'components/layout/Wrapper'; +import Title, { TitleSizes } from 'components/ui/Title'; +import Tabs from 'components/ui/Tabs'; +import { SocialIcons } from 'components/ui/Socials'; +import TeamMember from 'components/ui/TeamMember'; +import BackgroundCircle from 'components/ui/BackgroundCircle'; import styles from './Team.module.css'; -interface SocialLinks { - facebook: string | null; - linkedIn: string | null; - twitter: string | null; - github: string | null; -} +const founders = [ + { + firstName: 'Mike', + lastName: 'Manko', + position: 'CEO', + photoPath: './team/mike.png', + socials: [ + { + icon: SocialIcons.FACEBOOK, + link: 'https://www.facebook.com/stones.rolling.31', + }, + { + icon: SocialIcons.LINKEDIN, + link: 'https://www.linkedin.com/in/mikhail-manko-97a491a2/', + }, + { icon: SocialIcons.GITHUB, link: 'https://github.com/MikeMS-sys' }, + ], + }, + { + firstName: 'Andrew', + lastName: 'Skurlatov', + position: 'CTO', + photoPath: './team/andrew.png', + socials: [ + { + icon: SocialIcons.FACEBOOK, + link: 'https://www.facebook.com/andrey.skurlatov', + }, + { + icon: SocialIcons.LINKEDIN, + link: 'https://www.linkedin.com/in/andrew-skurlatov/', + }, + { icon: SocialIcons.GITHUB, link: 'https://github.com/andskur' }, + { icon: SocialIcons.TWITTER, link: 'https://twitter.com/Andskur1' }, + ], + }, +]; -const SocialLinks: React.VFC = props => { - const { facebook, github, twitter, linkedIn } = props; +const team = [ + { + firstName: 'Andrei', + lastName: 'Solovov', + position: 'Smart Contract Lead', + photoPath: './team/solovov.png', + socials: [ + { + icon: SocialIcons.LINKEDIN, + link: 'https://www.linkedin.com/in/andrey-solovov-bb665884/', + }, + { icon: SocialIcons.GITHUB, link: 'https://github.com/asolovov' }, + ], + }, + { + firstName: 'Pavel', + lastName: 'Dodonov', + position: 'Backend Lead', + photoPath: './team/pavel.png', + socials: [ + { + icon: SocialIcons.LINKEDIN, + link: 'https://www.linkedin.com/in/paveldodonov/', + }, + { icon: SocialIcons.GITHUB, link: 'https://github.com/Pashteto' }, + ], + }, +]; - return ( -
- {facebook && ( - - - - )} - {linkedIn && ( - - - - )} - {twitter && ( - - - - )} - {github && ( - - - - )} -
- ); +const breakpoints = { + 720: { + slidesPerView: 2, + spaceBetween: 20, + }, + 1024: { + slidesPerView: 4, + spaceBetween: 20, + }, }; -interface TeamMemberProps { - name: string; - position: string; - img: string; - socialLinks: SocialLinks; -} +const Team: FC = () => { + const swiperRef = useRef(null); + const swiperDelay = 3000; -const TeamMember: React.VFC = props => { - const { img, socialLinks, position, name } = props; - - return ( -
-
- {name} -
-
-
- {name} -
-
{position}
- -
-
+ const coloredSpanClassNames = classNames( + 'accentSecondaryText', + styles.coloredSpan ); -}; -const Team = () => { - const { - refs: { team }, - } = useScrollState(); + const tabs = [ + { + title: 'Founders', + content: ( + { + swiperRef.current = swiper; + }} + pagination={{ + clickable: true, + bulletActiveClass: styles.active, + renderBullet: function (index: number, className: string) { + return ``; + }, + }} + breakpoints={breakpoints} + centerInsufficientSlides={true} + slidesPerView={1} + spaceBetween={20} + autoplay={{ delay: swiperDelay }} + onSwiper={() => { + if (swiperRef.current) { + swiperRef.current.pagination.el.classList.add(styles.pagination); + } + }} + > + {founders && + founders.length && + founders.map(founder => ( + + + + ))} + + ), + }, + { + title: 'Team', + content: ( + { + swiperRef.current = swiper; + }} + pagination={{ + clickable: true, + bulletActiveClass: styles.active, + renderBullet: function (index: number, className: string) { + return ``; + }, + }} + breakpoints={breakpoints} + centerInsufficientSlides={true} + slidesPerView={1} + spaceBetween={20} + autoplay={{ delay: swiperDelay }} + onSwiper={() => { + if (swiperRef.current) { + swiperRef.current.pagination.el.classList.add(styles.pagination); + } + }} + > + {team && + team.length && + team.map(teamMember => ( + + + + ))} + +
+
+

And 10+

+

more talented engineers

+
+
+
+
+ ), + }, + ]; return ( -
-
- - Meet our leadership - - -
- founder -
-
Mike Manko
-
CEO
- -
- -
- founder -
-
Andrey Skurlatov
-
CTO
- -
- - Our team - - - {/**/} - - - - {/**/} - - -
-
+
+ +
+ + We are devoted to{' '} + <span className={coloredSpanClassNames}> + creating help humanity + </span>{' '} + get to the future faster Meet + + + +
+
+
); }; diff --git a/src/components/layout/Footer/Footer.module.css b/src/components/layout/Footer/Footer.module.css new file mode 100644 index 0000000..c52411a --- /dev/null +++ b/src/components/layout/Footer/Footer.module.css @@ -0,0 +1,141 @@ +.footer { + background-color: var(--background); +} + +.inner { + padding: 71px 0 44px; + + @media (--tablet-vertical) { + padding: 80px 0 46px; + } +} + +.logo { + margin: 0 auto 48px; + + @media (--tablet-vertical) { + margin: 0; + } +} + +.footerTop { + padding-bottom: 44px; + border-bottom: 1px solid #101314; + display: flex; + flex-direction: column; + align-items: center; + + @media (--tablet-vertical) { + flex-direction: row; + justify-content: space-between; + gap: 40px; + } +} + +.footerMedia { + display: flex; + flex-direction: column; + align-items: center; + + @media (--tablet-vertical) { + align-items: flex-end; + } +} + +.socials { + margin-bottom: 30px; + + @media (--tablet-vertical) { + margin-bottom: 25px; + } +} + +.emailList { + padding: 0; + margin: 0; + display: flex; + flex-direction: column; + align-items: center; + gap: 24px; + list-style: none; + + @media (--tablet-vertical) { + align-items: flex-end; + gap: 14px; + } +} + +.email { + color: var(--light-grey); + font-size: 16px; + line-height: 137%; + transition: all 0.2s; + + &:active { + color: var(--white); + } + + @media (hover: hover) { + &:hover, + &:focus { + color: var(--white); + } + } +} + +.footerBottom { + display: flex; + flex-direction: column; + align-items: center; + padding-top: 40px; + + @media (--tablet-vertical) { + flex-direction: row; + padding-top: 44px; + gap: 40px; + justify-content: space-between; + } +} + +.nav { + display: flex; + flex-direction: column; + align-items: center; + gap: 20px; + margin: 0 0 20px; + padding: 0; + list-style: none; + + @media (--tablet-vertical) { + flex-direction: row; + gap: 50px; + } +} + +.navItem { + color: var(--light-grey); + font-size: 14px; + line-height: 157%; + transition: all 0.2s; + + &:active { + color: var(--white); + } + + @media (hover: hover) { + &:hover, + &:focus { + color: var(--white); + } + } +} + +.copyright { + color: var(--light-grey); + font-size: 14px; + line-height: 157%; + + @media (--tablet-vertical) { + order: -1; + } +} diff --git a/src/components/layout/Footer/Footer.tsx b/src/components/layout/Footer/Footer.tsx new file mode 100644 index 0000000..cb55775 --- /dev/null +++ b/src/components/layout/Footer/Footer.tsx @@ -0,0 +1,69 @@ +import React, { FC } from 'react'; +import Link from 'next/link'; + +import Wrapper from 'components/layout/Wrapper'; +import Socials, { SocialIcons } from 'components/ui/Socials'; +import Logo from 'components/ui/Logo'; + +import styles from './Footer.module.css'; + +const socialItems = [ + { icon: SocialIcons.FACEBOOK, link: 'https://www.facebook.com/uddug.dev' }, + { + icon: SocialIcons.LINKEDIN, + link: 'https://www.linkedin.com/company/uddug/', + }, + { icon: SocialIcons.TWITTER, link: 'https://twitter.com/Uddug_dev' }, + { icon: SocialIcons.GITHUB, link: 'https://github.com/uddugteam' }, +]; + +const emails = ['info@uddug.com']; + +const navLinks = [ + { + name: 'Privacy policy', + link: '/privacy-policy', + }, +]; + +const Footer: FC = () => { + return ( +
+ +
+
+ +
+ +
    + {emails && + emails.length && + emails.map(item => ( +
  • + + {item} + +
  • + ))} +
+
+
+
+
    + {navLinks && + navLinks.length && + navLinks.map(item => ( +
  • + {item.name} +
  • + ))} +
+ Uddúg © 2024 +
+
+
+
+ ); +}; + +export default React.memo(Footer); diff --git a/src/components/layout/Footer/index.ts b/src/components/layout/Footer/index.ts new file mode 100644 index 0000000..ced11e5 --- /dev/null +++ b/src/components/layout/Footer/index.ts @@ -0,0 +1,3 @@ +import Footer from './Footer'; + +export default Footer; diff --git a/src/components/layout/Header/Header.module.css b/src/components/layout/Header/Header.module.css index 7a50ec9..7b8616d 100644 --- a/src/components/layout/Header/Header.module.css +++ b/src/components/layout/Header/Header.module.css @@ -1,14 +1,18 @@ -.wrapper { - z-index: 1000; +.header { + z-index: 2; + position: fixed; display: flex; justify-content: center; width: 100%; - background-color: var(--dark); - transition: .3s; + transition: 0.3s; color: var(--light); - &.light { - background-color: white; - color: var(--dark); + padding-top: 13px; + top: 0; + + &.scrolled { + padding-top: 0; + backdrop-filter: blur(20px); + background-color: rgba(1, 3, 5, 0.3); } } @@ -19,59 +23,138 @@ display: flex; align-items: center; justify-content: space-between; - padding: 0 20px; - - line-height: calc(11/8); @media (--tablet-vertical) { - padding: 0 32px; height: 72px; } +} + +.buttonsWrapper { + display: flex; + flex-direction: column; + align-items: stretch; + gap: 5px; + + @media (--desktop) { + flex-direction: row; + align-items: center; + gap: 48px; + } +} + +.navButton { + padding: 21px 30px 19px; + text-align: start; + margin: 0; + background-image: url('/icons/tick.svg'); + background-repeat: no-repeat; + background-position: center right 30px; + color: rgba(255, 255, 255, 0.6); @media (--tablet-landscape) { - padding: 0 60px; + padding: 21px 60px 19px; + background-position: center right 60px; } @media (--desktop) { - padding: 0 120px; + padding: 0; + text-align: center; + background-image: none; + overflow: hidden; } } -.logo { - width: 145px; - height: 28px; +.navButton:active { + color: var(--white); + background-color: rgba(255, 255, 255, 0.05); + background-image: none; + + @media (--desktop) { + background-color: transparent; + } } -.buttonsWrapper { - display: flex; - align-items: center; +.navButtonLink { + padding: 0; + background: none; } .contactUs { - background-color: var(--purple); - height: 36px; - width: 117px; - border-radius: 8px; - cursor: pointer; + margin: 0 30px; + padding: 12px 24px; + + @media (--tablet-landscape) { + margin: 0 60px; + } + + @media (--desktop) { + margin: 0; + } +} + +.burgerButton { + z-index: 1; + + @media (--desktop) { + display: none; + } +} + +.menuToggler { + z-index: 1; + background: transparent; + border: 1px solid var(--white); + + @media (--desktop) { + display: none; + } +} + +.mobileMenu { + overflow: hidden; + position: absolute; display: flex; - align-items: center; - justify-content: center; - font-weight: 600; - transition: .2s; - color: var(--light); + flex-direction: column; + justify-content: space-between; + top: -100vh; + left: 0; + right: 0; + padding: 150px 0 110px; + background-color: var(--background); + transition: all 0.5s; + height: 100vh; - &:hover { - background-color: var(--purple-hover); + @media (--desktop) { + display: none; } } -.navButton { - font-weight: 400; - margin-right: 48px; - cursor: pointer; - transition: .2s; +.opened .mobileMenu { + top: 0; +} + +.opened .menuToggler { + border: none; + padding: 0; + width: 26px; + height: 26px; + background-image: url('/icons/cross.svg'); + background-repeat: no-repeat; + background-position: center; +} + +.backgroundCircle { + top: 110px; + left: 20px; + transform: translate3d(0, 0, 0) rotate(-30deg); + + @media (--tablet-vertical) { + top: 50px; + left: auto; + right: -352px; + } - &:hover { - color: var(--orange); + @media (--desktop) { + display: none; } } diff --git a/src/components/layout/Header/Header.tsx b/src/components/layout/Header/Header.tsx index 1943707..0161e4f 100644 --- a/src/components/layout/Header/Header.tsx +++ b/src/components/layout/Header/Header.tsx @@ -1,97 +1,160 @@ -import React, { useMemo } from 'react'; +import React, { FC, useState, useEffect } from 'react'; +import Link from 'next/link'; import classNames from 'classnames'; -import * as Scroll from 'react-scroll'; import { useRouter } from 'next/router'; -const { scroller } = Scroll; - -import Icon from 'components/general/Icon'; -import { ScrollRefs, useScrollState } from 'contexts/scrollStateContext'; import { useScreenSize } from 'hooks/useScreenSize'; +import Wrapper from 'components/layout/Wrapper'; +import Logo from 'components/ui/Logo'; +import Button from 'components/ui/Button'; +import BurgerButton from 'components/ui/burger-button'; +import BackgroundCircle from 'components/ui/BackgroundCircle'; import styles from './Header.module.css'; -const scrollSpeed = 1; +const navLinks = [ + { + title: 'Projects', + link: '/#projects', + }, + { + title: 'Team', + link: '/#team', + }, + { + title: 'Careers', + link: '/#careers', + }, +]; + +const Header: FC = () => { + const [isMenuOpened, setIsMenuOpened] = useState(false); + const [isScrolled, setIsScrolled] = useState(false); -const Header: React.VFC = () => { const router = useRouter(); - const isPrivacyPolicyPage = useMemo( - () => router.pathname.indexOf('privacy-policy'), - [router.pathname] - ); + useEffect(() => { + const handleScroll = () => { + if (window.scrollY > 0) { + setIsScrolled(true); + } else { + setIsScrolled(false); + } + }; - const { scroll, refs } = useScrollState(); - const [isScrolled] = scroll; + window.addEventListener('scroll', handleScroll); - const screenSize = useScreenSize(); - const isWide = screenSize === 'desktop' || screenSize === 'tablet-landscape'; + return () => { + window.removeEventListener('scroll', handleScroll); + }; + }, []); - const smoothScrollElement = async (elementId: keyof ScrollRefs) => { - const homePage = document.getElementById('home-page'); - const scrollToPx = refs[elementId].current?.getBoundingClientRect().top; - if (!homePage || !scrollToPx) return; - const duration = Math.abs(homePage.scrollTop - scrollToPx) / scrollSpeed; - if (isPrivacyPolicyPage) { - await router.push('/'); + useEffect(() => { + if (isMenuOpened) { + document.body.style.overflow = 'hidden'; + document.body.style.touchAction = 'none'; + } else { + document.body.style.overflow = 'unset'; + document.body.style.touchAction = 'unset'; } - scroller.scrollTo(elementId, { - duration: duration, - containerId: 'home-page', - smooth: true, - }); - }; + }, [isMenuOpened]); + + const screenSize = useScreenSize(); + const isWide = screenSize === 'desktop'; + const headerClassnames = classNames( + styles.header, + isScrolled && [styles.scrolled], + isMenuOpened && styles.opened, + router.pathname.includes('privacy-policy') && [styles.scrolled] + ); + + const backgroundCircleClassnames = classNames(styles.backgroundCircle); return ( -
- -
+ + + ); }; -export default Header; +export default React.memo(Header); diff --git a/src/components/layout/MainLayout/MainLayout.tsx b/src/components/layout/MainLayout/MainLayout.tsx index 448512d..322725b 100644 --- a/src/components/layout/MainLayout/MainLayout.tsx +++ b/src/components/layout/MainLayout/MainLayout.tsx @@ -2,18 +2,17 @@ import { NextPage } from 'next'; import React from 'react'; import Header from 'components/layout/Header'; -import ScrollProvider from 'contexts/scrollStateContext'; +import Footer from 'components/layout/Footer'; const MainLayout: React.FC = props => { const { children } = props; return ( - -
-
- {children} -
-
+
+
+ {children} +
+
); }; diff --git a/src/components/layout/Wrapper/Wrapper.module.css b/src/components/layout/Wrapper/Wrapper.module.css new file mode 100644 index 0000000..fd1eeca --- /dev/null +++ b/src/components/layout/Wrapper/Wrapper.module.css @@ -0,0 +1,18 @@ +.wrapper { + max-width: 1440px; + width: 100%; + margin: 0 auto; + padding: 0 30px; + + @media (--tablet-vertical) { + padding: 0 30px; + } + + @media (--tablet-landscape) { + padding: 0 60px; + } + + @media (--desktop) { + padding: 0 120px; + } +} diff --git a/src/components/layout/Wrapper/Wrapper.tsx b/src/components/layout/Wrapper/Wrapper.tsx new file mode 100644 index 0000000..fd0b8d1 --- /dev/null +++ b/src/components/layout/Wrapper/Wrapper.tsx @@ -0,0 +1,13 @@ +import { FC } from 'react'; + +import styles from './Wrapper.module.css'; + +interface IWrapperProps { + children: React.ReactNode; +} + +const Wrapper: FC = ({ children }) => { + return
{children}
; +}; + +export default Wrapper; diff --git a/src/components/layout/Wrapper/index.ts b/src/components/layout/Wrapper/index.ts new file mode 100644 index 0000000..e99b69f --- /dev/null +++ b/src/components/layout/Wrapper/index.ts @@ -0,0 +1,3 @@ +import Wrapper from './Wrapper'; + +export default Wrapper; diff --git a/src/components/page/HomePage/HomePage.module.css b/src/components/page/HomePage/HomePage.module.css index 9c7db6b..709969a 100644 --- a/src/components/page/HomePage/HomePage.module.css +++ b/src/components/page/HomePage/HomePage.module.css @@ -1,4 +1,3 @@ .root { - overflow-y: auto; - overflow-x: hidden; -} \ No newline at end of file + max-width: 100vw; +} diff --git a/src/components/page/HomePage/HomePage.tsx b/src/components/page/HomePage/HomePage.tsx index 7fa2bfa..fe653c9 100644 --- a/src/components/page/HomePage/HomePage.tsx +++ b/src/components/page/HomePage/HomePage.tsx @@ -1,41 +1,45 @@ -import React, { UIEvent } from 'react'; +import React from 'react'; import { getLayout } from 'components/layout/MainLayout'; -import { useScrollState } from 'contexts/scrollStateContext/scrollStateContext'; import MainBlock from 'components/general/MainBlock'; +import Bullets from 'components/general/Bullets'; import Partners from 'components/general/Partners'; import Projects from 'components/general/Projects'; -import Mission from 'components/general/Mission'; import Team from 'components/general/Team'; import Careers from 'components/general/Careers'; -import Internship from 'components/general/Internship'; -import Footer from 'components/general/Footer'; -import RightBadge from 'components/layout/RightBadge'; +import ContactUs from 'components/general/ContactUs'; +import Footer from 'components/layout/Footer'; +// import Mission from 'components/general/Mission'; +// import Internship from 'components/general/Internship'; +// import RightBadge from 'components/layout/RightBadge'; import { AppNextPage } from '../../../../global'; import styles from './HomePage.module.css'; -const HomePage: AppNextPage = () => { - const [isScrolled, setIsScrolled] = useScrollState().scroll; - - const scrollHandler = (e: UIEvent) => { - const scrollTop = e.currentTarget.scrollTop; - const newIsScrolled = !(scrollTop === 0); - if (newIsScrolled !== isScrolled) setIsScrolled(newIsScrolled); - }; +const bullets = [ + { title: 'Web3', ico: 'web3-badge' }, + { title: 'ML / AI', ico: 'ml-ai-badge' }, + { title: 'NFT', ico: 'nft-badge' }, + { title: 'DeFi', ico: 'defi-badge' }, + { title: 'Clouds', ico: 'clouds-badge' }, + { title: 'Consulting', ico: 'consulting-badge' }, +]; +const HomePage: AppNextPage = () => { return ( -
+
+ - + - -
- -
+ {/*