Skip to content

Commit

Permalink
wip: started to add react-query - Ref gestion-de-projet#2507
Browse files Browse the repository at this point in the history
  • Loading branch information
ManelleG committed Jan 8, 2025
1 parent f260f4e commit 2a0bf74
Show file tree
Hide file tree
Showing 17 changed files with 276 additions and 78 deletions.
27 changes: 27 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"@mui/material": "^5.11.14",
"@mui/x-date-pickers": "^5.0.20",
"@reduxjs/toolkit": "^1.9.3",
"@tanstack/react-query": "^5.62.16",
"@types/redux-state-sync": "^3.1.5",
"ace-builds": "^1.16.0",
"antlr4": "^4.13.1-patch-1",
Expand Down Expand Up @@ -60,7 +61,7 @@
"build": "vite build",
"serve": "vite preview",
"lint": "eslint --ext .jsx,.js,.ts,.tsx src/",
"test": "vitest",
"test": "vitest",
"coverage": "vitest run --coverage",
"ui": "vitest --ui"
},
Expand Down
17 changes: 11 additions & 6 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,25 @@ import AppNavigation from './components/Routes/AppNavigation/AppNavigation'
import WarningDialog from 'components/ui/WarningDialog'

import { store, persistor } from './state/store'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'

import 'moment/dist/locale/fr'

moment.locale('fr')

const queryClient = new QueryClient()

const App = () => (
<LocalizationProvider dateAdapter={MomentUtils}>
<Provider store={store}>
<WarningDialog />
<PersistGate loading={null} persistor={persistor}>
<CssBaseline />

<AppNavigation />
</PersistGate>
<QueryClientProvider client={queryClient}>
<WarningDialog />
<PersistGate loading={null} persistor={persistor}>
<CssBaseline />

<AppNavigation />
</PersistGate>
</QueryClientProvider>
</Provider>
</LocalizationProvider>
)
Expand Down
7 changes: 6 additions & 1 deletion src/components/Exploration/components/CohortsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ const CohortsList = () => {
{ label: 'échantillons' }
]

const handlePageChange = (newPage: number) => {
searchParams.set('page', String(newPage))
setSearchParams(searchParams)
}

const onClickRow = (cohort: Cohort) => {
const searchParams = new URLSearchParams()
if (cohort.group_id) {
Expand Down Expand Up @@ -90,7 +95,7 @@ const CohortsList = () => {

{/* TODO: add circular progress */}

<ResearchesTable columns={columns}>
<ResearchesTable columns={columns} page={page} setPage={handlePageChange} total={total}>
{cohortsList.map((cohort) => {
const isExportable = appConfig.features.export.enabled ? cohort?.rights?.export_csv_nomi : false
const actions = [
Expand Down
58 changes: 45 additions & 13 deletions src/components/Exploration/components/ProjectsList.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,64 @@
import React from 'react'

import { Grid } from '@mui/material'
import { CircularProgress, Grid, Typography } from '@mui/material'
import ProjectCard from 'components/ui/ProjectCard'
import { useNavigate, useSearchParams } from 'react-router-dom'
import useProjects from '../hooks/useProjects'
import { ProjectType } from 'types'
import Button from 'components/ui/Button'
import useCreateProject from '../hooks/useCreateProject'
import useEditProject from '../hooks/useEditProject'
import useDeleteProject from '../hooks/useDeleteProject'

const ProjectsList = () => {
const navigate = useNavigate()
const [searchParams, setSearchParams] = useSearchParams()
const [searchParams] = useSearchParams()
const searchInput = searchParams.get('searchInput') ?? ''
const startDate = searchParams.get('startDate') ?? undefined
const endDate = searchParams.get('endDate') ?? undefined

const createProjectMutation = useCreateProject()
const editProjectMutation = useEditProject()
const deleteProjectMutation = useDeleteProject()

const { projectsList, total, loading } = useProjects(searchInput, startDate, endDate)

const handleAddProject = async () => {
const newProjectData: Omit<ProjectType, 'uuid'> = {
name: 'projet ajouté avec react-query :)',
description: "J'apprends, j'apprends!!"
}
createProjectMutation.mutate(newProjectData)
}

const handleEditProject = async (project: ProjectType) => {
const newProjectData = { uuid: project.uuid, name: project.name, description: 'Description ajoutée!' }
editProjectMutation.mutate(newProjectData)
}

const handleDeleteProject = async (project: ProjectType) => {
deleteProjectMutation.mutate(project)
}
return (
<Grid container xs={11} gap="50px">
{/* TODO: add circular progress */}

{projectsList.map((project) => (
<ProjectCard
key={project.created_at} // TODO: mettre autre chose comme key
title={project.name}
creationDate={project.created_at}
requestNumber={project.requests.length}
onclick={() => navigate(`/researches/projects/${project.uuid}${location.search}`)}
/>
))}
<Button onClick={handleAddProject}>Ajouter un projet</Button>
<Typography>{total} projets</Typography>

{loading ? (
<CircularProgress />
) : (
projectsList.map((project: ProjectType) => (
<ProjectCard
key={project.uuid}
title={project.name}
creationDate={project.created_at}
requestNumber={project.requests?.length ?? 0}
onclick={() => navigate(`/researches/projects/${project.uuid}${location.search}`)}
onedit={() => handleEditProject(project)}
ondelete={() => handleDeleteProject(project)}
/>
))
)}
</Grid>
)
}
Expand Down
43 changes: 25 additions & 18 deletions src/components/Exploration/components/RequestsList.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState } from 'react'
import React from 'react'

import { Box, CircularProgress, Grid, IconButton, TableRow, Tooltip, Typography } from '@mui/material'
import { useNavigate, useParams, useSearchParams } from 'react-router-dom'
Expand All @@ -16,6 +16,7 @@ import DeleteOutlineIcon from '@mui/icons-material/DeleteOutline'
import ShareIcon from '@mui/icons-material/Share'
import { useAppDispatch, useAppSelector } from 'state'
import { setSelectedRequestShare } from 'state/request'
import useProject from '../hooks/useProject'

// TODO: J'AVAIS OUBLIÉ MAIS PRÉVOIR LE SUPER FLOW DE DÉLÉTION MULTIPLE

Expand All @@ -30,13 +31,17 @@ const RequestsList = () => {
const page = parseInt(searchParams.get('page') ?? '1', 10)
const maintenanceIsActive = useAppSelector((state) => state?.me?.maintenance?.active ?? false)

console.log('test useProject(projectId)', useProject(projectId))
const { project: parentProject, projectLoading, projectIsError } = useProject(projectId)
const { requestsList, total, loading } = useRequests(projectId, searchInput, startDate, endDate, page)

const handlePageChange = (newPage: number) => {
searchParams.set('page', String(newPage))
setSearchParams(searchParams)
}

console.log('test parentProject', parentProject)

const columns: Column[] = [
{ label: 'nom de la requête', align: 'left' },
{ label: 'projet' }, // TODO: conditionner à si onglet requêtes + réfléchir si cliquable ou pas?
Expand Down Expand Up @@ -79,24 +84,27 @@ const RequestsList = () => {
return `${request.name}${sharedByDetails}`
}

// TODO: ajouter action pour déplacer la requête de projet

return (
<Grid container gap="20px">
{/* TODO: n'afficher que si onglet projets */}
{/* TODO: fetch le nom du projet */}
<Box display={'flex'} justifyContent={'center'} width={'100%'} alignItems={'center'}>
<Typography fontWeight={'bold'} fontSize={'24px'} fontFamily={"'Montserrat', sans-serif"}>
RequestsList
</Typography>
{/* TODO: ajouter les actions sur projet parent */}
<IconButton>
<Edit />
</IconButton>
<IconButton>
<Delete />
</IconButton>
</Box>

{/* TODO: add circular progress */}
{/* TODO: demander à Hicham d'ajouter une descr */}
{projectId && (
<Box display={'flex'} justifyContent={'center'} width={'100%'} alignItems={'center'}>
<Typography fontWeight={'bold'} fontSize={'24px'} fontFamily={"'Montserrat', sans-serif"}>
{parentProject?.name}
</Typography>
<Typography>{parentProject?.description}</Typography>
{/* TODO: ajouter les actions sur projet parent */}
<IconButton>
<Edit />
</IconButton>
<IconButton>
<Delete />
</IconButton>
</Box>
)}

{loading ? (
<CircularProgress />
) : (
Expand All @@ -114,7 +122,6 @@ const RequestsList = () => {
{getRequestName(request)}
<Tooltip title="Partager la requête">
<IconButton
// className={classes.editButton}
size="small"
onClick={() => onShareRequest(request.uuid)}
disabled={maintenanceIsActive}
Expand Down
16 changes: 16 additions & 0 deletions src/components/Exploration/hooks/useCreateProject.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { useMutation, useQueryClient } from '@tanstack/react-query'
import services from 'services/aphp'
import { ProjectType } from 'types'

const useCreateProject = () => {
const queryClient = useQueryClient()

return useMutation({
mutationFn: async (newProjectData: Omit<ProjectType, 'uuid'>) => await services.projects.addProject(newProjectData),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['projects'] })
}
})
}

export default useCreateProject
16 changes: 16 additions & 0 deletions src/components/Exploration/hooks/useDeleteProject.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { useMutation, useQueryClient } from '@tanstack/react-query'
import services from 'services/aphp'
import { ProjectType } from 'types'

const useDeleteProject = () => {
const queryClient = useQueryClient()

return useMutation({
mutationFn: async (project: ProjectType) => await services.projects.deleteProject(project),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['projects'] })
}
})
}

export default useDeleteProject
16 changes: 16 additions & 0 deletions src/components/Exploration/hooks/useEditProject.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { useMutation, useQueryClient } from '@tanstack/react-query'
import services from 'services/aphp'
import { ProjectType } from 'types'

const useEditProject = () => {
const queryClient = useQueryClient()

return useMutation({
mutationFn: async (newProjectData: ProjectType) => await services.projects.editProject(newProjectData),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['projects'] })
}
})
}

export default useEditProject
24 changes: 24 additions & 0 deletions src/components/Exploration/hooks/useProject.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import services from 'services/aphp'
import { useQuery } from '@tanstack/react-query'

const useProject = (projectId?: string) => {
const { data, isLoading, isError, error, refetch } = useQuery({
queryKey: ['project', projectId],
enabled: !!projectId, // ça veut dire qu'on fait pas l'appel si pas de projectId
queryFn: async () => {
if (!projectId) return null
const projectData = await services.projects.fetchProject(projectId)
return projectData
}
})

return {
project: data,
projectLoading: isLoading,
projectIsError: isError,
error,
refetch
}
}

export default useProject
36 changes: 19 additions & 17 deletions src/components/Exploration/hooks/useProjects.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
import React, { useEffect, useState } from 'react'
import services from 'services/aphp'
import { useQuery } from '@tanstack/react-query'

const useProjects = (searchTerm: string, startDate?: string, endDate?: string) => {
const [projectsList, setProjectsList] = useState<any[]>([])
const [total, setTotal] = useState(0)
const [loading, setLoading] = useState(false)

// TODO: à externaliser
const useProjects = (searchInput: string, startDate?: string, endDate?: string) => {
const fetchProjectsList = async () => {
// TODO: modifier le service de sorte à ajouter les filtres + try/catch
const projectsList = await services.projects.fetchProjectsList()
console.log('test projectsList', projectsList)
setProjectsList(projectsList.results)
setTotal(projectsList.count)
const projectsList = await services.projects.fetchProjectsList(searchInput, startDate, endDate)
return projectsList
}

useEffect(() => {
// setLoading(true)
console.log('test fetchPRoejctsList()', fetchProjectsList())
}, [searchTerm, startDate, endDate])
const { data, isLoading, isError, error, refetch } = useQuery({
queryKey: ['projects', searchInput, startDate, endDate],
queryFn: fetchProjectsList
})

const projectsList = data?.results ?? []
const total = data?.count ?? 0

return { projectsList, total, loading }
return {
projectsList,
total,
loading: isLoading,
isError,
error,
refetch
}
}

export default useProjects
Loading

0 comments on commit 2a0bf74

Please sign in to comment.