fix(tours): prevent duplicate day assignments

This commit is contained in:
elmocito
2026-10-05 23:53:11 +02:00
parent a9f9a23908
commit af7dbce105
14 changed files with 313 additions and 15 deletions
@@ -79,4 +79,13 @@ describe('ContextMenu', () => {
});
expect(onClose).toHaveBeenCalledOnce();
});
it('does not activate a disabled menu item', () => {
const onClick = vi.fn()
render(<ContextMenu menu={makeMenu(100, 200, [{ label: 'Already assigned', onClick, disabled: true }])} onClose={onClose} />)
const item = screen.getByRole('button', { name: 'Already assigned' })
expect(item).toBeDisabled()
fireEvent.click(item)
expect(onClick).not.toHaveBeenCalled()
})
});
+5 -4
View File
@@ -6,6 +6,7 @@ interface MenuItem {
label?: string
icon?: LucideIcon
onClick?: () => void
disabled?: boolean
danger?: boolean
divider?: boolean
}
@@ -84,15 +85,15 @@ export function ContextMenu({ menu, onClose }: ContextMenuProps) {
if (item.divider) return <div key={i} style={{ height: 1, background: 'var(--border-faint)', margin: '3px 6px' }} />
const Icon = item.icon
return (
<button type="button" key={i} onClick={() => { item.onClick?.(); onClose() }} style={{
<button type="button" key={i} disabled={item.disabled} onClick={() => { if (item.disabled) return; item.onClick?.(); onClose() }} style={{
display: 'flex', alignItems: 'center', gap: 8, width: '100%',
padding: '7px 10px', borderRadius: 7, border: 'none',
background: 'none', cursor: 'pointer', fontFamily: 'inherit',
background: 'none', cursor: item.disabled ? 'default' : 'pointer', fontFamily: 'inherit',
fontSize: 'calc(12px * var(--fs-scale-body, 1))', fontWeight: 500, textAlign: 'left',
color: item.danger ? '#ef4444' : 'var(--text-primary)',
color: item.danger ? '#ef4444' : 'var(--text-primary)', opacity: item.disabled ? 0.45 : 1,
transition: 'background 0.1s',
}}
onMouseEnter={e => e.currentTarget.style.background = item.danger ? 'rgba(239,68,68,0.08)' : 'var(--bg-hover)'}
onMouseEnter={e => { if (!item.disabled) e.currentTarget.style.background = item.danger ? 'rgba(239,68,68,0.08)' : 'var(--bg-hover)' }}
onMouseLeave={e => e.currentTarget.style.background = 'none'}
>
{Icon && <Icon size={13} style={{ flexShrink: 0, color: item.danger ? '#ef4444' : 'var(--text-faint)' }} />}