все к лучшему

This commit is contained in:
2025-07-22 08:34:05 +03:00
parent 3a1bb42aee
commit abc2ee44bd
9 changed files with 440 additions and 90 deletions

154
src/lib/hooks/useToast.tsx Normal file
View File

@@ -0,0 +1,154 @@
import { Toast, ToastContainer, ToastType } from '@/component/ui/toast'
import {
createContext,
FC,
PropsWithChildren,
useCallback,
useContext,
useState,
} from 'react'
interface ToastContextType {
showToast: (
message: string,
type?: ToastType,
options?: { title?: string; duration?: number }
) => void
removeToast: (id: string) => void
// Методы для быстрого доступа к разным типам уведомлений
success: (
message: string,
options?: { title?: string; duration?: number }
) => void
error: (
message: string,
options?: { title?: string; duration?: number }
) => void
warning: (
message: string,
options?: { title?: string; duration?: number }
) => void
info: (
message: string,
options?: { title?: string; duration?: number }
) => void
}
const ToastContext = createContext<ToastContextType | null>(null)
export const ToastProvider: FC<PropsWithChildren> = ({ children }) => {
const [toasts, setToasts] = useState<Toast[]>([])
const showToast = useCallback(
(
message: string,
type: ToastType = 'info',
options: { title?: string; duration?: number } = {}
) => {
const id = Math.random().toString(36).substr(2, 9)
const newToast: Toast = {
id,
message,
type,
title: options.title,
duration: options.duration,
}
setToasts(prev => [...prev, newToast])
},
[]
)
const removeToast = useCallback((id: string) => {
setToasts(prev => prev.filter(toast => toast.id !== id))
}, [])
// Методы для быстрого доступа
const success = useCallback(
(message: string, options?: { title?: string; duration?: number }) => {
showToast(message, 'success', options)
},
[showToast]
)
const error = useCallback(
(message: string, options?: { title?: string; duration?: number }) => {
showToast(message, 'error', options)
},
[showToast]
)
const warning = useCallback(
(message: string, options?: { title?: string; duration?: number }) => {
showToast(message, 'warning', options)
},
[showToast]
)
const info = useCallback(
(message: string, options?: { title?: string; duration?: number }) => {
showToast(message, 'info', options)
},
[showToast]
)
const value: ToastContextType = {
showToast,
removeToast,
success,
error,
warning,
info,
}
return (
<ToastContext.Provider value={value}>
{children}
<ToastContainer toasts={toasts} onRemove={removeToast} />
</ToastContext.Provider>
)
}
export const useToast = (): ToastContextType => {
const context = useContext(ToastContext)
if (!context) {
throw new Error('useToast must be used within a ToastProvider')
}
return context
}
// Глобальное переопределение alert
let globalToastContext: ToastContextType | null = null
export const setGlobalToastContext = (context: ToastContextType) => {
globalToastContext = context
}
// Переопределяем глобальный alert
if (typeof window !== 'undefined') {
const originalAlert = window.alert
window.alert = (message: string) => {
if (globalToastContext) {
// Определяем тип уведомления по содержанию сообщения
const lowerMessage = message.toLowerCase()
if (lowerMessage.includes('ошибка') || lowerMessage.includes('error')) {
globalToastContext.error(message)
} else if (
lowerMessage.includes('сохранен') ||
lowerMessage.includes('успешно')
) {
globalToastContext.success(message)
} else if (
lowerMessage.includes('предупреждение') ||
lowerMessage.includes('warning')
) {
globalToastContext.warning(message)
} else {
globalToastContext.info(message)
}
} else {
// Fallback на обычный alert, если контекст недоступен
originalAlert(message)
}
}
}