π Integrate Project Tracker with API /api/Projects
π API Integration Features: - Load project data from /api/Projects endpoint - Map API response to table format with proper field mapping - Implement loading states with Spin component - Add pagination support from API response ποΈ Data Mapping: - categoryName -> Category column - startDate -> Start Date column - progressPercentage -> Progress column - endDate -> Deadline column - status -> Status column - budget -> Budget column - projectName, clientName, createdByName mapped correctly π§ Technical Implementation: - Added useEffect for data loading on component mount - Implemented loadProjects async function - Added helper functions for status/category color mapping - Integrated API pagination with table pagination - Added error handling for API calls - Loading spinner during data fetch π¨ UI Enhancements: - Maintained existing table design and styling - Preserved all filter and search functionality - Added loading states for better UX - Dynamic status and category color mapping - Proper date formatting with dayjs π Ready for Backend: - API endpoint: /api/Projects - Expected response format documented - Pagination parameters: page, pageSize - Error handling implemented - Loading states managed
This commit is contained in:
parent
4103d668be
commit
83971f3c1a
@ -1,6 +1,6 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { Table, Progress, Tag, Avatar, Button, DatePicker, Select } from 'antd';
|
import { Table, Progress, Tag, Avatar, Button, DatePicker, Select, Spin } from 'antd';
|
||||||
import {
|
import {
|
||||||
Star,
|
Star,
|
||||||
Edit,
|
Edit,
|
||||||
@ -23,169 +23,101 @@ const ProjectTracker = () => {
|
|||||||
dayjs()
|
dayjs()
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Sample project data
|
// API data state
|
||||||
const projectData = [
|
const [projectData, setProjectData] = useState([]);
|
||||||
{
|
const [loading, setLoading] = useState(false);
|
||||||
key: '1',
|
const [pagination, setPagination] = useState({
|
||||||
id: 1,
|
currentPage: 1,
|
||||||
projectName: 'E-commerce Website Development',
|
pageSize: 10,
|
||||||
category: ['Web Development'],
|
totalCount: 0,
|
||||||
categoryColor: 'blue',
|
totalPages: 1
|
||||||
manager: [
|
});
|
||||||
{ name: 'John Smith', avatar: 'assets/img/profiles/avatar-01.jpg' },
|
|
||||||
{ name: 'Sarah Johnson', avatar: 'assets/img/profiles/avatar-02.jpg' }
|
// Load projects from API
|
||||||
],
|
const loadProjects = async (page = 1, pageSize = 10) => {
|
||||||
startDate: '01 Jan 2024',
|
setLoading(true);
|
||||||
progress: 85,
|
try {
|
||||||
deadline: '15 Mar 2024',
|
const response = await fetch(`/api/Projects?page=${page}&pageSize=${pageSize}`);
|
||||||
status: 'In Progress',
|
const result = await response.json();
|
||||||
statusColor: 'warning',
|
|
||||||
priority: 'high',
|
if (result.data) {
|
||||||
starred: true,
|
// Map API data to table format
|
||||||
budget: '$45,000',
|
const mappedData = result.data.map(project => ({
|
||||||
client: 'TechCorp Inc.'
|
key: project.id.toString(),
|
||||||
},
|
id: project.id,
|
||||||
{
|
projectName: project.projectName,
|
||||||
key: '2',
|
category: [project.categoryName],
|
||||||
id: 2,
|
categoryColor: getCategoryColor(project.categoryName),
|
||||||
projectName: 'Mobile App UI/UX Design',
|
manager: [
|
||||||
category: ['Design'],
|
{ name: project.createdByName, avatar: 'assets/img/profiles/avatar-01.jpg' }
|
||||||
categoryColor: 'purple',
|
],
|
||||||
manager: [
|
startDate: dayjs(project.startDate).format('DD MMM YYYY'),
|
||||||
{ name: 'Mike Wilson', avatar: 'assets/img/profiles/avatar-03.jpg' },
|
progress: project.progressPercentage,
|
||||||
{ name: 'Lisa Chen', avatar: 'assets/img/profiles/avatar-04.jpg' }
|
deadline: dayjs(project.endDate).format('DD MMM YYYY'),
|
||||||
],
|
status: formatStatus(project.status),
|
||||||
startDate: '15 Feb 2024',
|
statusColor: getStatusColor(project.status),
|
||||||
progress: 60,
|
priority: project.priority,
|
||||||
deadline: '30 Apr 2024',
|
starred: false,
|
||||||
status: 'In Progress',
|
budget: `$${project.budget.toLocaleString()}`,
|
||||||
statusColor: 'warning',
|
client: project.clientName
|
||||||
priority: 'medium',
|
}));
|
||||||
starred: false,
|
|
||||||
budget: '$28,000',
|
setProjectData(mappedData);
|
||||||
client: 'StartupXYZ'
|
setPagination(result.pagination);
|
||||||
},
|
}
|
||||||
{
|
} catch (error) {
|
||||||
key: '3',
|
console.error('Error loading projects:', error);
|
||||||
id: 3,
|
} finally {
|
||||||
projectName: 'Database Migration Project',
|
setLoading(false);
|
||||||
category: ['Backend'],
|
|
||||||
categoryColor: 'green',
|
|
||||||
manager: [
|
|
||||||
{ name: 'David Brown', avatar: 'assets/img/profiles/avatar-05.jpg' },
|
|
||||||
{ name: 'Emma Davis', avatar: 'assets/img/profiles/avatar-06.jpg' }
|
|
||||||
],
|
|
||||||
startDate: '10 Mar 2024',
|
|
||||||
progress: 100,
|
|
||||||
deadline: '25 Mar 2024',
|
|
||||||
status: 'Completed',
|
|
||||||
statusColor: 'success',
|
|
||||||
priority: 'high',
|
|
||||||
starred: true,
|
|
||||||
budget: '$35,000',
|
|
||||||
client: 'DataFlow Ltd.'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: '4',
|
|
||||||
id: 4,
|
|
||||||
projectName: 'Marketing Campaign Platform',
|
|
||||||
category: ['Marketing'],
|
|
||||||
categoryColor: 'orange',
|
|
||||||
manager: [
|
|
||||||
{ name: 'Tom Anderson', avatar: 'assets/img/profiles/avatar-07.jpg' },
|
|
||||||
{ name: 'Jessica White', avatar: 'assets/img/profiles/avatar-08.jpg' }
|
|
||||||
],
|
|
||||||
startDate: '20 Mar 2024',
|
|
||||||
progress: 40,
|
|
||||||
deadline: '15 Jun 2024',
|
|
||||||
status: 'In Progress',
|
|
||||||
statusColor: 'warning',
|
|
||||||
priority: 'medium',
|
|
||||||
starred: false,
|
|
||||||
budget: '$52,000',
|
|
||||||
client: 'MarketPro Agency'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: '5',
|
|
||||||
id: 5,
|
|
||||||
projectName: 'Cloud Infrastructure Setup',
|
|
||||||
category: ['DevOps'],
|
|
||||||
categoryColor: 'cyan',
|
|
||||||
manager: [
|
|
||||||
{ name: 'Alex Rodriguez', avatar: 'assets/img/profiles/avatar-09.jpg' },
|
|
||||||
{ name: 'Maria Garcia', avatar: 'assets/img/profiles/avatar-10.jpg' }
|
|
||||||
],
|
|
||||||
startDate: '05 Apr 2024',
|
|
||||||
progress: 75,
|
|
||||||
deadline: '20 May 2024',
|
|
||||||
status: 'In Progress',
|
|
||||||
statusColor: 'warning',
|
|
||||||
priority: 'high',
|
|
||||||
starred: true,
|
|
||||||
budget: '$38,000',
|
|
||||||
client: 'CloudTech Solutions'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: '6',
|
|
||||||
id: 6,
|
|
||||||
projectName: 'AI Chatbot Development',
|
|
||||||
category: ['AI/ML'],
|
|
||||||
categoryColor: 'red',
|
|
||||||
manager: [
|
|
||||||
{ name: 'Robert Lee', avatar: 'assets/img/profiles/avatar-11.jpg' },
|
|
||||||
{ name: 'Sophie Turner', avatar: 'assets/img/profiles/avatar-12.jpg' }
|
|
||||||
],
|
|
||||||
startDate: '12 Apr 2024',
|
|
||||||
progress: 30,
|
|
||||||
deadline: '30 Jul 2024',
|
|
||||||
status: 'Planning',
|
|
||||||
statusColor: 'default',
|
|
||||||
priority: 'low',
|
|
||||||
starred: false,
|
|
||||||
budget: '$65,000',
|
|
||||||
client: 'AI Innovations'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: '7',
|
|
||||||
id: 7,
|
|
||||||
projectName: 'Security Audit & Compliance',
|
|
||||||
category: ['Security'],
|
|
||||||
categoryColor: 'red',
|
|
||||||
manager: [
|
|
||||||
{ name: 'Michael Brown', avatar: 'assets/img/profiles/avatar-13.jpg' },
|
|
||||||
{ name: 'Rachel Davis', avatar: 'assets/img/profiles/avatar-14.jpg' }
|
|
||||||
],
|
|
||||||
startDate: '25 Apr 2024',
|
|
||||||
progress: 90,
|
|
||||||
deadline: '10 May 2024',
|
|
||||||
status: 'Review',
|
|
||||||
statusColor: 'processing',
|
|
||||||
priority: 'high',
|
|
||||||
starred: true,
|
|
||||||
budget: '$42,000',
|
|
||||||
client: 'SecureBank Corp'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: '8',
|
|
||||||
id: 8,
|
|
||||||
projectName: 'Content Management System',
|
|
||||||
category: ['Web Development'],
|
|
||||||
categoryColor: 'blue',
|
|
||||||
manager: [
|
|
||||||
{ name: 'Daniel Wilson', avatar: 'assets/img/profiles/avatar-15.jpg' },
|
|
||||||
{ name: 'Amanda Johnson', avatar: 'assets/img/profiles/avatar-16.jpg' }
|
|
||||||
],
|
|
||||||
startDate: '01 May 2024',
|
|
||||||
progress: 55,
|
|
||||||
deadline: '15 Aug 2024',
|
|
||||||
status: 'In Progress',
|
|
||||||
statusColor: 'warning',
|
|
||||||
priority: 'medium',
|
|
||||||
starred: false,
|
|
||||||
budget: '$48,000',
|
|
||||||
client: 'ContentHub Media'
|
|
||||||
}
|
}
|
||||||
];
|
};
|
||||||
|
|
||||||
|
// Helper functions for mapping
|
||||||
|
const getCategoryColor = (categoryName) => {
|
||||||
|
const colorMap = {
|
||||||
|
'Web Development': 'blue',
|
||||||
|
'Mobile App': 'green',
|
||||||
|
'Design': 'purple',
|
||||||
|
'Marketing': 'orange',
|
||||||
|
'DevOps': 'cyan',
|
||||||
|
'Data Science': 'red',
|
||||||
|
'Security': 'red',
|
||||||
|
'AI/ML': 'red'
|
||||||
|
};
|
||||||
|
return colorMap[categoryName] || 'blue';
|
||||||
|
};
|
||||||
|
|
||||||
|
const getStatusColor = (status) => {
|
||||||
|
const colorMap = {
|
||||||
|
'planning': 'default',
|
||||||
|
'in-progress': 'warning',
|
||||||
|
'review': 'processing',
|
||||||
|
'completed': 'success',
|
||||||
|
'on-hold': 'error'
|
||||||
|
};
|
||||||
|
return colorMap[status] || 'default';
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatStatus = (status) => {
|
||||||
|
const statusMap = {
|
||||||
|
'planning': 'Planning',
|
||||||
|
'in-progress': 'In Progress',
|
||||||
|
'review': 'Review',
|
||||||
|
'completed': 'Completed',
|
||||||
|
'on-hold': 'On Hold'
|
||||||
|
};
|
||||||
|
return statusMap[status] || status;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Load data on component mount
|
||||||
|
useEffect(() => {
|
||||||
|
loadProjects();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// Handle pagination change
|
||||||
|
const handleTableChange = (paginationInfo) => {
|
||||||
|
loadProjects(paginationInfo.current, paginationInfo.pageSize);
|
||||||
|
};
|
||||||
|
|
||||||
// Table columns configuration
|
// Table columns configuration
|
||||||
const columns = [
|
const columns = [
|
||||||
@ -443,18 +375,24 @@ const ProjectTracker = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="table-responsive">
|
<div className="table-responsive">
|
||||||
<Table
|
<Spin spinning={loading}>
|
||||||
rowSelection={rowSelection}
|
<Table
|
||||||
columns={columns}
|
rowSelection={rowSelection}
|
||||||
dataSource={projectData}
|
columns={columns}
|
||||||
pagination={{
|
dataSource={projectData}
|
||||||
pageSize: 10,
|
loading={loading}
|
||||||
showSizeChanger: true,
|
onChange={handleTableChange}
|
||||||
showQuickJumper: true,
|
pagination={{
|
||||||
showTotal: (total, range) =>
|
current: pagination.currentPage,
|
||||||
`Row Per Page: ${range[1] - range[0] + 1} Entries | Showing ${range[0]} to ${range[1]} of ${total} entries`
|
pageSize: pagination.pageSize,
|
||||||
}}
|
total: pagination.totalCount,
|
||||||
/>
|
showSizeChanger: true,
|
||||||
|
showQuickJumper: true,
|
||||||
|
showTotal: (total, range) =>
|
||||||
|
`Row Per Page: ${range[1] - range[0] + 1} Entries | Showing ${range[0]} to ${range[1]} of ${total} entries`
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Spin>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loadingβ¦
x
Reference in New Issue
Block a user