diff --git a/client/src/pages/admin-layout/ui/AdminLayoutPage.tsx b/client/src/pages/admin-layout/ui/AdminLayoutPage.tsx
index 72a6674..8dfb726 100644
--- a/client/src/pages/admin-layout/ui/AdminLayoutPage.tsx
+++ b/client/src/pages/admin-layout/ui/AdminLayoutPage.tsx
@@ -15,7 +15,7 @@ import Typography from '@mui/material/Typography'
import useMediaQuery from '@mui/material/useMediaQuery'
import { useQuery } from '@tanstack/react-query'
import { useUnit } from 'effector-react'
-import { FileText, Image, LayoutGrid, ListOrdered, MessageSquare, Store, Users } from 'lucide-react'
+import { Bell, FileText, Image, LayoutGrid, ListOrdered, MessageSquare, Store, Users } from 'lucide-react'
import { Navigate, Route, Routes, useLocation, useNavigate } from 'react-router-dom'
import { fetchAdminOrdersSummary } from '@/entities/order/api/admin-order-api'
import { AdminCategoriesPage } from '@/pages/admin-categories'
@@ -26,6 +26,7 @@ import { AdminProductsPage } from '@/pages/admin-products'
import { AdminReviewsPage } from '@/pages/admin-reviews'
import { AdminUsersPage } from '@/pages/admin-users'
import { $user } from '@/shared/model/auth'
+import { AdminNotificationsPage } from './AdminNotificationsPage'
type NavItem = {
to: string
@@ -61,6 +62,7 @@ export function AdminLayoutPage() {
{ to: '/admin/reviews', label: 'Отзывы', icon: },
{ to: '/admin/users', label: 'Пользователи', icon: },
{ to: '/admin/info', label: 'Инфо-страница', icon: },
+ { to: '/admin/notifications', label: 'Оповещения', icon: },
],
[],
)
@@ -188,6 +190,7 @@ export function AdminLayoutPage() {
} />
} />
} />
+ } />
} />
diff --git a/client/src/pages/admin-layout/ui/AdminNotificationsPage.tsx b/client/src/pages/admin-layout/ui/AdminNotificationsPage.tsx
new file mode 100644
index 0000000..3508376
--- /dev/null
+++ b/client/src/pages/admin-layout/ui/AdminNotificationsPage.tsx
@@ -0,0 +1,132 @@
+import { useState } from 'react'
+import Alert from '@mui/material/Alert'
+import Box from '@mui/material/Box'
+import FormControlLabel from '@mui/material/FormControlLabel'
+import Stack from '@mui/material/Stack'
+import Switch from '@mui/material/Switch'
+import TextField from '@mui/material/TextField'
+import Typography from '@mui/material/Typography'
+import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
+import {
+ fetchAdminNotificationSettings,
+ updateAdminNotificationSettings,
+} from '@/entities/notification/api/notifications-api'
+
+export function AdminNotificationsPage() {
+ const queryClient = useQueryClient()
+ const [error, setError] = useState(null)
+ const [success, setSuccess] = useState(false)
+
+ const { data, isLoading } = useQuery({
+ queryKey: ['admin', 'notifications', 'settings'],
+ queryFn: fetchAdminNotificationSettings,
+ })
+
+ const mutation = useMutation({
+ mutationFn: updateAdminNotificationSettings,
+ onSuccess: () => {
+ queryClient.invalidateQueries({ queryKey: ['admin', 'notifications', 'settings'] })
+ setSuccess(true)
+ setTimeout(() => setSuccess(false), 3000)
+ },
+ onError: (err: { response?: { data?: { error?: string } } }) => {
+ setError(err.response?.data?.error || 'Ошибка сохранения')
+ },
+ })
+
+ if (isLoading) return Загрузка...
+
+ const s = data?.settings
+ if (!s) return Не удалось загрузить настройки
+
+ const save = (updates: Record) => {
+ setError(null)
+ mutation.mutate(updates)
+ }
+
+ return (
+
+
+ Оповещения
+
+
+ Настройка оповещений администратора.
+
+
+ {error && (
+
+ {error}
+
+ )}
+ {success && (
+
+ Настройки сохранены
+
+ )}
+
+
+
+
+ Email
+
+ save({ emailEnabled: e.target.checked })} />}
+ label="Получать уведомления на почту"
+ />
+
+
+
+
+ Telegram
+
+ save({ telegramEnabled: e.target.checked })} />
+ }
+ label="Получать уведомления в Telegram"
+ />
+ {s.telegramEnabled && (
+
+ save({ telegramChatId: e.target.value })}
+ helperText="Заполняется автоматически при /start бота"
+ fullWidth
+ size="small"
+ />
+
+ )}
+
+
+
+
+ Типы уведомлений
+
+
+ save({ newOrder: e.target.checked })} />}
+ label="Новый заказ"
+ />
+ save({ newOrderMessage: e.target.checked })} />
+ }
+ label="Сообщение в заказе"
+ />
+ save({ newReview: e.target.checked })} />}
+ label="Новый отзыв"
+ />
+ save({ authCodeDuplicate: e.target.checked })} />
+ }
+ label="Дублировать код входа в Telegram"
+ />
+
+
+
+
+ )
+}