|
@@ -3,28 +3,40 @@ import React, { 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'
|
|
-import { PaperProvider, TextInput } from 'react-native-paper'
|
|
|
|
|
|
+import { Checkbox, IconButton, List, Modal, PaperProvider, Portal, TextInput, ToggleButton } from 'react-native-paper'
|
|
import { horizontalScale, moderateScale, screenWidth, verticalScale } from '../../constants/metrics'
|
|
import { horizontalScale, moderateScale, screenWidth, verticalScale } from '../../constants/metrics'
|
|
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 } from '../../api/data'
|
|
|
|
|
|
+import { getArticlesBySearch, getCategories, getMenus } 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'
|
|
-
|
|
|
|
|
|
+import ThemedTextButton from '../../components/molecules/Buttons/ThemeTextButton'
|
|
|
|
+import { FlatList } from 'react-native-gesture-handler'
|
|
|
|
|
|
const SearchPage = props => {
|
|
const SearchPage = props => {
|
|
|
|
|
|
|
|
+ const {
|
|
|
|
+ navigation,
|
|
|
|
+ route
|
|
|
|
+ } = 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 [currentFilter, setCurrentFilter] = useState("Category")
|
|
|
|
+
|
|
|
|
+ // * Filters Modal
|
|
|
|
+ const [isFiltersVisible, setFiltersVisible] = useState(false);
|
|
|
|
+ const showFilters = () => setFiltersVisible(true);
|
|
|
|
+ const hideFilters = () => setFiltersVisible(false);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
|
|
- const {
|
|
|
|
- navigation,
|
|
|
|
- route
|
|
|
|
- } = props
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -38,10 +50,10 @@ const SearchPage = props => {
|
|
backgroundColor: colors().dominant,
|
|
backgroundColor: colors().dominant,
|
|
paddingHorizontal: horizontalScale(16),
|
|
paddingHorizontal: horizontalScale(16),
|
|
paddingBottom: verticalScale(16),
|
|
paddingBottom: verticalScale(16),
|
|
- flexDirection:'row',
|
|
|
|
|
|
+ flexDirection: 'row',
|
|
alignItems: 'center',
|
|
alignItems: 'center',
|
|
// gap: horizontalScale(16),
|
|
// gap: horizontalScale(16),
|
|
- maxWidth:'100%'
|
|
|
|
|
|
+ maxWidth: '100%'
|
|
},
|
|
},
|
|
categoryContainer: {
|
|
categoryContainer: {
|
|
padding: verticalScale(16),
|
|
padding: verticalScale(16),
|
|
@@ -67,13 +79,69 @@ const SearchPage = props => {
|
|
maxWidth: "80%",
|
|
maxWidth: "80%",
|
|
textAlign: 'right'
|
|
textAlign: 'right'
|
|
},
|
|
},
|
|
- filtersButton:{
|
|
|
|
|
|
+ filtersButton: {
|
|
backgroundColor: colors().dominant,
|
|
backgroundColor: colors().dominant,
|
|
paddingRight: horizontalScale(8),
|
|
paddingRight: horizontalScale(8),
|
|
paddingLeft: horizontalScale(16),
|
|
paddingLeft: horizontalScale(16),
|
|
- alignItems:'center',
|
|
|
|
- justifyContent:'center',
|
|
|
|
- }
|
|
|
|
|
|
+ alignItems: 'center',
|
|
|
|
+ justifyContent: 'center',
|
|
|
|
+ },
|
|
|
|
+ filtersModalContainer: {
|
|
|
|
+ padding: moderateScale(16),
|
|
|
|
+ width: '100%',
|
|
|
|
+ height: '100%',
|
|
|
|
+ // marginHorizontal: horizontalScale(32),
|
|
|
|
+ justifyContent: 'flex-start',
|
|
|
|
+ backgroundColor: colors().dominant,
|
|
|
|
+ },
|
|
|
|
+ filtersHeader: {
|
|
|
|
+ flexDirection: 'row',
|
|
|
|
+ alignItems: 'center',
|
|
|
|
+ justifyContent: 'space-between'
|
|
|
|
+ },
|
|
|
|
+ filterHeading: {
|
|
|
|
+ fontFamily: fonts.type.semibold,
|
|
|
|
+ color: colors().recessive,
|
|
|
|
+ fontSize: moderateScale(20)
|
|
|
|
+ },
|
|
|
|
+ utilContainer: {
|
|
|
|
+ flexDirection: 'row',
|
|
|
|
+ gap: 8,
|
|
|
|
+ alignItems: 'center'
|
|
|
|
+ },
|
|
|
|
+ filterPillContainer:{
|
|
|
|
+ paddingVertical: verticalScale(8)
|
|
|
|
+ },
|
|
|
|
+ filterTitle: {
|
|
|
|
+ fontFamily: fonts.type.semibold,
|
|
|
|
+ color: colors().black,
|
|
|
|
+ fontSize: moderateScale(16),
|
|
|
|
+ paddingVertical: moderateScale(8)
|
|
|
|
+ },
|
|
|
|
+ filterPill: {
|
|
|
|
+ borderRadius: moderateScale(18),
|
|
|
|
+ paddingVertical: verticalScale(8),
|
|
|
|
+ paddingHorizontal: horizontalScale(12),
|
|
|
|
+ backgroundColor: colors().dominant,
|
|
|
|
+ width: 'auto',
|
|
|
|
+ },
|
|
|
|
+ selectedFilterPill: {
|
|
|
|
+ paddingVertical: verticalScale(8),
|
|
|
|
+ paddingHorizontal: horizontalScale(16),
|
|
|
|
+ backgroundColor: colors().primaryColor,
|
|
|
|
+ borderRadius: moderateScale(18),
|
|
|
|
+ width: 'auto',
|
|
|
|
+ },
|
|
|
|
+ selectedPillText: {
|
|
|
|
+ fontFamily: fonts.type.semibold,
|
|
|
|
+ fontSize: moderateScale(12),
|
|
|
|
+ color: colors().white,
|
|
|
|
+ },
|
|
|
|
+ pillText: {
|
|
|
|
+ fontFamily: fonts.type.semibold,
|
|
|
|
+ fontSize: moderateScale(12),
|
|
|
|
+ color: colors().recessive,
|
|
|
|
+ },
|
|
})
|
|
})
|
|
|
|
|
|
|
|
|
|
@@ -87,8 +155,19 @@ const SearchPage = props => {
|
|
.catch(err => console.log(err))
|
|
.catch(err => console.log(err))
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ const fetchFilters = () => {
|
|
|
|
+ getMenus()
|
|
|
|
+ .then(res => {
|
|
|
|
+ let filtersPayload = res.data.body.results
|
|
|
|
+ setFiltersData(prev => ({ ...prev, "Category": filtersPayload.map(item => item.heading.submenu.reduce((current, value) => ({ ...current, [value]: false }), {})) }))
|
|
|
|
+ setFiltersData(prev => ({ ...prev, "Source": filtersPayload.map(item => item.heading.submenu.reduce((current, value) => ({ ...current, [value]: false }), {})) }))
|
|
|
|
+ setFiltersData(prev => ({ ...prev, "Hash Tags": filtersPayload.map(item => item.heading.submenu.reduce((current, value) => ({ ...current, [value]: false }), {})) }))
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+
|
|
useConstructor(() => {
|
|
useConstructor(() => {
|
|
fetchCategories()
|
|
fetchCategories()
|
|
|
|
+ fetchFilters()
|
|
})
|
|
})
|
|
|
|
|
|
const onChangeText = (text) => {
|
|
const onChangeText = (text) => {
|
|
@@ -109,72 +188,143 @@ const SearchPage = props => {
|
|
}
|
|
}
|
|
return (
|
|
return (
|
|
<PaperProvider>
|
|
<PaperProvider>
|
|
- <SafeAreaView style={styles.container}>
|
|
|
|
- <ScrollView>
|
|
|
|
- <NewscoutTitleHeader title={"Search"} />
|
|
|
|
-
|
|
|
|
- <View style={styles.inputTextContainer}>
|
|
|
|
- <TextInput
|
|
|
|
- editable
|
|
|
|
- mode='outlined'
|
|
|
|
- placeholder='Search Text'
|
|
|
|
- placeholderTextColor={colors().grayShade_300}
|
|
|
|
- dense
|
|
|
|
- style={{
|
|
|
|
- backgroundColor: colors().grayShade_500,
|
|
|
|
- paddingVertical: moderateScale(4),
|
|
|
|
- // width: '100%',
|
|
|
|
-
|
|
|
|
- flex: 1
|
|
|
|
-
|
|
|
|
- }}
|
|
|
|
- contentStyle={{
|
|
|
|
- fontSize: moderateScale(16),
|
|
|
|
- fontFamily: fonts.type.medium,
|
|
|
|
- // height: moderateScale(16),
|
|
|
|
- }}
|
|
|
|
- outlineStyle={{
|
|
|
|
- borderColor: colors().dominant_variant,
|
|
|
|
- borderRadius: moderateScale(8),
|
|
|
|
- borderWidth: moderateScale(1),
|
|
|
|
- }}
|
|
|
|
- // underlineStyle={{backgroundColor: colors().dominant}}
|
|
|
|
- left={() => <Text>fdsfdss</Text>}
|
|
|
|
- right={() => <TouchableOpacity onPress={() => navigateToListViewPage(navigation,'search',searchText)}><IonIcon name="search" color={colors().grayShade_200} size={moderateScale(8)} /></TouchableOpacity>}
|
|
|
|
- onChangeText={onChangeText}
|
|
|
|
- />
|
|
|
|
- <TouchableOpacity style={styles.filtersButton} onPress={true}>
|
|
|
|
- <IonIcon name="filter" color={colors().recessive_variant} size={moderateScale(24)} />
|
|
|
|
- </TouchableOpacity>
|
|
|
|
- </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>
|
|
|
|
-
|
|
|
|
- )}
|
|
|
|
|
|
+ <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>
|
|
- : 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}
|
|
|
|
- />
|
|
|
|
|
|
+ <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>
|
|
|
|
+ <ScrollView showsVerticalScrollIndicator={false}>
|
|
|
|
+ {
|
|
|
|
+ // filtersData[currentFilter]
|
|
|
|
+ Object.keys(filtersData).length <= 0 ? <LoadingScreen/>
|
|
|
|
+ : Object.keys(filtersData[currentFilter]).map(item =>
|
|
|
|
+ { console.log(item)
|
|
|
|
+ return (<List.Item
|
|
|
|
+ style={styles.listItem}
|
|
|
|
+ titleStyle={styles.listItemText}
|
|
|
|
+ title={item}
|
|
|
|
+
|
|
|
|
+ right={props => <Checkbox
|
|
|
|
+ status={filtersData[currentFilter][item] === true ? 'checked' : 'unchecked'}
|
|
|
|
+ onPress={() =>
|
|
|
|
+ setFiltersData({...filtersData,[currentFilter]: {...filtersData[currentFilter],[item]: !filtersData[currentFilter][item]}})}
|
|
|
|
+ // setSelectedTopics({...filtersData,[item.heading.name]: !selectedTopics[item.heading.name]})}
|
|
|
|
+ color={colors().secondaryColor}
|
|
|
|
+ />}
|
|
|
|
+
|
|
|
|
+ />)}
|
|
|
|
+ )
|
|
|
|
+ }
|
|
|
|
+ </ScrollView>
|
|
|
|
+ </Modal>
|
|
|
|
+ </Portal>
|
|
|
|
+ <ScrollView>
|
|
|
|
+ <NewscoutTitleHeader title={"Search"} />
|
|
|
|
+
|
|
|
|
+ <View style={styles.inputTextContainer}>
|
|
|
|
+ <TextInput
|
|
|
|
+ editable
|
|
|
|
+ mode='outlined'
|
|
|
|
+ placeholder='Search Text'
|
|
|
|
+ placeholderTextColor={colors().grayShade_300}
|
|
|
|
+ dense
|
|
|
|
+ style={{
|
|
|
|
+ backgroundColor: colors().grayShade_500,
|
|
|
|
+ paddingVertical: moderateScale(4),
|
|
|
|
+ // width: '100%',
|
|
|
|
+
|
|
|
|
+ flex: 1
|
|
|
|
+
|
|
|
|
+ }}
|
|
|
|
+ contentStyle={{
|
|
|
|
+ fontSize: moderateScale(16),
|
|
|
|
+ fontFamily: fonts.type.medium,
|
|
|
|
+ // height: moderateScale(16),
|
|
|
|
+ }}
|
|
|
|
+ outlineStyle={{
|
|
|
|
+ borderColor: colors().dominant_variant,
|
|
|
|
+ borderRadius: moderateScale(8),
|
|
|
|
+ borderWidth: moderateScale(1),
|
|
|
|
+ }}
|
|
|
|
+ // underlineStyle={{backgroundColor: colors().dominant}}
|
|
|
|
+ left={() => <Text>fdsfdss</Text>}
|
|
|
|
+ right={() => <TouchableOpacity onPress={() => navigateToListViewPage(navigation, 'search', searchText)}><IonIcon name="search" color={colors().grayShade_200} size={moderateScale(8)} /></TouchableOpacity>}
|
|
|
|
+ onChangeText={onChangeText}
|
|
|
|
+ />
|
|
|
|
+ <TouchableOpacity style={styles.filtersButton} onPress={showFilters}>
|
|
|
|
+ <IonIcon name="filter" color={colors().recessive_variant} size={moderateScale(24)} />
|
|
|
|
+ </TouchableOpacity>
|
|
|
|
+ </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>
|
|
</View>
|
|
- }
|
|
|
|
- </ScrollView>
|
|
|
|
- </SafeAreaView>
|
|
|
|
|
|
+ : 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>
|
|
|
|
+ }
|
|
|
|
+ </ScrollView>
|
|
|
|
+ </SafeAreaView>
|
|
</PaperProvider>
|
|
</PaperProvider>
|
|
)
|
|
)
|
|
}
|
|
}
|