diff --git a/app/assets/images/group.svg b/app/assets/images/group.svg new file mode 100644 index 0000000000..4e187999db --- /dev/null +++ b/app/assets/images/group.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/soapbox/actions/groups.ts b/app/soapbox/actions/groups.ts index 974bd5ebb2..b97d52f206 100644 --- a/app/soapbox/actions/groups.ts +++ b/app/soapbox/actions/groups.ts @@ -140,7 +140,8 @@ const createGroup = (params: Record, shouldReset?: boolean) => if (shouldReset) { dispatch(resetGroupEditor()); } - dispatch(closeModal('MANAGE_GROUP')); + + return data; }).catch(err => dispatch(createGroupFail(err))); }; @@ -797,9 +798,9 @@ const submitGroupEditor = (shouldReset?: boolean) => (dispatch: AppDispatch, get if (header) params.header = header; if (groupId === null) { - dispatch(createGroup(params, shouldReset)); + return dispatch(createGroup(params, shouldReset)); } else { - dispatch(updateGroup(groupId, params, shouldReset)); + return dispatch(updateGroup(groupId, params, shouldReset)); } }; diff --git a/app/soapbox/components/list.tsx b/app/soapbox/components/list.tsx index 3dd77c34ca..b48b24a87b 100644 --- a/app/soapbox/components/list.tsx +++ b/app/soapbox/components/list.tsx @@ -84,7 +84,10 @@ const ListItem: React.FC = ({ label, hint, children, onClick, onSelec {children} {isSelected ? ( - + ) : null} ) : null} diff --git a/app/soapbox/components/ui/stack/stack.tsx b/app/soapbox/components/ui/stack/stack.tsx index 4795f11d3f..dceaf92143 100644 --- a/app/soapbox/components/ui/stack/stack.tsx +++ b/app/soapbox/components/ui/stack/stack.tsx @@ -11,6 +11,7 @@ const spaces = { 4: 'space-y-4', 5: 'space-y-5', 6: 'space-y-6', + 9: 'space-y-9', 10: 'space-y-10', }; diff --git a/app/soapbox/features/ui/components/modals/manage-group-modal/manage-group-modal.tsx b/app/soapbox/features/ui/components/modals/manage-group-modal/manage-group-modal.tsx index 77cdf5c298..2863060c55 100644 --- a/app/soapbox/features/ui/components/modals/manage-group-modal/manage-group-modal.tsx +++ b/app/soapbox/features/ui/components/modals/manage-group-modal/manage-group-modal.tsx @@ -5,6 +5,7 @@ import { submitGroupEditor } from 'soapbox/actions/groups'; import { Modal, Stack } from 'soapbox/components/ui'; import { useAppDispatch, useAppSelector } from 'soapbox/hooks'; +import ConfirmationStep from './steps/confirmation-step'; import DetailsStep from './steps/details-step'; import PrivacyStep from './steps/privacy-step'; @@ -12,16 +13,19 @@ const messages = defineMessages({ next: { id: 'manage_group.next', defaultMessage: 'Next' }, create: { id: 'manage_group.create', defaultMessage: 'Create' }, update: { id: 'manage_group.update', defaultMessage: 'Update' }, + done: { id: 'manage_group.done', defaultMessage: 'Done' }, }); enum Steps { ONE = 'ONE', TWO = 'TWO', + THREE = 'THREE', } const manageGroupSteps = { ONE: PrivacyStep, TWO: DetailsStep, + THREE: ConfirmationStep, }; interface IManageGroupModal { @@ -33,21 +37,24 @@ const ManageGroupModal: React.FC = ({ onClose }) => { const dispatch = useAppDispatch(); const id = useAppSelector((state) => state.group_editor.groupId); + const [group, setGroup] = useState(null); const isSubmitting = useAppSelector((state) => state.group_editor.isSubmitting); const [currentStep, setCurrentStep] = useState(id ? Steps.TWO : Steps.ONE); - const onClickClose = () => { + const handleClose = () => { onClose('MANAGE_GROUP'); }; const handleSubmit = () => { - dispatch(submitGroupEditor(true)); + return dispatch(submitGroupEditor(true)); }; const confirmationText = useMemo(() => { switch (currentStep) { + case Steps.THREE: + return intl.formatMessage(messages.done); case Steps.TWO: return intl.formatMessage(id ? messages.update : messages.create); default: @@ -61,8 +68,15 @@ const ManageGroupModal: React.FC = ({ onClose }) => { setCurrentStep(Steps.TWO); break; case Steps.TWO: - handleSubmit(); - onClose(); + handleSubmit() + .then((group) => { + setCurrentStep(Steps.THREE); + setGroup(group); + }) + .catch(() => {}); + break; + case Steps.THREE: + handleClose(); break; default: break; @@ -80,10 +94,11 @@ const ManageGroupModal: React.FC = ({ onClose }) => { confirmationText={confirmationText} confirmationDisabled={isSubmitting} confirmationFullWidth - onClose={onClickClose} + onClose={handleClose} > - + {/* @ts-ignore */} + ); diff --git a/app/soapbox/features/ui/components/modals/manage-group-modal/steps/confirmation-step.tsx b/app/soapbox/features/ui/components/modals/manage-group-modal/steps/confirmation-step.tsx new file mode 100644 index 0000000000..1b71e36c91 --- /dev/null +++ b/app/soapbox/features/ui/components/modals/manage-group-modal/steps/confirmation-step.tsx @@ -0,0 +1,119 @@ +import React from 'react'; +import { FormattedMessage } from 'react-intl'; + +import { Avatar, Divider, HStack, Stack, Text, Button } from 'soapbox/components/ui'; + +interface IConfirmationStep { + group: any +} + +const ConfirmationStep: React.FC = ({ group }) => { + const handleCopyLink = () => { + if (navigator.clipboard) { + navigator.clipboard.writeText(group.uri); + } + }; + + const handleShare = () => { + navigator.share({ + text: group.display_name, + url: group.uri, + }).catch((e) => { + if (e.name !== 'AbortError') console.error(e); + }); + }; + + return ( + + + + + + + + + + {group.display_name} + {group.note} + + + + + + + + + + + + + + + + + + + + + + + + + + + {('share' in navigator) && ( + + )} + + + + + ); +}; + +interface IInfoListNumber { + number: number +} + +const InfoListNumber: React.FC = ({ number }) => { + return ( +
+ {number} +
+ ); +}; + +interface IInfoListItem { + number: number + children: React.ReactNode +} + +const InfoListItem: React.FC = ({ number, children }) => { + return ( + +
+
{children}
+
+ ); +}; + +export default ConfirmationStep; diff --git a/app/soapbox/features/ui/components/modals/manage-group-modal/steps/details-step.tsx b/app/soapbox/features/ui/components/modals/manage-group-modal/steps/details-step.tsx index c40bcf3e1f..2450dffead 100644 --- a/app/soapbox/features/ui/components/modals/manage-group-modal/steps/details-step.tsx +++ b/app/soapbox/features/ui/components/modals/manage-group-modal/steps/details-step.tsx @@ -9,7 +9,7 @@ import { } from 'soapbox/actions/groups'; import Icon from 'soapbox/components/icon'; import { Avatar, Form, FormGroup, HStack, Input, Text, Textarea } from 'soapbox/components/ui'; -import { useAppDispatch, useAppSelector } from 'soapbox/hooks'; +import { useAppDispatch, useAppSelector, useInstance } from 'soapbox/hooks'; import { isDefaultAvatar, isDefaultHeader } from 'soapbox/utils/accounts'; import resizeImage from 'soapbox/utils/resize-image'; @@ -37,17 +37,17 @@ const HeaderPicker: React.FC = ({ src, onChange, accept, disabled } className={clsx('absolute top-0 h-full w-full transition-opacity', { 'opacity-0 hover:opacity-90 bg-primary-100 dark:bg-gray-800': src, })} - space={3} + space={1.5} alignItems='center' justifyContent='center' > - - + + = ({ src, onChange, accept, disabled } const AvatarPicker: React.FC = ({ src, onChange, accept, disabled }) => { return ( -