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

chore: Transactional emails to React email #2349

Merged
merged 37 commits into from
Apr 25, 2024
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
97831a2
moved emails to react emails
Dhruwang Mar 27, 2024
a2add42
merged main
Dhruwang Mar 27, 2024
700bf36
tweaks
Dhruwang Mar 27, 2024
2d799dc
fix: weekly
Dhruwang Mar 27, 2024
d55d10a
code improvements
Dhruwang Mar 28, 2024
f968d57
Merge branch 'main' of https://github.com/Dhruwang/formbricks into re…
Dhruwang Mar 28, 2024
9ce581a
file upload response email fixes
Dhruwang Mar 28, 2024
8b1316e
fix: warnings
Dhruwang Mar 28, 2024
0584933
revreted onboarding change
Dhruwang Mar 28, 2024
397a022
fix: build errors
Dhruwang Mar 28, 2024
bd8b1e5
merged main
Dhruwang Apr 9, 2024
19be962
Merge branch 'main' of https://github.com/formbricks/formbricks into …
gupta-piyush19 Apr 10, 2024
ed710f7
fix link and forget -> forgot
gupta-piyush19 Apr 10, 2024
2301115
Merge branch 'main' of https://github.com/formbricks/formbricks into …
gupta-piyush19 Apr 10, 2024
9001e94
Merge branch 'main' of https://github.com/Dhruwang/formbricks into re…
Dhruwang Apr 11, 2024
6e8062b
fix: question responsing display and tweaks
Dhruwang Apr 11, 2024
ab053ca
Merge branch 'main' into react-email
Dhruwang Apr 11, 2024
898f794
fix: variable naming
Dhruwang Apr 11, 2024
81fd0d0
Merge branch 'react-email' of https://github.com/formbricks/formbrick…
Dhruwang Apr 11, 2024
d13b955
added email package
Dhruwang Apr 11, 2024
347a136
Merge branch 'main' of https://github.com/Dhruwang/formbricks into re…
Dhruwang Apr 12, 2024
17969ef
cleanups and structural changes
Dhruwang Apr 12, 2024
23e7c95
fix: build
Dhruwang Apr 12, 2024
9132166
Merge branch 'main' into react-email
Dhruwang Apr 17, 2024
b856ad0
Merge branch 'main' of https://github.com/Dhruwang/formbricks into re…
Dhruwang Apr 23, 2024
bad78c0
Merge branch 'react-email' of https://github.com/formbricks/formbrick…
Dhruwang Apr 23, 2024
a05fbe3
Merge branch 'main' of https://github.com/Dhruwang/formbricks into re…
Dhruwang Apr 23, 2024
27b8d04
embed email fixes
Dhruwang Apr 23, 2024
a3018b1
solve conflict
mattinannt Apr 24, 2024
3961a92
rename types for code consistency
mattinannt Apr 24, 2024
22e9b16
Merge branch 'main' of https://github.com/formbricks/formbricks into …
Dhruwang Apr 25, 2024
6c12ecc
updated pnpm-lock
Dhruwang Apr 25, 2024
6df81b5
Merge branch 'react-email' of https://github.com/formbricks/formbrick…
Dhruwang Apr 25, 2024
60b0e89
fix: pnpm-lock
Dhruwang Apr 25, 2024
39d8036
Merge branch 'main' into react-email
mattinannt Apr 25, 2024
951c2e1
Merge branch 'main' of https://github.com/Dhruwang/formbricks into re…
Dhruwang Apr 25, 2024
a051cbf
Merge branch 'react-email' of https://github.com/formbricks/formbrick…
Dhruwang Apr 25, 2024
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { NotificationFooter } from "@/app/api/cron/weekly-summary/components/NotificationFooter";
import { TNotificationResponse } from "@/app/api/cron/weekly-summary/types";
import { Container, Text } from "@react-email/components";

import { EmailButton } from "@formbricks/lib/emails/EmailButton";

interface CreateReminderNotificationBodyProps {
webAppUrl: string;
notificationData: TNotificationResponse;
}

export const CreateReminderNotificationBody = ({
webAppUrl,
Dhruwang marked this conversation as resolved.
Show resolved Hide resolved
notificationData,
}: CreateReminderNotificationBodyProps) => {
return (
<Container>
<Text>
We’d love to send you a Weekly Summary, but currently there are no surveys running for
{notificationData.productName}.
</Text>
<Text className="pt-4 font-bold">Don’t let a week pass without learning about your users:</Text>
<EmailButton
label="Setup a new survey"
href={`${webAppUrl}/environments/${notificationData.environmentId}/surveys?utm_source=weekly&utm_medium=email&utm_content=SetupANewSurveyCTA`}
/>
<Text className="pt-4">
Need help finding the right survey for your product? Pick a 15-minute slot{" "}
<a href="https://cal.com/johannes/15">in our CEOs calendar</a> or reply to this email :)
</Text>
<NotificationFooter environmentId={notificationData.environmentId} webAppUrl={webAppUrl} />
</Container>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import { TNotificationDataSurvey, TSurveyResponseData } from "@/app/api/cron/weekly-summary/types";
import { Container, Hr, Link, Tailwind, Text } from "@react-email/components";

import { EmailButton } from "@formbricks/lib/emails/EmailButton";
import { renderEmailResponseValue } from "@formbricks/lib/emails/ResponseFinishedEmail";

const getButtonLabel = (count: number): string => {
if (count === 1) {
return "View Response";
}
return `View ${count > 2 ? count - 1 : "1"} more Response${count > 2 ? "s" : ""}`;
};

const convertSurveyStatus = (status: string): string => {
const statusMap = {
inProgress: "Live",
Dhruwang marked this conversation as resolved.
Show resolved Hide resolved
paused: "Paused",
completed: "Completed",
draft: "Draft",
scheduled: "Scheduled",
};

return statusMap[status] || status;
};

interface LiveSurveyNotificationProps {
webAppUrl: string;
environmentId: string;
surveys: TNotificationDataSurvey[];
}

export const LiveSurveyNotification = ({
webAppUrl,
environmentId,
surveys,
}: LiveSurveyNotificationProps) => {
const createSurveyFields = (surveyResponses: TSurveyResponseData[]) => {
if (surveyResponses.length === 0) {
return (
<Container className="mt-4">
<Text className="m-0 font-bold">No Responses yet!</Text>
</Container>
);
}
let surveyFields: JSX.Element[] = [];
const responseCount = surveyResponses.length;

surveyResponses.forEach((surveyResponse, index) => {
if (!surveyResponse.responseValue) {
return;
}

surveyFields.push(
<Container className="mt-4" key={`${index}-${surveyResponse.headline}`}>
<Text className="m-0">{surveyResponse.headline}</Text>
{renderEmailResponseValue(surveyResponse.responseValue, surveyResponse.questionType)}
</Container>
);

// Add <hr/> only when there are 2 or more responses to display, and it's not the last response
if (responseCount >= 2 && index < responseCount - 1) {
surveyFields.push(<Hr key={`hr-${index}`} />);
}
});

return surveyFields;
};

if (!surveys.length) return ` `;
Dhruwang marked this conversation as resolved.
Show resolved Hide resolved

return surveys.map((survey, index) => {
const displayStatus = convertSurveyStatus(survey.status);
const isLive = displayStatus === "Live";
Dhruwang marked this conversation as resolved.
Show resolved Hide resolved
const noResponseLastWeek = isLive && survey.responses.length === 0;
return (
<Tailwind key={index}>
<Container className="mt-12">
<Text className="mb-0 inline">
<Link
href={`${webAppUrl}/environments/${environmentId}/surveys/${survey.id}/responses?utm_source=weekly&utm_medium=email&utm_content=ViewResponsesCTA`}
className="text-xl text-black underline">
{survey.name}
</Link>
</Text>

<Text
className={`ml-2 inline ${isLive ? "bg-green-400 text-gray-100" : "bg-gray-300 text-blue-800"} rounded-full px-2 py-1 text-sm`}>
{displayStatus}
</Text>
{noResponseLastWeek ? (
<Text>No new response received this week 🕵️</Text>
) : (
createSurveyFields(survey.responses)
)}
{survey.responseCount > 0 && (
<Container className="mt-4 block">
<EmailButton
label={noResponseLastWeek ? "View previous responses" : getButtonLabel(survey.responseCount)}
href={`${webAppUrl}/environments/${environmentId}/surveys/${survey.id}/responses?utm_source=weekly&utm_medium=email&utm_content=ViewResponsesCTA`}
/>
</Container>
)}
</Container>
</Tailwind>
);
});
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Container, Link, Text } from "@react-email/components";
import { Tailwind } from "@react-email/components";

interface NotificatonFooterProps {
webAppUrl: string;
environmentId: string;
}
export const NotificationFooter = ({ webAppUrl, environmentId }: NotificatonFooterProps) => {
return (
<Tailwind>
<Container className="w-full">
<Text className="mb-0 pt-4 font-medium">All the best,</Text>
<Text className="mt-0">The Formbricks Team 🤍</Text>
<Container
className="mt-0 w-full rounded-md bg-slate-100 px-4 text-center text-xs leading-5"
style={{ fontStyle: "italic" }}>
<Text>
To halt Weekly Updates,{" "}
<Link
href={`${webAppUrl}/environments/${environmentId}/settings/notifications`}
className="text-black underline">
please turn them off
</Link>{" "}
in your settings 🙏
</Text>
</Container>
</Container>
</Tailwind>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { Container, Heading, Text } from "@react-email/components";
import React from "react";

interface NotificationHeaderProps {
productName: string;
startDate: string;
endDate: string;
startYear: number;
endYear: number;
}

export const NotificationHeader = ({
productName,
startDate,
endDate,
startYear,
endYear,
}: NotificationHeaderProps) => {
const getNotificationHeaderimePeriod = (
startDate: string,
endDate: string,
startYear: number,
endYear: number
) => {
if (startYear == endYear) {
return (
<Text className="m-0 text-right">
{startDate} - {endDate} {endYear}
</Text>
);
} else {
return (
<Text className="m-0 text-right">
{startDate} {startYear} - {endDate} {endYear}
</Text>
);
}
};
return (
<Container>
<div className="block px-0 py-4">
<div className="float-left mt-2">
<Heading className="m-0">Hey 👋</Heading>
</div>
<div className="float-right">
<Text className="m-0 text-right font-semibold">Weekly Report for {productName}</Text>
{getNotificationHeaderimePeriod(startDate, endDate, startYear, endYear)}
</div>
</div>
</Container>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { TInsights } from "@/app/api/cron/weekly-summary/types";
import { Column, Container, Row, Section, Text } from "@react-email/components";
import React from "react";

interface NotificationInsightProps {
insights: TInsights;
}

export const NotificationInsight = ({ insights }: NotificationInsightProps) => {
return (
<Container>
<Section className="my-4 rounded-md bg-slate-100">
<Row>
<Column className="text-center">
<Text className="text-sm">Surveys</Text>
<Text className="text-lg font-bold">{insights.numLiveSurvey}</Text>
</Column>
<Column className="text-center">
<Text className="text-sm">Displays</Text>
<Text className="text-lg font-bold">{insights.totalDisplays}</Text>
</Column>
<Column className="text-center">
<Text className="text-sm">Responses</Text>
<Text className="text-lg font-bold">{insights.totalResponses}</Text>
</Column>
<Column className="text-center">
<Text className="text-sm">Completed</Text>
<Text className="text-lg font-bold">{insights.totalCompletedResponses}</Text>
</Column>
{insights.totalDisplays !== 0 ? (
<Column className="text-center">
<Text className="text-sm">Completion %</Text>
<Text className="text-lg font-bold">{Math.round(insights.completionRate)}%</Text>
</Column>
) : (
""
)}
</Row>
</Section>
</Container>
);
};
Loading
Loading