diff --git a/packages/pl-fe/src/actions/events.ts b/packages/pl-fe/src/actions/events.ts index a67b69cb7..e6d49d556 100644 --- a/packages/pl-fe/src/actions/events.ts +++ b/packages/pl-fe/src/actions/events.ts @@ -6,7 +6,7 @@ import toast from 'pl-fe/toast'; import { importEntities } from './importer'; import { STATUS_FETCH_SOURCE_FAIL, STATUS_FETCH_SOURCE_REQUEST, STATUS_FETCH_SOURCE_SUCCESS } from './statuses'; -import type { Account, CreateEventParams, Location, MediaAttachment, PaginatedResponse, Status } from 'pl-api'; +import type { CreateEventParams, Location, MediaAttachment, PaginatedResponse, Status } from 'pl-api'; import type { AppDispatch, RootState } from 'pl-fe/store'; const EVENT_SUBMIT_REQUEST = 'EVENT_SUBMIT_REQUEST' as const; @@ -21,22 +21,6 @@ const EVENT_LEAVE_REQUEST = 'EVENT_LEAVE_REQUEST' as const; const EVENT_LEAVE_SUCCESS = 'EVENT_LEAVE_SUCCESS' as const; const EVENT_LEAVE_FAIL = 'EVENT_LEAVE_FAIL' as const; -const EVENT_PARTICIPATION_REQUESTS_FETCH_REQUEST = 'EVENT_PARTICIPATION_REQUESTS_FETCH_REQUEST' as const; -const EVENT_PARTICIPATION_REQUESTS_FETCH_SUCCESS = 'EVENT_PARTICIPATION_REQUESTS_FETCH_SUCCESS' as const; -const EVENT_PARTICIPATION_REQUESTS_FETCH_FAIL = 'EVENT_PARTICIPATION_REQUESTS_FETCH_FAIL' as const; - -const EVENT_PARTICIPATION_REQUESTS_EXPAND_REQUEST = 'EVENT_PARTICIPATION_REQUESTS_EXPAND_REQUEST' as const; -const EVENT_PARTICIPATION_REQUESTS_EXPAND_SUCCESS = 'EVENT_PARTICIPATION_REQUESTS_EXPAND_SUCCESS' as const; -const EVENT_PARTICIPATION_REQUESTS_EXPAND_FAIL = 'EVENT_PARTICIPATION_REQUESTS_EXPAND_FAIL' as const; - -const EVENT_PARTICIPATION_REQUEST_AUTHORIZE_REQUEST = 'EVENT_PARTICIPATION_REQUEST_AUTHORIZE_REQUEST' as const; -const EVENT_PARTICIPATION_REQUEST_AUTHORIZE_SUCCESS = 'EVENT_PARTICIPATION_REQUEST_AUTHORIZE_SUCCESS' as const; -const EVENT_PARTICIPATION_REQUEST_AUTHORIZE_FAIL = 'EVENT_PARTICIPATION_REQUEST_AUTHORIZE_FAIL' as const; - -const EVENT_PARTICIPATION_REQUEST_REJECT_REQUEST = 'EVENT_PARTICIPATION_REQUEST_REJECT_REQUEST' as const; -const EVENT_PARTICIPATION_REQUEST_REJECT_SUCCESS = 'EVENT_PARTICIPATION_REQUEST_REJECT_SUCCESS' as const; -const EVENT_PARTICIPATION_REQUEST_REJECT_FAIL = 'EVENT_PARTICIPATION_REQUEST_REJECT_FAIL' as const; - const EVENT_COMPOSE_CANCEL = 'EVENT_COMPOSE_CANCEL' as const; const EVENT_FORM_SET = 'EVENT_FORM_SET' as const; @@ -213,136 +197,6 @@ const leaveEventFail = (error: unknown, statusId: string, previousState: Exclude previousState, }); -const fetchEventParticipationRequests = (statusId: string) => - (dispatch: AppDispatch, getState: () => RootState) => { - dispatch(fetchEventParticipationRequestsRequest(statusId)); - - return getClient(getState).events.getEventParticipationRequests(statusId).then(response => { - dispatch(importEntities({ accounts: response.items.map(({ account }) => account) })); - return dispatch(fetchEventParticipationRequestsSuccess(statusId, response.items, response.next)); - }).catch(error => { - dispatch(fetchEventParticipationRequestsFail(statusId, error)); - }); - }; - -const fetchEventParticipationRequestsRequest = (statusId: string) => ({ - type: EVENT_PARTICIPATION_REQUESTS_FETCH_REQUEST, - statusId, -}); - -const fetchEventParticipationRequestsSuccess = (statusId: string, participations: Array<{ - account: Account; - participation_message: string; -}>, next: (() => Promise>) | null) => ({ - type: EVENT_PARTICIPATION_REQUESTS_FETCH_SUCCESS, - statusId, - participations, - next, -}); - -const fetchEventParticipationRequestsFail = (statusId: string, error: unknown) => ({ - type: EVENT_PARTICIPATION_REQUESTS_FETCH_FAIL, - statusId, - error, -}); - -const expandEventParticipationRequests = (statusId: string) => - (dispatch: AppDispatch, getState: () => RootState) => { - const next = getState().user_lists.event_participation_requests[statusId]?.next || null; - - if (next === null) { - return dispatch(noOp); - } - - dispatch(expandEventParticipationRequestsRequest(statusId)); - - return next().then(response => { - dispatch(importEntities({ accounts: response.items.map(({ account }) => account) })); - return dispatch(expandEventParticipationRequestsSuccess(statusId, response.items, response.next)); - }).catch(error => { - dispatch(expandEventParticipationRequestsFail(statusId, error)); - }); - }; - -const expandEventParticipationRequestsRequest = (statusId: string) => ({ - type: EVENT_PARTICIPATION_REQUESTS_EXPAND_REQUEST, - statusId, -}); - -const expandEventParticipationRequestsSuccess = (statusId: string, participations: Array<{ - account: Account; - participation_message: string; -}>, next: (() => Promise>) | null) => ({ - type: EVENT_PARTICIPATION_REQUESTS_EXPAND_SUCCESS, - statusId, - participations, - next, -}); - -const expandEventParticipationRequestsFail = (statusId: string, error: unknown) => ({ - type: EVENT_PARTICIPATION_REQUESTS_EXPAND_FAIL, - statusId, - error, -}); - -const authorizeEventParticipationRequest = (statusId: string, accountId: string) => - (dispatch: AppDispatch, getState: () => RootState) => { - dispatch(authorizeEventParticipationRequestRequest(statusId, accountId)); - - return getClient(getState).events.acceptEventParticipationRequest(statusId, accountId).then(() => { - dispatch(authorizeEventParticipationRequestSuccess(statusId, accountId)); - toast.success(messages.authorized); - }).catch(error => dispatch(authorizeEventParticipationRequestFail(statusId, accountId, error))); - }; - -const authorizeEventParticipationRequestRequest = (statusId: string, accountId: string) => ({ - type: EVENT_PARTICIPATION_REQUEST_AUTHORIZE_REQUEST, - statusId, - accountId, -}); - -const authorizeEventParticipationRequestSuccess = (statusId: string, accountId: string) => ({ - type: EVENT_PARTICIPATION_REQUEST_AUTHORIZE_SUCCESS, - statusId, - accountId, -}); - -const authorizeEventParticipationRequestFail = (statusId: string, accountId: string, error: unknown) => ({ - type: EVENT_PARTICIPATION_REQUEST_AUTHORIZE_FAIL, - statusId, - accountId, - error, -}); - -const rejectEventParticipationRequest = (statusId: string, accountId: string) => - (dispatch: AppDispatch, getState: () => RootState) => { - dispatch(rejectEventParticipationRequestRequest(statusId, accountId)); - - return getClient(getState).events.rejectEventParticipationRequest(statusId, accountId).then(() => { - dispatch(rejectEventParticipationRequestSuccess(statusId, accountId)); - toast.success(messages.rejected); - }).catch(error => dispatch(rejectEventParticipationRequestFail(statusId, accountId, error))); - }; - -const rejectEventParticipationRequestRequest = (statusId: string, accountId: string) => ({ - type: EVENT_PARTICIPATION_REQUEST_REJECT_REQUEST, - statusId, - accountId, -}); - -const rejectEventParticipationRequestSuccess = (statusId: string, accountId: string) => ({ - type: EVENT_PARTICIPATION_REQUEST_REJECT_SUCCESS, - statusId, - accountId, -}); - -const rejectEventParticipationRequestFail = (statusId: string, accountId: string, error: unknown) => ({ - type: EVENT_PARTICIPATION_REQUEST_REJECT_FAIL, - statusId, - accountId, - error, -}); - const fetchEventIcs = (statusId: string) => (dispatch: AppDispatch, getState: () => RootState) => getClient(getState).events.getEventIcs(statusId); @@ -425,20 +279,6 @@ type EventsAction = | ReturnType | ReturnType | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType | ReturnType | EventFormSetAction | { type: typeof RECENT_EVENTS_FETCH_REQUEST } @@ -458,18 +298,6 @@ export { EVENT_LEAVE_REQUEST, EVENT_LEAVE_SUCCESS, EVENT_LEAVE_FAIL, - EVENT_PARTICIPATION_REQUESTS_FETCH_REQUEST, - EVENT_PARTICIPATION_REQUESTS_FETCH_SUCCESS, - EVENT_PARTICIPATION_REQUESTS_FETCH_FAIL, - EVENT_PARTICIPATION_REQUESTS_EXPAND_REQUEST, - EVENT_PARTICIPATION_REQUESTS_EXPAND_SUCCESS, - EVENT_PARTICIPATION_REQUESTS_EXPAND_FAIL, - EVENT_PARTICIPATION_REQUEST_AUTHORIZE_REQUEST, - EVENT_PARTICIPATION_REQUEST_AUTHORIZE_SUCCESS, - EVENT_PARTICIPATION_REQUEST_AUTHORIZE_FAIL, - EVENT_PARTICIPATION_REQUEST_REJECT_REQUEST, - EVENT_PARTICIPATION_REQUEST_REJECT_SUCCESS, - EVENT_PARTICIPATION_REQUEST_REJECT_FAIL, EVENT_COMPOSE_CANCEL, EVENT_FORM_SET, RECENT_EVENTS_FETCH_REQUEST, @@ -481,10 +309,6 @@ export { submitEvent, joinEvent, leaveEvent, - fetchEventParticipationRequests, - expandEventParticipationRequests, - authorizeEventParticipationRequest, - rejectEventParticipationRequest, fetchEventIcs, cancelEventCompose, initEventEdit, diff --git a/packages/pl-fe/src/actions/export-data.ts b/packages/pl-fe/src/actions/export-data.ts index 9c28c1911..5f1d2b24e 100644 --- a/packages/pl-fe/src/actions/export-data.ts +++ b/packages/pl-fe/src/actions/export-data.ts @@ -33,7 +33,7 @@ type ExportDataAction = { | typeof EXPORT_BLOCKS_SUCCESS | typeof EXPORT_MUTES_SUCCESS; } | { - type: typeof EXPORT_FOLLOWS_FAIL + type: typeof EXPORT_FOLLOWS_FAIL | typeof EXPORT_BLOCKS_FAIL | typeof EXPORT_MUTES_FAIL; error?: unknown; diff --git a/packages/pl-fe/src/api/hooks/account-lists/use-event-participation-requests.ts b/packages/pl-fe/src/api/hooks/account-lists/use-event-participation-requests.ts new file mode 100644 index 000000000..da221cbcd --- /dev/null +++ b/packages/pl-fe/src/api/hooks/account-lists/use-event-participation-requests.ts @@ -0,0 +1,62 @@ + +import { InfiniteData, useInfiniteQuery, useMutation } from '@tanstack/react-query'; + +import { importEntities } from 'pl-fe/actions/importer'; +import { minifyList } from 'pl-fe/api/normalizers/minify-list'; +import { useClient } from 'pl-fe/hooks/use-client'; +import { queryClient } from 'pl-fe/queries/client'; +import { store } from 'pl-fe/store'; + +import type { PlApiClient } from 'pl-api'; + +const minifyRequestList = (response: Awaited)['events']['getEventParticipationRequests']>>) => + minifyList( + response, + ({ account, participation_message }) => ({ account_id: account.id, participation_message }), + (requests) => store.dispatch(importEntities({ accounts: requests.map(request => request.account) }) as any), + ); + +type MinifiedRequestList = ReturnType + +const removeRequest = (statusId: string, accountId: string) => + queryClient.setQueryData>(['accountsLists', 'eventParticipationRequests', statusId], (data) => data ? { + ...data, + pages: data.pages.map(({ items, ...page }) => ({ ...page, items: items.filter(({ account_id }) => account_id !== accountId) })), + } : undefined); + +const useEventParticipationRequests = (statusId: string) => { + const client = useClient(); + + return useInfiniteQuery({ + queryKey: ['accountsLists', 'eventParticipationRequests', statusId], + queryFn: ({ pageParam }) => pageParam.next?.() || client.events.getEventParticipationRequests(statusId).then(minifyRequestList), + initialPageParam: { previous: null, next: null, items: [], partial: false } as MinifiedRequestList, + getNextPageParam: (page) => page.next ? page : undefined, + select: (data) => data.pages.map(page => page.items).flat(), + }); +}; + +const useAcceptEventParticipationRequestMutation = (statusId: string, accountId: string) => { + const client = useClient(); + + return useMutation({ + mutationKey: ['accountsLists', 'eventParticipationRequests', statusId, accountId], + mutationFn: () => client.events.acceptEventParticipationRequest(statusId, accountId), + onSettled: () => removeRequest(statusId, accountId), + }); +}; + +const useRejectEventParticipationRequestMutation = (statusId: string, accountId: string) => { + const client = useClient(); + + return useMutation({ + mutationKey: ['accountsLists', 'eventParticipationRequests', statusId, accountId], + mutationFn: () => client.events.rejectEventParticipationRequest(statusId, accountId), + onSettled: () => removeRequest(statusId, accountId), + }); +}; +export { + useEventParticipationRequests, + useAcceptEventParticipationRequestMutation, + useRejectEventParticipationRequestMutation, +}; diff --git a/packages/pl-fe/src/api/hooks/account-lists/use-event-participations.ts b/packages/pl-fe/src/api/hooks/account-lists/use-event-participations.ts index 231e8516f..33d63dc1b 100644 --- a/packages/pl-fe/src/api/hooks/account-lists/use-event-participations.ts +++ b/packages/pl-fe/src/api/hooks/account-lists/use-event-participations.ts @@ -11,7 +11,7 @@ const useEventParticipations = (statusId: string) => { return useInfiniteQuery({ queryKey: ['accountsLists', 'eventParticipations', statusId], - queryFn: ({ pageParam }) => pageParam.next?.() || client.events.getEventParticipations(statusId).then(minifyAccountList), + queryFn: ({ pageParam }) => pageParam.next?.() || client.events.getEventParticipations(statusId).then(minifyAccountList), initialPageParam: { previous: null, next: null, items: [], partial: false } as PaginatedResponse, getNextPageParam: (page) => page.next ? page : undefined, select: (data) => data.pages.map(page => page.items).flat(), diff --git a/packages/pl-fe/src/features/compose-event/tabs/manage-pending-participants.tsx b/packages/pl-fe/src/features/compose-event/tabs/manage-pending-participants.tsx index 90ffeac59..d7ecea40a 100644 --- a/packages/pl-fe/src/features/compose-event/tabs/manage-pending-participants.tsx +++ b/packages/pl-fe/src/features/compose-event/tabs/manage-pending-participants.tsx @@ -1,20 +1,13 @@ -import React, { useEffect } from 'react'; +import React from 'react'; import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; -import { - fetchEventParticipationRequests, - rejectEventParticipationRequest, - authorizeEventParticipationRequest, - cancelEventCompose, -} from 'pl-fe/actions/events'; +import { useAcceptEventParticipationRequestMutation, useEventParticipationRequests } from 'pl-fe/api/hooks/account-lists/use-event-participation-requests'; import ScrollableList from 'pl-fe/components/scrollable-list'; import Button from 'pl-fe/components/ui/button'; import HStack from 'pl-fe/components/ui/hstack'; import Spinner from 'pl-fe/components/ui/spinner'; import Stack from 'pl-fe/components/ui/stack'; import AccountContainer from 'pl-fe/containers/account-container'; -import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch'; -import { useAppSelector } from 'pl-fe/hooks/use-app-selector'; const messages = defineMessages({ authorize: { id: 'compose_event.participation_requests.authorize', defaultMessage: 'Authorize' }, @@ -29,15 +22,9 @@ interface IAccount { const Account: React.FC = ({ eventId, id, participationMessage }) => { const intl = useIntl(); - const dispatch = useAppDispatch(); - const handleAuthorize = () => { - dispatch(authorizeEventParticipationRequest(eventId, id)); - }; - - const handleReject = () => { - dispatch(rejectEventParticipationRequest(eventId, id)); - }; + const { mutate: acceptEventParticipationRequest } = useAcceptEventParticipationRequestMutation(eventId, id); + const { mutate: rejectEventParticipationRequest } = useAcceptEventParticipationRequestMutation(eventId, id); return ( = ({ eventId, id, participationMessage }) => { theme='secondary' size='sm' text={intl.formatMessage(messages.authorize)} - onClick={handleAuthorize} + onClick={() => acceptEventParticipationRequest()} />