summaryrefslogtreecommitdiff
path: root/client/src/components
diff options
context:
space:
mode:
authorMichael Hunteman <michael@huntm.net>2024-10-05 11:06:50 -0700
committerMichael Hunteman <michael@huntm.net>2024-10-05 11:06:50 -0700
commitaacf26f374f48b88d532d1528d9d07aabf537610 (patch)
treea777bb304e16e9bc5bf63f0b91c2ce8c727a7090 /client/src/components
parent80c6cc650601613db580c154e8d50e5a13b69f03 (diff)
Add calendar inviteHEADmaster
Diffstat (limited to 'client/src/components')
-rw-r--r--client/src/components/AdminLogin.tsx2
-rw-r--r--client/src/components/CalendarDialog.tsx71
-rw-r--r--client/src/components/GlobalSnackbar.test.tsx2
-rw-r--r--client/src/components/GlobalSnackbar.tsx6
-rw-r--r--client/src/components/GuestLogin.tsx2
-rw-r--r--client/src/components/RsvpForm.tsx2
-rw-r--r--client/src/components/Schedule.test.tsx22
-rw-r--r--client/src/components/Schedule.tsx32
8 files changed, 130 insertions, 9 deletions
diff --git a/client/src/components/AdminLogin.tsx b/client/src/components/AdminLogin.tsx
index a4fce8d..bfc96d2 100644
--- a/client/src/components/AdminLogin.tsx
+++ b/client/src/components/AdminLogin.tsx
@@ -5,7 +5,7 @@ import { useForm } from 'react-hook-form';
import { useAppDispatch } from '../hooks';
import { setAdmin } from '../slices/auth/adminSlice';
import { useLoginAdminMutation } from '../slices/api/adminSlice';
-import { showSnackbar } from '../slices/snackbarSlice';
+import { showSnackbar } from '../slices/uiSlice';
import { isFetchBaseQueryError } from '../error';
import type { Credentials } from '../models';
import type { Data } from '../error';
diff --git a/client/src/components/CalendarDialog.tsx b/client/src/components/CalendarDialog.tsx
new file mode 100644
index 0000000..cff5512
--- /dev/null
+++ b/client/src/components/CalendarDialog.tsx
@@ -0,0 +1,71 @@
+import React from 'react';
+import {
+ Dialog,
+ DialogContent,
+ DialogContentText,
+ DialogTitle,
+ IconButton,
+ useTheme,
+} from '@mui/material';
+import CloseIcon from '@mui/icons-material/Close';
+import { useAppDispatch, useAppSelector } from '../hooks';
+import { hideDialog, selectUIState } from '../slices/uiSlice';
+
+function CalendarDialog() {
+ const dispatch = useAppDispatch();
+ const { dialogOpen } = useAppSelector(selectUIState);
+ const theme = useTheme();
+
+ const handleClose = () => {
+ dispatch(hideDialog());
+ };
+
+ return (
+ <Dialog
+ open={dialogOpen}
+ onClose={handleClose}
+ PaperProps={{ sx: { borderRadius: 2 } }}
+ >
+ <DialogTitle sx={{ textAlign: 'center' }}>
+ Calendar Invitation
+ </DialogTitle>
+ <IconButton
+ aria-label="close"
+ onClick={handleClose}
+ sx={(theme) => ({
+ position: 'absolute',
+ right: 8,
+ top: 8,
+ color: theme.palette.grey[500],
+ })}
+ >
+ <CloseIcon />
+ </IconButton>
+ <DialogContent
+ sx={{
+ height: '100%',
+ width: '100%',
+ display: 'flex',
+ flexDirection: 'column',
+ justifyContent: 'center',
+ alignItems: 'center',
+ gap: 4,
+ }}
+ >
+ <DialogContentText color="inherit">
+ Scan the QR code or click the link below to add the calendar invite to
+ your device.
+ </DialogContentText>
+ <img src="/madison-michael-qr-code.png" />
+ <a
+ href="/madison-michael-wedding.ics"
+ style={{ color: theme.palette.primary.main }}
+ >
+ Add to calendar
+ </a>
+ </DialogContent>
+ </Dialog>
+ );
+}
+
+export default CalendarDialog;
diff --git a/client/src/components/GlobalSnackbar.test.tsx b/client/src/components/GlobalSnackbar.test.tsx
index 2643816..ce6a6ba 100644
--- a/client/src/components/GlobalSnackbar.test.tsx
+++ b/client/src/components/GlobalSnackbar.test.tsx
@@ -4,7 +4,7 @@ import { describe, expect, it } from 'vitest';
import { createMemoryRouter, RouterProvider } from 'react-router-dom';
import { renderWithProviders } from '../renderWithProviders';
import routes from '../routes';
-import { showSnackbar } from '../slices/snackbarSlice';
+import { showSnackbar } from '../slices/uiSlice';
import setupStore from '../store';
describe('Global Snackbar', async () => {
diff --git a/client/src/components/GlobalSnackbar.tsx b/client/src/components/GlobalSnackbar.tsx
index c4457af..83d6582 100644
--- a/client/src/components/GlobalSnackbar.tsx
+++ b/client/src/components/GlobalSnackbar.tsx
@@ -1,18 +1,18 @@
import React from 'react';
import { Alert, Snackbar } from '@mui/material';
import { useAppDispatch, useAppSelector } from '../hooks';
-import { hideSnackbar, selectSnackbarState } from '../slices/snackbarSlice';
+import { hideSnackbar, selectUIState } from '../slices/uiSlice';
function GlobalSnackbar() {
const dispatch = useAppDispatch();
- const { open, message, severity } = useAppSelector(selectSnackbarState);
+ const { snackbarOpen, message, severity } = useAppSelector(selectUIState);
const handleClose = () => {
dispatch(hideSnackbar());
};
return (
- <Snackbar open={open} onClose={handleClose} autoHideDuration={5000}>
+ <Snackbar open={snackbarOpen} onClose={handleClose} autoHideDuration={5000}>
<div>
<Alert severity={severity} onClose={handleClose}>
{message}
diff --git a/client/src/components/GuestLogin.tsx b/client/src/components/GuestLogin.tsx
index 2f5a3eb..c2bfeb9 100644
--- a/client/src/components/GuestLogin.tsx
+++ b/client/src/components/GuestLogin.tsx
@@ -5,7 +5,7 @@ import { useForm } from 'react-hook-form';
import { useAppDispatch } from '../hooks';
import { setGuest } from '../slices/auth/guestSlice';
import { useLoginGuestMutation } from '../slices/api/guestSlice';
-import { showSnackbar } from '../slices/snackbarSlice';
+import { showSnackbar } from '../slices/uiSlice';
import { isFetchBaseQueryError } from '../error';
import type { Data } from '../error';
import type { Name } from '../models';
diff --git a/client/src/components/RsvpForm.tsx b/client/src/components/RsvpForm.tsx
index eae34c3..2a3552f 100644
--- a/client/src/components/RsvpForm.tsx
+++ b/client/src/components/RsvpForm.tsx
@@ -17,7 +17,7 @@ import { useForm, Controller, useFieldArray } from 'react-hook-form';
import { useAppDispatch } from '../hooks';
import { useUpdateGuestMutation } from '../slices/api/guestSlice';
import { isFetchBaseQueryError } from '../error';
-import { showSnackbar } from '../slices/snackbarSlice';
+import { showSnackbar } from '../slices/uiSlice';
import type { Data } from '../error';
import type { Guest } from '../models';
diff --git a/client/src/components/Schedule.test.tsx b/client/src/components/Schedule.test.tsx
new file mode 100644
index 0000000..76f0f91
--- /dev/null
+++ b/client/src/components/Schedule.test.tsx
@@ -0,0 +1,22 @@
+import '@testing-library/jest-dom';
+import React from 'react';
+import { fireEvent } from '@testing-library/react';
+import { userEvent } from '@testing-library/user-event';
+import { describe, expect, it } from 'vitest';
+import { createMemoryRouter, RouterProvider } from 'react-router-dom';
+import { renderWithProviders } from '../renderWithProviders';
+import routes from '../routes';
+
+describe('Schedule', async () => {
+ const memoryRouter = createMemoryRouter(routes, {
+ initialEntries: ['/schedule'],
+ });
+ it('displays calendar dialog', async () => {
+ const { getByLabelText, findByText } = renderWithProviders(
+ <RouterProvider router={memoryRouter} />
+ );
+
+ fireEvent.click(getByLabelText(/insert invitation/i));
+ expect(await findByText(/calendar invitation/i)).toBeInTheDocument();
+ });
+});
diff --git a/client/src/components/Schedule.tsx b/client/src/components/Schedule.tsx
index 0ce7e4c..64140e4 100644
--- a/client/src/components/Schedule.tsx
+++ b/client/src/components/Schedule.tsx
@@ -1,10 +1,25 @@
import React from 'react';
-import { Paper, Typography, useMediaQuery, useTheme } from '@mui/material';
+import {
+ IconButton,
+ Paper,
+ Typography,
+ useMediaQuery,
+ useTheme,
+} from '@mui/material';
import divineShepherd from '/divine-shepherd.jpg';
+import InsertInvitationIcon from '@mui/icons-material/InsertInvitation';
+import { useAppDispatch } from '../hooks';
+import { showDialog } from '../slices/uiSlice';
function Schedule() {
+ const dispatch = useAppDispatch();
const theme = useTheme();
const isMobile = useMediaQuery('(max-width: 768px)');
+
+ const handleOpen = () => {
+ dispatch(showDialog());
+ };
+
return (
<div
style={{
@@ -28,10 +43,23 @@ function Schedule() {
<div style={{ width: '35%' }}>
<p>April 26, 2025</p>
</div>
- <div style={{ width: '65%' }}>
+ <div
+ style={{
+ display: 'flex',
+ justifyContent: 'space-around',
+ width: '65%',
+ }}
+ >
<Typography variant="h5" sx={{ lineHeight: 1.6 }}>
Wedding Schedule
</Typography>
+ <IconButton
+ color="inherit"
+ onClick={handleOpen}
+ aria-label="insert invitation"
+ >
+ <InsertInvitationIcon />
+ </IconButton>
</div>
</div>
<hr style={{ width: '100%' }} />