feat: enhance MainForm layout and user experience; add new components and improve form structure

feat: update i18n configuration to prioritize browser language; enhance language detection
feat: add new translation keys for form submission feedback in English and German
This commit is contained in:
2026-01-20 19:07:03 +01:00
parent fd37e40253
commit c985a20207
5 changed files with 247 additions and 151 deletions

View File

@@ -1,6 +1,7 @@
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import "./index.css";
import "./utils/i18n";
import App from "./App.tsx";
createRoot(document.getElementById("root")!).render(

View File

@@ -7,6 +7,8 @@ import {
CircularProgress,
Autocomplete,
Chip,
Box,
Paper,
} from "@mui/material";
import { useTranslation } from "react-i18next";
import { useState, useEffect } from "react";
@@ -115,20 +117,28 @@ export const MainForm = () => {
};
return (
<>
<Chip label={`${t("next-id")}#${nextID ?? "N/A"}`} />
<Box className="min-h-screen bg-gray-800 flex items-center justify-center p-4">
<Paper
elevation={3}
className="w-full max-w-md p-6 rounded-lg"
sx={{ backgroundColor: "#fff" }}
>
<form
onSubmit={(e) => {
e.preventDefault();
handleSubmit();
}}
className="flex flex-col gap-4"
>
{/* User Selection */}
<Autocomplete
disablePortal
options={users}
value={selectedUser}
sx={{ width: 300 }}
renderInput={(params) => <TextField {...params} label={t("user")} />}
fullWidth
renderInput={(params) => (
<TextField {...params} label={t("user")} variant="filled" />
)}
onChange={(_event, value) => handleUserSelection(value)}
onKeyDown={(event) => {
if (event.key === "Enter") {
@@ -136,6 +146,22 @@ export const MainForm = () => {
}
}}
/>
{/* Next ID Chip */}
<Chip
label={`#${nextID ?? "N/A"}`}
color="primary"
sx={{
alignSelf: "flex-start",
fontWeight: "bold",
fontSize: "1rem",
py: 2,
px: 1,
}}
/>
{/* Name Fields - Two Columns */}
<Box className="grid grid-cols-2 gap-3">
<TextField
required
id="first-name"
@@ -144,6 +170,7 @@ export const MainForm = () => {
value={formData.firstName}
onChange={handleChange}
name="firstName"
fullWidth
/>
<TextField
required
@@ -153,7 +180,11 @@ export const MainForm = () => {
value={formData.lastName}
onChange={handleChange}
name="lastName"
fullWidth
/>
</Box>
{/* Email */}
<TextField
required
id="email"
@@ -163,7 +194,10 @@ export const MainForm = () => {
value={formData.email}
onChange={handleChange}
name="email"
fullWidth
/>
{/* Phone Number */}
<TextField
required
id="phone-number"
@@ -173,7 +207,11 @@ export const MainForm = () => {
value={formData.phoneNumber}
onChange={handleChange}
name="phoneNumber"
fullWidth
/>
{/* Tickets and Invoice Checkbox */}
<Box className="grid grid-cols-2 gap-3 items-center">
<TextField
required
id="tickets"
@@ -183,6 +221,8 @@ export const MainForm = () => {
value={formData.tickets}
onChange={handleChange}
name="tickets"
fullWidth
inputProps={{ min: 1 }}
/>
<FormControlLabel
control={
@@ -192,9 +232,13 @@ export const MainForm = () => {
/>
}
label={t("invoice")}
className="justify-end"
/>
</Box>
{/* Invoice Fields */}
{invoice && (
<>
<Box className="flex flex-col gap-3 pt-2 border-t border-gray-200">
<TextField
required
id="company-name"
@@ -203,7 +247,11 @@ export const MainForm = () => {
value={formData.companyName}
onChange={handleChange}
name="companyName"
fullWidth
/>
{/* Invoice Name Fields - Two Columns */}
<Box className="grid grid-cols-2 gap-3">
<TextField
required
id="first-name_invoice"
@@ -212,6 +260,7 @@ export const MainForm = () => {
value={formData.cmpFirstName}
onChange={handleChange}
name="cmpFirstName"
fullWidth
/>
<TextField
required
@@ -221,7 +270,10 @@ export const MainForm = () => {
value={formData.cpmLastName}
onChange={handleChange}
name="cpmLastName"
fullWidth
/>
</Box>
<TextField
required
id="street"
@@ -230,7 +282,9 @@ export const MainForm = () => {
value={formData.street}
onChange={handleChange}
name="street"
fullWidth
/>
<TextField
required
id="postal-code"
@@ -239,7 +293,9 @@ export const MainForm = () => {
value={formData.postalCode}
onChange={handleChange}
name="postalCode"
fullWidth
/>
<TextField
required
id="phone-number_invoice"
@@ -249,7 +305,9 @@ export const MainForm = () => {
value={formData.cpmPhoneNumber}
onChange={handleChange}
name="cpmPhoneNumber"
fullWidth
/>
<TextField
required
id="email_invoice"
@@ -259,24 +317,47 @@ export const MainForm = () => {
value={formData.cpmEmail}
onChange={handleChange}
name="cpmEmail"
fullWidth
/>
</>
</Box>
)}
{/* Payment methods - only one must be selected */}
{/* Payment Methods */}
<Box className="flex justify-center gap-4 pt-2">
<FormControlLabel control={<Checkbox />} label={t("cash")} />
<FormControlLabel control={<Checkbox />} label={t("paypal")} />
<FormControlLabel control={<Checkbox />} label={t("transfer")} />
{isLoading && <CircularProgress />}
<Button type="submit" variant="contained" disabled={isLoading}>
{t("submit")}
</Box>
{/* Submit Button */}
<Button
type="submit"
variant="contained"
disabled={isLoading}
fullWidth
size="large"
sx={{
mt: 2,
py: 1.5,
textTransform: "uppercase",
fontWeight: "bold",
}}
>
{isLoading ? (
<CircularProgress size={24} color="inherit" />
) : (
t("submit")
)}
</Button>
{/* Alert Message */}
{msg && (
<Alert severity={msg.type}>
<Alert severity={msg.type} sx={{ mt: 2 }}>
{msg.headline}: {msg.text}
</Alert>
)}
</form>
</>
</Paper>
</Box>
);
};

View File

@@ -22,7 +22,7 @@ i18n
.init({
resources,
fallbackLng: "en", // use en if detected lng is not available
lng: Cookies.get("language") || "en", // language to use, more information here: https://www.i18next.com/overview/configuration-options#languages-namespaces-resources
lng: Cookies.get("language") || navigator.language.split("-")[0] || "en", // Check cookie first, then browser language
// you can use the i18n.changeLanguage function to change the language manually: https://www.i18next.com/overview/api#changelanguage
// if you're using a language detector, do not define the lng option

View File

@@ -11,5 +11,12 @@
"submit": "Kaufen",
"failed-to-load-users": "Das Laden der Benutzer ist fehlgeschlagen.",
"user": "Benutzer",
"next-id": "Nächste Eintragsnummer: "
"next-id": "Nächste Eintragsnummer: ",
"form-submitted-successfully": "Formular erfolgreich übermittelt!",
"orm-submission-failed": "Formularübermittlung fehlgeschlagen.",
"success": "Erfolg",
"error": "Fehler",
"cash": "Bar",
"paypal": "PayPal",
"transfer": "Überweisung"
}

View File

@@ -11,5 +11,12 @@
"submit": "Buy",
"failed-to-load-users": "Failed to load users.",
"user": "User",
"next-id": "Next Entry Number: "
"next-id": "Next Entry Number: ",
"form-submitted-successfully": "Form submitted successfully!",
"orm-submission-failed": "Form submission failed.",
"success": "Success",
"error": "Error",
"cash": "Cash",
"paypal": "PayPal",
"transfer": "Bank Transfer"
}