Improve email UI

This commit is contained in:
MartinBraquet
2025-09-11 16:00:10 +02:00
parent d62447a12a
commit 41535a68be
8 changed files with 197 additions and 257 deletions

View File

@@ -29,6 +29,7 @@ export const sendNewMatchEmail = async (
react: (
<NewMatchEmail
onUser={lover.user}
email={privateUser.email}
matchedWithUser={matchedWithUser}
matchedLover={lover}
unsubscribeUrl={unsubscribeUrl}
@@ -67,6 +68,7 @@ export const sendNewMessageEmail = async (
toUser={toUser}
channelId={channelId}
unsubscribeUrl={unsubscribeUrl}
email={privateUser.email}
/>
),
})
@@ -82,6 +84,7 @@ export const sendNewMessageEmail = async (
toUser={toUser}
channelId={channelId}
unsubscribeUrl={unsubscribeUrl}
email={privateUser.email}
/>
),
})
@@ -109,6 +112,7 @@ export const sendNewEndorsementEmail = async (
onUser={onUser}
endorsementText={text}
unsubscribeUrl={unsubscribeUrl}
email={privateUser.email}
/>
),
})

View File

@@ -37,7 +37,7 @@ const getResend = () => {
if (resend) return resend
const apiKey = process.env.RESEND_KEY as string
console.log(`RESEND_KEY: ${apiKey}`)
// console.log(`RESEND_KEY: ${apiKey}`)
resend = new Resend(apiKey)
return resend
}

View File

@@ -1,41 +1,31 @@
import {
Body,
Button,
Container,
Column,
Head,
Html,
Img,
Link,
Preview,
Row,
Section,
Text,
} from '@react-email/components'
import { type User } from 'common/user'
import { DOMAIN } from 'common/envs/constants'
import { jamesUser, sinclairUser } from './functions/mock'
import {Body, Button, Column, Container, Head, Html, Preview, Row, Section, Text,} from '@react-email/components'
import {type User} from 'common/user'
import {DOMAIN} from 'common/envs/constants'
import {jamesUser, sinclairUser} from './functions/mock'
import {button, container, content, Footer, main, paragraph} from "email/utils";
interface NewEndorsementEmailProps {
fromUser: User
onUser: User
endorsementText: string
unsubscribeUrl: string
email?: string
}
export const NewEndorsementEmail = ({
fromUser,
onUser,
endorsementText,
unsubscribeUrl,
}: NewEndorsementEmailProps) => {
fromUser,
onUser,
endorsementText,
unsubscribeUrl,
email,
}: NewEndorsementEmailProps) => {
const name = onUser.name.split(' ')[0]
const endorsementUrl = `https://${DOMAIN}/${onUser.username}`
return (
<Html>
<Head />
<Head/>
<Preview>New endorsement from {fromUser.name}</Preview>
<Body style={main}>
<Container style={container}>
@@ -55,15 +45,15 @@ export const NewEndorsementEmail = ({
<Section style={endorsementContainer}>
<Row>
<Column>
<Img
src={fromUser.avatarUrl}
width="50"
height="50"
alt=""
style={avatarImage}
/>
</Column>
{/*<Column>*/}
{/* <Img*/}
{/* src={fromUser.avatarUrl}*/}
{/* width="50"*/}
{/* height="50"*/}
{/* alt=""*/}
{/* style={avatarImage}*/}
{/* />*/}
{/*</Column>*/}
<Column>
<Text style={endorsementTextStyle}>"{endorsementText}"</Text>
</Column>
@@ -75,15 +65,7 @@ export const NewEndorsementEmail = ({
</Section>
</Section>
<Section style={footer}>
<Text style={footerText}>
This e-mail has been sent to {name},{' '}
{/* <Link href={unsubscribeUrl} style={footerLink}>
click here to unsubscribe from this type of notification
</Link>
. */}
</Text>
</Section>
<Footer unsubscribeUrl={unsubscribeUrl} email={email ?? name}/>
</Container>
</Body>
</Html>
@@ -96,37 +78,9 @@ NewEndorsementEmail.PreviewProps = {
endorsementText:
"Sinclair is someone you want to have around because she injects creativity and humor into every conversation, and her laugh is infectious! Not to mention that she's a great employee, treats everyone with respect, and is even-tempered.",
unsubscribeUrl: 'https://compassmeet.com/unsubscribe',
email: 'someone@gmail.com',
} as NewEndorsementEmailProps
const main = {
backgroundColor: '#f4f4f4',
fontFamily: 'Arial, sans-serif',
wordSpacing: 'normal',
}
const container = {
margin: '0 auto',
maxWidth: '600px',
}
const logoContainer = {
padding: '20px 0px 5px 0px',
textAlign: 'center' as const,
backgroundColor: '#ffffff',
}
const content = {
backgroundColor: '#ffffff',
padding: '20px 25px',
}
const paragraph = {
fontSize: '18px',
lineHeight: '24px',
margin: '10px 0',
color: '#000000',
fontFamily: 'Arial, Helvetica, sans-serif',
}
const endorsementContainer = {
margin: '20px 0',
@@ -135,10 +89,6 @@ const endorsementContainer = {
borderRadius: '8px',
}
const avatarImage = {
borderRadius: '50%',
}
const endorsementTextStyle = {
fontSize: '16px',
lineHeight: '22px',
@@ -146,35 +96,4 @@ const endorsementTextStyle = {
color: '#333333',
}
const button = {
backgroundColor: '#4887ec',
borderRadius: '12px',
color: '#ffffff',
fontFamily: 'Helvetica, Arial, sans-serif',
fontSize: '16px',
fontWeight: 'semibold',
textDecoration: 'none',
textAlign: 'center' as const,
display: 'inline-block',
padding: '6px 10px',
margin: '10px 0',
}
const footer = {
margin: '20px 0',
textAlign: 'center' as const,
}
const footerText = {
fontSize: '11px',
lineHeight: '22px',
color: '#000000',
fontFamily: 'Ubuntu, Helvetica, Arial, sans-serif',
}
const footerLink = {
color: 'inherit',
textDecoration: 'none',
}
export default NewEndorsementEmail

View File

@@ -1,51 +1,43 @@
import {
Body,
Button,
Container,
Head,
Html,
Img,
Link,
Preview,
Section,
Text,
} from '@react-email/components'
import { DOMAIN } from 'common/envs/constants'
import { type LoverRow } from 'common/love/lover'
import { getLoveOgImageUrl } from 'common/love/og-image'
import { type User } from 'common/user'
import { jamesLover, jamesUser, sinclairUser } from './functions/mock'
import {Body, Button, Container, Head, Html, Preview, Section, Text,} from '@react-email/components'
import {DOMAIN} from 'common/envs/constants'
import {type LoverRow} from 'common/love/lover'
import {type User} from 'common/user'
import {jamesLover, jamesUser, sinclairUser} from './functions/mock'
import {Footer} from "email/utils";
interface NewMatchEmailProps {
onUser: User
matchedWithUser: User
matchedLover: LoverRow
unsubscribeUrl: string
email?: string
}
export const NewMatchEmail = ({
onUser,
matchedWithUser,
matchedLover,
unsubscribeUrl,
}: NewMatchEmailProps) => {
onUser,
matchedWithUser,
matchedLover,
unsubscribeUrl,
email
}: NewMatchEmailProps) => {
const name = onUser.name.split(' ')[0]
const userImgSrc = getLoveOgImageUrl(matchedWithUser, matchedLover)
// const userImgSrc = getLoveOgImageUrl(matchedWithUser, matchedLover)
const userUrl = `https://${DOMAIN}/${matchedWithUser.username}`
return (
<Html>
<Head />
<Head/>
<Preview>You have a new match!</Preview>
<Body style={main}>
<Container style={container}>
{/*<Section style={logoContainer}>*/}
{/* <Img*/}
{/* src="..."*/}
{/* width="550"*/}
{/* height="auto"*/}
{/* alt="compassmeet.com"*/}
{/* />*/}
{/*<Img*/}
{/* src="..."*/}
{/* width="550"*/}
{/* height="auto"*/}
{/* alt="compassmeet.com"*/}
{/*/>*/}
{/*</Section>*/}
<Section style={content}>
@@ -56,31 +48,21 @@ export const NewMatchEmail = ({
</Text>
<Section style={imageContainer}>
<Link href={userUrl}>
<Img
src={userImgSrc}
width="375"
height="200"
alt=""
style={profileImage}
/>
</Link>
{/*<Link href={userUrl}>*/}
{/* <Img*/}
{/* src={userImgSrc}*/}
{/* width="375"*/}
{/* height="200"*/}
{/* alt=""*/}
{/* style={profileImage}*/}
{/* />*/}
{/*</Link>*/}
<Button href={userUrl} style={button}>
View profile
</Button>
</Section>
</Section>
<Section style={footer}>
<Text style={footerText}>
This e-mail has been sent to {name},{' '}
{/* <Link href={unsubscribeUrl} style={footerLink}>
click here to unsubscribe from this type of notification
</Link>
. */}
</Text>
</Section>
<Footer unsubscribeUrl={unsubscribeUrl} email={email ?? name}/>
</Container>
</Body>
</Html>
@@ -91,11 +73,12 @@ NewMatchEmail.PreviewProps = {
onUser: sinclairUser,
matchedWithUser: jamesUser,
matchedLover: jamesLover,
email: 'someone@gmail.com',
unsubscribeUrl: 'https://compassmeet.com/unsubscribe',
} as NewMatchEmailProps
const main = {
backgroundColor: '#f4f4f4',
// backgroundColor: '#f4f4f4',
fontFamily: 'Arial, sans-serif',
wordSpacing: 'normal',
}
@@ -147,21 +130,4 @@ const button = {
margin: '10px 0',
}
const footer = {
margin: '20px 0',
textAlign: 'center' as const,
}
const footerText = {
fontSize: '11px',
lineHeight: '22px',
color: '#000000',
fontFamily: 'Ubuntu, Helvetica, Arial, sans-serif',
}
const footerLink = {
color: 'inherit',
textDecoration: 'none',
}
export default NewMatchEmail

View File

@@ -20,6 +20,7 @@ import {
} from './functions/mock'
import { DOMAIN } from 'common/envs/constants'
import { getLoveOgImageUrl } from 'common/love/og-image'
import {button, container, content, Footer, imageContainer, main, paragraph, profileImage} from "email/utils";
interface NewMessageEmailProps {
fromUser: User
@@ -27,6 +28,7 @@ interface NewMessageEmailProps {
toUser: User
channelId: number
unsubscribeUrl: string
email?: string
}
export const NewMessageEmail = ({
@@ -35,6 +37,7 @@ export const NewMessageEmail = ({
toUser,
channelId,
unsubscribeUrl,
email,
}: NewMessageEmailProps) => {
const name = toUser.name.split(' ')[0]
const creatorName = fromUser.name
@@ -62,15 +65,15 @@ export const NewMessageEmail = ({
<Text style={paragraph}>{creatorName} just messaged you!</Text>
<Section style={imageContainer}>
<Link href={messagesUrl}>
<Img
src={userImgSrc}
width="375"
height="200"
alt={`${creatorName}'s profile`}
style={profileImage}
/>
</Link>
{/*<Link href={messagesUrl}>*/}
{/* <Img*/}
{/* src={userImgSrc}*/}
{/* width="375"*/}
{/* height="200"*/}
{/* alt={`${creatorName}'s profile`}*/}
{/* style={profileImage}*/}
{/* />*/}
{/*</Link>*/}
<Button href={messagesUrl} style={button}>
View message
@@ -78,15 +81,7 @@ export const NewMessageEmail = ({
</Section>
</Section>
<Section style={footer}>
<Text style={footerText}>
This e-mail has been sent to {name},{' '}
{/* <Link href={unsubscribeUrl} style={{ color: 'inherit', textDecoration: 'none' }}>
click here to unsubscribe from this type of notification
</Link>
. */}
</Text>
</Section>
<Footer unsubscribeUrl={unsubscribeUrl} email={email ?? name}/>
</Container>
</Body>
</Html>
@@ -98,72 +93,9 @@ NewMessageEmail.PreviewProps = {
fromUserLover: jamesLover,
toUser: sinclairUser,
channelId: 1,
email: 'someone@gmail.com',
unsubscribeUrl: 'https://compassmeet.com/unsubscribe',
} as NewMessageEmailProps
const main = {
backgroundColor: '#f4f4f4',
fontFamily: 'Arial, sans-serif',
wordSpacing: 'normal',
}
const container = {
margin: '0 auto',
maxWidth: '600px',
}
const logoContainer = {
padding: '20px 0px 5px 0px',
textAlign: 'center' as const,
backgroundColor: '#ffffff',
}
const content = {
backgroundColor: '#ffffff',
padding: '20px 25px',
}
const paragraph = {
fontSize: '18px',
lineHeight: '24px',
margin: '10px 0',
color: '#000000',
fontFamily: 'Arial, Helvetica, sans-serif',
}
const imageContainer = {
textAlign: 'center' as const,
margin: '20px 0',
}
const profileImage = {
// border: '1px solid #ec489a',
}
const button = {
backgroundColor: '#4887ec',
borderRadius: '12px',
color: '#ffffff',
fontFamily: 'Helvetica, Arial, sans-serif',
fontSize: '16px',
fontWeight: 'semibold',
textDecoration: 'none',
textAlign: 'center' as const,
display: 'inline-block',
padding: '6px 10px',
margin: '10px 0',
}
const footer = {
margin: '20px 0',
textAlign: 'center' as const,
}
const footerText = {
fontSize: '11px',
lineHeight: '22px',
color: '#000000',
fontFamily: 'Ubuntu, Helvetica, Arial, sans-serif',
}
export default NewMessageEmail

View File

@@ -16,7 +16,7 @@ export const Test = (props: { name: string }) => {
}
Test.PreviewProps = {
name: 'Clarity',
name: 'Friend',
}
export default Test

View File

@@ -0,0 +1,118 @@
import {Link, Row, Section, Text} from "@react-email/components";
import {TbBrandDiscord, TbBrandGithub, TbBrandPatreon, TbBrandPaypal} from "react-icons/tb";
interface Props {
email?: string
unsubscribeUrl: string
}
export const Footer = ({
email,
unsubscribeUrl,
}: Props) => {
return <Section style={footer}>
<hr style={{border: 'none', borderTop: '1px solid #e0e0e0', margin: '20px 0'}}/>
<Row>
<Text style={footerText}>
Compass © {new Date().getFullYear()}
</Text>
<Row>
<Link href="https://github.com/CompassMeet/Compass">
<TbBrandGithub size={36} color={'black'}/>
</Link>
<Link href="https://discord.gg/8Vd7jzqjun">
<TbBrandDiscord size={36} color={'black'}/>
</Link>
<Link href="https://patreon.com/CompassMeet">
<TbBrandPatreon size={36} color={'black'}/>
</Link>
<Link href="https://www.paypal.com/paypalme/MartinBraquet">
<TbBrandPaypal size={36} color={'black'}/>
</Link>
</Row>
<Text style={footerText}>
The email was sent to {email}. To no longer receive these emails, unsubscribe {' '}
<Link href={unsubscribeUrl}>
here
</Link>
.
</Text>
</Row>
</Section>
}
export const footer = {
margin: '20px 0',
textAlign: 'center' as const,
}
export const footerText = {
fontSize: '11px',
lineHeight: '22px',
color: '#000000',
fontFamily: 'Ubuntu, Helvetica, Arial, sans-serif',
}
export const blackLinks = {
color: 'black'
}
// const footerLink = {
// color: 'inherit',
// textDecoration: 'none',
// }
export const main = {
// backgroundColor: '#f4f4f4',
fontFamily: 'Arial, sans-serif',
wordSpacing: 'normal',
}
export const container = {
margin: '0 auto',
maxWidth: '600px',
}
export const logoContainer = {
padding: '20px 0px 5px 0px',
textAlign: 'center' as const,
backgroundColor: '#ffffff',
}
export const content = {
backgroundColor: '#ffffff',
padding: '20px 25px',
}
export const paragraph = {
fontSize: '18px',
lineHeight: '24px',
margin: '10px 0',
color: '#000000',
fontFamily: 'Arial, Helvetica, sans-serif',
}
export const imageContainer = {
textAlign: 'center' as const,
margin: '20px 0',
}
export const profileImage = {
// border: '1px solid #ec489a',
}
export const button = {
backgroundColor: '#4887ec',
borderRadius: '12px',
color: '#ffffff',
fontFamily: 'Helvetica, Arial, sans-serif',
fontSize: '16px',
fontWeight: 'semibold',
textDecoration: 'none',
textAlign: 'center' as const,
display: 'inline-block',
padding: '6px 10px',
margin: '10px 0',
}

View File

@@ -11,6 +11,7 @@
"react": "19.0.0",
"react-dom": "19.0.0",
"react-email": "3.0.7",
"react-icons": "5.5.0",
"resend": "4.1.2"
},
"devDependencies": {