diff --git a/app/soapbox/entity-store/hooks/useEntityActions.ts b/app/soapbox/entity-store/hooks/useEntityActions.ts index 9406b3809..9312aef67 100644 --- a/app/soapbox/entity-store/hooks/useEntityActions.ts +++ b/app/soapbox/entity-store/hooks/useEntityActions.ts @@ -1,3 +1,5 @@ +import { useState } from 'react'; + import { useApi } from 'soapbox/hooks'; import { useCreateEntity } from './useCreateEntity'; @@ -24,19 +26,24 @@ function useEntityActions( const api = useApi(); const { entityType, path } = parseEntitiesPath(expandedPath); + const [isLoading, setIsLoading] = useState(false); + const deleteEntity = useDeleteEntity(entityType, (entityId) => { if (!endpoints.delete) return Promise.reject(endpoints); - return api.delete(endpoints.delete.replace(':id', entityId)); + return api.delete(endpoints.delete.replace(':id', entityId)) + .finally(() => setIsLoading(false)); }); const createEntity = useCreateEntity(path, (params: Params) => { if (!endpoints.post) return Promise.reject(endpoints); - return api.post(endpoints.post, params); + return api.post(endpoints.post, params) + .finally(() => setIsLoading(false)); }, opts); return { createEntity, deleteEntity, + isLoading, }; } diff --git a/app/soapbox/features/group/components/group-action-button.tsx b/app/soapbox/features/group/components/group-action-button.tsx index 64824866a..8c8a36db7 100644 --- a/app/soapbox/features/group/components/group-action-button.tsx +++ b/app/soapbox/features/group/components/group-action-button.tsx @@ -3,49 +3,84 @@ import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import { openModal } from 'soapbox/actions/modals'; import { Button } from 'soapbox/components/ui'; +import { deleteEntities } from 'soapbox/entity-store/actions'; +import { Entities } from 'soapbox/entity-store/entities'; import { useAppDispatch } from 'soapbox/hooks'; -import { useCancelMembershipRequest, useJoinGroup, useLeaveGroup } from 'soapbox/queries/groups'; -import { Group } from 'soapbox/types/entities'; +import { useCancelMembershipRequest, useJoinGroup, useLeaveGroup } from 'soapbox/hooks/api'; +import { GroupRoles } from 'soapbox/schemas/group-member'; +import toast from 'soapbox/toast'; + +import type { Group } from 'soapbox/types/entities'; interface IGroupActionButton { group: Group } const messages = defineMessages({ + confirmationConfirm: { id: 'confirmations.leave_group.confirm', defaultMessage: 'Leave' }, confirmationHeading: { id: 'confirmations.leave_group.heading', defaultMessage: 'Leave group' }, confirmationMessage: { id: 'confirmations.leave_group.message', defaultMessage: 'You are about to leave the group. Do you want to continue?' }, - confirmationConfirm: { id: 'confirmations.leave_group.confirm', defaultMessage: 'Leave' }, + joinRequestSuccess: { id: 'group.join.request_success', defaultMessage: 'Requested to join the group' }, + joinSuccess: { id: 'group.join.success', defaultMessage: 'Group joined successfully!' }, + leaveSuccess: { id: 'group.leave.success', defaultMessage: 'Left the group' }, }); const GroupActionButton = ({ group }: IGroupActionButton) => { const dispatch = useAppDispatch(); const intl = useIntl(); - const joinGroup = useJoinGroup(); - const leaveGroup = useLeaveGroup(); - const cancelRequest = useCancelMembershipRequest(); + const joinGroup = useJoinGroup(group); + const leaveGroup = useLeaveGroup(group); + const cancelRequest = useCancelMembershipRequest(group); const isRequested = group.relationship?.requested; const isNonMember = !group.relationship?.member && !isRequested; - const isAdmin = group.relationship?.role === 'owner'; + const isOwner = group.relationship?.role === GroupRoles.OWNER; const isBlocked = group.relationship?.blocked_by; - const onJoinGroup = () => joinGroup.mutate(group); + const onJoinGroup = () => joinGroup.mutate({}, { + onSuccess() { + toast.success( + group.locked + ? intl.formatMessage(messages.joinRequestSuccess) + : intl.formatMessage(messages.joinSuccess), + ); + }, + }); const onLeaveGroup = () => dispatch(openModal('CONFIRM', { heading: intl.formatMessage(messages.confirmationHeading), message: intl.formatMessage(messages.confirmationMessage), confirm: intl.formatMessage(messages.confirmationConfirm), - onConfirm: () => leaveGroup.mutate(group), + onConfirm: () => leaveGroup.mutate({}, { + onSuccess() { + toast.success(intl.formatMessage(messages.leaveSuccess)); + }, + }), })); - const onCancelRequest = () => cancelRequest.mutate(group); + const onCancelRequest = () => cancelRequest.mutate({}, { + onSuccess() { + dispatch(deleteEntities([group.id], Entities.GROUP_RELATIONSHIPS)); + }, + }); if (isBlocked) { return null; } + if (isOwner) { + return ( + + ); + } + if (isNonMember) { return ( - ); - } - return (