Initial commit: Lageplan v1.0 - Next.js 15.5, React 19

This commit is contained in:
Pepe Ziberi
2026-02-21 11:57:44 +01:00
commit adf3dc8c1d
167 changed files with 34265 additions and 0 deletions

View File

@@ -0,0 +1,75 @@
import { NextRequest, NextResponse } from 'next/server'
import { prisma } from '@/lib/db'
import { sendEmail, getSmtpConfig } from '@/lib/email'
import { z } from 'zod'
const contactSchema = z.object({
name: z.string().min(1).max(200),
email: z.string().email(),
message: z.string().min(1).max(5000),
})
// Get contact email from SystemSettings, fallback to app@lageplan.ch
async function getContactEmail(): Promise<string> {
try {
const setting = await (prisma as any).systemSetting.findUnique({
where: { key: 'contact_email' },
})
return setting?.value || 'app@lageplan.ch'
} catch {
return 'app@lageplan.ch'
}
}
export async function POST(req: NextRequest) {
try {
const body = await req.json()
const data = contactSchema.parse(body)
const contactEmail = await getContactEmail()
const smtpConfig = await getSmtpConfig()
if (smtpConfig) {
// Send via SMTP
const html = `
<h2>Neue Kontaktanfrage — Lageplan</h2>
<table style="border-collapse:collapse;width:100%;max-width:500px;">
<tr><td style="padding:8px;font-weight:bold;border-bottom:1px solid #eee;">Name</td><td style="padding:8px;border-bottom:1px solid #eee;">${escapeHtml(data.name)}</td></tr>
<tr><td style="padding:8px;font-weight:bold;border-bottom:1px solid #eee;">E-Mail</td><td style="padding:8px;border-bottom:1px solid #eee;"><a href="mailto:${escapeHtml(data.email)}">${escapeHtml(data.email)}</a></td></tr>
</table>
<h3 style="margin-top:20px;">Nachricht</h3>
<div style="background:#f9f9f9;padding:16px;border-radius:8px;white-space:pre-wrap;">${escapeHtml(data.message)}</div>
<p style="margin-top:20px;font-size:12px;color:#999;">Gesendet über das Kontaktformular auf lageplan.ch</p>
`
await sendEmail(contactEmail, `Kontaktanfrage von ${data.name}`, html)
} else {
// No SMTP configured — store in SystemSettings as fallback log
const logKey = `contact_msg_${Date.now()}`
await (prisma as any).systemSetting.create({
data: {
key: logKey,
value: JSON.stringify({ name: data.name, email: data.email, message: data.message, date: new Date().toISOString() }),
isSecret: false,
category: 'contact_messages',
},
})
}
return NextResponse.json({ success: true })
} catch (error) {
if (error instanceof z.ZodError) {
return NextResponse.json({ error: 'Bitte füllen Sie alle Felder korrekt aus.' }, { status: 400 })
}
console.error('Contact form error:', error)
return NextResponse.json({ error: 'Senden fehlgeschlagen. Bitte versuchen Sie es später.' }, { status: 500 })
}
}
function escapeHtml(str: string): string {
return str
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
}