diff --git a/src/app/(auth)/login/page.tsx b/src/app/(auth)/login/page.tsx index f7ecaea..e89ffda 100644 --- a/src/app/(auth)/login/page.tsx +++ b/src/app/(auth)/login/page.tsx @@ -2,8 +2,48 @@ import Form from "#/components/form/form" import { loginSchema } from "#/schema/loginSchema" +import { useMutation } from "@tanstack/react-query" +import { signIn } from "next-auth/react" +import { useRouter } from "next/navigation"; export default function LoginPage() { + const router = useRouter() + + const mutation = useMutation({ + mutationKey: ['login'], + mutationFn: async (data: { email: string; password: string }) => { + try { + const result = await signIn("credentials", { + email: data.email, + password: data.password, + redirect: false, + }) + + if (result?.error) { + const errorMessage = result.error.includes("CredentialsSignin") + ? "Email ou mot de passe incorrect" + : result.error; + console.error(errorMessage) + throw new Error(result.error) + } + return result + } catch (error: any) { + if (error.message.includes("Network Error")) { + console.error("Problème de connexion au serveur"); + } + console.error("Autre = ", error); + } + + + }, + onSuccess: () => { + router.push('/admin/home') + }, + onError: (error: Error) => { + console.error(error.message) + }, + }) + return(
Connexion} /> diff --git a/src/app/admin/home/page.tsx b/src/app/admin/home/page.tsx index 6c2cfee..b2c0f69 100644 --- a/src/app/admin/home/page.tsx +++ b/src/app/admin/home/page.tsx @@ -1,10 +1,18 @@ "use client" +import Statistics from "#/components/stats" import Table from "#/components/table/table" import { ColumnDef } from "@tanstack/react-table" +import { useSession } from "next-auth/react" +import { string } from "zod" export default function HomePage () { + + const session = useSession() + + console.log("Session = ", session) + type Payment = { id: string amount: number @@ -74,25 +82,32 @@ export default function HomePage () { const columns: ColumnDef[] = [ - { - id: "select", - header: ({ table }) => ( - table.toggleAllPageRowsSelected(!!value)} type="checkbox" name="" id="" /> - ), - cell: ({ row }) => ( - row.toggleSelected(!!value)} type="checkbox" name="" id="" /> - ), - }, + // { + // id: "select", + // header: ({ table }) => ( + // table.toggleAllPageRowsSelected(e.target.checked)} type="checkbox" name="" id="" /> + // ), + // cell: ({ row }) => ( + // row.toggleSelected(e.target.checked)} type="checkbox" name="" id="" /> + // ), + // }, { accessorKey: "status", - header: "Status", + header: "Statut du paiement", + // cell: ({row}) => { + // const value = String(row.getValue("status")) + // return( + //
+ // {value} + //
) + // } }, { accessorKey: "email", - header: ({ column }) => { + header: ({ }) => { return (

Email

) @@ -114,16 +129,26 @@ export default function HomePage () { }, - + { + accessorKey: "id", + cell: ({ cell }) => { + const value = String(cell.getValue()) + return ( +

{value}

+ ) + } + } ] return( - <> +
+ + - + ) } \ No newline at end of file diff --git a/src/app/api/auth/[...nextauth]/route.ts b/src/app/api/auth/[...nextauth]/route.ts index 2e22206..e929b04 100644 --- a/src/app/api/auth/[...nextauth]/route.ts +++ b/src/app/api/auth/[...nextauth]/route.ts @@ -13,7 +13,7 @@ const handler = NextAuth({ async authorize(credentials) { try { const response = await axios.post( - 'private-docs-api.intside.co/users/login/', + 'https://private-docs-api.intside.co/users/login/', { email: credentials?.email, password: credentials?.password, diff --git a/src/app/layout.tsx b/src/app/layout.tsx index c370554..8779002 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -3,6 +3,8 @@ import { Inter } from "next/font/google"; import "./globals.css"; import NextTopLoader from "nextjs-toploader"; import "../assets/css/ruben-ui.css" +import { AuthProvider } from "#/components/provider/authProvider"; +import { QueryClientProvide } from "#/components/provider/queryClient"; const inter = Inter({ subsets: ["latin"] }); @@ -16,6 +18,7 @@ export default function RootLayout({ }: Readonly<{ children: React.ReactNode; }>) { + return ( @@ -23,8 +26,12 @@ export default function RootLayout({ - - {children} + + + + {children} + + ); diff --git a/src/assets/icons/index.ts b/src/assets/icons/index.ts index c04d401..8d66946 100644 --- a/src/assets/icons/index.ts +++ b/src/assets/icons/index.ts @@ -23,7 +23,7 @@ import messagesIcon from "./message.svg" import homeIcon from "./NavItem.svg" import companiesIcon from "./buildings.svg" import arrowLeft from "./arrowLeft.svg" -import arrowRight from "./arrowLeft.svg" +import arrowRight from "./arrowRight.svg" import filesIcon from "./ph_files.svg" import pdfIcon from "./prime_file-pdf.svg" import wordIcon from "./prime_file-word.svg" diff --git a/src/components/form/form.tsx b/src/components/form/form.tsx index aa0a489..6a44dfe 100644 --- a/src/components/form/form.tsx +++ b/src/components/form/form.tsx @@ -37,6 +37,7 @@ export default function Form({ setErrors(newErrors) } else { setErrors({}) + submit(result.data) } } diff --git a/src/components/provider/authProvider.tsx b/src/components/provider/authProvider.tsx new file mode 100644 index 0000000..3d2cc8f --- /dev/null +++ b/src/components/provider/authProvider.tsx @@ -0,0 +1,7 @@ +'use client' +import { SessionProvider } from "next-auth/react"; +import { ReactNode } from "react"; + +export function AuthProvider({ children }: Readonly<{ children: ReactNode }>) { + return {children}; +} \ No newline at end of file diff --git a/src/components/provider/queryClient.tsx b/src/components/provider/queryClient.tsx new file mode 100644 index 0000000..0b4162d --- /dev/null +++ b/src/components/provider/queryClient.tsx @@ -0,0 +1,14 @@ +"use client"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; + +import { ReactNode } from "react"; + +export function QueryClientProvide({ + children, +}: Readonly<{ children: ReactNode }>) { + const queryClient = new QueryClient(); + + return ( + {children} + ); +} diff --git a/src/components/stats.tsx b/src/components/stats.tsx new file mode 100644 index 0000000..f238f2e --- /dev/null +++ b/src/components/stats.tsx @@ -0,0 +1,70 @@ +import Image from "next/image" +import { useQuery } from "@tanstack/react-query"; +import axios from "axios"; +import { useSession } from "next-auth/react"; +import { icons } from "#/assets/icons"; +import { Stats, StatsType, } from "#/types"; + +export default function Statistics() { + + const { data: session, status } = useSession(); + + const { data: stats, isLoading} = useQuery({ + enabled: status === 'authenticated', + queryKey: ["stats", session?.user.access_token], + queryFn: async () => { + try { + const response = await axios.get( + 'https://private-docs-api.intside.co/statistics', { + headers: { + 'Authorization': `Bearer ${session?.user.access_token}` + } + } + ) + + if(response.data) { + return response.data as Stats + } + } catch (error: any) { + console.error(error) + } + } + }) + + const statsData: StatsType[] = [ + { id: 1, title: 'Organisations', value: stats?.companies, icon: icons.companiesIcon, color: 'blue' }, + { id: 2, title: 'Utilisateurs', value: stats?.users, icon: icons.userIcon, color: 'blue' }, + { id: 3, title: 'Documents', value: stats?.documents, icon: icons.docummentTextIcon, color: 'blue' }, + { id: 4, title: 'Stockage', value: stats?.documents_size, icon: icons.archivesIcon, color: 'blue' } + ]; + + + + + return( +
+ {statsData.map(({ id, title, value, icon }) => ( +
+
+
+ +
+
+

{title}

+

{ status === "loading" && isLoading ? "Chargement..." : value}

+
+
+
+ ))} +
+ ) +} \ No newline at end of file diff --git a/src/components/table/table.tsx b/src/components/table/table.tsx index cc46a5d..a5145d0 100644 --- a/src/components/table/table.tsx +++ b/src/components/table/table.tsx @@ -11,6 +11,8 @@ import { } from "@tanstack/react-table" import { useState } from "react"; import { clsx, type ClassValue } from "clsx" +import Image from "next/image"; +import { icons } from "#/assets/icons"; interface DataTableProps { columns: ColumnDef[] @@ -43,6 +45,7 @@ export default function Table({ pageSize: pageSize, } }, + enableRowSelection: true, getFilteredRowModel: getFilteredRowModel(), onRowSelectionChange: setRowSelection, onColumnFiltersChange: setColumnFilters, @@ -66,9 +69,18 @@ export default function Table({
{table.getHeaderGroups().map((headerGroup) => ( + {headerGroup.headers.map((header) => { return( - + {row.getVisibleCells().map((cell) => (
+ table.toggleAllPageRowsSelected(e.target.checked)} + type="checkbox" name="" id="" + /> + + {flexRender( header.column.columnDef.header, header.getContext() @@ -83,6 +95,13 @@ export default function Table({ {table.getRowModel().rows.length ? ( table.getRowModel().rows.map((row) => (
+ row.toggleSelected(e.target.checked)} + type="checkbox" name="" id="" + /> + {flexRender(cell.column.columnDef.cell, cell.getContext())} @@ -104,11 +123,11 @@ export default function Table({
@@ -116,10 +135,10 @@ export default function Table({
diff --git a/src/types/index.ts b/src/types/index.ts index cc9effb..8107563 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -15,8 +15,23 @@ export interface FloatingLabelInputProps { export interface FormProps { title?: string, fields: FloatingLabelInputProps[], - submit: FormEventHandler | undefined, + submit: (param: any) => unknown, className: string, child: ReactNode, schema: ZodSchema +} + +export interface StatsType { + id: number; + title: string; + value: number | undefined; + icon: string; + color: string; +} + +export interface Stats { + companies: number + documents: number + users: number + documents_size: number } \ No newline at end of file