mirror of
https://github.com/Hestia-Homes/assessment-model.git
synced 2026-06-30 12:55:02 +00:00
open detail drawer at Measures section on row click
This commit is contained in:
parent
75c0cde009
commit
0fe8dd0ac9
2 changed files with 44 additions and 5 deletions
|
|
@ -22,7 +22,7 @@ import DocumentTable from "./DocumentTable";
|
|||
import MeasuresTable from "./MeasuresTable";
|
||||
import type { HubspotDeal } from "./types";
|
||||
import PropertyDrawer from "./PropertyDrawer";
|
||||
import PropertyDetailDrawer from "./PropertyDetailDrawer";
|
||||
import PropertyDetailDrawer, { type DrawerSection } from "./PropertyDetailDrawer";
|
||||
import AnalyticsView from "./AnalyticsView";
|
||||
import type {
|
||||
LiveTrackerProps,
|
||||
|
|
@ -77,6 +77,19 @@ export default function LiveTracker({
|
|||
|
||||
// ── Property detail drawer ───────────────────────────────────────────
|
||||
const [detailDeal, setDetailDeal] = useState<ClassifiedDeal | null>(null);
|
||||
const [detailFocusSection, setDetailFocusSection] = useState<
|
||||
DrawerSection | undefined
|
||||
>(undefined);
|
||||
|
||||
const openDetailDrawer = (deal: ClassifiedDeal, section?: DrawerSection) => {
|
||||
setDetailFocusSection(section);
|
||||
setDetailDeal(deal);
|
||||
};
|
||||
|
||||
const closeDetailDrawer = () => {
|
||||
setDetailDeal(null);
|
||||
setDetailFocusSection(undefined);
|
||||
};
|
||||
|
||||
const handleOpenTable = (
|
||||
stage: string,
|
||||
|
|
@ -230,7 +243,7 @@ export default function LiveTracker({
|
|||
<PropertyTable
|
||||
data={currentProject?.allDeals ?? []}
|
||||
onOpenDrawer={handleOpenDrawer}
|
||||
onOpenDetail={setDetailDeal}
|
||||
onOpenDetail={(deal) => openDetailDrawer(deal)}
|
||||
docStatusMap={docStatusMap}
|
||||
removalStatusByDeal={removalStatusByDeal}
|
||||
/>
|
||||
|
|
@ -310,6 +323,7 @@ export default function LiveTracker({
|
|||
userCapability={userCapability}
|
||||
approvalsByDeal={approvalsByDeal}
|
||||
portfolioId={portfolioId}
|
||||
onOpenDetail={(deal) => openDetailDrawer(deal, "measures")}
|
||||
/>
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
|
@ -427,11 +441,12 @@ export default function LiveTracker({
|
|||
{/* ── Property detail drawer ─────────────────────────────────────── */}
|
||||
<PropertyDetailDrawer
|
||||
deal={detailDeal}
|
||||
onClose={() => setDetailDeal(null)}
|
||||
onClose={closeDetailDrawer}
|
||||
portfolioId={portfolioId}
|
||||
userRole={userRole}
|
||||
userCapability={userCapability}
|
||||
userEmail={userEmail}
|
||||
focusSection={detailFocusSection}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -35,6 +35,12 @@ type Props = {
|
|||
userCapability: PortfolioCapabilityType;
|
||||
approvalsByDeal: ApprovalsByDeal;
|
||||
portfolioId: string;
|
||||
/**
|
||||
* Called when a measures row is clicked. The host (LiveTracker) opens the
|
||||
* PropertyDetailDrawer focused on the Measures section. Optional so the
|
||||
* table is still usable in isolation.
|
||||
*/
|
||||
onOpenDetail?: (deal: ClassifiedDeal) => void;
|
||||
};
|
||||
|
||||
function ApprovalStatus({
|
||||
|
|
@ -155,6 +161,7 @@ export default function MeasuresTable({
|
|||
userCapability,
|
||||
approvalsByDeal,
|
||||
portfolioId,
|
||||
onOpenDetail,
|
||||
}: Props) {
|
||||
const [search, setSearch] = useState("");
|
||||
// pendingChanges: dealId -> desired Set<measureName> (the full intended approved set)
|
||||
|
|
@ -338,15 +345,31 @@ export default function MeasuresTable({
|
|||
const hasPending = pendingChanges[deal.dealId] !== undefined;
|
||||
const isExpanded = expandedRows.has(deal.dealId);
|
||||
|
||||
const handleRowClick = () => {
|
||||
if (onOpenDetail) onOpenDetail(deal);
|
||||
};
|
||||
const handleRowKeyDown = (e: React.KeyboardEvent<HTMLTableRowElement>) => {
|
||||
if (!onOpenDetail) return;
|
||||
if (e.key === "Enter" || e.key === " ") {
|
||||
e.preventDefault();
|
||||
onOpenDetail(deal);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<React.Fragment key={deal.dealId}>
|
||||
<TableRow
|
||||
className={`border-b border-gray-50 hover:bg-gray-50/50 transition-colors ${hasPending ? "bg-amber-50/30" : ""}`}
|
||||
data-testid="measures-row"
|
||||
onClick={onOpenDetail ? handleRowClick : undefined}
|
||||
onKeyDown={onOpenDetail ? handleRowKeyDown : undefined}
|
||||
tabIndex={onOpenDetail ? 0 : undefined}
|
||||
role={onOpenDetail ? "button" : undefined}
|
||||
className={`border-b border-gray-50 hover:bg-gray-50/50 transition-colors ${hasPending ? "bg-amber-50/30" : ""} ${onOpenDetail ? "cursor-pointer" : ""}`}
|
||||
>
|
||||
{/* Expand toggle */}
|
||||
<TableCell className="py-3 pl-3 pr-0 w-6">
|
||||
<button
|
||||
onClick={() => toggleRowExpand(deal.dealId)}
|
||||
onClick={(e) => { e.stopPropagation(); toggleRowExpand(deal.dealId); }}
|
||||
className="text-gray-400 hover:text-brandblue transition-colors"
|
||||
aria-label={isExpanded ? "Collapse activity" : "Expand activity"}
|
||||
>
|
||||
|
|
@ -389,6 +412,7 @@ export default function MeasuresTable({
|
|||
return (
|
||||
<label
|
||||
key={measure}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
className={`flex items-center gap-1.5 cursor-pointer px-2 py-1 rounded-full text-xs border transition-colors ${
|
||||
isApproved
|
||||
? "bg-emerald-50 border-emerald-200 text-emerald-700"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue