Newer
Older
import { Button, TablePagination, TextField } from '@mui/material'
import {
CsvExportParams,
GridApi,
GridReadyEvent,
import { AgGridReact } from 'ag-grid-react'
import { DateTime } from 'luxon'
import React, { useCallback, useEffect, useMemo, useState } from 'react'
import { useWhoAmI } from '../../API'
import { getAxiosXSRFHeader } from '../../axios.config'
import { IGrdfConsent, grdfColumnDef } from '../../models/grdfConsent'
import { ISgeConsent, sgeColumnDefs } from '../../models/sgeConsent.model'
import { GrdfConsentService } from '../../services/grdfConsent.service'
import { SgeConsentService } from '../../services/sgeConsent.service'
import Loader from '../Loader/Loader'
import DownloadModal from './DownloadModal'
export const Consents: React.FC<{ type: 'sge' | 'grdf' }> = ({ type }) => {
const isGRDF = type === 'grdf'
const [isLoading, setIsLoading] = useState(false)
const [gridApi, setGridApi] = useState<GridApi | null>(null)
const [search, setSearch] = useState<string>('')
const [selectedNodes, setSelectedNodes] = useState<IRowNode[]>([])
const [isShowingSelection, setIsShowingSelection] = useState<boolean>(false)
const [openDownloadModal, setOpenDownloadModal] = useState<boolean>(false)
const [consents, setConsents] = useState<ISgeConsent[] | IGrdfConsent[]>([])
const [page, setPage] = useState<number>(0)
const [rowsPerPage, setRowsPerPage] = useState<number>(50)
const [totalRows, setTotalRows] = useState<number>(50)
const { data: user } = useWhoAmI()
setOpenDownloadModal(prev => !prev)
const consentService = useMemo(
() => (isGRDF ? new GrdfConsentService() : new SgeConsentService()),
[isGRDF]
)
const defaultColDef = useMemo(
() => ({
sortable: true,
resizable: true,
}),
[]
)
const columnDefs = useMemo(
() => (isGRDF ? grdfColumnDef : sgeColumnDefs),
[isGRDF]
)
const handleChangePage = useCallback(
(
_event: React.MouseEvent<HTMLButtonElement, MouseEvent> | null,
newPage: number
) => {
setPage(newPage)
},
[]
)
setRowsPerPage(event.target.value)
setPage(0)
}, [])
const checkSelectedNodes = useCallback(() => {
if (gridApi) {
const newNodes = gridApi.getRenderedNodes()
const idsToCheck: string[] = selectedNodes
.filter(node => node.isSelected)
.map(node => node.data.ID)
if (idsToCheck.includes(node.data.ID)) node.setSelected(true, false)
const searchConsents = async () => {
if (user) {
const consentPagination = await consentService.searchConsents(
search,
rowsPerPage,
page,
getAxiosXSRFHeader(user.xsrftoken)
)
if (consentPagination) {
setConsents(consentPagination.rows)
checkSelectedNodes()
setTotalRows(consentPagination.totalRows)
}
const handleSearchChange = (newSearch: string) => {
setSearch(newSearch)
setPage(0)
}
const resetSelection = useCallback(() => {
if (gridApi) {
setIsShowingSelection(false)
gridApi.setRowData(consents)
gridApi.deselectAll()
setSelectedNodes([])
}
}, [gridApi, consents])
const onRowSelected = useCallback(
(event: RowSelectedEvent) => {
if (event.node.isSelected()) {
const index = selectedNodes.findIndex(
return node.data.ID != event.node.data.ID
})
)
}
},
[selectedNodes]
)
const continueSelection = useCallback(() => {
if (gridApi) {
setIsShowingSelection(false)
gridApi?.setRowData(consents)
const newNodes = gridApi.getRenderedNodes()
// We have to select nodes that have already been selected since we cannot pass a Node array to init AgGrid
const idsToCheck: string[] = selectedNodes
.filter(node => node.isSelected)
.map(node => node.data.ID)
newNodes.forEach(node => {
if (idsToCheck.includes(node.data.ID)) node.setSelected(true)
})
}
}, [gridApi, consents, selectedNodes])
const showCurrentSelection = useCallback(() => {
setIsShowingSelection(true)
const dataFromNode = selectedNodes.map(item => item.data)
selectedNodes && gridApi?.setRowData(dataFromNode)
gridApi?.selectAll()
}, [gridApi, selectedNodes])
const exportData = useCallback(() => {
//You can change default column separator
const params: CsvExportParams = {
columnSeparator: ',',
}
gridApi?.exportDataAsCsv(params)
setOpenDownloadModal(false)
resetSelection()
}, [gridApi, resetSelection])
const onGridReady = ({ api }: GridReadyEvent) => {
//Grid init method
setGridApi(api)
api.sizeColumnsToFit()
}
useEffect(() => {
function handleResize() {
gridApi?.sizeColumnsToFit()
}
handleResize()
window.addEventListener('resize', handleResize)
return () => {
window.removeEventListener('resize', handleResize)
}
/** Trigger search when page loads or when admin changes input or pagination */
// /!\ Do not change dependencies or effect will not trigger when pagination changes
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [rowsPerPage, page, search, isGRDF])
<h1>Consentements {isGRDF ? 'GRDF' : 'Enedis'}</h1>
placeholder={`N°${isGRDF ? 'PCE' : 'PDL'} (14 chiffres)`}
label="Recherche"
value={search}
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
handleSearchChange(e.target.value)
}
disabled={isShowingSelection}
autoComplete="off"
/>
{isLoading && <Loader />}
{!isLoading && (
<AgGridReact
onGridReady={onGridReady}
defaultColDef={defaultColDef}
rowHeight={35}
rowData={consents}
columnDefs={columnDefs}
animateRows={true}
rowSelection="multiple"
allowDragFromColumnsToolPanel={false}
onRowSelected={onRowSelected}
sortingOrder={['asc', 'desc']}
rowMultiSelectWithClick={true}
pagination={false}
suppressCellFocus={true}
rowClassRules={{
expired: params => params.data.endDate < DateTime.now(),
}}
/>
)}
<TablePagination
labelRowsPerPage="Consentements par page"
component="div"
count={totalRows}
page={page}
onPageChange={handleChangePage}
rowsPerPage={rowsPerPage}
onRowsPerPageChange={handleChangeRowsPerPage}
rowsPerPageOptions={[10, 25, 50, 100]}
/>
)}
</div>
open={openDownloadModal}
toggleOpenModal={toggleOpenModal}
exportData={exportData}
/>
<Button
variant="outlined"
onClick={isShowingSelection ? continueSelection : resetSelection}
disabled={
!isShowingSelection && selectedNodes && selectedNodes.length === 0
}
>
{isShowingSelection
? 'Continuer ma sélection'
onClick={!isShowingSelection ? showCurrentSelection : toggleOpenModal}
disabled={selectedNodes && selectedNodes.length <= 0}
classes={{ contained: styles.btnText }}
>
{!isShowingSelection ? 'Voir mes sélections' : 'Télécharger'}
<div>{selectedNodes?.length}</div>
</Button>