This commit is contained in:
beabigegg
2025-08-29 19:02:19 +08:00
parent b0c86302ff
commit f3f2b7d596
17 changed files with 1632 additions and 157 deletions

View File

@@ -11,6 +11,9 @@ import {
Fade,
Chip,
Card,
Skeleton,
CircularProgress,
Backdrop,
} from '@mui/material';
import {
Add,
@@ -42,6 +45,16 @@ const TodosPage = () => {
const [viewMode, setViewMode] = useState<ViewMode>('list');
const [filterMode, setFilterMode] = useState<FilterMode>('all');
const [showFilters, setShowFilters] = useState(false);
const [appliedFilters, setAppliedFilters] = useState({
status: [] as string[],
priority: [] as string[],
assignee: '',
dateFrom: null as any,
dateTo: null as any,
starred: false,
overdue: false,
dueSoon: false,
});
const [showSearch, setShowSearch] = useState(false);
const [selectedTodos, setSelectedTodos] = useState<string[]>([]);
const [searchQuery, setSearchQuery] = useState('');
@@ -142,10 +155,68 @@ const TodosPage = () => {
case 'following':
return todo.followers?.includes(currentUser.ad_account) || false;
default:
return true;
break; // 繼續其他篩選
}
}
// 進階篩選
// 狀態篩選
if (appliedFilters.status.length > 0 && !appliedFilters.status.includes(todo.status)) {
return false;
}
// 優先級篩選
if (appliedFilters.priority.length > 0 && !appliedFilters.priority.includes(todo.priority)) {
return false;
}
// 指派人篩選
if (appliedFilters.assignee && currentUser) {
switch (appliedFilters.assignee) {
case 'me':
if (!todo.responsible_users?.includes(currentUser.ad_account)) return false;
break;
case 'created_by_me':
if (todo.creator_ad !== currentUser.ad_account) return false;
break;
case 'followed_by_me':
if (!todo.followers?.includes(currentUser.ad_account)) return false;
break;
}
}
// 日期篩選
if (appliedFilters.dateFrom || appliedFilters.dateTo) {
if (!todo.due_date) return false;
const dueDate = new Date(todo.due_date);
if (appliedFilters.dateFrom && dueDate < new Date(appliedFilters.dateFrom)) return false;
if (appliedFilters.dateTo && dueDate > new Date(appliedFilters.dateTo)) return false;
}
// 星號篩選
if (appliedFilters.starred && !todo.starred) {
return false;
}
// 逾期篩選
if (appliedFilters.overdue) {
if (!todo.due_date) return false;
const dueDate = new Date(todo.due_date);
const today = new Date();
today.setHours(0, 0, 0, 0);
if (dueDate >= today || todo.status === 'DONE') return false;
}
// 即將到期篩選
if (appliedFilters.dueSoon) {
if (!todo.due_date || todo.status === 'DONE') return false;
const dueDate = new Date(todo.due_date);
const today = new Date();
const threeDaysFromNow = new Date();
threeDaysFromNow.setDate(today.getDate() + 3);
if (dueDate < today || dueDate > threeDaysFromNow) return false;
}
return true;
});
@@ -544,7 +615,11 @@ const TodosPage = () => {
exit={{ opacity: 0, height: 0, marginBottom: 0 }}
transition={{ duration: 0.3 }}
>
<TodoFilters onClose={() => setShowFilters(false)} />
<TodoFilters
onClose={() => setShowFilters(false)}
onApply={setAppliedFilters}
initialFilters={appliedFilters}
/>
</motion.div>
)}
</AnimatePresence>
@@ -572,8 +647,28 @@ const TodosPage = () => {
{/* 主要內容區域 */}
<motion.div variants={itemVariants}>
<Fade in={true} timeout={500}>
<Box>
{viewMode === 'list' ? (
<Box sx={{ position: 'relative', minHeight: '400px' }}>
{loading ? (
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
{Array.from({ length: 3 }).map((_, index) => (
<Card key={index} sx={{ p: 3 }}>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2, mb: 2 }}>
<Skeleton variant="rectangular" width={20} height={20} />
<Skeleton variant="text" width="60%" height={32} />
<Skeleton variant="circular" width={24} height={24} sx={{ ml: 'auto' }} />
</Box>
<Skeleton variant="text" width="80%" height={20} sx={{ mb: 1 }} />
<Skeleton variant="text" width="40%" height={20} sx={{ mb: 2 }} />
<Box sx={{ display: 'flex', gap: 1, mb: 2 }}>
<Skeleton variant="rounded" width={60} height={24} />
<Skeleton variant="rounded" width={50} height={24} />
<Skeleton variant="rounded" width={70} height={24} />
</Box>
<Skeleton variant="text" width="30%" height={16} />
</Card>
))}
</Box>
) : viewMode === 'list' ? (
<TodoList
todos={filteredTodos}
selectedTodos={selectedTodos}