Skip to content

Commit 8bf5b1c

Browse files
committed
Fix enrollment checker build: resolve TypeScript errors and Vite config
The enrollment checker failed to build (SSG) and failed to run tests due to several issues: - generate-fonts.js crashed when the output directory didn't exist (ENOENT - exactOptionalPropertyTypes violations across enrollment feature components - Vitest couldn't resolve @sebt/design-system subpath exports due to a hard alias that bypassed the package's exports field - Dockerfile.ssg didn't exclude SSR-only API proxy routes from static export
1 parent ce87ac2 commit 8bf5b1c

13 files changed

Lines changed: 60 additions & 37 deletions

File tree

packages/design-system/design/scripts/generate-fonts.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
*/
1717

1818
import './load-env.js'
19-
import { readFileSync, writeFileSync, existsSync } from 'fs'
19+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs'
2020
import { join, dirname, relative } from 'path'
2121
import { fileURLToPath } from 'url'
2222

@@ -170,6 +170,7 @@ function main() {
170170
console.log(`✅ Found ${fonts.size} font(s): ${Array.from(fonts).join(', ')}`)
171171

172172
const fontsTs = generateFontsTs(fonts, state)
173+
mkdirSync(dirname(outputPath), { recursive: true })
173174
writeFileSync(outputPath, fontsTs, 'utf8')
174175

175176
console.log(`✅ Generated fonts.ts for ${state.toUpperCase()}`)

src/SEBT.EnrollmentChecker.Web/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ test-results/
6060
# Pa11y Accessibility Test Screenshots
6161
pa11y-screenshots/
6262

63+
# Generated Design Tokens (auto-generated from design/states/*.json)
64+
design/fonts.ts
65+
6366
# Generated i18n Locale Files
6467
content/locales/
6568
!content/locales/**/common.json

src/SEBT.EnrollmentChecker.Web/Dockerfile.ssg

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ ENV STATE=$STATE \
1818
NEXT_PUBLIC_PORTAL_URL=$NEXT_PUBLIC_PORTAL_URL \
1919
NEXT_PUBLIC_APPLICATION_URL=$NEXT_PUBLIC_APPLICATION_URL
2020

21+
# API routes are SSR-only proxies — remove them before static export
22+
RUN rm -rf src/SEBT.EnrollmentChecker.Web/src/app/api
23+
2124
RUN BUILD_STATIC=true pnpm --filter @sebt/enrollment-checker build
2225
# Output is in src/SEBT.EnrollmentChecker.Web/out/
2326
# Upload to S3: aws s3 sync src/SEBT.EnrollmentChecker.Web/out/ s3://your-bucket/

src/SEBT.EnrollmentChecker.Web/src/features/enrollment/api/checkEnrollment.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { http, HttpResponse } from 'msw'
2-
import { beforeEach, describe, expect, it } from 'vitest'
2+
import { describe, expect, it } from 'vitest'
33
import { server } from '../../../mocks/server'
44
import type { Child } from '../context/EnrollmentContext'
55
import { enrollmentCheckRequestSchema } from '../schemas/enrollmentSchema'

src/SEBT.EnrollmentChecker.Web/src/features/enrollment/components/ChildForm.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ export function ChildForm({
7777
label={tCommon('labelFirstName')}
7878
value={values.firstName ?? ''}
7979
onChange={e => set('firstName', e.target.value)}
80-
error={errors.firstName}
80+
{...(errors.firstName && { error: errors.firstName })}
8181
isRequired
8282
hint={nameHint}
8383
/>
@@ -91,7 +91,7 @@ export function ChildForm({
9191
label={tCommon('labelLastName')}
9292
value={values.lastName ?? ''}
9393
onChange={e => set('lastName', e.target.value)}
94-
error={errors.lastName}
94+
{...(errors.lastName && { error: errors.lastName })}
9595
isRequired
9696
hint={nameHint}
9797
/>

src/SEBT.EnrollmentChecker.Web/src/features/enrollment/components/ChildFormPage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export function ChildFormPage({ showSchoolField, apiBaseUrl }: ChildFormPageProp
6767
<p className="usa-prose">{t('body')}</p>
6868
<p className="usa-hint">{t('requiredFields', { ns: 'common' })}</p>
6969
<ChildForm
70-
initialValues={editingChild}
70+
{...(editingChild && { initialValues: editingChild })}
7171
onSubmit={handleSubmit}
7272
onCancel={handleCancel}
7373
showSchoolField={showSchoolField}

src/SEBT.EnrollmentChecker.Web/src/features/enrollment/components/ChildReviewCard.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ interface ChildReviewCardProps {
1010

1111
/** Format ISO date (YYYY-MM-DD) as a locale-aware date string (e.g., "April 12, 2015"). */
1212
function formatBirthdate(dateOfBirth: string, locale: string): string {
13-
const [year, month, day] = dateOfBirth.split('-').map(Number)
14-
const date = new Date(year, month - 1, day)
13+
const parts = dateOfBirth.split('-').map(Number)
14+
const date = new Date(parts[0]!, parts[1]! - 1, parts[2]!)
1515
return date.toLocaleDateString(locale, { year: 'numeric', month: 'long', day: 'numeric' })
1616
}
1717

src/SEBT.EnrollmentChecker.Web/src/features/enrollment/components/ResultsPage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export function ResultsPage({ results, applicationUrl }: ResultsPageProps) {
4343
firstName={child.firstName}
4444
lastName={child.lastName}
4545
displayStatus="error"
46-
errorMessage={child.statusMessage}
46+
{...(child.statusMessage !== undefined && { errorMessage: child.statusMessage })}
4747
/>
4848
))}
4949
</section>

src/SEBT.EnrollmentChecker.Web/src/features/enrollment/context/EnrollmentContext.tsx

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,22 @@ function loadFromStorage(): EnrollmentState {
7676
if (!raw) return initialState
7777
const parsed: unknown = JSON.parse(raw)
7878
const result = enrollmentStorageSchema.safeParse(parsed)
79-
return result.success ? result.data : initialState
79+
if (!result.success) return initialState
80+
return {
81+
editingChildId: result.data.editingChildId,
82+
children: result.data.children.map(parsedChild => {
83+
const child: Child = {
84+
id: parsedChild.id,
85+
firstName: parsedChild.firstName,
86+
lastName: parsedChild.lastName,
87+
dateOfBirth: parsedChild.dateOfBirth,
88+
...(parsedChild.middleName && { middleName: parsedChild.middleName }),
89+
...(parsedChild.schoolName && { schoolName: parsedChild.schoolName }),
90+
...(parsedChild.schoolCode && { schoolCode: parsedChild.schoolCode })
91+
}
92+
return child
93+
})
94+
}
8095
} catch {
8196
return initialState
8297
}
@@ -106,33 +121,36 @@ export function EnrollmentProvider({ children }: { children: ReactNode }) {
106121
const actions: EnrollmentActions = {
107122
addChild: (values) => update(s => {
108123
if (s.children.length >= MAX_CHILDREN) return s
109-
return {
110-
...s,
111-
children: [...s.children, {
124+
const child: Child = {
112125
id: uuidv4(),
113126
firstName: values.firstName,
114-
middleName: values.middleName,
115127
lastName: values.lastName,
116128
dateOfBirth: toDateOfBirth(values),
117-
schoolName: values.schoolName,
118-
schoolCode: values.schoolCode
119-
}]
120-
}}),
129+
...(values.middleName && { middleName: values.middleName }),
130+
...(values.schoolName && { schoolName: values.schoolName }),
131+
...(values.schoolCode && { schoolCode: values.schoolCode })
132+
}
133+
return { ...s, children: [...s.children, child] }
134+
}),
121135
updateChild: (id, values) => update(s => ({
122136
...s,
123-
children: s.children.map(c => c.id === id ? {
124-
id,
125-
firstName: values.firstName,
126-
middleName: values.middleName,
127-
lastName: values.lastName,
128-
dateOfBirth: toDateOfBirth(values),
129-
schoolName: values.schoolName,
130-
schoolCode: values.schoolCode
131-
} : c)
137+
children: s.children.map(child => {
138+
if (child.id !== id) return child
139+
const updated: Child = {
140+
id,
141+
firstName: values.firstName,
142+
lastName: values.lastName,
143+
dateOfBirth: toDateOfBirth(values),
144+
...(values.middleName && { middleName: values.middleName }),
145+
...(values.schoolName && { schoolName: values.schoolName }),
146+
...(values.schoolCode && { schoolCode: values.schoolCode })
147+
}
148+
return updated
149+
})
132150
})),
133151
removeChild: (id) => update(s => ({
134152
...s,
135-
children: s.children.filter(c => c.id !== id)
153+
children: s.children.filter(child => child.id !== id)
136154
})),
137155
setEditingChildId: (id) => update(s => ({ ...s, editingChildId: id })),
138156
clearState: () => {

src/SEBT.EnrollmentChecker.Web/src/features/enrollment/schemas/childSchema.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,11 @@ export function toDateOfBirth(values: Pick<ChildFormValues, 'month' | 'day' | 'y
2828

2929
/** Decompose an ISO date string into month/day/year for form population. */
3030
export function fromDateOfBirth(dateOfBirth: string): { month: string; day: string; year: string } {
31-
const [year, month, day] = dateOfBirth.split('-')
31+
const parts = dateOfBirth.split('-')
3232
// Strip leading zeros for natural display (e.g., "04" -> "4")
3333
return {
34-
month: String(parseInt(month, 10)),
35-
day: String(parseInt(day, 10)),
36-
year
34+
month: String(parseInt(parts[1]!, 10)),
35+
day: String(parseInt(parts[2]!, 10)),
36+
year: parts[0]!
3737
}
3838
}

0 commit comments

Comments
 (0)