feat: add user notification settings page
This commit is contained in:
@@ -16,11 +16,12 @@ import Typography from '@mui/material/Typography'
|
||||
import useMediaQuery from '@mui/material/useMediaQuery'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
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 { fetchUnreadMessageCount } from '@/entities/user/api/messages-api'
|
||||
import { AddressesPage } from '@/pages/me/ui/sections/AddressesPage'
|
||||
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 { OrdersPage } from '@/pages/me/ui/sections/OrdersPage'
|
||||
import { SettingsPage } from '@/pages/me/ui/sections/SettingsPage'
|
||||
@@ -56,6 +57,7 @@ export function MeLayoutPage() {
|
||||
{ to: '/me/messages', label: 'Сообщения', icon: <MessageCircle /> },
|
||||
{ to: '/me/settings', label: 'Настройки', icon: <Settings /> },
|
||||
{ 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="settings" element={<SettingsPage />} />
|
||||
<Route path="addresses" element={<AddressesPage />} />
|
||||
<Route path="notifications" element={<NotificationsPage />} />
|
||||
<Route path="*" element={<Navigate to="/me/settings" replace />} />
|
||||
</Routes>
|
||||
</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>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user