Merged in feat/LOY-197-screen-wake-dtmc (pull request #1996)
feat(LOY-197): add screen wake lock to dtmc Approved-by: Chuma Mcphoy (We Ahead)
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
|
import { useState } from "react"
|
||||||
import { Button } from "react-aria-components"
|
import { Button } from "react-aria-components"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
@@ -7,6 +8,7 @@ import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
|||||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||||
|
|
||||||
import Modal from "@/components/Modal"
|
import Modal from "@/components/Modal"
|
||||||
|
import useWakeLock from "@/hooks/useWakeLock"
|
||||||
|
|
||||||
import styles from "./digitalTeamMemberCard.module.css"
|
import styles from "./digitalTeamMemberCard.module.css"
|
||||||
|
|
||||||
@@ -20,97 +22,109 @@ export default function DigitalTeamMemberCardClient({
|
|||||||
user,
|
user,
|
||||||
}: DigitalTeamMemberCardClientProps) {
|
}: DigitalTeamMemberCardClientProps) {
|
||||||
const intl = useIntl()
|
const intl = useIntl()
|
||||||
|
const [isOpen, setIsOpen] = useState(false)
|
||||||
|
|
||||||
|
const { release, request } = useWakeLock({
|
||||||
|
reacquireOnPageVisible: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
function onToggle(modalState: boolean) {
|
||||||
|
setIsOpen(modalState)
|
||||||
|
if (modalState) {
|
||||||
|
request()
|
||||||
|
} else {
|
||||||
|
release()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<>
|
||||||
trigger={
|
<Button className={styles.button} onPress={() => onToggle(true)}>
|
||||||
<Button className={styles.button}>
|
<Typography variant="Body/Paragraph/mdBold">
|
||||||
<Typography variant="Body/Paragraph/mdBold">
|
<span className={styles.text}>
|
||||||
<span className={styles.text}>
|
{/* @ts-expect-error Icon is supported in font, just not in React Material Symbols package */}
|
||||||
{/* @ts-expect-error Icon is supported in font, just not in React Material Symbols package */}
|
<MaterialIcon icon="id_card" size={24} color="CurrentColor" />
|
||||||
<MaterialIcon icon="id_card" size={24} color="CurrentColor" />
|
{intl.formatMessage({
|
||||||
{intl.formatMessage({
|
defaultMessage: "Show Team Member Card",
|
||||||
defaultMessage: "Show Team Member Card",
|
})}
|
||||||
})}
|
</span>
|
||||||
</span>
|
</Typography>
|
||||||
</Typography>
|
</Button>
|
||||||
</Button>
|
<Modal onToggle={onToggle} isOpen={isOpen} className={styles.modal}>
|
||||||
}
|
<Typography variant="Title/xs">
|
||||||
className={styles.modal}
|
<h2 className={styles.title}>
|
||||||
>
|
{intl.formatMessage({ defaultMessage: "Scandic Family" })}
|
||||||
<Typography variant="Title/xs">
|
</h2>
|
||||||
<h2 className={styles.title}>
|
</Typography>
|
||||||
{intl.formatMessage({ defaultMessage: "Scandic Family" })}
|
<div className={styles.card}>
|
||||||
</h2>
|
<div className={styles.content}>
|
||||||
</Typography>
|
<div className={styles.top}>
|
||||||
<div className={styles.card}>
|
<Typography variant="Tag/sm">
|
||||||
<div className={styles.content}>
|
<span>
|
||||||
<div className={styles.top}>
|
{intl.formatMessage({ defaultMessage: "Team Member" })}
|
||||||
<Typography variant="Tag/sm">
|
</span>
|
||||||
<span>
|
</Typography>
|
||||||
{intl.formatMessage({ defaultMessage: "Team Member" })}
|
<Typography variant="Tag/sm">
|
||||||
</span>
|
{/* TODO: Should display country of employment */}
|
||||||
</Typography>
|
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||||
<Typography variant="Tag/sm">
|
<span>SWE</span>
|
||||||
{/* TODO: Should display country of employment */}
|
|
||||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
|
||||||
<span>SWE</span>
|
|
||||||
</Typography>
|
|
||||||
</div>
|
|
||||||
<div className={styles.middle}>
|
|
||||||
<div className={styles.employeeNumber}>
|
|
||||||
<Typography variant="Title/sm">
|
|
||||||
{/* TODO: Should display employee number */}
|
|
||||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
|
||||||
<div>123 456</div>
|
|
||||||
</Typography>
|
</Typography>
|
||||||
<svg
|
|
||||||
width="42"
|
|
||||||
height="42"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
className={styles.icon}
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M3.5 35V12.288C3.5 8.933 3.5 7 4.268 7c.912 0 1.569 1.156 3.17 3.978l11.374 20.044C20.413 33.844 21.041 35 21.982 35c.768 0 .768-1.933.768-5.288V7M28 22.75h10.5M29.016 8.016c1.355-1.355 7.113-1.355 8.468 0 1.355 1.355 1.355 7.113 0 8.468-1.355 1.355-7.114 1.355-8.468 0-1.355-1.355-1.355-7.113 0-8.468Z"
|
|
||||||
strokeWidth="2.625"
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div className={styles.middle}>
|
||||||
<Typography variant="Title/md">
|
<div className={styles.employeeNumber}>
|
||||||
<div>
|
<Typography variant="Title/sm">
|
||||||
{user.firstName} {user.lastName}
|
{/* TODO: Should display employee number */}
|
||||||
|
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||||
|
<div>123 456</div>
|
||||||
|
</Typography>
|
||||||
|
<svg
|
||||||
|
width="42"
|
||||||
|
height="42"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
className={styles.icon}
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M3.5 35V12.288C3.5 8.933 3.5 7 4.268 7c.912 0 1.569 1.156 3.17 3.978l11.374 20.044C20.413 33.844 21.041 35 21.982 35c.768 0 .768-1.933.768-5.288V7M28 22.75h10.5M29.016 8.016c1.355-1.355 7.113-1.355 8.468 0 1.355 1.355 1.355 7.113 0 8.468-1.355 1.355-7.114 1.355-8.468 0-1.355-1.355-1.355-7.113 0-8.468Z"
|
||||||
|
strokeWidth="2.625"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</Typography>
|
|
||||||
</div>
|
<Typography variant="Title/md">
|
||||||
<div className={styles.bottom}>
|
<div>
|
||||||
<Typography variant="Tag/sm">
|
{user.firstName} {user.lastName}
|
||||||
<span>
|
</div>
|
||||||
{/* TODO: Should display department of employment */}
|
</Typography>
|
||||||
{/* eslint-disable formatjs/no-literal-string-in-jsx */}
|
</div>
|
||||||
Haymarket by Scandic
|
<div className={styles.bottom}>
|
||||||
{/* eslint-enable */}
|
<Typography variant="Tag/sm">
|
||||||
</span>
|
<span>
|
||||||
</Typography>
|
{/* TODO: Should display department of employment */}
|
||||||
<Typography variant="Tag/sm">
|
{/* eslint-disable formatjs/no-literal-string-in-jsx */}
|
||||||
{/* TODO: Should display current state of employment */}
|
Haymarket by Scandic
|
||||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
{/* eslint-enable */}
|
||||||
<span>Employee</span>
|
</span>
|
||||||
</Typography>
|
</Typography>
|
||||||
|
<Typography variant="Tag/sm">
|
||||||
|
{/* TODO: Should display current state of employment */}
|
||||||
|
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||||
|
<span>Employee</span>
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<Typography variant="Body/Paragraph/mdRegular">
|
||||||
<Typography variant="Body/Paragraph/mdRegular">
|
<div className={styles.footer}>
|
||||||
<div className={styles.footer}>
|
{intl.formatMessage({
|
||||||
{intl.formatMessage({
|
defaultMessage:
|
||||||
defaultMessage:
|
"Book discounted stays for yourself, family and friends!",
|
||||||
"Book discounted stays for yourself, family and friends!",
|
})}
|
||||||
})}
|
</div>
|
||||||
</div>
|
</Typography>
|
||||||
</Typography>
|
</Modal>
|
||||||
</Modal>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
72
apps/scandic-web/hooks/useWakeLock.ts
Normal file
72
apps/scandic-web/hooks/useWakeLock.ts
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import { useCallback, useEffect, useRef } from "react"
|
||||||
|
|
||||||
|
let isSupported = false
|
||||||
|
|
||||||
|
if ("wakeLock" in navigator) {
|
||||||
|
isSupported = true
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Options {
|
||||||
|
reacquireOnPageVisible?: boolean
|
||||||
|
onRequest?: () => void
|
||||||
|
onRelease?: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uses the Wake Lock API to keep the screen from dimming or locking.
|
||||||
|
* https://developer.mozilla.org/en-US/docs/Web/API/Screen_Wake_Lock_API
|
||||||
|
*/
|
||||||
|
export default function useWakeLock({
|
||||||
|
reacquireOnPageVisible = false,
|
||||||
|
onRequest = () => undefined,
|
||||||
|
onRelease = () => undefined,
|
||||||
|
}: Options = {}) {
|
||||||
|
const wakeLock = useRef<WakeLockSentinel | null>(null)
|
||||||
|
|
||||||
|
const request = useCallback(async () => {
|
||||||
|
if (!isSupported) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
wakeLock.current = await navigator.wakeLock.request("screen")
|
||||||
|
|
||||||
|
onRequest()
|
||||||
|
|
||||||
|
wakeLock.current.onrelease = () => {
|
||||||
|
onRelease()
|
||||||
|
}
|
||||||
|
} catch (_err) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}, [onRelease, onRequest])
|
||||||
|
|
||||||
|
const release = useCallback(() => {
|
||||||
|
if (!isSupported) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
wakeLock.current?.release().then(() => {
|
||||||
|
wakeLock.current = null
|
||||||
|
})
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handleVisibilityChange = () => {
|
||||||
|
if (wakeLock.current !== null && document.visibilityState === "visible") {
|
||||||
|
request()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reacquireOnPageVisible) {
|
||||||
|
document.addEventListener("visibilitychange", handleVisibilityChange)
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener("visibilitychange", handleVisibilityChange)
|
||||||
|
}
|
||||||
|
}, [reacquireOnPageVisible, request])
|
||||||
|
|
||||||
|
return { isSupported, request, release }
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user