diff --git a/app/api/email/route.tsx b/app/api/email/route.tsx index e6880d6..0c03005 100644 --- a/app/api/email/route.tsx +++ b/app/api/email/route.tsx @@ -7,7 +7,12 @@ import dotenv from "dotenv"; dotenv.config(); export async function POST(request: NextRequest) { - const { email, name, message } = await request.json(); + const body = (await request.json()) as { + email: string; + name: string; + message: string; + }; + const { email, name, message } = body; const user = process.env.MY_EMAIL ?? ""; const pass = process.env.MY_PASSWORD ?? ""; @@ -38,7 +43,7 @@ export async function POST(request: NextRequest) { from: user, to: user, // Ensure this is the correct email address subject: `Message from ${name} (${email})`, - text: message + `\n\nSent from ${email}`, + text: message + "\n\n" + email, }; const sendMailPromise = () => diff --git a/app/api/sitemap/route.tsx b/app/api/sitemap/route.tsx index e1c10b7..3c45630 100644 --- a/app/api/sitemap/route.tsx +++ b/app/api/sitemap/route.tsx @@ -17,40 +17,20 @@ interface SitemapRoute { const baseUrl = process.env.NEXT_PUBLIC_BASE_URL || "https://dki.one"; const generateSitemap = async (): Promise => { + // Static pages + const staticRoutes: SitemapRoute[] = [ + { url: `${baseUrl}/`, lastModified: new Date().toISOString() }, + { + url: `${baseUrl}/privacy-policy`, + lastModified: new Date().toISOString(), + }, + { + url: `${baseUrl}/legal-notice`, + lastModified: new Date().toISOString(), + }, + ]; + try { - // Static pages - const staticRoutes: SitemapRoute[] = [ - { url: `${baseUrl}/`, lastModified: new Date().toISOString() }, - { - url: `${baseUrl}/privacy-policy`, - lastModified: new Date().toISOString(), - }, - { - url: `${baseUrl}/legal-notice`, - lastModified: new Date().toISOString(), - }, - ]; - - // Check if running in build environment - if (process.env.IS_BUILD) { - console.log("Running in build mode - using mock data"); - const mockProjectsData: ProjectsData = { - posts: [ - { slug: "project-1" }, - { slug: "project-2" }, - { slug: "project-3" }, - ], - }; - const projectRoutes: SitemapRoute[] = mockProjectsData.posts.map( - (project) => ({ - url: `${baseUrl}/projects/${project.slug}`, - lastModified: new Date().toISOString(), - }), - ); - return [...staticRoutes, ...projectRoutes]; - } - - // Fetch project data from API console.log("Fetching project data from API..."); const response = await fetch(`${baseUrl}/api/fetchAllProjects`, { headers: { "Cache-Control": "no-cache" }, @@ -58,13 +38,13 @@ const generateSitemap = async (): Promise => { if (!response.ok) { console.error(`Failed to fetch projects: ${response.statusText}`); - return staticRoutes; // Return static pages instead of throwing an error + return staticRoutes; // Fallback auf statische Seiten } const projectsData = (await response.json()) as ProjectsData; console.log("Fetched project data:", projectsData); - // Generate dynamic routes for projects + // Dynamische Projekt-Routen generieren const projectRoutes: SitemapRoute[] = projectsData.posts.map((project) => ({ url: `${baseUrl}/projects/${project.slug}`, lastModified: project.updated_at @@ -75,7 +55,7 @@ const generateSitemap = async (): Promise => { return [...staticRoutes, ...projectRoutes]; } catch (error) { console.error("Failed to generate sitemap:", error); - return staticRoutes; // Return static pages in case of failure + return staticRoutes; // Fallback nur auf statische Seiten } }; diff --git a/app/components/Contact.tsx b/app/components/Contact.tsx index f221f96..1ea0f99 100644 --- a/app/components/Contact.tsx +++ b/app/components/Contact.tsx @@ -1,87 +1,106 @@ -import React, {useEffect, useState} from "react"; -import {sendEmail} from "@/app/utils/send-email"; +import React, { useEffect, useState } from "react"; +import { sendEmail } from "@/app/utils/send-email"; -export type FormData = { - name: string; - email: string; - message: string; -} +export type ContactFormData = { + name: string; + email: string; + message: string; +}; export default function Contact() { - const [isVisible, setIsVisible] = useState(false); - const [banner, setBanner] = useState<{ show: boolean, message: string, type: 'success' | 'error' }>({ - show: false, - message: '', - type: 'success' - }); + const [isVisible, setIsVisible] = useState(false); + const [banner, setBanner] = useState<{ + show: boolean; + message: string; + type: "success" | "error"; + }>({ + show: false, + message: "", + type: "success", + }); - useEffect(() => { - setTimeout(() => { - setIsVisible(true); - }, 350); // Delay to start the animation after Projects - }, []); + useEffect(() => { + setTimeout(() => { + setIsVisible(true); + }, 350); // Delay to start the animation after Projects + }, []); - async function onSubmit(e: React.FormEvent) { - e.preventDefault(); - const form = e.currentTarget; - const data: FormData = { - name: (form.elements.namedItem('name') as HTMLInputElement).value, - email: (form.elements.namedItem('email') as HTMLInputElement).value, - message: (form.elements.namedItem('message') as HTMLTextAreaElement).value, - }; - const response = await sendEmail(data); - if (response.success) { - form.reset(); - } - setBanner({show: true, message: response.message, type: response.success ? 'success' : 'error'}); - setTimeout(() => { - setBanner({...banner, show: false}); - }, 3000); // Hide banner after 3 seconds + async function onSubmit(e: React.FormEvent) { + e.preventDefault(); + + const form = e.currentTarget as HTMLFormElement; + const formData = new FormData(form); + + const data: ContactFormData = { + name: formData.get("name") as string, + email: formData.get("email") as string, + message: formData.get("message") as string, + }; + + // Convert FormData to a plain object + const jsonData = JSON.stringify(data); + + const response = await sendEmail(jsonData); + if (response.success) { + form.reset(); } - return ( -
-

- Contact Me -

-
- {banner.show && ( -
- {banner.message} -
- )} -
- - - - -
-
-
- ); -} \ No newline at end of file + setBanner({ + show: true, + message: response.message, + type: response.success ? "success" : "error", + }); + setTimeout(() => { + setBanner((prev) => ({ ...prev, show: false })); + }, 3000); + } + + return ( +
+

+ Contact Me +

+
+ {banner.show && ( +
+ {banner.message} +
+ )} +
+ + + + +
+
+
+ ); +} diff --git a/app/utils/send-email.tsx b/app/utils/send-email.tsx index 51ff683..c2d44a2 100644 --- a/app/utils/send-email.tsx +++ b/app/utils/send-email.tsx @@ -1,17 +1,20 @@ -import {FormData} from "@/app/components/Contact"; +export function sendEmail( + data: string, +): Promise<{ success: boolean; message: string }> { + const apiEndpoint = "/api/email"; -export function sendEmail(data: FormData): Promise<{ success: boolean, message: string }> { - const apiEndpoint = '/api/email'; - - return fetch(apiEndpoint, { - method: 'POST', - body: JSON.stringify(data), + return fetch(apiEndpoint, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: data, + }) + .then((res) => res.json()) + .then((response) => { + return { success: true, message: response.message }; }) - .then((res) => res.json()) - .then((response) => { - return {success: true, message: response.message}; - }) - .catch((err) => { - return {success: false, message: err.message}; - }); -} \ No newline at end of file + .catch((err) => { + return { success: false, message: err.message }; + }); +}