все к лучшему
This commit is contained in:
154
src/lib/hooks/useToast.tsx
Normal file
154
src/lib/hooks/useToast.tsx
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user