From 431872716291d014d338fac77f2dc9c323c7624d Mon Sep 17 00:00:00 2001 From: Ricky Stretch Date: Sun, 29 Mar 2026 14:26:04 -0400 Subject: [PATCH] v012.42 updated --- backend/package.json | 2 +- build.sh | 2 +- frontend/package.json | 2 +- frontend/src/components/MobileEventForm.jsx | 39 ++++++++++++++++++--- frontend/src/components/SchedulePage.jsx | 1 + 5 files changed, 38 insertions(+), 8 deletions(-) diff --git a/backend/package.json b/backend/package.json index 11b8104..a8df2e7 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "rosterchirp-backend", - "version": "0.12.41", + "version": "0.12.42", "description": "RosterChirp backend server", "main": "src/index.js", "scripts": { diff --git a/build.sh b/build.sh index d814c17..16be5cd 100644 --- a/build.sh +++ b/build.sh @@ -13,7 +13,7 @@ # ───────────────────────────────────────────────────────────── set -euo pipefail -VERSION="${1:-0.12.41}" +VERSION="${1:-0.12.42}" ACTION="${2:-}" REGISTRY="${REGISTRY:-}" IMAGE_NAME="rosterchirp-dev" diff --git a/frontend/package.json b/frontend/package.json index e00ebb4..a517550 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "rosterchirp-frontend", - "version": "0.12.41", + "version": "0.12.42", "private": true, "scripts": { "dev": "vite", diff --git a/frontend/src/components/MobileEventForm.jsx b/frontend/src/components/MobileEventForm.jsx index 709ad2e..2c3c3ea 100644 --- a/frontend/src/components/MobileEventForm.jsx +++ b/frontend/src/components/MobileEventForm.jsx @@ -72,11 +72,32 @@ function fmt12(val) { function TimeInputMobile({ value, onChange }) { const [open, setOpen] = useState(false); const [inputVal, setInputVal] = useState(fmt12(value)); + const [keyboardOffset, setKeyboardOffset] = useState(0); const wrapRef = useRef(null); const listRef = useRef(null); useEffect(() => { setInputVal(fmt12(value)); }, [value]); + // Handle keyboard positioning with Visual Viewport API + useEffect(() => { + const handleViewportChange = () => { + if (window.visualViewport) { + const offset = window.innerHeight - window.visualViewport.height; + setKeyboardOffset(offset > 0 ? offset : 0); + } + }; + + if (open) { + handleViewportChange(); + window.visualViewport?.addEventListener('resize', handleViewportChange); + return () => { + window.visualViewport?.removeEventListener('resize', handleViewportChange); + }; + } else { + setKeyboardOffset(0); + } + }, [open]); + useEffect(() => { if (!open || !listRef.current) return; const idx = TIME_SLOTS.findIndex(s => s.value === value); @@ -108,16 +129,24 @@ function TimeInputMobile({ value, onChange }) { onKeyDown={e => { if (e.key === 'Enter') { e.preventDefault(); commit(inputVal); } if (e.key === 'Escape') { setInputVal(fmt12(value)); setOpen(false); } }} autoComplete="off" inputMode="text" + enterKeyHint="done" style={{ fontSize: 15, color: 'var(--primary)', fontWeight: 600, background: 'transparent', border: 'none', outline: 'none', cursor: 'text', width: 90 }} /> {open && (
0 ? keyboardOffset + 10 : 'auto', + top: keyboardOffset > 0 ? 'auto' : '100%', }} > {TIME_SLOTS.map(s => ( @@ -486,7 +515,7 @@ export default function MobileEventForm({ event, eventTypes, userGroups, selecte {/* form wrapper suppresses Chrome Android's autofill chip bar; autoComplete="new-password" on individual inputs is ignored by Chrome but respected on the form element */} -
e.preventDefault()} style={{ flex:1,overflowY:'auto', marginBottom:'50vh' }}> + e.preventDefault()} style={{ flex:1,overflowY:'auto' }}> {/* Title */}
setTitle(e.target.value)} autoComplete="new-password" placeholder="Add title" autoCorrect="off" autoCapitalize="sentences" spellCheck={false} style={{ width:'100%',border:'none',background:'transparent',fontSize:22,fontWeight:700,color:'var(--text-primary)',outline:'none' }}/> diff --git a/frontend/src/components/SchedulePage.jsx b/frontend/src/components/SchedulePage.jsx index 95876ca..5e9a51f 100644 --- a/frontend/src/components/SchedulePage.jsx +++ b/frontend/src/components/SchedulePage.jsx @@ -198,6 +198,7 @@ function TimeInput({ value, onChange, style }) { style={{ width: '100%', cursor: 'text' }} autoComplete="off" inputMode="text" + enterKeyHint="done" placeholder="9:00 AM" /> {open && (