feat: add user notification settings page

This commit is contained in:
Kirill
2026-05-18 11:51:41 +05:00
parent ea0d6bdb91
commit dfec821545
2 changed files with 103 additions and 1 deletions
+4 -1
View File
@@ -16,11 +16,12 @@ import Typography from '@mui/material/Typography'
import useMediaQuery from '@mui/material/useMediaQuery' import useMediaQuery from '@mui/material/useMediaQuery'
import { useQuery } from '@tanstack/react-query' import { useQuery } from '@tanstack/react-query'
import { useUnit } from 'effector-react' import { useUnit } from 'effector-react'
import { MapPin, MessageCircle, Settings, SlidersHorizontal, Truck } from 'lucide-react' import { MapPin, MessageCircle, Settings, SlidersHorizontal, Truck, Bell } from 'lucide-react'
import { Navigate, Route, Routes, useLocation, useNavigate } from 'react-router-dom' import { Navigate, Route, Routes, useLocation, useNavigate } from 'react-router-dom'
import { fetchUnreadMessageCount } from '@/entities/user/api/messages-api' import { fetchUnreadMessageCount } from '@/entities/user/api/messages-api'
import { AddressesPage } from '@/pages/me/ui/sections/AddressesPage' import { AddressesPage } from '@/pages/me/ui/sections/AddressesPage'
import { MessagesPage } from '@/pages/me/ui/sections/MessagesPage' import { MessagesPage } from '@/pages/me/ui/sections/MessagesPage'
import { NotificationsPage } from '@/pages/me/ui/sections/NotificationsPage'
import { OrderDetailPage } from '@/pages/me/ui/sections/OrderDetailPage' import { OrderDetailPage } from '@/pages/me/ui/sections/OrderDetailPage'
import { OrdersPage } from '@/pages/me/ui/sections/OrdersPage' import { OrdersPage } from '@/pages/me/ui/sections/OrdersPage'
import { SettingsPage } from '@/pages/me/ui/sections/SettingsPage' import { SettingsPage } from '@/pages/me/ui/sections/SettingsPage'
@@ -56,6 +57,7 @@ export function MeLayoutPage() {
{ to: '/me/messages', label: 'Сообщения', icon: <MessageCircle /> }, { to: '/me/messages', label: 'Сообщения', icon: <MessageCircle /> },
{ to: '/me/settings', label: 'Настройки', icon: <Settings /> }, { to: '/me/settings', label: 'Настройки', icon: <Settings /> },
{ to: '/me/addresses', label: 'Адреса доставки', icon: <MapPin /> }, { to: '/me/addresses', label: 'Адреса доставки', icon: <MapPin /> },
{ to: '/me/notifications', label: 'Оповещения', icon: <Bell /> },
], ],
[], [],
) )
@@ -189,6 +191,7 @@ export function MeLayoutPage() {
<Route path="messages" element={<MessagesPage />} /> <Route path="messages" element={<MessagesPage />} />
<Route path="settings" element={<SettingsPage />} /> <Route path="settings" element={<SettingsPage />} />
<Route path="addresses" element={<AddressesPage />} /> <Route path="addresses" element={<AddressesPage />} />
<Route path="notifications" element={<NotificationsPage />} />
<Route path="*" element={<Navigate to="/me/settings" replace />} /> <Route path="*" element={<Navigate to="/me/settings" replace />} />
</Routes> </Routes>
</Box> </Box>
@@ -0,0 +1,99 @@
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 Typography from '@mui/material/Typography'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import {
fetchUserNotificationSettings,
updateUserNotificationSettings,
} from '@/entities/notification/api/notifications-api'
const eventFields = [
{ key: 'orderCreated' as const, label: 'Заказ создан' },
{ key: 'orderStatusChanged' as const, label: 'Изменение статуса заказа' },
{ key: 'orderMessageReceived' as const, label: 'Сообщение в чате заказа' },
{ key: 'paymentStatusChanged' as const, label: 'Изменение статуса оплаты' },
]
export function NotificationsPage() {
const queryClient = useQueryClient()
const [error, setError] = useState<string | null>(null)
const { data, isLoading } = useQuery({
queryKey: ['me', 'notifications', 'settings'],
queryFn: fetchUserNotificationSettings,
})
const mutation = useMutation({
mutationFn: updateUserNotificationSettings,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['me', 'notifications', 'settings'] })
},
onError: (err: { response?: { data?: { error?: string } } }) => {
setError(err.response?.data?.error || 'Ошибка сохранения')
},
})
if (isLoading) return <Typography>Загрузка...</Typography>
const settings = data?.settings
if (!settings) return <Alert severity="error">Не удалось загрузить настройки</Alert>
const handleToggle = (field: string, value: boolean) => {
setError(null)
mutation.mutate({ [field]: value } as Record<string, boolean>)
}
return (
<Box>
<Typography variant="h4" gutterBottom>
Оповещения
</Typography>
<Typography color="text.secondary" sx={{ mb: 3 }}>
Настройте, какие уведомления вы хотите получать на почту.
</Typography>
{error && (
<Alert severity="error" sx={{ mb: 2 }}>
{error}
</Alert>
)}
<Stack spacing={3} sx={{ maxWidth: 480 }}>
<Box>
<FormControlLabel
control={
<Switch
checked={settings.globalEnabled}
onChange={(e) => handleToggle('globalEnabled', e.target.checked)}
/>
}
label={<Typography sx={{ fontWeight: 600 }}>Получать оповещения</Typography>}
/>
<Typography variant="body2" color="text.secondary" sx={{ ml: 4 }}>
Включите, чтобы получать уведомления о заказах на почту.
</Typography>
</Box>
<Box sx={{ pl: 4 }}>
{eventFields.map(({ key, label }) => (
<FormControlLabel
key={key}
control={
<Switch
checked={settings[key]}
disabled={!settings.globalEnabled}
onChange={(e) => handleToggle(key, e.target.checked)}
/>
}
label={label}
/>
))}
</Box>
</Stack>
</Box>
)
}