apply suggestions
continuous-integration/drone/push Build is passing Details

pull/118/head
maxime 1 year ago
parent d6f1a633a1
commit f9c42862e0

@ -8,21 +8,6 @@
</head>
<body>
<div id="root"></div>
<script
src="https://cdn.jsdelivr.net/npm/react/umd/react.production.min.js"
crossorigin></script>
<script
src="https://cdn.jsdelivr.net/npm/react-dom/umd/react-dom.production.min.js"
crossorigin></script>
<script
src="https://cdn.jsdelivr.net/npm/react-bootstrap@next/dist/react-bootstrap.min.js"
crossorigin></script>
<script>
var Alert = ReactBootstrap.Alert
</script>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

@ -45,8 +45,7 @@ export default function App() {
)
}
const storedAuth = useMemo(() => getStoredAuthentication(), [])
const fetcher = useMemo(() => new Fetcher(storedAuth), [storedAuth])
const fetcher = useMemo(() => new Fetcher(getStoredAuthentication()), [])
const [user, setUser] = useState<User | null>(null)
const handleAuthSuccess = useCallback(
@ -247,7 +246,7 @@ function AppLayout() {
interface UserContext {
user: User | null
setUser: (user: User) => void
setUser: (user: User | null) => void
}
const SignedInUserContext = createContext<UserContext | null>(null)
@ -257,7 +256,7 @@ export function useAppFetcher() {
return useContext(FetcherContext)
}
export function useUser(): [User | null, (user: User) => void] {
export function useUser(): [User | null, (user: User | null) => void] {
const { user, setUser } = useContext(SignedInUserContext)!
return [user, setUser]
}

@ -68,11 +68,9 @@ export class Fetcher {
}
const nextToken = response.headers.get("Next-Authorization")!
const expirationDate = new Date(
response.headers.get("Next-Authorization-Expiration-Date")!,
)
const expirationDate = response.headers.get("Next-Authorization-Expiration-Date")!
if (nextToken && expirationDate) {
this.auth = { token: nextToken, expirationDate }
this.auth = { token: nextToken, expirationDate: new Date(expirationDate) }
}
return response

@ -1,4 +1,4 @@
import { FormEvent, useCallback, useRef, useState } from "react"
import { FormEvent, useCallback, useEffect, useRef, useState } from "react"
import "../style/settings.css"
import { useAppFetcher, useUser } from "../App.tsx"
import { Fetcher } from "../app/Fetcher.ts"
@ -10,18 +10,19 @@ export default function ProfileSettings() {
const [errorMessages, setErrorMessages] = useState<string[]>([])
const [success, setSuccess] = useState(false)
const formRef = useRef<HTMLFormElement | null>(null)
const [name, setName] = useState(user!.name)
const [email, setEmail] = useState(user!.email)
const [password, setPassword] = useState<string>()
const [confirmPassword, setConfirmPassword] = useState<string>()
const passwordConfirmRef = useRef<HTMLInputElement>(null)
const formRef = useRef<HTMLFormElement>(null)
const submitForm = useCallback(
async (e: FormEvent) => {
e.preventDefault()
const { name, email, password, confirmPassword } =
Object.fromEntries<string>(
new FormData(formRef.current!) as Iterable<
[PropertyKey, string]
>,
)
passwordConfirmRef.current!.checkValidity()
if (password !== confirmPassword) {
setErrorMessages(["Les mots de passe ne correspondent pas !"])
return
@ -46,9 +47,15 @@ export default function ProfileSettings() {
formRef.current!.reset()
setErrorMessages([])
},
[fetcher, setUser, user],
[confirmPassword, email, fetcher, name, password, setUser, user],
)
useEffect(() => {
passwordConfirmRef.current!.setCustomValidity(
password === confirmPassword ? "" : "Les mots de passe ne correspondent pas !"
)
}, [confirmPassword, password])
const [modalShow, setModalShow] = useState(false)
const width = 150
@ -94,44 +101,64 @@ export default function ProfileSettings() {
ref={formRef}
id="credentials-form"
onSubmit={submitForm}>
<p>Nom d'utilisateur</p>
<label htmlFor="name">Nom d'utilisateur</label>
<input
className="settings-input"
id="name"
name="name"
type="text"
placeholder={"Nom d'utilisateur"}
defaultValue={user!.name}
autoComplete="username"
required
placeholder="Nom d'utilisateur"
value={name}
onChange={e => setName(e.target.value)}
/>
<p>Addresse email</p>
<label htmlFor="email">Adresse email</label>
<input
className="settings-input"
name="email"
id="email"
type="email"
placeholder={"Addresse email"}
defaultValue={user!.email}
placeholder={"Adresse email"}
autoComplete="email"
required
value={email}
onChange={e => setEmail(e.target.value)}
/>
<p>Mot de passe</p>
<label htmlFor="password">Mot de passe</label>
<input
className="settings-input"
name="password"
id={"password"}
type="password"
placeholder={"Mot de passe"}
autoComplete="new-password"
value={password}
onChange={e => setPassword(e.target.value)}
/>
<p>Confirmez le mot de passe</p>
<label htmlFor="confirmPassword">Confirmez le mot de passe</label>
<input
ref={passwordConfirmRef}
className="settings-input"
name="confirmPassword"
id="confirmPassword"
type="password"
autoComplete="new-password"
placeholder={"Confirmation du mot de passe"}
value={confirmPassword}
onChange={e => setConfirmPassword(e.target.value)}
/>
<button
className="settings-button"
type="submit"
onClick={submitForm}>
type="submit">
Mettre à jour
</button>
</form>
@ -173,11 +200,38 @@ function ProfileImageInputPopup({ show, onHide }: ProfileImageInputPopupProps) {
const fetcher = useAppFetcher()
const [user, setUser] = useUser()
const [link, setLink] = useState("")
useEffect(() => {
function onKeyUp(e: KeyboardEvent) {
if (e.key === "Escape") onHide()
}
window.addEventListener('keyup', onKeyUp)
return () => window.removeEventListener('keyup', onKeyUp)
}, [onHide])
const handleForm = useCallback(async (e: FormEvent) => {
e.preventDefault()
const url = urlRef.current!.value
const errors = await updateAccount(fetcher, {
profilePicture: url,
})
if (errors.length !== 0) {
setErrorMessages(errors)
return
}
setUser({ ...user!, profilePicture: url })
setErrorMessages([])
onHide()
}, [fetcher, onHide, setUser, user])
if (!show) return <></>
return (
<div id="profile-picture-popup">
<div id="profile-picture-popup-content">
<dialog id="profile-picture-popup">
<form id="profile-picture-popup-form" onSubmit={handleForm}>
<div id="profile-picture-popup-header">
<p id="profile-picture-popup-title">
Nouvelle photo de profil
@ -189,9 +243,9 @@ function ProfileImageInputPopup({ show, onHide }: ProfileImageInputPopupProps) {
{msg}
</div>
))}
<p id="profile-picture-popup-subtitle">
<label id="profile-picture-popup-subtitle" htmlFor="profile-picture">
Saisissez le lien vers votre nouvelle photo de profil
</p>
</label>
<input
className={
`settings-input ` +
@ -199,33 +253,26 @@ function ProfileImageInputPopup({ show, onHide }: ProfileImageInputPopupProps) {
? ""
: "invalid-input")
}
id="profile-picture"
ref={urlRef}
type="input"
type="url"
autoComplete="url"
required
placeholder={"lien vers une image"}
value={link}
onChange={e => setLink(e.target.value)}
/>
<div id="profile-picture-popup-footer">
<button className={"settings-button"} onClick={onHide}>
Annuler
</button>
<button
<input
type="submit"
className={"settings-button"}
onClick={async () => {
const url = urlRef.current!.value
const errors = await updateAccount(fetcher, {
profilePicture: url,
})
if (errors.length !== 0) {
setErrorMessages(errors)
return
}
setUser({ ...user!, profilePicture: url })
setErrorMessages([])
onHide()
}}>
Valider
</button>
value="Valider"
/>
</div>
</div>
</div>
</form>
</dialog>
)
}

@ -11,7 +11,7 @@ export function Header() {
<img
id="img-account"
src={user.profilePicture}
alt={"profile-picture"}
alt={`Photo de profil de ${user!.name}`}
/>
) : (
<AccountSvg id="img-account" />

@ -20,13 +20,13 @@ body {
#body {
display: flex;
flex-direction: row;
margin: 0px;
margin: 0;
height: 100%;
background-color: var(--home-second-color);
}
.data {
border: 1.5px solid var(--main-contrast-color);
border: 2px solid var(--main-contrast-color);
background-color: var(--home-main-color);
border-radius: 0.75cap;
color: var(--main-contrast-color);

@ -79,7 +79,7 @@
background-color: rgba(84, 78, 78, 0.33);
}
#profile-picture-popup-content {
#profile-picture-popup-form {
display: flex;
flex-direction: column;
row-gap: 20px;

@ -40,12 +40,6 @@
color: var(--accent-color);
}
#username {
text-align: center;
vertical-align: center;
margin: 0;
}
#clickable-header-right {
border-radius: 1cap;

Loading…
Cancel
Save