246 lines
8.7 KiB
TypeScript
246 lines
8.7 KiB
TypeScript
import type { ReactNode } from 'react'
|
|
import {
|
|
Html,
|
|
Head,
|
|
Body,
|
|
Container,
|
|
Section,
|
|
Text,
|
|
Heading,
|
|
Hr,
|
|
Img,
|
|
Preview,
|
|
Link,
|
|
Row,
|
|
Column,
|
|
} from '@react-email/components'
|
|
import type { Brand } from './types'
|
|
|
|
type EmailShellProps = {
|
|
brand: Brand
|
|
title: string
|
|
previewText: string
|
|
children: ReactNode
|
|
}
|
|
|
|
const DEFAULT_LOGO_PLACEHOLDER =
|
|
'https://dummyimage.com/120x40/0f172a/ffffff&text=Shitaye'
|
|
|
|
function IconMail() {
|
|
return (
|
|
<svg width="16" height="16" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
|
|
<path
|
|
fill="currentColor"
|
|
d="M20 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4-8 5-8-5V6l8 5 8-5v2z"
|
|
/>
|
|
</svg>
|
|
)
|
|
}
|
|
|
|
function IconPhone() {
|
|
return (
|
|
<svg width="16" height="16" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
|
|
<path
|
|
fill="currentColor"
|
|
d="M6.6 10.8c1.5 2.9 3.9 5.3 6.8 6.8l2.2-2.2c.3-.3.8-.4 1.2-.2 1.3.4 2.7.7 4.1.7.6 0 1 .4 1 1V21c0 .6-.4 1-1 1C10.1 22 2 13.9 2 4c0-.6.4-1 1-1h3.9c.6 0 1 .4 1 1 0 1.4.2 2.8.7 4.1.1.4 0 .9-.2 1.2L6.6 10.8z"
|
|
/>
|
|
</svg>
|
|
)
|
|
}
|
|
|
|
function ContactLine({
|
|
icon,
|
|
children,
|
|
}: {
|
|
icon: ReactNode
|
|
children: ReactNode
|
|
}) {
|
|
return (
|
|
<Row style={{ margin: '0 0 8px' }}>
|
|
<Column style={{ width: 24, paddingRight: 8 }}>
|
|
<Text style={{ margin: 0, color: 'inherit', display: 'block' }}>{icon}</Text>
|
|
</Column>
|
|
<Column style={{ width: 'auto' }}>{children}</Column>
|
|
</Row>
|
|
)
|
|
}
|
|
|
|
export function EmailShell({ brand, title, previewText, children }: EmailShellProps) {
|
|
const logoUrl = brand.logoUrl?.trim() ? brand.logoUrl.trim() : DEFAULT_LOGO_PLACEHOLDER
|
|
|
|
return (
|
|
<Html>
|
|
<Head />
|
|
<Preview>{previewText}</Preview>
|
|
<Body style={{ margin: '0', padding: '0', backgroundColor: brand.backgroundColor || '#f8fafc' }}>
|
|
<Container
|
|
style={{
|
|
maxWidth: 560,
|
|
width: '100%',
|
|
margin: '0 auto',
|
|
padding: '0 16px',
|
|
fontFamily:
|
|
'ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, "Apple Color Emoji", "Segoe UI Emoji"',
|
|
}}
|
|
>
|
|
<Section style={{ padding: '24px 0 18px', borderBottom: `1px solid ${brand.secondaryColor}` }}>
|
|
<Img
|
|
src={logoUrl}
|
|
width={120}
|
|
height={40}
|
|
alt={brand.hotelName}
|
|
style={{ objectFit: 'contain', display: 'block', margin: '0 0 10px' }}
|
|
/>
|
|
<Heading style={{ fontSize: 20, margin: '0', color: brand.textColor }}>{brand.hotelName}</Heading>
|
|
<Text style={{ margin: '6px 0 0', color: brand.textColor, opacity: 0.9 }}>{title}</Text>
|
|
</Section>
|
|
|
|
<Section style={{ padding: '22px 0' }}>{children}</Section>
|
|
|
|
<Hr style={{ borderColor: brand.secondaryColor, opacity: 0.2 }} />
|
|
<Section style={{ padding: '18px 0 28px' }}>
|
|
<Section
|
|
style={{
|
|
border: `1px solid ${brand.secondaryColor}`,
|
|
borderRadius: 12,
|
|
padding: 14,
|
|
backgroundColor: 'rgba(255,255,255,0.55)',
|
|
}}
|
|
>
|
|
{brand.footer.address ? (
|
|
<Text style={{ margin: 0, color: brand.textColor, fontSize: 12, lineHeight: '18px' }}>
|
|
{brand.footer.address}
|
|
</Text>
|
|
) : null}
|
|
|
|
{brand.footer.email ? (
|
|
<ContactLine icon={<IconMail />}>
|
|
<Text style={{ margin: 0, color: brand.textColor, fontSize: 12, lineHeight: '18px' }}>
|
|
<Link
|
|
href={`mailto:${brand.footer.email}`}
|
|
style={{ color: brand.primaryColor, textDecoration: 'none' }}
|
|
>
|
|
{brand.footer.email}
|
|
</Link>
|
|
</Text>
|
|
</ContactLine>
|
|
) : null}
|
|
|
|
{brand.footer.phone1 || brand.footer.phone2 ? (
|
|
<ContactLine icon={<IconPhone />}>
|
|
<Text style={{ margin: 0, color: brand.textColor, fontSize: 12, lineHeight: '18px' }}>
|
|
{brand.footer.phone1 ? brand.footer.phone1 : ''}
|
|
{brand.footer.phone1 && brand.footer.phone2 ? ' · ' : ''}
|
|
{brand.footer.phone2 ? brand.footer.phone2 : ''}
|
|
</Text>
|
|
</ContactLine>
|
|
) : null}
|
|
</Section>
|
|
|
|
<Section style={{ margin: '14px 0 0', padding: 0 }}>
|
|
<Text style={{ margin: '0 0 8px', color: brand.textColor, fontSize: 12, opacity: 0.85, lineHeight: '18px' }}>
|
|
Follow us
|
|
</Text>
|
|
<Link
|
|
href={brand.footer.socialFacebookUrl || '#'}
|
|
style={{
|
|
display: 'inline-block',
|
|
marginRight: 8,
|
|
marginBottom: 8,
|
|
padding: '8px 12px',
|
|
borderRadius: 999,
|
|
backgroundColor: brand.primaryColor,
|
|
color: '#ffffff',
|
|
textDecoration: 'none',
|
|
fontSize: 12,
|
|
fontWeight: 700,
|
|
}}
|
|
>
|
|
<svg width="14" height="14" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
|
|
<path
|
|
fill="#ffffff"
|
|
d="M14.5 3H17v3.2h-2.3c-.9 0-1.2.4-1.2 1.1V10H17l-.5 3.3h-3v7.7H10.3v-7.7H7.9V10h2.4V8c0-2.2 1.1-5 4.2-5z"
|
|
/>
|
|
</svg>
|
|
</Link>
|
|
<Link
|
|
href={brand.footer.socialInstagramUrl || '#'}
|
|
style={{
|
|
display: 'inline-block',
|
|
marginRight: 8,
|
|
marginBottom: 8,
|
|
padding: '8px 12px',
|
|
borderRadius: 999,
|
|
backgroundColor: brand.primaryColor,
|
|
color: '#ffffff',
|
|
textDecoration: 'none',
|
|
fontSize: 12,
|
|
fontWeight: 700,
|
|
}}
|
|
>
|
|
<svg width="14" height="14" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
|
|
<path
|
|
fill="#ffffff"
|
|
d="M7 2h10a5 5 0 0 1 5 5v10a5 5 0 0 1-5 5H7a5 5 0 0 1-5-5V7a5 5 0 0 1 5-5zm5 5.7A3.3 3.3 0 1 0 15.3 11 3.3 3.3 0 0 0 12 7.7zm6.2-.9a1 1 0 1 0 0 .1zM12 9a2 2 0 1 1-2 2 2 2 0 0 1 2-2z"
|
|
/>
|
|
<path
|
|
fill="#ffffff"
|
|
d="M17.5 2.7h.1"
|
|
opacity="0"
|
|
/>
|
|
</svg>
|
|
</Link>
|
|
<Link
|
|
href={brand.footer.socialTwitterUrl || '#'}
|
|
style={{
|
|
display: 'inline-block',
|
|
marginRight: 8,
|
|
marginBottom: 8,
|
|
padding: '8px 12px',
|
|
borderRadius: 999,
|
|
backgroundColor: brand.primaryColor,
|
|
color: '#ffffff',
|
|
textDecoration: 'none',
|
|
fontSize: 12,
|
|
fontWeight: 700,
|
|
}}
|
|
>
|
|
<svg width="14" height="14" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
|
|
<path
|
|
fill="#ffffff"
|
|
d="M18.3 2H21l-6.5 7.4L22 22h-6.2l-4.9-6.3L5 22H2.3l7.1-8.1L2 2h6.3l4.4 5.6L18.3 2zm-1.1 18h1.7L7.5 3.9H5.7L17.2 20z"
|
|
/>
|
|
</svg>
|
|
</Link>
|
|
<Link
|
|
href={brand.footer.socialLinkedInUrl || '#'}
|
|
style={{
|
|
display: 'inline-block',
|
|
padding: '8px 12px',
|
|
borderRadius: 999,
|
|
backgroundColor: brand.primaryColor,
|
|
color: '#ffffff',
|
|
textDecoration: 'none',
|
|
fontSize: 12,
|
|
fontWeight: 700,
|
|
}}
|
|
>
|
|
<svg width="14" height="14" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
|
|
<path
|
|
fill="#ffffff"
|
|
d="M6.5 6.8a2.2 2.2 0 1 1 0-4.4 2.2 2.2 0 0 1 0 4.4zM4.5 21.5V8.5h4v13h-4zM10.5 8.5h3.8v1.8h.1c.5-1 1.8-2 3.7-2 4 0 4.7 2.6 4.7 6v7.2h-4V15c0-1.3 0-3-1.8-3s-2.1 1.4-2.1 2.9v6.6h-4v-13z"
|
|
/>
|
|
</svg>
|
|
</Link>
|
|
</Section>
|
|
|
|
<Text style={{ margin: '14px 0 0', color: brand.textColor, fontSize: 12, lineHeight: '18px' }}>
|
|
© {new Date().getFullYear()} {brand.hotelName}. All rights reserved.
|
|
</Text>
|
|
</Section>
|
|
</Container>
|
|
</Body>
|
|
</Html>
|
|
)
|
|
}
|