themes and dimensions

This commit is contained in:
Owen Rees
2023-06-12 15:41:09 +02:00
parent 95f0a37c76
commit 254d4603aa
18 changed files with 204 additions and 34 deletions
+3 -3
View File
@@ -1,14 +1,14 @@
need a 'return to top' arrow button on smaller screens need a 'return to top' arrow button on smaller screens
muti-language i18n support muti-language i18n support- https://nextjs.org/docs/app/building-your-application/routing/internationalization
light/dark theme light/dark theme in all components
tests for tournois, testing the loading of map and table, then counting the markers tests for tournois, testing the loading of map and table, then counting the markers
logo for navbar and favicon logo for navbar and favicon
hover on table needs fixing - this only seemed to happen once I moved the logic into its own hook hover on table needs fixing - this only seemed to happen once I moved the logic into its own hook <- error is occuring on all hovers at the moment. Client/SSR issue?
document my new hook document my new hook
+64 -5
View File
@@ -1,14 +1,73 @@
import Layout from "@/components/Layout"; import Layout from "@/components/Layout";
// TODO fix page sizing
export default function Contact() { export default function Contact() {
return ( return (
<Layout> <Layout>
<header className="grid h-[calc(100%-216px)] md:h-[calc(100%-172px)] place-items-center"> <section className="grid place-items-center bg-white dark:bg-gray-800">
<div className="relative h-full w-full bg-amber-200"></div> <div className="pt-8 pb-32 lg:pt-16 px-4 mx-auto max-w-screen-md">
<div className="absolute"> <h2 className="mb-4 text-4xl tracking-tight font-extrabold text-center text-gray-900 dark:text-white">
<h1>Contactez-Nous</h1> Contactez-Nous
</h2>
<p className="mb-8 lg:mb-16 font-light text-center text-gray-500 dark:text-gray-400 sm:text-xl">
Vous souhaitez ajouter les tournois de votre fédération sur ce site?
Vous avez un problème technique? Vous aimeriez participer à ce
projet? Contactez-nous.
</p>
<form action="#" className="space-y-8">
<div>
<label
htmlFor="email"
className="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300"
>
Adresse e-mail
</label>
<input
type="email"
id="email"
className="shadow-sm bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500 dark:shadow-sm-light"
placeholder="nom@exemple.com"
required
/>
</div>
<div>
<label
htmlFor="subject"
className="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300"
>
Sujet
</label>
<input
type="text"
id="subject"
className="block p-3 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 shadow-sm focus:ring-primary-500 focus:border-primary-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500 dark:shadow-sm-light"
placeholder="Le motif de ma demande"
required
/>
</div>
<div className="sm:col-span-2">
<label
htmlFor="message"
className="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300"
>
Votre message
</label>
<textarea
id="message"
rows={6}
className="block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded-lg shadow-sm border border-gray-300 focus:ring-primary-500 focus:border-primary-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500"
placeholder="Détaillez ici votre demande..."
></textarea>
</div>
<button
type="submit"
className="py-3 px-5 text-sm font-medium text-center text-white rounded-lg bg-teal-600 sm:w-fit hover:bg-primary-800 focus:ring-4 focus:outline-none focus:ring-primary-300 dark:hover:bg-primary-700 dark:focus:ring-primary-800 dark:text-white"
>
Send message
</button>
</form>
</div> </div>
</header> </section>
</Layout> </Layout>
); );
} }
+1 -1
View File
@@ -4,7 +4,7 @@ import Layout from "@/components/Layout";
export default function Home() { export default function Home() {
return ( return (
<Layout> <Layout>
<header className="grid h-[calc(100%-216px)] md:h-[calc(100%-172px)] place-items-center"> <header className="grid h-[calc(100%-153px)] md:h-[calc(100%-173px)] place-items-center">
<div className="relative h-full w-full bg-[url('/images/map-bg.jpg')] bg-cover bg-center brightness-[0.2]"></div> <div className="relative h-full w-full bg-[url('/images/map-bg.jpg')] bg-cover bg-center brightness-[0.2]"></div>
<div className="absolute text-center"> <div className="absolute text-center">
<h1 className="text-5xl p-5">Echecs France</h1> <h1 className="text-5xl p-5">Echecs France</h1>
+8 -3
View File
@@ -3,10 +3,15 @@ import Layout from "@/components/Layout";
export default function About() { export default function About() {
return ( return (
<Layout> <Layout>
<header className="grid h-[calc(100%-216px)] md:h-[calc(100%-172px)] place-items-center"> <header className="grid h-[calc(100%-216px)] md:h-[calc(100%-174px)] place-items-center">
<div className="relative h-full w-full bg-amber-200"></div> <div className="relative h-full w-full bg-white dark:bg-gray-800"></div>
<div className="absolute"> <div className="absolute">
<h1>Qui Sommes-Nous</h1> <h2 className="mb-4 text-4xl tracking-tight font-extrabold text-center text-gray-900 dark:text-white">
Qui Sommes-Nous?
</h2>
<p className="mb-8 lg:mb-16 font-light text-center text-gray-500 dark:text-gray-400 sm:text-xl">
Prochainement
</p>
</div> </div>
</header> </header>
</Layout> </Layout>
+2 -2
View File
@@ -13,7 +13,7 @@ import getTournaments from "@/utils/getTournamentData";
const TournamentMap = dynamic(() => import("@/components/TournamentMap"), { const TournamentMap = dynamic(() => import("@/components/TournamentMap"), {
ssr: false, ssr: false,
loading: () => ( loading: () => (
<div className="h-screen grid text-black place-items-center"> <div className="h-screen grid place-items-center text-gray-900 bg-white dark:bg-gray-800 dark:text-white">
<p>Loading map...</p> <p>Loading map...</p>
</div> </div>
), ),
@@ -28,7 +28,7 @@ export default async function Tournaments() {
<div className=""> <div className="">
<TournamentMap tournamentData={tournamentData} /> <TournamentMap tournamentData={tournamentData} />
</div> </div>
<div className="bg-gray-800 lg:overflow-y-auto"> <div className="bg-white dark:bg-gray-800 lg:overflow-y-auto">
<TournamentTable tournamentData={tournamentData} /> <TournamentTable tournamentData={tournamentData} />
</div> </div>
</main> </main>
+6 -3
View File
@@ -1,19 +1,22 @@
import Link from "next/link"; import Link from "next/link";
import { FaGithub } from "react-icons/fa"; import { FaGithub, FaRegEnvelope } from "react-icons/fa";
export default function Footer() { export default function Footer() {
return ( return (
<footer className="grid justify-items-center bg-gray-800 text-white py-2 px-5"> <footer className="grid w-full fixed bottom-0 justify-items-center py-2 px-5 text-white bg-teal-600 text-gray-900 dark:bg-gray-700">
<div className="p-2"> <div className="p-2">
<p>&copy; {new Date().getFullYear()} - Owen Rees</p> <p>&copy; {new Date().getFullYear()} - Owen Rees</p>
</div> </div>
<div className="p-2"> <div className="flex p-2 space-x-4">
<Link <Link
href="https://github.com/TheRealOwenRees/echecsfrance" href="https://github.com/TheRealOwenRees/echecsfrance"
target="_blank" target="_blank"
> >
<FaGithub /> <FaGithub />
</Link> </Link>
<Link href="/contactez-nous">
<FaRegEnvelope />
</Link>
</div> </div>
</footer> </footer>
); );
+22
View File
@@ -0,0 +1,22 @@
"use client";
import HamburgerMenu from "@/components/HamburgerMenu";
import { useState } from "react";
// TODO make hamburger menu slide in from the right instead of conditional rendering
const Hamburger = () => {
const [menuVisible, setMenuVisible] = useState(false);
return (
<>
{" "}
<div className="space-y-2" onClick={() => setMenuVisible(!menuVisible)}>
<div className="w-8 h-0.5 bg-gray-600 dark:bg-white"></div>
<div className="w-8 h-0.5 bg-gray-600 dark:bg-white"></div>
<div className="w-8 h-0.5 bg-gray-600 dark:bg-white"></div>
</div>
{menuVisible && <HamburgerMenu />}
</>
);
};
export default Hamburger;
+25
View File
@@ -0,0 +1,25 @@
import Link from "next/link";
import ThemeSwitcher from "@/components/ThemeSwitcher";
const HamburgerMenu = () => {
return (
<div className="hamburgerMenu absolute top-16 right-0 z-[9999] bg-teal-600 flex md:hidden dark:bg-gray-600">
<ul className="list-reset text-white p-5">
<li className="py-5">
<Link href="/tournois">Tournois</Link>
</li>
<li className="py-5">
<Link href="/qui-sommes-nous">Qui Sommes-Nous</Link>
</li>
<li className="py-5">
<Link href="/contactez-nous">Contactez-Nous</Link>
</li>
<li className="py-5">
<ThemeSwitcher />
</li>
</ul>
</div>
);
};
export default HamburgerMenu;
+1 -1
View File
@@ -7,7 +7,7 @@ export default function Layout({
children: React.ReactNode; children: React.ReactNode;
}) { }) {
return ( return (
<div className="h-screen min-h-[400px] bg-white font-sans leading-normal tracking-normal"> <div className="h-screen min-h-[600px] bg-white dark:bg-gray-800 font-sans leading-normal tracking-normal">
<Navbar /> <Navbar />
{children} {children}
<Footer /> <Footer />
+17 -8
View File
@@ -1,19 +1,25 @@
import Link from "next/link"; import Link from "next/link";
import ThemeSwitcher from "@/components/ThemeSwitcher";
import Hamburger from "@/components/Hamburger";
export default function Navbar() { export default function Navbar() {
return ( return (
<nav className="bg-gray-800 pt-5 mt-0 w-full md:pt-2 px-5"> <nav className="w-full relative border-b-[1px] pt-5 mt-0 px-5 md:pt-2 bg-white dark:bg-gray-800 dark:border-gray-700">
<div className="container mx-auto flex flex-wrap items-center"> <div className="container mx-auto flex items-center">
<div className="flex w-full md:w-1/2 justify-center md:justify-start text-white font-extrabold"> <div className="pb-3 justify-center flex w-full md:w-1/2 md:pb-0 md:justify-start font-extrabold">
<Link <Link
className="text-white no-underline hover:text-white hover:no-underline" className="text-gray-900 dark:text-white no-underline hover:no-underline"
href="/" href="/"
> >
<span className="text-2xl pl-2">Echecs France</span> <span className="text-2xl">Echecs France</span>
</Link> </Link>
</div> </div>
<div className="flex w-full pt-2 justify-center md:w-1/2 md:justify-end"> <div className="pb-2 md:hidden">
<ul className="list-reset text-white no-underline flex flex-1 justify-around md:flex-none items-center"> <Hamburger />
</div>
<div className="hidden pt-2 justify-center md:flex md:w-1/2 md:justify-end">
<ul className="list-reset text-gray-900 dark:text-white no-underline flex flex-1 justify-around md:flex-none items-center">
<li className="mr-10"> <li className="mr-10">
<Link <Link
className="inline-block border-b-4 py-5 border-transparent hover:border-teal-600 transition-all ease-in-out duration-300" className="inline-block border-b-4 py-5 border-transparent hover:border-teal-600 transition-all ease-in-out duration-300"
@@ -30,7 +36,7 @@ export default function Navbar() {
Qui Sommes-Nous Qui Sommes-Nous
</Link> </Link>
</li> </li>
<li className=""> <li className="mr-10">
<Link <Link
className="inline-block border-b-4 py-5 border-transparent hover:border-teal-600 transition-all ease-in-out duration-300" className="inline-block border-b-4 py-5 border-transparent hover:border-teal-600 transition-all ease-in-out duration-300"
href="/contactez-nous" href="/contactez-nous"
@@ -38,6 +44,9 @@ export default function Navbar() {
Contactez-Nous Contactez-Nous
</Link> </Link>
</li> </li>
<li>
<ThemeSwitcher />
</li>
</ul> </ul>
</div> </div>
</div> </div>
+1 -1
View File
@@ -11,7 +11,7 @@ const SearchBar = ({
}: SearchBarProps) => { }: SearchBarProps) => {
return ( return (
<> <>
<div className="p-3 bg-gray-800"> <div className="p-3 bg-white dark:bg-gray-800">
<label htmlFor="table-search" className="sr-only"> <label htmlFor="table-search" className="sr-only">
Search Search
</label> </label>
+23
View File
@@ -0,0 +1,23 @@
"use client";
import { MdOutlineDarkMode, MdLightbulbOutline } from "react-icons/md";
import useDarkMode from "@/hooks/useDarkMode";
// TODO write tests for light/mode
// TODO new SVG for light/dark theme
// TODO fix TS error on setTheme
const ThemeSwitcher = () => {
const [colorTheme, setTheme] = useDarkMode();
return (
<>
{colorTheme === "light" ? (
<MdOutlineDarkMode onClick={() => setTheme("light")} />
) : (
<MdLightbulbOutline onClick={() => setTheme("dark")} />
)}
</>
);
};
export default ThemeSwitcher;
+1 -1
View File
@@ -24,7 +24,7 @@ export default function TournamentMap({ tournamentData }: TournamentDataProps) {
return ( return (
<section <section
id="tournament-map" id="tournament-map"
className="grid h-[calc(100vh-128px)] md:h-[calc(100vh-82px)] lg:h-[calc(100vh-172px)]" className="grid h-[calc(100vh-153px)] md:h-[calc(100vh-82px)] lg:h-[calc(100vh-174px)]"
> >
<MapContainer <MapContainer
center={center} center={center}
+3 -3
View File
@@ -18,16 +18,16 @@ export default function TournamentTable({
console.log(filteredTournamentData.length); console.log(filteredTournamentData.length);
const stickyHeader = "sticky top-0 p-3 bg-gray-600"; const stickyHeader = "sticky top-0 p-3 bg-teal-600 dark:bg-gray-600";
return ( return (
<section className="w-full grid auto-rows-max lg:h-[calc(100vh-172px)] lg:col-start-2 lg:col-end-3"> <section className="w-full grid auto-rows-max pb-20 lg:h-[calc(100vh-174px)] lg:col-start-2 lg:col-end-3">
<SearchBar <SearchBar
tournamentFilter={tournamentFilter} tournamentFilter={tournamentFilter}
setTournamentFilter={setTournamentFilter} setTournamentFilter={setTournamentFilter}
/> />
<table className="relative table-fixed w-full text-center text-xs"> <table className="relative table-fixed w-full text-center text-xs">
<thead className="bg-gray-600 text-white"> <thead>
<tr> <tr>
<th className={stickyHeader}>Date</th> <th className={stickyHeader}>Date</th>
<th className={stickyHeader}>Ville</th> <th className={stickyHeader}>Ville</th>
+2 -2
View File
@@ -31,7 +31,7 @@ describe("Verify component mount", () => {
}); });
it("correct h1 tags with page title included", () => { it("correct h1 tags with page title included", () => {
cy.get("h1").contains("qui sommes-nous", { matchCase: false }); cy.get("h2").contains("qui sommes-nous", { matchCase: false });
}); });
navbarFooterCheck(); navbarFooterCheck();
@@ -43,7 +43,7 @@ describe("Verify component mount", () => {
}); });
it("correct h1 tags with page title included", () => { it("correct h1 tags with page title included", () => {
cy.get("h1").contains("contactez-nous", { matchCase: false }); cy.get("h2").contains("contactez-nous", { matchCase: false });
}); });
navbarFooterCheck(); navbarFooterCheck();
+23
View File
@@ -0,0 +1,23 @@
import { useEffect, useState } from "react";
function useDarkMode() {
const [theme, setTheme] = useState(
typeof window !== "undefined" ? localStorage.theme : "dark"
);
const colorTheme = theme === "dark" ? "light" : "dark";
useEffect(() => {
const root = window.document.documentElement;
root.classList.remove(colorTheme);
root.classList.add(theme);
if (typeof window !== "undefined") {
localStorage.setItem("theme", theme);
}
}, [theme]);
return [colorTheme, setTheme];
}
export default useDarkMode;
+1 -1
View File
@@ -25,7 +25,7 @@ const useTournamentDataFilter = (
} else { } else {
state = filtered.map((t) => ( state = filtered.map((t) => (
<tr <tr
className="border-b border-gray-700 border-opacity-20 bg-gray-800 text-white transition duration-300 ease-in-out hover:bg-gray-400 hover:text-black" className="text-gray-900 bg-white dark:bg-gray-800 dark:text-white hover:bg-gray-400 hover:text-black"
key={t._id} key={t._id}
> >
<td className="p-3"> <td className="p-3">
+1
View File
@@ -1,5 +1,6 @@
/** @type {import('tailwindcss').Config} */ /** @type {import('tailwindcss').Config} */
module.exports = { module.exports = {
darkMode: "class",
content: [ content: [
"./pages/**/*.{js,ts,jsx,tsx,mdx}", "./pages/**/*.{js,ts,jsx,tsx,mdx}",
"./components/**/*.{js,ts,jsx,tsx,mdx}", "./components/**/*.{js,ts,jsx,tsx,mdx}",