mirror of
https://github.com/aljazceru/enclava.git
synced 2025-12-17 23:44:24 +01:00
toast fix
This commit is contained in:
4
.github/workflows/build-all.yml
vendored
4
.github/workflows/build-all.yml
vendored
@@ -2,10 +2,8 @@ name: Build All Docker Images
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, develop ]
|
||||
tags: [ 'v*' ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
|
||||
@@ -7,6 +7,7 @@ import { Toaster as HotToaster } from 'react-hot-toast'
|
||||
import { AuthProvider } from '@/contexts/AuthContext'
|
||||
import { ModulesProvider } from '@/contexts/ModulesContext'
|
||||
import { PluginProvider } from '@/contexts/PluginContext'
|
||||
import { ToastProvider } from '@/contexts/ToastContext'
|
||||
import { Navigation } from '@/components/ui/navigation'
|
||||
|
||||
const inter = Inter({ subsets: ['latin'] })
|
||||
@@ -68,13 +69,15 @@ export default function RootLayout({
|
||||
<AuthProvider>
|
||||
<ModulesProvider>
|
||||
<PluginProvider>
|
||||
<div className="min-h-screen bg-background">
|
||||
<Navigation />
|
||||
<main className="container mx-auto px-4 py-8">
|
||||
{children}
|
||||
</main>
|
||||
</div>
|
||||
<Toaster />
|
||||
<ToastProvider>
|
||||
<div className="min-h-screen bg-background">
|
||||
<Navigation />
|
||||
<main className="container mx-auto px-4 py-8">
|
||||
{children}
|
||||
</main>
|
||||
</div>
|
||||
<Toaster />
|
||||
</ToastProvider>
|
||||
<HotToaster />
|
||||
</PluginProvider>
|
||||
</ModulesProvider>
|
||||
|
||||
150
frontend/src/contexts/ToastContext.tsx
Normal file
150
frontend/src/contexts/ToastContext.tsx
Normal file
@@ -0,0 +1,150 @@
|
||||
"use client"
|
||||
|
||||
import React, { createContext, useContext, useState, useCallback, useRef } from 'react'
|
||||
import { generateShortId } from '@/lib/id-utils'
|
||||
|
||||
export interface ToastProps {
|
||||
id: string
|
||||
title?: string
|
||||
description?: string
|
||||
variant?: 'default' | 'destructive' | 'success' | 'warning'
|
||||
action?: React.ReactElement
|
||||
duration?: number
|
||||
}
|
||||
|
||||
export interface ToastOptions extends Omit<ToastProps, 'id'> {
|
||||
duration?: number
|
||||
}
|
||||
|
||||
interface ToastContextType {
|
||||
toasts: ToastProps[]
|
||||
toast: (options: ToastOptions) => () => void
|
||||
success: (title: string, description?: string, options?: Partial<ToastOptions>) => () => void
|
||||
error: (title: string, description?: string, options?: Partial<ToastOptions>) => () => void
|
||||
warning: (title: string, description?: string, options?: Partial<ToastOptions>) => () => void
|
||||
info: (title: string, description?: string, options?: Partial<ToastOptions>) => () => void
|
||||
dismiss: (id: string) => void
|
||||
clearAll: () => void
|
||||
}
|
||||
|
||||
const ToastContext = createContext<ToastContextType | undefined>(undefined)
|
||||
|
||||
export function ToastProvider({ children }: { children: React.ReactNode }) {
|
||||
const [toasts, setToasts] = useState<ToastProps[]>([])
|
||||
const timeoutRefs = useRef<Map<string, NodeJS.Timeout>>(new Map())
|
||||
|
||||
const dismissToast = useCallback((id: string) => {
|
||||
setToasts(prev => prev.filter(toast => toast.id !== id))
|
||||
|
||||
// Clear timeout if exists
|
||||
const timeoutId = timeoutRefs.current.get(id)
|
||||
if (timeoutId) {
|
||||
clearTimeout(timeoutId)
|
||||
timeoutRefs.current.delete(id)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const toast = useCallback((options: ToastOptions) => {
|
||||
const {
|
||||
duration = 5000,
|
||||
variant = 'default',
|
||||
...props
|
||||
} = options
|
||||
|
||||
// Generate unique ID using improved utility
|
||||
const id = generateShortId('toast')
|
||||
const toastWithId: ToastProps = {
|
||||
...props,
|
||||
id,
|
||||
variant,
|
||||
duration
|
||||
}
|
||||
|
||||
// Add to toasts array
|
||||
setToasts(prev => [...prev, toastWithId])
|
||||
|
||||
// Auto-remove after specified duration
|
||||
if (duration > 0) {
|
||||
const timeoutId = setTimeout(() => {
|
||||
dismissToast(id)
|
||||
}, duration)
|
||||
|
||||
timeoutRefs.current.set(id, timeoutId)
|
||||
}
|
||||
|
||||
// Return dismiss function for manual control
|
||||
return () => dismissToast(id)
|
||||
}, [dismissToast])
|
||||
|
||||
// Convenience methods for common toast types
|
||||
const success = useCallback((title: string, description?: string, options?: Partial<ToastOptions>) => {
|
||||
return toast({
|
||||
title,
|
||||
description,
|
||||
variant: 'success',
|
||||
...options
|
||||
})
|
||||
}, [toast])
|
||||
|
||||
const error = useCallback((title: string, description?: string, options?: Partial<ToastOptions>) => {
|
||||
return toast({
|
||||
title,
|
||||
description,
|
||||
variant: 'destructive',
|
||||
duration: 7000, // Errors should stay longer
|
||||
...options
|
||||
})
|
||||
}, [toast])
|
||||
|
||||
const warning = useCallback((title: string, description?: string, options?: Partial<ToastOptions>) => {
|
||||
return toast({
|
||||
title,
|
||||
description,
|
||||
variant: 'warning',
|
||||
...options
|
||||
})
|
||||
}, [toast])
|
||||
|
||||
const info = useCallback((title: string, description?: string, options?: Partial<ToastOptions>) => {
|
||||
return toast({
|
||||
title,
|
||||
description,
|
||||
variant: 'default',
|
||||
...options
|
||||
})
|
||||
}, [toast])
|
||||
|
||||
// Clear all toasts
|
||||
const clearAll = useCallback(() => {
|
||||
// Clear all timeouts
|
||||
timeoutRefs.current.forEach(timeoutId => clearTimeout(timeoutId))
|
||||
timeoutRefs.current.clear()
|
||||
|
||||
setToasts([])
|
||||
}, [])
|
||||
|
||||
const value: ToastContextType = {
|
||||
toasts,
|
||||
toast,
|
||||
success,
|
||||
error,
|
||||
warning,
|
||||
info,
|
||||
dismiss: dismissToast,
|
||||
clearAll,
|
||||
}
|
||||
|
||||
return (
|
||||
<ToastContext.Provider value={value}>
|
||||
{children}
|
||||
</ToastContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export function useToast() {
|
||||
const context = useContext(ToastContext)
|
||||
if (context === undefined) {
|
||||
throw new Error('useToast must be used within a ToastProvider')
|
||||
}
|
||||
return context
|
||||
}
|
||||
Reference in New Issue
Block a user