Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update email when linking respondent #2426

Merged
merged 7 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions src/features/surveys/components/SurveyLinkDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { ArrowForward } from '@mui/icons-material';
import {
Box,
Button,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
Divider,
Typography,
} from '@mui/material';

import messageIds from '../l10n/messageIds';
import { useNumericRouteParams } from 'core/hooks';
import { useMessages } from 'core/i18n';
import usePersonMutations from 'features/profile/hooks/usePersonMutations';
import { ZetkinPerson } from 'utils/types/zetkin';
import ZUIPersonAvatar from 'zui/ZUIPersonAvatar';

const SurveyLinkDialog = ({
email,
onClose,
open,
person,
}: {
email: string;
onClose: () => void;
open: boolean;
person: ZetkinPerson;
}) => {
const messages = useMessages(messageIds);
const { orgId } = useNumericRouteParams();
const { updatePerson } = usePersonMutations(orgId, person.id);

return (
<Dialog open={open}>
<DialogTitle>{messages.surveyDialog.title()}</DialogTitle>
<Divider />
<DialogContent>
<Box alignItems="center" display="flex" mb={2}>
{email}
<Box alignItems="center" display="flex" ml={2} mr={2}>
<ArrowForward
color="secondary"
sx={{
opacity: '50%',
}}
/>
</Box>
<ZUIPersonAvatar orgId={orgId} personId={person?.id ?? 0} size="sm" />
<Typography ml={2} variant="h6">
{person?.first_name} {person?.last_name}
</Typography>
</Box>
{messages.surveyDialog.description()}
</DialogContent>
<DialogActions>
<Button onClick={onClose} variant="outlined">
{messages.surveyDialog.cancel()}
</Button>
<Button
onClick={() => {
updatePerson({ email });
onClose();
}}
variant="contained"
>
{messages.surveyDialog.add()}
</Button>
</DialogActions>
</Dialog>
);
};

export default SurveyLinkDialog;
23 changes: 22 additions & 1 deletion src/features/surveys/components/SurveySubmissionsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import {
GridRenderCellParams,
useGridApiContext,
} from '@mui/x-data-grid-pro';
import { FC, useEffect, useMemo } from 'react';
import { FC, useEffect, useMemo, useState } from 'react';

import messageIds from '../l10n/messageIds';
import SurveyLinkDialog from './SurveyLinkDialog';
import SurveySubmissionPane from '../panes/SurveySubmissionPane';
import { useNumericRouteParams } from 'core/hooks';
import { usePanes } from 'utils/panes';
Expand All @@ -31,6 +32,9 @@ const SurveySubmissionsList = ({
const { orgId } = useRouter().query;
const { openPane } = usePanes();

const [dialogPerson, setDialogPerson] = useState<ZetkinPerson | null>(null);
const [dialogEmail, setDialogEmail] = useState('');

const sortedSubmissions = useMemo(() => {
const sorted = [...submissions].sort((subOne, subTwo) => {
const dateOne = new Date(subOne.submitted);
Expand Down Expand Up @@ -198,6 +202,15 @@ const SurveySubmissionsList = ({
id: row.id,
});
setRespondentId(person?.id || null);

const respondentEmail = row.respondent?.email;
if (person) {
const personHasNoEmail = person.email == null || person.email == '';
if (personHasNoEmail && respondentEmail != undefined) {
Comment on lines +207 to +209
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is much nicer! I believe it could have been made even simpler, by relying on the fact that null and undefined are falsy, like so:

Suggested change
if (person) {
const personHasNoEmail = person.email == null || person.email == '';
if (personHasNoEmail && respondentEmail != undefined) {
if (person) {
const personHasNoEmail = !person.email || person.email == '';
if (personHasNoEmail && respondentEmail) {

But that's not worth changing the code over!

setDialogEmail(respondentEmail);
setDialogPerson(person);
}
}
};

return (
Expand Down Expand Up @@ -247,6 +260,14 @@ const SurveySubmissionsList = ({
border: 'none',
}}
/>
{dialogPerson && (
<SurveyLinkDialog
email={dialogEmail}
onClose={() => setDialogPerson(null)}
open={!!dialogPerson}
person={dialogPerson}
/>
)}
</Box>
);
};
Expand Down
8 changes: 8 additions & 0 deletions src/features/surveys/l10n/messageIds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,14 @@ export default makeMessages('feat.surveys', {
suggestedPeople: m('Suggested people'),
unlink: m('Unlink'),
},
surveyDialog: {
add: m('Add'),
cancel: m("Don't add"),
description: m(
'The person you are about to link does not have an email address while the survey response does. Would you like to add it the person?'
),
title: m('Add email address'),
},
surveyForm: {
accept: m('I accept the terms stated below'),
error: m(
Expand Down
28 changes: 28 additions & 0 deletions src/features/surveys/store.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit';

import { personUpdated } from 'features/profile/store';
import { SurveyStats } from './rpc/getSurveyStats';
import {
ELEMENT_TYPE,
Expand Down Expand Up @@ -39,6 +40,33 @@ const initialState: SurveysStoreSlice = {
};

const surveysSlice = createSlice({
extraReducers: (builder) =>
builder.addCase(personUpdated, (state, action) => {
const person = action.payload;
const item = state.submissionList.items.find(
(item) => item?.data?.respondent?.id === person.id
);

if (item?.data?.respondent) {
const respondent = item.data.respondent;

if (person.email) {
respondent.email = person.email;
}
if (person.first_name) {
respondent.first_name = person.first_name;
}
if (person.last_name) {
respondent.last_name = person.last_name;
}
}
const submissionsUpdated = state.submissionList.items
.map((item) => item.data)
.filter((data): data is ZetkinSurveySubmission => data !== null);

addSubmissionToState(state, submissionsUpdated);
}),

rebecarubio marked this conversation as resolved.
Show resolved Hide resolved
initialState,
name: 'surveys',
reducers: {
Expand Down
Loading