feat: button to make password visible
This commit is contained in:
72
src/Icons.tsx
Normal file
72
src/Icons.tsx
Normal file
@@ -0,0 +1,72 @@
|
||||
export const Eye = () => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="1em"
|
||||
height="1em"
|
||||
viewBox="0 0 36 36"
|
||||
>
|
||||
<path
|
||||
fill="#E1E8ED"
|
||||
d="M35.059 18c0 3.304-7.642 11-17.067 11S.925 22.249.925 18c0-3.314 34.134-3.314 34.134 0"
|
||||
/>
|
||||
<path
|
||||
fill="#292F33"
|
||||
d="M35.059 18H.925c0-3.313 7.642-11 17.067-11s17.067 7.686 17.067 11"
|
||||
/>
|
||||
<path
|
||||
fill="#F5F8FA"
|
||||
d="M33.817 18c0 2.904-7.087 9.667-15.826 9.667S2.166 21.732 2.166 18c0-2.912 7.085-9.666 15.825-9.666C26.73 8.333 33.817 15.088 33.817 18"
|
||||
/>
|
||||
<circle
|
||||
cx="18"
|
||||
cy="18"
|
||||
r="8.458"
|
||||
fill="#8B5E3C"
|
||||
style={{ fill: "#919191", fillOpacity: 1 }}
|
||||
/>
|
||||
<circle cx="18" cy="18" r="4.708" fill="#292F33" />
|
||||
<circle cx="14.983" cy="15" r="2" fill="#F5F8FA" />
|
||||
</svg>
|
||||
);
|
||||
|
||||
export const EyeSlash = () => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="1em"
|
||||
height="1em"
|
||||
viewBox="0 0 36 36"
|
||||
>
|
||||
<path
|
||||
fill="#e1e8ed"
|
||||
d="M35.059 18c0 3.304-7.642 11-17.067 11S.925 22.249.925 18c0-3.314 34.134-3.314 34.134 0"
|
||||
/>
|
||||
<path
|
||||
fill="#292f33"
|
||||
d="M35.059 18H.925c0-3.313 7.642-11 17.067-11s17.067 7.686 17.067 11"
|
||||
/>
|
||||
<path
|
||||
fill="#f5f8fa"
|
||||
d="M33.817 18c0 2.904-7.087 9.667-15.826 9.667S2.166 21.732 2.166 18c0-2.912 7.085-9.666 15.825-9.666C26.73 8.333 33.817 15.088 33.817 18"
|
||||
/>
|
||||
<circle
|
||||
cx="18"
|
||||
cy="18"
|
||||
r="8.458"
|
||||
fill="#8B5E3C"
|
||||
style={{ fill: "#919191", fillOpacity: 1 }}
|
||||
/>
|
||||
<circle cx="18" cy="18" r="4.708" fill="#292f33" />
|
||||
<circle cx="14.983" cy="15" r="2" fill="#f5f8fa" />
|
||||
<path
|
||||
d="m-2.97 30.25 41.94-24.5"
|
||||
style={{
|
||||
fill: "#404040",
|
||||
fillOpacity: 1,
|
||||
stroke: "#404040",
|
||||
strokeWidth: 3,
|
||||
strokeDasharray: "none",
|
||||
strokeOpacity: 1,
|
||||
}}
|
||||
/>
|
||||
</svg>
|
||||
);
|
@@ -2,6 +2,7 @@ import { useEffect, useState } from "react";
|
||||
import { currentUser, login, User } from "./api";
|
||||
import Header from "./Header";
|
||||
import { useLocation, useNavigate } from "react-router";
|
||||
import { Eye, EyeSlash } from "./Icons";
|
||||
|
||||
export interface LoginProps {
|
||||
onLogin: (user: User) => void;
|
||||
@@ -12,6 +13,7 @@ export const Login = ({ onLogin }: LoginProps) => {
|
||||
const [password, setPassword] = useState("");
|
||||
const [error, setError] = useState("");
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [visible, setVisible] = useState(false);
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
|
||||
@@ -52,34 +54,65 @@ export const Login = ({ onLogin }: LoginProps) => {
|
||||
<>
|
||||
<Header />
|
||||
<form onSubmit={handleSubmit}>
|
||||
<div>
|
||||
<input
|
||||
type="text"
|
||||
id="username"
|
||||
name="username"
|
||||
placeholder="username"
|
||||
required
|
||||
value={username}
|
||||
onChange={(evt) => {
|
||||
setError("");
|
||||
setUsername(evt.target.value);
|
||||
<div
|
||||
style={{
|
||||
position: "relative",
|
||||
display: "flex",
|
||||
alignItems: "end",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
width: "100%",
|
||||
marginRight: "8px",
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
flexDirection: "column",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
type="password"
|
||||
id="password"
|
||||
name="password"
|
||||
placeholder="password"
|
||||
minLength={8}
|
||||
value={password}
|
||||
required
|
||||
onChange={(evt) => {
|
||||
setError("");
|
||||
setPassword(evt.target.value);
|
||||
>
|
||||
<div>
|
||||
<input
|
||||
type="text"
|
||||
id="username"
|
||||
name="username"
|
||||
placeholder="username"
|
||||
required
|
||||
value={username}
|
||||
onChange={(evt) => {
|
||||
setError("");
|
||||
setUsername(evt.target.value);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
type={visible ? "text" : "password"}
|
||||
id="password"
|
||||
name="password"
|
||||
placeholder="password"
|
||||
minLength={8}
|
||||
value={password}
|
||||
required
|
||||
onChange={(evt) => {
|
||||
setError("");
|
||||
setPassword(evt.target.value);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
right: "-1em",
|
||||
margin: "auto 4px",
|
||||
background: "unset",
|
||||
fontSize: "x-large",
|
||||
cursor: "pointer",
|
||||
}}
|
||||
/>
|
||||
onClick={() => setVisible(!visible)}
|
||||
>
|
||||
{visible ? <Eye /> : <EyeSlash />}
|
||||
</div>
|
||||
</div>
|
||||
<div>{error && <span style={{ color: "red" }}>{error}</span>}</div>
|
||||
<button type="submit" value="login" style={{ fontSize: "small" }}>
|
||||
|
@@ -2,6 +2,9 @@ import { jwtDecode, JwtPayload } from "jwt-decode";
|
||||
import { useEffect, useState } from "react";
|
||||
import { baseUrl } from "./api";
|
||||
import { useNavigate } from "react-router";
|
||||
import eye from "./eye.svg";
|
||||
import { Eye, EyeSlash } from "./Icons";
|
||||
import { relative } from "path";
|
||||
|
||||
interface SetPassToken extends JwtPayload {
|
||||
name: string;
|
||||
@@ -15,6 +18,7 @@ export const SetPassword = () => {
|
||||
const [token, setToken] = useState("");
|
||||
const [error, setError] = useState("");
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [visible, setVisible] = useState(false);
|
||||
const navigate = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
@@ -85,35 +89,66 @@ export const SetPassword = () => {
|
||||
</span>
|
||||
)}
|
||||
<form onSubmit={handleSubmit}>
|
||||
<div>
|
||||
<input
|
||||
type="password"
|
||||
id="password"
|
||||
name="password"
|
||||
placeholder="password"
|
||||
minLength={8}
|
||||
value={password}
|
||||
required
|
||||
onChange={(evt) => {
|
||||
setError("");
|
||||
setPassword(evt.target.value);
|
||||
<div
|
||||
style={{
|
||||
position: "relative",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
width: "100%",
|
||||
marginRight: "8px",
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
flexDirection: "column",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
type="password"
|
||||
id="password-repeat"
|
||||
name="password-repeat"
|
||||
placeholder="repeat password"
|
||||
minLength={8}
|
||||
value={passwordr}
|
||||
required
|
||||
onChange={(evt) => {
|
||||
setError("");
|
||||
setPasswordr(evt.target.value);
|
||||
>
|
||||
<div>
|
||||
<input
|
||||
type={visible ? "text" : "password"}
|
||||
id="password"
|
||||
name="password"
|
||||
placeholder="password"
|
||||
minLength={8}
|
||||
value={password}
|
||||
required
|
||||
onChange={(evt) => {
|
||||
setError("");
|
||||
setPassword(evt.target.value);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
type={visible ? "text" : "password"}
|
||||
id="password-repeat"
|
||||
name="password-repeat"
|
||||
placeholder="repeat password"
|
||||
minLength={8}
|
||||
value={passwordr}
|
||||
required
|
||||
onChange={(evt) => {
|
||||
setError("");
|
||||
setPasswordr(evt.target.value);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
right: 0,
|
||||
margin: "auto 4px",
|
||||
background: "unset",
|
||||
fontSize: "xx-large",
|
||||
cursor: "pointer",
|
||||
}}
|
||||
/>
|
||||
onClick={() => setVisible(!visible)}
|
||||
>
|
||||
{visible ? <Eye /> : <EyeSlash />}
|
||||
</div>
|
||||
</div>
|
||||
<div>{error && <span style={{ color: "red" }}>{error}</span>}</div>
|
||||
<button type="submit" value="login" style={{ fontSize: "small" }}>
|
||||
|
Reference in New Issue
Block a user