import { h } from 'preact' import { useCallback, useEffect, useState } from 'preact/hooks' import { route } from 'preact-router' import rek, { type FetchError } from 'rek' import { pick } from 'lowline' import { useNotifications } from '../contexts/notifications.tsx' import useItemsReducer from '../hooks/use_items_reducer.ts' import useRequestState from '../../shared/hooks/use_request_state.ts' import Button from './button.tsx' import ErrorDetails from './error_details.tsx' import ErrorsSearchForm from './errors_search_form.tsx' import ErrorsTable from './errors_table.tsx' import Modal from './modal.tsx' import PageHeader from './page_header.tsx' import Pagination from './pagination.tsx' import Section from './section.tsx' import s from './errors_page.module.scss' const defaultSort = '-id' export default function ErrorsPage() { const { notify } = useNotifications() const [{ pending }, request] = useRequestState() const [pagination, setPagination] = useState({}) const [errors, items] = useItemsReducer() const [selected, setSelected] = useState(null) useEffect(() => { fetch() }, [location.search]) const fetch = useCallback(async () => { try { const { items: errors, ...pagination } = await rek(`/api/errors${location.search}`) items.reset(errors) setPagination(pagination) } catch (err) { notify.error((err as FetchError).body?.message || (err as FetchError).message) } }, []) const onSearchSubmit = useCallback( (query: ANY) => { const currentParams = new URLSearchParams(location.search) if (currentParams.has('sort')) query = { ...query, sort: currentParams.get('sort') } route(location.pathname + (Object.keys(query).length ? '?' + new URLSearchParams(query) : '')) }, [location.search], ) const onSortBy = useCallback((column: string) => { const searchParams = new URLSearchParams(location.search) searchParams.delete('offset') searchParams.set('sort', (searchParams.get('sort') || defaultSort) === column ? '-' + column : column) route(location.pathname + '?' + searchParams) }, []) const onDelete = useCallback(async (id: number) => { if (confirm(`Sure you want to remove error #${id}`)) { try { request.pending() await rek.delete(`/api/errors/${id}`) fetch() notify.success(`Successfully deleted error #${id}`) } catch { notify.error(`Failed to delete error #${id}`) } request.reset() } }, []) const deleteErrors = useCallback( async (page: ANY) => { if (confirm(page ? 'Delete errors on page?' : 'Delete all filtered errors?')) { try { request.pending() await rek.delete('/api/errors', { searchParams: page ? { id: errors.map((error) => error.id).join(',') } : location.search, }) fetch() notify.success(page ? 'Errors on page deleted' : 'All filtered errors deleted') } catch (err) { notify.error(`Error deleting errors: ${(err as FetchError).body?.message || (err as FetchError).message}`) } request.reset() } }, [errors], ) return (
Errors
List
{selected != null && ( setSelected(null)}> error.id === selected)} /> )}
) }