diff --git a/src/pages/todo/Todo.css b/src/pages/todo/Todo.css
index 54f6f31..d1f7155 100644
--- a/src/pages/todo/Todo.css
+++ b/src/pages/todo/Todo.css
@@ -370,11 +370,21 @@
text-decoration-color: rgba(244, 114, 182, 0.4);
}
+/* ── 스와이프 보드 (모바일 전용) ──────────────────────────────────────── */
+
+.todo-swipe-board {
+ display: none;
+}
+
/* ── Responsive ──────────────────────────────────────────────────────── */
@media (max-width: 768px) {
.todo-board {
- grid-template-columns: 1fr;
+ display: none;
+ }
+
+ .todo-swipe-board {
+ display: block;
}
.todo-col {
diff --git a/src/pages/todo/Todo.jsx b/src/pages/todo/Todo.jsx
index 62ba2a8..1a0b65b 100644
--- a/src/pages/todo/Todo.jsx
+++ b/src/pages/todo/Todo.jsx
@@ -1,5 +1,10 @@
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { getTodos, addTodo, updateTodo, deleteTodo, clearTodos } from '../../api';
+import { useIsMobile } from '../../hooks/useIsMobile';
+import SwipeableView from '../../components/SwipeableView';
+import FAB from '../../components/FAB';
+import MobileSheet from '../../components/MobileSheet';
+import PullToRefresh from '../../components/PullToRefresh';
import './Todo.css';
const ACTIVE_COLUMNS = [
@@ -19,11 +24,13 @@ const toDateStr = (iso) => {
};
const Todo = () => {
+ const isMobile = useIsMobile();
const [todos, setTodos] = useState([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState('');
const [form, setForm] = useState(emptyForm);
const [formOpen, setFormOpen] = useState(false);
+ const [addSheetOpen, setAddSheetOpen] = useState(false);
const [saving, setSaving] = useState(false);
const [dragging, setDragging] = useState(null);
const [dragOver, setDragOver] = useState(null);
@@ -185,7 +192,66 @@ const Todo = () => {
);
+ /* ── 칸반 컬럼 렌더러 (재사용) ── */
+ const renderColumn = (col) => {
+ const items = byStatus(col.id);
+ return (
+
onDragOver(e, col.id)}
+ onDrop={(e) => onDrop(e, col.id)}
+ >
+
+ {col.label}
+ {items.length}
+
+
+ {items.length === 0 && (
+
드래그하여 이동
+ )}
+ {items.map((todo) => renderCard(todo, col.id))}
+
+
+ );
+ };
+
+ /* ── 추가 폼 (공통) ── */
+ const addForm = (
+
+ );
+
return (
+
{/* 툴바 */}
@@ -205,127 +271,126 @@ const Todo = () => {
- {/* 추가 폼 */}
- {formOpen && (
-
- )}
+ {/* 추가 폼 (데스크탑) */}
+ {formOpen && !isMobile && addForm}
{error &&
{error}
}
{loading && todos.length === 0 &&
불러오는 중...
}
- {/* 활성 보드 (할 일 + 진행 중) */}
-
- {ACTIVE_COLUMNS.map((col) => {
- const items = byStatus(col.id);
- return (
-
onDragOver(e, col.id)}
- onDrop={(e) => onDrop(e, col.id)}
- >
-
- {col.label}
- {items.length}
-
-
- {items.length === 0 && (
-
드래그하여 이동
+ {/* 모바일: SwipeableView 칸반 */}
+ {isMobile ? (
+
+
onDragOver(e, 'done')}
+ onDrop={(e) => onDrop(e, 'done')}
+ >
+
+
+ 완료
+ {doneTodos.length}
+
+
+
+ {doneDates.map((d) => (
+
+ ))}
+
+
+
+ {doneTodos.length === 0 ? (
+
{doneDate ? '해당 날짜에 완료된 항목이 없습니다' : '드래그하여 이동'}
+ ) : (
+ doneTodos.map((todo) => renderCard(todo, 'done'))
+ )}
+
+
+ )},
+ ]}
+ />
+
+ ) : (
+ <>
+ {/* 데스크탑: 활성 보드 (할 일 + 진행 중) */}
+
+ {ACTIVE_COLUMNS.map((col) => renderColumn(col))}
+
+
+ {/* 완료 패널 */}
+
onDragOver(e, 'done')}
+ onDrop={(e) => onDrop(e, 'done')}
+ >
+
+
+ 완료
+ {doneTodos.length}
+ {doneDates.length > 0 && doneDate === '' && (
+
+ 전체 {todos.filter(t => t.status === 'done').length}건
+
)}
- {items.map((todo) => renderCard(todo, col.id))}
+
+
+
+ {doneDates.map((d) => (
+
+ ))}
+ setDoneDate(e.target.value)}
+ title="날짜 직접 선택"
+ />
- );
- })}
-
+
+ {doneTodos.length === 0 ? (
+
+ {doneDate ? '해당 날짜에 완료된 항목이 없습니다' : '드래그하여 이동'}
+
+ ) : (
+ doneTodos.map((todo) => renderCard(todo, 'done'))
+ )}
+
+
+ >
+ )}
- {/* 완료 패널 */}
-
onDragOver(e, 'done')}
- onDrop={(e) => onDrop(e, 'done')}
+ {/* 모바일: 추가 바텀시트 */}
+
{ setAddSheetOpen(false); setForm(emptyForm); }}
+ title="태스크 추가"
>
- {/* 완료 패널 헤더 */}
-
-
- 완료
- {doneTodos.length}
- {doneDates.length > 0 && doneDate === '' && (
-
- 전체 {todos.filter(t => t.status === 'done').length}건
-
- )}
-
- {/* 날짜 필터 */}
-
-
- {doneDates.map((d) => (
-
- ))}
- setDoneDate(e.target.value)}
- title="날짜 직접 선택"
- />
-
-
+ {addForm}
+
- {/* 완료 카드 그리드 */}
-
- {doneTodos.length === 0 ? (
-
- {doneDate ? '해당 날짜에 완료된 항목이 없습니다' : '드래그하여 이동'}
-
- ) : (
- doneTodos.map((todo) => renderCard(todo, 'done'))
- )}
-
-
+
setAddSheetOpen(true)} label="태스크 추가" />
+
);
};