added password input component and integrated password change functionality in Header; updated LoginPage for localized labels

This commit is contained in:
2025-10-25 21:49:28 +02:00
parent cc0dcaf664
commit d94d68aa33
3 changed files with 278 additions and 8 deletions

View File

@@ -1,4 +1,15 @@
import { Badge, Button, Flex, Heading, Stack, Text } from "@chakra-ui/react";
import {
Badge,
Button,
Flex,
Heading,
Stack,
Text,
CloseButton,
Dialog,
Portal,
} from "@chakra-ui/react";
import { PasswordInput } from "@/components/ui/password-input";
import Cookies from "js-cookie";
import { useAtom } from "jotai";
import { setIsLoggedInAtom, triggerLogoutAtom } from "@/states/Atoms";
@@ -12,15 +23,64 @@ import {
CalendarPlus,
} from "lucide-react";
import { useUserContext } from "@/states/Context";
import { useState } from "react";
import MyAlert from "./myChakra/MyAlert";
const API_BASE =
(import.meta as any).env?.VITE_BACKEND_URL ||
import.meta.env.VITE_BACKEND_URL ||
"http://localhost:8002";
export const Header = () => {
const navigate = useNavigate();
const userData = useUserContext();
// Error handling states
const [isMsg, setIsMsg] = useState(false);
const [msgStatus, setMsgStatus] = useState<"error" | "success">("error");
const [msgTitle, setMsgTitle] = useState("");
const [msgDescription, setMsgDescription] = useState("");
const [oldPassword, setOldPassword] = useState("");
const [newPassword, setNewPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
const [, setTriggerLogout] = useAtom(triggerLogoutAtom);
const [, setIsLoggedIn] = useAtom(setIsLoggedInAtom);
const changePassword = async () => {
if (newPassword !== confirmPassword) {
setMsgTitle("Passwortänderung fehlgeschlagen");
setMsgDescription("Passwörter stimmen nicht überein");
setMsgStatus("error");
setIsMsg(true);
return;
}
const response = await fetch(`${API_BASE}/api/changePassword`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${Cookies.get("token")}`,
},
body: JSON.stringify({ oldPassword, newPassword }),
});
if (!response.ok) {
setMsgTitle("Passwortänderung fehlgeschlagen");
setMsgDescription("Bitte überprüfen Sie Ihre Eingaben");
setMsgStatus("error");
setIsMsg(true);
return;
}
setMsgTitle("Passwort erfolgreich geändert");
setMsgDescription("Ihr Passwort wurde erfolgreich geändert");
setMsgStatus("success");
setIsMsg(true);
};
return (
<Stack as="header" gap={3} className="mb-16">
<Flex
@@ -61,9 +121,60 @@ export const Header = () => {
<Button onClick={() => navigate("/my-loans", { replace: true })}>
<CircleUserRound /> Meine Ausleihen
</Button>
<Button>
<RotateCcwKey /> Passwort ändern
</Button>
<Dialog.Root>
<Dialog.Trigger asChild>
<Button>
<RotateCcwKey /> Passwort ändern
</Button>
</Dialog.Trigger>
<Portal>
<Dialog.Backdrop />
<Dialog.Positioner>
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>Passwort ändern</Dialog.Title>
</Dialog.Header>
<form
onSubmit={(e) => {
e.preventDefault();
changePassword();
}}
>
<Dialog.Body>
<PasswordInput
onChange={(e) => setOldPassword(e.target.value)}
placeholder="Altes Passwort"
/>
<PasswordInput
onChange={(e) => setNewPassword(e.target.value)}
placeholder="Neues Passwort"
/>
<PasswordInput
onChange={(e) => setConfirmPassword(e.target.value)}
placeholder="Neues Passwort wiederholen"
/>
</Dialog.Body>
<Dialog.Footer>
{isMsg && (
<MyAlert
status={msgStatus}
title={msgTitle}
description={msgDescription}
/>
)}
<Dialog.ActionTrigger asChild>
<Button variant="outline">Cancel</Button>
</Dialog.ActionTrigger>
<Button type="submit">Save</Button>
</Dialog.Footer>
</form>
<Dialog.CloseTrigger asChild>
<CloseButton size="sm" />
</Dialog.CloseTrigger>
</Dialog.Content>
</Dialog.Positioner>
</Portal>
</Dialog.Root>
<a
href="https://git.the1s.de/Matthias-Claudius-Schule/borrow-system/wiki"
target="_blank"