diff --git a/docker-compose.yml b/docker-compose.yml index dce8137..e624a1d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,9 +7,15 @@ services: - "3040:3000" # Kannst du später sogar löschen, wenn es nur noch über Caddy laufen soll environment: - NODE_ENV=production + - SES_SMTP_HOST=${SES_SMTP_HOST:-email-smtp.us-east-2.amazonaws.com} + - SES_SMTP_PORT=${SES_SMTP_PORT:-587} + - SES_SMTP_USER=${SES_SMTP_USER} + - SES_SMTP_PASS=${SES_SMTP_PASS} + - SES_FROM_EMAIL=${SES_FROM_EMAIL:-website@buddelectric.net} + - SES_TO_EMAIL=${SES_TO_EMAIL:-buddelectric@grandecom.net} networks: - bizmatch # <-- NEU: Container ins selbe Netz wie Caddy hängen networks: # <-- NEU: Netzwerk deklarieren bizmatch: - external: true \ No newline at end of file + external: true diff --git a/package-lock.json b/package-lock.json index 2c5ed31..a54d9c2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,12 +10,14 @@ "dependencies": { "lucide-react": "^0.563.0", "next": "16.1.6", + "nodemailer": "^9.0.1", "react": "19.2.3", "react-dom": "19.2.3" }, "devDependencies": { "@tailwindcss/postcss": "^4", "@types/node": "^20", + "@types/nodemailer": "^8.0.1", "@types/react": "^19", "@types/react-dom": "^19", "eslint": "^9", @@ -1556,6 +1558,16 @@ "undici-types": "~6.21.0" } }, + "node_modules/@types/nodemailer": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-8.0.1.tgz", + "integrity": "sha512-PxpaInm8V1JQDd4j0ds5HfvWQk8JupS1C0Picb96QJsrrRDjBH+DlK7L4ZdNSqNULhiZRQHc40nLVShaGxXAMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/react": { "version": "19.2.13", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.13.tgz", @@ -5046,6 +5058,15 @@ "dev": true, "license": "MIT" }, + "node_modules/nodemailer": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-9.0.1.tgz", + "integrity": "sha512-Gwv8SQewT616ZM/URn0H54b8PWo/Wum7md3EW2aWy1lO27+WZCX+Xyak3J+NlmHUjDh5ME+uesJUDRbR3Ye8Bw==", + "license": "MIT-0", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", diff --git a/package.json b/package.json index 3eec582..77893fd 100644 --- a/package.json +++ b/package.json @@ -11,12 +11,14 @@ "dependencies": { "lucide-react": "^0.563.0", "next": "16.1.6", + "nodemailer": "^9.0.1", "react": "19.2.3", "react-dom": "19.2.3" }, "devDependencies": { "@tailwindcss/postcss": "^4", "@types/node": "^20", + "@types/nodemailer": "^8.0.1", "@types/react": "^19", "@types/react-dom": "^19", "eslint": "^9", diff --git a/public/images/newspaper.webp b/public/images/newspaper.webp new file mode 100644 index 0000000..8144aa1 Binary files /dev/null and b/public/images/newspaper.webp differ diff --git a/src/app/about-us/page.tsx b/src/app/about-us/page.tsx index a39ae7e..b4d8f04 100644 --- a/src/app/about-us/page.tsx +++ b/src/app/about-us/page.tsx @@ -1,7 +1,8 @@ -import { Shield, CheckCircle2, Award, Clock } from "lucide-react"; +import { Shield, Award, Clock } from "lucide-react"; import Link from "next/link"; import Image from "next/image"; import { Metadata } from "next"; +import NewspaperClipping from "@/components/NewspaperClipping"; export const metadata: Metadata = { title: "About Budd Electric Co. | Family-Owned Since 1969", @@ -37,18 +38,8 @@ export default function AboutUs() {
-
- Budd Electric professional electrician team working on residential electrical services -
-
+ +

Who We Are

Three Generations of Excellence

@@ -65,13 +56,13 @@ export default function AboutUs() { 1969 Established
-
- 3rd Gen - Master Electricians -
+
+ 3rd Gen + Master Electricians +
- + diff --git a/src/app/api/contact/route.ts b/src/app/api/contact/route.ts new file mode 100644 index 0000000..30cb40a --- /dev/null +++ b/src/app/api/contact/route.ts @@ -0,0 +1,79 @@ +import { NextRequest, NextResponse } from "next/server"; +import nodemailer from "nodemailer"; + +export async function POST(request: NextRequest) { + try { + const body = await request.json(); + const { firstName, lastName, email, phone, serviceType, message } = body; + + if (!firstName || typeof firstName !== "string" || firstName.trim().length === 0) { + return NextResponse.json({ error: "First name is required." }, { status: 400 }); + } + if (!lastName || typeof lastName !== "string" || lastName.trim().length === 0) { + return NextResponse.json({ error: "Last name is required." }, { status: 400 }); + } + if (!email || typeof email !== "string" || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) { + return NextResponse.json({ error: "A valid email address is required." }, { status: 400 }); + } + if (!phone || typeof phone !== "string" || phone.trim().length === 0) { + return NextResponse.json({ error: "Phone number is required." }, { status: 400 }); + } + if (!serviceType || typeof serviceType !== "string" || serviceType.trim().length === 0) { + return NextResponse.json({ error: "Please select a service type." }, { status: 400 }); + } + if (!message || typeof message !== "string" || message.trim().length === 0) { + return NextResponse.json({ error: "Message is required." }, { status: 400 }); + } + + const smtpHost = process.env.SES_SMTP_HOST || "email-smtp.us-east-2.amazonaws.com"; + const smtpPort = parseInt(process.env.SES_SMTP_PORT || "587", 10); + const smtpUser = process.env.SES_SMTP_USER; + const smtpPass = process.env.SES_SMTP_PASS; + const fromEmail = process.env.SES_FROM_EMAIL || "website@buddelectric.net"; + const toEmail = process.env.SES_TO_EMAIL || "buddelectric@grandecom.net"; + + if (!smtpUser || !smtpPass) { + return NextResponse.json({ error: "Email service is not configured." }, { status: 500 }); + } + + const transporter = nodemailer.createTransport({ + host: smtpHost, + port: smtpPort, + secure: false, + auth: { + user: smtpUser, + pass: smtpPass, + }, + }); + + const serviceTypeLabels: Record = { + residential: "Residential Service", + commercial: "Commercial Project", + generator: "Generator Quote", + other: "Other", + }; + + const htmlBody = ` +

New Contact Form Submission

+ + + + + + +
Name${firstName} ${lastName}
Email${email}
Phone${phone}
Service Type${serviceTypeLabels[serviceType] || serviceType}
Message${message}
+ `; + + await transporter.sendMail({ + from: fromEmail, + to: toEmail, + replyTo: email, + subject: `New Contact Form Submission from ${firstName} ${lastName}`, + html: htmlBody, + }); + + return NextResponse.json({ success: true }, { status: 200 }); + } catch { + return NextResponse.json({ error: "Failed to send your message. Please try again or call us directly." }, { status: 500 }); + } +} diff --git a/src/app/contact-us/page.tsx b/src/app/contact-us/page.tsx index 4d42425..2154d37 100644 --- a/src/app/contact-us/page.tsx +++ b/src/app/contact-us/page.tsx @@ -1,6 +1,7 @@ -import { MapPin, Phone, Mail, Clock } from "lucide-react"; -import { Metadata } from "next"; -import Image from "next/image"; +import { MapPin, Phone, Mail, Clock } from "lucide-react"; +import { Metadata } from "next"; +import Image from "next/image"; +import ContactForm from "@/components/ContactForm"; export const metadata: Metadata = { title: "Contact Budd Electric Co. | Corpus Christi Electrician", @@ -99,41 +100,7 @@ export default function Contact() { {/* FORM */}

Send us a Message

-
-
-
- - -
-
- - -
-
-
- - -
-
- - -
-
- - -
-
- - -
- -
+
diff --git a/src/app/electrical-services/page.tsx b/src/app/electrical-services/page.tsx index e8984d6..7127e0a 100644 --- a/src/app/electrical-services/page.tsx +++ b/src/app/electrical-services/page.tsx @@ -1,12 +1,12 @@ -import { Home, Phone, Zap, Factory } from "lucide-react"; +import { Home, Zap, Building2 } from "lucide-react"; import Link from "next/link"; import Image from "next/image"; import { ArrowRight } from "lucide-react"; import { Metadata } from "next"; export const metadata: Metadata = { - title: "Electrical Services Corpus Christi | Residential & Commercial", - description: "Professional residential, commercial, and industrial electrical services in Corpus Christi, TX. Licensed electricians for all your electrical needs. Call (361) 855-2255.", + title: "Electrical Services Corpus Christi | Commercial & Residential", + description: "Professional commercial and residential electrical services in Corpus Christi, TX. Licensed electricians for all your electrical needs. Call (361) 855-2255.", }; export default function Services() { @@ -28,7 +28,7 @@ export default function Services() {

Electrical Services

- Comprehensive solutions for every need. Residential, Commercial, and Industrial. + Comprehensive solutions for every need. Commercial and Residential electrical services.

@@ -36,15 +36,79 @@ export default function Services() { {/* SERVICE LIST */}
+ {/* COMMERCIAL */} +
+
+
+ +
+

Commercial & Residential Electrical Remodels

+

+ We are your wiring, lighting and electrical service upgrade specialists in Corpus Christi and all of South Texas. We have encountered all the standard common electrical problems and have the experience, knowledge, skill, and expertise to solve them all. Our electrical repair expertise includes faulty outlets, panel reinstallation, meter replacement, new lighting fixtures, and adding circuits to your fuse box. Call Budd Electric Co. for a complimentary electrical repair consultation or free quote at (361) 855-2255. +

+
    + {["Commercial & Residential", "Complete Electrical Service Upgrades", "Electrical Repairs"].map((item, i) => ( +
  • + + {item} +
  • + ))} +
+
+
+ Commercial electrical wiring and service upgrades +
+
+ + {/* GENERATORS */} +
+
+ Kohler whole-home standby generator installation and service +
+
+
+ +
+

Kohler Generators

+

+ Don't be left in the dark during a storm. As an authorized Kohler dealer, we sell, install, and service standby generators to keep your power on when the grid goes down. +

+
    + {["Sales & Consultation", "Professional Installation", "Maintenance Plans", "Warranty Service", "Transfer Switch Install"].map((item, i) => ( +
  • + + {item} +
  • + ))} +
+
+
+ {/* RESIDENTIAL */} -
+

Residential Services

- Your home is your sanctuary. We ensure it's powered safely and efficiently. From simple outlet repairs to full-home rewiring, no job is too small or too complex. + Your home is your sanctuary. We ensure it's powered safely and efficiently. From simple outlet repairs to full-home rewiring, no job is too small or too complex.

    {["Service Upgrades", "Safety Inspections", "Lighting Installation", "Ceiling Fans", "Outlet Repair", "Panel Replacement"].map((item, i) => ( @@ -56,83 +120,19 @@ export default function Services() {
- Professional residential electrical wiring and home electrical services -
-
- - {/* COMMERCIAL */} -
-
- Commercial and industrial electrical wiring and services -
-
-
- -
-

Commercial & Industrial

-

- Keep your business running smoothly with our expert commercial services. We handle everything from new construction build-outs to ongoing maintenance contracts. -

-
    - {["New Construction Wiring", "Tenant Build-outs", "Parking Lot Lighting", "Emergency Lighting", "Data Cabling", "Troubleshooting"].map((item, i) => ( -
  • - - {item} -
  • - ))} -
-
-
- - {/* GENERATORS */} -
-
-
- -
-

Kohler Generators

-

- Don't be left in the dark during a storm. As an authorized Kohler dealer, we sell, install, and service standby generators to keep your power on when the grid goes down. -

-
    - {["Sales & Consultation", "Professional Installation", "Maintenance Plans", "Warranty Service", "Transfer Switch Install"].map((item, i) => ( -
  • - - {item} -
  • - ))} -
-
-
- Kohler whole-home standby generator installation and service + Professional residential electrical wiring and home electrical services
-
+ {/* CTA */}
diff --git a/src/app/page.tsx b/src/app/page.tsx index f6dce27..71d8e4c 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,6 +1,6 @@ import Link from "next/link"; import Image from "next/image"; -import { ArrowRight, Zap, Shield, Home as HomeIcon, Factory, HardHat, CheckCircle2, Star, Clock, MapPin, Phone } from "lucide-react"; +import { ArrowRight, Zap, Shield, Home as HomeIcon, Building2, CheckCircle2, Star, Clock, MapPin, Phone } from "lucide-react"; import ReviewCarousel from "@/components/ReviewCarousel"; import HeroCarousel from "@/components/HeroCarousel"; import FAQSection from "@/components/FAQSection"; @@ -56,16 +56,12 @@ export default function Home() { -
-
- - Licensed & Insured -
-
- - 24/7 Emergency Support -
-
+
+
+ + Licensed & Insured +
+
@@ -94,31 +90,31 @@ export default function Home() {
-

Residential

+

Residential Services

Complete home electrical services including safety inspections, repairs, lighting, and fan installations.

- Residential Services + Residential Services
- {/* Card 2 */} -
-
-
- -
-
-
- -
-

Commercial

-

- Reliable power for your business. New construction, maintenance, and industrial-grade solutions. -

- Commercial Services -
-
+ {/* Card 2 */} +
+
+
+ +
+
+
+ +
+

Commercial & Residential Electrical Remodels

+

+ Commercial & residential electrical remodels, wiring, lighting, and service upgrades for Corpus Christi and South Texas. +

+ Commercial Services +
+
{/* Card 3 */}
@@ -127,11 +123,11 @@ export default function Home() {
-

Generators

+

Kohler Generators

Authorized Kohler dealer. Keep your lights on when the grid goes down with standby power.

- Generator Services + Kohler Generator Services
diff --git a/src/components/ContactForm.tsx b/src/components/ContactForm.tsx new file mode 100644 index 0000000..670d0d4 --- /dev/null +++ b/src/components/ContactForm.tsx @@ -0,0 +1,95 @@ +"use client"; + +import { useState } from "react"; + +export default function ContactForm() { + const [formData, setFormData] = useState({ + firstName: "", + lastName: "", + email: "", + phone: "", + serviceType: "", + message: "", + }); + const [status, setStatus] = useState<"idle" | "loading" | "success" | "error">("idle"); + const [statusMessage, setStatusMessage] = useState(""); + + const handleChange = (e: React.ChangeEvent) => { + setFormData((prev) => ({ ...prev, [e.target.name]: e.target.value })); + }; + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setStatus("loading"); + setStatusMessage(""); + + try { + const res = await fetch("/api/contact", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(formData), + }); + const data = await res.json(); + + if (res.ok) { + setStatus("success"); + setStatusMessage("Thank you! Your message has been sent. We'll get back to you shortly."); + setFormData({ firstName: "", lastName: "", email: "", phone: "", serviceType: "", message: "" }); + } else { + setStatus("error"); + setStatusMessage(data.error || "Something went wrong. Please try again."); + } + } catch { + setStatus("error"); + setStatusMessage("Network error. Please check your connection and try again."); + } + }; + + return ( +
+
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ + {status === "success" && ( +
{statusMessage}
+ )} + {status === "error" && ( +
{statusMessage}
+ )} + + +
+ ); +} diff --git a/src/components/Header.tsx b/src/components/Header.tsx index 314c39f..15aafa4 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -45,7 +45,7 @@ export default function Header() { href="/contact-us" className="hidden lg:flex items-center gap-2 rounded bg-[color:var(--brand)] px-5 py-2.5 text-sm font-bold text-white shadow-lg shadow-red-900/20 transition hover:bg-[color:var(--brand-strong)] uppercase tracking-wider" > - Free Quote + Contact Us +
e.stopPropagation()} + > + Budd Electric Co. featured in the local newspaper +
+ + )} + + ); +}