Skip to content

Commit 4e69603

Browse files
authored
Merge pull request #1785 from Mephistic/handlebars-story
Storybook for Handlebars Templates
2 parents b028290 + c84ae00 commit 4e69603

File tree

7 files changed

+203
-219
lines changed

7 files changed

+203
-219
lines changed

functions/src/email/example1.handlebars

Lines changed: 0 additions & 16 deletions
This file was deleted.

functions/src/email/example2.handlebars

Lines changed: 0 additions & 24 deletions
This file was deleted.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@
175175
"eslint-config-prettier": "^8.3.0",
176176
"eslint-plugin-i18next": "^6.0.3",
177177
"eslint-plugin-jsx-a11y": "^6.9.0",
178+
"file-loader": "^6.2.0",
178179
"firebase-admin": "^10",
179180
"firebase-tools": "^11.16.0",
180181
"ini": "^1.3.5",
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
import { Meta, StoryObj } from "@storybook/react"
2+
import digestEmail from "functions/src/email/digestEmail.handlebars"
3+
import { EmailTemplateRenderer } from "./EmailTemplateRenderer"
4+
import {
5+
BillDigest,
6+
BillResult,
7+
NotificationEmailDigest,
8+
UserDigest
9+
} from "functions/src/notifications/emailTypes"
10+
import { Frequency } from "components/auth"
11+
12+
const meta: Meta = {
13+
title: "Email Templates/Notifications Digest",
14+
component: EmailTemplateRenderer,
15+
decorators: [
16+
Story => (
17+
// Use a narrow window to represent an email client
18+
// TODO: May need to update to match styling of a real email client
19+
<div style={{ background: "white", width: "600px", minHeight: "80vh" }}>
20+
<Story />
21+
</div>
22+
)
23+
]
24+
}
25+
26+
export default meta
27+
28+
type Story = StoryObj<typeof EmailTemplateRenderer>
29+
30+
// Generate test data for the digest email
31+
32+
// Summary of Bills
33+
const bills: BillDigest[] = [
34+
{
35+
billId: "H868",
36+
billName:
37+
"An Act improving campaign finance reporting by state ballot question committees",
38+
billCourt: "194",
39+
endorseCount: 2,
40+
neutralCount: 0,
41+
opposeCount: 1
42+
},
43+
{
44+
billId: "H1436",
45+
billName: "An Act relative to debt-free public higher education",
46+
billCourt: "194",
47+
endorseCount: 2,
48+
neutralCount: 0,
49+
opposeCount: 0
50+
},
51+
{
52+
billId: "H533",
53+
billName: "An Act to expand the use of career and academic plans",
54+
billCourt: "194",
55+
endorseCount: 10,
56+
neutralCount: 2,
57+
opposeCount: 24
58+
},
59+
{
60+
billId: "H841",
61+
billName:
62+
"An Act granting the city of Boston the authority to endow legal voting rights in municipal elections for city of Boston residents aged 16 and 17 years old",
63+
billCourt: "194",
64+
endorseCount: 35,
65+
neutralCount: 20,
66+
opposeCount: 10
67+
},
68+
{
69+
billId: "H54",
70+
billName:
71+
"An Act to build resilient infrastructure to generate higher-ed transformation",
72+
billCourt: "194",
73+
endorseCount: 0,
74+
neutralCount: 0,
75+
opposeCount: 1
76+
}
77+
]
78+
79+
const billResults: BillResult[] = [
80+
{
81+
billId: "H868",
82+
court: "194",
83+
position: "endorse"
84+
},
85+
{
86+
billId: "H1436",
87+
court: "194",
88+
position: "neutral"
89+
},
90+
{
91+
billId: "H533",
92+
court: "194",
93+
position: "oppose"
94+
},
95+
{
96+
billId: "H841",
97+
court: "194",
98+
position: "endorse"
99+
},
100+
{
101+
billId: "H54",
102+
court: "194",
103+
position: "oppose"
104+
},
105+
{
106+
billId: "H66",
107+
court: "194",
108+
position: "neutral"
109+
},
110+
{
111+
billId: "H30",
112+
court: "194",
113+
position: "endorse"
114+
}
115+
]
116+
117+
const generateTestUserData = (
118+
userId: string,
119+
userName: string,
120+
numBillsWithTestimony: number
121+
): UserDigest => {
122+
return {
123+
userId,
124+
userName,
125+
bills: billResults.slice(0, Math.min(6, numBillsWithTestimony)),
126+
newTestimonyCount: numBillsWithTestimony
127+
}
128+
}
129+
130+
const users = [
131+
generateTestUserData("0BvO7rSlFjRVHuLfd7RlHRYg2DN1", "John Doe", 7),
132+
generateTestUserData("2jBTpZQ1kXVVSaJvLy2mxfduoc64", "Jane Roe", 6),
133+
generateTestUserData(
134+
"381slAnGbzP6atlF4Af4D9pYQT24",
135+
"Society for the Humane Prevention of Testimony",
136+
5
137+
),
138+
generateTestUserData("Nyvk23VDNQSoK9TQ9LK5xF1DwT64", "Person McPersonson", 4),
139+
generateTestUserData("QDPq42rNB0O6wqVzfMmDHmNE8sN3", "Iranout Ofnameideas", 3)
140+
]
141+
142+
const generateTestData = (
143+
frequency: Frequency,
144+
numBills: number,
145+
numUsers: number
146+
): NotificationEmailDigest => {
147+
return {
148+
notificationFrequency: frequency,
149+
startDate: new Date("2025-04-01T04:00:00Z"),
150+
endDate: new Date(
151+
`2025-04-${frequency === "Monthly" ? "30" : "07"}T04:00:00Z`
152+
),
153+
bills: bills.slice(0, Math.min(4, numBills)),
154+
users: users.slice(0, Math.min(4, numUsers)),
155+
numBillsWithNewTestimony: numBills,
156+
numUsersWithNewTestimony: numUsers
157+
}
158+
}
159+
160+
// Frequency is guaranteed to be Monthly or Weekly,
161+
// and there must be at least 1 bill OR 1 user with testimony
162+
// or else a digest wouldn't be generated
163+
const createDigestStory = (context: NotificationEmailDigest) => {
164+
return {
165+
args: {
166+
templateSrcUrl: digestEmail,
167+
context
168+
}
169+
}
170+
}
171+
172+
export const FullDigest: Story = createDigestStory(
173+
generateTestData("Monthly", 4, 4)
174+
)
175+
176+
export const OnlyBills: Story = createDigestStory(
177+
generateTestData("Weekly", 4, 0)
178+
)
179+
180+
export const OnlyUsers: Story = createDigestStory(
181+
generateTestData("Weekly", 0, 4)
182+
)
183+
184+
export const TooManyBills: Story = createDigestStory(
185+
generateTestData("Monthly", 100, 0)
186+
)
187+
188+
export const TooManyUsers: Story = createDigestStory(
189+
generateTestData("Monthly", 0, 100)
190+
)
191+
192+
export const TooManyBillsAndUsers: Story = createDigestStory(
193+
generateTestData("Monthly", 100, 100)
194+
)

0 commit comments

Comments
 (0)