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
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>
75 lines
3.8 KiB
TypeScript
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>
|
|
)
|
|
}
|