diff --git a/package-lock.json b/package-lock.json index 65edd11..a7e0050 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,10 @@ "axios": "^1.7.9", "chart.js": "^4.4.7", "date-fns": "^4.1.0", + "dhtmlx-gantt": "^9.0.3", "formik": "^2.4.6", + "highcharts": "^12.0.2", + "highcharts-react-official": "^3.2.1", "jspdf": "^2.5.2", "jspdf-autotable": "^3.8.4", "moment": "^2.30.1", @@ -7952,6 +7955,11 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/dhtmlx-gantt": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/dhtmlx-gantt/-/dhtmlx-gantt-9.0.3.tgz", + "integrity": "sha512-bc6ypBpp1XdE9s7iop5j+O41gLcfxg1nAerV1wHcmG11NxpYI5iOmSAAzdLfC8wqCnIOYQhRz7ca2t4KURFJhQ==" + }, "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", @@ -10655,6 +10663,20 @@ "he": "bin/he" } }, + "node_modules/highcharts": { + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/highcharts/-/highcharts-12.0.2.tgz", + "integrity": "sha512-DKZFNn2Mk3EUmOfJIvIgPqBjUoKDkDW9WY1nT9zrhfB9SSyg5yVbVEFrw267C4+Hzg4U1H/0i0Z6S3VYJwg6qQ==" + }, + "node_modules/highcharts-react-official": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/highcharts-react-official/-/highcharts-react-official-3.2.1.tgz", + "integrity": "sha512-hyQTX7ezCxl7JqumaWiGsroGWalzh24GedQIgO3vJbkGOZ6ySRAltIYjfxhrq4HszJOySZegotEF7v+haQ75UA==", + "peerDependencies": { + "highcharts": ">=6.0.0", + "react": ">=16.8.0" + } + }, "node_modules/hoist-non-react-statics": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", @@ -16584,7 +16606,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/react-google-charts/-/react-google-charts-5.2.1.tgz", "integrity": "sha512-mCbPiObP8yWM5A9ogej7Qp3/HX4EzOwuEzUYvcfHtL98Xt4V/brD14KgfDzSNNtyD48MNXCpq5oVaYKt0ykQUQ==", - "license": "MIT", "peerDependencies": { "react": ">=16.3.0", "react-dom": ">=16.3.0" diff --git a/package.json b/package.json index bacdddf..0daceb6 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,10 @@ "axios": "^1.7.9", "chart.js": "^4.4.7", "date-fns": "^4.1.0", + "dhtmlx-gantt": "^9.0.3", "formik": "^2.4.6", + "highcharts": "^12.0.2", + "highcharts-react-official": "^3.2.1", "jspdf": "^2.5.2", "jspdf-autotable": "^3.8.4", "moment": "^2.30.1", diff --git a/src/components/Authentication/Login.jsx b/src/components/Authentication/Login.jsx index a6bd008..2c3c5ec 100644 --- a/src/components/Authentication/Login.jsx +++ b/src/components/Authentication/Login.jsx @@ -27,7 +27,7 @@ const LoginSignup = () => { const user_id = response.data.user.id; const access_token = response.data.token; const { role } = response.data.user; - const chatUser = response.data.chat.user; + const chatUser = response.data.chat?.user; const project = response.data.user.project; dispatch(setLogin({ user_id, access_token, role, chatUser, project })); diff --git a/src/components/ProjectOnboarding.jsx b/src/components/ProjectOnboarding.jsx index 08ae151..a0e7413 100644 --- a/src/components/ProjectOnboarding.jsx +++ b/src/components/ProjectOnboarding.jsx @@ -4,12 +4,13 @@ import React, { useState } from 'react'; import { useSelector } from 'react-redux'; import { useNavigate } from 'react-router-dom'; import ProjectOutlay from './ProjectOutlay'; + // import ShowProjectOutlay from './ShowProjectOutlay'; // import { setProject } from '../state/index'; function ProjectForm() { - // const dispatch = useDispatch(); const navigate = useNavigate(); + // const dispatch = useDispatch(); const { user_id } = useSelector((state) => state.auth); const initialValues = { projectTitle: '', @@ -18,6 +19,7 @@ function ProjectForm() { principalImplementingAgency: { agencyName: '', projectInvestigatorName: '', + projectInvestigatorEmail: '', }, projectInvestigators: [], subImplementingAgencies: [], @@ -177,8 +179,11 @@ function ProjectForm() { fundingSource: formData.fundingSource, description: formData.description, principalImplementingAgency: { - principalImplementingAgency: formData.principalImplementingAgency, - principalInvestigator: formData.projectInvestigators, + principalImplementingAgency: + formData.principalImplementingAgency.agencyName, + principalInvestigatorName: + formData.projectInvestigators.projectInvestigatorName, + principalInvestigatorEmail: formData.projectinvestigationEmail, }, subImplementingAgencies: formData.subImplementingAgencies, projectInvestigators: formData.subImplementingAgencies.investigatorEmail, diff --git a/src/components/ProjectOutlay.jsx b/src/components/ProjectOutlay.jsx index f56f41a..22ae240 100644 --- a/src/components/ProjectOutlay.jsx +++ b/src/components/ProjectOutlay.jsx @@ -1,7 +1,7 @@ import React, { useState } from 'react'; const ProjectOutlay = ({ projectOutlay, agencyName, Title }) => { - const [numYears, setNumYears] = useState(3); // Default number of years + const [numYears, setNumYears] = useState(3); const [data, setData] = useState({ 'Capital Expenditure': { 'Land Building': { totalCost: '', yearWise: Array(numYears).fill('') }, diff --git a/src/components/ganttchart.jsx b/src/components/ganttchart.jsx index 240e4b7..d6d7890 100644 --- a/src/components/ganttchart.jsx +++ b/src/components/ganttchart.jsx @@ -1,22 +1,53 @@ -import axios from 'axios'; import React, { useState, useEffect } from 'react'; import { Chart } from 'react-google-charts'; -const GanttChart = ({ id }) => { - const [taskjson, setTaskjson] = useState(null); // State to store the fetched task data +const GanttChart = () => { const [chartData, setChartData] = useState([]); // State to store the chart data useEffect(() => { - // Fetch data from the API + const demoData = [ + { + id: 1, + startDate: '2024-01-01T00:00:00Z', + description: 'Feasibility Study for Coal Block A', + deadline: '2024-06-30T23:59:59Z', + }, + { + id: 2, + startDate: '2024-07-01T00:00:00Z', + description: 'Environmental Impact Assessment', + deadline: '2024-12-31T23:59:59Z', + }, + { + id: 3, + startDate: '2025-01-01T00:00:00Z', + description: 'Land Acquisition and Approvals', + deadline: '2025-06-30T23:59:59Z', + }, + { + id: 4, + startDate: '2025-07-01T00:00:00Z', + description: 'Equipment Procurement', + deadline: '2025-12-31T23:59:59Z', + }, + { + id: 5, + startDate: '2026-01-01T00:00:00Z', + description: 'Initial Mining Operations', + deadline: '2026-12-31T23:59:59Z', + }, + ]; + + // Transform tasks to the format required by the Gantt chart const transformTasksToChartData = (tasks) => { const header = [ - 'Task ID', - 'Task Name', - 'Start Date', - 'End Date', - 'Duration', - 'Percent Complete', - 'Dependencies', + 'Task ID', // ID of the task + 'Task Name', // Description of the task + 'Start Date', // Start date of the task + 'End Date', // Deadline of the task + 'Duration', // Duration in days + 'Percent Complete', // Progress completion percentage + 'Dependencies', // Task dependencies (null for this case) ]; const rows = tasks.map((task) => { @@ -25,38 +56,24 @@ const GanttChart = ({ id }) => { const endDate = parseDate(transformedTask.endDate); return [ transformedTask.id, // Task ID as a string - transformedTask.name, // Task Name - startDate, // Start Date - endDate, // End Date + transformedTask.name, // Task Name (description) + startDate, // Start Date (ISO format converted to Date object) + endDate, // End Date (ISO format converted to Date object) (endDate - startDate) / (1000 * 60 * 60 * 24), // Duration in days percentageComplete(startDate, endDate), // Percent Complete - transformedTask.dependencies, // Dependencies + transformedTask.dependencies, // Dependencies (null for now) ]; }); return [header, ...rows]; }; - const fetchData = async () => { - try { - const response = await axios.get( - `${process.env.REACT_APP_PROJECT_BASE_API}/api/projects/${id}/getMilestones` - ); - const data = response.data.notification || {}; - setTaskjson(data); - - // Generate chart data after fetching - if (data.tasks) { - const formattedData = transformTasksToChartData(data.tasks); - setChartData(formattedData); - } - } catch (error) { - console.error('Error fetching data:', error); - } - }; - fetchData(); - }, [id]); + // Process the demo data + const formattedData = transformTasksToChartData(demoData); + setChartData(formattedData); + }, []); + // Calculate the percentage of completion for the Gantt task const percentageComplete = (startDate, endDate) => { const currentDate = Date.now(); if (currentDate >= endDate.getTime()) return 100; @@ -66,41 +83,41 @@ const GanttChart = ({ id }) => { ); }; + // Transform task data to the required Gantt format const transformDataToGanttJson = (task) => ({ id: task.id, // Ensure Task ID is a string name: task.description, // Map description to name - startDate: task.startDate.split('T')[0], // Extract date from ISO format - endDate: task.deadline.split('T')[0], // Extract date from ISO format - dependencies: null, // Default dependencies to null + startDate: task.startDate.split('T')[0], // Extract date from ISO format (YYYY-MM-DD) + endDate: task.deadline.split('T')[0], // Extract date from ISO format (YYYY-MM-DD) + dependencies: null, // Default dependencies to null (none in this case) }); + // Parse date from "YYYY-MM-DD" string format to JavaScript Date object const parseDate = (dateString) => { const [year, month, day] = dateString.split('-').map(Number); return new Date(year, month - 1, day); // Month is zero-based }; const options = { - height: 400, + // height: 400, gantt: { criticalPathEnabled: true, // Highlight the critical path criticalPathStyle: { stroke: '#e64a19', // Red color for critical path strokeWidth: 2, }, + innerGridTrack: { fill: '#f9f9f9' }, + innerGridDarkTrack: { fill: '#dedede' }, }, }; - if (!taskjson) { - return