(
task: VaultTask,
dayIso: string,
opts?: { isActive?: boolean; rowRef?: React.RefObject<HTMLDivElement> | null }
)
| 772 | // One task row in the week agenda: draggable to a calendar day (move / set |
| 773 | // due), click to open, right-click for actions, inline-editable. |
| 774 | const renderTaskRow = ( |
| 775 | task: VaultTask, |
| 776 | dayIso: string, |
| 777 | opts?: { isActive?: boolean; rowRef?: React.RefObject<HTMLDivElement> | null } |
| 778 | ): JSX.Element => |
| 779 | editingTaskId === task.id ? ( |
| 780 | <div key={task.id} className="flex items-center gap-2 px-1.5 py-1"> |
| 781 | <span className="h-3.5 w-3.5 shrink-0 rounded-sm border border-paper-400/70" /> |
| 782 | <input |
| 783 | autoFocus |
| 784 | value={editValue} |
| 785 | onChange={(e) => setEditValue(e.target.value)} |
| 786 | onKeyDown={(e) => { |
| 787 | if (e.key === 'Enter') { |
| 788 | e.preventDefault() |
| 789 | e.currentTarget.blur() |
| 790 | } else if (e.key === 'Escape') { |
| 791 | e.stopPropagation() |
| 792 | cancelEditRef.current = true |
| 793 | e.currentTarget.blur() |
| 794 | } |
| 795 | }} |
| 796 | onBlur={() => { |
| 797 | if (cancelEditRef.current) { |
| 798 | cancelEditRef.current = false |
| 799 | } else { |
| 800 | const text = editValue.trim() |
| 801 | if (text && text !== taskTail(task)) { |
| 802 | void applyTaskMutation(task, { kind: 'set-text', text }) |
| 803 | } |
| 804 | } |
| 805 | setEditingTaskId(null) |
| 806 | }} |
| 807 | className="min-w-0 flex-1 rounded border border-accent/60 bg-paper-100 px-1 py-0.5 text-xs outline-none" |
| 808 | spellCheck={false} |
| 809 | autoComplete="off" |
| 810 | /> |
| 811 | </div> |
| 812 | ) : ( |
| 813 | // Draggable <div> (not <button>) — Chromium/Electron won't fire dragstart |
| 814 | // on a native button. |
| 815 | <div |
| 816 | key={task.id} |
| 817 | ref={opts?.rowRef ?? undefined} |
| 818 | role="button" |
| 819 | tabIndex={0} |
| 820 | draggable |
| 821 | onDragStart={(e) => { |
| 822 | e.dataTransfer.effectAllowed = 'move' |
| 823 | e.dataTransfer.setData('text/plain', task.id) |
| 824 | dragTaskRef.current = task |
| 825 | }} |
| 826 | onDragEnd={() => { |
| 827 | dragTaskRef.current = null |
| 828 | setDragOverIso(null) |
| 829 | }} |
| 830 | onClick={() => void openTaskAt(task)} |
| 831 | onContextMenu={(e) => openTaskMenu(e, task)} |
no test coverage detected