Merge pull request 'fix visa build' (#26) from fea/hoang-05022026-Visa into main

Reviewed-on: UKSOURCE/hailearning.edu.vn#26
This commit is contained in:
2026-02-06 05:01:55 +00:00
2 changed files with 35 additions and 82 deletions

View File

@@ -10,6 +10,7 @@ interface VisaItem {
} }
interface VisaTypeCategory { interface VisaTypeCategory {
title?: string;
items: VisaItem[]; items: VisaItem[];
} }
@@ -433,7 +434,7 @@ function getFallbackVisaData(): VisaData {
tagline: "35+ years of excellence in UK visa consulting.", tagline: "35+ years of excellence in UK visa consulting.",
visaTypes: [ visaTypes: [
{ {
category: "Student & Work", title: "Student & Work",
items: [ items: [
{ {
title: "Student Visa", title: "Student Visa",
@@ -448,7 +449,7 @@ function getFallbackVisaData(): VisaData {
], ],
}, },
{ {
category: "Family & Other", title: "Family & Other",
items: [ items: [
{ {
title: "Skilled Worker Visa", title: "Skilled Worker Visa",
@@ -601,7 +602,7 @@ function getFallbackVisaData(): VisaData {
tagline: "Your pathway to a better life in Canada starts here.", tagline: "Your pathway to a better life in Canada starts here.",
visaTypes: [ visaTypes: [
{ {
category: "Study & Work", title: "Study & Work",
items: [ items: [
{ {
title: "Study Permit", title: "Study Permit",
@@ -614,7 +615,7 @@ function getFallbackVisaData(): VisaData {
], ],
}, },
{ {
category: "Immigration & Family", title: "Immigration & Family",
items: [ items: [
{ {
title: "Express Entry", title: "Express Entry",

View File

@@ -7,24 +7,33 @@ interface VisaDetailProps {
} }
export default function VisaDetail({ country }: VisaDetailProps) { export default function VisaDetail({ country }: VisaDetailProps) {
// 1. Kiểm tra an toàn (Null Check)
// Vì detailedView có kiểu là 'DetailedView | undefined', ta phải chắc chắn nó tồn tại
if (!country || !country.detailedView) {
return (
<div className="section-padding text-center">
<h3>Đang tải dữ liệu...</h3>
</div>
);
}
const { name: rootName, detailedView } = country; const { name: rootName, detailedView } = country;
// 2. Bóc tách dữ liệu sau khi đã kiểm tra detailedView tồn tại
const { const {
activeCountry: countryData, activeCountry: countryData,
relatedCountries, relatedCountries,
contactInfo, contactInfo,
} = country.detailedView; } = detailedView;
return ( return (
<> <>
{/* Breadcrumb-Wrapper Section Start */}
<Breadcrumb title={rootName} current={rootName} /> <Breadcrumb title={rootName} current={rootName} />
{/* Country-details Section Start */}
<section className="country-details-section section-padding fix"> <section className="country-details-section section-padding fix">
<div className="container"> <div className="container">
<div className="country-details-wrapper"> <div className="country-details-wrapper">
<div className="row g-4"> <div className="row g-4">
{/* Main Content */}
<div className="col-lg-8"> <div className="col-lg-8">
<div className="country-details-post"> <div className="country-details-post">
<div className="details-image"> <div className="details-image">
@@ -38,33 +47,19 @@ export default function VisaDetail({ country }: VisaDetailProps) {
{/* Visa Types */} {/* Visa Types */}
<div className="tourist-visa-box"> <div className="tourist-visa-box">
{/* Render mảng đầu tiên (index 0) */} {countryData.visaTypes?.map((type: any, idx: number) => (
{countryData.visaTypes?.[0] && ( <div
<div className="tourist-box style-2"> key={idx}
{countryData.visaTypes[0].items.map( className={`tourist-box ${idx === 0 ? "style-2" : ""}`}
(item: any, itemIdx: number) => ( >
{type.items.map((item: any, itemIdx: number) => (
<div key={itemIdx} className="tourist-content"> <div key={itemIdx} className="tourist-content">
<h5>{item.title}</h5> <h5>{item.title}</h5>
<p>{item.description}</p> <p>{item.description}</p>
</div> </div>
), ))}
)}
</div> </div>
)} ))}
{/* Render mảng thứ hai (index 1) */}
{countryData.visaTypes?.[1] && (
<div className="tourist-box">
{countryData.visaTypes[1].items.map(
(item: any, itemIdx: number) => (
<div key={itemIdx} className="tourist-content">
<h5>{item.title}</h5>
<p>{item.description}</p>
</div>
),
)}
</div>
)}
</div> </div>
{/* Visa Process */} {/* Visa Process */}
@@ -102,49 +97,6 @@ export default function VisaDetail({ country }: VisaDetailProps) {
)} )}
</div> </div>
)} )}
{/* Visa Categories */}
{countryData.visaCategories && (
<>
<h3 className="text mb-3">
{countryData.visaCategories.title}
</h3>
{countryData.visaCategories.steps.map(
(subGroup: string[], groupIdx: number) => (
<ul className="visa-list-2" key={groupIdx}>
{subGroup.map((category: string, idx: number) => (
<li key={idx}>
<i className="fa-solid fa-chevrons-right"></i>
{category}
</li>
))}
</ul>
),
)}
</>
)}
{/* Service Options */}
{countryData.visaService && (
<>
<h3 className="text">
{countryData.visaService.title}
</h3>
<ul className="list-item">
{countryData.visaService.steps.map(
(process: any, idx: number) => (
<li key={idx}>
<strong>
{process.number}. {process.title} -
</strong>
<span> {process.description}</span>
</li>
),
)}
</ul>
</>
)}
</div> </div>
</div> </div>
</div> </div>
@@ -152,7 +104,7 @@ export default function VisaDetail({ country }: VisaDetailProps) {
{/* Sidebar */} {/* Sidebar */}
<div className="col-lg-4"> <div className="col-lg-4">
<div className="country-details-sideber"> <div className="country-details-sideber">
{relatedCountries.map((relCountry: any, idx: number) => ( {relatedCountries?.map((relCountry: any, idx: number) => (
<div key={idx} className="icon-box-item"> <div key={idx} className="icon-box-item">
<div className="left-item"> <div className="left-item">
<div className="icon"> <div className="icon">
@@ -178,8 +130,6 @@ export default function VisaDetail({ country }: VisaDetailProps) {
<div className="content"> <div className="content">
<h3>{contactInfo.sectionTitle}</h3> <h3>{contactInfo.sectionTitle}</h3>
<p>{contactInfo.helpText}</p> <p>{contactInfo.helpText}</p>
{/* Phone */}
<div className="icon-item"> <div className="icon-item">
<div className="icon"> <div className="icon">
<i className="fa-solid fa-phone"></i> <i className="fa-solid fa-phone"></i>
@@ -187,13 +137,15 @@ export default function VisaDetail({ country }: VisaDetailProps) {
<div className="cont"> <div className="cont">
<span>{contactInfo.phone.label}: </span> <span>{contactInfo.phone.label}: </span>
<h6> <h6>
<a href={contactInfo.phone.link}> <a
href={contactInfo.phone.link}
style={{ color: "white" }}
>
{contactInfo.phone.value} {contactInfo.phone.value}
</a> </a>
</h6> </h6>
</div> </div>
</div> </div>
{/* Email */} {/* Email */}
<div className="icon-item"> <div className="icon-item">
<div className="icon"> <div className="icon">