feat(roles): системная роль — read-only форма прав вместо alert

Раньше клик по системной роли в списке выкидывал alert «Системная
роль, изменения недоступны». Теперь открывается обычная модалка с
правами, но: имя/описание disabled, все чекбоксы disabled, кнопка
«Сохранить» скрыта (вместо неё «Закрыть»). Юзер видит ровно какие
галки стоят у Администратора/Кладовщика/Кассира — это нужно как
шаблон при создании кастомной роли.

Также description страницы и заголовок модалки обновлены под новый
смысл: системные = только просмотр; кастомные = полный CRUD.
This commit is contained in:
nns 2026-05-06 11:16:56 +05:00
parent b073e99ca7
commit c6ece2adea

View file

@ -137,7 +137,7 @@ export function EmployeeRolesPage() {
<>
<ListPageShell
title="Роли сотрудников"
description="Системные роли можно редактировать (галки прав), но не удалять. Кастомные — полный CRUD."
description="Системные роли — только просмотр прав. Кастомные роли — полный CRUD; можно создать на основе системной как шаблона."
actions={
<>
<SearchBar value={search} onChange={setSearch} />
@ -158,10 +158,8 @@ export function EmployeeRolesPage() {
sortOrder={sortOrder}
onSortChange={setSort}
onRowClick={(r) => {
if (r.isSystem) {
alert('Системная роль, изменения недоступны.')
return
}
// Системные роли — показываем форму с правами в read-only.
// Все чекбоксы disabled, кнопка «Сохранить» скрыта (см. footer).
setForm({
id: r.id, name: r.name, description: r.description ?? '',
isSystem: r.isSystem, permissions: { ...blankPerms(), ...r.permissions },
@ -235,7 +233,9 @@ export function EmployeeRolesPage() {
<Modal
open={!!form}
onClose={() => setForm(null)}
title={form?.id ? `Редактировать роль${form.isSystem ? ' (системная)' : ''}` : 'Новая роль'}
title={form?.id
? (form.isSystem ? `Системная роль «${form.name}» (только просмотр)` : `Редактировать роль «${form.name}»`)
: 'Новая роль'}
width="max-w-2xl"
footer={
<>
@ -249,19 +249,30 @@ export function EmployeeRolesPage() {
<Trash2 className="w-4 h-4" /> Удалить
</Button>
)}
<Button variant="secondary" onClick={() => setForm(null)}>Отмена</Button>
<Button onClick={save} disabled={!form?.name}>Сохранить</Button>
<Button variant="secondary" onClick={() => setForm(null)}>
{form?.isSystem ? 'Закрыть' : 'Отмена'}
</Button>
{!form?.isSystem && (
<Button onClick={save} disabled={!form?.name}>Сохранить</Button>
)}
</>
}
>
{form && (
<div className="space-y-4">
<Field label="Название *">
<TextInput value={form.name} onChange={(e) => setForm({ ...form, name: e.target.value })} />
<TextInput value={form.name} disabled={form.isSystem}
onChange={(e) => setForm({ ...form, name: e.target.value })} />
</Field>
<Field label="Описание">
<TextArea rows={2} value={form.description} onChange={(e) => setForm({ ...form, description: e.target.value })} />
<TextArea rows={2} value={form.description} disabled={form.isSystem}
onChange={(e) => setForm({ ...form, description: e.target.value })} />
</Field>
{form.isSystem && (
<div className="rounded-md bg-slate-100 dark:bg-slate-800/60 border border-slate-200 dark:border-slate-700 px-3 py-2 text-xs text-slate-600 dark:text-slate-300">
Системная роль. Просмотр прав только для справки. Чтобы изменить права создайте кастомную роль на основе этого шаблона.
</div>
)}
{form.id && !form.isSystem && (
<div className="rounded-md bg-amber-50 border border-amber-200 dark:bg-amber-900/20 dark:border-amber-800 px-3 py-2 text-xs text-amber-800 dark:text-amber-200">
Изменение прав применится ко ВСЕМ сотрудникам с этой ролью.