Contract Summary Component (components/Editor/contract-summary.tsx)¶
Overview¶
A React component that displays contract information in a structured card layout with a table format. The component parses and presents contract details including issuer, scope of work, dates, and deliverables with associated icons.
Features¶
- Tabular data display
- Date parsing
- Icon integration
- Scrollable content
- Error handling
- Responsive layout
- Default values
- Whitespace handling
- Array data support
- Visual hierarchy
Implementation¶
interface ContractDate {
title: string;
value: string;
}
interface ParsedContractInfo {
label: string;
value: string | ContractDate[];
icon: React.ReactNode;
}
function parseContractSummary(summary: Summary): ParsedContractInfo[] {
const issuer = summary.ClientName || "Not specified";
const scopeOfWork = summary.ScopeOfWork || "Not specified";
const unitsDeliverables = summary.Deliverables || "Not specified";
let dates: ContractDate[] = [];
let datesSection: ParsedContractInfo[] = [];
try {
if (summary.Dates && summary.Dates.includes("Not Provided")) {
dates = [{ title: "Dates", value: "Not Provided" }];
} else {
dates = JSON.parse(summary.Dates.replace(/\\n/g, '').replace(/\\"/g, '"').replace(/^\[ /, '[').replace(/ \]$/, ']')) || [];
datesSection = dates.map((date) => ({
label: date.title,
value: date.value.includes("Not Provided") ? "Not Provided" : date.value || "Not specified",
icon: <Calendar className="w-4 h-4" />,
}));
}
} catch (error) {
console.error("Error parsing dates:", error);
}
return [
{
label: "Issuer",
value: issuer.includes("Not Provided") ? "Not Provided" : issuer || "Not specified",
icon: <FileText className="w-4 h-4" />,
},
{
label: "Scope of Work",
value: scopeOfWork.includes("Not Provided") ? "Not Provided" : scopeOfWork || "Not specified",
icon: <FileText className="w-4 h-4" />,
},
...datesSection,
{
label: "Units/Deliverables",
value: unitsDeliverables.includes("Not Provided") ? "Not Provided" : unitsDeliverables || "Not specified",
icon: <Hash className="w-4 h-4" />,
},
];
}
export function ContractSummary({ summary }: { summary: Summary }) {
const contractInfo = parseContractSummary(summary);
return (
<Card className="max-w-4xl mx-auto">
<CardHeader>
<CardTitle className="text-2xl font-bold">Contract Summary</CardTitle>
</CardHeader>
<div className="mt-2 border-t border-pink-525"></div>
<CardContent>
<div style={{ maxHeight: "435px", overflowY: "auto" }}>
<Table>
<TableHeader>
<TableRow>
<TableHead className="w-1/3">Field</TableHead>
<TableHead>Value</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{contractInfo.map((info, index) => (
<TableRow key={index}>
<TableCell className="font-medium flex items-center gap-2">
{info.icon}
{info.label}
</TableCell>
<TableCell className="whitespace-pre-wrap">
{Array.isArray(info.value) ? (
info.value.map((date, dateIndex) => (
<div key={dateIndex}>
<strong>{date.title}:</strong> {date.value || "\u00A0"}
</div>
))
) : (
<span>{info.value || "\u00A0"}</span>
)}
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
</CardContent>
</Card>
);
}
Dependencies¶
import { useState, useEffect } from "react"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
import { FileText, Calendar, Hash } from "lucide-react"
import { Summary } from "./summary"
Components Used¶
Notes¶
- Parses contract summary data
- Handles date formatting
- Provides fallback values
- Manages data display
- Implements error handling
- Supports scrollable content
- Uses icon indicators
- Maintains data structure
- Ensures accessibility
- Handles edge cases