104 lines
3.6 KiB
TypeScript
104 lines
3.6 KiB
TypeScript
|
|
'use client';
|
|
|
|
import { useState, useEffect } from 'react';
|
|
import { useParams } from 'next/navigation';
|
|
import { WorkItem, WorkItemStatus } from '@/lib/types';
|
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
import { faInfoCircle } from '@fortawesome/free-solid-svg-icons';
|
|
import { workItemApi } from '@/lib/api-client';
|
|
|
|
export default function DetailPage() {
|
|
const params = useParams();
|
|
const [workItem, setWorkItem] = useState<WorkItem | null>(null);
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
useEffect(() => {
|
|
// Ensure we have a valid ID string and convert to number
|
|
const idString = Array.isArray(params.id) ? params.id[0] : params.id;
|
|
const id = idString ? parseInt(idString, 10) : NaN;
|
|
|
|
if (!isNaN(id)) {
|
|
// Fetch work item asynchronously
|
|
workItemApi.getWorkItem(id).then(item => {
|
|
setWorkItem(item || null);
|
|
setLoading(false);
|
|
}).catch(error => {
|
|
console.error('Error fetching work item:', error);
|
|
setWorkItem(null);
|
|
setLoading(false);
|
|
});
|
|
} else {
|
|
setLoading(false);
|
|
}
|
|
}, [params.id]);
|
|
|
|
if (loading) {
|
|
return (
|
|
<div className="px-4 sm:px-0">
|
|
<div className="max-w-md mx-auto">
|
|
<div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
|
|
<p className="text-gray-500">Loading...</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (!workItem) {
|
|
return (
|
|
<div className="px-4 sm:px-0">
|
|
<div className="max-w-md mx-auto">
|
|
<div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
|
|
<p className="text-gray-500">Work item not found.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="px-4 sm:px-0">
|
|
<div className="max-w-md mx-auto">
|
|
<div className="bg-white rounded-lg shadow-sm border border-gray-200 overflow-hidden">
|
|
<div className="px-6 py-4 border-b border-gray-200 bg-gray-50">
|
|
<h1 className="text-lg font-semibold text-gray-900 flex items-center">
|
|
<FontAwesomeIcon icon={faInfoCircle} className="mr-2 h-5 w-5" />
|
|
Work Item Detail
|
|
</h1>
|
|
</div>
|
|
|
|
<div className="p-6 space-y-6">
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700 mb-2">ID</label>
|
|
<p className="text-lg font-semibold text-gray-900">{workItem.id}</p>
|
|
</div>
|
|
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700 mb-2">Title</label>
|
|
<p className="text-lg font-semibold text-gray-900">{workItem.title}</p>
|
|
</div>
|
|
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700 mb-2">Description</label>
|
|
<p className="text-gray-600 leading-relaxed">{workItem.description}</p>
|
|
</div>
|
|
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700 mb-2">Status</label>
|
|
<span className={`inline-flex px-3 py-1 text-sm font-medium rounded-full ${
|
|
workItem.status === WorkItemStatus.Pending
|
|
? 'bg-yellow-100 text-yellow-800'
|
|
: workItem.status === WorkItemStatus.Completed
|
|
? 'bg-green-100 text-green-800'
|
|
: 'bg-blue-100 text-blue-800'
|
|
}`}>
|
|
{workItem.status}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
} |