mirror of
https://github.com/TheRealOwenRees/echecsfrance.git
synced 2026-07-23 04:26:57 +00:00
Avatar with drop down menu for accessing zones and signing out
This commit is contained in:
@@ -3,11 +3,13 @@ import { useTranslations } from "next-intl";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
import { burgerMenuIsOpenAtom } from "@/atoms";
|
||||
import { useAuthMenuOptions } from "@/hooks/useAuthMenuOptions";
|
||||
import { Link } from "@/utils/navigation";
|
||||
|
||||
const HamburgerMenu = () => {
|
||||
const t = useTranslations("Nav");
|
||||
const [burgerMenuIsOpen, setBurgerMenuIsOpen] = useAtom(burgerMenuIsOpenAtom);
|
||||
const menuItems = useAuthMenuOptions();
|
||||
|
||||
const closeMenu = () => setBurgerMenuIsOpen(false);
|
||||
|
||||
@@ -20,35 +22,41 @@ const HamburgerMenu = () => {
|
||||
)}
|
||||
>
|
||||
<ul className="list-reset text-white">
|
||||
<li className="py-5 text-center text-xl">
|
||||
<Link
|
||||
onClick={closeMenu}
|
||||
href="/tournaments"
|
||||
className="border-b-2 border-transparent transition-all duration-300 ease-in-out hover:border-white"
|
||||
>
|
||||
<li className="py-3 text-center text-xl">
|
||||
<Link onClick={closeMenu} href="/tournaments">
|
||||
{t("tournaments")}
|
||||
</Link>
|
||||
</li>
|
||||
|
||||
<li className="py-5 text-center text-xl">
|
||||
<Link
|
||||
onClick={closeMenu}
|
||||
href="/clubs"
|
||||
className="border-b-2 border-transparent transition-all duration-300 ease-in-out hover:border-white"
|
||||
>
|
||||
<li className="py-3 text-center text-xl">
|
||||
<Link onClick={closeMenu} href="/clubs">
|
||||
{t("clubs")}
|
||||
</Link>
|
||||
</li>
|
||||
|
||||
<li className="py-5 text-center text-xl">
|
||||
<Link
|
||||
onClick={closeMenu}
|
||||
href="/elo"
|
||||
className="border-b-2 border-transparent transition-all duration-300 ease-in-out hover:border-white"
|
||||
>
|
||||
<li className="py-3 text-center text-xl">
|
||||
<Link onClick={closeMenu} href="/elo">
|
||||
{t("elo")}
|
||||
</Link>
|
||||
</li>
|
||||
|
||||
<hr className="my-5" />
|
||||
|
||||
{menuItems.map(({ title, onClick, className, disabled }, i) => (
|
||||
<li key={i} className="py-3 text-center text-xl">
|
||||
<button
|
||||
type="button"
|
||||
disabled={disabled}
|
||||
className={className}
|
||||
onClick={() => {
|
||||
onClick();
|
||||
closeMenu();
|
||||
}}
|
||||
>
|
||||
{title}
|
||||
</button>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -15,10 +15,7 @@ export default function Navbar() {
|
||||
] as const;
|
||||
|
||||
return (
|
||||
<nav
|
||||
className="relative mt-0 h-16 w-full overflow-x-clip border-b-[1px] bg-white px-5 dark:border-gray-700 dark:bg-gray-800"
|
||||
data-test="navbar"
|
||||
>
|
||||
<nav className="relative mt-0 h-16 w-full overflow-x-clip border-b-[1px] bg-white px-5 dark:border-gray-700 dark:bg-gray-800">
|
||||
<div className="container mx-auto flex h-full items-center justify-between">
|
||||
<Link
|
||||
className="font-extrabold text-gray-900 no-underline hover:no-underline dark:text-white"
|
||||
@@ -33,10 +30,7 @@ export default function Navbar() {
|
||||
<Hamburger />
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="hidden h-full justify-center md:flex md:w-1/2 md:justify-end"
|
||||
data-test="desktop-menu"
|
||||
>
|
||||
<div className="hidden h-full justify-center md:flex md:w-1/2 md:justify-end">
|
||||
<ul className="list-reset flex h-full flex-1 items-center gap-14 text-gray-900 no-underline dark:text-white md:flex-none">
|
||||
{links.map(({ title, route }) => (
|
||||
<li key={route} className="h-full">
|
||||
|
||||
@@ -6,7 +6,7 @@ export default function Contact() {
|
||||
const t = useTranslations("Contact");
|
||||
|
||||
return (
|
||||
<section className="grid place-items-center bg-white pb-20 dark:bg-gray-800">
|
||||
<section className="bg-white pb-20 dark:bg-gray-800">
|
||||
<div className="mx-auto max-w-screen-md px-4 py-8 lg:py-16">
|
||||
<h2
|
||||
className="mb-4 text-center text-4xl font-extrabold tracking-tight text-gray-900 dark:text-white"
|
||||
|
||||
@@ -5,6 +5,7 @@ import "leaflet-defaulticon-compatibility";
|
||||
import "leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility.css";
|
||||
import "leaflet/dist/leaflet.css";
|
||||
import { FeatureGroup, GeoJSON, MapContainer, TileLayer } from "react-leaflet";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
import { MapEvents } from "@/components/MapEvents";
|
||||
import type { ZoneModel } from "@/server/models/zoneModel";
|
||||
@@ -13,10 +14,10 @@ const center: LatLngLiteral = { lat: 47.0844, lng: 2.3964 };
|
||||
|
||||
export type ZoneThumbnailProps = {
|
||||
features: ZoneModel["features"];
|
||||
size: number;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
export const ZoneThumbnail = ({ features, size }: ZoneThumbnailProps) => {
|
||||
export const ZoneThumbnail = ({ features, className }: ZoneThumbnailProps) => {
|
||||
return (
|
||||
<MapContainer
|
||||
center={center}
|
||||
@@ -24,7 +25,7 @@ export const ZoneThumbnail = ({ features, size }: ZoneThumbnailProps) => {
|
||||
zoomControl={false}
|
||||
scrollWheelZoom={false}
|
||||
dragging={false}
|
||||
style={{ height: size, width: size }}
|
||||
className={twMerge("h-[200px] w-auto md:w-[200px]", className)}
|
||||
attributionControl={false}
|
||||
>
|
||||
<MapEvents bounds={L.geoJson(features).getBounds()} />
|
||||
|
||||
@@ -20,25 +20,27 @@ export default function ZonesLayout({ children }: { children: ReactNode }) {
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="mx-auto max-w-screen-md px-4 py-8 lg:py-16">
|
||||
{!sessionData ? (
|
||||
<div>
|
||||
<h2
|
||||
className="mb-4 text-center text-4xl font-extrabold tracking-tight text-gray-900 dark:text-white"
|
||||
data-test="header2"
|
||||
>
|
||||
{t("title")}
|
||||
</h2>
|
||||
<section className="bg-white pb-20 dark:bg-gray-800">
|
||||
<div className="mx-auto max-w-screen-md px-4 py-8 lg:py-16">
|
||||
{!sessionData ? (
|
||||
<div>
|
||||
<h2
|
||||
className="mb-4 text-center text-4xl font-extrabold tracking-tight text-gray-900 dark:text-white"
|
||||
data-test="header2"
|
||||
>
|
||||
{t("title")}
|
||||
</h2>
|
||||
|
||||
<p className="mb-8 text-center font-light text-gray-500 dark:text-gray-400 sm:text-xl lg:mb-16">
|
||||
{t("logonRequired")}
|
||||
</p>
|
||||
<p className="mb-8 text-center font-light text-gray-500 dark:text-gray-400 sm:text-xl lg:mb-16">
|
||||
{t("logonRequired")}
|
||||
</p>
|
||||
|
||||
<SignInForm />
|
||||
</div>
|
||||
) : (
|
||||
children
|
||||
)}
|
||||
</div>
|
||||
<SignInForm />
|
||||
</div>
|
||||
) : (
|
||||
children
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -86,12 +86,17 @@ const Zones = () => {
|
||||
|
||||
return (
|
||||
<div
|
||||
className="flex gap-4 text-gray-900 dark:text-white"
|
||||
className="flex flex-col gap-4 text-gray-900 dark:text-white md:flex-row"
|
||||
key={zone.id}
|
||||
>
|
||||
<ZoneThumbnail features={zone.features} size={200} />
|
||||
<div className="flex flex-1 flex-col justify-between">
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white">
|
||||
<h3 className="text-xl font-semibold text-gray-900 dark:text-white md:hidden">
|
||||
{zone.name}
|
||||
</h3>
|
||||
|
||||
<ZoneThumbnail features={zone.features} />
|
||||
|
||||
<div className="flex flex-1 flex-col justify-between gap-4">
|
||||
<h3 className="hidden text-xl font-semibold text-gray-900 dark:text-white md:block">
|
||||
{zone.name}
|
||||
</h3>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user