/** * PhotoGuidanceModal — Shows "how to take a good photo" tips for each photo type. * Shown automatically the first time a user reaches a photo type, and reachable * again via a "?" button. Content is grounded in what Pixie's AI actually * extracts from each photo type (see photoIntelligenceExtractor buildPrompt). */ import React from 'react'; import { Modal, ScrollView, StyleSheet, Text, TouchableOpacity, useWindowDimensions, View } from 'react-native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { green, dark, line } from '../constants/theme'; export type PhotoGuidanceType = 'environment' | 'placement' | 'setup' | 'progress'; interface PhotoGuidanceModalProps { visible: boolean; photoType: PhotoGuidanceType; onClose: () => void; } interface GuidanceContent { emoji: string; title: string; why: string; tips: string[]; busyGardenTip?: string; } const CONTENT: Record = { environment: { emoji: '📷', title: 'Show Pixie the space', why: 'This tells Pixie about the light, airflow, and setting your plant lives in.', tips: [ 'Step back and show the whole spot — Pixie needs to see the window, the light, and what\u2019s around the plant, not just the plant itself.', 'Capture the light honestly — take it in the light the spot actually gets. If it\u2019s a morning-sun corner, a morning photo says it best. Avoid flash — it hides the true light.', 'Show what\u2019s nearby — walls, other plants, a heater or AC vent, an overhang. These tell Pixie about airflow and shelter.', ], }, placement: { emoji: '📷', title: 'Show Pixie where it lives', why: 'This tells Pixie exactly where your plant sits within its space — and how much light it really gets.', tips: [ 'Get close enough that your plant is the star — Pixie needs to see this plant, not the whole room.', 'Show the light source — include the window, skylight, or grow light in the frame so Pixie can judge direct vs. indirect light.', 'Show the height — is it on the floor, a table, a shelf, or hanging? Pixie uses this to understand its light and microclimate.', 'Show what\u2019s beside it — nearby plants, a radiator, a drafty window. These shape the plant\u2019s little environment.', ], busyGardenTip: 'Garden\u2019s a bit busy? Get close so your plant fills most of the frame, and angle so a plain background (wall, sky, ground) is behind it. Pixie focuses best on one clear subject.', }, setup: { emoji: '📷', title: 'Show Pixie the setup', why: 'This tells Pixie about the pot, soil, and drainage your plant is growing in.', tips: [ 'Get close — fill the frame with the pot and soil. Pixie needs to see the container and the growing medium clearly.', 'Show the drainage — the holes, the saucer, or the tray. Pixie uses this to understand watering risk.', 'Show any support or extras — a stake, trellis, moss pole, or grow light.', 'In the ground? Snap the base of the plant too, so Pixie can see it\u2019s planted in soil or a raised bed.', 'Skip the flash — let Pixie see the true color of the soil and leaves.', ], busyGardenTip: 'Garden\u2019s a bit busy? Get close so your plant fills most of the frame, and angle so a plain background (wall, sky, ground) is behind it. Pixie focuses best on one clear subject.', }, progress: { emoji: '📷', title: 'Show Pixie how it\u2019s doing', why: 'This is how Pixie tracks your plant\u2019s health and growth over time — the more consistent, the smarter Pixie gets.', tips: [ 'Same plant, same angle, same light — consistency is everything. Pixie compares photos to spot changes.', 'Fill the frame with the plant — Pixie needs to see leaf color, new growth, and overall shape.', 'Show the whole plant, not just a leaf — unless you\u2019re capturing a specific change (a new leaf, a yellowing spot).', 'Add a memory note — if you did something (repotted, watered, moved it), say so. Pixie can\u2019t see actions, only results.', ], }, }; export function PhotoGuidanceModal({ visible, photoType, onClose }: PhotoGuidanceModalProps) { if (!visible) return null; const content = CONTENT[photoType]; // 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)); return ( {content.emoji} {content.title} {content.why} {content.tips.map((tip, i) => ( {i + 1} {tip} ))} {content.busyGardenTip ? ( {content.busyGardenTip} ) : null} Got it ); } 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: 16, alignItems: 'center', }, headerClose: { position: 'absolute', top: -4, right: -4, width: 34, height: 34, borderRadius: 17, backgroundColor: '#FFF9EE', borderWidth: 1.5, borderColor: line, alignItems: 'center', justifyContent: 'center', }, headerCloseText: { color: dark, fontSize: 16, fontWeight: '800', lineHeight: 18, }, emoji: { fontSize: 34, marginBottom: 4, }, title: { fontSize: 22, fontWeight: '800', color: dark, textAlign: 'center', }, body: { flexGrow: 0, }, why: { fontSize: 15, color: '#5D5A4E', lineHeight: 22, marginBottom: 14, fontStyle: 'italic', }, tipRow: { flexDirection: 'row', alignItems: 'flex-start', marginBottom: 10, gap: 10, }, tipNumber: { width: 22, height: 22, borderRadius: 11, backgroundColor: green + '22', color: dark, fontSize: 12.5, fontWeight: '900', textAlign: 'center', lineHeight: 22, overflow: 'hidden', }, tipText: { flex: 1, fontSize: 14.5, color: '#2F302A', lineHeight: 21, }, busyTip: { marginTop: 6, padding: 14, borderRadius: 18, backgroundColor: '#FFF3E8', }, busyTipText: { fontSize: 13.5, color: '#8A5D20', lineHeight: 20, }, gotItButton: { minHeight: 50, borderRadius: 999, backgroundColor: dark, alignItems: 'center', justifyContent: 'center', marginTop: 14, paddingHorizontal: 20, }, gotItButtonText: { color: '#fff', fontSize: 16, fontWeight: '900', }, });