diff --git a/app/spa/src/components/Projects/ProjectChartsTable.tsx b/app/spa/src/components/Projects/ProjectChartsTable.tsx
index 08d4c975a..42e4eac53 100644
--- a/app/spa/src/components/Projects/ProjectChartsTable.tsx
+++ b/app/spa/src/components/Projects/ProjectChartsTable.tsx
@@ -1,6 +1,8 @@
import { useState } from "react"
import {
+ Backdrop,
Box,
+ CircularProgress,
Grid,
Link,
Paper,
@@ -15,7 +17,6 @@ import {
import { gql, useQuery } from "@apollo/client"
import { useTranslation } from "react-i18next"
import { useParams } from "react-router-dom"
-import { Backdrop, CircularProgress } from "@mui/material"
import { formatDate, secondsToDays } from "../../lib/date"
import { DemandsList } from "../../modules/demand/demand.types"
import { Project } from "../../modules/project/project.types"
@@ -192,7 +193,7 @@ const ProjectChartsTable = () => {
{t("details.start")} |
{formatDate({
- date: project.startDate,
+ date: project.startDate || "",
format: "dd/MM/yyyy",
})}
|
@@ -202,7 +203,10 @@ const ProjectChartsTable = () => {
{t("details.end")}
- {formatDate({ date: project.endDate, format: "dd/MM/yyyy" })}
+ {formatDate({
+ date: project.endDate || "",
+ format: "dd/MM/yyyy",
+ })}
|
@@ -279,7 +283,7 @@ const ProjectChartsTable = () => {
})}
sx={{ color: "info.dark", textDecoration: "none" }}
>
- {project.upstreamDemands.length}
+ {project.upstreamDemands?.length}
@@ -313,7 +317,7 @@ const ProjectChartsTable = () => {
})}
sx={{ color: "info.dark", textDecoration: "none" }}
>
- {project.discardedDemands.length}
+ {project.discardedDemands?.length}
@@ -328,7 +332,7 @@ const ProjectChartsTable = () => {
})}
sx={{ color: "info.dark", textDecoration: "none" }}
>
- {project.unscoredDemands.length}
+ {project.unscoredDemands?.length}
@@ -339,18 +343,18 @@ const ProjectChartsTable = () => {
href={`/companies/${companySlug}/demand_blocks`}
sx={{ color: "info.dark", textDecoration: "none" }}
>
- {project.demandBlocks.length}
+ {project.demandBlocks?.length}
{t("details.flowPressure")} |
- {project.flowPressure.toFixed(2)} |
+ {project.flowPressure?.toFixed(2)} |
{tDemands("list.demandsTable.averageSpeed", {
- numberOfDemandsPerDay: project.averageSpeed.toFixed(2),
+ numberOfDemandsPerDay: project.averageSpeed?.toFixed(2),
})}
|
diff --git a/app/spa/src/components/Projects/ProjectDemandsCharts.tsx b/app/spa/src/components/Projects/ProjectDemandsCharts.tsx
index 460208ddb..35258bb74 100644
--- a/app/spa/src/components/Projects/ProjectDemandsCharts.tsx
+++ b/app/spa/src/components/Projects/ProjectDemandsCharts.tsx
@@ -4,38 +4,32 @@ import { useTranslation } from "react-i18next"
import { ChartGridItem } from "../charts/ChartGridItem"
import { BarChart } from "../charts/BarChart"
-import { LineChart } from "../charts/LineChart"
-import { normalizeCfdData } from "../charts/LineChart"
-import { ScatterChart } from "../charts/ScatterChart"
+import { LineChart, normalizeCfdData } from "../charts/LineChart"
import LineChartTooltip from "./../charts/tooltips/LineChartTooltip"
import { secondsToDays } from "../../lib/date"
import { Project } from "../../modules/project/project.types"
import { Grid } from "@mui/material"
-import { useContext } from "react"
-import { MeContext } from "../../contexts/MeContext"
import { ChartAxisData } from "../../modules/charts/charts.types"
import { cfdChartData } from "../../lib/charts"
-import { useNavigate } from "react-router-dom"
import { buildBurnupData } from "../../utils/charts"
import ProjectBurnup from "../../pages/Projects/Charts/ProjectBurnup"
+import ProjectLeadTime from "../../pages/Projects/Charts/ProjectLeadTime"
+import ProjectLeadTimeControlChart from "../../pages/Projects/Charts/ProjectLeadTimeControlChart"
type ProjectDemandsChartsProps = {
project: Project
hoursPerCoordinationStageChartData?: ChartAxisData
}
+// eslint-disable-next-line complexity
const ProjectDemandsCharts = ({
project,
hoursPerCoordinationStageChartData,
}: ProjectDemandsChartsProps) => {
const { t } = useTranslation(["projectChart"])
- const { me } = useContext(MeContext)
- const navigate = useNavigate()
const projectConsolidationsWeekly = project.projectConsolidationsWeekly
const projectConsolidationsLastMonth = project.projectConsolidationsLastMonth
- const demandsFinishedWithLeadtime = project.demandsFinishedWithLeadtime
- const lastProjectConsolidationsWeekly =
- project.lastProjectConsolidationsWeekly
+
const demandsFlowChartData = project.demandsFlowChartData
const leadTimeHistogramData = project.leadTimeHistogramData
const leadTimeBreakdownData = project.leadTimeBreakdown
@@ -45,26 +39,28 @@ const ProjectDemandsCharts = ({
const operationalRiskChartData = [
{
id: t("chartsTab.projectCharts.operational_math_risk_evolution_chart"),
- data: projectConsolidationsWeekly.map(
- ({ consolidationDate, operationalRisk }) => {
- return {
- x: consolidationDate,
- y: operationalRisk * 100,
+ data:
+ projectConsolidationsWeekly?.map(
+ ({ consolidationDate, operationalRisk }) => {
+ return {
+ x: consolidationDate || "",
+ y: (operationalRisk || 0) * 100,
+ }
}
- }
- ),
+ ) || [],
},
]
- const projectBugsChartData: BarDatum[] = projectConsolidationsWeekly.map(
- ({ bugsOpened, bugsClosed, consolidationDate }) => {
- return {
- index: consolidationDate,
- [t("chartsTab.projectCharts.bugs_openned")]: bugsOpened,
- [t("chartsTab.projectCharts.bugs_closed")]: bugsClosed,
+ const projectBugsChartData: BarDatum[] =
+ projectConsolidationsWeekly?.map(
+ ({ bugsOpened, bugsClosed, consolidationDate }) => {
+ return {
+ index: consolidationDate,
+ [t("chartsTab.projectCharts.bugs_opened")]: bugsOpened,
+ [t("chartsTab.projectCharts.bugs_closed")]: bugsClosed,
+ }
}
- }
- )
+ ) || []
const cfdXaxis = cumulativeFlowChartData?.xAxis || []
const cfdYaxis = cumulativeFlowChartData?.yAxis.reverse() || []
@@ -124,177 +120,123 @@ const ProjectDemandsCharts = ({
project.hoursBurnup
)
- const leadTimeP80ChartData = [
- {
- id: project.name,
- data: projectConsolidationsWeekly.map(
- ({ leadTimeP80, consolidationDate }) => {
- const leadTimep80InDays = secondsToDays(leadTimeP80)
-
- return {
- x: consolidationDate,
- y: leadTimep80InDays,
- }
- }
- ),
- },
- ]
-
const projectQualityChartData = [
{
- id: project.name,
- data: projectConsolidationsWeekly.map(
- ({ consolidationDate, projectQuality }) => ({
- x: consolidationDate,
- y: (1 - projectQuality) * 100,
- })
- ),
- },
- ]
-
- const leadTimeControlChartData = [
- {
- id: t("chartsTab.projectCharts.lead_time_control_label"),
+ id: project.name || "",
data:
- demandsFinishedWithLeadtime?.map(({ externalId, leadtime }) => {
- const leadTimeInDays = secondsToDays(leadtime)
-
- return {
- x: externalId,
- y: leadTimeInDays,
- }
- }) || [],
+ projectConsolidationsWeekly?.map(
+ ({ consolidationDate, projectQuality }) => ({
+ x: consolidationDate,
+ y: (1 - projectQuality) * 100,
+ })
+ ) || [],
},
]
- const leadTimeP65InDays = secondsToDays(
- lastProjectConsolidationsWeekly?.leadTimeP65
- )
- const leadTimeP80InDays = secondsToDays(
- lastProjectConsolidationsWeekly?.leadTimeP80
- )
- const leadTimeP95InDays = secondsToDays(
- lastProjectConsolidationsWeekly?.leadTimeP95
- )
-
- const leadTimeControlP65Marker = {
- value: leadTimeP65InDays,
- legend: t("chartsTab.projectCharts.lead_time_control_marker_p65", {
- leadTime: leadTimeP65InDays,
- }),
- }
-
- const leadTimeControlP80Marker = {
- value: leadTimeP80InDays,
- legend: t("chartsTab.projectCharts.lead_time_control_marker_p80", {
- leadTime: leadTimeP80InDays,
- }),
- }
-
- const leadTimeControlP95Marker = {
- value: leadTimeP95InDays,
- legend: t("chartsTab.projectCharts.lead_time_control_marker_p95", {
- leadTime: leadTimeP95InDays,
- }),
- }
-
const projectQualityForCodingChartData = [
{
id: project.name || "",
- data: projectConsolidationsWeekly.map(
- ({ consolidationDate, codeNeededBlocksCount }) => ({
- x: consolidationDate,
- y: codeNeededBlocksCount,
- })
- ),
+ data:
+ projectConsolidationsWeekly?.map(
+ ({ consolidationDate, codeNeededBlocksCount }) => ({
+ x: consolidationDate,
+ y: codeNeededBlocksCount,
+ })
+ ) || [],
},
]
const projectQualityForCodingPerDemand = [
{
id: project.name || "",
- data: projectConsolidationsWeekly.map(
- ({ consolidationDate, codeNeededBlocksPerDemand }) => ({
- x: consolidationDate,
- y: codeNeededBlocksPerDemand,
- })
- ),
+ data:
+ projectConsolidationsWeekly?.map(
+ ({ consolidationDate, codeNeededBlocksPerDemand }) => ({
+ x: consolidationDate,
+ y: codeNeededBlocksPerDemand,
+ })
+ ) || [],
},
]
const flowEfficiencyChartData = [
{
id: project.name || "",
- data: projectConsolidationsWeekly.map(
- ({ consolidationDate, flowEfficiency }) => {
- return {
- x: consolidationDate,
- y: flowEfficiency,
+ data:
+ projectConsolidationsWeekly?.map(
+ ({ consolidationDate, flowEfficiency }) => {
+ return {
+ x: consolidationDate,
+ y: flowEfficiency,
+ }
}
- }
- ),
+ ) || [],
},
]
const hoursPerDemandChartData = [
{
id: project.name || "",
- data: projectConsolidationsWeekly.map(
- ({ consolidationDate, hoursPerDemand }) => {
- return {
- x: consolidationDate,
- y: hoursPerDemand.toFixed(2),
+ data:
+ projectConsolidationsWeekly?.map(
+ ({ consolidationDate, hoursPerDemand }) => {
+ return {
+ x: consolidationDate,
+ y: hoursPerDemand.toFixed(2),
+ }
}
- }
- ),
+ ) || [],
},
]
- const projectHoursConsummed = projectConsolidationsWeekly.map(
- ({
- consolidationDate,
- projectThroughputHours,
- projectThroughputHoursAdditional,
- projectThroughputHoursUpstream,
- projectThroughputHoursDownstream,
- }) => {
- return {
- [t("chartsTab.projectCharts.hours_consumed_x_label")]:
- consolidationDate,
- [t("chartsTab.projectCharts.hours_consumed_upstream")]:
- projectThroughputHoursUpstream.toFixed(2),
- [t("chartsTab.projectCharts.hours_consumed_downstream")]:
- projectThroughputHoursDownstream.toFixed(2),
- [t("chartsTab.projectCharts.additional_hours_consumed")]:
- projectThroughputHoursAdditional?.toFixed(2) || 0,
- [t("chartsTab.projectCharts.hours_consumed_total_throughput")]:
- projectThroughputHours.toFixed(2),
+ const projectHoursConsummed =
+ projectConsolidationsWeekly?.map(
+ ({
+ consolidationDate,
+ projectThroughputHours,
+ projectThroughputHoursAdditional,
+ projectThroughputHoursUpstream,
+ projectThroughputHoursDownstream,
+ }) => {
+ return {
+ [t("chartsTab.projectCharts.hours_consumed_x_label")]:
+ consolidationDate,
+ [t("chartsTab.projectCharts.hours_consumed_upstream")]:
+ projectThroughputHoursUpstream.toFixed(2),
+ [t("chartsTab.projectCharts.hours_consumed_downstream")]:
+ projectThroughputHoursDownstream.toFixed(2),
+ [t("chartsTab.projectCharts.additional_hours_consumed")]:
+ projectThroughputHoursAdditional?.toFixed(2) || 0,
+ [t("chartsTab.projectCharts.hours_consumed_total_throughput")]:
+ projectThroughputHours.toFixed(2),
+ }
}
- }
- )
+ ) || []
- const projectConsumedHoursByRoleChartData = projectConsolidationsWeekly.map(
- ({
- consolidationDate,
- projectThroughputHours,
- projectThroughputHoursManagement,
- projectThroughputHoursDevelopment,
- projectThroughputHoursDesign,
- }) => {
- return {
- period: consolidationDate,
- [t("chartsTab.projectCharts.consumed_hours_by_role_design_effort")]:
- projectThroughputHoursDesign.toFixed(2),
- [t(
- "chartsTab.projectCharts.consumed_hours_by_role_development_effort"
- )]: projectThroughputHoursDevelopment.toFixed(2),
- [t("chartsTab.projectCharts.consumed_hours_by_role_management_effort")]:
- projectThroughputHoursManagement.toFixed(2),
- [t("chartsTab.projectCharts.consumed_hours_by_role_total_effort")]:
- projectThroughputHours.toFixed(2),
+ const projectConsumedHoursByRoleChartData =
+ projectConsolidationsWeekly?.map(
+ ({
+ consolidationDate,
+ projectThroughputHours,
+ projectThroughputHoursManagement,
+ projectThroughputHoursDevelopment,
+ projectThroughputHoursDesign,
+ }) => {
+ return {
+ period: consolidationDate,
+ [t("chartsTab.projectCharts.consumed_hours_by_role_design_effort")]:
+ projectThroughputHoursDesign.toFixed(2),
+ [t(
+ "chartsTab.projectCharts.consumed_hours_by_role_development_effort"
+ )]: projectThroughputHoursDevelopment.toFixed(2),
+ [t(
+ "chartsTab.projectCharts.consumed_hours_by_role_management_effort"
+ )]: projectThroughputHoursManagement.toFixed(2),
+ [t("chartsTab.projectCharts.consumed_hours_by_role_total_effort")]:
+ projectThroughputHours.toFixed(2),
+ }
}
- }
- )
+ ) || []
const projectConsumedHoursByRoleInMonthChartData =
projectConsolidationsLastMonth?.map(
@@ -430,43 +372,11 @@ const ProjectDemandsCharts = ({
}}
/>
-
- (
-
- ),
- }}
- />
-
-
- {
- navigate(
- `/companies/${me?.currentCompany?.slug}/demands/${props.data.x}`
- )
- }}
- />
-
+
+
+
+
diff --git a/app/spa/src/components/ReplenishingProjectsInfo.tsx b/app/spa/src/components/ReplenishingProjectsInfo.tsx
index e8d2b5fb6..4d58b8676 100644
--- a/app/spa/src/components/ReplenishingProjectsInfo.tsx
+++ b/app/spa/src/components/ReplenishingProjectsInfo.tsx
@@ -1,13 +1,13 @@
import {
+ Collapse,
+ IconButton,
+ Link,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow as MaterialTableRow,
- IconButton,
- Collapse,
- Link,
} from "@mui/material"
import { Box } from "@mui/system"
import { Fragment, useState } from "react"
@@ -63,31 +63,31 @@ const TableRow = ({ project, companySlug }: TableRowProps) => {
height: "24px",
borderRadius: "50%",
backgroundColor: getCustomerHappinessColor(
- project.customerHappiness
+ project.customerHappiness || 0
),
}}
/>
{project.remainingBacklog} demandas
- {project.flowPressurePercentage.toFixed(2)}%
- {secondsToReadbleDate(project.leadTimeP80)}
+ {project.flowPressurePercentage?.toFixed(2)}%
+ {secondsToReadbleDate(project.leadTimeP80 || 0)}
{project.qtyInProgress} demandas
{project.startDate}
{project.endDate}
- {project.monteCarloP80.toFixed(2)}
+ {project.monteCarloP80?.toFixed(2)}
-
+
- {project.customers.map(({ name, id }) => (
+ {project.customers?.map(({ name, id }) => (
{name}
))}
- {project.customerHappiness.toFixed(2)}
+ {project.customerHappiness?.toFixed(2)}
- {project.flowPressure.toFixed(2)}
+ {project.flowPressure?.toFixed(2)}
Limite de WiP: {project.maxWorkInProgress}
Idade: {project.aging} dias
@@ -95,9 +95,9 @@ const TableRow = ({ project, companySlug }: TableRowProps) => {
@@ -106,8 +106,8 @@ const TableRow = ({ project, companySlug }: TableRowProps) => {
-
- {project.products.map(({ name, id }) => (
+
+ {project.products?.map(({ name, id }) => (
{name}
@@ -119,38 +119,38 @@ const TableRow = ({ project, companySlug }: TableRowProps) => {
Dados do time:
-
+
Mín: {project.teamMonteCarloWeeksMin}
-
+
Monte Carlo 80%: {project.teamMonteCarloP80}
-
- Throughputs: ({project.weeklyThroughputs.join(", ")})
+
+ Throughputs: ({project.weeklyThroughputs?.join(", ")})
-
+
Máx: {project.teamMonteCarloWeeksMax}
-
+
Desvio padrão:{" "}
- {project.teamMonteCarloWeeksStdDev.toFixed(2)}
+ {project.teamMonteCarloWeeksStdDev?.toFixed(2)}
-
+
Selecionadas: {project.qtySelected}
-
+
Chances da data:{" "}
- {(project.teamBasedOddsToDeadline * 100).toFixed(2)}%
+ {((project.teamBasedOddsToDeadline || 0) * 100).toFixed(2)}%
diff --git a/app/spa/src/components/ReplenishingTeamInfo.tsx b/app/spa/src/components/ReplenishingTeamInfo.tsx
index 1b47a6dd1..1088b2d88 100644
--- a/app/spa/src/components/ReplenishingTeamInfo.tsx
+++ b/app/spa/src/components/ReplenishingTeamInfo.tsx
@@ -1,4 +1,4 @@
-import { Typography, Grid, Divider } from "@mui/material"
+import { Divider, Grid, Typography } from "@mui/material"
import { Box } from "@mui/system"
import { Fragment } from "react"
import { Project } from "../modules/project/project.types"
@@ -22,7 +22,7 @@ type ReplenishmentTeamInfoProps = {
}
export const getWipLimits = (projects: Project[]): number[] =>
- projects.map(({ maxWorkInProgress }) => maxWorkInProgress)
+ projects.map(({ maxWorkInProgress }) => maxWorkInProgress || 0)
export const isTeamWipLimitSurpassed = (
projects: Project[],
diff --git a/app/spa/src/components/TeamMemberDashboardTables.tsx b/app/spa/src/components/TeamMemberDashboardTables.tsx
index 879fe0abf..336a19636 100644
--- a/app/spa/src/components/TeamMemberDashboardTables.tsx
+++ b/app/spa/src/components/TeamMemberDashboardTables.tsx
@@ -158,8 +158,8 @@ const TeamMemberDashboardTables = ({
>
{project.name}
,
- ,
- ,
+ ,
+ ,
`${((project.currentRiskToDeadline || 0) * 100).toFixed(2)}%`,
`${((project.quality || 0) * 100).toFixed(2)}%`,
`${secondsToDays(project.leadTimeP80)} ${t("dashboard.days")}`,
diff --git a/app/spa/src/components/charts/ScatterChart.tsx b/app/spa/src/components/charts/ScatterChart.tsx
index fc022e00a..8b571e3f3 100644
--- a/app/spa/src/components/charts/ScatterChart.tsx
+++ b/app/spa/src/components/charts/ScatterChart.tsx
@@ -52,7 +52,7 @@ export const ScatterChart = ({
const chartData = Array.isArray(data)
? data
: axisDataToScatter(data, "Demands")
- const bottomAxisTicks = chartData[0].data.map((item) => item.x)
+ const bottomAxisTicks = chartData[0]?.data.map((item) => item.x)
const chartMarkers: NivoMarker[] =
markers?.map(({ value, legend }) => ({
axis: "y",
@@ -122,9 +122,9 @@ export const ScatterChart = ({
markers={chartMarkers}
tooltip={({ node }) => (
- {node.data.x}
+ {node?.data.x}
- Lead time: {node.data.y} {t("days")}
+ Lead time: {node?.data.y} {t("days")}
)}
enableGridX={false}
diff --git a/app/spa/src/locales/en/projectChart.json b/app/spa/src/locales/en/projectChart.json
index e6e2125f7..6023598f7 100644
--- a/app/spa/src/locales/en/projectChart.json
+++ b/app/spa/src/locales/en/projectChart.json
@@ -24,7 +24,7 @@
"operationalRisk": "Operational Risk (%)",
"bugs_chart": "Bugs",
"bugs_y_label": "Bugs",
- "bugs_openned": "Bugs Openned",
+ "bugs_opened": "Bugs Openned",
"bugs_closed": "Bugs Closed",
"demandsBurnupChart": "Demands Burnup for {{projectName}}",
"demandsBurnupYLabel": "Demands",
diff --git a/app/spa/src/locales/pt/projectChart.json b/app/spa/src/locales/pt/projectChart.json
index d92cc5d1e..f7068d362 100644
--- a/app/spa/src/locales/pt/projectChart.json
+++ b/app/spa/src/locales/pt/projectChart.json
@@ -24,7 +24,7 @@
"operationalRisk": "Risco Operacional (%)",
"bugs_chart": "Bugs",
"bugs_y_label": "Bugs",
- "bugs_openned": "Bugs Abertos",
+ "bugs_opened": "Bugs Abertos",
"bugs_closed": "Bugs Fechados",
"demandsBurnupChart": "Burn Up de Demandas para {{projectName}}",
"demandsBurnupYLabel": "Demandas",
diff --git a/app/spa/src/modules/project/components/ProjectsTable.tsx b/app/spa/src/modules/project/components/ProjectsTable.tsx
index dab0408fb..a9c3ea5cf 100644
--- a/app/spa/src/modules/project/components/ProjectsTable.tsx
+++ b/app/spa/src/modules/project/components/ProjectsTable.tsx
@@ -2,12 +2,12 @@ import { gql, useQuery } from "@apollo/client"
import { useTranslation } from "react-i18next"
import {
Backdrop,
- CircularProgress,
Box,
+ CircularProgress,
LinearProgress,
- styled,
linearProgressClasses,
Link,
+ styled,
Typography,
} from "@mui/material"
@@ -124,8 +124,8 @@ const ProjectsTable = ({ projectsFilters }: ProjectsTableProps) => {
{project.team?.name}
,
project.status,
- ,
- ,
+ ,
+ ,
`${project.numberOfDemands} ${t("projectsTable.row_demands")}`,
`${project.remainingDays} ${t("projectsTable.row_days")}`,
`${project.numberOfDemandsDelivered} ${t(
@@ -145,14 +145,14 @@ const ProjectsTable = ({ projectsFilters }: ProjectsTableProps) => {
>
- {`${project.consumedHours.toFixed(2)}h ${t(
+ {`${project.consumedHours?.toFixed(2)}h ${t(
"projectsTable.row_consumed"
)}`}
@@ -168,7 +168,7 @@ const ProjectsTable = ({ projectsFilters }: ProjectsTableProps) => {
],
collapseBody: [
project.customersNames,
- formatCurrency(project.value),
+ formatCurrency(project.value || 0),
project.maxWorkInProgress,
],
},
diff --git a/app/spa/src/modules/project/project.types.ts b/app/spa/src/modules/project/project.types.ts
index aa3f5639d..2424173e9 100644
--- a/app/spa/src/modules/project/project.types.ts
+++ b/app/spa/src/modules/project/project.types.ts
@@ -13,87 +13,86 @@ import {
import { Team } from "../team/team.types"
export type Project = {
- company?: Company
- customers: Customer[]
- products: Product[]
- latestDeliveries: Demand[]
-
id: string
- name: string
- customersNames: string
+ company?: Company
+ customers?: Customer[]
+ products?: Product[]
+ latestDeliveries?: Demand[]
+ name?: string
+ customersNames?: string
quality?: number
- team: Team
- status: string
- qtyHours: number
- consumedHours: number
- percentageHoursDelivered: number
- remainingWeeks: number
- remainingBacklog: number
- backlogCountFor: number
- flowPressure: number
- flowPressurePercentage: number
- pastWeeks: number
- remainingWork: number
- leadTimeP65: number
- leadTimeP80: number
- leadTimeP95: number
- qtySelected: number
- qtyInProgress: number
- monteCarloP80: number
- maxWorkInProgress: number
- lastWeekThroughput: number
- weeklyThroughputs: number[]
- modeWeeklyTroughputs: number
- stdDevWeeklyTroughputs: number
- currentMonteCarloWeeksMin: number
- currentMonteCarloWeeksMax: number
- currentMonteCarloWeeksStdDev: number
- currentWeeksByLittleLaw: number
- teamMonteCarloP80: number
- teamMonteCarloWeeksMin: number
- teamMonteCarloWeeksMax: number
- teamMonteCarloWeeksStdDev: number
- teamBasedOddsToDeadline: number
- customerHappiness: number
- startDate: string
- endDate: string
- aging: number
- firstDeadline: string
- daysDifferenceBetweenFirstAndLastDeadlines: number
- deadlinesChangeCount: number
- currentCost: number
- totalHoursConsumed: number
- averageSpeed: number
- averageDemandAging: number
- numberOfDemands: number
- numberOfDemandsDelivered: number
- numberOfRemainingBacklog: number
- totalThroughput: number
- failureLoad: number
- discoveredScope: number
- scope: number
- initialScope: number
- projectConsolidations: ProjectConsolidation[]
- projectConsolidationsWeekly: ProjectConsolidation[]
- projectConsolidationsLastMonth: ProjectConsolidation[]
+ team?: Team
+ status?: string
+ qtyHours?: number
+ consumedHours?: number
+ percentageHoursDelivered?: number
+ remainingWeeks?: number
+ remainingBacklog?: number
+ backlogCountFor?: number
+ flowPressure?: number
+ flowPressurePercentage?: number
+ pastWeeks?: number
+ remainingWork?: number
+ leadTimeP65?: number
+ leadTimeP80?: number
+ leadTimeP95?: number
+ qtySelected?: number
+ qtyInProgress?: number
+ monteCarloP80?: number
+ maxWorkInProgress?: number
+ lastWeekThroughput?: number
+ weeklyThroughputs?: number[]
+ modeWeeklyTroughputs?: number
+ stdDevWeeklyTroughputs?: number
+ currentMonteCarloWeeksMin?: number
+ currentMonteCarloWeeksMax?: number
+ currentMonteCarloWeeksStdDev?: number
+ currentWeeksByLittleLaw?: number
+ teamMonteCarloP80?: number
+ teamMonteCarloWeeksMin?: number
+ teamMonteCarloWeeksMax?: number
+ teamMonteCarloWeeksStdDev?: number
+ teamBasedOddsToDeadline?: number
+ customerHappiness?: number
+ startDate?: string
+ endDate?: string
+ aging?: number
+ firstDeadline?: string
+ daysDifferenceBetweenFirstAndLastDeadlines?: number
+ deadlinesChangeCount?: number
+ currentCost?: number
+ totalHoursConsumed?: number
+ averageSpeed?: number
+ averageDemandAging?: number
+ numberOfDemands?: number
+ numberOfDemandsDelivered?: number
+ numberOfRemainingBacklog?: number
+ totalThroughput?: number
+ failureLoad?: number
+ discoveredScope?: number
+ scope?: number
+ initialScope?: number
+ projectConsolidations?: ProjectConsolidation[]
+ projectConsolidationsWeekly?: ProjectConsolidation[]
+ projectConsolidationsLastMonth?: ProjectConsolidation[]
lastProjectConsolidationsWeekly?: ProjectConsolidation
currentRiskToDeadline?: number
- remainingDays: number
- currentTeamBasedRisk: number
- running: boolean
- upstreamDemands: Demand[]
- discardedDemands: Demand[]
- unscoredDemands: Demand[]
- demandBlocks: Demand[]
- demandsFinishedWithLeadtime: Demand[]
- numberOfDownstreamDemands: number
- averageQueueTime: number
- averageTouchTime: number
- value: number
+ remainingDays?: number
+ currentTeamBasedRisk?: number
+ running?: boolean
+ upstreamDemands?: Demand[]
+ discardedDemands?: Demand[]
+ unscoredDemands?: Demand[]
+ demandBlocks?: Demand[]
+ demandsFinishedWithLeadtime?: Demand[]
+ numberOfDownstreamDemands?: number
+ averageQueueTime?: number
+ averageTouchTime?: number
+ value?: number
projectMembers: {
- demandsCount: number
- memberName: string
+ demandsCount?: number
+ memberName?: string
}[]
hoursPerStageChartData: ChartAxisData
leadTimeBreakdown: NumberChartData
@@ -112,13 +111,13 @@ export type Project = {
}
export type Burnup = {
- idealBurn: number[]
- scope: number[]
- currentBurn: number[]
+ idealBurn?: number[]
+ scope?: number[]
+ currentBurn?: number[]
xAxis: string[]
}
export type ProjectsList = {
- totalCount: number
+ totalCount?: number
projects: Project[]
}
diff --git a/app/spa/src/pages/Projects/Charts/ProjectLeadTime.tsx b/app/spa/src/pages/Projects/Charts/ProjectLeadTime.tsx
new file mode 100644
index 000000000..fb41f8fa3
--- /dev/null
+++ b/app/spa/src/pages/Projects/Charts/ProjectLeadTime.tsx
@@ -0,0 +1,51 @@
+import { LineChart } from "../../../components/charts/LineChart"
+import { SliceTooltipProps } from "@nivo/line"
+import LineChartTooltip from "../../../components/charts/tooltips/LineChartTooltip"
+import { ChartGridItem } from "../../../components/charts/ChartGridItem"
+import { secondsToDays } from "../../../lib/date"
+import { Project } from "../../../modules/project/project.types"
+import { useTranslation } from "react-i18next"
+
+const ProjectLeadTime = ({ project }: ProjectLeadTimeProps) => {
+ const { t } = useTranslation(["projectChart"])
+
+ const projectConsolidationsWeekly = project.projectConsolidationsWeekly
+ const leadTimeP80ChartData = [
+ {
+ id: project.name || "",
+ data:
+ projectConsolidationsWeekly?.map(
+ ({ leadTimeP80, consolidationDate }) => {
+ const leadTimeP80InDays = secondsToDays(leadTimeP80)
+
+ return {
+ x: consolidationDate,
+ y: leadTimeP80InDays,
+ }
+ }
+ ) || [],
+ },
+ ]
+
+ return (
+
+ (
+
+ ),
+ }}
+ />
+
+ )
+}
+
+type ProjectLeadTimeProps = {
+ project: Project
+}
+
+export default ProjectLeadTime
diff --git a/app/spa/src/pages/Projects/Charts/ProjectLeadTimeControlChart.tsx b/app/spa/src/pages/Projects/Charts/ProjectLeadTimeControlChart.tsx
new file mode 100644
index 000000000..03fddc4a4
--- /dev/null
+++ b/app/spa/src/pages/Projects/Charts/ProjectLeadTimeControlChart.tsx
@@ -0,0 +1,93 @@
+import { ScatterChart } from "../../../components/charts/ScatterChart"
+import { ChartGridItem } from "../../../components/charts/ChartGridItem"
+import { secondsToDays } from "../../../lib/date"
+import { useTranslation } from "react-i18next"
+import { useNavigate } from "react-router-dom"
+import { useContext } from "react"
+import { MeContext } from "../../../contexts/MeContext"
+import { Project } from "../../../modules/project/project.types"
+
+const ProjectLeadTimeControlChart = ({
+ project,
+}: ProjectLeadTimeControlChartProps) => {
+ const { t } = useTranslation(["projectChart"])
+ const navigate = useNavigate()
+ const { me } = useContext(MeContext)
+
+ const demandsFinishedWithLeadtime = project.demandsFinishedWithLeadtime
+ const leadTimeControlChartData = [
+ {
+ id: t("chartsTab.projectCharts.lead_time_control_label"),
+ data:
+ demandsFinishedWithLeadtime?.map(({ externalId, leadtime }) => {
+ const leadTimeInDays = secondsToDays(leadtime)
+
+ return {
+ x: externalId,
+ y: leadTimeInDays,
+ }
+ }) || [],
+ },
+ ]
+
+ const lastProjectConsolidationsWeekly =
+ project.lastProjectConsolidationsWeekly
+ const leadTimeP65InDays = secondsToDays(
+ lastProjectConsolidationsWeekly?.leadTimeP65
+ )
+ const leadTimeP80InDays = secondsToDays(
+ lastProjectConsolidationsWeekly?.leadTimeP80
+ )
+ const leadTimeP95InDays = secondsToDays(
+ lastProjectConsolidationsWeekly?.leadTimeP95
+ )
+
+ const leadTimeControlP65Marker = {
+ value: leadTimeP65InDays,
+ legend: t("chartsTab.projectCharts.lead_time_control_marker_p65", {
+ leadTime: leadTimeP65InDays,
+ }),
+ }
+
+ const leadTimeControlP80Marker = {
+ value: leadTimeP80InDays,
+ legend: t("chartsTab.projectCharts.lead_time_control_marker_p80", {
+ leadTime: leadTimeP80InDays,
+ }),
+ }
+
+ const leadTimeControlP95Marker = {
+ value: leadTimeP95InDays,
+ legend: t("chartsTab.projectCharts.lead_time_control_marker_p95", {
+ leadTime: leadTimeP95InDays,
+ }),
+ }
+
+ return (
+
+ {
+ navigate(
+ `/companies/${me?.currentCompany?.slug}/demands/${props.data.x}`
+ )
+ }}
+ />
+
+ )
+}
+
+type ProjectLeadTimeControlChartProps = {
+ project: Project
+}
+
+export default ProjectLeadTimeControlChart
diff --git a/app/spa/src/pages/Projects/DemandsCharts.tsx b/app/spa/src/pages/Projects/DemandsCharts.tsx
index 6aa22a43b..b96b2ea72 100644
--- a/app/spa/src/pages/Projects/DemandsCharts.tsx
+++ b/app/spa/src/pages/Projects/DemandsCharts.tsx
@@ -142,8 +142,8 @@ const PROJECT_CHART_QUERY = gql`
`
type ProjectChartResult = {
- project: Project
- hoursPerCoordinationStageChartData: Pick
+ project?: Project
+ hoursPerCoordinationStageChartData?: Pick
}
type ProjectChartDTO = ProjectChartResult | undefined
@@ -166,7 +166,7 @@ const DemandsCharts = () => {
const project = data?.project
const hoursPerCoordinationStageChartData =
- data?.hoursPerCoordinationStageChartData.hoursPerStageChartData
+ data?.hoursPerCoordinationStageChartData?.hoursPerStageChartData
return project ? (
{
}
)
- const lastProjectConsolidation = data?.project.projectConsolidations.pop()
+ const lastProjectConsolidation = data?.project.projectConsolidations?.pop()
const currentLeadTime = [
{
diff --git a/app/spa/src/pages/Projects/RiskDrill.tsx b/app/spa/src/pages/Projects/RiskDrill.tsx
index b914b6c53..3bbb9d476 100644
--- a/app/spa/src/pages/Projects/RiskDrill.tsx
+++ b/app/spa/src/pages/Projects/RiskDrill.tsx
@@ -1,8 +1,8 @@
import { gql, useQuery } from "@apollo/client"
import { useParams } from "react-router-dom"
import {
- ProjectPage,
PROJECT_STANDARD_FRAGMENT,
+ ProjectPage,
} from "../../components/Projects/ProjectPage"
import TicketGroup from "../../components/TicketGroup"
import { Project } from "../../modules/project/project.types"
@@ -107,12 +107,12 @@ export const RiskDrill = () => {
},
{
title: "Percentil 80",
- value: data?.project.monteCarloP80.toFixed(2),
+ value: data?.project.monteCarloP80?.toFixed(2),
unity: "semanas",
},
{
title: "Desvio padrão",
- value: data?.project.currentMonteCarloWeeksStdDev.toFixed(2),
+ value: data?.project.currentMonteCarloWeeksStdDev?.toFixed(2),
unity: "semanas",
},
]
@@ -130,12 +130,12 @@ export const RiskDrill = () => {
},
{
title: "Percentil 80",
- value: data?.project.teamMonteCarloP80.toFixed(2),
+ value: data?.project.teamMonteCarloP80?.toFixed(2),
unity: "semanas",
},
{
title: "Desvio padrão",
- value: data?.project.teamMonteCarloWeeksStdDev.toFixed(2),
+ value: data?.project.teamMonteCarloWeeksStdDev?.toFixed(2),
unity: "semanas",
},
]
diff --git a/app/spa/src/pages/Users/ManagerDashboard.tsx b/app/spa/src/pages/Users/ManagerDashboard.tsx
index 61e33af83..18e0901fd 100644
--- a/app/spa/src/pages/Users/ManagerDashboard.tsx
+++ b/app/spa/src/pages/Users/ManagerDashboard.tsx
@@ -20,6 +20,8 @@ import ActiveContractsHoursTicket from "../../modules/contracts/ActiveContractsH
import ProjectBurnup from "../Projects/Charts/ProjectBurnup"
import { PROJECT_STANDARD_FRAGMENT } from "../../components/Projects/ProjectPage"
import ProjectHoursBurnup from "../Projects/Charts/ProjectHoursBurnup"
+import ProjectLeadTime from "../Projects/Charts/ProjectLeadTime"
+import ProjectLeadTimeControlChart from "../Projects/Charts/ProjectLeadTimeControlChart"
const ManagerDashboard = () => {
const { me } = useContext(MeContext)
@@ -81,14 +83,12 @@ const ManagerDashboard = () => {
-
-
-
-
-
-
-
-
+
+
+
+
+
+
>
) : (
@@ -109,44 +109,64 @@ const MANAGER_DASHBOARD_QUERY = gql`
me {
projects(name: $name) {
...ProjectStandardFragment
-
+ ...ProjectChartsFragment
totalActiveContractsHours
consumedActiveContractsHours
remainingActiveContractsHours
-
- demandsBurnup {
- scope
- xAxis
- idealBurn
- currentBurn
- }
-
- hoursBurnup {
- scope
- xAxis
- idealBurn
- currentBurn
- }
}
projectsActive {
...ProjectStandardFragment
+ ...ProjectChartsFragment
+ }
+ }
+ }
- demandsBurnup {
- scope
- xAxis
- idealBurn
- currentBurn
- }
+ fragment ProjectChartsFragment on Project {
+ demandsBurnup {
+ scope
+ xAxis
+ idealBurn
+ currentBurn
+ }
- hoursBurnup {
- scope
- xAxis
- idealBurn
- currentBurn
- }
- }
+ hoursBurnup {
+ scope
+ xAxis
+ idealBurn
+ currentBurn
+ }
+ demandsFinishedWithLeadtime {
+ id
+ leadtime
+ externalId
+ }
+ lastProjectConsolidationsWeekly {
+ leadTimeP65
+ leadTimeP80
+ leadTimeP95
+ }
+ projectConsolidationsWeekly {
+ leadTimeP80
+ projectQuality
+ consolidationDate
+ operationalRisk
+ codeNeededBlocksCount
+ codeNeededBlocksPerDemand
+ flowEfficiency
+ hoursPerDemand
+ projectThroughput
+ projectThroughputHours
+ projectThroughputHoursAdditional
+ bugsOpened
+ bugsClosed
+ projectThroughputHoursManagement
+ projectThroughputHoursDevelopment
+ projectThroughputHoursDesign
+ projectThroughputHoursUpstream
+ projectThroughputHoursDownstream
}
}
+
${PROJECT_STANDARD_FRAGMENT}
`
diff --git a/app/spa/src/utils/charts.ts b/app/spa/src/utils/charts.ts
index f253e38fe..11cc8c034 100644
--- a/app/spa/src/utils/charts.ts
+++ b/app/spa/src/utils/charts.ts
@@ -9,7 +9,7 @@ export const buildBurnupData = (
{
id: scopeLabel,
data:
- data?.scope.map((scope, index) => ({
+ data?.scope?.map((scope, index) => ({
x: data.xAxis?.[index],
y: scope,
})) || [],
@@ -17,7 +17,7 @@ export const buildBurnupData = (
{
id: idealLabel,
data:
- data?.idealBurn.map((idealScope, index) => ({
+ data?.idealBurn?.map((idealScope, index) => ({
x: data.xAxis?.[index],
y: idealScope.toFixed(2),
})) || [],
@@ -25,7 +25,7 @@ export const buildBurnupData = (
{
id: deliveredLabel,
data:
- data?.currentBurn.map((projectThroughput, index) => ({
+ data?.currentBurn?.map((projectThroughput, index) => ({
x: data.xAxis?.[index],
y: projectThroughput,
})) || [],