Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
E
exam_template
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
4
Issues
4
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Нұрасыл Қайратұлы
exam_template
Commits
6d00d179
Commit
6d00d179
authored
Apr 30, 2025
by
Нұрасыл Қайратұлы
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
#4
create auth form
parent
2bd6873f
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
411 additions
and
20 deletions
+411
-20
package.json
client/package.json
+2
-1
pnpm-lock.yaml
client/pnpm-lock.yaml
+198
-5
App.tsx
client/src/App.tsx
+21
-2
WrapperLayout.tsx
client/src/components/layout/WrapperLayout.tsx
+60
-0
AuthForm.tsx
client/src/components/ui/form/AuthForm.tsx
+51
-0
ProtectedRoute.tsx
client/src/components/ui/routes/ProtectedRoute.tsx
+16
-0
main.tsx
client/src/main.tsx
+8
-7
Auth.tsx
client/src/pages/auth/Auth.tsx
+12
-0
index.tsx
client/src/store/index.tsx
+6
-5
userSlice.ts
client/src/store/slices/userSlice.ts
+22
-0
auth.scss
client/src/styles/auth.scss
+7
-0
main.scss
client/src/styles/main.scss
+4
-0
user.ts
client/src/types/user.ts
+4
-0
No files found.
client/package.json
View file @
6d00d179
...
...
@@ -22,7 +22,8 @@
"react-dom"
:
"^18.2.0"
,
"react-redux"
:
"^9.1.0"
,
"react-router-dom"
:
"^6.22.3"
,
"redux-persist"
:
"^6.0.0"
"redux-persist"
:
"^6.0.0"
,
"sass"
:
"^1.87.0"
},
"devDependencies"
:
{
"@types/react"
:
"^18.2.43"
,
...
...
client/pnpm-lock.yaml
View file @
6d00d179
...
...
@@ -44,6 +44,9 @@ importers:
redux-persist
:
specifier
:
^6.0.0
version
:
6.0.0(react@18.3.1)(redux@5.0.1)
sass
:
specifier
:
^1.87.0
version
:
1.87.0
devDependencies
:
'
@types/react'
:
specifier
:
^18.2.43
...
...
@@ -62,7 +65,7 @@ importers:
version
:
6.21.0(eslint@8.57.1)(typescript@5.2.2)
'
@vitejs/plugin-react'
:
specifier
:
^4.2.1
version
:
4.4.1(vite@5.4.19)
version
:
4.4.1(vite@5.4.19
(sass@1.87.0)
)
eslint
:
specifier
:
^8.55.0
version
:
8.57.1
...
...
@@ -89,7 +92,7 @@ importers:
version
:
5.2.2
vite
:
specifier
:
^5.0.8
version
:
5.4.19
version
:
5.4.19
(sass@1.87.0)
packages
:
...
...
@@ -476,6 +479,88 @@ packages:
resolution
:
{
integrity
:
sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==
}
engines
:
{
node
:
'
>=
8'
}
'
@parcel/watcher-android-arm64@2.5.1'
:
resolution
:
{
integrity
:
sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==
}
engines
:
{
node
:
'
>=
10.0.0'
}
cpu
:
[
arm64
]
os
:
[
android
]
'
@parcel/watcher-darwin-arm64@2.5.1'
:
resolution
:
{
integrity
:
sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==
}
engines
:
{
node
:
'
>=
10.0.0'
}
cpu
:
[
arm64
]
os
:
[
darwin
]
'
@parcel/watcher-darwin-x64@2.5.1'
:
resolution
:
{
integrity
:
sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==
}
engines
:
{
node
:
'
>=
10.0.0'
}
cpu
:
[
x64
]
os
:
[
darwin
]
'
@parcel/watcher-freebsd-x64@2.5.1'
:
resolution
:
{
integrity
:
sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==
}
engines
:
{
node
:
'
>=
10.0.0'
}
cpu
:
[
x64
]
os
:
[
freebsd
]
'
@parcel/watcher-linux-arm-glibc@2.5.1'
:
resolution
:
{
integrity
:
sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==
}
engines
:
{
node
:
'
>=
10.0.0'
}
cpu
:
[
arm
]
os
:
[
linux
]
'
@parcel/watcher-linux-arm-musl@2.5.1'
:
resolution
:
{
integrity
:
sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==
}
engines
:
{
node
:
'
>=
10.0.0'
}
cpu
:
[
arm
]
os
:
[
linux
]
'
@parcel/watcher-linux-arm64-glibc@2.5.1'
:
resolution
:
{
integrity
:
sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==
}
engines
:
{
node
:
'
>=
10.0.0'
}
cpu
:
[
arm64
]
os
:
[
linux
]
'
@parcel/watcher-linux-arm64-musl@2.5.1'
:
resolution
:
{
integrity
:
sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==
}
engines
:
{
node
:
'
>=
10.0.0'
}
cpu
:
[
arm64
]
os
:
[
linux
]
'
@parcel/watcher-linux-x64-glibc@2.5.1'
:
resolution
:
{
integrity
:
sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==
}
engines
:
{
node
:
'
>=
10.0.0'
}
cpu
:
[
x64
]
os
:
[
linux
]
'
@parcel/watcher-linux-x64-musl@2.5.1'
:
resolution
:
{
integrity
:
sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==
}
engines
:
{
node
:
'
>=
10.0.0'
}
cpu
:
[
x64
]
os
:
[
linux
]
'
@parcel/watcher-win32-arm64@2.5.1'
:
resolution
:
{
integrity
:
sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==
}
engines
:
{
node
:
'
>=
10.0.0'
}
cpu
:
[
arm64
]
os
:
[
win32
]
'
@parcel/watcher-win32-ia32@2.5.1'
:
resolution
:
{
integrity
:
sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==
}
engines
:
{
node
:
'
>=
10.0.0'
}
cpu
:
[
ia32
]
os
:
[
win32
]
'
@parcel/watcher-win32-x64@2.5.1'
:
resolution
:
{
integrity
:
sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==
}
engines
:
{
node
:
'
>=
10.0.0'
}
cpu
:
[
x64
]
os
:
[
win32
]
'
@parcel/watcher@2.5.1'
:
resolution
:
{
integrity
:
sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==
}
engines
:
{
node
:
'
>=
10.0.0'
}
'
@pkgr/core@0.2.4'
:
resolution
:
{
integrity
:
sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw==
}
engines
:
{
node
:
^12.20.0 || ^14.18.0 || >=16.0.0
}
...
...
@@ -886,6 +971,10 @@ packages:
resolution
:
{
integrity
:
sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
}
engines
:
{
node
:
'
>=10'
}
chokidar@4.0.3
:
resolution
:
{
integrity
:
sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==
}
engines
:
{
node
:
'
>=
14.16.0'
}
classnames@2.5.1
:
resolution
:
{
integrity
:
sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==
}
...
...
@@ -965,6 +1054,11 @@ packages:
resolution
:
{
integrity
:
sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
}
engines
:
{
node
:
'
>=0.4.0'
}
detect-libc@1.0.3
:
resolution
:
{
integrity
:
sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==
}
engines
:
{
node
:
'
>=0.10'
}
hasBin
:
true
dir-glob@3.0.1
:
resolution
:
{
integrity
:
sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==
}
engines
:
{
node
:
'
>=8'
}
...
...
@@ -1267,6 +1361,9 @@ packages:
immer@10.1.1
:
resolution
:
{
integrity
:
sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==
}
immutable@5.1.1
:
resolution
:
{
integrity
:
sha512-3jatXi9ObIsPGr3N5hGw/vWWcTkq6hUYhpQz4k0wLC+owqWi/LiugIw9x0EdNZ2yGedKN/HzePiBvaJRXa0Ujg==
}
import-fresh@3.3.1
:
resolution
:
{
integrity
:
sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==
}
engines
:
{
node
:
'
>=6'
}
...
...
@@ -1497,6 +1594,9 @@ packages:
natural-compare@1.4.0
:
resolution
:
{
integrity
:
sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
}
node-addon-api@7.1.1
:
resolution
:
{
integrity
:
sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==
}
node-releases@2.0.19
:
resolution
:
{
integrity
:
sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==
}
...
...
@@ -1887,6 +1987,10 @@ packages:
resolution
:
{
integrity
:
sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==
}
engines
:
{
node
:
'
>=0.10.0'
}
readdirp@4.1.2
:
resolution
:
{
integrity
:
sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==
}
engines
:
{
node
:
'
>=
14.18.0'
}
redux-persist@6.0.0
:
resolution
:
{
integrity
:
sha512-71LLMbUq2r02ng2We9S215LtPu3fY0KgaGE0k8WRgl6RkqxtGfl7HUozz1Dftwsb0D/5mZ8dwAaPbtnzfvbEwQ==
}
peerDependencies
:
...
...
@@ -1963,6 +2067,11 @@ packages:
resolution
:
{
integrity
:
sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==
}
engines
:
{
node
:
'
>=
0.4'
}
sass@1.87.0
:
resolution
:
{
integrity
:
sha512-d0NoFH4v6SjEK7BoX810Jsrhj7IQSYHAHLi/iSpgqKc7LaIDshFRlSg5LOymf9FqQhxEHs2W5ZQXlvy0KD45Uw==
}
engines
:
{
node
:
'
>=14.0.0'
}
hasBin
:
true
scheduler@0.23.2
:
resolution
:
{
integrity
:
sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==
}
...
...
@@ -2606,6 +2715,67 @@ snapshots:
'
@nodelib/fs.scandir'
:
2.1.5
fastq
:
1.19.1
'
@parcel/watcher-android-arm64@2.5.1'
:
optional
:
true
'
@parcel/watcher-darwin-arm64@2.5.1'
:
optional
:
true
'
@parcel/watcher-darwin-x64@2.5.1'
:
optional
:
true
'
@parcel/watcher-freebsd-x64@2.5.1'
:
optional
:
true
'
@parcel/watcher-linux-arm-glibc@2.5.1'
:
optional
:
true
'
@parcel/watcher-linux-arm-musl@2.5.1'
:
optional
:
true
'
@parcel/watcher-linux-arm64-glibc@2.5.1'
:
optional
:
true
'
@parcel/watcher-linux-arm64-musl@2.5.1'
:
optional
:
true
'
@parcel/watcher-linux-x64-glibc@2.5.1'
:
optional
:
true
'
@parcel/watcher-linux-x64-musl@2.5.1'
:
optional
:
true
'
@parcel/watcher-win32-arm64@2.5.1'
:
optional
:
true
'
@parcel/watcher-win32-ia32@2.5.1'
:
optional
:
true
'
@parcel/watcher-win32-x64@2.5.1'
:
optional
:
true
'
@parcel/watcher@2.5.1'
:
dependencies
:
detect-libc
:
1.0.3
is-glob
:
4.0.3
micromatch
:
4.0.8
node-addon-api
:
7.1.1
optionalDependencies
:
'
@parcel/watcher-android-arm64'
:
2.5.1
'
@parcel/watcher-darwin-arm64'
:
2.5.1
'
@parcel/watcher-darwin-x64'
:
2.5.1
'
@parcel/watcher-freebsd-x64'
:
2.5.1
'
@parcel/watcher-linux-arm-glibc'
:
2.5.1
'
@parcel/watcher-linux-arm-musl'
:
2.5.1
'
@parcel/watcher-linux-arm64-glibc'
:
2.5.1
'
@parcel/watcher-linux-arm64-musl'
:
2.5.1
'
@parcel/watcher-linux-x64-glibc'
:
2.5.1
'
@parcel/watcher-linux-x64-musl'
:
2.5.1
'
@parcel/watcher-win32-arm64'
:
2.5.1
'
@parcel/watcher-win32-ia32'
:
2.5.1
'
@parcel/watcher-win32-x64'
:
2.5.1
optional
:
true
'
@pkgr/core@0.2.4'
:
{}
'
@rc-component/async-validator@5.0.4'
:
...
...
@@ -2892,14 +3062,14 @@ snapshots:
'
@ungap/structured-clone@1.3.0'
:
{}
'
@vitejs/plugin-react@4.4.1(vite@5.4.19)'
:
'
@vitejs/plugin-react@4.4.1(vite@5.4.19
(sass@1.87.0)
)'
:
dependencies
:
'
@babel/core'
:
7.26.10
'
@babel/plugin-transform-react-jsx-self'
:
7.25.9(@babel/core@7.26.10)
'
@babel/plugin-transform-react-jsx-source'
:
7.25.9(@babel/core@7.26.10)
'
@types/babel__core'
:
7.20.5
react-refresh
:
0.17.0
vite
:
5.4.19
vite
:
5.4.19
(sass@1.87.0)
transitivePeerDependencies
:
-
supports-color
...
...
@@ -3109,6 +3279,10 @@ snapshots:
ansi-styles
:
4.3.0
supports-color
:
7.2.0
chokidar@4.0.3
:
dependencies
:
readdirp
:
4.1.2
classnames@2.5.1
:
{}
color-convert@2.0.1
:
...
...
@@ -3189,6 +3363,9 @@ snapshots:
delayed-stream@1.0.0
:
{}
detect-libc@1.0.3
:
optional
:
true
dir-glob@3.0.1
:
dependencies
:
path-type
:
4.0.0
...
...
@@ -3623,6 +3800,8 @@ snapshots:
immer@10.1.1
:
{}
immutable@5.1.1
:
{}
import-fresh@3.3.1
:
dependencies
:
parent-module
:
1.0.1
...
...
@@ -3848,6 +4027,9 @@ snapshots:
natural-compare@1.4.0
:
{}
node-addon-api@7.1.1
:
optional
:
true
node-releases@2.0.19
:
{}
object-assign@4.1.1
:
{}
...
...
@@ -4322,6 +4504,8 @@ snapshots:
dependencies
:
loose-envify
:
1.4.0
readdirp@4.1.2
:
{}
redux-persist@6.0.0(react@18.3.1)(redux@5.0.1)
:
dependencies
:
redux
:
5.0.1
...
...
@@ -4429,6 +4613,14 @@ snapshots:
es-errors
:
1.3.0
is-regex
:
1.2.1
sass@1.87.0
:
dependencies
:
chokidar
:
4.0.3
immutable
:
5.1.1
source-map-js
:
1.2.1
optionalDependencies
:
'
@parcel/watcher'
:
2.5.1
scheduler@0.23.2
:
dependencies
:
loose-envify
:
1.4.0
...
...
@@ -4648,13 +4840,14 @@ snapshots:
dependencies
:
react
:
18.3.1
vite@5.4.19
:
vite@5.4.19
(sass@1.87.0)
:
dependencies
:
esbuild
:
0.21.5
postcss
:
8.5.3
rollup
:
4.40.1
optionalDependencies
:
fsevents
:
2.3.3
sass
:
1.87.0
which-boxed-primitive@1.1.1
:
dependencies
:
...
...
client/src/App.tsx
View file @
6d00d179
import
{
Routes
}
from
'react-router-dom'
;
import
{
shallowEqual
}
from
'react-redux'
;
import
{
Route
,
Routes
}
from
'react-router-dom'
;
import
WrapperLayout
from
'./components/layout/WrapperLayout'
;
import
{
ProtectedRoute
}
from
'./components/ui/routes/ProtectedRoute'
;
import
Auth
from
'./pages/auth/Auth'
;
import
{
useAppSelector
}
from
'./store/hooks'
;
function
App
()
{
return
<
Routes
></
Routes
>;
const
{
user
}
=
useAppSelector
((
state
)
=>
state
.
user
,
shallowEqual
);
return
(
<
Routes
>
<
Route
path=
"/"
element=
{
<
ProtectedRoute
user=
{
user
}
>
<
WrapperLayout
/>
</
ProtectedRoute
>
}
></
Route
>
<
Route
path=
"/auth"
element=
{
<
Auth
/>
}
/>
</
Routes
>
);
}
export
default
App
;
client/src/components/layout/WrapperLayout.tsx
0 → 100644
View file @
6d00d179
import
{
MenuFoldOutlined
,
MenuUnfoldOutlined
,
UserOutlined
}
from
'@ant-design/icons'
;
import
{
Button
,
Layout
,
Menu
,
theme
}
from
'antd'
;
import
{
MenuItemType
}
from
'antd/es/menu/interface'
;
import
{
useState
}
from
'react'
;
import
{
Outlet
}
from
'react-router-dom'
;
const
{
Header
,
Sider
,
Content
}
=
Layout
;
const
items
:
MenuItemType
[]
=
[
{
key
:
'1'
,
icon
:
<
UserOutlined
/>,
label
:
'nav 1'
,
},
];
const
WrapperLayout
=
()
=>
{
const
[
collapsed
,
setCollapsed
]
=
useState
(
false
);
const
{
token
:
{
colorBgContainer
,
borderRadiusLG
},
}
=
theme
.
useToken
();
return
(
<
Layout
style=
{
{
height
:
'100vh'
}
}
>
<
Sider
trigger=
{
null
}
collapsible
collapsed=
{
collapsed
}
>
<
div
className=
"demo-logo-vertical"
/>
<
Menu
theme=
"dark"
mode=
"inline"
defaultSelectedKeys=
{
[
'1'
]
}
items=
{
items
}
/>
</
Sider
>
<
Layout
>
<
Header
style=
{
{
padding
:
0
,
background
:
colorBgContainer
}
}
>
<
Button
type=
"text"
icon=
{
collapsed
?
<
MenuUnfoldOutlined
/>
:
<
MenuFoldOutlined
/>
}
onClick=
{
()
=>
setCollapsed
(
!
collapsed
)
}
style=
{
{
fontSize
:
'16px'
,
width
:
64
,
height
:
64
,
}
}
/>
</
Header
>
<
Content
style=
{
{
margin
:
'24px 16px'
,
padding
:
24
,
minHeight
:
280
,
background
:
colorBgContainer
,
borderRadius
:
borderRadiusLG
,
}
}
>
<
Outlet
/>
</
Content
>
</
Layout
>
</
Layout
>
);
};
export
default
WrapperLayout
;
client/src/components/ui/form/AuthForm.tsx
0 → 100644
View file @
6d00d179
import
{
LockOutlined
,
UserOutlined
}
from
'@ant-design/icons'
;
import
{
Button
,
Checkbox
,
Flex
,
Form
,
Input
}
from
'antd'
;
export
type
AuthField
=
{
username
:
string
;
password
:
string
;
isLogin
:
boolean
;
};
const
AuthForm
=
()
=>
{
const
onFinish
=
(
values
:
AuthField
)
=>
{
console
.
log
(
'Received values of form: '
,
values
);
};
return
(
<
Form
name=
"login"
initialValues=
{
{
remember
:
true
}
}
style=
{
{
maxWidth
:
360
}
}
onFinish=
{
onFinish
}
>
<
Form
.
Item
<
AuthField
>
name="username"
rules=
{
[{
required
:
true
,
message
:
'Please input your Username!'
}]
}
>
<
Input
prefix=
{
<
UserOutlined
/>
}
placeholder=
"Username"
/>
</
Form
.
Item
>
<
Form
.
Item
<
AuthField
>
name="password"
rules=
{
[{
required
:
true
,
message
:
'Please input your Password!'
}]
}
>
<
Input
prefix=
{
<
LockOutlined
/>
}
type=
"password"
placeholder=
"Password"
/>
</
Form
.
Item
>
<
Form
.
Item
>
<
Flex
justify=
"space-between"
align=
"center"
>
<
Form
.
Item
<
AuthField
>
name="isLogin" valuePropName="checked" noStyle
>
<
Checkbox
>
Check this if login
</
Checkbox
>
</
Form
.
Item
>
</
Flex
>
</
Form
.
Item
>
<
Form
.
Item
>
<
Button
block
type=
"primary"
htmlType=
"submit"
>
Submit
</
Button
>
</
Form
.
Item
>
</
Form
>
);
};
export
default
AuthForm
;
client/src/components/ui/routes/ProtectedRoute.tsx
0 → 100644
View file @
6d00d179
import
React
from
'react'
;
import
{
Navigate
}
from
'react-router-dom'
;
import
{
IUser
}
from
'../../../types/user'
;
type
ProtectedRouteProps
=
{
user
:
IUser
|
null
;
children
:
React
.
ReactNode
;
};
export
const
ProtectedRoute
=
({
user
,
children
}:
ProtectedRouteProps
)
=>
{
if
(
!
user
)
{
return
<
Navigate
to=
"/auth"
replace
/>;
}
return
children
;
};
client/src/main.tsx
View file @
6d00d179
import
React
from
'react'
import
ReactDOM
from
'react-dom/client'
import
{
Provider
}
from
'react-redux'
import
{
BrowserRouter
}
from
'react-router-dom'
import
{
PersistGate
}
from
'redux-persist/integration/react'
import
App
from
'./App.tsx'
import
store
,
{
persistor
}
from
'./store/index.tsx'
import
React
from
'react'
;
import
ReactDOM
from
'react-dom/client'
;
import
{
Provider
}
from
'react-redux'
;
import
{
BrowserRouter
}
from
'react-router-dom'
;
import
{
PersistGate
}
from
'redux-persist/integration/react'
;
import
App
from
'./App.tsx'
;
import
store
,
{
persistor
}
from
'./store/index.tsx'
;
import
'./styles/main.scss'
;
ReactDOM
.
createRoot
(
document
.
getElementById
(
'root'
)
!
).
render
(
<
React
.
StrictMode
>
...
...
client/src/pages/auth/Auth.tsx
0 → 100644
View file @
6d00d179
import
AuthForm
from
'../../components/ui/form/AuthForm'
;
import
'../../styles/auth.scss'
;
const
Auth
=
()
=>
{
return
(
<
div
className=
"Auth"
>
<
AuthForm
/>
</
div
>
);
};
export
default
Auth
;
client/src/store/index.tsx
View file @
6d00d179
import
{
configureStore
}
from
'@reduxjs/toolkit'
import
{
configureStore
}
from
'@reduxjs/toolkit'
;
import
{
FLUSH
,
PAUSE
,
...
...
@@ -8,8 +8,9 @@ import {
PURGE
,
REGISTER
,
REHYDRATE
,
}
from
'redux-persist'
import
storage
from
'redux-persist/lib/storage'
}
from
'redux-persist'
;
import
storage
from
'redux-persist/lib/storage'
;
import
userReducer
from
'./slices/userSlice'
;
const
persistConfig
=
{
key
:
'root'
,
...
...
@@ -18,11 +19,11 @@ const persistConfig = {
whitelist
:
[
'user'
],
};
const
persist
Slice
=
persistReducer
(
persistConfig
);
const
persist
User
=
persistReducer
(
persistConfig
,
userReducer
);
const
store
=
configureStore
({
reducer
:
{
root
:
persistSlice
user
:
persistUser
,
},
middleware
:
(
getDefaultMiddleware
)
=>
getDefaultMiddleware
({
...
...
client/src/store/slices/userSlice.ts
0 → 100644
View file @
6d00d179
import
{
createSlice
}
from
'@reduxjs/toolkit'
;
import
{
IUser
}
from
'../../types/user'
;
interface
State
{
user
:
IUser
|
null
;
error
:
Error
|
null
;
loading
:
boolean
;
}
const
initialState
:
State
=
{
user
:
null
,
error
:
null
,
loading
:
false
,
};
const
userSlice
=
createSlice
({
name
:
'user'
,
initialState
,
reducers
:
{},
});
export
default
userSlice
.
reducer
;
client/src/styles/auth.scss
0 → 100644
View file @
6d00d179
.Auth
{
height
:
100vh
;
width
:
100%
;
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
}
client/src/styles/main.scss
0 → 100644
View file @
6d00d179
*
{
margin
:
0
;
box-sizing
:
border-box
;
}
client/src/types/user.ts
0 → 100644
View file @
6d00d179
export
interface
IUser
{
id
:
number
;
username
:
string
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment