diff --git a/Docs/backend_API_docs/README.md b/Docs/backend_API_docs/README.md index e993c89..0d15fc0 100644 --- a/Docs/backend_API_docs/README.md +++ b/Docs/backend_API_docs/README.md @@ -1,7 +1,7 @@ # Borrow System API Documentation **Frontend:** https://insta.the1s.de -**Backend base URL:** `https://backend.insta.the1s.de/api` +**Backend base URL:** `https://insta.the1s.de/backend/api` --- diff --git a/FrontendV2/nginx.conf b/FrontendV2/nginx.conf index 4aa4fa8..cbb9122 100644 --- a/FrontendV2/nginx.conf +++ b/FrontendV2/nginx.conf @@ -9,6 +9,14 @@ server { try_files $uri $uri/ /index.html; } + location = /backend { + return 301 /backend/; + } + + location /backend/ { + proxy_pass http://borrow_system-backend_v2:8004/; + } + location ~* \.(?:js|mjs|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ { expires 1y; access_log off; diff --git a/FrontendV2/src/App.tsx b/FrontendV2/src/App.tsx index 5c774c9..05c206c 100644 --- a/FrontendV2/src/App.tsx +++ b/FrontendV2/src/App.tsx @@ -16,7 +16,6 @@ import { Box, Flex } from "@chakra-ui/react"; import { Footer } from "./components/footer/Footer"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { API_BASE } from "@/config/api.config"; -import { NotFoundPage } from "./pages/NotFoundPage"; const queryClient = new QueryClient(); @@ -84,7 +83,6 @@ function App() { } /> - } /> diff --git a/FrontendV2/src/components/Header.tsx b/FrontendV2/src/components/Header.tsx index 2ba22cb..a01199e 100644 --- a/FrontendV2/src/components/Header.tsx +++ b/FrontendV2/src/components/Header.tsx @@ -4,25 +4,18 @@ import { Heading, Stack, Text, - CloseButton, - Dialog, - Portal, HStack, IconButton, Menu, Box, Avatar, - Card, - Grid, } 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"; import { useNavigate } from "react-router-dom"; import { CircleUserRound, - RotateCcwKey, Code, LifeBuoy, LogOut, @@ -33,69 +26,19 @@ import { } from "lucide-react"; import { useUserContext } from "@/states/Context"; import { useState } from "react"; -import MyAlert from "./myChakra/MyAlert"; import { useTranslation } from "react-i18next"; -import { API_BASE } from "@/config/api.config"; +import { UserDialogue } from "./UserDialogue"; export const Header = () => { const navigate = useNavigate(); const userData = useUserContext(); - console.log(userData); const { t } = useTranslation(); - // 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); - // Dialog control - const [isPwOpen, setPwOpen] = useState(false); const [userDialog, setUserDialog] = useState(false); - const changePassword = async () => { - if (newPassword !== confirmPassword) { - setMsgTitle(t("err_pw_change")); - setMsgDescription(t("pw_mismatch")); - setMsgStatus("error"); - setIsMsg(true); - return; - } - - const response = await fetch(`${API_BASE}/api/users/change-password`, { - method: "POST", - headers: { - "Content-Type": "application/json", - Authorization: `Bearer ${Cookies.get("token")}`, - }, - body: JSON.stringify({ oldPassword, newPassword }), - }); - - if (!response.ok) { - setMsgTitle(t("err_pw_change")); - setMsgDescription(t("pw_mismatch")); - setMsgStatus("error"); - setIsMsg(true); - return; - } - - setMsgTitle(t("pw_success")); - setMsgDescription(t("pw_success_desc")); - setMsgStatus("success"); - setIsMsg(true); - - setOldPassword(""); - setNewPassword(""); - setConfirmPassword(""); - }; - const username = userData.first_name ? userData.first_name : "N/A"; const fullname = userData.first_name + " " + userData.last_name; const randomColor = [ @@ -375,146 +318,7 @@ export const Header = () => { {/* User Info Dialoge */} - {userDialog && ( - - - - - - - - - - - {t("user-info-desc")} - - - - - - - {t("first-name")}: - - {userData.first_name} - - - {t("last-name")}: - - {userData.last_name} - - - {t("username")}: - - {userData.username} - - - {t("role")}: - - {userData.role} - - - {t("admin-status")}: - - - {userData.is_admin ? t("yes") : t("no")} - - - - - - - - - - - - - )} - - {/* Passwort-Dialog (kontrolliert) */} - setPwOpen(e.open)}> - - - - - - {t("change-password")} - -
{ - e.preventDefault(); - changePassword(); - }} - > - - - setOldPassword(e.target.value)} - placeholder={t("old-password")} - /> - setNewPassword(e.target.value)} - placeholder={t("new-password")} - /> - setConfirmPassword(e.target.value)} - placeholder={t("confirm-password")} - /> - - - - - {isMsg && ( - - )} - - - - - - - - -
- - - -
-
-
-
+ {userDialog && } ); }; diff --git a/FrontendV2/src/components/UserDialogue.tsx b/FrontendV2/src/components/UserDialogue.tsx new file mode 100644 index 0000000..d4e88b6 --- /dev/null +++ b/FrontendV2/src/components/UserDialogue.tsx @@ -0,0 +1,220 @@ +import { + Button, + Flex, + Stack, + Text, + CloseButton, + Dialog, + Portal, + HStack, + Box, + Avatar, + Card, + Grid, +} from "@chakra-ui/react"; +import { PasswordInput } from "@/components/ui/password-input"; +import { RotateCcwKey } from "lucide-react"; +import MyAlert from "./myChakra/MyAlert"; +import { API_BASE } from "@/config/api.config"; +import { useUserContext } from "@/states/Context"; +import { useState } from "react"; +import { useTranslation } from "react-i18next"; +import Cookies from "js-cookie"; + +type UserDialogueProps = { + setUserDialog: (value: boolean) => void; + fullname: string; + randomColor: string[]; +}; + +export const UserDialogue = (props: UserDialogueProps) => { + const userData = useUserContext(); + const { t } = useTranslation(); + // 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(""); + + // Dialog control + const [isPwOpen, setPwOpen] = useState(false); + + const changePassword = async () => { + if (newPassword !== confirmPassword) { + setMsgTitle(t("err_pw_change")); + setMsgDescription(t("pw_mismatch")); + setMsgStatus("error"); + setIsMsg(true); + return; + } + + const response = await fetch(`${API_BASE}/api/users/change-password`, { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${Cookies.get("token")}`, + }, + body: JSON.stringify({ oldPassword, newPassword }), + }); + + if (!response.ok) { + setMsgTitle(t("err_pw_change")); + setMsgDescription(t("pw_mismatch")); + setMsgStatus("error"); + setIsMsg(true); + return; + } + + setMsgTitle(t("pw_success")); + setMsgDescription(t("pw_success_desc")); + setMsgStatus("success"); + setIsMsg(true); + + setOldPassword(""); + setNewPassword(""); + setConfirmPassword(""); + }; + + return ( + + + + + + + + + + + {t("user-info-desc")} + + + + + + + {t("first-name")}: + + {userData.first_name} + + + {t("last-name")}: + + {userData.last_name} + + + {t("username")}: + + {userData.username} + + + {t("role")}: + + {userData.role} + + + {t("admin-status")}: + + {userData.is_admin ? t("yes") : t("no")} + + + + + + + + + + + + {/* Passwort-Dialog (kontrolliert) */} + setPwOpen(e.open)}> + + + + + + {t("change-password")} + +
{ + e.preventDefault(); + changePassword(); + }} + > + + + setOldPassword(e.target.value)} + placeholder={t("old-password")} + /> + setNewPassword(e.target.value)} + placeholder={t("new-password")} + /> + setConfirmPassword(e.target.value)} + placeholder={t("confirm-password")} + /> + + + + + {isMsg && ( + + )} + + + + + + + + +
+ + + +
+
+
+
+
+ ); +}; diff --git a/FrontendV2/src/pages/NotFoundPage.tsx b/FrontendV2/src/pages/NotFoundPage.tsx deleted file mode 100644 index b3c36f6..0000000 --- a/FrontendV2/src/pages/NotFoundPage.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import React from "react"; - -export const NotFoundPage = () => { - return ( - <> - - - ) -}; diff --git a/FrontendV2/src/utils/i18n/locales/de/de.json b/FrontendV2/src/utils/i18n/locales/de/de.json index f9d361b..2d7cf8f 100644 --- a/FrontendV2/src/utils/i18n/locales/de/de.json +++ b/FrontendV2/src/utils/i18n/locales/de/de.json @@ -63,7 +63,7 @@ "timezone-info": "Die angezeigten Daten und Uhrzeiten werden in deutscher Zeitzone dargestellt und müssen auch so eingegeben werden.", "optional-note": "Optionale Notiz", "note": "Notiz", - "user-info-desc": "Hier können Sie Ihre persönlichen Informationen einsehen und ändern.", + "user-info-desc": "Hier können Sie Ihre persönlichen Informationen einsehen und das Passwort ändern. Falls Sie weitere Änderungen benötigen, wenden Sie sich bitte an einen Administrator.", "role": "Rolle", "admin-status": "Admin-Status", "first-name": "Vorname", diff --git a/FrontendV2/src/utils/i18n/locales/en/en.json b/FrontendV2/src/utils/i18n/locales/en/en.json index 8d8f891..8091bb0 100644 --- a/FrontendV2/src/utils/i18n/locales/en/en.json +++ b/FrontendV2/src/utils/i18n/locales/en/en.json @@ -63,7 +63,7 @@ "timezone-info": "The displayed dates and times are shown in Berlin timezone and must also be entered as such.", "optional-note": "Optional note", "note": "Note", - "user-info-desc": "Here you can view and edit your personal information.", + "user-info-desc": "Here you can view your personal information and change your password. If you need to make further changes, please contact an administrator.", "role": "Role", "admin-status": "Admin status", "first-name": "First name", diff --git a/admin/nginx.conf b/admin/nginx.conf index 4aa4fa8..cbb9122 100644 --- a/admin/nginx.conf +++ b/admin/nginx.conf @@ -9,6 +9,14 @@ server { try_files $uri $uri/ /index.html; } + location = /backend { + return 301 /backend/; + } + + location /backend/ { + proxy_pass http://borrow_system-backend_v2:8004/; + } + location ~* \.(?:js|mjs|css|png|jpg|jpeg|gif|ico|svg|woff2?)$ { expires 1y; access_log off; diff --git a/docker-compose.yml b/docker-compose.yml index ea6314a..b8e5953 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -22,8 +22,6 @@ services: networks: - proxynet build: ./backendV2 - ports: - - "8102:8102" environment: NODE_ENV: production DB_HOST: mysql_v2