@vrplatform/email 1.0.2-stage.39634972675 → 1.0.2-stage.39762444931
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 +0 -2
- package/build/main/templates/OwnerStatementEmailTemplate.js +14 -23
- package/build/main/templates/OwnerStatementEmailTemplate.js.map +1 -1
- package/build/module/templates/OwnerStatementEmailTemplate.d.ts +0 -2
- package/build/module/templates/OwnerStatementEmailTemplate.js +14 -23
- package/build/module/templates/OwnerStatementEmailTemplate.js.map +1 -1
- package/package.json +1 -1
- package/src/templates/OwnerStatementEmailTemplate.tsx +16 -28
|
@@ -5,8 +5,6 @@ export declare const getDefaultOwnerStatementEmailData: (mode: "tag" | "text", a
|
|
|
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;
|
|
10
8
|
}) => ActionEmailData;
|
|
11
9
|
export declare const OwnerStatementEmailTemplate: ({ data, tenant, themeColors, mode, user, listing, month, unsubscribeHref, renewHref, }: ActionEmailTemplateProps & {
|
|
12
10
|
/** Requests a new no-login link once the emailed one has expired. */
|
|
@@ -13,30 +13,21 @@ const getDefaultOwnerStatementEmailData = (mode, args) => {
|
|
|
13
13
|
const listingName = mode === 'tag' ? extensions_1.EMAIL_LISTING_COMPONENT : args.listingName;
|
|
14
14
|
const month = mode === 'tag' ? extensions_1.EMAIL_DATE_COMPONENT : args.month;
|
|
15
15
|
const userName = mode === 'tag' ? extensions_1.EMAIL_USER_NAME_COMPONENT : args.userName;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
subject: mode === 'tag'
|
|
21
|
-
? 'Your owner statement is ready'
|
|
22
|
-
: `Your ${args.month} owner statement for ${args.listingName}`,
|
|
23
|
-
shortDescription: mode === 'tag'
|
|
24
|
-
? 'Your owner statement is ready. Open it with one click, no login needed.'
|
|
25
|
-
: `Your ${args.month} statement for ${args.listingName} is ready. Open it with one click, no login needed.`,
|
|
26
|
-
header: 'Your owner statement is ready',
|
|
27
|
-
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>`,
|
|
28
|
-
buttonText: 'View statement',
|
|
29
|
-
bodyTwo: `<p style="color:#737373;font-size:13px">If the button doesn't work, copy this link into your browser: ${ownerStatementHref}</p>`,
|
|
30
|
-
href: args.ownerStatementHref,
|
|
31
|
-
};
|
|
32
|
-
}
|
|
16
|
+
// Owners open the statement by link without a login and viewers log in to
|
|
17
|
+
// the owner portal, so the text names neither. Subject and preview text are
|
|
18
|
+
// plain text without tokens, so a saved template must not keep the editor's
|
|
19
|
+
// sample month and listing.
|
|
33
20
|
return {
|
|
34
|
-
subject:
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
21
|
+
subject: mode === 'tag'
|
|
22
|
+
? 'Your owner statement is ready'
|
|
23
|
+
: `Your ${args.month} owner statement for ${args.listingName}`,
|
|
24
|
+
shortDescription: mode === 'tag'
|
|
25
|
+
? 'Your owner statement is ready to view.'
|
|
26
|
+
: `Your ${args.month} statement for ${args.listingName} is ready to view.`,
|
|
27
|
+
header: 'Your owner statement is ready',
|
|
28
|
+
bodyOne: `<p>Hi ${userName},</p><p>${args.appName} published your ${month} owner statement for ${listingName}. Open it with the button below.</p>`,
|
|
29
|
+
buttonText: 'View statement',
|
|
30
|
+
bodyTwo: `<p style="color:#737373;font-size:13px">If the button doesn't work, copy this link into your browser: ${ownerStatementHref}</p>`,
|
|
40
31
|
href: args.ownerStatementHref,
|
|
41
32
|
};
|
|
42
33
|
};
|
|
@@ -1 +1 @@
|
|
|
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 // Subject and preview text are plain text without tokens, so a saved\n // template must not keep the editor's sample month and listing.\n return {\n subject:\n mode === 'tag'\n ? 'Your owner statement is ready'\n : `Your ${args.month} owner statement for ${args.listingName}`,\n shortDescription:\n mode === 'tag'\n ? 'Your owner statement is ready. Open it with one click, no login needed.'\n : `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
|
+
{"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 }\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 // Owners open the statement by link without a login and viewers log in to\n // the owner portal, so the text names neither. Subject and preview text are\n // plain text without tokens, so a saved template must not keep the editor's\n // sample month and listing.\n return {\n subject:\n mode === 'tag'\n ? 'Your owner statement is ready'\n : `Your ${args.month} owner statement for ${args.listingName}`,\n shortDescription:\n mode === 'tag'\n ? 'Your owner statement is ready to view.'\n : `Your ${args.month} statement for ${args.listingName} is ready to view.`,\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.</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\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"]}
|
|
@@ -5,8 +5,6 @@ export declare const getDefaultOwnerStatementEmailData: (mode: "tag" | "text", a
|
|
|
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;
|
|
10
8
|
}) => ActionEmailData;
|
|
11
9
|
export declare const OwnerStatementEmailTemplate: ({ data, tenant, themeColors, mode, user, listing, month, unsubscribeHref, renewHref, }: ActionEmailTemplateProps & {
|
|
12
10
|
/** Requests a new no-login link once the emailed one has expired. */
|
|
@@ -10,30 +10,21 @@ export const getDefaultOwnerStatementEmailData = (mode, args) => {
|
|
|
10
10
|
const listingName = mode === 'tag' ? EMAIL_LISTING_COMPONENT : args.listingName;
|
|
11
11
|
const month = mode === 'tag' ? EMAIL_DATE_COMPONENT : args.month;
|
|
12
12
|
const userName = mode === 'tag' ? EMAIL_USER_NAME_COMPONENT : args.userName;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
subject: mode === 'tag'
|
|
18
|
-
? 'Your owner statement is ready'
|
|
19
|
-
: `Your ${args.month} owner statement for ${args.listingName}`,
|
|
20
|
-
shortDescription: mode === 'tag'
|
|
21
|
-
? 'Your owner statement is ready. Open it with one click, no login needed.'
|
|
22
|
-
: `Your ${args.month} statement for ${args.listingName} is ready. Open it with one click, no login needed.`,
|
|
23
|
-
header: 'Your owner statement is ready',
|
|
24
|
-
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>`,
|
|
25
|
-
buttonText: 'View statement',
|
|
26
|
-
bodyTwo: `<p style="color:#737373;font-size:13px">If the button doesn't work, copy this link into your browser: ${ownerStatementHref}</p>`,
|
|
27
|
-
href: args.ownerStatementHref,
|
|
28
|
-
};
|
|
29
|
-
}
|
|
13
|
+
// Owners open the statement by link without a login and viewers log in to
|
|
14
|
+
// the owner portal, so the text names neither. Subject and preview text are
|
|
15
|
+
// plain text without tokens, so a saved template must not keep the editor's
|
|
16
|
+
// sample month and listing.
|
|
30
17
|
return {
|
|
31
|
-
subject:
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
18
|
+
subject: mode === 'tag'
|
|
19
|
+
? 'Your owner statement is ready'
|
|
20
|
+
: `Your ${args.month} owner statement for ${args.listingName}`,
|
|
21
|
+
shortDescription: mode === 'tag'
|
|
22
|
+
? 'Your owner statement is ready to view.'
|
|
23
|
+
: `Your ${args.month} statement for ${args.listingName} is ready to view.`,
|
|
24
|
+
header: 'Your owner statement is ready',
|
|
25
|
+
bodyOne: `<p>Hi ${userName},</p><p>${args.appName} published your ${month} owner statement for ${listingName}. Open it with the button below.</p>`,
|
|
26
|
+
buttonText: 'View statement',
|
|
27
|
+
bodyTwo: `<p style="color:#737373;font-size:13px">If the button doesn't work, copy this link into your browser: ${ownerStatementHref}</p>`,
|
|
37
28
|
href: args.ownerStatementHref,
|
|
38
29
|
};
|
|
39
30
|
};
|
|
@@ -1 +1 @@
|
|
|
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 // Subject and preview text are plain text without tokens, so a saved\n // template must not keep the editor's sample month and listing.\n return {\n subject:\n mode === 'tag'\n ? 'Your owner statement is ready'\n : `Your ${args.month} owner statement for ${args.listingName}`,\n shortDescription:\n mode === 'tag'\n ? 'Your owner statement is ready. Open it with one click, no login needed.'\n : `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
|
+
{"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 }\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 // Owners open the statement by link without a login and viewers log in to\n // the owner portal, so the text names neither. Subject and preview text are\n // plain text without tokens, so a saved template must not keep the editor's\n // sample month and listing.\n return {\n subject:\n mode === 'tag'\n ? 'Your owner statement is ready'\n : `Your ${args.month} owner statement for ${args.listingName}`,\n shortDescription:\n mode === 'tag'\n ? 'Your owner statement is ready to view.'\n : `Your ${args.month} statement for ${args.listingName} is ready to view.`,\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.</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\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
|
@@ -22,8 +22,6 @@ export const getDefaultOwnerStatementEmailData = (
|
|
|
22
22
|
listingName: string;
|
|
23
23
|
userName: string;
|
|
24
24
|
month: string;
|
|
25
|
-
/** The owner opens the statement through an emailed link, without a login. */
|
|
26
|
-
noLogin?: boolean;
|
|
27
25
|
}
|
|
28
26
|
): ActionEmailData => {
|
|
29
27
|
const ownerStatementHref =
|
|
@@ -34,33 +32,23 @@ export const getDefaultOwnerStatementEmailData = (
|
|
|
34
32
|
const month = mode === 'tag' ? EMAIL_DATE_COMPONENT : args.month;
|
|
35
33
|
const userName = mode === 'tag' ? EMAIL_USER_NAME_COMPONENT : args.userName;
|
|
36
34
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
subject:
|
|
42
|
-
mode === 'tag'
|
|
43
|
-
? 'Your owner statement is ready'
|
|
44
|
-
: `Your ${args.month} owner statement for ${args.listingName}`,
|
|
45
|
-
shortDescription:
|
|
46
|
-
mode === 'tag'
|
|
47
|
-
? 'Your owner statement is ready. Open it with one click, no login needed.'
|
|
48
|
-
: `Your ${args.month} statement for ${args.listingName} is ready. Open it with one click, no login needed.`,
|
|
49
|
-
header: 'Your owner statement is ready',
|
|
50
|
-
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>`,
|
|
51
|
-
buttonText: 'View statement',
|
|
52
|
-
bodyTwo: `<p style="color:#737373;font-size:13px">If the button doesn't work, copy this link into your browser: ${ownerStatementHref}</p>`,
|
|
53
|
-
href: args.ownerStatementHref,
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
|
|
35
|
+
// Owners open the statement by link without a login and viewers log in to
|
|
36
|
+
// the owner portal, so the text names neither. Subject and preview text are
|
|
37
|
+
// plain text without tokens, so a saved template must not keep the editor's
|
|
38
|
+
// sample month and listing.
|
|
57
39
|
return {
|
|
58
|
-
subject:
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
40
|
+
subject:
|
|
41
|
+
mode === 'tag'
|
|
42
|
+
? 'Your owner statement is ready'
|
|
43
|
+
: `Your ${args.month} owner statement for ${args.listingName}`,
|
|
44
|
+
shortDescription:
|
|
45
|
+
mode === 'tag'
|
|
46
|
+
? 'Your owner statement is ready to view.'
|
|
47
|
+
: `Your ${args.month} statement for ${args.listingName} is ready to view.`,
|
|
48
|
+
header: 'Your owner statement is ready',
|
|
49
|
+
bodyOne: `<p>Hi ${userName},</p><p>${args.appName} published your ${month} owner statement for ${listingName}. Open it with the button below.</p>`,
|
|
50
|
+
buttonText: 'View statement',
|
|
51
|
+
bodyTwo: `<p style="color:#737373;font-size:13px">If the button doesn't work, copy this link into your browser: ${ownerStatementHref}</p>`,
|
|
64
52
|
href: args.ownerStatementHref,
|
|
65
53
|
};
|
|
66
54
|
};
|