Skip to content
This repository has been archived by the owner on Jun 9, 2023. It is now read-only.

Commit

Permalink
Added functionality to send Email to selected Group of People (#712)
Browse files Browse the repository at this point in the history
* Added functionality to send Email to selected Group of People
i. Server
	1. resolver.ts
		Modified the sendEventInvite Resolver to take an
		emailGroup as optional argument.
ii. Client
	1. Added New argument in method definitions in graphql.tsx
	2. Created a new Modal component to shoqw the checkboxes for
	   seleting the group
	3. Added a button in Actions components to show the Modal
	   componenet

* Updated the Interested button to Cancelled and Updated the Queries in resolver

1. sendEmailModal.tsx
	1. Created the Interface of FormInputs
	2. Used the interface in useForm
	3. renamed the metho to atleastOneChecked
	4. Removed the Extra error message in atleastonechecked
	5. Removed defaultChecked
2. resolver.ts
	1. Added the strict type Checking in emailGroups Parameter
	2. Removed the console.log

* Updated the error message in the Modal

Co-authored-by: Ravi <Ravichandra.cheekati@oracle.com>
  • Loading branch information
Ravichandra-C and Ravi authored Sep 27, 2021
1 parent 4fc5ad0 commit f72989d
Show file tree
Hide file tree
Showing 4 changed files with 175 additions and 8 deletions.
5 changes: 3 additions & 2 deletions client/src/generated/graphql.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -729,6 +729,7 @@ export type DeleteRsvpMutation = {

export type SendEventInviteMutationVariables = Exact<{
id: Scalars['Int'];
emailGroups?: Maybe<Array<string>>;
}>;

export type SendEventInviteMutation = {
Expand Down Expand Up @@ -1892,8 +1893,8 @@ export type DeleteRsvpMutationOptions = Apollo.BaseMutationOptions<
DeleteRsvpMutationVariables
>;
export const SendEventInviteDocument = gql`
mutation sendEventInvite($id: Int!) {
sendEventInvite(id: $id)
mutation sendEventInvite($id: Int!, $emailGroups: [String!]) {
sendEventInvite(id: $id, emailGroups: $emailGroups)
}
`;
export type SendEventInviteMutationFn = Apollo.MutationFunction<
Expand Down
11 changes: 10 additions & 1 deletion client/src/modules/dashboard/Events/components/Actions.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { useDisclosure } from '@chakra-ui/hooks';
import { Button, HStack } from '@chakra-ui/react';
import { useConfirm, useConfirmDelete } from 'chakra-confirm';
import { LinkButton } from 'chakra-next-link';
import React, { useMemo } from 'react';

import { EVENT, EVENTS } from '../graphql/queries';
import SendEmailModal from './SendEmailModal';
import {
Event,
useCancelEventMutation,
Expand All @@ -17,6 +18,7 @@ interface ActionsProps {
}

const Actions: React.FC<ActionsProps> = ({ event, onDelete, hideCancel }) => {
const { isOpen, onOpen, onClose } = useDisclosure();
const [cancel] = useCancelEventMutation();
const [remove] = useDeleteEventMutation();

Expand Down Expand Up @@ -53,6 +55,9 @@ const Actions: React.FC<ActionsProps> = ({ event, onDelete, hideCancel }) => {
}
};

const clickEmailAttendees = () => {
onOpen();
};
return (
<HStack spacing="1">
<Button size="sm" colorScheme="red" onClick={clickDelete}>
Expand All @@ -70,6 +75,10 @@ const Actions: React.FC<ActionsProps> = ({ event, onDelete, hideCancel }) => {
Cancel
</Button>
)}
<Button size="sm" colorScheme="blue" onClick={clickEmailAttendees}>
Email Attendees
</Button>
<SendEmailModal onClose={onClose} isOpen={isOpen} eventId={event.id} />
</HStack>
);
};
Expand Down
114 changes: 114 additions & 0 deletions client/src/modules/dashboard/Events/components/SendEmailModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { Button } from '@chakra-ui/button';
import { Checkbox } from '@chakra-ui/checkbox';
import { Stack } from '@chakra-ui/layout';
import {
Modal,
ModalBody,
ModalContent,
ModalHeader,
ModalCloseButton,
ModalFooter,
ModalOverlay,
} from '@chakra-ui/modal';
import { Alert, AlertIcon, AlertDescription } from '@chakra-ui/react';
import React from 'react';
import { useForm } from 'react-hook-form';
import { useSendEventInviteMutation } from 'generated/graphql';
interface SendEmailModalProps {
onClose: () => any;
isOpen: boolean;
eventId: number;
}
interface FormInputs {
confirmed: boolean;
on_waitlist: boolean;
canceled: boolean;
}
const SendEmailModal: React.FC<SendEmailModalProps> = ({
onClose,
isOpen,
eventId,
}) => {
const {
register,
getValues,
handleSubmit,
formState: { errors },
} = useForm<FormInputs>({ defaultValues: { confirmed: true } });

const atLeastOneChecked = () => {
return (
getValues('confirmed') ||
getValues('on_waitlist') ||
getValues('canceled')
);
};

const [publish] = useSendEventInviteMutation();
const onSubmit = (data: FormInputs) => {
const emailGroups = [];
if (data.confirmed) {
emailGroups.push('confirmed');
}
if (data.canceled) {
emailGroups.push('canceled');
}
if (data.on_waitlist) {
emailGroups.push('on_waitlist');
}
publish({ variables: { id: eventId, emailGroups: emailGroups } });
onClose();
};
return (
<Modal isOpen={isOpen} onClose={onClose}>
<ModalOverlay />
<ModalContent>
<ModalHeader>Send Email to Attendees</ModalHeader>
<ModalCloseButton />
<ModalBody>
<form id="sendemail" onSubmit={handleSubmit(onSubmit)}>
<label htmlFor="attendees">
Who do you want to send the email to?
</label>
<Stack spacing={10} direction="row">
<Checkbox
{...register('confirmed', { validate: atLeastOneChecked })}
>
Confirmed
</Checkbox>
<Checkbox
{...register('on_waitlist', { validate: atLeastOneChecked })}
>
Waitlist
</Checkbox>
<Checkbox
{...register('canceled', { validate: atLeastOneChecked })}
>
Cancelled
</Checkbox>
</Stack>
</form>
{Object.keys(errors).length == 3 && (
<Alert status="error">
<AlertIcon />
<AlertDescription>
Please select at least one checkbox
</AlertDescription>
</Alert>
)}
</ModalBody>

<ModalFooter>
<Button colorScheme="teal" mr={3} onClick={onClose}>
Close
</Button>
<Button type="submit" variant="solid" form="sendemail">
Send Email
</Button>
</ModalFooter>
</ModalContent>
</Modal>
);
};

export default SendEmailModal;
53 changes: 48 additions & 5 deletions server/src/controllers/Events/resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,17 +273,60 @@ ${venue.postal_code} <br>
}

@Mutation(() => Boolean)
async sendEventInvite(@Arg('id', () => Int) id: number) {
async sendEventInvite(
@Arg('id', () => Int) id: number,
@Arg('emailGroups', () => [String], {
nullable: true,
defaultValue: ['interested'],
})
emailGroups: Array<'confirmed' | 'on_waitlist' | 'canceled' | 'interested'>,
) {
const event = await Event.findOne(id, {
relations: ['venue', 'chapter', 'chapter.users', 'chapter.users.user'],
relations: [
'venue',
'chapter',
'chapter.users',
'chapter.users.user',
'rsvps',
'rsvps.user',
],
});

if (!event) throw new Error("Can't find event");

// TODO: the default should probably be to bcc everyone.
const addresses = event.chapter.users
.filter((role) => role.interested)
.map(({ user }) => user.email);
const addresses: string[] = [];
if (emailGroups.includes('interested')) {
const interestedUsers: string[] = event.chapter.users
.filter((role) => role.interested)
.map(({ user }) => user.email);

addresses.push(...interestedUsers);
}
if (emailGroups.includes('on_waitlist')) {
const waitlistUsers: string[] = event.rsvps
.filter((rsvp) => rsvp.on_waitlist && rsvp.interested)
.map(({ user }) => user.email);
addresses.push(...waitlistUsers);
}
if (emailGroups.includes('confirmed')) {
const confirmedUsers: string[] = event.rsvps
.filter(
(rsvp) => !rsvp.on_waitlist && !rsvp.canceled && rsvp.interested,
)
.map(({ user }) => user.email);
addresses.push(...confirmedUsers);
}
if (emailGroups.includes('canceled')) {
const confirmedUsers: string[] = event.rsvps
.filter((rsvp) => rsvp.canceled && rsvp.interested)
.map(({ user }) => user.email);
addresses.push(...confirmedUsers);
}

if (!addresses.length) {
return true;
}
const subject = `Invitation to ${event.name}.`;

const chapterURL = `${process.env.CLIENT_LOCATION}/chapters/${event.chapter.id}`;
Expand Down

0 comments on commit f72989d

Please sign in to comment.