diff --git a/index.html b/index.html
index 100cf7a..ac1a9f6 100644
--- a/index.html
+++ b/index.html
@@ -2,10 +2,14 @@
-
-
- Aura Web App
+
+
+
+
+
+
+ AURA
diff --git a/package-lock.json b/package-lock.json
index 54e3445..3bd0c69 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,6 +9,7 @@
"version": "0.0.0",
"dependencies": {
"react": "^18.2.0",
+ "react-circular-progressbar": "^2.1.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.11.0"
},
@@ -23,7 +24,8 @@
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.3.4",
"typescript": "^5.0.2",
- "vite": "^4.3.2"
+ "vite": "^4.3.2",
+ "vite-plugin-copy": "^0.1.6"
}
},
"node_modules/@ampproject/remapping": {
@@ -2551,6 +2553,14 @@
"node": ">=0.10.0"
}
},
+ "node_modules/react-circular-progressbar": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/react-circular-progressbar/-/react-circular-progressbar-2.1.0.tgz",
+ "integrity": "sha512-xp4THTrod4aLpGy68FX/k1Q3nzrfHUjUe5v6FsdwXBl3YVMwgeXYQKDrku7n/D6qsJA9CuunarAboC2xCiKs1g==",
+ "peerDependencies": {
+ "react": "^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
"node_modules/react-dom": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
@@ -2963,6 +2973,18 @@
}
}
},
+ "node_modules/vite-plugin-copy": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/vite-plugin-copy/-/vite-plugin-copy-0.1.6.tgz",
+ "integrity": "sha512-bqIaefZOE2Jx8P5wJuHKL5GzCERa/pcwdUQWaocyTNXgalN2xkxXH7LmqRJ34V2OlKF2F9E/zj0zITS7U6PpUg==",
+ "dev": true,
+ "dependencies": {
+ "fast-glob": "^3.2.7"
+ },
+ "engines": {
+ "node": ">=14.8.0"
+ }
+ },
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@@ -4724,6 +4746,12 @@
"loose-envify": "^1.1.0"
}
},
+ "react-circular-progressbar": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/react-circular-progressbar/-/react-circular-progressbar-2.1.0.tgz",
+ "integrity": "sha512-xp4THTrod4aLpGy68FX/k1Q3nzrfHUjUe5v6FsdwXBl3YVMwgeXYQKDrku7n/D6qsJA9CuunarAboC2xCiKs1g==",
+ "requires": {}
+ },
"react-dom": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
@@ -4968,6 +4996,15 @@
"rollup": "^3.21.0"
}
},
+ "vite-plugin-copy": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/vite-plugin-copy/-/vite-plugin-copy-0.1.6.tgz",
+ "integrity": "sha512-bqIaefZOE2Jx8P5wJuHKL5GzCERa/pcwdUQWaocyTNXgalN2xkxXH7LmqRJ34V2OlKF2F9E/zj0zITS7U6PpUg==",
+ "dev": true,
+ "requires": {
+ "fast-glob": "^3.2.7"
+ }
+ },
"which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
diff --git a/package.json b/package.json
index 65a41ce..b5bbe61 100644
--- a/package.json
+++ b/package.json
@@ -11,6 +11,7 @@
},
"dependencies": {
"react": "^18.2.0",
+ "react-circular-progressbar": "^2.1.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.11.0"
},
@@ -25,6 +26,7 @@
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.3.4",
"typescript": "^5.0.2",
- "vite": "^4.3.2"
+ "vite": "^4.3.2",
+ "vite-plugin-copy": "^0.1.6"
}
}
diff --git a/src/assets/android-chrome-192x192.png b/src/assets/android-chrome-192x192.png
new file mode 100644
index 0000000..8ee328e
Binary files /dev/null and b/src/assets/android-chrome-192x192.png differ
diff --git a/src/assets/android-chrome-512x512.png b/src/assets/android-chrome-512x512.png
new file mode 100644
index 0000000..1e190fc
Binary files /dev/null and b/src/assets/android-chrome-512x512.png differ
diff --git a/src/assets/apple-touch-icon.png b/src/assets/apple-touch-icon.png
new file mode 100644
index 0000000..5b69426
Binary files /dev/null and b/src/assets/apple-touch-icon.png differ
diff --git a/src/assets/browserconfig.xml b/src/assets/browserconfig.xml
new file mode 100644
index 0000000..b3930d0
--- /dev/null
+++ b/src/assets/browserconfig.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+ #da532c
+
+
+
diff --git a/src/assets/favicon-16x16.png b/src/assets/favicon-16x16.png
new file mode 100644
index 0000000..0ce7744
Binary files /dev/null and b/src/assets/favicon-16x16.png differ
diff --git a/src/assets/favicon-32x32.png b/src/assets/favicon-32x32.png
new file mode 100644
index 0000000..ff73b7a
Binary files /dev/null and b/src/assets/favicon-32x32.png differ
diff --git a/src/assets/favicon.ico b/src/assets/favicon.ico
new file mode 100644
index 0000000..45d15b1
Binary files /dev/null and b/src/assets/favicon.ico differ
diff --git a/src/assets/mstile-150x150.png b/src/assets/mstile-150x150.png
new file mode 100644
index 0000000..925d8af
Binary files /dev/null and b/src/assets/mstile-150x150.png differ
diff --git a/src/assets/site.webmanifest b/src/assets/site.webmanifest
new file mode 100644
index 0000000..1e9747b
--- /dev/null
+++ b/src/assets/site.webmanifest
@@ -0,0 +1,19 @@
+{
+ "name": "",
+ "short_name": "",
+ "icons": [
+ {
+ "src": "/assets/android-chrome-192x192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ },
+ {
+ "src": "/assets/android-chrome-512x512.png",
+ "sizes": "512x512",
+ "type": "image/png"
+ }
+ ],
+ "theme_color": "#ffffff",
+ "background_color": "#ffffff",
+ "display": "standalone"
+}
diff --git a/src/components/CreateProfilePage/ProcessFlow.tsx b/src/components/CreateProfilePage/ProcessFlow.tsx
new file mode 100644
index 0000000..6b927db
--- /dev/null
+++ b/src/components/CreateProfilePage/ProcessFlow.tsx
@@ -0,0 +1,67 @@
+import { useEffect, useState } from 'react'
+import ProcessItem from "./ProcessItem"
+
+interface Task {
+ (): Promise
+}
+
+type ProcessItem = {
+ task: Task
+ label: string
+}
+
+type ProcessFlowProps = {
+ items: ProcessItem[]
+ onDone: () => void
+}
+
+enum ProcessStatus {
+ Idle,
+ Pending,
+ Done,
+}
+
+const createChaining = (tasks: Task[], callback: (idx: number) => void) => {
+ return tasks.reduce((chain, task, idx) => {
+ return chain.then(task).then(()=> callback(idx))
+ }, Promise.resolve())
+}
+
+const getMultiplier = (currentIdx: number, length: number): number => {
+ return Math.max(length - (currentIdx + 1) - 1, 0)
+}
+
+const calculateTop = (currentIdx: number, length: number): number => {
+ const itemHeight = 56
+ return getMultiplier(currentIdx, length) * itemHeight
+}
+
+function ProcessFlow({ items, onDone }: ProcessFlowProps): JSX.Element {
+ const [status, setStatus] = useState(ProcessStatus.Idle)
+ const [doneTaskIdx, setDoneTaskIdx] = useState(-1)
+ const tasks = items.map(({ task }) => task)
+
+ useEffect(() => {
+ if (status !== ProcessStatus.Idle) return
+ setStatus(ProcessStatus.Pending)
+ createChaining(tasks, setDoneTaskIdx)
+ .then(() => setStatus(ProcessStatus.Done))
+ .then(() => onDone())
+ }, [status, tasks, onDone])
+
+ const toItems = ({ label }: ProcessItem, idx: number): JSX.Element => {
+ return
+ }
+ return (
+
+ {items.map(toItems)}
+
+ )
+}
+
+export default ProcessFlow
diff --git a/src/components/CreateProfilePage/ProcessItem.tsx b/src/components/CreateProfilePage/ProcessItem.tsx
new file mode 100644
index 0000000..517a9c3
--- /dev/null
+++ b/src/components/CreateProfilePage/ProcessItem.tsx
@@ -0,0 +1,23 @@
+type ProcessItemProps = {
+ top: number
+ label: string
+ isDone: boolean
+}
+
+function ProcessItem({ top, label, isDone }: ProcessItemProps): JSX.Element {
+
+ return (
+
+
+ {
+ isDone
+ ?
✅
+ :
+ }
+
+
{label}
+
+ )
+}
+
+export default ProcessItem
diff --git a/src/components/CreateProfilePage/index.tsx b/src/components/CreateProfilePage/index.tsx
index f9042a6..c1ba642 100644
--- a/src/components/CreateProfilePage/index.tsx
+++ b/src/components/CreateProfilePage/index.tsx
@@ -1,19 +1,44 @@
-import { useEffect } from "react"
+import { useState } from "react"
import { useNavigate } from "react-router-dom"
+import { CircularProgressbar, buildStyles } from 'react-circular-progressbar'
+import ProcessFlow from "./ProcessFlow"
import Title from "../Title"
import routes from "../../routes"
+import './styles.css'
+
+const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))
function CreateProfilePage(): JSX.Element {
const navigate = useNavigate()
-
- useEffect(() => {
- const timerId = setTimeout(() => navigate(routes.client.emailEnter()), 3000)
- return () => clearTimeout(timerId)
- }, [navigate])
+ const [progress, setProgress] = useState(0)
+ const processItems = [
+ { task: () => sleep(3300).then(() => setProgress(35)), label: 'Zodiac data analysis' },
+ { task: () => sleep(2550).then(() => setProgress(61)), label: 'Drawing Wallpapers' },
+ { task: () => sleep(3789).then(() => setProgress(98)), label: 'Preparing results' },
+ ]
+ const handleDone = () => Promise.resolve()
+ .then(() => setProgress(100))
+ .then(() => sleep(1000))
+ .then(() => navigate(routes.client.emailEnter()))
return (
Creating your profile
+
+
+
+
)
}
diff --git a/src/components/CreateProfilePage/styles.css b/src/components/CreateProfilePage/styles.css
new file mode 100644
index 0000000..4ef8b68
--- /dev/null
+++ b/src/components/CreateProfilePage/styles.css
@@ -0,0 +1,91 @@
+.progressbar {
+ width: 100%;
+ max-width: 250px;
+ margin: 24px auto;
+}
+
+.process-items {
+ overflow: hidden;
+}
+
+.process-item {
+ display: flex;
+ font-size: 24px;
+ font-weight: 400;
+ margin-bottom: 24px;
+ line-height: 32px;
+ position: relative;
+ transition: top .4s ease-in-out;
+}
+
+.process-item__pick {
+ position: relative;
+ margin-right: 15px;
+ width: 32px;
+ height: 32px;
+ clear: both;
+}
+
+.process-item__icon {
+ font-size: 32px;
+}
+
+.process-item__loader {
+ display: block;
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ margin: auto;
+ width: 32px;
+ height: 32px;
+ animation: loader-1-1 4.8s linear infinite;
+}
+
+@keyframes loader-1-1 {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+}
+
+.process-item__loader span {
+ display: block;
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ margin: auto;
+ height: 32px;
+ width: 32px;
+ clip: rect(0, 32px, 32px, 16px);
+ animation: loader-1-2 1.2s linear infinite;
+}
+
+@keyframes loader-1-2 {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(220deg); }
+}
+
+.process-item__loader span::after {
+ position: absolute;
+ box-sizing: border-box;
+ content: "";
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ margin: auto;
+ height: 32px;
+ width: 32px;
+ clip: rect(0, 32px, 32px, 16px);
+ border: 3px solid #000;
+ border-radius: 50%;
+ animation: loader-1-3 1.2s cubic-bezier(0.770, 0.000, 0.175, 1.000) infinite;
+}
+
+@keyframes loader-1-3 {
+ 0% { transform: rotate(-140deg); }
+ 50% { transform: rotate(-160deg); }
+ 100% { transform: rotate(140deg); }
+}
diff --git a/src/components/SubscriptionPage/index.tsx b/src/components/SubscriptionPage/index.tsx
index 8d64f8d..4c059af 100644
--- a/src/components/SubscriptionPage/index.tsx
+++ b/src/components/SubscriptionPage/index.tsx
@@ -25,11 +25,8 @@ function SubscriptionPage(): JSX.Element {
<>
-
- Your personalized Aries Wallpaper has been created! Find your happiness now and get an additional individual horoscope based on your energies.
-
-
+
diff --git a/src/main.ts b/src/main.ts
index 897a2a0..54dbd90 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,5 +1,6 @@
import ReactDOM from 'react-dom/client'
import init from './init'
+import 'react-circular-progressbar/dist/styles.css'
import './fonts.css'
import './index.css'
diff --git a/vite.config.ts b/vite.config.ts
index 5a33944..20b8e9f 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -1,7 +1,21 @@
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
+import { copy } from 'vite-plugin-copy'
// https://vitejs.dev/config/
export default defineConfig({
- plugins: [react()],
+ build: {
+ manifest: false,
+ },
+ plugins: [
+ react(),
+ copy([
+ { src: 'src/assets/favicon.ico', dest: 'dist' },
+ { src: 'src/assets/browserconfig.xml', dest: 'dist' },
+ { src: 'src/assets/mstile-150x150.png', dest: 'dist' },
+ { src: 'src/assets/android-chrome-192x192.png', dest: 'dist/assets' },
+ { src: 'src/assets/android-chrome-512x512.png', dest: 'dist/assets' },
+ { src: 'src/assets/android-chrome-512x512.png', dest: 'dist/assets' },
+ ], { hook: 'writeBundle' }),
+ ],
})