Multi-tenant factory inspection system (SpiFox, Enkid, Alpet): - FastAPI backend with JWT auth, PostgreSQL (asyncpg) - Next.js 16 frontend with App Router, SWR data fetching - Machines CRUD with equipment parts management - Part lifecycle tracking (hours/count/date) with counters - Partial unique index for soft-delete support - 24 pytest tests passing, E2E verified Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
48 lines
1.4 KiB
TypeScript
48 lines
1.4 KiB
TypeScript
'use client';
|
|
|
|
import React, { createContext, useContext, useState, useCallback } from 'react';
|
|
import { Toast, ToastType } from '../components/Toast';
|
|
|
|
interface ToastContextType {
|
|
addToast: (message: string, type: ToastType, duration?: number) => void;
|
|
removeToast: (id: string) => void;
|
|
}
|
|
|
|
const ToastContext = createContext<ToastContextType | undefined>(undefined);
|
|
|
|
export const ToastProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
|
const [toasts, setToasts] = useState<Array<{ id: string; message: string; type: ToastType; duration?: number }>>([]);
|
|
|
|
const addToast = useCallback((message: string, type: ToastType, duration?: number) => {
|
|
const id = Math.random().toString(36).substr(2, 9);
|
|
setToasts((prev) => [...prev, { id, message, type, duration }]);
|
|
}, []);
|
|
|
|
const removeToast = useCallback((id: string) => {
|
|
setToasts((prev) => prev.filter((toast) => toast.id !== id));
|
|
}, []);
|
|
|
|
return (
|
|
<ToastContext.Provider value={{ addToast, removeToast }}>
|
|
{children}
|
|
<div className="toast-container">
|
|
{toasts.map((toast) => (
|
|
<Toast
|
|
key={toast.id}
|
|
{...toast}
|
|
onClose={removeToast}
|
|
/>
|
|
))}
|
|
</div>
|
|
</ToastContext.Provider>
|
|
);
|
|
};
|
|
|
|
export const useToast = () => {
|
|
const context = useContext(ToastContext);
|
|
if (context === undefined) {
|
|
throw new Error('useToast must be used within a ToastProvider');
|
|
}
|
|
return context;
|
|
};
|