This commit is contained in:
Daniil Chemerkin 2024-10-07 23:50:06 +00:00
parent 97d674a0cd
commit e6805ccb21
146 changed files with 5247 additions and 1109 deletions

636
package-lock.json generated
View File

@ -55,7 +55,8 @@
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.3",
"typescript": "^5.0.4",
"vite": "^4.3.8"
"vite": "^4.3.8",
"vite-plugin-svgr": "^4.2.0"
}
},
"node_modules/@ampproject/remapping": {
@ -1474,6 +1475,29 @@
"node": ">=14"
}
},
"node_modules/@rollup/pluginutils": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz",
"integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/estree": "^1.0.0",
"estree-walker": "^2.0.2",
"picomatch": "^2.3.1"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
},
"peerDependenciesMeta": {
"rollup": {
"optional": true
}
}
},
"node_modules/@smakss/react-scroll-direction": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/@smakss/react-scroll-direction/-/react-scroll-direction-4.0.4.tgz",
@ -1503,12 +1527,271 @@
"resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-2.1.9.tgz",
"integrity": "sha512-0RSvCJrzEVx52e8hbSAcZ2vv6OzoFj5fe5XC50GSrcev1Y4t2XDE6W5CIhR/Y6l3CPgO/P4luqoLWuvpUkBhig=="
},
"node_modules/@svgr/babel-plugin-add-jsx-attribute": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz",
"integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=14"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/gregberge"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
"node_modules/@svgr/babel-plugin-remove-jsx-attribute": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz",
"integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=14"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/gregberge"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
"node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz",
"integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=14"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/gregberge"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
"node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz",
"integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=14"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/gregberge"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
"node_modules/@svgr/babel-plugin-svg-dynamic-title": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz",
"integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=14"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/gregberge"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
"node_modules/@svgr/babel-plugin-svg-em-dimensions": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz",
"integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=14"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/gregberge"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
"node_modules/@svgr/babel-plugin-transform-react-native-svg": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz",
"integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=14"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/gregberge"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
"node_modules/@svgr/babel-plugin-transform-svg-component": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz",
"integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/gregberge"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
"node_modules/@svgr/babel-preset": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz",
"integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==",
"dev": true,
"license": "MIT",
"dependencies": {
"@svgr/babel-plugin-add-jsx-attribute": "8.0.0",
"@svgr/babel-plugin-remove-jsx-attribute": "8.0.0",
"@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0",
"@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0",
"@svgr/babel-plugin-svg-dynamic-title": "8.0.0",
"@svgr/babel-plugin-svg-em-dimensions": "8.0.0",
"@svgr/babel-plugin-transform-react-native-svg": "8.1.0",
"@svgr/babel-plugin-transform-svg-component": "8.0.0"
},
"engines": {
"node": ">=14"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/gregberge"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
"node_modules/@svgr/core": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz",
"integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/core": "^7.21.3",
"@svgr/babel-preset": "8.1.0",
"camelcase": "^6.2.0",
"cosmiconfig": "^8.1.3",
"snake-case": "^3.0.4"
},
"engines": {
"node": ">=14"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/gregberge"
}
},
"node_modules/@svgr/core/node_modules/cosmiconfig": {
"version": "8.3.6",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz",
"integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==",
"dev": true,
"license": "MIT",
"dependencies": {
"import-fresh": "^3.3.0",
"js-yaml": "^4.1.0",
"parse-json": "^5.2.0",
"path-type": "^4.0.0"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/d-fischer"
},
"peerDependencies": {
"typescript": ">=4.9.5"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/@svgr/hast-util-to-babel-ast": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz",
"integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/types": "^7.21.3",
"entities": "^4.4.0"
},
"engines": {
"node": ">=14"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/gregberge"
}
},
"node_modules/@svgr/plugin-jsx": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz",
"integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/core": "^7.21.3",
"@svgr/babel-preset": "8.1.0",
"@svgr/hast-util-to-babel-ast": "8.0.0",
"svg-parser": "^2.0.4"
},
"engines": {
"node": ">=14"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/gregberge"
},
"peerDependencies": {
"@svgr/core": "*"
}
},
"node_modules/@types/core-js": {
"version": "2.5.8",
"resolved": "https://registry.npmjs.org/@types/core-js/-/core-js-2.5.8.tgz",
"integrity": "sha512-VgnAj6tIAhJhZdJ8/IpxdatM8G4OD3VWGlp6xIxUGENZlpbob9Ty4VVdC1FIEp0aK6DBscDDjyzy5FB60TuNqg==",
"dev": true
},
"node_modules/@types/estree": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/history": {
"version": "4.7.11",
"resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz",
@ -2049,6 +2332,19 @@
"node": ">=6"
}
},
"node_modules/camelcase": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
"integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001481",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001481.tgz",
@ -2397,6 +2693,24 @@
"url": "https://github.com/fb55/domutils?sponsor=1"
}
},
"node_modules/dot-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz",
"integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==",
"dev": true,
"license": "MIT",
"dependencies": {
"no-case": "^3.0.4",
"tslib": "^2.0.3"
}
},
"node_modules/dot-case/node_modules/tslib": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
"integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==",
"dev": true,
"license": "0BSD"
},
"node_modules/electron-to-chromium": {
"version": "1.4.376",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.376.tgz",
@ -2779,6 +3093,13 @@
"node": ">=4.0"
}
},
"node_modules/estree-walker": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"dev": true,
"license": "MIT"
},
"node_modules/esutils": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
@ -3514,6 +3835,23 @@
"loose-envify": "cli.js"
}
},
"node_modules/lower-case": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
"integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==",
"dev": true,
"license": "MIT",
"dependencies": {
"tslib": "^2.0.3"
}
},
"node_modules/lower-case/node_modules/tslib": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
"integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==",
"dev": true,
"license": "0BSD"
},
"node_modules/lru-cache": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
@ -3737,6 +4075,24 @@
"integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
"dev": true
},
"node_modules/no-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
"integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==",
"dev": true,
"license": "MIT",
"dependencies": {
"lower-case": "^2.0.2",
"tslib": "^2.0.3"
}
},
"node_modules/no-case/node_modules/tslib": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
"integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==",
"dev": true,
"license": "0BSD"
},
"node_modules/node-fetch": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
@ -4576,6 +4932,24 @@
"jquery": ">=1.8.0"
}
},
"node_modules/snake-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz",
"integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==",
"dev": true,
"license": "MIT",
"dependencies": {
"dot-case": "^3.0.4",
"tslib": "^2.0.3"
}
},
"node_modules/snake-case/node_modules/tslib": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
"integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==",
"dev": true,
"license": "0BSD"
},
"node_modules/source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
@ -4687,6 +5061,13 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/svg-parser": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz",
"integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==",
"dev": true,
"license": "MIT"
},
"node_modules/tar": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
@ -4913,6 +5294,21 @@
}
}
},
"node_modules/vite-plugin-svgr": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/vite-plugin-svgr/-/vite-plugin-svgr-4.2.0.tgz",
"integrity": "sha512-SC7+FfVtNQk7So0XMjrrtLAbEC8qjFPifyD7+fs/E6aaNdVde6umlVVh0QuwDLdOMu7vp5RiGFsB70nj5yo0XA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@rollup/pluginutils": "^5.0.5",
"@svgr/core": "^8.1.0",
"@svgr/plugin-jsx": "^8.1.0"
},
"peerDependencies": {
"vite": "^2.6.0 || 3 || 4 || 5"
}
},
"node_modules/void-elements": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz",
@ -5919,6 +6315,17 @@
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.6.2.tgz",
"integrity": "sha512-LzqpSrMK/3JBAVBI9u3NWtOhWNw5AMQfrUFYB0+bDHTSw17z++WJLsPsxAuK+oSddsxk4d7F/JcdDPM1M5YAhA=="
},
"@rollup/pluginutils": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz",
"integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==",
"dev": true,
"requires": {
"@types/estree": "^1.0.0",
"estree-walker": "^2.0.2",
"picomatch": "^2.3.1"
}
},
"@smakss/react-scroll-direction": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/@smakss/react-scroll-direction/-/react-scroll-direction-4.0.4.tgz",
@ -5938,12 +6345,139 @@
"resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-2.1.9.tgz",
"integrity": "sha512-0RSvCJrzEVx52e8hbSAcZ2vv6OzoFj5fe5XC50GSrcev1Y4t2XDE6W5CIhR/Y6l3CPgO/P4luqoLWuvpUkBhig=="
},
"@svgr/babel-plugin-add-jsx-attribute": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz",
"integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==",
"dev": true,
"requires": {}
},
"@svgr/babel-plugin-remove-jsx-attribute": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz",
"integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==",
"dev": true,
"requires": {}
},
"@svgr/babel-plugin-remove-jsx-empty-expression": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz",
"integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==",
"dev": true,
"requires": {}
},
"@svgr/babel-plugin-replace-jsx-attribute-value": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz",
"integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==",
"dev": true,
"requires": {}
},
"@svgr/babel-plugin-svg-dynamic-title": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz",
"integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==",
"dev": true,
"requires": {}
},
"@svgr/babel-plugin-svg-em-dimensions": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz",
"integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==",
"dev": true,
"requires": {}
},
"@svgr/babel-plugin-transform-react-native-svg": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz",
"integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==",
"dev": true,
"requires": {}
},
"@svgr/babel-plugin-transform-svg-component": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz",
"integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==",
"dev": true,
"requires": {}
},
"@svgr/babel-preset": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz",
"integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==",
"dev": true,
"requires": {
"@svgr/babel-plugin-add-jsx-attribute": "8.0.0",
"@svgr/babel-plugin-remove-jsx-attribute": "8.0.0",
"@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0",
"@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0",
"@svgr/babel-plugin-svg-dynamic-title": "8.0.0",
"@svgr/babel-plugin-svg-em-dimensions": "8.0.0",
"@svgr/babel-plugin-transform-react-native-svg": "8.1.0",
"@svgr/babel-plugin-transform-svg-component": "8.0.0"
}
},
"@svgr/core": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz",
"integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==",
"dev": true,
"requires": {
"@babel/core": "^7.21.3",
"@svgr/babel-preset": "8.1.0",
"camelcase": "^6.2.0",
"cosmiconfig": "^8.1.3",
"snake-case": "^3.0.4"
},
"dependencies": {
"cosmiconfig": {
"version": "8.3.6",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz",
"integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==",
"dev": true,
"requires": {
"import-fresh": "^3.3.0",
"js-yaml": "^4.1.0",
"parse-json": "^5.2.0",
"path-type": "^4.0.0"
}
}
}
},
"@svgr/hast-util-to-babel-ast": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz",
"integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==",
"dev": true,
"requires": {
"@babel/types": "^7.21.3",
"entities": "^4.4.0"
}
},
"@svgr/plugin-jsx": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz",
"integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==",
"dev": true,
"requires": {
"@babel/core": "^7.21.3",
"@svgr/babel-preset": "8.1.0",
"@svgr/hast-util-to-babel-ast": "8.0.0",
"svg-parser": "^2.0.4"
}
},
"@types/core-js": {
"version": "2.5.8",
"resolved": "https://registry.npmjs.org/@types/core-js/-/core-js-2.5.8.tgz",
"integrity": "sha512-VgnAj6tIAhJhZdJ8/IpxdatM8G4OD3VWGlp6xIxUGENZlpbob9Ty4VVdC1FIEp0aK6DBscDDjyzy5FB60TuNqg==",
"dev": true
},
"@types/estree": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
"dev": true
},
"@types/history": {
"version": "4.7.11",
"resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz",
@ -6326,6 +6860,12 @@
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="
},
"camelcase": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
"integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
"dev": true
},
"caniuse-lite": {
"version": "1.0.30001481",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001481.tgz",
@ -6574,6 +7114,24 @@
"domhandler": "^5.0.3"
}
},
"dot-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz",
"integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==",
"dev": true,
"requires": {
"no-case": "^3.0.4",
"tslib": "^2.0.3"
},
"dependencies": {
"tslib": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
"integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==",
"dev": true
}
}
},
"electron-to-chromium": {
"version": "1.4.376",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.376.tgz",
@ -6855,6 +7413,12 @@
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
"dev": true
},
"estree-walker": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"dev": true
},
"esutils": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
@ -7415,6 +7979,23 @@
"js-tokens": "^3.0.0 || ^4.0.0"
}
},
"lower-case": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
"integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==",
"dev": true,
"requires": {
"tslib": "^2.0.3"
},
"dependencies": {
"tslib": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
"integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==",
"dev": true
}
}
},
"lru-cache": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
@ -7572,6 +8153,24 @@
"integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
"dev": true
},
"no-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
"integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==",
"dev": true,
"requires": {
"lower-case": "^2.0.2",
"tslib": "^2.0.3"
},
"dependencies": {
"tslib": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
"integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==",
"dev": true
}
}
},
"node-fetch": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
@ -8115,6 +8714,24 @@
"integrity": "sha512-XB9Ftrf2EEKfzoQXt3Nitrt/IPbT+f1fgqBdoxO3W/+JYvtEOW6EgxnWfr9GH6nmULv7Y2tPmEX3koxThVmebA==",
"requires": {}
},
"snake-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz",
"integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==",
"dev": true,
"requires": {
"dot-case": "^3.0.4",
"tslib": "^2.0.3"
},
"dependencies": {
"tslib": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
"integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==",
"dev": true
}
}
},
"source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
@ -8199,6 +8816,12 @@
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="
},
"svg-parser": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz",
"integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==",
"dev": true
},
"tar": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
@ -8335,6 +8958,17 @@
"rollup": "^3.21.0"
}
},
"vite-plugin-svgr": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/vite-plugin-svgr/-/vite-plugin-svgr-4.2.0.tgz",
"integrity": "sha512-SC7+FfVtNQk7So0XMjrrtLAbEC8qjFPifyD7+fs/E6aaNdVde6umlVVh0QuwDLdOMu7vp5RiGFsB70nj5yo0XA==",
"dev": true,
"requires": {
"@rollup/pluginutils": "^5.0.5",
"@svgr/core": "^8.1.0",
"@svgr/plugin-jsx": "^8.1.0"
}
},
"void-elements": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz",

View File

@ -61,6 +61,7 @@
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.3",
"typescript": "^5.0.4",
"vite": "^4.3.8"
"vite": "^4.3.8",
"vite-plugin-svgr": "^4.2.0"
}
}

View File

@ -14,6 +14,7 @@
"privacy_policy": "Datenschutzbestimmungen",
"terms_of_use": "Nutzungsbedingungen",
"policy": "Ich stimme den <privacyPolicy>, den <termsOfUse> sowie der Verwendung von Cookies und Tracking-Technologien, die Ihre Zustimmung erfordern, zu",
"copyright": "@ <year> Wit Apps LLC, California, US",
"profile": "Profil",
"personality_traits": "Persönlichkeitsmerkmale",
"relationship_pattern": "Beziehungsmuster",
@ -622,7 +623,10 @@
"description": "You are missing out on both readings"
}
},
"description": "*Zusatzdienste oder Angebote, die zum Zeitpunkt des Kaufs ausgewählt wurden, werden Ihnen in Rechnung gestellt. Dies ist eine einmalige Zahlung."
"description": "*Zusatzdienste oder Angebote, die zum Zeitpunkt des Kaufs ausgewählt wurden, werden Ihnen in Rechnung gestellt. Dies ist eine einmalige Zahlung.",
"v1": {
"continue": "Weitermachen"
}
},
"/unlimited-readings": {
"personal_affirmations": "persönliche Bestätigungen für jeden Tag",
@ -644,15 +648,17 @@
"30-minute": "30-minütige private Beratung mit einem Experten",
"description": "Sie können eine Vorhersage der Zukunft anfordern, eine Live-Kompatibilitätsanalyse, Liebeskompatibilität usw.",
"one_time_price_offer": "Einmaliges Preisangebot:",
"original_price": "Originalpreis: <oldPrice> Sparen Sie <discount>%",
"original_price": "Originalpreis: <oldPrice> <discount>",
"you_will_be_charged": "*Zusatzdienste oder Angebote, die zum Zeitpunkt des Kaufs ausgewählt wurden, werden Ihnen in Rechnung gestellt.\n Dies ist eine einmalige Zahlung.",
"get_my_consultation": "Meine Beratung erhalten"
"get_my_consultation": "Meine Beratung erhalten",
"discount_save": "Sparen Sie"
},
"/get-information-partner": {
"title": "Wunderbar! Lassen Sie uns herausfinden, was funktioniert (und was nicht) und dann weitermachen.",
"description": "Jetzt benötigen wir einige Informationen über das Profil Ihres Partners, um das astrologische Synastrie-Diagramm zwischen Ihnen und Ihrem Partner zu erstellen."
},
"/additional-discount": {
"header_title": "Sie erhalten einen geheimen Rabatt!",
"title": "Sparen Sie <discount> Rabatt!",
"description1": "<discount> Rabatt auf Ihren personalisierten Plan",
"description2": "<trialDuration>-Tage-Testphase",
@ -660,6 +666,7 @@
"button": "Geheimen Rabatt erhalten!"
},
"/trial-payment-with-discount": {
"header_title": "Sie erhalten einen geheimen Rabatt!",
"title": "Sie erhalten einen geheimen Rabatt!",
"cancel_anytime": "Kein Druck. Jederzeit kündbar.",
"secret_discount_applied": "Geheimer Rabatt angewendet!",
@ -779,7 +786,9 @@
},
"/email": {
"title": "Enter your email to get your advanced Palmistry reading with AURA",
"not_share": "We dont share any personal information."
"not_share": "We dont share any personal information.",
"placeholder_email": "Ihre E-Mail",
"placeholder_name": "Ihr Name"
},
"went_wrong": "Something went wrong.",
"app_number_one": {

View File

@ -14,6 +14,7 @@
"privacy_policy": "Datenschutzerklärung",
"terms_of_use": "Nutzungsbedingungen",
"policy": "Ich stimme der <privacyPolicy>, den <termsOfUse> sowie der Verwendung von Cookies und Tracking-Technologien zu, die deine Zustimmung erfordern.",
"copyright": "@ <year> Wit Apps LLC, California, US",
"profile": "Profil",
"personality_traits": "Persönlichkeitsmerkmale",
"relationship_pattern": "Beziehungsmuster",
@ -625,7 +626,10 @@
"description": "You are missing out on both readings"
}
},
"description": "*Für die zusätzlichen Dienstleistungen oder Angebote, die zum Zeitpunkt des Kaufs ausgewählt werden, werden Gebühren erhoben. Dies ist eine einmalige Zahlung."
"description": "*Für die zusätzlichen Dienstleistungen oder Angebote, die zum Zeitpunkt des Kaufs ausgewählt werden, werden Gebühren erhoben. Dies ist eine einmalige Zahlung.",
"v1": {
"continue": "Weitermachen"
}
},
"/unlimited-readings": {
"personal_affirmations": "persönliche Affirmationen für jeden Tag",
@ -647,15 +651,17 @@
"30-minute": "30-minütige private Beratung mit einem Experten",
"description": "Du kannst um eine Vorhersage der Zukunft, eine Live-Kompatibilitätsanalyse, Liebeskompatibilität usw. bitten",
"one_time_price_offer": "Einmaliges Preisangebot: ",
"original_price": "Originalpreis: <oldPrice> Spare <discount>%",
"original_price": "Originalpreis: <oldPrice> <discount>",
"you_will_be_charged": "*Für die zusätzlichen Dienstleistungen oder Angebote, die zum Zeitpunkt des Kaufs ausgewählt werden, werden Gebühren erhoben.\n Dies ist eine einmalige Zahlung.",
"get_my_consultation": "Meine Beratung erhalten"
"get_my_consultation": "Meine Beratung erhalten",
"discount_save": "Spare"
},
"/get-information-partner": {
"title": "Wunderbar! Lass uns herausfinden, was funktioniert (und was nicht) und darauf aufbauen.",
"description": "Nun benötigen wir einige Informationen über das Profil deines Partners, um den astrologischen Synastrie-Blueprint zwischen dir und deinem Partner zu erstellen."
},
"/additional-discount": {
"header_title": "Du erhältst einen geheimen Rabatt!",
"title": "Spare <discount> Rabatt!",
"description1": "<discount> Rabatt auf deinen personalisierten Plan",
"description2": "<trialDuration>-tägige Testversion",
@ -663,6 +669,7 @@
"button": "Geheimen Rabatt erhalten!"
},
"/trial-payment-with-discount": {
"header_title": "Du erhältst einen geheimen Rabatt!",
"title": "Du erhältst einen geheimen Rabatt!",
"cancel_anytime": "Kein Druck. Jederzeit kündbar.",
"secret_discount_applied": "Geheimer Rabatt angewendet!",
@ -779,7 +786,9 @@
},
"/email": {
"title": "Enter your email to get your advanced Palmistry reading with AURA",
"not_share": "We dont share any personal information."
"not_share": "We dont share any personal information.",
"placeholder_email": "Deine E-Mail-Adresse",
"placeholder_name": "Dein Name"
},
"went_wrong": "Something went wrong.",
"app_number_one": {

View File

@ -31,6 +31,7 @@
"privacy_policy": "Privacy Policy",
"terms_of_use": "Terms of use",
"policy": "I agree to the <privacyPolicy>, <termsOfUse> and to the use of cookies and tracking technologies, that require your consent",
"copyright": "@ <year> Wit Apps LLC, California, US",
"profile": "Profile",
"personality_traits": "Personality traits",
"relationship_pattern": "Relationship Pattern",
@ -628,7 +629,10 @@
"description": "You are missing out on both readings"
}
},
"description": "*You will be charged for the add-on services or offers selected at the time of purchase. This is a non-recuring payment."
"description": "*You will be charged for the add-on services or offers selected at the time of purchase. This is a non-recuring payment.",
"v1": {
"continue": "Continue"
}
},
"/unlimited-readings": {
"personal_affirmations": "personal affirmations for everyday",
@ -650,15 +654,17 @@
"30-minute": "30-minute private consultation with an expert",
"description": "You can ask for prediction of the future, live compatibility analysis; love compatibility etc",
"one_time_price_offer": "One time price offer: ",
"original_price": "Original price: <oldPrice> Save <discount>%",
"original_price": "Original price: <oldPrice> <discount>",
"you_will_be_charged": "*You will be charged for the add-on services or offers selected at the time of purchase.\n This is a non-recuring payment.",
"get_my_consultation": "Get my consultation"
"get_my_consultation": "Get my consultation",
"discount_save": "Save"
},
"/get-information-partner": {
"title": "Wonderful! Let's find out what's working (and what isn't) and go from there.",
"description": "Now we need some information about Your Partner's Profile to create the astrological synastry blueprint between you and your partner."
},
"/additional-discount": {
"header_title": "You get a secret discount!",
"title": "Save <discount> off!",
"description1": "<discount> off on your personalized plan",
"description2": "<trialDuration>-day trial",
@ -666,6 +672,7 @@
"button": "Get secret discount!"
},
"/trial-payment-with-discount": {
"header_title": "You get a secret discount!",
"title": "You get a secret discount!",
"cancel_anytime": "No pressure. Cancel anytime.",
"secret_discount_applied": "Secret discount applied!",
@ -778,7 +785,9 @@
},
"/email": {
"title": "Enter your email to get your advanced Palmistry reading with AURA",
"not_share": "We dont share any personal information."
"not_share": "We dont share any personal information.",
"placeholder_email": "Your email",
"placeholder_name": "Your name"
},
"went_wrong": "Something went wrong.",
"app_number_one": {
@ -883,6 +892,12 @@
"total_due": "Total due today: <trialPrice>",
"app_number_one_color": "25 million people.",
"app_number_one": "The #1 Astrology app trusted by over <color>"
},
"/camera": {
"bad_photo": "Bad photo!",
"try_again": "Try again",
"do_better": "You can do it better",
"next": "Next"
}
}
}

View File

@ -31,6 +31,7 @@
"privacy_policy": "Privacy Policy",
"terms_of_use": "Terms of use",
"policy": "I agree to the <privacyPolicy>, <termsOfUse> and to the use of cookies and tracking technologies, that require your consent",
"copyright": "@ <year> Wit Apps LLC, California, US",
"profile": "Profile",
"personality_traits": "Personality traits",
"relationship_pattern": "Relationship Pattern",
@ -628,7 +629,10 @@
"description": "You are missing out on both readings"
}
},
"description": "*You will be charged for the add-on services or offers selected at the time of purchase. This is a non-recuring payment."
"description": "*You will be charged for the add-on services or offers selected at the time of purchase. This is a non-recuring payment.",
"v1": {
"continue": "Continue"
}
},
"/unlimited-readings": {
"personal_affirmations": "personal affirmations for everyday",
@ -650,15 +654,17 @@
"30-minute": "30-minute private consultation with an expert",
"description": "You can ask for prediction of the future, live compatibility analysis; love compatibility etc",
"one_time_price_offer": "One time price offer: ",
"original_price": "Original price: <oldPrice> Save <discount>%",
"original_price": "Original price: <oldPrice> <discount>",
"you_will_be_charged": "*You will be charged for the add-on services or offers selected at the time of purchase.\n This is a non-recuring payment.",
"get_my_consultation": "Get my consultation"
"get_my_consultation": "Get my consultation",
"discount_save": "Save"
},
"/get-information-partner": {
"title": "Wonderful! Let's find out what's working (and what isn't) and go from there.",
"description": "Now we need some information about Your Partner's Profile to create the astrological synastry blueprint between you and your partner."
},
"/additional-discount": {
"header_title": "You get a secret discount!",
"title": "Save <discount> off!",
"description1": "<discount> off on your personalized plan",
"description2": "<trialDuration>-day trial",
@ -666,6 +672,7 @@
"button": "Get secret discount!"
},
"/trial-payment-with-discount": {
"header_title": "You get a secret discount!",
"title": "You get a secret discount!",
"cancel_anytime": "No pressure. Cancel anytime.",
"secret_discount_applied": "Secret discount applied!",
@ -778,7 +785,9 @@
},
"/email": {
"title": "Enter your email to get your advanced Palmistry reading with AURA",
"not_share": "We dont share any personal information."
"not_share": "We dont share any personal information.",
"placeholder_email": "Your email",
"placeholder_name": "Your name"
},
"went_wrong": "Something went wrong.",
"app_number_one": {
@ -883,6 +892,12 @@
"total_due": "Total due today: <trialPrice>",
"app_number_one_color": "25 million people.",
"app_number_one": "The #1 Astrology app trusted by over <color>"
},
"/camera": {
"bad_photo": "Bad photo!",
"try_again": "Try again",
"do_better": "You can do it better",
"next": "Next"
}
}
}

View File

@ -30,6 +30,7 @@
"privacy_policy": "Política de Privacidad",
"terms_of_use": "Términos de Uso",
"policy": "Estoy de acuerdo con la <privacyPolicy>, los <termsOfUse> y con el uso de cookies y tecnologías de seguimiento que requieren tu consentimiento",
"copyright": "@ <year> Wit Apps LLC, California, US",
"profile": "Perfil",
"personality_traits": "Rasgos de personalidad",
"relationship_pattern": "Patrón de Relación",
@ -625,7 +626,10 @@
"description": "Te estás perdiendo dos lecturas"
}
},
"description": "*Se te cobrará por los servicios o ofertas adicionales seleccionados en el momento de la compra. Este es un pago no recurrente."
"description": "*Se te cobrará por los servicios o ofertas adicionales seleccionados en el momento de la compra. Este es un pago no recurrente.",
"v1": {
"continue": "Continuar"
}
},
"/unlimited-readings": {
"personal_affirmations": "afirmaciones personales para cada día",
@ -647,15 +651,17 @@
"30-minute": "Consulta privada de 30 minutos con un experto",
"description": "Puedes pedir predicciones del futuro, análisis de compatibilidad en vivo; compatibilidad amorosa, etc.",
"one_time_price_offer": "Oferta de precio único:",
"original_price": "Precio original: <oldPrice> Ahorra <discount>%",
"original_price": "Precio original: <oldPrice> <discount>",
"you_will_be_charged": "*Se te cobrará por los servicios adicionales u ofertas seleccionadas en el momento de la compra.\n Este es un pago no recurrente.",
"get_my_consultation": "Obtener mi consulta"
"get_my_consultation": "Obtener mi consulta",
"discount_save": "Ahorra"
},
"/get-information-partner": {
"title": "¡Maravilloso! Descubramos qué está funcionando (y qué no) y avancemos desde allí.",
"description": "Ahora necesitamos alguna información sobre el perfil de tu pareja para crear el plano astrológico de sinastría entre tú y tu pareja."
},
"/additional-discount": {
"header_title": "¡Obtienes un descuento secreto!",
"title": "¡Ahorra <discount> de descuento!",
"description1": "<discount> de descuento en tu plan personalizado",
"description2": "<trialDuration>-días de prueba",
@ -663,6 +669,7 @@
"button": "¡Obtén descuento secreto!"
},
"/trial-payment-with-discount": {
"header_title": "¡Obtienes un descuento secreto!",
"title": "¡Obtienes un descuento secreto!",
"cancel_anytime": "Sin presiones. Cancela en cualquier momento.",
"secret_discount_applied": "¡Descuento secreto aplicado!",
@ -674,216 +681,5 @@
},
"/trial-choice": {
"button": "Elige una cantidad que creas razonable."
},
"assistantId": "asst_rG0fI4HaRFx5AcX6eNPZc6gY",
"v": "v1",
"config": "es.female",
"threadId": "thread_WJOMVhNOTyfYW9eN2kPAE1Fn",
"skip_trial": "Omitir Prueba",
"add_consultant": "Agregar Consultora",
"add_guides": "Agregar Guías",
"/skip-trial": {
"title": "¿No piensas mirar atrás?",
"price_per_week": "<price> por semana",
"billing_period": "Período de facturación",
"billed_amount": "Monto facturado",
"billed_in_4_weeks": "Facturado en 4 semanas",
"start_trial": {
"every_week": "Cada semana",
"start_trial": "Iniciar prueba"
},
"skip_trial": {
"save": "ahorra <save>%",
"every_4_weeks": "Cada 4 semanas",
"skip_trial": "Aceptar oferta y omitir prueba"
}
},
"/add-consultant": {
"caution": "¡Precaución!",
"caution_text": "Para evitar cargos dobles, por favor no cierres la página ni retrocedas.",
"unlock_profound": "Descubre profundos conocimientos sobre tu personalidad, relaciones, trayectoria profesional y momentos cruciales de la vida a través de la astrología, empoderándote para tomar decisiones informadas y lograr una mayor realización.",
"choose_from": "Elige entre más de 80 astrólogos expertos."
},
"palmistry-v1": {
"next": "Siguiente",
"went_wrong": "Algo salió mal.",
"biometric_data": "No se recopilan datos biométricos. Todo el proceso de reconocimiento se realiza en tu dispositivo.",
"/find-your-happiness": {
"title": "Encuentra tu felicidad con predicciones altamente personalizadas.",
"point1": "calificado por usuarios reales",
"point2": "93.4% de precisión",
"point3": "elección de 20 millones de usuarios",
"point4": "puntuación de satisfacción de 4.8",
"text": "Entiende a ti misma y mejora tus relaciones con la astrología"
},
"/gender": {
"title": "¿Cuál es tu género?",
"description": "En la quiromancia, todos somos una mezcla de lo masculino y lo femenino, así que nos ayuda saber el tuyo."
},
"/birthdate": {
"title": "¿Cuál es tu fecha de nacimiento?",
"text": "Tu fecha de nacimiento revela tus rasgos principales de personalidad, necesidades y deseos."
},
"/palms-information": {
"title": "Tus palmas contienen una gran cantidad de información sobre tu destino y personalidad."
},
"/what-aspects": {
"title": "¿En qué aspectos de tu vida deseas obtener información a través de la quiromancia?",
"answer1": "Amor y Relaciones",
"answer2": "Salud y Vitalidad",
"answer3": "Carrera y Destino"
},
"/relationship-status": {
"title": "Para conocerte mejor, por favor dinos tu estado civil",
"answer1": "Soltera",
"answer2": "En una relación"
},
"/element-resonates": {
"title": "¿Con qué elemento resuenas más?",
"answer1": "Agua",
"answer2": "Fuego",
"answer3": "Aire",
"answer4": "Tierra"
},
"/favorite-color": {
"title": "¿Cuál es tu color favorito?",
"answer1": "Azul",
"answer2": "Verde",
"answer3": "Naranja",
"answer4": "Violeta",
"answer5": "Rojo",
"answer6": "Amarillo"
},
"/head-or-heart": {
"title": "¿Tomas decisiones con la cabeza o con el corazón?",
"answer1": "Corazón",
"answer2": "Cabeza",
"answer3": "Ambos"
},
"/relate-following": {
"title": "¿Te identificas con lo siguiente?",
"question1": "Encuentro consuelo y comodidad pasando tiempo sola.",
"question2": "Valoro y disfruto de mi propia compañía.",
"question3": "Prefiero socializar en grupo en lugar de pasar tiempo sola.",
"question4": "La soledad es algo que trato de evitar activamente.",
"question5": "Disfruto de actividades que puedo hacer de manera independiente.",
"strongly_agree": "Totalmente de acuerdo",
"strongly_disagree": "Totalmente en desacuerdo"
},
"/let-scan": {
"title": "Vamos a escanear tus palmas",
"text": "Sigue las instrucciones en pantalla, así podremos analizar las líneas de tu palma y revelar tu futuro y los secretos de tu destino."
},
"/scan-instruction": {
"title": "Toma una foto de tu palma como se indica",
"button": "Tomar una foto ahora"
},
"/email": {
"title": "Ingresa tu correo electrónico para obtener tu lectura avanzada de quiromancia con AURA",
"not_share": "No compartimos ninguna información personal."
},
"app_number_one": {
"text": "La aplicación <color> confiada por más de 25 millones de personas.",
"color": "#1 en Astrología"
},
"/trial-payment": {
"palm_is_ready": {
"title": "Tu lectura de palma <color>",
"title_color": "Está lista",
"description": "“Acabo de recibir los resultados del escaneo de tu palma. ¡Hablemos!”",
"text1": "<color> 6 años en lecturas de quiromancia y guía espiritual.",
"text1_color": "Akho",
"text2": "Elige entre más de 80 lectores de palma y astrólogos."
},
"joined_today": {
"text1": "Chats ilimitados con un lector de palma",
"text2": "<count> personas se unieron hoy"
},
"get_personal_prediction": "Obtén una predicción personalizada",
"how_work": {
"title": "¿Cómo funciona AURA?",
"point1_title": "Envíanos tu escaneo de la palma",
"point1_text": "Analizamos las líneas de tu palma para obtener pistas sobre tu futuro",
"point2_title": "Se genera tu lectura de la palma",
"point2_text": "Uno de nuestros lectores de palma profesionales prepara un informe lleno de pistas sobre tu futuro",
"point3_title": "Empieza tu prueba para recibir tu predicción",
"point3_text": "Una vez que seas miembro de AURA, te enviaremos tu informe de predicción para que puedas empezar a vivir una vida mejor.",
"point4_title": "Habla con un especialista en lectura de palma en cualquier momento",
"point4_text": "Obtén apoyo continuo discutiendo tus lecturas, horóscopos personales y compatibilidades con nuestro equipo de expertos."
},
"money_back_guarantee": {
"title": "Garantía de devolución del 100% del dinero",
"text": "Si no notas ningún progreso después de usar la aplicación durante al menos una semana, estamos listos para hacer un reembolso completo dentro de los 14 días."
},
"begin_trial_now": "Comienza la prueba ahora",
"what_included": {
"title": "¿Qué está incluido?",
"point1": "<bold> lecturas de palma",
"point1_bold": "Ilimitadas",
"point2": "<bold> con astrólogos profesionales",
"point2_bold": "Chats en vivo 1:1",
"point3": "<bold> lecturas",
"point3_bold": "Compatibilidad diaria",
"point4": "Consejos cósmicos de relación",
"point5": "Horóscopos diarios"
},
"palms_say_about": {
"title": "¿Qué dicen tus palmas sobre ti?",
"point1": "<color> muestra tu actitud hacia el amor y la calidad del amor",
"point1_color": "Línea del amor",
"point2": "Un pulgar largo indica buena fortuna",
"point3": "<color> refleja tu inteligencia y mentalidad",
"point3_color": "Línea de la cabeza",
"point4": "Un dedo índice largo indica un líder nato",
"point5": "<color> define la calidad de tu vida y lo que lograrás",
"point5_color": "Línea de la vida",
"point6": "Un dedo medio corto revela un espíritu libre",
"point7": "<color> representa tus logros materiales y objetivos profesionales",
"point7_color": "Línea del destino",
"point8": "Un dedo anular largo revela que una persona tiende a tomar riesgos",
"point9": "Un dedo meñique corto indica la falta de confianza en uno mismo"
},
"discover_more": "Descubre más",
"why_love": "¿Por qué todos <color>?",
"why_love_color": "aman AURA",
"reviews": {
"username1": "Rebecca Bauman",
"tagline1": "\"¡Ha cambiado mi vida!\"",
"text1": "Estoy agradecida por esta aplicación y por Akho. ¡Ella es una excelente lectora de palma y astróloga—clara, minuciosa y tranquilizadora. Espero con ansias más sesiones con ella!",
"username2": "Mika Ryan",
"tagline2": "\"Después de años de búsqueda, finalmente he encontrado un verdadero amor.\"",
"text2": "Tenía dudas sobre si realmente valía la pena probarlo, pero ahora no tengo arrepentimientos y estoy disfrutando mis nuevas relaciones.",
"username3": "Amanda Holmes",
"tagline3": "\"He encontrado un trabajo que realmente disfruto.\"",
"text3": "Gracias a Vladana, finalmente he descubierto una pista sobre cuál es realmente el propósito de mi vida y qué tipo de trabajo resuena más conmigo."
},
"success_story": "¡Conviértete en una historia de éxito de AURA!",
"as_seen_in": "<color> Visto en",
"footer": {
"text1": "¿Preguntas? Estamos aquí para ayudarte",
"text2": "Atención al Cliente",
"text3": "Centro de Ayuda"
}
},
"/payment": {
"will_be_charged_trial_info": "<trialPrice> por tu prueba de <trialDuration> días",
"will_be_charged_email_reminder": "te enviaremos un recordatorio por correo electrónico",
"will_be_charged": "Se te cobrará solo <trialInfo>. Luego <fullPrice> <trialPrice> por semana. Ahorra <save> cada semana. Te enviaremos un <emailReminder> antes de que termine tu prueba.",
"payment_information": {
"personalized_offer": "Oferta personalizada reservada",
"title": "Comienza tu prueba de <trialDuration> días",
"total_today": "Total hoy",
"code_applied_bold": "AURA24",
"code_applied": "¡Código <bold> aplicado!"
},
"guarantees": {
"no_commitment": "Sin compromiso. Cancela en cualquier momento.",
"30_day_money_back": "Garantía de devolución del dinero en 30 días"
},
"get_personal_prediction": "Obtén una predicción personalizada",
"total_due": "Total adeudado hoy: <trialPrice>",
"app_number_one_color": "25 millones de personas.",
"app_number_one": "La aplicación de astrología #1 confiada por más de <color>"
}
}
}
}

View File

@ -30,6 +30,7 @@
"privacy_policy": "Política de Privacidad",
"terms_of_use": "Términos de uso",
"policy": "Estoy de acuerdo con la <privacyPolicy>, los <termsOfUse> y con el uso de cookies y tecnologías de seguimiento, que requieren tu consentimiento",
"copyright": "@ <year> Wit Apps LLC, California, US",
"profile": "Perfil",
"personality_traits": "Rasgos de personalidad",
"relationship_pattern": "Patrón de relaciones",
@ -625,7 +626,10 @@
"description": "Te estás perdiendo ambas lecturas"
}
},
"description": "*Se te cobrará por los servicios adicionales u ofertas seleccionadas en el momento de la compra. Este es un pago único."
"description": "*Se te cobrará por los servicios adicionales u ofertas seleccionadas en el momento de la compra. Este es un pago único.",
"v1": {
"continue": "Continuar"
}
},
"/unlimited-readings": {
"personal_affirmations": "afirmaciones personales para cada día",
@ -647,15 +651,17 @@
"30-minute": "Consulta privada de 30 minutos con un experto",
"description": "Puedes pedir predicción del futuro, análisis de compatibilidad en vivo; compatibilidad en el amor, etc.",
"one_time_price_offer": "Precio de oferta única:",
"original_price": "Precio original: <oldPrice> Ahorra <discount>%",
"original_price": "Precio original: <oldPrice> <discount>",
"you_will_be_charged": "*Se te cobrará por los servicios adicionales u ofertas seleccionadas en el momento de la compra. Este es un pago no recurrente.",
"get_my_consultation": "Obtener mi consulta"
"get_my_consultation": "Obtener mi consulta",
"discount_save": "Ahorra"
},
"/get-information-partner": {
"title": "¡Maravilloso! Vamos a descubrir lo que funciona (y lo que no) y partiremos de ahí.",
"description": "Ahora necesitamos algo de información sobre el Perfil de tu Pareja para crear el mapa astrológico de sinastría entre tú y tu pareja."
},
"/additional-discount": {
"header_title": "¡Tienes un descuento secreto!",
"title": "¡Ahorra <discount> de descuento!",
"description1": "<discount> de descuento en tu plan personalizado",
"description2": "Prueba de <trialDuration> días",
@ -663,6 +669,7 @@
"button": "¡Obtener descuento secreto!"
},
"/trial-payment-with-discount": {
"header_title": "¡Tienes un descuento secreto!",
"title": "¡Tienes un descuento secreto!",
"cancel_anytime": "Sin presión. Cancela en cualquier momento.",
"secret_discount_applied": "¡Descuento secreto aplicado!",
@ -780,7 +787,9 @@
},
"/email": {
"title": "Introduce tu correo electrónico para obtener tu lectura avanzada de quiromancia con AURA",
"not_share": "No compartimos ninguna información personal."
"not_share": "No compartimos ninguna información personal.",
"placeholder_email": "Tu correo electrónico",
"placeholder_name": "Tu nombre"
},
"app_number_one": {
"text": "La aplicación <color> en la que confían más de 25 millones de personas.",
@ -886,4 +895,4 @@
"app_number_one": "La aplicación #1 en Astrología en la que confían más de <color>"
}
}
}
}

View File

@ -14,6 +14,7 @@
"privacy_policy": "Politique de confidentialité",
"terms_of_use": "Conditions d'utilisation",
"policy": "Je suis d'accord avec la <privacyPolicy>, les <termsOfUse> et l'utilisation de cookies et des technologies de suivi qui nécessitent votre consentement",
"copyright": "@ <year> Wit Apps LLC, California, US",
"profile": "Profil",
"personality_traits": "Traits de personnalité",
"relationship_pattern": "Modèle relationnel",
@ -625,7 +626,10 @@
"description": "You are missing out on both readings"
}
},
"description": "*Vous serez facturé pour les services supplémentaires ou les offres sélectionnés au moment de l'achat. C'est un paiement non récurrent."
"description": "*Vous serez facturé pour les services supplémentaires ou les offres sélectionnés au moment de l'achat. C'est un paiement non récurrent.",
"v1": {
"continue": "Continuer"
}
},
"/unlimited-readings": {
"personal_affirmations": "affirmations personnelles pour chaque jour",
@ -647,15 +651,17 @@
"30-minute": "Consultation privée de 30 minutes avec un expert",
"description": "Vous pouvez demander une prédiction du futur, une analyse de compatibilité en direct ; compatibilité amoureuse, etc.",
"one_time_price_offer": "Offre de prix unique : ",
"original_price": "Prix initial : <oldPrice> Économisez <discount>%",
"original_price": "Prix initial : <oldPrice> <discount>",
"you_will_be_charged": "*Vous serez facturé pour les services supplémentaires ou les offres sélectionnés au moment de l'achat.\n C'est un paiement non récurrent.",
"get_my_consultation": "Obtenir ma consultation"
"get_my_consultation": "Obtenir ma consultation",
"discount_save": "Économisez"
},
"/get-information-partner": {
"title": "Génial ! Voyons ce qui fonctionne (et ce qui ne fonctionne pas) et progressons à partir de là.",
"description": "Maintenant, nous avons besoin de quelques informations sur le profil de votre partenaire pour créer la carte de synastrie astrologique entre vous et votre partenaire."
},
"/additional-discount": {
"header_title": "¡Tienes un descuento secreto!",
"title": "Économisez <discount> de réduction !",
"description1": "<discount> de réduction sur votre plan personnalisé",
"description2": "essai de <trialDuration> jours",
@ -663,7 +669,8 @@
"button": "Obtenir le rabais secret !"
},
"/trial-payment-with-discount": {
"title": "Vous bénéficiez d'un rabais secret !",
"header_title": "¡Tienes un descuento secreto!",
"title": "¡Tienes un descuento secreto!",
"cancel_anytime": "Pas de pression. Annulez à tout moment.",
"secret_discount_applied": "Rabais secret appliqué !",
"cost": "Votre coût toutes les 14 jours après l'essai :",
@ -779,7 +786,9 @@
},
"/email": {
"title": "Enter your email to get your advanced Palmistry reading with AURA",
"not_share": "We dont share any personal information."
"not_share": "We dont share any personal information.",
"placeholder_email": "Votre e-mail",
"placeholder_name": "Votre nom"
},
"went_wrong": "Something went wrong.",
"app_number_one": {

View File

@ -14,6 +14,7 @@
"privacy_policy": "Politique de confidentialité",
"terms_of_use": "Conditions d'utilisation",
"policy": "J'accepte la <privacyPolicy>, les <termsOfUse> et l'utilisation de cookies et technologies de suivi, nécessitant votre consentement",
"copyright": "@ <year> Wit Apps LLC, California, US",
"profile": "Profil",
"personality_traits": "Traits de personnalité",
"relationship_pattern": "Modèle de relation",
@ -622,7 +623,10 @@
"description": "You are missing out on both readings"
}
},
"description": "*Vous serez facturé pour les services ou offres supplémentaires sélectionnés au moment de l'achat. Ceci est un paiement non récurrent."
"description": "*Vous serez facturé pour les services ou offres supplémentaires sélectionnés au moment de l'achat. Ceci est un paiement non récurrent.",
"v1": {
"continue": "Continuer"
}
},
"/unlimited-readings": {
"personal_affirmations": "affirmations personnelles pour chaque jour",
@ -644,15 +648,17 @@
"30-minute": "Consultation privée de 30 minutes avec un expert",
"description": "Vous pouvez demander une prédiction du futur, une analyse de compatibilité en direct, une compatibilité amoureuse, etc.",
"one_time_price_offer": "Offre tarif unique : ",
"original_price": "Prix d'origine : <oldPrice> Économisez <discount>%",
"original_price": "Prix d'origine : <oldPrice> <discount>",
"you_will_be_charged": "*Vous serez facturé pour les services ou offres complémentaires sélectionnés au moment de l'achat.\n Ce paiement n'est pas récurrent.",
"get_my_consultation": "Obtenir ma consultation"
"get_my_consultation": "Obtenir ma consultation",
"discount_save": "Économisez"
},
"/get-information-partner": {
"title": "Merveilleux ! Découvrons ce qui fonctionne (et ce qui ne fonctionne pas) et avançons à partir de là.",
"description": "Nous avons besoin de quelques informations sur le profil de votre partenaire pour créer la carte de synastrie astrologique entre vous et votre partenaire."
},
"/additional-discount": {
"header_title": "Vous bénéficiez d'une réduction secrète !",
"title": "Économisez <discount> de réduction!",
"description1": "<discount> de réduction sur votre plan personnalisé",
"description2": "Essai de <trialDuration> jours",
@ -660,6 +666,7 @@
"button": "Obtenez une réduction secrète!"
},
"/trial-payment-with-discount": {
"header_title": "Vous bénéficiez d'une réduction secrète !",
"title": "Vous bénéficiez d'une réduction secrète !",
"cancel_anytime": "Pas de pression. Annulez à tout moment.",
"secret_discount_applied": "Réduction secrète appliquée !",
@ -779,7 +786,9 @@
},
"/email": {
"title": "Enter your email to get your advanced Palmistry reading with AURA",
"not_share": "We dont share any personal information."
"not_share": "We dont share any personal information.",
"placeholder_email": "Votre e-mail",
"placeholder_name": "Votre nom"
},
"went_wrong": "Something went wrong.",
"app_number_one": {

View File

@ -14,6 +14,7 @@
"privacy_policy": "गोपनीयता नीति",
"terms_of_use": "उपयोग की शर्तें",
"policy": "मैं <privacyPolicy>, <termsOfUse> और कूकीज़ और ट्रैकिंग तकनीकों के उपयोग के लिए सहमत हूँ, जिसके लिए आपकी सहमति आवश्यक है",
"copyright": "@ <year> Wit Apps LLC, California, US",
"profile": "प्रोफाइल",
"personality_traits": "व्यक्तित्व गुण",
"relationship_pattern": "संबंध पैटर्न",
@ -625,7 +626,10 @@
"description": "You are missing out on both readings"
}
},
"description": "*आपसे खरीद के समय चयनित ऐड-ऑन सेवाओं या ऑफर के लिए शुल्क लिया जाएगा। यह एक गैर-आवर्ती भुगतान है।"
"description": "*आपसे खरीद के समय चयनित ऐड-ऑन सेवाओं या ऑफर के लिए शुल्क लिया जाएगा। यह एक गैर-आवर्ती भुगतान है।",
"v1": {
"continue": "जारी रखना"
}
},
"/unlimited-readings": {
"personal_affirmations": "हर दिन के लिए व्यक्तिगत सकारात्मक वचन",
@ -647,15 +651,17 @@
"30-minute": "30 मिनट का निजी परामर्श एक विशेषज्ञ के साथ",
"description": "आप भविष्य की भविष्यवाणी, लाइव संगतता विश्लेषण, प्रेम संगतता आदि के लिए पूछ सकते हैं",
"one_time_price_offer": "एक बार की मूल्य पेशकश: ",
"original_price": "मूल कीमत: <oldPrice> <discount>% बचाएं",
"original_price": "मूल कीमत: <oldPrice> <discount> बचाएं",
"you_will_be_charged": "*आपसे खरीद के समय चयनित ऐड-ऑन सेवाओं या ऑफर के लिए शुल्क लिया जाएगा।\n यह एक गैर-आवर्ती भुगतान है।",
"get_my_consultation": "मेरा परामर्श प्राप्त करें"
"get_my_consultation": "मेरा परामर्श प्राप्त करें",
"discount_save": ""
},
"/get-information-partner": {
"title": "शानदार! चलिए देखते हैं कि क्या काम कर रहा है (और क्या नहीं) और वहीं से आगे बढ़ते हैं।",
"description": "अब हमें आपके और आपके साथी के बीच ज्योतिषीय तालमेल ब्लूप्रिंट बनाने के लिए आपके साथी की प्रोफाइल के बारे में कुछ जानकारी चाहिए।"
},
"/additional-discount": {
"header_title": "आपको गुप्त छूट मिल रही है!",
"title": "<discount> की बचत करें!",
"description1": "आपकी व्यक्तिगत योजना पर <discount> की छूट",
"description2": "<trialDuration>-दिन का ट्रायल",
@ -663,6 +669,7 @@
"button": "गुप्त छूट प्राप्त करें!"
},
"/trial-payment-with-discount": {
"header_title": "आपको गुप्त छूट मिल रही है!",
"title": "आपको गुप्त छूट मिल रही है!",
"cancel_anytime": "कोई दबाव नहीं। कभी भी रद्द कर सकते हैं।",
"secret_discount_applied": "गुप्त छूट लागू कर दी गई है!",
@ -779,7 +786,9 @@
},
"/email": {
"title": "Enter your email to get your advanced Palmistry reading with AURA",
"not_share": "We dont share any personal information."
"not_share": "We dont share any personal information.",
"placeholder_email": "आपका ईमेल",
"placeholder_name": "आपका नाम"
},
"went_wrong": "Something went wrong.",
"app_number_one": {

View File

@ -14,6 +14,7 @@
"privacy_policy": "गोपनीयता नीति",
"terms_of_use": "उपयोग की शर्तें",
"policy": "मैं <privacyPolicy>, <termsOfUse> और कुकीज़ और ट्रैकिंग तकनीकों के उपयोग से सहमत हूं, जिसके लिए आपकी सहमति की आवश्यकता है",
"copyright": "@ <year> Wit Apps LLC, California, US",
"profile": "प्रोफाइल",
"personality_traits": "व्यक्तित्व लक्षण",
"relationship_pattern": "संबंध पैटर्न",
@ -622,7 +623,10 @@
"description": "You are missing out on both readings"
}
},
"description": "*आपसे खरीद के समय चयनित ऐड-ऑन सेवाओं या ऑफ़रों के लिए शुल्क लिया जाएगा। यह एक गैर-पुनरावृत्त भुगतान है।"
"description": "*आपसे खरीद के समय चयनित ऐड-ऑन सेवाओं या ऑफ़रों के लिए शुल्क लिया जाएगा। यह एक गैर-पुनरावृत्त भुगतान है।",
"v1": {
"continue": "जारी रखना"
}
},
"/unlimited-readings": {
"personal_affirmations": "हर दिन के लिए व्यक्तिगत पुष्टि",
@ -644,15 +648,17 @@
"30-minute": "विशेषज्ञ के साथ 30-मिनट का निजी परामर्श",
"description": "आप भविष्य की भविष्यवाणी, लाइव संगति विश्लेषण, प्रेम संगति आदि के बारे में पूछ सकते हैं",
"one_time_price_offer": "एक बार का मूल्य प्रस्ताव: ",
"original_price": "मूल्य: <oldPrice> <discount>% बचत करें",
"original_price": "मूल्य: <oldPrice> <discount> बचत करें",
"you_will_be_charged": "*खरीद के समय चयनित अतिरिक्त सेवाओं या ऑफ़रों के लिए आपसे शुल्क लिया जाएगा। यह एक गैर-पुनरावृत्त भुगतान है।",
"get_my_consultation": "मेरा परामर्श प्राप्त करें"
"get_my_consultation": "मेरा परामर्श प्राप्त करें",
"discount_save": ""
},
"/get-information-partner": {
"title": "बहुत बढ़िया! चलिए यह पता लगाते हैं कि क्या काम कर रहा है (और क्या नहीं) और वहीं से आगे बढ़ते हैं।",
"description": "अब हमें आपके साथी के प्रोफाइल के बारे में कुछ जानकारी चाहिए ताकि हम आपके और आपके साथी के बीच ज्योतिषीय संबंध ब्लूप्रिंट बना सकें।"
},
"/additional-discount": {
"header_title": "आपको एक गुप्त छूट मिली है!",
"title": "<discount> की बचत करें!",
"description1": "आपकी व्यक्तिगत योजना पर <discount> की छूट",
"description2": "<trialDuration>-दिन का परीक्षण",
@ -660,6 +666,7 @@
"button": "गुप्त छूट प्राप्त करें!"
},
"/trial-payment-with-discount": {
"header_title": "आपको एक गुप्त छूट मिली है!",
"title": "आपको एक गुप्त छूट मिली है!",
"cancel_anytime": "कोई दबाव नहीं। कभी भी रद्द करें।",
"secret_discount_applied": "गुप्त छूट लागू!",
@ -779,7 +786,9 @@
},
"/email": {
"title": "Enter your email to get your advanced Palmistry reading with AURA",
"not_share": "We dont share any personal information."
"not_share": "We dont share any personal information.",
"placeholder_email": "आपका ईमेल",
"placeholder_name": "आपका नाम"
},
"went_wrong": "Something went wrong.",
"app_number_one": {

View File

@ -14,6 +14,7 @@
"privacy_policy": "Política de Privacidade",
"terms_of_use": "Termos de Uso",
"policy": "Concordo com a <privacyPolicy>, os <termsOfUse> e com o uso de cookies e tecnologias de rastreamento, que exigem seu consentimento",
"copyright": "@ <year> Wit Apps LLC, California, US",
"profile": "Perfil",
"personality_traits": "Traços de Personalidade",
"relationship_pattern": "Padrão de Relacionamento",
@ -625,7 +626,10 @@
"description": "You are missing out on both readings"
}
},
"description": "*Você será cobrada pelos serviços ou ofertas adicionais selecionados no momento da compra. Este é um pagamento não recorrente."
"description": "*Você será cobrada pelos serviços ou ofertas adicionais selecionados no momento da compra. Este é um pagamento não recorrente.",
"v1": {
"continue": "Continuar"
}
},
"/unlimited-readings": {
"personal_affirmations": "afirmações pessoais para todos os dias",
@ -647,15 +651,17 @@
"30-minute": "Consulta privada de 30 minutos com um especialista",
"description": "Você pode pedir previsão do futuro, análise de compatibilidade ao vivo; compatibilidade amorosa etc",
"one_time_price_offer": "Oferta de preço único: ",
"original_price": "Preço original: <oldPrice> Economize <discount>%",
"original_price": "Preço original: <oldPrice> <discount>",
"you_will_be_charged": "*Você será cobrada pelos serviços ou ofertas adicionais selecionados no momento da compra.\nEste é um pagamento não recorrente.",
"get_my_consultation": "Obter minha consulta"
"get_my_consultation": "Obter minha consulta",
"discount_save": "Economize"
},
"/get-information-partner": {
"title": "Maravilhoso! Vamos descobrir o que está funcionando (e o que não está) e seguir a partir daí.",
"description": "Agora precisamos de algumas informações sobre o Perfil do seu Parceiro para criar a sinastria astrológica entre você e seu parceiro."
},
"/additional-discount": {
"header_title": "Você conseguiu um desconto secreto!",
"title": "Economize <discount> de desconto!",
"description1": "<discount> de desconto no seu plano personalizado",
"description2": "Teste de <trialDuration> dias",
@ -663,6 +669,7 @@
"button": "Obter desconto secreto!"
},
"/trial-payment-with-discount": {
"header_title": "Você conseguiu um desconto secreto!",
"title": "Você conseguiu um desconto secreto!",
"cancel_anytime": "Sem pressão. Cancele a qualquer momento.",
"secret_discount_applied": "Desconto secreto aplicado!",
@ -779,7 +786,9 @@
},
"/email": {
"title": "Enter your email to get your advanced Palmistry reading with AURA",
"not_share": "We dont share any personal information."
"not_share": "We dont share any personal information.",
"placeholder_email": "Seu email",
"placeholder_name": "Seu nome"
},
"went_wrong": "Something went wrong.",
"app_number_one": {

View File

@ -14,6 +14,7 @@
"privacy_policy": "Política de Privacidade",
"terms_of_use": "Termos de Uso",
"policy": "Eu concordo com a <privacyPolicy>, <termsOfUse> e com o uso de cookies e tecnologias de rastreamento que requerem seu consentimento",
"copyright": "@ <year> Wit Apps LLC, California, US",
"profile": "Perfil",
"personality_traits": "Traços de Personalidade",
"relationship_pattern": "Padrão de Relacionamento",
@ -622,7 +623,10 @@
"description": "You are missing out on both readings"
}
},
"description": "*Você será cobrado pelos serviços adicionais ou ofertas selecionadas no momento da compra. Este é um pagamento não recorrente."
"description": "*Você será cobrado pelos serviços adicionais ou ofertas selecionadas no momento da compra. Este é um pagamento não recorrente.",
"v1": {
"continue": "Continuar"
}
},
"/unlimited-readings": {
"personal_affirmations": "afirmações pessoais para todos os dias",
@ -644,15 +648,17 @@
"30-minute": "Consulta privada de 30 minutos com um especialista",
"description": "Você pode pedir previsão do futuro, análise de compatibilidade ao vivo; compatibilidade amorosa etc.",
"one_time_price_offer": "Preço único da oferta: ",
"original_price": "Preço original: <oldPrice> Economize <discount>%",
"original_price": "Preço original: <oldPrice> <discount>",
"you_will_be_charged": "*Você será cobrado pelos serviços adicionais ou ofertas selecionadas no momento da compra.\n Este é um pagamento não recorrente.",
"get_my_consultation": "Obter minha consulta"
"get_my_consultation": "Obter minha consulta",
"discount_save": "Economize"
},
"/get-information-partner": {
"title": "Maravilhoso! Vamos descobrir o que está funcionando (e o que não está) e seguir a partir daí.",
"description": "Agora precisamos de algumas informações sobre o Perfil do Seu Parceiro para criar o mapa de sinastria astrológica entre você e seu parceiro."
},
"/additional-discount": {
"header_title": "Você ganhou um desconto secreto!",
"title": "Economize <discount>!",
"description1": "<discount> de desconto em seu plano personalizado",
"description2": "Teste de <trialDuration> dias",
@ -660,6 +666,7 @@
"button": "Obter desconto secreto!"
},
"/trial-payment-with-discount": {
"header_title": "Você ganhou um desconto secreto!",
"title": "Você ganhou um desconto secreto!",
"cancel_anytime": "Sem pressão. Cancele a qualquer momento.",
"secret_discount_applied": "Desconto secreto aplicado!",
@ -779,7 +786,9 @@
},
"/email": {
"title": "Enter your email to get your advanced Palmistry reading with AURA",
"not_share": "We dont share any personal information."
"not_share": "We dont share any personal information.",
"placeholder_email": "Seu email",
"placeholder_name": "Seu nome"
},
"went_wrong": "Something went wrong.",
"app_number_one": {

View File

@ -14,6 +14,7 @@
"privacy_policy": "Política de Privacidade",
"terms_of_use": "Termos de Uso",
"policy": "Concordo com a <privacyPolicy>, <termsOfUse> e com o uso de cookies e tecnologias de rastreamento, que requerem o teu consentimento",
"copyright": "@ <year> Wit Apps LLC, California, US",
"profile": "Perfil",
"personality_traits": "Características de Personalidade",
"relationship_pattern": "Padrão de Relacionamento",
@ -625,7 +626,10 @@
"description": "You are missing out on both readings"
}
},
"description": "*Serás cobrada pelos serviços ou ofertas adicionais selecionados no momento da compra. Este é um pagamento não recorrente."
"description": "*Serás cobrada pelos serviços ou ofertas adicionais selecionados no momento da compra. Este é um pagamento não recorrente.",
"v1": {
"continue": "Continuar"
}
},
"/unlimited-readings": {
"personal_affirmations": "afirmações pessoais para todos os dias",
@ -647,15 +651,17 @@
"30-minute": "Consulta privada de 30 minutos com um especialista",
"description": "Podes pedir previsão do futuro, análise de compatibilidade ao vivo, compatibilidade amorosa, etc.",
"one_time_price_offer": "Preço de oferta único: ",
"original_price": "Preço original: <oldPrice> Poupa <discount>%",
"original_price": "Preço original: <oldPrice> <discount>",
"you_will_be_charged": "*Serás cobrada pelos serviços ou ofertas adicionais selecionados no momento da compra. Este é um pagamento não recorrente.",
"get_my_consultation": "Obter a minha consulta"
"get_my_consultation": "Obter a minha consulta",
"discount_save": "Poupa"
},
"/get-information-partner": {
"title": "Maravilha! Vamos descobrir o que está a funcionar (e o que não está) e partir daí.",
"description": "Agora precisamos de algumas informações sobre o perfil do teu parceiro para criar o mapa de sinastria astrológica entre ti e o teu parceiro."
},
"/additional-discount": {
"header_title": "Tens um desconto secreto!",
"title": "Poupa <discount>!",
"description1": "<discount> de desconto no teu plano personalizado",
"description2": "Período experimental de <trialDuration> dias",
@ -663,6 +669,7 @@
"button": "Obter desconto secreto!"
},
"/trial-payment-with-discount": {
"header_title": "Tens um desconto secreto!",
"title": "Tens um desconto secreto!",
"cancel_anytime": "Sem pressão. Podes cancelar a qualquer momento.",
"secret_discount_applied": "Desconto secreto aplicado!",
@ -779,7 +786,9 @@
},
"/email": {
"title": "Enter your email to get your advanced Palmistry reading with AURA",
"not_share": "We dont share any personal information."
"not_share": "We dont share any personal information.",
"placeholder_email": "O teu email",
"placeholder_name": "O teu nome"
},
"went_wrong": "Something went wrong.",
"app_number_one": {

View File

@ -14,6 +14,7 @@
"privacy_policy": "Política de Privacidade",
"terms_of_use": "Termos de Utilização",
"policy": "Concordo com a <privacyPolicy>, os <termsOfUse> e com o uso de cookies e tecnologias de rastreamento, que requerem o seu consentimento",
"copyright": "@ <year> Wit Apps LLC, California, US",
"profile": "Perfil",
"personality_traits": "Traços de Personalidade",
"relationship_pattern": "Padrão de Relacionamento",
@ -625,7 +626,10 @@
"description": "You are missing out on both readings"
}
},
"description": "*Serás cobrado pelos serviços adicionais ou ofertas selecionadas no momento da compra. Este é um pagamento não recorrente."
"description": "*Serás cobrado pelos serviços adicionais ou ofertas selecionadas no momento da compra. Este é um pagamento não recorrente.",
"v1": {
"continue": "Continuar"
}
},
"/unlimited-readings": {
"personal_affirmations": "afirmações personalizadas para todos os dias",
@ -647,15 +651,17 @@
"30-minute": "Consulta privada de 30 minutos com um especialista",
"description": "Podes pedir previsão do futuro, análise de compatibilidade ao vivo; compatibilidade amorosa, etc.",
"one_time_price_offer": "Preço da oferta única: ",
"original_price": "Preço original: <oldPrice> Poupa <discount>%",
"original_price": "Preço original: <oldPrice> <discount>",
"you_will_be_charged": "*Serás cobrado pelos serviços adicionais ou ofertas selecionadas no momento da compra.\n Este é um pagamento não recorrente.",
"get_my_consultation": "Obter a minha consulta"
"get_my_consultation": "Obter a minha consulta",
"discount_save": "Poupa"
},
"/get-information-partner": {
"title": "Maravilhoso! Vamos descobrir o que está a funcionar (e o que não está) e seguir a partir daí.",
"description": "Agora precisamos de algumas informações sobre o Perfil do teu Parceiro para criar o mapa sinástrico astrológico entre ti e o teu parceiro."
},
"/additional-discount": {
"header_title": "Recebeste um desconto secreto!",
"title": "Poupa <discount>!",
"description1": "<discount> de desconto no teu plano personalizado",
"description2": "Teste de <trialDuration> dias",
@ -663,6 +669,7 @@
"button": "Obter desconto secreto!"
},
"/trial-payment-with-discount": {
"header_title": "Recebeste um desconto secreto!",
"title": "Recebeste um desconto secreto!",
"cancel_anytime": "Sem pressões. Cancela a qualquer momento.",
"secret_discount_applied": "Desconto secreto aplicado!",
@ -779,7 +786,9 @@
},
"/email": {
"title": "Enter your email to get your advanced Palmistry reading with AURA",
"not_share": "We dont share any personal information."
"not_share": "We dont share any personal information.",
"placeholder_email": "O teu email",
"placeholder_name": "O teu nome"
},
"went_wrong": "Something went wrong.",
"app_number_one": {

View File

@ -656,6 +656,7 @@
"description": "Теперь нам нужно немного информации о Профиле Твоего Партнёра, чтобы создать астрологическую карту синастрии между вами."
},
"/additional-discount": {
"header_title": "Ты получила секретную скидку!",
"title": "Сэкономь <discount>!",
"description1": "<discount> на персонализированный план",
"description2": "<trialDuration>-дневный пробный период",
@ -663,6 +664,7 @@
"button": "Получить секретную скидку!"
},
"/trial-payment-with-discount": {
"header_title": "Ты получила секретную скидку!",
"title": "Ты получила секретную скидку!",
"cancel_anytime": "Без обязательств. Отмена в любое время.",
"secret_discount_applied": "Секретная скидка применена!",
@ -779,7 +781,9 @@
},
"/email": {
"title": "Enter your email to get your advanced Palmistry reading with AURA",
"not_share": "We dont share any personal information."
"not_share": "We dont share any personal information.",
"placeholder_email": "Ваш email",
"placeholder_name": "Ваше имя"
},
"went_wrong": "Something went wrong.",
"app_number_one": {

View File

@ -656,6 +656,7 @@
"description": "Теперь нам нужна некоторая информация о профиле вашего партнёра, чтобы создать астрологическую синастрийную карту между вами и вашим партнёром."
},
"/additional-discount": {
"header_title": "Вы получили секретную скидку!",
"title": "Сэкономьте <discount>!",
"description1": "Скидка <discount> на ваш персонализированный план",
"description2": "<trialDuration>-дневный пробный период",
@ -663,6 +664,7 @@
"button": "Получить секретную скидку!"
},
"/trial-payment-with-discount": {
"header_title": "Вы получили секретную скидку!",
"title": "Вы получили секретную скидку!",
"cancel_anytime": "Никакого давления. Отмена в любое время.",
"secret_discount_applied": "Секретная скидка применена!",
@ -779,7 +781,9 @@
},
"/email": {
"title": "Enter your email to get your advanced Palmistry reading with AURA",
"not_share": "We dont share any personal information."
"not_share": "We dont share any personal information.",
"placeholder_email": "Ваш email",
"placeholder_name": "Ваше имя"
},
"went_wrong": "Something went wrong.",
"app_number_one": {

Binary file not shown.

View File

@ -0,0 +1,27 @@
<svg width="78" height="23" viewBox="0 0 78 23" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M77.2617 19.8559C77.2617 21.052 76.2726 22.0208 75.0493 22.0208H2.6479C1.42514 22.0208 0.432617 21.052 0.432617 19.8559V2.59112C0.432617 1.39559 1.42514 0.42334 2.6479 0.42334H75.0487C76.2726 0.42334 77.2611 1.39559 77.2611 2.59112L77.2617 19.8559Z" fill="black"/>
<path d="M74.8148 0.449482C76.1471 0.449482 77.2312 1.50648 77.2312 2.80545V19.6388C77.2312 20.9378 76.1471 21.9947 74.8148 21.9947H2.87749C1.54521 21.9947 0.461118 20.9378 0.461118 19.6388V2.80545C0.461118 1.50648 1.54521 0.449482 2.87749 0.449482H74.8148ZM74.8148 -0.000107846H2.87749C1.29559 -0.000107846 0 1.26309 0 2.80545V19.6388C0 21.1811 1.29559 22.4443 2.87749 22.4443H74.8148C76.3967 22.4443 77.6923 21.1811 77.6923 19.6388V2.80545C77.6923 1.26309 76.3967 -0.000107846 74.8148 -0.000107846Z" fill="#A6A6A6"/>
<path d="M17.3402 11.1009C17.3235 9.29241 18.8589 8.41259 18.9291 8.37163C18.0596 7.1355 16.7117 6.96661 16.2381 6.95314C15.1061 6.83699 14.008 7.61357 13.4314 7.61357C12.8432 7.61357 11.9552 6.96436 10.9982 6.98344C9.76662 7.00196 8.61447 7.69718 7.98257 8.77675C6.67849 10.978 7.65109 14.2128 8.90049 15.9921C9.52548 16.8635 10.2558 17.8365 11.2117 17.8022C12.1469 17.7646 12.4962 17.2209 13.6248 17.2209C14.743 17.2209 15.071 17.8022 16.0459 17.7803C17.0496 17.7646 17.6814 16.905 18.2846 16.0257C19.0068 15.027 19.2969 14.0433 19.3084 13.9928C19.2848 13.985 17.3592 13.2684 17.3402 11.1009Z" fill="white"/>
<path d="M15.4986 5.78266C16.0016 5.16937 16.3457 4.335 16.2502 3.48828C15.5222 3.5197 14.6117 3.97925 14.0875 4.57908C13.6236 5.10765 13.2093 5.974 13.3163 6.78874C14.1341 6.84821 14.9737 6.38642 15.4986 5.78266Z" fill="white"/>
<path d="M30.872 17.6771H29.565L28.8491 15.4837H26.3606L25.6787 17.6771H24.4062L26.8717 10.2098H28.3945L30.872 17.6771ZM28.6333 14.5635L27.9859 12.6136C27.9174 12.4144 27.789 11.9454 27.5997 11.2069H27.5767C27.5013 11.5245 27.3798 11.9936 27.213 12.6136L26.577 14.5635H28.6333Z" fill="white"/>
<path d="M37.2117 14.9188C37.2117 15.8345 36.9579 16.5584 36.4504 17.0897C35.9957 17.5627 35.4311 17.799 34.7572 17.799C34.0298 17.799 33.5073 17.5442 33.189 17.0347H33.166V19.8712H31.939V14.0653C31.939 13.4896 31.9235 12.8988 31.8936 12.2928H32.9726L33.0411 13.1462H33.0641C33.4733 12.5032 34.0943 12.1823 34.9276 12.1823C35.579 12.1823 36.1229 12.4331 36.558 12.9353C36.9942 13.438 37.2117 14.099 37.2117 14.9188ZM35.9618 14.9626C35.9618 14.4385 35.8409 14.0064 35.598 13.6664C35.3327 13.3118 34.9765 13.1345 34.5299 13.1345C34.2272 13.1345 33.9521 13.2332 33.7064 13.4279C33.4601 13.6243 33.2989 13.8807 33.2235 14.1983C33.1855 14.3465 33.1666 14.4677 33.1666 14.563V15.4608C33.1666 15.8525 33.2897 16.183 33.536 16.4529C33.7823 16.7228 34.1023 16.8574 34.496 16.8574C34.9581 16.8574 35.3178 16.6835 35.575 16.3367C35.8328 15.9894 35.9618 15.5315 35.9618 14.9626Z" fill="white"/>
<path d="M43.5647 14.9188C43.5647 15.8345 43.3109 16.5584 42.8027 17.0897C42.3486 17.5627 41.7841 17.799 41.1102 17.799C40.3827 17.799 39.8602 17.5442 39.5425 17.0347H39.5195V19.8712H38.2925V14.0653C38.2925 13.4896 38.277 12.8988 38.2471 12.2928H39.3261L39.3946 13.1462H39.4176C39.8262 12.5032 40.4472 12.1823 41.2811 12.1823C41.932 12.1823 42.4758 12.4331 42.9121 12.9353C43.3466 13.438 43.5647 14.099 43.5647 14.9188ZM42.3147 14.9626C42.3147 14.4385 42.1933 14.0064 41.9504 13.6664C41.6851 13.3118 41.33 13.1345 40.8829 13.1345C40.5796 13.1345 40.3051 13.2332 40.0587 13.4279C39.8124 13.6243 39.6519 13.8807 39.5765 14.1983C39.5391 14.3465 39.5195 14.4677 39.5195 14.563V15.4608C39.5195 15.8525 39.6427 16.183 39.8878 16.4529C40.1341 16.7222 40.4541 16.8574 40.8489 16.8574C41.311 16.8574 41.6707 16.6835 41.928 16.3367C42.1858 15.9894 42.3147 15.5315 42.3147 14.9626Z" fill="white"/>
<path d="M50.6654 15.5832C50.6654 16.2184 50.4392 16.7352 49.9851 17.1341C49.4862 17.5701 48.7916 17.7878 47.899 17.7878C47.0748 17.7878 46.4142 17.6329 45.9141 17.3226L46.1984 16.3256C46.737 16.6431 47.3281 16.8025 47.972 16.8025C48.4342 16.8025 48.7939 16.7004 49.0523 16.4973C49.3095 16.2941 49.4378 16.0214 49.4378 15.6814C49.4378 15.3784 49.3319 15.1231 49.1196 14.916C48.9084 14.709 48.5556 14.5165 48.063 14.3387C46.7221 13.8511 46.0522 13.1368 46.0522 12.1975C46.0522 11.5836 46.287 11.0803 46.7572 10.6886C47.2256 10.2964 47.8506 10.1006 48.6321 10.1006C49.3291 10.1006 49.908 10.219 50.3701 10.4552L50.0634 11.4304C49.6318 11.2015 49.1438 11.087 48.5976 11.087C48.166 11.087 47.8287 11.1908 47.587 11.3973C47.3827 11.5819 47.2803 11.8069 47.2803 12.0735C47.2803 12.3686 47.3971 12.6127 47.6319 12.8046C47.8362 12.9819 48.2074 13.1738 48.7461 13.3808C49.405 13.6395 49.889 13.942 50.2004 14.2887C50.5106 14.6344 50.6654 15.067 50.6654 15.5832Z" fill="white"/>
<path d="M54.7216 13.1907H53.3692V15.8049C53.3692 16.4698 53.6074 16.802 54.0851 16.802C54.3044 16.802 54.4862 16.7835 54.6301 16.7464L54.6641 17.6549C54.4224 17.743 54.1041 17.7873 53.7099 17.7873C53.2253 17.7873 52.8466 17.6431 52.5733 17.3553C52.3011 17.0668 52.1641 16.5832 52.1641 15.9037V13.1896H51.3584V12.2918H52.1641V11.3059L53.3692 10.9513V12.2918H54.7216V13.1907Z" fill="white"/>
<path d="M60.8241 14.9407C60.8241 15.7684 60.5813 16.4479 60.0967 16.9792C59.5886 17.5263 58.9141 17.799 58.0733 17.799C57.263 17.799 56.6178 17.537 56.1367 17.0129C55.6556 16.4888 55.415 15.8273 55.415 15.0299C55.415 14.1956 55.6625 13.5121 56.1592 12.9808C56.6547 12.4488 57.3234 12.1829 58.1642 12.1829C58.9745 12.1829 59.6265 12.4449 60.1186 12.9695C60.5893 13.4785 60.8241 14.1355 60.8241 14.9407ZM59.5511 14.9794C59.5511 14.4829 59.4424 14.057 59.222 13.7018C58.9647 13.272 58.597 13.0576 58.1205 13.0576C57.6273 13.0576 57.2526 13.2725 56.9954 13.7018C56.7749 14.0575 56.6662 14.4902 56.6662 15.0019C56.6662 15.4985 56.7749 15.9243 56.9954 16.279C57.2607 16.7088 57.6313 16.9231 58.1095 16.9231C58.578 16.9231 58.9457 16.7043 59.211 16.2678C59.4372 15.9058 59.5511 15.4755 59.5511 14.9794Z" fill="white"/>
<path d="M64.813 13.3449C64.6916 13.323 64.5621 13.3118 64.4263 13.3118C63.9947 13.3118 63.6609 13.4706 63.4261 13.7887C63.2218 14.0693 63.1193 14.4239 63.1193 14.852V17.6772H61.8929L61.9044 13.9885C61.9044 13.3679 61.8889 12.8028 61.8584 12.2934H62.9271L62.972 13.3236H63.0059C63.1354 12.9695 63.3397 12.6844 63.6194 12.4707C63.8928 12.2782 64.188 12.1823 64.5063 12.1823C64.6197 12.1823 64.7221 12.1901 64.813 12.2041V13.3449Z" fill="white"/>
<path d="M70.2994 14.7301C70.2994 14.9444 70.2851 15.1251 70.2546 15.2727H66.5737C66.5881 15.8046 66.7659 16.2114 67.1077 16.492C67.4179 16.7428 67.8191 16.8685 68.3117 16.8685C68.8567 16.8685 69.3539 16.7838 69.8011 16.6138L69.9933 17.4442C69.4707 17.6664 68.8538 17.7769 68.1419 17.7769C67.2856 17.7769 66.6134 17.5312 66.1242 17.0402C65.6362 16.5492 65.3916 15.8899 65.3916 15.0628C65.3916 14.2509 65.6189 13.5748 66.0741 13.0355C66.5507 12.4598 67.1946 12.172 68.0049 12.172C68.8009 12.172 69.4034 12.4598 69.8126 13.0355C70.1366 13.4929 70.2994 14.0585 70.2994 14.7301ZM69.1295 14.4198C69.1375 14.0652 69.0575 13.7588 68.8912 13.5001C68.6788 13.1674 68.3525 13.0013 67.9134 13.0013C67.5123 13.0013 67.186 13.1635 66.9368 13.4889C66.7325 13.7476 66.6111 14.0579 66.5737 14.4192H69.1295V14.4198Z" fill="white"/>
<path d="M28.2295 5.61623C28.2295 6.27665 28.0263 6.7738 27.6206 7.10766C27.2448 7.41571 26.7107 7.57001 26.019 7.57001C25.676 7.57001 25.3825 7.55543 25.1367 7.52625V3.91774C25.4573 3.86724 25.8026 3.84143 26.1755 3.84143C26.8344 3.84143 27.3311 3.98115 27.666 4.26058C28.0413 4.57649 28.2295 5.02818 28.2295 5.61623ZM27.5935 5.6325C27.5935 5.20437 27.4773 4.87612 27.2448 4.64719C27.0123 4.41881 26.6727 4.30435 26.2256 4.30435C26.0356 4.30435 25.8739 4.31669 25.7398 4.3425V7.08578C25.8141 7.097 25.9499 7.10205 26.1473 7.10205C26.6088 7.10205 26.9651 6.97692 27.216 6.72666C27.4669 6.47641 27.5935 6.11169 27.5935 5.6325Z" fill="white"/>
<path d="M31.6014 6.19314C31.6014 6.59995 31.4823 6.93325 31.244 7.19473C30.9943 7.4635 30.6634 7.59761 30.2501 7.59761C29.8519 7.59761 29.5348 7.46911 29.2983 7.211C29.0623 6.95345 28.9443 6.62857 28.9443 6.23691C28.9443 5.8273 29.0658 5.4912 29.3098 5.23028C29.5538 4.96936 29.8818 4.83862 30.295 4.83862C30.6933 4.83862 31.0133 4.96712 31.2555 5.22467C31.4857 5.47492 31.6014 5.79812 31.6014 6.19314ZM30.9758 6.21222C30.9758 5.96814 30.9218 5.75884 30.8141 5.58434C30.6875 5.37336 30.5074 5.26787 30.2732 5.26787C30.0309 5.26787 29.8467 5.37336 29.7201 5.58434C29.6119 5.75884 29.5584 5.97151 29.5584 6.22288C29.5584 6.46697 29.6125 6.67626 29.7201 6.85077C29.8507 7.06174 30.0326 7.16723 30.2674 7.16723C30.4976 7.16723 30.6783 7.06006 30.8084 6.84516C30.92 6.66728 30.9758 6.45631 30.9758 6.21222Z" fill="white"/>
<path d="M36.123 4.89246L35.2742 7.53753H34.7217L34.3701 6.38894C34.2809 6.10221 34.2084 5.81717 34.152 5.53437H34.141C34.0886 5.82502 34.0161 6.10951 33.9229 6.38894L33.5494 7.53753H32.9906L32.1924 4.89246H32.8122L33.1189 6.14991C33.1932 6.4473 33.2542 6.73066 33.3031 6.99887H33.314C33.3589 6.77779 33.4332 6.49611 33.5379 6.15552L33.9229 4.89302H34.4144L34.7833 6.12858C34.8725 6.4299 34.945 6.72 35.0008 6.99943H35.0175C35.0584 6.72729 35.1199 6.4372 35.2017 6.12858L35.5308 4.89302H36.123V4.89246Z" fill="white"/>
<path d="M39.249 7.53754H38.6459V6.02254C38.6459 5.5557 38.4641 5.32228 38.0992 5.32228C37.9202 5.32228 37.7758 5.38624 37.6636 5.51474C37.5525 5.64323 37.4961 5.79473 37.4961 5.96811V7.53698H36.893V5.64828C36.893 5.41598 36.8855 5.16404 36.8711 4.89134H37.4011L37.4293 5.30488H37.446C37.5162 5.17639 37.621 5.07034 37.7585 4.98561C37.922 4.88685 38.105 4.83691 38.3052 4.83691C38.5584 4.83691 38.7691 4.91659 38.9366 5.07651C39.1449 5.27234 39.249 5.56468 39.249 5.95296V7.53754Z" fill="white"/>
<path d="M40.9121 7.53747H40.3096V3.67871H40.9121V7.53747Z" fill="white"/>
<path d="M44.4627 6.19314C44.4627 6.59995 44.3436 6.93325 44.1054 7.19473C43.8556 7.4635 43.5241 7.59761 43.1115 7.59761C42.7127 7.59761 42.3955 7.46911 42.1596 7.211C41.9236 6.95345 41.8057 6.62857 41.8057 6.23691C41.8057 5.8273 41.9271 5.4912 42.1711 5.23028C42.4151 4.96936 42.7432 4.83862 43.1558 4.83862C43.5546 4.83862 43.874 4.96712 44.1169 5.22467C44.3471 5.47492 44.4627 5.79812 44.4627 6.19314ZM43.8366 6.21222C43.8366 5.96814 43.7825 5.75884 43.6749 5.58434C43.5488 5.37336 43.3681 5.26787 43.1345 5.26787C42.8916 5.26787 42.7075 5.37336 42.5814 5.58434C42.4732 5.75884 42.4197 5.97151 42.4197 6.22288C42.4197 6.46697 42.4738 6.67626 42.5814 6.85077C42.7121 7.06174 42.8939 7.16723 43.1287 7.16723C43.3589 7.16723 43.5391 7.06006 43.6691 6.84516C43.7814 6.66728 43.8366 6.45631 43.8366 6.21222Z" fill="white"/>
<path d="M47.3815 7.53757H46.8399L46.795 7.23288H46.7784C46.593 7.47585 46.3289 7.59761 45.9859 7.59761C45.7298 7.59761 45.5226 7.51737 45.3667 7.35801C45.2251 7.21324 45.1543 7.03313 45.1543 6.81934C45.1543 6.49614 45.2924 6.24982 45.5704 6.07924C45.8478 5.90866 46.238 5.82506 46.7404 5.82898V5.77961C46.7404 5.43116 46.5528 5.25721 46.177 5.25721C45.9094 5.25721 45.6734 5.32286 45.4697 5.45304L45.3471 5.067C45.5992 4.91493 45.9105 4.83862 46.2777 4.83862C46.9867 4.83862 47.3423 5.20335 47.3423 5.93279V6.90688C47.3423 7.17116 47.3556 7.38158 47.3815 7.53757ZM46.7553 6.62857V6.22064C46.0901 6.20942 45.7574 6.38729 45.7574 6.7537C45.7574 6.89173 45.7954 6.99497 45.8731 7.06399C45.9508 7.13301 46.0498 7.16723 46.1677 7.16723C46.3001 7.16723 46.4238 7.12627 46.5366 7.04491C46.65 6.96299 46.7197 6.85918 46.7455 6.73181C46.7519 6.70319 46.7553 6.66841 46.7553 6.62857Z" fill="white"/>
<path d="M50.8085 7.53747H50.2733L50.2451 7.11271H50.2284C50.0575 7.43591 49.7663 7.59751 49.3571 7.59751C49.0302 7.59751 48.758 7.47238 48.5422 7.22213C48.3264 6.97187 48.2188 6.64699 48.2188 6.24804C48.2188 5.81991 48.3356 5.47314 48.5704 5.2083C48.7977 4.96141 49.0762 4.83797 49.4077 4.83797C49.772 4.83797 50.027 4.95748 50.172 5.19708H50.1835V3.67871H50.7872V6.82486C50.7872 7.08241 50.7941 7.31976 50.8085 7.53747ZM50.1835 6.42198V5.98095C50.1835 5.90464 50.1777 5.84292 50.1668 5.79578C50.1329 5.65438 50.0598 5.53543 49.9487 5.43948C49.8365 5.34353 49.7012 5.29527 49.5453 5.29527C49.3202 5.29527 49.1441 5.38224 49.0147 5.55675C48.8863 5.73126 48.8213 5.95402 48.8213 6.22616C48.8213 6.48763 48.8829 6.69973 49.0066 6.86302C49.1372 7.03696 49.3133 7.12393 49.5338 7.12393C49.7317 7.12393 49.89 7.05155 50.0103 6.90622C50.1265 6.77212 50.1835 6.61052 50.1835 6.42198Z" fill="white"/>
<path d="M55.9676 6.19314C55.9676 6.59995 55.8485 6.93325 55.6102 7.19473C55.3605 7.4635 55.0301 7.59761 54.6164 7.59761C54.2187 7.59761 53.9016 7.46911 53.6645 7.211C53.4285 6.95345 53.3105 6.62857 53.3105 6.23691C53.3105 5.8273 53.432 5.4912 53.676 5.23028C53.92 4.96936 54.248 4.83862 54.6618 4.83862C55.0595 4.83862 55.38 4.96712 55.6218 5.22467C55.8519 5.47492 55.9676 5.79812 55.9676 6.19314ZM55.3426 6.21222C55.3426 5.96814 55.2885 5.75884 55.1809 5.58434C55.0537 5.37336 54.8742 5.26787 54.6394 5.26787C54.3977 5.26787 54.2135 5.37336 54.0863 5.58434C53.9781 5.75884 53.9246 5.97151 53.9246 6.22288C53.9246 6.46697 53.9787 6.67626 54.0863 6.85077C54.217 7.06174 54.3988 7.16723 54.6336 7.16723C54.8638 7.16723 55.0451 7.06006 55.1752 6.84516C55.2862 6.66728 55.3426 6.45631 55.3426 6.21222Z" fill="white"/>
<path d="M59.2104 7.53754H58.6078V6.02254C58.6078 5.5557 58.426 5.32228 58.0605 5.32228C57.8816 5.32228 57.7371 5.38624 57.6255 5.51474C57.5138 5.64323 57.458 5.79473 57.458 5.96811V7.53698H56.8543V5.64828C56.8543 5.41598 56.8474 5.16404 56.833 4.89134H57.3625L57.3907 5.30488H57.4074C57.4781 5.17639 57.5829 5.07034 57.7198 4.98561C57.8839 4.88685 58.0663 4.83691 58.2672 4.83691C58.5198 4.83691 58.7304 4.91659 58.8979 5.07651C59.1068 5.27234 59.2104 5.56468 59.2104 5.95296V7.53754Z" fill="white"/>
<path d="M63.2694 5.33298H62.6053V6.61793C62.6053 6.94449 62.7233 7.10778 62.9569 7.10778C63.0651 7.10778 63.1549 7.0988 63.2257 7.08028L63.2412 7.52636C63.1221 7.57013 62.9656 7.59201 62.7728 7.59201C62.5345 7.59201 62.3492 7.52132 62.2151 7.37991C62.0805 7.23852 62.0137 7.0006 62.0137 6.66674V5.33298H61.6172V4.89251H62.0137V4.40771L62.6047 4.23376V4.89195H63.2689V5.33298H63.2694Z" fill="white"/>
<path d="M66.4616 7.53747H65.8579V6.03369C65.8579 5.55956 65.676 5.32221 65.3117 5.32221C65.032 5.32221 64.841 5.45968 64.7362 5.73462C64.7184 5.79242 64.708 5.86312 64.708 5.94616V7.53691H64.1055V3.67871H64.708V5.27283H64.7195C64.9094 4.98273 65.1817 4.83797 65.5344 4.83797C65.7842 4.83797 65.9908 4.91764 66.1548 5.07756C66.3591 5.27676 66.4616 5.57302 66.4616 5.96468V7.53747Z" fill="white"/>
<path d="M69.7557 6.08982C69.7557 6.19531 69.7476 6.28397 69.7332 6.35635H67.9244C67.9325 6.61783 68.0188 6.81702 68.1863 6.95506C68.3394 7.0785 68.5368 7.14022 68.7785 7.14022C69.0461 7.14022 69.2901 7.0987 69.5099 7.0151L69.6043 7.42358C69.3471 7.53244 69.0443 7.58687 68.6939 7.58687C68.2738 7.58687 67.9428 7.46623 67.7034 7.22495C67.4629 6.98367 67.3438 6.65991 67.3438 6.25367C67.3438 5.85472 67.4548 5.52254 67.6787 5.2577C67.9123 4.9749 68.2283 4.8335 68.6271 4.8335C69.0173 4.8335 69.3137 4.9749 69.514 5.2577C69.6757 5.48214 69.7557 5.75989 69.7557 6.08982ZM69.1802 5.93776C69.1848 5.76326 69.1451 5.61288 69.0633 5.48607C68.9586 5.32278 68.7992 5.24086 68.5834 5.24086C68.3866 5.24086 68.226 5.32054 68.1034 5.48046C68.0033 5.60783 67.944 5.75989 67.9244 5.93776H69.1802Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

BIN
public/v1/smartphone-1.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

BIN
public/v1/smartphone-2.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

BIN
public/v1/smartphone-3.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

BIN
public/v1/smartphone-4.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

BIN
public/v1/smartphone-5.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
public/v1/test.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

View File

@ -32,6 +32,7 @@ import {
UserVideos,
UserPDF,
Locale,
Session
} from './resources'
const api = {
@ -86,9 +87,12 @@ const api = {
// User videos
getUserVideos: createMethod<UserVideos.PayloadGet, UserVideos.ResponseGet>(UserVideos.createRequest),
// User PDF
getUserPDFCompatibility: createMethod<UserPDF.PayloadGet, UserPDF.ResponseGet>(UserPDF.createRequest),
getUserPDF: createMethod<UserPDF.PayloadGet, UserPDF.ResponseGet>(UserPDF.createRequest),
// Locale
getLocale: createMethod<undefined, Locale.ResponseGet>(Locale.createRequest),
// Session
createSession: createMethod<Session.PayloadCreate, Session.ResponseCreate>(Session.createRequest),
updateSession: createMethod<Session.PayloadUpdate, Session.ResponseUpdate>(Session.updateRequest)
}
export type ApiContextValue = typeof api

View File

@ -0,0 +1,68 @@
import routes from "@/routes";
import { getBaseHeaders } from "../utils";
import { IUTM } from "@/store/utm";
import { ICreateAuthorizeUser } from "./User";
export interface PayloadCreate {
feature: string, // Type: string
locale: string, // Type: string
timezone: string, // Type: string
source: string, // Type: string
sign: boolean, // Type: boolean
signDate: string | undefined, // Type: string, ISO Date
utm: IUTM // Type: { [key: string]: string } - Optional
}
export interface PayloadUpdate {
sessionId: string,
data: {
feature: string, // Type: string
profile?: Partial<ICreateAuthorizeUser>;
partner?: Partial<Exclude<ICreateAuthorizeUser, "relationship_status">>;
answers?: Partial<IAnswersSession>;
}
}
export interface IAnswersSession {
what_aspects: 'love_relationships' | 'health_vitality' | 'career_destiny', // Type: string, optional - 'love_relationships' | 'health_vitality' | 'career_destiny';
relationship_status: 'single' | 'in_relationship', // Type: string, optional - 'single' | 'in_relationship';
element_resonates: 'water' | 'fire' | 'air' | 'earth', // Type: string, optional - 'water' | 'fire' | 'air' | 'earth';
favorite_color: 'blue' | 'green' | 'orange' | 'violet' | 'red' | 'yellow', // Type: string, optional - 'blue' | 'green' | 'orange' | 'violet' | 'red' | 'yellow';
head_or_heart: 'head' | 'heart' | 'both', // Type: string, optional - 'head' | 'heart' | 'both';
time_alone: 1 | 2 | 3 | 4 | 5, // Type: number, optional - 1 | 2 | 3 | 4 | 5;
own_company: 1 | 2 | 3 | 4 | 5, // Type: number, optional - 1 | 2 | 3 | 4 | 5;
socializing_in_groups: 1 | 2 | 3 | 4 | 5, // Type: number, optional - 1 | 2 | 3 | 4 | 5;
loneliness_avoid: 1 | 2 | 3 | 4 | 5, // Type: number, optional - 1 | 2 | 3 | 4 | 5;
activities_independently: 1 | 2 | 3 | 4 | 5 // Type: number, optional - 1 | 2 | 3 | 4 | 5;
}
export interface ResponseCreate {
status: "success" | string,
sessionId: string
}
export interface ResponseUpdate {
status: "success" | string,
message: "Session updated" | string
}
export const createRequest = (data: PayloadCreate) => {
const url = new URL(routes.server.createSession());
const body = JSON.stringify(data);
return new Request(url, {
method: "POST",
body,
headers: getBaseHeaders()
});
};
export const updateRequest = ({ data, sessionId }: PayloadUpdate) => {
const url = new URL(routes.server.updateSession(sessionId));
const body = JSON.stringify(data);
return new Request(url, {
method: "PATCH",
body,
headers: getBaseHeaders()
});
};

View File

@ -146,15 +146,15 @@ export enum EGender {
"other" = "other"
}
enum ERelationshipStatus {
"single",
"relationship",
"married",
"complicated",
"other"
export enum ERelationshipStatus {
"single" = "single",
"relationship" = "relationship",
"married" = "married",
"complicated" = "complicated",
"other" = "other"
}
interface ICreateAuthorizeUser {
export interface ICreateAuthorizeUser {
name: string;
birthdate: string | null;
gender: EGender;

View File

@ -1,21 +1,30 @@
import routes from "@/routes";
import { getAuthHeaders } from "../utils";
export enum PDFKey {
Compatibility = "compatibility",
Palmistry = "palmistry",
}
interface Payload {
token: string;
key: PDFKey;
}
export type PayloadGet = Payload;
export interface IUserPDFCompatibility {
url: string
export interface IUserPDF {
id: string | null;
status: "ready" | string;
type: string;
url: string | undefined | null;
}
type ResponseGetSuccess = IUserPDFCompatibility;
type ResponseGetSuccess = IUserPDF;
export type ResponseGet = ResponseGetSuccess;
export const createRequest = ({ token }: PayloadGet): Request => {
const url = new URL(routes.server.getUserPDFCompatibility());
export const createRequest = ({ token, key }: PayloadGet): Request => {
const url = new URL(routes.server.getUserPDF(key));
return new Request(url, { method: "GET", headers: getAuthHeaders(token) });
};

View File

@ -30,3 +30,4 @@ export * as Payment from "./Payment";
export * as UserVideos from "./UserVideos";
export * as UserPDF from "./UserPDF";
export * as Locale from "./Locale";
export * as Session from "./Session";

View File

@ -5,10 +5,26 @@ import {
ApiError,
buildUnknownError,
} from "./errors";
import { ESourceAuthorization } from "./resources/User";
export function createMethod<P, R>(createRequest: (payload: P) => Request) {
return async (payload: P): Promise<R> => {
const request = createRequest(payload);
let source = ESourceAuthorization["aura.main.new"];
if (location.pathname.includes("/palmistry")) {
source = ESourceAuthorization["aura.palmistry"];
}
if (location.pathname.includes("/v1/palmistry")) {
source = ESourceAuthorization["aura.palmistry.new"];
}
const sessionId = localStorage.getItem(`${source}_sessionId`);
if (sessionId?.length) {
request.headers.append("session-id", sessionId);
}
const response = await fetch(request);
const data: R | ErrorResponse = await response.json();
const statusCode = response.status;

Binary file not shown.

View File

@ -129,6 +129,7 @@ import AdditionalPurchasesPalmistry from "../palmistry/AdditionalPurchases";
import AddConsultant from "../palmistry/AdditionalPurchases/pages/AddConsultant";
import AddGuides from "../palmistry/AdditionalPurchases/pages/AddGuides";
import SkipTrial from "../palmistry/AdditionalPurchases/pages/SkipTrial";
import { parseQueryParams } from "@/services/url";
const isProduction = import.meta.env.MODE === "production";
@ -149,6 +150,24 @@ function App(): JSX.Element {
const jwtToken = searchParams.get("token");
const isForce = searchParams.get("force");
// parse utm query
useEffect(() => {
const availableUrls = [
routes.client.genderV1(),
routes.client.palmistryV1Welcome(),
routes.client.palmistryWelcome(),
];
const isPageAvailable = availableUrls.reduce(
(acc, url) => !!location.pathname.includes(url) || acc,
false
);
if (isPageAvailable) {
const utm = parseQueryParams();
dispatch(actions.utm.update(utm));
}
}, [dispatch, location.pathname]);
useEffect(() => {
if (isForce === "true") {
dispatch(actions.userConfig.addIsForceShortPath(true));
@ -289,9 +308,7 @@ function App(): JSX.Element {
return (
<Routes>
<Route element={<AuthorizedUserOutlet />}>
<Route path="*" element={<ABDesignV1Routes />} />
</Route>
<Route path="*" element={<ABDesignV1Routes />} />
<Route path={`${palmistryV1Prefix}/*`} element={<PalmistryV1Routes />} />
<Route path={`${routes.client.mikeV1()}/*`} element={<MikeV1Routes />} />
<Route element={<Layout setIsSpecialOfferOpen={setIsSpecialOfferOpen} />}>
@ -1183,7 +1200,7 @@ function ShortPathOutlet(props: IShortPathOutletProps): JSX.Element {
return <Navigate to={productUrls[productKey]} replace={true} />;
}
function AuthorizedUserOutlet(): JSX.Element {
export function AuthorizedUserOutlet(): JSX.Element {
const status = useSelector(selectors.selectStatus);
const { user } = useAuth();
return user && status === "subscribed" ? (
@ -1193,7 +1210,7 @@ function AuthorizedUserOutlet(): JSX.Element {
);
}
function PrivateOutlet(): JSX.Element {
export function PrivateOutlet(): JSX.Element {
const { user } = useAuth();
return user ? (
<Outlet />

View File

@ -1,22 +1,25 @@
import "./styles.scss";
import { ReactNode } from "react";
import { LegacyRef, ReactNode, forwardRef } from "react";
import cn from "classnames";
type BlurComponentProps = {
children: ReactNode;
isActiveBlur?: boolean;
className: string;
className?: string;
gradientClassName?: string;
};
export default function BlurComponent({
children,
isActiveBlur,
className,
gradientClassName = "",
}: BlurComponentProps) {
const BlurComponent = forwardRef(function BlurComponent(
{
children,
isActiveBlur,
className,
gradientClassName = "",
}: BlurComponentProps,
ref: LegacyRef<HTMLDivElement>
) {
return (
<div className={cn("gradient-container", className)}>
<div className={cn("gradient-container", className)} ref={ref}>
{children}
{isActiveBlur && (
<div className={cn("gradient-blur", gradientClassName)}>
@ -30,4 +33,6 @@ export default function BlurComponent({
)}
</div>
);
}
});
export default BlurComponent;

View File

@ -28,6 +28,9 @@ import TextWithFinger from "../TextWithFinger";
// } from "../PredictionMoonsSlider";
import { predictionMoonsPeriods } from "@/data";
import { useDynamicSize } from "@/hooks/useDynamicSize";
import { PDFKey } from "@/api/resources/UserPDF";
import Loader, { LoaderColor } from "../Loader";
import { sleep } from "@/services/date";
// import WallpapersZodiacSign from "../WallpapersZodiacSign";
// import ThermalSlider from "../ThermalSlider";
// import MoonPhaseTracker from "../MoonPhaseTracker";
@ -85,9 +88,9 @@ function HomePage(): JSX.Element {
);
}, [dispatch]);
const handleCompatibilityPDF = () => {
if (!PDFCompatibility?.url?.length) return;
window.location.href = PDFCompatibility?.url;
const handlePDF = (pdf: UserPDF.ResponseGet | null) => {
if (!pdf?.url?.length) return;
window.location.href = pdf?.url;
// setIsShowPDF(true);
};
@ -131,15 +134,50 @@ function HomePage(): JSX.Element {
// isPending
} = useApiCall<Asset[]>(assetsData);
const getUserPDFCompatibility = useCallback(async () => {
const pdf = await api.getUserPDFCompatibility({
token,
});
return pdf;
}, [api, token]);
const getUserPDF = useCallback(
async (key: PDFKey): Promise<UserPDF.IUserPDF> => {
try {
const pdf = await api.getUserPDF({
token,
key,
});
if (!pdf?.url?.length || pdf.status !== "ready") {
await sleep(5000);
return getUserPDF(key);
}
return pdf;
} catch (error) {
console.error("Error: ", error);
return {
id: null,
url: null,
status: "not_allowed",
type: key,
};
}
},
[api, token]
);
const { data: PDFCompatibility } = useApiCall<UserPDF.ResponseGet>(
getUserPDFCompatibility
const getUserCompatibility = useCallback(async () => {
return await getUserPDF(PDFKey.Compatibility);
}, [getUserPDF]);
const getUserPalmistry = useCallback(async () => {
return await getUserPDF(PDFKey.Palmistry);
}, [getUserPDF]);
const { data: PDFCompatibility, isPending: isPendingCompatibilityPDF } =
useApiCall<UserPDF.ResponseGet>(getUserCompatibility);
const { data: PDFPalmistry, isPending: isPendingPalmistryPDF } =
useApiCall<UserPDF.ResponseGet>(getUserPalmistry);
const getIsPDFLoading = useCallback(
(pdf: UserPDF.ResponseGet | null, isPending: boolean) => {
return isPending || !pdf || !pdf.url?.length || pdf.status !== "ready";
},
[]
);
useEffect(() => {
@ -174,7 +212,7 @@ function HomePage(): JSX.Element {
const getMoonsImages = async () => {
const assets = (
await api.getAssets({ category: String("au.prediction_moons" || "1") })
await api.getAssets({ category: String("au.prediction_moons") || "1" })
).assets;
const randomAssets: Asset[] = [];
for (let i = 0; i < predictionMoonsPeriods.length; i++) {
@ -310,13 +348,49 @@ function HomePage(): JSX.Element {
crossClickHandler={() => setIsShowOnboardingHome(false)}
/>
</Onboarding>
{!!PDFCompatibility?.url?.length && (
{PDFPalmistry?.status !== "not_allowed" && (
<BlurringSubstrate
style={{ color: "#fff" }}
className={styles["content__buttons-item"]}
clickHandler={handleCompatibilityPDF}
className={`${styles["content__buttons-item"]} ${
getIsPDFLoading(PDFPalmistry, isPendingPalmistryPDF)
? styles["content__buttons-loading"]
: ""
}`}
clickHandler={() => handlePDF(PDFPalmistry)}
>
<strong>Your Personalized READING</strong>
<>
{getIsPDFLoading(PDFPalmistry, isPendingPalmistryPDF) && (
<Loader
color={LoaderColor.White}
className={styles["buttons-loader"]}
/>
)}
<strong>Your Palmistry READING</strong>
</>
</BlurringSubstrate>
)}
{PDFCompatibility?.status !== "not_allowed" && (
<BlurringSubstrate
style={{ color: "#fff" }}
className={`${styles["content__buttons-item"]} ${
getIsPDFLoading(PDFCompatibility, isPendingCompatibilityPDF)
? styles["content__buttons-loading"]
: ""
}`}
clickHandler={() => handlePDF(PDFCompatibility)}
>
<>
{getIsPDFLoading(
PDFCompatibility,
isPendingCompatibilityPDF
) && (
<Loader
color={LoaderColor.White}
className={styles["buttons-loader"]}
/>
)}
<strong>Your Personalized READING</strong>
</>
</BlurringSubstrate>
)}
<BlurringSubstrate

View File

@ -260,6 +260,29 @@
fill: #fff;
}
.buttons-loader {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 9;
}
.content__buttons-loading {
overflow: hidden;
}
.content__buttons-loading::after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #000000;
opacity: 0.5;
}
@keyframes pulse {
0% {
transform: scale(0.9);

View File

@ -1,5 +1,6 @@
.container {
width: 100vw;
max-width: 508px;
display: flex;
flex-direction: column;
align-items: center;

View File

@ -42,6 +42,10 @@ function PaymentModal(props: HTMLAttributes<HTMLDivElement>) {
placementKey={
EPlacementKeys["aura.placement.palmistry.redesign"]
}
noProductRedirect={{
pagesFrom: [routes.client.palmistryV1TrialPayment()],
url: routes.client.palmistryV1TrialChoice(),
}}
/>
)}

View File

@ -13,7 +13,12 @@
text-align: -webkit-center;
transition: 0.5s height;
max-width: 560px;
margin-left: -66px;
// margin-left: -66px;
// left: 50%;
// transform: translate(-50%, 0);
left: 0;
right: 0;
margin: 0 auto;
}
.widget_success {

View File

@ -10,9 +10,12 @@ import routes, { palmistryV1Prefix } from "@/routes";
import { useNavigate } from "react-router-dom";
import { useTranslations } from "@/hooks/translations";
import { ELocalesPlacement } from "@/locales";
import { useSession } from "@/hooks/session/useSession";
import { ESourceAuthorization } from "@/api/resources/User";
function Birthdate() {
const { translate } = useTranslations(ELocalesPlacement.PalmistryV1);
const { updateSession } = useSession();
const navigate = useNavigate();
const dispatch = useDispatch();
const birthdateFromStore = useSelector(selectors.selectBirthdate);
@ -35,11 +38,19 @@ function Birthdate() {
return age;
};
const handleNext = () => {
const handleNext = async () => {
const age = getAge();
metricService.userParams({
age,
});
await updateSession(
{
profile: {
birthdate: `${birthdate} 00:00`,
},
},
ESourceAuthorization["aura.palmistry.new"]
);
dispatch(actions.form.addDate(birthdate));
dispatch(actions.questionnaire.update({ birthdate }));
navigate(routes.client.palmistryV1PalmsInformation());

View File

@ -2,7 +2,7 @@ import PalmCameraModal from "@/components/palmistry/palm-camera-modal/palm-camer
import styles from "./styles.module.scss";
import { DataURIToBlob } from "@/services/data";
import { useApi } from "@/api";
import { IPalmistryFinger } from "@/api/resources/Palmistry";
import { IPalmistryFinger, IPalmistryLine } from "@/api/resources/Palmistry";
import { IPalmistryFingerLocal } from "@/store/palmistry";
import { useDispatch } from "react-redux";
import { actions } from "@/store";
@ -10,6 +10,10 @@ import { useNavigate } from "react-router-dom";
import routes from "@/routes";
import { useState } from "react";
import Loader, { LoaderColor } from "@/components/Loader";
import UploadModal from "@/components/palmistry/upload-modal/upload-modal";
import Toast from "@/components/pages/ABDesign/v1/components/Toast";
import { useTranslations } from "@/hooks/translations";
import { ELocalesPlacement } from "@/locales";
const fingersNames = {
thumb: "Thumb finger",
@ -31,43 +35,127 @@ const setFingersNames = (
});
};
const isProduction = import.meta.env.MODE === "production";
enum EToastVisible {
"try_again" = "try_again",
"try_again_or_next" = "try_again_or_next",
}
function Camera() {
const { translate } = useTranslations(ELocalesPlacement.PalmistryV1);
const navigate = useNavigate();
const api = useApi();
const dispatch = useDispatch();
const [isLoading, setIsLoading] = useState(false);
const [uploadMenuModalIsOpen, setUploadMenuModalIsOpen] = useState(false);
const [toastVisible, setToastVisible] = useState<EToastVisible | null>(null);
const handleNext = () => {
navigate(routes.client.palmistryV1ScannedPhoto());
};
/**
* Check if the palmistry lines are valid for the next step.
* If the length of the lines is less than 2, show the "try_again" toast.
* If the length of the lines is 2, show the "try_again_or_next" toast.
* Otherwise, return true.
* @param {IPalmistryLine[]} lines - The palmistry lines.
* @returns {boolean} Whether the palmistry lines are valid for the next step.
*/
const checkPalmistryLines = (lines: IPalmistryLine[]): boolean => {
if (!lines.length || lines.length < 2) {
setToastVisible(EToastVisible.try_again);
return false;
}
if (lines.length === 2) {
setToastVisible(EToastVisible.try_again_or_next);
return false;
}
return true;
};
const getLines = async (file: File | Blob) => {
setIsLoading(true);
const formData = new FormData();
formData.append("file", file);
const result = await api.getPalmistryLines({ formData });
const fingers = setFingersNames(result?.fingers);
try {
const result = await api.getPalmistryLines({ formData });
const fingers = setFingersNames(result?.fingers);
dispatch(
actions.palmistry.update({
lines: result?.lines,
fingers,
})
);
setIsLoading(false);
dispatch(
actions.palmistry.update({
lines: result?.lines,
fingers,
})
);
return result;
} catch (error) {
dispatch(
actions.palmistry.update({
lines: [],
fingers: [],
})
);
return null;
} finally {
setIsLoading(false);
}
};
const onTakePhoto = async (photo: string) => {
// setIsUpladProcessing(true);
const file = DataURIToBlob(photo);
await getLines(file);
// setPalmPhoto(photo as string);
const onTakePhoto = async (photo: string) => {
setUploadMenuModalIsOpen(false);
const file = DataURIToBlob(photo);
const result = await getLines(file);
dispatch(
actions.palmistry.update({
photo,
})
);
navigate(routes.client.palmistryV1ScannedPhoto());
if (!checkPalmistryLines(result?.lines || [])) return;
handleNext();
};
const onSelectFile = async (event: React.ChangeEvent<HTMLInputElement>) => {
setUploadMenuModalIsOpen(false);
if (!event.target.files || event.target.files.length === 0) return;
const result = await getLines(event.target.files[0]);
const reader = new FileReader();
reader.onloadend = () => {
dispatch(
actions.palmistry.update({
photo: reader.result as string,
})
);
if (!checkPalmistryLines(result?.lines || [])) return;
handleNext();
};
reader.readAsDataURL(event.target.files[0]);
};
return (
<>
{!isLoading && (
{!isProduction && uploadMenuModalIsOpen && (
<UploadModal
onClose={() => setUploadMenuModalIsOpen(false)}
onSelectFile={onSelectFile}
onChooseCamera={() => true}
/>
)}
{!isProduction && (
<button
className={styles["upload-button"]}
onClick={() => setUploadMenuModalIsOpen(true)}
>
Upload
</button>
)}
{!isLoading && !uploadMenuModalIsOpen && (
<PalmCameraModal
onClose={() => console.log("close")}
onTakePhoto={onTakePhoto}
@ -76,6 +164,34 @@ function Camera() {
{isLoading && (
<Loader className={styles.loader} color={LoaderColor.Black} />
)}
{toastVisible === EToastVisible.try_again && (
<Toast classNameContainer={styles["toast-container"]} variant="error">
<div className={styles["toast-content"]}>
<span>{translate("/camera.bad_photo")}</span>
<button onClick={() => setToastVisible(null)}>
{translate("/camera.try_again")}
</button>
</div>
</Toast>
)}
{toastVisible === EToastVisible.try_again_or_next && (
<Toast classNameContainer={styles["toast-container"]} variant="error">
<div
className={styles["toast-content"]}
style={{ flexDirection: "column" }}
>
<span>{translate("/camera.do_better")}</span>
<div className={styles["buttons-container"]}>
<button onClick={() => setToastVisible(null)}>
{translate("/camera.try_again")}
</button>
<button onClick={() => handleNext()}>
{translate("/camera.next")}
</button>
</div>
</div>
</Toast>
)}
</>
);
}

View File

@ -4,3 +4,47 @@
top: 50%;
left: 50%;
}
.upload-button {
position: fixed;
top: 32px;
right: 32px;
z-index: 3000;
}
.toast-container {
position: fixed;
bottom: calc(0dvh + 16px);
width: 100%;
z-index: 3000;
padding: 0 16px;
}
.toast-content {
display: flex;
flex-direction: row;
gap: 8px;
align-items: center;
justify-content: space-between;
& > button,
& > .buttons-container > button {
padding: 6px 18px;
border: none;
background-color: #fff;
color: #000;
border-radius: 4px;
font-size: 14px;
font-weight: 500;
}
& > .buttons-container > button {
width: 100%;
}
& > .buttons-container {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px;
}
}

View File

@ -15,9 +15,13 @@ import FireSVG from "../../images/SVG/Fire";
import AirSVG from "../../images/SVG/Air";
import EarthSVG from "../../images/SVG/Earth";
import { ELottieKeys, useLottie } from "@/hooks/lottie/useLottie";
import { IAnswersSession } from "@/api/resources/Session";
import { useSession } from "@/hooks/session/useSession";
import { ESourceAuthorization } from "@/api/resources/User";
function ElementResonates() {
const { translate } = useTranslations(ELocalesPlacement.PalmistryV1);
const { updateSession } = useSession();
const navigate = useNavigate();
const dispatch = useDispatch();
const { elementResonates } = useSelector(selectors.selectPalmistryV1Answers);
@ -25,7 +29,11 @@ function ElementResonates() {
preloadKey: ELottieKeys.letScan,
});
const answers = useMemo(
const answers: {
id: IAnswersSession["element_resonates"];
title: string;
Icon: JSX.Element;
}[] = useMemo(
() => [
{
id: "water",
@ -51,14 +59,19 @@ function ElementResonates() {
[translate]
);
const handleClick = async (id: string) => {
const handleClick = async (id: IAnswersSession["element_resonates"]) => {
dispatch(actions.palmistryV1Answers.update({ elementResonates: id }));
await updateSession({
answers: {
element_resonates: id,
},
}, ESourceAuthorization["aura.palmistry.new"]);
if (id !== elementResonates) await sleep(answerTimeOut);
navigate(routes.client.palmistryV1FavoriteColor());
};
return (
<div>
<div className={styles.container}>
<Title variant="h2" className={styles.title}>
{translate("/element-resonates.title")}
</Title>

View File

@ -1,3 +1,7 @@
.container {
width: 100%;
}
.answer {
justify-content: flex-start;
padding-left: 15px;

View File

@ -1,7 +1,7 @@
import Title from "@/components/Title";
import styles from "./styles.module.scss";
import EmailInput from "@/components/pages/ABDesign/v1/pages/EmailEnterPage/EmailInput";
import { useEffect, useState } from "react";
import { useCallback, useEffect, useState } from "react";
import { useDispatch } from "react-redux";
import { actions } from "@/store";
import Button from "../../components/Button";
@ -16,32 +16,53 @@ import { ELocalesPlacement } from "@/locales";
import metricService, {
EGoals,
EMetrics,
useMetricABFlags,
} from "@/services/metric/metricService";
import NameInput from "@/components/pages/ABDesign/v1/pages/EmailEnterPage/NameInput";
import { useSession } from "@/hooks/session/useSession";
function Email() {
const { updateSession } = useSession();
const dispatch = useDispatch();
const navigate = useNavigate();
const { error, isLoading, token, user, authorization } = useAuthentication();
const { translate } = useTranslations(ELocalesPlacement.PalmistryV1);
const [email, setEmail] = useState("");
const [name, setName] = useState("");
const [isValidEmail, setIsValidEmail] = useState(false);
const [isValidName, setIsValidName] = useState(true);
const [isDisabled, setIsDisabled] = useState(true);
const [isAuth, setIsAuth] = useState(false);
const { flags } = useMetricABFlags();
const auraVideoTrial = flags?.auraVideoTrial?.[0];
const handleValidEmail = (email: string) => {
dispatch(actions.form.addEmail(email));
setEmail(email);
setIsValidEmail(true);
};
const handleValidName = (name: string) => {
if (name) {
dispatch(
actions.user.update({
username: name,
})
);
}
setName(name);
setIsValidName(true);
};
useEffect(() => {
if (isValidEmail) {
if (isValidName && isValidEmail) {
setIsDisabled(false);
} else {
setIsDisabled(true);
}
}, [isValidEmail, email]);
}, [isValidEmail, email, isValidName, name]);
const handleClick = () => {
authorize();
@ -53,6 +74,14 @@ function Email() {
};
const authorize = async () => {
await updateSession(
{
profile: {
name,
},
},
ESourceAuthorization["aura.palmistry.new"]
);
metricService.reachGoal(EGoals.LEAD, [EMetrics.FACEBOOK]);
metricService.reachGoal(EGoals.ENTERED_EMAIL, [
EMetrics.KLAVIYO,
@ -63,18 +92,25 @@ function Email() {
await authorization(email, ESourceAuthorization["aura.palmistry.new"]);
};
const handleNext = useCallback(() => {
if (auraVideoTrial === "on") {
return navigate(routes.client.palmistryV1TrialChoiceVideo());
}
return navigate(routes.client.palmistryV1TrialChoice());
}, [auraVideoTrial, navigate]);
useEffect(() => {
if (user && token?.length && !isLoading && !error) {
setIsAuth(true);
dispatch(actions.paywalls.resetIsMustUpdate());
const timeout = setTimeout(() => {
navigate(routes.client.palmistryV1TrialChoice());
handleNext();
}, 1000);
return () => {
clearTimeout(timeout);
};
}
}, [dispatch, error, isLoading, navigate, token?.length, user]);
}, [dispatch, error, handleNext, isLoading, token?.length, user]);
return (
<>
@ -84,11 +120,18 @@ function Email() {
<EmailInput
name="email"
value={email}
placeholder={"Your email"}
placeholder={translate("/email.placeholder_email")}
inputClassName={styles.input}
onValid={handleValidEmail}
onInvalid={() => setIsValidEmail(false)}
/>
<NameInput
value={name}
placeholder={translate("/email.placeholder_name")}
inputClassName={styles.input}
onValid={handleValidName}
onInvalid={() => setIsValidName(true)}
/>
<p className={styles["not-share"]}>{translate("/email.not_share")}</p>
<Button
className={styles.button}

View File

@ -12,9 +12,13 @@ import { ELocalesPlacement } from "@/locales";
import { useMemo } from "react";
import TabSVG from "../../images/SVG/Tab";
import { usePreloadImages } from "@/hooks/preload/images";
import { IAnswersSession } from "@/api/resources/Session";
import { useSession } from "@/hooks/session/useSession";
import { ESourceAuthorization } from "@/api/resources/User";
function FavoriteColor() {
const { translate } = useTranslations(ELocalesPlacement.PalmistryV1);
const { updateSession } = useSession();
const navigate = useNavigate();
const dispatch = useDispatch();
const { favoriteColor } = useSelector(selectors.selectPalmistryV1Answers);
@ -27,7 +31,11 @@ function FavoriteColor() {
"/v1/palmistry/trial-payment/avatar-4.png",
]);
const answers = useMemo(
const answers: {
id: IAnswersSession["favorite_color"];
title: string;
color?: string;
}[] = useMemo(
() => [
{
id: "blue",
@ -62,14 +70,19 @@ function FavoriteColor() {
[translate]
);
const handleClick = async (id: string) => {
const handleClick = async (id: IAnswersSession["favorite_color"]) => {
dispatch(actions.palmistryV1Answers.update({ favoriteColor: id }));
await updateSession({
answers: {
favorite_color: id,
},
}, ESourceAuthorization["aura.palmistry.new"]);
if (id !== favoriteColor) await sleep(answerTimeOut);
navigate(routes.client.palmistryV1HeadOrHeart());
};
return (
<div>
<div className={styles.container}>
<Title variant="h2" className={styles.title}>
{translate("/favorite-color.title")}
</Title>

View File

@ -1,3 +1,7 @@
.container {
width: 100%;
}
.answer {
justify-content: flex-start;
padding-left: 70px;

View File

@ -16,11 +16,14 @@ import { useNavigate } from "react-router-dom";
import routes from "@/routes";
import { usePreloadImages } from "@/hooks/preload/images";
import { ELottieKeys, useLottie } from "@/hooks/lottie/useLottie";
import { useSession } from "@/hooks/session/useSession";
import { EGender, ESourceAuthorization } from "@/api/resources/User";
function GenderPalmistry() {
const { translate } = useTranslations(ELocalesPlacement.PalmistryV1);
const dispatch = useDispatch();
const navigate = useNavigate();
const { createSession, updateSession } = useSession();
const { checked: privacyPolicyChecked } = useSelector(
selectors.selectPrivacyPolicy
);
@ -42,7 +45,22 @@ function GenderPalmistry() {
metricService.userParams({
gender: genders.find((g) => g.id === gender)?.name,
});
const session = await createSession(
ESourceAuthorization["aura.palmistry.new"]
);
if (session?.sessionId?.length) {
await updateSession(
{
profile: {
gender: EGender[gender as keyof typeof EGender],
},
},
ESourceAuthorization["aura.palmistry.new"],
session.sessionId
);
}
return navigate(routes.client.palmistryV1Birthdate());
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [gender, navigate]);
useEffect(() => {

View File

@ -11,9 +11,13 @@ import { useTranslations } from "@/hooks/translations";
import { ELocalesPlacement } from "@/locales";
import { useMemo } from "react";
import { usePreloadImages } from "@/hooks/preload/images";
import { useSession } from "@/hooks/session/useSession";
import { IAnswersSession } from "@/api/resources/Session";
import { ESourceAuthorization } from "@/api/resources/User";
function HeadOrHeart() {
const { translate } = useTranslations(ELocalesPlacement.PalmistryV1);
const { updateSession } = useSession();
const navigate = useNavigate();
const dispatch = useDispatch();
const { headOrHeart } = useSelector(selectors.selectPalmistryV1Answers);
@ -30,26 +34,35 @@ function HeadOrHeart() {
"/v1/palmistry/partners.png",
]);
const answers = useMemo(
() => [
{
id: "heart",
title: translate("/head-or-heart.answer1"),
},
{
id: "head",
title: translate("/head-or-heart.answer2"),
},
{
id: "both",
title: translate("/head-or-heart.answer3"),
},
],
[translate]
);
const answers: { id: IAnswersSession["head_or_heart"]; title: string }[] =
useMemo(
() => [
{
id: "heart",
title: translate("/head-or-heart.answer1"),
},
{
id: "head",
title: translate("/head-or-heart.answer2"),
},
{
id: "both",
title: translate("/head-or-heart.answer3"),
},
],
[translate]
);
const handleClick = async (id: string) => {
const handleClick = async (id: IAnswersSession["head_or_heart"]) => {
dispatch(actions.palmistryV1Answers.update({ headOrHeart: id }));
await updateSession(
{
answers: {
head_or_heart: id,
},
},
ESourceAuthorization["aura.palmistry.new"]
);
if (id !== headOrHeart) await sleep(answerTimeOut);
navigate(routes.client.palmistryV1HeadOrHeartResult());
};

View File

@ -27,6 +27,7 @@ function LetScan() {
data={animationData}
autoplay
loop={false}
width={1920}
/>
<Title variant="h2" className={styles.title}>
{translate("/let-scan.title")}

View File

@ -35,4 +35,5 @@
.lottie-animation {
aspect-ratio: 116 / 87;
max-width: 360px;
}

View File

@ -25,6 +25,7 @@ function PalmsInformation() {
data={animationData}
autoplay
loop={false}
width={1920}
/>
)}
<Title variant="h2" className={styles.title}>

View File

@ -12,8 +12,10 @@
text-align: left;
font-weight: 500;
margin-top: 42px;
max-width: 400px;
}
.lottie-animation {
aspect-ratio: 233 / 261;
max-width: 360px;
}

View File

@ -6,14 +6,25 @@ import { useEffect, useMemo, useState } from "react";
import { sleep } from "@/services/date";
import { useTranslations } from "@/hooks/translations";
import { ELocalesPlacement } from "@/locales";
import { useSession } from "@/hooks/session/useSession";
import { ESourceAuthorization } from "@/api/resources/User";
function RelateFollowing() {
const { translate } = useTranslations(ELocalesPlacement.PalmistryV1);
const { updateSession } = useSession();
const navigate = useNavigate();
const { questionId } = useParams();
const [activeButton, setActiveButton] = useState<number | null>();
const questions = useMemo(
const questions: {
id:
| "time_alone"
| "own_company"
| "socializing_in_groups"
| "loneliness_avoid"
| "activities_independently";
title: string;
}[] = useMemo(
() => [
{
id: "time_alone",
@ -28,11 +39,11 @@ function RelateFollowing() {
title: translate("/relate-following.question3"),
},
{
id: "loneliness",
id: "loneliness_avoid",
title: translate("/relate-following.question4"),
},
{
id: "independently",
id: "activities_independently",
title: translate("/relate-following.question5"),
},
],
@ -47,6 +58,14 @@ function RelateFollowing() {
const handleClick = async (answerIndex: number) => {
setActiveButton(answerIndex);
await updateSession(
{
answers: {
[questions[parseInt(questionId) - 1].id]: answerIndex + 1,
},
},
ESourceAuthorization["aura.palmistry.new"]
);
await sleep(400);
if (Number(questionId) < questions.length) {
return navigate(

View File

@ -44,10 +44,11 @@
.buttons-text-container {
width: 100%;
max-width: 344px;
display: flex;
flex-direction: row;
justify-content: space-between;
margin-top: 30px;
margin: 30px auto 0;
gap: 8px;
& > span {

View File

@ -11,9 +11,13 @@ import { useTranslations } from "@/hooks/translations";
import { ELocalesPlacement } from "@/locales";
import { useMemo } from "react";
import { ELottieKeys, useLottie } from "@/hooks/lottie/useLottie";
import { useSession } from "@/hooks/session/useSession";
import { IAnswersSession } from "@/api/resources/Session";
import { ESourceAuthorization } from "@/api/resources/User";
function RelationshipStatus() {
const { translate } = useTranslations(ELocalesPlacement.PalmistryV1);
const { updateSession } = useSession();
const navigate = useNavigate();
const dispatch = useDispatch();
const { relationshipStatus } = useSelector(
@ -23,7 +27,10 @@ function RelationshipStatus() {
preloadKey: ELottieKeys.scalesNeutralPalmistry,
});
const answers = useMemo(
const answers: {
id: IAnswersSession["relationship_status"];
title: string;
}[] = useMemo(
() => [
{
id: "single",
@ -37,14 +44,19 @@ function RelationshipStatus() {
[translate]
);
const handleClick = async (id: string) => {
const handleClick = async (id: IAnswersSession["relationship_status"]) => {
dispatch(actions.palmistryV1Answers.update({ relationshipStatus: id }));
await updateSession({
answers: {
relationship_status: id,
},
}, ESourceAuthorization["aura.palmistry.new"]);
if (id !== relationshipStatus) await sleep(answerTimeOut);
navigate(routes.client.palmistryV1ElementResonates());
};
return (
<div>
<div className={styles.container}>
<Title variant="h2" className={styles.title}>
{translate("/relationship-status.title")}
</Title>

View File

@ -0,0 +1,3 @@
.container {
width: 100%;
}

View File

@ -6,13 +6,18 @@ import Title from "@/components/Title";
import PriceList from "@/components/pages/ABDesign/v1/components/PriceList";
import { usePaywall } from "@/hooks/paywall/usePaywall";
import { EPlacementKeys } from "@/api/resources/Paywall";
import { ELocalesPlacement } from "@/locales";
import {
ELocalesPlacement,
getDefaultLocaleByLanguage,
language,
} from "@/locales";
import { useState } from "react";
import Button from "../../components/Button";
import routes from "@/routes";
import { useNavigate } from "react-router-dom";
import Loader from "@/components/Loader";
import { useTranslations } from "@/hooks/translations";
import { useMetricABFlags } from "@/services/metric/metricService";
function TrialChoice() {
const { translate } = useTranslations(ELocalesPlacement.PalmistryV1);
@ -23,6 +28,9 @@ function TrialChoice() {
localesPlacement: ELocalesPlacement.V1,
});
const { flags } = useMetricABFlags();
const isLongText = flags?.text?.[0] === "on";
const [isDisabled, setIsDisabled] = useState(true);
const selectedPrice = useSelector(selectors.selectSelectedPrice);
@ -50,9 +58,51 @@ function TrialChoice() {
{!isLoading && (
<>
<EmailSubstrate className={styles["email-substrate"]} email={email} />
<Title className={styles.title} variant="h2">
{getText("text.0")}
</Title>
{(getDefaultLocaleByLanguage(language) !== "en" || !isLongText) && (
<Title className={styles.title} variant="h2">
{getText("text.0")}
</Title>
)}
{getDefaultLocaleByLanguage(language) === "en" && isLongText && (
<p className={styles.text}>
AURA is the only accurate app with reliable fate line analysis,
verified by professionals and guaranteed to provide precise
predictions.
<br />
<br />
AURA has already helped millions of people find happiness and
discover the whole truth about their relationships.
<br />
<br />
Your fate analysis, which will completely change your life, is
almost ready! Before we provide it to you, we would like to offer
you the opportunity to choose the amount you consider reasonable
to try AURA for 7 days and which you think is fair for the changes
that will happen to you:
<br />
<br />
You will discover all the most intimate secrets that the stars
have prepared for you and solve relationship issues within just
one month;
<br />
<br />
You will once and for all put the finishing touches on unresolved
issues and forget about problems that have been haunting you for
years (if not decades);
<br />
<br />
You will save hundreds of dollars on fake and unprofessional
astrological predictions and fortune tellers;
<br />
<br />
You will receive not only a personal analysis but also
personalized daily horoscopes, learn who and how is draining your
energy, and get other personalized readings.
<br />
<br />A 7-day trial period costs us $13.76, but please choose the
amount that suits you best:
</p>
)}
<div className={styles["price-container"]}>
<PriceList

View File

@ -100,3 +100,9 @@
opacity: 1;
}
}
.text {
white-space: pre-wrap;
margin-top: 40px;
margin-bottom: 6px;
}

View File

@ -0,0 +1,96 @@
import { useDispatch, useSelector } from "react-redux";
import EmailSubstrate from "../../components/EmailSubstrate";
import styles from "./styles.module.scss";
import { actions, selectors } from "@/store";
import PriceList from "@/components/pages/ABDesign/v1/components/PriceList";
import { usePaywall } from "@/hooks/paywall/usePaywall";
import { EPlacementKeys } from "@/api/resources/Paywall";
import { ELocalesPlacement } from "@/locales";
import { useEffect, useRef, useState } from "react";
import Button from "../../components/Button";
import routes from "@/routes";
import { useNavigate, useOutletContext } from "react-router-dom";
import Loader from "@/components/Loader";
import { useTranslations } from "@/hooks/translations";
import { IOutletContext } from "@/routerComponents/Palmistry/v1/LayoutPersonalVideo";
function TrialChoiceVideo() {
const { translate } = useTranslations(ELocalesPlacement.PalmistryV1);
const navigate = useNavigate();
const dispatch = useDispatch();
const { products, isLoading, currency, getText } = usePaywall({
placementKey: EPlacementKeys["aura.placement.palmistry.redesign"],
localesPlacement: ELocalesPlacement.V1,
});
const [isDisabled, setIsDisabled] = useState(true);
const selectedPrice = useSelector(selectors.selectSelectedPrice);
const email = useSelector(selectors.selectEmail);
const homeConfig = useSelector(selectors.selectHome);
const containerVideoRef = useRef<HTMLDivElement>(null);
const { containerVideoRef: videoRef, isVisibleElements } =
useOutletContext<IOutletContext>();
const handlePriceItem = () => {
setIsDisabled(false);
};
const handleNext = () => {
if (isDisabled) {
return;
}
dispatch(
actions.siteConfig.update({
home: { pathFromHome: homeConfig.pathFromHome, isShowNavbar: false },
})
);
navigate(routes.client.palmistryV1TrialPayment());
};
useEffect(() => {
if (!containerVideoRef.current || !videoRef.current) return;
containerVideoRef.current?.appendChild(videoRef.current);
videoRef.current.classList.add(styles["personal-video"]);
}, [videoRef]);
useEffect(() => {
dispatch(actions.personalVideo.updateIsVideoPlaying(true));
}, [dispatch]);
return (
<div className={styles.container}>
<div ref={containerVideoRef} />
{!isLoading && isVisibleElements && (
<>
<EmailSubstrate className={styles["email-substrate"]} email={email} />
<div className={styles["price-container"]}>
<PriceList
products={products}
activeItem={selectedPrice}
classNameItem={styles["price-item"]}
classNameItemActive={`${styles["price-item-active"]}`}
classNamePricesContainer={styles["prices-container"]}
currency={currency}
click={handlePriceItem}
/>
<p className={styles["auxiliary-text"]}>{getText("text.1")}</p>
</div>
<Button
className={styles.button}
disabled={isDisabled}
onClick={handleNext}
>
{translate("next")}
</Button>
</>
)}
{isLoading && <Loader className={styles.loader} />}
</div>
);
}
export default TrialChoiceVideo;

View File

@ -0,0 +1,134 @@
.container {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
}
.email-substrate {
display: grid;
grid-template-columns: 1fr 36px;
align-content: center;
position: absolute;
max-width: calc(100% + 9px);
top: -18px;
right: -26px;
height: 46px;
filter: opacity(0);
will-change: opacity;
animation: appearance 1s forwards;
}
.title {
font-size: 28px;
line-height: 125%;
margin-top: 44px;
color: #2c2c2c;
font-weight: 500;
filter: opacity(0);
will-change: opacity;
animation: appearance 1s forwards 0.5s;
}
.prices-container {
justify-content: center;
gap: 10px;
width: fit-content;
margin: 0 auto;
filter: opacity(0);
will-change: opacity;
animation: appearance 1s forwards 1s;
}
.price-item {
border: solid #2c2c2c 1px;
width: 70px;
height: 65px;
font-size: 20px;
font-weight: 500;
&:last-child::after {
content: "";
position: absolute;
width: 2px;
height: 20px;
background-color: #224e90;
bottom: -30px;
left: 50%;
}
&.price-item-active {
border: solid #224e90 3px !important;
background-color: transparent;
color: #224e90;
}
}
.price-container {
position: relative;
width: 100%;
margin-top: 10px;
display: flex;
flex-direction: column;
gap: 32px;
}
.auxiliary-text {
font-size: 15px;
line-height: 125%;
font-weight: 600;
color: #0244a5;
width: 100%;
text-align: center;
filter: opacity(0);
will-change: opacity;
animation: appearance 1s forwards 1s;
}
.cursor {
position: absolute;
width: 2px;
height: 20px;
background-color: #224e90;
top: 71px;
right: 34px;
}
.loader {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.button {
margin-top: 20px;
transition: background 0.2s ease, color 0.2s ease;
filter: opacity(0);
will-change: opacity;
animation: appearance 1s forwards 1.5s;
&:disabled {
border: solid #224e90 1px;
background: none;
color: #120d0d;
opacity: 1;
}
}
.personal-video {
display: block;
margin-top: 44px !important;
border-radius: 0 !important;
background-image: url("/trial-choice-preview.png") !important;
}
@keyframes appearance {
0% {
filter: opacity(0);
}
100% {
filter: opacity(1);
}
}

View File

@ -11,9 +11,13 @@ import { ELocalesPlacement } from "@/locales";
import { useTranslations } from "@/hooks/translations";
import { useMemo } from "react";
import { ELottieKeys, useLottie } from "@/hooks/lottie/useLottie";
import { useSession } from "@/hooks/session/useSession";
import { IAnswersSession } from "@/api/resources/Session";
import { ESourceAuthorization } from "@/api/resources/User";
function WhatAspects() {
const { translate } = useTranslations(ELocalesPlacement.PalmistryV1);
const { updateSession } = useSession();
const dispatch = useDispatch();
const navigate = useNavigate();
const { whatAspects } = useSelector(selectors.selectPalmistryV1Answers);
@ -21,26 +25,35 @@ function WhatAspects() {
preloadKey: ELottieKeys.scalesHeartPalmistry,
});
const aspects = useMemo(
() => [
{
id: "love_and_relationships",
title: translate("/what-aspects.answer1"),
},
{
id: "health_and_vitality",
title: translate("/what-aspects.answer2"),
},
{
id: "career_destiny",
title: translate("/what-aspects.answer3"),
},
],
[translate]
);
const aspects: { id: IAnswersSession["what_aspects"]; title: string }[] =
useMemo(
() => [
{
id: "love_relationships",
title: translate("/what-aspects.answer1"),
},
{
id: "health_vitality",
title: translate("/what-aspects.answer2"),
},
{
id: "career_destiny",
title: translate("/what-aspects.answer3"),
},
],
[translate]
);
const handleClick = async (id: string) => {
const handleClick = async (id: IAnswersSession["what_aspects"]) => {
dispatch(actions.palmistryV1Answers.update({ whatAspects: id }));
await updateSession(
{
answers: {
what_aspects: id,
},
},
ESourceAuthorization["aura.palmistry.new"]
);
if (id !== whatAspects) await sleep(answerTimeOut);
navigate(routes.client.palmistryV1RelationshipStatus());
};

View File

@ -4,7 +4,7 @@ import styles from "./styles.module.scss";
import cn from "classnames";
import { EPlacementKeys, IPaywallProduct } from "@/api/resources/Paywall";
import { useNavigate } from "react-router-dom";
import { useLocation, useNavigate } from "react-router-dom";
import {
Dispatch,
LegacyRef,
@ -35,6 +35,10 @@ interface IPaymentModalNewProps {
placementKey: EPlacementKeys;
activeProduct: IPaywallProduct;
setHeight?: Dispatch<SetStateAction<number>>;
noProductRedirect?: {
pagesFrom: string[];
url: string;
};
}
export default function PaymentModalNew({
@ -42,9 +46,11 @@ export default function PaymentModalNew({
activeProduct,
placementKey,
setHeight,
noProductRedirect,
}: IPaymentModalNewProps) {
const { translate } = useTranslations(ELocalesPlacement.PalmistryV1);
const navigate = useNavigate();
const location = useLocation();
const ref = useRef<HTMLDivElement>();
const currency = useSelector(selectors.selectCurrency);
const [stripePromise, setStripePromise] =
@ -90,9 +96,16 @@ export default function PaymentModalNew({
(product) => product._id === activeProduct?._id
);
if (!activeProduct || !isActiveProduct) {
if (noProductRedirect) {
if (noProductRedirect.pagesFrom.includes(location.pathname)) {
return navigate(noProductRedirect.url);
}
return;
}
navigate(routes.client.trialChoice());
}
})();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [activeProduct, navigate, products, publicKey]);
const resizeHandler = () => {

View File

@ -9,7 +9,7 @@ import { ELocalesPlacement } from "@/locales";
function PaymentFailPage(): JSX.Element {
const { translate } = useTranslations(ELocalesPlacement.V1);
const navigate = useNavigate();
const handleNext = () => navigate(routes.client.trialPayment());
const handleNext = () => navigate(routes.client.trialPaymentV1());
return (
<section className={`${styles.page} page`}>

View File

@ -21,7 +21,7 @@ function PaymentSuccessPage(): JSX.Element {
const handleNext = () => {
dispatch(actions.status.update("subscribed"));
navigate(routes.client.addReport());
navigate(routes.client.addReportV1());
};
useEffect(() => {

View File

@ -9,6 +9,8 @@ import { useState } from "react";
import QuestionnaireGreenButton from "../../../../ui/GreenButton";
import { ELottieKeys, useLottie } from "@/hooks/lottie/useLottie";
import { ELocalesPlacement } from "@/locales";
import { useSession } from "@/hooks/session/useSession";
import { ESourceAuthorization } from "@/api/resources/User";
interface IBirthPlaceCustomAnswerProps {
affiliation?: "self" | "partner";
@ -18,6 +20,7 @@ function BirthPlaceCustomAnswer({
affiliation = "self",
}: IBirthPlaceCustomAnswerProps) {
const { translate } = useTranslations(ELocalesPlacement.V1);
const { updateSession } = useSession();
const navigate = useNavigate();
const dispatch = useDispatch();
const questionnaire = useSelector(selectors.selectQuestionnaire);
@ -43,11 +46,33 @@ function BirthPlaceCustomAnswer({
return dispatch(actions.questionnaire.update({ birthPlace }));
};
const handleNext = () => {
const handleNext = async () => {
if (affiliation === "partner") {
if (isKnownPartnerBirthPlace) {
await updateSession(
{
partner: {
birthplace: {
address: birthPlace,
},
},
},
ESourceAuthorization["aura.main.new"]
);
}
return navigate(routes.client.relationshipAlmostThereV1());
}
// affiliation === "self"
await updateSession(
{
profile: {
birthplace: {
address: birthPlace,
},
},
},
ESourceAuthorization["aura.main.new"]
);
return navigate(routes.client.loadingInRelationshipV1());
};
@ -62,7 +87,9 @@ function BirthPlaceCustomAnswer({
checked={!isKnownPartnerBirthPlace}
onChange={() => setIsKnownPartnerBirthPlace((prev) => !prev)}
/>
{translate("/questionnaire/partnerProfile/partnerBirthPlace.checkbox")}
{translate(
"/questionnaire/partnerProfile/partnerBirthPlace.checkbox"
)}
</label>
)}
<div className={styles.container}>

View File

@ -8,6 +8,8 @@ import routes from "@/routes";
import { useState } from "react";
import QuestionnaireGreenButton from "../../../../ui/GreenButton";
import { ELocalesPlacement } from "@/locales";
import { useSession } from "@/hooks/session/useSession";
import { ESourceAuthorization } from "@/api/resources/User";
interface IBirthtimeCustomAnswerProps {
affiliation?: "self" | "partner";
@ -17,6 +19,7 @@ function BirthtimeCustomAnswer({
affiliation = "self",
}: IBirthtimeCustomAnswerProps) {
const { translate } = useTranslations(ELocalesPlacement.V1);
const { updateSession } = useSession();
const navigate = useNavigate();
const dispatch = useDispatch();
const selfBirthtime = useSelector(selectors.selectBirthtime);
@ -24,6 +27,11 @@ function BirthtimeCustomAnswer({
const birthtimeFromStore =
affiliation === "self" ? selfBirthtime : questionnaire.partnerBirthtime;
const birthdate =
affiliation === "self"
? questionnaire.birthdate
: questionnaire.partnerBirthdate;
const [birthtime, setBirthtime] = useState(birthtimeFromStore);
const handleChange = (_birthtime: string) => {
@ -33,12 +41,22 @@ function BirthtimeCustomAnswer({
}
};
const handleNext = () => {
const handleNext = async () => {
if (affiliation === "self") {
await updateSession({
profile: {
birthdate: `${birthdate} ${birthtime}`,
},
}, ESourceAuthorization["aura.main.new"]);
dispatch(actions.questionnaire.update({ birthtime }));
navigate(`${routes.client.questionnaireV1()}/profile/birthPlace`);
}
if (affiliation === "partner") {
await updateSession({
partner: {
birthdate: `${birthdate} ${birthtime}`,
},
}, ESourceAuthorization["aura.main.new"]);
dispatch(actions.questionnaire.update({ partnerBirthtime: birthtime }));
navigate(
`${routes.client.questionnaireV1()}/partnerProfile/partnerBirthPlace`

View File

@ -0,0 +1,36 @@
import { useGenderInfo } from "@/components/pages/Mike/v1/lib/getGenderInfo";
import styles from "./styles.module.css";
import { PropsWithChildren } from "react";
import Header from "../../components/Header";
import Title from "@/components/Title";
interface DiscountLayoutProps {
title?: string;
}
function DiscountLayout({
children,
title,
}: PropsWithChildren<DiscountLayoutProps>) {
const genderInfo = useGenderInfo();
return (
<section
className={`${styles.page} page`}
style={{
backgroundColor: genderInfo?.id === "male" ? "#C0E5FF" : "#C0E5FF",
}}
>
<Header className={styles.header} />
{title && (
<Title variant="h2" className={styles.title}>
{title}
</Title>
)}
{children}
</section>
);
}
export default DiscountLayout;

View File

@ -0,0 +1,33 @@
.page {
height: fit-content;
align-items: center;
flex-direction: column;
height: 100%;
width: 100%;
max-width: 460px;
color: rgba(44, 44, 44, 1);
overflow-y: auto;
}
.header {
margin-bottom: 26px;
}
.title {
display: block;
width: calc(100% + 64px);
margin-inline: -32px;
padding-block: 8px;
font-size: 36px;
line-height: 1.3;
font-weight: 700;
margin-bottom: 16px;
background: linear-gradient(47.7deg, #FFA1BA 19.68%, #9A55FF 83.92%);
color: #fff;
}
@media (max-width: 390px) {
.title {
font-size: 30px;
}
}

View File

@ -1,6 +1,4 @@
import Title from "@/components/Title";
import styles from "./styles.module.css";
import MainButton from "@/components/MainButton";
import { useNavigate } from "react-router-dom";
import routes from "@/routes";
import { usePaywall } from "@/hooks/paywall/usePaywall";
@ -11,6 +9,8 @@ import { useEffect } from "react";
import { useTranslations } from "@/hooks/translations";
import { addCurrency, ELocalesPlacement } from "@/locales";
import Loader from "@/components/Loader";
import DiscountLayout from "../../layouts/Discount/DiscountLayout";
import QuestionnaireGreenButton from "../../ui/GreenButton";
function AdditionalDiscount() {
const { translate } = useTranslations(ELocalesPlacement.V1);
@ -42,55 +42,51 @@ function AdditionalDiscount() {
};
return (
<section className={`${styles.page} page`}>
<DiscountLayout title={translate("/additional-discount.header_title")}>
{isLoading && <Loader className={styles.loader} />}
{!isLoading && (
<>
<Title variant="h2" className={styles.title}>
{translate("/additional-discount.title", {
discount: (getText("discount.1") as string).replace("-", ""),
})}
</Title>
<img
src="/friends.webp"
alt="Friends"
style={{ minHeight: "180px" }}
/>
<div className={styles["discount-point"]}>
<img src="/fire.webp" alt="Fire" />
<p className={styles["discount-point-description"]}>
{translate("/additional-discount.description1", {
discount: (getText("discount.1") as string).replace("-", ""),
})}
</p>
</div>
<div className={styles["discount-point"]}>
<img src="/present.webp" alt="Present" />
<p className={styles["discount-point-description"]}>
{translate("/additional-discount.description2", {
trialDuration: activeProduct?.trialDuration,
})}
</p>
<div className={styles["discount-container"]}>
<div className={styles["discount-point"]}>
<img src="/fire.webp" alt="Fire" />
<p className={styles["discount-point-description"]}>
{translate("/additional-discount.description1", {
discount: (getText("discount.1") as string).replace("-", ""),
})}
</p>
</div>
<div className={styles["discount-point"]}>
<img src="/present.webp" alt="Present" />
<p className={styles["discount-point-description"]}>
{translate("/additional-discount.description2", {
trialDuration: activeProduct?.trialDuration,
})}
</p>
</div>
</div>
<p className={styles["discount-description"]}>
{translate("/additional-discount.price", {
price: (
<span>
<span className={styles["new-price"]}>
{addCurrency((activeProduct?.price || 0) / 100, currency)}
</span>
),
fullPrice: addCurrency(
Number(getText("full.price")) / 100,
currency
fullPrice: (
<span className={styles["old-price"]}>
{addCurrency(Number(getText("full.price")) / 100, currency)}
</span>
),
})}
</p>
<MainButton className={styles.button} onClick={handleNext}>
<QuestionnaireGreenButton
className={styles.button}
onClick={handleNext}
>
{translate("/additional-discount.button")}
</MainButton>
</QuestionnaireGreenButton>
</>
)}
</section>
</DiscountLayout>
);
}

View File

@ -1,74 +1,56 @@
.page {
position: relative;
height: fit-content;
min-height: 100dvh;
.discount-container {
margin-inline: -16px;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
background-position-y: top;
background-position-x: center;
background-size: contain;
background-repeat: no-repeat;
color: #fff;
padding-bottom: 64px;
background-image: url("/ellipse.webp");
background-color: #fff0f0;
color: #333333;
width: 100%;
max-width: 460px;
}
.title {
font-size: 32px;
line-height: 44px;
margin-bottom: 20px;
gap: 25px;
padding: 36px 38px;
background: #fff;
box-shadow: 2px 11px 17.1px -1px #00000021;
border-radius: 12px;
}
.discount-point {
display: flex;
flex-direction: row;
align-items: center;
justify-content: start;
gap: 20px;
width: 100%;
max-width: 262px;
margin-top: 20px;
}
.discount-point > img {
width: 48px;
height: 48px;
width: 60px;
height: 60px;
}
.discount-point-description {
font-weight: 700;
font-size: 18px;
line-height: 140%;
color: #000;
font-size: 24px;
line-height: 1.2;
}
.discount-description {
font-size: 16px;
margin-top: 20px;
margin-top: 44px;
font-size: 24px;
line-height: 1.2;
}
.discount-description > span {
color: #8e8cf0;
.new-price {
color: #9A55FF;
font-weight: 700;
background: linear-gradient(0deg, #FFA1BA 14.64%, #9A55FF 85.34%);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.old-price {
position: relative;
text-decoration: line-through;
}
.button {
background: rgb(187, 107, 217);
height: 50px;
min-height: 0;
min-width: 0;
max-width: 300px;
box-shadow: rgba(0, 0, 0, 0.25) 0px 4px 4px 0px;
border-radius: 16px;
margin-top: 16px;
font-size: 16px;
font-weight: normal;
min-height: auto;
border-radius: 20px;
margin-top: 8px;
box-shadow: 2px 11px 17.1px -1px rgba(0, 0, 0, 0.13);
}
.loader {

View File

@ -0,0 +1,3 @@
<svg width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14 0C11.2311 0 8.52431 0.821086 6.22202 2.35943C3.91973 3.89776 2.12532 6.08427 1.06569 8.64243C0.006066 11.2006 -0.271181 14.0155 0.269012 16.7313C0.809205 19.447 2.14258 21.9416 4.10051 23.8995C6.05844 25.8574 8.55301 27.1908 11.2687 27.731C13.9845 28.2712 16.7994 27.9939 19.3576 26.9343C21.9157 25.8747 24.1022 24.0803 25.6406 21.778C27.1789 19.4757 28 16.7689 28 14C27.9961 10.2882 26.5198 6.72949 23.8952 4.10483C21.2705 1.48017 17.7118 0.00391976 14 0ZM20.1465 11.5312L12.6081 19.0696C12.5081 19.1697 12.3893 19.2492 12.2586 19.3034C12.1278 19.3576 11.9877 19.3855 11.8462 19.3855C11.7046 19.3855 11.5645 19.3576 11.4338 19.3034C11.303 19.2492 11.1843 19.1697 11.0842 19.0696L7.85347 15.8388C7.65139 15.6368 7.53787 15.3627 7.53787 15.0769C7.53787 14.7911 7.65139 14.5171 7.85347 14.315C8.05554 14.1129 8.32961 13.9994 8.61539 13.9994C8.90117 13.9994 9.17524 14.1129 9.37731 14.315L11.8462 16.7852L18.6227 10.0073C18.7228 9.90725 18.8415 9.82788 18.9723 9.77373C19.103 9.71958 19.2431 9.69171 19.3846 9.69171C19.5261 9.69171 19.6662 9.71958 19.797 9.77373C19.9277 9.82788 20.0465 9.90725 20.1465 10.0073C20.2466 10.1074 20.326 10.2261 20.3801 10.3569C20.4343 10.4876 20.4621 10.6277 20.4621 10.7692C20.4621 10.9107 20.4343 11.0508 20.3801 11.1816C20.326 11.3123 20.2466 11.4311 20.1465 11.5312Z" fill="#716EFF"/>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,69 @@
import styles from "./styles.module.css";
import cn from "classnames";
import { IAdditionalPurchasesStep } from "@/data/additionalPurchases";
import { useRef } from "react";
import CheckMark from "./checkMark.svg";
import { useTranslations } from "@/hooks/translations";
import { ELocalesPlacement } from "@/locales";
interface IAdditionalPurchasesStepsProps {
steps: IAdditionalPurchasesStep[];
activeStep: number;
}
function AdditionalPurchasesSteps({
steps,
activeStep,
}: IAdditionalPurchasesStepsProps) {
const { translate } = useTranslations(ELocalesPlacement.V1);
const containerRef = useRef<HTMLDivElement>(null);
const titlesRef = useRef<Array<HTMLSpanElement | null>>([]);
return (
<div ref={containerRef} className={styles.container}>
<div className={styles["steps-container"]}>
{steps.map(({ title, id }, index) => (
<div
className={cn(styles["step-item"], {
[styles.active]: activeStep === id,
[styles["step-check"]]: activeStep > id,
})}
key={index}
>
<div className={styles["step-with-line"]}>
<div
className={cn(styles.step, {
[styles.active]: activeStep === id,
[styles["next-step"]]: activeStep === 0 && id === 1,
})}
>
<span
ref={(el) => (titlesRef.current[index] = el)}
className={styles.title}
key={index}
>
{translate(title)}
</span>
{activeStep < id && <div className={styles.circle} />}
{activeStep > id && (
<img src={CheckMark} alt="Circle with dote" />
)}
</div>
{id !== steps.length - 1 && (
<div
className={cn(styles.line, {
[styles["line-check"]]: activeStep > id,
})}
/>
)}
</div>
</div>
))}
</div>
</div>
);
}
export default AdditionalPurchasesSteps;

View File

@ -0,0 +1,152 @@
.container {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
padding: 4px 8px 0px;
}
.titles-container {
position: relative;
min-height: 32px;
height: fit-content;
display: flex;
flex-direction: row;
align-items: flex-end;
justify-content: space-between;
width: 100%;
}
.steps-container {
position: relative;
width: 100%;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
padding-top: 42px;
}
.step-item {
position: relative;
}
.step-item::after {
content: '';
position: absolute;
top: -4px;
left: -4px;
width: 34px;
height: 34px;
border-radius: 50%;
border-top: 1px solid rgba(198, 206, 236, 1);
border-left: 1px solid rgba(198, 206, 236, 1);
border-right: 1px solid #fff;
border-bottom: 1px solid #fff;
rotate: 45deg;
background: #fff;
z-index: 5;
}
.step-item:nth-child(2n):after {
rotate: -135deg;
}
.step-item:not(:last-child) {
width: 100%;
}
.step-item.active::after, .step-check::after {
border-top: 1px solid rgba(113, 110, 255, 1);
border-left: 1px solid rgba(113, 110, 255, 1);
}
.step-with-line {
display: flex;
flex-direction: row;
align-items: center;
padding-right: 6.25rem;
}
.step-with-line:last-child {
padding-right: 0;
}
.step {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
position: relative;
width: 28px;
height: 28px;
border-radius: 50%;
z-index: 9;
}
.title {
position: absolute;
font-weight: 400;
font-size: 14px;
line-height: 16px;
color: rgba(78, 103, 195, 1);
width: min-content;
text-align: center;
bottom: 40px;
min-width: 75px;
width: 100%;
}
.step.active {
background: rgba(113, 110, 255, 1);
}
.next-step .circle {
background-color: rgba(198, 206, 236, 1);
}
.title-first {
width: max-content;
left: 0;
}
.title-last {
right: 0;
text-align: right;
}
.circle {
background: #fff;
border: 4px solid rgba(198, 206, 236, 1);
width: 28px;
height: 28px;
border-radius: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.dote {
width: 10px;
height: 10px;
border-radius: 100%;
background: red;
}
.line {
width: calc(100% - 34px);
height: 1px;
background-color: rgba(198, 206, 236, 1);
position: absolute;
bottom: 14px;
left: 31px;
z-index: 6;
}
.line-check {
background-color: rgba(113, 110, 255, 1);
}
.active .line {
background: linear-gradient(90deg, rgba(113, 110, 255, 1), rgba(198, 206, 236, 1) );
}

View File

@ -0,0 +1,57 @@
import Title from "@/components/Title";
import styles from "./styles.module.css";
import Icon from "/v1/icon-heart-hand.webp";
import { useTranslations } from "@/hooks/translations";
import { addCurrency, ELocalesPlacement } from "@/locales";
import { useSelector } from "react-redux";
import { selectors } from "@/store";
import { useMemo } from "react";
interface IConsultationTableProps {
price: number;
}
function ConsultationTable({ price }: IConsultationTableProps) {
const { translate } = useTranslations(ELocalesPlacement.V1);
const currency = useSelector(selectors.selectCurrency);
const _price = useMemo(() => {
return addCurrency((price / 100).toFixed(2), currency);
}, [currency, price]);
return (
<div className={styles.container}>
<Title variant="h2" className={styles.title}>
{translate("/add-consultation.your_unique_consultation")}
</Title>
<div className={styles["center-container"]}>
<div className={styles.header}>
<img src={Icon} alt="Icon" />
<span>{translate("/add-consultation.30-minute")}</span>
</div>
</div>
<div className={styles.footer}>
<p className={styles.text}>
{translate("/add-consultation.description")}
</p>
<div className={styles["price-container"]}>
<span className={styles["one-time-price"]}>
{translate("/add-consultation.one_time_price_offer")} {_price}
</span>
<br />
<span className={styles["old-price-container"]}>
{translate("/add-consultation.original_price", {
oldPrice: addCurrency(99.99, currency),
discount: (
<span className={styles.save}>
{translate("/add-consultation.discount_save")} 50%
</span>
),
})}
</span>
</div>
</div>
</div>
);
}
export default ConsultationTable;

View File

@ -0,0 +1,95 @@
.container {
margin: 36px 6px 0;
padding: 15px 22px 32px;
display: flex;
flex-direction: column;
-webkit-box-align: center;
align-items: center;
position: relative;
border-radius: 10px;
box-shadow: 3px 4px 16.6px 0px rgba(0, 0, 0, 0.28);
}
.title {
font-weight: 600;
font-size: 24px;
line-height: 1.04;
color: rgba(44, 44, 44, 1);
text-align: center;
margin-bottom: 20px;
}
.center-container {
margin: 0 -44px 0 -14px;
padding: 6px 38px 6px 17px;
border-radius: 10px;
background: linear-gradient(90deg, rgba(54, 209, 220, 0.25) 0%, rgba(91, 134, 229, 0.25) 100%);
box-shadow: 3px 4px 4px 0px rgba(0, 0, 0, 0.25);
}
.center-container > .header {
display: flex;
align-items: center;
gap: 14px;
}
.center-container > .header > img {
width: 54px;
height: 54px;
}
.center-container > .header > span {
-webkit-text-fill-color: transparent;
background-image: linear-gradient(90deg, #152331 0%, #000000 100%);
background-clip: text;
color: #000;
font-size: 18px;
line-height: 1.4;
font-weight: 400;
}
.footer {
padding: 23px 0 0;
width: 100%;
}
.footer > .text {
margin-bottom: 30px;
color: rgba(44, 44, 44, 1);
font-size: 15px;
font-weight: 500;
line-height: 1.4;
}
.price-container {
margin: 0 12px;
}
.one-time-price {
color: rgba(44, 44, 44, 1);
font-weight: 400;
font-size: 16px;
line-height: 1.2;
}
.old-price-container {
display: block;
margin-top: 3px;
color: rgba(145, 145, 145, 1);
font-size: 15px;
font-weight: 500;
line-height: 1.4;
}
.save {
display: inline-block;
margin-left: 6px;
padding: 0px 6px;
border-radius: 50px;
font-size: 15px;
line-height: 25px;
/* height: 25px; */
color: #fff;
background: linear-gradient(90.02deg, #05D4B6 22.83%, #22908E 74.26%, #0CC3AC 93.75%),
linear-gradient(104.1deg, rgba(58, 113, 109, 0.2) 18.93%, rgba(60, 60, 60, 0.2) 54.17%, rgba(33, 136, 137, 0.2) 67.72%);
}

View File

@ -0,0 +1,17 @@
import { ELocalesPlacement } from "@/locales";
import styles from "./styles.module.css";
import { useTranslations } from "@/hooks/translations";
function Copyright() {
const { translate } = useTranslations(ELocalesPlacement.V1);
return (
<p className={styles.copyright}>
{translate("copyright", {
year: new Date().getFullYear(),
})}
</p>
);
}
export default Copyright;

View File

@ -0,0 +1,8 @@
.copyright {
display: block;
width: 100%;
font-size: 11px;
line-height: 1.2;
color: rgba(77, 77, 77, 1);
text-align: center;
}

View File

@ -0,0 +1,57 @@
import { firstSliderList } from "@/data/additionalPurchases";
import styles from "./styles.module.css";
import { useTranslations } from "@/hooks/translations";
import { addCurrency, ELocalesPlacement } from "@/locales";
import { useSelector } from "react-redux";
import { selectors } from "@/store";
import { useMemo } from "react";
interface IFirstSlideProps {
price: number;
classNameSlide?: string;
}
function FirstSlide({ price, classNameSlide = "" }: IFirstSlideProps) {
const { translate } = useTranslations(ELocalesPlacement.V1);
const currency = useSelector(selectors.selectCurrency);
const _price = useMemo(() => {
return addCurrency((price / 100).toFixed(2), currency);
}, [currency, price]);
return (
<div className={styles.container}>
<div className={classNameSlide}>
<img
className={styles.image}
src="/v1/smartphone-1.webp"
alt="Premium Intro"
/>
<div className={styles["right-half"]}>
<ul className={styles.list}>
{firstSliderList.map((item, index) => (
<li className={styles.item} key={index}>
<span style={{ backgroundImage: `url(${item.icon})` }} />
<p>{translate(item.title)}</p>
</li>
))}
<li className={styles.item}>
<span>5</span>
<p>minutes to read</p>
</li>
</ul>
<div className={styles.bottom}>
<div className={styles.links}>
<img src="/v1/get_on_appstore.svg" alt="get on appstore" />
</div>
<p className={styles.price}>
{_price.split(".")[0]}
<sup>{_price.split(".")[1]}</sup>
</p>
</div>
</div>
</div>
</div>
);
}
export default FirstSlide;

View File

@ -0,0 +1,85 @@
.container {
padding: 0 10px;
}
.image {
width: calc(46.5% - 16px);
object-fit: contain;
}
.right-half {
display: flex;
flex-direction: column;
margin-left: 14px;
padding-bottom: 6px;
}
.list {
margin-top: auto;
display: flex;
flex-direction: column;
gap: 8px;
}
.item {
font-size: 13px;
display: flex;
-webkit-box-align: center;
align-items: start;
color: #fff;
}
.item p::first-letter {
text-transform: uppercase;
}
.item > span {
display: inline-block;
background-size: contain;
background-position: center center;
background-repeat: no-repeat;
width: 18px;
height: 18px;
margin-right: 6px;
flex-shrink: 0;
margin-top: -3px;
text-align: center;
font-size: 18px;
font-weight: 800;
color: rgba(113, 110, 255, 1);
}
.bottom {
display: flex;
align-items: flex-end;
justify-content: space-between;
margin-right: 6px;
}
.bottom .links {
display: flex;
flex-direction: column;
margin-bottom: 5px;
gap: 2px;
}
.bottom > .price {
border-radius: 50px;
padding: 12px 15px 8px;
font-weight: 700;
display: flex;
-webkit-box-align: center;
align-items: center;
font-size: 17px;
line-height: 1.2;
color: rgba(44, 44, 44, 1);
background: #fff;
box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25);
}
.bottom > .price > sup {
font-size: 9px;
font-weight: 700;
position: relative;
top: -6px;
}

View File

@ -0,0 +1,52 @@
import MainButton from "@/components/MainButton";
import styles from "./styles.module.css";
import { useTranslations } from "@/hooks/translations";
import { ELocalesPlacement } from "@/locales";
import BlurComponent from "@/components/BlurComponent";
import { useDetectSticky } from "@/hooks/useDetectSticky";
interface IFooterButtonProps {
classNameContainer?: string;
classNameButton?: string;
classNameSkip?: string;
children?: React.ReactNode;
disabled?: boolean;
onClick: () => void;
onClickSkip: () => void;
}
function FooterButton({
children,
onClick,
onClickSkip,
classNameContainer = "",
classNameButton = "",
classNameSkip = "",
disabled = false,
}: IFooterButtonProps) {
const { translate } = useTranslations(ELocalesPlacement.V1);
const { isSticky, ref: blurRef } = useDetectSticky<HTMLDivElement>();
return (
<BlurComponent
className={`${styles.container} ${classNameContainer}`}
isActiveBlur={isSticky}
ref={blurRef}
>
{/* <BlurComponent> */}
<MainButton
className={`${styles.button} ${classNameButton}`}
disabled={disabled}
onClick={onClick}
>
{children}
</MainButton>
<p onClick={onClickSkip} className={`${styles.skip} ${classNameSkip}`}>
{translate("skip_this_offer")}
</p>
</BlurComponent>
// </div>
);
}
export default FooterButton;

View File

@ -0,0 +1,42 @@
.container {
display: flex;
flex-direction: column;
width: 100%;
-webkit-box-align: center;
align-items: center;
position: sticky;
bottom: -4px;
left: 0;
margin-top: 0px;
padding-bottom: 20px;
z-index: 5;
padding-left: 15px;
padding-right: 15px;
}
.button {
border-radius: 8px;
margin-bottom: 8px;
min-height: 0;
height: 60px;
max-width: 360px;
width: 100%;
background: linear-gradient(90.02deg, #05D4B6 22.83%, #22908E 74.26%, #0CC3AC 93.75%),
linear-gradient(104.1deg, rgba(58, 113, 109, 0.2) 18.93%, rgba(60, 60, 60, 0.2) 54.17%, rgba(33, 136, 137, 0.2) 67.72%);
color: #fff;
font-size: 19px;
font-weight: 500;
z-index: 10;
}
.skip {
position: relative;
text-decoration: underline;
text-underline-offset: 3px;
font-size: 14px;
text-align: center;
z-index: 5;
user-select: none;
cursor: pointer;
z-index: 10;
}

View File

@ -0,0 +1,18 @@
import { useTranslations } from "@/hooks/translations";
import styles from "./styles.module.css";
import { ELocalesPlacement } from "@/locales";
interface IPaymentAddressProps {
className?: string;
}
function PaymentAddress({ className = "" }: IPaymentAddressProps) {
const { translate } = useTranslations(ELocalesPlacement.V1);
return (
<p className={`${styles.address} ${className}`}>
{translate("payment_modal.address")}
</p>
);
}
export default PaymentAddress;

View File

@ -0,0 +1,7 @@
.address {
margin-bottom: 8px;
color: rgba(77, 77, 77, 1);
font-size: 11px;
text-align: center;
text-transform: uppercase;
}

View File

@ -0,0 +1,3 @@
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M15 0C12.0333 0 9.13319 0.879735 6.66645 2.52796C4.19971 4.17618 2.27713 6.51886 1.14181 9.25975C0.00649926 12.0006 -0.290551 15.0166 0.288227 17.9264C0.867006 20.8361 2.29562 23.5088 4.3934 25.6066C6.49119 27.7044 9.16394 29.133 12.0736 29.7118C14.9834 30.2906 17.9994 29.9935 20.7403 28.8582C23.4811 27.7229 25.8238 25.8003 27.472 23.3335C29.1203 20.8668 30 17.9667 30 15C29.9958 11.023 28.4141 7.21017 25.602 4.39804C22.7898 1.5859 18.977 0.00419974 15 0ZM21.5856 12.3548L13.5087 20.4317C13.4015 20.539 13.2742 20.6241 13.1342 20.6822C12.9941 20.7402 12.8439 20.7701 12.6923 20.7701C12.5407 20.7701 12.3905 20.7402 12.2505 20.6822C12.1104 20.6241 11.9831 20.539 11.876 20.4317L8.41443 16.9702C8.19792 16.7537 8.07629 16.46 8.07629 16.1538C8.07629 15.8477 8.19792 15.554 8.41443 15.3375C8.63094 15.121 8.92459 14.9994 9.23077 14.9994C9.53696 14.9994 9.83061 15.121 10.0471 15.3375L12.6923 17.9841L19.9529 10.7221C20.0601 10.6149 20.1874 10.5299 20.3274 10.4719C20.4675 10.4138 20.6176 10.384 20.7692 10.384C20.9208 10.384 21.071 10.4138 21.211 10.4719C21.3511 10.5299 21.4784 10.6149 21.5856 10.7221C21.6928 10.8293 21.7778 10.9566 21.8358 11.0967C21.8939 11.2367 21.9237 11.3868 21.9237 11.5385C21.9237 11.6901 21.8939 11.8402 21.8358 11.9803C21.7778 12.1203 21.6928 12.2476 21.5856 12.3548Z" fill="#85B6FF"/>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,76 @@
import { ISignUpOffer } from "@/data/additionalPurchases";
import styles from "./styles.module.css";
import CheckMark from "./check-mark-1.svg?react";
import { getPriceCentsToDollars } from "@/services/price";
import { useTranslations } from "@/hooks/translations";
import { addCurrency, ELocalesPlacement } from "@/locales";
import { useSelector } from "react-redux";
import { selectors } from "@/store";
import cn from "classnames";
interface ISignUpOfferProps extends ISignUpOffer {
isActive: boolean;
onClick: () => void;
}
function SignUpOffer(props: ISignUpOfferProps) {
const { id, subtitle, emoji, isActive, onClick } = props;
const { current, old, discount } = props.price;
const { translate } = useTranslations(ELocalesPlacement.V1);
const currency = useSelector(selectors.selectCurrency);
return (
<div
className={`${styles.container} ${isActive && styles.active}`}
onClick={onClick}
>
<span
className={styles.emoji}
style={{ backgroundImage: `url(/${emoji})` }}
></span>
<div className={styles["text-container"]}>
<div className={styles["title-container"]}>
<p className={styles.title}>
{translate(`/add-report.products.${id}.title`)}
</p>
<div
className={cn(styles["discount-container"], {
[styles.active]: id === "ultra_pack",
})}
>
<span className={styles.discount}>
{translate(`/add-report.products.${id}.discount`, {
discount,
})}
</span>
</div>
</div>
{!!subtitle?.length && (
<span className={styles.subtitle}>
{translate(`/add-report.products.${id}.description`)}
</span>
)}
<div className={styles["price-container"]}>
<span className={styles.price}>
{translate(`/add-report.products.${id}.price`, {
price: (
<span className={styles["current-price"]}>
{addCurrency(getPriceCentsToDollars(current || 0), currency)}
</span>
),
oldPrice: (
<span className={styles["old-price"]}>
{addCurrency(getPriceCentsToDollars(old || 0), currency)}
</span>
),
})}
</span>
</div>
</div>
<div className={styles.mark}>{isActive && <CheckMark />}</div>
</div>
);
}
export default SignUpOffer;

View File

@ -0,0 +1,124 @@
.container {
display: flex;
-webkit-box-align: center;
align-items: center;
-webkit-box-pack: justify;
justify-content: space-between;
border: unset;
box-sizing: border-box;
cursor: pointer;
padding: 15px 17px 21px 13px;
margin-left: auto;
margin-right: auto;
border-radius: 20px;
color: #000;
max-width: 450px;
width: 100%;
background: rgba(248, 248, 248, 1);
box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25);
}
.container.active {
}
.mark {
flex-shrink: 0;
border-radius: 50%;
margin-left: 10px;
width: 30px;
height: 30px;
display: flex;
-webkit-box-align: center;
align-items: center;
-webkit-box-pack: center;
justify-content: center;
border: 1px solid rgba(110, 159, 255, 1);
}
.text-container {
display: flex;
flex-direction: column;
-webkit-box-flex: 1;
flex-grow: 1;
margin-left: 16px;
}
.title-container {
width: 100%;
display: flex;
-webkit-box-align: center;
align-items: center;
}
.title {
font-weight: 600;
text-transform: uppercase;
font-size: 12px;
line-height: 135%;
}
.subtitle {
color: rgba(65, 60, 175, 1);
font-size: 12px;
line-height: 135%;
margin-bottom: 5px;
}
.price-container {
margin-top: 4px;
font-size: 12px;
font-weight: 400;
color: #000;
}
.current-price {
font-size: 14px;
}
.old-price {
}
.discount-container {
border-radius: 50px;
display: inline-block;
margin-left: 10px;
padding: 3px 6px;
text-align: center;
background: #fff;
border: 1px solid rgba(255, 110, 110, 1);
}
.discount {
font-size: 12px;
line-height: 1.2;
vertical-align: middle;
color: rgba(44, 44, 44, 1);
}
.discount-container.active {
background: rgba(255, 110, 110, 1);
}
.discount-container.active .discount {
color: #fff;
}
.emoji {
display: inline-block;
background-size: contain;
background-position: center center;
background-repeat: no-repeat;
width: 26px;
height: 26px;
}
@media (max-width: 380px) {
.text-container {
margin-left: 8px;
}
.mark {
margin-left: 8px;
}
}

View File

@ -0,0 +1,5 @@
<svg width="37" height="37" viewBox="0 0 37 37" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="18.4996" cy="18.5" r="15.2826" transform="rotate(180 18.4996 18.5)" fill="#094FA5"/>
<path d="M0 18.5C0 8.28273 8.28273 0 18.5 0C28.7173 0 37 8.28273 37 18.5C37 28.7173 28.7173 37 18.5 37C8.28273 37 0 28.7173 0 18.5ZM36.0357 18.5C36.0357 8.8153 28.1847 0.964302 18.5 0.964302C8.8153 0.964302 0.964302 8.8153 0.964302 18.5C0.964302 28.1847 8.8153 36.0357 18.5 36.0357C28.1847 36.0357 36.0357 28.1847 36.0357 18.5Z" fill="#094FA5"/>
<path d="M16.5607 23.326L21.7178 18.0978L16.5607 12.8695L15.283 14.1649L19.1623 18.0978L15.283 22.0307L16.5607 23.326Z" fill="#F8F8F8"/>
</svg>

After

Width:  |  Height:  |  Size: 683 B

View File

@ -0,0 +1,16 @@
import { DetailedHTMLProps, HTMLAttributes } from "react";
import styles from "./styles.module.css";
import Arrow from "./arrow.svg?react";
function SliderNextArrow(
props: DetailedHTMLProps<HTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
) {
const { className, style, onClick } = props;
return (
<button onClick={onClick} className={`${styles.arrow} ${className}`}>
<Arrow style={style} />
</button>
);
}
export default SliderNextArrow;

View File

@ -0,0 +1,10 @@
.arrow {
z-index: 2 !important;
width: 37px !important;
height: 37px !important;
right: -7px !important;
}
.arrow::before {
content: none!important;
}

View File

@ -0,0 +1,20 @@
import { DetailedHTMLProps, HTMLAttributes } from "react";
import styles from "./styles.module.css";
import Arrow from "../SliderNextArrow/arrow.svg?react";
function SliderPrevArrow(
props: DetailedHTMLProps<HTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
) {
const { className, style, onClick } = props;
return (
<button
className={`${styles.arrow} ${className}`}
style={style}
onClick={onClick}
>
<Arrow />
</button>
);
}
export default SliderPrevArrow;

View File

@ -0,0 +1,11 @@
.arrow {
z-index: 2 !important;
width: 37px !important;
height: 37px !important;
left: -7px !important;
transform: translate(0px, -50%) scale(-1) !important;
}
.arrow::before {
content: none!important ;
}

View File

@ -0,0 +1,26 @@
import Title from "@/components/Title";
import styles from "./styles.module.css";
import { useTranslations } from "@/hooks/translations";
import { ELocalesPlacement } from "@/locales";
function ThankYouBanner() {
const { translate } = useTranslations(ELocalesPlacement.V1);
return (
<div className={styles.container}>
<img
className={styles.image}
src="/smiling-face-with-hearts.webp"
alt="Love"
/>
<div className={styles["text-container"]}>
<Title variant="h4" className={styles.title}>
{translate("/add-report.thank_you")}
</Title>
<p className={styles.text}>{translate("/add-report.order_successful")}</p>
</div>
</div>
);
}
export default ThankYouBanner;

View File

@ -0,0 +1,32 @@
.container {
margin: 12px -24px 0;
margin-top: 12px;
padding: 12px 27px 16px;
background-color: rgba(193, 229, 255, 1);
border-radius: 8px;
display: flex;
flex-direction: row;
align-items: center;
gap: 13px;
color: rgba(44, 44, 44, 1);
height: min-content;
}
.image {
height: 31px;
aspect-ratio: 1 / 1;
}
.title {
text-align: left;
margin-bottom: 0px;
font-size: 20px;
font-weight: 500;
line-height: 135%;
}
.text {
font-size: 16px;
line-height: 20px;
font-weight: 500;
}

View File

@ -0,0 +1,21 @@
import { Outlet } from "react-router-dom";
import AdditionalPurchasesSteps from "./components/AdditionalPurchasesSteps";
import styles from "./styles.module.css";
import { steps } from "@/data/additionalPurchases";
import Header from "../../components/Header";
function AdditionalPurchases() {
const activeStep = steps.findIndex((value) =>
window.location.href.includes(value.link)
);
return (
<section className={`${styles.page} page`}>
<Header className={styles.header} />
<AdditionalPurchasesSteps steps={steps} activeStep={activeStep} />
<Outlet />
</section>
);
}
export default AdditionalPurchases;

View File

@ -0,0 +1,138 @@
import Title from "@/components/Title";
import styles from "./styles.module.css";
import ConsultationTable from "../../components/ConsultationTable";
import FooterButton from "../../components/FooterButton";
import { useNavigate } from "react-router-dom";
import routes from "@/routes";
import { useAuth } from "@/auth";
import { SinglePayment, useApi, useApiCall } from "@/api";
import { useSelector } from "react-redux";
import { selectors } from "@/store";
import { useCallback, useState } from "react";
import { ResponsePost } from "@/api/resources/SinglePayment";
import { createSinglePayment } from "@/services/singlePayment";
import Modal from "@/components/Modal";
import PaymentForm from "@/components/pages/SinglePaymentPage/PaymentForm";
import { getPriceCentsToDollars } from "@/services/price";
import Loader, { LoaderColor } from "@/components/Loader";
import { useTranslations } from "@/hooks/translations";
import { ELocalesPlacement } from "@/locales";
import Copyright from "../../components/Copyright";
function AddConsultationPage() {
const navigate = useNavigate();
const { translate } = useTranslations(ELocalesPlacement.V1);
const { user: userFromStore } = useAuth();
const api = useApi();
const tokenFromStore = useSelector(selectors.selectToken);
const [isLoading, setIsLoading] = useState(false);
const [paymentIntent, setPaymentIntent] = useState<ResponsePost | null>(null);
const [isError, setIsError] = useState(false);
const returnUrl = `${window.location.protocol}//${
window.location.host
}${routes.client.getInformationPartner()}`;
const loadData = useCallback(async () => {
return await api.getSinglePaymentProducts({ token: tokenFromStore });
}, [api, tokenFromStore]);
const { data: products, isPending: isPendingProducts } =
useApiCall<SinglePayment.ResponseGet[]>(loadData);
const currentProduct = products?.find(
(product) => product.key === "main.unique.individual.consultation"
);
const handleClick = async () => {
try {
if (!userFromStore || !currentProduct) return;
setIsLoading(true);
const { _id, key } = currentProduct;
const paymentInfo = {
productId: _id,
key,
};
const paymentIntent = await createSinglePayment(
userFromStore,
paymentInfo,
tokenFromStore,
userFromStore.email,
userFromStore.profile.full_name,
userFromStore.profile.birthday,
returnUrl,
api
);
setPaymentIntent(paymentIntent);
if ("payment" in paymentIntent) {
if (paymentIntent.payment.status === "paid")
return navigate(routes.client.getInformationPartner());
return setIsError(true);
}
} catch (error) {
setIsError(true);
} finally {
setIsLoading(false);
}
};
const handleClickSkip = () => {
navigate(routes.client.getInformationPartner());
};
return (
<div className={styles.container}>
{!isLoading &&
paymentIntent &&
"paymentIntent" in paymentIntent &&
!!tokenFromStore.length && (
<>
<Modal
open={!!paymentIntent}
onClose={() => setPaymentIntent(null)}
>
<Title variant="h1" className={styles["modal-title"]}>
{getPriceCentsToDollars(currentProduct?.price || 0)}$
</Title>
<PaymentForm
stripePublicKey={paymentIntent.paymentIntent.data.public_key}
clientSecret={paymentIntent.paymentIntent.data.client_secret}
returnUrl={returnUrl}
/>
</Modal>
</>
)}
{!currentProduct?.price && (
<Loader className={styles.loader} color={LoaderColor.Black} />
)}
{!!currentProduct?.price && (
<>
<Title variant="h2" className={styles.title}>
{translate("/add-consultation.more_for_you")}
</Title>
<Title variant="h2" className={styles.subtitle}>
{translate("/add-consultation.exclusive_offer")}
</Title>
<ConsultationTable price={currentProduct?.price || 0} />
<p className={styles.description}>
{translate("/add-consultation.you_will_be_charged")}
</p>
{isError && <p className={styles.error}>{translate("went_wrong")}</p>}
<FooterButton
onClick={handleClick}
onClickSkip={handleClickSkip}
disabled={isPendingProducts || isLoading}
classNameButton={styles.button}
>
{isPendingProducts || isLoading ? (
<Loader color={LoaderColor.White} />
) : (
translate("/add-consultation.get_my_consultation")
)}
</FooterButton>
<Copyright />
</>
)}
</div>
);
}
export default AddConsultationPage;

View File

@ -0,0 +1,65 @@
@font-face {
font-display: swap;
font-family: SF Pro Text;
font-style: normal;
font-weight: 300;
src: url(/src/assets/media/sf-pro-text-light.woff) format("woff")
}
.container {
width: 100%;
}
.loader {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.title {
text-align: center;
font-size: 26px;
font-weight: 600;
line-height: 1;
color: #000;
margin-top: 40px;
margin-bottom: 0;
}
.subtitle {
margin-top: 10px;
font-size: 19px;
line-height: 1.2;
text-align: center;
font-weight: 400;
color: #000;
margin-bottom: 0;
}
.description {
margin-top: 22px;
margin-bottom: 40px;
font-size: 13px;
font-weight: 300;
max-width: 370px;
margin-left: auto;
margin-right: auto;
text-align: center;
line-height: 1.25;
color: rgba(77, 77, 77, 1);
white-space: pre-wrap;
}
.button {
max-width: 310px;
}
.error {
max-width: 526px;
margin-left: auto;
margin-right: auto;
text-align: center;
font-size: 14px;
color: red;
}

View File

@ -0,0 +1,158 @@
import styles from "./styles.module.css";
import Title from "@/components/Title";
import ThankYouBanner from "../../components/ThankYouBanner";
import { signUpOffers } from "@/data/additionalPurchases";
import SignUpOffer from "../../components/SignUpOffer";
import { useCallback, useState } from "react";
import { useNavigate } from "react-router-dom";
import FooterButton from "../../components/FooterButton";
import routes from "@/routes";
import { createSinglePayment } from "@/services/singlePayment";
import { ResponsePost } from "@/api/resources/SinglePayment";
import { useAuth } from "@/auth";
import { useSelector } from "react-redux";
import { selectors } from "@/store";
import { SinglePayment, useApi, useApiCall } from "@/api";
import Loader, { LoaderColor } from "@/components/Loader";
import { getPriceCentsToDollars } from "@/services/price";
import Modal from "@/components/Modal";
import PaymentForm from "@/components/pages/SinglePaymentPage/PaymentForm";
import { useTranslations } from "@/hooks/translations";
import { ELocalesPlacement } from "@/locales";
import Copyright from "../../components/Copyright";
function AddReportPage() {
const navigate = useNavigate();
const { translate } = useTranslations(ELocalesPlacement.V1);
const { user: userFromStore } = useAuth();
const api = useApi();
const tokenFromStore = useSelector(selectors.selectToken);
const [paymentIntent, setPaymentIntent] = useState<ResponsePost | null>(null);
const [isLoading, setIsLoading] = useState(false);
const [isError, setIsError] = useState(false);
const [activeOffer, setActiveOffer] = useState(signUpOffers[0]);
const returnUrl = `${window.location.protocol}//${
window.location.host
}${routes.client.unlimitedReadingsV1()}`;
const loadData = useCallback(async () => {
return await api.getSinglePaymentProducts({ token: tokenFromStore });
}, [api, tokenFromStore]);
const { data: products, isPending: isPendingProducts } =
useApiCall<SinglePayment.ResponseGet[]>(loadData);
const getCurrentProduct = (id: string) => {
return products?.find((product) => product.key === id) || null;
};
const handleClick = async () => {
try {
if (!userFromStore || !activeOffer) return;
const currentProduct = getCurrentProduct(activeOffer?.productKey);
if (!currentProduct) return;
setIsLoading(true);
const { _id, key } = currentProduct;
const paymentInfo = {
productId: _id,
key,
};
const paymentIntent = await createSinglePayment(
userFromStore,
paymentInfo,
tokenFromStore,
userFromStore.email,
userFromStore.profile.full_name,
userFromStore.profile.birthday,
returnUrl,
api
);
setPaymentIntent(paymentIntent);
if ("payment" in paymentIntent) {
if (paymentIntent.payment.status === "paid")
return navigate(routes.client.unlimitedReadingsV1());
return setIsError(true);
}
} catch (error) {
setIsError(true);
} finally {
setIsLoading(false);
}
};
const handleClickSkip = () => {
navigate(routes.client.unlimitedReadingsV1());
};
return (
<div className={styles.container}>
{!isLoading &&
paymentIntent &&
"paymentIntent" in paymentIntent &&
!!tokenFromStore.length && (
<>
<Modal
open={!!paymentIntent}
onClose={() => setPaymentIntent(null)}
>
<Title variant="h1" className={styles["modal-title"]}>
{getPriceCentsToDollars(activeOffer.price.current || 0)}$
</Title>
<PaymentForm
stripePublicKey={paymentIntent.paymentIntent.data.public_key}
clientSecret={paymentIntent.paymentIntent.data.client_secret}
returnUrl={returnUrl}
/>
</Modal>
</>
)}
<ThankYouBanner />
<Title variant="h2" className={styles.title}>
{translate("/add-report.choose_offer")}
</Title>
<Title variant="h3" className={styles.subtitle}>
{translate("/add-report.available_only_now")}
</Title>
<div className={styles["offers-container"]}>
{!isPendingProducts &&
signUpOffers.map((offer, index) => (
<SignUpOffer
key={index}
isActive={offer.id === activeOffer.id}
onClick={() => setActiveOffer(offer)}
{...offer}
price={{
...offer.price,
current: getCurrentProduct(offer.productKey)?.price || 0,
}}
/>
))}
{isPendingProducts && <Loader color={LoaderColor.Black} />}
</div>
<p className={styles.description}>
{translate("/add-report.description")}
</p>
{isError && (
<p className={`${styles.description} ${styles.error}`}>
{translate("went_wrong")}
</p>
)}
<FooterButton
onClick={handleClick}
onClickSkip={handleClickSkip}
disabled={isPendingProducts || isLoading}
classNameButton={styles.button}
>
{isLoading ? (
<Loader color={LoaderColor.White} />
) : (
translate("/add-report.v1.continue")
)}
</FooterButton>
<Copyright />
</div>
);
}
export default AddReportPage;

Some files were not shown because too many files have changed in this diff Show More