From 49adf11a4e192a881370b8a2903bb2818b78b3bf Mon Sep 17 00:00:00 2001 From: Khalim Conn-Kowlessar Date: Thu, 7 May 2026 20:50:27 +0000 Subject: [PATCH] added stubbed activity log --- .../your-projects/live/ActivityLog.tsx | 82 +++++++++++++++++++ .../your-projects/live/MeasuresTable.tsx | 81 +----------------- .../live/PropertyDetailDrawer.tsx | 9 +- 3 files changed, 85 insertions(+), 87 deletions(-) create mode 100644 src/app/portfolio/[slug]/(portfolio)/your-projects/live/ActivityLog.tsx diff --git a/src/app/portfolio/[slug]/(portfolio)/your-projects/live/ActivityLog.tsx b/src/app/portfolio/[slug]/(portfolio)/your-projects/live/ActivityLog.tsx new file mode 100644 index 0000000..c43e2e1 --- /dev/null +++ b/src/app/portfolio/[slug]/(portfolio)/your-projects/live/ActivityLog.tsx @@ -0,0 +1,82 @@ +"use client"; + +import { useQuery } from "@tanstack/react-query"; + +type AuditEvent = { + id: string; + hubspotDealId: string; + measureName: string; + action: string; + actedByEmail: string; + actedByName: string | null; + actedAt: string; +}; + +function formatDate(iso: string) { + return new Date(iso).toLocaleString("en-GB", { + day: "numeric", + month: "short", + year: "numeric", + hour: "2-digit", + minute: "2-digit", + }); +} + +export function ActivityLog({ + dealId, + portfolioId, +}: { + dealId: string; + portfolioId: string; +}) { + const { data, isLoading } = useQuery<{ events: AuditEvent[] }>({ + queryKey: ["approvalEvents", portfolioId, dealId], + queryFn: async () => { + const res = await fetch( + `/api/portfolio/${portfolioId}/approvals?dealIds=${dealId}&include=events`, + ); + if (!res.ok) throw new Error("Failed to fetch events"); + return res.json(); + }, + staleTime: 30_000, + }); + + if (isLoading) { + return ( +

Loading activity…

+ ); + } + + const events = data?.events ?? []; + + if (events.length === 0) { + return ( +

No activity yet.

+ ); + } + + return ( +
+ {events.map((e) => ( +
+ + {e.action === "approved" ? "Approved" : "Unapproved"} + + {e.measureName} + · + + {e.actedByName ?? e.actedByEmail} + + · + {formatDate(e.actedAt)} +
+ ))} +
+ ); +} diff --git a/src/app/portfolio/[slug]/(portfolio)/your-projects/live/MeasuresTable.tsx b/src/app/portfolio/[slug]/(portfolio)/your-projects/live/MeasuresTable.tsx index b25dd5d..89fc210 100644 --- a/src/app/portfolio/[slug]/(portfolio)/your-projects/live/MeasuresTable.tsx +++ b/src/app/portfolio/[slug]/(portfolio)/your-projects/live/MeasuresTable.tsx @@ -2,7 +2,6 @@ import React, { useMemo, useState } from "react"; import { useRouter } from "next/navigation"; -import { useQuery } from "@tanstack/react-query"; import { Table, TableBody, @@ -17,16 +16,7 @@ import { Search, ChevronDown, ChevronRight } from "lucide-react"; import { STAGE_COLORS } from "./types"; import type { ClassifiedDeal, ApprovalsByDeal } from "./types"; import { parseMeasures } from "@/app/lib/parseMeasures"; - -type AuditEvent = { - id: string; - hubspotDealId: string; - measureName: string; - action: string; // 'approved' | 'unapproved' - actedByEmail: string; - actedByName: string | null; - actedAt: string; // ISO string -}; +import { ActivityLog } from "./ActivityLog"; type Props = { data: ClassifiedDeal[]; @@ -66,75 +56,6 @@ function ApprovalStatus({ ); } -function formatDate(iso: string) { - return new Date(iso).toLocaleString("en-GB", { - day: "numeric", - month: "short", - year: "numeric", - hour: "2-digit", - minute: "2-digit", - }); -} - -function ActivityLog({ - dealId, - portfolioId, -}: { - dealId: string; - portfolioId: string; -}) { - const { data, isLoading } = useQuery<{ events: AuditEvent[] }>({ - queryKey: ["approvalEvents", portfolioId, dealId], - queryFn: async () => { - const res = await fetch( - `/api/portfolio/${portfolioId}/approvals?dealIds=${dealId}&include=events`, - ); - if (!res.ok) throw new Error("Failed to fetch events"); - return res.json(); - }, - staleTime: 30_000, - }); - - if (isLoading) { - return ( -

Loading activity…

- ); - } - - const events = data?.events ?? []; - - if (events.length === 0) { - return ( -

No activity yet.

- ); - } - - return ( -
- {events.map((e) => ( -
- - {e.action === "approved" ? "Approved" : "Unapproved"} - - {e.measureName} - · - - {e.actedByName ?? e.actedByEmail} - - · - {formatDate(e.actedAt)} -
- ))} -
- ); -} - export default function MeasuresTable({ data, approvalsByDeal, diff --git a/src/app/portfolio/[slug]/(portfolio)/your-projects/live/PropertyDetailDrawer.tsx b/src/app/portfolio/[slug]/(portfolio)/your-projects/live/PropertyDetailDrawer.tsx index 4f90bb7..469e037 100644 --- a/src/app/portfolio/[slug]/(portfolio)/your-projects/live/PropertyDetailDrawer.tsx +++ b/src/app/portfolio/[slug]/(portfolio)/your-projects/live/PropertyDetailDrawer.tsx @@ -1,5 +1,6 @@ "use client"; +import { ActivityLog } from "./ActivityLog"; import { useEffect, useMemo, useState } from "react"; import { useQuery, useQueryClient } from "@tanstack/react-query"; import { X, CheckCircle2, Circle, AlertTriangle, ChevronRight, ChevronDown, Trash2, RotateCcw, Loader2 } from "lucide-react"; @@ -516,13 +517,7 @@ export function SurveyRequestSection({ ); } -// ----------------------------------------------------------------------- -// Approval log placeholder (expand into a real implementation as needed) -// ----------------------------------------------------------------------- -export function ApprovalLogSection({ dealId, portfolioId }: { dealId: string; portfolioId: string }) { - void dealId; void portfolioId; - return

No approvals recorded.

; -} +export const ApprovalLogSection = ActivityLog; function formatDateTime(d: string | Date | null | undefined): string { if (!d) return "";