diff --git a/api/visa.ts b/api/visa.ts new file mode 100644 index 0000000..0a6f9e4 --- /dev/null +++ b/api/visa.ts @@ -0,0 +1,831 @@ +// app/api/visa/route.ts + +import { NextRequest, NextResponse } from "next/server"; + +// ==================== INTERFACES ==================== + +interface VisaItem { + title: string; + description: string; +} + +interface VisaTypeCategory { + items: VisaItem[]; +} + +interface VisaProcessStep { + number: string; + title: string; + description: string; +} + +interface VisaProcess { + title: string; + steps: VisaProcessStep[]; +} + +interface VisaCategory { + title: string; + steps: string[][]; +} + +interface VisaService { + title: string; + steps: VisaProcessStep[]; +} + +interface RelatedCountry { + id: number; + name: string; + icon: string; +} + +interface ContactInfo { + sectionTitle: string; + helpText: string; + img: string; + phone: { + label: string; + value: string; + link: string; + }; + email: { + label: string; + value: string; + link: string; + }; + location: { + label: string; + address: string; + }; +} + +interface ActiveCountry { + id: number; + name: string; + title: string; + mainImage: string; + description: string; + additionalInfo: string; + tagline: string; + visaTypes: VisaTypeCategory[]; + visaProcess: VisaProcess; + gallery: string[]; + visaCategories: VisaCategory; + visaService: VisaService; +} + +export interface DetailedView { + activeCountry: ActiveCountry; + relatedCountries: RelatedCountry[]; + contactInfo: ContactInfo; +} + +export interface VisaCountry { + id: number; + name: string; + slug: string; + icon: string; + services: string[]; + detailedView?: DetailedView; +} + +export interface VisaHero { + title: string; + summaryList: VisaCountry[]; +} + +export interface VisaData { + hero: VisaHero; +} + +export interface VisaApiResponse { + success: boolean; + message?: string; + data?: VisaCountry | VisaCountry[] | VisaHero | null; + error?: string; +} + +export interface VisaInquiry { + name: string; + email: string; + phone: string; + country: string; + visaType: string; +} + +export interface VisaInquiryResponse { + success: boolean; + message: string; + inquiryId?: string; + data?: VisaInquiry; +} + +// ==================== HELPER FUNCTIONS ==================== + +const getApiUrl = (): string => { + return process.env.NEXT_PUBLIC_API_URL || "http://localhost:3001"; +}; + +/** + * Fetch visa data từ remote API hoặc fallback + * @param slug - Optional country slug + * @returns Promise + */ +export async function fetchVisaData(): Promise { + const apiUrl = getApiUrl(); + const url = `${apiUrl}`; // Đảm bảo apiUrl không thừa dấu / ở cuối + + try { + const response = await fetch(`${url}/api/visa`, { + method: "GET", + headers: { "Content-Type": "application/json" }, + cache: "no-store", + }); + + if (!response.ok) throw new Error(`API returned ${response.status}`); + + const apiResponse = await response.json(); + + if (!apiResponse.success || !apiResponse.hero) { + throw new Error("Dữ liệu API không đúng cấu trúc"); + } + + // Hàm bổ trợ để nối URL chuẩn + const fixUrl = (path: string) => { + if (!path || path.startsWith("http")) return path; + return `${url}${path.startsWith("/") ? "" : "/"}${path}`; + }; + + // Duyệt qua danh sách summaryList để ghi đè toàn bộ ảnh + if (apiResponse.hero.summaryList) { + apiResponse.hero.summaryList = apiResponse.hero.summaryList.map( + (country: any) => { + // 1. Fix icon cấp gốc + const updatedCountry = { + ...country, + icon: fixUrl(country.icon), + }; + + // 2. Fix sâu trong detailedView (nếu có) + if (updatedCountry.detailedView) { + const dv = updatedCountry.detailedView; + + updatedCountry.detailedView = { + ...dv, + // Fix ảnh trong activeCountry + activeCountry: dv.activeCountry + ? { + ...dv.activeCountry, + mainImage: fixUrl(dv.activeCountry.mainImage), + gallery: dv.activeCountry.gallery?.map(fixUrl), + } + : dv.activeCountry, + + // Fix icon trong danh sách nước liên quan + relatedCountries: dv.relatedCountries?.map((rc: any) => ({ + ...rc, + icon: fixUrl(rc.icon), + })), + + // Fix ảnh nền trong contactInfo + contactInfo: dv.contactInfo + ? { + ...dv.contactInfo, + img: fixUrl(dv.contactInfo.img), + } + : dv.contactInfo, + }; + } + + return updatedCountry; + }, + ); + } + + return apiResponse; + } catch (error) { + console.error("❌ Error fetching:", error); + return getFallbackVisaData(); + } +} +// ==================== FALLBACK DATA ==================== + +/** + * Fallback visa data - được dùng khi API không hoạt động + */ +function getFallbackVisaData(): VisaData { + return { + hero: { + title: "Visa Services ", + summaryList: [ + { + id: 1, + name: "France", + slug: "france", + icon: "/assets/img/home-2/visa/03.png", + services: [ + "Student Visa & Admission", + "Work Visa – H1B", + "Work permit for Canada", + "Student Visa for Canada", + ], + detailedView: { + activeCountry: { + id: 1, + name: "France", + title: "COUNTRY FRANCE", + mainImage: "/assets/img/inner-page/country-details/details-1.jpg", + description: + "France is one of the most popular destinations for international students, offering world-class universities, diverse cultural experiences, and countless career opportunities...", + additionalInfo: + "Our consultancy provides complete guidance for study visas, work permits, and permanent residency pathways tailored to your goals.", + tagline: + "Over the last 35 Years we made an impact that is strong & we have long way to go.", + visaTypes: [ + { + items: [ + { + title: "Tourist Visa", + description: + "Broad term that can refer to various aspects of interconnectedness", + }, + { + title: "Work Permit", + description: + "Broad term that can refer to various aspects of interconnectedness", + }, + ], + }, + { + items: [ + { + title: "Student", + description: + "Broad term that can refer to various aspects of interconnectedness", + }, + { + title: "Family Visa", + description: + "Broad term that can refer to various aspects of interconnectedness", + }, + ], + }, + ], + visaProcess: { + title: "France Visa Process", + steps: [ + { + number: "01", + title: "Consultation & Eligibility Check", + description: + "Our experts review your profile and visa requirements.", + }, + { + number: "02", + title: "Application Preparation", + description: + "We help with document collection, form filling, and statement drafting.", + }, + { + number: "03", + title: "Submission", + description: + "Visa application is submitted online with required fees.", + }, + { + number: "04", + title: "Interview Guidance", + description: + "Get training and mock sessions for embassy interview.", + }, + { + number: "05", + title: "Approval & Travel", + description: + "Once approved, we provide travel and pre-departure guidance.", + }, + ], + }, + gallery: [ + "/assets/img/inner-page/country-details/details-2.jpg", + "/assets/img/inner-page/country-details/details-3.png", + ], + visaCategories: { + title: "Types of France Visas", + steps: [ + [ + "Student Visa (F1, M1, J1)", + "Work Visa (H1B, L1)", + "Tourist Visa (B1/B2)", + ], + [ + "Family/Spouse Visa (K1, IR1, F2A)", + "Green Card / Immigrant Visa", + ], + ], + }, + visaService: { + title: "Our France Visa Service Options", + steps: [ + { + number: "01", + title: "Consultation & Eligibility Check", + description: + "Our experts review your profile and visa requirements.", + }, + { + number: "02", + title: "Application Preparation", + description: + "We help with document collection, form filling, and statement drafting.", + }, + { + number: "03", + title: "Submission", + description: + "Visa application is submitted online with required fees.", + }, + { + number: "04", + title: "Interview Guidance", + description: + "Get training and mock sessions for embassy interview.", + }, + { + number: "05", + title: "Approval & Travel", + description: + "Once approved, we provide travel and pre-departure guidance.", + }, + ], + }, + }, + relatedCountries: [ + { + id: 1, + name: "Canada", + icon: "/assets/img/inner-page/country-details/01.png", + }, + { + id: 2, + name: "USA", + icon: "/assets/img/inner-page/country-details/02.png", + }, + { + id: 3, + name: "UK", + icon: "/assets/img/inner-page/country-details/03.png", + }, + { + id: 4, + name: "Germany", + icon: "/assets/img/inner-page/country-details/05.png", + }, + { + id: 5, + name: "Spain", + icon: "/assets/img/inner-page/country-details/06.png", + }, + ], + contactInfo: { + sectionTitle: "Visa & Immigration", + helpText: "Need Help? Book Lab Visit", + img: "/assets/img/inner-page/country-details/bg.jpg", + phone: { + label: "Call Us", + value: "+33 1 23 45 67 89", + link: "tel:+33123456789", + }, + email: { + label: "Mail Us", + value: "visa@france-consultant.com", + link: "mailto:visa@france-consultant.com", + }, + location: { + label: "Location", + address: "Paris, Lyon, Marseille", + }, + }, + }, + }, + { + id: 2, + name: "UK", + slug: "uk", + icon: "/assets/img/home-2/visa/11.png", + services: [ + "Student Visa & Admission", + "Work Visa – Skilled Worker", + "Family Visa", + "Entrepreneur Visa", + ], + detailedView: { + activeCountry: { + id: 2, + name: "United Kingdom", + title: "COUNTRY UK", + mainImage: "/assets/img/inner-page/country-details/details-1.jpg", + description: + "The UK is a world leader in education and innovation, offering exceptional universities and career opportunities for international professionals...", + additionalInfo: + "We provide comprehensive support for UK student visas, work visas, and family sponsorship applications.", + tagline: "35+ years of excellence in UK visa consulting.", + visaTypes: [ + { + category: "Student & Work", + items: [ + { + title: "Student Visa", + description: + "Study at UK universities with part-time work opportunities", + }, + { + title: "Graduate Visa", + description: + "Work in the UK after completing your studies", + }, + ], + }, + { + category: "Family & Other", + items: [ + { + title: "Skilled Worker Visa", + description: "Work in a skilled occupation in the UK", + }, + { + title: "Family Visa", + description: "Join your family in the UK", + }, + ], + }, + ], + visaProcess: { + title: "UK Visa Process", + steps: [ + { + number: "01", + title: "Eligibility Assessment", + description: + "We evaluate your qualifications and circumstances.", + }, + { + number: "02", + title: "Documentation", + description: + "Comprehensive document preparation and review.", + }, + { + number: "03", + title: "Application Submission", + description: "Submit your visa application online.", + }, + { + number: "04", + title: "Biometrics & Interview", + description: "Complete biometric appointment if required.", + }, + { + number: "05", + title: "Visa Decision", + description: "Receive your visa and start your UK journey.", + }, + ], + }, + gallery: [ + "/assets/img/inner-page/country-details/details-2.jpg", + "/assets/img/inner-page/country-details/details-3.png", + ], + visaCategories: { + title: "Types of UK Visas", + steps: [ + [ + "Student Visa (Tier 4)", + "Graduate Visa", + "Skilled Worker Visa", + ], + ["Family Visa", "Visitor Visa", "Entrepreneur Visa"], + ], + }, + visaService: { + title: "Our UK Visa Services", + steps: [ + { + number: "01", + title: "Initial Consultation", + description: "Free assessment of your visa eligibility.", + }, + { + number: "02", + title: "Document Preparation", + description: "Expert guidance on all required documents.", + }, + { + number: "03", + title: "Application Submission", + description: "Professional submission and tracking.", + }, + { + number: "04", + title: "Interview Coaching", + description: "Prepare for your visa interview.", + }, + { + number: "05", + title: "Post-Visa Support", + description: "Guidance for accommodation and settlement.", + }, + ], + }, + }, + relatedCountries: [ + { + id: 1, + name: "Canada", + icon: "/assets/img/inner-page/country-details/01.png", + }, + { + id: 2, + name: "USA", + icon: "/assets/img/inner-page/country-details/02.png", + }, + { + id: 3, + name: "Australia", + icon: "/assets/img/inner-page/country-details/03.png", + }, + ], + contactInfo: { + sectionTitle: "UK Visa & Immigration", + helpText: "Need Help? Book Consultation", + img: "/assets/img/inner-page/country-details/bg.jpg", + phone: { + label: "Call Us", + value: "+44 20 7946 0958", + link: "tel:+442079460958", + }, + email: { + label: "Mail Us", + value: "visa@uk-consultant.com", + link: "mailto:visa@uk-consultant.com", + }, + location: { + label: "Location", + address: "London, Manchester, Birmingham", + }, + }, + }, + }, + { + id: 3, + name: "Canada", + slug: "canada", + icon: "/assets/img/home-2/visa/02.png", + services: [ + "Student Visa & Admission", + "Work Permit", + "Express Entry", + "Family Sponsorship", + ], + detailedView: { + activeCountry: { + id: 3, + name: "Canada", + title: "COUNTRY CANADA", + mainImage: "/assets/img/inner-page/country-details/details-1.jpg", + description: + "Canada is known for its high quality of life, excellent education system, and welcoming immigration policies...", + additionalInfo: + "We specialize in Express Entry, study permits, and work permits for Canada.", + tagline: "Your pathway to a better life in Canada starts here.", + visaTypes: [ + { + category: "Study & Work", + items: [ + { + title: "Study Permit", + description: "Study at Canadian institutions", + }, + { + title: "Work Permit", + description: "Temporary work in Canada", + }, + ], + }, + { + category: "Immigration & Family", + items: [ + { + title: "Express Entry", + description: "Fast-track permanent residency", + }, + { + title: "Family Sponsorship", + description: "Bring your family to Canada", + }, + ], + }, + ], + visaProcess: { + title: "Canada Visa Process", + steps: [ + { + number: "01", + title: "Initial Assessment", + description: + "We assess your eligibility for Canadian programs.", + }, + { + number: "02", + title: "Documentation", + description: "Prepare comprehensive application packages.", + }, + { + number: "03", + title: "Application", + description: "Submit to IRCC (Immigration Canada).", + }, + { + number: "04", + title: "Medical & Security", + description: "Complete medical exams and security checks.", + }, + { + number: "05", + title: "Approval", + description: "Receive your visa and prepare for arrival.", + }, + ], + }, + gallery: [ + "/assets/img/inner-page/country-details/details-2.jpg", + "/assets/img/inner-page/country-details/details-3.png", + ], + visaCategories: { + title: "Types of Canadian Visas", + steps: [ + [ + "Study Permit", + "Work Permit (Open/Closed)", + "International Mobility Program", + ], + [ + "Express Entry (FSW, CEC, FST)", + "Provincial Nominee Program", + "Family Sponsorship", + ], + ], + }, + visaService: { + title: "Our Canada Visa Services", + steps: [ + { + number: "01", + title: "Free Consultation", + description: "Discuss your Canadian immigration goals.", + }, + { + number: "02", + title: "Eligibility Check", + description: "Determine best pathway for you.", + }, + { + number: "03", + title: "Application Support", + description: "Complete assistance with applications.", + }, + { + number: "04", + title: "Preparation", + description: "Prepare for medical exams and interviews.", + }, + { + number: "05", + title: "Settlement Support", + description: "Help with housing and job search.", + }, + ], + }, + }, + relatedCountries: [ + { + id: 1, + name: "USA", + icon: "/assets/img/inner-page/country-details/01.png", + }, + { + id: 2, + name: "Australia", + icon: "/assets/img/inner-page/country-details/02.png", + }, + ], + contactInfo: { + sectionTitle: "Canada Visa & Immigration", + helpText: "Ready to Immigrate to Canada?", + img: "/assets/img/inner-page/country-details/bg.jpg", + phone: { + label: "Call Us", + value: "+1 416 815 7755", + link: "tel:+14168157755", + }, + email: { + label: "Mail Us", + value: "visa@canada-consultant.com", + link: "mailto:visa@canada-consultant.com", + }, + location: { + label: "Location", + address: "Toronto, Vancouver, Montreal", + }, + }, + }, + }, + { + id: 4, + name: "Germany", + slug: "germany", + icon: "/assets/img/home-2/visa/12.png", + services: [ + "Student Visa & Admission", + "Work Visa – H1B", + "Work permit for Canada", + "Student Visa for Canada", + ], + }, + { + id: 5, + name: "Spain", + slug: "spain", + icon: "/assets/img/home-2/visa/13.png", + services: [ + "Student Visa & Admission", + "Work Visa – H1B", + "Work permit for Canada", + "Student Visa for Canada", + ], + }, + { + id: 6, + name: "South Korea", + slug: "south-korea", + icon: "/assets/img/home-2/visa/14.png", + services: [ + "Student Visa & Admission", + "Work Visa – H1B", + "Work permit for Canada", + "Student Visa for Canada", + ], + }, + { + id: 7, + name: "Japan", + slug: "japan", + icon: "/assets/img/home-2/visa/15.png", + services: [ + "Student Visa & Admission", + "Work Visa – H1B", + "Work permit for Canada", + "Student Visa for Canada", + ], + }, + { + id: 8, + name: "Croatia", + slug: "croatia", + icon: "/assets/img/home-2/visa/16.png", + services: [ + "Student Visa & Admission", + "Work Visa – H1B", + "Work permit for Canada", + "Student Visa for Canada", + ], + }, + { + id: 9, + name: "England", + slug: "england", + icon: "/assets/img/home-2/visa/17.png", + services: [ + "Student Visa & Admission", + "Work Visa – H1B", + "Work permit for Canada", + "Student Visa for Canada", + ], + }, + { + id: 10, + name: "Indonesia", + slug: "indonesia", + icon: "/assets/img/home-2/visa/18.png", + services: [ + "Student Visa & Admission", + "Work Visa – H1B", + "Work permit for Canada", + "Student Visa for Canada", + ], + }, + ], + }, + }; +} diff --git a/app/components/layout/Header/header.json b/app/components/layout/Header/header.json index 8363255..db125f6 100644 --- a/app/components/layout/Header/header.json +++ b/app/components/layout/Header/header.json @@ -108,7 +108,7 @@ "children": [ { "label": "Visa List", - "href": "/visa-list" + "href": "/visa" }, { "label": "Visa Details", diff --git a/app/layout.tsx b/app/layout.tsx index 7e73f2b..c1bbf86 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -43,19 +43,46 @@ export default function RootLayout({ {children}