From bfb8ee258d8607f73508d98e2d8f777bd44e520b Mon Sep 17 00:00:00 2001 From: Anusha Bhat Date: Tue, 29 Sep 2020 14:04:43 +0530 Subject: [PATCH 1/2] Add Cancel RSVP functionality --- src/actions/attendeesAction.js | 26 ++++++- src/components/EventDetails/ConfirmPopup.js | 29 ++++++++ .../EventDetails/EventDetailsContainer.js | 13 +++- .../EventDetails/IndividualParticipation.js | 68 ++++++++++++------- src/sagas/attendeesSaga.js | 32 +++++++-- 5 files changed, 136 insertions(+), 32 deletions(-) create mode 100644 src/components/EventDetails/ConfirmPopup.js diff --git a/src/actions/attendeesAction.js b/src/actions/attendeesAction.js index 2d6a06d..81a7ccc 100644 --- a/src/actions/attendeesAction.js +++ b/src/actions/attendeesAction.js @@ -15,12 +15,15 @@ import { REGISTER_PARTICIPANT_INITIATED, REGISTER_PARTICIPANT_SUCCESS, REGISTER_PARTICIPANT_FAIL, + CANCEL_PARTICIPATION_INITIATED, + CANCEL_PARTICIPATION_SUCCESS, + CANCEL_PARTICIPATION_FAIL, ADD_TEAM_MEMBER_SUCCESS, ADD_TEAM_MEMBER_FAIL, INVITATION_ACCEPT_REJECT_INITIATED, INVITATION_ACCEPT_REJECT_SUCCESS, INVITATION_ACCEPT_REJECT_FAIL -} from '../utils/constants'; +} from "../utils/constants"; export function fetchAttendeesInitiated(eventID) { return { @@ -168,3 +171,24 @@ export function invitationAcceptRejectFail(payload) { payload }; } + +export function cancelParticipationInitiated(payload) { + return { + type: CANCEL_PARTICIPATION_INITIATED, + payload + }; +} + +export function cancelParticipationSuccess(payload) { + return { + type: CANCEL_PARTICIPATION_SUCCESS, + payload + }; +} + +export function cancelParticipationFail(payload) { + return { + type: CANCEL_PARTICIPATION_FAIL, + payload + }; +} diff --git a/src/components/EventDetails/ConfirmPopup.js b/src/components/EventDetails/ConfirmPopup.js new file mode 100644 index 0000000..2c405d3 --- /dev/null +++ b/src/components/EventDetails/ConfirmPopup.js @@ -0,0 +1,29 @@ +import React from "react"; +import { Button, Popconfirm } from "antd"; + +const ConfirmPopup = ({ handleConfirm, btnText, disabled, loading, icon }) => { + return ( +
+ + + +
+ ); +}; + +export default ConfirmPopup; diff --git a/src/components/EventDetails/EventDetailsContainer.js b/src/components/EventDetails/EventDetailsContainer.js index 411d06f..1cc0afb 100644 --- a/src/components/EventDetails/EventDetailsContainer.js +++ b/src/components/EventDetails/EventDetailsContainer.js @@ -251,6 +251,14 @@ class EventDetailsContainer extends Component { this.props.registerIndividualParticipation(payLoad); }; + handleRSVPCancel = () => { + const payload = { + eventId: this.props.event.id + }; + + this.props.cancelIndividualParticipation(payload); + }; + handleAcceptReject = (value, teamId, memberId) => { const payload = { eventId: this.props.event.id, @@ -314,6 +322,7 @@ class EventDetailsContainer extends Component { dispatch(registerParticipantInitiated(payload)), invitationAcceptRejectInitiated: payload => - dispatch(invitationAcceptRejectInitiated(payload)) + dispatch(invitationAcceptRejectInitiated(payload)), + cancelIndividualParticipation: payload => + dispatch(cancelParticipationInitiated(payload)) }; } diff --git a/src/components/EventDetails/IndividualParticipation.js b/src/components/EventDetails/IndividualParticipation.js index cefcdf4..91dc07b 100644 --- a/src/components/EventDetails/IndividualParticipation.js +++ b/src/components/EventDetails/IndividualParticipation.js @@ -1,29 +1,49 @@ -import React from 'react'; -import { Button, Popconfirm } from 'antd'; -const individualParticipation = ({rsvp, handleRSVPClick, attending, isPastEvent, loading }) => { - if (attending || rsvp) { - return
{isPastEvent? 'You have attended this event': 'You are going.'}
- } - - return ( +import React from "react"; +import { Button, Popconfirm } from "antd"; +import ConfirmPopup from "./ConfirmPopup"; +const individualParticipation = ({ + rsvp, + handleRSVPClick, + attending, + isPastEvent, + loading, + handleRSVPCancel +}) => { + if (attending || rsvp) { + if (isPastEvent) + return ( +
+ You have attended this event{" "} +
+ ); + else + return (
-
-
- {}: handleRSVPClick}> - - -
-
+
You are going!
+
- ); + ); + } + + return ( +
+
+ +
+
+ ); }; export default individualParticipation; diff --git a/src/sagas/attendeesSaga.js b/src/sagas/attendeesSaga.js index 3776720..43baa10 100644 --- a/src/sagas/attendeesSaga.js +++ b/src/sagas/attendeesSaga.js @@ -1,4 +1,4 @@ -import { call, put, takeEvery } from 'redux-saga/effects'; +import { call, put, takeEvery, takeLatest } from "redux-saga/effects"; import { fetchAttendeesSuccess, fetchAttendeesFailed, @@ -13,8 +13,10 @@ import { registerParticipantSuccess, registerParticipantFail, invitationAcceptRejectSuccess, - invitationAcceptRejectFail -} from 'ACTION/attendeesAction'; + invitationAcceptRejectFail, + cancelParticipationSuccess, + cancelParticipationFail +} from "ACTION/attendeesAction"; import { FETCH_ATTENDEES_INITIATED, ADD_TEAM_MEMBER_INITIATED, @@ -22,10 +24,14 @@ import { UPDATE_TEAM_INITIATED, DELETE_TEAM_INITIATED, REGISTER_PARTICIPANT_INITIATED, + CANCEL_PARTICIPATION_INITIATED, INVITATION_ACCEPT_REJECT_INITIATED -} from 'UTILS/constants'; -import RequestHandler from '../HTTP'; -import { showFailureNotification, showSuccessNotification } from '../components/shared/Notification'; +} from "UTILS/constants"; +import RequestHandler from "../HTTP"; +import { + showFailureNotification, + showSuccessNotification +} from "../components/shared/Notification"; function* fetchAttendees(action) { try { @@ -144,6 +150,19 @@ function* inviteAcceptReject(action) { } } +function* cancelParticipation(action) { + try { + const response = yield call(() => + RequestHandler.delete(`events/${action.payload.eventId}/rsvp`) + ); + showSuccessNotification("Cancelled RSVP!"); + + yield put(cancelParticipationSuccess(response)); + } catch (error) { + yield put(cancelParticipationFail(error)); + } +} + export default function* attendeesSaga() { yield takeEvery(FETCH_ATTENDEES_INITIATED, fetchAttendees); yield takeEvery(ADD_TEAM_MEMBER_INITIATED, addTeamMember); @@ -152,4 +171,5 @@ export default function* attendeesSaga() { yield takeEvery(DELETE_TEAM_INITIATED, deleteTeam); yield takeEvery(REGISTER_PARTICIPANT_INITIATED, registerParticipant); yield takeEvery(INVITATION_ACCEPT_REJECT_INITIATED, inviteAcceptReject); + yield takeLatest(CANCEL_PARTICIPATION_INITIATED, cancelParticipation); } From a4fa9802e112f00e9a33d4429a9191a66bcbd7d2 Mon Sep 17 00:00:00 2001 From: Anusha Bhat Date: Thu, 1 Oct 2020 11:35:33 +0530 Subject: [PATCH 2/2] Updated css and add missing constant and reudcer file --- src/components/EventDetails/ConfirmPopup.js | 19 ++++++---- src/components/EventDetails/EventDetails.scss | 12 ++++++- .../EventDetails/IndividualParticipation.js | 6 ++-- src/reducers/attendeesReducer.js | 35 +++++++++++++++++-- src/utils/constants.js | 4 +++ 5 files changed, 64 insertions(+), 12 deletions(-) diff --git a/src/components/EventDetails/ConfirmPopup.js b/src/components/EventDetails/ConfirmPopup.js index 2c405d3..33c5814 100644 --- a/src/components/EventDetails/ConfirmPopup.js +++ b/src/components/EventDetails/ConfirmPopup.js @@ -1,9 +1,18 @@ import React from "react"; import { Button, Popconfirm } from "antd"; -const ConfirmPopup = ({ handleConfirm, btnText, disabled, loading, icon }) => { +const ConfirmPopup = ({ + handleConfirm, + btnText, + disabled, + loading, + icon, + btnClass, + type, + parentClass +}) => { return ( -
+
{ onConfirm={handleConfirm} >
); @@ -40,6 +39,9 @@ const individualParticipation = ({ loading={loading} btnText="RSVP" icon="check" + btnClass="button yesButton ant-btn-round" + type="ghost" + parentClass="yes-no-buttons-wrapper " />
diff --git a/src/reducers/attendeesReducer.js b/src/reducers/attendeesReducer.js index 98de3e3..dd7c386 100644 --- a/src/reducers/attendeesReducer.js +++ b/src/reducers/attendeesReducer.js @@ -20,9 +20,12 @@ import { REGISTER_PARTICIPANT_FAIL, INVITATION_ACCEPT_REJECT_INITIATED, INVITATION_ACCEPT_REJECT_SUCCESS, - INVITATION_ACCEPT_REJECT_FAIL -} from 'UTILS/constants'; -import { getTeamMembers } from '../utils/util'; + INVITATION_ACCEPT_REJECT_FAIL, + CANCEL_PARTICIPATION_FAIL, + CANCEL_PARTICIPATION_INITIATED, + CANCEL_PARTICIPATION_SUCCESS +} from "UTILS/constants"; +import { getTeamMembers } from "../utils/util"; const initialState = { isLoading: false, @@ -43,6 +46,12 @@ function addNewAttendees({members}) { return members || []; } +function removeAttendee({ members }) { + const email = localStorage.getItem("email") || ""; + + return members.filter(m => m.invitee && m.invitee.email !== email); +} + export default function eventReducer(state = initialState, action) { switch (action.type) { case FETCH_ATTENDEES_INITIATED: @@ -220,6 +229,26 @@ export default function eventReducer(state = initialState, action) { error: action.payload }; + case CANCEL_PARTICIPATION_INITIATED: + return { + ...state, + rsvpLoading: true + }; + case CANCEL_PARTICIPATION_SUCCESS: + const newMembers = removeAttendee(state); + return { + ...state, + members: newMembers, + rsvpLoading: false, + rsvp: false + }; + case CANCEL_PARTICIPATION_FAIL: + return { + ...state, + rsvpLoading: false, + rsvpError: action.payload + }; + default: return state; } diff --git a/src/utils/constants.js b/src/utils/constants.js index 9873fb8..d924efd 100644 --- a/src/utils/constants.js +++ b/src/utils/constants.js @@ -55,6 +55,10 @@ export const MEMBER_INVITE_STATUS = { PENDING: 'invited' }; +export const CANCEL_PARTICIPATION_INITIATED = "CANCEL_PARTICIPATION_INITIATED"; +export const CANCEL_PARTICIPATION_SUCCESS = "CANCEL_PARTICIPATION_SUCCESS"; +export const CANCEL_PARTICIPATION_FAIL = "CANCEL_PARTICIPATION_FAIL"; + export const HTTP_STANDARD_ERRORS = { 400: 'Bad request', 401: 'Unauthorized',