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
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
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
+64 -5
View File
@@ -1,14 +1,73 @@
import Layout from "@/components/Layout";
// TODO fix page sizing
export default function Contact() {
return (
<Layout>
<header className="grid h-[calc(100%-216px)] md:h-[calc(100%-172px)] place-items-center">
<div className="relative h-full w-full bg-amber-200"></div>
<div className="absolute">
<h1>Contactez-Nous</h1>
<section className="grid place-items-center bg-white dark:bg-gray-800">
<div className="pt-8 pb-32 lg:pt-16 px-4 mx-auto max-w-screen-md">
<h2 className="mb-4 text-4xl tracking-tight font-extrabold text-center text-gray-900 dark:text-white">
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>
</header>
</section>
</Layout>
);
}
+1 -1
View File
@@ -4,7 +4,7 @@ import Layout from "@/components/Layout";
export default function Home() {
return (
<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="absolute text-center">
<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() {
return (
<Layout>
<header className="grid h-[calc(100%-216px)] md:h-[calc(100%-172px)] place-items-center">
<div className="relative h-full w-full bg-amber-200"></div>
<header className="grid h-[calc(100%-216px)] md:h-[calc(100%-174px)] place-items-center">
<div className="relative h-full w-full bg-white dark:bg-gray-800"></div>
<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>
</header>
</Layout>
+2 -2
View File
@@ -13,7 +13,7 @@ import getTournaments from "@/utils/getTournamentData";
const TournamentMap = dynamic(() => import("@/components/TournamentMap"), {
ssr: false,
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>
</div>
),
@@ -28,7 +28,7 @@ export default async function Tournaments() {
<div className="">
<TournamentMap tournamentData={tournamentData} />
</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} />
</div>
</main>
+6 -3
View File
@@ -1,19 +1,22 @@
import Link from "next/link";
import { FaGithub } from "react-icons/fa";
import { FaGithub, FaRegEnvelope } from "react-icons/fa";
export default function Footer() {
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">
<p>&copy; {new Date().getFullYear()} - Owen Rees</p>
</div>
<div className="p-2">
<div className="flex p-2 space-x-4">
<Link
href="https://github.com/TheRealOwenRees/echecsfrance"
target="_blank"
>
<FaGithub />
</Link>
<Link href="/contactez-nous">
<FaRegEnvelope />
</Link>
</div>
</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;
}) {
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 />
{children}
<Footer />
+17 -8
View File
@@ -1,19 +1,25 @@
import Link from "next/link";
import ThemeSwitcher from "@/components/ThemeSwitcher";
import Hamburger from "@/components/Hamburger";
export default function Navbar() {
return (
<nav className="bg-gray-800 pt-5 mt-0 w-full md:pt-2 px-5">
<div className="container mx-auto flex flex-wrap items-center">
<div className="flex w-full md:w-1/2 justify-center md:justify-start text-white font-extrabold">
<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 items-center">
<div className="pb-3 justify-center flex w-full md:w-1/2 md:pb-0 md:justify-start font-extrabold">
<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="/"
>
<span className="text-2xl pl-2">Echecs France</span>
<span className="text-2xl">Echecs France</span>
</Link>
</div>
<div className="flex w-full pt-2 justify-center md:w-1/2 md:justify-end">
<ul className="list-reset text-white no-underline flex flex-1 justify-around md:flex-none items-center">
<div className="pb-2 md:hidden">
<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">
<Link
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
</Link>
</li>
<li className="">
<li className="mr-10">
<Link
className="inline-block border-b-4 py-5 border-transparent hover:border-teal-600 transition-all ease-in-out duration-300"
href="/contactez-nous"
@@ -38,6 +44,9 @@ export default function Navbar() {
Contactez-Nous
</Link>
</li>
<li>
<ThemeSwitcher />
</li>
</ul>
</div>
</div>
+1 -1
View File
@@ -11,7 +11,7 @@ const SearchBar = ({
}: SearchBarProps) => {
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">
Search
</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 (
<section
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
center={center}
+3 -3
View File
@@ -18,16 +18,16 @@ export default function TournamentTable({
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 (
<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
tournamentFilter={tournamentFilter}
setTournamentFilter={setTournamentFilter}
/>
<table className="relative table-fixed w-full text-center text-xs">
<thead className="bg-gray-600 text-white">
<thead>
<tr>
<th className={stickyHeader}>Date</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", () => {
cy.get("h1").contains("qui sommes-nous", { matchCase: false });
cy.get("h2").contains("qui sommes-nous", { matchCase: false });
});
navbarFooterCheck();
@@ -43,7 +43,7 @@ describe("Verify component mount", () => {
});
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();
+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 {
state = filtered.map((t) => (
<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}
>
<td className="p-3">
+1
View File
@@ -1,5 +1,6 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
darkMode: "class",
content: [
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
"./components/**/*.{js,ts,jsx,tsx,mdx}",