Compare commits

...

10 Commits

Author SHA1 Message Date
Tiago Ribeiro
b162770e2d Navbar.tsx edited online with Bitbucket 2025-03-19 10:51:51 +00:00
Tiago Ribeiro
ce44293669 Removed telemetry 2024-05-21 22:42:43 +01:00
Tiago Ribeiro
d6dd879db8 Merge branch 'master' of bitbucket.org:ecropdev/encoach-landing-page 2024-04-22 13:48:21 +01:00
Tiago Ribeiro
f15d01ba2c Updated the Twitter logo to X 2024-04-22 13:47:51 +01:00
João Ramos
7b1df2d74b Merged in missing-dir-country-manager-contact (pull request #12)
Fixed a missing dir on the Country Manager contact page

Approved-by: Tiago Ribeiro
2024-04-19 08:18:51 +00:00
Joao Ramos
df5c49f4f0 Fixed a missing dir on the Country Manager contact page 2024-04-18 19:19:33 +01:00
João Ramos
514cee1487 Merged in advertisement-banner (pull request #11)
Added Advertisement Banner support
2024-04-08 22:50:20 +00:00
Joao Ramos
33199f26ec Added Advertisement Banner support 2024-04-08 18:47:32 +01:00
Tiago Ribeiro
3359c47379 Updated the code to allow for images 2024-04-01 00:50:53 +01:00
Tiago Ribeiro
1c5f16d42b Updated some client pages to externalize the Navbar and Footer 2024-03-21 12:47:03 +00:00
32 changed files with 313 additions and 215 deletions

View File

@@ -21,7 +21,7 @@ COPY . .
# Next.js collects completely anonymous telemetry data about general usage. # Next.js collects completely anonymous telemetry data about general usage.
# Learn more here: https://nextjs.org/telemetry # Learn more here: https://nextjs.org/telemetry
# Uncomment the following line in case you want to disable telemetry during the build. # Uncomment the following line in case you want to disable telemetry during the build.
# ENV NEXT_TELEMETRY_DISABLED 1 ENV NEXT_TELEMETRY_DISABLED 1
ARG STRAPI_URL=http://localhost:1337 ARG STRAPI_URL=http://localhost:1337
ARG STRAPI_TOKEN=TOKEN ARG STRAPI_TOKEN=TOKEN

View File

@@ -23,7 +23,7 @@
"react": "^18", "react": "^18",
"react-dom": "^18", "react-dom": "^18",
"react-hook-form": "^7.50.1", "react-hook-form": "^7.50.1",
"react-icons": "^4.11.0", "react-icons": "^5.1.0",
"react-string-replace": "^1.1.1", "react-string-replace": "^1.1.1",
"react-toastify": "^10.0.4", "react-toastify": "^10.0.4",
"sharp": "^0.32.6" "sharp": "^0.32.6"

View File

@@ -3,7 +3,7 @@ import About from "@/templates/About";
import AboutPage from "@/types/cms/about"; import AboutPage from "@/types/cms/about";
export default async function Page() { export default async function Page() {
const {data} = await getData<AboutPage>("about", "en"); const data = await getData<AboutPage>("about", "en");
return <About data={data.data.attributes} language="en" />; return <About data={data} language="en" />;
} }

View File

@@ -3,7 +3,7 @@ import About from "@/templates/About";
import AboutPage from "@/types/cms/about"; import AboutPage from "@/types/cms/about";
export default async function Page() { export default async function Page() {
const {data} = await getData<AboutPage>("about", "ar"); const data = await getData<AboutPage>("about", "ar");
return <About data={data.data.attributes} language="ar" />; return <About data={data} language="ar" />;
} }

View File

@@ -1,9 +1,17 @@
import {getData} from "@/cms"; import {getData} from "@/cms";
import Footer from "@/components/Footer";
import Navbar from "@/components/Navbar";
import ContactUs from "@/templates/ContactUs"; import ContactUs from "@/templates/ContactUs";
import ContactPage from "@/types/cms/contact"; import ContactPage from "@/types/cms/contact";
export default async function Page() { export default async function Page() {
const {data} = await getData<ContactPage>("contact", "ar"); const data = await getData<ContactPage>("contact", "ar");
return <ContactUs data={data.data.attributes} page="/contact" language="ar" />; return (
<main className="text-mti-black flex h-screen w-full flex-col bg-white" dir="rtl">
<Navbar currentPage="/contact" language="ar" />
<ContactUs data={data} />;
<Footer language="ar" />
</main>
);
} }

View File

@@ -15,7 +15,7 @@ export async function generateStaticParams() {
} }
export default async function Page({params: {country}}: PageProps) { export default async function Page({params: {country}}: PageProps) {
const {data} = await getData<CountryManagerContactsPage>("country-managers-contact", language); const data = await getData<CountryManagerContactsPage>("country-managers-contact", language);
return <AgentContacts data={data.data.attributes} country={country} page={`/contacts/${country}`} language={language} />; return <AgentContacts data={data} country={country} page={`/contacts/${country}`} language={language} />;
} }

View File

@@ -3,7 +3,7 @@ import History from "@/templates/History";
import HistoryPage from "@/types/cms/history"; import HistoryPage from "@/types/cms/history";
export default async function Page() { export default async function Page() {
const {data} = await getData<HistoryPage>("history", "ar"); const data = await getData<HistoryPage>("history", "ar");
return <History data={data.data.attributes} language="ar" />; return <History data={data} language="ar" />;
} }

View File

@@ -1,10 +1,16 @@
import {getData} from "@/cms"; import {getData} from "@/cms";
import Home from "@/templates/Home"; import Home from "@/templates/Home";
import HomePage from "@/types/cms/home"; import HomePage, {HomePageData} from "@/types/cms/home";
import {NextPageContext} from "next"; import {NextPageContext} from "next";
export default async function Page() { export default async function Page() {
const {data} = await getData<HomePage>("home", "ar"); const data = await getData<HomePageData>("home", "ar");
return <Home data={data.data.attributes} language="ar" />; const home: HomePage = {
...data,
Banner: data?.Banner?.data?.attributes,
AdvertisementBanner: data?.AdvertisementBanner?.data?.attributes,
};
return <Home data={home} language="ar" />;
} }

View File

@@ -1,9 +1,17 @@
import {getData} from "@/cms"; import {getData} from "@/cms";
import Footer from "@/components/Footer";
import Navbar from "@/components/Navbar";
import Price from "@/templates/Price"; import Price from "@/templates/Price";
import PricePage from "@/types/cms/price"; import PricePage from "@/types/cms/price";
export default async function Page() { export default async function Page() {
const {data} = await getData<PricePage>("price", "ar"); const data = await getData<PricePage>("price", "ar");
return <Price data={data.data.attributes} language="ar" />; return (
<main className="h-screen w-full bg-white text-mti-black flex flex-col" dir="rtl">
<Navbar currentPage="/price" language="ar" />
<Price data={data} language="ar" />
<Footer language="ar" />
</main>
);
} }

View File

@@ -4,7 +4,7 @@ import Terms from "@/templates/Terms";
import PrivacyPolicyPage from "@/types/cms/privacyPolicy"; import PrivacyPolicyPage from "@/types/cms/privacyPolicy";
export default async function Page() { export default async function Page() {
const {data} = await getData<PrivacyPolicyPage>("privacy-policy", "ar"); const data = await getData<PrivacyPolicyPage>("privacy-policy", "ar");
return <Privacy data={data.data.attributes} language="ar" />; return <Privacy data={data} language="ar" />;
} }

View File

@@ -3,7 +3,7 @@ import Services from "@/templates/Services";
import ServicesPage from "@/types/cms/services"; import ServicesPage from "@/types/cms/services";
export default async function Page() { export default async function Page() {
const {data} = await getData<ServicesPage>("services", "ar"); const data = await getData<ServicesPage>("services", "ar");
return <Services data={data.data.attributes} language="ar" />; return <Services data={data} language="ar" />;
} }

View File

@@ -3,7 +3,7 @@ import Terms from "@/templates/Terms";
import TermsAndConditionsPage from "@/types/cms/termsConditions"; import TermsAndConditionsPage from "@/types/cms/termsConditions";
export default async function Page() { export default async function Page() {
const {data} = await getData<TermsAndConditionsPage>("terms-and-conditions", "ar"); const data = await getData<TermsAndConditionsPage>("terms-and-conditions", "ar");
return <Terms data={data.data.attributes} language="ar" />; return <Terms data={data} language="ar" />;
} }

View File

@@ -1,9 +1,17 @@
import {getData} from "@/cms"; import {getData} from "@/cms";
import Footer from "@/components/Footer";
import Navbar from "@/components/Navbar";
import ContactUs from "@/templates/ContactUs"; import ContactUs from "@/templates/ContactUs";
import ContactPage from "@/types/cms/contact"; import ContactPage from "@/types/cms/contact";
export default async function Page() { export default async function Page() {
const {data} = await getData<ContactPage>("contact", "en"); const data = await getData<ContactPage>("contact", "en");
return <ContactUs data={data.data.attributes} page="/contact" language="en" />; return (
<main className="text-mti-black flex h-screen w-full flex-col bg-white" dir="ltr">
<Navbar currentPage="/contact" language="en" />
<ContactUs data={data} />;
<Footer language="en" />
</main>
);
} }

View File

@@ -15,7 +15,7 @@ export async function generateStaticParams() {
} }
export default async function Page({params: {country}}: PageProps) { export default async function Page({params: {country}}: PageProps) {
const {data} = await getData<CountryManagerContactsPage>("country-managers-contact", language); const data = await getData<CountryManagerContactsPage>("country-managers-contact", language);
return <AgentContacts data={data.data.attributes} country={country} page={`/contacts/${country}`} language={language} />; return <AgentContacts data={data} country={country} page={`/contacts/${country}`} language={language} />;
} }

View File

@@ -3,7 +3,7 @@ import History from "@/templates/History";
import HistoryPage from "@/types/cms/history"; import HistoryPage from "@/types/cms/history";
export default async function Page() { export default async function Page() {
const {data} = await getData<HistoryPage>("history", "en"); const data = await getData<HistoryPage>("history", "en");
return <History data={data.data.attributes} language="en" />; return <History data={data} language="en" />;
} }

View File

@@ -1,10 +1,16 @@
import {getData} from "@/cms"; import {getData} from "@/cms";
import Home from "@/templates/Home"; import Home from "@/templates/Home";
import HomePage from "@/types/cms/home"; import HomePage, {HomePageData} from "@/types/cms/home";
import {NextPageContext} from "next"; import {NextPageContext} from "next";
export default async function Page() { export default async function Page() {
const {data} = await getData<HomePage>("home", "en"); const data = await getData<HomePageData>("home", "en");
return <Home data={data.data.attributes} language="en" />; const home: HomePage = {
...data,
Banner: data?.Banner?.data?.attributes,
AdvertisementBanner: data?.AdvertisementBanner?.data?.attributes,
};
return <Home data={home} language="en" />;
} }

View File

@@ -1,9 +1,17 @@
import {getData} from "@/cms"; import {getData} from "@/cms";
import Footer from "@/components/Footer";
import Navbar from "@/components/Navbar";
import Price from "@/templates/Price"; import Price from "@/templates/Price";
import PricePage from "@/types/cms/price"; import PricePage from "@/types/cms/price";
export default async function Page() { export default async function Page() {
const {data} = await getData<PricePage>("price", "en"); const data = await getData<PricePage>("price", "en");
return <Price data={data.data.attributes} language="en" />; return (
<main className="h-screen w-full bg-white text-mti-black flex flex-col" dir="ltr">
<Navbar currentPage="/price" language="en" />
<Price data={data} language="en" />
<Footer language="en" />
</main>
);
} }

View File

@@ -4,7 +4,7 @@ import Terms from "@/templates/Terms";
import PrivacyPolicyPage from "@/types/cms/privacyPolicy"; import PrivacyPolicyPage from "@/types/cms/privacyPolicy";
export default async function Page() { export default async function Page() {
const {data} = await getData<PrivacyPolicyPage>("privacy-policy", "en"); const data = await getData<PrivacyPolicyPage>("privacy-policy", "en");
return <Privacy data={data.data.attributes} language="en" />; return <Privacy data={data} language="en" />;
} }

View File

@@ -3,7 +3,7 @@ import Services from "@/templates/Services";
import ServicesPage from "@/types/cms/services"; import ServicesPage from "@/types/cms/services";
export default async function Page() { export default async function Page() {
const {data} = await getData<ServicesPage>("services", "en"); const data = await getData<ServicesPage>("services", "en");
return <Services data={data.data.attributes} language="en" />; return <Services data={data} language="en" />;
} }

View File

@@ -3,7 +3,7 @@ import Terms from "@/templates/Terms";
import TermsAndConditionsPage from "@/types/cms/termsConditions"; import TermsAndConditionsPage from "@/types/cms/termsConditions";
export default async function Page() { export default async function Page() {
const {data} = await getData<TermsAndConditionsPage>("terms-and-conditions", "en"); const data = await getData<TermsAndConditionsPage>("terms-and-conditions", "en");
return <Terms data={data.data.attributes} language="en" />; return <Terms data={data} language="en" />;
} }

View File

@@ -13,11 +13,12 @@ interface StrapiResponse<T> {
meta: object; meta: object;
} }
type Result<T> = {data: StrapiResponse<T>; isError: boolean}; export async function getData<T>(page: string, locale: "ar" | "en"): Promise<T> {
export async function getData<T>(page: string, locale: "ar" | "en"): Promise<Result<T>> {
const request = await axios.get<StrapiResponse<T>>(`${process.env.STRAPI_URL}/api/${page}/?populate=deep&locale=${locale}`, { const request = await axios.get<StrapiResponse<T>>(`${process.env.STRAPI_URL}/api/${page}/?populate=deep&locale=${locale}`, {
headers: {Authorization: `Bearer ${process.env.STRAPI_TOKEN}`}, headers: {Authorization: `Bearer ${process.env.STRAPI_TOKEN}`},
}); });
return {data: request.data, isError: request.status !== 200};
console.log('GetDAta', page, JSON.stringify(request.data.data.attributes, null, 2));
return request.data.data.attributes;
} }

View File

@@ -1,106 +1,119 @@
import Link from "next/link"; import Link from "next/link";
import {BiLogoFacebook} from "react-icons/bi"; import { BiLogoFacebook } from "react-icons/bi";
import {BsInstagram, BsTwitter} from "react-icons/bs"; import { BsInstagram, BsTwitterX } from "react-icons/bs";
import translation from "@/translation/footer.json"; import translation from "@/translation/footer.json";
import clsx from "clsx"; import clsx from "clsx";
import FooterSection from "@/types/cms/footer"; import FooterSection from "@/types/cms/footer";
interface Props { interface Props {
language: "en" | "ar"; language: "en" | "ar";
data: FooterSection; data: FooterSection;
} }
interface FooterLinkProps { interface FooterLinkProps {
language: "en" | "ar"; language: "en" | "ar";
children: string; children: string;
href: string; href: string;
} }
const FooterLink = ({language, href, children}: FooterLinkProps) => { const FooterLink = ({ language, href, children }: FooterLinkProps) => {
return <Link href={`${language === "ar" ? "/ar" : ""}${href}`}>{children}</Link>; return (
<Link href={`${language === "ar" ? "/ar" : ""}${href}`}>{children}</Link>
);
}; };
export default function Footer({language, data}: Props) { export default function Footer({ language, data }: Props) {
return ( return (
<> <>
<section className="bg-mti-gray-seasalt w-full"> <section className="bg-mti-gray-seasalt w-full">
<div <div
className={clsx( className={clsx(
"w-full py-10 px-8 md:px-28 flex flex-col md:justify-between gap-8 lg:container lg:mx-auto", "w-full py-10 px-8 md:px-28 flex flex-col md:justify-between gap-8 lg:container lg:mx-auto",
language === "ar" ? "md:flex-row-reverse" : "md:flex-row", language === "ar" ? "md:flex-row-reverse" : "md:flex-row",
)}> )}
<div className="flex flex-col gap-4"> >
<span className="font-bold text-xl">{data.Navigation.Text}</span> <div className="flex flex-col gap-4">
<div className="flex flex-col gap-2"> <span className="font-bold text-xl">{data.Navigation.Text}</span>
<FooterLink language={language} href={`/about`}> <div className="flex flex-col gap-2">
{data.Navigation.WhyUs} <FooterLink language={language} href={`/about`}>
</FooterLink> {data.Navigation.WhyUs}
<FooterLink language={language} href={`/about#capabilities`}> </FooterLink>
{data.Navigation.Capabilities} <FooterLink language={language} href={`/about#capabilities`}>
</FooterLink> {data.Navigation.Capabilities}
<FooterLink language={language} href={`/about#expertise`}> </FooterLink>
{data.Navigation.Expertise} <FooterLink language={language} href={`/about#expertise`}>
</FooterLink> {data.Navigation.Expertise}
<FooterLink language={language} href="/history"> </FooterLink>
{data.Navigation.History} <FooterLink language={language} href="/history">
</FooterLink> {data.Navigation.History}
<FooterLink language={language} href="/contact"> </FooterLink>
{data.Navigation.Contact} <FooterLink language={language} href="/contact">
</FooterLink> {data.Navigation.Contact}
</div> </FooterLink>
</div> </div>
<div className="flex flex-col gap-4"> </div>
<span className="font-bold text-xl">{data.Services.Text}</span> <div className="flex flex-col gap-4">
<div className="flex flex-col gap-2"> <span className="font-bold text-xl">{data.Services.Text}</span>
<FooterLink language={language} href="/#benefits"> <div className="flex flex-col gap-2">
{data.Services.EnCoachBenefits} <FooterLink language={language} href="/#benefits">
</FooterLink> {data.Services.EnCoachBenefits}
<FooterLink language={language} href="#testimonials"> </FooterLink>
{data.Services.StudentTestimonials} <FooterLink language={language} href="#testimonials">
</FooterLink> {data.Services.StudentTestimonials}
</div> </FooterLink>
</div> </div>
<div className="flex flex-col gap-4"> </div>
<span className="font-bold text-xl">{data.About.Text}</span> <div className="flex flex-col gap-4">
<div className="flex flex-col gap-2"> <span className="font-bold text-xl">{data.About.Text}</span>
<FooterLink language={language} href="/terms"> <div className="flex flex-col gap-2">
{data.About.Terms} <FooterLink language={language} href="/terms">
</FooterLink> {data.About.Terms}
<FooterLink language={language} href="/privacy-policy"> </FooterLink>
{data.About.PrivacyPolicy} <FooterLink language={language} href="/privacy-policy">
</FooterLink> {data.About.PrivacyPolicy}
<FooterLink language={language} href="/about"> </FooterLink>
{data.About.Text} <FooterLink language={language} href="/about">
</FooterLink> {data.About.Text}
</div> </FooterLink>
</div> </div>
<div className="flex flex-col gap-4"> </div>
<span className="font-bold text-xl">{data.GetInTouch.Title}</span> <div className="flex flex-col gap-4">
<div className="flex flex-col gap-4"> <span className="font-bold text-xl">{data.GetInTouch.Title}</span>
<span className="max-w-[280px]">{data.GetInTouch.Text}</span> <div className="flex flex-col gap-4">
<div className={clsx("flex gap-6 items-center", language === "ar" && "flex-row-reverse justify-start")}> <span className="max-w-[280px]">{data.GetInTouch.Text}</span>
<Link <div
href="https://facebook.com" className={clsx(
className="bg-mti-purple-ultralight rounded-full w-10 h-10 flex items-center justify-center hover:bg-mti-purple-dark text-mti-purple-light hover:text-white transition ease-in-out duration-300"> "flex gap-6 items-center",
<BiLogoFacebook className="w-6 h-6" /> language === "ar" && "flex-row-reverse justify-start",
</Link> )}
<Link >
href="https://twitter.com" <Link
className="bg-mti-purple-ultralight rounded-full w-10 h-10 flex items-center justify-center hover:bg-mti-purple-dark text-mti-purple-light hover:text-white transition ease-in-out duration-300"> href="https://facebook.com"
<BsTwitter className="w-5 h-5" /> className="bg-mti-purple-ultralight rounded-full w-10 h-10 flex items-center justify-center hover:bg-mti-purple-dark text-mti-purple-light hover:text-white transition ease-in-out duration-300"
</Link> >
<Link <BiLogoFacebook className="w-6 h-6" />
href="https://instagram.com" </Link>
className="bg-mti-purple-ultralight rounded-full w-10 h-10 flex items-center justify-center hover:bg-mti-purple-dark text-mti-purple-light hover:text-white transition ease-in-out duration-300"> <Link
<BsInstagram className="w-5 h-5" /> href="https://twitter.com"
</Link> className="bg-mti-purple-ultralight rounded-full w-10 h-10 flex items-center justify-center hover:bg-mti-purple-dark text-mti-purple-light hover:text-white transition ease-in-out duration-300"
</div> >
</div> <BsTwitterX className="w-5 h-5" />
</div> </Link>
</div> <Link
</section> href="https://instagram.com"
className="bg-mti-purple-ultralight rounded-full w-10 h-10 flex items-center justify-center hover:bg-mti-purple-dark text-mti-purple-light hover:text-white transition ease-in-out duration-300"
>
<BsInstagram className="w-5 h-5" />
</Link>
</div>
</div>
</div>
</div>
</section>
<footer className="w-full py-10 bg-mti-rose-light text-white flex items-center justify-center">© {data.Copyright}</footer> <footer className="w-full py-10 bg-mti-rose-light text-white flex items-center justify-center">
</> © {data.Copyright}
); </footer>
</>
);
} }

View File

@@ -7,7 +7,7 @@ interface Props {
} }
export default async function FooterContainer({language}: Props) { export default async function FooterContainer({language}: Props) {
const {data} = await getData<FooterSection>("footer", language); const data = await getData<FooterSection>("footer", language);
return <Footer data={data.data.attributes} language={language} />; return <Footer data={data} language={language} />;
} }

View File

@@ -117,6 +117,11 @@ export default function Navbar({currentPage, language, data}: Props) {
)} )}
</div> </div>
<div className="flex w-fit items-center gap-4"> <div className="flex w-fit items-center gap-4">
<Link
href="https://platform.encoach.com/official-exam"
className="hover:bg-mti-purple-dark border-mti-purple-dark rounded-xl border px-8 py-2 transition duration-300 ease-in-out hover:text-white">
Official Exam
</Link>
<Link <Link
href="https://platform.encoach.com" href="https://platform.encoach.com"
className="hover:bg-mti-purple-dark border-mti-purple-dark rounded-xl border px-8 py-2 transition duration-300 ease-in-out hover:text-white"> className="hover:bg-mti-purple-dark border-mti-purple-dark rounded-xl border px-8 py-2 transition duration-300 ease-in-out hover:text-white">

View File

@@ -8,7 +8,7 @@ interface Props {
} }
export default async function NavbarContainer({currentPage, language}: Props) { export default async function NavbarContainer({currentPage, language}: Props) {
const {data} = await getData<NavBarSection>("nav-bar", language); const data = await getData<NavBarSection>("nav-bar", language);
return <Navbar data={data.data.attributes} language={language} currentPage={currentPage} />; return <Navbar data={data} language={language} currentPage={currentPage} />;
} }

View File

@@ -33,7 +33,7 @@ export async function AgentContacts({language, page, country, data}: Props) {
const contact = (await getCountryManagers(country, language)) as Contact; const contact = (await getCountryManagers(country, language)) as Contact;
return ( return (
<main className="text-mti-black flex h-screen w-full flex-col bg-white"> <main className="text-mti-black flex h-screen w-full flex-col bg-white" dir={language === "ar" ? "rtl" : "ltr"}>
<Navbar currentPage={page} language={language} /> <Navbar currentPage={page} language={language} />
<section className="bg-mti-purple h-full w-full p-8 text-center text-white md:p-16"> <section className="bg-mti-purple h-full w-full p-8 text-center text-white md:p-16">

View File

@@ -18,9 +18,7 @@ type FormValues = {
}; };
interface Props { interface Props {
language: "en" | "ar";
data: ContactPage; data: ContactPage;
page: string;
} }
const ErrorMessage = ({message}: {message: string}) => ( const ErrorMessage = ({message}: {message: string}) => (
@@ -28,7 +26,7 @@ const ErrorMessage = ({message}: {message: string}) => (
<span className="text-mti-red">{message}</span> <span className="text-mti-red">{message}</span>
</div> </div>
); );
export default function App({language, data, page}: Props) { export default function App({data}: Props) {
const selectOptions = [ const selectOptions = [
{ {
label: data.Feedback, label: data.Feedback,
@@ -92,67 +90,63 @@ export default function App({language, data, page}: Props) {
return ( return (
<> <>
<ToastContainer /> <ToastContainer />
<main className="text-mti-black flex h-screen w-full flex-col bg-white" dir={language === "ar" ? "rtl" : "ltr"}> <section className="w-full bg-mti-purple text-white text-center p-8 md:p-16">
<Navbar currentPage={page} language={language} /> <div className="w-full h-full flex flex-col items-center justify-center">
<section className="w-full bg-mti-purple text-white text-center p-8 md:p-16"> <Title>{data.Title}</Title>
<div className="w-full h-full flex flex-col items-center justify-center"> </div>
<Title>{data.Title}</Title> </section>
</div> <section className="w-full bg-white text-center p-8 md:p-16 flex justify-center items-center gap-32">
</section> <form onSubmit={handleSubmit(onSubmit)} className="form-control items-center gap-2 text-mti-black flex flex-col w-96">
<section className="w-full bg-white text-center p-8 md:p-16 flex justify-center items-center gap-32"> <input
<form onSubmit={handleSubmit(onSubmit)} className="form-control items-center gap-2 text-mti-black flex flex-col w-96"> id="name"
<input type="text"
id="name" placeholder={data.Name}
type="text" {...register("name", {required: true})}
placeholder={data.Name} className="input input-bordered md:w-full sm:w-1/2 max-w-md"
{...register("name", {required: true})} />
className="input input-bordered md:w-full sm:w-1/2 max-w-md" {errors.name && errors.name.type === "required" && <ErrorMessage message={data.FieldRequired} />}
/> <input
{errors.name && errors.name.type === "required" && <ErrorMessage message={data.FieldRequired} />} id="email"
<input placeholder={data.Email}
id="email" type="text"
placeholder={data.Email} {...register("email", {required: true, pattern: /^\S+@\S+$/i})}
type="text" className="input input-bordered md:w-full sm:w-1/2 max-w-md"
{...register("email", {required: true, pattern: /^\S+@\S+$/i})} />
className="input input-bordered md:w-full sm:w-1/2 max-w-md" {errors.email && errors.email.type === "required" && <ErrorMessage message={data.FieldRequired} />}
/> {errors.email && errors.email.type === "pattern" && <ErrorMessage message={data.InvalidEmail} />}
{errors.email && errors.email.type === "required" && <ErrorMessage message={data.FieldRequired} />} <input
{errors.email && errors.email.type === "pattern" && <ErrorMessage message={data.InvalidEmail} />} id="subject"
<input placeholder={data.Subject}
id="subject" type="text"
placeholder={data.Subject} {...register("subject", {required: true})}
type="text" className="input input-bordered md:w-full sm:w-1/2 max-w-md"
{...register("subject", {required: true})} />
className="input input-bordered md:w-full sm:w-1/2 max-w-md" {errors.subject && errors.subject.type === "required" && <ErrorMessage message={data.FieldRequired} />}
/> <select id="type" {...register("type", {required: true})} className="select select-bordered md:w-full sm:w-1/2 max-w-md">
{errors.subject && errors.subject.type === "required" && <ErrorMessage message={data.FieldRequired} />} <option value="" disabled>
<select id="type" {...register("type", {required: true})} className="select select-bordered md:w-full sm:w-1/2 max-w-md"> {data.SelectType}
<option value="" disabled> </option>
{data.SelectType} {selectOptions.map((option) => (
<option key={option.value} value={option.value}>
{option.label}
</option> </option>
{selectOptions.map((option) => ( ))}
<option key={option.value} value={option.value}> </select>
{option.label} {errors.type && errors.type.type === "required" && <ErrorMessage message={data.FieldRequired} />}
</option> <textarea
))} id="description"
</select> placeholder={data.Description}
{errors.type && errors.type.type === "required" && <ErrorMessage message={data.FieldRequired} />} {...register("description", {required: true})}
<textarea className="textarea textarea-bordered md:w-full sm:w-1/2 max-w-md"
id="description" rows={5}
placeholder={data.Description} />
{...register("description", {required: true})} {errors.description && errors.description.type === "required" && <ErrorMessage message={data.FieldRequired} />}
className="textarea textarea-bordered md:w-full sm:w-1/2 max-w-md" <input type="submit" className="btn" disabled={!isDirty || !isValid} value={data.Submit} />
rows={5} </form>
/> <div className="flex flex-col">
{errors.description && errors.description.type === "required" && <ErrorMessage message={data.FieldRequired} />} <Image src="/person_laptop_focus.jpg" alt="Contact Us" width={500} height={340} className="rounded-xl" />
<input type="submit" className="btn" disabled={!isDirty || !isValid} value={data.Submit} /> </div>
</form> </section>
<div className="flex flex-col">
<Image src="/person_laptop_focus.jpg" alt="Contact Us" width={500} height={340} className="rounded-xl" />
</div>
</section>
<Footer language={language} />
</main>
</> </>
); );
} }

View File

@@ -20,9 +20,21 @@ export default function Home({language, data}: Props) {
className={clsx("h-screen w-full bg-white text-mti-black flex flex-col", language === "ar" && "text-right")} className={clsx("h-screen w-full bg-white text-mti-black flex flex-col", language === "ar" && "text-right")}
dir={language === "ar" ? "rtl" : "ltr"}> dir={language === "ar" ? "rtl" : "ltr"}>
<Navbar currentPage="/" language={language} /> <Navbar currentPage="/" language={language} />
{data.AdvertisementBanner?.url && (
<section className="w-full relative bg-white mb-4">
<img
src={data.AdvertisementBanner.url}
alt={data.AdvertisementBanner.alternativeText || 'Advertisement Banner'}
className="w-full"
/>
</section>
)}
<section className="w-full relative bg-white"> <section className="w-full relative bg-white">
<img src="/banner_encoach_home.png" alt="IELTS Packages - Together we prepare for the future" className="w-full" /> <img
src={data.Banner?.url || "/banner_encoach_home.png"}
alt={data.Banner?.alternativeText ?? "IELTS Packages - Together we prepare for the future"}
className="w-full"
/>
<Link href={language === "ar" ? "/ar/price" : "/price"}> <Link href={language === "ar" ? "/ar/price" : "/price"}>
<button className="absolute bottom-1/12 -lg:hidden left-1/12 bg-mti-purple-light hover:bg-mti-purple text-white rounded-xl px-8 py-4 transition ease-in-out duration-300 shadow"> <button className="absolute bottom-1/12 -lg:hidden left-1/12 bg-mti-purple-light hover:bg-mti-purple text-white rounded-xl px-8 py-4 transition ease-in-out duration-300 shadow">
{data.GetStartedButton} {data.GetStartedButton}

View File

@@ -67,8 +67,7 @@ export default function Page({language, data}: Props) {
getData(); getData();
}, []); }, []);
return ( return (
<main className="h-screen w-full bg-white text-mti-black flex flex-col" dir={language === "ar" ? "rtl" : "ltr"}> <>
<Navbar currentPage="/price" language={language} />
<section className="w-full relative bg-white px-8 flex flex-col items-center text-center gap-4"> <section className="w-full relative bg-white px-8 flex flex-col items-center text-center gap-4">
<h2 className="text-3xl font-bold">{data.Title}</h2> <h2 className="text-3xl font-bold">{data.Title}</h2>
<div className="grid grid-cols-2 gap-8"> <div className="grid grid-cols-2 gap-8">
@@ -103,7 +102,6 @@ export default function Page({language, data}: Props) {
{data.SignUp} {data.SignUp}
</Link> </Link>
</section> </section>
<Footer language={language} /> </>
</main>
); );
} }

View File

@@ -13,3 +13,24 @@ export type TitleWithTagAndText = TagTitle & TitleWithText;
export interface TitleWithTextAndList extends TitleWithText { export interface TitleWithTextAndList extends TitleWithText {
List: string; List: string;
} }
export interface ImageData {
data: {
id: number;
attributes: Image;
};
}
export interface Image {
name: string;
alternativeText: string | null;
caption: string | null;
width: number;
height: number;
hash: string;
ext: string;
mime: string;
size: number;
url: string;
previewUrl: string | null;
}

View File

@@ -1,6 +1,6 @@
import {TagTitle, TitleWithTagAndText, TitleWithText} from "./common"; import {TagTitle, TitleWithTagAndText, TitleWithText, ImageData, Image} from "./common";
export default interface HomePage { interface Base {
GetStartedButton: string; GetStartedButton: string;
Modules: Modules; Modules: Modules;
LearnAI: TitleWithTagAndText; LearnAI: TitleWithTagAndText;
@@ -12,6 +12,16 @@ export default interface HomePage {
Accreditation: string; Accreditation: string;
} }
export default interface HomePage extends Base {
Banner: Image;
AdvertisementBanner: Image;
}
export interface HomePageData extends Base {
Banner: ImageData;
AdvertisementBanner: ImageData;
}
interface Modules { interface Modules {
Reading: TitleWithText; Reading: TitleWithText;
Listening: TitleWithText; Listening: TitleWithText;

View File

@@ -2263,10 +2263,10 @@ react-hook-form@^7.50.1:
resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.50.1.tgz#f6aeb17a863327e5a0252de8b35b4fc8990377ed" resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.50.1.tgz#f6aeb17a863327e5a0252de8b35b4fc8990377ed"
integrity sha512-3PCY82oE0WgeOgUtIr3nYNNtNvqtJ7BZjsbxh6TnYNbXButaD5WpjOmTjdxZfheuHKR68qfeFnEDVYoSSFPMTQ== integrity sha512-3PCY82oE0WgeOgUtIr3nYNNtNvqtJ7BZjsbxh6TnYNbXButaD5WpjOmTjdxZfheuHKR68qfeFnEDVYoSSFPMTQ==
react-icons@^4.11.0: react-icons@^5.1.0:
version "4.11.0" version "5.1.0"
resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.11.0.tgz#4b0e31c9bfc919608095cc429c4f1846f4d66c65" resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-5.1.0.tgz#9e7533cc256571a610c2a1ec8a7a143fb1222943"
integrity sha512-V+4khzYcE5EBk/BvcuYRq6V/osf11ODUM2J8hg2FDSswRrGvqiYUYPRy4OdrWaQOBj4NcpJfmHZLNaD+VH0TyA== integrity sha512-D3zug1270S4hbSlIRJ0CUS97QE1yNNKDjzQe3HqY0aefp2CBn9VgzgES27sRR2gOvFK+0CNx/BW0ggOESp6fqQ==
react-is@^16.13.1: react-is@^16.13.1:
version "16.13.1" version "16.13.1"