import { aggregateAcrossTeams, formatAggregationResult, loopGet, } from "../lib/loop-api.js"; // ─── Loop API V2: /residential/{dept}/viewings/{id} ──────────── // Fields: id, dateCreated, dateOfAppointment, dateOfAppointmentEnd, // dateBuyerFeedbackGiven, dateSellerFeedbackGiven, dateDone, // status, type, comment, buyerFeedback, sellerFeedback, // buyerConfirmed, sellerConfirmed, agentConfirmed, // property (nested PropertySummary), buyer (nested BuyerSummary), // seller (nested SellerSummary), // attendingAgent (nested TeamMember), creatingAgent (nested TeamMember), // teamId // ──────────────────────────────────────────────────────────────── interface LoopViewingDetail { id: number; dateCreated?: string; dateOfAppointment?: string; dateOfAppointmentEnd?: string; dateBuyerFeedbackGiven?: string | null; dateSellerFeedbackGiven?: string | null; dateDone?: string | null; status?: string; type?: string; comment?: string | null; buyerFeedback?: string | null; sellerFeedback?: string | null; buyerConfirmed?: boolean; sellerConfirmed?: boolean; agentConfirmed?: boolean; property?: { id: number; propertyAddress?: string; status?: string; propertyType?: string; price?: number; bedrooms?: number; [key: string]: unknown; }; buyer?: { id: number; buyerGroupName?: string; maxPrice?: number | null; position?: string; viewingCount?: number; offerCount?: number; [key: string]: unknown; }; seller?: { id: number; sellerGroupName?: string; propertyAddress?: string; price?: number; [key: string]: unknown; }; attendingAgent?: { id: string; firstName?: string; lastName?: string; email?: string; mobilePhone?: string; jobTitle?: string; [key: string]: unknown; }; creatingAgent?: { id: string; firstName?: string; lastName?: string; [key: string]: unknown; }; teamId?: string; [key: string]: unknown; } type Department = "sales" | "lettings"; export async function viewingDetail(params: { accountId: string; viewingId: number; department: Department; teamName?: string; }): Promise { const { accountId, viewingId, department, teamName } = params; const result = await aggregateAcrossTeams( accountId, "viewings", "loop-viewing-detail", async (apiKey, team) => { const path = `/residential/${department}/viewings/${viewingId}`; const data = await loopGet(apiKey, path, "loop-viewing-detail", team); if (data && typeof data === "object" && !Array.isArray(data)) { return [data]; } return []; }, { teamName } ); return formatAggregationResult( result, (v) => { const propAddr = v.property?.propertyAddress ?? "Unknown property"; const lines = [`**${propAddr}** [Viewing ID: ${v.id}]`]; // Appointment time if (v.dateOfAppointment) { const start = formatDateTime(v.dateOfAppointment); const end = v.dateOfAppointmentEnd ? formatDateTime(v.dateOfAppointmentEnd) : ""; lines.push(`Date/Time: ${start}${end ? ` — ${end}` : ""}`); } if (v.status) lines.push(`Status: ${v.status}`); if (v.type) lines.push(`Type: ${v.type}`); // Confirmation status const confirmParts: string[] = []; if (v.buyerConfirmed != null) confirmParts.push(`Buyer: ${v.buyerConfirmed ? "yes" : "no"}`); if (v.sellerConfirmed != null) confirmParts.push(`Seller: ${v.sellerConfirmed ? "yes" : "no"}`); if (v.agentConfirmed != null) confirmParts.push(`Agent: ${v.agentConfirmed ? "yes" : "no"}`); if (confirmParts.length) lines.push(`Confirmed — ${confirmParts.join(", ")}`); // Property details if (v.property) { const prop = v.property; if (prop.price != null) lines.push(`Property price: £${prop.price.toLocaleString("en-GB")}`); if (prop.propertyType) lines.push(`Property type: ${prop.propertyType}`); if (prop.bedrooms != null) lines.push(`Bedrooms: ${prop.bedrooms}`); if (prop.id) lines.push(`Property ID: ${prop.id}`); } // Buyer if (v.buyer) { const b = v.buyer; lines.push(`\n**Buyer:** ${b.buyerGroupName ?? "Unknown"} [ID: ${b.id}]`); if (b.maxPrice != null) lines.push(` Max price: £${b.maxPrice.toLocaleString("en-GB")}`); if (b.position && b.position !== "none") lines.push(` Position: ${b.position}`); } // Seller if (v.seller) { const s = v.seller; lines.push(`\n**Seller:** ${s.sellerGroupName ?? "Unknown"} [ID: ${s.id}]`); } // Attending agent if (v.attendingAgent) { const a = v.attendingAgent; const agentName = [a.firstName, a.lastName].filter(Boolean).join(" "); const title = a.jobTitle ? ` (${a.jobTitle})` : ""; const contact = a.email ?? a.mobilePhone ?? ""; lines.push(`\n**Attending agent:** ${agentName}${title}${contact ? ` — ${contact}` : ""}`); } // Feedback if (v.buyerFeedback) lines.push(`\nBuyer feedback: ${v.buyerFeedback}`); if (v.sellerFeedback) lines.push(`Seller feedback: ${v.sellerFeedback}`); if (v.comment) lines.push(`Notes: ${v.comment}`); return lines.join("\n"); }, "viewing details" ); } function formatDateTime(iso: string): string { const [datePart, timePart] = iso.split("T"); if (!timePart) return datePart; return `${datePart} ${timePart.slice(0, 5)}`; }