fix: updated contact information in imprint & /contact page
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import { Modal } from '../ui/Modal';
|
import { Modal } from "../ui/Modal";
|
||||||
import { useTranslation } from '../../i18n';
|
import { useTranslation } from "../../i18n";
|
||||||
import styles from './ImpressumModal.module.css';
|
import styles from "./ImpressumModal.module.css";
|
||||||
|
|
||||||
interface ImpressumModalProps {
|
interface ImpressumModalProps {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
@@ -16,8 +16,10 @@ export function ImpressumModal({ isOpen, onClose }: ImpressumModalProps) {
|
|||||||
<section>
|
<section>
|
||||||
<h3>Angaben gemäß § 5 TMG</h3>
|
<h3>Angaben gemäß § 5 TMG</h3>
|
||||||
<p>
|
<p>
|
||||||
Melvin Ragusa<br />
|
Melvin Ragusa
|
||||||
Provinzialstraße 177<br />
|
<br />
|
||||||
|
Provinzialstraße 177
|
||||||
|
<br />
|
||||||
44388 Dortmund
|
44388 Dortmund
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
@@ -25,31 +27,38 @@ export function ImpressumModal({ isOpen, onClose }: ImpressumModalProps) {
|
|||||||
<section>
|
<section>
|
||||||
<h3>Kontakt</h3>
|
<h3>Kontakt</h3>
|
||||||
<p>
|
<p>
|
||||||
Telefon: 0160 95098973<br />
|
Telefon: 0160 95098973
|
||||||
E-Mail: info@ragusa-it.dev
|
<br />
|
||||||
|
E-Mail: kontakt@ragusa-it.dev
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<h3>Umsatzsteuer-ID</h3>
|
<h3>Umsatzsteuer-ID</h3>
|
||||||
<p>
|
<p>
|
||||||
Umsatzsteuer-Identifikationsnummer gemäß § 27 a Umsatzsteuergesetz:<br />
|
Umsatzsteuer-Identifikationsnummer gemäß § 27 a Umsatzsteuergesetz:
|
||||||
<em>Als Kleinunternehmer im Sinne von § 19 Abs. 1 UStG wird keine Umsatzsteuer berechnet.</em>
|
<br />
|
||||||
|
<em>
|
||||||
|
Als Kleinunternehmer im Sinne von § 19 Abs. 1 UStG wird keine
|
||||||
|
Umsatzsteuer berechnet.
|
||||||
|
</em>
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<h3>Redaktionell verantwortlich</h3>
|
<h3>Redaktionell verantwortlich</h3>
|
||||||
<p>
|
<p>
|
||||||
Melvin Ragusa<br />
|
Melvin Ragusa
|
||||||
Provinzialstraße 177<br />
|
<br />
|
||||||
|
Provinzialstraße 177
|
||||||
|
<br />
|
||||||
44388 Dortmund
|
44388 Dortmund
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<h3>Hinweis</h3>
|
<h3>Hinweis</h3>
|
||||||
<p>Kein Ladengeschäft. Termine nur nach Vereinbarung.</p>
|
<p>Kein Ladengeschäft. Termine nur nach Vereinbarung.</p>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
import { type ReactNode, useEffect } from 'react';
|
import { type ReactNode, useEffect } from "react";
|
||||||
import { createPortal } from 'react-dom';
|
import { createPortal } from "react-dom";
|
||||||
import { motion, AnimatePresence } from 'motion/react';
|
import { motion, AnimatePresence } from "motion/react";
|
||||||
import styles from './Modal.module.css';
|
import styles from "./Modal.module.css";
|
||||||
|
|
||||||
// I need to check if lucide-react is installed.
|
|
||||||
// Based on package list, react-icons is installed.
|
|
||||||
|
|
||||||
interface ModalProps {
|
interface ModalProps {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
@@ -17,22 +14,22 @@ export function Modal({ isOpen, onClose, title, children }: ModalProps) {
|
|||||||
// Prevent body scroll when modal is open
|
// Prevent body scroll when modal is open
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isOpen) {
|
if (isOpen) {
|
||||||
document.body.style.overflow = 'hidden';
|
document.body.style.overflow = "hidden";
|
||||||
} else {
|
} else {
|
||||||
document.body.style.overflow = 'unset';
|
document.body.style.overflow = "unset";
|
||||||
}
|
}
|
||||||
return () => {
|
return () => {
|
||||||
document.body.style.overflow = 'unset';
|
document.body.style.overflow = "unset";
|
||||||
};
|
};
|
||||||
}, [isOpen]);
|
}, [isOpen]);
|
||||||
|
|
||||||
// Close on escape key
|
// Close on escape key
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleEscape = (e: KeyboardEvent) => {
|
const handleEscape = (e: KeyboardEvent) => {
|
||||||
if (e.key === 'Escape') onClose();
|
if (e.key === "Escape") onClose();
|
||||||
};
|
};
|
||||||
window.addEventListener('keydown', handleEscape);
|
window.addEventListener("keydown", handleEscape);
|
||||||
return () => window.removeEventListener('keydown', handleEscape);
|
return () => window.removeEventListener("keydown", handleEscape);
|
||||||
}, [onClose]);
|
}, [onClose]);
|
||||||
|
|
||||||
return createPortal(
|
return createPortal(
|
||||||
@@ -88,6 +85,6 @@ export function Modal({ isOpen, onClose, title, children }: ModalProps) {
|
|||||||
</motion.div>
|
</motion.div>
|
||||||
)}
|
)}
|
||||||
</AnimatePresence>,
|
</AnimatePresence>,
|
||||||
document.body
|
document.body,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { useState, type FormEvent } from 'react';
|
import { useState, type FormEvent } from "react";
|
||||||
import { motion } from 'motion/react';
|
import { motion } from "motion/react";
|
||||||
import emailjs from '@emailjs/browser';
|
import emailjs from "@emailjs/browser";
|
||||||
import { useTranslation } from '../i18n';
|
import { useTranslation } from "../i18n";
|
||||||
import { config } from '../config';
|
import { config } from "../config";
|
||||||
import { Button, Input, Textarea } from '../components/ui';
|
import { Button, Input, Textarea } from "../components/ui";
|
||||||
import styles from './Contact.module.css';
|
import styles from "./Contact.module.css";
|
||||||
|
|
||||||
interface FormData {
|
interface FormData {
|
||||||
name: string;
|
name: string;
|
||||||
@@ -23,34 +23,36 @@ interface FormErrors {
|
|||||||
export function Contact() {
|
export function Contact() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [formData, setFormData] = useState<FormData>({
|
const [formData, setFormData] = useState<FormData>({
|
||||||
name: '',
|
name: "",
|
||||||
email: '',
|
email: "",
|
||||||
subject: '',
|
subject: "",
|
||||||
message: '',
|
message: "",
|
||||||
});
|
});
|
||||||
const [errors, setErrors] = useState<FormErrors>({});
|
const [errors, setErrors] = useState<FormErrors>({});
|
||||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||||
const [submitStatus, setSubmitStatus] = useState<'idle' | 'success' | 'error'>('idle');
|
const [submitStatus, setSubmitStatus] = useState<
|
||||||
|
"idle" | "success" | "error"
|
||||||
|
>("idle");
|
||||||
|
|
||||||
const validateForm = (): boolean => {
|
const validateForm = (): boolean => {
|
||||||
const newErrors: FormErrors = {};
|
const newErrors: FormErrors = {};
|
||||||
|
|
||||||
if (!formData.name.trim()) {
|
if (!formData.name.trim()) {
|
||||||
newErrors.name = 'Required';
|
newErrors.name = "Required";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!formData.email.trim()) {
|
if (!formData.email.trim()) {
|
||||||
newErrors.email = 'Required';
|
newErrors.email = "Required";
|
||||||
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) {
|
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) {
|
||||||
newErrors.email = 'Invalid email';
|
newErrors.email = "Invalid email";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!formData.subject.trim()) {
|
if (!formData.subject.trim()) {
|
||||||
newErrors.subject = 'Required';
|
newErrors.subject = "Required";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!formData.message.trim()) {
|
if (!formData.message.trim()) {
|
||||||
newErrors.message = 'Required';
|
newErrors.message = "Required";
|
||||||
}
|
}
|
||||||
|
|
||||||
setErrors(newErrors);
|
setErrors(newErrors);
|
||||||
@@ -63,7 +65,7 @@ export function Contact() {
|
|||||||
if (!validateForm()) return;
|
if (!validateForm()) return;
|
||||||
|
|
||||||
setIsSubmitting(true);
|
setIsSubmitting(true);
|
||||||
setSubmitStatus('idle');
|
setSubmitStatus("idle");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const templateParams = {
|
const templateParams = {
|
||||||
@@ -79,7 +81,7 @@ export function Contact() {
|
|||||||
config.emailJs.serviceId,
|
config.emailJs.serviceId,
|
||||||
config.emailJs.templateIdAdmin,
|
config.emailJs.templateIdAdmin,
|
||||||
templateParams,
|
templateParams,
|
||||||
{ publicKey: config.emailJs.publicKey }
|
{ publicKey: config.emailJs.publicKey },
|
||||||
);
|
);
|
||||||
|
|
||||||
// Send Auto-reply to User
|
// Send Auto-reply to User
|
||||||
@@ -87,14 +89,14 @@ export function Contact() {
|
|||||||
config.emailJs.serviceId,
|
config.emailJs.serviceId,
|
||||||
config.emailJs.templateIdUser,
|
config.emailJs.templateIdUser,
|
||||||
templateParams,
|
templateParams,
|
||||||
{ publicKey: config.emailJs.publicKey }
|
{ publicKey: config.emailJs.publicKey },
|
||||||
);
|
);
|
||||||
|
|
||||||
setSubmitStatus('success');
|
setSubmitStatus("success");
|
||||||
setFormData({ name: '', email: '', subject: '', message: '' });
|
setFormData({ name: "", email: "", subject: "", message: "" });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('EmailJS Error:', error);
|
console.error("EmailJS Error:", error);
|
||||||
setSubmitStatus('error');
|
setSubmitStatus("error");
|
||||||
} finally {
|
} finally {
|
||||||
setIsSubmitting(false);
|
setIsSubmitting(false);
|
||||||
}
|
}
|
||||||
@@ -141,7 +143,7 @@ export function Contact() {
|
|||||||
label={t.contact.form.name}
|
label={t.contact.form.name}
|
||||||
placeholder={t.contact.form.namePlaceholder}
|
placeholder={t.contact.form.namePlaceholder}
|
||||||
value={formData.name}
|
value={formData.name}
|
||||||
onChange={(e) => handleChange('name', e.target.value)}
|
onChange={(e) => handleChange("name", e.target.value)}
|
||||||
error={errors.name}
|
error={errors.name}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -150,7 +152,7 @@ export function Contact() {
|
|||||||
type="email"
|
type="email"
|
||||||
placeholder={t.contact.form.emailPlaceholder}
|
placeholder={t.contact.form.emailPlaceholder}
|
||||||
value={formData.email}
|
value={formData.email}
|
||||||
onChange={(e) => handleChange('email', e.target.value)}
|
onChange={(e) => handleChange("email", e.target.value)}
|
||||||
error={errors.email}
|
error={errors.email}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -158,7 +160,7 @@ export function Contact() {
|
|||||||
label={t.contact.form.subject}
|
label={t.contact.form.subject}
|
||||||
placeholder={t.contact.form.subjectPlaceholder}
|
placeholder={t.contact.form.subjectPlaceholder}
|
||||||
value={formData.subject}
|
value={formData.subject}
|
||||||
onChange={(e) => handleChange('subject', e.target.value)}
|
onChange={(e) => handleChange("subject", e.target.value)}
|
||||||
error={errors.subject}
|
error={errors.subject}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -166,7 +168,7 @@ export function Contact() {
|
|||||||
label={t.contact.form.message}
|
label={t.contact.form.message}
|
||||||
placeholder={t.contact.form.messagePlaceholder}
|
placeholder={t.contact.form.messagePlaceholder}
|
||||||
value={formData.message}
|
value={formData.message}
|
||||||
onChange={(e) => handleChange('message', e.target.value)}
|
onChange={(e) => handleChange("message", e.target.value)}
|
||||||
error={errors.message}
|
error={errors.message}
|
||||||
rows={6}
|
rows={6}
|
||||||
/>
|
/>
|
||||||
@@ -178,10 +180,12 @@ export function Contact() {
|
|||||||
isLoading={isSubmitting}
|
isLoading={isSubmitting}
|
||||||
disabled={isSubmitting}
|
disabled={isSubmitting}
|
||||||
>
|
>
|
||||||
{isSubmitting ? t.contact.form.sending : t.contact.form.submit}
|
{isSubmitting
|
||||||
|
? t.contact.form.sending
|
||||||
|
: t.contact.form.submit}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
{submitStatus === 'success' && (
|
{submitStatus === "success" && (
|
||||||
<motion.p
|
<motion.p
|
||||||
className={styles.success}
|
className={styles.success}
|
||||||
initial={{ opacity: 0, y: 10 }}
|
initial={{ opacity: 0, y: 10 }}
|
||||||
@@ -191,7 +195,7 @@ export function Contact() {
|
|||||||
</motion.p>
|
</motion.p>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{submitStatus === 'error' && (
|
{submitStatus === "error" && (
|
||||||
<motion.p
|
<motion.p
|
||||||
className={styles.error}
|
className={styles.error}
|
||||||
initial={{ opacity: 0, y: 10 }}
|
initial={{ opacity: 0, y: 10 }}
|
||||||
@@ -215,14 +219,21 @@ export function Contact() {
|
|||||||
<div className={styles.infoList}>
|
<div className={styles.infoList}>
|
||||||
<div className={styles.infoItem}>
|
<div className={styles.infoItem}>
|
||||||
<div className={styles.infoIcon}>
|
<div className={styles.infoIcon}>
|
||||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
<svg
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="2"
|
||||||
|
>
|
||||||
<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z" />
|
<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z" />
|
||||||
<polyline points="22,6 12,13 2,6" />
|
<polyline points="22,6 12,13 2,6" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h3>{t.contact.info.email}</h3>
|
<h3>{t.contact.info.email}</h3>
|
||||||
<a href="mailto:info@ragusa-it.dev">info@ragusa-it.dev</a>
|
<a href="mailto:kontakt@ragusa-it.dev">
|
||||||
|
kontakt@ragusa-it.dev
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user