feat: build IPTEK company website with full bilingual support
- Complete Next.js 16 app with App Router: Home, About, Products, Contact, Privacy pages - Product detail pages: ZappCare, Unified TMS, EMR Clinic - Bilingual support (Indonesian/English) via LanguageContext + translations.ts - Language switcher pill button (🇮🇩 ID / 🇬🇧 EN) in Navbar with localStorage persistence - Navbar with logo, responsive mobile menu, translated nav links - Contact form with captcha, server action email sending, translated labels - Material Design 3 color tokens, Manrope + Inter fonts, Material Symbols icons - Local product image assets and company logo Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
67
app/actions/sendContact.ts
Normal file
67
app/actions/sendContact.ts
Normal file
@ -0,0 +1,67 @@
|
||||
"use server";
|
||||
|
||||
import nodemailer from "nodemailer";
|
||||
|
||||
export type ContactPayload = {
|
||||
name: string;
|
||||
email: string;
|
||||
company: string;
|
||||
phone: string;
|
||||
topic: string;
|
||||
message: string;
|
||||
};
|
||||
|
||||
export type SendResult = { ok: true } | { ok: false; error: string };
|
||||
|
||||
export async function sendContactEmail(data: ContactPayload): Promise<SendResult> {
|
||||
const { SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS } = process.env;
|
||||
|
||||
if (!SMTP_HOST || !SMTP_USER || !SMTP_PASS) {
|
||||
return { ok: false, error: "Konfigurasi email server belum diatur." };
|
||||
}
|
||||
|
||||
const transporter = nodemailer.createTransport({
|
||||
host: SMTP_HOST,
|
||||
port: Number(SMTP_PORT ?? 587),
|
||||
secure: Number(SMTP_PORT) === 465,
|
||||
auth: { user: SMTP_USER, pass: SMTP_PASS },
|
||||
});
|
||||
|
||||
const html = `
|
||||
<div style="font-family: Inter, sans-serif; max-width: 600px; margin: 0 auto; color: #191c1e;">
|
||||
<div style="background: linear-gradient(135deg, #004cca, #0062ff); padding: 32px; border-radius: 12px 12px 0 0;">
|
||||
<h1 style="color: white; margin: 0; font-size: 24px;">Pesan Baru dari Website IPTEK</h1>
|
||||
</div>
|
||||
<div style="background: #f7f9fb; padding: 32px; border-radius: 0 0 12px 12px; border: 1px solid #e0e3e5;">
|
||||
<table style="width: 100%; border-collapse: collapse;">
|
||||
<tr><td style="padding: 8px 0; color: #737687; width: 140px; font-size: 13px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em;">Nama</td><td style="padding: 8px 0; font-weight: 500;">${data.name}</td></tr>
|
||||
<tr><td style="padding: 8px 0; color: #737687; font-size: 13px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em;">Email</td><td style="padding: 8px 0;"><a href="mailto:${data.email}" style="color: #004cca;">${data.email}</a></td></tr>
|
||||
<tr><td style="padding: 8px 0; color: #737687; font-size: 13px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em;">Perusahaan</td><td style="padding: 8px 0;">${data.company || "-"}</td></tr>
|
||||
<tr><td style="padding: 8px 0; color: #737687; font-size: 13px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em;">WhatsApp</td><td style="padding: 8px 0;">${data.phone || "-"}</td></tr>
|
||||
<tr><td style="padding: 8px 0; color: #737687; font-size: 13px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em;">Topik</td><td style="padding: 8px 0;"><span style="background: #dbe1ff; color: #004cca; padding: 3px 10px; border-radius: 99px; font-size: 13px; font-weight: 600;">${data.topic}</span></td></tr>
|
||||
</table>
|
||||
<div style="margin-top: 24px; padding-top: 24px; border-top: 1px solid #e0e3e5;">
|
||||
<p style="color: #737687; font-size: 13px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; margin: 0 0 10px;">Pesan</p>
|
||||
<p style="margin: 0; line-height: 1.7; white-space: pre-wrap;">${data.message}</p>
|
||||
</div>
|
||||
<div style="margin-top: 24px; padding-top: 16px; border-top: 1px solid #e0e3e5; font-size: 12px; color: #737687;">
|
||||
Dikirim pada ${new Date().toLocaleString("id-ID", { timeZone: "Asia/Jakarta", dateStyle: "long", timeStyle: "short" })} WIB
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
try {
|
||||
await transporter.sendMail({
|
||||
from: `"IPTEK Website" <${SMTP_USER}>`,
|
||||
to: "support@iptek.co",
|
||||
replyTo: data.email,
|
||||
subject: `[${data.topic}] Pesan dari ${data.name} – IPTEK Website`,
|
||||
html,
|
||||
});
|
||||
return { ok: true };
|
||||
} catch (err) {
|
||||
console.error("Email send error:", err);
|
||||
return { ok: false, error: "Gagal mengirim pesan. Silakan coba lagi atau hubungi kami langsung." };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user