diff --git a/src/app/admin/admins/page.tsx b/src/app/admin/admins/page.tsx index fb2e7f8..681778e 100644 --- a/src/app/admin/admins/page.tsx +++ b/src/app/admin/admins/page.tsx @@ -23,7 +23,7 @@ export default function Admins() { const [selectedAdminId, setSelectedAdminId] = useState(null); const queryClient = useQueryClient(); - + const { data: users, refetch, @@ -47,7 +47,6 @@ export default function Admins() { }, }); - const createMutation = useMutation({ mutationFn: async (data: { last_name: string; @@ -193,7 +192,7 @@ export default function Admins() { width={24} height={24} src={icons.editIcon} - className="cursor-pointer responsive-icon" + className="cursor-pointer responsive-icon mr-1" /> } @@ -227,13 +226,19 @@ export default function Admins() { submit={updateMutation.mutate} schema={adminSchema} child={ - +
+ +
} /> } @@ -265,7 +270,9 @@ export default function Admins() { title="Supprimer un admin" content={
-

Voulez-vous vraiment supprimer cet admin ?

+

+ Voulez-vous vraiment supprimer cet admin ? +

+
+ +
} /> } diff --git a/src/app/admin/home/page.tsx b/src/app/admin/home/page.tsx index d87b1eb..b256169 100644 --- a/src/app/admin/home/page.tsx +++ b/src/app/admin/home/page.tsx @@ -1,209 +1,224 @@ -"use client" +"use client"; -import { icons } from "#/assets/icons" -import Statistics from "#/components/stats" -import Table from "#/components/table/table" -import { Company } from "#/types" -import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query" -import { ColumnDef } from "@tanstack/react-table" -import axios from "axios" -import { useSession } from "next-auth/react" -import Image from "next/image" -import { Modal } from "#/components/modal" -import { useState } from "react" +import { icons } from "#/assets/icons"; +import Statistics from "#/components/stats"; +import Table from "#/components/table/table"; +import { Company } from "#/types"; +import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; +import { ColumnDef } from "@tanstack/react-table"; +import axios from "axios"; +import { useSession } from "next-auth/react"; +import Image from "next/image"; +import { Modal } from "#/components/modal"; +import { useState } from "react"; -export default function HomePage () { - - const {data: session, status} = useSession() - const queryClient = useQueryClient() +export default function HomePage() { + const { data: session, status } = useSession(); + const queryClient = useQueryClient(); const [open, setOpen] = useState(false); const [selectedId, setSelectedId] = useState(null); - console.log("Session = ", session) + console.log("Session = ", session); - const { data: companies, refetch, isLoading} = useQuery({ - enabled: status === 'authenticated', + const { + data: companies, + refetch, + isLoading, + } = useQuery({ + enabled: status === "authenticated", queryKey: ["companies"], queryFn: async () => { - try { - const response = await axios.get( - 'https://private-docs-api.intside.co/companies', { - headers: { - 'Authorization': `Bearer ${session?.user.access_token}` - } - } - ) + try { + const response = await axios.get( + "https://private-docs-api.intside.co/companies", + { + headers: { + Authorization: `Bearer ${session?.user.access_token}`, + }, + } + ); - if(response.data) { - return response.data.data as Company[] - } - } catch (error) { - console.error(error) + if (response.data) { + return response.data.data as Company[]; } - } - }) + } catch (error) { + console.error(error); + } + }, + }); const { mutate } = useMutation({ mutationFn: async (id: string) => { try { const response = await axios.delete( - `https://private-docs-api.intside.co/companies/${id}/`, { + `https://private-docs-api.intside.co/companies/${id}/`, + { headers: { - 'Authorization': `Bearer ${session?.user.access_token}` - } - } - ) + Authorization: `Bearer ${session?.user.access_token}`, + }, + } + ); - if(response.status === 200 || response.status === 201) { - console.log('Suppresion réussie !') - setOpen(false) + if (response.status === 200 || response.status === 201) { + console.log("Suppresion réussie !"); + setOpen(false); } } catch (error) { - console.error(error) + console.error(error); } }, onSuccess: () => { - queryClient.invalidateQueries({ queryKey: ["companies"] }) - - refetch() - } - }) - + queryClient.invalidateQueries({ queryKey: ["companies"] }); + refetch(); + }, + }); const columns: ColumnDef[] = [ - { - accessorKey: "name", - header: "Organisations", - }, - { - accessorKey: "total_users", - header: "Utilisateurs", - }, - { - header: "Administrateurs", - cell: ({ row }) => { - const value = String(row.original.owner.first_name) + " " + String(row.original.owner.last_name) - const initials = String(row.original.owner.first_name[0]) + String(row.original.owner.last_name[0]) - return( -
-
- {initials} + { + accessorKey: "name", + header: "Organisations", + }, + { + accessorKey: "total_users", + header: "Utilisateurs", + }, + { + header: "Administrateurs", + cell: ({ row }) => { + const value = + String(row.original.owner.first_name) + + " " + + String(row.original.owner.last_name); + const initials = + String(row.original.owner.first_name[0]) + + String(row.original.owner.last_name[0]); + return ( +
+
+ {initials} +
+

{value}

-

{value}

-
- ) - } - }, - { - accessorKey: "owner.email", - header: "Adresse e-mail" - }, - { - accessorKey: "status", - header: "Statut", - cell: ({ cell }) => { - const status = String(cell.getValue()) - return ( -

{ + const status = String(cell.getValue()); + return ( +

- { - status === "active" ? "Actif" : - status === "inactive" ? "Inactif" : - status === "pending" ? "En attente" : - status === "blocked" ? "Bloquée" : - "" - } -

- ) - } - }, - { - id: "delete", - cell: ({ row }) => { - const id = String(row.original.id); - return ( -
- { - if (!isOpen) { - setSelectedId(null); - } - }} - trigger={ -
{ - setSelectedId(id); - }} - > - -
- } - title={ -

- Supprimer cette organisation -

- } - content={ -
-

- Voulez-vous vraiment supprimer cette organisation ? -

- -
- - -
-
- } - /> -
- ); + > + {status === "active" + ? "Actif" + : status === "inactive" + ? "Inactif" + : status === "pending" + ? "En attente" + : status === "blocked" + ? "Bloquée" + : ""} +

+ ); + }, }, - }, -] + { + id: "delete", + cell: ({ row }) => { + const id = String(row.original.id); + return ( +
+ { + if (!isOpen) { + setSelectedId(null); + } + }} + trigger={ +
{ + setSelectedId(id); + }} + > + +
+ } + title={ +

+ Supprimer cette organisation +

+ } + content={ +
+

+ Voulez-vous vraiment supprimer l'organisation{" "} + {row.original.name} ? +

- return( +
+ + +
+
+ } + /> +
+ ); + }, + }, + ]; + + return (

Dernières organisations actives

- - ) -} \ No newline at end of file + ); +} diff --git a/src/app/admin/organizations/[id]/page.tsx b/src/app/admin/organizations/[id]/page.tsx index 59de245..e41d373 100644 --- a/src/app/admin/organizations/[id]/page.tsx +++ b/src/app/admin/organizations/[id]/page.tsx @@ -118,7 +118,7 @@ export default function Profile() {
-
+
diff --git a/src/app/admin/organizations/[id]/update/page.tsx b/src/app/admin/organizations/[id]/update/page.tsx index a3609cf..4cc300d 100644 --- a/src/app/admin/organizations/[id]/update/page.tsx +++ b/src/app/admin/organizations/[id]/update/page.tsx @@ -290,7 +290,11 @@ export default function Update() { onOpenChange={setOpenBlockModal} trigger={ } content={ diff --git a/src/app/admin/organizations/page.tsx b/src/app/admin/organizations/page.tsx index 1a400c1..de6e78d 100644 --- a/src/app/admin/organizations/page.tsx +++ b/src/app/admin/organizations/page.tsx @@ -51,9 +51,7 @@ export default function Organizations() { }, }); - const { - data: users, - } = useQuery({ + const { data: users } = useQuery({ enabled: status === "authenticated", queryKey: ["organizations"], queryFn: async () => { @@ -167,112 +165,127 @@ export default function Organizations() { { header: "Administrateurs", cell: ({ row }) => { - const value = String(row.original.owner.first_name) + " " + String(row.original.owner.last_name) - const initials = String(row.original.owner.first_name[0]) + String(row.original.owner.last_name[0]) - return( + const value = + String(row.original.owner.first_name) + + " " + + String(row.original.owner.last_name); + const initials = + String(row.original.owner.first_name[0]) + + String(row.original.owner.last_name[0]); + return (
{initials}

{value}

- ) - } + ); + }, }, { accessorKey: "owner.email", - header: "Adresse e-mail" + header: "Adresse e-mail", }, { accessorKey: "status", header: "Statut", cell: ({ cell }) => { - const status = String(cell.getValue()) + const status = String(cell.getValue()); return (

- { - status === "active" ? "Actif" : - status === "inactive" ? "Inactif" : - status === "pending" ? "En attente" : - status === "blocked" ? "Bloquée" : - "" - } + {status === "active" + ? "Actif" + : status === "inactive" + ? "Inactif" + : status === "pending" + ? "En attente" + : status === "blocked" + ? "Bloquée" + : ""}

- ) - } + ); + }, }, { id: "delete", cell: ({ row }) => { const company = row.original; - return ( -
{ mutate(id) }} - > - - {/* Modal de suppression */} - { - if (!isOpen) { - setSelectedAdminId(null); - setOpenDeleteModal(false); - } + return ( +
{ mutate(id) }} + > + {/* Modal de suppression */} + { + if (!isOpen) { + setSelectedAdminId(null); + setOpenDeleteModal(false); + } + }} + trigger={ +
{ + setSelectedAdminId(company.id); + setOpenDeleteModal(true); }} - trigger={ -
+ +
+ } + title="Supprimer une organisation" + content={ +
+

+ Voulez-vous vraiment supprimer l'organisation{" "} + {row.original.name} ? +

+ +
+
- } - title="Supprimer une organisation" - content={ -
-

Voulez-vous vraiment supprimer cette organisation ?

-
- - -
-
- } - /> -
- ) - } - } - ] + Annuler + + +
+
+ } + /> +
+ ); + }, + }, + ]; return (
-

+

Sélectionner une action +

bulkDeleteMutation.mutate(selectedIds)} @@ -334,10 +350,7 @@ export default function Organizations() { } }} trigger={ -
setOpenModal(true)} - className="cursor-pointer p-3 bg-blue-600 text-white rounded-full" - > +
setOpenModal(true)} className="cta"> Ajouter une organisation
} @@ -371,22 +384,31 @@ export default function Organizations() { name: "owner", label: "Administrateur", type: "select", - options: users?.map((user: { id: string; name: string }) => ({ - label: user.name, - value: user.id, - })) || [], + options: + users?.map((user: { id: string; name: string }) => ({ + label: user.name, + value: user.id, + })) || [], }, ]} submit={createMutation.mutate} // Le type est maintenant compatible schema={companySchema} child={ - +
+ +
} /> } diff --git a/src/app/globals.css b/src/app/globals.css index 018286c..7f3dbe2 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -102,6 +102,8 @@ body { .cta{ padding: 10px 24px; + width: max-content; + height: max-content; color: white; background-color: var(--primary); font-size: 14px; @@ -109,6 +111,12 @@ body { border: 1px solid var(--primary); border-radius: 100px; cursor: pointer; + text-wrap: nowrap; +} + +.cta.modal-cta{ + width: 240px; + height: 40px; } .cta.cancel{ @@ -138,6 +146,42 @@ hr{ color: var(--gray); } +input[type="checkbox"] { + appearance: none; + -webkit-appearance: none; + -moz-appearance: none; + + width: 24px; + height: 24px; + border: 1px solid var(--secondary) !important; + border-radius: 6px !important; + background-color: transparent; + cursor: pointer; + position: relative; +} + + +input[type="checkbox"]:checked { + background-color: var(--primary); + border-color: var(--primary); +} + + +input[type="checkbox"]:checked::before { + content: "✔"; + font-size: 18px; + color: white; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} + +.modal-input{ + width: 490px; + margin-left: auto; + margin-right: auto; +} /* Scroll Bar */ diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 13bb7fd..69dc281 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,7 +1,7 @@ import type { Metadata } from "next"; import "./globals.css"; import NextTopLoader from "nextjs-toploader"; -import "../assets/css/ruben-ui.css" +import "../assets/css/ruben-ui.css"; import { AuthProvider } from "#/components/provider/authProvider"; import { QueryClientProvide } from "#/components/provider/queryClient"; import { ToastClient } from "#/components/provider/toastClient"; @@ -16,7 +16,6 @@ export default function RootLayout({ }: Readonly<{ children: React.ReactNode; }>) { - return ( diff --git a/src/assets/icons/chevron-down.svg b/src/assets/icons/chevron-down.svg new file mode 100644 index 0000000..532f579 --- /dev/null +++ b/src/assets/icons/chevron-down.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/index.ts b/src/assets/icons/index.ts index 6d9b354..fed2f25 100644 --- a/src/assets/icons/index.ts +++ b/src/assets/icons/index.ts @@ -42,6 +42,7 @@ import moonIcon from "./moon.svg" import trash from "./trash.svg" import mailIcon from "./sms.svg" import personalCard from "./personalcard.svg" +import arrowDown from "#/assets/icons/chevron-down.svg" export const icons = { @@ -88,7 +89,9 @@ export const icons = { moonIcon, trash, mailIcon, - personalCard + personalCard, + arrowDown + } diff --git a/src/components/admin/adminHeader.tsx b/src/components/admin/adminHeader.tsx index 8ed7042..ecb59a8 100644 --- a/src/components/admin/adminHeader.tsx +++ b/src/components/admin/adminHeader.tsx @@ -1,6 +1,6 @@ -"use client" +"use client"; import Image from "next/image"; -import { icons } from "#/assets/icons" +import { icons } from "#/assets/icons"; import * as React from "react"; import { DropdownMenu } from "radix-ui"; import Link from "next/link"; @@ -10,11 +10,12 @@ import { signOutFunc } from "#/lib/function"; export default function AdminHeader() { const [open, setOpen] = React.useState(false); - return ( <> - ) -} \ No newline at end of file + ); +} diff --git a/src/components/floatingLabelInput.tsx b/src/components/floatingLabelInput.tsx index 9aec32b..555a48a 100644 --- a/src/components/floatingLabelInput.tsx +++ b/src/components/floatingLabelInput.tsx @@ -1,14 +1,14 @@ "use client"; -import { FloatingLabelInputProps } from '#/types'; -import React, { useState } from 'react'; -import Image from 'next/image'; -import { icons } from '#/assets/icons'; +import { FloatingLabelInputProps } from "#/types"; +import React, { useState } from "react"; +import Image from "next/image"; +import { icons } from "#/assets/icons"; -export default function FloatingLabelInput({ - label, - placeholder, - type, +export default function FloatingLabelInput({ + label, + placeholder, + type, options, button, showPasswordToggle = false, @@ -17,12 +17,14 @@ export default function FloatingLabelInput({ onChange, }: FloatingLabelInputProps) { const [showPassword, setShowPassword] = useState(false); - const [selectedValue, setSelectedValue] = useState(defaultValue || ''); + const [selectedValue, setSelectedValue] = useState(defaultValue || ""); - const handleChange = (e: React.ChangeEvent) => { + const handleChange = ( + e: React.ChangeEvent + ) => { const value = e.target.value; - if (type === 'select') { + if (type === "select") { setSelectedValue(value); } @@ -30,28 +32,29 @@ export default function FloatingLabelInput({ onChange(value); } }; - const renderInput = () => { - switch(type) { - case 'select': + switch (type) { + case "select": return (
- {button &&
{button}
}
); - - case 'password': + + case "password": return (
{showPasswordToggle && ( )}
); - - case 'search': - return ( -
-
- -
- - {button &&
{button}
} + case "search": + return ( +
+
+
- ); - + + {button &&
{button}
} +
+ ); + default: return (
-
); -} \ No newline at end of file +} diff --git a/src/components/modal.tsx b/src/components/modal.tsx index 02396f6..0b83d4e 100644 --- a/src/components/modal.tsx +++ b/src/components/modal.tsx @@ -1,12 +1,14 @@ import * as Dialog from "@radix-ui/react-dialog"; import { ReactNode } from "react"; +import { icons } from "#/assets/icons"; +import Image from "next/image"; export function Modal({ trigger, title, content, open, - onOpenChange + onOpenChange, }: { trigger: ReactNode; title?: string | ReactNode; @@ -16,29 +18,29 @@ export function Modal({ }) { return ( - - {trigger} - + {trigger} - e.preventDefault()} > - + {title} - -
- {content} -
-
{onOpenChange?.(false)}} - > - X -
+
{content}
+ +
{ + onOpenChange?.(false); + }} + > + +
); -} \ No newline at end of file +} diff --git a/src/components/table/table.tsx b/src/components/table/table.tsx index e392269..948ca8c 100644 --- a/src/components/table/table.tsx +++ b/src/components/table/table.tsx @@ -177,7 +177,7 @@ export default function Table({