brf/client/admin/components/invites_page.tsx
2025-12-18 07:31:37 +01:00

75 lines
2.1 KiB
TypeScript

import { h } from 'preact'
import { useCallback, useEffect, useState } from 'preact/hooks'
import { route } from 'preact-router'
import rek, { type FetchError } from 'rek'
import { useNotifications } from '../contexts/notifications.tsx'
import useItemsReducer from '../hooks/use_items_reducer.ts'
import InviteForm from './invite_form.tsx'
import InvitesTable from './invites_table.tsx'
import PageHeader from './page_header.tsx'
import Section from './section.tsx'
import s from './invites_page.module.scss'
const InvitesPage = () => {
const { notify } = useNotifications()
const [invites, actions] = useItemsReducer()
const [roles, setRoles] = useState()
useEffect(() => {
Promise.all([rek('/api/invites' + location.search), rek('/api/roles')]).then(([invites, roles]) => {
setRoles(roles)
actions.reset(invites)
})
}, [location.search])
const onDelete = useCallback(async (id: number) => {
if (confirm(`Delete invite ${id}?`)) {
try {
await rek.delete(`/api/invites/${id}`)
actions.del(id)
notify.success(`Invite ${id} deleted`)
} catch (err) {
notify.error((err as FetchError).body?.message || (err as FetchError).toString())
}
}
}, [])
const onSortBy = useCallback((column: string) => {
const searchParams = new URLSearchParams(location.search)
const newSort = (searchParams.get('sort') || 'id') === column ? '-' + column : column
route(location.pathname + (newSort !== 'id' ? `?sort=${newSort}` : ''))
}, [])
return (
<section>
<PageHeader>Invites</PageHeader>
<div className={s.row}>
<Section className={s.left}>
<Section.Heading>Create New Invite</Section.Heading>
<Section.Body>
<InviteForm onCreate={actions.add} roles={roles} />
</Section.Body>
</Section>
</div>
<Section>
<Section.Heading>List</Section.Heading>
<Section.Body noPadding>
<InvitesTable invites={invites} onDelete={onDelete} onSortBy={onSortBy} />
</Section.Body>
</Section>
</section>
)
}
export default InvitesPage