✨ feat(pop-up): add event pop up dialog
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 306 KiB |
@@ -0,0 +1,61 @@
|
||||
import { act, fireEvent, render, screen } from '@testing-library/react'
|
||||
|
||||
import EventDialog from './index.js'
|
||||
|
||||
describe('EventDialog', () => {
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
vi.useRealTimers()
|
||||
})
|
||||
|
||||
it('appears after a delay', () => {
|
||||
vi.setSystemTime(new Date(2026, 9, 19))
|
||||
render(<EventDialog />)
|
||||
|
||||
expect(screen.queryByRole('img')).not.toBeInTheDocument()
|
||||
|
||||
act(() => {
|
||||
vi.advanceTimersByTime(3000)
|
||||
})
|
||||
|
||||
expect(screen.getByRole('img', { name: /open day/i })).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('can be dismissed', () => {
|
||||
vi.setSystemTime(new Date(2026, 9, 19))
|
||||
render(<EventDialog />)
|
||||
act(() => {
|
||||
vi.advanceTimersByTime(3000)
|
||||
})
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: /close/i }))
|
||||
act(() => {
|
||||
vi.runAllTimers()
|
||||
})
|
||||
|
||||
expect(screen.queryByRole('img')).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('still appears on October 25th', () => {
|
||||
vi.setSystemTime(new Date(2026, 9, 25, 23, 59))
|
||||
render(<EventDialog />)
|
||||
act(() => {
|
||||
vi.advanceTimersByTime(3000)
|
||||
})
|
||||
|
||||
expect(screen.getByRole('img', { name: /open day/i })).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('does not appear after October 25th', () => {
|
||||
vi.setSystemTime(new Date(2026, 9, 26))
|
||||
render(<EventDialog />)
|
||||
act(() => {
|
||||
vi.advanceTimersByTime(10000)
|
||||
})
|
||||
|
||||
expect(screen.queryByRole('img')).not.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,43 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { Box, Dialog, IconButton } from '@mui/material'
|
||||
import CloseIcon from '@mui/icons-material/Close'
|
||||
|
||||
const SHOW_DELAY_MS = 3000
|
||||
// Local midnight after Oct 25th, so the event is promoted through the whole day.
|
||||
const EXPIRES_AT = new Date(2026, 9, 26)
|
||||
|
||||
const EventDialog = () => {
|
||||
const [open, setOpen] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
if (Date.now() >= EXPIRES_AT.getTime()) return
|
||||
const timer = setTimeout(() => setOpen(true), SHOW_DELAY_MS)
|
||||
return () => clearTimeout(timer)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<Dialog open={open} onClose={() => setOpen(false)} maxWidth={false} aria-label="Open Day event">
|
||||
<IconButton
|
||||
aria-label="Close"
|
||||
onClick={() => setOpen(false)}
|
||||
sx={{ position: 'absolute', top: 4, right: 4, bgcolor: 'background.paper', '&:hover': { bgcolor: 'background.paper' } }}>
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
<Box
|
||||
component="img"
|
||||
src="/images/20261024_banner_open_day.webp"
|
||||
alt="Open Day, October 24th"
|
||||
sx={{
|
||||
display: 'block',
|
||||
width: 'auto',
|
||||
height: 'auto',
|
||||
maxWidth: 'calc(100vw - 64px)',
|
||||
maxHeight: 'calc(100vh - 64px)',
|
||||
objectFit: 'contain',
|
||||
}}
|
||||
/>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
||||
export default EventDialog
|
||||
@@ -1,6 +1,8 @@
|
||||
import { useEffect } from 'react'
|
||||
import { Outlet, useLocation } from 'react-router-dom'
|
||||
|
||||
import EventDialog from 'components/molecules/EventDialog/index.js'
|
||||
|
||||
/**
|
||||
* Route tracking component that wraps all routes and includes analytics page tracking
|
||||
*/
|
||||
@@ -11,7 +13,12 @@ const RouteTracker = () => {
|
||||
window.scrollTo(0, 0)
|
||||
}, [location])
|
||||
|
||||
return <Outlet />
|
||||
return (
|
||||
<>
|
||||
<Outlet />
|
||||
<EventDialog />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default RouteTracker
|
||||
|
||||
Reference in New Issue
Block a user