/** * ResolveInvestigationModal — Phase 2 of the memory loop. * When a user marks an investigation case resolved, this modal captures * "what worked" and "what didn't" so Pixie remembers the outcome for the * plant's NEXT case. Records successful/unsuccessful interventions into the * plant's intelligence profile (the growing per-plant JSON). */ import React, { useState } from 'react'; import { Modal, StyleSheet, Text, TextInput, TouchableOpacity, useWindowDimensions, View } from 'react-native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { green, dark, line } from '../constants/theme'; interface ResolveInvestigationModalProps { visible: boolean; plantName: string; onConfirm: (outcome: { successful: string[]; unsuccessful: string[] }) => void; onClose: () => void; } export function ResolveInvestigationModal({ visible, plantName, onConfirm, onClose, }: ResolveInvestigationModalProps) { const [whatWorked, setWhatWorked] = useState(''); const [whatDidnt, setWhatDidnt] = useState(''); // Pixel-based card height (Bekky rule #2 — no percentage maxHeight on modal cards). const insets = useSafeAreaInsets(); const { height: windowHeight } = useWindowDimensions(); const cardMaxHeight = Math.max(320, windowHeight - (insets.top + 24) - (insets.bottom + 24)); if (!visible) return null; const handleConfirm = () => { const successful = whatWorked.trim() ? whatWorked.split(/[;\n]/).map(s => s.trim()).filter(Boolean) : []; const unsuccessful = whatDidnt.trim() ? whatDidnt.split(/[;\n]/).map(s => s.trim()).filter(Boolean) : []; onConfirm({ successful, unsuccessful }); setWhatWorked(''); setWhatDidnt(''); }; return ( Resolve this case {plantName} Tell Pixie what happened so she can remember it for this plant's next problem. This is optional — you can resolve without adding anything. What worked? (optional) What didn't work? (optional) Not now ✓ Resolve Case ); } const s = StyleSheet.create({ overlay: { flex: 1, backgroundColor: 'rgba(16, 42, 16, 0.65)', justifyContent: 'center', alignItems: 'center', padding: 24, }, card: { width: '100%', maxWidth: 460, backgroundColor: '#FFFCF5', borderRadius: 24, padding: 24, paddingBottom: 20, maxHeight: '88%', shadowColor: '#000', shadowOpacity: 0.25, shadowRadius: 24, shadowOffset: { width: 0, height: 8 }, elevation: 12, }, header: { marginBottom: 14, alignItems: 'center' }, emoji: { fontSize: 34, marginBottom: 4 }, title: { fontSize: 22, fontWeight: '800', color: dark, textAlign: 'center' }, subtitle: { fontSize: 15, color: '#5D5A4E', textAlign: 'center', marginTop: 4, fontStyle: 'italic' }, body: { fontSize: 14, color: '#3A382E', lineHeight: 21, marginBottom: 14, textAlign: 'center' }, label: { fontSize: 13.5, fontWeight: '800', color: dark, marginBottom: 6, marginTop: 6 }, input: { minHeight: 70, borderRadius: 16, borderWidth: 1.5, borderColor: line, backgroundColor: '#FFF9EE', paddingHorizontal: 14, paddingVertical: 10, fontSize: 14.5, color: '#2F302A', textAlignVertical: 'top', marginBottom: 10, }, buttonRow: { flexDirection: 'row', gap: 12, marginTop: 8 }, cancelButton: { flex: 1, minHeight: 50, borderRadius: 999, borderWidth: 1.5, borderColor: '#B85C4A', backgroundColor: '#FCE9E6', alignItems: 'center', justifyContent: 'center', paddingHorizontal: 16, }, cancelButtonText: { color: '#8E2F1E', fontSize: 15, fontWeight: '900' }, confirmButton: { flex: 1, minHeight: 50, borderRadius: 999, backgroundColor: dark, alignItems: 'center', justifyContent: 'center', paddingHorizontal: 16, }, confirmButtonText: { color: '#fff', fontSize: 15, fontWeight: '900' }, });