Skip to content

Commit

Permalink
feat: pretty 404 for events/rsvps
Browse files Browse the repository at this point in the history
  • Loading branch information
mplewis committed Dec 3, 2024
1 parent 78258a8 commit c4c842e
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 7 deletions.
2 changes: 1 addition & 1 deletion NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
- [ ] Make required env vars required with `mustEnv`, etc. (e.g. `SITE_HOST`)
- [ ] Make Sentry DSN optional
- [ ] Consensually gather user emails for mailing list
- [ ] Add pretty error messages for 404s (e.g. clicked an expired/tidied link)
- [ ] Redirect old slugs on slug change
- [ ] Add sticky bit to "sent you a confirmation email for your RSVP"
- [ ] Site-wide announcement feature
Expand All @@ -48,6 +47,7 @@
- [ ] Replace shared API lib dir with Yarn "shared package" workspace
- [ ] Add advanced crash logging
- [ ] Linter for secrets in build
- [x] Add pretty error messages for 404s (e.g. clicked an expired/tidied link)
- [x] Resend confirmation if an RSVP enters an existing email
- [x] Captcha
- [x] Hold RSVP locally with cookie
Expand Down
2 changes: 1 addition & 1 deletion api/src/services/responses/responses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export const responseByEditToken: QueryResolvers['responseByEditToken'] =
include: { event: true, reminders: true },
})

if (!resp) throw new RedwoodError("Sorry, we couldn't find that RSVP.")
if (!resp) return null

if (!resp.confirmed) {
const updated = await db.response.update({
Expand Down
21 changes: 21 additions & 0 deletions web/src/components/DeadEnd/DeadEnd.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type { Meta, StoryObj } from '@storybook/react'

import DeadEnd from './DeadEnd'

const meta: Meta<typeof DeadEnd> = {
component: DeadEnd,
tags: ['autodocs'],
}

export default meta

type Story = StoryObj<typeof DeadEnd>

/** DeadEnd tells users when their request can't be completed and they have to turn back. */
export const Primary: Story = {
args: {
title: 'Page not found',
desc: "Sorry, we couldn't find the page you were looking for.",
c2a: { text: 'Go home', to: '#' },
},
}
45 changes: 45 additions & 0 deletions web/src/components/DeadEnd/DeadEnd.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Link } from '@redwoodjs/router'

import PageHead from '../PageHead/PageHead'
import Typ from '../Typ/Typ'

export type Props = {
title: string
desc: string | string[]
c2a: { text: string } & ({ href: string } | { to: string })
}

const DeadEnd = (props: Props) => {
const { title, c2a } = props
const desc = Array.isArray(props.desc) ? props.desc : [props.desc]

const action = (() => {
if ('href' in c2a) {
return (
<a className="button is-primary mt-3" href={c2a.href}>
{c2a.text}
</a>
)
} else {
return (
<Link className="button is-primary mt-3" to={c2a.to}>
{c2a.text}
</Link>
)
}
})()

return (
<div className="has-text-centered mx-auto" style={{ maxWidth: '600px' }}>
<PageHead title={title} desc={desc.join(' ')} />
{desc.map((p, i) => (
<Typ x="p" key={i}>
{p}
</Typ>
))}
{action}
</div>
)
}

export default DeadEnd
14 changes: 13 additions & 1 deletion web/src/components/EditEventCell/EditEventCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type {

import type { CellSuccessProps, CellFailureProps } from '@redwoodjs/web'

import DeadEnd from '../DeadEnd/DeadEnd'
import EditEventForm from '../EditEventForm/EditEventForm'
import LoadingBuddy from '../LoadingBuddy/LoadingBuddy'
export const QUERY = gql`
Expand Down Expand Up @@ -38,7 +39,18 @@ export const Loading = () => (
</div>
)

export const Empty = () => <div>Event not found</div>
export const Empty = () => (
<DeadEnd
title="Event not found"
desc={[
"Sorry, we couldn't find the event you were looking for.",
'Please double-check that you have the correct link.',
'Our system automatically cleans up unconfirmed and completed events. ' +
"If you're using an old link, your event may have expired.",
]}
c2a={{ text: 'Go home', to: '/' }}
/>
)

export const Failure = ({
error,
Expand Down
14 changes: 13 additions & 1 deletion web/src/components/EditResponseCell/EditResponseCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { responseTokenAtom } from 'src/data/atoms'
import { promptConfirm } from 'src/logic/prompt'

import CalButtons from '../CalButtons/CalButtons'
import DeadEnd from '../DeadEnd/DeadEnd'
import DeleteButton from '../DeleteButton/DeleteButton'
import LoadingBuddy from '../LoadingBuddy/LoadingBuddy'
import PageHead from '../PageHead/PageHead'
Expand Down Expand Up @@ -87,7 +88,18 @@ export const Loading = () => (
</div>
)

export const Empty = () => <div>Empty</div>
export const Empty = () => (
<DeadEnd
title="RSVP not found"
desc={[
"Sorry, we couldn't find your RSVP.",
'Please double-check that you have the correct link.',
'Our system automatically cleans up completed events. ' +
"If you're using an old link, the event may have expired.",
]}
c2a={{ text: 'Go home', to: '/' }}
/>
)

export const Failure = ({
error,
Expand Down
14 changes: 13 additions & 1 deletion web/src/components/PreviewEventCell/PreviewEventCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type {

import type { CellSuccessProps, CellFailureProps } from '@redwoodjs/web'

import DeadEnd from '../DeadEnd/DeadEnd'
import LoadingBuddy from '../LoadingBuddy/LoadingBuddy'
import PageHead from '../PageHead/PageHead'
import ShowEvent from '../ShowEvent/ShowEvent'
Expand All @@ -31,7 +32,18 @@ export const Loading = () => (
</div>
)

export const Empty = () => <div>Event not found</div>
export const Empty = () => (
<DeadEnd
title="Event not found"
desc={[
"Sorry, we couldn't find the event you were looking for.",
'Please double-check that you have the correct link.',
'Our system automatically cleans up unconfirmed and completed events. ' +
"If you're using an old link, your event may have expired.",
]}
c2a={{ text: 'Go home', to: '/' }}
/>
)

export const Failure = ({
error,
Expand Down
15 changes: 13 additions & 2 deletions web/src/components/ViewEventCell/ViewEventCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type {

import { CellSuccessProps, CellFailureProps, Metadata } from '@redwoodjs/web'

import DeadEnd from '../DeadEnd/DeadEnd'
import LoadingBuddy from '../LoadingBuddy/LoadingBuddy'
import ShowEvent from '../ShowEvent/ShowEvent'

Expand Down Expand Up @@ -39,8 +40,18 @@ export const Loading = () => (
</div>
)

export const Empty = () => <div>Event not found</div>

export const Empty = () => (
<DeadEnd
title="Event not found"
desc={[
"Sorry, we couldn't find the event you were looking for.",
'Please double-check that you have the correct link.',
'Our system automatically cleans up unconfirmed and completed events. ' +
"If you're using an old link, your event may have expired.",
]}
c2a={{ text: 'Go home', to: '/' }}
/>
)
export const Failure = ({
error,
}: CellFailureProps<FindViewEventQueryVariables>) => (
Expand Down

0 comments on commit c4c842e

Please sign in to comment.