Skip to content

Instantly share code, notes, and snippets.

@suzubara
Created July 13, 2020 21:25
Show Gist options
  • Save suzubara/5614034757bbc8365326f4942f9c4304 to your computer and use it in GitHub Desktop.
Save suzubara/5614034757bbc8365326f4942f9c4304 to your computer and use it in GitHub Desktop.
Renew Session Modal component
import React, { useRef, useState } from 'react'
import ReactDOM from 'react-dom'
import {
Button,
Modal,
connectModal,
ConnectedModalProps,
useModal,
} from '@trussworks/react-uswds'
import {
useGlobalModal,
useTimeout,
useInterval,
} from '../../containers/customHooks'
import styles from './RenewSessionModal.module.scss'
interface RenewSessionModalProps extends ConnectedModalProps {
timeoutLength: number
onRenew: () => void
onLogout: () => void
}
export const RenewSessionModal = ({
timeoutLength,
onRenew,
onLogout,
}: RenewSessionModalProps): React.ReactElement => {
const [countdown, setCountdown] = useState(timeoutLength / 1000)
useTimeout(() => {
onLogout()
}, timeoutLength)
useInterval(() => {
setCountdown(countdown - 1)
}, 1000)
const countdownMinutes = Math.floor(countdown / 60)
const countdownDisplay =
countdownMinutes > 0
? `${countdownMinutes} min${
countdown % 60 !== 0 ? `, ${countdown % 60} sec` : ''
}`
: `${countdown} sec`
return (
<Modal
title={<h2>Extend session?</h2>}
actions={
<>
<Button type="button" outline onClick={onLogout}>
Log out
</Button>
<Button type="button" onClick={onRenew}>
Extend session
</Button>
</>
}
className={styles.RenewSessionModal}
data-testid="renewSessionModal">
<p>
Your session will expire in <strong>{countdownDisplay}.</strong>
</p>
<p>Would you like to extend it?</p>
</Modal>
)
}
export const ConnectedRenewSessionModal = ({
onLogout,
onRenew,
lastRequest,
}: Pick<RenewSessionModalProps, 'onLogout' | 'onRenew'> & {
lastRequest?: number
}): React.ReactElement => {
const now = useRef(Date.now())
const sessionLength = 1000 * 60 * 3 // 3 minutes
const timeoutLength = 1000 * 60 * 2 // 2 minutes (total of 5 minutes)
const sessionModal = useModal()
const ModalComponent = connectModal(RenewSessionModal)
const modalRoot = document.getElementById('modal-root')
useGlobalModal(sessionModal.isOpen)
useTimeout(
() => {
sessionModal.openModal()
},
sessionLength,
[now.current, lastRequest]
)
const handleLogout = (): void => {
sessionModal.closeModal()
onLogout()
}
const handleRenew = (): void => {
sessionModal.closeModal()
onRenew()
// restart timeout
now.current = Date.now()
}
return modalRoot ? (
ReactDOM.createPortal(
<ModalComponent
onRenew={handleRenew}
onLogout={handleLogout}
timeoutLength={timeoutLength}
isOpen={sessionModal.isOpen}
onClose={sessionModal.closeModal}
/>,
modalRoot
)
) : (
<ModalComponent
onRenew={handleRenew}
onLogout={handleLogout}
timeoutLength={timeoutLength}
isOpen={sessionModal.isOpen}
onClose={sessionModal.closeModal}
/>
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment