food-market/src/food-market.web/src/App.tsx
nns 033f20e215
Some checks failed
CI / POS (WPF, Windows) (push) Waiting to run
Docker Web / Deploy Web on stage (push) Blocked by required conditions
CI / Backend (.NET 8) (push) Successful in 42s
CI / Web (React + Vite) (push) Successful in 38s
Docker Web / Build + push Web (push) Has been cancelled
feat(web): Employees + Roles pages with permissions matrix
EmployeesPage (/settings/employees):
- Таблица: ФИО + должность, Роль, Email, Телефон, Учётка (есть/нет),
  Статус (Активен/Уволен).
- Модалка добавления: ФИО + Position + Email + Phone + Role.
  Если выбрана роль «Кассир» — появляется блок «Кассы» с чекбоксами
  привязки к RetailPoint'ам (multi-select).
- Чекбокс «Создать учётную запись» (по умолчанию ✓): сервер
  возвращает generatedPassword один раз, показываем в отдельной
  модалке с copy-кнопками логина и временного пароля.
- Update/Delete как обычно. Снять Активен → серверная установка FiredAt.

EmployeeRolesPage (/settings/employee-roles):
- Таблица системных + кастомных ролей с счётчиком активных прав
  (N/21). Системные помечены бэйджем «Системная».
- Модалка edit: имя, описание, матрица прав сгруппированная по 6
  блокам (Каталог/Закупки/Продажи/Контрагенты/Отчёты/Настройки).
  Удаление кнопка только для кастомных.

Меню «Настройки организации» дополнено пунктами «Сотрудники»
(иконка UserCog) и «Роли» (иконка Shield).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 12:06:03 +05:00

75 lines
3.8 KiB
TypeScript

import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { LoginPage } from '@/pages/LoginPage'
import { DashboardPage } from '@/pages/DashboardPage'
import { CountriesPage } from '@/pages/CountriesPage'
import { UnitsOfMeasurePage } from '@/pages/UnitsOfMeasurePage'
import { PriceTypesPage } from '@/pages/PriceTypesPage'
import { StoresPage } from '@/pages/StoresPage'
import { RetailPointsPage } from '@/pages/RetailPointsPage'
import { ProductGroupsPage } from '@/pages/ProductGroupsPage'
import { CounterpartiesPage } from '@/pages/CounterpartiesPage'
import { ProductsPage } from '@/pages/ProductsPage'
import { ProductEditPage } from '@/pages/ProductEditPage'
import { MoySkladImportPage } from '@/pages/MoySkladImportPage'
import { OrganizationSettingsPage } from '@/pages/OrganizationSettingsPage'
import { EmployeesPage } from '@/pages/EmployeesPage'
import { EmployeeRolesPage } from '@/pages/EmployeeRolesPage'
import { StockPage } from '@/pages/StockPage'
import { StockMovementsPage } from '@/pages/StockMovementsPage'
import { SuppliesPage } from '@/pages/SuppliesPage'
import { SupplyEditPage } from '@/pages/SupplyEditPage'
import { RetailSalesPage } from '@/pages/RetailSalesPage'
import { RetailSaleEditPage } from '@/pages/RetailSaleEditPage'
import { AppLayout } from '@/components/AppLayout'
import { ProtectedRoute } from '@/components/ProtectedRoute'
const queryClient = new QueryClient({
defaultOptions: {
queries: {
refetchOnWindowFocus: false,
retry: 1,
},
},
})
export default function App() {
return (
<QueryClientProvider client={queryClient}>
<BrowserRouter>
<Routes>
<Route path="/login" element={<LoginPage />} />
<Route element={<ProtectedRoute />}>
<Route element={<AppLayout />}>
<Route path="/" element={<DashboardPage />} />
<Route path="/catalog/products" element={<ProductsPage />} />
<Route path="/catalog/products/new" element={<ProductEditPage />} />
<Route path="/catalog/products/:id" element={<ProductEditPage />} />
<Route path="/catalog/product-groups" element={<ProductGroupsPage />} />
<Route path="/catalog/units" element={<UnitsOfMeasurePage />} />
<Route path="/catalog/price-types" element={<PriceTypesPage />} />
<Route path="/catalog/counterparties" element={<CounterpartiesPage />} />
<Route path="/catalog/stores" element={<StoresPage />} />
<Route path="/catalog/retail-points" element={<RetailPointsPage />} />
<Route path="/catalog/countries" element={<CountriesPage />} />
<Route path="/inventory/stock" element={<StockPage />} />
<Route path="/inventory/movements" element={<StockMovementsPage />} />
<Route path="/purchases/supplies" element={<SuppliesPage />} />
<Route path="/purchases/supplies/new" element={<SupplyEditPage />} />
<Route path="/purchases/supplies/:id" element={<SupplyEditPage />} />
<Route path="/sales/retail" element={<RetailSalesPage />} />
<Route path="/sales/retail/new" element={<RetailSaleEditPage />} />
<Route path="/sales/retail/:id" element={<RetailSaleEditPage />} />
<Route path="/admin/import/moysklad" element={<MoySkladImportPage />} />
<Route path="/settings/organization" element={<OrganizationSettingsPage />} />
<Route path="/settings/employees" element={<EmployeesPage />} />
<Route path="/settings/employee-roles" element={<EmployeeRolesPage />} />
</Route>
</Route>
<Route path="*" element={<Navigate to="/" replace />} />
</Routes>
</BrowserRouter>
</QueryClientProvider>
)
}