first
@@ -0,0 +1 @@
|
|||||||
|
VITE_API_URL=http://localhost:3000
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
env: { browser: true, es2020: true },
|
||||||
|
extends: [
|
||||||
|
'eslint:recommended',
|
||||||
|
'plugin:@typescript-eslint/recommended',
|
||||||
|
'plugin:react-hooks/recommended',
|
||||||
|
],
|
||||||
|
ignorePatterns: ['dist', '.eslintrc.cjs'],
|
||||||
|
parser: '@typescript-eslint/parser',
|
||||||
|
plugins: ['react-refresh'],
|
||||||
|
rules: {
|
||||||
|
'react-refresh/only-export-components': [
|
||||||
|
'warn',
|
||||||
|
{ allowConstantExport: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
*.local
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
# React + TypeScript + Vite
|
||||||
|
|
||||||
|
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
|
||||||
|
|
||||||
|
Currently, two official plugins are available:
|
||||||
|
|
||||||
|
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
|
||||||
|
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
|
||||||
|
|
||||||
|
## Expanding the ESLint configuration
|
||||||
|
|
||||||
|
If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
|
||||||
|
|
||||||
|
- Configure the top-level `parserOptions` property like this:
|
||||||
|
|
||||||
|
```js
|
||||||
|
parserOptions: {
|
||||||
|
ecmaVersion: 'latest',
|
||||||
|
sourceType: 'module',
|
||||||
|
project: ['./tsconfig.json', './tsconfig.node.json'],
|
||||||
|
tsconfigRootDir: __dirname,
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
|
||||||
|
- Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
|
||||||
|
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Vite + React + TS</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"name": "client",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.0.0",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "tsc && vite build",
|
||||||
|
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
||||||
|
"preview": "vite preview"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"framer-motion": "^10.18.0",
|
||||||
|
"gsap": "^3.12.4",
|
||||||
|
"react": "^18.2.0",
|
||||||
|
"react-dom": "^18.2.0",
|
||||||
|
"react-router-dom": "^6.18.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/react": "^18.2.15",
|
||||||
|
"@types/react-dom": "^18.2.7",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
||||||
|
"@typescript-eslint/parser": "^6.0.0",
|
||||||
|
"@vitejs/plugin-react-swc": "^3.3.2",
|
||||||
|
"autoprefixer": "^10.4.16",
|
||||||
|
"eslint": "^8.45.0",
|
||||||
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
|
"eslint-plugin-react-refresh": "^0.4.3",
|
||||||
|
"postcss": "^8.4.31",
|
||||||
|
"tailwindcss": "^3.3.5",
|
||||||
|
"typescript": "^5.0.2",
|
||||||
|
"vite": "^4.4.5"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
export default {
|
||||||
|
plugins: {
|
||||||
|
tailwindcss: {},
|
||||||
|
autoprefixer: {},
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> <svg xmlns="http://www.w3.org/2000/svg" width="512" height="304" viewBox="0 0 512 304" fill="none"> <path d="M512 105.43H451.761C449.3 79.657 427.534 59.43 401.127 59.43H389.256L369.256 0H142.744L122.744 59.43H110.873C84.466 59.43 62.7 79.657 60.239 105.43H0V255.43H60.093C61.635 282.105 83.818 303.335 110.872 303.335H162.654C180.677 303.335 198.047 296.768 211.562 284.842C223.841 274.007 239.623 268.04 255.999 268.04C272.376 268.04 288.157 274.007 300.437 284.842C313.952 296.768 331.321 303.335 349.345 303.335H401.127C428.181 303.335 450.363 282.104 451.906 255.43H512V105.43ZM164.3 30H347.7L357.604 59.43H154.397L164.3 30ZM30 135.43H60V225.43H30V135.43ZM422 252.463C422 263.972 412.637 273.335 401.128 273.335H349.346C338.637 273.335 328.317 269.433 320.287 262.348C302.522 246.673 279.691 238.04 256 238.04C232.309 238.04 209.478 246.673 191.715 262.348C183.684 269.433 173.364 273.335 162.655 273.335H110.873C99.364 273.335 90 263.972 90 252.463V110.302C90 98.793 99.364 89.43 110.873 89.43H401.128C412.637 89.43 422 98.793 422 110.302V252.463ZM482 225.43H452V135.43H482V225.43Z" fill="#CE56C2"></path> <path d="M241.109 121.087H271.109V151.087H241.109V121.087Z" fill="#CE56C2"></path> <path d="M300.891 121.087H330.891V151.087H300.891V121.087Z" fill="#CE56C2"></path> <path d="M181.109 121.087H211.109V151.087H181.109V121.087Z" fill="#CE56C2"></path> </svg>
|
||||||
|
After Width: | Height: | Size: 1.4 KiB |
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> <svg xmlns="http://www.w3.org/2000/svg" width="412" height="437" viewBox="0 0 412 437" fill="none"> <path d="M115.677 159.145V280.492L205.647 322.666L295.618 280.492V159.145L205.647 114.16L115.677 159.145ZM192.794 149.326V223.627L141.383 250.939V175.031L192.794 149.326ZM157.279 271.603L205.647 245.907L254.016 271.602L205.647 294.276L157.279 271.603ZM269.912 250.939L218.5 223.627V149.326L269.912 175.031V250.939Z" fill="#CE56C2"></path> <path d="M411.294 167.088V77.1176H359.882V0H51.4118V77.1176H0V167.088H25.7059V102.824H51.4118V334.176H25.7059V269.912H0V359.882H51.4118V437H359.882V359.882H411.294V269.912H385.588V334.176H359.882V102.824H385.588V167.088H411.294ZM334.176 334.176H308.471V359.882H334.176V411.294H77.1177V359.882H102.824V334.176H77.1177V102.824H102.824V77.1176H77.1177V25.7059H334.176V77.1176H308.471V102.824H334.176V334.176Z" fill="#CE56C2"></path> <path d="M179.941 359.882H231.353V385.588H179.941V359.882Z" fill="#CE56C2"></path> <path d="M192.794 51.4116H218.5V77.1175H192.794V51.4116Z" fill="#CE56C2"></path> </svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> <svg xmlns="http://www.w3.org/2000/svg" width="472" height="437" viewBox="0 0 472 437" fill="none"> <rect x="13" y="13" width="287" height="411" rx="61" stroke="#CE56C2" stroke-width="26"></rect> <path d="M77.528 17L102.013 49.7868C103.523 51.809 105.899 53 108.422 53H208.625C211.388 53 213.957 51.5734 215.417 49.2269L235.472 17" stroke="#CE56C2" stroke-width="26"></path> <line x1="69.6867" y1="153" x2="244.433" y2="153" stroke="#CE56C2" stroke-width="26"></line> <line x1="69.6867" y1="206" x2="244.433" y2="206" stroke="#CE56C2" stroke-width="26"></line> <line x1="69.6867" y1="259" x2="173.817" y2="259" stroke="#CE56C2" stroke-width="26"></line> <mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="221" y="53" width="251" height="346"> <path fill-rule="evenodd" clip-rule="evenodd" d="M397.731 53H295C254.131 53 221 86.1309 221 127V324.147C221 365.016 254.131 398.147 295 398.147H397.731C438.6 398.147 471.731 365.016 471.731 324.147V127C471.731 86.1309 438.6 53 397.731 53ZM397.731 79C424.241 79 445.731 100.49 445.731 127V324.147C445.731 350.657 424.241 372.147 397.731 372.147H295C268.49 372.147 247 350.657 247 324.147V127C247 100.49 268.49 79 295 79H397.731Z" fill="#CE56C2"></path> </mask> <g mask="url(#mask0)"> <rect width="136" height="372" transform="matrix(-1 0 0 1 471.731 44)" fill="#CE56C2"></rect> </g> <line x1="346" y1="165" x2="430" y2="165" stroke="#CE56C2" stroke-width="26"></line> <line x1="346" y1="207" x2="430" y2="207" stroke="#CE56C2" stroke-width="26"></line> <line x1="346" y1="247" x2="430" y2="247" stroke="#CE56C2" stroke-width="26"></line> </svg>
|
||||||
|
After Width: | Height: | Size: 1.6 KiB |
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> <svg xmlns="http://www.w3.org/2000/svg" width="498" height="384" viewBox="0 0 498 384" fill="none"> <path d="M218.134 148.861C211.55 137.457 196.968 133.55 185.564 140.134C174.16 146.718 170.252 161.3 176.837 172.705L216.575 241.534C197.591 252.525 191.085 276.808 202.03 295.819L223.294 332.649L270.696 351.169L277.248 362.519L291.014 354.571L281.672 338.389L234.27 319.87L215.796 287.871C209.212 276.467 213.119 261.884 224.523 255.3L252.34 303.481L266.106 295.533L190.602 164.757C188.408 160.955 189.71 156.095 193.512 153.9C197.313 151.705 202.174 153.007 204.368 156.809L239.196 217.131L265.248 210.276L261.198 194.902L246.862 198.682L218.134 148.861Z" fill="#CE56C2" stroke="#CE56C2" stroke-width="8"></path> <path d="M280.637 206.268L296.008 202.219L291.959 186.848L276.588 190.897L280.637 206.268Z" fill="#CE56C2" stroke="#CE56C2" stroke-width="8"></path> <path d="M311.363 198.133L326.829 194.068L362.208 255.347L357.455 294.801L366.726 310.859L380.492 302.911L373.868 291.437L378.621 251.983L334.523 175.603L307.318 182.766L311.363 198.133Z" fill="#CE56C2" stroke="#CE56C2" stroke-width="8"></path> <path d="M164 275H12V12H486V275H410.5" stroke="#CE56C2" stroke-width="24"></path> <path d="M257.5 141.5C257.5 100.079 223.921 66.5 182.5 66.5C141.079 66.5 107.5 100.079 107.5 141.5C107.5 175.266 129.814 203.82 160.5 213.222" stroke="#CE56C2" stroke-width="24"></path> </svg>
|
||||||
|
After Width: | Height: | Size: 1.4 KiB |
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> <svg xmlns="http://www.w3.org/2000/svg" width="538" height="390" viewBox="0 0 538 390" fill="none"> <path d="M85 44.9853V166.332L174.971 208.506L264.941 166.332V44.9853L174.971 0L85 44.9853ZM162.118 35.1657V109.467L110.706 136.779V60.8715L162.118 35.1657ZM126.602 157.443L174.971 131.747L223.339 157.443L174.971 180.116L126.602 157.443ZM239.235 136.779L187.824 109.467V35.1657L239.235 60.8715V136.779Z" fill="#CE56C2"></path> <path d="M58 56H12V320H367.5M298 56H486V136" stroke="#CE56C2" stroke-width="24"></path> <path d="M526 176V338C526 360.091 508.091 378 486 378H408C385.909 378 368 360.091 368 338V176C368 153.909 385.909 136 408 136H486C508.091 136 526 153.909 526 176Z" stroke="#CE56C2" stroke-width="24"></path> <path d="M421.5 176H474" stroke="#CE56C2" stroke-width="24"></path> </svg>
|
||||||
|
After Width: | Height: | Size: 835 B |
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> <svg xmlns="http://www.w3.org/2000/svg" width="418" height="417" viewBox="0 0 418 417" fill="none"> <path d="M217.5 389C158.049 389 125.155 346.512 100.848 304.944C100.623 304.562 94.0272 292.331 91.3265 285.981C83.1204 266.117 79 245.211 79 223.733V159.559C79 103.174 115.426 82.494 141.169 77.9485C146.865 64.2254 164.247 43.4586 217.154 42.0707C258.115 40.8562 297.951 55.3601 323.747 80.5509C344.851 101.144 356 128.365 356 159.298V223.473C356 244.864 351.88 265.804 343.743 285.721C340.626 292.956 333.909 304.944 333.148 306.297C307.196 349.392 275.376 389 217.5 389V389ZM221.361 68.0422C220.201 68.0422 219.006 68.0596 217.846 68.0769C177.023 69.1699 165.009 83.2227 164.351 90.4919C163.762 97.0846 158.257 102.844 151.661 102.983C146.952 103.139 104.969 106.089 104.969 159.559V223.715C104.969 241.776 108.431 259.333 115.287 275.901C117.607 281.366 123.458 292.14 123.458 292.14C148.25 334.507 173.855 362.976 217.5 362.976C260.123 362.976 284.776 336.259 310.711 293.164C336.645 250.069 317.203 281.679 319.8 275.624C326.569 259.073 330.031 241.463 330.031 223.455V159.298C330.031 135.218 321.825 114.989 305.638 99.2011C285.78 79.8222 253.77 68.0422 221.361 68.0422V68.0422Z" fill="#CE56C2"></path> <path d="M91.9939 194C87.0424 194 82.2813 191.149 80.1345 186.329C77.2087 179.799 80.1345 172.128 86.6961 169.208L113.219 157.374C113.566 157.218 151.602 139.579 151.602 106.978C151.602 100.724 156.086 95.3678 162.232 94.2276C168.413 93.0528 174.49 96.5254 176.723 102.365C177.537 104.455 194.676 147.474 234.686 159.879C228.056 138.542 230.774 119.693 230.947 118.622C231.778 113.128 236.054 108.774 241.542 107.824C246.961 106.822 252.519 109.517 255.185 114.389C264.378 131.269 283.889 156.233 296.58 156.233C301.202 156.233 303.107 156.147 305.08 156.043C309.651 155.836 314.291 155.629 343.255 156.13C350.423 156.268 356.136 162.176 355.998 169.329C355.859 176.412 350.077 182.045 343.013 182.045C342.944 182.045 342.857 182.045 342.771 182.045C314.741 181.509 310.222 181.716 306.31 181.924C304.042 182.027 301.843 182.131 296.58 182.131C286.798 182.131 277.536 177.95 269.243 171.851C270.385 175.151 270.195 178.848 268.533 182.045C266.317 186.364 261.85 189.076 256.985 189.076C212.803 189.076 184.583 162.643 168.724 140.633C153.905 167.273 125.425 180.282 123.798 180.991L97.2743 192.825C95.5776 193.637 93.7771 194 91.9939 194V194Z" fill="#CE56C2"></path> <path d="M217.483 328C200.134 328 183.876 320.975 171.647 308.235C166.666 303.027 166.804 294.744 171.958 289.694C177.13 284.643 185.329 284.8 190.31 289.991C204.839 305.194 230.092 305.212 244.69 289.991C249.706 284.8 257.905 284.678 263.042 289.694C268.196 294.727 268.334 303.027 263.353 308.235C251.072 320.975 234.814 328 217.483 328V328Z" fill="#CE56C2"></path> <path d="M12 322V404.5H97" stroke="#CE56C2" stroke-width="24"></path> <path d="M13 94.5V12H98" stroke="#CE56C2" stroke-width="24"></path> <path d="M406 322V404.5H321" stroke="#CE56C2" stroke-width="24"></path> <path d="M406 94.5V12H321" stroke="#CE56C2" stroke-width="24"></path> <circle cx="218" cy="217" r="11" fill="#CE56C2"></circle> <circle cx="218" cy="246" r="11" fill="#CE56C2"></circle> <circle cx="218" cy="275" r="11" fill="#CE56C2"></circle> <circle cx="127" cy="216" r="11" fill="#CE56C2"></circle> <circle cx="156" cy="199" r="11" fill="#CE56C2"></circle> <circle cx="185" cy="215" r="11" fill="#CE56C2"></circle> <circle cx="156" cy="232" r="11" fill="#CE56C2"></circle> <circle cx="250" cy="216" r="11" fill="#CE56C2"></circle> <circle cx="279" cy="199" r="11" fill="#CE56C2"></circle> <circle cx="308" cy="215" r="11" fill="#CE56C2"></circle> <circle cx="279" cy="232" r="11" fill="#CE56C2"></circle> </svg>
|
||||||
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 182 KiB |
|
After Width: | Height: | Size: 144 KiB |
|
After Width: | Height: | Size: 171 KiB |
|
After Width: | Height: | Size: 148 KiB |
|
After Width: | Height: | Size: 146 KiB |
|
After Width: | Height: | Size: 140 KiB |
|
After Width: | Height: | Size: 109 KiB |
|
After Width: | Height: | Size: 91 KiB |
|
After Width: | Height: | Size: 155 KiB |
|
After Width: | Height: | Size: 158 KiB |
|
After Width: | Height: | Size: 154 KiB |
|
After Width: | Height: | Size: 148 KiB |
|
After Width: | Height: | Size: 116 KiB |
|
After Width: | Height: | Size: 169 KiB |
|
After Width: | Height: | Size: 134 KiB |
|
After Width: | Height: | Size: 189 KiB |
|
After Width: | Height: | Size: 99 KiB |
|
After Width: | Height: | Size: 134 KiB |
|
After Width: | Height: | Size: 123 KiB |
|
After Width: | Height: | Size: 238 KiB |
|
After Width: | Height: | Size: 133 KiB |
|
After Width: | Height: | Size: 95 KiB |
|
After Width: | Height: | Size: 176 KiB |
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> <svg xmlns="http://www.w3.org/2000/svg" width="10" height="22" viewBox="0 0 10 22" fill="none"> <path d="M2.13892 4.11856C2.13892 4.66467 2.13892 7.03113 2.13892 7.03113H0V10.6036H2.13892V21.2299H6.53055V10.6263H9.48864C9.48864 10.6263 9.76169 8.91975 9.89822 7.03113C9.51139 7.03113 6.5533 7.03113 6.5533 7.03113C6.5533 7.03113 6.5533 4.96047 6.5533 4.5964C6.5533 4.23233 7.03115 3.73173 7.50899 3.73173C7.98684 3.73173 8.98803 3.73173 9.89822 3.73173C9.89822 3.25389 9.89822 1.57006 9.89822 0C8.66947 0 7.25869 0 6.64432 0C2.04791 0 2.13892 3.59521 2.13892 4.11856Z" fill="white"></path> </svg>
|
||||||
|
After Width: | Height: | Size: 636 B |
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> <svg xmlns="http://www.w3.org/2000/svg" width="21" height="21" viewBox="0 0 21 21" fill="none"> <path fill-rule="evenodd" clip-rule="evenodd" d="M20.4544 3.62643C20.7129 4.29114 20.8934 5.05825 20.9426 6.17406C20.9918 7.29403 20.9959 7.65091 20.9959 10.5021C20.9959 13.3532 20.9836 13.7101 20.9344 14.83C20.8852 15.9459 20.7046 16.709 20.4463 17.3777C19.9006 18.7888 18.7848 19.9046 17.3735 20.4503C16.709 20.7088 15.9418 20.8892 14.826 20.9384C13.7061 20.9878 13.3492 20.9999 10.498 20.9999C7.6469 20.9999 7.28987 20.9878 6.17005 20.9384C5.05408 20.8892 4.29113 20.7088 3.62242 20.4503C2.92502 20.1878 2.28915 19.7734 1.76402 19.2401C1.23071 18.715 0.816466 18.0833 0.549813 17.3777C0.291332 16.713 0.110732 15.9459 0.0615354 14.83C0.0123391 13.7101 0 13.3532 0 10.5021C0 7.65091 0.0123391 7.29403 0.0657019 6.16989C0.114898 5.05408 0.295338 4.29114 0.553819 3.62242C0.816466 2.92502 1.23071 2.28915 1.76402 1.76402C2.28915 1.22654 2.92085 0.816306 3.62658 0.549653C4.29114 0.291332 5.05824 0.110732 6.17406 0.0615355C7.29403 0.0123391 7.65091 0 10.502 0C13.3532 0 13.7101 0.0123391 14.8342 0.0657019C15.95 0.114898 16.7131 0.295338 17.3817 0.553819C18.0791 0.816306 18.7149 1.23071 19.2401 1.76402C19.7776 2.28915 20.1878 2.92085 20.4544 3.62643ZM17.2594 5.51879C17.955 5.51879 18.5189 4.95487 18.5189 4.25939C18.5189 3.56375 17.955 3 17.2594 3C16.5639 3 16 3.56375 16 4.25939C16 4.95487 16.5639 5.51879 17.2594 5.51879ZM6 10.5C6 12.9848 8.01539 15 10.5 15C12.9848 15 15 12.9848 15 10.5C15 8.01518 12.9848 6 10.5 6C8.01539 6 6 8.01518 6 10.5Z" fill="white"></path> </svg>
|
||||||
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 268 B |
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> <svg xmlns="http://www.w3.org/2000/svg" width="23" height="13" viewBox="0 0 23 13" fill="none"> <path d="M19.4822 8.16886C20.2331 8.89701 21.0295 9.60239 21.7121 10.3988C22.0079 10.7629 22.281 11.1269 22.5085 11.5365C22.8043 12.1281 22.5313 12.788 22.0079 12.8108H18.7085C17.8666 12.879 17.184 12.5377 16.6151 11.9461C16.16 11.491 15.7277 10.9904 15.2954 10.5126C15.1133 10.3078 14.9313 10.1257 14.7037 9.98922C14.2486 9.69341 13.8618 9.78443 13.6115 10.2623C13.3385 10.7401 13.293 11.2635 13.2702 11.8096C13.2247 12.5832 12.9971 12.788 12.2235 12.8335C10.5624 12.9018 8.9696 12.6515 7.49056 11.8096C6.19355 11.0587 5.19236 10.012 4.30493 8.82874C2.59835 6.53054 1.30134 3.98204 0.118107 1.36527C-0.154947 0.773653 0.0498433 0.45509 0.686969 0.45509C1.75643 0.432335 2.84865 0.432335 3.91811 0.45509C4.35044 0.45509 4.64625 0.705389 4.80553 1.11497C5.39715 2.5485 6.10254 3.91377 6.98996 5.16527C7.21751 5.50659 7.46781 5.8479 7.80912 6.07545C8.19595 6.3485 8.49176 6.25748 8.67379 5.82515C8.78757 5.5521 8.83307 5.25629 8.85583 4.98323C8.94685 3.98204 8.94685 2.98084 8.81032 2.00239C8.7193 1.38802 8.37799 0.978443 7.74086 0.86467C7.4223 0.796407 7.46781 0.682634 7.62709 0.500598C7.90014 0.182035 8.15044 0 8.62828 0H12.36C12.9516 0.113772 13.0882 0.386826 13.1564 0.978443V5.11976C13.1564 5.34731 13.2702 6.02994 13.6798 6.18922C13.9983 6.30299 14.2259 6.02994 14.4307 5.82515C15.3181 4.86946 15.9552 3.75449 16.5241 2.59401C16.7744 2.09341 17.0019 1.54731 17.2067 1.02395C17.366 0.637126 17.6163 0.432335 18.0486 0.45509H21.6439C21.7576 0.45509 21.8486 0.455089 21.9624 0.477844C22.5768 0.591616 22.7361 0.841915 22.554 1.43353C22.2582 2.36647 21.6894 3.14012 21.1205 3.91377C20.5289 4.73293 19.8918 5.5521 19.2774 6.37126C18.754 7.12216 18.7995 7.50898 19.4822 8.16886Z" fill="white"></path> </svg>
|
||||||
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> <svg xmlns="http://www.w3.org/2000/svg" width="376" height="376" viewBox="0 0 376 376" fill="none"> <path d="M356.803 99.8946C352.741 84.7933 340.835 72.8891 325.735 68.8228C298.151 61.2754 187.812 61.2754 187.812 61.2754C187.812 61.2754 77.4773 61.2754 49.893 68.5367C35.0843 72.5987 22.8875 84.7955 18.8255 99.8946C11.5664 127.477 11.5664 184.678 11.5664 184.678C11.5664 184.678 11.5664 242.168 18.8255 269.462C22.8918 284.561 34.7939 296.465 49.8952 300.532C77.7677 308.081 187.816 308.081 187.816 308.081C187.816 308.081 298.151 308.081 325.735 300.82C340.837 296.756 352.741 284.852 356.807 269.753C364.064 242.168 364.064 184.969 364.064 184.969C364.064 184.969 364.355 127.477 356.803 99.8946V99.8946ZM152.683 237.523V131.833L244.435 184.678L152.683 237.523Z" fill="white"></path> </svg>
|
||||||
|
After Width: | Height: | Size: 834 B |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 154 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 114 KiB |
|
After Width: | Height: | Size: 107 KiB |
|
After Width: | Height: | Size: 89 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 49 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 108 KiB |
|
After Width: | Height: | Size: 493 KiB |
|
After Width: | Height: | Size: 2.7 MiB |
|
After Width: | Height: | Size: 228 KiB |
|
After Width: | Height: | Size: 6.4 MiB |
|
After Width: | Height: | Size: 4.7 MiB |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -0,0 +1,28 @@
|
|||||||
|
import ArrowIcon from "../../icons/ArrowIcon";
|
||||||
|
|
||||||
|
type DirectionImageProps = {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
image: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const DirectionImage = ({ title, description, image }: DirectionImageProps) => {
|
||||||
|
return (
|
||||||
|
<div className="h-[280px] text-white relative rounded-xl overflow-hidden after:absolute after:content-[''] after:z-10 after:w-full after:h-full after:top-0 after:left-0 after:bg-gradient-to-b after:from-[rgba(158,54,148,0.5)] after:to-[rgba(0,0,0,0.5)] cursor-pointer group">
|
||||||
|
<img
|
||||||
|
src={image}
|
||||||
|
className="object-cover h-full group-hover:scale-105 transition-all duration-700 w-full"
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
<div className="absolute flex justify-between left-0 top-0 z-20 w-full py-8 px-5 text-[22px]">
|
||||||
|
<div>{title}</div>
|
||||||
|
<ArrowIcon />
|
||||||
|
</div>
|
||||||
|
<div className="absolute left-0 bottom-0 z-20 py-8 px-5 text-[18px]">
|
||||||
|
{description}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DirectionImage;
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import DirectionImage from "./DirectionImage";
|
||||||
|
import { DirectionImageType } from "../../types";
|
||||||
|
|
||||||
|
const directionImages: DirectionImageType[] = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
image: "/images/directions/direction-1.jpg",
|
||||||
|
title: "НЕДВИЖИМОСТЬ",
|
||||||
|
desctiption: "Покажет квартиры на этапе строительства",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
image: "/images/directions/direction-2.jpg",
|
||||||
|
title: "ТРЕНАЖЁРЫ",
|
||||||
|
desctiption: "Обучит работе с оборудованием",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
image: "/images/directions/direction-3.jpg",
|
||||||
|
title: "ТЕХНИКА",
|
||||||
|
desctiption: "Презентует технику в 3D",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
image: "/images/directions/direction-4.jpg",
|
||||||
|
title: "ВЫСТАВКИ",
|
||||||
|
desctiption: "Вовлечёт посетителей стенда",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
image: "/images/directions/direction-5.jpg",
|
||||||
|
title: "ОНЛАЙН МЕРОПРИЯТИЯ",
|
||||||
|
desctiption: "Соберёт аудиторию со всего мира",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const DirectionImageContainer = () => {
|
||||||
|
return (
|
||||||
|
<div className="w-[1440px] mx-auto py-20 grid grid-cols-3 gap-5 h-fit">
|
||||||
|
{directionImages.map((dir) => (
|
||||||
|
<DirectionImage
|
||||||
|
title={dir.title}
|
||||||
|
description={dir.desctiption}
|
||||||
|
image={dir.image}
|
||||||
|
key={dir.id}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DirectionImageContainer;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import PrivacyPolicy from "./PrivacyPolicy";
|
||||||
|
import Tabs from "../Tabs";
|
||||||
|
|
||||||
|
const Footer = () => {
|
||||||
|
return (
|
||||||
|
<footer className="">
|
||||||
|
<Tabs />
|
||||||
|
<div className="w-[1440px] mx-auto flex justify-center py-4 flex-col">
|
||||||
|
<PrivacyPolicy />
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Footer;
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
const FooterSocials = () => {
|
||||||
|
return (
|
||||||
|
<div className="flex gap-2 items-center">
|
||||||
|
<div>
|
||||||
|
<img src="/images/footer-vk.svg" width={30} />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<img src="/images/footer-telegram.png" width={30} />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<img src="/images/footer-facebook.svg" width={11} />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<img src="/images/footer-instagram.svg" width={20} />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<img src="/images/footer-youtube.svg" width={30} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FooterSocials;
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import LogoIcon from "../../icons/LogoIcon";
|
||||||
|
import FooterSocials from "./FooterSocials";
|
||||||
|
|
||||||
|
const PrivacyPolicy = () => {
|
||||||
|
return (
|
||||||
|
<div className="flex justify-between">
|
||||||
|
<div className="flex gap-14">
|
||||||
|
<LogoIcon width="90" height="150" />
|
||||||
|
<div className="text-[#edaedd] text-xs flex items-end leading-5">
|
||||||
|
Политика конфиденциальности <br />
|
||||||
|
copyright © Graff Interactive
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-5 text-white">
|
||||||
|
<div className="text-5xl font-bold">8 (800) 770 00 67</div>
|
||||||
|
<div className="text-2xl">Russia</div>
|
||||||
|
<div className="text-2xl text-[#edaedd]">info@graff.tech</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-5">
|
||||||
|
<FooterSocials />
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<div className="text-[#edaedd]">Разработка сайта:</div>
|
||||||
|
<div className="text-[#edaedd]">ТитанСофт</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PrivacyPolicy;
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import LogoIcon from "../../icons/LogoIcon";
|
||||||
|
import SocialLinks from "./SocialLinks";
|
||||||
|
import LanguageSwitcher from "./LanguageSwitcher";
|
||||||
|
import Tabs from "../Tabs";
|
||||||
|
|
||||||
|
const Header = (): JSX.Element => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<header className="px-10 flex justify-between text-[#edaedd] text-lg font-semibold py-12">
|
||||||
|
<div className="w-1/5">
|
||||||
|
<LogoIcon />
|
||||||
|
</div>
|
||||||
|
<div className="3/5">
|
||||||
|
<Tabs isHeader />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex gap-[35px] w-1/5 justify-end">
|
||||||
|
<SocialLinks />
|
||||||
|
<LanguageSwitcher />
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Header;
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
const languages: Language[] = ["Ru", "Eng"];
|
||||||
|
|
||||||
|
type Language = "Ru" | "Eng";
|
||||||
|
|
||||||
|
const LanguageSwitcher = () => {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
const [language, setLanguage] = useState<Language>("Ru");
|
||||||
|
|
||||||
|
const onLangClick = (lang: Language) => {
|
||||||
|
return () => setLanguage(lang);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex gap-[20px] px-[10px]">
|
||||||
|
{languages.map((lang) => (
|
||||||
|
<button
|
||||||
|
onClick={onLangClick(lang)}
|
||||||
|
key={lang}
|
||||||
|
className="h-fit my-auto "
|
||||||
|
>
|
||||||
|
{lang}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LanguageSwitcher;
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import VkIcon from "../../icons/VkIcon";
|
||||||
|
import FacebookIcon from "../../icons/FacebookIcon";
|
||||||
|
import InstagramIcon from "../../icons/InstagramIcon";
|
||||||
|
import YoutubeIcon from "../../icons/YoutubeIcon";
|
||||||
|
|
||||||
|
const SocialLinks = () => {
|
||||||
|
return (
|
||||||
|
<div className="flex gap-[10px] my-auto">
|
||||||
|
<FacebookIcon />
|
||||||
|
<VkIcon />
|
||||||
|
<InstagramIcon />
|
||||||
|
<YoutubeIcon />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SocialLinks;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
type HeaderTitleProps = {
|
||||||
|
title: string;
|
||||||
|
description?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const HeaderTitle = ({ title, description }: HeaderTitleProps) => {
|
||||||
|
return (
|
||||||
|
<div className="text-white mx-auto w-[1440px] flex flex-col pb-8 gap-8">
|
||||||
|
<h2 className="text-6xl font-bold">{title}</h2>
|
||||||
|
<p className="w-[39%]">{description}</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default HeaderTitle;
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
const AboutUs = () => {
|
||||||
|
return (
|
||||||
|
<section className="flex flex-col w-[1440px] mx-auto pb-20">
|
||||||
|
<div className="text-white flex justify-center py-40">
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<h2 className="font-semibold text-white text-7xl pb-10">
|
||||||
|
К нам приходят
|
||||||
|
</h2>
|
||||||
|
<p className="text-wrap w-full text-2xl">
|
||||||
|
Когда нужно продать то, что еще не построено, презентовать то, что
|
||||||
|
еще не создано, разработать технологичные и эффективные визуальные
|
||||||
|
решения для продвижения бизнеса.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<img
|
||||||
|
className="w-full"
|
||||||
|
src="https://thumb.tildacdn.com/tild3666-3766-4530-a263-356432653536/-/resize/820x/-/format/webp/A81I0037_2.jpg"
|
||||||
|
alt="img"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<ul className="grid grid-cols-2 text-white text-[18px] gap-10">
|
||||||
|
<li className="flex flex-row items-center gap-5 ">
|
||||||
|
<div>
|
||||||
|
<img
|
||||||
|
className="w-[88px] max-w-none"
|
||||||
|
src="https://thumb.tildacdn.com/tild6538-3462-4634-b139-386636633133/-/resize/108x/-/format/webp/Group_50.png"
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Собственный штат разработчиков и полный цикл производства продукта
|
||||||
|
внутри компании.
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li className="flex flex-row items-center gap-5">
|
||||||
|
<div>
|
||||||
|
<img
|
||||||
|
className="w-[88px] max-w-none"
|
||||||
|
src="https://thumb.tildacdn.com/tild3863-3662-4136-b363-376264643236/-/resize/108x/-/format/webp/2.png"
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>Умеем работать с удалённым заказчиком.</div>
|
||||||
|
</li>
|
||||||
|
<li className="flex flex-row items-center gap-5">
|
||||||
|
<div>
|
||||||
|
<img
|
||||||
|
className="w-[88px] max-w-none"
|
||||||
|
src="https://thumb.tildacdn.com/tild6337-6133-4233-a334-376437313564/-/resize/108x/-/format/webp/3.png"
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>Работа над международными проектами.</div>
|
||||||
|
</li>
|
||||||
|
<li className="flex flex-row items-center gap-5">
|
||||||
|
<div>
|
||||||
|
<img
|
||||||
|
className="w-[88px] max-w-none"
|
||||||
|
src="https://thumb.tildacdn.com/tild6637-3165-4164-b537-326461633832/-/resize/108x/-/format/webp/14.png"
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>14 лет разрабатываем интерактивный контент.</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AboutUs;
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
const LastProjects = () => {
|
||||||
|
return (
|
||||||
|
<section className="flex flex-col place-items-center mt-10">
|
||||||
|
<h2 className="font-semibold text-white text-7xl py-10">
|
||||||
|
Последние проекты
|
||||||
|
</h2>
|
||||||
|
<div className="flex flex-col gap-16">
|
||||||
|
<div className="flex gap-10 w-full justify-center">
|
||||||
|
<div className="flex flex-col text-white gap-5">
|
||||||
|
<img
|
||||||
|
src="https://thumb.tildacdn.com/tild3662-3166-4165-a533-346530303466/-/resize/570x/-/format/webp/nks.png"
|
||||||
|
className="w-[700px]"
|
||||||
|
/>
|
||||||
|
<button className="text-left text-4xl hover:text-[#E498FF] w-fit">
|
||||||
|
ЖК "Rewolution Towers" НКС <br /> Девелопмент
|
||||||
|
</button>
|
||||||
|
<button className="text-left text-2xl hover:text-[#E498FF]">
|
||||||
|
Интерактивная презентация для застройщика г.
|
||||||
|
<br /> Екатеринбург
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col text-white gap-5">
|
||||||
|
<img
|
||||||
|
src="https://thumb.tildacdn.com/tild3732-3665-4566-b232-343231333038/-/resize/570x/-/format/webp/image_3.png"
|
||||||
|
className="w-[700px]"
|
||||||
|
/>
|
||||||
|
<button className="text-left text-4xl hover:text-[#E498FF] w-fit">
|
||||||
|
ЖК "Графика" Мавис
|
||||||
|
</button>
|
||||||
|
<button className="text-left text-2xl hover:text-[#E498FF]">
|
||||||
|
Интерактивная презентация для жилого комплекса включает
|
||||||
|
<br /> в себя интерактивный макет для сенсорного дисплея и<br />{" "}
|
||||||
|
прогулку по жилому комплексу в шлеме виртуальной
|
||||||
|
<br /> реальности.
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col text-white gap-5">
|
||||||
|
<img
|
||||||
|
src="https://thumb.tildacdn.com/tild6138-3138-4233-b234-636362346132/-/format/webp/image_2.png"
|
||||||
|
alt="img"
|
||||||
|
className="w-[1440px]"
|
||||||
|
/>
|
||||||
|
<button className="text-left text-4xl hover:text-[#E498FF] w-fit">
|
||||||
|
ЖК «Айвазовский» ЭНКО
|
||||||
|
</button>
|
||||||
|
<button className="text-left text-2xl hover:text-[#E498FF] w-fit">
|
||||||
|
Интерактивная презентация для жилого комплекса включает <br />в себя
|
||||||
|
интерактивный макет для сенсорного дисплея и <br />
|
||||||
|
прогулку по жилому комплексу в шлеме виртуальной
|
||||||
|
<br /> реальности.
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<button className="py-5 px-16 bg-[#ce56c2] text-[18px] w-fit m-auto flex items-center rounded-full text-white font-semibold shadow-xl shadow-[rgba(245,101,231,0.4)] hover:bg-[#b82caa] transition-all duration-300">
|
||||||
|
Открыть все работы
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div></div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LastProjects;
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import Question from "./Question";
|
||||||
|
import SubmitApplication from "../SubmitApplication";
|
||||||
|
|
||||||
|
const Feedback = () => {
|
||||||
|
return (
|
||||||
|
<div className="bg-white text-black">
|
||||||
|
<div className="w-[1440px] flex flex-col mx-auto">
|
||||||
|
<section className="w-full px-48 pt-16 ">
|
||||||
|
<h3 className="text-5xl font-bold pb-12">
|
||||||
|
Частые
|
||||||
|
<br /> вопросы
|
||||||
|
</h3>
|
||||||
|
<ul className="border-t">
|
||||||
|
<Question
|
||||||
|
title="Сколько времени разарбатывается проект?"
|
||||||
|
description="Трудозатраты на разработку проекта рассчитываются индивидуально, в зависимости от сложности моделирования и функционала будущего приложения. В среднем разработка проекта занимает от 3 до 6 месяцев."
|
||||||
|
/>
|
||||||
|
<Question
|
||||||
|
title="Как рассчитывается стоимость проекта?"
|
||||||
|
description="Расчет коммерческого предложения производится индивидуально. Все зависит от объемов работы."
|
||||||
|
/>
|
||||||
|
<Question
|
||||||
|
title="Можно ли совместить несколько технологий в одном проекте?"
|
||||||
|
description="Конечно можно! Многие наши проекты совмещают в себе несколько технологий. С примерами вы можете ознакомиться в разделе Проекты."
|
||||||
|
/>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
<SubmitApplication title="Начать проект просто" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Feedback;
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
import CrossCircleIcon from "../../icons/CrossCircleIcon";
|
||||||
|
|
||||||
|
type QuestionProps = {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const Question = ({ title, description }: QuestionProps) => {
|
||||||
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
|
const handleOnQuestionClick = () => {
|
||||||
|
setIsOpen((prev) => !prev);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<li
|
||||||
|
className={`group cursor-pointer flex justify-between items-center text-2xl border-b flex-col select-none transition-[height] duration-500 overflow-hidden pb-7 ${
|
||||||
|
isOpen ? "h-40" : "h-24"
|
||||||
|
}`}
|
||||||
|
onClick={handleOnQuestionClick}
|
||||||
|
>
|
||||||
|
<div className="flex w-full justify-between py-7">
|
||||||
|
<div>{title}</div>
|
||||||
|
<CrossCircleIcon isOpen={isOpen} />
|
||||||
|
</div>
|
||||||
|
<div className="text-base mr-auto">{description}</div>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Question;
|
||||||
@@ -0,0 +1,207 @@
|
|||||||
|
import LongArrowIcon from "../../icons/LongArrowIcon";
|
||||||
|
import ShadowIcon from "../../icons/ShadowIcon";
|
||||||
|
|
||||||
|
const images = [
|
||||||
|
{ id: "services-2", url: "/images/services-2.png" },
|
||||||
|
{ id: "services-3", url: "/images/services-3.png" },
|
||||||
|
{ id: "services-4", url: "/images/services-4.png" },
|
||||||
|
{ id: "services-5", url: "/images/services-5.png" },
|
||||||
|
{ id: "services-6", url: "/images/services-6.png" },
|
||||||
|
{ id: "services-7", url: "/images/services-7.png" },
|
||||||
|
{ id: "services-8", url: "/images/services-8.png" },
|
||||||
|
{ id: "services-9", url: "/images/services-9.png" },
|
||||||
|
{ id: "services-10", url: "/images/services-10.png" },
|
||||||
|
{ id: "services-11", url: "/images/services-11.png" },
|
||||||
|
{ id: "services-1", url: "/images/services-1.png" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const Services = () => {
|
||||||
|
const handleOnMouseEnter = (id: string) => {
|
||||||
|
return () => {
|
||||||
|
const image = document.getElementById(`services-${id}`);
|
||||||
|
if (image) {
|
||||||
|
image.style.opacity = "100%";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOnMouseLeave = (id: string) => {
|
||||||
|
return () => {
|
||||||
|
const image = document.getElementById(`services-${id}`);
|
||||||
|
if (image) {
|
||||||
|
image.style.opacity = "0%";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="flex py-16">
|
||||||
|
<div className="grid grid-cols-3 border-white text-white justify-center mx-auto text-2xl uppercase gap-28">
|
||||||
|
<div>
|
||||||
|
<div className="font-bold flex gap-16">
|
||||||
|
Что мы делаем
|
||||||
|
<LongArrowIcon />
|
||||||
|
</div>
|
||||||
|
<div className="h-full relative px-12">
|
||||||
|
{images.map((img) => (
|
||||||
|
<img
|
||||||
|
id={img.id}
|
||||||
|
src={img.url}
|
||||||
|
key={img.id}
|
||||||
|
alt="картинка"
|
||||||
|
className="absolute opacity-0 transition-opacity duration-300"
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-5">
|
||||||
|
<div>По технологиям</div>
|
||||||
|
<button
|
||||||
|
className="text-left relative"
|
||||||
|
onMouseEnter={handleOnMouseEnter("2")}
|
||||||
|
onMouseLeave={handleOnMouseLeave("2")}
|
||||||
|
>
|
||||||
|
<div className="font-bold hover:text-[#E498FF] transition-all duration-300 w-fit">
|
||||||
|
<ShadowIcon />
|
||||||
|
VR
|
||||||
|
</div>
|
||||||
|
<div className="text-[#bca6ea] text-xl">Виртуальная реальность</div>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="text-left relative"
|
||||||
|
onMouseEnter={handleOnMouseEnter("3")}
|
||||||
|
onMouseLeave={handleOnMouseLeave("3")}
|
||||||
|
>
|
||||||
|
<div className="font-bold hover:text-[#E498FF] transition-all duration-300">
|
||||||
|
<ShadowIcon />
|
||||||
|
AR
|
||||||
|
</div>
|
||||||
|
<div className="text-[#bca6ea] text-xl">Дополненная реальность</div>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="text-left relative"
|
||||||
|
onMouseEnter={handleOnMouseEnter("4")}
|
||||||
|
onMouseLeave={handleOnMouseLeave("4")}
|
||||||
|
>
|
||||||
|
<div className="font-bold hover:text-[#E498FF] transition-all duration-300">
|
||||||
|
<ShadowIcon />
|
||||||
|
TOUCH-SCREEN
|
||||||
|
</div>
|
||||||
|
<div className="text-[#bca6ea] text-xl">
|
||||||
|
3D графика для презентаций
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="text-left relative"
|
||||||
|
onMouseEnter={handleOnMouseEnter("5")}
|
||||||
|
onMouseLeave={handleOnMouseLeave("5")}
|
||||||
|
>
|
||||||
|
<div className="font-bold hover:text-[#E498FF] transition-all duration-300">
|
||||||
|
<ShadowIcon />
|
||||||
|
WEB GL
|
||||||
|
</div>
|
||||||
|
<div className="text-[#bca6ea] text-xl">
|
||||||
|
3D для сайта и мобильных приложений
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="text-left relative"
|
||||||
|
onMouseEnter={handleOnMouseEnter("6")}
|
||||||
|
onMouseLeave={handleOnMouseLeave("6")}
|
||||||
|
>
|
||||||
|
<div className="font-bold hover:text-[#E498FF] transition-all duration-300">
|
||||||
|
<ShadowIcon />
|
||||||
|
KINECT REAL SENSE
|
||||||
|
</div>
|
||||||
|
<div className="text-[#bca6ea] text-xl">
|
||||||
|
Презентации с бесконтактным управлением
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="text-left relative"
|
||||||
|
onMouseEnter={handleOnMouseEnter("7")}
|
||||||
|
onMouseLeave={handleOnMouseLeave("7")}
|
||||||
|
>
|
||||||
|
<div className="font-bold hover:text-[#E498FF] transition-all duration-300">
|
||||||
|
<ShadowIcon />
|
||||||
|
Mobile Apps
|
||||||
|
</div>
|
||||||
|
<div className="text-[#bca6ea] text-xl">
|
||||||
|
Мобильные приложения для бизнеса
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-5">
|
||||||
|
<div>По направлениям</div>
|
||||||
|
<button
|
||||||
|
className="text-left relative"
|
||||||
|
onMouseEnter={handleOnMouseEnter("8")}
|
||||||
|
onMouseLeave={handleOnMouseLeave("8")}
|
||||||
|
>
|
||||||
|
<div className="font-bold hover:text-[#E498FF] transition-all duration-300">
|
||||||
|
<ShadowIcon />
|
||||||
|
НЕДВИЖИМОСТЬ
|
||||||
|
</div>
|
||||||
|
<div className="text-[#bca6ea] text-xl">
|
||||||
|
Покажет квартиры на этапе строительства
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="text-left relative"
|
||||||
|
onMouseEnter={handleOnMouseEnter("9")}
|
||||||
|
onMouseLeave={handleOnMouseLeave("9")}
|
||||||
|
>
|
||||||
|
<div className="font-bold hover:text-[#E498FF] transition-all duration-300">
|
||||||
|
<ShadowIcon />
|
||||||
|
ТРЕНАЖЕРЫ
|
||||||
|
</div>
|
||||||
|
<div className="text-[#bca6ea] text-xl">
|
||||||
|
Обучит работе с оборудованием
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="text-left relative"
|
||||||
|
onMouseEnter={handleOnMouseEnter("10")}
|
||||||
|
onMouseLeave={handleOnMouseLeave("10")}
|
||||||
|
>
|
||||||
|
<div className="font-bold hover:text-[#E498FF] transition-all duration-300">
|
||||||
|
<ShadowIcon />
|
||||||
|
ТЕХНИКА
|
||||||
|
</div>
|
||||||
|
<div className="text-[#bca6ea] text-xl">
|
||||||
|
Презентует техники в 3D
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="text-left relative"
|
||||||
|
onMouseEnter={handleOnMouseEnter("11")}
|
||||||
|
onMouseLeave={handleOnMouseLeave("11")}
|
||||||
|
>
|
||||||
|
<div className="font-bold hover:text-[#E498FF] transition-all duration-300">
|
||||||
|
<ShadowIcon />
|
||||||
|
ВЫСТАВКИ
|
||||||
|
</div>
|
||||||
|
<div className="text-[#bca6ea] text-xl">
|
||||||
|
Вовлечет посетителей стенда
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="text-left relative"
|
||||||
|
onMouseEnter={handleOnMouseEnter("1")}
|
||||||
|
onMouseLeave={handleOnMouseLeave("1")}
|
||||||
|
>
|
||||||
|
<div className="font-bold hover:text-[#E498FF] transition-all duration-300">
|
||||||
|
<ShadowIcon />
|
||||||
|
ОНЛАЙН МЕРОПРИЯТИЯ
|
||||||
|
</div>
|
||||||
|
<div className="text-[#bca6ea] text-xl">
|
||||||
|
Презентации с бесконтактным управлением
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Services;
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
import FirstSlide from "./slides/FirstSlide";
|
||||||
|
import SecondSlide from "./slides/SecondSlide";
|
||||||
|
import ThirdSlide from "./slides/ThirdSlide";
|
||||||
|
|
||||||
|
const slides = [
|
||||||
|
{ element: <FirstSlide />, id: 1 },
|
||||||
|
{ element: <SecondSlide />, id: 2 },
|
||||||
|
{ element: <ThirdSlide />, id: 3 },
|
||||||
|
];
|
||||||
|
|
||||||
|
const MainPageSlider = () => {
|
||||||
|
const [offset, setOffset] = useState(-0);
|
||||||
|
|
||||||
|
const handleRightArrowClick = () => {
|
||||||
|
setOffset((currentOffset) => {
|
||||||
|
if (currentOffset === -1 * slides.length + 1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return currentOffset - 1;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleLeftArrowClick = () => {
|
||||||
|
setOffset((currentOffset) => {
|
||||||
|
if (currentOffset === 0) {
|
||||||
|
return -1 * slides.length + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return currentOffset + 1;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<div className="flex h-[calc(100vh-150px)] justify-between w-[calc(100vw-20px)] px-2 pt-20">
|
||||||
|
<div className="w-[calc(100vw-80px)] overflow-hidden">
|
||||||
|
<div
|
||||||
|
className="flex transition-[1.25s]"
|
||||||
|
style={{ transform: `translateX(calc(${offset}*100vw))` }}
|
||||||
|
>
|
||||||
|
{slides.map((slide) => (
|
||||||
|
<div key={slide.id}>{slide.element}</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="">
|
||||||
|
<button
|
||||||
|
onClick={handleLeftArrowClick}
|
||||||
|
className="left-arrow absolute top-[50%] left-4 -translate-y-[50%]"
|
||||||
|
></button>
|
||||||
|
<button
|
||||||
|
className="right-arrow absolute top-[50%] right-4 -translate-y-[50%]"
|
||||||
|
onClick={handleRightArrowClick}
|
||||||
|
></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MainPageSlider;
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
import { useRef } from "react";
|
||||||
|
|
||||||
|
const FirstSlide = () => {
|
||||||
|
const firstImageRef = useRef(null);
|
||||||
|
const secondImageRef = useRef(null);
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// if (firstImageRef.current) {
|
||||||
|
// console.log("imageRef.current", firstImageRef.current);
|
||||||
|
// gsap.fromTo(
|
||||||
|
// firstImageRef.current,
|
||||||
|
// { transform: "scale(2.0)" },
|
||||||
|
// {
|
||||||
|
// transform: "scale(1.6)",
|
||||||
|
// duration: 1.5,
|
||||||
|
// scrollTrigger: {
|
||||||
|
// trigger: firstImageRef.current,
|
||||||
|
// start: "10% bottom",
|
||||||
|
// },
|
||||||
|
// }
|
||||||
|
// );
|
||||||
|
// gsap.fromTo(
|
||||||
|
// secondImageRef.current,
|
||||||
|
// { transform: "scale(2.0)", left: "5%" },
|
||||||
|
// {
|
||||||
|
// transform: "scale(1.6)",
|
||||||
|
// left: "-5%",
|
||||||
|
// duration: 2.2,
|
||||||
|
// scrollTrigger: {
|
||||||
|
// trigger: firstImageRef.current,
|
||||||
|
// start: "10% bottom",
|
||||||
|
// },
|
||||||
|
// }
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// }, []);
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col justify-center align-middle min-w-[100vw] max-w-[100vw]">
|
||||||
|
<p className="font-bold text-8xl text-wrap text-white mx-auto leading-[87px]">
|
||||||
|
Технологии расширенной
|
||||||
|
<br /> реальности для вашего бизнеса
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* <motion.div
|
||||||
|
initial={{ scale: 1.2 }}
|
||||||
|
whileInView={{ scale: 1 }}
|
||||||
|
viewport={{ amount: "all" }}
|
||||||
|
transition={{ duration: 1, ease: [0.58, 0.12, 0.27, 0.98] }}
|
||||||
|
className="flex flex-col gap-1"
|
||||||
|
> */}
|
||||||
|
<img
|
||||||
|
ref={firstImageRef}
|
||||||
|
className="absolute top-[40%]"
|
||||||
|
src="/images/slides/first-slide-2.png"
|
||||||
|
alt="image"
|
||||||
|
/>
|
||||||
|
{/* </motion.div> */}
|
||||||
|
<img
|
||||||
|
ref={secondImageRef}
|
||||||
|
className="absolute top-[40%] scale-150 left-[10%]"
|
||||||
|
src="/images/slides/first-slide-1.png"
|
||||||
|
alt="image"
|
||||||
|
/>
|
||||||
|
<p className="absolute text-white text-4xl top-[85%] left-[57%]">
|
||||||
|
Мы приглашаем вас в мир
|
||||||
|
<br /> удивительного будущего с<br /> технологиями виртуальной <br /> и
|
||||||
|
смешанной реальности
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FirstSlide;
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import { useEffect, useRef } from "react";
|
||||||
|
import { gsap } from "gsap";
|
||||||
|
|
||||||
|
const SecondSlide = () => {
|
||||||
|
const firstImageRef = useRef(null);
|
||||||
|
useEffect(() => {
|
||||||
|
if (firstImageRef.current)
|
||||||
|
gsap.to(firstImageRef.current, {
|
||||||
|
left: "151%",
|
||||||
|
top: "18%",
|
||||||
|
duration: 1.5,
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col justify-center align-middle min-w-[100vw] max-w-[100vw]">
|
||||||
|
<p className="font-bold text-8xl text-wrap text-white w-[1500px] mx-auto leading-[87px]">
|
||||||
|
Решаем задачи с помощью
|
||||||
|
<br /> интерактивных решений
|
||||||
|
</p>
|
||||||
|
<img
|
||||||
|
className="w-[60%] mx-auto"
|
||||||
|
src="/images/slides/second-slide-1.svg"
|
||||||
|
alt="image"
|
||||||
|
/>
|
||||||
|
<img
|
||||||
|
ref={firstImageRef}
|
||||||
|
className="absolute left-[167%] scale-75 top-[2%]"
|
||||||
|
src="/images/slides/second-slide-2.svg"
|
||||||
|
alt="image"
|
||||||
|
/>
|
||||||
|
<p className="absolute text-white text-4xl left-[168%] w-[500px] top-[69%]">
|
||||||
|
Мы презентуем ваш бизнес с помощью инновационных технологий
|
||||||
|
визуализации: 3D, виртуальной(VR) и дополненной (AR)реальности, 360
|
||||||
|
фото, видео, аэросъемки.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SecondSlide;
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import { useRef, useEffect } from "react";
|
||||||
|
import { gsap } from "gsap";
|
||||||
|
|
||||||
|
const ThirdSlide = () => {
|
||||||
|
const firstImageRef = useRef(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (firstImageRef.current)
|
||||||
|
gsap.fromTo(
|
||||||
|
firstImageRef.current,
|
||||||
|
{
|
||||||
|
transform: "scale(1.15)",
|
||||||
|
},
|
||||||
|
{ transform: "scale(1)", duration: 1.5 }
|
||||||
|
);
|
||||||
|
}, []);
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col justify-center align-middle min-w-[100vw] max-w-[100vw] relative">
|
||||||
|
<p className="font-bold text-8xl text-wrap text-white w-[1500px] mx-auto leading-[87px]">
|
||||||
|
Комплексный подход к каждому
|
||||||
|
<br /> проекту
|
||||||
|
</p>
|
||||||
|
<img
|
||||||
|
className="w-[85%] absolute top-[-150%] left-[5%]"
|
||||||
|
src="/images/slides/third-slide-1.svg"
|
||||||
|
alt="image"
|
||||||
|
/>
|
||||||
|
<img
|
||||||
|
ref={firstImageRef}
|
||||||
|
className="absolute top-[-100%] left-[-18%]"
|
||||||
|
src="/images/slides/third-slide-2.svg"
|
||||||
|
alt="image"
|
||||||
|
/>
|
||||||
|
<p className="absolute text-white text-4xl w-[550px] top-[360%] left-[60%]">
|
||||||
|
Анализируем потенциальную аудиторию и исходные данные. Разрабатываем
|
||||||
|
решения от концепции до идеального проекта. Создаем и реализуем ваши
|
||||||
|
самые смелые идеи и задумки.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ThirdSlide;
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
import { useEffect, useRef, useState } from "react";
|
||||||
|
import ScrollToTopIcon from "../icons/ScrollToTopIcon";
|
||||||
|
|
||||||
|
const ScrollToTopButton = () => {
|
||||||
|
const [isVisible, setIsVisible] = useState<boolean>(true);
|
||||||
|
const buttonRef = useRef<HTMLButtonElement>(null);
|
||||||
|
|
||||||
|
const handleOnScroll = () => {
|
||||||
|
if (window.scrollY > 1000) {
|
||||||
|
setIsVisible(true);
|
||||||
|
} else {
|
||||||
|
setIsVisible(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOnClick = () => {
|
||||||
|
window.scrollTo({
|
||||||
|
top: 0,
|
||||||
|
behavior: "smooth",
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
window.addEventListener("scroll", handleOnScroll);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener("scroll", handleOnScroll);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
ref={buttonRef}
|
||||||
|
className={`fixed bottom-5 right-5 ${isVisible ? "" : "hidden"}`}
|
||||||
|
onClick={handleOnClick}
|
||||||
|
>
|
||||||
|
<ScrollToTopIcon />
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// const contentRef = useRef<HTMLDivElement>(null);
|
||||||
|
// const divRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
// function handleClick() {
|
||||||
|
// onClick();
|
||||||
|
|
||||||
|
// setTimeout(() => {
|
||||||
|
// window.scrollTo({
|
||||||
|
// top: divRef.current?.offsetTop,
|
||||||
|
// behavior: "smooth",
|
||||||
|
// });
|
||||||
|
// }, 200);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return (
|
||||||
|
// <div ref={divRef} className="w-[300px] flex flex-col">
|
||||||
|
// <button onClick={handleClick} className="p-4 bg-red-300">
|
||||||
|
// {title}
|
||||||
|
// </button>
|
||||||
|
// <div
|
||||||
|
// ref={contentRef}
|
||||||
|
// className={`bg-blue-300 ${
|
||||||
|
// selected
|
||||||
|
// ? `${contentRef.current} opacity-100 h-[1500px]`
|
||||||
|
// : "h-0 opaci
|
||||||
|
|
||||||
|
export default ScrollToTopButton;
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import ApplicationMessageIcon from "../icons/ApplicationMessageIcon";
|
||||||
|
|
||||||
|
type SubmitApplicationProps = {
|
||||||
|
title: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const SubmitApplication = ({ title }: SubmitApplicationProps) => {
|
||||||
|
return (
|
||||||
|
<div className="bg-white text-black pt-20">
|
||||||
|
<section className="flex flex-col gap-28 mx-auto w-[1440px]">
|
||||||
|
<h2 className="text-7xl mx-auto font-bold text-center w-[95%]">
|
||||||
|
{title}
|
||||||
|
</h2>
|
||||||
|
<div className="flex gap-4">
|
||||||
|
<p className="w-[50%] text-3xl">
|
||||||
|
Оставьте заявку и наш менеджер свяжется с вами. Расскажем о том, как
|
||||||
|
мы сможем решить ваши задачи, дадим оценку стоимости и сроков
|
||||||
|
</p>
|
||||||
|
<div className="flex items-center gap-8 select-none cursor-pointer group ">
|
||||||
|
<div className="text-[#564aa3] group-hover:text-[#E498FF] text-4xl font-bold transition-all duration-300">
|
||||||
|
Оставить заявку
|
||||||
|
</div>
|
||||||
|
<ApplicationMessageIcon />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<img src="/images/graffTechLove.png" alt="graff" />
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SubmitApplication;
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
interface TabProps {
|
||||||
|
value: string;
|
||||||
|
onClick: () => void;
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Tab = ({ value, onClick, className }: TabProps): JSX.Element => {
|
||||||
|
return (
|
||||||
|
<button onClick={onClick} className={`${className}`}>
|
||||||
|
{value}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Tab;
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
import { useNavigate, useLocation } from "react-router-dom";
|
||||||
|
import Tab from "./Tab";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
|
type Tab = {
|
||||||
|
link: string;
|
||||||
|
label: string;
|
||||||
|
id: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
const tabs: Tab[] = [
|
||||||
|
{ link: "/technology", label: "Технологии", id: 1 },
|
||||||
|
{ link: "/directions", label: "Направления", id: 2 },
|
||||||
|
{ link: "/gallery", label: "Проекты", id: 3 },
|
||||||
|
{ link: "/clients", label: "Наши клиекнты", id: 4 },
|
||||||
|
{ link: "/blog", label: "Блог", id: 5 },
|
||||||
|
{ link: "/contacts", label: "Контакты", id: 6 },
|
||||||
|
{ link: "/vacancy", label: "Вакансии", id: 7 },
|
||||||
|
{ link: "/about", label: "О компании", id: 8 },
|
||||||
|
];
|
||||||
|
|
||||||
|
type TabsProps = {
|
||||||
|
isHeader?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
const Tabs = ({ isHeader = false }: TabsProps) => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const location = useLocation();
|
||||||
|
|
||||||
|
const handleOnNavigateClick = (tab: string) => {
|
||||||
|
return () => {
|
||||||
|
navigate(tab);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{isHeader ? (
|
||||||
|
<HeaderTabs
|
||||||
|
handleOnNavigateClick={handleOnNavigateClick}
|
||||||
|
pathname={location.pathname}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<FooterTabs
|
||||||
|
handleOnNavigateClick={handleOnNavigateClick}
|
||||||
|
pathname={location.pathname}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
type HeaderTabsProps = {
|
||||||
|
handleOnNavigateClick: (tab: string) => () => void;
|
||||||
|
pathname: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const HeaderTabs = ({ handleOnNavigateClick, pathname }: HeaderTabsProps) => {
|
||||||
|
const [currentTab, setCurrentTab] = useState<Tab | undefined>(undefined);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setCurrentTab(tabs.find((tab) => tab.link === pathname));
|
||||||
|
}, [pathname]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col self-end gap-2 items-lef w-[1440px] self-right mx-auto justify-center">
|
||||||
|
<nav className="flex gap-[30px]">
|
||||||
|
{tabs.map((tab) => {
|
||||||
|
const isSelected = tab.link === pathname;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tab
|
||||||
|
className={`h-fit mr-auto duration-300 ${
|
||||||
|
isSelected ? "text-[#bdbac4]" : "hover:text-[#fff]"
|
||||||
|
}`}
|
||||||
|
key={tab.id}
|
||||||
|
value={tab.label}
|
||||||
|
onClick={handleOnNavigateClick(tab.link)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</nav>
|
||||||
|
<div
|
||||||
|
className={`text-[16px] font-normal text-[#705a7f] flex gap-2 ${
|
||||||
|
currentTab?.label ? "opacity-100" : "opacity-0"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<div>Главная</div>{" "}
|
||||||
|
<div className="text-[#bcb9c3]">/ {currentTab?.label}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
type FooterTabsProps = {
|
||||||
|
handleOnNavigateClick: (tab: string) => () => void;
|
||||||
|
pathname: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const FooterTabs = ({ handleOnNavigateClick, pathname }: FooterTabsProps) => (
|
||||||
|
<div className="flex self-center text-white font-semibold">
|
||||||
|
<nav className="flex gap-7 items-center mx-auto py-5">
|
||||||
|
{tabs.map((tab) => {
|
||||||
|
const isSelected = tab.link === pathname;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tab
|
||||||
|
key={tab.id}
|
||||||
|
value={tab.label}
|
||||||
|
onClick={handleOnNavigateClick(tab.link)}
|
||||||
|
className={`h-fit m-auto uppercase transition-all duration-300 text-[12px] ${
|
||||||
|
isSelected ? "text-[#8675a8]" : "hover:text-[#E498FF]"
|
||||||
|
}`}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default Tabs;
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
import { useRef } from "react";
|
||||||
|
import { AccordionType } from "../../types";
|
||||||
|
|
||||||
|
type AccordionProps = {
|
||||||
|
accordion: AccordionType;
|
||||||
|
isSelected?: boolean;
|
||||||
|
onClick: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const Accordion = ({
|
||||||
|
accordion,
|
||||||
|
onClick,
|
||||||
|
isSelected = false,
|
||||||
|
}: AccordionProps) => {
|
||||||
|
const { title, description, icon, content } = accordion;
|
||||||
|
const divRef = useRef<HTMLDivElement>(null);
|
||||||
|
const contentRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
const handleOnClick = () => {
|
||||||
|
onClick();
|
||||||
|
|
||||||
|
const timeout = setTimeout(() => {
|
||||||
|
window.scrollTo({
|
||||||
|
top: contentRef.current?.offsetTop,
|
||||||
|
behavior: "smooth",
|
||||||
|
});
|
||||||
|
|
||||||
|
clearTimeout(timeout);
|
||||||
|
}, 500);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={contentRef}
|
||||||
|
className={`overflow-y-hidden ${
|
||||||
|
!isSelected ? "max-h-[165px]" : "max-h-[2000px]"
|
||||||
|
} transition-all duration-500 ease-in-out`}
|
||||||
|
>
|
||||||
|
<div className="flex flex-col border-b border-[#e5e0ee]">
|
||||||
|
<div
|
||||||
|
ref={divRef}
|
||||||
|
className="flex w-[1440px] mx-auto py-8 cursor-pointer select-none justify-between"
|
||||||
|
onClick={handleOnClick}
|
||||||
|
>
|
||||||
|
<div className="flex flex-col gap-3">
|
||||||
|
<div className="font-bold text-6xl">{title}</div>
|
||||||
|
<div className="text-[#bca6ea] text-xl">{description}</div>
|
||||||
|
</div>
|
||||||
|
<img src={icon} alt={title} className="w-20" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="w-[1440px] mx-auto py-20">{content}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Accordion;
|
||||||
|
|
||||||
|
// const contentRef = useRef<HTMLDivElement>(null);
|
||||||
|
// const divRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
// function handleClick() {
|
||||||
|
// onClick();
|
||||||
|
|
||||||
|
// setTimeout(() => {
|
||||||
|
// window.scrollTo({
|
||||||
|
// top: divRef.current?.offsetTop,
|
||||||
|
// behavior: "smooth",
|
||||||
|
// });
|
||||||
|
// }, 200);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return (
|
||||||
|
// <div ref={divRef} className="w-[300px] flex flex-col">
|
||||||
|
// <button onClick={handleClick} className="p-4 bg-red-300">
|
||||||
|
// {title}
|
||||||
|
// </button>
|
||||||
|
// <div
|
||||||
|
// ref={contentRef}
|
||||||
|
// className={`bg-blue-300 ${
|
||||||
|
// selected
|
||||||
|
// ? `${contentRef.current} opacity-100 h-[1500px]`
|
||||||
|
// : "h-0 opaci
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
import Accordion from "./Accordion";
|
||||||
|
import { AccordionType } from "../../types";
|
||||||
|
import { useState } from "react";
|
||||||
|
import VR from "./accordions/VR";
|
||||||
|
import AR from "./accordions/AR";
|
||||||
|
import MobileApp from "./accordions/MobileApp";
|
||||||
|
import TouchScreen from "./accordions/TouchScreen";
|
||||||
|
import WebGl from "./accordions/WebGl";
|
||||||
|
import KinnectRealSense from "./accordions/KinnectRealSense";
|
||||||
|
|
||||||
|
const accordions: AccordionType[] = [
|
||||||
|
{
|
||||||
|
title: "VR",
|
||||||
|
description: "Виртуальная реальность",
|
||||||
|
content: <VR />,
|
||||||
|
icon: "/images/accordion-1.svg",
|
||||||
|
id: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "AR",
|
||||||
|
description: "Дополненная реальность",
|
||||||
|
content: <AR />,
|
||||||
|
icon: "/images/accordion-2.svg",
|
||||||
|
id: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Mobile App",
|
||||||
|
description: "Мобильные приложения",
|
||||||
|
content: <MobileApp />,
|
||||||
|
icon: "/images/accordion-3.svg",
|
||||||
|
id: 3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Touch-screen",
|
||||||
|
description: "3D графика для презентаций",
|
||||||
|
content: <TouchScreen />,
|
||||||
|
icon: "/images/accordion-4.svg",
|
||||||
|
id: 4,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "WEB GL",
|
||||||
|
description: "3D для сайта и мобильных приложений",
|
||||||
|
content: <WebGl />,
|
||||||
|
icon: "/images/accordion-5.svg",
|
||||||
|
id: 5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "KINECT REAL SENSE",
|
||||||
|
description: "Презентации с бесконтактным управлением",
|
||||||
|
content: <KinnectRealSense />,
|
||||||
|
icon: "/images/accordion-6.svg",
|
||||||
|
id: 6,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const AccordionsContainer = () => {
|
||||||
|
const [selected, setSelected] = useState<AccordionType | null>(null);
|
||||||
|
|
||||||
|
const handleOnClick = (accordion: AccordionType) => {
|
||||||
|
if (selected?.id === accordion.id) {
|
||||||
|
setSelected(null);
|
||||||
|
} else {
|
||||||
|
setSelected(accordion);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col bg-white">
|
||||||
|
{accordions.map((acc) => (
|
||||||
|
<Accordion
|
||||||
|
accordion={acc}
|
||||||
|
key={acc.id}
|
||||||
|
isSelected={selected?.id === acc.id}
|
||||||
|
onClick={() => handleOnClick(acc)}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AccordionsContainer;
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { AdvantageType } from "../../types";
|
||||||
|
|
||||||
|
type TechnologyAdvantagesProps = {
|
||||||
|
title: string;
|
||||||
|
advantages: AdvantageType[];
|
||||||
|
};
|
||||||
|
|
||||||
|
const TechnologyAdvantages = ({
|
||||||
|
title,
|
||||||
|
advantages,
|
||||||
|
}: TechnologyAdvantagesProps) => {
|
||||||
|
return (
|
||||||
|
<div className="py-5">
|
||||||
|
<h3 className="text-5xl font-bold pb-10">{title}</h3>
|
||||||
|
<div className="flex gap-10">
|
||||||
|
{advantages.map((adv) => (
|
||||||
|
<div className="w-1/6 flex flex-col gap-5" key={adv.title}>
|
||||||
|
<div className="text-[#edaedd] text-4xl font-bold">{adv.title}</div>
|
||||||
|
<div className="text-2xl">{adv.description}</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TechnologyAdvantages;
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
import TechnologyCategoryIcon from "../../../icons/TechnologyCategoryIcon";
|
||||||
|
import { AdvantageType } from "../../../types";
|
||||||
|
import TechnologyAdvantages from "../TechnologyAdvantages";
|
||||||
|
|
||||||
|
const ADVANTAGES: AdvantageType[] = [
|
||||||
|
{
|
||||||
|
title: "01",
|
||||||
|
description: "AR добавляет элементы цифрового мира в реальный.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "02",
|
||||||
|
description: "Дает возможность кастомизировать и примерить товар",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "03",
|
||||||
|
description: 'AR позволяет "оживить" статичный экспонат',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "04",
|
||||||
|
description: "Повышает эффективность обучения",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "05",
|
||||||
|
description: "Наглядно демонстрирует преимущества и работу продуктов",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const AR = () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className="flex justify-between pb-10">
|
||||||
|
<p className="text-2xl w-[65%]">
|
||||||
|
Сегодня покупатель недвижимости платит не просто за квадратные метры –
|
||||||
|
он платит за уникальные характеристики дома – инфраструктуру, удобный
|
||||||
|
и комфортный двор, дизайн подъездов и холлов, вид из окон. Нужно
|
||||||
|
показать ему все преимущества жилого комплекса на любой стадии
|
||||||
|
строительства еще в офисе продаж.
|
||||||
|
</p>
|
||||||
|
<div className="flex items-center gap-10 ">
|
||||||
|
<div className="w-[173px] h-[173px] rounded-full border-[3px] border-[#f1c7e7] flex justify-center items-center relative">
|
||||||
|
<div className="w-0 h-0 border border-t-0 border-r-[14px] border-b-[22px] border-l-[14px] border-transparent border-b-[#67568a] rotate-90"></div>
|
||||||
|
<div className="w-full h-full rounded-full border-[5px] border-[#f1c7e78c] flex justify-center items-center cursor-pointer animate-ping-3s absolute"></div>
|
||||||
|
</div>
|
||||||
|
<div className="text-3xl">
|
||||||
|
Как это
|
||||||
|
<br /> работает
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<TechnologyAdvantages
|
||||||
|
advantages={ADVANTAGES}
|
||||||
|
title="Что позволяет дополненная реальность"
|
||||||
|
/>
|
||||||
|
<div className="flex gap-8">
|
||||||
|
<div className="w-1/3 relative">
|
||||||
|
<img
|
||||||
|
src="images/accordions/accordion-ar-1.png"
|
||||||
|
alt=""
|
||||||
|
className="w-full"
|
||||||
|
/>
|
||||||
|
<TechnologyCategoryIcon
|
||||||
|
title="AR"
|
||||||
|
className="absolute right-5 top-3"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="w-1/3 relative">
|
||||||
|
<img
|
||||||
|
src="images/accordions/accordion-ar-2.png"
|
||||||
|
alt=""
|
||||||
|
className="w-full"
|
||||||
|
/>
|
||||||
|
<TechnologyCategoryIcon
|
||||||
|
title="AR"
|
||||||
|
className="absolute right-5 top-3"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="w-1/3 relative">
|
||||||
|
<img
|
||||||
|
src="images/accordions/accordion-ar-3.png"
|
||||||
|
alt=""
|
||||||
|
className="w-full rel"
|
||||||
|
/>
|
||||||
|
<TechnologyCategoryIcon
|
||||||
|
title="AR"
|
||||||
|
className="absolute right-5 top-3"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AR;
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
import TechnologyCategoryIcon from "../../../icons/TechnologyCategoryIcon";
|
||||||
|
import { AdvantageType } from "../../../types";
|
||||||
|
import TechnologyAdvantages from "../TechnologyAdvantages";
|
||||||
|
|
||||||
|
const ADVANTAGES: AdvantageType[] = [
|
||||||
|
{
|
||||||
|
title: "01",
|
||||||
|
description:
|
||||||
|
"Помогает реализовать бесконтактный метод взаимодействия с контентом",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "02",
|
||||||
|
description:
|
||||||
|
"Дает возможность работать на малых расстояниях порядка метра и только внутри помещений",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "03",
|
||||||
|
description: "Возможность сканирования предметов",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "04",
|
||||||
|
description: "Приложения интуитивно понятны",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "05",
|
||||||
|
description:
|
||||||
|
"Позволяет манипулировать фото изображениями с использованием данных о глубине",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const KinnectRealSense = () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className="flex justify-between pb-10">
|
||||||
|
<p className="text-2xl w-[65%]">
|
||||||
|
<b>KINECT REAL SENSE Technology</b> - это продукт с технологиями
|
||||||
|
глубины и слежения, предназначенных для того, чтобы дать машинам и
|
||||||
|
устройствам возможности восприятия глубины. Технологии, используются в
|
||||||
|
автономных беспилотных летательных аппаратах, роботах, AR/VR,
|
||||||
|
устройствах умного дома и многих других продуктах широкого рынка.
|
||||||
|
</p>
|
||||||
|
<div className="flex items-center gap-10 ">
|
||||||
|
<div className="w-[173px] h-[173px] rounded-full border-[3px] border-[#f1c7e7] flex justify-center items-center relative">
|
||||||
|
<div className="w-0 h-0 border border-t-0 border-r-[14px] border-b-[22px] border-l-[14px] border-transparent border-b-[#67568a] rotate-90"></div>
|
||||||
|
<div className="w-full h-full rounded-full border-[5px] border-[#f1c7e78c] flex justify-center items-center cursor-pointer animate-ping-3s absolute"></div>
|
||||||
|
</div>
|
||||||
|
<div className="text-3xl">
|
||||||
|
Как это
|
||||||
|
<br /> работает
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<TechnologyAdvantages
|
||||||
|
advantages={ADVANTAGES}
|
||||||
|
title="Что позволяет Touch screen"
|
||||||
|
/>
|
||||||
|
<div className="flex gap-8">
|
||||||
|
<div className="w-1/3 relative">
|
||||||
|
<img
|
||||||
|
src="images/accordions/accordion-kinnectRealSense-1.png"
|
||||||
|
alt=""
|
||||||
|
className="w-full"
|
||||||
|
/>
|
||||||
|
<TechnologyCategoryIcon
|
||||||
|
title="KINNECT REAL SENSE"
|
||||||
|
className="absolute right-5 top-3"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="w-1/3 relative">
|
||||||
|
<img
|
||||||
|
src="images/accordions/accordion-kinnectRealSense-2.png"
|
||||||
|
alt=""
|
||||||
|
className="w-full"
|
||||||
|
/>
|
||||||
|
<TechnologyCategoryIcon
|
||||||
|
title="KINNECT REAL SENSE"
|
||||||
|
className="absolute right-5 top-3"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="w-1/3 relative">
|
||||||
|
<img
|
||||||
|
src="images/accordions/accordion-kinnectRealSense-3.png"
|
||||||
|
alt=""
|
||||||
|
className="w-full rel"
|
||||||
|
/>
|
||||||
|
<TechnologyCategoryIcon
|
||||||
|
title="KINNECT REAL SENSE"
|
||||||
|
className="absolute right-5 top-3"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default KinnectRealSense;
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
import TechnologyCategoryIcon from "../../../icons/TechnologyCategoryIcon";
|
||||||
|
import { AdvantageType } from "../../../types";
|
||||||
|
import TechnologyAdvantages from "../TechnologyAdvantages";
|
||||||
|
|
||||||
|
const ADVANTAGES: AdvantageType[] = [
|
||||||
|
{
|
||||||
|
title: "01",
|
||||||
|
description:
|
||||||
|
"Работать на мобильном устройстве через сенсорный экран или кнопки",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "02",
|
||||||
|
description:
|
||||||
|
"Показать любой вид оборудования, техники и инфраструктурных объектов без физических моделей",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "03",
|
||||||
|
description: "Выполняет функции даже в фоновом режиме",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "04",
|
||||||
|
description: "Хранить персональные данные пользователя",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "05",
|
||||||
|
description: "Возможность задействовать все ресурсы",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const MobileApp = () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className="flex justify-between pb-10">
|
||||||
|
<p className="text-2xl w-[65%]">
|
||||||
|
Показать продукцию потенциальному заказчику, даже на этапе разработки,
|
||||||
|
можно с помощью современных интерактивных технологий — виртуальной и
|
||||||
|
дополненной реальности, мультимедийных сенсорных панелей и мобильных
|
||||||
|
устройств.
|
||||||
|
</p>
|
||||||
|
<div className="flex items-center gap-10 ">
|
||||||
|
<div className="w-[173px] h-[173px] rounded-full border-[3px] border-[#f1c7e7] flex justify-center items-center relative">
|
||||||
|
<div className="w-0 h-0 border border-t-0 border-r-[14px] border-b-[22px] border-l-[14px] border-transparent border-b-[#67568a] rotate-90"></div>
|
||||||
|
<div className="w-full h-full rounded-full border-[5px] border-[#f1c7e78c] flex justify-center items-center cursor-pointer animate-ping-3s absolute"></div>
|
||||||
|
</div>
|
||||||
|
<div className="text-3xl">
|
||||||
|
Как это
|
||||||
|
<br /> работает
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<TechnologyAdvantages
|
||||||
|
advantages={ADVANTAGES}
|
||||||
|
title="Что позволяет Mobile App"
|
||||||
|
/>
|
||||||
|
<div className="flex gap-8">
|
||||||
|
<div className="w-1/3 relative">
|
||||||
|
<img
|
||||||
|
src="images/accordions/accordion-mobileApp-1.png"
|
||||||
|
alt=""
|
||||||
|
className="w-full"
|
||||||
|
/>
|
||||||
|
<TechnologyCategoryIcon
|
||||||
|
title="MobileApp"
|
||||||
|
className="absolute right-5 top-3"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="w-1/3 relative">
|
||||||
|
<img
|
||||||
|
src="images/accordions/accordion-mobileApp-2.png"
|
||||||
|
alt=""
|
||||||
|
className="w-full"
|
||||||
|
/>
|
||||||
|
<TechnologyCategoryIcon
|
||||||
|
title="MobileApp"
|
||||||
|
className="absolute right-5 top-3"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="w-1/3 relative">
|
||||||
|
<img
|
||||||
|
src="images/accordions/accordion-mobileApp-3.png"
|
||||||
|
alt=""
|
||||||
|
className="w-full rel"
|
||||||
|
/>
|
||||||
|
<TechnologyCategoryIcon
|
||||||
|
title="MobileApp"
|
||||||
|
className="absolute right-5 top-3"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MobileApp;
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
import TechnologyCategoryIcon from "../../../icons/TechnologyCategoryIcon";
|
||||||
|
import { AdvantageType } from "../../../types";
|
||||||
|
import TechnologyAdvantages from "../TechnologyAdvantages";
|
||||||
|
|
||||||
|
const ADVANTAGES: AdvantageType[] = [
|
||||||
|
{
|
||||||
|
title: "01",
|
||||||
|
description:
|
||||||
|
"Демонстрирует интерактивные инструкции, навигацию производства",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "02",
|
||||||
|
description:
|
||||||
|
"Применение в сложных промышленных схемах и в качестве оборудования самообслуживания",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "03",
|
||||||
|
description:
|
||||||
|
"Помогает продемонстрировать 3D конфигуратор, систему подбора недвижимости",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "04",
|
||||||
|
description: "Позволяет проводить обучение сотрудников с элементами игры",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "05",
|
||||||
|
description:
|
||||||
|
"Управление с сенсорного экрана, это отличная альтернатива VR или другим контроллерам",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const TouchScreen = () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className="flex justify-between pb-10">
|
||||||
|
<p className="text-2xl w-[65%]">
|
||||||
|
Сенсорные дисплеи и тач-панели - отличное решение для демонстрации
|
||||||
|
всех преимуществ продукта в рамках выставки или фестиваля.
|
||||||
|
<br />
|
||||||
|
<br /> Презентация на сенсорном дисплее обладает преимуществами
|
||||||
|
интуитивного управления мобильного приложения и высоким уровнем
|
||||||
|
графики, недоступным для мобильных устройств.
|
||||||
|
</p>
|
||||||
|
<div className="flex items-center gap-10 ">
|
||||||
|
<div className="w-[173px] h-[173px] rounded-full border-[3px] border-[#f1c7e7] flex justify-center items-center relative">
|
||||||
|
<div className="w-0 h-0 border border-t-0 border-r-[14px] border-b-[22px] border-l-[14px] border-transparent border-b-[#67568a] rotate-90"></div>
|
||||||
|
<div className="w-full h-full rounded-full border-[5px] border-[#f1c7e78c] flex justify-center items-center cursor-pointer animate-ping-3s absolute"></div>
|
||||||
|
</div>
|
||||||
|
<div className="text-3xl">
|
||||||
|
Как это
|
||||||
|
<br /> работает
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<TechnologyAdvantages
|
||||||
|
advantages={ADVANTAGES}
|
||||||
|
title="Что позволяет Touch screen"
|
||||||
|
/>
|
||||||
|
<div className="flex gap-8">
|
||||||
|
<div className="w-1/3 relative">
|
||||||
|
<img
|
||||||
|
src="images/accordions/accordion-touchScreen-1.png"
|
||||||
|
alt=""
|
||||||
|
className="w-full"
|
||||||
|
/>
|
||||||
|
<TechnologyCategoryIcon
|
||||||
|
title="Touch screen"
|
||||||
|
className="absolute right-5 top-3"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="w-1/3 relative">
|
||||||
|
<img
|
||||||
|
src="images/accordions/accordion-touchScreen-2.png"
|
||||||
|
alt=""
|
||||||
|
className="w-full"
|
||||||
|
/>
|
||||||
|
<TechnologyCategoryIcon
|
||||||
|
title="Touch screen"
|
||||||
|
className="absolute right-5 top-3"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="w-1/3 relative">
|
||||||
|
<img
|
||||||
|
src="images/accordions/accordion-touchScreen-3.png"
|
||||||
|
alt=""
|
||||||
|
className="w-full rel"
|
||||||
|
/>
|
||||||
|
<TechnologyCategoryIcon
|
||||||
|
title="Touch screen"
|
||||||
|
className="absolute right-5 top-3"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TouchScreen;
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
import TechnologyCategoryIcon from "../../../icons/TechnologyCategoryIcon";
|
||||||
|
import { AdvantageType } from "../../../types";
|
||||||
|
import TechnologyAdvantages from "../TechnologyAdvantages";
|
||||||
|
|
||||||
|
const ADVANTAGES: AdvantageType[] = [
|
||||||
|
{
|
||||||
|
title: "01",
|
||||||
|
description: "VR позволяет создать быстрый и мощный wow-эффект",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "02",
|
||||||
|
description:
|
||||||
|
"Презентовать товар и услугу, которую в реальности продемонстрировать сложно",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "03",
|
||||||
|
description:
|
||||||
|
"Показать объем пространства, планировки объекта, который может быть еще не построен",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "04",
|
||||||
|
description:
|
||||||
|
"VR в обучении позволяет повысить эффективность подачи материала",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "05",
|
||||||
|
description:
|
||||||
|
"Мы не смотрим на изображение на экране, а непосредственно находимся в виртуальном пространстве",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const VR = () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className="flex justify-between pb-10">
|
||||||
|
<p className="text-2xl w-[65%]">
|
||||||
|
Сегодня покупатель недвижимости платит не просто за квадратные метры –
|
||||||
|
он платит за уникальные характеристики дома – инфраструктуру, удобный
|
||||||
|
и комфортный двор, дизайн подъездов и холлов, вид из окон. Нужно
|
||||||
|
показать ему все преимущества жилого комплекса на любой стадии
|
||||||
|
строительства еще в офисе продаж.
|
||||||
|
</p>
|
||||||
|
<div className="flex items-center gap-10 ">
|
||||||
|
<div className="w-[173px] h-[173px] rounded-full border-[3px] border-[#f1c7e7] flex justify-center items-center relative">
|
||||||
|
<div className="w-0 h-0 border border-t-0 border-r-[14px] border-b-[22px] border-l-[14px] border-transparent border-b-[#67568a] rotate-90"></div>
|
||||||
|
<div className="w-full h-full rounded-full border-[5px] border-[#f1c7e78c] flex justify-center items-center cursor-pointer animate-ping-3s absolute"></div>
|
||||||
|
</div>
|
||||||
|
<div className="text-3xl">
|
||||||
|
Как это
|
||||||
|
<br /> работает
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<TechnologyAdvantages
|
||||||
|
advantages={ADVANTAGES}
|
||||||
|
title="Что позволяет виртуальная реальность"
|
||||||
|
/>
|
||||||
|
<div className="flex gap-8">
|
||||||
|
<div className="w-1/3">
|
||||||
|
<img
|
||||||
|
src="images/accordions/accordion-vr-1.png"
|
||||||
|
alt=""
|
||||||
|
className="w-full"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="w-1/3 relative">
|
||||||
|
<img
|
||||||
|
src="images/accordions/accordion-vr-2.png"
|
||||||
|
alt=""
|
||||||
|
className="w-full"
|
||||||
|
/>
|
||||||
|
<TechnologyCategoryIcon
|
||||||
|
title="VR"
|
||||||
|
className="absolute right-5 top-3"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="w-1/3 relative">
|
||||||
|
<img
|
||||||
|
src="images/accordions/accordion-vr-3.png"
|
||||||
|
alt=""
|
||||||
|
className="w-full rel"
|
||||||
|
/>
|
||||||
|
<TechnologyCategoryIcon
|
||||||
|
title="VR"
|
||||||
|
className="absolute right-5 top-3"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default VR;
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
import TechnologyCategoryIcon from "../../../icons/TechnologyCategoryIcon";
|
||||||
|
import { AdvantageType } from "../../../types";
|
||||||
|
import TechnologyAdvantages from "../TechnologyAdvantages";
|
||||||
|
|
||||||
|
const ADVANTAGES: AdvantageType[] = [
|
||||||
|
{
|
||||||
|
title: "01",
|
||||||
|
description: "Выводить 3D графику на экран",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "02",
|
||||||
|
description: "Конструировать приложения как веб-страницы",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "03",
|
||||||
|
description:
|
||||||
|
"Успешно отображать одну и туже программу на разных устройствах",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "04",
|
||||||
|
description:
|
||||||
|
"Реализовывать более сложные взаимодействия элементов и отображения динамического контента",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "05",
|
||||||
|
description:
|
||||||
|
"Использовать трехмерную графику для визуализации различной информации",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const WebGl = () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className="flex justify-between pb-10">
|
||||||
|
<p className="text-2xl w-[65%]">
|
||||||
|
WebGL — это то, что «оживляет» веб-ресурс, позволяет обойтись без
|
||||||
|
флеш-плеера, так как она выполняется видеокартой и является «частью»
|
||||||
|
элемента «canvas» разметки HTML.
|
||||||
|
</p>
|
||||||
|
<div className="flex items-center gap-10 ">
|
||||||
|
<div className="w-[173px] h-[173px] rounded-full border-[3px] border-[#f1c7e7] flex justify-center items-center relative">
|
||||||
|
<div className="w-0 h-0 border border-t-0 border-r-[14px] border-b-[22px] border-l-[14px] border-transparent border-b-[#67568a] rotate-90"></div>
|
||||||
|
<div className="w-full h-full rounded-full border-[5px] border-[#f1c7e78c] flex justify-center items-center cursor-pointer animate-ping-3s absolute"></div>
|
||||||
|
</div>
|
||||||
|
<div className="text-3xl">
|
||||||
|
Как это
|
||||||
|
<br /> работает
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<TechnologyAdvantages
|
||||||
|
advantages={ADVANTAGES}
|
||||||
|
title="Что позволяет дополненная реальность"
|
||||||
|
/>
|
||||||
|
<div className="flex gap-8">
|
||||||
|
<div className="w-1/3 relative">
|
||||||
|
<img
|
||||||
|
src="images/accordions/accordion-webGl-1.png"
|
||||||
|
alt=""
|
||||||
|
className="w-full"
|
||||||
|
/>
|
||||||
|
<TechnologyCategoryIcon
|
||||||
|
title="Web Gl"
|
||||||
|
className="absolute right-5 top-3"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="w-1/3 relative">
|
||||||
|
<img
|
||||||
|
src="images/accordions/accordion-webGl-2.png"
|
||||||
|
alt=""
|
||||||
|
className="w-full"
|
||||||
|
/>
|
||||||
|
<TechnologyCategoryIcon
|
||||||
|
title="Web Gl"
|
||||||
|
className="absolute right-5 top-3"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="w-1/3 relative">
|
||||||
|
<img
|
||||||
|
src="images/accordions/accordion-webGl-3.png"
|
||||||
|
alt=""
|
||||||
|
className="w-full rel"
|
||||||
|
/>
|
||||||
|
<TechnologyCategoryIcon
|
||||||
|
title="Web Gl"
|
||||||
|
className="absolute right-5 top-3"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default WebGl;
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import Header from "./Header/Header";
|
||||||
|
import Footer from "./Footer/Footer";
|
||||||
|
import { Outlet } from "react-router-dom";
|
||||||
|
import ScrollToTopButton from "./ScrollToTopButton";
|
||||||
|
|
||||||
|
const Wrapper = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Header />
|
||||||
|
<Outlet />
|
||||||
|
<ScrollToTopButton />
|
||||||
|
<Footer />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Wrapper;
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
const ApplicationMessageIcon = () => {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="110"
|
||||||
|
height="110"
|
||||||
|
viewBox="0 0 148 148"
|
||||||
|
fill="none"
|
||||||
|
>
|
||||||
|
{" "}
|
||||||
|
<circle cx="74" cy="74" r="74" fill="url(#paint0_linear)" />{" "}
|
||||||
|
<g filter="url(#filter0_d)">
|
||||||
|
{" "}
|
||||||
|
<path
|
||||||
|
d="M74.3051 40.0041C55.6194 39.7186 40.3684 54.4253 40.0065 73.1097C39.9535 75.8527 40.2276 78.5231 40.7926 81.0841C41.7491 85.4206 42.3178 89.8337 42.3178 94.2747V102.859C42.3178 104.174 43.3838 105.24 44.6991 105.24H53.2832C57.724 105.24 62.1371 105.809 66.4738 106.765C69.0348 107.33 71.7051 107.604 74.448 107.551C93.1321 107.19 107.839 91.939 107.554 73.2536C107.276 55.0153 92.5433 40.2825 74.3051 40.0041Z"
|
||||||
|
fill="url(#paint1_linear)"
|
||||||
|
/>{" "}
|
||||||
|
</g>{" "}
|
||||||
|
<path
|
||||||
|
d="M58.8805 79.7806C61.7702 79.7806 64.1126 77.4381 64.1126 74.5485C64.1126 71.6589 61.7702 69.3164 58.8805 69.3164C55.9909 69.3164 53.6484 71.6589 53.6484 74.5485C53.6484 77.4381 55.9909 79.7806 58.8805 79.7806Z"
|
||||||
|
fill="#7160D0"
|
||||||
|
/>{" "}
|
||||||
|
<path
|
||||||
|
d="M73.6774 79.7806C76.567 79.7806 78.9095 77.4381 78.9095 74.5485C78.9095 71.6589 76.567 69.3164 73.6774 69.3164C70.7878 69.3164 68.4453 71.6589 68.4453 74.5485C68.4453 77.4381 70.7878 79.7806 73.6774 79.7806Z"
|
||||||
|
fill="#7160D0"
|
||||||
|
/>{" "}
|
||||||
|
<path
|
||||||
|
d="M88.4743 79.7806C91.3639 79.7806 93.7064 77.4381 93.7064 74.5485C93.7064 71.6589 91.3639 69.3164 88.4743 69.3164C85.5847 69.3164 83.2422 71.6589 83.2422 74.5485C83.2422 77.4381 85.5847 79.7806 88.4743 79.7806Z"
|
||||||
|
fill="#7160D0"
|
||||||
|
/>{" "}
|
||||||
|
<defs>
|
||||||
|
{" "}
|
||||||
|
<filter
|
||||||
|
id="filter0_d"
|
||||||
|
x="28"
|
||||||
|
y="30"
|
||||||
|
width="91.558"
|
||||||
|
height="91.5578"
|
||||||
|
filterUnits="userSpaceOnUse"
|
||||||
|
colorInterpolationFilters="sRGB"
|
||||||
|
>
|
||||||
|
{" "}
|
||||||
|
<feFlood floodOpacity="0" result="BackgroundImageFix" />{" "}
|
||||||
|
<feColorMatrix
|
||||||
|
in="SourceAlpha"
|
||||||
|
type="matrix"
|
||||||
|
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
||||||
|
/>{" "}
|
||||||
|
<feOffset dy="2" /> <feGaussianBlur stdDeviation="6" />{" "}
|
||||||
|
<feColorMatrix
|
||||||
|
type="matrix"
|
||||||
|
values="0 0 0 0 0.335497 0 0 0 0 0.192014 0 0 0 0 0.658333 0 0 0 0.8 0"
|
||||||
|
/>{" "}
|
||||||
|
<feBlend
|
||||||
|
mode="normal"
|
||||||
|
in2="BackgroundImageFix"
|
||||||
|
result="effect1_dropShadow"
|
||||||
|
/>{" "}
|
||||||
|
<feBlend
|
||||||
|
mode="normal"
|
||||||
|
in="SourceGraphic"
|
||||||
|
in2="effect1_dropShadow"
|
||||||
|
result="shape"
|
||||||
|
/>{" "}
|
||||||
|
</filter>{" "}
|
||||||
|
<linearGradient
|
||||||
|
id="paint0_linear"
|
||||||
|
x1="118.5"
|
||||||
|
y1="4.00001"
|
||||||
|
x2="40"
|
||||||
|
y2="148"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
>
|
||||||
|
{" "}
|
||||||
|
<stop offset="0.401825" stopColor="#564AA3" />{" "}
|
||||||
|
<stop offset="0.987093" stopColor="#AA5CE8" />{" "}
|
||||||
|
</linearGradient>{" "}
|
||||||
|
<linearGradient
|
||||||
|
id="paint1_linear"
|
||||||
|
x1="99.5"
|
||||||
|
y1="22"
|
||||||
|
x2="61.5"
|
||||||
|
y2="121"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
>
|
||||||
|
{" "}
|
||||||
|
<stop offset="0.447243" stopColor="white" />{" "}
|
||||||
|
<stop offset="0.754958" stopColor="#DCD6FF" />{" "}
|
||||||
|
<stop offset="1" stopColor="white" />{" "}
|
||||||
|
</linearGradient>{" "}
|
||||||
|
</defs>{" "}
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ApplicationMessageIcon;
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
const ArrowIcon = () => {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
role="presentation"
|
||||||
|
width="14"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 14 24"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M1 0.994385L12 11.9944L1 22.9944"
|
||||||
|
stroke="white"
|
||||||
|
stroke-width="2"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ArrowIcon;
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
type CrossCircleIconProps = {
|
||||||
|
isOpen: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
const CrossCircleIcon = ({ isOpen }: CrossCircleIconProps) => {
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
className={`bg-[#d2c3ee] text-white w-10 h-10 flex rounded-full items-center justify-center stroke-white group-hover:stroke-black group-hover:bg-[#eee] ${
|
||||||
|
isOpen ? "rotate-45" : "rotate-0"
|
||||||
|
} transition-all duration-500`}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
role="presentation"
|
||||||
|
focusable="false"
|
||||||
|
width="24px"
|
||||||
|
height="24px"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<g
|
||||||
|
stroke-width="1px"
|
||||||
|
fill="none"
|
||||||
|
fill-rule="evenodd"
|
||||||
|
stroke-linecap="square"
|
||||||
|
>
|
||||||
|
<g transform="translate(1.000000, 1.000000)">
|
||||||
|
<path d="M0,11 L22,11"></path>
|
||||||
|
<path d="M11,0 L11,22"></path>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CrossCircleIcon;
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
const FacebookIcon = () => {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
className="t-sociallinks__svg"
|
||||||
|
role="presentation"
|
||||||
|
width="30px"
|
||||||
|
height="30px"
|
||||||
|
viewBox="0 0 100 100"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
clipRule="evenodd"
|
||||||
|
d="M50 100c27.6142 0 50-22.3858 50-50S77.6142 0 50 0 0 22.3858 0 50s22.3858 50 50 50Zm3.431-73.9854c-2.5161.0701-5.171.6758-7.0464 2.4577-1.5488 1.4326-2.329 3.5177-2.5044 5.602-.0534 1.4908-.0458 2.9855-.0382 4.4796.0058 1.1205.0115 2.2407-.0085 3.3587-.6888.005-1.3797.0036-2.0709.0021-.9218-.0019-1.8441-.0038-2.7626.0096 0 .8921.0013 1.7855.0026 2.6797.0026 1.791.0052 3.5853-.0026 5.3799.9185.0134 1.8409.0115 2.7627.0096.6912-.0015 1.382-.0029 2.0708.0021.0155 3.5565.0127 7.1128.0098 10.669-.0036 4.4452-.0072 8.8903.0252 13.3354 1.8903-.0134 3.7765-.0115 5.6633-.0095 1.4152.0014 2.8306.0028 4.2484-.0022.0117-4.0009.0088-7.9986.0058-11.9963-.0029-3.9979-.0058-7.9957.0059-11.9964.9533-.005 1.9067-.0036 2.86-.0021 1.2713.0019 2.5425.0038 3.8137-.0096.396-2.679.7335-5.3814.9198-8.0947-1.2576-.0058-2.5155-.0058-3.7734-.0058-1.2578 0-2.5157 0-3.7734-.0059 0-.4689-.0007-.9378-.0014-1.4066-.0022-1.4063-.0044-2.8123.0131-4.2188.198-1.0834 1.3158-1.9104 2.3992-1.8403h5.1476c.0117-2.8069.0117-5.602 0-8.4089-.6636 0-1.3273-.0007-1.9911-.0014-1.9915-.0022-3.9832-.0044-5.975.0131Z"
|
||||||
|
fill="#ffffff"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FacebookIcon;
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
const InstagramIcon = () => {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
className="t-sociallinks__svg"
|
||||||
|
role="presentation"
|
||||||
|
width="30px"
|
||||||
|
height="30px"
|
||||||
|
viewBox="0 0 100 100"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
clipRule="evenodd"
|
||||||
|
d="M50 100C77.6142 100 100 77.6142 100 50C100 22.3858 77.6142 0 50 0C22.3858 0 0 22.3858 0 50C0 77.6142 22.3858 100 50 100ZM25 39.3918C25 31.4558 31.4566 25 39.3918 25H60.6082C68.5442 25 75 31.4566 75 39.3918V60.8028C75 68.738 68.5442 75.1946 60.6082 75.1946H39.3918C31.4558 75.1946 25 68.738 25 60.8028V39.3918ZM36.9883 50.0054C36.9883 42.8847 42.8438 37.0922 50.0397 37.0922C57.2356 37.0922 63.0911 42.8847 63.0911 50.0054C63.0911 57.1252 57.2356 62.9177 50.0397 62.9177C42.843 62.9177 36.9883 57.1252 36.9883 50.0054ZM41.7422 50.0054C41.7422 54.5033 45.4641 58.1638 50.0397 58.1638C54.6153 58.1638 58.3372 54.5041 58.3372 50.0054C58.3372 45.5066 54.6145 41.8469 50.0397 41.8469C45.4641 41.8469 41.7422 45.5066 41.7422 50.0054ZM63.3248 39.6355C65.0208 39.6355 66.3956 38.2606 66.3956 36.5646C66.3956 34.8687 65.0208 33.4938 63.3248 33.4938C61.6288 33.4938 60.2539 34.8687 60.2539 36.5646C60.2539 38.2606 61.6288 39.6355 63.3248 39.6355Z"
|
||||||
|
fill="#ffffff"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default InstagramIcon;
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
const LongArrowIcon = () => {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="131"
|
||||||
|
height="8"
|
||||||
|
viewBox="0 0 131 8"
|
||||||
|
fill="none"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M130.354 4.35355C130.549 4.15829 130.549 3.84171 130.354 3.64645L127.172 0.464466C126.976 0.269204 126.66 0.269204 126.464 0.464466C126.269 0.659728 126.269 0.976311 126.464 1.17157L129.293 4L126.464 6.82843C126.269 7.02369 126.269 7.34027 126.464 7.53553C126.66 7.7308 126.976 7.7308 127.172 7.53553L130.354 4.35355ZM0 4.5H130V3.5H0V4.5Z"
|
||||||
|
fill="white"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LongArrowIcon;
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
const ScrollToTopIcon = () => {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
role="presentation"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
x="0px"
|
||||||
|
y="0px"
|
||||||
|
width="50px"
|
||||||
|
height="50px"
|
||||||
|
viewBox="0 0 48 48"
|
||||||
|
enable-background="new 0 0 48 48"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<path
|
||||||
|
style={{ fill: "#ce56c2" }}
|
||||||
|
d="M24,3.125c11.511,0,20.875,9.364,20.875,20.875S35.511,44.875,24,44.875S3.125,35.511,3.125,24S12.489,3.125,24,3.125
|
||||||
|
M24,0.125C10.814,0.125,0.125,10.814,0.125,24S10.814,47.875,24,47.875S47.875,37.186,47.875,24S37.186,0.125,24,0.125L24,0.125z"
|
||||||
|
></path>
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
style={{ fill: "#ce56c2" }}
|
||||||
|
d="M25.5,36.033c0,0.828-0.671,1.5-1.5,1.5s-1.5-0.672-1.5-1.5V16.87l-7.028,7.061c-0.293,0.294-0.678,0.442-1.063,0.442
|
||||||
|
c-0.383,0-0.766-0.146-1.058-0.437c-0.587-0.584-0.589-1.534-0.005-2.121l9.591-9.637c0.281-0.283,0.664-0.442,1.063-0.442
|
||||||
|
c0,0,0.001,0,0.001,0c0.399,0,0.783,0.16,1.063,0.443l9.562,9.637c0.584,0.588,0.58,1.538-0.008,2.122
|
||||||
|
c-0.589,0.583-1.538,0.58-2.121-0.008l-6.994-7.049L25.5,36.033z"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ScrollToTopIcon;
|
||||||