Formular und Liste responsiv gestaltet
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+120
-118
@@ -204,131 +204,133 @@ export default function AusgabenForm({ onSuccess, selectedEntry, typ }: Ausgaben
|
||||
setEditId(null);
|
||||
};
|
||||
|
||||
const fieldInputClass = "w-full min-w-0 px-2 py-1 text-sm rounded border-2 border-gray-400 bg-white focus:border-blue-500 focus:outline-none";
|
||||
|
||||
return (
|
||||
<div className="bg-[#CCCCFF] border border-black p-6 rounded-lg mb-6">
|
||||
<div className="bg-[#CCCCFF] border border-black p-3 sm:p-6 rounded-lg mb-6">
|
||||
{editId && (
|
||||
<div className="mb-4 p-3 bg-blue-100 border border-blue-400 rounded text-sm text-blue-800">
|
||||
ℹ️ <strong>Bearbeitungsmodus:</strong> Sie bearbeiten einen bestehenden Eintrag.
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
<form onSubmit={handleSubmit}>
|
||||
<table className="w-full text-center">
|
||||
<thead>
|
||||
<tr >
|
||||
<th className="p-2 w-32">Datum</th>
|
||||
<th className="p-2">Wo</th>
|
||||
<th className="p-2">Was</th>
|
||||
<th className="p-2 w-12">Kat.</th>
|
||||
<th className="p-2 w-24">Wieviel</th>
|
||||
<th className="p-2 w-4"></th>
|
||||
<th className="p-2 w-38 text-left">Wie</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="p-2 w-32">
|
||||
<input
|
||||
type="date"
|
||||
value={formData.Datum}
|
||||
onChange={(e) => handleDateChange(e.target.value)}
|
||||
className="w-full px-2 py-1 text-base rounded border-2 border-gray-400 bg-white focus:border-blue-500 focus:outline-none"
|
||||
required
|
||||
/>
|
||||
</td>
|
||||
<td className="p-2">
|
||||
<input
|
||||
type="text"
|
||||
value={formData.Wo}
|
||||
onChange={(e) => setFormData({ ...formData, Wo: e.target.value })}
|
||||
className="w-full px-2 py-1 text-base rounded border-2 border-gray-400 bg-white focus:border-blue-500 focus:outline-none"
|
||||
placeholder="Geschäft/Ort"
|
||||
list="wo-suggestions"
|
||||
required
|
||||
/>
|
||||
<datalist id="wo-suggestions">
|
||||
{autoCompleteWo.map((wo, index) => (
|
||||
<option key={index} value={wo} />
|
||||
{/* Wo/Was sind auf Mobil/Tablet volle Breite (mehr Platz zum Tippen), am Desktop feste Spaltenbreiten wie zuvor im Tabellen-Layout. */}
|
||||
<div className="grid grid-cols-2 sm:grid-cols-4 md:grid-cols-[110px_1fr_1fr_70px_100px_140px] gap-3 sm:gap-2">
|
||||
<div className="flex flex-col gap-1">
|
||||
<label className="text-xs font-medium text-center">Datum</label>
|
||||
<input
|
||||
type="date"
|
||||
value={formData.Datum}
|
||||
onChange={(e) => handleDateChange(e.target.value)}
|
||||
className={fieldInputClass}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-1 col-span-2 sm:col-span-2 md:col-span-1">
|
||||
<label className="text-xs font-medium text-center">Wo</label>
|
||||
<input
|
||||
type="text"
|
||||
value={formData.Wo}
|
||||
onChange={(e) => setFormData({ ...formData, Wo: e.target.value })}
|
||||
className={fieldInputClass}
|
||||
placeholder="Geschäft/Ort"
|
||||
list="wo-suggestions"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-1 col-span-2 sm:col-span-2 md:col-span-1">
|
||||
<label className="text-xs font-medium text-center">Was</label>
|
||||
<input
|
||||
type="text"
|
||||
value={formData.Was}
|
||||
onChange={(e) => setFormData({ ...formData, Was: e.target.value })}
|
||||
className={fieldInputClass}
|
||||
placeholder="Beschreibung"
|
||||
list="was-suggestions"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-1">
|
||||
<label className="text-xs font-medium text-center">Kat.</label>
|
||||
<div ref={katDropdownRef} className="relative w-full">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setKatDropdownOpen((o) => !o)}
|
||||
className={`${fieldInputClass} text-left`}
|
||||
>
|
||||
{formData.Kat}
|
||||
</button>
|
||||
{katDropdownOpen && (
|
||||
<ul className="absolute z-50 left-0 mt-1 w-48 max-w-[calc(100vw-2rem)] bg-white border-2 border-gray-400 rounded shadow-lg max-h-60 overflow-y-auto text-left">
|
||||
{categories.map((cat) => (
|
||||
<li
|
||||
key={cat.value}
|
||||
className={`px-3 py-1 cursor-pointer hover:bg-blue-100 text-sm ${
|
||||
formData.Kat === cat.value ? 'bg-blue-50 font-semibold' : ''
|
||||
}`}
|
||||
onMouseDown={() => {
|
||||
setFormData({ ...formData, Kat: cat.value });
|
||||
setKatDropdownOpen(false);
|
||||
}}
|
||||
>
|
||||
{cat.value} - {cat.label}
|
||||
</li>
|
||||
))}
|
||||
</datalist>
|
||||
</td>
|
||||
<td className="p-2">
|
||||
<input
|
||||
type="text"
|
||||
value={formData.Was}
|
||||
onChange={(e) => setFormData({ ...formData, Was: e.target.value })}
|
||||
className="w-full px-2 py-1 text-base rounded border-2 border-gray-400 bg-white focus:border-blue-500 focus:outline-none"
|
||||
placeholder="Beschreibung"
|
||||
list="was-suggestions"
|
||||
required
|
||||
/>
|
||||
<datalist id="was-suggestions">
|
||||
{autoCompleteWas.map((was, index) => (
|
||||
<option key={index} value={was} />
|
||||
))}
|
||||
</datalist>
|
||||
</td>
|
||||
<td className="p-2 w-12">
|
||||
<div ref={katDropdownRef} className="relative w-full">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setKatDropdownOpen((o) => !o)}
|
||||
className="w-full px-2 py-1 text-base text-left rounded border-2 border-gray-400 bg-white focus:border-blue-500 focus:outline-none"
|
||||
>
|
||||
{formData.Kat}
|
||||
</button>
|
||||
{katDropdownOpen && (
|
||||
<ul className="absolute z-50 left-0 mt-1 w-48 bg-white border-2 border-gray-400 rounded shadow-lg max-h-60 overflow-y-auto text-left">
|
||||
{categories.map((cat) => (
|
||||
<li
|
||||
key={cat.value}
|
||||
className={`px-3 py-1 cursor-pointer hover:bg-blue-100 text-sm ${
|
||||
formData.Kat === cat.value ? 'bg-blue-50 font-semibold' : ''
|
||||
}`}
|
||||
onMouseDown={() => {
|
||||
setFormData({ ...formData, Kat: cat.value });
|
||||
setKatDropdownOpen(false);
|
||||
}}
|
||||
>
|
||||
{cat.value} - {cat.label}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
</td>
|
||||
<td className="p-2 w-24">
|
||||
<input
|
||||
type="text"
|
||||
inputMode="decimal"
|
||||
value={formData.Wieviel}
|
||||
onChange={(e) => {
|
||||
const val = e.target.value.replace(/[^0-9.,]/g, '').replace(',', '.');
|
||||
setFormData({ ...formData, Wieviel: val });
|
||||
}}
|
||||
className="w-full px-2 py-1 text-base rounded border-2 border-gray-400 bg-white focus:border-blue-500 focus:outline-none"
|
||||
placeholder="0.00"
|
||||
required
|
||||
/>
|
||||
</td>
|
||||
<td className="p-2 w-4 text-left">€</td>
|
||||
<td className="p-2 w-38">
|
||||
<select
|
||||
value={formData.Wie}
|
||||
onChange={(e) => setFormData({ ...formData, Wie: e.target.value })}
|
||||
className="w-full px-2 py-1 text-base rounded border-2 border-gray-400 bg-white focus:border-blue-500 focus:outline-none"
|
||||
required
|
||||
>
|
||||
{zahlungsarten.map((za) => (
|
||||
<option key={za.value} value={za.value}>
|
||||
{za.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-1">
|
||||
<label className="text-xs font-medium text-center">
|
||||
Wieviel
|
||||
<span className="text-[10px] font-normal"> (€)</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
inputMode="decimal"
|
||||
value={formData.Wieviel}
|
||||
onChange={(e) => {
|
||||
const val = e.target.value.replace(/[^0-9.,]/g, '').replace(',', '.');
|
||||
setFormData({ ...formData, Wieviel: val });
|
||||
}}
|
||||
className={fieldInputClass}
|
||||
placeholder="0.00"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-1 col-span-2 sm:col-span-2 md:col-span-1">
|
||||
<label className="text-xs font-medium text-center">Wie</label>
|
||||
<select
|
||||
value={formData.Wie}
|
||||
onChange={(e) => setFormData({ ...formData, Wie: e.target.value })}
|
||||
className={fieldInputClass}
|
||||
required
|
||||
>
|
||||
{zahlungsarten.map((za) => (
|
||||
<option key={za.value} value={za.value}>
|
||||
{za.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<datalist id="wo-suggestions">
|
||||
{autoCompleteWo.map((wo, index) => (
|
||||
<option key={index} value={wo} />
|
||||
))}
|
||||
</datalist>
|
||||
<datalist id="was-suggestions">
|
||||
{autoCompleteWas.map((was, index) => (
|
||||
<option key={index} value={was} />
|
||||
))}
|
||||
</datalist>
|
||||
|
||||
{/* Wochentag */}
|
||||
<div className="mt-3 text-left pl-3">
|
||||
@@ -336,7 +338,7 @@ export default function AusgabenForm({ onSuccess, selectedEntry, typ }: Ausgaben
|
||||
</div>
|
||||
|
||||
{/* Buttons */}
|
||||
<div className="mb-3 flex gap-10 justify-center">
|
||||
<div className="mb-3 flex gap-4 sm:gap-10 justify-center">
|
||||
<button
|
||||
type="submit"
|
||||
disabled={isSubmitting}
|
||||
|
||||
Reference in New Issue
Block a user