|
@@ -1,5 +1,5 @@
|
|
import { FlatList, ScrollView, StyleSheet, Text, TouchableOpacity, TouchableWithoutFeedback, View } from 'react-native'
|
|
import { FlatList, ScrollView, StyleSheet, Text, TouchableOpacity, TouchableWithoutFeedback, View } from 'react-native'
|
|
-import React, { useState } from 'react'
|
|
|
|
|
|
+import React, { useEffect, useState } from 'react'
|
|
import { SafeAreaView } from 'react-native-safe-area-context'
|
|
import { SafeAreaView } from 'react-native-safe-area-context'
|
|
import NewscoutTitleHeader from '../../components/molecules/Header/NewscoutTitleHeader'
|
|
import NewscoutTitleHeader from '../../components/molecules/Header/NewscoutTitleHeader'
|
|
import colors from '../../constants/colors'
|
|
import colors from '../../constants/colors'
|
|
@@ -8,7 +8,7 @@ import { horizontalScale, moderateScale, screenWidth, verticalScale } from '../.
|
|
import IonIcon from 'react-native-vector-icons/Ionicons'
|
|
import IonIcon from 'react-native-vector-icons/Ionicons'
|
|
import fonts from '../../constants/fonts'
|
|
import fonts from '../../constants/fonts'
|
|
import { navigateToArticle, navigateToListViewPage, useConstructor } from '../../constants/functions'
|
|
import { navigateToArticle, navigateToListViewPage, useConstructor } from '../../constants/functions'
|
|
-import { getArticlesBySearch, getCategories, getMenus } from '../../api/data'
|
|
|
|
|
|
+import { getArticlesBySearch, getCategories, getMenus, getTrendingNews } from '../../api/data'
|
|
import LoadingScreen from '../../components/organisms/Sections/LoadingScreen'
|
|
import LoadingScreen from '../../components/organisms/Sections/LoadingScreen'
|
|
import { PAGINATE_BY } from '../../api/urls'
|
|
import { PAGINATE_BY } from '../../api/urls'
|
|
import HorizontalNewsCardVariant from '../../components/molecules/Cards/HorizontalNewsCardVariant'
|
|
import HorizontalNewsCardVariant from '../../components/molecules/Cards/HorizontalNewsCardVariant'
|
|
@@ -24,21 +24,20 @@ const SearchPage = props => {
|
|
const [isSearching, setSearching] = useState(false)
|
|
const [isSearching, setSearching] = useState(false)
|
|
const [categories, setCategories] = useState([])
|
|
const [categories, setCategories] = useState([])
|
|
const [searchText, setSearchText] = useState("")
|
|
const [searchText, setSearchText] = useState("")
|
|
|
|
+
|
|
const [suggestedNews, setSuggestedNews] = useState([])
|
|
const [suggestedNews, setSuggestedNews] = useState([])
|
|
|
|
+
|
|
const [filtersData, setFiltersData] = useState({})
|
|
const [filtersData, setFiltersData] = useState({})
|
|
const [currentFilter, setCurrentFilter] = useState("Category")
|
|
const [currentFilter, setCurrentFilter] = useState("Category")
|
|
|
|
|
|
|
|
+ const [recentSearches, setRecentSearches] = useState([])
|
|
|
|
+
|
|
|
|
+ const [pagesLoaded, setPagesLoaded] = useState(1)
|
|
// * Filters Modal
|
|
// * Filters Modal
|
|
const [isFiltersVisible, setFiltersVisible] = useState(false);
|
|
const [isFiltersVisible, setFiltersVisible] = useState(false);
|
|
const showFilters = () => setFiltersVisible(true);
|
|
const showFilters = () => setFiltersVisible(true);
|
|
const hideFilters = () => setFiltersVisible(false);
|
|
const hideFilters = () => setFiltersVisible(false);
|
|
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
const styles = StyleSheet.create({
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
container: {
|
|
backgroundColor: colors().dominant,
|
|
backgroundColor: colors().dominant,
|
|
@@ -48,7 +47,7 @@ const SearchPage = props => {
|
|
inputTextContainer: {
|
|
inputTextContainer: {
|
|
backgroundColor: colors().dominant,
|
|
backgroundColor: colors().dominant,
|
|
paddingHorizontal: horizontalScale(16),
|
|
paddingHorizontal: horizontalScale(16),
|
|
- paddingBottom: verticalScale(16),
|
|
|
|
|
|
+ paddingVertical: verticalScale(16),
|
|
flexDirection: 'row',
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
alignItems: 'center',
|
|
// gap: horizontalScale(16),
|
|
// gap: horizontalScale(16),
|
|
@@ -126,15 +125,17 @@ const SearchPage = props => {
|
|
},
|
|
},
|
|
selectedFilterPill: {
|
|
selectedFilterPill: {
|
|
paddingVertical: verticalScale(8),
|
|
paddingVertical: verticalScale(8),
|
|
- paddingHorizontal: horizontalScale(16),
|
|
|
|
- backgroundColor: colors().primaryColor,
|
|
|
|
- borderRadius: moderateScale(18),
|
|
|
|
|
|
+ paddingHorizontal: horizontalScale(8),
|
|
|
|
+ // backgroundColor: colors().primaryColor,
|
|
|
|
+ borderRadius: 0,
|
|
width: 'auto',
|
|
width: 'auto',
|
|
|
|
+ borderColor: colors().primaryColor,
|
|
|
|
+ borderBottomWidth: 3
|
|
},
|
|
},
|
|
selectedPillText: {
|
|
selectedPillText: {
|
|
- fontFamily: fonts.type.semibold,
|
|
|
|
- fontSize: moderateScale(12),
|
|
|
|
- color: colors().white,
|
|
|
|
|
|
+ fontFamily: fonts.type.bold,
|
|
|
|
+ fontSize: moderateScale(14),
|
|
|
|
+ color: colors().recessive,
|
|
},
|
|
},
|
|
pillText: {
|
|
pillText: {
|
|
fontFamily: fonts.type.semibold,
|
|
fontFamily: fonts.type.semibold,
|
|
@@ -142,7 +143,10 @@ const SearchPage = props => {
|
|
color: colors().recessive,
|
|
color: colors().recessive,
|
|
},
|
|
},
|
|
filterCheckboxes: {
|
|
filterCheckboxes: {
|
|
- alignItems: 'flex-start'
|
|
|
|
|
|
+ alignItems: 'flex-start',
|
|
|
|
+ flexDirection: 'column',
|
|
|
|
+ gap: moderateScale(8),
|
|
|
|
+
|
|
},
|
|
},
|
|
listItemText: {
|
|
listItemText: {
|
|
fontFamily: fonts.type.medium,
|
|
fontFamily: fonts.type.medium,
|
|
@@ -159,9 +163,9 @@ const SearchPage = props => {
|
|
getCategories().then(res => setCategories(res.data.body.results)).catch(err => console.log(err))
|
|
getCategories().then(res => setCategories(res.data.body.results)).catch(err => console.log(err))
|
|
}
|
|
}
|
|
|
|
|
|
- const fetchSuggestions = (search_text) => {
|
|
|
|
- getArticlesBySearch(search_text)
|
|
|
|
- .then(res => setSuggestedNews(res.data.body.results.slice(0, PAGINATE_BY)))
|
|
|
|
|
|
+ const fetchSuggestions = (search_text, page = 1, filters = "") => {
|
|
|
|
+ getArticlesBySearch(search_text, page, filters)
|
|
|
|
+ .then(res => setSuggestedNews(prev => [...prev, ...res.data.body.results]))
|
|
.catch(err => console.log(err))
|
|
.catch(err => console.log(err))
|
|
}
|
|
}
|
|
|
|
|
|
@@ -177,120 +181,71 @@ const SearchPage = props => {
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ const getRecentSearches = () => {
|
|
|
|
+ getTrendingNews().then(res => setRecentSearches(res.data.body.results.slice(0, PAGINATE_BY))).catch(err => console.error(err))
|
|
|
|
+ }
|
|
|
|
+
|
|
useConstructor(() => {
|
|
useConstructor(() => {
|
|
fetchCategories()
|
|
fetchCategories()
|
|
fetchFilters()
|
|
fetchFilters()
|
|
|
|
+ getRecentSearches()
|
|
})
|
|
})
|
|
|
|
|
|
- const onChangeText = (text) => {
|
|
|
|
- if (text.length > 0) {
|
|
|
|
- console.warn(text)
|
|
|
|
- setSearching(true)
|
|
|
|
- setSearchText(text)
|
|
|
|
|
|
+ const onChangeText = text => {
|
|
|
|
+ if (text.length <= 0) {
|
|
setSuggestedNews([])
|
|
setSuggestedNews([])
|
|
- fetchSuggestions(text)
|
|
|
|
-
|
|
|
|
- } else {
|
|
|
|
- console.warn(text)
|
|
|
|
setSearching(false)
|
|
setSearching(false)
|
|
- setSearchText(text)
|
|
|
|
- setSuggestedNews([])
|
|
|
|
}
|
|
}
|
|
|
|
+ setSearchText(text)
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+ const onSearch = () => {
|
|
|
|
+ navigation.push('SearchListPage', { query: searchText })
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ const clearAllFilters = () => {
|
|
|
|
+ setFiltersData(prev => ({ ...prev, "Category": Object.entries(filtersData['Category']).reduce((current, value) => ({ ...current, [value[0]]: false }), {}) }))
|
|
|
|
+ setFiltersData(prev => ({ ...prev, "Source": Object.entries(filtersData['Source']).reduce((current, value) => ({ ...current, [value[0]]: false }), {}) }))
|
|
|
|
+ setFiltersData(prev => ({ ...prev, "Hash Tags": Object.entries(filtersData['Hash Tags']).reduce((current, value) => ({ ...current, [value[0]]: false }), {}) }))
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ const applyFilters = () => {
|
|
|
|
+ setSuggestedNews([])
|
|
|
|
+ setSearching(true)
|
|
|
|
+ hideFilters()
|
|
|
|
+ setPagesLoaded(1)
|
|
|
|
+ console.log(createFilters(filtersData))
|
|
|
|
+ fetchSuggestions(searchText, 1, createFilters(filtersData))
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ const createFilters = (filterObject) => {
|
|
|
|
+ let filterText = ""
|
|
|
|
+ for (const obj of Object.entries(filterObject)) {
|
|
|
|
+ for (const category of Object.entries(obj[1])) {
|
|
|
|
+ if (category[1] === true) {
|
|
|
|
+ filterText += `&${obj[0].toLowerCase()}=${category[0]}`
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return filterText
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // useEffect(() => {
|
|
|
|
+ // fetchSuggestions(searchText,pagesLoaded,createFilters(filtersData))
|
|
|
|
+ // },[pagesLoaded])
|
|
|
|
+
|
|
|
|
+
|
|
return (
|
|
return (
|
|
<PaperProvider>
|
|
<PaperProvider>
|
|
<SafeAreaView style={styles.container}>
|
|
<SafeAreaView style={styles.container}>
|
|
- <Portal>
|
|
|
|
- <Modal visible={isFiltersVisible} onDismiss={hideFilters} contentContainerStyle={styles.filtersModalContainer}>
|
|
|
|
- <View style={styles.filtersHeader}>
|
|
|
|
- <Text style={styles.filterHeading}>Filters</Text>
|
|
|
|
- <View style={styles.utilContainer}>
|
|
|
|
- <ThemedTextButton theme={'primary-contained'} title={'Clear All'} buttonStyle={{ paddingVertical: verticalScale(6) }} />
|
|
|
|
-
|
|
|
|
- <IconButton
|
|
|
|
- icon="close"
|
|
|
|
- iconColor={colors().recessive}
|
|
|
|
- size={moderateScale(24)}
|
|
|
|
- onPress={hideFilters}
|
|
|
|
- style={{ alignSelf: 'flex-end' }}
|
|
|
|
- />
|
|
|
|
- </View>
|
|
|
|
- </View>
|
|
|
|
- <View>
|
|
|
|
- <ScrollView horizontal contentContainerStyle={styles.filterPillContainer}>
|
|
|
|
- <ToggleButton.Group
|
|
|
|
- onValueChange={value => {
|
|
|
|
- setCurrentFilter(value)
|
|
|
|
- }}
|
|
|
|
- >
|
|
|
|
- {
|
|
|
|
- Object.keys(filtersData).map(item =>
|
|
|
|
- <ToggleButton
|
|
|
|
- key={item}
|
|
|
|
- icon={() => (
|
|
|
|
- <Text
|
|
|
|
- style={[
|
|
|
|
- item === currentFilter
|
|
|
|
- ? styles.selectedPillText
|
|
|
|
- : styles.pillText,
|
|
|
|
- ]}>
|
|
|
|
- {item}
|
|
|
|
- </Text>
|
|
|
|
- )}
|
|
|
|
- style={[
|
|
|
|
- item === currentFilter
|
|
|
|
- ? styles.selectedFilterPill
|
|
|
|
- : styles.filterPill,
|
|
|
|
- { marginHorizontal: horizontalScale(4) },
|
|
|
|
- ]}
|
|
|
|
- value={item}
|
|
|
|
- />)
|
|
|
|
- }
|
|
|
|
- </ToggleButton.Group>
|
|
|
|
- </ScrollView>
|
|
|
|
- </View>
|
|
|
|
|
|
|
|
- {
|
|
|
|
- // filtersData[currentFilter]
|
|
|
|
- Object.keys(filtersData).length <= 0 ? <LoadingScreen />
|
|
|
|
- :
|
|
|
|
- <FlatList
|
|
|
|
- contentContainerStyle={styles.filterCheckboxes}
|
|
|
|
- showsVerticalScrollIndicator={false}
|
|
|
|
- data={Object.entries(filtersData[currentFilter])}
|
|
|
|
- renderItem={filter => <List.Item
|
|
|
|
- key={filter.item[0]}
|
|
|
|
- style={styles.listItem}
|
|
|
|
- titleStyle={styles.listItemText}
|
|
|
|
- title={filter.item[0]}
|
|
|
|
- left={props => <Checkbox
|
|
|
|
- status={filtersData[currentFilter][filter.item[0]] === true ? 'checked' : 'unchecked'}
|
|
|
|
- onPress={() =>{
|
|
|
|
- setFiltersData({ ...filtersData, [currentFilter]: { ...filtersData[currentFilter], [filter.item[0]]: !filtersData[currentFilter][filter.item[0]] } })
|
|
|
|
- console.log(filtersData[currentFilter][filter.item[0]])
|
|
|
|
- }}
|
|
|
|
-
|
|
|
|
- color={colors().secondaryColor}
|
|
|
|
- />}
|
|
|
|
-
|
|
|
|
- />}
|
|
|
|
- // keyExtractor={item => item.index}
|
|
|
|
- />}
|
|
|
|
- <ThemedTextButton theme={'secondary-contained'} title={'Apply'} buttonStyle={{ paddingVertical: verticalScale(6),marginTop: verticalScale(8) }} />
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- </Modal>
|
|
|
|
- </Portal>
|
|
|
|
<ScrollView>
|
|
<ScrollView>
|
|
- <NewscoutTitleHeader title={"Search"} />
|
|
|
|
|
|
+ {/* <NewscoutTitleHeader title={"Search"} /> */}
|
|
|
|
|
|
<View style={styles.inputTextContainer}>
|
|
<View style={styles.inputTextContainer}>
|
|
<TextInput
|
|
<TextInput
|
|
|
|
+ returnKeyType='search'
|
|
editable
|
|
editable
|
|
mode='outlined'
|
|
mode='outlined'
|
|
placeholder='Search Text'
|
|
placeholder='Search Text'
|
|
@@ -299,8 +254,6 @@ const SearchPage = props => {
|
|
style={{
|
|
style={{
|
|
backgroundColor: colors().grayShade_500,
|
|
backgroundColor: colors().grayShade_500,
|
|
paddingVertical: moderateScale(4),
|
|
paddingVertical: moderateScale(4),
|
|
- // width: '100%',
|
|
|
|
-
|
|
|
|
flex: 1
|
|
flex: 1
|
|
|
|
|
|
}}
|
|
}}
|
|
@@ -318,37 +271,44 @@ const SearchPage = props => {
|
|
left={() => <Text>fdsfdss</Text>}
|
|
left={() => <Text>fdsfdss</Text>}
|
|
right={() => <TouchableOpacity onPress={() => navigateToListViewPage(navigation, 'search', searchText)}><IonIcon name="search" color={colors().grayShade_200} size={moderateScale(8)} /></TouchableOpacity>}
|
|
right={() => <TouchableOpacity onPress={() => navigateToListViewPage(navigation, 'search', searchText)}><IonIcon name="search" color={colors().grayShade_200} size={moderateScale(8)} /></TouchableOpacity>}
|
|
onChangeText={onChangeText}
|
|
onChangeText={onChangeText}
|
|
|
|
+ onSubmitEditing={onSearch}
|
|
/>
|
|
/>
|
|
- <TouchableOpacity style={styles.filtersButton} onPress={showFilters}>
|
|
|
|
- <IonIcon name="filter" color={colors().recessive_variant} size={moderateScale(24)} />
|
|
|
|
- </TouchableOpacity>
|
|
|
|
</View>
|
|
</View>
|
|
- {
|
|
|
|
- isSearching === false ?
|
|
|
|
- <View style={styles.categoryContainer}>
|
|
|
|
- {categories.map((item) =>
|
|
|
|
- <TouchableOpacity onPress={() => navigateToListViewPage(navigation, "category", item.heading.name)}>
|
|
|
|
- <View style={styles.category}>
|
|
|
|
- <Text style={styles.categoryText}>{item.heading.name}</Text>
|
|
|
|
- </View>
|
|
|
|
- </TouchableOpacity>
|
|
|
|
|
|
|
|
- )}
|
|
|
|
- </View>
|
|
|
|
- : suggestedNews.length <= 0 ?
|
|
|
|
- <View style={{ alignItems: 'center', justifyContent: 'center', }}><LoadingScreen containerHeight={600} /></View> : <View style={styles.categoryContainer}>
|
|
|
|
- {suggestedNews.map((item) =>
|
|
|
|
- <HorizontalNewsCardVariant
|
|
|
|
- onPress={() => navigateToArticle(navigation, item.id, item.slug)}
|
|
|
|
- timestamp={item.published_on}
|
|
|
|
- headline={item.title}
|
|
|
|
- image={{ uri: item.cover_image }}
|
|
|
|
- category={item.category}
|
|
|
|
- tagline={item.id}
|
|
|
|
|
|
+ <View >
|
|
|
|
+ <View style={[styles.categoryContainer, { gap: 0 }]}>
|
|
|
|
+ {
|
|
|
|
+ recentSearches.map(item => {
|
|
|
|
+ const newsTag = item.articles[0]
|
|
|
|
+ return <TouchableOpacity onPress={() => navigateToArticle(navigation, newsTag.id, newsTag.slug)}>
|
|
|
|
+ <List.Item
|
|
|
|
+ title={newsTag.title}
|
|
|
|
+ titleStyle={{ fontFamily: fonts.type.regular, fontSize: moderateScale(12), color: colors().grayShade_200 }}
|
|
|
|
+ style={{ paddingVertical: 0 }}
|
|
|
|
+ left={() => <IonIcon name="trending-up" color={colors().grayShade_300} size={moderateScale(16)} />}
|
|
|
|
+
|
|
/>
|
|
/>
|
|
- )}
|
|
|
|
- </View>
|
|
|
|
- }
|
|
|
|
|
|
+ </TouchableOpacity>
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ )
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ </View>
|
|
|
|
+ <View style={styles.categoryContainer}>
|
|
|
|
+ {categories.map((item) =>
|
|
|
|
+ <TouchableOpacity onPress={() => navigateToListViewPage(navigation, "category", item.heading.name)}>
|
|
|
|
+ <View style={styles.category}>
|
|
|
|
+ <Text style={styles.categoryText}>{item.heading.name}</Text>
|
|
|
|
+ </View>
|
|
|
|
+ </TouchableOpacity>
|
|
|
|
+
|
|
|
|
+ )}
|
|
|
|
+ </View>
|
|
|
|
+ </View>
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
</ScrollView>
|
|
</ScrollView>
|
|
</SafeAreaView>
|
|
</SafeAreaView>
|
|
</PaperProvider>
|
|
</PaperProvider>
|