Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
T
thecybernanny-webapp
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
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
asranov0003
thecybernanny-webapp
Commits
ed8c6b3c
Commit
ed8c6b3c
authored
Jul 24, 2025
by
asranov0003
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: add recover password page
parent
e599a481
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
109 additions
and
2 deletions
+109
-2
RecoverPassword.tsx
src/pages/RecoverPassword/RecoverPassword.tsx
+89
-0
index.ts
src/pages/RecoverPassword/index.ts
+1
-0
Settings.css
src/pages/Settings/Settings.css
+2
-0
Settings.tsx
src/pages/Settings/Settings.tsx
+6
-2
Router.tsx
src/routes/Router.tsx
+11
-0
No files found.
src/pages/RecoverPassword/RecoverPassword.tsx
0 → 100644
View file @
ed8c6b3c
import
React
from
"react"
;
import
{
useTranslation
}
from
"react-i18next"
;
import
{
useNavigate
}
from
"react-router-dom"
;
import
{
useAppDispatch
,
useAppSelector
,
type
RootState
,
}
from
"../../stores/store"
;
import
{
useForm
}
from
"react-hook-form"
;
import
{
authRecover
}
from
"../../stores/slices/authSlice"
;
import
AuthHeader
from
"../Auth/AuthHeader"
;
import
CInput
from
"../../components/CInput"
;
import
CButton
from
"../../components/CButton"
;
interface
IRecoverFormData
{
login
:
string
;
newPassword
:
string
;
repeatPassword
:
string
;
}
const
RecoverPasswor
:
React
.
FC
=
()
=>
{
const
{
t
}
=
useTranslation
();
const
navigate
=
useNavigate
();
const
dispatch
=
useAppDispatch
();
const
{
loadingRecover
,
errorRecover
,
successRecover
}
=
useAppSelector
(
(
state
:
RootState
)
=>
state
.
auth
);
const
{
register
,
handleSubmit
,
formState
:
{
errors
},
watch
,
}
=
useForm
<
IRecoverFormData
>
();
const
newPasswordValue
=
watch
(
"newPassword"
);
const
onSubmit
=
async
(
data
:
IRecoverFormData
)
=>
{
dispatch
(
authRecover
(
data
));
};
return
(
<
div
className=
"wrapper recover"
>
<
AuthHeader
back
onBack=
{
()
=>
navigate
(
"/settings"
)
}
/>
<
h2
>
{
t
(
"auth.passwordRecovery"
)
}
</
h2
>
<
form
className=
"auth__form"
onSubmit=
{
handleSubmit
(
onSubmit
)
}
>
<
CInput
label=
{
`${t("auth.login")}`
}
placeholder=
{
`${t("auth.loginPlaceholder")}`
}
{
...
register
("
login
",
{
required
:
t
("
error
.
requiredField
")
})}
error=
{
errors
.
login
?.
message
as
string
}
/>
<
CInput
label=
{
`${t("auth.newPassword")}`
}
placeholder=
{
`${t("auth.newPasswordPlaceholder")}`
}
type=
"password"
{
...
register
("
newPassword
",
{
required
:
t
("
error
.
requiredField
")
})}
error=
{
errors
.
newPassword
?.
message
as
string
}
/>
<
CInput
label=
{
`${t("auth.repeatPassword")}`
}
placeholder=
{
`${t("auth.repeatPasswordPlaceholder")}`
}
type=
"password"
{
...
register
("
repeatPassword
",
{
required
:
t
("
error
.
requiredField
"),
validate
:
(
value
)
=
>
value === newPasswordValue || t("auth.passwordsDoNotMatch"),
})}
error=
{
errors
.
repeatPassword
?.
message
as
string
}
/
>
{
successRecover
&&
(
<
p
className=
"text-success text-center"
>
{
successRecover
}
</
p
>
)
}
{
errorRecover
&&
(
<
p
className=
"text-danger text-center"
>
{
errorRecover
}
</
p
>
)
}
<
CButton
title=
{
`${t("button.continue")}`
}
isLoading=
{
loadingRecover
}
/>
</
form
>
</
div
>
);
};
export default RecoverPasswor;
src/pages/RecoverPassword/index.ts
0 → 100644
View file @
ed8c6b3c
export
{
default
}
from
"./RecoverPassword"
;
src/pages/Settings/Settings.css
View file @
ed8c6b3c
...
...
@@ -19,6 +19,8 @@
display
:
flex
;
align-items
:
center
;
gap
:
0.5rem
;
text-decoration
:
none
;
color
:
var
(
--text-color
);
cursor
:
pointer
;
}
...
...
src/pages/Settings/Settings.tsx
View file @
ed8c6b3c
...
...
@@ -12,6 +12,7 @@ import { useAppDispatch } from "../../stores/store";
import
{
logout
}
from
"../../stores/slices/authSlice"
;
import
CModal
from
"../../components/CModal"
;
import
CButton
from
"../../components/CButton"
;
import
{
Link
}
from
"react-router-dom"
;
const
Settings
:
React
.
FC
=
()
=>
{
const
[
isOpenLogoutModal
,
setIsOpenLogoutModal
]
=
useState
(
false
);
...
...
@@ -64,10 +65,13 @@ const Settings: React.FC = () => {
{
t
(
"settings.deleteAccount"
)
}
</
div
>
<
div
className=
"settings__content__action"
>
<
Link
to=
{
"/settings/recover-password"
}
className=
"settings__content__action"
>
<
IoKeyOutline
className=
"settings__content__action__icon"
/>
{
" "
}
{
t
(
"settings.recoverPassword"
)
}
</
div
>
</
Link
>
<
div
className=
"settings__content__action"
onClick=
{
toggleLogoutModal
}
>
<
MdOutlineLogout
className=
"settings__content__action__icon"
/>
{
" "
}
...
...
src/routes/Router.tsx
View file @
ed8c6b3c
...
...
@@ -28,6 +28,7 @@ import BlockApps from "../pages/BlockApps";
import
UsageLimits
from
"../pages/UsageLimits"
;
import
Terms
from
"../pages/Auth/Terms"
;
import
Privacy
from
"../pages/Auth/Privacy"
;
import
RecoverPassword
from
"../pages/RecoverPassword"
;
const
Router
:
React
.
FC
=
()
=>
{
const
isAuthenticated
=
!!
localStorage
.
getItem
(
`token-
${
TG_USER_ID
}
`
);
...
...
@@ -129,6 +130,16 @@ const Router: React.FC = () => {
],
},
{
path
:
"/settings"
,
element
:
<
ProtectedRoute
element=
{
<
Outlet
/>
}
redirectTo=
"/"
/>,
children
:
[
{
path
:
"recover-password"
,
element
:
<
RecoverPassword
/>,
},
],
},
{
path
:
"/pincode"
,
element
:
<
Pincode
/>,
},
...
...
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