From c866c01dfecb9b5fc1c0a8c6211dfddd67c47cc9 Mon Sep 17 00:00:00 2001 From: araemer Date: Sat, 25 Oct 2025 08:00:59 +0200 Subject: [PATCH] Clean up css --- frontend/src/App.css | 83 ++++------- frontend/src/components/LoginPage.tsx | 133 +++++++++--------- .../basics/BasicButtonDefinitions.ts | 47 ++++--- frontend/src/components/basics/Button.tsx | 4 +- frontend/src/components/basics/ButtonLink.tsx | 56 ++++---- .../components/basics/NumberStepControl.tsx | 2 +- .../src/components/basics/PasswordField.tsx | 36 ++--- .../src/components/basics/SearchField.tsx | 63 +++++---- .../recipes/IngredientGroupListEditor.tsx | 3 +- .../recipes/IngredientListEditor.tsx | 4 +- .../InstructionStepDesktopListItem.tsx | 2 +- .../InstructionStepListDesktopEditor.tsx | 2 +- .../InstructionStepListMobileEditor.tsx | 2 +- .../recipes/InstructionStepMobileListItem.tsx | 2 +- .../components/recipes/RecipeDetailPage.tsx | 12 +- .../src/components/recipes/RecipeEditor.tsx | 11 +- .../src/components/recipes/RecipeListPage.tsx | 2 +- 17 files changed, 214 insertions(+), 250 deletions(-) diff --git a/frontend/src/App.css b/frontend/src/App.css index 8a48b11..2bddac5 100644 --- a/frontend/src/App.css +++ b/frontend/src/App.css @@ -4,6 +4,31 @@ @tailwind utilities; /* Custom recipe app styles */ +@layer preflight { + /* headlines */ + h1 { + @apply text-3xl font-black text-blue-900; + } + + h2 { + @apply text-xl font-bold mb-4 mt-4; + } + + h3 { + @apply font-semibold; + } + + /* labels */ + label { + @apply text-gray-600; + } + + /* input fields */ + input, textarea { + @apply p-2 w-full border rounded-md bg-white placeholder-gray-400 border-gray-600 hover:border-blue-800 transition-colors text-gray-600 focus:outline-none focus:border-blue-900; + } +} + @layer components { /* background */ @@ -24,17 +49,6 @@ @apply sticky bg-gray-100 top-0 left-0 right-0 pb-6 border-b-2 border-gray-300; } - .content-title { - @apply text-3xl font-black pb-6 text-blue-900; - } - - .section-heading { - @apply text-xl font-bold pb-4 pt-4; - } - - .subsection-heading { - @apply font-semibold pb-2 pt-4; - } /* icons */ .default-icon { @@ -42,58 +56,11 @@ } - /* labels */ - .label { - @apply text-gray-600; - } - /* errors */ .error-text { @apply text-sm text-red-600; } - /* buttons */ - .basic-button { - @apply px-4 py-2 shadow-md rounded-lg whitespace-nowrap disabled:opacity-50 disabled:cursor-not-allowed; - } - - .default-button-bg { - @apply bg-gray-300 hover:bg-gray-400; - } - - .default-button-text { - @apply text-gray-600; - } - - .primary-button-bg { - @apply bg-blue-300 hover:bg-blue-400; - } - - .primary-button-text { - @apply text-gray-600; - } - - .dark-button-bg { - @apply bg-gray-600 hover:bg-gray-800; - } - - .dark-button-text { - @apply text-white; - } - - .transparent-button-bg { - @apply bg-transparent hover:bg-transparent; - } - - .transparent-button-text { - @apply text-gray-600; - } - - /* input fields like input and textarea */ - .input-field { - @apply p-2 w-full border rounded-md bg-white placeholder-gray-400 border-gray-600 hover:border-blue-800 transition-colors text-gray-600 focus:outline-none focus:border-blue-900; - } - /* groups */ .button-group { @apply flex gap-4 mt-8; diff --git a/frontend/src/components/LoginPage.tsx b/frontend/src/components/LoginPage.tsx index ffd6c74..22b4d1f 100644 --- a/frontend/src/components/LoginPage.tsx +++ b/frontend/src/components/LoginPage.tsx @@ -1,81 +1,80 @@ -import { useState } from "react"; +import {useState} from "react"; import Button from "./basics/Button"; -import type { LoginRequestDto } from "../api/dtos/LoginRequestDto"; -import type { LoginResponseDto } from "../api/dtos/LoginResponseDto"; -import { login } from "../api/points/AuthPoint"; -import { getRecipeListUrl } from "../routes"; -import { useNavigate } from "react-router-dom"; +import type {LoginRequestDto} from "../api/dtos/LoginRequestDto"; +import type {LoginResponseDto} from "../api/dtos/LoginResponseDto"; +import {login} from "../api/points/AuthPoint"; +import {getRecipeListUrl} from "../routes"; +import {useNavigate} from "react-router-dom"; import PasswordField from "./basics/PasswordField"; -import { ButtonType } from "./basics/BasicButtonDefinitions"; +import {ButtonType} from "./basics/BasicButtonDefinitions"; export default function LoginPage() { - const [userName, setUserName] = useState(""); - const [password, setPassword] = useState(""); - const [errorMessage, setErrorMessage] = useState(null); + const [userName, setUserName] = useState(""); + const [password, setPassword] = useState(""); + const [errorMessage, setErrorMessage] = useState(null); - const navigate = useNavigate(); + const navigate = useNavigate(); - /** - * Login - */ - const executeLogin = async () => { - const dto: LoginRequestDto = { - userName, - password, + /** + * Login + */ + const executeLogin = async () => { + const dto: LoginRequestDto = { + userName, + password, + }; + + try { + console.log("Trying to log in with " + dto.userName); + const loginResponse: LoginResponseDto = await login(dto); + localStorage.setItem("session", JSON.stringify(loginResponse)); + console.log("Successfully logged in as " + loginResponse.userData?.userName); + setErrorMessage(null); + // navigate to recipe list after successful login + navigate(getRecipeListUrl()); + } catch (err: any) { + console.error("Login failed:", err); + setErrorMessage("Login fehlgeschlagen! Bitte überprüfe Benutzername und Passwort."); + } }; - try { - console.log("Trying to log in with " + dto.userName); - const loginResponse: LoginResponseDto = await login(dto); - localStorage.setItem("session", JSON.stringify(loginResponse)); - console.log("Successfully logged in as " + loginResponse.userData?.userName); - setErrorMessage(null); - // navigate to recipe list after successful login - navigate(getRecipeListUrl()); - } catch (err: any) { - console.error("Login failed:", err); - setErrorMessage("Login fehlgeschlagen! Bitte überprüfe Benutzername und Passwort."); - } - }; + /** + * Catch key events in order to trigger login on enter + */ + const handleKeyDown = (event: React.KeyboardEvent) => { + if (event.key === "Enter") { + executeLogin(); + } + }; - /** - * Catch key events in order to trigger login on enter - */ - const handleKeyDown = (event: React.KeyboardEvent) => { - if (event.key === "Enter") { - executeLogin(); - } - }; + return ( +
+
+

Anmeldung

- return ( -
-
-

Anmeldung

+ setUserName(e.target.value)} + onKeyDown={handleKeyDown} + /> - setUserName(e.target.value)} - onKeyDown={handleKeyDown} - /> + - + {/* error message */} + {errorMessage && ( +

{errorMessage}

+ )} - {/* error message */} - {errorMessage && ( -

{errorMessage}

- )} - -
-
- ); +
+
+ ); } diff --git a/frontend/src/components/basics/BasicButtonDefinitions.ts b/frontend/src/components/basics/BasicButtonDefinitions.ts index bccbb72..1c4a678 100644 --- a/frontend/src/components/basics/BasicButtonDefinitions.ts +++ b/frontend/src/components/basics/BasicButtonDefinitions.ts @@ -1,38 +1,39 @@ -import type { LucideIcon } from "lucide-react"; +import type {LucideIcon} from "lucide-react"; /** * Basic definitions used by all Button types, such as Button.tsx and ButtonLink.tsx */ export type BasicButtonProps = { - /** Optional Lucide icon (e.g. Plus, X, Check) */ - icon?: LucideIcon; - text?: string; - buttonType?: ButtonType; - /** Optional additional style */ - className?: string; + /** Optional Lucide icon (e.g. Plus, X, Check) */ + icon?: LucideIcon; + text?: string; + buttonType?: ButtonType; + /** Optional additional style */ + className?: string; } +export const basicButtonStyle = "px-4 py-2 shadow-md rounded-lg whitespace-nowrap disabled:opacity-50 disabled:cursor-not-allowed" /** * Define button types here. * Export as enum like class. */ export const ButtonType = { - DarkButton: { - textColor: "dark-button-text", - backgroundColor: "dark-button-bg", - }, - PrimaryButton: { - textColor: "primary-button-text", - backgroundColor: "primary-button-bg", - }, - DefaultButton: { - textColor: "default-button-text", - backgroundColor: "default-button-bg", - }, - TransparentButton: { - textColor: "transparent-button-text", - backgroundColor: "transparent-button-bg", - }, + DarkButton: { + textColor: "text-white", + backgroundColor: "bg-gray-600 hover:bg-gray-800", + }, + PrimaryButton: { + textColor: "text-gray-600", + backgroundColor: "bg-blue-300 hover:bg-blue-400", + }, + DefaultButton: { + textColor: "text-gray-600", + backgroundColor: "bg-gray-300 hover:bg-gray-400", + }, + TransparentButton: { + textColor: "text-gray-600", + backgroundColor: "bg-transparent hover:bg-transparent", + }, } as const; export type ButtonType = typeof ButtonType[keyof typeof ButtonType]; \ No newline at end of file diff --git a/frontend/src/components/basics/Button.tsx b/frontend/src/components/basics/Button.tsx index d6ee011..0ba947c 100644 --- a/frontend/src/components/basics/Button.tsx +++ b/frontend/src/components/basics/Button.tsx @@ -1,5 +1,5 @@ import {defaultIconSize} from "./SvgIcon"; -import {type BasicButtonProps, ButtonType} from "./BasicButtonDefinitions"; +import {type BasicButtonProps, basicButtonStyle, ButtonType} from "./BasicButtonDefinitions"; type ButtonProps = BasicButtonProps & { onClick: () => void; @@ -20,7 +20,7 @@ export default function Button({ }: ButtonProps) { return ( ); diff --git a/frontend/src/components/basics/SearchField.tsx b/frontend/src/components/basics/SearchField.tsx index d344d63..c7a5b6e 100644 --- a/frontend/src/components/basics/SearchField.tsx +++ b/frontend/src/components/basics/SearchField.tsx @@ -1,21 +1,22 @@ -import { useState } from "react"; -import { Search, X} from "lucide-react"; -import { defaultIconSize } from "./SvgIcon"; +import {useState} from "react"; +import {Search, X} from "lucide-react"; +import {defaultIconSize} from "./SvgIcon"; + /** * Custom search field component including a clear search functionality */ -type SearchFieldProps = { - onSearchStringChanged: (searchString : string) => void +type SearchFieldProps = { + onSearchStringChanged: (searchString: string) => void } /** * @param SearchFieldProps consisting of an initial searchString and an onSearchStringChanged handler * @returns Custom search field component */ -export default function SearchField({onSearchStringChanged} : SearchFieldProps){ +export default function SearchField({onSearchStringChanged}: SearchFieldProps) { const [currentSearchString, setCurrentSearchString] = useState("") - - const changeSearchString = (newSearchString : string) => { + + const changeSearchString = (newSearchString: string) => { console.log(newSearchString); setCurrentSearchString(newSearchString); onSearchStringChanged(newSearchString) @@ -23,34 +24,34 @@ export default function SearchField({onSearchStringChanged} : SearchFieldProps){ return (
- {/* Input of searchfield + {/* Input of searchfield Defines border and behavior. Requires extra padding at both sides to accommodate the icons */} - changeSearchString(e.target.value) } - /> - {/* Right icon: X + changeSearchString(e.target.value)} + /> + {/* Right icon: X Clears search string on click */} - - {/* Left icon: Looking glass */} -
- + + {/* Left icon: Looking glass */} +
+ +
-
) } diff --git a/frontend/src/components/recipes/IngredientGroupListEditor.tsx b/frontend/src/components/recipes/IngredientGroupListEditor.tsx index 21344f7..7f9196e 100644 --- a/frontend/src/components/recipes/IngredientGroupListEditor.tsx +++ b/frontend/src/components/recipes/IngredientGroupListEditor.tsx @@ -34,13 +34,12 @@ export function IngredientGroupListEditor({ingredientGroupList, onChange}: Ingre } return (
-

Zutaten

+

Zutaten

{ingredientGroupList.map((ingGrp, index) => (
handleUpdate(index, "title", e.target.value)} diff --git a/frontend/src/components/recipes/IngredientListEditor.tsx b/frontend/src/components/recipes/IngredientListEditor.tsx index e289099..b7f4df6 100644 --- a/frontend/src/components/recipes/IngredientListEditor.tsx +++ b/frontend/src/components/recipes/IngredientListEditor.tsx @@ -57,7 +57,6 @@ export function IngredientListEditor({ingredients, onChange}: IngredientListEdit
{ @@ -66,13 +65,12 @@ export function IngredientListEditor({ingredients, onChange}: IngredientListEdit }} /> handleUpdate(index, "unit", e.target.value)} /> handleUpdate(index, "name", e.target.value)} diff --git a/frontend/src/components/recipes/InstructionStepDesktopListItem.tsx b/frontend/src/components/recipes/InstructionStepDesktopListItem.tsx index aff0952..0f834b2 100644 --- a/frontend/src/components/recipes/InstructionStepDesktopListItem.tsx +++ b/frontend/src/components/recipes/InstructionStepDesktopListItem.tsx @@ -44,7 +44,7 @@ export function InstructionStepDesktopListItem({