129 lines
3.4 KiB
TypeScript
129 lines
3.4 KiB
TypeScript
'use client';
|
|
|
|
import { useState, useEffect } from 'react';
|
|
|
|
interface Task {
|
|
id: string;
|
|
headline: string;
|
|
projectName: string;
|
|
projectId: number;
|
|
status: number;
|
|
dueDate: string | null;
|
|
milestone: string | null;
|
|
details: string | null;
|
|
createdOn: string;
|
|
editedOn: string | null;
|
|
assignedTo: number[];
|
|
}
|
|
|
|
export default function Flow() {
|
|
const [tasks, setTasks] = useState<Task[]>([]);
|
|
const [loading, setLoading] = useState(false);
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
const getStatusLabel = (status: number): string => {
|
|
switch (status) {
|
|
case 1:
|
|
return 'New';
|
|
case 2:
|
|
return 'In Progress';
|
|
case 3:
|
|
return 'Done';
|
|
case 4:
|
|
return 'In Progress';
|
|
case 5:
|
|
return 'Done';
|
|
default:
|
|
return 'Unknown';
|
|
}
|
|
};
|
|
|
|
const getStatusColor = (status: number): string => {
|
|
switch (status) {
|
|
case 1:
|
|
return 'bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-300';
|
|
case 2:
|
|
case 4:
|
|
return 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-300';
|
|
case 3:
|
|
case 5:
|
|
return 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300';
|
|
default:
|
|
return 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-300';
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
const fetchTasks = async () => {
|
|
setLoading(true);
|
|
setError(null);
|
|
try {
|
|
const response = await fetch('/api/leantime/tasks');
|
|
if (!response.ok) {
|
|
throw new Error('Failed to fetch tasks');
|
|
}
|
|
const data = await response.json();
|
|
if (data.tasks && Array.isArray(data.tasks)) {
|
|
// Sort tasks by creation date (oldest first)
|
|
const sortedTasks = data.tasks.sort((a: Task, b: Task) => {
|
|
const dateA = new Date(a.createdOn).getTime();
|
|
const dateB = new Date(b.createdOn).getTime();
|
|
return dateA - dateB;
|
|
});
|
|
setTasks(sortedTasks);
|
|
} else {
|
|
console.error('Invalid tasks data format:', data);
|
|
setError('Invalid tasks data format');
|
|
}
|
|
} catch (err) {
|
|
console.error('Error fetching tasks:', err);
|
|
setError(err instanceof Error ? err.message : 'An error occurred');
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
fetchTasks();
|
|
}, []);
|
|
|
|
if (loading) {
|
|
return <div>Loading...</div>;
|
|
}
|
|
|
|
if (error) {
|
|
return <div>Error: {error}</div>;
|
|
}
|
|
|
|
if (tasks.length === 0) {
|
|
return <div>No tasks found</div>;
|
|
}
|
|
|
|
return (
|
|
<div className="grid grid-cols-1 gap-4">
|
|
{tasks.map((task) => (
|
|
<div
|
|
key={task.id}
|
|
className="bg-white dark:bg-gray-800 rounded-lg shadow p-4"
|
|
>
|
|
<div className="flex items-start justify-between">
|
|
<div className="flex-1">
|
|
<h3 className="text-sm font-medium text-gray-900 dark:text-gray-100">
|
|
{task.headline}
|
|
</h3>
|
|
<p className="mt-1 text-xs text-gray-500 dark:text-gray-400">
|
|
{task.projectName}
|
|
</p>
|
|
</div>
|
|
<span
|
|
className={`inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${getStatusColor(
|
|
task.status
|
|
)}`}
|
|
>
|
|
{getStatusLabel(task.status)}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|