Skip to content

Commit 6dc8dfd

Browse files
FEAT:added the action plan to the print view (#102)
1 parent 21a53cf commit 6dc8dfd

7 files changed

Lines changed: 89 additions & 24 deletions

File tree

frontend/src/app/[locale]/generate-referrals/page.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,7 @@ export default function Page() {
331331
<PrintableReferralsReport
332332
resources={result ?? []}
333333
clientDescription={clientDescription}
334+
actionPlan={actionPlan}
334335
/>
335336
</div>
336337
</>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { ActionPlan } from "@/util/fetchActionPlan";
2+
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
3+
import { FileText } from "lucide-react";
4+
import { parseMarkdownToHTML } from "@/util/markdown";
5+
export function ActionPlanDisplay({ actionPlan }: { actionPlan: ActionPlan }) {
6+
return (
7+
<Card className="bg-blue-50 border-blue-200 shadow-sm mb-5">
8+
<CardHeader>
9+
<CardTitle className="text-lg font-semibold text-blue-900 flex items-center gap-2">
10+
<FileText className="w-5 h-5 text-blue-600" />
11+
{actionPlan.title}
12+
</CardTitle>
13+
</CardHeader>
14+
<CardContent>
15+
<div className="mb-3 text-black text-base">{actionPlan.summary}</div>
16+
<div
17+
className="prose prose-sm max-w-none text-gray-800"
18+
dangerouslySetInnerHTML={{
19+
__html: parseMarkdownToHTML(actionPlan.content),
20+
}}
21+
/>
22+
</CardContent>
23+
</Card>
24+
);
25+
}

frontend/src/components/ActionPlanSection.tsx

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
44
import { Spinner } from "@/components/ui/spinner";
55
import { Resource } from "@/types/resources";
66
import { ActionPlan } from "@/util/fetchActionPlan";
7-
import { parseMarkdownToHTML } from "@/util/markdown";
7+
import { ActionPlanDisplay } from "@/components/ActionPlanDisplay";
88

99
interface ActionPlanSectionProps {
1010
resources: Resource[];
@@ -104,27 +104,7 @@ export function ActionPlanSection({
104104
</Card>
105105

106106
{/* Action Plan Display */}
107-
{actionPlan && (
108-
<Card className="bg-blue-50 border-blue-200 shadow-sm mb-5">
109-
<CardHeader>
110-
<CardTitle className="text-lg font-semibold text-blue-900 flex items-center gap-2">
111-
<FileText className="w-5 h-5 text-blue-600" />
112-
{actionPlan.title}
113-
</CardTitle>
114-
</CardHeader>
115-
<CardContent>
116-
<div className="mb-3 text-black text-base">
117-
{actionPlan.summary}
118-
</div>
119-
<div
120-
className="prose prose-sm max-w-none text-gray-800"
121-
dangerouslySetInnerHTML={{
122-
__html: parseMarkdownToHTML(actionPlan.content),
123-
}}
124-
/>
125-
</CardContent>
126-
</Card>
127-
)}
107+
{actionPlan && <ActionPlanDisplay actionPlan={actionPlan} />}
128108
</>
129109
);
130110
}

frontend/src/components/ClientDetailsInput.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ export function ClientDetailsInput({
280280
loading ||
281281
(selectedCategories.length === 0 && !clientDescription.trim())
282282
}
283-
className="min-w-[16rem] generate-referrals-button text-lg pt-6 pb-6"
283+
className="min-w-[16rem] w-full row-auto generate-referrals-button text-lg pt-6 pb-6"
284284
data-testid="findResourcesButton"
285285
>
286286
{!loading && (
@@ -290,7 +290,7 @@ export function ClientDetailsInput({
290290
)}
291291
{loading && (
292292
<>
293-
<Spinner className="" />
293+
<Spinner className="w-5 h-5" />
294294
Generating Resources...
295295
</>
296296
)}

frontend/src/util/printReferrals.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,17 @@ import { Resource } from "@/types/resources";
22
import React from "react";
33
import ResourcesList from "@/components/ResourcesList";
44
import ClientDetailsPromptBubble from "@/components/ClientDetailsPromptBubble";
5+
import { ActionPlanDisplay } from "@/components/ActionPlanDisplay";
6+
import { ActionPlan } from "@/util/fetchActionPlan";
57

68
export function PrintableReferralsReport({
79
resources,
810
clientDescription,
11+
actionPlan,
912
}: {
1013
resources: Resource[];
1114
clientDescription: string;
15+
actionPlan?: ActionPlan | null;
1216
}) {
1317
const date = new Date();
1418
return (
@@ -25,6 +29,11 @@ export function PrintableReferralsReport({
2529
</div>
2630
<ClientDetailsPromptBubble clientDescription={clientDescription} />
2731
<ResourcesList resources={resources ?? []} />
32+
{actionPlan && (
33+
<div className="print:mt-3">
34+
<ActionPlanDisplay actionPlan={actionPlan} />
35+
</div>
36+
)}
2837

2938
<div className="text-center text-slate-500 text-[12px] mt-5 pt-4 border-t border-slate-200">
3039
Report generated by Goodwill Central Texas GenAI Referral Tool

frontend/tests/jest.setup.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,8 @@ import "@testing-library/jest-dom";
33
import { toHaveNoViolations } from "jest-axe";
44

55
expect.extend(toHaveNoViolations);
6+
7+
// Mock the markdown parser to avoid ES module issues with unified/remark/rehype
8+
jest.mock("../src/util/markdown", () => ({
9+
parseMarkdownToHTML: (content: string) => content,
10+
}));

frontend/tests/util/printReferrals.test.tsx

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { render, screen } from "tests/react-utils";
22
import { PrintableReferralsReport } from "@/util/printReferrals";
33
import { Resource } from "@/types/resources";
4+
import { ActionPlan } from "@/util/fetchActionPlan";
45

56
describe("PrintableReferralsReport", () => {
67
const mockResources: Resource[] = [
@@ -27,6 +28,14 @@ describe("PrintableReferralsReport", () => {
2728
},
2829
];
2930

31+
const sampleActionPlan: ActionPlan = {
32+
title: "Expunge your record after fulfilling probation requirements",
33+
summary:
34+
"Having a clean record will help you in your job application process.",
35+
content:
36+
"### Project RIO\\n**How to apply:**\\n- Call the Project RIO line and ask for the Austin office: 1-800-453-8140. ([hrw.org](https://www.hrw.org/news/2010/07/20/texas-prison-resources?utm_source=openai))\\n- Visit or mail to the TWC Project RIO office at 101 East 15th Street, Room 506-T, Austin, TX 78778 to set an intake appointment. ([hrw.org](https://www.hrw.org/news/2010/07/20/texas-prison-resources?utm_source=openai))\\n\\n**Documents needed:**\\n- Photo ID (state ID or driver’s license)\\n- Proof of release/parole papers or probation completion\\n- Social Security card or number\\n- Recent resume or list of past jobs (if available)\\n\\n**Timeline:**\\n- First appointment often same week to 2 weeks.\\n\\n**Key tip:**\\n- Tell staff you are eligible for employer incentives (Work Opportunity Tax Credit). Project RIO staff can connect you to employers and note hiring incentives. ([ojp.gov](https://www.ojp.gov/ncjrs/virtual-library/abstracts/project-rio-procedures-and-reporting-manual?utm_source=openai))\\n",
37+
};
38+
3039
it("displays the header with organization name", () => {
3140
render(
3241
<PrintableReferralsReport
@@ -152,4 +161,40 @@ describe("PrintableReferralsReport", () => {
152161
),
153162
).toBeInTheDocument();
154163
});
164+
165+
it("displays action plan when provided", () => {
166+
render(
167+
<PrintableReferralsReport
168+
resources={mockResources}
169+
clientDescription={"client needs help accessing Goodwill classes"}
170+
actionPlan={sampleActionPlan}
171+
/>,
172+
);
173+
174+
expect(screen.getByText(sampleActionPlan.title)).toBeInTheDocument();
175+
expect(screen.getByText(sampleActionPlan.summary)).toBeInTheDocument();
176+
});
177+
178+
it("does not display action plan section when actionPlan is null", () => {
179+
render(
180+
<PrintableReferralsReport
181+
resources={mockResources}
182+
clientDescription={"client needs help accessing Goodwill classes"}
183+
actionPlan={null}
184+
/>,
185+
);
186+
187+
expect(screen.queryByText(sampleActionPlan.title)).not.toBeInTheDocument();
188+
});
189+
190+
it("does not display action plan section when actionPlan is undefined", () => {
191+
render(
192+
<PrintableReferralsReport
193+
resources={mockResources}
194+
clientDescription={"client needs help accessing Goodwill classes"}
195+
/>,
196+
);
197+
198+
expect(screen.queryByText(sampleActionPlan.title)).not.toBeInTheDocument();
199+
});
155200
});

0 commit comments

Comments
 (0)