feat: Shoring column in ProjectHealth widget + populate country data
Widget: added "Shoring" column with ShoringBadge per project showing offshore % with color indicator (green/yellow/red). Backend: added id field to ProjectHealthRow for badge queries. Database: assigned diverse countries to 11 resources for realistic shoring data (25 DE, 5 ES, 4 IN, 2 US instead of all-DE). Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
@@ -4,6 +4,7 @@ import { useMemo } from "react";
|
|||||||
import { trpc } from "~/lib/trpc/client.js";
|
import { trpc } from "~/lib/trpc/client.js";
|
||||||
import type { WidgetProps } from "~/components/dashboard/widget-registry.js";
|
import type { WidgetProps } from "~/components/dashboard/widget-registry.js";
|
||||||
import { InfoTooltip } from "~/components/ui/InfoTooltip.js";
|
import { InfoTooltip } from "~/components/ui/InfoTooltip.js";
|
||||||
|
import { ShoringBadge } from "~/components/projects/ShoringIndicator.js";
|
||||||
import { WidgetFilterBar, type WidgetFilter } from "~/components/dashboard/WidgetFilterBar.js";
|
import { WidgetFilterBar, type WidgetFilter } from "~/components/dashboard/WidgetFilterBar.js";
|
||||||
import { useWidgetFilterOptions } from "~/hooks/useWidgetFilterOptions.js";
|
import { useWidgetFilterOptions } from "~/hooks/useWidgetFilterOptions.js";
|
||||||
|
|
||||||
@@ -90,6 +91,9 @@ export function ProjectHealthWidget({ config, onConfigChange }: WidgetProps) {
|
|||||||
<th className="px-3 py-2 text-center font-medium text-gray-500 dark:text-gray-400">
|
<th className="px-3 py-2 text-center font-medium text-gray-500 dark:text-gray-400">
|
||||||
B / S / T <InfoTooltip content="Budget health (spent vs budget), Staffing health (filled vs total demands), Timeline health (within end date)" />
|
B / S / T <InfoTooltip content="Budget health (spent vs budget), Staffing health (filled vs total demands), Timeline health (within end date)" />
|
||||||
</th>
|
</th>
|
||||||
|
<th className="px-3 py-2 text-center font-medium text-gray-500 dark:text-gray-400">
|
||||||
|
Shoring <InfoTooltip content="Offshore staffing ratio: percentage of hours from non-onshore resources. Color indicates threshold status." />
|
||||||
|
</th>
|
||||||
<th className="px-3 py-2 text-right font-medium text-gray-500 dark:text-gray-400">
|
<th className="px-3 py-2 text-right font-medium text-gray-500 dark:text-gray-400">
|
||||||
Score <InfoTooltip content="Composite score: average of Budget, Staffing, and Timeline health (0-100)" />
|
Score <InfoTooltip content="Composite score: average of Budget, Staffing, and Timeline health (0-100)" />
|
||||||
</th>
|
</th>
|
||||||
@@ -118,6 +122,9 @@ export function ProjectHealthWidget({ config, onConfigChange }: WidgetProps) {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
<td className="px-3 py-2 text-center">
|
||||||
|
<ShoringBadge projectId={(row as any).id} />
|
||||||
|
</td>
|
||||||
<td className="px-3 py-2 text-right">
|
<td className="px-3 py-2 text-right">
|
||||||
<span
|
<span
|
||||||
className={`inline-block px-2 py-0.5 rounded-full font-semibold tabular-nums ${scoreBadge(row.compositeScore)}`}
|
className={`inline-block px-2 py-0.5 rounded-full font-semibold tabular-nums ${scoreBadge(row.compositeScore)}`}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import type { PrismaClient } from "@planarchy/db";
|
|||||||
import { calculateInclusiveDays } from "./shared.js";
|
import { calculateInclusiveDays } from "./shared.js";
|
||||||
|
|
||||||
export interface ProjectHealthRow {
|
export interface ProjectHealthRow {
|
||||||
|
id: string;
|
||||||
projectName: string;
|
projectName: string;
|
||||||
shortCode: string;
|
shortCode: string;
|
||||||
clientId: string | null;
|
clientId: string | null;
|
||||||
@@ -94,6 +95,7 @@ export async function getDashboardProjectHealth(
|
|||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
id: p.id,
|
||||||
projectName: p.name,
|
projectName: p.name,
|
||||||
shortCode: p.shortCode,
|
shortCode: p.shortCode,
|
||||||
clientId: p.clientId,
|
clientId: p.clientId,
|
||||||
|
|||||||
Reference in New Issue
Block a user