issues/27: admin content CRUD promotions pattern
This commit is contained in:
committed by
Valeriy Petrov
parent
5aab178eb8
commit
dde8ab9ceb
@@ -0,0 +1,115 @@
|
||||
import { useState, useRef } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import { useGetSiteServicesListQuery } from '/src/api/apiSiteServices';
|
||||
import { selectRegions } from '../store/slice/regionSlice';
|
||||
import { useOutsideClick } from '../hooks/useOutsideClick';
|
||||
import { LoadingComponent } from '../components/Placeholders/LoadingComponent';
|
||||
import { ErrorComponent } from '../components/Placeholders/ErrorComponent';
|
||||
|
||||
export const SiteServicesListPage = () => {
|
||||
const [ searchValue, setSearchValue ] = useState( '' );
|
||||
const [ currentPage, setCurrentPage ] = useState( 1 );
|
||||
const [ expandedId, setExpandedId ] = useState( '' );
|
||||
const navigate = useNavigate();
|
||||
const regions = useSelector(selectRegions);
|
||||
const tableRef = useRef( null );
|
||||
useOutsideClick( tableRef, () => setExpandedId( null ));
|
||||
|
||||
const { data: response = {}, isFetching, error: queryError } =
|
||||
useGetSiteServicesListQuery( { search: searchValue, page: currentPage } );
|
||||
const pagination = response.pagination || {};
|
||||
const items = response.data ? response.data : [];
|
||||
|
||||
const renderPagination = () => {
|
||||
const total = pagination.total_pages || 1;
|
||||
const current = pagination.current_page || 1;
|
||||
const pages = new Set( [ 1, total ] );
|
||||
for ( let page = current - 2; page <= current + 2; page += 1 ) {
|
||||
if ( page > 1 && page < total ) pages.add( page );
|
||||
}
|
||||
const sorted = Array.from( pages ).sort( ( a, b ) => a - b );
|
||||
const elements = [];
|
||||
let last = 0;
|
||||
sorted.forEach( page => {
|
||||
if ( last && page - last > 1 ) {
|
||||
elements.push(
|
||||
<li key={ `dots-${last}` } className="page-item disabled">
|
||||
<span className="page-link">…</span>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
elements.push(
|
||||
<li key={ page } className={`page-item ${ page === current ? 'active' : '' }`}>
|
||||
<button type="button" className="page-link" onClick={ () => page !== current && setCurrentPage( page ) }>
|
||||
{ page }
|
||||
</button>
|
||||
</li>
|
||||
);
|
||||
last = page;
|
||||
});
|
||||
return (
|
||||
<nav>
|
||||
<ul className="pagination justify-content-center">
|
||||
<li className={`page-item ${ !pagination.has_previous_page ? 'disabled' : '' }`}>
|
||||
<button type="button" className="page-link" onClick={ () => pagination.has_previous_page && setCurrentPage(current - 1) }>«</button>
|
||||
</li>
|
||||
{ elements }
|
||||
<li className={`page-item ${ !pagination.has_next_page ? 'disabled' : '' }`}>
|
||||
<button type="button" className="page-link" onClick={ () => pagination.has_next_page && setCurrentPage(current + 1) }>»</button>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="container-fluid">
|
||||
<h1 className="h3 mb-4 text-gray-800">Услуги сайта</h1>
|
||||
<div className="d-flex justify-content-between mb-3" style={{ marginRight: '0.1rem', marginLeft: '0.1rem' }}>
|
||||
<div className="form-group align-self-end mr-3">
|
||||
<input type="button" className="btn btn-outline-primary" value="Добавить" onClick={ e => { e.stopPropagation(); navigate(`/site-services/create`); } } />
|
||||
</div>
|
||||
<div className="form-group flex-grow-1">
|
||||
<label>Поиск</label>
|
||||
<input type="text" className="form-control" value={ searchValue } onChange={ e => { setSearchValue( e.target.value ); setCurrentPage( 1 ); } } />
|
||||
</div>
|
||||
</div>
|
||||
{ isFetching ? <LoadingComponent /> : queryError ? <ErrorComponent /> : (
|
||||
<>
|
||||
<div className="table-responsive" ref={tableRef}>
|
||||
<table className="table table-hover table-bordered">
|
||||
<thead><tr>
|
||||
<th>ID</th>
|
||||
<th>Название</th>
|
||||
<th>Alias</th>
|
||||
<th>Активно</th>
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
{items.map( item => (
|
||||
<>
|
||||
<tr key={ item.id } className={ `cursor-pointer${ expandedId === item.id ? ' table-success' : '' }` } onClick={ () => setExpandedId( expandedId === item.id ? null : item.id ) }>
|
||||
<td>{ item.id }</td>
|
||||
<td>{ item.name }</td>
|
||||
<td>{ item.alias }</td>
|
||||
<td>{ item.active ? 'Да' : 'Нет' }</td>
|
||||
</tr>
|
||||
{ expandedId === item.id && (
|
||||
<tr className='table-success'>
|
||||
<td colSpan={ 4 }>
|
||||
<input type="button" className="btn btn-outline-primary" value="Редактировать" onClick={ e => { e.stopPropagation(); navigate(`/site-services/edit/${item.id}`) } } />
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
</>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{ renderPagination() }
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user