/** * PixieAlert — Custom light-themed alert for Android dark-mode fix. * Native Alert.alert() renders dark on some devices (Xiaomi). This is a * parchment-themed drop-in replacement: white card, green pill buttons. * Same API: (title, message, buttons?) where buttons: [{text, style?, onPress?}] * 'default' = green fill, 'cancel' = green outline, 'destructive' = red fill. */ import React from 'react'; import { Modal, StyleSheet, Text, TouchableOpacity, View } from 'react-native'; import { green, dark, line } from '../constants/theme'; // EdgeModal cast — lets the backdrop extend under the nav/status bars so the // dimmed overlay covers the whole screen (header + nav included), not just the // body. Same pattern used across PixieSprout's modals. const EdgeModal = Modal as any; export interface PixieAlertButton { text: string; style?: 'default' | 'cancel' | 'destructive'; onPress?: () => void; } interface PixieAlertProps { visible: boolean; title: string; message?: string; /** Optional custom body content rendered below `message` (Bekky, 2026-09-05): * lets the weather alert modal show a tidy 2-column plant list. */ children?: React.ReactNode; buttons?: PixieAlertButton[]; onRequestClose?: () => void; /** 'row' (default) = buttons side-by-side; 'column' = stacked full-width rows */ layout?: 'row' | 'column'; } export function PixieAlert({ visible, title, message, children, buttons = [], onRequestClose, layout = 'row' }: PixieAlertProps) { if (!visible) return null; const single = buttons.length === 1; return ( {title} {message ? {message} : null} {children} {buttons.length > 0 ? ( {buttons.map((btn, i) => { let btnStyle = s.btnDefault; let btnTextStyle = s.btnDefaultText; if (btn.style === 'cancel') { btnStyle = s.btnCancel; btnTextStyle = s.btnCancelText; } else if (btn.style === 'destructive') { btnStyle = s.btnDestructive; btnTextStyle = s.btnDestructiveText; } return ( { if (btn.onPress) btn.onPress(); }} > {btn.text} ); })} ) : null} ); } const s = StyleSheet.create({ overlay: { flex: 1, backgroundColor: 'rgba(16, 42, 16, 0.55)', justifyContent: 'center', alignItems: 'center', padding: 28, }, card: { width: '100%', maxWidth: 360, backgroundColor: '#FFFCF5', borderRadius: 24, padding: 24, shadowColor: '#000', shadowOpacity: 0.25, shadowRadius: 20, shadowOffset: { width: 0, height: 8 }, elevation: 12, }, title: { fontSize: 20, fontWeight: '800', color: dark, textAlign: 'center', marginBottom: 8, }, message: { fontSize: 15, color: '#3A382E', textAlign: 'center', lineHeight: 22, marginBottom: 20, }, buttonRow: { flexDirection: 'row', gap: 12, }, buttonColumn: { flexDirection: 'column', gap: 10, }, btnColumnItem: { width: '100%', minHeight: 52, }, btnFull: { flex: 1, }, btnDefault: { flex: 1, minHeight: 50, borderRadius: 999, backgroundColor: dark, alignItems: 'center', justifyContent: 'center', paddingHorizontal: 16, }, btnDefaultText: { color: '#fff', fontSize: 16, fontWeight: '900', }, btnCancel: { flex: 1, minHeight: 50, borderRadius: 999, borderWidth: 1.5, borderColor: '#B85C4A', backgroundColor: '#FCE9E6', alignItems: 'center', justifyContent: 'center', paddingHorizontal: 16, }, btnCancelText: { color: '#8E2F1E', fontSize: 16, fontWeight: '900', }, btnDestructive: { flex: 1, minHeight: 50, borderRadius: 999, backgroundColor: '#B74A35', alignItems: 'center', justifyContent: 'center', paddingHorizontal: 16, }, btnDestructiveText: { color: '#fff', fontSize: 16, fontWeight: '900', }, });