Move cancel button to the modal
This commit is contained in:
@@ -60,7 +60,7 @@ const getDefaultNotification = () => {
|
|||||||
return defaultNotification
|
return defaultNotification
|
||||||
}
|
}
|
||||||
|
|
||||||
const TaskInput = ({ onChoreUpdate, isModalOpen, onClose }) => {
|
const TaskInput = ({ onChoreUpdate, isModalOpen, onClose, initialMode }) => {
|
||||||
const { ResponsiveModal } = useResponsiveModal()
|
const { ResponsiveModal } = useResponsiveModal()
|
||||||
const isMobile = useMediaQuery(theme => theme.breakpoints.down('sm'))
|
const isMobile = useMediaQuery(theme => theme.breakpoints.down('sm'))
|
||||||
const pickerEmptyDisplay = isMobile ? 'icon' : 'icon-text'
|
const pickerEmptyDisplay = isMobile ? 'icon' : 'icon-text'
|
||||||
@@ -136,6 +136,29 @@ const TaskInput = ({ onChoreUpdate, isModalOpen, onClose }) => {
|
|||||||
voiceInputService.isSupported().then(setVoiceAvailable)
|
voiceInputService.isSupported().then(setVoiceAvailable)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
// Quick-capture widget entry points (donetick://chores/add?mode=voice|scan)
|
||||||
|
// land here: open straight into the requested panel, once per modal open so
|
||||||
|
// backing out of the panel doesn't bounce the user right back into it.
|
||||||
|
const appliedInitialModeRef = useRef(false)
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isModalOpen) {
|
||||||
|
appliedInitialModeRef.current = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (appliedInitialModeRef.current) return
|
||||||
|
|
||||||
|
if (initialMode === 'voice') {
|
||||||
|
// isSupported() resolves async — wait for the answer before deciding.
|
||||||
|
if (!voiceAvailable) return
|
||||||
|
appliedInitialModeRef.current = true
|
||||||
|
setShowVoice(true)
|
||||||
|
} else if (initialMode === 'scan') {
|
||||||
|
appliedInitialModeRef.current = true
|
||||||
|
setScanAutoCapture(true)
|
||||||
|
setShowScan(true)
|
||||||
|
}
|
||||||
|
}, [isModalOpen, initialMode, voiceAvailable])
|
||||||
|
|
||||||
// Priority colors
|
// Priority colors
|
||||||
const priorityColors = {
|
const priorityColors = {
|
||||||
0: TASK_COLOR.NO_PRIORITY,
|
0: TASK_COLOR.NO_PRIORITY,
|
||||||
@@ -817,18 +840,21 @@ const TaskInput = ({ onChoreUpdate, isModalOpen, onClose }) => {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
{/* Sub-panels (voice/scan) own their own confirm action */}
|
||||||
size='lg'
|
{!showScan && !showVoice && (
|
||||||
variant='solid'
|
<Button
|
||||||
color='primary'
|
size='lg'
|
||||||
disabled={!taskTitle.trim()}
|
variant='solid'
|
||||||
onClick={createChore}
|
color='primary'
|
||||||
>
|
disabled={!taskTitle.trim()}
|
||||||
Create
|
onClick={createChore}
|
||||||
{showKeyboardShortcuts && (
|
>
|
||||||
<KeyboardShortcutHint shortcut='Enter' sx={{ ml: 1 }} />
|
Create
|
||||||
)}
|
{showKeyboardShortcuts && (
|
||||||
</Button>
|
<KeyboardShortcutHint shortcut='Enter' sx={{ ml: 1 }} />
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
@@ -1177,7 +1203,6 @@ const TaskInput = ({ onChoreUpdate, isModalOpen, onClose }) => {
|
|||||||
userLabels={userLabels || []}
|
userLabels={userLabels || []}
|
||||||
members={circleMembers?.res || []}
|
members={circleMembers?.res || []}
|
||||||
userProfile={userProfile}
|
userProfile={userProfile}
|
||||||
onClose={() => setShowVoice(false)}
|
|
||||||
onUseSingle={handleVoiceSingle}
|
onUseSingle={handleVoiceSingle}
|
||||||
onCreateMany={handleVoiceCreateMany}
|
onCreateMany={handleVoiceCreateMany}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -171,9 +171,6 @@ const ScanPanel = ({ open, onTaskExtracted, onClose, initialImageUrl, autoCaptur
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<Box sx={{ ml: 'auto', display: 'flex', gap: 1 }}>
|
<Box sx={{ ml: 'auto', display: 'flex', gap: 1 }}>
|
||||||
<Button size='sm' variant='plain' color='neutral' onClick={onClose}>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
{isNativeScanner ? (
|
{isNativeScanner ? (
|
||||||
<Button
|
<Button
|
||||||
size='sm'
|
size='sm'
|
||||||
@@ -297,9 +294,6 @@ const ScanPanel = ({ open, onTaskExtracted, onClose, initialImageUrl, autoCaptur
|
|||||||
>
|
>
|
||||||
Retake
|
Retake
|
||||||
</Button>
|
</Button>
|
||||||
<Button size='sm' variant='plain' color='neutral' onClick={onClose}>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -411,7 +411,6 @@ const VoicePanel = ({
|
|||||||
userLabels = [],
|
userLabels = [],
|
||||||
members = [],
|
members = [],
|
||||||
userProfile,
|
userProfile,
|
||||||
onClose,
|
|
||||||
onUseSingle,
|
onUseSingle,
|
||||||
onCreateMany,
|
onCreateMany,
|
||||||
}) => {
|
}) => {
|
||||||
@@ -426,7 +425,6 @@ const VoicePanel = ({
|
|||||||
removeSegment,
|
removeSegment,
|
||||||
updateSegment,
|
updateSegment,
|
||||||
patchSegment,
|
patchSegment,
|
||||||
reset,
|
|
||||||
isNative,
|
isNative,
|
||||||
} = useVoiceToTask({ members, userLabels })
|
} = useVoiceToTask({ members, userLabels })
|
||||||
const [creating, setCreating] = useState(false)
|
const [creating, setCreating] = useState(false)
|
||||||
@@ -463,11 +461,6 @@ const VoicePanel = ({
|
|||||||
const isListening = phase === 'listening'
|
const isListening = phase === 'listening'
|
||||||
const showActions = segments.length > 0 && !isListening && !creating
|
const showActions = segments.length > 0 && !isListening && !creating
|
||||||
|
|
||||||
const handleCancel = () => {
|
|
||||||
reset()
|
|
||||||
onClose()
|
|
||||||
}
|
|
||||||
|
|
||||||
const mergedTask = segment => ({
|
const mergedTask = segment => ({
|
||||||
...parseVoiceTask(segment.text, parseCtx),
|
...parseVoiceTask(segment.text, parseCtx),
|
||||||
...(segment.overrides || {}),
|
...(segment.overrides || {}),
|
||||||
@@ -644,62 +637,52 @@ const VoicePanel = ({
|
|||||||
level='body-xs'
|
level='body-xs'
|
||||||
sx={{ opacity: 0.5, px: 2, textAlign: 'center' }}
|
sx={{ opacity: 0.5, px: 2, textAlign: 'center' }}
|
||||||
>
|
>
|
||||||
Pause or say “also” between tasks · say
|
Pause between tasks · say “scratch that” to
|
||||||
“scratch that” to remove the last one
|
remove the last one
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* ── Footer ── */}
|
{/* ── Footer — dismissing is the modal's Cancel; this owns confirm only ── */}
|
||||||
<Box
|
{(creating || showActions) && (
|
||||||
sx={{
|
<Box
|
||||||
px: 1.5,
|
sx={{
|
||||||
py: 1,
|
px: 1.5,
|
||||||
display: 'flex',
|
py: 1,
|
||||||
alignItems: 'center',
|
display: 'flex',
|
||||||
gap: 1,
|
justifyContent: 'flex-end',
|
||||||
borderTop: '1px solid',
|
gap: 1,
|
||||||
borderColor: 'divider',
|
borderTop: '1px solid',
|
||||||
}}
|
borderColor: 'divider',
|
||||||
>
|
}}
|
||||||
<Button
|
|
||||||
size='sm'
|
|
||||||
variant='plain'
|
|
||||||
color='neutral'
|
|
||||||
onClick={handleCancel}
|
|
||||||
>
|
>
|
||||||
Cancel
|
{creating ? (
|
||||||
</Button>
|
|
||||||
<Box sx={{ ml: 'auto', display: 'flex', gap: 1 }}>
|
|
||||||
{creating && (
|
|
||||||
<Button size='sm' variant='solid' color='primary' loading>
|
<Button size='sm' variant='solid' color='primary' loading>
|
||||||
Creating…
|
Creating…
|
||||||
</Button>
|
</Button>
|
||||||
|
) : segments.length === 1 ? (
|
||||||
|
<Button
|
||||||
|
size='sm'
|
||||||
|
variant='solid'
|
||||||
|
color='primary'
|
||||||
|
onClick={() =>
|
||||||
|
onUseSingle(segments[0].text, segments[0].overrides || {})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Use Task
|
||||||
|
</Button>
|
||||||
|
) : (
|
||||||
|
<Button
|
||||||
|
size='sm'
|
||||||
|
variant='solid'
|
||||||
|
color='primary'
|
||||||
|
onClick={handleCreateAll}
|
||||||
|
>
|
||||||
|
Create {segments.length} Tasks
|
||||||
|
</Button>
|
||||||
)}
|
)}
|
||||||
{showActions &&
|
|
||||||
(segments.length === 1 ? (
|
|
||||||
<Button
|
|
||||||
size='sm'
|
|
||||||
variant='solid'
|
|
||||||
color='primary'
|
|
||||||
onClick={() =>
|
|
||||||
onUseSingle(segments[0].text, segments[0].overrides || {})
|
|
||||||
}
|
|
||||||
>
|
|
||||||
Use Task
|
|
||||||
</Button>
|
|
||||||
) : (
|
|
||||||
<Button
|
|
||||||
size='sm'
|
|
||||||
variant='solid'
|
|
||||||
color='primary'
|
|
||||||
onClick={handleCreateAll}
|
|
||||||
>
|
|
||||||
Create {segments.length} Tasks
|
|
||||||
</Button>
|
|
||||||
))}
|
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user