import React, { useState, useCallback } from 'react'; import { View, StyleSheet, Pressable, Animated } from 'react-native'; import MemoList, { MemoModel } from './MemoList'; import SearchBar from './SearchBar'; import Icon from '~/components/atoms/Icon'; import Text from '~/components/atoms/Text'; import { useTheme } from '~/features/theme/ThemeProvider'; import { useMemoListSearch } from '~/features/memos/hooks/useMemoListSearch'; import { useTranslation } from 'react-i18next'; interface SearchableMemoListProps { showArchived?: boolean | null; spaceId?: string; tagIds?: string[]; selectionMode?: boolean; selectedMemoIds?: string[]; onMemoSelection?: (memoId: string, selected: boolean) => void; refreshTrigger?: number; onShare?: (memo: MemoModel) => void; onMemosLoaded?: (memos: MemoModel[]) => void; } const SearchableMemoList: React.FC = ({ showArchived, spaceId, tagIds, selectionMode, selectedMemoIds, onMemoSelection, refreshTrigger, onShare, onMemosLoaded, }) => { const { isDark, themeVariant } = useTheme(); const { t } = useTranslation(); const [isSearchMode, setIsSearchMode] = useState(false); const [allMemos, setAllMemos] = useState([]); const searchAnimation = useState(new Animated.Value(0))[0]; // Use the search hook const { searchQuery, setSearchQuery, filteredMemos, searchCount, isSearching, clearSearch } = useMemoListSearch(allMemos, { searchFields: ['title', 'intro', 'transcript', 'tags'], minSearchLength: 2, includeArchived: showArchived || false, }); // Callback when memos are loaded from MemoList const handleMemosLoaded = useCallback( (memos: MemoModel[]) => { setAllMemos(memos); onMemosLoaded?.(memos); }, [onMemosLoaded] ); // Toggle search mode with animation const toggleSearchMode = useCallback(() => { const newMode = !isSearchMode; setIsSearchMode(newMode); Animated.timing(searchAnimation, { toValue: newMode ? 1 : 0, duration: 200, useNativeDriver: true, }).start(); if (!newMode) { clearSearch(); } }, [isSearchMode, searchAnimation, clearSearch]); // Handle search close const handleSearchClose = useCallback(() => { setIsSearchMode(false); clearSearch(); Animated.timing(searchAnimation, { toValue: 0, duration: 200, useNativeDriver: true, }).start(); }, [searchAnimation, clearSearch]); // Determine which memos to display const memosToDisplay = isSearching ? filteredMemos : allMemos; return ( {/* Search Bar with animation */} {isSearchMode && ( 0 ? 1 : 0} /> )} {/* Search Button (floating) */} {!isSearchMode && !selectionMode && ( {t('common.search', 'Suche')} )} {/* Memo List */} {/* No Results Message */} {isSearching && searchCount === 0 && searchQuery.length >= 2 && ( {t('memo.noSearchResults', 'Keine Memos für')} "{searchQuery}"{' '} {t('memo.found', 'gefunden')} )} ); }; const styles = StyleSheet.create({ container: { flex: 1, position: 'relative', }, searchBarContainer: { position: 'absolute', top: 0, left: 0, right: 0, zIndex: 100, }, searchButton: { position: 'absolute', top: 16, right: 16, flexDirection: 'row', alignItems: 'center', paddingHorizontal: 16, paddingVertical: 8, borderRadius: 20, borderWidth: 1, gap: 8, zIndex: 90, elevation: 5, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.1, shadowRadius: 4, }, searchButtonText: { fontSize: 14, fontWeight: '500', }, noResultsContainer: { position: 'absolute', top: '40%', left: 0, right: 0, alignItems: 'center', justifyContent: 'center', paddingHorizontal: 32, }, noResultsText: { fontSize: 16, textAlign: 'center', marginTop: 16, }, }); export default SearchableMemoList;