Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
X
xplot
Overview
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
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
digit_plot
xplot
Commits
5f4fcedc
Commit
5f4fcedc
authored
Aug 27, 2024
by
dliangx
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
login page impl
parent
e25eeeae
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
378 additions
and
0 deletions
+378
-0
src/components/login/Login.tsx
+163
-0
src/components/login/Register.tsx
+187
-0
src/components/login/RequireAuth.tsx
+28
-0
No files found.
src/components/login/Login.tsx
0 → 100644
View file @
5f4fcedc
import
{
useRef
,
useState
}
from
"react"
;
import
{
Back
,
ForwardArrow
}
from
"../common/Icon"
;
const
Login
=
()
=>
{
const
[
loginName
,
setLoginName
]
=
useState
(
""
);
const
[
loginPass
,
setLoginPass
]
=
useState
(
""
);
const
[
error
,
setError
]
=
useState
(
""
);
const
loginNameRef
=
useRef
<
HTMLInputElement
>
(
null
);
const
loginPassRef
=
useRef
<
HTMLInputElement
>
(
null
);
const
regexUsername
=
"^[a-zA-Z][a-zA-Z0-9_]{4,15}$"
;
const
regexPassword
=
/^
(?=
.*
[
a-z
])(?=
.*
[
A-Z
])(?=
.*
\d)(?=
.*
[
!@#$%^&*()_+
])[
A-Za-z
\d
!@#$%^&*()_+
]{6,18}
$/
;
const
usernameRegexNotMatch
=
"username consists of characters and numbers, and is between 5 and 16 in length"
;
const
passwordRegexNotMatch
=
"password starts with a letter, is between 6~18 in length, and can only contain letters, numbers "
;
function
regex_username_test
(
username
:
string
)
{
if
(
username
!=
""
&&
!
username
.
match
(
regexUsername
))
{
setError
(
usernameRegexNotMatch
);
}
else
{
setError
(
""
);
}
}
function
regex_password_test
(
password
:
string
)
{
if
(
password
!=
""
&&
!
password
.
match
(
regexPassword
))
{
setError
(
passwordRegexNotMatch
);
}
else
{
setError
(
""
);
}
}
function
handle_login
(
username
:
string
,
password
:
string
)
{
if
(
username
==
""
)
{
setError
(
"please fill username "
);
loginNameRef
.
current
?.
focus
();
return
;
}
if
(
!
username
.
match
(
regexUsername
))
{
setError
(
usernameRegexNotMatch
);
loginNameRef
.
current
?.
focus
();
return
;
}
if
(
password
==
""
)
{
setError
(
"please fill password"
);
loginPassRef
.
current
?.
focus
();
return
;
}
if
(
!
password
.
match
(
regexPassword
))
{
setError
(
passwordRegexNotMatch
);
loginPassRef
.
current
?.
focus
();
return
;
}
login
();
}
const
login
=
()
=>
{
const
url
=
import
.
meta
.
env
.
VITE_API_URL
+
"/login"
;
const
bodyStr
=
JSON
.
stringify
({
name
:
loginName
,
password
:
loginPass
});
fetch
(
url
,
{
method
:
"POST"
,
body
:
bodyStr
,
headers
:
{
"content-type"
:
"application/json"
,
},
})
.
then
(
async
(
response
)
=>
{
const
text
=
response
.
text
();
if
(
response
.
ok
)
{
return
text
;
}
else
if
(
response
.
status
==
400
)
{
console
.
log
(
response
.
status
);
setError
(
await
text
);
return
;
}
})
.
then
((
data
)
=>
{
if
(
!!
data
)
{
localStorage
.
setItem
(
"username"
,
loginName
);
localStorage
.
setItem
(
"user_token"
,
data
);
var
now
=
new
Date
();
localStorage
.
setItem
(
"expire_time"
,
new
Date
(
now
.
getTime
()
+
99
*
24
*
60
*
60
*
1000
).
toLocaleDateString
()
);
history
.
go
(
-
1
);
}
})
.
catch
((
error
)
=>
{
console
.
error
(
"Error:"
,
error
);
});
};
return
(
<>
<
div
className=
"flex h-10 pt-2 pr-12 items-end w-full "
>
<
Back
className=
" ml-2 "
onClick=
{
()
=>
history
.
go
(
-
1
)
}
/>
</
div
>
<
div
className=
" mt-20 "
>
<
div
className=
"w-4/5 m-auto pb-4"
>
<
div
className=
"text-center w-full mr-2 h-12 "
onClick=
{
()
=>
{
setError
(
""
);
}
}
>
LOGIN
</
div
>
</
div
>
<
div
className=
"flex"
>
<
input
placeholder=
"username"
type=
"text"
ref=
{
loginNameRef
}
value=
{
loginName
}
onChange=
{
(
e
)
=>
{
regex_username_test
(
e
.
target
.
value
);
setLoginName
(
e
.
target
.
value
);
}
}
className=
"w-4/5 m-auto h-12 mb-4 bg-transparent p-2 border-b rounded-none border-gray-600 hover:border-gray-300 focus:outline-none "
autoFocus
></
input
>
</
div
>
<
div
className=
"flex "
>
<
div
className=
" relative w-4/5 m-auto place-items-end "
>
<
input
placeholder=
"password"
type=
"password"
ref=
{
loginPassRef
}
value=
{
loginPass
}
onChange=
{
(
e
)
=>
{
regex_password_test
(
e
.
target
.
value
);
setLoginPass
(
e
.
target
.
value
);
}
}
className=
"w-full m-auto h-12 bg-transparent p-2 border-b rounded-none border-gray-600 hover:border-gray-300 focus:outline-none "
></
input
>
<
ForwardArrow
className=
"absolute bottom-2 right-2 z-10 "
onClick=
{
()
=>
handle_login
(
loginName
,
loginPass
)
}
/>
</
div
>
</
div
>
{
error
!=
""
&&
(
<
div
className=
"mt-10 w-4/5 m-auto text-center text-orange-400"
>
{
error
}
</
div
>
)
}
</
div
>
</>
);
};
export
default
Login
;
src/components/login/Register.tsx
0 → 100644
View file @
5f4fcedc
import
{
useRef
,
useState
}
from
"react"
;
import
{
Back
,
ForwardArrow
}
from
"../common/Icon"
;
const
Register
=
()
=>
{
const
[
registerName
,
setRegisterName
]
=
useState
(
""
);
const
[
registerPass
,
setRegisterPass
]
=
useState
(
""
);
const
[
registerRep
,
setRegisterRep
]
=
useState
(
""
);
const
[
error
,
setError
]
=
useState
(
""
);
const
registerNameRef
=
useRef
<
HTMLInputElement
>
(
null
);
const
registerPassRef
=
useRef
<
HTMLInputElement
>
(
null
);
const
registerRepRef
=
useRef
<
HTMLInputElement
>
(
null
);
const
regexUsername
=
"^[a-zA-Z][a-zA-Z0-9_]{4,15}$"
;
const
regexPassword
=
/^
(?=
.*
[
a-z
])(?=
.*
[
A-Z
])(?=
.*
\d)(?=
.*
[
!@#$%^&*()_+
])[
A-Za-z
\d
!@#$%^&*()_+
]{6,18}
$/
;
const
usernameRegexNotMatch
=
"username consists of characters and numbers, and is between 5 and 16 in length"
;
const
passwordRegexNotMatch
=
"password starts with a letter, is between 6~18 in length, and can only contain letters, numbers "
;
const
passwordTwiceNotMatch
=
"the password entered twice is not the same"
;
function
regex_username_test
(
username
:
string
)
{
if
(
username
!=
""
&&
!
username
.
match
(
regexUsername
))
{
setError
(
usernameRegexNotMatch
);
}
else
{
setError
(
""
);
}
}
function
regex_password_test
(
password
:
string
)
{
if
(
password
!=
""
&&
!
password
.
match
(
regexPassword
))
{
setError
(
passwordRegexNotMatch
);
}
else
{
setError
(
""
);
}
}
function
handle_register
(
username
:
string
,
password
:
string
,
passwordRep
:
string
)
{
if
(
username
==
""
)
{
setError
(
"please fill username "
);
registerNameRef
.
current
?.
focus
();
return
;
}
if
(
!
username
.
match
(
regexUsername
))
{
setError
(
usernameRegexNotMatch
);
registerNameRef
.
current
?.
focus
();
return
;
}
if
(
password
==
""
)
{
setError
(
"please fill password"
);
registerPassRef
.
current
?.
focus
();
return
;
}
if
(
!
password
.
match
(
regexPassword
))
{
setError
(
passwordRegexNotMatch
);
registerPassRef
.
current
?.
focus
();
return
;
}
if
(
passwordRep
==
""
)
{
setError
(
passwordTwiceNotMatch
);
registerRepRef
.
current
?.
focus
();
return
;
}
if
(
!
passwordRep
.
match
(
regexPassword
))
{
setError
(
passwordRegexNotMatch
);
registerRepRef
.
current
?.
focus
();
return
;
}
if
(
password
!==
passwordRep
)
{
setError
(
passwordTwiceNotMatch
);
return
;
}
register
();
}
const
register
=
()
=>
{
const
url
=
import
.
meta
.
env
.
VITE_API_URL
+
"/register"
;
const
bodyStr
=
JSON
.
stringify
({
name
:
registerName
,
password
:
registerPass
,
});
fetch
(
url
,
{
method
:
"POST"
,
body
:
bodyStr
,
headers
:
{
"content-type"
:
"application/json"
,
},
})
.
then
((
response
)
=>
response
.
text
())
.
then
((
data
)
=>
{
console
.
log
(
data
);
if
(
data
==
"success"
)
{
history
.
go
(
-
1
);
}
else
{
setError
(
data
);
}
})
.
catch
((
error
)
=>
{
console
.
error
(
"Error:"
,
error
);
});
};
return
(
<>
<
div
className=
"flex h-10 pt-2 pr-12 items-end w-full "
>
<
Back
className=
" ml-2 "
onClick=
{
()
=>
history
.
go
(
-
1
)
}
/>
</
div
>
<
div
className=
" mt-20 "
>
<
div
className=
"flex w-4/5 m-auto pb-4"
>
<
div
className=
"text-center w-full ml-2 h-8"
onClick=
{
()
=>
{
setError
(
""
);
}
}
>
REGISTER
</
div
>
</
div
>
<
div
className=
"flex"
>
<
input
placeholder=
"username"
type=
"text"
ref=
{
registerNameRef
}
value=
{
registerName
}
onChange=
{
(
e
)
=>
{
regex_username_test
(
e
.
target
.
value
);
setRegisterName
(
e
.
target
.
value
);
}
}
className=
"w-4/5 m-auto h-12 bg-transparent p-2 border-b rounded-none border-gray-600 hover:border-gray-300 focus:outline-none "
autoFocus
></
input
>
</
div
>
<
div
className=
"flex "
>
<
div
className=
" relative w-4/5 m-auto place-items-end "
>
<
input
placeholder=
"password"
type=
"password"
ref=
{
registerPassRef
}
value=
{
registerPass
}
onChange=
{
(
e
)
=>
{
regex_password_test
(
e
.
target
.
value
);
setRegisterPass
(
e
.
target
.
value
);
}
}
className=
"w-full m-auto h-12 bg-transparent p-2 border-b rounded-none border-gray-600 hover:border-gray-300 focus:outline-none "
></
input
>
</
div
>
</
div
>
<
div
className=
"flex "
>
<
div
className=
" relative w-4/5 m-auto place-items-end "
>
<
input
placeholder=
"password"
type=
"password"
ref=
{
registerRepRef
}
value=
{
registerRep
}
onChange=
{
(
e
)
=>
{
regex_password_test
(
e
.
target
.
value
);
setRegisterRep
(
e
.
target
.
value
);
}
}
className=
"w-full m-auto h-12 bg-transparent p-2 border-b rounded-none border-gray-600 hover:border-gray-300 focus:outline-none "
></
input
>
<
ForwardArrow
className=
"absolute bottom-2 right-2 z-10 "
onClick=
{
()
=>
handle_register
(
registerName
,
registerPass
,
registerRep
)
}
/>
</
div
>
</
div
>
{
error
!=
""
&&
(
<
div
className=
"mt-10 w-4/5 m-auto text-center text-orange-400"
>
{
error
}
</
div
>
)
}
</
div
>
</>
);
};
export
default
Register
;
src/components/login/RequireAuth.tsx
0 → 100644
View file @
5f4fcedc
import
{
Navigate
,
useLocation
}
from
"react-router-dom"
;
const
RequireAuth
=
({
children
}:
{
children
:
JSX
.
Element
})
=>
{
const
isUserLoggedIn
=
()
=>
{
return
!!
localStorage
.
getItem
(
"user_token"
);
};
let
location
=
useLocation
();
if
(
!
isUserLoggedIn
())
{
return
<
Navigate
to=
"/login"
state=
{
{
from
:
location
}
}
replace
/>;
}
else
{
const
expire_time
=
localStorage
.
getItem
(
"expire_time"
);
if
(
expire_time
!=
null
)
{
if
(
new
Date
(
expire_time
)
<
new
Date
())
{
localStorage
.
removeItem
(
"user_token"
);
localStorage
.
removeItem
(
"expire_time"
);
return
<
Navigate
to=
"/login"
state=
{
{
from
:
location
}
}
replace
/>;
}
}
else
{
localStorage
.
removeItem
(
"user_token"
);
localStorage
.
removeItem
(
"expire_time"
);
return
<
Navigate
to=
"/login"
state=
{
{
from
:
location
}
}
replace
/>;
}
}
return
children
;
};
export
default
RequireAuth
;
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