Compare commits
10 Commits
v0.1.0
...
d4965b7aba
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d4965b7aba | ||
|
|
16b4627166 | ||
|
|
181198c0cb | ||
|
|
5ca3fd2613 | ||
|
|
0cd7ec8b22 | ||
|
|
66c1323f00 | ||
| a63304b5e4 | |||
|
|
effd9dae2d | ||
|
|
1787e94f8e | ||
|
|
855ec2f138 |
13
README.md
13
README.md
@@ -45,10 +45,12 @@
|
||||
### MVP1
|
||||
|
||||
**1. Landing**
|
||||
|
||||
- преимущества сервиса
|
||||
- оставить заявку (редирект на Страницу оформления заказа)
|
||||
|
||||
**2. Страница для оформления заказа**
|
||||
|
||||
- форма
|
||||
- номер машины (mask input)
|
||||
- цвет машины
|
||||
@@ -58,10 +60,12 @@
|
||||
- после заполнения редирект на страницу с деталями заказа
|
||||
|
||||
**3. Страница с деталями заказа**
|
||||
|
||||
- описание заказа
|
||||
- детали заказа (id, статус)
|
||||
|
||||
**3. АРМ оператора**
|
||||
|
||||
- список заказов (RUD)
|
||||
- id заказа
|
||||
- статус заказа (готово / не готово)
|
||||
@@ -72,7 +76,6 @@
|
||||
- кнопка "Добавить"
|
||||
- кнопка "Удалить"
|
||||
|
||||
|
||||
### Built With
|
||||
|
||||
[![React][React.js]][React-url]
|
||||
@@ -103,6 +106,14 @@
|
||||
|
||||
<p align="right">(<a href="#readme-top">back to top</a>)</p>
|
||||
|
||||
## Instructions
|
||||
### Stubs types generation
|
||||
1. generate types with json-literal-typer (should be installed globally)
|
||||
```sh
|
||||
npx json-literal-typer -i <path to json> -o <path to output ts-file>
|
||||
```
|
||||
2. export default type from output file
|
||||
|
||||
<!-- PARTICIPANTS -->
|
||||
|
||||
## Participants
|
||||
|
||||
@@ -3,6 +3,7 @@ import pluginJs from "@eslint/js";
|
||||
import tseslint from "typescript-eslint";
|
||||
import pluginReact from "eslint-plugin-react";
|
||||
import stylistic from '@stylistic/eslint-plugin';
|
||||
import pluginImport from 'eslint-plugin-import';
|
||||
|
||||
export default [
|
||||
{ files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"] },
|
||||
@@ -12,7 +13,8 @@ export default [
|
||||
pluginReact.configs.flat.recommended,
|
||||
{
|
||||
plugins: {
|
||||
'@stylistic': stylistic
|
||||
'@stylistic': stylistic,
|
||||
'import': pluginImport,
|
||||
},
|
||||
"rules": {
|
||||
"no-unused-vars": "off",
|
||||
@@ -24,13 +26,20 @@ export default [
|
||||
"caughtErrorsIgnorePattern": "^_"
|
||||
}
|
||||
],
|
||||
"sort-imports": ["error", {
|
||||
"ignoreCase": false,
|
||||
"ignoreDeclarationSort": true,
|
||||
"ignoreMemberSort": true,
|
||||
"memberSyntaxSortOrder": ["none", "all", "multiple", "single"],
|
||||
"allowSeparatedGroups": true
|
||||
}],
|
||||
"sort-imports": ["off"],
|
||||
"import/order": [
|
||||
"error",
|
||||
{
|
||||
"groups": [
|
||||
"builtin",
|
||||
"external",
|
||||
"internal",
|
||||
"parent",
|
||||
["sibling", "index"]
|
||||
],
|
||||
"newlines-between": "always",
|
||||
}
|
||||
],
|
||||
semi: ["error", "always"],
|
||||
'@stylistic/indent': ['error', 2],
|
||||
'react/prop-types': 'off'
|
||||
|
||||
374
package-lock.json
generated
374
package-lock.json
generated
@@ -31,6 +31,7 @@
|
||||
"@stylistic/eslint-plugin": "^2.10.1",
|
||||
"@types/react-dom": "^18.3.1",
|
||||
"eslint": "^9.14.0",
|
||||
"eslint-plugin-import": "^2.31.0",
|
||||
"eslint-plugin-react": "^7.37.2",
|
||||
"globals": "^15.11.0",
|
||||
"prettier": "3.3.3",
|
||||
@@ -3617,6 +3618,13 @@
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@rtsao/scc": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz",
|
||||
"integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@stylistic/eslint-plugin": {
|
||||
"version": "2.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.10.1.tgz",
|
||||
@@ -3700,6 +3708,13 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
||||
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="
|
||||
},
|
||||
"node_modules/@types/json5": {
|
||||
"version": "0.0.29",
|
||||
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
|
||||
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/lodash": {
|
||||
"version": "4.17.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.13.tgz",
|
||||
@@ -3791,16 +3806,17 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser": {
|
||||
"version": "8.12.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.12.2.tgz",
|
||||
"integrity": "sha512-MrvlXNfGPLH3Z+r7Tk+Z5moZAc0dzdVjTgUgwsdGweH7lydysQsnSww3nAmsq8blFuRD5VRlAr9YdEFw3e6PBw==",
|
||||
"version": "8.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.14.0.tgz",
|
||||
"integrity": "sha512-2p82Yn9juUJq0XynBXtFCyrBDb6/dJombnz6vbo6mgQEtWHfvHbQuEa9kAOVIt1c9YFwi7H6WxtPj1kg+80+RA==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "8.12.2",
|
||||
"@typescript-eslint/types": "8.12.2",
|
||||
"@typescript-eslint/typescript-estree": "8.12.2",
|
||||
"@typescript-eslint/visitor-keys": "8.12.2",
|
||||
"@typescript-eslint/scope-manager": "8.14.0",
|
||||
"@typescript-eslint/types": "8.14.0",
|
||||
"@typescript-eslint/typescript-estree": "8.14.0",
|
||||
"@typescript-eslint/visitor-keys": "8.14.0",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"engines": {
|
||||
@@ -3819,6 +3835,117 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "8.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.14.0.tgz",
|
||||
"integrity": "sha512-aBbBrnW9ARIDn92Zbo7rguLnqQ/pOrUguVpbUwzOhkFg2npFDwTgPGqFqE0H5feXcOoJOfX3SxlJaKEVtq54dw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.14.0",
|
||||
"@typescript-eslint/visitor-keys": "8.14.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": {
|
||||
"version": "8.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.14.0.tgz",
|
||||
"integrity": "sha512-yjeB9fnO/opvLJFAsPNYlKPnEM8+z4og09Pk504dkqonT02AyL5Z9SSqlE0XqezS93v6CXn49VHvB2G7XSsl0g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": {
|
||||
"version": "8.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.14.0.tgz",
|
||||
"integrity": "sha512-OPXPLYKGZi9XS/49rdaCbR5j/S14HazviBlUQFvSKz3npr3NikF+mrgK7CFVur6XEt95DZp/cmke9d5i3vtVnQ==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.14.0",
|
||||
"@typescript-eslint/visitor-keys": "8.14.0",
|
||||
"debug": "^4.3.4",
|
||||
"fast-glob": "^3.3.2",
|
||||
"is-glob": "^4.0.3",
|
||||
"minimatch": "^9.0.4",
|
||||
"semver": "^7.6.0",
|
||||
"ts-api-utils": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": {
|
||||
"version": "8.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.14.0.tgz",
|
||||
"integrity": "sha512-vG0XZo8AdTH9OE6VFRwAZldNc7qtJ/6NLGWak+BtENuEUXGZgFpihILPiBvKXvJ2nFu27XNGC6rKiwuaoMbYzQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "8.14.0",
|
||||
"eslint-visitor-keys": "^3.4.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser/node_modules/eslint-visitor-keys": {
|
||||
"version": "3.4.3",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
|
||||
"integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser/node_modules/semver": {
|
||||
"version": "7.6.3",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
|
||||
"integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "8.12.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.12.2.tgz",
|
||||
@@ -4377,6 +4504,27 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/array.prototype.findlastindex": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz",
|
||||
"integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.7",
|
||||
"define-properties": "^1.2.1",
|
||||
"es-abstract": "^1.23.2",
|
||||
"es-errors": "^1.3.0",
|
||||
"es-object-atoms": "^1.0.0",
|
||||
"es-shim-unscopables": "^1.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/array.prototype.flat": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz",
|
||||
@@ -5680,6 +5828,124 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-import-resolver-node": {
|
||||
"version": "0.3.9",
|
||||
"resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz",
|
||||
"integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"debug": "^3.2.7",
|
||||
"is-core-module": "^2.13.0",
|
||||
"resolve": "^1.22.4"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-import-resolver-node/node_modules/debug": {
|
||||
"version": "3.2.7",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
|
||||
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ms": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-module-utils": {
|
||||
"version": "2.12.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz",
|
||||
"integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"debug": "^3.2.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"eslint": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-module-utils/node_modules/debug": {
|
||||
"version": "3.2.7",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
|
||||
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ms": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-import": {
|
||||
"version": "2.31.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz",
|
||||
"integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@rtsao/scc": "^1.1.0",
|
||||
"array-includes": "^3.1.8",
|
||||
"array.prototype.findlastindex": "^1.2.5",
|
||||
"array.prototype.flat": "^1.3.2",
|
||||
"array.prototype.flatmap": "^1.3.2",
|
||||
"debug": "^3.2.7",
|
||||
"doctrine": "^2.1.0",
|
||||
"eslint-import-resolver-node": "^0.3.9",
|
||||
"eslint-module-utils": "^2.12.0",
|
||||
"hasown": "^2.0.2",
|
||||
"is-core-module": "^2.15.1",
|
||||
"is-glob": "^4.0.3",
|
||||
"minimatch": "^3.1.2",
|
||||
"object.fromentries": "^2.0.8",
|
||||
"object.groupby": "^1.0.3",
|
||||
"object.values": "^1.2.0",
|
||||
"semver": "^6.3.1",
|
||||
"string.prototype.trimend": "^1.0.8",
|
||||
"tsconfig-paths": "^3.15.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-import/node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-import/node_modules/debug": {
|
||||
"version": "3.2.7",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
|
||||
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ms": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-import/node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-react": {
|
||||
"version": "7.37.2",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.2.tgz",
|
||||
@@ -6692,20 +6958,6 @@
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/function-bind": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||
@@ -8351,6 +8603,21 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/object.groupby": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz",
|
||||
"integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.7",
|
||||
"define-properties": "^1.2.1",
|
||||
"es-abstract": "^1.23.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/object.values": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz",
|
||||
@@ -10148,6 +10415,16 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/strip-bom": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
|
||||
"integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/strip-json-comments": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
|
||||
@@ -10413,6 +10690,32 @@
|
||||
"typescript": ">=4.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tsconfig-paths": {
|
||||
"version": "3.15.0",
|
||||
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz",
|
||||
"integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/json5": "^0.0.29",
|
||||
"json5": "^1.0.2",
|
||||
"minimist": "^1.2.6",
|
||||
"strip-bom": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tsconfig-paths/node_modules/json5": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
|
||||
"integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"minimist": "^1.2.0"
|
||||
},
|
||||
"bin": {
|
||||
"json5": "lib/cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz",
|
||||
@@ -10572,6 +10875,35 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/typescript-eslint/node_modules/@typescript-eslint/parser": {
|
||||
"version": "8.12.2",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.12.2.tgz",
|
||||
"integrity": "sha512-MrvlXNfGPLH3Z+r7Tk+Z5moZAc0dzdVjTgUgwsdGweH7lydysQsnSww3nAmsq8blFuRD5VRlAr9YdEFw3e6PBw==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "8.12.2",
|
||||
"@typescript-eslint/types": "8.12.2",
|
||||
"@typescript-eslint/typescript-estree": "8.12.2",
|
||||
"@typescript-eslint/visitor-keys": "8.12.2",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "^8.57.0 || ^9.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/uglify-js": {
|
||||
"version": "3.19.3",
|
||||
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz",
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
"@stylistic/eslint-plugin": "^2.10.1",
|
||||
"@types/react-dom": "^18.3.1",
|
||||
"eslint": "^9.14.0",
|
||||
"eslint-plugin-import": "^2.31.0",
|
||||
"eslint-plugin-react": "^7.37.2",
|
||||
"globals": "^15.11.0",
|
||||
"prettier": "3.3.3",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { generatePath } from "react-router-dom";
|
||||
import { getNavigationValue } from "@brojs/cli";
|
||||
|
||||
import { Order } from "../models";
|
||||
|
||||
export const URLs = {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import React from 'react';
|
||||
import { BrowserRouter } from 'react-router-dom';
|
||||
import Routers from './routes';
|
||||
import { ChakraProvider, theme as chakraTheme } from '@chakra-ui/react';
|
||||
|
||||
import Routers from './routes';
|
||||
import ErrorBoundary from './components/ErrorBoundary';
|
||||
|
||||
const App = () => {
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { Box, Flex } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
import { Navigate, Route, Routes } from 'react-router-dom';
|
||||
|
||||
import Sidebar from '../Sidebar';
|
||||
import Orders from '../Orders';
|
||||
import Masters from '../Masters';
|
||||
import React from 'react';
|
||||
import { Navigate, Route, Routes } from 'react-router-dom';
|
||||
|
||||
const LayoutArm = () => (
|
||||
<Flex h='100vh'>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Badge, Link, Stack, Td, Tr } from '@chakra-ui/react';
|
||||
|
||||
import MasterActionsMenu from '../MasterActionsMenu';
|
||||
|
||||
const MasterItem = ({ name, schedule, phone }) => {
|
||||
|
||||
@@ -11,10 +11,11 @@ import {
|
||||
useDisclosure,
|
||||
Flex,
|
||||
} from '@chakra-ui/react';
|
||||
import i18next from 'i18next';
|
||||
|
||||
import { mastersData } from '../../mocks';
|
||||
import MasterItem from '../MasterItem';
|
||||
import MasterDrawer from '../MasterDrawer';
|
||||
import i18next from 'i18next';
|
||||
|
||||
const TABLE_HEADERS = ['name', 'currentJob', 'phone', 'actions'];
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { Box, Heading, Table, Thead, Tbody, Tr, Th } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
import i18next from 'i18next';
|
||||
|
||||
import { ordersData } from '../../mocks';
|
||||
import OrderItem from '../OrderItem';
|
||||
import i18next from 'i18next';
|
||||
const Orders = () => {
|
||||
const TABLE_HEADERS = [
|
||||
'carNumber',
|
||||
|
||||
@@ -1,50 +1,29 @@
|
||||
import React, { FC } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
MdEco,
|
||||
MdMiscellaneousServices,
|
||||
MdPlace,
|
||||
MdHandshake,
|
||||
} from 'react-icons/md';
|
||||
import { Heading, HStack, List, Text, VStack } from '@chakra-ui/react';
|
||||
|
||||
import { CtaButton, PageSection } from '../';
|
||||
|
||||
import { ListItem } from './ListItem';
|
||||
import { BenefitsSectionProps } from './types';
|
||||
import { iconsMap } from './helper';
|
||||
|
||||
export const BenefitsSection: FC = () => {
|
||||
const { t } = useTranslation('~', {
|
||||
keyPrefix: 'dry-wash.landing.benefits-section',
|
||||
});
|
||||
|
||||
const listData = [
|
||||
{
|
||||
Icon: MdEco,
|
||||
children: t('list.0'),
|
||||
},
|
||||
{
|
||||
Icon: MdMiscellaneousServices,
|
||||
children: t('list.1'),
|
||||
},
|
||||
{
|
||||
Icon: MdPlace,
|
||||
children: t('list.2'),
|
||||
},
|
||||
{
|
||||
Icon: MdHandshake,
|
||||
children: t('list.3'),
|
||||
},
|
||||
];
|
||||
export const BenefitsSection: FC<BenefitsSectionProps> = ({
|
||||
data: { heading, description, list } = {},
|
||||
}) => {
|
||||
const { t } = useTranslation('~', { keyPrefix: 'dry-wash.landing' });
|
||||
|
||||
return (
|
||||
<PageSection>
|
||||
<VStack w='full' spacing={2}>
|
||||
<Heading as='h2'>{t('heading')}</Heading>
|
||||
<Text>
|
||||
{t('description')}
|
||||
</Text>
|
||||
<Heading as='h2'>{t(heading)}</Heading>
|
||||
<Text>{t(description)}</Text>
|
||||
</VStack>
|
||||
<List display='flex' flexDirection='column' spacing={3}>
|
||||
{listData.map((props, i) => (
|
||||
<ListItem key={i} {...props} />
|
||||
{list.map((itemKey, i) => (
|
||||
<ListItem key={i} Icon={iconsMap[itemKey]}>
|
||||
{t(itemKey)}
|
||||
</ListItem>
|
||||
))}
|
||||
</List>
|
||||
<HStack w='full' justify='flex-end'>
|
||||
|
||||
13
src/components/landing/BenefitsSection/helper.ts
Normal file
13
src/components/landing/BenefitsSection/helper.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { IconType } from "react-icons";
|
||||
import { MdEco, MdMiscellaneousServices, MdPlace, MdHandshake } from "react-icons/md";
|
||||
|
||||
import { ArrElement } from "../../../lib";
|
||||
|
||||
import { BenefitsList } from "./types";
|
||||
|
||||
export const iconsMap: Record<ArrElement<BenefitsList>, IconType> = {
|
||||
"benefits-section.list.0": MdEco,
|
||||
"benefits-section.list.1": MdMiscellaneousServices,
|
||||
"benefits-section.list.2": MdPlace,
|
||||
"benefits-section.list.3": MdHandshake,
|
||||
};
|
||||
@@ -1 +1,2 @@
|
||||
export type { BenefitsSectionProps } from './types';
|
||||
export { BenefitsSection } from './BenefitsSection';
|
||||
14
src/components/landing/BenefitsSection/types.ts
Normal file
14
src/components/landing/BenefitsSection/types.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
export type BenefitsList = [
|
||||
'benefits-section.list.0',
|
||||
'benefits-section.list.1',
|
||||
'benefits-section.list.2',
|
||||
'benefits-section.list.3',
|
||||
];
|
||||
|
||||
export type BenefitsSectionProps = {
|
||||
data: {
|
||||
heading: 'benefits-section.heading';
|
||||
description: 'benefits-section.description';
|
||||
list: BenefitsList;
|
||||
};
|
||||
};
|
||||
@@ -2,10 +2,11 @@ import React, { FC } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Link as RouterLink } from 'react-router-dom';
|
||||
import { ButtonProps, Button } from '@chakra-ui/react';
|
||||
|
||||
import { URLs } from '../../../__data__/urls';
|
||||
|
||||
export const CtaButton: FC<ButtonProps> = (props) => {
|
||||
const { t } = useTranslation();
|
||||
const { t } = useTranslation('~', { keyPrefix: 'dry-wash.landing' });
|
||||
|
||||
return (
|
||||
<Button
|
||||
@@ -14,7 +15,7 @@ export const CtaButton: FC<ButtonProps> = (props) => {
|
||||
colorScheme='primary'
|
||||
{...props}
|
||||
>
|
||||
{t('dry-wash.landing.make-order-button')}
|
||||
{t('make-order-button')}
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -2,7 +2,9 @@ import React, { FC } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Link, List, ListItem } from '@chakra-ui/react';
|
||||
import { Link as RouterLink } from 'react-router-dom';
|
||||
|
||||
import { SiteLogo, PageSection } from '../';
|
||||
|
||||
import { Copyright } from './Copyright';
|
||||
|
||||
export const Footer: FC = () => {
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
import React, { FC } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Box, Heading, Text, Center, VStack, BoxProps } from '@chakra-ui/react';
|
||||
import { Box, Heading, Text, Center, VStack } from '@chakra-ui/react';
|
||||
|
||||
import { DemoVideoPosterImg } from '../../../assets/images';
|
||||
import { CtaButton, SiteLogo, PageSection } from '../';
|
||||
|
||||
type HeroSectionProps = Pick<BoxProps, 'flexShrink'>;
|
||||
import { HeroSectionProps } from './types';
|
||||
|
||||
export const HeroSection: FC<HeroSectionProps> = ({ flexShrink }) => {
|
||||
const { t } = useTranslation('~', {
|
||||
keyPrefix: 'dry-wash.landing.hero-section',
|
||||
});
|
||||
export const HeroSection: FC<HeroSectionProps> = ({
|
||||
data: { headline, description, video } = {},
|
||||
flexShrink,
|
||||
}) => {
|
||||
const { t } = useTranslation('~', { keyPrefix: 'dry-wash.landing' });
|
||||
|
||||
return (
|
||||
<Box flexShrink={flexShrink} as='header' pos='relative' zIndex={0}>
|
||||
<Box
|
||||
as='video'
|
||||
src={`${__webpack_public_path__}/remote-assets/demo.mp4`}
|
||||
src={`${__webpack_public_path__}/remote-assets/${video}`}
|
||||
poster={DemoVideoPosterImg}
|
||||
autoPlay
|
||||
loop
|
||||
@@ -46,14 +48,14 @@ export const HeroSection: FC<HeroSectionProps> = ({ flexShrink }) => {
|
||||
color='white'
|
||||
__css={{ textWrap: 'balance' }}
|
||||
>
|
||||
{t('headline')}
|
||||
{t(headline)}
|
||||
</Heading>
|
||||
<Text
|
||||
textAlign='center'
|
||||
__css={{ textWrap: 'balance' }}
|
||||
color='white'
|
||||
>
|
||||
{t('description')}
|
||||
{t(description)}
|
||||
</Text>
|
||||
</VStack>
|
||||
<CtaButton size='lg' />
|
||||
|
||||
9
src/components/landing/HeroSection/types.ts
Normal file
9
src/components/landing/HeroSection/types.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { BoxProps } from "@chakra-ui/react";
|
||||
|
||||
export type HeroSectionProps = {
|
||||
data: {
|
||||
headline: 'hero-section.headline';
|
||||
description: 'hero-section.description';
|
||||
video: string;
|
||||
};
|
||||
} & Pick<BoxProps, 'flexShrink'>;
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { FC } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Image } from '@chakra-ui/react';
|
||||
|
||||
import { LogoSvg } from '../../../assets/icons';
|
||||
|
||||
export const SiteLogo: FC = () => {
|
||||
|
||||
@@ -8,8 +8,10 @@ import {
|
||||
Tabs,
|
||||
Text,
|
||||
} from '@chakra-ui/react';
|
||||
|
||||
import { mockReview } from '../../../../mocks/landing';
|
||||
import { Review } from '../../../../models';
|
||||
|
||||
import { ReviewCard } from './ReviewCard';
|
||||
|
||||
const SLIDE_CHANGE_INTERVAL = 5000;
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
import React, { FC } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Heading, HStack } from '@chakra-ui/react';
|
||||
import { CtaButton, PageSection } from '../';
|
||||
import { ReviewsSlider } from './ReviewsSlider';
|
||||
|
||||
export const SocialProofSection: FC = () => {
|
||||
const { t } = useTranslation('~', {
|
||||
keyPrefix: 'dry-wash.landing.social-proof-section',
|
||||
});
|
||||
import { CtaButton, PageSection } from '../';
|
||||
|
||||
import { ReviewsSlider } from './ReviewsSlider';
|
||||
import { SocialProofSectionProps } from './types';
|
||||
|
||||
export const SocialProofSection: FC<SocialProofSectionProps> = ({
|
||||
data: { heading } = {},
|
||||
}) => {
|
||||
const { t } = useTranslation('~', { keyPrefix: 'dry-wash.landing' });
|
||||
|
||||
return (
|
||||
<PageSection>
|
||||
<Heading as='h2'>{t('heading')}</Heading>
|
||||
<Heading as='h2'>{t(heading)}</Heading>
|
||||
<ReviewsSlider />
|
||||
<HStack w='full' justify='flex-end'>
|
||||
<CtaButton />
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
export type { SocialProofSectionProps } from './types';
|
||||
export { SocialProofSection } from './SocialProofSection';
|
||||
5
src/components/landing/SocialProofSection/types.ts
Normal file
5
src/components/landing/SocialProofSection/types.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export type SocialProofSectionProps = {
|
||||
data: {
|
||||
heading: 'social-proof-section.heading';
|
||||
};
|
||||
};
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { FC, PropsWithChildren } from 'react';
|
||||
import { ChakraProvider } from '@chakra-ui/react';
|
||||
|
||||
import { default as landingTheme } from './theme-config';
|
||||
import Fonts from './Fonts';
|
||||
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import { i18nextReactInitConfig } from '@brojs/cli';
|
||||
import App from './app';
|
||||
import i18next from 'i18next';
|
||||
|
||||
import App from './app';
|
||||
|
||||
i18next.t = i18next.t.bind(i18next);
|
||||
const i18nextPromise = i18nextReactInitConfig(i18next);
|
||||
export default () => <App />;
|
||||
|
||||
1
src/lib/index.ts
Normal file
1
src/lib/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './types';
|
||||
41
src/lib/types.ts
Normal file
41
src/lib/types.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* @example type Output = ArrElement<['a', 'b', 'c']>;
|
||||
* // "a" | "b" | "c"
|
||||
*/
|
||||
export type ArrElement<ArrType> = ArrType extends readonly (infer ElementType)[]
|
||||
? ElementType
|
||||
: never;
|
||||
|
||||
/**
|
||||
* @example type Output = Split<'a.b1' | 'a.b2', '.'>;
|
||||
* // ["a", "b1"] | ["a", "b2"]
|
||||
*/
|
||||
type Split<S extends string, D extends string> =
|
||||
S extends `${infer A}${D}${infer B}` ? [A, ...Split<B, D>] : [S];
|
||||
|
||||
/**
|
||||
* @example type Output = NestedObject<["a", "b1"] | ["a", "b2"]>;
|
||||
* // { a: { b1: string; }; } | { a: { b2: string; }; }
|
||||
*/
|
||||
type NestedObject<T extends string[]> =
|
||||
T extends [infer Head, ...infer Tail] ?
|
||||
Head extends string ?
|
||||
{ [key in Head]: NestedObject<Tail extends string[] ? Tail : []> } : never :
|
||||
string;
|
||||
|
||||
/**
|
||||
* @example type Output = UnionToIntersection<{ a: { b1: string; }; } | { a: { b2: string; }; }>;
|
||||
* // { a: { b1: string; }; } & { a: { b2: string; }; }
|
||||
*/
|
||||
type UnionToIntersection<U> =
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
|
||||
|
||||
/**
|
||||
* @example type Output = CreateTree<'a.b1' | 'a.b2', '.'>;
|
||||
* // { a: { b1: string; }; } & { a: { b2: string; }; }
|
||||
*/
|
||||
export type CreateTree<T> =
|
||||
UnionToIntersection<T extends infer U ?
|
||||
U extends string ?
|
||||
NestedObject<Split<U, '.'>> : never : never>;
|
||||
23
src/models/i18next.d.ts
vendored
23
src/models/i18next.d.ts
vendored
@@ -1,24 +1,5 @@
|
||||
import defaultLocale from '../../locales/ru.json';
|
||||
|
||||
type Split<S extends string, D extends string> =
|
||||
S extends `${infer A}${D}${infer B}` ? [A, ...Split<B, D>] : [S];
|
||||
|
||||
type NestedObject<T extends string[]> =
|
||||
T extends [infer Head, ...infer Tail] ?
|
||||
Head extends string ?
|
||||
{ [key in Head]: NestedObject<Tail extends string[] ? Tail : []> } : never :
|
||||
string;
|
||||
|
||||
// Основная утилита для обработки union type
|
||||
type CreateTree<T> =
|
||||
UnionToIntersection<T extends infer U ?
|
||||
U extends string ?
|
||||
NestedObject<Split<U, '.'>> : never : never>;
|
||||
|
||||
// Утилита для объединения типов
|
||||
type UnionToIntersection<U> =
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
|
||||
import { CreateTree } from '../lib';
|
||||
|
||||
type LanguageResource = CreateTree<keyof typeof defaultLocale>;
|
||||
|
||||
@@ -26,6 +7,6 @@ declare module "i18next" {
|
||||
interface CustomTypeOptions {
|
||||
resources: {
|
||||
'~': LanguageResource
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
1
src/models/landing/index.ts
Normal file
1
src/models/landing/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './stubs';
|
||||
1
src/models/landing/stubs/index.ts
Normal file
1
src/models/landing/stubs/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { default as LandingSuccessStub } from './success';
|
||||
27
src/models/landing/stubs/success.ts
Normal file
27
src/models/landing/stubs/success.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
// Generated by json-literal-typer
|
||||
// <-- BEGIN
|
||||
interface HeroXsection {
|
||||
description: "hero-section.description";
|
||||
headline: "hero-section.headline";
|
||||
video: "demo.mp4";
|
||||
}
|
||||
|
||||
interface Sections {
|
||||
description?: "benefits-section.description";
|
||||
heading: "benefits-section.heading" | "social-proof-section.heading";
|
||||
list?: ("benefits-section.list.0" | "benefits-section.list.1" | "benefits-section.list.2" | "benefits-section.list.3")[];
|
||||
type: "benefits-section" | "social-proof-section";
|
||||
}
|
||||
|
||||
interface Body {
|
||||
"hero-section": HeroXsection;
|
||||
sections: Sections[];
|
||||
}
|
||||
|
||||
interface Root {
|
||||
body: Body;
|
||||
success: true;
|
||||
}
|
||||
// END -->
|
||||
|
||||
export default Root;
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import LayoutArm from '../../components/LayoutArm';
|
||||
|
||||
const Page = () => {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { FC } from 'react';
|
||||
import { Container, VStack } from '@chakra-ui/react';
|
||||
|
||||
import {
|
||||
BenefitsSection,
|
||||
Footer,
|
||||
@@ -7,6 +8,12 @@ import {
|
||||
SocialProofSection,
|
||||
} from '../../components/landing';
|
||||
import { LandingThemeProvider } from '../../containers';
|
||||
import { LandingSuccessStub } from '../../models/landing';
|
||||
const landingSuccessStub = import(
|
||||
'../../../stubs/json/landing/success.json'
|
||||
) as unknown as LandingSuccessStub;
|
||||
|
||||
import { isBenefitsSectionData, isSocialProofSectionData } from './types';
|
||||
|
||||
const Page: FC = () => {
|
||||
return (
|
||||
@@ -20,10 +27,19 @@ const Page: FC = () => {
|
||||
centerContent
|
||||
>
|
||||
<VStack w='full' h='full' alignItems='stretch' flexGrow={1}>
|
||||
<HeroSection flexShrink={0} />
|
||||
<HeroSection
|
||||
data={landingSuccessStub['body']['hero-section']}
|
||||
flexShrink={0}
|
||||
/>
|
||||
<VStack as='main' flexGrow={1}>
|
||||
<BenefitsSection />
|
||||
<SocialProofSection />
|
||||
{landingSuccessStub.body.sections.map(({ type, ...data }, i) => {
|
||||
if (isBenefitsSectionData(type, data)) {
|
||||
return <BenefitsSection key={i} data={data} />;
|
||||
}
|
||||
if (isSocialProofSectionData(type, data)) {
|
||||
return <SocialProofSection key={i} data={data} />;
|
||||
}
|
||||
})}
|
||||
</VStack>
|
||||
<Footer />
|
||||
</VStack>
|
||||
|
||||
15
src/pages/landing/types.ts
Normal file
15
src/pages/landing/types.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import LandingSuccess from "../../../stubs/json/landing/success.json";
|
||||
import { BenefitsSectionProps, SocialProofSectionProps } from "../../components/landing";
|
||||
import { ArrElement } from "../../lib";
|
||||
|
||||
type SectionsItemData = ArrElement<typeof LandingSuccess['body']['sections']>;
|
||||
type SectionType = SectionsItemData['type'];
|
||||
type SectionData = Omit<SectionsItemData, 'type'>;
|
||||
|
||||
export const isBenefitsSectionData = (type: SectionType, data: SectionData): data is BenefitsSectionProps['data'] => {
|
||||
return type === 'benefits-section';
|
||||
};
|
||||
|
||||
export const isSocialProofSectionData = (type: SectionType, data: SectionData): data is SocialProofSectionProps['data'] => {
|
||||
return type === 'social-proof-section';
|
||||
};
|
||||
@@ -2,9 +2,10 @@ import React from 'react';
|
||||
import { Text, Button, Center, VStack, Heading } from '@chakra-ui/react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Player } from '@lottiefiles/react-lottie-player';
|
||||
import animate from '../../assets/animation/notFound.json';
|
||||
import i18next from 'i18next';
|
||||
|
||||
import animate from '../../assets/animation/notFound.json';
|
||||
|
||||
const NotFound = () => {
|
||||
return (
|
||||
<Center minH='100vh'>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import { Link as RouterLink } from 'react-router-dom';
|
||||
import { Button } from '@chakra-ui/react';
|
||||
|
||||
import { URLs } from '../../__data__/urls';
|
||||
import { mockOrder } from '../../mocks/landing';
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { lazy, Suspense } from 'react';
|
||||
import { Routes, Route } from 'react-router-dom';
|
||||
|
||||
import { PageSpinner } from './components';
|
||||
import Arm from './pages/arm';
|
||||
import { URLs } from './__data__/urls';
|
||||
|
||||
27
stubs/json/landing/success.json
Normal file
27
stubs/json/landing/success.json
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"success": true,
|
||||
"body": {
|
||||
"hero-section": {
|
||||
"headline": "hero-section.headline",
|
||||
"description": "hero-section.description",
|
||||
"video": "demo.mp4"
|
||||
},
|
||||
"sections": [
|
||||
{
|
||||
"type": "benefits-section",
|
||||
"heading": "benefits-section.heading",
|
||||
"description": "benefits-section.description",
|
||||
"list": [
|
||||
"benefits-section.list.0",
|
||||
"benefits-section.list.1",
|
||||
"benefits-section.list.2",
|
||||
"benefits-section.list.3"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "social-proof-section",
|
||||
"heading": "social-proof-section.heading"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user