Initial commit

This commit is contained in:
r2xrzh9q2z-lab
2026-02-02 11:00:08 +07:00
commit d53d4417b2
116 changed files with 79533 additions and 0 deletions

89
app/contact/contact.json Normal file
View File

@@ -0,0 +1,89 @@
{
"title": "Liên Hệ Với Chúng Tôi",
"subtitle": "Chúng tôi luôn sẵn sàng hỗ trợ bạn 24/7",
"contactInfo": {
"address": {
"label": "Địa chỉ",
"value": "123 Nguyễn Huệ, Quận 1, TP.HCM",
"icon": "📍"
},
"phone": {
"label": "Điện thoại",
"value": "+84 28 1234 5678",
"icon": "📞"
},
"email": {
"label": "Email",
"value": "info@visaservice.com",
"icon": "✉️"
},
"hours": {
"label": "Giờ làm việc",
"value": "Thứ 2 - Thứ 6: 8:00 - 18:00\nThứ 7: 8:00 - 12:00",
"icon": "🕒"
}
},
"offices": [
{
"name": "Văn Phòng TP.HCM",
"address": "123 Nguyễn Huệ, Quận 1, TP.HCM",
"phone": "+84 28 1234 5678",
"email": "hcm@visaservice.com"
},
{
"name": "Văn Phòng Hà Nội",
"address": "456 Hoàn Kiếm, Hà Nội",
"phone": "+84 24 1234 5678",
"email": "hanoi@visaservice.com"
},
{
"name": "Văn Phòng Đà Nẵng",
"address": "789 Hải Châu, Đà Nẵng",
"phone": "+84 236 1234 567",
"email": "danang@visaservice.com"
}
],
"formFields": [
{
"name": "fullName",
"label": "Họ và tên",
"type": "text",
"required": true,
"placeholder": "Nhập họ và tên của bạn"
},
{
"name": "email",
"label": "Email",
"type": "email",
"required": true,
"placeholder": "example@email.com"
},
{
"name": "phone",
"label": "Số điện thoại",
"type": "tel",
"required": true,
"placeholder": "+84 xxx xxx xxx"
},
{
"name": "service",
"label": "Dịch vụ quan tâm",
"type": "select",
"required": true,
"options": [
"Tư vấn visa",
"Chuẩn bị hồ sơ",
"Đặt vé máy bay",
"Tour trọn gói",
"Khác"
]
},
{
"name": "message",
"label": "Tin nhắn",
"type": "textarea",
"required": false,
"placeholder": "Mô tả chi tiết nhu cầu của bạn..."
}
]
}

157
app/contact/page.tsx Normal file
View File

@@ -0,0 +1,157 @@
"use client";
import { useState } from "react";
import contactData from "./contact.json";
export default function ContactPage() {
const [formData, setFormData] = useState({
fullName: "",
email: "",
phone: "",
service: "",
message: "",
});
const handleInputChange = (
e: React.ChangeEvent<
HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement
>,
) => {
const { name, value } = e.target;
setFormData((prev) => ({
...prev,
[name]: value,
}));
};
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
console.log("Form submitted:", formData);
// Handle form submission here
alert(
"Cảm ơn bạn đã liên hệ! Chúng tôi sẽ phản hồi trong thời gian sớm nhất.",
);
};
return (
<div className="container mx-auto px-4 py-8">
<div className="max-w-6xl mx-auto">
{/* Header */}
<div className="text-center mb-12">
<h1 className="text-4xl font-bold text-gray-900 mb-4">
{contactData.title}
</h1>
<p className="text-xl text-gray-600">{contactData.subtitle}</p>
</div>
<div className="grid lg:grid-cols-2 gap-12">
{/* Contact Information */}
<div>
<h2 className="text-2xl font-bold text-gray-900 mb-6">
Thông Tin Liên Hệ
</h2>
{/* Contact Details */}
<div className="space-y-6 mb-8">
{Object.entries(contactData.contactInfo).map(([key, info]) => (
<div key={key} className="flex items-start">
<span className="text-2xl mr-4">{info.icon}</span>
<div>
<h3 className="font-semibold text-gray-900">
{info.label}
</h3>
<p className="text-gray-700 whitespace-pre-line">
{info.value}
</p>
</div>
</div>
))}
</div>
{/* Offices */}
<h3 className="text-xl font-bold text-gray-900 mb-4">Văn Phòng</h3>
<div className="space-y-4">
{contactData.offices.map((office, index) => (
<div key={index} className="bg-gray-50 p-4 rounded-lg">
<h4 className="font-semibold text-gray-900 mb-2">
{office.name}
</h4>
<p className="text-gray-700 text-sm mb-1">
📍 {office.address}
</p>
<p className="text-gray-700 text-sm mb-1">
📞 {office.phone}
</p>
<p className="text-gray-700 text-sm"> {office.email}</p>
</div>
))}
</div>
</div>
{/* Contact Form */}
<div>
<h2 className="text-2xl font-bold text-gray-900 mb-6">
Gửi Tin Nhắn
</h2>
<form onSubmit={handleSubmit} className="space-y-6">
{contactData.formFields.map((field) => (
<div key={field.name}>
<label className="block text-sm font-medium text-gray-700 mb-2">
{field.label}
{field.required && (
<span className="text-red-500 ml-1">*</span>
)}
</label>
{field.type === "textarea" ? (
<textarea
name={field.name}
value={formData[field.name as keyof typeof formData]}
onChange={handleInputChange}
placeholder={field.placeholder}
required={field.required}
rows={4}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
) : field.type === "select" ? (
<select
name={field.name}
value={formData[field.name as keyof typeof formData]}
onChange={handleInputChange}
required={field.required}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
>
<option value="">Chọn dịch vụ</option>
{field.options?.map((option, index) => (
<option key={index} value={option}>
{option}
</option>
))}
</select>
) : (
<input
type={field.type}
name={field.name}
value={formData[field.name as keyof typeof formData]}
onChange={handleInputChange}
placeholder={field.placeholder}
required={field.required}
className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
)}
</div>
))}
<button
type="submit"
className="w-full bg-blue-600 text-white py-3 px-6 rounded-lg hover:bg-blue-700 transition-colors font-medium"
>
Gửi Tin Nhắn
</button>
</form>
</div>
</div>
</div>
</div>
);
}