0% found this document useful (0 votes)
4 views6 pages

React Router Country Details App

Uploaded by

stephenojo48
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views6 pages

React Router Country Details App

Uploaded by

stephenojo48
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd

import { BrowserRouter as Router, Routes, Route } from "react-router-dom";

import Homepage from "./pages/Homepage";


import Login from "./pages/Login";
import SignUp from "./pages/SignUp";
import CountryDetail from "./pages/CountryDetail";

function App() {
return (
<>
<Router>
<Routes>
<Route path="/" element={<Homepage />} />
<Route path="/login" element={<Login />} />
<Route path="/signup" element={<SignUp />} />
<Route path="/countries" element={<CountryDetail />} />
</Routes>
</Router>
</>
);
}

export default App;

import React from "react";


import Hero from "../components/homepage/hero";
import Header from "../components/common/Header";
import Countries from "../components/homepage/Countries";
import WhyAfriTour from "../components/homepage/WhyAfriTour";
import Newsletter from "../components/homepage/Newsletter";
import Footer from "../components/homepage/Footer";
import FooterTest from "../components/homepage/FooterTest";
import Accommodations from "../components/homepage/Accommodations";

const Homepage = () => {


return (
<div>
<Header />
<Hero />
<WhyAfriTour />
<Countries />
<Accommodations/>
<Newsletter />
<Footer />
</div>
);
};

export default Homepage;

import React, { useEffect } from "react";


import { useSearchParams } from "react-router-dom";
import { countries } from "../data/countries";
import { Link } from "react-router-dom";
import { useState } from "react";

const CountryDetail = () => {


const [searchParams] = useSearchParams();
const countryParam = [Link]("country");

const country = [Link](


(eachCountry) => [Link] === countryParam,
);

const [imageIndex, setImageIndex] = useState({});

const [preloadedImages, setPreloadedImages] = useState(new Set());

const [selectedFilter, setSelectedFilter] = useState("all");

const [currentFactIndex, setCurrentFactIndex] = useState(0);

useEffect(() => {
const interval = setInterval(() => {
setCurrentFactIndex((prevIndex) => (prevIndex + 1) %
[Link]);
}, 5000);
return () => clearInterval(interval);
}, [[Link]]);

const preloadImage = (imageSrc) => {


if (![Link](imageSrc)) {
const img = new Image();
[Link] = imageSrc;
[Link] = () => {
setPreloadedImages((prev) => new Set([...prev, imageSrc]));
};
}
};

const handleImageClick = (locationId, imagesLocation) => {


setImageIndex((changingState) => {
const currentImageIndex = changingState[locationId] || 0;
const nextImageIndex =
currentImageIndex === [Link] - 1
? 0
: currentImageIndex + 1;

const imageAfterNext =
nextImageIndex === [Link] - 1 ? 0 : nextImageIndex + 1;
preloadImage(imagesLocation[imageAfterNext]);

return {
...changingState,
[locationId]: nextImageIndex,
};
});
};

if (!country) {
return (
<div className="flex min-h-screen items-center justify-center">
<div className="text-center">
<p className="mb-2 text-xl font-bold text-stone-800">
Country not found for parameter: {countryParam}
</p>
<p className="text-stone-600">
Try: /countries?country=egypt, /countries?country=morocco, etc.
</p>
</div>
</div>
);
}

const handleFilterClick = (filterName) => {


setSelectedFilter(filterName);
[Link]("Selected filter:", filterName);
};

return (
<div className="relative flex min-h-screen w-full flex-col">
{/* HERO SECTION */}
<div className="relative flex h-screen items-center justify-center">
<div className="absolute inset-0 z-0">
<img
src={[Link]}
alt=""
className="h-full w-full object-cover"
/>
</div>
<div className="absolute inset-0 z-10 bg-gradient-to-br from-stone-900/80
via-amber-900/40 to-stone-800/90"></div>

<div className="relative z-30 text-center">


<div className="rounded-2xl border border-white/10 bg-white/5 p-8
backdrop-blur-sm">
<h1 className="mb-4 text-6xl font-bold text-white">
{[Link]}
</h1>
<p className="max-w-2xl text-xl text-stone-200">
{[Link]}
</p>
</div>
</div>
</div>

{/* {Cultural Facts} */}


<section className="bg-amber-50 py-12">
<div className="mx-auto max-w-6xl px-4">
<div className="rounded-xl border-l-4 border-amber-600 bg-white p-6
shadow-md">
<div className="mb-3 flex items-center">
<div className="mr-3 flex h-8 w-8 items-center justify-center
rounded-full bg-amber-600">
<span className="text-sm font-bold text-white">!</span>
</div>
<h3 className="text-lg font-bold text-stone-800">
Cultural Insight
</h3>
</div>
<p className="text-lg leading-relaxed text-stone-700">
{[Link][currentFactIndex]}
</p>
<div className="mt-4 flex space-x-1">
{[Link]((_, index) => (
<div
key={index}
className={`h-1 rounded-full transition-all duration-300 ${
index === currentFactIndex
? "w-8 bg-amber-600"
: "w-2 bg-amber-200"
}`}
/>
))}
</div>
</div>
</div>
</section>

{/* Facts */}


<div className="bg-stone-50 px-8 py-16">
<div className="mx-auto max-w-6xl">
<h2 className="mb-12 text-center text-3xl font-bold text-stone-800">
Quick Facts About {[Link]}
</h2>

{/* Facts Grid */}


<div className="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
{/* Population */}
<div className="rounded-xl bg-white p-6 shadow-md transition-shadow
hover:bg-amber-50 hover:shadow-lg">
<div className="mb-2 text-2xl text-amber-600">👥</div>
<h3 className="mb-1 text-lg font-bold text-stone-800">
Population
</h3>
<p className="text-stone-600">{[Link]}</p>
</div>

{/* Capital */}


<div className="rounded-xl bg-white p-6 shadow-md transition-shadow
hover:bg-amber-50 hover:shadow-lg">
<div className="mb-2 text-2xl text-amber-600"></div>
<h3 className="mb-1 text-lg font-bold text-stone-800">Capital</h3>
<p className="text-stone-600">{[Link]}</p>
</div>

{/* Language */}


<div className="rounded-xl bg-white p-6 shadow-md transition-shadow
hover:bg-amber-50 hover:shadow-lg">
<div className="mb-2 text-2xl text-amber-600"></div>
<h3 className="mb-1 text-lg font-bold text-stone-800">
Language
</h3>
<p className="text-stone-600">{[Link]}</p>
</div>

{/* Currency */}


<div className="rounded-xl bg-white p-6 shadow-md transition-shadow
hover:bg-amber-50 hover:shadow-lg">
<div className="mb-2 text-2xl text-amber-600">💰</div>
<h3 className="mb-1 text-lg font-bold text-stone-800">
Currency
</h3>
<p className="text-stone-600">{[Link]}</p>
</div>

{/* Best Time */}


<div className="rounded-xl bg-white p-6 shadow-md transition-shadow
hover:bg-amber-50 hover:shadow-lg">
<div className="mb-2 text-2xl text-amber-600">🌞</div>
<h3 className="mb-1 text-lg font-bold text-stone-800">
Best Time
</h3>
<p className="text-stone-600">{[Link]}</p>
</div>

{/* Time Zone */}


<div className="rounded-xl bg-white p-6 shadow-md transition-shadow
hover:bg-amber-50 hover:shadow-lg">
<div className="mb-2 text-2xl text-amber-600">🕐</div>
<h3 className="mb-1 text-lg font-bold text-stone-800">
Time Zone
</h3>
<p className="text-stone-600">{[Link]}</p>
</div>
</div>
</div>
</div>

{/* Locations Section */}


<div className="p-8">
<h2 className="mb-4 text-2xl font-bold text-stone-400">
Top Destination
</h2>

{/* Filter Buttons */}


<div className="mb-6 flex flex-wrap gap-2">
<button
onClick={() => handleFilterClick("all")}
className={`rounded-full px-4 py-2 font-medium ${selectedFilter ===
"all" ? "bg-stone-800 text-white" : "bg-stone-200 text-stone-700 hover:bg-stone-
300"}`}
>
All
</button>

<button
onClick={() => handleFilterClick("ancient")}
className={`rounded-full px-4 py-2 font-medium ${selectedFilter ===
"ancient" ? "bg-stone-800 text-white" : "bg-stone-200 text-stone-700 hover:bg-
stone-300"}`}
>
Ancient
</button>

<button
onClick={() => handleFilterClick("adventure")}
className={`rounded-full px-4 py-2 font-medium ${selectedFilter ===
"adventure" ? "bg-stone-800 text-white" : "bg-stone-200 text-stone-700 hover:bg-
stone-300"}`}
>
Adventure
</button>
<button
onClick={() => handleFilterClick("safari")}
className={`rounded-full px-4 py-2 font-medium ${selectedFilter ===
"safari" ? "bg-stone-800 text-white" : "bg-stone-200 text-stone-700 hover:bg-stone-
300"}`}
>
Safari
</button>

<button
onClick={() => handleFilterClick("cultural")}
className={`rounded-full px-4 py-2 font-medium ${selectedFilter ===
"cultural" ? "bg-stone-800 text-white" : "bg-stone-200 text-stone-700 hover:bg-
stone-300"}`}
>
Cultural
</button>
</div>
{/* Map through locations */}
<div className="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
{[Link]
.filter((location) => {
if (selectedFilter === "all") {
return true;
}
return [Link](selectedFilter);
})

.map((location) => (
<div
key={[Link]}
className="rounded-lg bg-white p-4 shadow-md"
>
<img
src={[Link][imageIndex[[Link]] || 0]}
alt={[Link]}
className="mb-3 h-48 w-full cursor-pointer rounded-md object-
cover transition-all duration-300 ease-in-out hover:scale-105"
onClick={() =>
handleImageClick([Link], [Link])
}
/>
<h3 className="text-lg font-bold text-stone-800">
{[Link]}
</h3>
<p className="font-semibold text-amber-600">
${[Link]}
</p>
<p className="mt-2 text-sm text-stone-600">{[Link]}</p>
</div>
))}
</div>
</div>
</div>
);
};

export default CountryDetail;

You might also like