Squashed new RBAC
All checks were successful
Deploy on push / deploy (push) Successful in 7s

This commit is contained in:
2025-07-02 22:30:21 +03:00
parent 7585dae0ab
commit 82111ed0f6
100 changed files with 14785 additions and 5888 deletions

View File

@@ -5,6 +5,7 @@ import styles from '../styles/Table.module.css'
import Button from '../ui/Button'
import Modal from '../ui/Modal'
import Pagination from '../ui/Pagination'
import TableControls from '../ui/TableControls'
import { getAuthTokenFromCookie } from '../utils/auth'
/**
@@ -59,7 +60,7 @@ const InvitesRoute: Component<InvitesRouteProps> = (props) => {
const [statusFilter, setStatusFilter] = createSignal('all')
const [pagination, setPagination] = createSignal({
page: 1,
perPage: 10,
perPage: 20,
total: 0,
totalPages: 1
})
@@ -69,18 +70,26 @@ const InvitesRoute: Component<InvitesRouteProps> = (props) => {
const [selectAll, setSelectAll] = createSignal(false)
// Состояние для модального окна подтверждения удаления
const [deleteModal, setDeleteModal] = createSignal<{ show: boolean; invite: Invite | null }>({
const [deleteModal, setDeleteModal] = createSignal<{
show: boolean
invite: Invite | null
}>({
show: false,
invite: null
})
// Состояние для модального окна подтверждения пакетного удаления
const [batchDeleteModal, setBatchDeleteModal] = createSignal<{ show: boolean }>({
const [batchDeleteModal, setBatchDeleteModal] = createSignal<{
show: boolean
}>({
show: false
})
// Добавляю состояние сортировки
const [sortState, setSortState] = createSignal<SortState>({ field: null, direction: 'asc' })
const [sortState, setSortState] = createSignal<SortState>({
field: null,
direction: 'asc'
})
/**
* Загружает список приглашений с учетом фильтров и пагинации
@@ -122,7 +131,7 @@ const InvitesRoute: Component<InvitesRouteProps> = (props) => {
setInvites(data.invites || [])
setPagination({
page: data.page || 1,
perPage: data.perPage || 10,
perPage: data.perPage || 20,
total: data.total || 0,
totalPages: data.totalPages || 1
})
@@ -353,68 +362,49 @@ const InvitesRoute: Component<InvitesRouteProps> = (props) => {
return (
<div class={styles.container}>
{/* Новая компактная панель поиска и фильтров */}
<div class={styles.searchSection}>
<div class={styles.searchRow}>
<input
type="text"
placeholder="Поиск по приглашающему, приглашаемому, публикации..."
value={search()}
onInput={(e) => setSearch(e.target.value)}
onKeyPress={(e) => e.key === 'Enter' && handleSearch()}
class={styles.fullWidthSearch}
/>
</div>
<div class={styles.filtersRow}>
<select
value={statusFilter()}
onChange={(e) => handleStatusFilterChange(e.target.value)}
class={styles.statusFilter}
>
<option value="all">Все статусы</option>
<option value="pending">Ожидает ответа</option>
<option value="accepted">Принято</option>
<option value="rejected">Отклонено</option>
</select>
<Button onClick={handleSearch} disabled={loading()}>
🔍 Поиск
</Button>
<Button onClick={() => loadInvites(pagination().page)} disabled={loading()}>
{loading() ? 'Загрузка...' : '🔄 Обновить'}
</Button>
</div>
</div>
{/* Панель пакетных действий */}
<Show when={!loading() && invites().length > 0}>
<div class={styles['batch-actions']}>
<div class={styles['select-all-container']}>
<input
type="checkbox"
id="select-all"
checked={selectAll()}
onChange={(e) => handleSelectAll(e.target.checked)}
class={styles.checkbox}
/>
<label for="select-all" class={styles['select-all-label']}>
Выбрать все
</label>
</div>
<TableControls
searchValue={search()}
onSearchChange={(value) => setSearch(value)}
onSearch={handleSearch}
searchPlaceholder="Поиск по приглашающему, приглашаемому, публикации..."
isLoading={loading()}
actions={
<Show when={getSelectedCount() > 0}>
<div class={styles['selected-count']}>Выбрано: {getSelectedCount()}</div>
<button
class={styles['batch-delete-button']}
class={`${styles.button} ${styles.danger}`}
onClick={() => setBatchDeleteModal({ show: true })}
title="Удалить выбранные приглашения"
>
Удалить выбранные
Удалить выбранные ({getSelectedCount()})
</button>
</Show>
}
>
<select
value={statusFilter()}
onChange={(e) => handleStatusFilterChange(e.target.value)}
class={styles.statusFilter}
>
<option value="all">Все статусы</option>
<option value="pending">Ожидает ответа</option>
<option value="accepted">Принято</option>
<option value="rejected">Отклонено</option>
</select>
</TableControls>
{/* Панель выбора всех */}
<Show when={!loading() && invites().length > 0}>
<div class={styles['select-all-container']} style={{ 'margin-bottom': '10px' }}>
<input
type="checkbox"
id="select-all"
checked={selectAll()}
onChange={(e) => handleSelectAll(e.target.checked)}
class={styles.checkbox}
/>
<label for="select-all" class={styles['select-all-label']}>
Выбрать все
</label>
</div>
</Show>