Skip to content

Commit a762106

Browse files
committed
fixup! #24 collect charge and disposition data as part of case summaries
1 parent e329884 commit a762106

File tree

2 files changed

+88
-42
lines changed

2 files changed

+88
-42
lines changed

frontend/src/components/app/SearchResult.tsx

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,20 +53,54 @@ const SearchResult: React.FC<SearchResultProps> = ({ searchResult: sr }) => {
5353
</div>
5454

5555
{summary && (
56-
<div className="mt-4 grid grid-cols-1 md:grid-cols-2 gap-4">
56+
<div className="mt-4 space-y-4">
5757
<div className="text-sm text-gray-700">
5858
<p className="font-medium">{summary.caseName}</p>
5959
<p>{summary.court}</p>
6060
</div>
6161

62-
{/* <div className="text-sm text-gray-700">
63-
<p className="font-medium">{summary.offenseDescription}</p>
64-
{summary.dispositions?.map((d, i) => (
65-
<div key={i} className="mt-1 text-gray-500">
66-
{d.description} ({d.date})
67-
</div>
68-
))}
69-
</div> */}
62+
{summary.charges && summary.charges.length > 0 && (
63+
<div className="space-y-3">
64+
<h4 className="text-sm font-medium text-gray-700">Charges</h4>
65+
{summary.charges.map((charge, idx) => (
66+
<div key={idx} className="pl-2 border-l-2 border-gray-200">
67+
<div className="text-sm text-gray-800">
68+
<div className="font-medium mb-1">{charge.description}</div>
69+
<div className="grid grid-cols-2 gap-2 text-xs text-gray-600">
70+
<div>
71+
<span className="font-medium">Filed:</span> {new Date(charge.filedDate).toLocaleDateString()}
72+
</div>
73+
<div>
74+
<span className="font-medium">Offense:</span> {new Date(charge.offenseDate).toLocaleDateString()}
75+
</div>
76+
<div>
77+
<span className="font-medium">Statute:</span> {charge.statute}
78+
</div>
79+
<div>
80+
<span className="font-medium">Degree:</span> {charge.degree.description}
81+
</div>
82+
{charge.fine > 0 && (
83+
<div>
84+
<span className="font-medium">Fine:</span> ${charge.fine.toFixed(2)}
85+
</div>
86+
)}
87+
</div>
88+
89+
{charge.dispositions && charge.dispositions.length > 0 && (
90+
<div className="mt-2">
91+
<p className="text-xs font-medium mb-1">Dispositions:</p>
92+
{charge.dispositions.map((d, i) => (
93+
<div key={i} className="text-xs text-gray-500 ml-2">
94+
{d.description} ({new Date(d.date).toLocaleDateString()})
95+
</div>
96+
))}
97+
</div>
98+
)}
99+
</div>
100+
</div>
101+
))}
102+
</div>
103+
)}
70104
</div>
71105
)}
72106
</div>

serverless/lib/CaseProcessor.ts

Lines changed: 45 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -657,53 +657,57 @@ async function fetchCaseSummary(caseId: string): Promise<CaseSummary | null> {
657657

658658
function buildCaseSummary(rawData: Record<string, any>): CaseSummary | null {
659659
try {
660-
if (!rawData.summary || !rawData.charges || !rawData.dispositionEvents) {
660+
if (!rawData['summary'] || !rawData['charges'] || !rawData['dispositionEvents']) {
661661
console.error('Missing required raw data for building case summary');
662662
return null;
663663
}
664664

665665
const caseSummary: CaseSummary = {
666-
caseName: rawData.summary.CaseSummaryHeader.Style,
667-
court: rawData.summary.CaseSummaryHeader.Heading,
666+
caseName: rawData['summary']['CaseSummaryHeader']['Style'] || '',
667+
court: rawData['summary']['CaseSummaryHeader']['Heading'] || '',
668668
charges: []
669669
};
670670

671671
const chargeMap = new Map<string, Charge>();
672672

673673
// Process charges
674-
const charges = rawData.charges['Charges'] || [];
674+
const charges = rawData['charges']['Charges'] || [];
675675
charges.forEach((chargeData: any) => {
676676
if (!chargeData) return;
677677

678+
// The charge offense data is nested within the ChargeOffense property
679+
const chargeOffense = chargeData['ChargeOffense'] || {};
680+
678681
const charge: Charge = {
679682
offenseDate: chargeData['OffenseDate'] || '',
680683
filedDate: chargeData['FiledDate'] || '',
681-
description: chargeData['ChargeOffenseDescription'] || '',
682-
statute: chargeData['Statute'] || '',
684+
description: chargeOffense['ChargeOffenseDescription'] || '',
685+
statute: chargeOffense['Statute'] || '',
683686
degree: {
684-
code: chargeData['Degree'] || '',
685-
description: chargeData['DegreeDescription'] || ''
687+
code: chargeOffense['Degree'] || '',
688+
description: chargeOffense['DegreeDescription'] || ''
686689
},
687-
fine: chargeData['FineAmount'] || 0,
690+
fine: typeof chargeOffense['FineAmount'] === 'number' ? chargeOffense['FineAmount'] : 0,
688691
dispositions: []
689692
};
690693

691694
// Add to charges array
692695
caseSummary.charges.push(charge);
693696

694697
// Add to map for easy lookup when processing dispositions
695-
if (chargeData.Id) {
698+
if (chargeData['ChargeId']) {
696699
chargeMap.set(chargeData['ChargeId'], charge);
697700
}
698701
});
699702

700703
// Process dispositions and link them to charges
701-
const events = rawData.dispositionEvents['Events'] || [];
702-
events.filter((dispData: any) => dispData && dispData['Type'] === 'CriminalDispositionEvent')
703-
.forEach((dispData: any) => {
704-
if (!dispData) return;
704+
const events = rawData['dispositionEvents']['Events'] || [];
705+
events.filter((eventData: any) => eventData && eventData['Type'] === 'CriminalDispositionEvent')
706+
.forEach((eventData: any) => {
707+
if (!eventData || !eventData['Event']) return;
705708

706-
const dispositions = dispData['CriminalDispositions'] || [];
709+
// CriminalDispositions are inside the Event property
710+
const dispositions = eventData['Event']['CriminalDispositions'] || [];
707711

708712
// Alert if more than one disposition
709713
if (dispositions && dispositions.length > 1) {
@@ -713,31 +717,39 @@ function buildCaseSummary(rawData: Record<string, any>): CaseSummary | null {
713717
'Multiple dispositions found for a single event',
714718
new Error('Unexpected multiple dispositions'),
715719
{
716-
caseId: rawData.summary?.CaseSummaryHeader?.CaseId || 'unknown',
717-
chargeId: dispData.ChargeId || 'unknown',
718-
eventId: dispData.Id || 'unknown'
720+
caseId: rawData['summary']['CaseSummaryHeader']['CaseId'] || 'unknown',
721+
eventId: eventData['EventId'] || 'unknown'
719722
}
720723
).catch(err => console.error('Failed to log alert:', err));
721724
}
722725

723-
if (!dispositions.length) return;
726+
dispositions.forEach((disp: any) => {
727+
if (!disp) return;
724728

725-
const disp = dispositions[0];
726-
if (!disp) return;
729+
// Extract the event date from either the Event.Date or SortEventDate
730+
const eventDate = eventData['Event']['Date'] || eventData['SortEventDate'] || '';
727731

728-
// Create the disposition object
729-
const disposition: Disposition = {
730-
date: disp['EventDate'] || '',
731-
code: disp['CriminalDispositionTypeId']?.['Code'] || '',
732-
description: disp['CriminalDispositionTypeId']?.['Description'] || ''
733-
};
732+
// The criminal disposition type information contains the code and description
733+
const dispTypeId = disp['CriminalDispositionTypeId'] || {};
734734

735-
// Add disposition to charge
736-
const chargeId = disp['ChargeID'];
737-
const charge = chargeMap.get(chargeId);
738-
if (charge) {
739-
charge.dispositions.push(disposition);
740-
}
735+
// Create the disposition object
736+
const disposition: Disposition = {
737+
date: eventDate,
738+
code: dispTypeId['Word'] || '',
739+
description: dispTypeId['Description'] || ''
740+
};
741+
742+
// The charge ID is in ChargeID (note the capitalization)
743+
const chargeId = disp['ChargeID'];
744+
745+
// Find the matching charge and add the disposition
746+
if (chargeId) {
747+
const charge = chargeMap.get(chargeId);
748+
if (charge) {
749+
charge.dispositions.push(disposition);
750+
}
751+
}
752+
});
741753
});
742754

743755
return caseSummary;

0 commit comments

Comments
 (0)