Snap Beginn/Ende to next 15-minute boundary on change and on load
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -19,10 +19,24 @@ function toLocalDatetimeValue(isoOrDatetime: string): string {
|
||||
return isoOrDatetime.slice(0, 16);
|
||||
}
|
||||
|
||||
function snapTo15(value: string): string {
|
||||
if (!value) return value;
|
||||
const d = new Date(value);
|
||||
if (isNaN(d.getTime())) return value;
|
||||
const rem = d.getMinutes() % 15;
|
||||
if (rem !== 0) {
|
||||
d.setMinutes(d.getMinutes() + (15 - rem));
|
||||
d.setSeconds(0);
|
||||
}
|
||||
const pad = (n: number) => String(n).padStart(2, '0');
|
||||
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;
|
||||
}
|
||||
|
||||
function nowLocalDatetime(): string {
|
||||
const now = new Date();
|
||||
const pad = (n: number) => String(n).padStart(2, '0');
|
||||
return `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}T${pad(now.getHours())}:${pad(now.getMinutes())}`;
|
||||
const raw = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}T${pad(now.getHours())}:${pad(now.getMinutes())}`;
|
||||
return snapTo15(raw);
|
||||
}
|
||||
|
||||
const NO_OBJEKTE_ARTEN: ArtFuehrung[] = ['BEO-Sitzung', 'Technischer Dienst'];
|
||||
@@ -160,7 +174,7 @@ export default function LogbuchForm({ kuppel, currentUserBeo, editEntry, onSaved
|
||||
const labelCls = 'block text-sm font-medium text-gray-700 mb-0.5';
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit} className="space-y-3 max-w-2xl">
|
||||
<form onSubmit={handleSubmit} className="space-y-3 max-w-2xl mx-auto border-2 border-gray-400 rounded-xl p-4 bg-white">
|
||||
|
||||
{/* Art der Führung — volle Breite */}
|
||||
<div>
|
||||
@@ -179,8 +193,9 @@ export default function LogbuchForm({ kuppel, currentUserBeo, editEntry, onSaved
|
||||
<input
|
||||
type="datetime-local"
|
||||
value={beginn}
|
||||
onChange={(e) => setBeginn(e.target.value)}
|
||||
onChange={(e) => setBeginn(snapTo15(e.target.value))}
|
||||
required
|
||||
step={900}
|
||||
className="w-full px-2 py-2 border-2 border-gray-400 rounded-lg bg-white text-sm focus:border-blue-500 focus:outline-none"
|
||||
/>
|
||||
</div>
|
||||
@@ -189,8 +204,9 @@ export default function LogbuchForm({ kuppel, currentUserBeo, editEntry, onSaved
|
||||
<input
|
||||
type="datetime-local"
|
||||
value={ende}
|
||||
onChange={(e) => setEnde(e.target.value)}
|
||||
onChange={(e) => setEnde(snapTo15(e.target.value))}
|
||||
required
|
||||
step={900}
|
||||
className="w-full px-2 py-2 border-2 border-gray-400 rounded-lg bg-white text-sm focus:border-blue-500 focus:outline-none"
|
||||
/>
|
||||
</div>
|
||||
@@ -270,8 +286,8 @@ export default function LogbuchForm({ kuppel, currentUserBeo, editEntry, onSaved
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Buttons — volle Breite auf Mobile */}
|
||||
<div className="flex flex-col sm:flex-row gap-3">
|
||||
{/* Buttons — zentriert */}
|
||||
<div className="flex flex-col sm:flex-row gap-3 justify-center">
|
||||
<button
|
||||
type="submit"
|
||||
disabled={saving}
|
||||
|
||||
Reference in New Issue
Block a user