refactor: remove email templates and consolidate locale utility functions
- Delete email template files: `email-formats.ts`, `newsletter-welcome.tsx`, `reset-password.tsx`, and `verify-email.tsx` - Move `getLocaleFromRequest` utility function from `auth.ts` to `utils.ts` - Update Chinese translation for newsletter and copyright text - Improve code organization and remove redundant email-related files
This commit is contained in:
parent
074a6d9f1e
commit
8c3f64d0aa
@ -1,61 +0,0 @@
|
||||
/**
|
||||
* https://demo.react.email/preview/welcome/stripe-welcome
|
||||
*/
|
||||
export const main = {
|
||||
fontFamily: '-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Ubuntu,sans-serif',
|
||||
};
|
||||
|
||||
export const container = {
|
||||
};
|
||||
|
||||
export const box = {
|
||||
padding: "8px",
|
||||
};
|
||||
|
||||
export const hr = {
|
||||
borderColor: "#e6ebf1",
|
||||
margin: "20px 0",
|
||||
};
|
||||
|
||||
export const paragraph = {
|
||||
color: "#525f7f",
|
||||
fontSize: "16px",
|
||||
lineHeight: "24px",
|
||||
textAlign: "left" as const,
|
||||
};
|
||||
|
||||
export const anchor = {
|
||||
color: "#556cd6",
|
||||
};
|
||||
|
||||
export const button = {
|
||||
backgroundColor: "#656ee8",
|
||||
borderRadius: "5px",
|
||||
color: "#fff",
|
||||
fontSize: "16px",
|
||||
fontWeight: "bold",
|
||||
textDecoration: "none",
|
||||
textAlign: "center" as const,
|
||||
display: "block",
|
||||
width: "100%",
|
||||
padding: "10px",
|
||||
};
|
||||
|
||||
export const footer = {
|
||||
width: "100%",
|
||||
color: "#8898aa",
|
||||
fontSize: "12px",
|
||||
lineHeight: "16px",
|
||||
display: "table",
|
||||
tableLayout: "fixed" as const,
|
||||
};
|
||||
|
||||
export const footerLeft = {
|
||||
display: "table-cell",
|
||||
textAlign: "left" as const,
|
||||
};
|
||||
|
||||
export const footerRight = {
|
||||
display: "table-cell",
|
||||
textAlign: "right" as const,
|
||||
};
|
@ -1,91 +0,0 @@
|
||||
import { siteConfig } from "@/config/site";
|
||||
import {
|
||||
Body,
|
||||
Container,
|
||||
Head,
|
||||
Hr,
|
||||
Html,
|
||||
Img,
|
||||
Link,
|
||||
Preview,
|
||||
Section,
|
||||
Text,
|
||||
} from "@react-email/components";
|
||||
import {
|
||||
anchor,
|
||||
box,
|
||||
container,
|
||||
footer,
|
||||
footerLeft,
|
||||
footerRight,
|
||||
hr,
|
||||
main,
|
||||
paragraph,
|
||||
} from "./email-formats";
|
||||
import { getBaseUrl } from "@/lib/urls/get-base-url";
|
||||
|
||||
/**
|
||||
* email for newsletter welcome
|
||||
*/
|
||||
export const NewsletterWelcomeEmail = ({ email }: { email: string }) => {
|
||||
const unsubscribeUrl = `${getBaseUrl()}/unsubscribe?email=${encodeURIComponent(email)}`;
|
||||
|
||||
return (
|
||||
<Html>
|
||||
<Head />
|
||||
<Preview>Welcome to {siteConfig.name}!</Preview>
|
||||
<Body style={main}>
|
||||
<Container style={container}>
|
||||
<Section style={box}>
|
||||
<Img
|
||||
src={`${getBaseUrl()}/logo.png`}
|
||||
width="32"
|
||||
height="32"
|
||||
alt="Logo"
|
||||
/>
|
||||
<Hr style={hr} />
|
||||
<Text style={paragraph}>
|
||||
Welcome to our community!
|
||||
</Text>
|
||||
<Text style={paragraph}>
|
||||
We value your participation and feedback. Please don't hesitate to
|
||||
reach out to us if you have any questions or suggestions.
|
||||
</Text>
|
||||
<Text style={paragraph}>
|
||||
Thanks, <br />
|
||||
The{" "}
|
||||
<Link style={anchor} href={getBaseUrl()}>
|
||||
{siteConfig.name}
|
||||
</Link>{" "}
|
||||
team
|
||||
</Text>
|
||||
<Hr style={hr} />
|
||||
<Text style={footer}>
|
||||
<span style={footerLeft}>
|
||||
© {new Date().getFullYear()}
|
||||
All Rights Reserved.
|
||||
</span>
|
||||
<span style={footerRight}>
|
||||
</span>
|
||||
</Text>
|
||||
<Text style={footer}>
|
||||
<span>
|
||||
If you wish to unsubscribe, please{" "}
|
||||
<Link style={anchor} href={unsubscribeUrl} target="_blank">
|
||||
click here
|
||||
</Link>
|
||||
.
|
||||
</span>
|
||||
</Text>
|
||||
</Section>
|
||||
</Container>
|
||||
</Body>
|
||||
</Html>
|
||||
);
|
||||
};
|
||||
|
||||
NewsletterWelcomeEmail.PreviewProps = {
|
||||
email: "support@mksaas.com",
|
||||
};
|
||||
|
||||
export default NewsletterWelcomeEmail;
|
@ -1,101 +0,0 @@
|
||||
import { siteConfig } from "@/config/site";
|
||||
import {
|
||||
Body,
|
||||
Button,
|
||||
Container,
|
||||
Head,
|
||||
Hr,
|
||||
Html,
|
||||
Img,
|
||||
Link,
|
||||
Preview,
|
||||
Section,
|
||||
Text,
|
||||
} from "@react-email/components";
|
||||
import {
|
||||
anchor,
|
||||
box,
|
||||
button,
|
||||
container,
|
||||
footer,
|
||||
footerLeft,
|
||||
footerRight,
|
||||
hr,
|
||||
main,
|
||||
paragraph,
|
||||
} from "./email-formats";
|
||||
import { getBaseUrl } from "@/lib/urls/get-base-url";
|
||||
|
||||
interface ResetPasswordEmailProps {
|
||||
userName?: string;
|
||||
resetLink?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* email for reset password
|
||||
*/
|
||||
export const ResetPasswordEmail = ({
|
||||
userName,
|
||||
resetLink,
|
||||
}: ResetPasswordEmailProps) => {
|
||||
return (
|
||||
<Html>
|
||||
<Head />
|
||||
<Preview>Reset your password</Preview>
|
||||
<Body style={main}>
|
||||
<Container style={container}>
|
||||
<Section style={box}>
|
||||
<Img
|
||||
src={`${getBaseUrl()}/logo.png`}
|
||||
width="32"
|
||||
height="32"
|
||||
alt="Logo"
|
||||
/>
|
||||
<Hr style={hr} />
|
||||
<Text style={paragraph}>Hi {userName},</Text>
|
||||
<Text style={paragraph}>
|
||||
Someone recently requested a password change for your account. If
|
||||
this was you, you can set a new password here:
|
||||
</Text>
|
||||
<Button style={button} href={resetLink}>
|
||||
Reset password
|
||||
</Button>
|
||||
<Hr style={hr} />
|
||||
<Text style={paragraph}>
|
||||
If you don't want to change your password or didn't
|
||||
request this, just ignore and delete this message.
|
||||
</Text>
|
||||
<Text style={paragraph}>
|
||||
To keep your account secure, please don't forward this email
|
||||
to anyone.
|
||||
</Text>
|
||||
<Text style={paragraph}>
|
||||
Thanks, <br />
|
||||
The{" "}
|
||||
<Link style={anchor} href={getBaseUrl()}>
|
||||
{siteConfig.name}
|
||||
</Link>{" "}
|
||||
team
|
||||
</Text>
|
||||
<Hr style={hr} />
|
||||
<Text style={footer}>
|
||||
<span style={footerLeft}>
|
||||
© {new Date().getFullYear()}
|
||||
All Rights Reserved.
|
||||
</span>
|
||||
<span style={footerRight}>
|
||||
</span>
|
||||
</Text>
|
||||
</Section>
|
||||
</Container>
|
||||
</Body>
|
||||
</Html>
|
||||
);
|
||||
};
|
||||
|
||||
ResetPasswordEmail.PreviewProps = {
|
||||
userName: "Mksaas",
|
||||
resetLink: "https://demo.mksaas.com",
|
||||
} as ResetPasswordEmailProps;
|
||||
|
||||
export default ResetPasswordEmail;
|
@ -1,93 +0,0 @@
|
||||
import { siteConfig } from "@/config/site";
|
||||
import {
|
||||
Body,
|
||||
Button,
|
||||
Container,
|
||||
Head,
|
||||
Hr,
|
||||
Html,
|
||||
Img,
|
||||
Link,
|
||||
Preview,
|
||||
Section,
|
||||
Text,
|
||||
} from "@react-email/components";
|
||||
import {
|
||||
anchor,
|
||||
box,
|
||||
button,
|
||||
container,
|
||||
footer,
|
||||
footerLeft,
|
||||
footerRight,
|
||||
hr,
|
||||
main,
|
||||
paragraph,
|
||||
} from "./email-formats";
|
||||
import { getBaseUrl } from "@/lib/urls/get-base-url";
|
||||
|
||||
interface VerifyEmailProps {
|
||||
confirmLink?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* email for verify email
|
||||
*/
|
||||
export const VerifyEmail = ({ confirmLink }: VerifyEmailProps) => {
|
||||
return (
|
||||
<Html>
|
||||
<Head />
|
||||
<Preview>Confirm your email address</Preview>
|
||||
<Body style={main}>
|
||||
<Container style={container}>
|
||||
<Section style={box}>
|
||||
<Img
|
||||
src={`${getBaseUrl()}/logo.png`}
|
||||
width="32"
|
||||
height="32"
|
||||
alt="Logo"
|
||||
/>
|
||||
<Hr style={hr} />
|
||||
<Text style={paragraph}>Confirm your email address</Text>
|
||||
<Text style={paragraph}>
|
||||
Thanks for starting the new account creation process. We want to
|
||||
make sure it's really you. Please click the confirmation link to
|
||||
continue.
|
||||
</Text>
|
||||
<Button style={button} href={confirmLink}>
|
||||
Confirm Email
|
||||
</Button>
|
||||
<Hr style={hr} />
|
||||
<Text style={paragraph}>
|
||||
If you don't want to create an account, you can ignore this
|
||||
message.
|
||||
</Text>
|
||||
<Text style={paragraph}>
|
||||
Thanks, <br />
|
||||
The{" "}
|
||||
<Link style={anchor} href={getBaseUrl()}>
|
||||
{siteConfig.name}
|
||||
</Link>{" "}
|
||||
team
|
||||
</Text>
|
||||
<Hr style={hr} />
|
||||
<Text style={footer}>
|
||||
<span style={footerLeft}>
|
||||
© {new Date().getFullYear()}
|
||||
All Rights Reserved.
|
||||
</span>
|
||||
<span style={footerRight}>
|
||||
</span>
|
||||
</Text>
|
||||
</Section>
|
||||
</Container>
|
||||
</Body>
|
||||
</Html>
|
||||
);
|
||||
};
|
||||
|
||||
VerifyEmail.PreviewProps = {
|
||||
confirmLink: "https://demo.mksaas.com",
|
||||
} as VerifyEmailProps;
|
||||
|
||||
export default VerifyEmail;
|
@ -70,7 +70,7 @@
|
||||
"mail": {
|
||||
"common": {
|
||||
"team": "{name} 团队",
|
||||
"copyright": "版权所有 {year}。保留所有权利。"
|
||||
"copyright": "版权所有 {year}"
|
||||
},
|
||||
"verifyEmail": {
|
||||
"title": "你好, {name}.",
|
||||
@ -85,7 +85,7 @@
|
||||
"subject": "重置您的密码"
|
||||
},
|
||||
"subscribeNewsletter": {
|
||||
"body": "感谢您订阅我们的邮件列表,我们将持续为您提供最新新闻和更新。",
|
||||
"body": "感谢您订阅我们的邮件列表,我们将持续为您带来最新的新闻和更新。",
|
||||
"subject": "感谢您的订阅"
|
||||
}
|
||||
}
|
||||
|
@ -1,23 +1,14 @@
|
||||
import { siteConfig } from "@/config/site";
|
||||
import db from "@/db/index";
|
||||
import { account, session, user, verification } from "@/db/schema";
|
||||
import { Locale, LOCALE_COOKIE_NAME, routing } from "@/i18n/routing";
|
||||
import { send } from "@/mail/send";
|
||||
import { getLocaleFromRequest } from "@/lib/utils";
|
||||
import { betterAuth } from "better-auth";
|
||||
import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
||||
import { admin } from "better-auth/plugins";
|
||||
import { parse as parseCookies } from "cookie";
|
||||
|
||||
const from = process.env.RESEND_FROM || "delivered@resend.dev";
|
||||
|
||||
const getLocaleFromRequest = (request?: Request) => {
|
||||
const cookies = parseCookies(request?.headers.get("cookie") ?? "");
|
||||
return (
|
||||
(cookies[LOCALE_COOKIE_NAME] as Locale) ??
|
||||
routing.defaultLocale
|
||||
);
|
||||
};
|
||||
|
||||
export const auth = betterAuth({
|
||||
appName: siteConfig.name,
|
||||
database: drizzleAdapter(db, {
|
||||
|
@ -1,5 +1,7 @@
|
||||
import { AppInfo } from "@/constants/app-info";
|
||||
import { Locale, LOCALE_COOKIE_NAME, routing } from "@/i18n/routing";
|
||||
import { type ClassValue, clsx } from "clsx";
|
||||
import { parse as parseCookies } from "cookie";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
@ -61,4 +63,19 @@ export function getLocaleDate(input: string | number): string {
|
||||
const month = (date.getMonth() + 1).toString().padStart(2, "0");
|
||||
const day = date.getDate().toString().padStart(2, "0");
|
||||
return `${year}/${month}/${day}`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the locale from a request by parsing the cookies
|
||||
* If no locale is found in the cookies, returns the default locale
|
||||
*
|
||||
* @param request - The request to get the locale from
|
||||
* @returns The locale from the request or the default locale
|
||||
*/
|
||||
export const getLocaleFromRequest = (request?: Request) => {
|
||||
const cookies = parseCookies(request?.headers.get("cookie") ?? "");
|
||||
return (
|
||||
(cookies[LOCALE_COOKIE_NAME] as Locale) ??
|
||||
routing.defaultLocale
|
||||
);
|
||||
};
|
Loading…
Reference in New Issue
Block a user