Compare commits
2 Commits
50cfc8835f
...
92088e9c8a
| Author | SHA1 | Date | |
|---|---|---|---|
| 92088e9c8a | |||
| d24a188621 |
@@ -35,7 +35,14 @@ export const TodoPage: React.FC = () => {
|
|||||||
const [addingDate, setAddingDate] = useState<string | null>(null)
|
const [addingDate, setAddingDate] = useState<string | null>(null)
|
||||||
const [newTodoContent, setNewTodoContent] = useState('')
|
const [newTodoContent, setNewTodoContent] = useState('')
|
||||||
const [isInitialLoad, setIsInitialLoad] = useState(true)
|
const [isInitialLoad, setIsInitialLoad] = useState(true)
|
||||||
const inputRef = useRef<HTMLInputElement>(null)
|
const inputRef = useRef<HTMLTextAreaElement>(null)
|
||||||
|
const editInputRef = useRef<HTMLTextAreaElement>(null)
|
||||||
|
|
||||||
|
const adjustTextAreaHeight = (el: HTMLTextAreaElement) => {
|
||||||
|
const baseHeight = 28 // 1.75rem = 28px
|
||||||
|
el.style.height = baseHeight + 'px'
|
||||||
|
el.style.height = Math.max(el.scrollHeight, baseHeight) + 'px'
|
||||||
|
}
|
||||||
|
|
||||||
const loadTodoData = useCallback(async (year: number, month: number, isInitial: boolean = false) => {
|
const loadTodoData = useCallback(async (year: number, month: number, isInitial: boolean = false) => {
|
||||||
if (isInitial) {
|
if (isInitial) {
|
||||||
@@ -62,9 +69,16 @@ export const TodoPage: React.FC = () => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (addingDate && inputRef.current) {
|
if (addingDate && inputRef.current) {
|
||||||
inputRef.current.focus()
|
inputRef.current.focus()
|
||||||
|
adjustTextAreaHeight(inputRef.current)
|
||||||
}
|
}
|
||||||
}, [addingDate])
|
}, [addingDate])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (editingItem && editInputRef.current) {
|
||||||
|
adjustTextAreaHeight(editInputRef.current)
|
||||||
|
}
|
||||||
|
}, [editingItem])
|
||||||
|
|
||||||
const handlePrevMonth = () => {
|
const handlePrevMonth = () => {
|
||||||
if (currentMonth === 1) {
|
if (currentMonth === 1) {
|
||||||
setCurrentMonth(12)
|
setCurrentMonth(12)
|
||||||
@@ -134,7 +148,18 @@ export const TodoPage: React.FC = () => {
|
|||||||
if (!editingItem) return
|
if (!editingItem) return
|
||||||
const { date, index } = editingItem
|
const { date, index } = editingItem
|
||||||
const newContent = editContent.trim()
|
const newContent = editContent.trim()
|
||||||
if (!newContent) return
|
if (!newContent) {
|
||||||
|
try {
|
||||||
|
const data = await deleteTodoItem(currentYear, currentMonth, date, index)
|
||||||
|
setDayTodos(data.dayTodos)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to delete TODO:', error)
|
||||||
|
} finally {
|
||||||
|
setEditingItem(null)
|
||||||
|
setEditContent('')
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const data = await updateTodoItem(currentYear, currentMonth, date, index, newContent)
|
const data = await updateTodoItem(currentYear, currentMonth, date, index, newContent)
|
||||||
@@ -266,11 +291,11 @@ export const TodoPage: React.FC = () => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="pl-2 space-y-1">
|
<div className="pl-2 space-y-2">
|
||||||
{dayTodo?.items.map((item, index) => (
|
{dayTodo?.items.map((item, index) => (
|
||||||
<div
|
<div
|
||||||
key={item.id}
|
key={item.id}
|
||||||
className="flex items-center gap-3 group h-7"
|
className="flex items-center gap-3 group"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
onClick={() => canEdit && handleToggleTodo(date, index, !item.completed)}
|
onClick={() => canEdit && handleToggleTodo(date, index, !item.completed)}
|
||||||
@@ -288,18 +313,23 @@ export const TodoPage: React.FC = () => {
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
{editingItem?.date === date && editingItem?.index === index ? (
|
{editingItem?.date === date && editingItem?.index === index ? (
|
||||||
<input
|
<textarea
|
||||||
type="text"
|
ref={editInputRef}
|
||||||
value={editContent}
|
value={editContent}
|
||||||
onChange={(e) => setEditContent(e.target.value)}
|
onChange={(e) => {
|
||||||
|
setEditContent(e.target.value)
|
||||||
|
adjustTextAreaHeight(e.target)
|
||||||
|
}}
|
||||||
onKeyDown={handleEditKeyDown}
|
onKeyDown={handleEditKeyDown}
|
||||||
onBlur={handleSaveEdit}
|
onBlur={handleSaveEdit}
|
||||||
autoFocus
|
autoFocus
|
||||||
className="flex-1 px-2 py-0.5 bg-transparent border border-gray-300 dark:border-gray-600 rounded focus:outline-none focus:ring-2 focus:ring-gray-400 text-gray-800 dark:text-gray-200"
|
rows={1}
|
||||||
|
className="flex-1 px-2 bg-transparent border border-gray-300 dark:border-gray-600 rounded focus:outline-none focus:ring-2 focus:ring-gray-400 text-gray-800 dark:text-gray-200 resize-none overflow-hidden align-top"
|
||||||
|
style={{ height: '1.75rem' }}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<span
|
<span
|
||||||
onDoubleClick={() => canEdit && handleStartEdit(date, index, item.content)}
|
onDoubleClick={() => canEdit && !item.completed && handleStartEdit(date, index, item.content)}
|
||||||
className={`flex-1 ${canEdit ? 'cursor-pointer' : 'cursor-default'
|
className={`flex-1 ${canEdit ? 'cursor-pointer' : 'cursor-default'
|
||||||
} ${item.completed
|
} ${item.completed
|
||||||
? 'text-gray-400 dark:text-gray-500 line-through'
|
? 'text-gray-400 dark:text-gray-500 line-through'
|
||||||
@@ -310,7 +340,7 @@ export const TodoPage: React.FC = () => {
|
|||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{canEdit && (
|
{canEdit && !item.completed && (
|
||||||
<button
|
<button
|
||||||
onClick={() => handleDeleteTodo(date, index)}
|
onClick={() => handleDeleteTodo(date, index)}
|
||||||
className="p-1 opacity-0 group-hover:opacity-100 hover:bg-red-100 dark:hover:bg-red-900/30 rounded transition-all text-red-500"
|
className="p-1 opacity-0 group-hover:opacity-100 hover:bg-red-100 dark:hover:bg-red-900/30 rounded transition-all text-red-500"
|
||||||
@@ -322,19 +352,23 @@ export const TodoPage: React.FC = () => {
|
|||||||
))}
|
))}
|
||||||
|
|
||||||
{canEdit && addingDate === date && (
|
{canEdit && addingDate === date && (
|
||||||
<div className="flex items-center gap-3 h-7">
|
<div className="flex items-center gap-3">
|
||||||
<div className="w-4 h-4 rounded-full border-2 border-gray-400 dark:border-gray-500 shrink-0" />
|
<div className="w-4 h-4 rounded-full border-2 border-gray-400 dark:border-gray-500 shrink-0" />
|
||||||
<input
|
<textarea
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
type="text"
|
|
||||||
value={newTodoContent}
|
value={newTodoContent}
|
||||||
onChange={(e) => setNewTodoContent(e.target.value)}
|
onChange={(e) => {
|
||||||
|
setNewTodoContent(e.target.value)
|
||||||
|
adjustTextAreaHeight(e.target)
|
||||||
|
}}
|
||||||
onKeyDown={(e) => handleKeyDown(e, date)}
|
onKeyDown={(e) => handleKeyDown(e, date)}
|
||||||
onBlur={() => {
|
onBlur={() => {
|
||||||
handleAddTodo(date, false)
|
handleAddTodo(date, false)
|
||||||
}}
|
}}
|
||||||
placeholder="输入任务内容..."
|
placeholder="输入任务内容..."
|
||||||
className="flex-1 px-2 py-0.5 bg-transparent border border-gray-300 dark:border-gray-600 rounded focus:outline-none focus:ring-2 focus:ring-gray-400 text-gray-800 dark:text-gray-200 placeholder-gray-400"
|
rows={1}
|
||||||
|
className="flex-1 px-2 bg-transparent border border-gray-300 dark:border-gray-600 rounded focus:outline-none focus:ring-2 focus:ring-gray-400 text-gray-800 dark:text-gray-200 placeholder-gray-400 resize-none overflow-hidden align-top"
|
||||||
|
style={{ height: '1.75rem' }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user