mirror of
https://github.com/Sonny93/my-links.git
synced 2025-12-11 16:53:05 +00:00
refacto: extract app urls to constant file
This commit is contained in:
@@ -1,13 +1,15 @@
|
|||||||
|
import PATHS from "constants/paths";
|
||||||
import { useSession } from "next-auth/react";
|
import { useSession } from "next-auth/react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
|
// Component used to access to the session client side
|
||||||
export default function Auth({ children }) {
|
export default function Auth({ children }) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { status } = useSession({
|
const { status } = useSession({
|
||||||
required: true,
|
required: true,
|
||||||
onUnauthenticated: () =>
|
onUnauthenticated: () =>
|
||||||
router.push(
|
router.push(
|
||||||
`/signin?info=${encodeURI(
|
`${PATHS.LOGIN}?info=${encodeURI(
|
||||||
"Vous devez être connecté pour accéder à cette page"
|
"Vous devez être connecté pour accéder à cette page"
|
||||||
)}`
|
)}`
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { motion } from "framer-motion";
|
|||||||
import LinkTag from "next/link";
|
import LinkTag from "next/link";
|
||||||
import { AiFillStar } from "react-icons/ai";
|
import { AiFillStar } from "react-icons/ai";
|
||||||
|
|
||||||
|
import PATHS from "constants/paths";
|
||||||
import { Link } from "types";
|
import { Link } from "types";
|
||||||
|
|
||||||
import EditItem from "components/QuickActions/EditItem";
|
import EditItem from "components/QuickActions/EditItem";
|
||||||
@@ -30,7 +31,7 @@ export default function LinkItem({
|
|||||||
categoryId: link.category.id,
|
categoryId: link.category.id,
|
||||||
};
|
};
|
||||||
axios
|
axios
|
||||||
.put(`/api/link/edit/${link.id}`, payload)
|
.put(`${PATHS.API.LINK.EDIT}/${link.id}`, payload)
|
||||||
.then(() => toggleFavorite(link.id))
|
.then(() => toggleFavorite(link.id))
|
||||||
.catch(console.error);
|
.catch(console.error);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { useRouter } from "next/dist/client/router";
|
||||||
|
|
||||||
import styles from "./message-manager.module.scss";
|
import styles from "./message-manager.module.scss";
|
||||||
|
|
||||||
interface MessageManagerProps {
|
interface MessageManagerProps {
|
||||||
@@ -10,11 +12,20 @@ export default function MessageManager({
|
|||||||
success,
|
success,
|
||||||
info,
|
info,
|
||||||
}: MessageManagerProps) {
|
}: MessageManagerProps) {
|
||||||
|
const infoUrl = useRouter().query?.info as string;
|
||||||
|
const errorUrl = useRouter().query?.error as string;
|
||||||
|
const successUrl = useRouter().query?.success as string;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{info && <div className={styles["info-msg"]}>{info}</div>}
|
{info && <div className={styles["info-msg"]}>{info}</div>}
|
||||||
|
{infoUrl && <div className={styles["info-msg"]}>{infoUrl}</div>}
|
||||||
|
|
||||||
{error && <div className={styles["error-msg"]}>{error}</div>}
|
{error && <div className={styles["error-msg"]}>{error}</div>}
|
||||||
|
{errorUrl && <div className={styles["error-msg"]}>{errorUrl}</div>}
|
||||||
|
|
||||||
{success && <div className={styles["success-msg"]}>{success}</div>}
|
{success && <div className={styles["success-msg"]}>{success}</div>}
|
||||||
|
{successUrl && <div className={styles["success-msg"]}>{successUrl}</div>}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import Favorites from "./Favorites/Favorites";
|
|||||||
import UserCard from "./UserCard/UserCard";
|
import UserCard from "./UserCard/UserCard";
|
||||||
|
|
||||||
import { Category, Link } from "types";
|
import { Category, Link } from "types";
|
||||||
|
import PATHS from "constants/paths";
|
||||||
|
|
||||||
import styles from "./sidemenu.module.scss";
|
import styles from "./sidemenu.module.scss";
|
||||||
|
|
||||||
@@ -68,11 +69,11 @@ function MenuControls({
|
|||||||
<kbd>S</kbd>
|
<kbd>S</kbd>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles["action"]}>
|
<div className={styles["action"]}>
|
||||||
<LinkTag href={"/category/create"}>Créer categorie</LinkTag>
|
<LinkTag href={PATHS.CATEGORY.CREATE}>Créer categorie</LinkTag>
|
||||||
<kbd>C</kbd>
|
<kbd>C</kbd>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles["action"]}>
|
<div className={styles["action"]}>
|
||||||
<LinkTag href={`/link/create?categoryId=${categoryActive.id}`}>
|
<LinkTag href={`${PATHS.LINK.CREATE}?categoryId=${categoryActive.id}`}>
|
||||||
Créer lien
|
Créer lien
|
||||||
</LinkTag>
|
</LinkTag>
|
||||||
<kbd>L</kbd>
|
<kbd>L</kbd>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { signOut, useSession } from "next-auth/react";
|
|||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { FiLogOut } from "react-icons/fi";
|
import { FiLogOut } from "react-icons/fi";
|
||||||
|
|
||||||
|
import PATHS from "constants/paths";
|
||||||
import styles from "./user-card.module.scss";
|
import styles from "./user-card.module.scss";
|
||||||
|
|
||||||
export default function UserCard() {
|
export default function UserCard() {
|
||||||
@@ -18,7 +19,7 @@ export default function UserCard() {
|
|||||||
{data.user.name}
|
{data.user.name}
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
onClick={() => signOut({ callbackUrl: "/signin" })}
|
onClick={() => signOut({ callbackUrl: PATHS.LOGIN })}
|
||||||
className="reset"
|
className="reset"
|
||||||
>
|
>
|
||||||
<FiLogOut size={24} />
|
<FiLogOut size={24} />
|
||||||
|
|||||||
30
src/constants/paths.ts
Normal file
30
src/constants/paths.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
const PATHS = {
|
||||||
|
LOGIN: "/signin",
|
||||||
|
HOME: "/",
|
||||||
|
CATEGORY: {
|
||||||
|
CREATE: "/category/create",
|
||||||
|
EDIT: "/category/edit",
|
||||||
|
REMOVE: "/category/remove",
|
||||||
|
},
|
||||||
|
LINK: {
|
||||||
|
CREATE: "/link/create",
|
||||||
|
EDIT: "/link/edit",
|
||||||
|
REMOVE: "/link/remove",
|
||||||
|
},
|
||||||
|
API: {
|
||||||
|
CATEGORY: {
|
||||||
|
CREATE: "/category/create",
|
||||||
|
EDIT: "/category/edit",
|
||||||
|
REMOVE: "/category/remove",
|
||||||
|
},
|
||||||
|
LINK: {
|
||||||
|
CREATE: "/link/create",
|
||||||
|
EDIT: "/link/edit",
|
||||||
|
REMOVE: "/link/remove",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
NOT_FOUND: "/404",
|
||||||
|
SERVER_ERROR: "/505",
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PATHS;
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { PrismaClient } from "@prisma/client";
|
import { PrismaClient } from "@prisma/client";
|
||||||
|
import PATHS from "constants/paths";
|
||||||
import NextAuth from "next-auth";
|
import NextAuth from "next-auth";
|
||||||
import GoogleProvider from "next-auth/providers/google";
|
import GoogleProvider from "next-auth/providers/google";
|
||||||
|
|
||||||
@@ -30,13 +31,16 @@ export default NextAuth({
|
|||||||
);
|
);
|
||||||
if (accountParam.provider !== "google") {
|
if (accountParam.provider !== "google") {
|
||||||
return (
|
return (
|
||||||
"/signin?error=" + encodeURI("Authentitifcation via Google requise")
|
PATHS.LOGIN +
|
||||||
|
"?error=" +
|
||||||
|
encodeURI("Authentitifcation via Google requise")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const email = profile?.email;
|
const email = profile?.email;
|
||||||
if (email === "") {
|
if (email === "") {
|
||||||
return (
|
return (
|
||||||
"/signin?error=" +
|
PATHS.LOGIN +
|
||||||
|
"?error=" +
|
||||||
encodeURI(
|
encodeURI(
|
||||||
"Impossible de récupérer l'email associé à ce compte Google"
|
"Impossible de récupérer l'email associé à ce compte Google"
|
||||||
)
|
)
|
||||||
@@ -45,7 +49,8 @@ export default NextAuth({
|
|||||||
const googleId = profile?.sub;
|
const googleId = profile?.sub;
|
||||||
if (googleId === "") {
|
if (googleId === "") {
|
||||||
return (
|
return (
|
||||||
"/signin?error=" +
|
PATHS.LOGIN +
|
||||||
|
"?error=" +
|
||||||
encodeURI(
|
encodeURI(
|
||||||
"Impossible de récupérer l'identifiant associé à ce compte Google"
|
"Impossible de récupérer l'identifiant associé à ce compte Google"
|
||||||
)
|
)
|
||||||
@@ -70,7 +75,8 @@ export default NextAuth({
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
"/signin?error=" +
|
PATHS.LOGIN +
|
||||||
|
"?error=" +
|
||||||
encodeURI(
|
encodeURI(
|
||||||
"Vous n'êtes pas autorisé à vous connecter avec ce compte Google"
|
"Vous n'êtes pas autorisé à vous connecter avec ce compte Google"
|
||||||
)
|
)
|
||||||
@@ -81,15 +87,16 @@ export default NextAuth({
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
return (
|
return (
|
||||||
"/signin?error=" +
|
PATHS.LOGIN +
|
||||||
|
"?error=" +
|
||||||
encodeURI("Une erreur est survenue lors de l'authentification")
|
encodeURI("Une erreur est survenue lors de l'authentification")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
pages: {
|
pages: {
|
||||||
signIn: "/signin",
|
signIn: PATHS.LOGIN,
|
||||||
error: "/signin",
|
error: PATHS.LOGIN,
|
||||||
},
|
},
|
||||||
session: {
|
session: {
|
||||||
maxAge: 60 * 60 * 6, // Session de 6 heures
|
maxAge: 60 * 60 * 6, // Session de 6 heures
|
||||||
|
|||||||
@@ -9,18 +9,20 @@ import SearchModal from "components/SearchModal/SearchModal";
|
|||||||
import SideMenu from "components/SideMenu/SideMenu";
|
import SideMenu from "components/SideMenu/SideMenu";
|
||||||
|
|
||||||
import * as Keys from "constants/keys";
|
import * as Keys from "constants/keys";
|
||||||
|
import PATHS from "constants/paths";
|
||||||
import useModal from "hooks/useModal";
|
import useModal from "hooks/useModal";
|
||||||
import { Category, Link, SearchItem } from "types";
|
import { Category, Link, SearchItem } from "types";
|
||||||
import { prisma } from "utils/back";
|
|
||||||
import { BuildCategory } from "utils/front";
|
import { BuildCategory } from "utils/front";
|
||||||
import { pushStateVanilla } from "utils/link";
|
import { pushStateVanilla } from "utils/link";
|
||||||
|
import prisma from "utils/prisma";
|
||||||
|
|
||||||
interface HomeProps {
|
interface HomePageProps {
|
||||||
categories: Category[];
|
categories: Category[];
|
||||||
currentCategory: Category | undefined;
|
currentCategory: Category | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Home(props: HomeProps) {
|
function Home(props: HomePageProps) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const modal = useModal();
|
const modal = useModal();
|
||||||
|
|
||||||
@@ -46,7 +48,10 @@ function Home(props: HomeProps) {
|
|||||||
): SearchItem => ({
|
): SearchItem => ({
|
||||||
id: item.id,
|
id: item.id,
|
||||||
name: item.name,
|
name: item.name,
|
||||||
url: type === "link" ? (item as Link).url : `/?categoryId=${item.id}`,
|
url:
|
||||||
|
type === "link"
|
||||||
|
? (item as Link).url
|
||||||
|
: `${PATHS.HOME}?categoryId=${item.id}`,
|
||||||
type,
|
type,
|
||||||
category: type === "link" ? (item as Link).category : undefined,
|
category: type === "link" ? (item as Link).category : undefined,
|
||||||
});
|
});
|
||||||
@@ -92,7 +97,7 @@ function Home(props: HomeProps) {
|
|||||||
|
|
||||||
const handleSelectCategory = (category: Category) => {
|
const handleSelectCategory = (category: Category) => {
|
||||||
setCategoryActive(category);
|
setCategoryActive(category);
|
||||||
pushStateVanilla(`/?categoryId=${category.id}`);
|
pushStateVanilla(`${PATHS.HOME}?categoryId=${category.id}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
useHotkeys(
|
useHotkeys(
|
||||||
@@ -111,7 +116,7 @@ function Home(props: HomeProps) {
|
|||||||
useHotkeys(
|
useHotkeys(
|
||||||
Keys.OPEN_CREATE_LINK_KEY,
|
Keys.OPEN_CREATE_LINK_KEY,
|
||||||
() => {
|
() => {
|
||||||
router.push(`/link/create?categoryId=${categoryActive.id}`);
|
router.push(`${PATHS.LINK.CREATE}?categoryId=${categoryActive.id}`);
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
enabled: !modal.isShowing,
|
enabled: !modal.isShowing,
|
||||||
@@ -189,7 +194,7 @@ export async function getServerSideProps({ query }) {
|
|||||||
if (categoriesDB.length === 0) {
|
if (categoriesDB.length === 0) {
|
||||||
return {
|
return {
|
||||||
redirect: {
|
redirect: {
|
||||||
destination: "/category/create",
|
destination: PATHS.CATEGORY.CREATE,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,50 +1,35 @@
|
|||||||
import { Provider } from "next-auth/providers";
|
import { Provider } from "next-auth/providers";
|
||||||
import { getProviders, signIn, useSession } from "next-auth/react";
|
import { getProviders, signIn } from "next-auth/react";
|
||||||
import { NextSeo } from "next-seo";
|
import { NextSeo } from "next-seo";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useRouter } from "next/router";
|
|
||||||
|
|
||||||
import MessageManager from "components/MessageManager/MessageManager";
|
import MessageManager from "components/MessageManager/MessageManager";
|
||||||
|
import PATHS from "constants/paths";
|
||||||
|
|
||||||
import styles from "styles/login.module.scss";
|
import styles from "styles/login.module.scss";
|
||||||
|
|
||||||
export default function SignIn({ providers }: { providers: Provider[] }) {
|
interface SignInProps {
|
||||||
const { data: session, status } = useSession();
|
providers: Provider[];
|
||||||
const info = useRouter().query?.info as string;
|
|
||||||
const error = useRouter().query?.error as string;
|
|
||||||
|
|
||||||
if (status === "loading") {
|
|
||||||
return (
|
|
||||||
<div className="App" style={{ alignItems: "center" }}>
|
|
||||||
<p style={{ height: "fit-content" }}>
|
|
||||||
Chargement de la session en cours
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
export default function SignIn({ providers }: SignInProps) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<NextSeo title="Authentification" />
|
<NextSeo title="Authentification" />
|
||||||
<div className="App">
|
<div className="App">
|
||||||
<div className={styles["wrapper"]}>
|
<div className={styles["wrapper"]}>
|
||||||
<h2>Se connecter</h2>
|
<h2>Se connecter</h2>
|
||||||
<MessageManager error={error} info={info} />
|
<MessageManager />
|
||||||
{session !== null && (
|
|
||||||
<MessageManager info="Vous êtes déjà connecté" />
|
|
||||||
)}
|
|
||||||
<div className={styles["providers"]}>
|
<div className={styles["providers"]}>
|
||||||
{Object.values(providers).map(({ name, id }) => (
|
{Object.values(providers).map(({ name, id }) => (
|
||||||
<button
|
<button
|
||||||
|
onClick={() => signIn(id, { callbackUrl: PATHS.HOME })}
|
||||||
key={id}
|
key={id}
|
||||||
onClick={() => signIn(id, { callbackUrl: "/" })}
|
|
||||||
disabled={session !== null}
|
|
||||||
>
|
>
|
||||||
Continuer avec {name}
|
Continuer avec {name}
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<Link href="/">← Revenir à l'accueil</Link>
|
<Link href={PATHS.HOME}>← Revenir à l'accueil</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
import { PrismaClient } from "@prisma/client";
|
|
||||||
|
|
||||||
export const prisma = new PrismaClient();
|
|
||||||
5
src/utils/prisma.ts
Normal file
5
src/utils/prisma.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import { PrismaClient } from "@prisma/client";
|
||||||
|
|
||||||
|
const prisma = new PrismaClient();
|
||||||
|
|
||||||
|
export default prisma;
|
||||||
Reference in New Issue
Block a user