first commit
ci / build (push) Failing after 23s
deploy / deploy (push) Failing after 10m12s

This commit is contained in:
soroush.asadi
2026-05-31 12:47:02 +03:30
commit add78d8460
100 changed files with 15221 additions and 0 deletions
+99
View File
@@ -0,0 +1,99 @@
import { NextResponse } from 'next/server';
import { Resend } from 'resend';
export const runtime = 'edge';
type ContactPayload = {
name?: string;
company?: string;
service?: string;
budget?: string;
message?: string;
locale?: 'fa' | 'en';
};
const required = ['name', 'service', 'budget', 'message'] as const;
function escape(str: string) {
return str
.replace(/&/g, '&')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;');
}
export async function POST(req: Request) {
let body: ContactPayload;
try {
body = (await req.json()) as ContactPayload;
} catch {
return NextResponse.json({ error: 'Invalid JSON' }, { status: 400 });
}
for (const k of required) {
if (!body[k] || String(body[k]).trim().length < 2) {
return NextResponse.json(
{ error: `Missing field: ${k}` },
{ status: 422 },
);
}
}
const apiKey = process.env.RESEND_API_KEY;
const inbox = process.env.CONTACT_INBOX;
const from = process.env.CONTACT_FROM;
// Graceful no-op for local dev so the form UX can be validated
// without forcing a Resend key. Production should set these.
if (!apiKey || !inbox || !from) {
if (process.env.NODE_ENV === 'production') {
return NextResponse.json(
{ error: 'Email service is not configured' },
{ status: 500 },
);
}
console.info('[contact] received (no Resend key — logging only):', body);
return NextResponse.json({ ok: true, dev: true });
}
const resend = new Resend(apiKey);
const subject = `New consultation request — ${body.name}`;
const html = `
<div style="font-family: ui-sans-serif, system-ui, sans-serif; line-height: 1.55;">
<h2 style="margin: 0 0 12px;">New consultation request</h2>
<table style="border-collapse: collapse;">
<tr><td style="padding: 4px 12px 4px 0; color:#475569;">Name</td><td>${escape(body.name!)}</td></tr>
<tr><td style="padding: 4px 12px 4px 0; color:#475569;">Company</td><td>${escape(body.company ?? '')}</td></tr>
<tr><td style="padding: 4px 12px 4px 0; color:#475569;">Service</td><td>${escape(body.service!)}</td></tr>
<tr><td style="padding: 4px 12px 4px 0; color:#475569;">Budget</td><td>${escape(body.budget!)}</td></tr>
<tr><td style="padding: 4px 12px 4px 0; color:#475569;">Locale</td><td>${escape(body.locale ?? '')}</td></tr>
</table>
<h3 style="margin: 20px 0 6px;">Message</h3>
<p style="white-space: pre-wrap; background:#f8fafc; padding:12px; border-radius:8px;">${escape(body.message!)}</p>
</div>
`;
try {
const { error } = await resend.emails.send({
from,
to: inbox,
subject,
html,
replyTo: body.company ? `${body.name} <${body.company}>` : undefined,
});
if (error) {
console.error('[contact] resend error', error);
return NextResponse.json(
{ error: 'Email service rejected the request' },
{ status: 502 },
);
}
return NextResponse.json({ ok: true });
} catch (err) {
console.error('[contact] send failed', err);
return NextResponse.json(
{ error: 'Email service unreachable' },
{ status: 502 },
);
}
}