113 lines
3.3 KiB
TypeScript
113 lines
3.3 KiB
TypeScript
import React, { createContext, useContext, useState, ReactNode } from 'react';
|
|
import { Modal, View, Text, TouchableOpacity, TouchableWithoutFeedback } from 'react-native';
|
|
import { CheckCircle, XCircle, Info, AlertTriangle } from 'lucide-react-native';
|
|
|
|
type AlertType = 'success' | 'error' | 'info' | 'warning';
|
|
|
|
interface AlertContextData {
|
|
showAlert: (type: AlertType, title: string, message: string) => void;
|
|
hideAlert: () => void;
|
|
}
|
|
|
|
const AlertContext = createContext<AlertContextData>({} as AlertContextData);
|
|
|
|
const ALERT_CONFIG = {
|
|
success: {
|
|
icon: CheckCircle,
|
|
color: 'text-green-600',
|
|
bgColor: 'bg-green-100',
|
|
btnColor: 'bg-green-600',
|
|
},
|
|
error: {
|
|
icon: XCircle,
|
|
color: 'text-red-600',
|
|
bgColor: 'bg-red-100',
|
|
btnColor: 'bg-red-600',
|
|
},
|
|
info: {
|
|
icon: Info,
|
|
color: 'text-sky-600',
|
|
bgColor: 'bg-sky-100',
|
|
btnColor: 'bg-sky-600',
|
|
},
|
|
warning: {
|
|
icon: AlertTriangle,
|
|
color: 'text-orange-600',
|
|
bgColor: 'bg-orange-100',
|
|
btnColor: 'bg-orange-600',
|
|
},
|
|
};
|
|
|
|
export const AlertProvider = ({ children }: { children: ReactNode }) => {
|
|
const [visible, setVisible] = useState(false);
|
|
const [title, setTitle] = useState('');
|
|
const [message, setMessage] = useState('');
|
|
const [type, setType] = useState<AlertType>('info');
|
|
|
|
const showAlert = (newType: AlertType, newTitle: string, newMessage: string) => {
|
|
setType(newType);
|
|
setTitle(newTitle);
|
|
setMessage(newMessage);
|
|
setVisible(true);
|
|
};
|
|
|
|
const hideAlert = () => {
|
|
setVisible(false);
|
|
};
|
|
|
|
const { icon: Icon, color, bgColor, btnColor } = ALERT_CONFIG[type];
|
|
|
|
return (
|
|
<AlertContext.Provider value={{ showAlert, hideAlert }}>
|
|
{children}
|
|
|
|
{/* IL COMPONENTE ALERT MODALE */}
|
|
<Modal
|
|
transparent
|
|
visible={visible}
|
|
animationType="fade"
|
|
onRequestClose={hideAlert}
|
|
>
|
|
{/* Backdrop scuro */}
|
|
<TouchableOpacity
|
|
activeOpacity={1}
|
|
onPress={hideAlert} // Chiude se clicchi fuori (opzionale)
|
|
className="flex-1 bg-black/60 justify-center items-center px-6"
|
|
>
|
|
{/* Contenitore Alert */}
|
|
<TouchableWithoutFeedback>
|
|
<View className="bg-white w-full max-w-sm rounded-3xl p-6 items-center shadow-2xl">
|
|
|
|
{/* Icona Cerchiata */}
|
|
<View className={`${bgColor} p-4 rounded-full mb-4`}>
|
|
<Icon size={32} className={color} strokeWidth={2.5} />
|
|
</View>
|
|
|
|
{/* Testi */}
|
|
<Text className="text-xl font-bold text-gray-900 text-center mb-2">
|
|
{title}
|
|
</Text>
|
|
|
|
<Text className="text-lg text-gray-500 text-center leading-relaxed mb-8">
|
|
{message}
|
|
</Text>
|
|
|
|
{/* Pulsante OK */}
|
|
<TouchableOpacity
|
|
onPress={hideAlert}
|
|
className={`w-full py-3.5 rounded-xl ${btnColor} active:opacity-90 shadow-sm`}
|
|
>
|
|
<Text className="text-white text-center font-bold text-lg">
|
|
Ok, ho capito
|
|
</Text>
|
|
</TouchableOpacity>
|
|
|
|
</View>
|
|
</TouchableWithoutFeedback>
|
|
</TouchableOpacity>
|
|
</Modal>
|
|
</AlertContext.Provider>
|
|
);
|
|
};
|
|
|
|
export const useAlert = () => useContext(AlertContext); |