Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 14x 14x 14x 14x 14x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 6x 6x 5x 5x 6x 1x 1x 8x 8x 1x 1x 8x 8x 8x 8x 8x 14x 14x 14x 7x 14x 14x 14x 14x 14x 14x 14x 14x 14x 14x 14x 14x 14x 14x 14x 14x 14x 14x 14x 14x 14x 14x 10x 10x 10x 10x 10x 10x 10x 14x 14x 14x 14x 14x 14x 14x 14x 14x 14x 14x 14x 1x | import { IParams } from '@/core/services/http/http.models'; import AutoComplete from '@/shared/components/AutoComplete/AutoComplete'; import Card from '@/shared/components/Card/Card'; import Paginator from '@/shared/components/Paginator/Paginator'; import { setTableParams } from '@/shared/utils/table-utils'; import { useCallback, useEffect, useState } from 'react'; import { apiEpisodes, getEpisodes } from './EpisodesPage.service'; import { catchError, of, tap } from 'rxjs'; import { IEpisode } from '@/shared/types/character'; import { format } from 'date-fns/format'; import { DATE_TIME_FORMAT } from '@/shared/enums/date-time-formats'; import { ILazyState } from '@/shared/types/lazyParams'; import { useToast } from '@/hooks/useToast'; const EpisodesPage: React.FC = () => { const [data, setData] = useState<IEpisode[]>([]); const [params, setParams] = useState<IParams>({ page: 1 }); const toast = useToast(); const getData = useCallback( (event?: ILazyState) => { const baseParams = { ...setTableParams(event as ILazyState) }; if (!baseParams?.page) return; const fullParams = { ...baseParams, }; setParams(fullParams); if (fullParams?.pageSize) delete fullParams.pageSize; const { pages, ...rest } = fullParams || {}; const subscription = getEpisodes(rest) .pipe( tap((res) => { const { results = [], info = {} } = res || {}; if (results.length) { setParams((prevParams) => ({ ...prevParams, pages: info.pages })); setData(results ?? []); } else { toast.showError('Error fetching episodes'); } }), catchError((error) => { console.error('Failed to fetch episodes.', error); return of({}); }) ) .subscribe(); return () => subscription.unsubscribe(); }, [params] ); useEffect(() => { getData(params); }, []); return ( <div className="main-page-container"> <h2 className="page-title">Episodes</h2> <AutoComplete url={apiEpisodes} queryVal={(params?.name as string) ?? ''} paramName="name" onSelect={(name) => getData({ ...params, page: 1, filters: { ['name']: { value: name, matchMode: 'contains' } } })} className="py-3" /> <div className="paginator-top"> <Paginator currentPage={typeof params.page === 'number' ? params.page : 1} totalPages={typeof params.pages === 'number' ? params.pages : 1} onPageChange={(newPage) => getData({ ...params, page: newPage })} maxVisiblePages={3} /> </div> <div className="page-layout-one-col"> <div className="card-grid"> {data?.map((item, i) => ( <Card key={`card-main-${i}`} name={item.name} image={null}> <div className="main-card-content"> <div className="card-footer"> <span>Created: {format(new Date(item.created as string), DATE_TIME_FORMAT.FNS_DATE)}</span> </div> </div> </Card> ))} </div> </div> <div className="paginator-bottom"> <Paginator currentPage={typeof params.page === 'number' ? params.page : 1} totalPages={typeof params.pages === 'number' ? params.pages : 1} onPageChange={(newPage) => getData({ ...params, page: newPage })} /> </div> </div> ); }; export default EpisodesPage; |