154 lines
4.7 KiB
TypeScript
154 lines
4.7 KiB
TypeScript
'use server';
|
|
|
|
import client, { ensureAuthenticated } from '@/lib/directus';
|
|
import { createItem } from '@directus/sdk';
|
|
import { sendEmail } from '@/lib/mail/mailer';
|
|
import { render, ContactFormNotification, ConfirmationMessage } from '@mintel/mail';
|
|
import React from 'react';
|
|
import { getServerAppServices } from '@/lib/services/create-services.server';
|
|
|
|
export async function sendContactFormAction(formData: FormData) {
|
|
const services = getServerAppServices();
|
|
const logger = services.logger.child({ action: 'sendContactFormAction' });
|
|
|
|
// Set analytics context from request headers for high-fidelity server-side tracking
|
|
const { headers } = await import('next/headers');
|
|
const requestHeaders = await headers();
|
|
|
|
if ('setServerContext' in services.analytics) {
|
|
(services.analytics as any).setServerContext({
|
|
userAgent: requestHeaders.get('user-agent') || undefined,
|
|
language: requestHeaders.get('accept-language')?.split(',')[0] || undefined,
|
|
referrer: requestHeaders.get('referer') || undefined,
|
|
ip: requestHeaders.get('x-forwarded-for')?.split(',')[0] || undefined,
|
|
});
|
|
}
|
|
|
|
// Track attempt
|
|
services.analytics.track('contact-form-attempt');
|
|
|
|
const name = formData.get('name') as string;
|
|
const email = formData.get('email') as string;
|
|
const message = formData.get('message') as string;
|
|
const productName = formData.get('productName') as string | null;
|
|
|
|
if (!name || !email || !message) {
|
|
logger.warn('Missing required fields in contact form', {
|
|
name: !!name,
|
|
email: !!email,
|
|
message: !!message,
|
|
});
|
|
return { success: false, error: 'Missing required fields' };
|
|
}
|
|
|
|
// 1. Save to Directus
|
|
try {
|
|
await ensureAuthenticated();
|
|
if (productName) {
|
|
await client.request(
|
|
createItem('product_requests', {
|
|
product_name: productName,
|
|
email,
|
|
message,
|
|
}),
|
|
);
|
|
logger.info('Product request stored in Directus');
|
|
} else {
|
|
await client.request(
|
|
createItem('contact_submissions', {
|
|
name,
|
|
email,
|
|
message,
|
|
}),
|
|
);
|
|
logger.info('Contact submission stored in Directus');
|
|
}
|
|
} catch (error) {
|
|
logger.error('Failed to store submission in Directus', { error });
|
|
services.errors.captureException(error, { action: 'directus_store_submission' });
|
|
}
|
|
|
|
// 2. Send Emails
|
|
logger.info('Sending branded emails', { email, productName });
|
|
|
|
const notificationSubject = productName
|
|
? `Product Inquiry: ${productName}`
|
|
: 'New Contact Form Submission';
|
|
const confirmationSubject = 'Thank you for your inquiry';
|
|
|
|
try {
|
|
// 2a. Send notification to Mintel/Client
|
|
const notificationHtml = await render(
|
|
React.createElement(ContactFormNotification, {
|
|
name,
|
|
email,
|
|
message,
|
|
productName: productName || undefined,
|
|
}),
|
|
);
|
|
|
|
const notificationResult = await sendEmail({
|
|
replyTo: email,
|
|
subject: notificationSubject,
|
|
html: notificationHtml,
|
|
});
|
|
|
|
if (notificationResult.success) {
|
|
logger.info('Notification email sent successfully', {
|
|
messageId: notificationResult.messageId,
|
|
});
|
|
}
|
|
|
|
// 2b. Send confirmation to Customer (branded as KLZ Cables)
|
|
const confirmationHtml = await render(
|
|
React.createElement(ConfirmationMessage, {
|
|
name,
|
|
clientName: 'KLZ Cables',
|
|
// brandColor: '#82ed20', // Optional: could be KLZ specific
|
|
}),
|
|
);
|
|
|
|
const confirmationResult = await sendEmail({
|
|
to: email,
|
|
subject: confirmationSubject,
|
|
html: confirmationHtml,
|
|
});
|
|
|
|
if (confirmationResult.success) {
|
|
logger.info('Confirmation email sent successfully', {
|
|
messageId: confirmationResult.messageId,
|
|
});
|
|
}
|
|
|
|
// Notify via Gotify (Internal)
|
|
await services.notifications.notify({
|
|
title: `📩 ${notificationSubject}`,
|
|
message: `New message from ${name} (${email}):\n\n${message}`,
|
|
priority: 5,
|
|
});
|
|
|
|
// Track success
|
|
services.analytics.track('contact-form-success', {
|
|
is_product_request: !!productName,
|
|
});
|
|
|
|
return { success: true };
|
|
} catch (error) {
|
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
logger.error('Failed to send branded emails', {
|
|
error: errorMsg,
|
|
stack: error instanceof Error ? error.stack : undefined,
|
|
});
|
|
|
|
services.errors.captureException(error, { action: 'sendContactFormAction', email });
|
|
|
|
await services.notifications.notify({
|
|
title: '🚨 Contact Form Error',
|
|
message: `Failed to send emails for ${name} (${email}). Error: ${errorMsg}`,
|
|
priority: 8,
|
|
});
|
|
|
|
return { success: false, error: errorMsg };
|
|
}
|
|
}
|