Onboarding

This commit is contained in:
2026-04-22 21:37:52 +02:00
parent c16fee77af
commit 3e9f863121
21 changed files with 2524 additions and 184 deletions

View File

@@ -11,35 +11,25 @@ import { PlantDatabaseService } from '../services/plantDatabaseService';
import { IdentificationResult } from '../types';
import { DatabaseEntry } from '../services/plantDatabaseService';
import { ResultCard } from '../components/ResultCard';
import { ThemeBackdrop } from '../components/ThemeBackdrop';
import { SafeImage } from '../components/SafeImage';
import { resolveImageUri } from '../utils/imageUri';
export default function LexiconScreen() {
const { isDarkMode, colorPalette, language, t, savePlant, getLexiconSearchHistory, saveLexiconSearchQuery, clearLexiconSearchHistory } = useApp();
const colors = useColors(isDarkMode, colorPalette);
const insets = useSafeAreaInsets();
const router = useRouter();
const params = useLocalSearchParams();
const categoryIdParam = Array.isArray(params.categoryId) ? params.categoryId[0] : params.categoryId;
const categoryLabelParam = Array.isArray(params.categoryLabel) ? params.categoryLabel[0] : params.categoryLabel;
const decodeParam = (value?: string | string[]) => {
if (!value || typeof value !== 'string') return '';
try {
return decodeURIComponent(value);
} catch {
return value;
}
};
const initialCategoryId = typeof categoryIdParam === 'string' ? categoryIdParam : null;
const initialCategoryLabel = decodeParam(categoryLabelParam);
const topInsetFallback = Platform.OS === 'android' ? (StatusBar.currentHeight || 0) : 20;
const topInset = insets.top > 0 ? insets.top : topInsetFallback;
const [searchQuery, setSearchQuery] = useState(initialCategoryLabel);
const [activeCategoryId, setActiveCategoryId] = useState<string | null>(initialCategoryId);
import { ThemeBackdrop } from '../components/ThemeBackdrop';
import { SafeImage } from '../components/SafeImage';
import { resolveImageUri } from '../utils/imageUri';
import { OnboardingProgressService } from '../services/onboardingProgressService';
export default function LexiconScreen() {
const { session, isDarkMode, colorPalette, language, t, savePlant, getLexiconSearchHistory, saveLexiconSearchQuery, clearLexiconSearchHistory } = useApp();
const colors = useColors(isDarkMode, colorPalette);
const insets = useSafeAreaInsets();
const router = useRouter();
const params = useLocalSearchParams();
const categoryIdParam = Array.isArray(params.categoryId) ? params.categoryId[0] : params.categoryId;
const initialCategoryId = typeof categoryIdParam === 'string' ? categoryIdParam : null;
const topInsetFallback = Platform.OS === 'android' ? (StatusBar.currentHeight || 0) : 20;
const topInset = insets.top > 0 ? insets.top : topInsetFallback;
const [searchQuery, setSearchQuery] = useState('');
const [activeCategoryId, setActiveCategoryId] = useState<string | null>(initialCategoryId);
const [selectedItem, setSelectedItem] = useState<(IdentificationResult & { imageUri: string }) | null>(null);
const [isAiSearching, setIsAiSearching] = useState(false);
const [aiResults, setAiResults] = useState<DatabaseEntry[] | null>(null);
@@ -66,20 +56,25 @@ export default function LexiconScreen() {
}
}
}
}, [detailParam]);
}, [detailParam]);
React.useEffect(() => {
setActiveCategoryId(initialCategoryId);
setSearchQuery('');
}, [initialCategoryId]);
React.useEffect(() => {
setActiveCategoryId(initialCategoryId);
setSearchQuery(initialCategoryLabel);
}, [initialCategoryId, initialCategoryLabel]);
React.useEffect(() => {
const loadHistory = async () => {
const history = getLexiconSearchHistory();
setSearchHistory(history);
};
loadHistory();
}, []);
React.useEffect(() => {
const loadHistory = async () => {
const history = getLexiconSearchHistory();
setSearchHistory(history);
};
loadHistory();
}, []);
React.useEffect(() => {
if (!session?.userId) return;
OnboardingProgressService.completeStep(session.userId, 'lexicon');
}, [session?.userId]);
const handleResultClose = () => {
if (openedWithDetail) {