chore: transfer repo
This commit is contained in:
202
components/ui/ContactForm.tsx
Normal file
202
components/ui/ContactForm.tsx
Normal file
@@ -0,0 +1,202 @@
|
||||
'use client';
|
||||
|
||||
import { Button } from '@/components/ui/Button';
|
||||
import { Checkbox } from '@/components/ui/Checkbox';
|
||||
import { Heading, Label, Text } from '@/components/ui/Typography';
|
||||
import { useState } from 'react';
|
||||
|
||||
interface ContactFormProps {
|
||||
title?: string;
|
||||
subtitle?: string;
|
||||
}
|
||||
|
||||
export function ContactForm({ title = 'Kontaktiraj nas', subtitle = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.' }: ContactFormProps) {
|
||||
// Form state
|
||||
const [formData, setFormData] = useState({
|
||||
name: '',
|
||||
email: '',
|
||||
message: '',
|
||||
acceptTerms: false
|
||||
});
|
||||
|
||||
// Validation errors
|
||||
const [errors, setErrors] = useState<Record<string, string>>({});
|
||||
|
||||
// Form submission status
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
const [isSubmitted, setIsSubmitted] = useState(false);
|
||||
|
||||
// Handle input changes
|
||||
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
|
||||
const { name, value, type } = e.target;
|
||||
|
||||
// Handle checkbox
|
||||
if (type === 'checkbox') {
|
||||
const checked = (e.target as HTMLInputElement).checked;
|
||||
setFormData(prev => ({ ...prev, [name]: checked }));
|
||||
} else {
|
||||
setFormData(prev => ({ ...prev, [name]: value }));
|
||||
}
|
||||
|
||||
// Clear error when user starts typing
|
||||
if (errors[name]) {
|
||||
setErrors(prev => {
|
||||
const newErrors = { ...prev };
|
||||
delete newErrors[name];
|
||||
return newErrors;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Handle checkbox change specifically
|
||||
const handleCheckboxChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const { name, checked } = e.target;
|
||||
setFormData(prev => ({ ...prev, [name]: checked }));
|
||||
|
||||
// Clear error when user changes checkbox
|
||||
if (errors[name]) {
|
||||
setErrors(prev => {
|
||||
const newErrors = { ...prev };
|
||||
delete newErrors[name];
|
||||
return newErrors;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Validate form
|
||||
const validateForm = () => {
|
||||
const newErrors: Record<string, string> = {};
|
||||
|
||||
// Name validation
|
||||
if (!formData.name.trim()) {
|
||||
newErrors.name = 'Molimo unesite vaše ime i prezime';
|
||||
}
|
||||
|
||||
// Email validation
|
||||
if (!formData.email.trim()) {
|
||||
newErrors.email = 'Molimo unesite vašu email adresu';
|
||||
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) {
|
||||
newErrors.email = 'Molimo unesite ispravnu email adresu';
|
||||
}
|
||||
|
||||
// Message validation
|
||||
if (!formData.message.trim()) {
|
||||
newErrors.message = 'Molimo unesite vašu poruku';
|
||||
} else if (formData.message.trim().length < 10) {
|
||||
newErrors.message = 'Vaša poruka mora sadržavati barem 10 znakova';
|
||||
}
|
||||
|
||||
// Terms validation
|
||||
if (!formData.acceptTerms) {
|
||||
newErrors.acceptTerms = 'Molimo prihvatite uvjete korištenja';
|
||||
}
|
||||
|
||||
setErrors(newErrors);
|
||||
return Object.keys(newErrors).length === 0;
|
||||
};
|
||||
|
||||
// Handle form submission
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
|
||||
if (validateForm()) {
|
||||
setIsSubmitting(true);
|
||||
|
||||
// Simulate API call
|
||||
setTimeout(() => {
|
||||
setIsSubmitting(false);
|
||||
setIsSubmitted(true);
|
||||
|
||||
// Reset form after submission
|
||||
setFormData({
|
||||
name: '',
|
||||
email: '',
|
||||
message: '',
|
||||
acceptTerms: false
|
||||
});
|
||||
|
||||
// Hide success message after 5 seconds
|
||||
setTimeout(() => {
|
||||
setIsSubmitted(false);
|
||||
}, 5000);
|
||||
}, 1000);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Heading level={2} className="mb-4">{title}</Heading>
|
||||
<Text size="lg" className="mb-8">{subtitle}</Text>
|
||||
|
||||
{isSubmitted ? (
|
||||
<div className="p-4 bg-green-50 border border-green-200 rounded-md mb-6">
|
||||
<Text className="text-green-700 font-medium">Vaša poruka je uspješno poslana!</Text>
|
||||
<Text className="text-green-600">Hvala vam na vašem upitu. Odgovorit ćemo vam u najkraćem mogućem roku.</Text>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
<form className="space-y-6" onSubmit={handleSubmit}>
|
||||
<div>
|
||||
<Label htmlFor="name" className="block mb-2 text-[16px] leading-[24px]">Ime i Prezime</Label>
|
||||
<input
|
||||
type="text"
|
||||
id="name"
|
||||
name="name"
|
||||
value={formData.name}
|
||||
onChange={handleChange}
|
||||
className={`w-full p-3 border ${errors.name ? 'border-red-500' : 'border-gray-300'} rounded`}
|
||||
/>
|
||||
{errors.name && <Text size="sm" className="mt-1 text-red-500">{errors.name}</Text>}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label htmlFor="email" className="block mb-2 text-[16px] leading-[24px]">Email</Label>
|
||||
<input
|
||||
type="email"
|
||||
id="email"
|
||||
name="email"
|
||||
value={formData.email}
|
||||
onChange={handleChange}
|
||||
className={`w-full p-3 border ${errors.email ? 'border-red-500' : 'border-gray-300'} rounded`}
|
||||
/>
|
||||
{errors.email && <Text size="sm" className="mt-1 text-red-500">{errors.email}</Text>}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label htmlFor="message" className="block mb-2 text-[16px] leading-[24px]">Poruka</Label>
|
||||
<textarea
|
||||
id="message"
|
||||
name="message"
|
||||
value={formData.message}
|
||||
onChange={handleChange}
|
||||
rows={5}
|
||||
className={`w-full p-3 border ${errors.message ? 'border-red-500' : 'border-gray-300'} rounded`}
|
||||
placeholder="Upišite vašu poruku..."
|
||||
/>
|
||||
{errors.message && <Text size="sm" className="mt-1 text-red-500">{errors.message}</Text>}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Checkbox
|
||||
id="acceptTerms"
|
||||
name="acceptTerms"
|
||||
checked={formData.acceptTerms}
|
||||
onChange={handleCheckboxChange}
|
||||
label="Prihvaćam uvjete korištenja"
|
||||
className={errors.acceptTerms ? "ring-2 ring-red-500 rounded-sm" : ""}
|
||||
/>
|
||||
{errors.acceptTerms && <Text size="sm" className="mt-1 text-red-500">{errors.acceptTerms}</Text>}
|
||||
</div>
|
||||
|
||||
<Button
|
||||
type="submit"
|
||||
variant="primary"
|
||||
className="px-8 py-3 bg-black text-white"
|
||||
disabled={isSubmitting}
|
||||
>
|
||||
{isSubmitting ? 'Slanje...' : 'Pošalji'}
|
||||
</Button>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user