mirror of
https://github.com/Hestia-Homes/assessment-model.git
synced 2026-06-08 11:37:25 +00:00
added stubbed activity log
This commit is contained in:
parent
9118f9202b
commit
49adf11a4e
3 changed files with 85 additions and 87 deletions
|
|
@ -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 (
|
||||
<p className="text-xs text-gray-400 py-2 pl-4">Loading activity…</p>
|
||||
);
|
||||
}
|
||||
|
||||
const events = data?.events ?? [];
|
||||
|
||||
if (events.length === 0) {
|
||||
return (
|
||||
<p className="text-xs text-gray-400 py-2 pl-4">No activity yet.</p>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="pl-4 pr-2 pb-3 space-y-1.5">
|
||||
{events.map((e) => (
|
||||
<div key={e.id} className="flex items-center gap-2 text-xs">
|
||||
<span
|
||||
className={`px-1.5 py-0.5 rounded text-xs font-medium ${
|
||||
e.action === "approved"
|
||||
? "bg-emerald-50 text-emerald-700"
|
||||
: "bg-red-50 text-red-600"
|
||||
}`}
|
||||
>
|
||||
{e.action === "approved" ? "Approved" : "Unapproved"}
|
||||
</span>
|
||||
<span className="font-medium text-gray-700">{e.measureName}</span>
|
||||
<span className="text-gray-400">·</span>
|
||||
<span className="text-gray-500">
|
||||
{e.actedByName ?? e.actedByEmail}
|
||||
</span>
|
||||
<span className="text-gray-400">·</span>
|
||||
<span className="text-gray-400">{formatDate(e.actedAt)}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -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 (
|
||||
<p className="text-xs text-gray-400 py-2 pl-4">Loading activity…</p>
|
||||
);
|
||||
}
|
||||
|
||||
const events = data?.events ?? [];
|
||||
|
||||
if (events.length === 0) {
|
||||
return (
|
||||
<p className="text-xs text-gray-400 py-2 pl-4">No activity yet.</p>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="pl-4 pr-2 pb-3 space-y-1.5">
|
||||
{events.map((e) => (
|
||||
<div key={e.id} className="flex items-center gap-2 text-xs">
|
||||
<span
|
||||
className={`px-1.5 py-0.5 rounded text-xs font-medium ${
|
||||
e.action === "approved"
|
||||
? "bg-emerald-50 text-emerald-700"
|
||||
: "bg-red-50 text-red-600"
|
||||
}`}
|
||||
>
|
||||
{e.action === "approved" ? "Approved" : "Unapproved"}
|
||||
</span>
|
||||
<span className="font-medium text-gray-700">{e.measureName}</span>
|
||||
<span className="text-gray-400">·</span>
|
||||
<span className="text-gray-500">
|
||||
{e.actedByName ?? e.actedByEmail}
|
||||
</span>
|
||||
<span className="text-gray-400">·</span>
|
||||
<span className="text-gray-400">{formatDate(e.actedAt)}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function MeasuresTable({
|
||||
data,
|
||||
approvalsByDeal,
|
||||
|
|
|
|||
|
|
@ -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 <p className="text-xs text-gray-400">No approvals recorded.</p>;
|
||||
}
|
||||
export const ApprovalLogSection = ActivityLog;
|
||||
|
||||
function formatDateTime(d: string | Date | null | undefined): string {
|
||||
if (!d) return "";
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue