diff --git a/package-lock.json b/package-lock.json index 383d54d..b231fc4 100755 --- a/package-lock.json +++ b/package-lock.json @@ -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", diff --git a/package.json b/package.json index 8e98bcf..c6bbbbe 100755 --- a/package.json +++ b/package.json @@ -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" } } diff --git a/public/locales/v1/de/female_de.json b/public/locales/v1/de/female_de.json index e2b3d5d..df7eadd 100644 --- a/public/locales/v1/de/female_de.json +++ b/public/locales/v1/de/female_de.json @@ -14,6 +14,7 @@ "privacy_policy": "Datenschutzbestimmungen", "terms_of_use": "Nutzungsbedingungen", "policy": "Ich stimme den , den sowie der Verwendung von Cookies und Tracking-Technologien, die Ihre Zustimmung erfordern, zu", + "copyright": "@ 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: Sparen Sie %", + "original_price": "Originalpreis: ", "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 Rabatt!", "description1": " Rabatt auf Ihren personalisierten Plan", "description2": "-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 don’t share any personal information." + "not_share": "We don’t share any personal information.", + "placeholder_email": "Ihre E-Mail", + "placeholder_name": "Ihr Name" }, "went_wrong": "Something went wrong.", "app_number_one": { diff --git a/public/locales/v1/de/male_de.json b/public/locales/v1/de/male_de.json index e048ec7..48db8e8 100644 --- a/public/locales/v1/de/male_de.json +++ b/public/locales/v1/de/male_de.json @@ -14,6 +14,7 @@ "privacy_policy": "Datenschutzerklärung", "terms_of_use": "Nutzungsbedingungen", "policy": "Ich stimme der , den sowie der Verwendung von Cookies und Tracking-Technologien zu, die deine Zustimmung erfordern.", + "copyright": "@ 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: Spare %", + "original_price": "Originalpreis: ", "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 Rabatt!", "description1": " Rabatt auf deinen personalisierten Plan", "description2": "-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 don’t share any personal information." + "not_share": "We don’t share any personal information.", + "placeholder_email": "Deine E-Mail-Adresse", + "placeholder_name": "Dein Name" }, "went_wrong": "Something went wrong.", "app_number_one": { diff --git a/public/locales/v1/en/female_en.json b/public/locales/v1/en/female_en.json index cef0b05..f342177 100644 --- a/public/locales/v1/en/female_en.json +++ b/public/locales/v1/en/female_en.json @@ -31,6 +31,7 @@ "privacy_policy": "Privacy Policy", "terms_of_use": "Terms of use", "policy": "I agree to the , and to the use of cookies and tracking technologies, that require your consent", + "copyright": "@ 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: Save %", + "original_price": "Original price: ", "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 off!", "description1": " off on your personalized plan", "description2": "-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 don’t share any personal information." + "not_share": "We don’t 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: ", "app_number_one_color": "25 million people.", "app_number_one": "The #1 Astrology app trusted by over " + }, + "/camera": { + "bad_photo": "Bad photo!", + "try_again": "Try again", + "do_better": "You can do it better", + "next": "Next" } } } diff --git a/public/locales/v1/en/male_en.json b/public/locales/v1/en/male_en.json index cef0b05..f342177 100644 --- a/public/locales/v1/en/male_en.json +++ b/public/locales/v1/en/male_en.json @@ -31,6 +31,7 @@ "privacy_policy": "Privacy Policy", "terms_of_use": "Terms of use", "policy": "I agree to the , and to the use of cookies and tracking technologies, that require your consent", + "copyright": "@ 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: Save %", + "original_price": "Original price: ", "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 off!", "description1": " off on your personalized plan", "description2": "-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 don’t share any personal information." + "not_share": "We don’t 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: ", "app_number_one_color": "25 million people.", "app_number_one": "The #1 Astrology app trusted by over " + }, + "/camera": { + "bad_photo": "Bad photo!", + "try_again": "Try again", + "do_better": "You can do it better", + "next": "Next" } } } diff --git a/public/locales/v1/es/female_es.json b/public/locales/v1/es/female_es.json index 495c1ed..127c60c 100644 --- a/public/locales/v1/es/female_es.json +++ b/public/locales/v1/es/female_es.json @@ -30,6 +30,7 @@ "privacy_policy": "Política de Privacidad", "terms_of_use": "Términos de Uso", "policy": "Estoy de acuerdo con la , los y con el uso de cookies y tecnologías de seguimiento que requieren tu consentimiento", + "copyright": "@ 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: Ahorra %", + "original_price": "Precio original: ", "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 de descuento!", "description1": " de descuento en tu plan personalizado", "description2": "-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": " 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 %", - "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 confiada por más de 25 millones de personas.", - "color": "#1 en Astrología" - }, - "/trial-payment": { - "palm_is_ready": { - "title": "Tu lectura de palma ", - "title_color": "Está lista", - "description": "“Acabo de recibir los resultados del escaneo de tu palma. ¡Hablemos!”", - "text1": " 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": " 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": " lecturas de palma", - "point1_bold": "Ilimitadas", - "point2": " con astrólogos profesionales", - "point2_bold": "Chats en vivo 1:1", - "point3": " 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": " 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": " refleja tu inteligencia y mentalidad", - "point3_color": "Línea de la cabeza", - "point4": "Un dedo índice largo indica un líder nato", - "point5": " 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": " 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 ?", - "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": " Visto en", - "footer": { - "text1": "¿Preguntas? Estamos aquí para ayudarte", - "text2": "Atención al Cliente", - "text3": "Centro de Ayuda" - } - }, - "/payment": { - "will_be_charged_trial_info": " por tu prueba de días", - "will_be_charged_email_reminder": "te enviaremos un recordatorio por correo electrónico", - "will_be_charged": "Se te cobrará solo . Luego por semana. Ahorra cada semana. Te enviaremos un antes de que termine tu prueba.", - "payment_information": { - "personalized_offer": "Oferta personalizada reservada", - "title": "Comienza tu prueba de días", - "total_today": "Total hoy", - "code_applied_bold": "AURA24", - "code_applied": "¡Código 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: ", - "app_number_one_color": "25 millones de personas.", - "app_number_one": "La aplicación de astrología #1 confiada por más de " - } } -} +} \ No newline at end of file diff --git a/public/locales/v1/es/male_es.json b/public/locales/v1/es/male_es.json index c79c3a7..d449a72 100644 --- a/public/locales/v1/es/male_es.json +++ b/public/locales/v1/es/male_es.json @@ -30,6 +30,7 @@ "privacy_policy": "Política de Privacidad", "terms_of_use": "Términos de uso", "policy": "Estoy de acuerdo con la , los y con el uso de cookies y tecnologías de seguimiento, que requieren tu consentimiento", + "copyright": "@ 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: Ahorra %", + "original_price": "Precio original: ", "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 de descuento!", "description1": " de descuento en tu plan personalizado", "description2": "Prueba de 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 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 " } } -} \ No newline at end of file +} diff --git a/public/locales/v1/fr/female_fr.json b/public/locales/v1/fr/female_fr.json index 5f13fdf..204da90 100644 --- a/public/locales/v1/fr/female_fr.json +++ b/public/locales/v1/fr/female_fr.json @@ -14,6 +14,7 @@ "privacy_policy": "Politique de confidentialité", "terms_of_use": "Conditions d'utilisation", "policy": "Je suis d'accord avec la , les et l'utilisation de cookies et des technologies de suivi qui nécessitent votre consentement", + "copyright": "@ 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 : Économisez %", + "original_price": "Prix initial : ", "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 de réduction !", "description1": " de réduction sur votre plan personnalisé", "description2": "essai de 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 don’t share any personal information." + "not_share": "We don’t share any personal information.", + "placeholder_email": "Votre e-mail", + "placeholder_name": "Votre nom" }, "went_wrong": "Something went wrong.", "app_number_one": { diff --git a/public/locales/v1/fr/male_fr.json b/public/locales/v1/fr/male_fr.json index 41298e7..4028984 100644 --- a/public/locales/v1/fr/male_fr.json +++ b/public/locales/v1/fr/male_fr.json @@ -14,6 +14,7 @@ "privacy_policy": "Politique de confidentialité", "terms_of_use": "Conditions d'utilisation", "policy": "J'accepte la , les et l'utilisation de cookies et technologies de suivi, nécessitant votre consentement", + "copyright": "@ 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 : Économisez %", + "original_price": "Prix d'origine : ", "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 de réduction !", "description1": " de réduction sur votre plan personnalisé", "description2": "Essai de 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 don’t share any personal information." + "not_share": "We don’t share any personal information.", + "placeholder_email": "Votre e-mail", + "placeholder_name": "Votre nom" }, "went_wrong": "Something went wrong.", "app_number_one": { diff --git a/public/locales/v1/hi/female_hi.json b/public/locales/v1/hi/female_hi.json index f3a483b..8614a19 100644 --- a/public/locales/v1/hi/female_hi.json +++ b/public/locales/v1/hi/female_hi.json @@ -14,6 +14,7 @@ "privacy_policy": "गोपनीयता नीति", "terms_of_use": "उपयोग की शर्तें", "policy": "मैं , और कूकीज़ और ट्रैकिंग तकनीकों के उपयोग के लिए सहमत हूँ, जिसके लिए आपकी सहमति आवश्यक है", + "copyright": "@ 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": "मूल कीमत: % बचाएं", + "original_price": "मूल कीमत: बचाएं", "you_will_be_charged": "*आपसे खरीद के समय चयनित ऐड-ऑन सेवाओं या ऑफर के लिए शुल्क लिया जाएगा।\n यह एक गैर-आवर्ती भुगतान है।", - "get_my_consultation": "मेरा परामर्श प्राप्त करें" + "get_my_consultation": "मेरा परामर्श प्राप्त करें", + "discount_save": "" }, "/get-information-partner": { "title": "शानदार! चलिए देखते हैं कि क्या काम कर रहा है (और क्या नहीं) और वहीं से आगे बढ़ते हैं।", "description": "अब हमें आपके और आपके साथी के बीच ज्योतिषीय तालमेल ब्लूप्रिंट बनाने के लिए आपके साथी की प्रोफाइल के बारे में कुछ जानकारी चाहिए।" }, "/additional-discount": { + "header_title": "आपको गुप्त छूट मिल रही है!", "title": " की बचत करें!", "description1": "आपकी व्यक्तिगत योजना पर की छूट", "description2": "-दिन का ट्रायल", @@ -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 don’t share any personal information." + "not_share": "We don’t share any personal information.", + "placeholder_email": "आपका ईमेल", + "placeholder_name": "आपका नाम" }, "went_wrong": "Something went wrong.", "app_number_one": { diff --git a/public/locales/v1/hi/male_hi.json b/public/locales/v1/hi/male_hi.json index a2c3cb0..49f0aef 100644 --- a/public/locales/v1/hi/male_hi.json +++ b/public/locales/v1/hi/male_hi.json @@ -14,6 +14,7 @@ "privacy_policy": "गोपनीयता नीति", "terms_of_use": "उपयोग की शर्तें", "policy": "मैं , और कुकीज़ और ट्रैकिंग तकनीकों के उपयोग से सहमत हूं, जिसके लिए आपकी सहमति की आवश्यकता है", + "copyright": "@ 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": "मूल्य: % बचत करें", + "original_price": "मूल्य: बचत करें", "you_will_be_charged": "*खरीद के समय चयनित अतिरिक्त सेवाओं या ऑफ़रों के लिए आपसे शुल्क लिया जाएगा। यह एक गैर-पुनरावृत्त भुगतान है।", - "get_my_consultation": "मेरा परामर्श प्राप्त करें" + "get_my_consultation": "मेरा परामर्श प्राप्त करें", + "discount_save": "" }, "/get-information-partner": { "title": "बहुत बढ़िया! चलिए यह पता लगाते हैं कि क्या काम कर रहा है (और क्या नहीं) और वहीं से आगे बढ़ते हैं।", "description": "अब हमें आपके साथी के प्रोफाइल के बारे में कुछ जानकारी चाहिए ताकि हम आपके और आपके साथी के बीच ज्योतिषीय संबंध ब्लूप्रिंट बना सकें।" }, "/additional-discount": { + "header_title": "आपको एक गुप्त छूट मिली है!", "title": " की बचत करें!", "description1": "आपकी व्यक्तिगत योजना पर की छूट", "description2": "-दिन का परीक्षण", @@ -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 don’t share any personal information." + "not_share": "We don’t share any personal information.", + "placeholder_email": "आपका ईमेल", + "placeholder_name": "आपका नाम" }, "went_wrong": "Something went wrong.", "app_number_one": { diff --git a/public/locales/v1/pt-br/female_pt-br.json b/public/locales/v1/pt-br/female_pt-br.json index d7dcad9..61c3ec5 100644 --- a/public/locales/v1/pt-br/female_pt-br.json +++ b/public/locales/v1/pt-br/female_pt-br.json @@ -14,6 +14,7 @@ "privacy_policy": "Política de Privacidade", "terms_of_use": "Termos de Uso", "policy": "Concordo com a , os e com o uso de cookies e tecnologias de rastreamento, que exigem seu consentimento", + "copyright": "@ 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: Economize %", + "original_price": "Preço original: ", "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 de desconto!", "description1": " de desconto no seu plano personalizado", "description2": "Teste de 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 don’t share any personal information." + "not_share": "We don’t share any personal information.", + "placeholder_email": "Seu email", + "placeholder_name": "Seu nome" }, "went_wrong": "Something went wrong.", "app_number_one": { diff --git a/public/locales/v1/pt-br/male_pt-br.json b/public/locales/v1/pt-br/male_pt-br.json index 6b262b0..236dd33 100644 --- a/public/locales/v1/pt-br/male_pt-br.json +++ b/public/locales/v1/pt-br/male_pt-br.json @@ -14,6 +14,7 @@ "privacy_policy": "Política de Privacidade", "terms_of_use": "Termos de Uso", "policy": "Eu concordo com a , e com o uso de cookies e tecnologias de rastreamento que requerem seu consentimento", + "copyright": "@ 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: Economize %", + "original_price": "Preço original: ", "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 !", "description1": " de desconto em seu plano personalizado", "description2": "Teste de 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 don’t share any personal information." + "not_share": "We don’t share any personal information.", + "placeholder_email": "Seu email", + "placeholder_name": "Seu nome" }, "went_wrong": "Something went wrong.", "app_number_one": { diff --git a/public/locales/v1/pt-pt/female_pt-pt.json b/public/locales/v1/pt-pt/female_pt-pt.json index 1048130..01171c2 100644 --- a/public/locales/v1/pt-pt/female_pt-pt.json +++ b/public/locales/v1/pt-pt/female_pt-pt.json @@ -14,6 +14,7 @@ "privacy_policy": "Política de Privacidade", "terms_of_use": "Termos de Uso", "policy": "Concordo com a , e com o uso de cookies e tecnologias de rastreamento, que requerem o teu consentimento", + "copyright": "@ 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: Poupa %", + "original_price": "Preço original: ", "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 !", "description1": " de desconto no teu plano personalizado", "description2": "Período experimental de 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 don’t share any personal information." + "not_share": "We don’t share any personal information.", + "placeholder_email": "O teu email", + "placeholder_name": "O teu nome" }, "went_wrong": "Something went wrong.", "app_number_one": { diff --git a/public/locales/v1/pt-pt/male_pt-pt.json b/public/locales/v1/pt-pt/male_pt-pt.json index 66f3ee3..f833294 100644 --- a/public/locales/v1/pt-pt/male_pt-pt.json +++ b/public/locales/v1/pt-pt/male_pt-pt.json @@ -14,6 +14,7 @@ "privacy_policy": "Política de Privacidade", "terms_of_use": "Termos de Utilização", "policy": "Concordo com a , os e com o uso de cookies e tecnologias de rastreamento, que requerem o seu consentimento", + "copyright": "@ 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: Poupa %", + "original_price": "Preço original: ", "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 !", "description1": " de desconto no teu plano personalizado", "description2": "Teste de 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 don’t share any personal information." + "not_share": "We don’t share any personal information.", + "placeholder_email": "O teu email", + "placeholder_name": "O teu nome" }, "went_wrong": "Something went wrong.", "app_number_one": { diff --git a/public/locales/v1/ru/female_ru.json b/public/locales/v1/ru/female_ru.json index 28d364a..e456590 100644 --- a/public/locales/v1/ru/female_ru.json +++ b/public/locales/v1/ru/female_ru.json @@ -656,6 +656,7 @@ "description": "Теперь нам нужно немного информации о Профиле Твоего Партнёра, чтобы создать астрологическую карту синастрии между вами." }, "/additional-discount": { + "header_title": "Ты получила секретную скидку!", "title": "Сэкономь !", "description1": " на персонализированный план", "description2": "-дневный пробный период", @@ -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 don’t share any personal information." + "not_share": "We don’t share any personal information.", + "placeholder_email": "Ваш email", + "placeholder_name": "Ваше имя" }, "went_wrong": "Something went wrong.", "app_number_one": { diff --git a/public/locales/v1/ru/male_ru.json b/public/locales/v1/ru/male_ru.json index 4d5a614..a5626a8 100644 --- a/public/locales/v1/ru/male_ru.json +++ b/public/locales/v1/ru/male_ru.json @@ -656,6 +656,7 @@ "description": "Теперь нам нужна некоторая информация о профиле вашего партнёра, чтобы создать астрологическую синастрийную карту между вами и вашим партнёром." }, "/additional-discount": { + "header_title": "Вы получили секретную скидку!", "title": "Сэкономьте !", "description1": "Скидка на ваш персонализированный план", "description2": "-дневный пробный период", @@ -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 don’t share any personal information." + "not_share": "We don’t share any personal information.", + "placeholder_email": "Ваш email", + "placeholder_name": "Ваше имя" }, "went_wrong": "Something went wrong.", "app_number_one": { diff --git a/public/trial-choice-palmistry.mp4 b/public/trial-choice-palmistry.mp4 new file mode 100644 index 0000000..e590134 Binary files /dev/null and b/public/trial-choice-palmistry.mp4 differ diff --git a/public/v1/get_on_appstore.svg b/public/v1/get_on_appstore.svg new file mode 100644 index 0000000..86243da --- /dev/null +++ b/public/v1/get_on_appstore.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/v1/icon-heart-hand.webp b/public/v1/icon-heart-hand.webp new file mode 100644 index 0000000..a2e3f02 Binary files /dev/null and b/public/v1/icon-heart-hand.webp differ diff --git a/public/v1/smartphone-1.webp b/public/v1/smartphone-1.webp new file mode 100644 index 0000000..0881985 Binary files /dev/null and b/public/v1/smartphone-1.webp differ diff --git a/public/v1/smartphone-2.webp b/public/v1/smartphone-2.webp new file mode 100644 index 0000000..4c572fb Binary files /dev/null and b/public/v1/smartphone-2.webp differ diff --git a/public/v1/smartphone-3.webp b/public/v1/smartphone-3.webp new file mode 100644 index 0000000..776295b Binary files /dev/null and b/public/v1/smartphone-3.webp differ diff --git a/public/v1/smartphone-4.webp b/public/v1/smartphone-4.webp new file mode 100644 index 0000000..e093afd Binary files /dev/null and b/public/v1/smartphone-4.webp differ diff --git a/public/v1/smartphone-5.webp b/public/v1/smartphone-5.webp new file mode 100644 index 0000000..6ffcb9b Binary files /dev/null and b/public/v1/smartphone-5.webp differ diff --git a/public/v1/test.png b/public/v1/test.png new file mode 100644 index 0000000..06941e7 Binary files /dev/null and b/public/v1/test.png differ diff --git a/src/api/api.ts b/src/api/api.ts index cc8088f..6a8f99b 100644 --- a/src/api/api.ts +++ b/src/api/api.ts @@ -32,6 +32,7 @@ import { UserVideos, UserPDF, Locale, + Session } from './resources' const api = { @@ -86,9 +87,12 @@ const api = { // User videos getUserVideos: createMethod(UserVideos.createRequest), // User PDF - getUserPDFCompatibility: createMethod(UserPDF.createRequest), + getUserPDF: createMethod(UserPDF.createRequest), // Locale getLocale: createMethod(Locale.createRequest), + // Session + createSession: createMethod(Session.createRequest), + updateSession: createMethod(Session.updateRequest) } export type ApiContextValue = typeof api diff --git a/src/api/resources/Session.ts b/src/api/resources/Session.ts new file mode 100644 index 0000000..851c5fb --- /dev/null +++ b/src/api/resources/Session.ts @@ -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; + partner?: Partial>; + answers?: Partial; + } +} + +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() + }); +}; diff --git a/src/api/resources/User.ts b/src/api/resources/User.ts index 82fed09..767809c 100644 --- a/src/api/resources/User.ts +++ b/src/api/resources/User.ts @@ -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; diff --git a/src/api/resources/UserPDF.ts b/src/api/resources/UserPDF.ts index e00e661..05159c4 100644 --- a/src/api/resources/UserPDF.ts +++ b/src/api/resources/UserPDF.ts @@ -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) }); }; diff --git a/src/api/resources/index.ts b/src/api/resources/index.ts index f416102..08b59f0 100644 --- a/src/api/resources/index.ts +++ b/src/api/resources/index.ts @@ -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"; diff --git a/src/api/utils.ts b/src/api/utils.ts index 4c38e1a..77335f2 100644 --- a/src/api/utils.ts +++ b/src/api/utils.ts @@ -5,10 +5,26 @@ import { ApiError, buildUnknownError, } from "./errors"; +import { ESourceAuthorization } from "./resources/User"; export function createMethod(createRequest: (payload: P) => Request) { return async (payload: P): Promise => { 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; diff --git a/src/assets/media/sf-pro-text-light.woff b/src/assets/media/sf-pro-text-light.woff new file mode 100644 index 0000000..60771fc Binary files /dev/null and b/src/assets/media/sf-pro-text-light.woff differ diff --git a/src/components/App/index.tsx b/src/components/App/index.tsx index 6eaca01..ab99467 100755 --- a/src/components/App/index.tsx +++ b/src/components/App/index.tsx @@ -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 ( - }> - } /> - + } /> } /> } /> }> @@ -1183,7 +1200,7 @@ function ShortPathOutlet(props: IShortPathOutletProps): JSX.Element { return ; } -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 ? ( diff --git a/src/components/BlurComponent/index.tsx b/src/components/BlurComponent/index.tsx index 928a0b4..d43b845 100644 --- a/src/components/BlurComponent/index.tsx +++ b/src/components/BlurComponent/index.tsx @@ -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 +) { return ( -
+
{children} {isActiveBlur && (
@@ -30,4 +33,6 @@ export default function BlurComponent({ )}
); -} +}); + +export default BlurComponent; diff --git a/src/components/HomePage/index.tsx b/src/components/HomePage/index.tsx index 835dfd8..6869ff7 100644 --- a/src/components/HomePage/index.tsx +++ b/src/components/HomePage/index.tsx @@ -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(assetsData); - const getUserPDFCompatibility = useCallback(async () => { - const pdf = await api.getUserPDFCompatibility({ - token, - }); - return pdf; - }, [api, token]); + const getUserPDF = useCallback( + async (key: PDFKey): Promise => { + 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( - 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(getUserCompatibility); + + const { data: PDFPalmistry, isPending: isPendingPalmistryPDF } = + useApiCall(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)} /> - {!!PDFCompatibility?.url?.length && ( + {PDFPalmistry?.status !== "not_allowed" && ( handlePDF(PDFPalmistry)} > - Your Personalized READING + <> + {getIsPDFLoading(PDFPalmistry, isPendingPalmistryPDF) && ( + + )} + Your Palmistry READING + + + )} + {PDFCompatibility?.status !== "not_allowed" && ( + handlePDF(PDFCompatibility)} + > + <> + {getIsPDFLoading( + PDFCompatibility, + isPendingCompatibilityPDF + ) && ( + + )} + Your Personalized READING + )} ) { placementKey={ EPlacementKeys["aura.placement.palmistry.redesign"] } + noProductRedirect={{ + pagesFrom: [routes.client.palmistryV1TrialPayment()], + url: routes.client.palmistryV1TrialChoice(), + }} /> )} diff --git a/src/components/PalmistryV1/components/PaymentModal/styles.module.scss b/src/components/PalmistryV1/components/PaymentModal/styles.module.scss index 5b7e725..2134380 100644 --- a/src/components/PalmistryV1/components/PaymentModal/styles.module.scss +++ b/src/components/PalmistryV1/components/PaymentModal/styles.module.scss @@ -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 { diff --git a/src/components/PalmistryV1/pages/Birthdate/index.tsx b/src/components/PalmistryV1/pages/Birthdate/index.tsx index c84d420..3197bc7 100644 --- a/src/components/PalmistryV1/pages/Birthdate/index.tsx +++ b/src/components/PalmistryV1/pages/Birthdate/index.tsx @@ -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()); diff --git a/src/components/PalmistryV1/pages/Camera/index.tsx b/src/components/PalmistryV1/pages/Camera/index.tsx index 4c08009..9d25550 100644 --- a/src/components/PalmistryV1/pages/Camera/index.tsx +++ b/src/components/PalmistryV1/pages/Camera/index.tsx @@ -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(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) => { + 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 && ( + setUploadMenuModalIsOpen(false)} + onSelectFile={onSelectFile} + onChooseCamera={() => true} + /> + )} + {!isProduction && ( + + )} + {!isLoading && !uploadMenuModalIsOpen && ( console.log("close")} onTakePhoto={onTakePhoto} @@ -76,6 +164,34 @@ function Camera() { {isLoading && ( )} + {toastVisible === EToastVisible.try_again && ( + +
+ {translate("/camera.bad_photo")} + +
+
+ )} + {toastVisible === EToastVisible.try_again_or_next && ( + +
+ {translate("/camera.do_better")} +
+ + +
+
+
+ )} ); } diff --git a/src/components/PalmistryV1/pages/Camera/styles.module.scss b/src/components/PalmistryV1/pages/Camera/styles.module.scss index 7459518..af74740 100644 --- a/src/components/PalmistryV1/pages/Camera/styles.module.scss +++ b/src/components/PalmistryV1/pages/Camera/styles.module.scss @@ -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; + } +} diff --git a/src/components/PalmistryV1/pages/ElementResonates/index.tsx b/src/components/PalmistryV1/pages/ElementResonates/index.tsx index 50c99a6..fd274ff 100644 --- a/src/components/PalmistryV1/pages/ElementResonates/index.tsx +++ b/src/components/PalmistryV1/pages/ElementResonates/index.tsx @@ -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 ( -
+
{translate("/element-resonates.title")} diff --git a/src/components/PalmistryV1/pages/ElementResonates/styles.module.scss b/src/components/PalmistryV1/pages/ElementResonates/styles.module.scss index b76b428..4a0a092 100644 --- a/src/components/PalmistryV1/pages/ElementResonates/styles.module.scss +++ b/src/components/PalmistryV1/pages/ElementResonates/styles.module.scss @@ -1,3 +1,7 @@ +.container { + width: 100%; +} + .answer { justify-content: flex-start; padding-left: 15px; diff --git a/src/components/PalmistryV1/pages/Email/index.tsx b/src/components/PalmistryV1/pages/Email/index.tsx index bf96b1f..2a4058f 100644 --- a/src/components/PalmistryV1/pages/Email/index.tsx +++ b/src/components/PalmistryV1/pages/Email/index.tsx @@ -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() { setIsValidEmail(false)} /> + setIsValidName(true)} + />

{translate("/email.not_share")}

+ + )} + {isLoading && } +
+ ); +} + +export default TrialChoiceVideo; diff --git a/src/components/PalmistryV1/pages/TrialChoiceVideo/styles.module.scss b/src/components/PalmistryV1/pages/TrialChoiceVideo/styles.module.scss new file mode 100644 index 0000000..87bcdd7 --- /dev/null +++ b/src/components/PalmistryV1/pages/TrialChoiceVideo/styles.module.scss @@ -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); + } +} diff --git a/src/components/PalmistryV1/pages/WhatAspects/index.tsx b/src/components/PalmistryV1/pages/WhatAspects/index.tsx index aa7d8b5..c510d43 100644 --- a/src/components/PalmistryV1/pages/WhatAspects/index.tsx +++ b/src/components/PalmistryV1/pages/WhatAspects/index.tsx @@ -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()); }; diff --git a/src/components/PaymentModalNew/index.tsx b/src/components/PaymentModalNew/index.tsx index c5ad485..4db9a9e 100644 --- a/src/components/PaymentModalNew/index.tsx +++ b/src/components/PaymentModalNew/index.tsx @@ -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>; + 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(); 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 = () => { diff --git a/src/components/PaymentPage/results/ErrorPage/index.tsx b/src/components/PaymentPage/results/ErrorPage/index.tsx index 151ccbe..1cd9847 100644 --- a/src/components/PaymentPage/results/ErrorPage/index.tsx +++ b/src/components/PaymentPage/results/ErrorPage/index.tsx @@ -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 (
diff --git a/src/components/PaymentPage/results/SuccessPage/index.tsx b/src/components/PaymentPage/results/SuccessPage/index.tsx index 4cce120..f9c1dca 100644 --- a/src/components/PaymentPage/results/SuccessPage/index.tsx +++ b/src/components/PaymentPage/results/SuccessPage/index.tsx @@ -21,7 +21,7 @@ function PaymentSuccessPage(): JSX.Element { const handleNext = () => { dispatch(actions.status.update("subscribed")); - navigate(routes.client.addReport()); + navigate(routes.client.addReportV1()); }; useEffect(() => { diff --git a/src/components/pages/ABDesign/v1/components/Questionnaire/CustomAnswers/BirthPlace/index.tsx b/src/components/pages/ABDesign/v1/components/Questionnaire/CustomAnswers/BirthPlace/index.tsx index af757b2..83b66b7 100644 --- a/src/components/pages/ABDesign/v1/components/Questionnaire/CustomAnswers/BirthPlace/index.tsx +++ b/src/components/pages/ABDesign/v1/components/Questionnaire/CustomAnswers/BirthPlace/index.tsx @@ -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" + )} )}
diff --git a/src/components/pages/ABDesign/v1/components/Questionnaire/CustomAnswers/Birthtime/index.tsx b/src/components/pages/ABDesign/v1/components/Questionnaire/CustomAnswers/Birthtime/index.tsx index 5b8f6f9..22a2f3f 100644 --- a/src/components/pages/ABDesign/v1/components/Questionnaire/CustomAnswers/Birthtime/index.tsx +++ b/src/components/pages/ABDesign/v1/components/Questionnaire/CustomAnswers/Birthtime/index.tsx @@ -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` diff --git a/src/components/pages/ABDesign/v1/layouts/Discount/DiscountLayout.tsx b/src/components/pages/ABDesign/v1/layouts/Discount/DiscountLayout.tsx new file mode 100644 index 0000000..23fa430 --- /dev/null +++ b/src/components/pages/ABDesign/v1/layouts/Discount/DiscountLayout.tsx @@ -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) { + const genderInfo = useGenderInfo(); + + return ( +
+
+ {title && ( + + {title} + + )} + + {children} +
+ ); +} + +export default DiscountLayout; diff --git a/src/components/pages/ABDesign/v1/layouts/Discount/styles.module.css b/src/components/pages/ABDesign/v1/layouts/Discount/styles.module.css new file mode 100644 index 0000000..456992b --- /dev/null +++ b/src/components/pages/ABDesign/v1/layouts/Discount/styles.module.css @@ -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; + } +} \ No newline at end of file diff --git a/src/components/pages/ABDesign/v1/pages/AdditionalDiscount/index.tsx b/src/components/pages/ABDesign/v1/pages/AdditionalDiscount/index.tsx index 22cffa4..4eaa976 100644 --- a/src/components/pages/ABDesign/v1/pages/AdditionalDiscount/index.tsx +++ b/src/components/pages/ABDesign/v1/pages/AdditionalDiscount/index.tsx @@ -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 ( -
+ {isLoading && } {!isLoading && ( <> - - {translate("/additional-discount.title", { - discount: (getText("discount.1") as string).replace("-", ""), - })} - - Friends -
- Fire -

- {translate("/additional-discount.description1", { - discount: (getText("discount.1") as string).replace("-", ""), - })} -

-
-
- Present -

- {translate("/additional-discount.description2", { - trialDuration: activeProduct?.trialDuration, - })} -

+
+
+ Fire +

+ {translate("/additional-discount.description1", { + discount: (getText("discount.1") as string).replace("-", ""), + })} +

+
+
+ Present +

+ {translate("/additional-discount.description2", { + trialDuration: activeProduct?.trialDuration, + })} +

+

{translate("/additional-discount.price", { price: ( - + {addCurrency((activeProduct?.price || 0) / 100, currency)} ), - fullPrice: addCurrency( - Number(getText("full.price")) / 100, - currency + fullPrice: ( + + {addCurrency(Number(getText("full.price")) / 100, currency)} + ), })}

- + {translate("/additional-discount.button")} - + )} -
+ ); } diff --git a/src/components/pages/ABDesign/v1/pages/AdditionalDiscount/styles.module.css b/src/components/pages/ABDesign/v1/pages/AdditionalDiscount/styles.module.css index 3e60ef6..7caa0df 100644 --- a/src/components/pages/ABDesign/v1/pages/AdditionalDiscount/styles.module.css +++ b/src/components/pages/ABDesign/v1/pages/AdditionalDiscount/styles.module.css @@ -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 { diff --git a/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/AdditionalPurchasesSteps/checkMark.svg b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/AdditionalPurchasesSteps/checkMark.svg new file mode 100644 index 0000000..937287a --- /dev/null +++ b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/AdditionalPurchasesSteps/checkMark.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/AdditionalPurchasesSteps/index.tsx b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/AdditionalPurchasesSteps/index.tsx new file mode 100644 index 0000000..8a9f0e7 --- /dev/null +++ b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/AdditionalPurchasesSteps/index.tsx @@ -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(null); + const titlesRef = useRef>([]); + + return ( +
+
+ {steps.map(({ title, id }, index) => ( +
id, + })} + key={index} + > +
+
+ (titlesRef.current[index] = el)} + className={styles.title} + key={index} + > + {translate(title)} + + {activeStep < id &&
} + {activeStep > id && ( + Circle with dote + )} +
+ + {id !== steps.length - 1 && ( +
id, + })} + /> + )} +
+
+ ))} +
+
+ ); +} + +export default AdditionalPurchasesSteps; diff --git a/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/AdditionalPurchasesSteps/styles.module.css b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/AdditionalPurchasesSteps/styles.module.css new file mode 100644 index 0000000..14dc68a --- /dev/null +++ b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/AdditionalPurchasesSteps/styles.module.css @@ -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) ); +} diff --git a/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/ConsultationTable/index.tsx b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/ConsultationTable/index.tsx new file mode 100644 index 0000000..e6432a9 --- /dev/null +++ b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/ConsultationTable/index.tsx @@ -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 ( +
+ + {translate("/add-consultation.your_unique_consultation")} + +
+
+ Icon + {translate("/add-consultation.30-minute")} +
+
+
+

+ {translate("/add-consultation.description")} +

+
+ + {translate("/add-consultation.one_time_price_offer")} {_price} + +
+ + {translate("/add-consultation.original_price", { + oldPrice: addCurrency(99.99, currency), + discount: ( + + {translate("/add-consultation.discount_save")} 50% + + ), + })} + +
+
+
+ ); +} + +export default ConsultationTable; diff --git a/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/ConsultationTable/styles.module.css b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/ConsultationTable/styles.module.css new file mode 100644 index 0000000..7bdc8c8 --- /dev/null +++ b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/ConsultationTable/styles.module.css @@ -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%); +} diff --git a/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/Copyright/index.tsx b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/Copyright/index.tsx new file mode 100644 index 0000000..431626d --- /dev/null +++ b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/Copyright/index.tsx @@ -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 ( +

+ {translate("copyright", { + year: new Date().getFullYear(), + })} +

+ ); +} + +export default Copyright; diff --git a/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/Copyright/styles.module.css b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/Copyright/styles.module.css new file mode 100644 index 0000000..d5711d1 --- /dev/null +++ b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/Copyright/styles.module.css @@ -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; + } \ No newline at end of file diff --git a/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/FirstSlide/index.tsx b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/FirstSlide/index.tsx new file mode 100644 index 0000000..13dab6e --- /dev/null +++ b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/FirstSlide/index.tsx @@ -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 ( +
+
+ Premium Intro +
+
    + {firstSliderList.map((item, index) => ( +
  • + +

    {translate(item.title)}

    +
  • + ))} +
  • + 5 +

    minutes to read

    +
  • +
+
+
+ get on appstore +
+

+ {_price.split(".")[0]} + {_price.split(".")[1]} +

+
+
+
+
+ ); +} + +export default FirstSlide; diff --git a/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/FirstSlide/styles.module.css b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/FirstSlide/styles.module.css new file mode 100644 index 0000000..6a03851 --- /dev/null +++ b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/FirstSlide/styles.module.css @@ -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; +} diff --git a/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/FooterButton/index.tsx b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/FooterButton/index.tsx new file mode 100644 index 0000000..e3f21d5 --- /dev/null +++ b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/FooterButton/index.tsx @@ -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(); + + return ( + + {/* */} + + {children} + +

+ {translate("skip_this_offer")} +

+
+ //
+ ); +} + +export default FooterButton; diff --git a/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/FooterButton/styles.module.css b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/FooterButton/styles.module.css new file mode 100644 index 0000000..68816e4 --- /dev/null +++ b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/FooterButton/styles.module.css @@ -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; +} diff --git a/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/PaymentAddress/index.tsx b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/PaymentAddress/index.tsx new file mode 100644 index 0000000..dc39a91 --- /dev/null +++ b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/PaymentAddress/index.tsx @@ -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 ( +

+ {translate("payment_modal.address")} +

+ ); +} + +export default PaymentAddress; diff --git a/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/PaymentAddress/styles.module.css b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/PaymentAddress/styles.module.css new file mode 100644 index 0000000..8deb3f0 --- /dev/null +++ b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/PaymentAddress/styles.module.css @@ -0,0 +1,7 @@ +.address { + margin-bottom: 8px; + color: rgba(77, 77, 77, 1); + font-size: 11px; + text-align: center; + text-transform: uppercase; +} diff --git a/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/SignUpOffer/check-mark-1.svg b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/SignUpOffer/check-mark-1.svg new file mode 100644 index 0000000..ecbf477 --- /dev/null +++ b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/SignUpOffer/check-mark-1.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/SignUpOffer/index.tsx b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/SignUpOffer/index.tsx new file mode 100644 index 0000000..451eba7 --- /dev/null +++ b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/SignUpOffer/index.tsx @@ -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 ( +
+ +
+
+

+ {translate(`/add-report.products.${id}.title`)} +

+ +
+ + {translate(`/add-report.products.${id}.discount`, { + discount, + })} + +
+
+ {!!subtitle?.length && ( + + {translate(`/add-report.products.${id}.description`)} + + )} +
+ + {translate(`/add-report.products.${id}.price`, { + price: ( + + {addCurrency(getPriceCentsToDollars(current || 0), currency)} + + ), + oldPrice: ( + + {addCurrency(getPriceCentsToDollars(old || 0), currency)} + + ), + })} + +
+
+
{isActive && }
+
+ ); +} + +export default SignUpOffer; diff --git a/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/SignUpOffer/styles.module.css b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/SignUpOffer/styles.module.css new file mode 100644 index 0000000..c283113 --- /dev/null +++ b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/SignUpOffer/styles.module.css @@ -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; + } +} \ No newline at end of file diff --git a/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/SliderNextArrow/arrow.svg b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/SliderNextArrow/arrow.svg new file mode 100644 index 0000000..6961fc7 --- /dev/null +++ b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/SliderNextArrow/arrow.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/SliderNextArrow/index.tsx b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/SliderNextArrow/index.tsx new file mode 100644 index 0000000..7ea854c --- /dev/null +++ b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/SliderNextArrow/index.tsx @@ -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, HTMLButtonElement> +) { + const { className, style, onClick } = props; + return ( + + ); +} + +export default SliderNextArrow; diff --git a/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/SliderNextArrow/styles.module.css b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/SliderNextArrow/styles.module.css new file mode 100644 index 0000000..f499248 --- /dev/null +++ b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/SliderNextArrow/styles.module.css @@ -0,0 +1,10 @@ +.arrow { + z-index: 2 !important; + width: 37px !important; + height: 37px !important; + right: -7px !important; +} + +.arrow::before { + content: none!important; +} \ No newline at end of file diff --git a/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/SliderPrevArrow/index.tsx b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/SliderPrevArrow/index.tsx new file mode 100644 index 0000000..48e66ce --- /dev/null +++ b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/SliderPrevArrow/index.tsx @@ -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, HTMLButtonElement> +) { + const { className, style, onClick } = props; + return ( + + ); +} + +export default SliderPrevArrow; diff --git a/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/SliderPrevArrow/styles.module.css b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/SliderPrevArrow/styles.module.css new file mode 100644 index 0000000..ab55088 --- /dev/null +++ b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/SliderPrevArrow/styles.module.css @@ -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 ; +} diff --git a/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/ThankYouBanner/index.tsx b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/ThankYouBanner/index.tsx new file mode 100644 index 0000000..ae7f319 --- /dev/null +++ b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/ThankYouBanner/index.tsx @@ -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 ( +
+ Love +
+ + {translate("/add-report.thank_you")} + +

{translate("/add-report.order_successful")}

+
+
+ ); +} + +export default ThankYouBanner; diff --git a/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/ThankYouBanner/styles.module.css b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/ThankYouBanner/styles.module.css new file mode 100644 index 0000000..6a2c0ab --- /dev/null +++ b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/components/ThankYouBanner/styles.module.css @@ -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; +} diff --git a/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/index.tsx b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/index.tsx new file mode 100644 index 0000000..9f067d1 --- /dev/null +++ b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/index.tsx @@ -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 ( +
+
+ + +
+ ); +} + +export default AdditionalPurchases; diff --git a/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/pages/AddConsultation/index.tsx b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/pages/AddConsultation/index.tsx new file mode 100644 index 0000000..56c632a --- /dev/null +++ b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/pages/AddConsultation/index.tsx @@ -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(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(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 ( +
+ {!isLoading && + paymentIntent && + "paymentIntent" in paymentIntent && + !!tokenFromStore.length && ( + <> + setPaymentIntent(null)} + > + + {getPriceCentsToDollars(currentProduct?.price || 0)}$ + + + + + )} + {!currentProduct?.price && ( + + )} + {!!currentProduct?.price && ( + <> + + {translate("/add-consultation.more_for_you")} + + + {translate("/add-consultation.exclusive_offer")} + + +

+ {translate("/add-consultation.you_will_be_charged")} +

+ {isError &&

{translate("went_wrong")}

} + + {isPendingProducts || isLoading ? ( + + ) : ( + translate("/add-consultation.get_my_consultation") + )} + + + + )} +
+ ); +} + +export default AddConsultationPage; diff --git a/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/pages/AddConsultation/styles.module.css b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/pages/AddConsultation/styles.module.css new file mode 100644 index 0000000..ab57920 --- /dev/null +++ b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/pages/AddConsultation/styles.module.css @@ -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; +} diff --git a/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/pages/AddReport/index.tsx b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/pages/AddReport/index.tsx new file mode 100644 index 0000000..055dac1 --- /dev/null +++ b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/pages/AddReport/index.tsx @@ -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(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(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 ( +
+ {!isLoading && + paymentIntent && + "paymentIntent" in paymentIntent && + !!tokenFromStore.length && ( + <> + setPaymentIntent(null)} + > + + {getPriceCentsToDollars(activeOffer.price.current || 0)}$ + + + + + )} + + + + {translate("/add-report.choose_offer")} + + + {translate("/add-report.available_only_now")} + +
+ {!isPendingProducts && + signUpOffers.map((offer, index) => ( + setActiveOffer(offer)} + {...offer} + price={{ + ...offer.price, + current: getCurrentProduct(offer.productKey)?.price || 0, + }} + /> + ))} + {isPendingProducts && } +
+

+ {translate("/add-report.description")} +

+ {isError && ( +

+ {translate("went_wrong")} +

+ )} + + {isLoading ? ( + + ) : ( + translate("/add-report.v1.continue") + )} + + +
+ ); +} + +export default AddReportPage; diff --git a/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/pages/AddReport/styles.module.css b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/pages/AddReport/styles.module.css new file mode 100644 index 0000000..a04ba60 --- /dev/null +++ b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/pages/AddReport/styles.module.css @@ -0,0 +1,53 @@ +.container { + width: 100%; +} + +.offers-container { + margin-top: 25px; + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + gap: 20px; +} + +.description { + margin-top: 16px; + margin-bottom: 32px; + margin-left: auto; + margin-right: auto; + text-align: center; + font-size: 10px; + line-height: 1.1; +} + +.title { + text-align: center; + font-size: 22px; + font-weight: 600; + line-height: 135%; + color: #000; + margin-top: 11px; + margin-bottom: 5px; +} + +.modal-title { + margin-bottom: 16px; +} + +.subtitle { + font-size: 14px; + text-align: center; + font-weight: 400; + color: #000; + margin-bottom: 0; + line-height: 135%; +} + +.error { + color: red; +} + +.button { + max-width: 310px!important; +} \ No newline at end of file diff --git a/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/pages/UnlimitedReadings/index.tsx b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/pages/UnlimitedReadings/index.tsx new file mode 100644 index 0000000..96c7e5f --- /dev/null +++ b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/pages/UnlimitedReadings/index.tsx @@ -0,0 +1,189 @@ +import Title from "@/components/Title"; +import styles from "./styles.module.css"; +import { unlimitedReadings } from "@/data/additionalPurchases"; +import FooterButton from "../../components/FooterButton"; +import { useNavigate } from "react-router-dom"; +import Slider, { Settings } from "react-slick"; +import FirstSlide from "../../components/FirstSlide"; +import SliderNextArrow from "../../components/SliderNextArrow"; +import SliderPrevArrow from "../../components/SliderPrevArrow"; +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 { createSinglePayment } from "@/services/singlePayment"; +import Loader, { LoaderColor } from "@/components/Loader"; +import { ResponsePost } from "@/api/resources/SinglePayment"; +import Modal from "@/components/Modal"; +import { getPriceCentsToDollars } from "@/services/price"; +import PaymentForm from "@/components/pages/SinglePaymentPage/PaymentForm"; +import { useTranslations } from "@/hooks/translations"; +import { addCurrency, ELocalesPlacement } from "@/locales"; +import Copyright from "../../components/Copyright"; + +const sliderSettings: Settings = { + dots: false, + infinite: false, + speed: 500, + slidesToShow: 1, + slidesToScroll: 1, + className: styles["slider-container"], + nextArrow: , + prevArrow: , +}; + +function UnlimitedReadingsPage() { + const navigate = useNavigate(); + const { translate } = useTranslations(ELocalesPlacement.V1); + const { user: userFromStore } = useAuth(); + const api = useApi(); + const tokenFromStore = useSelector(selectors.selectToken); + const currency = useSelector(selectors.selectCurrency); + const [isLoading, setIsLoading] = useState(false); + const [paymentIntent, setPaymentIntent] = useState(null); + const [isError, setIsError] = useState(false); + const returnUrl = `${window.location.protocol}//${ + window.location.host + }${routes.client.addConsultationV1()}`; + + const loadData = useCallback(async () => { + return await api.getSinglePaymentProducts({ token: tokenFromStore }); + }, [api, tokenFromStore]); + + const { data: products, isPending: isPendingProducts } = + useApiCall(loadData); + + const currentProduct = products?.find( + (product) => product.key === "main.unlimited.readings" + ); + + 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.addConsultationV1()); + return setIsError(true); + } + } catch (error) { + setIsError(true); + } finally { + setIsLoading(false); + } + }; + + const handleClickSkip = () => { + navigate(routes.client.addConsultationV1()); + }; + + return ( +
+ {!isLoading && + paymentIntent && + "paymentIntent" in paymentIntent && + !!tokenFromStore.length && ( + <> + setPaymentIntent(null)} + > + + {getPriceCentsToDollars(currentProduct?.price || 0)}$ + + + + + )} + {!currentProduct && ( + + )} + {!!currentProduct?.price && ( + <> + + +
+
+ Premium Intro + Premium Intro +
+
+
+
+ Premium Intro + Premium Intro +
+
+
+ + {translate("/unlimited-readings.title")} + +
    + {unlimitedReadings.map(({ title, icon }, index) => ( +
  • + + {translate(title)} +
  • + ))} +
+ {isError &&

{translate("went_wrong")}

} + + {isPendingProducts || isLoading ? ( + + ) : ( + translate("/unlimited-readings.add_unlimited_readings") + )} + +

+ {translate("/unlimited-readings.description", { + price: addCurrency( + ((currentProduct?.price || 0) / 100).toFixed(2), + currency + ), + })} +

+ + + )} +
+ ); +} + +export default UnlimitedReadingsPage; diff --git a/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/pages/UnlimitedReadings/styles.module.css b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/pages/UnlimitedReadings/styles.module.css new file mode 100644 index 0000000..5cad8d2 --- /dev/null +++ b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/pages/UnlimitedReadings/styles.module.css @@ -0,0 +1,95 @@ +.container { + width: 100%; +} + +.loader { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} + +.title { + max-width: 336px; + margin: 20px auto 15px; + text-align: center; + font-size: 22px; + font-weight: 600; + line-height: 1.1; + color: #000; +} + +.list { + max-width: 305px; + margin: 0 auto 28px; + display: flex; + flex-direction: column; + gap: 27px; +} + +.list .item { + display: flex; + font-size: 16px; + line-height: 1.2; +} + +.item > .image { + display: block; + background-size: contain; + background-position: center center; + background-repeat: no-repeat; + width: 28px; + height: 28px; + margin-right: 10px; + position: relative; + top: 3px; + flex-shrink: 0; +} + +.policy { + margin-top: -8px; + margin-bottom: 8px; + color: #000; + font-size: 10px; + line-height: 1.25; +} + +.slider-container { + margin-top: 20px; + margin: 20px -10px 0; +} + +.slider { + padding: 0 10px; +} + +.slider-inner { + display: flex ; + border-radius: 10px; + padding: 16px 8px 0 20px; + background-color: rgba(133, 182, 255, 1); +} + +.slider-inner-img { + padding: 11px 20px 0; + justify-content: space-between; + gap: 10px; +} + +.slider-inner-img > img { + width: calc(50% - 10px); + object-fit: contain; +} + +.error { + max-width: 526px; + margin-left: auto; + margin-right: auto; + text-align: center; + font-size: 14px; + color: red; +} + +.button { + max-width: 310px; +} \ No newline at end of file diff --git a/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/styles.module.css b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/styles.module.css new file mode 100644 index 0000000..9a4250c --- /dev/null +++ b/src/components/pages/ABDesign/v1/pages/AdditionalPurchases/styles.module.css @@ -0,0 +1,17 @@ +.page { + padding: 24px 22px 10px; + max-width: 460px; + width: 100%; + position: relative; + min-height: 100dvh; + display: flex; + justify-content: start; + align-items: center; + flex-direction: column; + overflow: inherit; + overflow-x: clip; +} + +.header { + margin-bottom: 24px; +} diff --git a/src/components/pages/ABDesign/v1/pages/EmailEnterPage/NameInput.tsx b/src/components/pages/ABDesign/v1/pages/EmailEnterPage/NameInput.tsx index c403686..51eb162 100644 --- a/src/components/pages/ABDesign/v1/pages/EmailEnterPage/NameInput.tsx +++ b/src/components/pages/ABDesign/v1/pages/EmailEnterPage/NameInput.tsx @@ -1,5 +1,6 @@ import { useState } from "react"; import styles from "./styles.module.css"; +import { FormField } from "@/types"; interface INameInputProps { value: string; @@ -13,11 +14,12 @@ const isValidName = (name: string) => { }; function NameInput({ + inputClassName, value, placeholder, onValid, onInvalid, -}: INameInputProps) { +}: INameInputProps & Partial>) { const [name, setName] = useState(value); const handleChangeName = (event: React.ChangeEvent) => { @@ -33,6 +35,7 @@ function NameInput({ return (
{ + const handleClick = async () => { + if (name.length) { + await updateSession( + { + profile: { + name, + }, + }, + ESourceAuthorization["aura.main.new"] + ); + } authorize(); metricService.reachGoal(EGoals.ENTERED_EMAIL, [ EMetrics.KLAVIYO, diff --git a/src/components/pages/ABDesign/v1/pages/Gender/index.tsx b/src/components/pages/ABDesign/v1/pages/Gender/index.tsx index 649b439..bb177c8 100644 --- a/src/components/pages/ABDesign/v1/pages/Gender/index.tsx +++ b/src/components/pages/ABDesign/v1/pages/Gender/index.tsx @@ -20,12 +20,15 @@ import metricService, { import { usePreloadImages } from "@/hooks/preload/images"; import { useTranslations } from "@/hooks/translations"; import { ELocalesPlacement } from "@/locales"; +import { useSession } from "@/hooks/session/useSession"; +import { EGender, ESourceAuthorization } from "@/api/resources/User"; interface IGenderPageProps { productKey?: EProductKeys; } function GenderPage({ productKey }: IGenderPageProps): JSX.Element { + const { createSession, updateSession } = useSession(); const { translate } = useTranslations(ELocalesPlacement.V1); const dispatch = useDispatch(); const navigate = useNavigate(); @@ -91,6 +94,18 @@ function GenderPage({ productKey }: IGenderPageProps): JSX.Element { if (productKey === EProductKeys["chat.aura"]) { return navigate(routes.client.advisorChatBirthdate()); } + const session = await createSession(ESourceAuthorization["aura.main.new"]); + if (session?.sessionId?.length) { + await updateSession( + { + profile: { + gender: EGender[selectedGender.id as keyof typeof EGender], + }, + }, + ESourceAuthorization["aura.main.new"], + session.sessionId + ); + } if (isNextPageMentioned === "true") { return navigate(routes.client.mentionedInV1()); } diff --git a/src/components/pages/ABDesign/v1/pages/NoBirthtime/index.tsx b/src/components/pages/ABDesign/v1/pages/NoBirthtime/index.tsx index 7756c9d..f20f9e3 100644 --- a/src/components/pages/ABDesign/v1/pages/NoBirthtime/index.tsx +++ b/src/components/pages/ABDesign/v1/pages/NoBirthtime/index.tsx @@ -10,25 +10,51 @@ import { ELottieKeys, useLottie } from "@/hooks/lottie/useLottie"; import { DotLottieReact } from "@lottiefiles/dotlottie-react"; import { useTranslations } from "@/hooks/translations"; import { ELocalesPlacement } from "@/locales"; +import { useSession } from "@/hooks/session/useSession"; +import { useSelector } from "react-redux"; +import { selectors } from "@/store"; +import { ESourceAuthorization } from "@/api/resources/User"; function NoBirthtimePage() { + const { updateSession } = useSession(); const [searchParams] = useSearchParams(); const affiliation = searchParams.get("affiliation") || "self"; const navigate = useNavigate(); const { translate } = useTranslations(ELocalesPlacement.V1); const { width: pageWidth, elementRef: pageRef } = useDynamicSize({}); + const questionnaire = useSelector(selectors.selectQuestionnaire); + const birthdate = + affiliation === "self" + ? questionnaire.birthdate + : questionnaire.partnerBirthdate; const { animationData } = useLottie({ loadKey: ELottieKeys.hourglass, }); - const handleNext = () => { + const handleNext = async () => { if (affiliation === "partner") { + await updateSession( + { + partner: { + birthdate: `${birthdate} 00:00`, + }, + }, + ESourceAuthorization["aura.main.new"] + ); navigate( `${routes.client.questionnaireV1()}/partnerProfile/partnerBirthPlace` ); } if (affiliation === "self") { + await updateSession( + { + profile: { + birthdate: `${birthdate} 00:00`, + }, + }, + ESourceAuthorization["aura.main.new"] + ); navigate(`${routes.client.questionnaireV1()}/profile/birthPlace`); } }; diff --git a/src/components/pages/ABDesign/v1/pages/Onboarding/index.tsx b/src/components/pages/ABDesign/v1/pages/Onboarding/index.tsx index e8caebb..1ea6267 100644 --- a/src/components/pages/ABDesign/v1/pages/Onboarding/index.tsx +++ b/src/components/pages/ABDesign/v1/pages/Onboarding/index.tsx @@ -2,7 +2,7 @@ import Title from "@/components/Title"; import styles from "./styles.module.scss"; import { useCallback, useEffect, useRef, useState } from "react"; import routes from "@/routes"; -import { useNavigate } from "react-router-dom"; +import { useNavigate, useSearchParams } from "react-router-dom"; import { onboardingTitles } from "../../data/onboarding"; import ProgressBarLine from "@/components/ui/ProgressBarLine"; import { usePaywall } from "@/hooks/paywall/usePaywall"; @@ -40,7 +40,13 @@ function OnboardingPage() { const { flags } = useMetricABFlags(); const auraVideoTrial = flags?.auraVideoTrial?.[0]; + const [searchParams] = useSearchParams(); + const path = searchParams.get("path"); + const handleNext = useCallback(() => { + if (path === "palmistry") { + return navigate(routes.client.home()); + } if (auraVideoTrial === "on") { return navigate(routes.client.trialChoiceVideoV1()); } @@ -48,7 +54,7 @@ function OnboardingPage() { return navigate(routes.client.tryAppV1()); } return navigate(routes.client.trialChoiceV1()); - }, [auraVideoTrial, authCode?.length, navigate]); + }, [auraVideoTrial, authCode?.length, navigate, path]); useEffect(() => { if (isVideoReady && progress >= 100) { diff --git a/src/components/pages/ABDesign/v1/pages/TrialPaymentWithDiscount/PaymentDiscountTable/index.tsx b/src/components/pages/ABDesign/v1/pages/TrialPaymentWithDiscount/PaymentDiscountTable/index.tsx index ac57685..fc370e0 100644 --- a/src/components/pages/ABDesign/v1/pages/TrialPaymentWithDiscount/PaymentDiscountTable/index.tsx +++ b/src/components/pages/ABDesign/v1/pages/TrialPaymentWithDiscount/PaymentDiscountTable/index.tsx @@ -60,27 +60,40 @@ function PaymentDiscountTable() { {getText("discount.1")}
-
-

{translate("/trial-payment-with-discount.cost")}

-
- - {addCurrency(Number(getText("full.price")) / 100, currency)} - - - {addCurrency((activeProduct?.price || 0) / 100, currency)} - -
-
-

- {translate("/trial-payment-with-discount.you_save", { - save: addCurrency(30, currency), - })} -

-
-
-

{translate("/trial-payment-with-discount.total_today")}

- {activeProduct && {getPrice(activeProduct)}} -
+ + + + + + + + + + + + + + +
+

{translate("/trial-payment-with-discount.cost")}

+

+ {translate("/trial-payment-with-discount.you_save", { + save: addCurrency(30, currency), + })} +

+
+ + {addCurrency(Number(getText("full.price")) / 100, currency)} + + + + {addCurrency((activeProduct?.price || 0) / 100, currency)} + +
+

{translate("/trial-payment-with-discount.total_today")}

+
+ {activeProduct && {getPrice(activeProduct)}} +
)}
diff --git a/src/components/pages/ABDesign/v1/pages/TrialPaymentWithDiscount/PaymentDiscountTable/styles.module.css b/src/components/pages/ABDesign/v1/pages/TrialPaymentWithDiscount/PaymentDiscountTable/styles.module.css index a600e7f..ad3a98c 100644 --- a/src/components/pages/ABDesign/v1/pages/TrialPaymentWithDiscount/PaymentDiscountTable/styles.module.css +++ b/src/components/pages/ABDesign/v1/pages/TrialPaymentWithDiscount/PaymentDiscountTable/styles.module.css @@ -1,53 +1,49 @@ .container { position: relative; - padding: 16px 12px; - border-radius: 8px; - margin-top: 20px; - width: 100%; + margin-inline: -16px; + width: calc(100% + 32px); + padding: 15px 12px; + border-radius: 12px; min-height: 250px; - background-color: #fbfbff; + background-color: #fff; + box-shadow: 2px 11px 17.1px -1px rgba(0, 0, 0, 0.13); } .title { - font-size: 18px; - line-height: 28px; + margin-bottom: 5px; + font-size: 20px; + line-height: 1.25; text-align: center; - color: #0f0f0f; + color: rgba(54, 54, 54, 1); } .no-pressure { - font-weight: 600; - font-size: 14px; - line-height: 25px; + font-weight: 500; + font-size: 11px; + line-height: 1.2; text-align: center; - margin-top: 4px; - color: #4f4f4f; + color: rgba(54, 54, 54, 1); } .applied { display: flex; align-items: center; justify-content: space-between; - background: linear-gradient( - 95.17deg, - rgb(207, 139, 243) -16.49%, - rgb(167, 112, 239) -15.14%, - rgb(253, 185, 155) 115.23% - ); - border-radius: 6px; - margin-top: 16px; - padding: 3px 9px; + background: linear-gradient(90deg, #ffa1ba 0%, #fffcab 100%); + margin-top: 14px; + margin-inline: -12px; + padding: 5px 9px; } .present-image { - width: 20px; + width: 17px; } .applied .description { - font-size: 14px; - font-weight: 700; - line-height: 24px; - color: rgb(251, 251, 255); + font-size: 16px; + font-weight: 500; + line-height: 26px; + color: rgba(54, 54, 54, 1); } .applied > .side { @@ -55,112 +51,110 @@ flex-direction: row; align-items: center; justify-content: center; - gap: 4px; + gap: 6px; } .discount { position: relative; - font-weight: 400; - font-size: 14px; - color: rgb(51, 51, 51); - line-height: 19px; - margin-right: 10px; + font-weight: 500; + font-size: 20px; + color: rgb(54, 54, 54); + line-height: 1.3; + margin-right: 6px; } .discount::before { - position: absolute; content: ""; - left: -2px; - top: 50%; - right: -2px; - border-top: 1px solid rgb(235, 87, 87); - border-right-color: rgb(235, 87, 87); - border-bottom-color: rgb(235, 87, 87); - border-left-color: rgb(235, 87, 87); - transform: rotate(8deg); + position: absolute; + top: 55%; + right: 0; + width: 82%; + height: 1.5px; + background-color: rgb(54, 54, 54); } .applied strong { - font-weight: 800; - font-size: 14px; - line-height: 19px; - color: rgb(15, 15, 15); -} - -.cost-container { - width: 100%; - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; - margin-top: 8px; -} - -.cost-container > p { - font-size: 14px; - line-height: 24px; - font-weight: 600; - color: rgb(79, 79, 79); -} - -.cost-container .discount { - color: rgb(130, 130, 130); -} - -.cost-container strong { - font-size: 14px; - font-weight: 600; - line-height: 19px; - color: rgb(51, 51, 51); -} - -.save { - font-size: 14px; - font-weight: 600; - line-height: 24px; - color: rgb(32, 31, 31); -} - -.line { - height: 1px; - background-color: rgb(153, 116, 246); - margin-top: 16px; - margin-bottom: 16px; - box-sizing: content-box; -} - -.total-container { - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; -} - -.total-container > p { - font-size: 16px; - font-weight: 600; - line-height: 24px; - color: rgb(15, 15, 15); -} - -.total-container strong { - font-size: 18px; font-weight: 700; - line-height: 24px; - background: linear-gradient( - 165.54deg, - rgb(20, 19, 51) -33.39%, - rgb(32, 34, 97) 15.89%, - rgb(84, 60, 151) 55.84%, - rgb(105, 57, 162) 74.96% - ) - text; + font-size: 20px; + line-height: 1.3; + color: #9a55ff; + background: linear-gradient(0, #ffa1ba 15%, #9a55ff 85%); + background-clip: text; + -webkit-background-clip: text; -webkit-text-fill-color: transparent; } +.table-cost { + margin-top: 8px; + width: 100%; +} + +.table-cost tbody tr:first-child { + width: 100%; +} + +.table-cost tbody th { + text-align: left; +} + +.table-cost tbody th * { + font-size: 12px; + line-height: 1.2; + font-weight: 500; + color: rgba(54, 54, 54, 1); +} + +.table-cost .discount { + margin-right: 20px; +} + +.table-cost .save { + margin-top: 2px; +} + +.table-cost tbody tr:last-child th { + padding-bottom: 5px; +} + +.table-cost tfoot { + position: relative; +} + +.table-cost tfoot::after { + content: ""; + position: absolute; + top: 0; + left: -8px; + width: calc(100% + 16px); + height: 1px; + background-color: rgba(54, 54, 54, 1); +} + +.table-cost tfoot tr:first-child th { + padding-top: 18px; +} + +.table-cost tfoot th { + text-align: left; + font-size: 16px; + font-weight: 500; + line-height: 1.25; +} + .loader { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); -} \ No newline at end of file +} + +@media (max-width: 390px) { + .applied .description { + font-size: 14px; + } + + .discount, + .applied strong { + font-size: 18px; + } +} diff --git a/src/components/pages/ABDesign/v1/pages/TrialPaymentWithDiscount/index.tsx b/src/components/pages/ABDesign/v1/pages/TrialPaymentWithDiscount/index.tsx index 5c3e24b..e42eec3 100644 --- a/src/components/pages/ABDesign/v1/pages/TrialPaymentWithDiscount/index.tsx +++ b/src/components/pages/ABDesign/v1/pages/TrialPaymentWithDiscount/index.tsx @@ -1,6 +1,4 @@ -import Title from "@/components/Title"; import styles from "./styles.module.css"; -import MainButton from "@/components/MainButton"; import PaymentDiscountTable from "./PaymentDiscountTable"; import Modal from "@/components/Modal"; import { useState } from "react"; @@ -10,6 +8,8 @@ import { EPlacementKeys } from "@/api/resources/Paywall"; import PaymentModal from "@/components/PaymentModal"; import { useTranslations } from "@/hooks/translations"; import { addCurrency, ELocalesPlacement } from "@/locales"; +import DiscountLayout from "../../layouts/Discount/DiscountLayout"; +import QuestionnaireGreenButton from "../../ui/GreenButton"; function TrialPaymentWithDiscount() { const { translate } = useTranslations(ELocalesPlacement.V1); @@ -22,7 +22,7 @@ function TrialPaymentWithDiscount() { }; return ( -
+ - Party popper - - {translate("/trial-payment-with-discount.title")} - - setIsOpenPaymentModal(true)} - > - {translate("/trial-payment-with-discount.button", { - trialDuration: activeProduct?.trialDuration, - })} - -

+ +

+ setIsOpenPaymentModal(true)} + > + {translate("/trial-payment-with-discount.button", { + trialDuration: activeProduct?.trialDuration, + })} + +
+

{translate("/trial-payment-with-discount.description", { trialDuration: activeProduct?.trialDuration, price: addCurrency((activeProduct?.price || 0) / 100, currency), })}

-
+ ); } diff --git a/src/components/pages/ABDesign/v1/pages/TrialPaymentWithDiscount/styles.module.css b/src/components/pages/ABDesign/v1/pages/TrialPaymentWithDiscount/styles.module.css index ecae37f..bec4a91 100644 --- a/src/components/pages/ABDesign/v1/pages/TrialPaymentWithDiscount/styles.module.css +++ b/src/components/pages/ABDesign/v1/pages/TrialPaymentWithDiscount/styles.module.css @@ -1,62 +1,27 @@ -.page { - position: relative; - height: fit-content; - min-height: 100dvh; - display: flex; - justify-content: center; - align-items: center; - flex-direction: column; - color: #fff; - padding-bottom: 64px; - background-color: #fff0f0; - width: 100%; - max-width: 460px; -} - -.party-popper { - width: 32px; -} - -.title { - margin-top: 11px; - font-size: 24px; - line-height: 33px; - text-align: center; - background: linear-gradient( - 165.54deg, - rgb(20, 19, 51) -33.39%, - rgb(32, 34, 97) 15.89%, - rgb(84, 60, 151) 55.84%, - rgb(105, 57, 162) 74.96% - ) - text; - -webkit-text-fill-color: transparent; - font-weight: 700; +.button-wrapper { + margin-top: 42px; + flex-grow: 1; + align-items: start; } .button { - margin-top: 32px; - border-radius: 30px; - min-height: 0; - height: 50px; - font-size: 20px; - font-weight: normal; - line-height: 22px; - width: 100%; - min-width: 0; - max-width: 360px; - background: #27ae60; - color: #fbfbff; + min-height: auto; + border-radius: 20px; + box-shadow: 2px 11px 17.1px -1px rgba(0, 0, 0, 0.13); } .policy { - color: rgb(51, 51, 51); - font-size: 13px; - font-weight: 400; - line-height: 20px; - margin-top: 28px; - padding-bottom: 10px; - max-width: 400px; + margin: 63px -32px -15px; + padding: 77px 22px 34px; + color: #fff; + font-size: 14px; + font-weight: 600; + line-height: 1.3; + background: linear-gradient(270deg, #ffa1ba -0.02%, #9a55ff 100%); + background-image: url("data:image/svg+xml,%3Csvg width='419' viewBox='0 0 419 400' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M418.859 43.2297C234.323 133.518 162.458 -74.6173 0 32.4194V400H418.859V43.2297Z' fill='url(%23paint0_linear_799_596)'/%3E%3Cdefs%3E%3ClinearGradient id='paint0_linear_799_596' x1='418.926' y1='400' x2='0.00759072' y2='400' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%23FFA1BA'/%3E%3Cstop offset='1' stop-color='%239A55FF'/%3E%3C/linearGradient%3E%3C/defs%3E%3C/svg%3E%0A"); + background-size: cover; + background-repeat: no-repeat; + } .modal { @@ -66,3 +31,9 @@ bottom: 0; transform: translate(-50%, 0); } + +@media (max-width: 390px) { + .button { + font-size: 26px; + } +} diff --git a/src/components/pages/AdditionalPurchases/components/ConsultationTable/index.tsx b/src/components/pages/AdditionalPurchases/components/ConsultationTable/index.tsx index a8a25ee..94a1d73 100644 --- a/src/components/pages/AdditionalPurchases/components/ConsultationTable/index.tsx +++ b/src/components/pages/AdditionalPurchases/components/ConsultationTable/index.tsx @@ -49,7 +49,11 @@ function ConsultationTable({ price }: IConsultationTableProps) { {addCurrency(99.99, currency)} ), - discount: Economisez 50, + discount: ( + + {translate("/add-consultation.discount_save")} 50% + + ), })}
diff --git a/src/components/pages/GetInformationPartner/index.tsx b/src/components/pages/GetInformationPartner/index.tsx index c9c7498..2c9e92f 100644 --- a/src/components/pages/GetInformationPartner/index.tsx +++ b/src/components/pages/GetInformationPartner/index.tsx @@ -1,7 +1,7 @@ import Title from "@/components/Title"; import styles from "./styles.module.css"; import MainButton from "@/components/MainButton"; -import { useNavigate } from "react-router-dom"; +import { useNavigate, useSearchParams } from "react-router-dom"; import routes from "@/routes"; import { useTranslations } from "@/hooks/translations"; import { ELocalesPlacement } from "@/locales"; @@ -9,12 +9,24 @@ import { ELocalesPlacement } from "@/locales"; function GetInformationPartnerPage() { const { translate } = useTranslations(ELocalesPlacement.V1); const navigate = useNavigate(); + const [searchParams] = useSearchParams(); + const path = searchParams.get("path"); + console.log(path); + const handleBack = () => { - navigate(routes.client.addConsultation()); + if (path === "palmistry") { + return navigate(routes.client.addGuides()); + } + navigate(routes.client.addConsultationV1()); }; const handleNext = () => { + if (path === "palmistry") { + return navigate( + `${routes.client.palmistryOnboardingV1()}?path=palmistry` + ); + } navigate(routes.client.home()); }; diff --git a/src/components/palmistry/AdditionalPurchases/pages/AddGuides/index.tsx b/src/components/palmistry/AdditionalPurchases/pages/AddGuides/index.tsx index 696eae3..8ba74d1 100644 --- a/src/components/palmistry/AdditionalPurchases/pages/AddGuides/index.tsx +++ b/src/components/palmistry/AdditionalPurchases/pages/AddGuides/index.tsx @@ -46,11 +46,15 @@ function AddGuides() { return products?.find((product) => product.key === id) || null; }; + const handleNext = () => { + navigate(`${routes.client.getInformationPartner()}?path=palmistry`); + }; + const handleClick = async () => { try { if (!userFromStore || !activeOffer) return; if (activeOffer.id === "skip_offer") { - return navigate(routes.client.home()); + return handleNext(); } const currentProduct = getCurrentProduct(activeOffer?.productKey); if (!currentProduct) return; @@ -73,11 +77,11 @@ function AddGuides() { setPaymentIntent(paymentIntent); if ("payment" in paymentIntent) { if (paymentIntent.payment.status === "paid") - return navigate(routes.client.home()); + return handleNext(); return setIsError(true); } if ("status" in paymentIntent && paymentIntent.status === "paid") { - return navigate(routes.client.home()); + return handleNext(); } } catch (error) { setIsError(true); @@ -87,7 +91,7 @@ function AddGuides() { }; const handleClickSkip = () => { - navigate(routes.client.home()); + handleNext(); }; return ( diff --git a/src/components/palmistry/step-birthdate/step-birthdate.tsx b/src/components/palmistry/step-birthdate/step-birthdate.tsx index 2ba0761..6e77e4d 100644 --- a/src/components/palmistry/step-birthdate/step-birthdate.tsx +++ b/src/components/palmistry/step-birthdate/step-birthdate.tsx @@ -1,32 +1,38 @@ -import React from 'react'; -import { useDispatch } from 'react-redux'; +import React from "react"; +import { useDispatch } from "react-redux"; -import { actions } from '@/store'; -import InputWrapper from '../input-wrapper/input-wrapper'; -import InputItem from '../input-item/input-item'; -import Button from '../button/button'; -import useSteps from '../../../hooks/palmistry/use-steps'; +import { actions } from "@/store"; +import InputWrapper from "../input-wrapper/input-wrapper"; +import InputItem from "../input-item/input-item"; +import Button from "../button/button"; +import useSteps from "../../../hooks/palmistry/use-steps"; +import { useSession } from "@/hooks/session/useSession"; +import { ESourceAuthorization } from "@/api/resources/User"; enum Field { - year = 'year', - month = 'month', - day = 'day', + year = "year", + month = "month", + day = "day", } -const dateDivider = '-'; +const dateDivider = "-"; export default function StepBirthdate() { const steps = useSteps(); const dispatch = useDispatch(); + const { updateSession } = useSession(); - const [year, setYear] = React.useState(''); - const [month, setMonth] = React.useState(''); - const [day, setDay] = React.useState(''); - const [fieldsWithErrors, setFieldsWithErrors] = React.useState(new Set as Set); + const [year, setYear] = React.useState(""); + const [month, setMonth] = React.useState(""); + const [day, setDay] = React.useState(""); + const [fieldsWithErrors, setFieldsWithErrors] = React.useState( + new Set() as Set + ); const [errorIsVisible, setErrorIsVisible] = React.useState(false); React.useEffect(() => { - const [storedYear, storedMonth, storedDay] = steps.storedValue.split(dateDivider); + const [storedYear, storedMonth, storedDay] = + steps.storedValue.split(dateDivider); if (storedYear) setYear(storedYear); if (storedMonth) setMonth(storedMonth); @@ -43,7 +49,7 @@ export default function StepBirthdate() { setFieldsWithErrors((prevValue) => { const newValue = new Set(prevValue); - if (value !== '' && yearNumber < 1924) { + if (value !== "" && yearNumber < 1924) { newValue.add(Field.year); } else { newValue.delete(Field.year); @@ -56,7 +62,9 @@ export default function StepBirthdate() { }; const onChangeMonth = (value: string) => { - const monthNumber = Number(Number(value).toString().replace(/\D/g, '').slice(0, 2)); + const monthNumber = Number( + Number(value).toString().replace(/\D/g, "").slice(0, 2) + ); if (Number.isNaN(monthNumber) || monthNumber > 12) { return; @@ -65,7 +73,7 @@ export default function StepBirthdate() { setFieldsWithErrors((prevValue) => { const newValue = new Set(prevValue); - if (value !== '' && (monthNumber < 1 || monthNumber > 12)) { + if (value !== "" && (monthNumber < 1 || monthNumber > 12)) { newValue.add(Field.year); } else { newValue.delete(Field.year); @@ -88,7 +96,7 @@ export default function StepBirthdate() { setFieldsWithErrors((prevValue) => { const newValue = new Set(prevValue); - if (value !== '' && dayNumber === 0) { + if (value !== "" && dayNumber === 0) { newValue.add(Field.day); } else { newValue.delete(Field.day); @@ -100,8 +108,8 @@ export default function StepBirthdate() { if ( Number.isNaN(dayNumber) || !monthNumber || - monthNumber === 2 && dayNumber > 29 || - [4, 6, 9, 11].includes(monthNumber) && dayNumber > 30 || + (monthNumber === 2 && dayNumber > 29) || + ([4, 6, 9, 11].includes(monthNumber) && dayNumber > 30) || dayNumber > 31 ) { return; @@ -128,11 +136,13 @@ export default function StepBirthdate() { const formIsValid = Boolean(year && month && day && !fieldsWithErrors.size); - const onNext = () => { + const onNext = async () => { if (!formIsValid) return; const birthdate = [year, month, day].join(dateDivider); + await updateSession({ profile: { birthdate: `${birthdate} 00:00` } }, ESourceAuthorization["aura.palmistry"]); + dispatch(actions.form.addDate(birthdate)); steps.saveCurrent(birthdate); @@ -142,7 +152,9 @@ export default function StepBirthdate() { return ( <> -

What’s your date of birth?

+

+ What’s your date of birth? +

Your birth date reveals your core personality traits, needs and desires. @@ -172,7 +184,7 @@ export default function StepBirthdate() { onFocus={() => onFocus(Field.month)} onBlur={() => onBlur(Field.month)} /> - + Date not found. Please check your details and try again. + "palmistry-container__error-text", + errorIsVisible ? "palmistry-container__error-text_visible" : "", + ].join(" ")} + > + Date not found. Please check your details and try again. +

- - diff --git a/src/components/palmistry/step-color-you-like/step-color-you-like.tsx b/src/components/palmistry/step-color-you-like/step-color-you-like.tsx index 1552a12..60daff5 100644 --- a/src/components/palmistry/step-color-you-like/step-color-you-like.tsx +++ b/src/components/palmistry/step-color-you-like/step-color-you-like.tsx @@ -1,11 +1,26 @@ -import Button from '../button/button'; -import ColorCircle from '../color-circle/color-circle'; -import useSteps, { ColorYouLikeChoice } from '../../../hooks/palmistry/use-steps'; +import Button from "../button/button"; +import ColorCircle from "../color-circle/color-circle"; +import useSteps, { + ColorYouLikeChoice, +} from "../../../hooks/palmistry/use-steps"; +import { useSession } from "@/hooks/session/useSession"; +import { IAnswersSession } from "@/api/resources/Session"; +import { ESourceAuthorization } from "@/api/resources/User"; export default function StepColorYouLike() { const steps = useSteps(); + const { updateSession } = useSession(); - const onNext = (choice: ColorYouLikeChoice) => { + const onNext = async (choice: ColorYouLikeChoice) => { + await updateSession( + { + answers: { + favorite_color: + choice.toLowerCase() as IAnswersSession["favorite_color"], + }, + }, + ESourceAuthorization["aura.palmistry"] + ); steps.saveCurrent(choice); steps.goNext(choice); }; @@ -22,7 +37,7 @@ export default function StepColorYouLike() { active={steps.storedValue === ColorYouLikeChoice.Red} onClick={() => onNext(ColorYouLikeChoice.Red)} > - + Red @@ -32,7 +47,7 @@ export default function StepColorYouLike() { active={steps.storedValue === ColorYouLikeChoice.Yellow} onClick={() => onNext(ColorYouLikeChoice.Yellow)} > - + Yellow @@ -42,7 +57,7 @@ export default function StepColorYouLike() { active={steps.storedValue === ColorYouLikeChoice.Blue} onClick={() => onNext(ColorYouLikeChoice.Blue)} > - + Blue @@ -52,7 +67,7 @@ export default function StepColorYouLike() { active={steps.storedValue === ColorYouLikeChoice.Orange} onClick={() => onNext(ColorYouLikeChoice.Orange)} > - + Orange @@ -62,7 +77,7 @@ export default function StepColorYouLike() { active={steps.storedValue === ColorYouLikeChoice.Green} onClick={() => onNext(ColorYouLikeChoice.Green)} > - + Green @@ -72,7 +87,7 @@ export default function StepColorYouLike() { active={steps.storedValue === ColorYouLikeChoice.Violet} onClick={() => onNext(ColorYouLikeChoice.Violet)} > - + Violet diff --git a/src/components/palmistry/step-decisions/step-decisions.tsx b/src/components/palmistry/step-decisions/step-decisions.tsx index d9417da..1a8cfc6 100644 --- a/src/components/palmistry/step-decisions/step-decisions.tsx +++ b/src/components/palmistry/step-decisions/step-decisions.tsx @@ -1,11 +1,24 @@ -import Button from '../button/button'; -import useSteps, { DecisionsChoice } from '../../../hooks/palmistry/use-steps'; +import Button from "../button/button"; +import useSteps, { DecisionsChoice } from "../../../hooks/palmistry/use-steps"; +import { useSession } from "@/hooks/session/useSession"; +import { IAnswersSession } from "@/api/resources/Session"; +import { ESourceAuthorization } from "@/api/resources/User"; export default function StepDecisions() { const steps = useSteps(); + const { updateSession } = useSession(); - const onNext = (choice: DecisionsChoice) => { + const onNext = async (choice: DecisionsChoice) => { steps.saveCurrent(choice); + await updateSession( + { + answers: { + head_or_heart: + choice.toLowerCase() as IAnswersSession["head_or_heart"], + }, + }, + ESourceAuthorization["aura.palmistry"] + ); steps.goNext(choice); }; @@ -14,7 +27,7 @@ export default function StepDecisions() {

Do you make decisions with your head or your heart?

- +
+ > + {answer} + ))}

Strongly -
+
Disagree

Strongly -
+
Agree

diff --git a/src/components/palmistry/step-resonated-element/step-resonated-element.tsx b/src/components/palmistry/step-resonated-element/step-resonated-element.tsx index 039058f..3d1f09e 100644 --- a/src/components/palmistry/step-resonated-element/step-resonated-element.tsx +++ b/src/components/palmistry/step-resonated-element/step-resonated-element.tsx @@ -1,11 +1,26 @@ -import Button from '../button/button'; -import useSteps, { ResonatedElementChoice } from '../../../hooks/palmistry/use-steps'; +import Button from "../button/button"; +import useSteps, { + ResonatedElementChoice, +} from "../../../hooks/palmistry/use-steps"; +import { useSession } from "@/hooks/session/useSession"; +import { IAnswersSession } from "@/api/resources/Session"; +import { ESourceAuthorization } from "@/api/resources/User"; export default function StepResonatedElement() { const steps = useSteps(); + const { updateSession } = useSession(); - const onNext = (choice: ResonatedElementChoice) => { + const onNext = async (choice: ResonatedElementChoice) => { steps.saveCurrent(choice); + await updateSession( + { + answers: { + element_resonates: + choice.toLowerCase() as IAnswersSession["element_resonates"], + }, + }, + ESourceAuthorization["aura.palmistry"] + ); steps.goNext(choice); }; @@ -21,9 +36,23 @@ export default function StepResonatedElement() { active={steps.storedValue === ResonatedElementChoice.Earth} onClick={() => onNext(ResonatedElementChoice.Earth)} > - - - + + + onNext(ResonatedElementChoice.Water)} > - - + + onNext(ResonatedElementChoice.Fire)} > - - + + onNext(ResonatedElementChoice.Air)} > - - - - + + + + Air diff --git a/src/components/palmistry/step-subscription-plan/step-subscription-plan.tsx b/src/components/palmistry/step-subscription-plan/step-subscription-plan.tsx index b32fbc3..ed8ff2d 100644 --- a/src/components/palmistry/step-subscription-plan/step-subscription-plan.tsx +++ b/src/components/palmistry/step-subscription-plan/step-subscription-plan.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useRef } from "react"; import { useDispatch } from "react-redux"; import { useSelector } from "react-redux"; @@ -9,13 +9,18 @@ import EmailHeader from "@/components/palmistry/email-header/email-header"; import { actions } from "@/store"; import { EPlacementKeys } from "@/api/resources/Paywall"; import { usePaywall } from "@/hooks/paywall/usePaywall"; -import {addCurrency} from "@/locales"; -import {getPriceCentsToDollars} from "@/services/price"; +import { addCurrency, getDefaultLocaleByLanguage, language } from "@/locales"; +import { getPriceCentsToDollars } from "@/services/price"; +import { IOutletContext } from "@/routerComponents/Palmistry/v1/LayoutPersonalVideo"; +import styles from "./styles.module.scss"; +import { useMetricABFlags } from "@/services/metric/metricService"; const bestPlanId = "stripe.15"; - -export default function StepSubscriptionPlan() { +export default function StepSubscriptionPlan({ + containerVideoRef: videoRef, + isVisibleElements, +}: Partial) { const steps = useSteps(); const dispatch = useDispatch(); const activeProductFromStore = useSelector(selectors.selectActiveProduct); @@ -32,6 +37,12 @@ export default function StepSubscriptionPlan() { const [email, setEmail] = React.useState(steps.getStoredValue(Step.Email)); + const containerVideoRef = useRef(null); + + const { flags } = useMetricABFlags(); + const auraVideoTrial = flags?.auraVideoTrial?.[0]; + const isLongText = flags?.text?.[0] === "on"; + React.useEffect(() => { if (!defaultProduct || activeProductFromStore) return; const targetDefaultProduct = products.find((p) => p.key === defaultProduct); @@ -43,7 +54,7 @@ export default function StepSubscriptionPlan() { activeProduct: targetDefaultProduct, }) ); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line react-hooks/exhaustive-deps }, [defaultProduct]); React.useEffect(() => { @@ -67,95 +78,178 @@ export default function StepSubscriptionPlan() { steps.goNext(); }; + React.useEffect(() => { + if (!containerVideoRef.current || !videoRef?.current) return; + containerVideoRef.current?.appendChild(videoRef.current); + if (auraVideoTrial === "on") { + videoRef.current.classList.add(styles["personal-video"]); + } + }, [auraVideoTrial, videoRef]); + + React.useEffect(() => { + if (auraVideoTrial === "on") { + dispatch(actions.personalVideo.updateIsVideoPlaying(true)); + } else { + dispatch(actions.personalVideo.updateIsVideoPlaying(false)); + } + }, [auraVideoTrial, dispatch]); + + const isShowDefault = () => { + if (auraVideoTrial === "on") { + return false; + } + return getDefaultLocaleByLanguage(language) !== "en" || !isLongText; + }; + return ( <> +
+ {auraVideoTrial !== "on" && + getDefaultLocaleByLanguage(language) === "en" && + isLongText && ( +

+ AURA is the only accurate app with reliable fate line analysis, + verified by professionals and guaranteed to provide precise + predictions. +
+
+ AURA has already helped millions of people find happiness and + discover the whole truth about their relationships. +
+
+ 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: +
+
+ You will discover all the most intimate secrets that the stars have + prepared for you and solve relationship issues within just one + month; +
+
+ 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); +
+
+ You will save hundreds of dollars on fake and unprofessional + astrological predictions and fortune tellers; +
+
+ 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. +
+
A 7-day trial period costs us $13.76, but please choose the + amount that suits you best: +

+ )} + {(isVisibleElements || auraVideoTrial !== "on") && ( + <> + {isShowDefault() && ( + <> +
+ We've helped millions of people to reveal the destiny of their + love life and what the future holds for them and their families. +
-
- We've helped millions of people to reveal the destiny of their love life - and what the future holds for them and their families. -
+
+ + + + + + + + + + + + + + + + + + +
+ + )} -
- - - - - - - - - - - - - - - - - - -
- -
- {products.map((_product) => ( -
setProduct(_product._id)} - > -

{addCurrency(getPriceCentsToDollars(_product.trialPrice || 0), currency)}

+
+ {products.map((_product) => ( +
setProduct(_product._id)} + > +

+ {addCurrency( + getPriceCentsToDollars(_product.trialPrice || 0), + currency + )} +

+
+ ))}
- ))} -
- - It costs us {addCurrency(13.73, currency)} to compensate our AURA employees for the trial, but - please choose the amount you are comfortable with. - + + It costs us {addCurrency(13.73, currency)} to compensate our AURA + employees for the trial, but please choose the amount you are + comfortable with. + - + + + )} ); } diff --git a/src/components/palmistry/step-subscription-plan/styles.module.scss b/src/components/palmistry/step-subscription-plan/styles.module.scss new file mode 100644 index 0000000..acb0ec2 --- /dev/null +++ b/src/components/palmistry/step-subscription-plan/styles.module.scss @@ -0,0 +1,53 @@ +.personal-video { + display: block !important; + margin-top: 16px !important; + border-radius: 0 !important; + background-image: url("/trial-choice-preview.png") !important; +} + +.title { + filter: opacity(0); + will-change: opacity; + animation: appearance 1s forwards; +} + +.image { + filter: opacity(0); + will-change: opacity; + animation: appearance 1s forwards 0.5s; +} + +.plans { + filter: opacity(0); + will-change: opacity; + animation: appearance 1s forwards 1s; +} + +.subscription-text { + filter: opacity(0); + will-change: opacity; + animation: appearance 1s forwards 1.5s; +} + +.button { + filter: opacity(0); + will-change: opacity; + animation: appearance 1s forwards 2s; +} + +@keyframes appearance { + 0% { + filter: opacity(0); + } + + 100% { + filter: opacity(1); + } +} + +.text { + filter: opacity(0); + will-change: opacity; + animation: appearance 1s forwards; + margin: -16px 0 16px; +} diff --git a/src/components/palmistry/step-welcome/step-welcome.tsx b/src/components/palmistry/step-welcome/step-welcome.tsx index c3a1ec8..44f68b9 100644 --- a/src/components/palmistry/step-welcome/step-welcome.tsx +++ b/src/components/palmistry/step-welcome/step-welcome.tsx @@ -1,16 +1,25 @@ -import Button from '@/components/palmistry/button/button'; -import useSteps from '@/hooks/palmistry/use-steps'; +import { ESourceAuthorization } from "@/api/resources/User"; +import Button from "@/components/palmistry/button/button"; +import useSteps from "@/hooks/palmistry/use-steps"; +import { useSession } from "@/hooks/session/useSession"; export default function StepWelcome() { + const { createSession } = useSession(); const steps = useSteps(); - const onNext = () => { + const onNext = async () => { + await createSession(ESourceAuthorization["aura.palmistry"]); steps.goNext(); }; return ( <> - +
- Find your happiness with highly-personalized predictions. + + Find your happiness with highly-personalized predictions. +
@@ -51,19 +62,28 @@ export default function StepWelcome() {

- By continuing, you agree to our{' '} - + By continuing, you agree to our{" "} + EULA - {' '} - and{' '} - + {" "} + and{" "} + Privacy Notice .

- This Palm Reading App is for entertainment purposes only and will not make death predictions + This Palm Reading App is for entertainment purposes only and will + not make death predictions
diff --git a/src/components/palmistry/step-wish/step-wish.tsx b/src/components/palmistry/step-wish/step-wish.tsx index e695d18..7a824ce 100644 --- a/src/components/palmistry/step-wish/step-wish.tsx +++ b/src/components/palmistry/step-wish/step-wish.tsx @@ -1,10 +1,30 @@ -import Button from '../button/button'; -import useSteps, { WishChoice } from '../../../hooks/palmistry/use-steps'; +import Button from "../button/button"; +import useSteps, { WishChoice } from "../../../hooks/palmistry/use-steps"; +import { useSession } from "@/hooks/session/useSession"; +import { IAnswersSession } from "@/api/resources/Session"; +import { ESourceAuthorization } from "@/api/resources/User"; + +const choiceForSession: { + [key in WishChoice]: IAnswersSession["what_aspects"]; +} = { + [WishChoice.Love]: "love_relationships", + [WishChoice.Health]: "health_vitality", + [WishChoice.Career]: "career_destiny", +}; export default function StepWish() { const steps = useSteps(); + const { updateSession } = useSession(); - const onNext = (choice: WishChoice) => { + const onNext = async (choice: WishChoice) => { + await updateSession( + { + answers: { + what_aspects: choiceForSession[choice], + }, + }, + ESourceAuthorization["aura.palmistry"] + ); steps.saveCurrent(choice); steps.goNext(choice); }; @@ -12,9 +32,12 @@ export default function StepWish() { return ( <>
-

What aspects of your life do you wish to gain insight into through palmistry?

+

+ What aspects of your life do you wish to gain insight into through + palmistry? +

- +