From 3927db30e946ec4c3256f0f36ed9fe474ceb1816 Mon Sep 17 00:00:00 2001 From: F <150372421+GalacticCodeGambit@users.noreply.github.com> Date: Mon, 27 Apr 2026 14:27:55 +0200 Subject: [PATCH 01/11] Rename models.py to Models.py --- project/backend/{models.py => Models.py} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename project/backend/{models.py => Models.py} (93%) diff --git a/project/backend/models.py b/project/backend/Models.py similarity index 93% rename from project/backend/models.py rename to project/backend/Models.py index a4fafcc..43c573e 100644 --- a/project/backend/models.py +++ b/project/backend/Models.py @@ -18,4 +18,4 @@ class RefreshRequest(BaseModel): refresh_token: str class LogoutRequest(BaseModel): - refresh_token: str \ No newline at end of file + refresh_token: str From cf47a4e29001dd055d287ae51e7951807eeb0dfc Mon Sep 17 00:00:00 2001 From: F <150372421+GalacticCodeGambit@users.noreply.github.com> Date: Mon, 27 Apr 2026 14:31:47 +0200 Subject: [PATCH 02/11] Rename auth.py to Auth.py --- project/backend/{auth.py => Auth.py} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename project/backend/{auth.py => Auth.py} (98%) diff --git a/project/backend/auth.py b/project/backend/Auth.py similarity index 98% rename from project/backend/auth.py rename to project/backend/Auth.py index 9cd5c9d..4a61551 100644 --- a/project/backend/auth.py +++ b/project/backend/Auth.py @@ -134,4 +134,4 @@ async def getCurrentUser(token: Annotated[str, Depends(oauth2_scheme)]) -> User: if konto is None: raise credentials_exception - return User(email=konto["email"], name=konto["name"]) \ No newline at end of file + return User(email=konto["email"], name=konto["name"]) From c7cfad1ab47647577e161d99a6ba9669ca9f4f3b Mon Sep 17 00:00:00 2001 From: F <150372421+GalacticCodeGambit@users.noreply.github.com> Date: Mon, 27 Apr 2026 14:32:45 +0200 Subject: [PATCH 03/11] Rename Routes.py to routes.py --- project/backend/{routes.py => Routes.py} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename project/backend/{routes.py => Routes.py} (99%) diff --git a/project/backend/routes.py b/project/backend/Routes.py similarity index 99% rename from project/backend/routes.py rename to project/backend/Routes.py index fe42bef..d312329 100644 --- a/project/backend/routes.py +++ b/project/backend/Routes.py @@ -147,4 +147,4 @@ async def updateCurrentUser( except Exception as e: print(f"E-Mail konnte nicht gesendet werden: {e}") - return {"success": True} \ No newline at end of file + return {"success": True} From 3d8441f4806bc215abeadf172fb0033e445684e7 Mon Sep 17 00:00:00 2001 From: Samuel Goebel Date: Mon, 27 Apr 2026 14:40:25 +0200 Subject: [PATCH 04/11] Added Refactoring Summary --- docs/CodeReafktorisierungZusammenfassungen.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 docs/CodeReafktorisierungZusammenfassungen.md diff --git a/docs/CodeReafktorisierungZusammenfassungen.md b/docs/CodeReafktorisierungZusammenfassungen.md new file mode 100644 index 0000000..40cf8ac --- /dev/null +++ b/docs/CodeReafktorisierungZusammenfassungen.md @@ -0,0 +1,8 @@ + +# Zusammenfassung der Refaktorisierung + +Der *Code des kompletten Backends*, bis auf die Tests, wurde *refaktorisiert*. Dabei wurde der Fokus auf Klassennamen, Methodennamen, Dateinamen, sowie Klassenvariablen gelegt.
+Ziel der vorgenommenen Refaktorisierung war, dass alle gesetzten Namen zu vereinheitlichen. Für diesen Zweck wurde von dem gesamten Team eine einheitliche Namenskonvention beschlossen: +$\quad$Alle Namen sollen komplett in **Englisch** mit **UpperCamelCase** definiert werden, um einerseits die **Verständlichkeit** und andererseits die **Wartbarkeit** durch die Vereinheitlichung zu sichern. Ferner werden alle Namen **zusammengeschrieben**, wobei Methoden- und Variablennamen am Anfang *klein geschrieben* sowie Klassen- und Dateinamen *groß geschrieben* werden.
+Dieser Regel nach wurde die Backend-Refaktorisierung durchgeführt. Dennoch wurden teilweise temporäre Variablen innerhalb von Methoden noch nicht refaktorisiert, was zukünftig noch angepasst werden muss. Außerdem fand noch keine Reafktorisierung des Front-Ends statt, welche zeitnah für die weitere Entwicklung erheischt wird. + From f3d2f1559e3f93aafefc52d2a46b1014e9a400b2 Mon Sep 17 00:00:00 2001 From: PrussianBaron Date: Mon, 27 Apr 2026 14:44:04 +0200 Subject: [PATCH 05/11] Refactor documentation for code naming conventions --- docs/CodeReafktorisierungZusammenfassungen.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/CodeReafktorisierungZusammenfassungen.md b/docs/CodeReafktorisierungZusammenfassungen.md index 40cf8ac..cfecb92 100644 --- a/docs/CodeReafktorisierungZusammenfassungen.md +++ b/docs/CodeReafktorisierungZusammenfassungen.md @@ -1,8 +1,12 @@ # Zusammenfassung der Refaktorisierung -Der *Code des kompletten Backends*, bis auf die Tests, wurde *refaktorisiert*. Dabei wurde der Fokus auf Klassennamen, Methodennamen, Dateinamen, sowie Klassenvariablen gelegt.
-Ziel der vorgenommenen Refaktorisierung war, dass alle gesetzten Namen zu vereinheitlichen. Für diesen Zweck wurde von dem gesamten Team eine einheitliche Namenskonvention beschlossen: -$\quad$Alle Namen sollen komplett in **Englisch** mit **UpperCamelCase** definiert werden, um einerseits die **Verständlichkeit** und andererseits die **Wartbarkeit** durch die Vereinheitlichung zu sichern. Ferner werden alle Namen **zusammengeschrieben**, wobei Methoden- und Variablennamen am Anfang *klein geschrieben* sowie Klassen- und Dateinamen *groß geschrieben* werden.
+Der *Code des kompletten Backends*, bis auf die Tests, wurde *refaktorisiert*. Dabei wurde der Fokus auf Klassennamen, Methodennamen, Dateinamen, sowie Klassenvariablen gelegt. +
+
+Ziel der vorgenommenen Refaktorisierung war, dass alle gesetzten Namen zu vereinheitlichen. Für diesen Zweck wurde von dem gesamten Team eine einheitliche Namenskonvention beschlossen:
+Alle Namen sollen komplett in **Englisch** mit **UpperCamelCase** definiert werden, um einerseits die **Verständlichkeit** und andererseits die **Wartbarkeit** durch die Vereinheitlichung zu sichern. Ferner werden alle Namen **zusammengeschrieben**, wobei Methoden- und Variablennamen am Anfang *klein geschrieben* sowie Klassen- und Dateinamen *groß geschrieben* werden. +
+
Dieser Regel nach wurde die Backend-Refaktorisierung durchgeführt. Dennoch wurden teilweise temporäre Variablen innerhalb von Methoden noch nicht refaktorisiert, was zukünftig noch angepasst werden muss. Außerdem fand noch keine Reafktorisierung des Front-Ends statt, welche zeitnah für die weitere Entwicklung erheischt wird. From 8394fa0774a43be3fc8d230f83d0c9c075fe02e1 Mon Sep 17 00:00:00 2001 From: Eden Tabea Bernhard <105359952+EdenBernhard@users.noreply.github.com> Date: Mon, 27 Apr 2026 14:48:46 +0200 Subject: [PATCH 06/11] Fix spelling errors in refactoring documentation Corrected spelling of 'Refaktorisierung' and 'Frontend'. --- docs/CodeReafktorisierungZusammenfassungen.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/CodeReafktorisierungZusammenfassungen.md b/docs/CodeReafktorisierungZusammenfassungen.md index cfecb92..1abd8a8 100644 --- a/docs/CodeReafktorisierungZusammenfassungen.md +++ b/docs/CodeReafktorisierungZusammenfassungen.md @@ -8,5 +8,5 @@ Ziel der vorgenommenen Refaktorisierung war, dass alle gesetzten Namen zu verein Alle Namen sollen komplett in **Englisch** mit **UpperCamelCase** definiert werden, um einerseits die **Verständlichkeit** und andererseits die **Wartbarkeit** durch die Vereinheitlichung zu sichern. Ferner werden alle Namen **zusammengeschrieben**, wobei Methoden- und Variablennamen am Anfang *klein geschrieben* sowie Klassen- und Dateinamen *groß geschrieben* werden.

-Dieser Regel nach wurde die Backend-Refaktorisierung durchgeführt. Dennoch wurden teilweise temporäre Variablen innerhalb von Methoden noch nicht refaktorisiert, was zukünftig noch angepasst werden muss. Außerdem fand noch keine Reafktorisierung des Front-Ends statt, welche zeitnah für die weitere Entwicklung erheischt wird. +Dieser Regel nach wurde die Backend-Refaktorisierung durchgeführt. Dennoch wurden teilweise temporäre Variablen innerhalb von Methoden noch nicht refaktorisiert, was zukünftig noch angepasst werden muss. Außerdem fand noch keine Refaktorisierung des Frontends statt, welche zeitnah für die weitere Entwicklung erheischt wird. From 49d82de42d345200ba9f4e0ddb18b2245cba3c40 Mon Sep 17 00:00:00 2001 From: Nicoolaus <162422307+Nicoolaus@users.noreply.github.com> Date: Tue, 28 Apr 2026 09:43:23 +0200 Subject: [PATCH 07/11] Delete project/data/LazyCookDB.sqlite3 --- project/data/LazyCookDB.sqlite3 | Bin 65536 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 project/data/LazyCookDB.sqlite3 diff --git a/project/data/LazyCookDB.sqlite3 b/project/data/LazyCookDB.sqlite3 deleted file mode 100644 index 3aa5d49652e8d3f73b7fa732624cdb8d60a9c72e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 65536 zcmeI)%~RrL90%|O6%?y@V;m3r?Cd%tRcQbb@Y0PC0Yy*@%VH0dmncyLA>iAgGj?Cv z>9qX^dhS2cnI3xTp|>7;>L1WU5A94J2m;wLb+-uAnQulQ5P6;_pWp9!NO+=qyAio2 zk%MyeBvT_UW`3BD|Xssee{U^Vz-vb7Nw2MS-DEl zmG+9o9~XF0AR@mW5lH)GvS22?EPO6ku9s@z00~D$At=O2G$xX0A`)5Zt>CJhzwaV9 zVsRlHjFK%OMHbo(w~@H8A;g8KU)Uq9SIL5$w~<(s1cZn{(fs_LpAQK7yQC?aHeFL_ zT*}F((tDSgh=z9)LRU+dNTXz3R-40OvITtga;3iPMzPtQV z=0qZ*@IoZ5j(Q&h-&t3y@1s0T`q9EQ>BrY=g>qFV^>pQJi<3s{$Fq8|S0k5psE;39 ze>UEX_{(H7;%b%Z{e&jsH;vJ)_wI<$-{|7&OVDW*x^cg?<+jC%f74R;I_*#&&7Xg2 zG+7@%W?xS>wL0TNXU(Kh>%88}SlnkdU9ldzpE?|im-KV>IUo0j`1pd0>kP=Z#-foy zHkZk04L;V(-i~M5(ODmV9UL`T=jYk4)T67obWoL)f>=J5O5N*Yn%H!2=_NXiX49q5 zK~gKZIRLu<<2hP>t>L8(nKxrwYwYYH5nAn*E>2|{6TU{o@V2lg^4mM_@af!o^PLa5 zs+6foc}?j7VS`UZMB-1x>A|CzZr9uU&S*yM|8k(JpZ=aPqjhUuFa5hywlRcv(%iT+ zVze$UvZ?04)H=9Sq)J^X<)pWsj%vEWTN@V|qrnn=r|soOtjRhz$G&l^9}Vi6L~C~q znljpl<+?j|X9)Y;eWa6&Tx<_TPIuQ>bZ3rt#>bm(p`Sv9j8c&DI~heeFIV&0&ZPgY z_sU;gW81R9XyxbhlBX3U`eCLoHeJ&J{C?ozBT$9ZS#7rK~+KiIP$y8&93trw->+yQ{JutDGJN z{q~KDP(KT;JxN?`C69u8PR_Zy%&jatSBQgK zbNbd+yk@#ztmSux{$POs1Rwwb2tWV=5P$##AOHafK;VH3SV!Cww|%M5nEy9eeq$_u z&^s&;fB*y_009U<00Izz00bZa0SG)$ff>WdJlp-}A_g-%GB?rsLxAS_|Mahn<%Hg0 zfdB*`009U<00Izz00bZa0SG)ef$JHAiJ7?eZM!NNf5~&Y?+X=_-QsaMd*-QZDqG3y z^W477`SbCeq>?JWI6qACbx+Z8ytS`fgtnc^b0u)>T^GE9H+irt$^6m!YAARaO7NSW z)oAEYy_nv;%sE7QF}=&Nwz6vHRymK?x5#m89H+h5zPbH+hF;&_Y|`byW~II#*$gko z4tHH%&pEfrc`NCw%X-ouPKnvP|F{qc`IF8IPq8lNMd5N!mUaqf7rsI^wf`bgEXnam zDjDz`U4$cvY&CTd+pfOVq~`VgcAwAb^15$pQe(TXas9u+5@sx6%l8j1#Aq-CAOHaf zKmY;|fB*y_009UNISAC*G@ z0uX=z1Rwwb2tWV=5P$##1|op@|A8>05(q#50uX=z1Rwwb2tWV=5P-l?1u*|VRDM(r z0SG_<0uX=z1Rwwb2tWV=5EzI6=Klx6j7lH?0SG_<0uX=z1Rwwb2tWV=LlyW3C>axR From d721f6b84088efea478bcd2a8be439b66adefbef Mon Sep 17 00:00:00 2001 From: Hellocrafting Date: Tue, 28 Apr 2026 16:55:57 +0200 Subject: [PATCH 08/11] AI Agent md's changed --- .../agents/{agent.md => agent-template.md} | 0 .github/agents/doc-agent.md | 93 +++++++++++++++++++ .github/agents/lint-agent.md | 0 .github/agents/test-agent.md | 78 ++++++++++++++++ 4 files changed, 171 insertions(+) rename .github/agents/{agent.md => agent-template.md} (100%) delete mode 100644 .github/agents/lint-agent.md diff --git a/.github/agents/agent.md b/.github/agents/agent-template.md similarity index 100% rename from .github/agents/agent.md rename to .github/agents/agent-template.md diff --git a/.github/agents/doc-agent.md b/.github/agents/doc-agent.md index e69de29..a0f5a1d 100644 --- a/.github/agents/doc-agent.md +++ b/.github/agents/doc-agent.md @@ -0,0 +1,93 @@ +--- +name: Doc Agent +description: This agent helps maintain and create documentation for both the frontend (React) and backend (Python) of the project. +--- + +You are an expert technical writer for this project. + +## Persona +- You specialize in creating and maintaining clear, accurate documentation +- You understand the codebase and translate that into documentation developers can actually use +- Your output: documentation that reduces onboarding time and prevents misuse of APIs and components + +## Project Knowledge + + + + + +**Tech Stack:** +- **Frontend:** React 19.2.0 — see `project/frontend/package.json` and `project/Dockerfile-frontend` +- **Backend:** Python 3.11.10-slim — see `project/Dockerfile-backend` + + +**File Structure:** +- `project/frontend` – React frontend source +- `project/frontend/docs` – place frontend documentation here +- `project/backend` – Python backend source +- `project/backend/docs` – place backend documentation here + +## Tools + +**Frontend (React):** +- Build: `npm run build` +- Lint: `npm run lint --fix` + +**Backend (Python):** +- Lint: `ruff check . --fix` +- Type check: `mypy project/backend` + +## Standards + +**Naming conventions:** +- JS/TS functions: camelCase (`getUserData`, `calculateTotal`) +- JS/TS classes: PascalCase (`UserService`, `DataController`) +- Constants: UPPER_SNAKE_CASE (`API_KEY`, `MAX_RETRIES`) +- Python functions/variables: camelCase (`getUserData`, `calculateTotal`) — project convention, PEP 8 not enforced +- Python classes: PascalCase (`UserService`, `DataController`) + +**Documentation style:** +- Write for the reader who has no context — assume nothing +- Use plain language; avoid jargon unless it's defined +- Every public function, class, and API endpoint must have a docstring or JSDoc comment +- Include a usage example wherever the behaviour isn't immediately obvious + +**Doc style examples:** + +```typescript +// ✅ Good +/** + * Fetches a user by their unique ID. + * @param id - The user's UUID + * @returns The matching User object + * @throws Error if ID is empty or user is not found + */ +async function fetchUserById(id: string): Promise { + if (!id) throw new Error('User ID required'); + + const response = await api.get(`/users/${id}`); + return response.data; +} +``` + +```python +# ✅ Good +def fetchUserById(userId: str) -> User: + """ + Fetches a user by their unique ID. + + Args: + userId: The user's UUID. + + Returns: + The matching User object. + + Raises: + ValueError: If userId is empty. + """ +``` + +## Boundaries +- ✅ **Always:** Write docs to the correct `docs/` folder, follow naming conventions, include usage examples for non-obvious behaviour +- ⚠️ **Ask first:** Changing doc structure or folder layout, adding doc generation dependencies, modifying existing public API descriptions +- 🚫 **Never:** Commit secrets or API keys, document unimplemented behaviour as if it exists \ No newline at end of file diff --git a/.github/agents/lint-agent.md b/.github/agents/lint-agent.md deleted file mode 100644 index e69de29..0000000 diff --git a/.github/agents/test-agent.md b/.github/agents/test-agent.md index e69de29..c61202f 100644 --- a/.github/agents/test-agent.md +++ b/.github/agents/test-agent.md @@ -0,0 +1,78 @@ +--- +name: Unit Test Agent +description: This agent helps maintain and create unit tests for both the frontend (React) and backend (Python) of the project. +--- + +You are an expert test engineer for this project. + +## Persona +- You specialize in creating and maintaining unit tests +- You understand the codebase and translate that into comprehensive, reliable tests +- Your output: unit tests that catch bugs early and are easy to maintain + +## Project Knowledge + +**Tech Stack:** +- **Frontend:** React 19.2.0 — see `project/frontend/package.json` and `project/Dockerfile-frontend` +- **Backend:** Python 3.11.10-slim — see `project/Dockerfile-backend` + +**File Structure:** +- `project/frontend` – React frontend source +- `project/frontend/tests` – place frontend tests here +- `project/backend` – Python backend source +- `project/backend/tests` – place backend tests here + +## Tools + +**Frontend (React):** +- Test: `npm test` (Jest) +- Run single test: `npm test -- --testPathPattern=` +- Watch mode: `npm test -- --watch` +- Coverage: `npm test -- --coverage` +- Lint: `npm run lint --fix` +- Build: `npm run build` + +**Backend (Python):** +- Test: `pytest project/backend/tests` +- Run single test: `pytest project/backend/tests/` +- Verbose: `pytest -v project/backend/tests` +- Coverage: `pytest --cov=project/backend project/backend/tests` +- Lint: `ruff check . --fix` +- Type check: `mypy project/backend` + +## Standards + +**Naming conventions:** +- JS/TS functions: camelCase (`getUserData`, `calculateTotal`) +- JS/TS classes: PascalCase (`UserService`, `DataController`) +- Constants: UPPER_SNAKE_CASE (`API_KEY`, `MAX_RETRIES`) +- Python functions/variables: camelCase (`getUserData`, `calculateTotal`) — project convention, PEP 8 not enforced +- Python classes: PascalCase (`UserService`, `DataController`) + +**Code style examples:** + +```typescript +// ✅ Good +async function fetchUserById(id: string): Promise { + if (!id) throw new Error('User ID required'); + const response = await api.get(`/users/${id}`); + return response.data; +} +``` + +```python +# ✅ Good +def test_fetch_user_by_id_returns_user(): + user = fetch_user_by_id("abc123") + assert user.id == "abc123" + +# ✅ Good — test invalid input +def test_fetch_user_by_id_raises_on_empty(): + with pytest.raises(ValueError): + fetch_user_by_id("") +``` + +## Boundaries +- ✅ **Always:** Write tests to the correct `tests/` folder, run tests before commits, follow naming conventions +- ⚠️ **Ask first:** Database schema changes, adding dependencies, modifying CI/CD config +- 🚫 **Never:** Commit secrets or API keys, edit `node_modules/` or `vendor/` \ No newline at end of file From 97103930c49efb5553226c9cb1040943bc4bd844 Mon Sep 17 00:00:00 2001 From: nicla Date: Tue, 28 Apr 2026 16:57:41 +0200 Subject: [PATCH 09/11] =?UTF-8?q?Passwort=20und=20Email=20=C3=84nderung=20?= =?UTF-8?q?zu=20Popups=20ge=C3=A4ndert.=20und=20neugeordnet=20untereinande?= =?UTF-8?q?r?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- project/backend/EmailService.py | 10 +- project/backend/Routes.py | 24 ++--- project/frontend/app/profile/page.tsx | 126 +++++++++++++++----------- 3 files changed, 92 insertions(+), 68 deletions(-) diff --git a/project/backend/EmailService.py b/project/backend/EmailService.py index 912c79b..caa8a0f 100644 --- a/project/backend/EmailService.py +++ b/project/backend/EmailService.py @@ -3,14 +3,14 @@ from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart -GMAIL_USER = os.environ.get("GMAIL_USER") -GMAIL_PASSWORD = os.environ.get("GMAIL_PASSWORD") +gmailUser = os.environ.get("GMAIL_USER") +gmailPassword = os.environ.get("GMAIL_PASSWORD") def sendPasswordChangedEmail(to_email: str, name: str) -> None: try: msg = MIMEMultipart("alternative") msg["Subject"] = "Dein Passwort wurde geändert" - msg["From"] = GMAIL_USER + msg["From"] = gmailUser msg["To"] = to_email html = f""" @@ -25,8 +25,8 @@ def sendPasswordChangedEmail(to_email: str, name: str) -> None: msg.attach(MIMEText(html, "html")) with smtplib.SMTP_SSL("smtp.gmail.com", 465) as server: - server.login(GMAIL_USER, GMAIL_PASSWORD) - server.sendmail(GMAIL_USER, to_email, msg.as_string()) + server.login(gmailUser, gmailPassword) + server.sendmail(gmailUser, to_email, msg.as_string()) except Exception as e: print(f"E-Mail Fehler: {e}") diff --git a/project/backend/Routes.py b/project/backend/Routes.py index d312329..ac10775 100644 --- a/project/backend/Routes.py +++ b/project/backend/Routes.py @@ -117,15 +117,15 @@ class UpdateUser(_BaseModel): @router.patch("/users/me") async def updateCurrentUser( data: UpdateUser, - current_user: Annotated[User, Depends(getCurrentUser)] + currentUser: Annotated[User, Depends(getCurrentUser)] ): - Account = getAccountByEmail(current_user.email) + Account = getAccountByEmail(currentUser.email) # E-Mail ändern if data.email: - fehler = validateEmail(data.email) - if fehler: - raise HTTPException(status_code=400, detail=fehler) + error = validateEmail(data.email) + if error: + raise HTTPException(status_code=400, detail=error) updateAccount(Account["id"], email=data.email) # Passwort ändern @@ -133,17 +133,17 @@ async def updateCurrentUser( if not verifyPassword(data.currentPassword, Account["hashedPassword"]): raise HTTPException(status_code=401, detail="Falsches Passwort") - fehler = validatePassword(data.newPassword) - if fehler: - raise HTTPException(status_code=400, detail=fehler) + error = validatePassword(data.newPassword) + if error: + raise HTTPException(status_code=400, detail=error) - neuer_hash = hashPassword(data.newPassword) - updateAccount(Account["id"], password_hash=neuer_hash) + newHash = hashPassword(data.newPassword) + updateAccount(Account["id"], password_hash=newHash) # NEU: try/catch um echten Fehler zu sehen - empfaenger_email = data.email if data.email else Account["email"] + RecieverEmail = data.email if data.email else Account["email"] try: - sendPasswordChangedEmail(empfaenger_email, Account["name"]) + sendPasswordChangedEmail(RecieverEmail, Account["name"]) except Exception as e: print(f"E-Mail konnte nicht gesendet werden: {e}") diff --git a/project/frontend/app/profile/page.tsx b/project/frontend/app/profile/page.tsx index 46e9882..df2c2ea 100644 --- a/project/frontend/app/profile/page.tsx +++ b/project/frontend/app/profile/page.tsx @@ -13,6 +13,9 @@ export default function Profile() { const router = useRouter(); const [showConfirm, setShowConfirm] = useState(false); + const [showEmailModal, setShowEmailModal] = useState(false); + const [showPasswordModal, setShowPasswordModal] = useState(false); + // E-Mail ändern const [newEmail, setNewEmail] = useState(""); const [emailMsg, setEmailMsg] = useState(""); @@ -94,88 +97,109 @@ export default function Profile() { {/* Inhalt */} -
+
{/* Profil-Anzeige */} -
+

Profil

E-Mail: {user.email}

Name: {user.name}

- {/* E-Mail ändern */} -
-

E-Mail ändern

- setNewEmail(e.target.value)} - className="border rounded-lg px-3 py-2 text-sm w-full" - /> + {/* Buttons */} +
+

Einstellungen

- {emailMsg &&

{emailMsg}

} -
- - {/* Passwort ändern */} -
-

Passwort ändern

- setCurrentPassword(e.target.value)} - className="border rounded-lg px-3 py-2 text-sm w-full" - /> - setNewPassword(e.target.value)} - className="border rounded-lg px-3 py-2 text-sm w-full" - /> - {passwordMsg &&

{passwordMsg}

}
- {/* Bestätigungs-Modal */} - {showConfirm && ( + {/* E-Mail Modal */} + {showEmailModal && ( +
setShowEmailModal(false)} + > +
e.stopPropagation()} + > +

E-Mail ändern

+ setNewEmail(e.target.value)} + className="border rounded-lg px-3 py-2 text-sm w-full" + /> + {emailMsg &&

{emailMsg}

} +
+ + +
+
+
+ )} + + {/* Passwort Modal */} + {showPasswordModal && (
setShowConfirm(false)} + onClick={() => setShowPasswordModal(false)} >
e.stopPropagation()} > -

Konto löschen

-

- Möchtest du dein Konto wirklich löschen? Diese Aktion kann nicht rückgängig gemacht werden. -

-
+

Passwort ändern

+ setCurrentPassword(e.target.value)} + className="border rounded-lg px-3 py-2 text-sm w-full" + /> + setNewPassword(e.target.value)} + className="border rounded-lg px-3 py-2 text-sm w-full" + /> + {passwordMsg &&

{passwordMsg}

} +
From 3c9a943a1bf2aed42cd1f04c3141a9f5b01a223e Mon Sep 17 00:00:00 2001 From: GalacticCodeGambit <150372421+GalacticCodeGambit@users.noreply.github.com> Date: Thu, 30 Apr 2026 10:01:26 +0200 Subject: [PATCH 10/11] Update README.md to mark tasks as completed for account management features --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 978af29..65a05fa 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ LazyCook soll eine Webanwendung sein. Die es ermöglichen seine vorhanden Zutate - [ ] KI-basierte Rezeptvorschläge Einbindung - [ ] [#33](https://github.com/GalacticCodeGambit/LazyCook/issues/33) Alle gespeicherten Zutaten aus der Datenbank, sollen auf einer Seite angezeigt werden und Suchbar sein z.B. nach Gerichtname "Pizza". - [ ] Auf der Zutaten-Seite, werden grundlegende Zutaten wie z.B. Tomaten, Mehl, Salz und Milch automatisch vorgeschlagen. Diese sollen hinzufügbar oder ignorierbar sein. -- [ ] [#46](https://github.com/GalacticCodeGambit/LazyCook/issues/46) Konto löschen/bearbeiten können +- [x] [#46](https://github.com/GalacticCodeGambit/LazyCook/issues/46) Konto löschen/bearbeiten können - [ ] Fehlende Zutaten werden von einem Rezept in einer Einkaufliste aufgelistet - [ ] Der Nutzer kann Rezepte in die Datenbank hinzufügen/erstellen - [x] [#47](https://github.com/GalacticCodeGambit/LazyCook/issues/47) Der Nutzer kann bereits hinzugefügte Zutaten bearbeiten, wie z.B. Menge, Einheit From 84ee0e920b2c97d9a35187281a94881a15a1c6c5 Mon Sep 17 00:00:00 2001 From: Eden Tabea Bernhard <105359952+EdenBernhard@users.noreply.github.com> Date: Mon, 4 May 2026 10:38:18 +0200 Subject: [PATCH 11/11] Feat/improve profile design (#135) * Feature: Profile drop down as component and shown in profile * Feature: Profile drop down as component and shown in profile --- project/backend/Auth.py | 21 +------ project/backend/Routes.py | 7 +-- project/data/LazyCookDB.sqlite3 | Bin 0 -> 65536 bytes .../app/components/profile_dropdown.tsx | 59 ++++++++++++++++++ project/frontend/app/profile/page.tsx | 25 +++++--- project/frontend/app/recipeFinder/page.tsx | 47 ++------------ 6 files changed, 81 insertions(+), 78 deletions(-) create mode 100644 project/data/LazyCookDB.sqlite3 create mode 100644 project/frontend/app/components/profile_dropdown.tsx diff --git a/project/backend/Auth.py b/project/backend/Auth.py index 4a61551..41283b0 100644 --- a/project/backend/Auth.py +++ b/project/backend/Auth.py @@ -1,5 +1,5 @@ """ -auth.py – Authentifizierungslogik (JWT, Passwort-Hashing, Refresh Tokens, Dependencies) +Auth.py – Authentifizierungslogik (JWT, Passwort-Hashing, Refresh Tokens, Dependencies) """ import re @@ -23,26 +23,7 @@ ACCESS_TOKEN_EXPIRE_MINUTES = 10 # kurze Laufzeit für Access Token refreshToken_EXPIRE_DAYS = 7 # lange Laufzeit für Refresh Token -# ── Modelle ──────────────────────────────────────────────────── -class Token(BaseModel): - access_token: str - refresh_token: str - token_type: str -class User(BaseModel): - email: str - name: str - -class UserCreate(BaseModel): - email: str - name: str - password: str - -class RefreshRequest(BaseModel): - refresh_token: str - -class LogoutRequest(BaseModel): - refresh_token: str # ── Passwort-Hashing ────────────────────────────────────────── def hashPassword(password: str) -> str: diff --git a/project/backend/Routes.py b/project/backend/Routes.py index ac10775..0289641 100644 --- a/project/backend/Routes.py +++ b/project/backend/Routes.py @@ -6,11 +6,6 @@ from Auth import ( - Token, - User, - UserCreate, - RefreshRequest, - LogoutRequest, createTokenPair, getCurrentUser, hashPassword, @@ -29,7 +24,7 @@ updateAccount, ) -from Models import User, Token, UserCreate +from Models import User, Token, UserCreate, RefreshRequest, LogoutRequest router = APIRouter() diff --git a/project/data/LazyCookDB.sqlite3 b/project/data/LazyCookDB.sqlite3 new file mode 100644 index 0000000000000000000000000000000000000000..8f8acc3ee212d9a9495fca4da0907069ff828483 GIT binary patch literal 65536 zcmeI)&2Qr99S3m83rsRYNDdX6PSx>fW~8JUsBK~lxpWMe_uybm2=qXCG2n#vcaXMH zI=kCy)mG}c=l%oz6DswvhgA>N9@=A1z4TU9J+x8{gap#i>^4MVcD_gigNMgIe}2E` z!PpNIjf9kzOysMLa=JxWHQO4kR`Zr1G#bs0df!&>lbc>$SeraiAGK4<^A>kBmaNub z{HMmK&1tqw#?KAE-~657=NsSK{DuBskN&OO)c;}i*Xw`O=2naInt1Iea=*_DIqf6vDi6+f>gajuD&;BaYH|Bx=84|)@}>4?)TnIup3-bJQ~5@;|zM=QNLaomfhPt;ih2gIh)L0c+ZFiXpP7U*}QezA{ zlmF$sQkyD~6gBl^>z#8`Z+iMv`)O)aZsU$I{`+{Q$R=H8Zn57zW=$2rv8d)uOpH1{ z7n1~kSl!qWAC~5K=)2pmq{}iP@uw1T*-;lU@O7r5UPOB{<)=12Q+`~#RjfAVl-^wV zz5T~J(+{4`%l$ZWDQf)qA7y;J$?@NfnT$_@nY-P)Got>BDZU3uy1I$E zdA~LCz5R{m~h++V$)A8H*oSZLZioy5D#> zmip@F>Io;he4MyzC9enMTXQk2pgpTzXY#(7SH0JsDe8Lp(I?(Dz3KI9?PueoD^boj z ze-2dVmp{9%GX-DIEC1<|9S-5wWv)A3)tUD9wTaQdba`;ulUXa3o_R%Q;-1Ybp35YuA7z{}fB*y_009U<00Izz00cfjf!c~*asvU?YYG2}yBQDCByBU32WFZjDEjb#KD1IbtzN@CRkv7CvZZv>qF$39oXc;! za>kOACArxmJeOOvSnE!qUMqNA7EhgTcYFs~vMtoyX92IfLmsz_eP^}7Q39=`1zR~b z2*%I6(W@;U5EOYxI}Q)*n`&NHj9+MsUl{-T0j3zc3;_s000Izz00bZa0SG_<0uXrr z1iroM(B6KoV#Tz|Y}|HI!C?Hm`u+b)jqyw4U*5kRM#K<+00bZa0SG_<0uX=z1Rwx` z4_M%_cJ-Nd@?(wdmDShU>7R=Xf5-o1qBETTuYddxjj_D-=Pi%nw}$UN`AmI^8w4N# z0SG_<0uX=z1R(H@5xCgV>owX7$B}iV8!>ZozCgLXX1-jgDm`yIZ*zuXmGgA;EMA}k z_E;n1J&E?ig{~{ujVj_ny&ZEO54=b2UcOHzs>M#U+DW*XXgUz~QGy`L?ZSAbF{4gz zmMH5X6{Fkdk3uG?pf1PrfOxQWZEyX zwMeGn4<*{k)KRV%q`Qeu?$qq5c*Q);M~-TaQofuLj_a=Ed9sksHcGU!7w@?fiqHrv z%|3S{Cid`vu`qUqu~WCkG+ckNvp$Kbl$WE?)AOP)Cb>=$R4c(ApM=ArP*3F?y}Z+U zYz_n*tY^SbzCqD^%1Cap8jy>rPFkcZa;6$Q9SG5UxZ(^s2b`?Ly9eH;c*BWg4oTKx zvyoQXaa&BI^%py9lb9H(+RBk$b2*(WWzRx2m(&kdyh1R+x0rO(9JC9CQcf&(Yra~C z7Ui?EQXn5Z8gzngGn-PX1G?%DIGb)Rau&6@QxPs)76#@SC;E_4r>5I16lJGu%zwvp zx&C5jbrMr|U}MQj)*P*!7NQ{~$(TE|Gn+i2!|rIEVFyy8WVZ>fu%ABb7fupgccMur zLVSR6^~(oT-Q5WWA|9_Cjq{$a=iHvn4+f>ujMI3oJZ+&F)P4~Io z$=i8*JRgx2?#yZPdHcQ?7hr8+-*rfoq)w){QbQ)vMzZ#sA&n;6kJevotMmIuA@%ct zdOH~k_{~BgVzskfGCu zfB*y_009U<00Izz00bZafdvcT`u~DK(HsOI009U<00Izz00bZa0SG`~2?hQG0wt;; literal 0 HcmV?d00001 diff --git a/project/frontend/app/components/profile_dropdown.tsx b/project/frontend/app/components/profile_dropdown.tsx new file mode 100644 index 0000000..503d7ed --- /dev/null +++ b/project/frontend/app/components/profile_dropdown.tsx @@ -0,0 +1,59 @@ +import {useEffect, useRef, useState} from "react"; +import { useRouter } from "next/navigation"; +import {useAuth} from "@/lib/auth"; +import {LogOut, User, UserCircle} from "lucide-react"; + +export default function ProfileDropdown() { + const menuRef = useRef(null); + const { user, loading, logout } = useAuth(); + const router = useRouter(); + const [open, setOpen] = useState(false); + + + const handleLogout = () => { + logout(); + router.replace("/"); + } + const handleProfil = () => { + setOpen(false); + console.log("Profil ansehen"); + router.push("/profile"); + }; + + + return ( +
+
+ + + {open && ( +
+ + +
+ )} +
+
+ ); +} \ No newline at end of file diff --git a/project/frontend/app/profile/page.tsx b/project/frontend/app/profile/page.tsx index df2c2ea..1f5a269 100644 --- a/project/frontend/app/profile/page.tsx +++ b/project/frontend/app/profile/page.tsx @@ -1,14 +1,17 @@ "use client"; -import { useState } from "react"; +import { useRef, useState} from "react"; import { useAuth, fetchWithAuth } from "@/lib/auth"; import { useRouter } from "next/navigation"; -import { ChefHat } from "lucide-react"; +import {ChefHat} from "lucide-react"; import { Button } from '../components/ui/button'; +import ProfileDropdown from "@/app/components/profile_dropdown"; const API_URL = process.env.NEXT_PUBLIC_API_URL ?? "http://localhost:3000"; export default function Profile() { + + const menuRef = useRef(null); const { user, logout } = useAuth(); const router = useRouter(); const [showConfirm, setShowConfirm] = useState(false); @@ -87,13 +90,11 @@ export default function Profile() { - -
+ + + + +
{/* Inhalt */} @@ -122,6 +123,12 @@ export default function Profile() { Passwort ändern
+
diff --git a/project/frontend/app/recipeFinder/page.tsx b/project/frontend/app/recipeFinder/page.tsx index af0ec13..a0a276b 100644 --- a/project/frontend/app/recipeFinder/page.tsx +++ b/project/frontend/app/recipeFinder/page.tsx @@ -8,6 +8,7 @@ import "./style.css" import {Button} from "@/app/components/ui/button"; import Modal from "@/app/components/modal"; import AddIngredientsPopup from "@/app/recipeFinder/popup"; +import ProfileDropdown from "@/app/components/profile_dropdown"; const EINHEITEN = ["Stück", "g", "kg", "ml", "l", "EL", "TL", "Prise"]; @@ -76,16 +77,6 @@ export default function RecipeFinder() { if (!user) return null; - const handleLogout = () => { - logout(); - router.replace("/"); - } - const handleProfil = () => { - setOpen(false); - console.log("Profil ansehen"); - router.push("/profile"); - }; - const handleAdd = (ingredient: IngredientInput) => { setIngredients(prev => [...prev, ingredient]); }; @@ -145,39 +136,9 @@ export default function RecipeFinder() { Favoriten -
-
- - - {open && ( -
- - -
- )} -
-
+ + +