diff options
Diffstat (limited to 'app')
| -rw-r--r-- | app/Header.js | 12 | ||||
| -rw-r--r-- | app/Navbar.js | 46 | ||||
| -rw-r--r-- | app/PSA.js | 47 | ||||
| -rw-r--r-- | app/layout.js | 4 | ||||
| -rw-r--r-- | app/page.js | 4 | ||||
| -rw-r--r-- | app/psa.json | 5 | ||||
| -rw-r--r-- | app/services/page.js | 2 | ||||
| -rw-r--r-- | app/travel-advisory/HistoryModal.js | 40 | ||||
| -rw-r--r-- | app/travel-advisory/ListCountries.js | 66 | ||||
| -rw-r--r-- | app/travel-advisory/page.js | 4 | ||||
| -rw-r--r-- | app/updates/DateFormatter.js | 9 | ||||
| -rw-r--r-- | app/updates/PostPreview.js | 15 | ||||
| -rw-r--r-- | app/updates/[slug]/page.js | 4 | ||||
| -rw-r--r-- | app/updates/getPostMetadata.js | 24 | ||||
| -rw-r--r-- | app/updates/page.js | 6 |
15 files changed, 276 insertions, 12 deletions
diff --git a/app/Header.js b/app/Header.js new file mode 100644 index 0000000..bd70dd0 --- /dev/null +++ b/app/Header.js @@ -0,0 +1,12 @@ +const Header = ({title, description}) => { + return ( + <div className="bg-center bg-no-repeat bg-[url('/jumbotron.webp')] bg-gray-700 bg-blend-multiply"> + <div className="md:px-40 px-10 max-w-screen-xl text-left py-24 lg:py-10 space-y-3"> + <h1 className="font-medium text-4xl">{title}</h1> + <h2 className="font-light text-lg">{description}</h2> + </div> + </div> + ) +} + +export default Header; diff --git a/app/Navbar.js b/app/Navbar.js new file mode 100644 index 0000000..1555eb9 --- /dev/null +++ b/app/Navbar.js @@ -0,0 +1,46 @@ +"use client"; +import Image from "next/image"; +import Link from "next/link"; +import { useState } from "react"; + +const Navbar = () => { + const [navbar, setNavbar] = useState(false); + return ( + <nav className="border-gray-200 bg-neutral-900"> + <div className="max-w-screen-xl flex flex-wrap items-center justify-between mx-auto p-4"> + <div className="flex items-center"> + <Image src="/alure_flag.svg" className="mr-5" alt="Alure Flag" width={70} height={70}/> + <span className="self-center text-2xl font-medium whitespace-nowrap dark:text-white"><p>Government</p><p>of Alure Regions</p></span> + </div> + <button data-collapse-toggle="navbar-default" type="button" + className="transition duration-150 ease-out hover:ease-in inline-flex items-center p-2 w-10 h-10 justify-center text-sm text-gray-500 rounded-lg md:hidden hover:bg-zinc-600 focus:outline-none focus:ring-2 focus:ring-gray-200 dark:text-gray-400 dark:hover:bg-gray-700 dark:focus:ring-gray-600" + aria-controls="navbar-default" aria-expanded="false" onClick={() => setNavbar(!navbar)}> + <span className="sr-only">Open main menu</span> + <svg className="w-5 h-5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" + viewBox="0 0 17 14"> + <path stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" + d="M1 1h15M1 7h15M1 13h15"/> + </svg> + </button> + <div className={`w-full md:block md:w-auto ${navbar ? 'block' : 'hidden' }`}> + <ul className="font-medium text-lg flex flex-col p-4 md:p-0 mt-4 rounded-lg md:flex-row md:space-x-8 md:mt-0"> + {[ + ['Home', '/'], + ['Updates', '/updates'], + ['Services', '/services'], + ['Travel Advisory', '/travel-advisory'], + ].map(([title, url]) => ( + <li key="links"> + <Link href={url} className="transition duration-150 ease-out hover:ease-in block py-2 pl-3 pr-4 rounded md:border-0 md:p-0 text-white md:hover:text-blue-500 hover:bg-gray-700 hover:text-white md:hover:bg-transparent" onClick={() => setNavbar(!navbar)}> + {title} + </Link> + </li> + ))} + </ul> + </div> + </div> + </nav> + ) +} + +export default Navbar; diff --git a/app/PSA.js b/app/PSA.js new file mode 100644 index 0000000..06bf9ba --- /dev/null +++ b/app/PSA.js @@ -0,0 +1,47 @@ +import psaMessage from './psa.json' assert { type: 'json' }; +import Link from "next/link"; + +const PSA = () => { + let defaultStyle = "flex flex-row md:px-40 px-30 py-0.5 space-x-2"; + let styleImportant; + let important; + switch (psaMessage.important) { + case 0: + styleImportant = "hidden" + defaultStyle += ' ' + styleImportant + break; + case 1: + important = "Latest News:" + styleImportant = "bg-zinc-700" + defaultStyle += ' ' + styleImportant + break; + case 2: + important = "WARNING!" + styleImportant = "bg-yellow-700" + defaultStyle += ' ' + styleImportant + break; + case 3: + important = "EMERGENCY!" + styleImportant = "bg-red-800" + defaultStyle += ' ' + styleImportant + break; + + } + + return ( + <div className={defaultStyle}> + <p className="text-lg font-medium">{important}</p> + <div className="flex flex-row space-x-3"> + <p>{psaMessage.announcement}</p> + <p className="text-blue-200 hover:text-blue-500 active:text-blue-700"> + {psaMessage.link && ( + <Link href={psaMessage.link}> + Learn more ↗ + </Link> + )}</p> + </div> + </div> + ) +} + +export default PSA; diff --git a/app/layout.js b/app/layout.js index fa5c790..50dad73 100644 --- a/app/layout.js +++ b/app/layout.js @@ -1,7 +1,7 @@ import './globals.css' import { Exo } from 'next/font/google' -import Navbar from "@/components/Navbar"; -import PSA from "@/components/PSA"; +import Navbar from "@/app/Navbar"; +import PSA from "@/app/PSA"; const exo = Exo({ subsets: ['latin'] }) diff --git a/app/page.js b/app/page.js index 60f5965..5a089df 100644 --- a/app/page.js +++ b/app/page.js @@ -1,5 +1,5 @@ -import getPostMetadata from "@/components/updates/getPostMetadata"; -import PostPreview from "@/components/updates/PostPreview"; +import getPostMetadata from "@/app/updates/getPostMetadata"; +import PostPreview from "@/app/updates/PostPreview"; import Link from "next/link"; export const metadata = { diff --git a/app/psa.json b/app/psa.json new file mode 100644 index 0000000..df9869f --- /dev/null +++ b/app/psa.json @@ -0,0 +1,5 @@ +{ + "important": 0, + "announcement": "No important announcements", + "link": "https://google.ca" +} diff --git a/app/services/page.js b/app/services/page.js index c91b92e..3acd69f 100644 --- a/app/services/page.js +++ b/app/services/page.js @@ -1,4 +1,4 @@ -import Header from "@/components/Header"; +import Header from "@/app/Header"; export const metadata = { title: 'Services', diff --git a/app/travel-advisory/HistoryModal.js b/app/travel-advisory/HistoryModal.js new file mode 100644 index 0000000..3ef2ea8 --- /dev/null +++ b/app/travel-advisory/HistoryModal.js @@ -0,0 +1,40 @@ +const HistoryModal = ({ isVisible, onClose, countries, dangerLevel, history }) => { + if (!isVisible) return null; + const handleClose = (e) => { + if(e.target.id === 'wrapper') onClose(); + } + + let historyList; + if (history && history.length > 0) { + historyList = history.map((event, index) => { + return ( + <li key={index}>{event}</li> + ) + }) + } else { + historyList = <li>Currently no diplomatic tensions in this country.</li>; + } + + return ( + <div id="wrapper" className="fixed inset-0 bg bg-opacity-25 backdrop-blur-sm flex justify-center items-center" onClick={handleClose}> + <div className="w-[700px]"> + <div className="flex flex-col"> + <div className="bg-zinc-800 p-5 rounded-lg border border-gray-700"> + <div className="divide-y space-y-3"> + <div> + <h1 className="font-medium text-3xl">{countries}</h1> + <h2 className="font-medium text-xl">{dangerLevel}</h2> + </div> + <div> + <h1 className="font-medium text-2xl pt-3">History</h1> + <ul>{historyList}</ul> + </div> + </div> + </div> + </div> + </div> + </div> + ) +} + +export default HistoryModal; diff --git a/app/travel-advisory/ListCountries.js b/app/travel-advisory/ListCountries.js new file mode 100644 index 0000000..c2e233d --- /dev/null +++ b/app/travel-advisory/ListCountries.js @@ -0,0 +1,66 @@ +"use client" +import countriesData from '@/app/travel-advisory/countries.json' assert { type: 'json' }; +import HistoryModal from "@/app/travel-advisory/HistoryModal"; +import { useState } from "react"; + +export function getDangerLevel(danger) { + let dangerLevel; + switch (danger) { + case 0: + dangerLevel = "Take normal security precautions" + break; + case 1: + dangerLevel = "Exercise a high degree of caution" + break; + case 2: + dangerLevel = "Avoid non-essential travel" + break; + case 3: + dangerLevel = "Avoid all travel" + break; + default: + dangerLevel = "Seems like the danger level is broken!" + break; + } + + return dangerLevel; +} + +export function Countries(){ + // eslint-disable-next-line react-hooks/rules-of-hooks + const [showModal, setShowModal] = useState(false); + const [selectedCountry, setSelectedCountry] = useState(null); + const [selectedDangerLevel, setSelectedDangerLevel] = useState(null); + const [selectedCountryHistory, setSelectedCountryHistory] = useState(null); + const countries = countriesData.countries; + + return countries.map((country) => { + let dangerLevel = getDangerLevel(country.danger); + + const settlementsList = country.settlements.map((settlement) => { + return ( + <div key={settlement.name}> + <h2 className="font-medium md:text-3xl text-xl">{settlement.name}</h2> + <h2 className="text-base">{getDangerLevel(settlement.danger)}</h2> + </div> + ) + }) + + return ( + <div key="countries" className="bg-center bg-no-repeat bg-[image:var(--image-url)] bg-gray-500 bg-blend-multiply" style={{'--image-url': `url(${country.image})`}} > + <div className="sm:px-40 px-10 py-10 space-y-3"> + <h1 className="font-medium md:text-5xl text-3xl">{country.name}</h1> + <h2 className="text-lg">{dangerLevel}</h2> + <div className="space-y-3">{settlementsList}</div> + <button className="transition duration-200 ease-in-out px-4 py-2 font-medium rounded-full bg-blue-600 hover:bg-blue-700 active:bg-blue-800" onClick={()=> { + setSelectedCountry(country.name); + setSelectedDangerLevel(dangerLevel) + setSelectedCountryHistory(country.history) + setShowModal(true) + }}>Information</button> + </div> + <HistoryModal isVisible={showModal} onClose={() => setShowModal(false)} countries={selectedCountry} dangerLevel={selectedDangerLevel} history={selectedCountryHistory} /> + </div> + ) + }) +} diff --git a/app/travel-advisory/page.js b/app/travel-advisory/page.js index 415b6c2..259aaa4 100644 --- a/app/travel-advisory/page.js +++ b/app/travel-advisory/page.js @@ -1,5 +1,5 @@ -import { Countries, getDangerLevel } from "@/components/travel-advisory/ListCountries"; -import Header from "@/components/Header"; +import { Countries, getDangerLevel } from "@/app/travel-advisory/ListCountries"; +import Header from "@/app/Header"; export const metadata = { title: 'Travel Advisory', diff --git a/app/updates/DateFormatter.js b/app/updates/DateFormatter.js new file mode 100644 index 0000000..9e236d0 --- /dev/null +++ b/app/updates/DateFormatter.js @@ -0,0 +1,9 @@ + +import { parseISO, format } from 'date-fns' + +const DateFormatter = (dateString) => { + const date = parseISO(dateString) + return <time dateTime={dateString}>{format(date, 'LLLL d, yyyy')}</time> +} + +export default DateFormatter diff --git a/app/updates/PostPreview.js b/app/updates/PostPreview.js new file mode 100644 index 0000000..23e2176 --- /dev/null +++ b/app/updates/PostPreview.js @@ -0,0 +1,15 @@ +import Link from "next/link"; +import DateFormatter from '@/app/updates/DateFormatter' + +export default function PostPreview(props) { + return ( + <div key="post" className="bg-zinc-800 py-3 px-5 border border-gray-600 rounded-lg space-y-3"> + <Link href={`/updates/${props.slug}`}> + <h2 className="font-medium text-2xl hover:underline">{props.title}</h2> + </Link> + <span className="text-sm">{props.author}</span> + <p>{props.description}</p> + <p className="font-medium text-sm">Posted on {DateFormatter(props.date)}</p> + </div> + ) +} diff --git a/app/updates/[slug]/page.js b/app/updates/[slug]/page.js index d91440e..102a98a 100644 --- a/app/updates/[slug]/page.js +++ b/app/updates/[slug]/page.js @@ -1,8 +1,8 @@ import {readFileSync} from "fs"; import Markdown from "markdown-to-jsx" import matter from "gray-matter"; -import getPostMetadata from "@/components/updates/getPostMetadata"; -import DateFormatter from "@/components/updates/DateFormatter"; +import getPostMetadata from "@/app/updates/getPostMetadata"; +import DateFormatter from "@/app/updates/DateFormatter"; const getPostContent = (slug) => { const folder = "posts/"; diff --git a/app/updates/getPostMetadata.js b/app/updates/getPostMetadata.js new file mode 100644 index 0000000..515cc79 --- /dev/null +++ b/app/updates/getPostMetadata.js @@ -0,0 +1,24 @@ +import {readdirSync, readFileSync} from "fs"; +import matter from "gray-matter"; + +export default function getPostMetadata() { + const folder = "posts/"; + const files = readdirSync(folder); + const markdownPosts = files.filter((file) => file.endsWith(".md")); + + const posts = markdownPosts.map((fileName) => { + const fileContent = readFileSync(`posts/${fileName}`, "utf-8"); + const matterResult = matter(fileContent); + return { + title: matterResult.data.title, + author: matterResult.data.author, + date: matterResult.data.date, + description: matterResult.data.description, + slug: fileName.replace(".md", "") + } + }) + + // Sort the posts by date in descending order + posts.sort((a, b) => new Date(b.date) - new Date(a.date)); + return posts +} diff --git a/app/updates/page.js b/app/updates/page.js index 04215c9..148c135 100644 --- a/app/updates/page.js +++ b/app/updates/page.js @@ -1,6 +1,6 @@ -import getPostMetadata from "@/components/updates/getPostMetadata"; -import PostPreview from "@/components/updates/PostPreview"; -import Header from "@/components/Header"; +import getPostMetadata from "@/app/updates/getPostMetadata"; +import PostPreview from "@/app/updates/PostPreview"; +import Header from "@/app/Header"; export const metadata = { title: 'Updates', |
