mirror of
https://github.com/TheRealOwenRees/echecsfrance.git
synced 2026-07-23 04:26:57 +00:00
Fix routing details
This commit is contained in:
@@ -1,13 +1,27 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useTranslations } from "next-intl";
|
import { useLocale, useTranslations } from "next-intl";
|
||||||
import { useSearchParams } from "next/navigation";
|
import { useSearchParams } from "next/navigation";
|
||||||
|
|
||||||
import { SignInForm } from "@/components/SignInForm";
|
import { SignInForm } from "@/components/SignInForm";
|
||||||
|
import { Locale, getPathname, routing } from "@/utils/routing";
|
||||||
|
|
||||||
export default function SignIn() {
|
export default function SignIn() {
|
||||||
const t = useTranslations("SignIn");
|
const t = useTranslations("SignIn");
|
||||||
const params = useSearchParams();
|
const params = useSearchParams();
|
||||||
|
const locale = useLocale();
|
||||||
|
|
||||||
|
const allowedLocales = routing.locales as unknown as Array<string>;
|
||||||
|
const effectiveLocal = allowedLocales.includes(locale)
|
||||||
|
? (locale as Locale)
|
||||||
|
: routing.defaultLocale;
|
||||||
|
|
||||||
|
const fallbackPath = getPathname({
|
||||||
|
locale: effectiveLocal,
|
||||||
|
href: { pathname: "/tournaments" },
|
||||||
|
});
|
||||||
|
|
||||||
|
const fallbackUrl = `/${effectiveLocal}${fallbackPath}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="grid place-items-center bg-white pb-20 dark:bg-gray-800">
|
<section className="grid place-items-center bg-white pb-20 dark:bg-gray-800">
|
||||||
@@ -22,9 +36,7 @@ export default function SignIn() {
|
|||||||
{t("info")}
|
{t("info")}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<SignInForm
|
<SignInForm callbackPath={params.get("callbackUrl") ?? fallbackUrl} />
|
||||||
callbackPath={params.get("callbackUrl") ?? "/tournaments"}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { FaGithub, FaRegEnvelope } from "react-icons/fa";
|
|||||||
import { MdOutlinePrivacyTip } from "react-icons/md";
|
import { MdOutlinePrivacyTip } from "react-icons/md";
|
||||||
|
|
||||||
import { burgerMenuIsOpenAtom } from "@/atoms";
|
import { burgerMenuIsOpenAtom } from "@/atoms";
|
||||||
import { Link, usePathname, useRouter } from "@/utils/navigation";
|
import { Link, usePathname, useRouter } from "@/utils/routing";
|
||||||
|
|
||||||
import ThemeSwitcher from "./ThemeSwitcher";
|
import ThemeSwitcher from "./ThemeSwitcher";
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { twMerge } from "tailwind-merge";
|
|||||||
|
|
||||||
import { burgerMenuIsOpenAtom } from "@/atoms";
|
import { burgerMenuIsOpenAtom } from "@/atoms";
|
||||||
import { useAuthMenuOptions } from "@/hooks/useAuthMenuOptions";
|
import { useAuthMenuOptions } from "@/hooks/useAuthMenuOptions";
|
||||||
import { Link } from "@/utils/navigation";
|
import { Link } from "@/utils/routing";
|
||||||
|
|
||||||
const HamburgerMenu = () => {
|
const HamburgerMenu = () => {
|
||||||
const t = useTranslations("Nav");
|
const t = useTranslations("Nav");
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
|
|
||||||
import AuthButton from "@/components/AuthButton";
|
import AuthButton from "@/components/AuthButton";
|
||||||
import { Link } from "@/utils/navigation";
|
import { Link } from "@/utils/routing";
|
||||||
|
|
||||||
import Hamburger from "./Hamburger";
|
import Hamburger from "./Hamburger";
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { useTranslations } from "next-intl";
|
|||||||
|
|
||||||
import InfoMessage from "@/components/InfoMessage";
|
import InfoMessage from "@/components/InfoMessage";
|
||||||
import { deleteAccount } from "@/server/deleteAccount";
|
import { deleteAccount } from "@/server/deleteAccount";
|
||||||
import { useRouter } from "@/utils/navigation";
|
import { useRouter } from "@/utils/routing";
|
||||||
|
|
||||||
export default function Contact() {
|
export default function Contact() {
|
||||||
const t = useTranslations("DeleteAccount");
|
const t = useTranslations("DeleteAccount");
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import { fetchTournamentResultsSchema } from "@/schemas";
|
|||||||
import { fetchTournamentResults } from "@/server/fetchTournamentResults";
|
import { fetchTournamentResults } from "@/server/fetchTournamentResults";
|
||||||
import { SearchedTournament } from "@/server/searchTournaments";
|
import { SearchedTournament } from "@/server/searchTournaments";
|
||||||
import { TimeControl } from "@/types";
|
import { TimeControl } from "@/types";
|
||||||
import { Link } from "@/utils/navigation";
|
import { Link } from "@/utils/routing";
|
||||||
|
|
||||||
import { KFactor } from "./KFactor";
|
import { KFactor } from "./KFactor";
|
||||||
import { ManualEloForm } from "./ManualEloForm";
|
import { ManualEloForm } from "./ManualEloForm";
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ import {
|
|||||||
} from "@/atoms";
|
} from "@/atoms";
|
||||||
import { Map, MapMarker } from "@/components/Map";
|
import { Map, MapMarker } from "@/components/Map";
|
||||||
import { TimeControlColours } from "@/constants";
|
import { TimeControlColours } from "@/constants";
|
||||||
import { generatePieSVG } from "@/lib/pie";
|
|
||||||
import { TimeControl } from "@/types";
|
import { TimeControl } from "@/types";
|
||||||
|
import { generatePieSVG } from "@/utils/pie";
|
||||||
|
|
||||||
import Legend from "./Legend";
|
import Legend from "./Legend";
|
||||||
import TimeControlFilters from "./TimeControlFilters";
|
import TimeControlFilters from "./TimeControlFilters";
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { useTranslations } from "next-intl";
|
|||||||
import InfoMessage, { clearMessage } from "@/components/InfoMessage";
|
import InfoMessage, { clearMessage } from "@/components/InfoMessage";
|
||||||
import { useZones } from "@/hooks/useZones";
|
import { useZones } from "@/hooks/useZones";
|
||||||
import { createZone } from "@/server/createZone";
|
import { createZone } from "@/server/createZone";
|
||||||
import { useRouter } from "@/utils/navigation";
|
import { useRouter } from "@/utils/routing";
|
||||||
|
|
||||||
import { ZoneForm, ZoneFormValues } from "../components/ZoneForm";
|
import { ZoneForm, ZoneFormValues } from "../components/ZoneForm";
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { useParams } from "next/navigation";
|
|||||||
import InfoMessage, { clearMessage } from "@/components/InfoMessage";
|
import InfoMessage, { clearMessage } from "@/components/InfoMessage";
|
||||||
import { useZones } from "@/hooks/useZones";
|
import { useZones } from "@/hooks/useZones";
|
||||||
import { editZone } from "@/server/editZone";
|
import { editZone } from "@/server/editZone";
|
||||||
import { useRouter } from "@/utils/navigation";
|
import { useRouter } from "@/utils/routing";
|
||||||
|
|
||||||
import { ZoneForm, ZoneFormValues } from "../../components/ZoneForm";
|
import { ZoneForm, ZoneFormValues } from "../../components/ZoneForm";
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { Spinner } from "@/components/Spinner";
|
|||||||
import { useZones } from "@/hooks/useZones";
|
import { useZones } from "@/hooks/useZones";
|
||||||
import { deleteZone } from "@/server/deleteZone";
|
import { deleteZone } from "@/server/deleteZone";
|
||||||
import { TimeControl } from "@/types";
|
import { TimeControl } from "@/types";
|
||||||
import { Link, useRouter } from "@/utils/navigation";
|
import { Link, useRouter } from "@/utils/routing";
|
||||||
|
|
||||||
const ZoneThumbnail = dynamic(() => import("./components/ZoneThumbnail"), {
|
const ZoneThumbnail = dynamic(() => import("./components/ZoneThumbnail"), {
|
||||||
ssr: false,
|
ssr: false,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { HiUserGroup } from "react-icons/hi2";
|
|||||||
import { twMerge } from "tailwind-merge";
|
import { twMerge } from "tailwind-merge";
|
||||||
|
|
||||||
import bannerImage from "@/img/banner.jpeg";
|
import bannerImage from "@/img/banner.jpeg";
|
||||||
import { Link } from "@/utils/navigation";
|
import { Link } from "@/utils/routing";
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
const t = useTranslations("Home");
|
const t = useTranslations("Home");
|
||||||
|
|||||||
+16
-14
@@ -1,28 +1,30 @@
|
|||||||
import { MetadataRoute } from "next";
|
import { MetadataRoute } from "next";
|
||||||
|
|
||||||
import { locales, pathnames } from "@/utils/navigation";
|
import { Pathnames, routing } from "@/utils/routing";
|
||||||
|
|
||||||
export default function sitemap(): MetadataRoute.Sitemap {
|
export default function sitemap(): MetadataRoute.Sitemap {
|
||||||
return locales.flatMap((locale) => {
|
return routing.locales.flatMap((locale) => {
|
||||||
const prefix = `https://echecsfrance.com${
|
const prefix = `https://echecsfrance.com${
|
||||||
locale === "fr" ? "" : `/${locale}`
|
locale === "fr" ? "" : `/${locale}`
|
||||||
}`;
|
}`;
|
||||||
|
|
||||||
const paths = Object.keys(pathnames) as Array<keyof typeof pathnames>;
|
const paths = Object.keys(routing.pathnames) as Array<Pathnames>;
|
||||||
|
|
||||||
|
return paths
|
||||||
|
.filter((pathname) => !pathname.includes("["))
|
||||||
|
.map((pathname) => {
|
||||||
|
const route = routing.pathnames[pathname];
|
||||||
|
if (typeof route === "string") {
|
||||||
|
return {
|
||||||
|
url: `${prefix}${route}`,
|
||||||
|
lastModified: new Date(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return paths.map((pathname) => {
|
|
||||||
const route = pathnames[pathname];
|
|
||||||
if (typeof route === "string") {
|
|
||||||
return {
|
return {
|
||||||
url: `${prefix}${route}`,
|
url: `${prefix}${route[locale]}`,
|
||||||
lastModified: new Date(),
|
lastModified: new Date(),
|
||||||
};
|
};
|
||||||
}
|
});
|
||||||
|
|
||||||
return {
|
|
||||||
url: `${prefix}${route[locale]}`,
|
|
||||||
lastModified: new Date(),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import { regionFilterAtom } from "@/atoms";
|
|||||||
import { BaseOption, Select, SelectProps } from "@/components/form/Select";
|
import { BaseOption, Select, SelectProps } from "@/components/form/Select";
|
||||||
import { useZones } from "@/hooks/useZones";
|
import { useZones } from "@/hooks/useZones";
|
||||||
import { Zone } from "@/server/myZones";
|
import { Zone } from "@/server/myZones";
|
||||||
import { useRouter } from "@/utils/navigation";
|
import { useRouter } from "@/utils/routing";
|
||||||
|
|
||||||
type RegionSelectProps = Omit<
|
type RegionSelectProps = Omit<
|
||||||
SelectProps<false, string, Zone | null>,
|
SelectProps<false, string, Zone | null>,
|
||||||
|
|||||||
@@ -4,14 +4,14 @@ import { useEffect, useState } from "react";
|
|||||||
|
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { signIn } from "next-auth/react";
|
import { signIn } from "next-auth/react";
|
||||||
import { useLocale, useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
|
import { usePathname as useRawPathname } from "next/navigation";
|
||||||
import { FormProvider, useForm } from "react-hook-form";
|
import { FormProvider, useForm } from "react-hook-form";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { clearMessage } from "@/components/InfoMessage";
|
import { clearMessage } from "@/components/InfoMessage";
|
||||||
import InfoMessage from "@/components/InfoMessage";
|
import InfoMessage from "@/components/InfoMessage";
|
||||||
import { TextField } from "@/components/form/TextField";
|
import { TextField } from "@/components/form/TextField";
|
||||||
import { usePathname } from "@/utils/navigation";
|
|
||||||
|
|
||||||
const signInSchema = z.object({
|
const signInSchema = z.object({
|
||||||
email: z.string().email(),
|
email: z.string().email(),
|
||||||
@@ -25,14 +25,17 @@ type SignInFormProps = {
|
|||||||
|
|
||||||
export const SignInForm = ({ callbackPath }: SignInFormProps) => {
|
export const SignInForm = ({ callbackPath }: SignInFormProps) => {
|
||||||
const t = useTranslations("SignIn");
|
const t = useTranslations("SignIn");
|
||||||
const locale = useLocale();
|
|
||||||
const path = usePathname();
|
// We use the version from next/navigation to get the raw pathname in the current locale
|
||||||
|
const path = useRawPathname();
|
||||||
|
|
||||||
const [responseMessage, setResponseMessage] = useState({
|
const [responseMessage, setResponseMessage] = useState({
|
||||||
isSuccessful: false,
|
isSuccessful: false,
|
||||||
message: "",
|
message: "",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log(path);
|
||||||
|
|
||||||
const form = useForm<SignInFormValues>({
|
const form = useForm<SignInFormValues>({
|
||||||
resolver: zodResolver(signInSchema),
|
resolver: zodResolver(signInSchema),
|
||||||
});
|
});
|
||||||
@@ -54,7 +57,7 @@ export const SignInForm = ({ callbackPath }: SignInFormProps) => {
|
|||||||
const result = await signIn("nodemailer", {
|
const result = await signIn("nodemailer", {
|
||||||
email,
|
email,
|
||||||
redirect: false,
|
redirect: false,
|
||||||
callbackUrl: callbackPath ?? `/${locale}/${path}`,
|
callbackUrl: callbackPath ?? path,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (result?.error) {
|
if (result?.error) {
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
import { useSession } from "next-auth/react";
|
||||||
|
|
||||||
import { myZones } from "@/server/myZones";
|
import { myZones } from "@/server/myZones";
|
||||||
|
|
||||||
export const useZones = () => {
|
export const useZones = () => {
|
||||||
|
const { status } = useSession();
|
||||||
|
|
||||||
const query = useQuery({
|
const query = useQuery({
|
||||||
queryKey: ["zones"],
|
queryKey: ["zones"],
|
||||||
queryFn: async () => myZones(),
|
queryFn: async () => myZones(),
|
||||||
@@ -10,6 +13,7 @@ export const useZones = () => {
|
|||||||
staleTime: Infinity,
|
staleTime: Infinity,
|
||||||
gcTime: 10 * 60 * 1000,
|
gcTime: 10 * 60 * 1000,
|
||||||
retry: false,
|
retry: false,
|
||||||
|
enabled: status === "authenticated",
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
import { getRequestConfig } from "next-intl/server";
|
import { getRequestConfig } from "next-intl/server";
|
||||||
import { notFound } from "next/navigation";
|
import { notFound } from "next/navigation";
|
||||||
|
|
||||||
import { routing } from "./utils/navigation";
|
import { routing } from "./utils/routing";
|
||||||
|
|
||||||
export default getRequestConfig(async ({ locale }) => {
|
export default getRequestConfig(async ({ locale }) => {
|
||||||
// Validate that the incoming `locale` parameter is valid
|
// Validate that the incoming `locale` parameter is valid
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
import createMiddleware from "next-intl/middleware";
|
import createMiddleware from "next-intl/middleware";
|
||||||
|
|
||||||
import { routing } from "@/utils/navigation";
|
import { routing } from "@/utils/routing";
|
||||||
|
|
||||||
export default createMiddleware(routing);
|
export default createMiddleware(routing);
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ export function html(params: {
|
|||||||
<tr>
|
<tr>
|
||||||
<td align="center"
|
<td align="center"
|
||||||
style="padding: 10px 0px; font-size: 22px; font-family: Helvetica, Arial, sans-serif; color: ${color.text};">
|
style="padding: 10px 0px; font-size: 22px; font-family: Helvetica, Arial, sans-serif; color: ${color.text};">
|
||||||
${t("email.subject", { host })}
|
${t("email.subject", { host: escapedHost })}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -144,12 +144,10 @@ export default function Nodemailer(
|
|||||||
|
|
||||||
const t = await getTranslations({ locale, namespace: "SignIn" });
|
const t = await getTranslations({ locale, namespace: "SignIn" });
|
||||||
|
|
||||||
console.log("Connection URL", url);
|
|
||||||
|
|
||||||
const { host } = new URL(url);
|
const { host } = new URL(url);
|
||||||
|
|
||||||
console.log(config);
|
|
||||||
if (!(config.server as unknown as any)?.host) {
|
if (!(config.server as unknown as any)?.host) {
|
||||||
|
console.log("Connection URL", url);
|
||||||
console.log(text({ url, host, t }));
|
console.log(text({ url, host, t }));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
import { createLocalizedPathnamesNavigation } from "next-intl/navigation";
|
import { createLocalizedPathnamesNavigation } from "next-intl/navigation";
|
||||||
import { defineRouting } from "next-intl/routing";
|
import { defineRouting } from "next-intl/routing";
|
||||||
|
|
||||||
export const locales = ["fr", "en"] as const;
|
|
||||||
|
|
||||||
export const routing = defineRouting({
|
export const routing = defineRouting({
|
||||||
locales,
|
locales: ["fr", "en"],
|
||||||
defaultLocale: "fr",
|
defaultLocale: "fr",
|
||||||
localePrefix: "as-needed",
|
localePrefix: "as-needed",
|
||||||
|
|
||||||
Reference in New Issue
Block a user