diff --git a/src/features/surveys/components/SurveyLinkDialog.tsx b/src/features/surveys/components/SurveyLinkDialog.tsx
new file mode 100644
index 000000000..d9b7f76f1
--- /dev/null
+++ b/src/features/surveys/components/SurveyLinkDialog.tsx
@@ -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 (
+
+ );
+};
+
+export default SurveyLinkDialog;
diff --git a/src/features/surveys/components/SurveySubmissionsList.tsx b/src/features/surveys/components/SurveySubmissionsList.tsx
index 14a96d63a..f4d0c0780 100644
--- a/src/features/surveys/components/SurveySubmissionsList.tsx
+++ b/src/features/surveys/components/SurveySubmissionsList.tsx
@@ -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';
@@ -31,6 +32,9 @@ const SurveySubmissionsList = ({
const { orgId } = useRouter().query;
const { openPane } = usePanes();
+ const [dialogPerson, setDialogPerson] = useState(null);
+ const [dialogEmail, setDialogEmail] = useState('');
+
const sortedSubmissions = useMemo(() => {
const sorted = [...submissions].sort((subOne, subTwo) => {
const dateOne = new Date(subOne.submitted);
@@ -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) {
+ setDialogEmail(respondentEmail);
+ setDialogPerson(person);
+ }
+ }
};
return (
@@ -247,6 +260,14 @@ const SurveySubmissionsList = ({
border: 'none',
}}
/>
+ {dialogPerson && (
+ setDialogPerson(null)}
+ open={!!dialogPerson}
+ person={dialogPerson}
+ />
+ )}
);
};
diff --git a/src/features/surveys/l10n/messageIds.ts b/src/features/surveys/l10n/messageIds.ts
index f83e84f67..5dd6c4f0e 100644
--- a/src/features/surveys/l10n/messageIds.ts
+++ b/src/features/surveys/l10n/messageIds.ts
@@ -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(
diff --git a/src/features/surveys/store.ts b/src/features/surveys/store.ts
index db0513878..73035d4fc 100644
--- a/src/features/surveys/store.ts
+++ b/src/features/surveys/store.ts
@@ -1,5 +1,6 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
+import { personUpdated } from 'features/profile/store';
import { SurveyStats } from './rpc/getSurveyStats';
import {
ELEMENT_TYPE,
@@ -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);
+ }),
+
initialState,
name: 'surveys',
reducers: {