From 5b62149051c60faf6c71e198cb6474212214509f Mon Sep 17 00:00:00 2001 From: nguyenvanbao Date: Sat, 31 Jan 2026 12:35:43 +0700 Subject: [PATCH] feat: setup frontend Next.js project structure --- .gitignore | 3 + Dockerfile | 0 README.md | 218 ++++++++++++-- app/about/about.json | 33 ++ app/about/page.tsx | 49 +++ app/appointment/appointment.json | 255 ++++++++++++++++ app/appointment/page.tsx | 501 +++++++++++++++++++++++++++++++ app/blog/blog.json | 93 ++++++ app/blog/page.tsx | 144 +++++++++ app/components/Footer.tsx | 191 ++++++++++++ app/components/Header.tsx | 114 +++++++ app/contact/contact.json | 89 ++++++ app/contact/page.tsx | 157 ++++++++++ app/countries/countries.json | 188 ++++++++++++ app/countries/page.tsx | 231 ++++++++++++++ app/layout.tsx | 15 +- app/pricing/page.tsx | 188 ++++++++++++ app/pricing/pricing.json | 128 ++++++++ app/services/page.tsx | 73 +++++ app/services/services.json | 58 ++++ app/visa/page.tsx | 238 +++++++++++++++ app/visa/visa.json | 206 +++++++++++++ docker-compose.yml | 0 docker-entrypoint.sh | 0 pages/[level]/[slug]/index.tsx | 14 + pages/[level]/index.tsx | 13 + pages/_app.tsx | 6 + pages/_document.tsx | 13 + 28 files changed, 3195 insertions(+), 23 deletions(-) create mode 100644 Dockerfile create mode 100644 app/about/about.json create mode 100644 app/about/page.tsx create mode 100644 app/appointment/appointment.json create mode 100644 app/appointment/page.tsx create mode 100644 app/blog/blog.json create mode 100644 app/blog/page.tsx create mode 100644 app/components/Footer.tsx create mode 100644 app/components/Header.tsx create mode 100644 app/contact/contact.json create mode 100644 app/contact/page.tsx create mode 100644 app/countries/countries.json create mode 100644 app/countries/page.tsx create mode 100644 app/pricing/page.tsx create mode 100644 app/pricing/pricing.json create mode 100644 app/services/page.tsx create mode 100644 app/services/services.json create mode 100644 app/visa/page.tsx create mode 100644 app/visa/visa.json create mode 100644 docker-compose.yml create mode 100644 docker-entrypoint.sh create mode 100644 pages/[level]/[slug]/index.tsx create mode 100644 pages/[level]/index.tsx create mode 100644 pages/_app.tsx create mode 100644 pages/_document.tsx diff --git a/.gitignore b/.gitignore index 5ef6a52..49e96f5 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,6 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts + +#vs code +/.vscode \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..e69de29 diff --git a/README.md b/README.md index e215bc4..1cc3745 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,218 @@ -This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). +# VisaService - Website Dịch Vụ Visa -## Getting Started +Website dịch vụ visa chuyên nghiệp được xây dựng với Next.js 15, TypeScript và Tailwind CSS. Hỗ trợ tư vấn visa cho hơn 50 quốc gia với tỷ lệ thành công 99%. -First, run the development server: +## 🚀 Tính Năng + +- **8 Trang Chính**: Trang chủ, Giới thiệu, Dịch vụ, Visa, Quốc gia, Bảng giá, Blog, Liên hệ +- **Hệ Thống Đặt Lịch**: Đặt lịch tư vấn với chuyên gia +- **Responsive Design**: Tối ưu cho mọi thiết bị +- **JSON-Based Content**: Dễ dàng quản lý nội dung +- **Interactive Components**: Form, accordion, filter, modal +- **SEO Optimized**: Metadata và structure tối ưu + +## 🛠️ Công Nghệ Sử Dụng + +- **Framework**: Next.js 15 (App Router) +- **Language**: TypeScript +- **Styling**: Tailwind CSS +- **Icons**: Emoji icons +- **Deployment**: Docker support + +## 📁 Cấu Trúc Thư Mục + +``` +app/ +├── components/ # Shared components +│ ├── Header.tsx # Navigation header +│ └── Footer.tsx # Site footer +├── about/ # Trang giới thiệu +│ ├── about.json # Dữ liệu về công ty +│ └── page.tsx # Component trang +├── services/ # Trang dịch vụ +│ ├── services.json # Dữ liệu dịch vụ +│ └── page.tsx # Component trang +├── visa/ # Trang visa +│ ├── visa.json # Dữ liệu các loại visa +│ └── page.tsx # Component trang +├── countries/ # Trang quốc gia +│ ├── countries.json # Dữ liệu quốc gia +│ └── page.tsx # Component trang +├── pricing/ # Trang bảng giá +│ ├── pricing.json # Dữ liệu giá cả +│ └── page.tsx # Component trang +├── blog/ # Trang blog +│ ├── blog.json # Dữ liệu bài viết +│ └── page.tsx # Component trang +├── contact/ # Trang liên hệ +│ ├── contact.json # Thông tin liên hệ +│ └── page.tsx # Component trang +├── appointment/ # Trang đặt lịch +│ ├── appointment.json # Dữ liệu booking +│ └── page.tsx # Component trang +├── layout.tsx # Root layout +├── page.tsx # Trang chủ +└── globals.css # Global styles +``` + +## 🚀 Hướng Dẫn Chạy Dự Án + +### Yêu Cầu Hệ Thống + +- Node.js 18+ +- npm, yarn, hoặc pnpm + +### Cài Đặt và Chạy + +1. **Clone repository** + +```bash +git clone +cd visa-service-website +``` + +2. **Cài đặt dependencies** + +```bash +npm install +# hoặc +yarn install +# hoặc +pnpm install +``` + +3. **Chạy development server** ```bash npm run dev -# or +# hoặc yarn dev -# or +# hoặc pnpm dev -# or -bun dev ``` -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. +4. **Mở trình duyệt** + Truy cập [http://localhost:3000](http://localhost:3000) để xem website -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. +### Scripts Có Sẵn -This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. +```bash +npm run dev # Chạy development server +npm run build # Build production +npm run start # Chạy production server +npm run lint # Kiểm tra code style +``` -## Learn More +## 🐳 Chạy Với Docker -To learn more about Next.js, take a look at the following resources: +### Development với Docker -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. +```bash +# Build và chạy container +docker-compose up --build -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! +# Chạy ở background +docker-compose up -d -## Deploy on Vercel +# Dừng container +docker-compose down +``` -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. +### Production với Docker -Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. +```bash +# Build production image +docker build -t visa-service . + +# Chạy container +docker run -p 3000:3000 visa-service +``` + +## 📝 Tùy Chỉnh Nội Dung + +### Cập Nhật Dữ Liệu + +Mỗi trang có file JSON riêng chứa dữ liệu: + +- `about/about.json` - Thông tin công ty +- `services/services.json` - Danh sách dịch vụ +- `visa/visa.json` - Các loại visa +- `countries/countries.json` - Quốc gia hỗ trợ +- `pricing/pricing.json` - Bảng giá dịch vụ +- `blog/blog.json` - Bài viết blog +- `contact/contact.json` - Thông tin liên hệ +- `appointment/appointment.json` - Cấu hình đặt lịch + +### Thêm Trang Mới + +1. Tạo thư mục mới trong `app/` +2. Tạo file `data.json` chứa dữ liệu +3. Tạo file `page.tsx` với React component +4. Cập nhật navigation trong `Header.tsx` + +### Tùy Chỉnh Styling + +- Sử dụng Tailwind CSS classes +- Tùy chỉnh theme trong `tailwind.config.js` +- Global styles trong `app/globals.css` + +## 🌐 Deployment + +### Vercel (Khuyến nghị) + +1. Push code lên GitHub +2. Kết nối repository với Vercel +3. Deploy tự động + +### Netlify + +1. Build project: `npm run build` +2. Upload thư mục `out/` lên Netlify + +### VPS/Server + +1. Build project: `npm run build` +2. Chạy: `npm run start` +3. Sử dụng PM2 hoặc Docker cho production + +## 📱 Responsive Design + +Website được tối ưu cho: + +- **Mobile**: < 768px +- **Tablet**: 768px - 1024px +- **Desktop**: > 1024px + +## 🔧 Cấu Hình Môi Trường + +Tạo file `.env.local` (tùy chọn): + +```env +NEXT_PUBLIC_SITE_URL=http://localhost:3000 +NEXT_PUBLIC_CONTACT_EMAIL=info@visaservice.com +NEXT_PUBLIC_PHONE=1900-1234 +``` + +## 🤝 Đóng Góp + +1. Fork repository +2. Tạo feature branch: `git checkout -b feature/new-feature` +3. Commit changes: `git commit -m 'Add new feature'` +4. Push branch: `git push origin feature/new-feature` +5. Tạo Pull Request + +## 📄 License + +MIT License - xem file [LICENSE](LICENSE) để biết thêm chi tiết. + +## 📞 Hỗ Trợ + +- **Email**: info@visaservice.com +- **Phone**: 1900 1234 +- **Website**: [visaservice.com](https://visaservice.com) + +--- + +**Phát triển bởi**: VisaService Team +**Phiên bản**: 1.0.0 +**Cập nhật**: January 2025 diff --git a/app/about/about.json b/app/about/about.json new file mode 100644 index 0000000..73963bd --- /dev/null +++ b/app/about/about.json @@ -0,0 +1,33 @@ +{ + "title": "Về Chúng Tôi", + "subtitle": "Đối tác tin cậy cho dịch vụ visa và du lịch", + "description": "Chúng tôi là công ty hàng đầu trong lĩnh vực tư vấn visa và dịch vụ du lịch, với hơn 10 năm kinh nghiệm phục vụ khách hàng.", + "sections": [ + { + "heading": "Sứ Mệnh", + "content": "Mang đến cho khách hàng những trải nghiệm du lịch tuyệt vời và hỗ trợ thủ tục visa một cách nhanh chóng, chính xác." + }, + { + "heading": "Tầm Nhìn", + "content": "Trở thành công ty dẫn đầu trong lĩnh vực dịch vụ visa và du lịch tại Việt Nam." + }, + { + "heading": "Giá Trị Cốt Lõi", + "content": "Uy tín - Chất lượng - Tận tâm - Chuyên nghiệp" + } + ], + "stats": [ + { + "number": "10000+", + "label": "Khách hàng hài lòng" + }, + { + "number": "50+", + "label": "Quốc gia hỗ trợ visa" + }, + { + "number": "99%", + "label": "Tỷ lệ thành công" + } + ] +} diff --git a/app/about/page.tsx b/app/about/page.tsx new file mode 100644 index 0000000..46f771d --- /dev/null +++ b/app/about/page.tsx @@ -0,0 +1,49 @@ +import aboutData from "./about.json"; + +export default function AboutPage() { + return ( +
+
+ {/* Header */} +
+

+ {aboutData.title} +

+

{aboutData.subtitle}

+

+ {aboutData.description} +

+
+ + {/* Sections */} +
+ {aboutData.sections.map((section, index) => ( +
+

+ {section.heading} +

+

{section.content}

+
+ ))} +
+ + {/* Stats */} +
+

+ Thành Tích Của Chúng Tôi +

+
+ {aboutData.stats.map((stat, index) => ( +
+
+ {stat.number} +
+
{stat.label}
+
+ ))} +
+
+
+
+ ); +} diff --git a/app/appointment/appointment.json b/app/appointment/appointment.json new file mode 100644 index 0000000..eabf228 --- /dev/null +++ b/app/appointment/appointment.json @@ -0,0 +1,255 @@ +{ + "title": "Đặt Lịch Tư Vấn", + "subtitle": "Nhận tư vấn miễn phí từ chuyên gia visa của chúng tôi", + "hero": { + "title": "Tư Vấn Visa Miễn Phí", + "description": "Đặt lịch hẹn với chuyên gia để được tư vấn chi tiết về visa và dịch vụ phù hợp nhất cho bạn.", + "benefits": [ + "Tư vấn 1-1 với chuyên gia", + "Phân tích hồ sơ miễn phí", + "Báo giá chi tiết", + "Lộ trình xin visa rõ ràng" + ] + }, + "appointmentTypes": [ + { + "id": "consultation", + "name": "Tư Vấn Tổng Quát", + "duration": "30 phút", + "price": "Miễn phí", + "description": "Tư vấn về loại visa phù hợp, yêu cầu cơ bản và quy trình xin visa", + "icon": "💬", + "popular": true + }, + { + "id": "document-review", + "name": "Kiểm Tra Hồ Sơ", + "duration": "45 phút", + "price": "500,000 VNĐ", + "description": "Kiểm tra chi tiết hồ sơ hiện tại và đưa ra lời khuyên cải thiện", + "icon": "📋", + "popular": false + }, + { + "id": "interview-prep", + "name": "Luyện Phỏng Vấn", + "duration": "60 phút", + "price": "800,000 VNĐ", + "description": "Luyện tập kỹ năng phỏng vấn visa với chuyên gia có kinh nghiệm", + "icon": "🎯", + "popular": false + }, + { + "id": "premium", + "name": "Tư Vấn Cao Cấp", + "duration": "90 phút", + "price": "1,200,000 VNĐ", + "description": "Tư vấn toàn diện bao gồm chiến lược, hồ sơ và luyện phỏng vấn", + "icon": "⭐", + "popular": false + } + ], + "timeSlots": [ + { + "time": "08:00", + "label": "8:00 AM", + "available": true + }, + { + "time": "09:00", + "label": "9:00 AM", + "available": true + }, + { + "time": "10:00", + "label": "10:00 AM", + "available": false + }, + { + "time": "11:00", + "label": "11:00 AM", + "available": true + }, + { + "time": "13:00", + "label": "1:00 PM", + "available": true + }, + { + "time": "14:00", + "label": "2:00 PM", + "available": true + }, + { + "time": "15:00", + "label": "3:00 PM", + "available": false + }, + { + "time": "16:00", + "label": "4:00 PM", + "available": true + }, + { + "time": "17:00", + "label": "5:00 PM", + "available": true + } + ], + "consultants": [ + { + "id": "nguyen-van-a", + "name": "Nguyễn Văn A", + "title": "Chuyên gia Visa Mỹ & Canada", + "experience": "8 năm kinh nghiệm", + "specialties": ["Visa Mỹ", "Visa Canada", "Visa du học"], + "languages": ["Tiếng Việt", "English"], + "rating": 4.9, + "reviews": 156, + "avatar": "/images/consultant-1.jpg", + "description": "Chuyên gia hàng đầu về visa Bắc Mỹ với tỷ lệ thành công 98%" + }, + { + "id": "tran-thi-b", + "name": "Trần Thị B", + "title": "Chuyên gia Visa Châu Âu", + "experience": "6 năm kinh nghiệm", + "specialties": ["Visa Schengen", "Visa Anh", "Visa du lịch"], + "languages": ["Tiếng Việt", "English", "Français"], + "rating": 4.8, + "reviews": 203, + "avatar": "/images/consultant-2.jpg", + "description": "Chuyên gia visa châu Âu với kinh nghiệm sống và làm việc tại Pháp" + }, + { + "id": "le-van-c", + "name": "Lê Văn C", + "title": "Chuyên gia Visa Châu Á", + "experience": "5 năm kinh nghiệm", + "specialties": ["Visa Nhật Bản", "Visa Hàn Quốc", "Visa Singapore"], + "languages": ["Tiếng Việt", "日本語", "한국어"], + "rating": 4.9, + "reviews": 134, + "avatar": "/images/consultant-3.jpg", + "description": "Chuyên gia visa châu Á với khả năng giao tiếp đa ngôn ngữ" + } + ], + "formFields": [ + { + "name": "fullName", + "label": "Họ và tên", + "type": "text", + "required": true, + "placeholder": "Nhập họ và tên đầy đủ" + }, + { + "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": "visaType", + "label": "Loại visa quan tâm", + "type": "select", + "required": true, + "options": [ + "Visa du lịch", + "Visa công tác", + "Visa du học", + "Visa thăm thân", + "Visa lao động", + "Chưa xác định" + ] + }, + { + "name": "country", + "label": "Quốc gia đích", + "type": "select", + "required": true, + "options": [ + "Mỹ", + "Canada", + "Schengen", + "Anh", + "Úc", + "Nhật Bản", + "Hàn Quốc", + "Singapore", + "Khác" + ] + }, + { + "name": "travelDate", + "label": "Dự kiến ngày đi", + "type": "date", + "required": false, + "placeholder": "" + }, + { + "name": "previousVisa", + "label": "Đã từng xin visa nước này?", + "type": "select", + "required": false, + "options": [ + "Chưa bao giờ", + "Đã xin và được duyệt", + "Đã xin nhưng bị từ chối", + "Đang trong quá trình xin" + ] + }, + { + "name": "notes", + "label": "Ghi chú thêm", + "type": "textarea", + "required": false, + "placeholder": "Mô tả thêm về tình huống của bạn..." + } + ], + "faqs": [ + { + "question": "Tư vấn có thực sự miễn phí không?", + "answer": "Có, buổi tư vấn tổng quát 30 phút đầu tiên hoàn toàn miễn phí. Bạn chỉ cần đặt lịch và tham gia." + }, + { + "question": "Tôi có thể hủy hoặc đổi lịch hẹn không?", + "answer": "Có, bạn có thể hủy hoặc đổi lịch hẹn trước 24 giờ mà không mất phí. Liên hệ với chúng tôi để thay đổi." + }, + { + "question": "Buổi tư vấn diễn ra như thế nào?", + "answer": "Buổi tư vấn có thể diễn ra trực tiếp tại văn phòng hoặc online qua video call tùy theo lựa chọn của bạn." + }, + { + "question": "Tôi cần chuẩn bị gì cho buổi tư vấn?", + "answer": "Bạn nên chuẩn bị các câu hỏi cụ thể và nếu có, mang theo hộ chiếu và các giấy tờ liên quan để được tư vấn chính xác hơn." + } + ], + "offices": [ + { + "name": "TP. Hồ Chí Minh", + "address": "123 Nguyễn Huệ, Quận 1", + "phone": "+84 28 1234 5678", + "hours": "8:00 - 18:00 (T2-T6), 8:00 - 12:00 (T7)" + }, + { + "name": "Hà Nội", + "address": "456 Hoàn Kiếm, Hà Nội", + "phone": "+84 24 1234 5678", + "hours": "8:00 - 18:00 (T2-T6), 8:00 - 12:00 (T7)" + }, + { + "name": "Đà Nẵng", + "address": "789 Hải Châu, Đà Nẵng", + "phone": "+84 236 1234 567", + "hours": "8:00 - 18:00 (T2-T6), 8:00 - 12:00 (T7)" + } + ] +} diff --git a/app/appointment/page.tsx b/app/appointment/page.tsx new file mode 100644 index 0000000..d1667bc --- /dev/null +++ b/app/appointment/page.tsx @@ -0,0 +1,501 @@ +"use client"; + +import { useState } from "react"; +import appointmentData from "./appointment.json"; + +export default function AppointmentPage() { + const [selectedType, setSelectedType] = useState("consultation"); + const [selectedConsultant, setSelectedConsultant] = useState(""); + const [selectedDate, setSelectedDate] = useState(""); + const [selectedTime, setSelectedTime] = useState(""); + const [selectedOffice, setSelectedOffice] = useState("online"); + const [openFaq, setOpenFaq] = useState(null); + + const [formData, setFormData] = useState({ + fullName: "", + email: "", + phone: "", + visaType: "", + country: "", + travelDate: "", + previousVisa: "", + notes: "", + }); + + 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("Appointment booked:", { + type: selectedType, + consultant: selectedConsultant, + date: selectedDate, + time: selectedTime, + office: selectedOffice, + ...formData, + }); + alert( + "Đặt lịch thành công! Chúng tôi sẽ liên hệ xác nhận trong thời gian sớm nhất.", + ); + }; + + const toggleFaq = (index: number) => { + setOpenFaq(openFaq === index ? null : index); + }; + + const selectedAppointmentType = appointmentData.appointmentTypes.find( + (type) => type.id === selectedType, + ); + const selectedConsultantData = appointmentData.consultants.find( + (c) => c.id === selectedConsultant, + ); + + return ( +
+
+ {/* Header */} +
+

+ {appointmentData.title} +

+

+ {appointmentData.subtitle} +

+ + {/* Benefits */} +
+ {appointmentData.hero.benefits.map((benefit, index) => ( +
+

{benefit}

+
+ ))} +
+
+ +
+ {/* Booking Form */} +
+
+

+ Đặt Lịch Hẹn +

+ +
+ {/* Appointment Type */} +
+ +
+ {appointmentData.appointmentTypes.map((type) => ( +
setSelectedType(type.id)} + > +
+
+ {type.icon} +
+

{type.name}

+ {type.popular && ( + + Phổ biến + + )} +
+
+
+
+ {type.price} +
+
+ {type.duration} +
+
+
+

+ {type.description} +

+
+ ))} +
+
+ + {/* Consultant Selection */} +
+ +
+
setSelectedConsultant("")} + > +
+ Để chúng tôi chọn chuyên gia phù hợp +
+
+ Dựa trên loại visa và quốc gia bạn quan tâm +
+
+ + {appointmentData.consultants.map((consultant) => ( +
setSelectedConsultant(consultant.id)} + > +
+
+ 👤 +
+
+
+ {consultant.name} +
+
+ {consultant.title} +
+
+ + ⭐ {consultant.rating} + + + ({consultant.reviews} đánh giá) + + {consultant.experience} +
+
+
+
+ ))} +
+
+ + {/* Date & Time */} +
+
+ + setSelectedDate(e.target.value)} + min={new Date().toISOString().split("T")[0]} + required + className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent" + /> +
+ +
+ + +
+
+ + {/* Office Selection */} +
+ +
+
setSelectedOffice("online")} + > +
+ 💻 +
+
Tư vấn online
+
+ Video call qua Zoom/Google Meet +
+
+
+
+ + {appointmentData.offices.map((office, index) => ( +
setSelectedOffice(office.name)} + > +
+ 🏢 +
+
+ Văn phòng {office.name} +
+
+ {office.address} +
+
+ {office.hours} +
+
+
+
+ ))} +
+
+ + {/* Personal Information */} +
+

+ Thông Tin Cá Nhân +

+
+ {appointmentData.formFields.map((field) => ( +
+ + + {field.type === "textarea" ? ( +