forked from UKSOURCE/hailearning.edu.vn
Initial commit
This commit is contained in:
89
app/contact/contact.json
Normal file
89
app/contact/contact.json
Normal 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
157
app/contact/page.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user