Skip to content

Commit b3326af

Browse files
authored
Feat/add wizgov widget (#1195)
* add WizgovWidgetProps interface and update exports in internal index (cherry picked from commit b6632d97bc166abd16c18c930ff7e1c823003659) * add wizgov property to IsomerSiteConfigProps interface * add WizgovWidgetClient component * integrate WizgovWidgetClient into Skeleton layout * add conditional rendering of prod/staging link * refactor WizgovWidget to use environment prop instead of site; update Skeleton layout accordingly * refactor WizgovWidget: remove WizgovWidgetClient, integrate script loading directly, and simplify props handling
1 parent 2f645d7 commit b3326af

File tree

7 files changed

+69
-0
lines changed

7 files changed

+69
-0
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import type { IsomerSiteProps } from "~/types"
2+
3+
export interface WizgovProps {
4+
"data-agency": string
5+
}
6+
7+
export interface WizgovWidgetProps extends WizgovProps {
8+
environment: IsomerSiteProps["environment"]
9+
}

packages/components/src/interfaces/internal/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,4 @@ export type {
4242
GoogleTagManagerBodyProps,
4343
} from "./GoogleTagManager"
4444
export type { AttrsDirProps } from "./AttrsDir"
45+
export type { WizgovWidgetProps, WizgovProps } from "./Wizgov"
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
"use client"
2+
3+
import { useEffect } from "react"
4+
5+
import type { WizgovWidgetProps } from "~/interfaces"
6+
7+
// Reference: https://github.com/opengovsg/wizgov
8+
export const WizgovWidget = ({
9+
environment,
10+
...wizgovProps
11+
}: WizgovWidgetProps) => {
12+
const scriptUrl =
13+
environment === "production"
14+
? "https://script.wiz.gov.sg/widget.js"
15+
: "https://script-staging.wiz.gov.sg/widget.js"
16+
17+
const reloadWizgovScript = () => {
18+
const scriptId = "isomer-wizgov-script"
19+
20+
const existingScriptTag = document.getElementById(scriptId)
21+
if (existingScriptTag) {
22+
existingScriptTag.remove()
23+
}
24+
25+
const scriptTag = document.createElement("script")
26+
scriptTag.id = scriptId
27+
scriptTag.async = true
28+
scriptTag.type = "text/javascript"
29+
scriptTag.src = scriptUrl
30+
scriptTag.referrerPolicy = "origin"
31+
document.body.appendChild(scriptTag)
32+
}
33+
34+
useEffect(() => {
35+
// to not render during static site generation on the server
36+
if (typeof window === "undefined") return
37+
38+
// Only inject the script after everything else has finished loading
39+
// This is to replicate Next.js lazyOnload behaviour (as recommended for widgets)
40+
if (document.readyState === "complete") {
41+
reloadWizgovScript()
42+
} else {
43+
window.addEventListener("load", () => reloadWizgovScript())
44+
return () =>
45+
window.removeEventListener("load", () => reloadWizgovScript())
46+
}
47+
}, [])
48+
49+
return <div id="wizgov-widget" data-agency={wizgovProps["data-agency"]} />
50+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { WizgovWidget } from "./WizgovWidget"

packages/components/src/templates/next/components/internal/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,4 @@ export {
3232
export { BlogCard } from "./BlogCard"
3333
export { FontPreload } from "./FontPreload"
3434
export { ScrollToTop } from "./ScrollToTop"
35+
export { WizgovWidget } from "./Wizgov"

packages/components/src/templates/next/layouts/Skeleton/Skeleton.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
UnsupportedBrowserBanner,
1515
VicaStylesheet,
1616
VicaWidget,
17+
WizgovWidget,
1718
Wogaa,
1819
} from "../../components/internal"
1920
import { SKIP_TO_CONTENT_ANCHOR_ID } from "../../constants"
@@ -111,7 +112,11 @@ export const Skeleton = ({
111112
)}
112113

113114
{/* Ensures that the webchat widget only loads after the page has loaded */}
115+
{/* Note: did not account for both being added to the config as it's a very unlikely scenario and there's "correct" way to handle this */}
114116
{site.vica && <VicaWidget site={site} {...site.vica} />}
117+
{site.wizgov && (
118+
<WizgovWidget environment={site.environment} {...site.wizgov} />
119+
)}
115120
</>
116121
)
117122
}

packages/components/src/types/site.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type {
33
NavbarProps,
44
NotificationProps,
55
VicaWidgetProps,
6+
WizgovProps,
67
} from "~/interfaces"
78
import type { SiteConfigFooterProps } from "~/interfaces/internal/Footer"
89

@@ -31,6 +32,7 @@ export interface IsomerSiteConfigProps {
3132
notification?: Omit<NotificationProps, "LinkComponent" | "site">
3233
siteGtmId?: string
3334
vica?: VicaWidgetProps
35+
wizgov?: WizgovProps
3436
}
3537

3638
export type IsomerSiteProps = IsomerGeneratedSiteProps &

0 commit comments

Comments
 (0)