diff --git a/frontend/src/hooks/useGuests/index.tsx b/frontend/src/hooks/useGuests/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..d18b246546fb848b0a2ad5641e09fd865f674343 --- /dev/null +++ b/frontend/src/hooks/useGuests/index.tsx @@ -0,0 +1,47 @@ +import { useEffect, useState } from 'react' +import { FetchedGuest, Guest } from '../../interfaces' +import { parseRole } from '../../utils' + +const useGuests = () => { + const [guests, setGuests] = useState<Guest[]>([]) + + const getGuestsInfo = async () => { + try { + const response = await fetch('/api/ui/v1/guests/?format=json') + const jsonResponse = await response.json() + if (response.ok) { + const persons = await jsonResponse.persons + setGuests( + persons.map( + (person: FetchedGuest): Guest => ({ + pid: person.pid, + first: person.first, + last: person.last, + email: person.email, + mobile: person.mobile, + fnr: person.fnr, + active: person.active, + roles: person.roles.map((role) => parseRole(role)), + registered: person.registered, + verified: person.verified, + }) + ) + ) + } + } catch (error) { + setGuests([]) + } + } + + const reloadGuests = () => { + getGuestsInfo() + } + + useEffect(() => { + getGuestsInfo() + }, []) + + return { guests, reloadGuests } +} + +export default useGuests diff --git a/frontend/src/routes/sponsor/guest/guestInfo/index.tsx b/frontend/src/routes/sponsor/guest/guestInfo/index.tsx index 453d413980749f102d208c0b511e711dccd583a2..d01f6f02b20756eab34cb3b86ed523662c72803f 100644 --- a/frontend/src/routes/sponsor/guest/guestInfo/index.tsx +++ b/frontend/src/routes/sponsor/guest/guestInfo/index.tsx @@ -33,6 +33,7 @@ type GuestInfoProps = { guest: Guest updateEmail: (validEmail: string) => void resend: () => void + reloadGuests: () => void } type CancelConfirmationDialogProps = { @@ -81,6 +82,7 @@ export default function GuestInfo({ guest, updateEmail, resend, + reloadGuests, }: GuestInfoProps) { const { pid } = useParams<GuestInfoParams>() const [t] = useTranslation(['common']) @@ -127,11 +129,8 @@ export default function GuestInfo({ .then((result) => { if (result !== null) { // The invite for the guest has been cancelled, send the user back to the sponsor front page - // Sending the user first to "/" since this clears the state. If the user is sent - // directly to "/sponsor" then the page does not reload and the cancelled entry is - // still in the list of sent invites - history.push('/') - history.replace('/sponsor') + reloadGuests() + history.push('/sponsor') } }) .catch((error) => { diff --git a/frontend/src/routes/sponsor/guest/index.tsx b/frontend/src/routes/sponsor/guest/index.tsx index c1a60676bcc078245e2fb5fb713e10badcfd07f3..8046bae7ae41923a7b2517d68c258d563a258ff2 100644 --- a/frontend/src/routes/sponsor/guest/index.tsx +++ b/frontend/src/routes/sponsor/guest/index.tsx @@ -9,7 +9,11 @@ type GuestInfoParams = { pid: string } -function GuestRoutes() { +type GuestRoutesProps = { + reloadGuests: () => void +} + +function GuestRoutes({ reloadGuests }: GuestRoutesProps) { const { pid } = useParams<GuestInfoParams>() const { guestInfo, reloadGuestInfo } = useGuest(pid) @@ -62,6 +66,7 @@ function GuestRoutes() { guest={guestInfo} updateEmail={updateEmail} resend={resend} + reloadGuests={reloadGuests} /> </Route> </> diff --git a/frontend/src/routes/sponsor/index.tsx b/frontend/src/routes/sponsor/index.tsx index d070e2b28d5d4cef3fb69234c66d4c6335ebd40f..0ae812164733dbdfabd7d28e81ce72ae24425666 100644 --- a/frontend/src/routes/sponsor/index.tsx +++ b/frontend/src/routes/sponsor/index.tsx @@ -1,50 +1,16 @@ -import { useEffect, useState } from 'react' import { Route } from 'react-router-dom' import FrontPage from 'routes/sponsor/frontpage' -import { FetchedGuest, Guest } from 'interfaces' -import { parseRole } from 'utils' import GuestRoutes from './guest' +import useGuests from '../../hooks/useGuests' function Sponsor() { - const [guests, setGuests] = useState<Guest[]>([]) - - const getGuestsInfo = async () => { - try { - const response = await fetch('/api/ui/v1/guests/?format=json') - const jsonResponse = await response.json() - if (response.ok) { - const persons = await jsonResponse.persons - setGuests( - persons.map( - (person: FetchedGuest): Guest => ({ - pid: person.pid, - first: person.first, - last: person.last, - email: person.email, - mobile: person.mobile, - fnr: person.fnr, - active: person.active, - roles: person.roles.map((role) => parseRole(role)), - registered: person.registered, - verified: person.verified, - }) - ) - ) - } - } catch (error) { - setGuests([]) - } - } - - useEffect(() => { - getGuestsInfo() - }, []) + const { guests, reloadGuests } = useGuests() return ( <> <Route path="/sponsor/guest/:pid"> - <GuestRoutes /> + <GuestRoutes reloadGuests={reloadGuests} /> </Route> <Route exact path="/sponsor"> <FrontPage guests={guests} /> diff --git a/gregui/api/views/invitation.py b/gregui/api/views/invitation.py index bf32e2e7ef00d8a7f4c06a6df20f27126f6e542e..88531650500f689621c08b79a0e9214aeaa3a7e3 100644 --- a/gregui/api/views/invitation.py +++ b/gregui/api/views/invitation.py @@ -80,8 +80,11 @@ class InvitationView(CreateAPIView, DestroyAPIView): return Response(status=status.HTTP_201_CREATED) def delete(self, request, *args, **kwargs) -> Response: - person_id = int(request.query_params["person_id"]) - person = Person.objects.get(id=person_id) + try: + person_id = int(request.query_params["person_id"]) + person = Person.objects.get(id=person_id) + except Person.DoesNotExist: + return Response(status=status.HTTP_404_NOT_FOUND) if person.is_registered or person.is_verified: # The guest has already gone through the registration step. The guest should