@vrplatform/email 1.0.2-stage.37478928158 → 1.0.2-stage.37579320177
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/main/templates/OwnerStatementEmailTemplate.d.ts +7 -2
- package/build/main/templates/OwnerStatementEmailTemplate.js +79 -3
- package/build/main/templates/OwnerStatementEmailTemplate.js.map +1 -1
- package/build/module/templates/OwnerStatementEmailTemplate.d.ts +7 -2
- package/build/module/templates/OwnerStatementEmailTemplate.js +80 -4
- package/build/module/templates/OwnerStatementEmailTemplate.js.map +1 -1
- package/package.json +1 -1
- package/src/templates/OwnerStatementEmailTemplate.tsx +195 -8
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { ActionEmailData, ActionEmailTemplateProps } from '../components/ActionEmailTemplate';
|
|
2
2
|
export declare const getDefaultOwnerStatementEmailData: (mode: "tag" | "text", args: {
|
|
3
3
|
appName: string;
|
|
4
4
|
ownerStatementHref: string;
|
|
5
5
|
listingName: string;
|
|
6
6
|
userName: string;
|
|
7
7
|
month: string;
|
|
8
|
+
/** The owner opens the statement through an emailed link, without a login. */
|
|
9
|
+
noLogin?: boolean;
|
|
8
10
|
}) => ActionEmailData;
|
|
9
|
-
export declare const OwnerStatementEmailTemplate: (
|
|
11
|
+
export declare const OwnerStatementEmailTemplate: ({ data, tenant, themeColors, mode, user, listing, month, unsubscribeHref, renewHref, }: ActionEmailTemplateProps & {
|
|
12
|
+
/** Requests a new no-login link once the emailed one has expired. */
|
|
13
|
+
renewHref?: string;
|
|
14
|
+
}) => import("react").JSX.Element;
|
|
@@ -2,13 +2,28 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.OwnerStatementEmailTemplate = exports.getDefaultOwnerStatementEmailData = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const heading_1 = require("@react-email/heading");
|
|
6
|
+
const text_1 = require("@react-email/text");
|
|
5
7
|
const extensions_1 = require("../extensions");
|
|
6
|
-
const
|
|
8
|
+
const Button_1 = require("../components/Button");
|
|
9
|
+
const EmailContainer_1 = require("../components/EmailContainer");
|
|
10
|
+
const utils_1 = require("../components/utils");
|
|
7
11
|
const getDefaultOwnerStatementEmailData = (mode, args) => {
|
|
8
12
|
const ownerStatementHref = mode === 'tag' ? extensions_1.EMAIL_ACTION_LINK_COMPONENT : args.ownerStatementHref;
|
|
9
13
|
const listingName = mode === 'tag' ? extensions_1.EMAIL_LISTING_COMPONENT : args.listingName;
|
|
10
14
|
const month = mode === 'tag' ? extensions_1.EMAIL_DATE_COMPONENT : args.month;
|
|
11
15
|
const userName = mode === 'tag' ? extensions_1.EMAIL_USER_NAME_COMPONENT : args.userName;
|
|
16
|
+
if (args.noLogin) {
|
|
17
|
+
return {
|
|
18
|
+
subject: `Your ${args.month} owner statement for ${args.listingName}`,
|
|
19
|
+
shortDescription: `Your ${args.month} statement for ${args.listingName} is ready. Open it with one click, no login needed.`,
|
|
20
|
+
header: 'Your owner statement is ready',
|
|
21
|
+
bodyOne: `<p>Hi ${userName},</p><p>${args.appName} published your ${month} owner statement for ${listingName}. Open it with the button below. You don't need a login.</p>`,
|
|
22
|
+
buttonText: 'View statement',
|
|
23
|
+
bodyTwo: `<p style="color:#737373;font-size:13px">If the button doesn't work, copy this link into your browser: ${ownerStatementHref}</p>`,
|
|
24
|
+
href: args.ownerStatementHref,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
12
27
|
return {
|
|
13
28
|
subject: 'Owner statement was published',
|
|
14
29
|
shortDescription: `An owner statement is ready for you. Log in to ${args.appName} now to view it.`,
|
|
@@ -20,8 +35,69 @@ const getDefaultOwnerStatementEmailData = (mode, args) => {
|
|
|
20
35
|
};
|
|
21
36
|
};
|
|
22
37
|
exports.getDefaultOwnerStatementEmailData = getDefaultOwnerStatementEmailData;
|
|
23
|
-
const
|
|
24
|
-
|
|
38
|
+
const mutedColor = '#737373';
|
|
39
|
+
const borderColor = '#e5e7eb';
|
|
40
|
+
const OwnerStatementEmailTemplate = ({ data, tenant, themeColors, mode, user, listing, month, unsubscribeHref, renewHref, }) => {
|
|
41
|
+
const parse = (html) => (0, utils_1.parseEmailHtml)(html, {
|
|
42
|
+
href: data.href,
|
|
43
|
+
userName: user.firstName || '',
|
|
44
|
+
date: month || '',
|
|
45
|
+
listingName: listing || '',
|
|
46
|
+
});
|
|
47
|
+
return ((0, jsx_runtime_1.jsxs)(EmailContainer_1.EmailContainer, { title: data.subject, shortDescription: data.shortDescription, tenant: tenant, mode: mode, unsubscribeHref: unsubscribeHref, children: [(0, jsx_runtime_1.jsx)(text_1.Text, { style: {
|
|
48
|
+
color: themeColors[8],
|
|
49
|
+
fontSize: 12,
|
|
50
|
+
fontWeight: 600,
|
|
51
|
+
letterSpacing: '0.08em',
|
|
52
|
+
textTransform: 'uppercase',
|
|
53
|
+
margin: '0 0 8px',
|
|
54
|
+
}, children: "Owner statement" }), (0, jsx_runtime_1.jsx)(heading_1.Heading, { style: {
|
|
55
|
+
fontSize: 26,
|
|
56
|
+
fontWeight: 600,
|
|
57
|
+
lineHeight: '34px',
|
|
58
|
+
margin: '0 0 32px',
|
|
59
|
+
}, children: data.header?.trim() || 'Your owner statement is ready' }), data.banner?.trim() && ((0, jsx_runtime_1.jsx)(text_1.Text, { style: {
|
|
60
|
+
padding: '16px 20px',
|
|
61
|
+
backgroundColor: '#f8f9fa',
|
|
62
|
+
borderLeft: `3px solid ${themeColors[8]}`,
|
|
63
|
+
borderRadius: '4px',
|
|
64
|
+
margin: '0 0 32px',
|
|
65
|
+
whiteSpace: 'pre-line',
|
|
66
|
+
}, children: data.banner.trim() })), (0, jsx_runtime_1.jsx)("div", {
|
|
67
|
+
// biome-ignore lint/security/noDangerouslySetInnerHtml: values are escaped by parseEmailHtml
|
|
68
|
+
dangerouslySetInnerHTML: { __html: parse(data.bodyOne) } }), (listing || month) && ((0, jsx_runtime_1.jsx)("table", { role: "presentation", cellPadding: 0, cellSpacing: 0, width: "100%", style: {
|
|
69
|
+
border: `1px solid ${borderColor}`,
|
|
70
|
+
borderRadius: '8px',
|
|
71
|
+
borderCollapse: 'separate',
|
|
72
|
+
margin: '24px 0 0',
|
|
73
|
+
}, children: (0, jsx_runtime_1.jsx)("tbody", { children: [
|
|
74
|
+
['Property', listing],
|
|
75
|
+
['Statement', month],
|
|
76
|
+
].map(([label, value], index) => value ? ((0, jsx_runtime_1.jsxs)("tr", { children: [(0, jsx_runtime_1.jsx)("td", { style: {
|
|
77
|
+
padding: '14px 20px',
|
|
78
|
+
color: mutedColor,
|
|
79
|
+
fontSize: 14,
|
|
80
|
+
borderTop: index ? `1px solid ${borderColor}` : 'none',
|
|
81
|
+
}, children: label }), (0, jsx_runtime_1.jsx)("td", { style: {
|
|
82
|
+
padding: '14px 20px',
|
|
83
|
+
fontSize: 14,
|
|
84
|
+
fontWeight: 600,
|
|
85
|
+
textAlign: 'right',
|
|
86
|
+
borderTop: index ? `1px solid ${borderColor}` : 'none',
|
|
87
|
+
}, children: value })] }, label)) : null) }) })), (0, jsx_runtime_1.jsx)(Button_1.Button, { href: data.href, mode: mode, "data-testid": "view-owner-statement-button", label: data.buttonText?.trim() || 'View statement', themeColors: themeColors, style: { marginTop: '24px', marginBottom: '32px' } }), renewHref && ((0, jsx_runtime_1.jsxs)("div", { style: {
|
|
88
|
+
padding: '20px',
|
|
89
|
+
backgroundColor: '#f8f9fa',
|
|
90
|
+
borderRadius: '8px',
|
|
91
|
+
marginBottom: '32px',
|
|
92
|
+
}, children: [(0, jsx_runtime_1.jsx)(text_1.Text, { style: { fontWeight: 600, margin: '0 0 4px' }, children: "Link expired?" }), (0, jsx_runtime_1.jsx)(text_1.Text, { style: { color: mutedColor, fontSize: 14, margin: 0 }, children: "For your security, this link opens only this statement and works for 7 days. After that, request a new one and we'll email it to this address." }), (0, jsx_runtime_1.jsx)(Button_1.Button, { href: renewHref, mode: mode, "data-testid": "renew-owner-statement-link-button", label: "Send me a new link", themeColors: themeColors, style: {
|
|
93
|
+
background: '#ffffff',
|
|
94
|
+
border: `1px solid ${themeColors[8]}`,
|
|
95
|
+
color: themeColors[8],
|
|
96
|
+
marginTop: '16px',
|
|
97
|
+
marginBottom: 0,
|
|
98
|
+
} })] })), (0, jsx_runtime_1.jsx)("div", {
|
|
99
|
+
// biome-ignore lint/security/noDangerouslySetInnerHtml: values are escaped by parseEmailHtml
|
|
100
|
+
dangerouslySetInnerHTML: { __html: parse(data.bodyTwo) } })] }));
|
|
25
101
|
};
|
|
26
102
|
exports.OwnerStatementEmailTemplate = OwnerStatementEmailTemplate;
|
|
27
103
|
//# sourceMappingURL=OwnerStatementEmailTemplate.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OwnerStatementEmailTemplate.js","sourceRoot":"src/","sources":["templates/OwnerStatementEmailTemplate.tsx"],"names":[],"mappings":";;;;AAAA,8CAKuB;AACvB,2EAI2C;AAEpC,MAAM,iCAAiC,GAAG,CAC/C,IAAoB,EACpB,IAMC,EACgB,EAAE;IACnB,MAAM,kBAAkB,GACtB,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,wCAA2B,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC;IAEzE,MAAM,WAAW,GACf,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,oCAAuB,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC;IAC9D,MAAM,KAAK,GAAG,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,iCAAoB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;IACjE,MAAM,QAAQ,GAAG,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,sCAAyB,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC;IAE5E,OAAO;QACL,OAAO,EAAE,+BAA+B;QACxC,gBAAgB,EAAE,kDAAkD,IAAI,CAAC,OAAO,kBAAkB;QAClG,MAAM,EAAE,+BAA+B;QACvC,OAAO,EAAE,SAAS,QAAQ,YAAY,KAAK,iCAAiC,WAAW,gCAAgC,IAAI,CAAC,OAAO,sEAAsE;QACzM,UAAU,EAAE,sBAAsB;QAClC,OAAO,EAAE,wGAAwG,kBAAkB,MAAM;QACzI,IAAI,EAAE,IAAI,CAAC,kBAAkB;KAC9B,CAAC;AACJ,CAAC,CAAC;AA3BW,QAAA,iCAAiC,qCA2B5C;AAEK,MAAM,2BAA2B,GAAG,CACzC,KAA+B,EAC/B,EAAE;IACF,OAAO,uBAAC,yCAAmB,OAAK,KAAK,GAAI,CAAC;AAC5C,CAAC,CAAC;AAJW,QAAA,2BAA2B,+BAItC","sourcesContent":["import {\n EMAIL_ACTION_LINK_COMPONENT,\n EMAIL_DATE_COMPONENT,\n EMAIL_LISTING_COMPONENT,\n EMAIL_USER_NAME_COMPONENT,\n} from '../extensions';\nimport {\n type ActionEmailData,\n ActionEmailTemplate,\n type ActionEmailTemplateProps,\n} from '../components/ActionEmailTemplate';\n\nexport const getDefaultOwnerStatementEmailData = (\n mode: 'tag' | 'text',\n args: {\n appName: string;\n ownerStatementHref: string;\n listingName: string;\n userName: string;\n month: string;\n }\n): ActionEmailData => {\n const ownerStatementHref =\n mode === 'tag' ? EMAIL_ACTION_LINK_COMPONENT : args.ownerStatementHref;\n\n const listingName =\n mode === 'tag' ? EMAIL_LISTING_COMPONENT : args.listingName;\n const month = mode === 'tag' ? EMAIL_DATE_COMPONENT : args.month;\n const userName = mode === 'tag' ? EMAIL_USER_NAME_COMPONENT : args.userName;\n\n return {\n subject: 'Owner statement was published',\n shortDescription: `An owner statement is ready for you. Log in to ${args.appName} now to view it.`,\n header: 'Owner statement was published',\n bodyOne: `<p>Hi ${userName},<p>Your ${month} owner statement for property ${listingName} is ready for your review on ${args.appName}.</p><p>To access your statement, please click the button below:</p>`,\n buttonText: 'View Owner statement',\n bodyTwo: `<p>If you have any trouble with the button, you can copy and paste the link below into your browser: ${ownerStatementHref}</p>`,\n href: args.ownerStatementHref,\n };\n};\n\nexport const OwnerStatementEmailTemplate = (\n props: ActionEmailTemplateProps\n) => {\n return <ActionEmailTemplate {...props} />;\n};\n"]}
|
|
1
|
+
{"version":3,"file":"OwnerStatementEmailTemplate.js","sourceRoot":"src/","sources":["templates/OwnerStatementEmailTemplate.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Heading } from '@react-email/heading';\nimport { Text } from '@react-email/text';\nimport {\n EMAIL_ACTION_LINK_COMPONENT,\n EMAIL_DATE_COMPONENT,\n EMAIL_LISTING_COMPONENT,\n EMAIL_USER_NAME_COMPONENT,\n} from '../extensions';\nimport type {\n ActionEmailData,\n ActionEmailTemplateProps,\n} from '../components/ActionEmailTemplate';\nimport { Button } from '../components/Button';\nimport { EmailContainer } from '../components/EmailContainer';\nimport { parseEmailHtml } from '../components/utils';\n\nexport const getDefaultOwnerStatementEmailData = (\n mode: 'tag' | 'text',\n args: {\n appName: string;\n ownerStatementHref: string;\n listingName: string;\n userName: string;\n month: string;\n /** The owner opens the statement through an emailed link, without a login. */\n noLogin?: boolean;\n }\n): ActionEmailData => {\n const ownerStatementHref =\n mode === 'tag' ? EMAIL_ACTION_LINK_COMPONENT : args.ownerStatementHref;\n\n const listingName =\n mode === 'tag' ? EMAIL_LISTING_COMPONENT : args.listingName;\n const month = mode === 'tag' ? EMAIL_DATE_COMPONENT : args.month;\n const userName = mode === 'tag' ? EMAIL_USER_NAME_COMPONENT : args.userName;\n\n if (args.noLogin) {\n return {\n subject: `Your ${args.month} owner statement for ${args.listingName}`,\n shortDescription: `Your ${args.month} statement for ${args.listingName} is ready. Open it with one click, no login needed.`,\n header: 'Your owner statement is ready',\n bodyOne: `<p>Hi ${userName},</p><p>${args.appName} published your ${month} owner statement for ${listingName}. Open it with the button below. You don't need a login.</p>`,\n buttonText: 'View statement',\n bodyTwo: `<p style=\"color:#737373;font-size:13px\">If the button doesn't work, copy this link into your browser: ${ownerStatementHref}</p>`,\n href: args.ownerStatementHref,\n };\n }\n\n return {\n subject: 'Owner statement was published',\n shortDescription: `An owner statement is ready for you. Log in to ${args.appName} now to view it.`,\n header: 'Owner statement was published',\n bodyOne: `<p>Hi ${userName},<p>Your ${month} owner statement for property ${listingName} is ready for your review on ${args.appName}.</p><p>To access your statement, please click the button below:</p>`,\n buttonText: 'View Owner statement',\n bodyTwo: `<p>If you have any trouble with the button, you can copy and paste the link below into your browser: ${ownerStatementHref}</p>`,\n href: args.ownerStatementHref,\n };\n};\n\nconst mutedColor = '#737373';\nconst borderColor = '#e5e7eb';\n\nexport const OwnerStatementEmailTemplate = ({\n data,\n tenant,\n themeColors,\n mode,\n user,\n listing,\n month,\n unsubscribeHref,\n renewHref,\n}: ActionEmailTemplateProps & {\n /** Requests a new no-login link once the emailed one has expired. */\n renewHref?: string;\n}) => {\n const parse = (html: string) =>\n parseEmailHtml(html, {\n href: data.href,\n userName: user.firstName || '',\n date: month || '',\n listingName: listing || '',\n });\n\n return (\n <EmailContainer\n title={data.subject}\n shortDescription={data.shortDescription}\n tenant={tenant}\n mode={mode}\n unsubscribeHref={unsubscribeHref}\n >\n <Text\n style={{\n color: themeColors[8],\n fontSize: 12,\n fontWeight: 600,\n letterSpacing: '0.08em',\n textTransform: 'uppercase',\n margin: '0 0 8px',\n }}\n >\n Owner statement\n </Text>\n <Heading\n style={{\n fontSize: 26,\n fontWeight: 600,\n lineHeight: '34px',\n margin: '0 0 32px',\n }}\n >\n {data.header?.trim() || 'Your owner statement is ready'}\n </Heading>\n\n {data.banner?.trim() && (\n <Text\n style={{\n padding: '16px 20px',\n backgroundColor: '#f8f9fa',\n borderLeft: `3px solid ${themeColors[8]}`,\n borderRadius: '4px',\n margin: '0 0 32px',\n whiteSpace: 'pre-line',\n }}\n >\n {data.banner.trim()}\n </Text>\n )}\n\n <div\n // biome-ignore lint/security/noDangerouslySetInnerHtml: values are escaped by parseEmailHtml\n dangerouslySetInnerHTML={{ __html: parse(data.bodyOne) }}\n />\n\n {(listing || month) && (\n <table\n role=\"presentation\"\n cellPadding={0}\n cellSpacing={0}\n width=\"100%\"\n style={{\n border: `1px solid ${borderColor}`,\n borderRadius: '8px',\n borderCollapse: 'separate',\n margin: '24px 0 0',\n }}\n >\n <tbody>\n {[\n ['Property', listing],\n ['Statement', month],\n ].map(([label, value], index) =>\n value ? (\n <tr key={label}>\n <td\n style={{\n padding: '14px 20px',\n color: mutedColor,\n fontSize: 14,\n borderTop: index ? `1px solid ${borderColor}` : 'none',\n }}\n >\n {label}\n </td>\n <td\n style={{\n padding: '14px 20px',\n fontSize: 14,\n fontWeight: 600,\n textAlign: 'right',\n borderTop: index ? `1px solid ${borderColor}` : 'none',\n }}\n >\n {value}\n </td>\n </tr>\n ) : null\n )}\n </tbody>\n </table>\n )}\n\n <Button\n href={data.href}\n mode={mode}\n data-testid=\"view-owner-statement-button\"\n label={data.buttonText?.trim() || 'View statement'}\n themeColors={themeColors}\n style={{ marginTop: '24px', marginBottom: '32px' }}\n />\n\n {renewHref && (\n <div\n style={{\n padding: '20px',\n backgroundColor: '#f8f9fa',\n borderRadius: '8px',\n marginBottom: '32px',\n }}\n >\n <Text style={{ fontWeight: 600, margin: '0 0 4px' }}>\n Link expired?\n </Text>\n <Text style={{ color: mutedColor, fontSize: 14, margin: 0 }}>\n For your security, this link opens only this statement and works for\n 7 days. After that, request a new one and we'll email it to this\n address.\n </Text>\n <Button\n href={renewHref}\n mode={mode}\n data-testid=\"renew-owner-statement-link-button\"\n label=\"Send me a new link\"\n themeColors={themeColors}\n style={{\n background: '#ffffff',\n border: `1px solid ${themeColors[8]}`,\n color: themeColors[8],\n marginTop: '16px',\n marginBottom: 0,\n }}\n />\n </div>\n )}\n\n <div\n // biome-ignore lint/security/noDangerouslySetInnerHtml: values are escaped by parseEmailHtml\n dangerouslySetInnerHTML={{ __html: parse(data.bodyTwo) }}\n />\n </EmailContainer>\n );\n};\n"]}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { ActionEmailData, ActionEmailTemplateProps } from '../components/ActionEmailTemplate';
|
|
2
2
|
export declare const getDefaultOwnerStatementEmailData: (mode: "tag" | "text", args: {
|
|
3
3
|
appName: string;
|
|
4
4
|
ownerStatementHref: string;
|
|
5
5
|
listingName: string;
|
|
6
6
|
userName: string;
|
|
7
7
|
month: string;
|
|
8
|
+
/** The owner opens the statement through an emailed link, without a login. */
|
|
9
|
+
noLogin?: boolean;
|
|
8
10
|
}) => ActionEmailData;
|
|
9
|
-
export declare const OwnerStatementEmailTemplate: (
|
|
11
|
+
export declare const OwnerStatementEmailTemplate: ({ data, tenant, themeColors, mode, user, listing, month, unsubscribeHref, renewHref, }: ActionEmailTemplateProps & {
|
|
12
|
+
/** Requests a new no-login link once the emailed one has expired. */
|
|
13
|
+
renewHref?: string;
|
|
14
|
+
}) => import("react").JSX.Element;
|
|
@@ -1,11 +1,26 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Heading } from '@react-email/heading';
|
|
3
|
+
import { Text } from '@react-email/text';
|
|
2
4
|
import { EMAIL_ACTION_LINK_COMPONENT, EMAIL_DATE_COMPONENT, EMAIL_LISTING_COMPONENT, EMAIL_USER_NAME_COMPONENT, } from '../extensions';
|
|
3
|
-
import {
|
|
5
|
+
import { Button } from '../components/Button';
|
|
6
|
+
import { EmailContainer } from '../components/EmailContainer';
|
|
7
|
+
import { parseEmailHtml } from '../components/utils';
|
|
4
8
|
export const getDefaultOwnerStatementEmailData = (mode, args) => {
|
|
5
9
|
const ownerStatementHref = mode === 'tag' ? EMAIL_ACTION_LINK_COMPONENT : args.ownerStatementHref;
|
|
6
10
|
const listingName = mode === 'tag' ? EMAIL_LISTING_COMPONENT : args.listingName;
|
|
7
11
|
const month = mode === 'tag' ? EMAIL_DATE_COMPONENT : args.month;
|
|
8
12
|
const userName = mode === 'tag' ? EMAIL_USER_NAME_COMPONENT : args.userName;
|
|
13
|
+
if (args.noLogin) {
|
|
14
|
+
return {
|
|
15
|
+
subject: `Your ${args.month} owner statement for ${args.listingName}`,
|
|
16
|
+
shortDescription: `Your ${args.month} statement for ${args.listingName} is ready. Open it with one click, no login needed.`,
|
|
17
|
+
header: 'Your owner statement is ready',
|
|
18
|
+
bodyOne: `<p>Hi ${userName},</p><p>${args.appName} published your ${month} owner statement for ${listingName}. Open it with the button below. You don't need a login.</p>`,
|
|
19
|
+
buttonText: 'View statement',
|
|
20
|
+
bodyTwo: `<p style="color:#737373;font-size:13px">If the button doesn't work, copy this link into your browser: ${ownerStatementHref}</p>`,
|
|
21
|
+
href: args.ownerStatementHref,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
9
24
|
return {
|
|
10
25
|
subject: 'Owner statement was published',
|
|
11
26
|
shortDescription: `An owner statement is ready for you. Log in to ${args.appName} now to view it.`,
|
|
@@ -16,7 +31,68 @@ export const getDefaultOwnerStatementEmailData = (mode, args) => {
|
|
|
16
31
|
href: args.ownerStatementHref,
|
|
17
32
|
};
|
|
18
33
|
};
|
|
19
|
-
|
|
20
|
-
|
|
34
|
+
const mutedColor = '#737373';
|
|
35
|
+
const borderColor = '#e5e7eb';
|
|
36
|
+
export const OwnerStatementEmailTemplate = ({ data, tenant, themeColors, mode, user, listing, month, unsubscribeHref, renewHref, }) => {
|
|
37
|
+
const parse = (html) => parseEmailHtml(html, {
|
|
38
|
+
href: data.href,
|
|
39
|
+
userName: user.firstName || '',
|
|
40
|
+
date: month || '',
|
|
41
|
+
listingName: listing || '',
|
|
42
|
+
});
|
|
43
|
+
return (_jsxs(EmailContainer, { title: data.subject, shortDescription: data.shortDescription, tenant: tenant, mode: mode, unsubscribeHref: unsubscribeHref, children: [_jsx(Text, { style: {
|
|
44
|
+
color: themeColors[8],
|
|
45
|
+
fontSize: 12,
|
|
46
|
+
fontWeight: 600,
|
|
47
|
+
letterSpacing: '0.08em',
|
|
48
|
+
textTransform: 'uppercase',
|
|
49
|
+
margin: '0 0 8px',
|
|
50
|
+
}, children: "Owner statement" }), _jsx(Heading, { style: {
|
|
51
|
+
fontSize: 26,
|
|
52
|
+
fontWeight: 600,
|
|
53
|
+
lineHeight: '34px',
|
|
54
|
+
margin: '0 0 32px',
|
|
55
|
+
}, children: data.header?.trim() || 'Your owner statement is ready' }), data.banner?.trim() && (_jsx(Text, { style: {
|
|
56
|
+
padding: '16px 20px',
|
|
57
|
+
backgroundColor: '#f8f9fa',
|
|
58
|
+
borderLeft: `3px solid ${themeColors[8]}`,
|
|
59
|
+
borderRadius: '4px',
|
|
60
|
+
margin: '0 0 32px',
|
|
61
|
+
whiteSpace: 'pre-line',
|
|
62
|
+
}, children: data.banner.trim() })), _jsx("div", {
|
|
63
|
+
// biome-ignore lint/security/noDangerouslySetInnerHtml: values are escaped by parseEmailHtml
|
|
64
|
+
dangerouslySetInnerHTML: { __html: parse(data.bodyOne) } }), (listing || month) && (_jsx("table", { role: "presentation", cellPadding: 0, cellSpacing: 0, width: "100%", style: {
|
|
65
|
+
border: `1px solid ${borderColor}`,
|
|
66
|
+
borderRadius: '8px',
|
|
67
|
+
borderCollapse: 'separate',
|
|
68
|
+
margin: '24px 0 0',
|
|
69
|
+
}, children: _jsx("tbody", { children: [
|
|
70
|
+
['Property', listing],
|
|
71
|
+
['Statement', month],
|
|
72
|
+
].map(([label, value], index) => value ? (_jsxs("tr", { children: [_jsx("td", { style: {
|
|
73
|
+
padding: '14px 20px',
|
|
74
|
+
color: mutedColor,
|
|
75
|
+
fontSize: 14,
|
|
76
|
+
borderTop: index ? `1px solid ${borderColor}` : 'none',
|
|
77
|
+
}, children: label }), _jsx("td", { style: {
|
|
78
|
+
padding: '14px 20px',
|
|
79
|
+
fontSize: 14,
|
|
80
|
+
fontWeight: 600,
|
|
81
|
+
textAlign: 'right',
|
|
82
|
+
borderTop: index ? `1px solid ${borderColor}` : 'none',
|
|
83
|
+
}, children: value })] }, label)) : null) }) })), _jsx(Button, { href: data.href, mode: mode, "data-testid": "view-owner-statement-button", label: data.buttonText?.trim() || 'View statement', themeColors: themeColors, style: { marginTop: '24px', marginBottom: '32px' } }), renewHref && (_jsxs("div", { style: {
|
|
84
|
+
padding: '20px',
|
|
85
|
+
backgroundColor: '#f8f9fa',
|
|
86
|
+
borderRadius: '8px',
|
|
87
|
+
marginBottom: '32px',
|
|
88
|
+
}, children: [_jsx(Text, { style: { fontWeight: 600, margin: '0 0 4px' }, children: "Link expired?" }), _jsx(Text, { style: { color: mutedColor, fontSize: 14, margin: 0 }, children: "For your security, this link opens only this statement and works for 7 days. After that, request a new one and we'll email it to this address." }), _jsx(Button, { href: renewHref, mode: mode, "data-testid": "renew-owner-statement-link-button", label: "Send me a new link", themeColors: themeColors, style: {
|
|
89
|
+
background: '#ffffff',
|
|
90
|
+
border: `1px solid ${themeColors[8]}`,
|
|
91
|
+
color: themeColors[8],
|
|
92
|
+
marginTop: '16px',
|
|
93
|
+
marginBottom: 0,
|
|
94
|
+
} })] })), _jsx("div", {
|
|
95
|
+
// biome-ignore lint/security/noDangerouslySetInnerHtml: values are escaped by parseEmailHtml
|
|
96
|
+
dangerouslySetInnerHTML: { __html: parse(data.bodyTwo) } })] }));
|
|
21
97
|
};
|
|
22
98
|
//# sourceMappingURL=OwnerStatementEmailTemplate.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OwnerStatementEmailTemplate.js","sourceRoot":"src/","sources":["templates/OwnerStatementEmailTemplate.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,2BAA2B,EAC3B,oBAAoB,EACpB,uBAAuB,EACvB,yBAAyB,GAC1B,MAAM,eAAe,CAAC;AACvB,OAAO,EAEL,mBAAmB,GAEpB,MAAM,mCAAmC,CAAC;AAE3C,MAAM,CAAC,MAAM,iCAAiC,GAAG,CAC/C,IAAoB,EACpB,IAMC,EACgB,EAAE;IACnB,MAAM,kBAAkB,GACtB,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC;IAEzE,MAAM,WAAW,GACf,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC;IAC9D,MAAM,KAAK,GAAG,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;IACjE,MAAM,QAAQ,GAAG,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC;IAE5E,OAAO;QACL,OAAO,EAAE,+BAA+B;QACxC,gBAAgB,EAAE,kDAAkD,IAAI,CAAC,OAAO,kBAAkB;QAClG,MAAM,EAAE,+BAA+B;QACvC,OAAO,EAAE,SAAS,QAAQ,YAAY,KAAK,iCAAiC,WAAW,gCAAgC,IAAI,CAAC,OAAO,sEAAsE;QACzM,UAAU,EAAE,sBAAsB;QAClC,OAAO,EAAE,wGAAwG,kBAAkB,MAAM;QACzI,IAAI,EAAE,IAAI,CAAC,kBAAkB;KAC9B,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,2BAA2B,GAAG,CACzC,KAA+B,EAC/B,EAAE;IACF,OAAO,KAAC,mBAAmB,OAAK,KAAK,GAAI,CAAC;AAC5C,CAAC,CAAC","sourcesContent":["import {\n EMAIL_ACTION_LINK_COMPONENT,\n EMAIL_DATE_COMPONENT,\n EMAIL_LISTING_COMPONENT,\n EMAIL_USER_NAME_COMPONENT,\n} from '../extensions';\nimport {\n type ActionEmailData,\n ActionEmailTemplate,\n type ActionEmailTemplateProps,\n} from '../components/ActionEmailTemplate';\n\nexport const getDefaultOwnerStatementEmailData = (\n mode: 'tag' | 'text',\n args: {\n appName: string;\n ownerStatementHref: string;\n listingName: string;\n userName: string;\n month: string;\n }\n): ActionEmailData => {\n const ownerStatementHref =\n mode === 'tag' ? EMAIL_ACTION_LINK_COMPONENT : args.ownerStatementHref;\n\n const listingName =\n mode === 'tag' ? EMAIL_LISTING_COMPONENT : args.listingName;\n const month = mode === 'tag' ? EMAIL_DATE_COMPONENT : args.month;\n const userName = mode === 'tag' ? EMAIL_USER_NAME_COMPONENT : args.userName;\n\n return {\n subject: 'Owner statement was published',\n shortDescription: `An owner statement is ready for you. Log in to ${args.appName} now to view it.`,\n header: 'Owner statement was published',\n bodyOne: `<p>Hi ${userName},<p>Your ${month} owner statement for property ${listingName} is ready for your review on ${args.appName}.</p><p>To access your statement, please click the button below:</p>`,\n buttonText: 'View Owner statement',\n bodyTwo: `<p>If you have any trouble with the button, you can copy and paste the link below into your browser: ${ownerStatementHref}</p>`,\n href: args.ownerStatementHref,\n };\n};\n\nexport const OwnerStatementEmailTemplate = (\n props: ActionEmailTemplateProps\n) => {\n return <ActionEmailTemplate {...props} />;\n};\n"]}
|
|
1
|
+
{"version":3,"file":"OwnerStatementEmailTemplate.js","sourceRoot":"src/","sources":["templates/OwnerStatementEmailTemplate.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Heading } from '@react-email/heading';\nimport { Text } from '@react-email/text';\nimport {\n EMAIL_ACTION_LINK_COMPONENT,\n EMAIL_DATE_COMPONENT,\n EMAIL_LISTING_COMPONENT,\n EMAIL_USER_NAME_COMPONENT,\n} from '../extensions';\nimport type {\n ActionEmailData,\n ActionEmailTemplateProps,\n} from '../components/ActionEmailTemplate';\nimport { Button } from '../components/Button';\nimport { EmailContainer } from '../components/EmailContainer';\nimport { parseEmailHtml } from '../components/utils';\n\nexport const getDefaultOwnerStatementEmailData = (\n mode: 'tag' | 'text',\n args: {\n appName: string;\n ownerStatementHref: string;\n listingName: string;\n userName: string;\n month: string;\n /** The owner opens the statement through an emailed link, without a login. */\n noLogin?: boolean;\n }\n): ActionEmailData => {\n const ownerStatementHref =\n mode === 'tag' ? EMAIL_ACTION_LINK_COMPONENT : args.ownerStatementHref;\n\n const listingName =\n mode === 'tag' ? EMAIL_LISTING_COMPONENT : args.listingName;\n const month = mode === 'tag' ? EMAIL_DATE_COMPONENT : args.month;\n const userName = mode === 'tag' ? EMAIL_USER_NAME_COMPONENT : args.userName;\n\n if (args.noLogin) {\n return {\n subject: `Your ${args.month} owner statement for ${args.listingName}`,\n shortDescription: `Your ${args.month} statement for ${args.listingName} is ready. Open it with one click, no login needed.`,\n header: 'Your owner statement is ready',\n bodyOne: `<p>Hi ${userName},</p><p>${args.appName} published your ${month} owner statement for ${listingName}. Open it with the button below. You don't need a login.</p>`,\n buttonText: 'View statement',\n bodyTwo: `<p style=\"color:#737373;font-size:13px\">If the button doesn't work, copy this link into your browser: ${ownerStatementHref}</p>`,\n href: args.ownerStatementHref,\n };\n }\n\n return {\n subject: 'Owner statement was published',\n shortDescription: `An owner statement is ready for you. Log in to ${args.appName} now to view it.`,\n header: 'Owner statement was published',\n bodyOne: `<p>Hi ${userName},<p>Your ${month} owner statement for property ${listingName} is ready for your review on ${args.appName}.</p><p>To access your statement, please click the button below:</p>`,\n buttonText: 'View Owner statement',\n bodyTwo: `<p>If you have any trouble with the button, you can copy and paste the link below into your browser: ${ownerStatementHref}</p>`,\n href: args.ownerStatementHref,\n };\n};\n\nconst mutedColor = '#737373';\nconst borderColor = '#e5e7eb';\n\nexport const OwnerStatementEmailTemplate = ({\n data,\n tenant,\n themeColors,\n mode,\n user,\n listing,\n month,\n unsubscribeHref,\n renewHref,\n}: ActionEmailTemplateProps & {\n /** Requests a new no-login link once the emailed one has expired. */\n renewHref?: string;\n}) => {\n const parse = (html: string) =>\n parseEmailHtml(html, {\n href: data.href,\n userName: user.firstName || '',\n date: month || '',\n listingName: listing || '',\n });\n\n return (\n <EmailContainer\n title={data.subject}\n shortDescription={data.shortDescription}\n tenant={tenant}\n mode={mode}\n unsubscribeHref={unsubscribeHref}\n >\n <Text\n style={{\n color: themeColors[8],\n fontSize: 12,\n fontWeight: 600,\n letterSpacing: '0.08em',\n textTransform: 'uppercase',\n margin: '0 0 8px',\n }}\n >\n Owner statement\n </Text>\n <Heading\n style={{\n fontSize: 26,\n fontWeight: 600,\n lineHeight: '34px',\n margin: '0 0 32px',\n }}\n >\n {data.header?.trim() || 'Your owner statement is ready'}\n </Heading>\n\n {data.banner?.trim() && (\n <Text\n style={{\n padding: '16px 20px',\n backgroundColor: '#f8f9fa',\n borderLeft: `3px solid ${themeColors[8]}`,\n borderRadius: '4px',\n margin: '0 0 32px',\n whiteSpace: 'pre-line',\n }}\n >\n {data.banner.trim()}\n </Text>\n )}\n\n <div\n // biome-ignore lint/security/noDangerouslySetInnerHtml: values are escaped by parseEmailHtml\n dangerouslySetInnerHTML={{ __html: parse(data.bodyOne) }}\n />\n\n {(listing || month) && (\n <table\n role=\"presentation\"\n cellPadding={0}\n cellSpacing={0}\n width=\"100%\"\n style={{\n border: `1px solid ${borderColor}`,\n borderRadius: '8px',\n borderCollapse: 'separate',\n margin: '24px 0 0',\n }}\n >\n <tbody>\n {[\n ['Property', listing],\n ['Statement', month],\n ].map(([label, value], index) =>\n value ? (\n <tr key={label}>\n <td\n style={{\n padding: '14px 20px',\n color: mutedColor,\n fontSize: 14,\n borderTop: index ? `1px solid ${borderColor}` : 'none',\n }}\n >\n {label}\n </td>\n <td\n style={{\n padding: '14px 20px',\n fontSize: 14,\n fontWeight: 600,\n textAlign: 'right',\n borderTop: index ? `1px solid ${borderColor}` : 'none',\n }}\n >\n {value}\n </td>\n </tr>\n ) : null\n )}\n </tbody>\n </table>\n )}\n\n <Button\n href={data.href}\n mode={mode}\n data-testid=\"view-owner-statement-button\"\n label={data.buttonText?.trim() || 'View statement'}\n themeColors={themeColors}\n style={{ marginTop: '24px', marginBottom: '32px' }}\n />\n\n {renewHref && (\n <div\n style={{\n padding: '20px',\n backgroundColor: '#f8f9fa',\n borderRadius: '8px',\n marginBottom: '32px',\n }}\n >\n <Text style={{ fontWeight: 600, margin: '0 0 4px' }}>\n Link expired?\n </Text>\n <Text style={{ color: mutedColor, fontSize: 14, margin: 0 }}>\n For your security, this link opens only this statement and works for\n 7 days. After that, request a new one and we'll email it to this\n address.\n </Text>\n <Button\n href={renewHref}\n mode={mode}\n data-testid=\"renew-owner-statement-link-button\"\n label=\"Send me a new link\"\n themeColors={themeColors}\n style={{\n background: '#ffffff',\n border: `1px solid ${themeColors[8]}`,\n color: themeColors[8],\n marginTop: '16px',\n marginBottom: 0,\n }}\n />\n </div>\n )}\n\n <div\n // biome-ignore lint/security/noDangerouslySetInnerHtml: values are escaped by parseEmailHtml\n dangerouslySetInnerHTML={{ __html: parse(data.bodyTwo) }}\n />\n </EmailContainer>\n );\n};\n"]}
|
package/package.json
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
|
+
import { Heading } from '@react-email/heading';
|
|
2
|
+
import { Text } from '@react-email/text';
|
|
1
3
|
import {
|
|
2
4
|
EMAIL_ACTION_LINK_COMPONENT,
|
|
3
5
|
EMAIL_DATE_COMPONENT,
|
|
4
6
|
EMAIL_LISTING_COMPONENT,
|
|
5
7
|
EMAIL_USER_NAME_COMPONENT,
|
|
6
8
|
} from '../extensions';
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
type ActionEmailTemplateProps,
|
|
9
|
+
import type {
|
|
10
|
+
ActionEmailData,
|
|
11
|
+
ActionEmailTemplateProps,
|
|
11
12
|
} from '../components/ActionEmailTemplate';
|
|
13
|
+
import { Button } from '../components/Button';
|
|
14
|
+
import { EmailContainer } from '../components/EmailContainer';
|
|
15
|
+
import { parseEmailHtml } from '../components/utils';
|
|
12
16
|
|
|
13
17
|
export const getDefaultOwnerStatementEmailData = (
|
|
14
18
|
mode: 'tag' | 'text',
|
|
@@ -18,6 +22,8 @@ export const getDefaultOwnerStatementEmailData = (
|
|
|
18
22
|
listingName: string;
|
|
19
23
|
userName: string;
|
|
20
24
|
month: string;
|
|
25
|
+
/** The owner opens the statement through an emailed link, without a login. */
|
|
26
|
+
noLogin?: boolean;
|
|
21
27
|
}
|
|
22
28
|
): ActionEmailData => {
|
|
23
29
|
const ownerStatementHref =
|
|
@@ -28,6 +34,18 @@ export const getDefaultOwnerStatementEmailData = (
|
|
|
28
34
|
const month = mode === 'tag' ? EMAIL_DATE_COMPONENT : args.month;
|
|
29
35
|
const userName = mode === 'tag' ? EMAIL_USER_NAME_COMPONENT : args.userName;
|
|
30
36
|
|
|
37
|
+
if (args.noLogin) {
|
|
38
|
+
return {
|
|
39
|
+
subject: `Your ${args.month} owner statement for ${args.listingName}`,
|
|
40
|
+
shortDescription: `Your ${args.month} statement for ${args.listingName} is ready. Open it with one click, no login needed.`,
|
|
41
|
+
header: 'Your owner statement is ready',
|
|
42
|
+
bodyOne: `<p>Hi ${userName},</p><p>${args.appName} published your ${month} owner statement for ${listingName}. Open it with the button below. You don't need a login.</p>`,
|
|
43
|
+
buttonText: 'View statement',
|
|
44
|
+
bodyTwo: `<p style="color:#737373;font-size:13px">If the button doesn't work, copy this link into your browser: ${ownerStatementHref}</p>`,
|
|
45
|
+
href: args.ownerStatementHref,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
31
49
|
return {
|
|
32
50
|
subject: 'Owner statement was published',
|
|
33
51
|
shortDescription: `An owner statement is ready for you. Log in to ${args.appName} now to view it.`,
|
|
@@ -39,8 +57,177 @@ export const getDefaultOwnerStatementEmailData = (
|
|
|
39
57
|
};
|
|
40
58
|
};
|
|
41
59
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
60
|
+
const mutedColor = '#737373';
|
|
61
|
+
const borderColor = '#e5e7eb';
|
|
62
|
+
|
|
63
|
+
export const OwnerStatementEmailTemplate = ({
|
|
64
|
+
data,
|
|
65
|
+
tenant,
|
|
66
|
+
themeColors,
|
|
67
|
+
mode,
|
|
68
|
+
user,
|
|
69
|
+
listing,
|
|
70
|
+
month,
|
|
71
|
+
unsubscribeHref,
|
|
72
|
+
renewHref,
|
|
73
|
+
}: ActionEmailTemplateProps & {
|
|
74
|
+
/** Requests a new no-login link once the emailed one has expired. */
|
|
75
|
+
renewHref?: string;
|
|
76
|
+
}) => {
|
|
77
|
+
const parse = (html: string) =>
|
|
78
|
+
parseEmailHtml(html, {
|
|
79
|
+
href: data.href,
|
|
80
|
+
userName: user.firstName || '',
|
|
81
|
+
date: month || '',
|
|
82
|
+
listingName: listing || '',
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<EmailContainer
|
|
87
|
+
title={data.subject}
|
|
88
|
+
shortDescription={data.shortDescription}
|
|
89
|
+
tenant={tenant}
|
|
90
|
+
mode={mode}
|
|
91
|
+
unsubscribeHref={unsubscribeHref}
|
|
92
|
+
>
|
|
93
|
+
<Text
|
|
94
|
+
style={{
|
|
95
|
+
color: themeColors[8],
|
|
96
|
+
fontSize: 12,
|
|
97
|
+
fontWeight: 600,
|
|
98
|
+
letterSpacing: '0.08em',
|
|
99
|
+
textTransform: 'uppercase',
|
|
100
|
+
margin: '0 0 8px',
|
|
101
|
+
}}
|
|
102
|
+
>
|
|
103
|
+
Owner statement
|
|
104
|
+
</Text>
|
|
105
|
+
<Heading
|
|
106
|
+
style={{
|
|
107
|
+
fontSize: 26,
|
|
108
|
+
fontWeight: 600,
|
|
109
|
+
lineHeight: '34px',
|
|
110
|
+
margin: '0 0 32px',
|
|
111
|
+
}}
|
|
112
|
+
>
|
|
113
|
+
{data.header?.trim() || 'Your owner statement is ready'}
|
|
114
|
+
</Heading>
|
|
115
|
+
|
|
116
|
+
{data.banner?.trim() && (
|
|
117
|
+
<Text
|
|
118
|
+
style={{
|
|
119
|
+
padding: '16px 20px',
|
|
120
|
+
backgroundColor: '#f8f9fa',
|
|
121
|
+
borderLeft: `3px solid ${themeColors[8]}`,
|
|
122
|
+
borderRadius: '4px',
|
|
123
|
+
margin: '0 0 32px',
|
|
124
|
+
whiteSpace: 'pre-line',
|
|
125
|
+
}}
|
|
126
|
+
>
|
|
127
|
+
{data.banner.trim()}
|
|
128
|
+
</Text>
|
|
129
|
+
)}
|
|
130
|
+
|
|
131
|
+
<div
|
|
132
|
+
// biome-ignore lint/security/noDangerouslySetInnerHtml: values are escaped by parseEmailHtml
|
|
133
|
+
dangerouslySetInnerHTML={{ __html: parse(data.bodyOne) }}
|
|
134
|
+
/>
|
|
135
|
+
|
|
136
|
+
{(listing || month) && (
|
|
137
|
+
<table
|
|
138
|
+
role="presentation"
|
|
139
|
+
cellPadding={0}
|
|
140
|
+
cellSpacing={0}
|
|
141
|
+
width="100%"
|
|
142
|
+
style={{
|
|
143
|
+
border: `1px solid ${borderColor}`,
|
|
144
|
+
borderRadius: '8px',
|
|
145
|
+
borderCollapse: 'separate',
|
|
146
|
+
margin: '24px 0 0',
|
|
147
|
+
}}
|
|
148
|
+
>
|
|
149
|
+
<tbody>
|
|
150
|
+
{[
|
|
151
|
+
['Property', listing],
|
|
152
|
+
['Statement', month],
|
|
153
|
+
].map(([label, value], index) =>
|
|
154
|
+
value ? (
|
|
155
|
+
<tr key={label}>
|
|
156
|
+
<td
|
|
157
|
+
style={{
|
|
158
|
+
padding: '14px 20px',
|
|
159
|
+
color: mutedColor,
|
|
160
|
+
fontSize: 14,
|
|
161
|
+
borderTop: index ? `1px solid ${borderColor}` : 'none',
|
|
162
|
+
}}
|
|
163
|
+
>
|
|
164
|
+
{label}
|
|
165
|
+
</td>
|
|
166
|
+
<td
|
|
167
|
+
style={{
|
|
168
|
+
padding: '14px 20px',
|
|
169
|
+
fontSize: 14,
|
|
170
|
+
fontWeight: 600,
|
|
171
|
+
textAlign: 'right',
|
|
172
|
+
borderTop: index ? `1px solid ${borderColor}` : 'none',
|
|
173
|
+
}}
|
|
174
|
+
>
|
|
175
|
+
{value}
|
|
176
|
+
</td>
|
|
177
|
+
</tr>
|
|
178
|
+
) : null
|
|
179
|
+
)}
|
|
180
|
+
</tbody>
|
|
181
|
+
</table>
|
|
182
|
+
)}
|
|
183
|
+
|
|
184
|
+
<Button
|
|
185
|
+
href={data.href}
|
|
186
|
+
mode={mode}
|
|
187
|
+
data-testid="view-owner-statement-button"
|
|
188
|
+
label={data.buttonText?.trim() || 'View statement'}
|
|
189
|
+
themeColors={themeColors}
|
|
190
|
+
style={{ marginTop: '24px', marginBottom: '32px' }}
|
|
191
|
+
/>
|
|
192
|
+
|
|
193
|
+
{renewHref && (
|
|
194
|
+
<div
|
|
195
|
+
style={{
|
|
196
|
+
padding: '20px',
|
|
197
|
+
backgroundColor: '#f8f9fa',
|
|
198
|
+
borderRadius: '8px',
|
|
199
|
+
marginBottom: '32px',
|
|
200
|
+
}}
|
|
201
|
+
>
|
|
202
|
+
<Text style={{ fontWeight: 600, margin: '0 0 4px' }}>
|
|
203
|
+
Link expired?
|
|
204
|
+
</Text>
|
|
205
|
+
<Text style={{ color: mutedColor, fontSize: 14, margin: 0 }}>
|
|
206
|
+
For your security, this link opens only this statement and works for
|
|
207
|
+
7 days. After that, request a new one and we'll email it to this
|
|
208
|
+
address.
|
|
209
|
+
</Text>
|
|
210
|
+
<Button
|
|
211
|
+
href={renewHref}
|
|
212
|
+
mode={mode}
|
|
213
|
+
data-testid="renew-owner-statement-link-button"
|
|
214
|
+
label="Send me a new link"
|
|
215
|
+
themeColors={themeColors}
|
|
216
|
+
style={{
|
|
217
|
+
background: '#ffffff',
|
|
218
|
+
border: `1px solid ${themeColors[8]}`,
|
|
219
|
+
color: themeColors[8],
|
|
220
|
+
marginTop: '16px',
|
|
221
|
+
marginBottom: 0,
|
|
222
|
+
}}
|
|
223
|
+
/>
|
|
224
|
+
</div>
|
|
225
|
+
)}
|
|
226
|
+
|
|
227
|
+
<div
|
|
228
|
+
// biome-ignore lint/security/noDangerouslySetInnerHtml: values are escaped by parseEmailHtml
|
|
229
|
+
dangerouslySetInnerHTML={{ __html: parse(data.bodyTwo) }}
|
|
230
|
+
/>
|
|
231
|
+
</EmailContainer>
|
|
232
|
+
);
|
|
46
233
|
};
|