Skip to content

Commit

Permalink
Merge pull request #16 from DTS-STN/develop
Browse files Browse the repository at this point in the history
Adding layout components, QoL hooks, and assets into the project
  • Loading branch information
JeremyKennedy authored Dec 7, 2021
2 parents 32536dc + d5ed8f9 commit 79657ff
Show file tree
Hide file tree
Showing 18 changed files with 355 additions and 13 deletions.
10 changes: 0 additions & 10 deletions components/Alert/index.jsx

This file was deleted.

27 changes: 27 additions & 0 deletions components/Contexts/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React, { useState } from 'react'
import { useStorage } from '../Hooks'
import { dictionaryList } from '../../i18n'

export const LanguageContext = React.createContext({
userLanguage: 'en',
userLanguageChange: (selected) => void 0,
})

export function LanguageProvider({ children }) {
const [userLanguage, setUserLanguage] = useStorage<string>(
'local',
'lang',
'en'
)

return (
<LanguageContext.Provider
value={{
userLanguage,
userLanguageChange: (selected) => setUserLanguage(selected),
}}
>
{children}
</LanguageContext.Provider>
)
}
58 changes: 58 additions & 0 deletions components/Hooks/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { useContext, useState } from 'react'
import { LanguageContext } from '../Contexts'
import { languageOptions, dictionaryList } from '../../i18n'

type StorageType = 'session' | 'local'

// Stuff's a user's data into the client side storage of the developer's choosing
export const useStorage = <T,>(
type: StorageType,
key: string,
initialValue: T
) => {
// NextJs renders component serverside and there is no window available there
const isBrowser: boolean = ((): boolean => typeof window !== 'undefined')()

const store = type == 'local' ? 'localStorage' : 'sessionStorage'

const [storedValue, setStoredValue] = useState<T>(() => {
try {
if (isBrowser) {
const item = window[store].getItem(key)
return item ? JSON.parse(item) : initialValue
}
return ''
} catch (error) {
console.log(error)
return initialValue
}
})

const setValue = (value: T | ((val: T) => T)) => {
try {
const valueToStore =
value instanceof Function ? value(storedValue) : value

setStoredValue(valueToStore)
window[store].setItem(key, JSON.stringify(valueToStore))
} catch (error) {
console.log(error)
}
}
return [storedValue, setValue] as const
}

// For text heavy components, just pull in the correct language's dictionary and use dot notation to get your values in the component
export const useTranslation = () => {
const { userLanguage } = useContext(LanguageContext)

// use current language to fetch the correct i18n data
return dictionaryList[userLanguage]
}

// For one off text needs where you want a specific text value internationalized
export const useInternationalization = (key: string) => {
const { userLanguage } = useContext(LanguageContext)
if (dictionaryList[userLanguage] == undefined) return ''
return dictionaryList[userLanguage][key]
}
3 changes: 3 additions & 0 deletions components/Layout/Footer.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.footerBackground {
background: #26374a url(/bgc.png) no-repeat 100% 100%;
}
102 changes: 102 additions & 0 deletions components/Layout/Footer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import styles from './Footer.module.css'
import Image from 'next/image'

export const Footer = () => (
<footer className="text-[14px]">
<div
className={`w-full h-auto bg-custom-blue-dark ${styles.footerBackground}`}
>
<div
className="py-7 container mx-auto"
role="navigation"
aria-labelledby="footerNav1"
>
<h3 className="sr-only" id="footerNav1">
About government
</h3>
<ul className="flex flex-col text-xs lg:grid lg:grid-cols-2 xl:grid xl:grid-cols-3 lg:gap-1">
<li className="text-white w-64 md:w-56 lg:w-80 my-2.5 hover:underline">
<a className="font-body" href="#">
Contact us
</a>
</li>
<li className="text-white w-64 md:w-56 lg:w-80 my-2.5 hover:underline">
<a className="font-body" href="#">
News
</a>
</li>
<li className="text-white w-64 md:w-56 lg:w-80 my-2.5 hover:underline">
<a className="font-body" href="#">
Prime Minister
</a>
</li>
<li className="text-white w-64 md:w-56 lg:w-80 my-2.5 hover:underline">
<a className="font-body" href="#">
Departments and agencies
</a>
</li>
<li className="text-white w-64 md:w-56 lg:w-80 my-2.5 hover:underline">
<a className="font-body" href="#">
Treaties, laws and regulations
</a>
</li>
<li className="text-white w-64 md:w-56 lg:w-80 my-2.5 hover:underline">
<a className="font-body" href="#">
How government works
</a>
</li>
<li className="text-white w-64 md:w-56 lg:w-80 my-2.5 hover:underline">
<a className="font-body" href="#">
Public service and military
</a>
</li>
<li className="text-white w-64 md:w-56 lg:w-80 my-2.5 hover:underline">
<a className="font-body" href="#">
Government-wide reporting
</a>
</li>
<li className="text-white w-64 md:w-56 lg:w-80 my-2.5 hover:underline">
<a className="font-body" href="#">
Open government
</a>
</li>
</ul>
</div>
</div>
<div className="my-8">
<div className="container mx-auto flex justify-between items-center">
<nav className="">
<ul className="flex flex-row list-disc space-x-6">
<li className="list-none">
<a href="#">Social media</a>
</li>

<li>
<a href="#">Mobile applications</a>
</li>

<li>
<a href="#">About Canada.ca</a>
</li>

<li>
<a href="#">Terms and conditions</a>
</li>

<li>
<a href="#">Privacy</a>
</li>
</ul>
</nav>
<div>
<Image
width="200px"
height="40px"
src="/wmms-blk.svg"
alt="Symbol of the Government of Canada"
/>
</div>
</div>
</div>
</footer>
)
42 changes: 42 additions & 0 deletions components/Layout/Header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React from 'react'
import Image from 'next/image'
import { useInternationalization } from '../Hooks'

export const Header = () => (
<header className="border-b border-black/20 pb-10 -mx-4">
<div className="container mx-auto">
<div className="flex justify-between items-center">
<Image
src="/gc-sig.png"
width="360px"
height="34px"
alt="Government of Canada banner image"
/>
<label htmlFor="search-gc" className="block mb-2">
<input
type="search"
id="search-gc"
placeholder={useInternationalization('search')}
className="h-auto min-h-9 py-1.5 px-3 align-middle text-muted bg-white rounded-tl rounded-bl border-[1px] border-solid border-form-border focus:border-form-highlighted focus:shadow-active-form"
/>
<button className="py-1.5 px-3 h-[38px] rounded-tr rounded-br text-white bg-primary hover:bg-primary-hover border-primary-border font-normal text-base text-center whitespace-nowrap align-middle cursor-pointer border-[1px] border-solid">
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-5 w-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={3}
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
/>
</svg>
</button>
</label>
</div>
</div>
</header>
)
43 changes: 43 additions & 0 deletions components/Layout/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { useRouter } from 'next/router'
import React, { useContext } from 'react'
import { LanguageContext } from '../Contexts'
import { useInternationalization } from '../Hooks'
import { Footer } from './Footer'
import { Header } from './Header'

export const Layout: React.VFC<{
children: React.ReactNode
}> = ({ children }) => {
const otherLang = useInternationalization('otherLang')
const otherLangNameFull = useInternationalization('otherLangFull')

const { userLanguageChange } = useContext(LanguageContext)

return (
<main>
<div className="mx-4 min-h-screen">
<div className="container mx-auto">
<div className="flex justify-end my-4">
<button
className="btn-link btn underline"
onClick={(e) => userLanguageChange(otherLang)}
>
{otherLangNameFull}
</button>
</div>
</div>
<Header />
<div className="bg-primary -mx-4">
<div className="flex flex-row justify-between items-center container mx-auto">
<h3 className="text-h3 py-3 text-white font-bold">
Service Canada
</h3>
<p className="font-bold text-white">Sign out</p>
</div>
</div>
<div className="container mx-auto flex flex-col mb-16">{children}</div>
</div>
<Footer />
</main>
)
}
8 changes: 8 additions & 0 deletions i18n/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"otherLang": "fr",
"otherLangFull": "Français",
"search": "Search Canada.ca",
"welcome": "Welcome",
"branch": "Branch number",
"req": "required"
}
8 changes: 8 additions & 0 deletions i18n/fr.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"otherLang": "en",
"otherLangFull": "English",
"search": "Rechercher dans Canada.ca",
"welcome": "Bienvenue",
"branch": "FR - Branch number",
"req": "FR - required"
}
9 changes: 9 additions & 0 deletions i18n/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import fr from './fr.json'
import en from './en.json'

export const dictionaryList = { en, fr }

export const languageOptions = {
en: 'English',
fr: 'Français',
}
29 changes: 29 additions & 0 deletions public/CanadaBackdrop.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed public/alert-example-wet.png
Binary file not shown.
Binary file removed public/alert-example.png
Binary file not shown.
Binary file added public/bgc.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions public/gc-image-enfr.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/gc-sig.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

1 comment on commit 79657ff

@vercel
Copy link

@vercel vercel bot commented on 79657ff Dec 7, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.