Base markup has been added
This commit is contained in:
parent
1fdc0aae1f
commit
3b52ed4989
2
Makefile
2
Makefile
@ -5,7 +5,7 @@ install-local:
|
|||||||
npm install
|
npm install
|
||||||
|
|
||||||
start:
|
start:
|
||||||
npm run dev
|
npm run dev -- --host
|
||||||
|
|
||||||
build:
|
build:
|
||||||
npm run build
|
npm run build
|
||||||
|
|||||||
@ -10,6 +10,6 @@
|
|||||||
<body>
|
<body>
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
<script type="module" src="/src/main.tsx"></script>
|
<script type="module" src="/src/main.ts"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
118
package-lock.json
generated
118
package-lock.json
generated
@ -9,11 +9,13 @@
|
|||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0"
|
"react-dom": "^18.2.0",
|
||||||
|
"react-router-dom": "^6.11.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/react": "^18.0.28",
|
"@types/react": "^18.0.28",
|
||||||
"@types/react-dom": "^18.0.11",
|
"@types/react-dom": "^18.0.11",
|
||||||
|
"@types/react-router-dom": "^5.3.3",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.57.1",
|
"@typescript-eslint/eslint-plugin": "^5.57.1",
|
||||||
"@typescript-eslint/parser": "^5.57.1",
|
"@typescript-eslint/parser": "^5.57.1",
|
||||||
"@vitejs/plugin-react": "^4.0.0",
|
"@vitejs/plugin-react": "^4.0.0",
|
||||||
@ -929,6 +931,20 @@
|
|||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@remix-run/router": {
|
||||||
|
"version": "1.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.6.0.tgz",
|
||||||
|
"integrity": "sha512-N13NRw3T2+6Xi9J//3CGLsK2OqC8NMme3d/YX+nh05K9YHWGcv8DycHJrqGScSP4T75o8IN6nqIMhVFU8ohg8w==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/history": {
|
||||||
|
"version": "4.7.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz",
|
||||||
|
"integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/@types/json-schema": {
|
"node_modules/@types/json-schema": {
|
||||||
"version": "7.0.11",
|
"version": "7.0.11",
|
||||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
|
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
|
||||||
@ -961,6 +977,27 @@
|
|||||||
"@types/react": "*"
|
"@types/react": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/react-router": {
|
||||||
|
"version": "5.1.20",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz",
|
||||||
|
"integrity": "sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/history": "^4.7.11",
|
||||||
|
"@types/react": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/react-router-dom": {
|
||||||
|
"version": "5.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz",
|
||||||
|
"integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/history": "^4.7.11",
|
||||||
|
"@types/react": "*",
|
||||||
|
"@types/react-router": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/scheduler": {
|
"node_modules/@types/scheduler": {
|
||||||
"version": "0.16.3",
|
"version": "0.16.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz",
|
||||||
@ -2535,6 +2572,36 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-router": {
|
||||||
|
"version": "6.11.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.11.0.tgz",
|
||||||
|
"integrity": "sha512-hTm6KKNpj9SDG4syIWRjCU219O0RZY8RUPobCFt9p+PlF7nnkRgMoh2DieTKvw3F3Mw6zg565HGnSv8BuoY5oQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@remix-run/router": "1.6.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=16.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-router-dom": {
|
||||||
|
"version": "6.11.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.11.0.tgz",
|
||||||
|
"integrity": "sha512-Q3mK1c/CYoF++J6ZINz7EZzwlgSOZK/kc7lxIA7PhtWhKju4KfF1WHqlx0kVCIFJAWztuYVpXZeljEbds8z4Og==",
|
||||||
|
"dependencies": {
|
||||||
|
"@remix-run/router": "1.6.0",
|
||||||
|
"react-router": "6.11.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=16.8",
|
||||||
|
"react-dom": ">=16.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/resolve-from": {
|
"node_modules/resolve-from": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
|
||||||
@ -3512,6 +3579,17 @@
|
|||||||
"fastq": "^1.6.0"
|
"fastq": "^1.6.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@remix-run/router": {
|
||||||
|
"version": "1.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.6.0.tgz",
|
||||||
|
"integrity": "sha512-N13NRw3T2+6Xi9J//3CGLsK2OqC8NMme3d/YX+nh05K9YHWGcv8DycHJrqGScSP4T75o8IN6nqIMhVFU8ohg8w=="
|
||||||
|
},
|
||||||
|
"@types/history": {
|
||||||
|
"version": "4.7.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz",
|
||||||
|
"integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@types/json-schema": {
|
"@types/json-schema": {
|
||||||
"version": "7.0.11",
|
"version": "7.0.11",
|
||||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
|
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
|
||||||
@ -3544,6 +3622,27 @@
|
|||||||
"@types/react": "*"
|
"@types/react": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/react-router": {
|
||||||
|
"version": "5.1.20",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz",
|
||||||
|
"integrity": "sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/history": "^4.7.11",
|
||||||
|
"@types/react": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@types/react-router-dom": {
|
||||||
|
"version": "5.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz",
|
||||||
|
"integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/history": "^4.7.11",
|
||||||
|
"@types/react": "*",
|
||||||
|
"@types/react-router": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/scheduler": {
|
"@types/scheduler": {
|
||||||
"version": "0.16.3",
|
"version": "0.16.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz",
|
||||||
@ -4640,6 +4739,23 @@
|
|||||||
"integrity": "sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==",
|
"integrity": "sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"react-router": {
|
||||||
|
"version": "6.11.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.11.0.tgz",
|
||||||
|
"integrity": "sha512-hTm6KKNpj9SDG4syIWRjCU219O0RZY8RUPobCFt9p+PlF7nnkRgMoh2DieTKvw3F3Mw6zg565HGnSv8BuoY5oQ==",
|
||||||
|
"requires": {
|
||||||
|
"@remix-run/router": "1.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"react-router-dom": {
|
||||||
|
"version": "6.11.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.11.0.tgz",
|
||||||
|
"integrity": "sha512-Q3mK1c/CYoF++J6ZINz7EZzwlgSOZK/kc7lxIA7PhtWhKju4KfF1WHqlx0kVCIFJAWztuYVpXZeljEbds8z4Og==",
|
||||||
|
"requires": {
|
||||||
|
"@remix-run/router": "1.6.0",
|
||||||
|
"react-router": "6.11.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"resolve-from": {
|
"resolve-from": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
|
||||||
|
|||||||
@ -11,11 +11,13 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0"
|
"react-dom": "^18.2.0",
|
||||||
|
"react-router-dom": "^6.11.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/react": "^18.0.28",
|
"@types/react": "^18.0.28",
|
||||||
"@types/react-dom": "^18.0.11",
|
"@types/react-dom": "^18.0.11",
|
||||||
|
"@types/react-router-dom": "^5.3.3",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.57.1",
|
"@typescript-eslint/eslint-plugin": "^5.57.1",
|
||||||
"@typescript-eslint/parser": "^5.57.1",
|
"@typescript-eslint/parser": "^5.57.1",
|
||||||
"@vitejs/plugin-react": "^4.0.0",
|
"@vitejs/plugin-react": "^4.0.0",
|
||||||
|
|||||||
42
src/App.css
42
src/App.css
@ -1,42 +0,0 @@
|
|||||||
#root {
|
|
||||||
max-width: 1280px;
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 2rem;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo {
|
|
||||||
height: 6em;
|
|
||||||
padding: 1.5em;
|
|
||||||
will-change: filter;
|
|
||||||
transition: filter 300ms;
|
|
||||||
}
|
|
||||||
.logo:hover {
|
|
||||||
filter: drop-shadow(0 0 2em #646cffaa);
|
|
||||||
}
|
|
||||||
.logo.react:hover {
|
|
||||||
filter: drop-shadow(0 0 2em #61dafbaa);
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes logo-spin {
|
|
||||||
from {
|
|
||||||
transform: rotate(0deg);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-reduced-motion: no-preference) {
|
|
||||||
a:nth-of-type(2) .logo {
|
|
||||||
animation: logo-spin infinite 20s linear;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.card {
|
|
||||||
padding: 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.read-the-docs {
|
|
||||||
color: #888;
|
|
||||||
}
|
|
||||||
24
src/App.tsx
24
src/App.tsx
@ -1,24 +0,0 @@
|
|||||||
import { useState } from 'react'
|
|
||||||
import './App.css'
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<h1>Let's start!</h1>
|
|
||||||
<h2>What's your date of birth?</h2>
|
|
||||||
<button>Next</button>
|
|
||||||
<footer>
|
|
||||||
<p>By continuing, you agree to our
|
|
||||||
<a href='https://aura.wit.life/terms'>EULA</a>
|
|
||||||
and
|
|
||||||
<a href='https://aura.wit.life/privacy'>Privacy Notice</a>.
|
|
||||||
Have a question? Reach our support team
|
|
||||||
<a href='https://aura.wit.life/'>here</a>
|
|
||||||
</p>
|
|
||||||
<small>For entertaiment purposes only</small>
|
|
||||||
</footer>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default App
|
|
||||||
BIN
src/assets/media/sf-mono-bold.otf
Normal file
BIN
src/assets/media/sf-mono-bold.otf
Normal file
Binary file not shown.
BIN
src/assets/media/sf-pro-text-bold.woff
Normal file
BIN
src/assets/media/sf-pro-text-bold.woff
Normal file
Binary file not shown.
BIN
src/assets/media/sf-pro-text-medium.woff
Normal file
BIN
src/assets/media/sf-pro-text-medium.woff
Normal file
Binary file not shown.
BIN
src/assets/media/sf-pro-text-regular.woff
Normal file
BIN
src/assets/media/sf-pro-text-regular.woff
Normal file
Binary file not shown.
BIN
src/assets/media/sf-pro-text-semibold.woff
Normal file
BIN
src/assets/media/sf-pro-text-semibold.woff
Normal file
Binary file not shown.
31
src/components/App/index.tsx
Normal file
31
src/components/App/index.tsx
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import { Routes, Route, Navigate } from 'react-router-dom';
|
||||||
|
import BirthdayPage from '../BirthdayPage'
|
||||||
|
import BirthtimePage from '../BirthtimePage'
|
||||||
|
import CreateProfilePage from '../CreateProfilePage'
|
||||||
|
import NotFoundPage from '../NotFoundPage'
|
||||||
|
import Header from '../Header'
|
||||||
|
import routes from '../../routes'
|
||||||
|
import './styles.css'
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
return (
|
||||||
|
<div className='container'>
|
||||||
|
<Header />
|
||||||
|
<main className='content'>
|
||||||
|
<section className='page'>
|
||||||
|
<Routes>
|
||||||
|
<Route path={routes.client.root()} element={
|
||||||
|
<Navigate to={routes.client.birthday()} />
|
||||||
|
} />
|
||||||
|
<Route path={routes.client.birthday()} element={<BirthdayPage />} />
|
||||||
|
<Route path={routes.client.birthtime()} element={<BirthtimePage />} />
|
||||||
|
<Route path={routes.client.createProfile()} element={<CreateProfilePage />} />
|
||||||
|
<Route path="*" element={<NotFoundPage />} />
|
||||||
|
</Routes>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App
|
||||||
25
src/components/App/styles.css
Normal file
25
src/components/App/styles.css
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0 auto;
|
||||||
|
max-width: 560px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
height: 100vh;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page {
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
flex: 1 1;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 15px 32px;
|
||||||
|
}
|
||||||
15
src/components/BackButton/index.tsx
Normal file
15
src/components/BackButton/index.tsx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import './styles.css'
|
||||||
|
|
||||||
|
function BackButton({ className, ...props }: React.ButtonHTMLAttributes<HTMLDivElement>): JSX.Element {
|
||||||
|
const combinedClassNames = ['back-btn', className].filter(Boolean).join(' ')
|
||||||
|
return (
|
||||||
|
<div className={combinedClassNames} {...props}>
|
||||||
|
<svg width="25" height="25" viewBox="0 0 25 25" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M19.7676 12.3203H5.76758" stroke="black" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"></path>
|
||||||
|
<path d="M12.7676 19.3203L5.76758 12.3203L12.7676 5.32031" stroke="black" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"></path>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BackButton
|
||||||
9
src/components/BackButton/styles.css
Normal file
9
src/components/BackButton/styles.css
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
.back-btn {
|
||||||
|
display: flex;
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
left: 28px;
|
||||||
|
cursor: pointer;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
27
src/components/BirthdayPage/index.tsx
Normal file
27
src/components/BirthdayPage/index.tsx
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { useNavigate } from 'react-router-dom'
|
||||||
|
import routes from '../../routes'
|
||||||
|
import Policy from '../Policy'
|
||||||
|
import Purposes from '../Purposes'
|
||||||
|
import Title from '../Title'
|
||||||
|
import DateControl from '../DateControl'
|
||||||
|
import MainButton from '../MainButton'
|
||||||
|
import './styles.css'
|
||||||
|
|
||||||
|
function BirthdayPage(): JSX.Element {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const handleNext = () => navigate(routes.client.birthtime())
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Title variant='h3' className='mt-24'>Let's start!</Title>
|
||||||
|
<Title variant='h2'>What's your date of birth?</Title>
|
||||||
|
<DateControl />
|
||||||
|
<MainButton label='Next' onClick={handleNext} />
|
||||||
|
<footer className='footer'>
|
||||||
|
<Policy />
|
||||||
|
<Purposes />
|
||||||
|
</footer>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BirthdayPage
|
||||||
5
src/components/BirthdayPage/styles.css
Normal file
5
src/components/BirthdayPage/styles.css
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
.footer {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
21
src/components/BirthtimePage/index.tsx
Normal file
21
src/components/BirthtimePage/index.tsx
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { useNavigate } from "react-router-dom"
|
||||||
|
import Title from "../Title"
|
||||||
|
import MainButton from "../MainButton"
|
||||||
|
import TimeControl from "../TimeControl"
|
||||||
|
import routes from "../../routes"
|
||||||
|
import './styles.css'
|
||||||
|
|
||||||
|
function BirthtimePage(): JSX.Element {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const handleNext = () => navigate(routes.client.createProfile())
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Title variant="h2" className="mt-24">What time were you born?</Title>
|
||||||
|
<p className="description">We use NASA data to determine the exact position of the planets in the sky at the time of your birth to create wallpapers that are just right for you.</p>
|
||||||
|
<TimeControl />
|
||||||
|
<MainButton label='Next' onClick={handleNext} />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BirthtimePage
|
||||||
7
src/components/BirthtimePage/styles.css
Normal file
7
src/components/BirthtimePage/styles.css
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
.description {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 140%;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
11
src/components/CreateProfilePage/index.tsx
Normal file
11
src/components/CreateProfilePage/index.tsx
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import Title from "../Title"
|
||||||
|
|
||||||
|
function CreateProfilePage(): JSX.Element {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Title variant="h2" className="mt-24">Creating your profile</Title>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CreateProfilePage
|
||||||
33
src/components/DateControl/index.tsx
Normal file
33
src/components/DateControl/index.tsx
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import './styles.css'
|
||||||
|
|
||||||
|
function DateControl(): JSX.Element {
|
||||||
|
return (
|
||||||
|
<div className='date-control'>
|
||||||
|
<div className='date-control__container'>
|
||||||
|
<div className="date-control__field">
|
||||||
|
<h3 className='date-control__field-label'>Year</h3>
|
||||||
|
<label className="date-control__input">
|
||||||
|
<input type="number" placeholder=" " max="4" />
|
||||||
|
<p className="date-control__input-placeholder">YYYY</p>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className="date-control__field">
|
||||||
|
<h3 className='date-control__field-label'>Month</h3>
|
||||||
|
<label className="date-control__input">
|
||||||
|
<input type="text" placeholder=" " />
|
||||||
|
<p className="date-control__input-placeholder">MM</p>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className="date-control__field">
|
||||||
|
<h3 className='date-control__field-label'>Day</h3>
|
||||||
|
<label className="date-control__input">
|
||||||
|
<input type="text" placeholder=" " />
|
||||||
|
<p className="date-control__input-placeholder">DD</p>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DateControl
|
||||||
99
src/components/DateControl/styles.css
Normal file
99
src/components/DateControl/styles.css
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
.date-control {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-control__container {
|
||||||
|
grid-gap: 12px;
|
||||||
|
background-color: #fff;
|
||||||
|
display: grid;
|
||||||
|
gap: 12px;
|
||||||
|
grid-template-columns: repeat(3,1fr);
|
||||||
|
max-width: 400px;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
z-index: 3;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-control__field-label {
|
||||||
|
color: #6b7baa;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 16px;
|
||||||
|
margin: 0 0 6px 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-control__input {
|
||||||
|
display: block;
|
||||||
|
font-size: 16px;
|
||||||
|
width: 100%;
|
||||||
|
height: 48px;
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-control__input > input {
|
||||||
|
appearance: none;
|
||||||
|
border-radius: 8px;
|
||||||
|
color: #121620;
|
||||||
|
font-size: 16px;
|
||||||
|
height: 48px;
|
||||||
|
line-height: 18px;
|
||||||
|
max-width: 400px;
|
||||||
|
min-width: 96px;
|
||||||
|
outline: none;
|
||||||
|
padding: 12px 12px 5px;
|
||||||
|
transition: border-color .3s ease;
|
||||||
|
width: 100%;
|
||||||
|
background: #eff2fd;
|
||||||
|
border: 2px solid #dee5f9;
|
||||||
|
padding-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-control__input > input:focus {
|
||||||
|
border-color: #066fde;
|
||||||
|
transition-delay: .1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-control__input-placeholder {
|
||||||
|
color: #6b7baa;
|
||||||
|
font-size: 16px;
|
||||||
|
left: 12px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
transition: top .3s ease,color .3s ease,font-size .3s ease;
|
||||||
|
white-space: nowrap;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-control__input input:focus + .date-control__input-placeholder,
|
||||||
|
.date-control__input input:not(:placeholder-shown) + .date-control__input-placeholder {
|
||||||
|
display: none;
|
||||||
|
font-size: 12px;
|
||||||
|
top: 12px;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-control__field-select {
|
||||||
|
display: block;
|
||||||
|
font-size: 16px;
|
||||||
|
width: 100%;
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 0;
|
||||||
|
appearance: none;
|
||||||
|
border-radius: 8px;
|
||||||
|
color: #121620;
|
||||||
|
height: 48px;
|
||||||
|
line-height: 18px;
|
||||||
|
max-width: 400px;
|
||||||
|
min-width: 96px;
|
||||||
|
outline: none;
|
||||||
|
padding: 12px 12px 5px;
|
||||||
|
transition: border-color .3s ease;
|
||||||
|
background: #eff2fd;
|
||||||
|
border: 2px solid #dee5f9;
|
||||||
|
padding-top: 5px;
|
||||||
|
}
|
||||||
BIN
src/components/Header/icon.png
Normal file
BIN
src/components/Header/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 MiB |
40
src/components/Header/index.tsx
Normal file
40
src/components/Header/index.tsx
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import { useState, useEffect } from 'react'
|
||||||
|
import { useNavigate, useLocation } from 'react-router-dom'
|
||||||
|
import routes, { isNotEntrypoint } from '../../routes'
|
||||||
|
import BackButton from '../BackButton'
|
||||||
|
import iconUrl from './icon.png'
|
||||||
|
import './styles.css'
|
||||||
|
|
||||||
|
function Header(): JSX.Element {
|
||||||
|
const navigate = useNavigate()
|
||||||
|
const location = useLocation()
|
||||||
|
const [initialPath, setInitialPath] = useState<string | null>(null);
|
||||||
|
const [isNavigated, setIsNavigated] = useState<boolean>(false);
|
||||||
|
const showBackButton = isNotEntrypoint(location.pathname)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!initialPath) {
|
||||||
|
setInitialPath(location.pathname)
|
||||||
|
}
|
||||||
|
if (initialPath && location.pathname !== initialPath && !isNavigated) {
|
||||||
|
setIsNavigated(true)
|
||||||
|
}
|
||||||
|
}, [location.pathname, initialPath, isNavigated])
|
||||||
|
|
||||||
|
const goBack = () => {
|
||||||
|
if (initialPath && isNotEntrypoint(initialPath) && !isNavigated) {
|
||||||
|
navigate(routes.client.root())
|
||||||
|
} else {
|
||||||
|
navigate(-1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<header className="header">
|
||||||
|
{ showBackButton ? <BackButton className="pa" onClick={goBack} /> : null }
|
||||||
|
<img src={iconUrl} alt="logo" width="40" height="40" />
|
||||||
|
</header>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Header
|
||||||
10
src/components/Header/styles.css
Normal file
10
src/components/Header/styles.css
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
.header {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
background: #eff1fd;
|
||||||
|
height: 50px;
|
||||||
|
min-height: 50px;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
13
src/components/MainButton/index.tsx
Normal file
13
src/components/MainButton/index.tsx
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import './styles.css'
|
||||||
|
|
||||||
|
type ButtonProps = {
|
||||||
|
label: string;
|
||||||
|
} & React.ButtonHTMLAttributes<HTMLButtonElement>;
|
||||||
|
|
||||||
|
|
||||||
|
function MainButton({ className, label, ...props}: ButtonProps): JSX.Element {
|
||||||
|
const combinedClassNames = ['main-btn', className].filter(Boolean).join(' ')
|
||||||
|
return <button className={combinedClassNames} {...props}>{label}</button>
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MainButton
|
||||||
22
src/components/MainButton/styles.css
Normal file
22
src/components/MainButton/styles.css
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
.main-btn {
|
||||||
|
align-items: center;
|
||||||
|
background: #000;
|
||||||
|
border: none;
|
||||||
|
border-radius: 20px;
|
||||||
|
color: #fff;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 500;
|
||||||
|
justify-content: center;
|
||||||
|
line-height: 20px;
|
||||||
|
max-width: 400px;
|
||||||
|
min-height: 60px;
|
||||||
|
min-width: 250px;
|
||||||
|
padding: 12px 16px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-btn:disabled {
|
||||||
|
opacity: 50%;
|
||||||
|
}
|
||||||
10
src/components/NotFoundPage/index.tsx
Normal file
10
src/components/NotFoundPage/index.tsx
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
function NotFoundPage() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h1>Oops!</h1>
|
||||||
|
<p>Sorry, an unexpected error has occurred.</p>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NotFoundPage
|
||||||
39
src/components/Policy/index.tsx
Normal file
39
src/components/Policy/index.tsx
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import { ReactNode } from 'react'
|
||||||
|
import './styles.css'
|
||||||
|
|
||||||
|
enum PolicyContentType {
|
||||||
|
Text = 'text',
|
||||||
|
Link = 'link',
|
||||||
|
}
|
||||||
|
|
||||||
|
type PolicyContent = {
|
||||||
|
type: PolicyContentType
|
||||||
|
content: string
|
||||||
|
href?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
function Policy(): JSX.Element {
|
||||||
|
const text: PolicyContent[] = [
|
||||||
|
{ type: PolicyContentType.Text, content: 'By continuing, you agree to our ' },
|
||||||
|
{ type: PolicyContentType.Link, content: 'EULA', href: 'https://aura.wit.life/terms' },
|
||||||
|
{ type: PolicyContentType.Text, content: ' and ' },
|
||||||
|
{ type: PolicyContentType.Link, content: 'Privacy Notice', href: 'https://aura.wit.life/privacy' },
|
||||||
|
{ type: PolicyContentType.Text, content: '. Have a question? Reach our support team ' },
|
||||||
|
{ type: PolicyContentType.Link, content: 'here', href: 'https://aura.wit.life/' },
|
||||||
|
]
|
||||||
|
const toElement = (item: PolicyContent, idx: number) => {
|
||||||
|
switch (item.type) {
|
||||||
|
case 'text':
|
||||||
|
return item.content
|
||||||
|
case 'link':
|
||||||
|
return <a key={idx} href={item.href} target="_blank" rel="noreferrer nofollow">{item.content}</a>
|
||||||
|
default:
|
||||||
|
throw new Error(`Unknown type: ${item.type}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const content = text.map<ReactNode>(toElement)
|
||||||
|
|
||||||
|
return <div className="policy"><p>{ content }</p></div>
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Policy
|
||||||
20
src/components/Policy/styles.css
Normal file
20
src/components/Policy/styles.css
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
.policy {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
max-width: 400px;
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 20px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.policy p,
|
||||||
|
.policy a {
|
||||||
|
color: #121620;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.policy a {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
7
src/components/Purposes/index.tsx
Normal file
7
src/components/Purposes/index.tsx
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import './styles.css'
|
||||||
|
|
||||||
|
function Purposes(): JSX.Element {
|
||||||
|
return <small className="purposes">For entertaiment purposes only</small>
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Purposes
|
||||||
6
src/components/Purposes/styles.css
Normal file
6
src/components/Purposes/styles.css
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
.purposes {
|
||||||
|
color: #8e8e93;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 18px;
|
||||||
|
margin-top: 6px;
|
||||||
|
}
|
||||||
33
src/components/TimeControl/index.tsx
Normal file
33
src/components/TimeControl/index.tsx
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
function TimeControl(): JSX.Element {
|
||||||
|
return (
|
||||||
|
<div className='date-control'>
|
||||||
|
<div className='date-control__container'>
|
||||||
|
<div className="date-control__field">
|
||||||
|
<select className="date-control__field-select">
|
||||||
|
{Array.from(Array(12).keys()).map((hour) => (
|
||||||
|
<option key={hour} value={hour + 1}>{hour + 1}</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div className="date-control__field">
|
||||||
|
<select className="date-control__field-select">
|
||||||
|
{Array.from(Array(60).keys()).map((minute) => {
|
||||||
|
const formattedMinute = String(minute).padStart(2, '0');
|
||||||
|
return (
|
||||||
|
<option key={minute} value={minute}>{formattedMinute}</option>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div className="date-control__field">
|
||||||
|
<select className="date-control__field-select">
|
||||||
|
<option value="AM">AM</option>
|
||||||
|
<option value="PM">PM</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TimeControl
|
||||||
17
src/components/Title/index.tsx
Normal file
17
src/components/Title/index.tsx
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { PropsWithChildren, HTMLAttributes } from 'react'
|
||||||
|
import './styles.css'
|
||||||
|
|
||||||
|
type TitleProps = PropsWithChildren<{
|
||||||
|
variant?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'
|
||||||
|
} & HTMLAttributes<HTMLElement>>
|
||||||
|
|
||||||
|
|
||||||
|
function Title({ children, variant, className, ...props }: TitleProps): JSX.Element {
|
||||||
|
const combinedClassNames = ['title', className].filter(Boolean).join(' ')
|
||||||
|
const Tag = variant ?? 'h1'
|
||||||
|
return (
|
||||||
|
<Tag className={combinedClassNames} {...props}>{ children }</Tag>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Title
|
||||||
6
src/components/Title/styles.css
Normal file
6
src/components/Title/styles.css
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
.title {
|
||||||
|
letter-spacing: .2px;
|
||||||
|
line-height: 150%;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
38
src/fonts.css
Normal file
38
src/fonts.css
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
@font-face {
|
||||||
|
font-display: swap;
|
||||||
|
font-family: SF Pro Text;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: url(./assets/media/sf-pro-text-regular.woff) format("woff")
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-display: swap;
|
||||||
|
font-family: SF Pro Text;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 500;
|
||||||
|
src: url(./assets/media/sf-pro-text-medium.woff) format("woff")
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-display: swap;
|
||||||
|
font-family: SF Pro Text;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 600;
|
||||||
|
src: url(./assets/media/sf-pro-text-semibold.woff) format("woff")
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-display: swap;
|
||||||
|
font-family: SF Pro Text;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
src: url(./assets/media/sf-pro-text-bold.woff) format("woff")
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-display: swap;
|
||||||
|
font-family: "sf mono bold, sans-serif";
|
||||||
|
font-style: normal;
|
||||||
|
src: url(./assets/media/sf-mono-bold.otf) format("opentype")
|
||||||
|
}
|
||||||
137
src/index.css
137
src/index.css
@ -1,69 +1,94 @@
|
|||||||
:root {
|
* {
|
||||||
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
box-sizing: border-box;
|
||||||
line-height: 1.5;
|
font-family: SF Pro Text, sans-serif;
|
||||||
font-weight: 400;
|
|
||||||
|
|
||||||
color-scheme: light dark;
|
|
||||||
color: rgba(255, 255, 255, 0.87);
|
|
||||||
background-color: #242424;
|
|
||||||
|
|
||||||
font-synthesis: none;
|
|
||||||
text-rendering: optimizeLegibility;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
-webkit-text-size-adjust: 100%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
h2 {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 20px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: #646cff;
|
|
||||||
text-decoration: inherit;
|
|
||||||
}
|
|
||||||
a:hover {
|
|
||||||
color: #535bf2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
h4 {
|
||||||
margin: 0;
|
font-weight: 400;
|
||||||
display: flex;
|
|
||||||
place-items: center;
|
|
||||||
min-width: 320px;
|
|
||||||
min-height: 100vh;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
button,h4 {
|
||||||
font-size: 3.2em;
|
font-size: 18px;
|
||||||
line-height: 1.1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
border-radius: 8px;
|
line-height: 20px;
|
||||||
border: 1px solid transparent;
|
|
||||||
padding: 0.6em 1.2em;
|
|
||||||
font-size: 1em;
|
|
||||||
font-weight: 500;
|
|
||||||
font-family: inherit;
|
|
||||||
background-color: #1a1a1a;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: border-color 0.25s;
|
|
||||||
}
|
|
||||||
button:hover {
|
|
||||||
border-color: #646cff;
|
|
||||||
}
|
|
||||||
button:focus,
|
|
||||||
button:focus-visible {
|
|
||||||
outline: 4px auto -webkit-focus-ring-color;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-color-scheme: light) {
|
a,abbr,acronym,address,applet,article,aside,audio,b,big,blockquote,body,canvas,caption,center,cite,code,dd,del,details,dfn,div,dl,dt,em,embed,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,html,i,iframe,img,ins,kbd,label,legend,li,mark,menu,nav,object,ol,output,p,pre,q,ruby,s,samp,section,small,span,strike,strong,sub,summary,sup,table,tbody,td,tfoot,th,thead,time,tr,tt,u,ul,var,video {
|
||||||
:root {
|
border: 0;
|
||||||
color: #213547;
|
margin: 0;
|
||||||
background-color: #ffffff;
|
padding: 0;
|
||||||
}
|
vertical-align: initial;
|
||||||
a:hover {
|
}
|
||||||
color: #747bff;
|
|
||||||
}
|
article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section {
|
||||||
button {
|
display: block;
|
||||||
background-color: #f9f9f9;
|
}
|
||||||
}
|
|
||||||
|
body,html {
|
||||||
|
height: 100%;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.height-initial {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol,ul {
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div[class^=divider] {
|
||||||
|
font-family: SF Pro Text Regular,sans-serif
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
scrollbar-color: #cde8f9 #fff;
|
||||||
|
scrollbar-width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
margin: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background-color: #cde8f9;
|
||||||
|
border: 3px solid #fff;
|
||||||
|
border-radius: 10px;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#root {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
a,button,div,input,select,textarea {
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-24 {
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pa {
|
||||||
|
position: absolute;
|
||||||
}
|
}
|
||||||
|
|||||||
15
src/init.tsx
Normal file
15
src/init.tsx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { BrowserRouter } from 'react-router-dom'
|
||||||
|
import App from './components/App'
|
||||||
|
|
||||||
|
const init = async () => {
|
||||||
|
return (
|
||||||
|
<React.StrictMode>
|
||||||
|
<BrowserRouter>
|
||||||
|
<App />
|
||||||
|
</BrowserRouter>
|
||||||
|
</React.StrictMode>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default init
|
||||||
21
src/main.ts
Normal file
21
src/main.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import ReactDOM from 'react-dom/client'
|
||||||
|
import init from './init'
|
||||||
|
import './fonts.css'
|
||||||
|
import './index.css'
|
||||||
|
|
||||||
|
const getRootElement = (id: string): HTMLElement => {
|
||||||
|
const root = document.getElementById(id)
|
||||||
|
|
||||||
|
if (root) return root;
|
||||||
|
|
||||||
|
const element = document.createElement('div')
|
||||||
|
element.id = id
|
||||||
|
document.body.appendChild(element)
|
||||||
|
|
||||||
|
return element
|
||||||
|
}
|
||||||
|
|
||||||
|
const vdom = await init()
|
||||||
|
const rootElement = getRootElement('root')
|
||||||
|
|
||||||
|
ReactDOM.createRoot(rootElement).render(vdom)
|
||||||
10
src/main.tsx
10
src/main.tsx
@ -1,10 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
import ReactDOM from 'react-dom/client'
|
|
||||||
import App from './App.tsx'
|
|
||||||
import './index.css'
|
|
||||||
|
|
||||||
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
|
|
||||||
<React.StrictMode>
|
|
||||||
<App />
|
|
||||||
</React.StrictMode>,
|
|
||||||
)
|
|
||||||
24
src/routes.ts
Normal file
24
src/routes.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
const host = '';
|
||||||
|
const prefix = 'api/v1';
|
||||||
|
|
||||||
|
const routes = {
|
||||||
|
client: {
|
||||||
|
root: () => [host, ''].join('/'),
|
||||||
|
email: () => [host, 'email'].join('/'),
|
||||||
|
birthday: () => [host, 'birthday'].join('/'),
|
||||||
|
birthtime: () => [host, 'birthtime'].join('/'),
|
||||||
|
subscription: () => [host, 'subscription'].join('/'),
|
||||||
|
createProfile: () => [host, 'profile', 'create'].join('/'),
|
||||||
|
},
|
||||||
|
server: {
|
||||||
|
locales: () => [host, prefix, 'locales.json'].join('/'),
|
||||||
|
translations: () => [host, prefix, 't.json'].join('/'),
|
||||||
|
userRegistration: () => [host, prefix, 'user', 'registration.json'].join('/'),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export const entrypoints = [routes.client.root(), routes.client.birthday()]
|
||||||
|
export const isEntrypoint = (path: string) => entrypoints.includes(path)
|
||||||
|
export const isNotEntrypoint = (path: string) => !isEntrypoint(path)
|
||||||
|
|
||||||
|
export default routes
|
||||||
Loading…
Reference in New Issue
Block a user