ca-grow-ops-manager/frontend/src/components/tasks/TasksDueTodayWidget.tsx
fullsizemalt 47de301f77
Some checks are pending
Test / backend-test (push) Waiting to run
Test / frontend-test (push) Waiting to run
style: Dark/Light mode contrast audit
- Boost text contrast in both themes
- Strengthen border visibility (subtle borders now visible)
- Convert 39 files from hardcoded dark:/light: to CSS vars
- Tertiary text now more readable on both backgrounds
2025-12-27 12:12:10 -08:00

88 lines
3.7 KiB
TypeScript

import { useState, useEffect } from 'react';
import { CheckCircle, Clock, AlertTriangle, List } from 'lucide-react';
import { tasksApi, Task } from '../../lib/tasksApi';
import CompleteTaskModal from './CompleteTaskModal';
interface TasksDueTodayWidgetProps {
userId: string;
}
export default function TasksDueTodayWidget({ userId }: TasksDueTodayWidgetProps) {
const [tasks, setTasks] = useState<Task[]>([]);
const [selectedTask, setSelectedTask] = useState<Task | null>(null);
useEffect(() => {
loadTasks();
}, [userId]);
const loadTasks = async () => {
if (!userId) return;
try {
const today = new Date().toISOString().split('T')[0];
// Fetch pending tasks assigned to user due on or before today
// Note: API filtering might need adjustment if it strictly matches dates.
// For now, let's fetch pending and filter client-side for "Due <= Today"
const data = await tasksApi.getAll({
assigneeId: userId,
status: 'PENDING'
});
const dueTasks = data.filter(t => {
if (!t.dueDate) return false;
const due = new Date(t.dueDate).toISOString().split('T')[0];
return due <= today;
});
setTasks(dueTasks);
} catch (e) {
console.error(e);
}
};
if (tasks.length === 0) return null;
return (
<div className="bg-[var(--color-bg-elevated)] rounded-2xl shadow-sm border border-[var(--color-border-default)] p-6">
<div className="flex justify-between items-center mb-4">
<h3 className="text-lg font-bold text-[var(--color-text-primary)] flex items-center gap-2">
<List className="text-[var(--color-primary)]" />
Tasks Due Today
</h3>
<span className="px-2 py-1 bg-red-100 text-red-700 text-xs font-bold rounded-full">
{tasks.length} Pending
</span>
</div>
<div className="space-y-3">
{tasks.map(task => (
<div key={task.id} className="flex items-start justify-between p-3 bg-slate-50 dark:bg-slate-700/50 rounded-xl border border-slate-100 dark:border-slate-700">
<div className="flex items-start gap-3">
<button
onClick={() => setSelectedTask(task)}
className="mt-1 w-5 h-5 rounded-full border-2 border-slate-300 dark:border-slate-500 hover:border-emerald-500 hover:bg-emerald-50 dark:hover:bg-emerald-900/20 transition-colors"
/>
<div>
<h4 className="font-medium text-[var(--color-text-primary)] text-sm">{task.title}</h4>
<div className="flex gap-2 text-xs text-[var(--color-text-tertiary)] mt-1">
{task.room && <span>📍 {task.room.name}</span>}
{task.priority === 'HIGH' && <span className="text-red-500 font-bold">High Priority</span>}
</div>
</div>
</div>
</div>
))}
</div>
{selectedTask && (
<CompleteTaskModal
task={selectedTask}
onClose={() => setSelectedTask(null)}
onSuccess={() => {
loadTasks();
setSelectedTask(null);
}}
/>
)}
</div>
);
}