feat: task time estimates and velocity chart on dashboard
- Added estimatedHours column to tasks schema - Backend: create/update support for estimatedHours - New /api/tasks/stats/velocity endpoint: daily completions, weekly velocity, estimate totals - Dashboard: velocity chart with 7-day bar chart, this week count, avg/week, estimate summary - TaskDetailPanel: estimated hours input field - CreateTaskModal: estimated hours in advanced options - TaskCard, KanbanBoard, TaskPage: estimate badge display
This commit is contained in:
@@ -12,6 +12,7 @@ interface CreateTaskModalProps {
|
||||
priority?: string;
|
||||
projectId?: string;
|
||||
dueDate?: string;
|
||||
estimatedHours?: number;
|
||||
}) => void;
|
||||
}
|
||||
|
||||
@@ -22,6 +23,7 @@ export function CreateTaskModal({ open, onClose, onCreate }: CreateTaskModalProp
|
||||
const [priority, setPriority] = useState("medium");
|
||||
const [projectId, setProjectId] = useState("");
|
||||
const [dueDate, setDueDate] = useState("");
|
||||
const [estimatedHours, setEstimatedHours] = useState("");
|
||||
const [projects, setProjects] = useState<Project[]>([]);
|
||||
const [showAdvanced, setShowAdvanced] = useState(false);
|
||||
|
||||
@@ -53,6 +55,7 @@ export function CreateTaskModal({ open, onClose, onCreate }: CreateTaskModalProp
|
||||
priority,
|
||||
projectId: projectId || undefined,
|
||||
dueDate: dueDate ? new Date(dueDate).toISOString() : undefined,
|
||||
estimatedHours: estimatedHours ? Number(estimatedHours) : undefined,
|
||||
});
|
||||
// Reset form
|
||||
setTitle("");
|
||||
@@ -61,6 +64,7 @@ export function CreateTaskModal({ open, onClose, onCreate }: CreateTaskModalProp
|
||||
setPriority("medium");
|
||||
setProjectId("");
|
||||
setDueDate("");
|
||||
setEstimatedHours("");
|
||||
setShowAdvanced(false);
|
||||
onClose();
|
||||
};
|
||||
@@ -179,6 +183,23 @@ export function CreateTaskModal({ open, onClose, onCreate }: CreateTaskModalProp
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Estimated Hours */}
|
||||
<div>
|
||||
<label className="text-xs font-medium text-gray-500 block mb-1">Estimated Hours</label>
|
||||
<div className="flex items-center gap-2">
|
||||
<input
|
||||
type="number"
|
||||
min="0"
|
||||
step="1"
|
||||
value={estimatedHours}
|
||||
onChange={(e) => setEstimatedHours(e.target.value)}
|
||||
placeholder="0"
|
||||
className="w-24 text-sm border border-gray-200 rounded-lg px-3 py-1.5 focus:outline-none focus:ring-2 focus:ring-amber-400 bg-white"
|
||||
/>
|
||||
<span className="text-sm text-gray-500">hours</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Source */}
|
||||
<div>
|
||||
<label className="text-xs font-medium text-gray-500 block mb-1">Source</label>
|
||||
|
||||
Reference in New Issue
Block a user