From 35aa72bce890d8cd518be0ce9c7ec844d8a5b4c6 Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Tue, 14 Apr 2026 21:07:08 +0000 Subject: [PATCH] handling incorrect aggregation due to timezones --- src/app/db/schema/crm/hubspot_deal_table.ts | 2 +- .../live/CompletionTrendsChart.tsx | 58 ++++++++++++++++--- .../your-projects/live/SurveyIssuesPanel.tsx | 2 +- .../(portfolio)/your-projects/live/page.tsx | 2 +- .../(portfolio)/your-projects/live/types.ts | 1 + 5 files changed, 55 insertions(+), 10 deletions(-) diff --git a/src/app/db/schema/crm/hubspot_deal_table.ts b/src/app/db/schema/crm/hubspot_deal_table.ts index 04c73b6..3b7161e 100644 --- a/src/app/db/schema/crm/hubspot_deal_table.ts +++ b/src/app/db/schema/crm/hubspot_deal_table.ts @@ -48,7 +48,7 @@ export const hubspotDealData = pgTable("hubspot_deal_data", { damnpMouldAndRepairComments: text("damp_mould_and_repairs_comments"), confirmedSurveyDate: timestamp("confirmed_survey_date", { precision: 6, withTimezone: true }), confirmedSurveyTime: text("confirmed_survey_time"), - SurveyedDate: timestamp("surveyed_date", { precision: 6, withTimezone: true }), + surveyedDate: timestamp("surveyed_date", { precision: 6, withTimezone: true }), createdAt: timestamp("created_at", { precision: 6, withTimezone: true }) .defaultNow() diff --git a/src/app/portfolio/[slug]/(portfolio)/your-projects/live/CompletionTrendsChart.tsx b/src/app/portfolio/[slug]/(portfolio)/your-projects/live/CompletionTrendsChart.tsx index dfcd492..3fa3b4e 100644 --- a/src/app/portfolio/[slug]/(portfolio)/your-projects/live/CompletionTrendsChart.tsx +++ b/src/app/portfolio/[slug]/(portfolio)/your-projects/live/CompletionTrendsChart.tsx @@ -110,9 +110,9 @@ const DESIGN_TYPE_ORDER = [ function getMondayOfWeek(date: Date): string { const d = new Date(date); - const day = d.getDay(); - d.setDate(d.getDate() - (day === 0 ? 6 : day - 1)); - d.setHours(0, 0, 0, 0); + const day = d.getUTCDay(); + d.setUTCDate(d.getUTCDate() - (day === 0 ? 6 : day - 1)); + d.setUTCHours(0, 0, 0, 0); return d.toISOString().split("T")[0]; } @@ -132,7 +132,7 @@ function fillWeekGaps(keys: string[]): string[] { const end = new Date(sorted[sorted.length - 1]); while (current <= end) { result.push(current.toISOString().split("T")[0]); - current.setDate(current.getDate() + 7); + current.setUTCDate(current.getUTCDate() + 7); } return result; } @@ -314,14 +314,28 @@ export default function CompletionTrendsChart({ const isDesign = metric === "design"; const isStacked = isCoordination || isAssessments || isLodgement || isDesign; - // External assessments with no date + // Assessments (retrofit or EPC) with no date const undatedAssessments = isAssessments ? deals.filter((d) => { const o = d.outcome ?? ""; - return (o === "Surveyed" || o === "Surveyed - Pending Upload") && !d.surveyedDate; + return ( + (o === "Surveyed" || o === "Surveyed - Pending Upload" || o === "EPC Completed") && + !d.surveyedDate + ); }) : []; + // Dated assessments broken down by type — used for summary badges + const retrofitDeals = isAssessments + ? deals.filter((d) => { + const o = d.outcome ?? ""; + return (o === "Surveyed" || o === "Surveyed - Pending Upload") && !!d.surveyedDate; + }) + : []; + const epcDeals = isAssessments + ? deals.filter((d) => d.outcome === "EPC Completed" && !!d.surveyedDate) + : []; + // Build chart data let chartData: Record[]; let categories: string[]; @@ -363,7 +377,37 @@ export default function CompletionTrendsChart({ Trends Over Time - {totalCompleted !== null && ( + {isAssessments ? ( +
+ {([ + { label: "Retrofit Assessments", dealList: retrofitDeals }, + { label: "EPCs", dealList: epcDeals }, + ] as const).filter(({ dealList }) => dealList.length > 0).map(({ label, dealList }) => ( + + ))} +
+ ) : totalCompleted !== null && (
{totalCompleted} diff --git a/src/app/portfolio/[slug]/(portfolio)/your-projects/live/SurveyIssuesPanel.tsx b/src/app/portfolio/[slug]/(portfolio)/your-projects/live/SurveyIssuesPanel.tsx index d8c576b..65cc8ab 100644 --- a/src/app/portfolio/[slug]/(portfolio)/your-projects/live/SurveyIssuesPanel.tsx +++ b/src/app/portfolio/[slug]/(portfolio)/your-projects/live/SurveyIssuesPanel.tsx @@ -5,7 +5,7 @@ import { AlertCircle } from "lucide-react"; import { Card, CardContent } from "@/app/shadcn_components/ui/card"; import type { ClassifiedDeal } from "./types"; -const SUCCESSFUL_OUTCOMES = new Set(["Surveyed", "Surveyed - Pending Upload"]); +const SUCCESSFUL_OUTCOMES = new Set(["Surveyed", "Surveyed - Pending Upload", "EPC Completed"]); const COLUMNS: (keyof ClassifiedDeal)[] = [ "dealname", diff --git a/src/app/portfolio/[slug]/(portfolio)/your-projects/live/page.tsx b/src/app/portfolio/[slug]/(portfolio)/your-projects/live/page.tsx index 55da823..f7002fc 100644 --- a/src/app/portfolio/[slug]/(portfolio)/your-projects/live/page.tsx +++ b/src/app/portfolio/[slug]/(portfolio)/your-projects/live/page.tsx @@ -53,7 +53,7 @@ function mapDbRowToHubspotDeal(row: DbDeal): HubspotDeal { measuresLodgementDate: row.measuresLodgementDate, fullLodgementDate: row.lodgementDate, confirmedSurveyDate: row.confirmedSurveyDate, - surveyedDate: row.SurveyedDate, + surveyedDate: row.surveyedDate, designType: row.dealType, createdAt: row.createdAt, updatedAt: row.updatedAt, diff --git a/src/app/portfolio/[slug]/(portfolio)/your-projects/live/types.ts b/src/app/portfolio/[slug]/(portfolio)/your-projects/live/types.ts index 931413c..40fa764 100644 --- a/src/app/portfolio/[slug]/(portfolio)/your-projects/live/types.ts +++ b/src/app/portfolio/[slug]/(portfolio)/your-projects/live/types.ts @@ -230,6 +230,7 @@ export type DocumentDrawerState = { export const SURVEYOR_OUTCOMES = [ "Surveyed", "Surveyed - Pending Upload", + "EPC Completed", "Tenant Refusal", "Other", "Not Viable",