From f2a3f47e070c9057facc41083442ee621c949a4a Mon Sep 17 00:00:00 2001 From: KNSONWS Date: Tue, 3 Feb 2026 16:05:36 +0100 Subject: [PATCH] form --- .env.example | 4 ++++ .gitignore | 1 + package-lock.json | 26 ++++++++++++++++++++++++++ package.json | 1 + src/lib/appwrite.ts | 42 ++++++++++++++++++++++++++++++++++++++++++ src/pages/Contact.tsx | 28 ++++++++++++++++++---------- src/vite-env.d.ts | 11 +++++++++++ 7 files changed, 103 insertions(+), 10 deletions(-) create mode 100644 .env.example create mode 100644 src/lib/appwrite.ts diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..9a233fb --- /dev/null +++ b/.env.example @@ -0,0 +1,4 @@ +VITE_APPWRITE_PROJECT_ID="696b82270034001dab69" +VITE_APPWRITE_ENDPOINT="https://appwrite.webklar.com/v1" +VITE_APPWRITE_DATABASE_ID="contacts" +VITE_APPWRITE_CONTACT_COLLECTION_ID="messages" diff --git a/.gitignore b/.gitignore index a547bf3..438657a 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ node_modules dist dist-ssr *.local +.env # Editor directories and files .vscode/* diff --git a/package-lock.json b/package-lock.json index d46d86c..05f0bdd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -39,6 +39,7 @@ "@react-three/fiber": "^8.18.0", "@tabler/icons-react": "^3.36.1", "@tanstack/react-query": "^5.83.0", + "appwrite": "^22.0.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "cmdk": "^1.1.1", @@ -3770,6 +3771,15 @@ "node": ">= 8" } }, + "node_modules/appwrite": { + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/appwrite/-/appwrite-22.0.0.tgz", + "integrity": "sha512-iFlfshYttuQheIyar6m789+Z/gvfKWQxWQCDhHzH9cEkFkn+laJZV8nMvGRH+1rTYNfAcFuycWKBGZiEDFxXug==", + "dependencies": { + "bignumber.js": "9.0.0", + "json-bigint": "1.0.0" + } + }, "node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", @@ -3886,6 +3896,14 @@ ], "license": "MIT" }, + "node_modules/bignumber.js": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", + "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==", + "engines": { + "node": "*" + } + }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -5742,6 +5760,14 @@ "node": ">=6" } }, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", diff --git a/package.json b/package.json index 6bcdbc7..dd1850d 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "@react-three/fiber": "^8.18.0", "@tabler/icons-react": "^3.36.1", "@tanstack/react-query": "^5.83.0", + "appwrite": "^22.0.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "cmdk": "^1.1.1", diff --git a/src/lib/appwrite.ts b/src/lib/appwrite.ts new file mode 100644 index 0000000..22178dc --- /dev/null +++ b/src/lib/appwrite.ts @@ -0,0 +1,42 @@ +/** + * Appwrite-Anbindung für das Kontaktformular. + * + * In der Appwrite Console anlegen: + * 1. Database (z. B. ID: "contacts") + * 2. Collection (z. B. ID: "messages") mit String-Attributen: name, email, company, message + * 3. Unter "Settings" der Collection: Create-Berechtigung für "Any" aktivieren (öffentliches Formular) + * 4. IDs in .env setzen: VITE_APPWRITE_DATABASE_ID, VITE_APPWRITE_CONTACT_COLLECTION_ID + */ +import { Client, Databases, ID } from "appwrite"; + +const client = new Client() + .setEndpoint(import.meta.env.VITE_APPWRITE_ENDPOINT) + .setProject(import.meta.env.VITE_APPWRITE_PROJECT_ID); + +const databases = new Databases(client); + +const CONTACT_DATABASE_ID = import.meta.env.VITE_APPWRITE_DATABASE_ID ?? "698124a20035e8f6dc42"; +const CONTACT_COLLECTION_ID = import.meta.env.VITE_APPWRITE_CONTACT_COLLECTION_ID ?? "contact_submissions"; + +export type ContactFormData = { + name: string; + email: string; + company: string; + message: string; +}; + +export async function createContactDocument(data: ContactFormData) { + return databases.createDocument( + CONTACT_DATABASE_ID, + CONTACT_COLLECTION_ID, + ID.unique(), + { + name: data.name, + email: data.email, + company: data.company, + message: data.message, + } + ); +} + +export { client, databases }; diff --git a/src/pages/Contact.tsx b/src/pages/Contact.tsx index eed2979..70682d8 100644 --- a/src/pages/Contact.tsx +++ b/src/pages/Contact.tsx @@ -6,6 +6,7 @@ import { Textarea } from "@/components/ui/textarea"; import { Label } from "@/components/ui/label"; import { ArrowLeft, Send } from "lucide-react"; import { useToast } from "@/hooks/use-toast"; +import { createContactDocument } from "@/lib/appwrite"; const Contact = () => { const { toast } = useToast(); @@ -30,16 +31,23 @@ const Contact = () => { e.preventDefault(); setIsSubmitting(true); - // Simulate form submission - await new Promise((resolve) => setTimeout(resolve, 1000)); - - toast({ - title: "Nachricht gesendet!", - description: "Wir melden uns innerhalb von 24 Stunden bei Ihnen.", - }); - - setFormData({ name: "", email: "", company: "", message: "" }); - setIsSubmitting(false); + try { + await createContactDocument(formData); + toast({ + title: "Nachricht gesendet!", + description: "Wir melden uns innerhalb von 24 Stunden bei Ihnen.", + }); + setFormData({ name: "", email: "", company: "", message: "" }); + } catch (err) { + const message = err instanceof Error ? err.message : "Speichern fehlgeschlagen."; + toast({ + variant: "destructive", + title: "Fehler beim Senden", + description: message, + }); + } finally { + setIsSubmitting(false); + } }; return ( diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts index 11f02fe..c98094c 100644 --- a/src/vite-env.d.ts +++ b/src/vite-env.d.ts @@ -1 +1,12 @@ /// + +interface ImportMetaEnv { + readonly VITE_APPWRITE_PROJECT_ID: string; + readonly VITE_APPWRITE_ENDPOINT: string; + readonly VITE_APPWRITE_DATABASE_ID?: string; + readonly VITE_APPWRITE_CONTACT_COLLECTION_ID?: string; +} + +interface ImportMeta { + readonly env: ImportMetaEnv; +}