refactor: abstract site URL across email templates
- Add NEXT_PUBLIC_SITE_URL to .env.local - Update email templates to accept siteUrl prop - Update webhook handler to pass siteUrl from env var - Update create-webhooks.graphql with placeholder URL
This commit is contained in:
@@ -6,6 +6,8 @@ import { OrderShipped } from "@/emails/OrderShipped";
|
||||
import { OrderCancelled } from "@/emails/OrderCancelled";
|
||||
import { OrderPaid } from "@/emails/OrderPaid";
|
||||
|
||||
const SITE_URL = process.env.NEXT_PUBLIC_SITE_URL || "https://dev.manoonoils.com";
|
||||
|
||||
interface SaleorWebhookHeaders {
|
||||
"saleor-event": string;
|
||||
"saleor-domain": string;
|
||||
@@ -159,6 +161,7 @@ async function handleOrderConfirmed(order: SaleorOrder) {
|
||||
items: parseOrderItems(order.lines, currency),
|
||||
total: formatPrice(order.total.gross.amount, currency),
|
||||
shippingAddress: formatAddress(order.shippingAddress),
|
||||
siteUrl: SITE_URL,
|
||||
}),
|
||||
language,
|
||||
idempotencyKey: `order-confirmed/${order.id}`,
|
||||
@@ -175,6 +178,7 @@ async function handleOrderConfirmed(order: SaleorOrder) {
|
||||
items: parseOrderItems(order.lines, currency),
|
||||
total: formatPrice(order.total.gross.amount, currency),
|
||||
shippingAddress: formatAddress(order.shippingAddress),
|
||||
siteUrl: SITE_URL,
|
||||
}),
|
||||
eventType: "ORDER_CONFIRMED",
|
||||
orderId: order.id,
|
||||
@@ -219,6 +223,7 @@ async function handleOrderFulfilled(order: SaleorOrder) {
|
||||
items: parseOrderItems(order.lines, currency),
|
||||
trackingNumber,
|
||||
trackingUrl,
|
||||
siteUrl: SITE_URL,
|
||||
}),
|
||||
language,
|
||||
idempotencyKey: `order-fulfilled/${order.id}`,
|
||||
@@ -234,6 +239,7 @@ async function handleOrderFulfilled(order: SaleorOrder) {
|
||||
items: parseOrderItems(order.lines, currency),
|
||||
trackingNumber,
|
||||
trackingUrl,
|
||||
siteUrl: SITE_URL,
|
||||
}),
|
||||
eventType: "ORDER_FULFILLED",
|
||||
orderId: order.id,
|
||||
@@ -272,6 +278,7 @@ async function handleOrderCancelled(order: SaleorOrder) {
|
||||
items: parseOrderItems(order.lines, currency),
|
||||
total: formatPrice(order.total.gross.amount, currency),
|
||||
reason,
|
||||
siteUrl: SITE_URL,
|
||||
}),
|
||||
language,
|
||||
idempotencyKey: `order-cancelled/${order.id}`,
|
||||
@@ -287,6 +294,7 @@ async function handleOrderCancelled(order: SaleorOrder) {
|
||||
items: parseOrderItems(order.lines, currency),
|
||||
total: formatPrice(order.total.gross.amount, currency),
|
||||
reason,
|
||||
siteUrl: SITE_URL,
|
||||
}),
|
||||
eventType: "ORDER_CANCELLED",
|
||||
orderId: order.id,
|
||||
@@ -316,6 +324,7 @@ async function handleOrderFullyPaid(order: SaleorOrder) {
|
||||
customerName,
|
||||
items: parseOrderItems(order.lines, currency),
|
||||
total: formatPrice(order.total.gross.amount, currency),
|
||||
siteUrl: SITE_URL,
|
||||
}),
|
||||
language,
|
||||
idempotencyKey: `order-paid/${order.id}`,
|
||||
@@ -330,6 +339,7 @@ async function handleOrderFullyPaid(order: SaleorOrder) {
|
||||
customerName,
|
||||
items: parseOrderItems(order.lines, currency),
|
||||
total: formatPrice(order.total.gross.amount, currency),
|
||||
siteUrl: SITE_URL,
|
||||
}),
|
||||
eventType: "ORDER_FULLY_PAID",
|
||||
orderId: order.id,
|
||||
|
||||
@@ -16,6 +16,7 @@ interface BaseLayoutProps {
|
||||
children: React.ReactNode;
|
||||
previewText: string;
|
||||
language: string;
|
||||
siteUrl: string;
|
||||
}
|
||||
|
||||
const translations: Record<string, { footer: string; company: string }> = {
|
||||
@@ -37,7 +38,7 @@ const translations: Record<string, { footer: string; company: string }> = {
|
||||
},
|
||||
};
|
||||
|
||||
export function BaseLayout({ children, previewText, language }: BaseLayoutProps) {
|
||||
export function BaseLayout({ children, previewText, language, siteUrl }: BaseLayoutProps) {
|
||||
const t = translations[language] || translations.en;
|
||||
|
||||
return (
|
||||
@@ -48,7 +49,7 @@ export function BaseLayout({ children, previewText, language }: BaseLayoutProps)
|
||||
<Container style={styles.container}>
|
||||
<Section style={styles.logoSection}>
|
||||
<Img
|
||||
src="https://manoonoils.com/logo.png"
|
||||
src={`${siteUrl}/logo.png`}
|
||||
width="150"
|
||||
height="auto"
|
||||
alt="ManoonOils"
|
||||
|
||||
@@ -16,6 +16,7 @@ interface OrderCancelledProps {
|
||||
items: OrderItem[];
|
||||
total: string;
|
||||
reason?: string;
|
||||
siteUrl: string;
|
||||
}
|
||||
|
||||
const translations: Record<
|
||||
@@ -85,11 +86,12 @@ export function OrderCancelled({
|
||||
items,
|
||||
total,
|
||||
reason,
|
||||
siteUrl,
|
||||
}: OrderCancelledProps) {
|
||||
const t = translations[language] || translations.en;
|
||||
|
||||
return (
|
||||
<BaseLayout previewText={t.preview} language={language}>
|
||||
<BaseLayout previewText={t.preview} language={language} siteUrl={siteUrl}>
|
||||
<Text style={styles.title}>{t.title}</Text>
|
||||
<Text style={styles.greeting}>{t.greeting.replace("{name}", customerName)}</Text>
|
||||
<Text style={styles.text}>{t.orderCancelled}</Text>
|
||||
@@ -124,7 +126,7 @@ export function OrderCancelled({
|
||||
</Section>
|
||||
|
||||
<Section style={styles.buttonSection}>
|
||||
<Button href="https://manoonoils.com" style={styles.button}>
|
||||
<Button href={siteUrl} style={styles.button}>
|
||||
{language === "sr" ? "Pogledajte proizvode" : "Browse Products"}
|
||||
</Button>
|
||||
</Section>
|
||||
|
||||
@@ -17,6 +17,7 @@ interface OrderConfirmationProps {
|
||||
items: OrderItem[];
|
||||
total: string;
|
||||
shippingAddress?: string;
|
||||
siteUrl: string;
|
||||
}
|
||||
|
||||
const translations: Record<
|
||||
@@ -101,11 +102,12 @@ export function OrderConfirmation({
|
||||
items,
|
||||
total,
|
||||
shippingAddress,
|
||||
siteUrl,
|
||||
}: OrderConfirmationProps) {
|
||||
const t = translations[language] || translations.en;
|
||||
|
||||
return (
|
||||
<BaseLayout previewText={t.preview} language={language}>
|
||||
<BaseLayout previewText={t.preview} language={language} siteUrl={siteUrl}>
|
||||
<Text style={styles.title}>{t.title}</Text>
|
||||
<Text style={styles.greeting}>{t.greeting.replace("{name}", customerName)}</Text>
|
||||
<Text style={styles.text}>{t.orderReceived}</Text>
|
||||
@@ -142,7 +144,7 @@ export function OrderConfirmation({
|
||||
)}
|
||||
|
||||
<Section style={styles.buttonSection}>
|
||||
<Button href="https://manoonoils.com" style={styles.button}>
|
||||
<Button href={siteUrl} style={styles.button}>
|
||||
{language === "sr"
|
||||
? "Pogledajte narudžbinu"
|
||||
: language === "de"
|
||||
|
||||
@@ -15,6 +15,7 @@ interface OrderPaidProps {
|
||||
customerName: string;
|
||||
items: OrderItem[];
|
||||
total: string;
|
||||
siteUrl: string;
|
||||
}
|
||||
|
||||
const translations: Record<
|
||||
@@ -92,11 +93,12 @@ export function OrderPaid({
|
||||
customerName,
|
||||
items,
|
||||
total,
|
||||
siteUrl,
|
||||
}: OrderPaidProps) {
|
||||
const t = translations[language] || translations.en;
|
||||
|
||||
return (
|
||||
<BaseLayout previewText={t.preview} language={language}>
|
||||
<BaseLayout previewText={t.preview} language={language} siteUrl={siteUrl}>
|
||||
<Text style={styles.title}>{t.title}</Text>
|
||||
<Text style={styles.greeting}>{t.greeting.replace("{name}", customerName)}</Text>
|
||||
<Text style={styles.text}>{t.orderPaid}</Text>
|
||||
@@ -131,7 +133,7 @@ export function OrderPaid({
|
||||
</Section>
|
||||
|
||||
<Section style={styles.buttonSection}>
|
||||
<Button href="https://manoonoils.com" style={styles.button}>
|
||||
<Button href={siteUrl} style={styles.button}>
|
||||
{language === "sr" ? "Nastavite kupovinu" : "Continue Shopping"}
|
||||
</Button>
|
||||
</Section>
|
||||
|
||||
@@ -16,6 +16,7 @@ interface OrderShippedProps {
|
||||
items: OrderItem[];
|
||||
trackingNumber?: string;
|
||||
trackingUrl?: string;
|
||||
siteUrl: string;
|
||||
}
|
||||
|
||||
const translations: Record<
|
||||
@@ -80,11 +81,12 @@ export function OrderShipped({
|
||||
items,
|
||||
trackingNumber,
|
||||
trackingUrl,
|
||||
siteUrl,
|
||||
}: OrderShippedProps) {
|
||||
const t = translations[language] || translations.en;
|
||||
|
||||
return (
|
||||
<BaseLayout previewText={t.preview} language={language}>
|
||||
<BaseLayout previewText={t.preview} language={language} siteUrl={siteUrl}>
|
||||
<Text style={styles.title}>{t.title}</Text>
|
||||
<Text style={styles.greeting}>{t.greeting.replace("{name}", customerName)}</Text>
|
||||
<Text style={styles.text}>{t.orderShipped}</Text>
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
# Replace YOUR_STOREFRONT_URL with your actual storefront URL
|
||||
# Dev: https://dev.manoonoils.com
|
||||
# Prod: https://manoonoils.com
|
||||
|
||||
mutation CreateSaleorWebhooks {
|
||||
orderConfirmedWebhook: webhookCreate(input: {
|
||||
name: "Resend - Order Confirmed"
|
||||
targetUrl: "https://manoonoils.com/api/webhooks/saleor"
|
||||
targetUrl: "YOUR_STOREFRONT_URL/api/webhooks/saleor"
|
||||
events: [ORDER_CONFIRMED]
|
||||
isActive: true
|
||||
}) {
|
||||
@@ -20,7 +24,7 @@ mutation CreateSaleorWebhooks {
|
||||
|
||||
orderPaidWebhook: webhookCreate(input: {
|
||||
name: "Resend - Order Paid"
|
||||
targetUrl: "https://manoonoils.com/api/webhooks/saleor"
|
||||
targetUrl: "YOUR_STOREFRONT_URL/api/webhooks/saleor"
|
||||
events: [ORDER_FULLY_PAID]
|
||||
isActive: true
|
||||
}) {
|
||||
@@ -39,7 +43,7 @@ mutation CreateSaleorWebhooks {
|
||||
|
||||
orderCancelledWebhook: webhookCreate(input: {
|
||||
name: "Resend - Order Cancelled"
|
||||
targetUrl: "https://manoonoils.com/api/webhooks/saleor"
|
||||
targetUrl: "YOUR_STOREFRONT_URL/api/webhooks/saleor"
|
||||
events: [ORDER_CANCELLED]
|
||||
isActive: true
|
||||
}) {
|
||||
@@ -58,7 +62,7 @@ mutation CreateSaleorWebhooks {
|
||||
|
||||
orderFulfilledWebhook: webhookCreate(input: {
|
||||
name: "Resend - Order Fulfilled"
|
||||
targetUrl: "https://manoonoils.com/api/webhooks/saleor"
|
||||
targetUrl: "YOUR_STOREFRONT_URL/api/webhooks/saleor"
|
||||
events: [ORDER_FULFILLED]
|
||||
isActive: true
|
||||
}) {
|
||||
|
||||
Reference in New Issue
Block a user