Procházet zdrojové kódy

Refactored Search Page

Savio Fernando před 11 měsíci
rodič
revize
20ade7e112

+ 89 - 0
src/components/organisms/Sections/CategorySearchSection.js

@@ -0,0 +1,89 @@
+import { Image, StyleSheet, Text, TouchableOpacity, View } from 'react-native'
+import React, { useState } from 'react'
+import { useConstructor } from '../../../utils/functions'
+import { getCategories } from '../../../api/data'
+import fonts from '../../../constants/fonts'
+import colors from '../../../constants/colors'
+import { horizontalScale, moderateScale, verticalScale } from '../../../constants/metrics'
+import { BASE_URL } from '../../../api/urls'
+import LoadingScreen from './LoadingScreen'
+
+const CategorySearchSection = props => {
+
+    const {
+        navigation,
+        route
+    } = props
+
+    const [categories, setCategories] = useState(null)
+
+    const fetchCategories = () => {
+        getCategories().then(res => setCategories(res.data.body.results)).catch(err => console.log(err))
+    }
+
+    useConstructor(() => {
+        fetchCategories()
+    })
+
+    const styles = StyleSheet.create({
+        sectionHeader: {
+            fontFamily: fonts.type.semibold,
+            color: colors().recessive,
+            paddingHorizontal: horizontalScale(16),
+
+
+        },
+        categoryContainer: {
+            padding: verticalScale(16),
+            flexDirection: 'row',
+            flexWrap: 'wrap',
+            gap: moderateScale(16),
+        },
+        category: {
+            height: verticalScale(110),
+            width: 170,
+            backgroundColor: colors().secondaryColor,
+            borderRadius: moderateScale(8),
+            padding: moderateScale(10),
+            alignItems: 'center',
+            justifyContent: 'center',
+            gap: verticalScale(16)
+        },
+        categoryIcon: {
+            height: moderateScale(36),
+            width: moderateScale(36),
+            tintColor: colors().white
+        },
+        categoryText: {
+            fontFamily: fonts.type.semibold,
+            color: colors().white,
+            fontSize: moderateScale(14),
+            textAlign: 'right'
+        },
+    })
+
+    return (
+        <View>
+            <Text style={styles.sectionHeader}>Browse by Categories</Text>
+            <View style={styles.categoryContainer}>
+                {
+                    categories !== null ?
+                        categories.length > 0 ?
+                            categories.map((item) =>
+                                <TouchableOpacity onPress={() => navigateToListViewPage(navigation, "category", item.heading.name)}>
+                                    <View style={styles.category}>
+                                        <Image source={{ uri: BASE_URL + "/" + item.heading.icon }} style={styles.categoryIcon} />
+                                        <Text style={styles.categoryText}>{item.heading.name}</Text>
+                                    </View>
+                                </TouchableOpacity>
+
+                            ) : <></>
+                        : <LoadingScreen containerHeight={verticalScale(240)}/>
+                }
+
+            </View>
+        </View>
+    )
+}
+
+export default CategorySearchSection

+ 70 - 0
src/components/organisms/Sections/RecentSearchesSection.js

@@ -0,0 +1,70 @@
+import { StyleSheet, Text, TouchableOpacity, View } from 'react-native'
+import React, { useState } from 'react'
+import { horizontalScale, moderateScale, verticalScale } from '../../../constants/metrics'
+import colors from '../../../constants/colors'
+import fonts from '../../../constants/fonts'
+import { useConstructor } from '../../../utils/functions'
+import { getTrendingNews } from '../../../api/data'
+import { PAGINATE_BY } from '../../../api/urls'
+import { List } from 'react-native-paper'
+import IonIcon from 'react-native-vector-icons/Ionicons'
+import LoadingScreen from './LoadingScreen'
+
+const RecentSearchesSection = props => {
+
+    const [recentSearches, setRecentSearches] = useState(null)
+
+    const {
+        navigation,
+        route
+    } = props
+
+    const getRecentSearches = () => {
+        getTrendingNews().then(res => setRecentSearches(res.data.body.results.slice(0, PAGINATE_BY))).catch(err => console.error(err))
+    }
+
+    useConstructor(() => {
+        getRecentSearches()
+    })
+
+    const styles = StyleSheet.create({
+        sectionHeader: {
+            fontFamily: fonts.type.semibold,
+            color: colors().recessive,
+            paddingHorizontal: horizontalScale(16),
+        },
+        categoryContainer: {
+            padding: verticalScale(16),
+            flexDirection: 'row',
+            flexWrap: 'wrap',
+            gap: moderateScale(16),
+        },
+    })
+
+    return (
+        <View>
+            <Text style={styles.sectionHeader}>Recent Searches</Text>
+            <View style={[styles.categoryContainer, { gap: 0 }]}>
+                {
+                    recentSearches !== null ?
+                        recentSearches.length > 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)} />}
+
+                                    />
+                                </TouchableOpacity>
+                            }) : <></> : <LoadingScreen containerHeight={verticalScale(240)}/>
+                }
+            </View>
+        </View>
+    )
+}
+
+export default RecentSearchesSection
+

+ 7 - 202
src/screens/Search/SearchPage.js

@@ -1,4 +1,4 @@
-import { FlatList, ScrollView, StyleSheet, Text, TouchableOpacity, TouchableWithoutFeedback, View } from 'react-native'
+import { FlatList, Image, ScrollView, StyleSheet, Text, TouchableOpacity, TouchableWithoutFeedback, View } from 'react-native'
 import React, { useEffect, useState } from 'react'
 import { SafeAreaView } from 'react-native-safe-area-context'
 import NewscoutTitleHeader from '../../components/molecules/Header/NewscoutTitleHeader'
@@ -10,9 +10,11 @@ import fonts from '../../constants/fonts'
 import { navigateToArticle, navigateToListViewPage, useConstructor } from '../../utils/functions'
 import { getArticlesBySearch, getCategories, getMenus, getTrendingNews } from '../../api/data'
 import LoadingScreen from '../../components/organisms/Sections/LoadingScreen'
-import { PAGINATE_BY } from '../../api/urls'
+import { BASE_URL, PAGINATE_BY } from '../../api/urls'
 import HorizontalNewsCardVariant from '../../components/molecules/Cards/HorizontalNewsCardVariant'
 import ThemedTextButton from '../../components/molecules/Buttons/ThemeTextButton'
+import CategorySearchSection from '../../components/organisms/Sections/CategorySearchSection'
+import RecentSearchesSection from '../../components/organisms/Sections/RecentSearchesSection'
 
 const SearchPage = props => {
 
@@ -22,17 +24,14 @@ const SearchPage = props => {
   } = props
 
   const [isSearching, setSearching] = useState(false)
-  const [categories, setCategories] = useState([])
   const [searchText, setSearchText] = useState("")
 
   const [suggestedNews, setSuggestedNews] = useState([])
 
-  const [filtersData, setFiltersData] = useState({})
-  const [currentFilter, setCurrentFilter] = useState("Category")
 
   const [recentSearches, setRecentSearches] = useState([])
 
-  const [pagesLoaded, setPagesLoaded] = useState(1)
+
   // * Filters Modal
   const [isFiltersVisible, setFiltersVisible] = useState(false);
   const showFilters = () => setFiltersVisible(true);
@@ -50,104 +49,13 @@ const SearchPage = props => {
       paddingVertical: verticalScale(16),
       flexDirection: 'row',
       alignItems: 'center',
-      // gap: horizontalScale(16),
       maxWidth: '100%'
     },
-    categoryContainer: {
-      padding: verticalScale(16),
-      flexDirection: 'row',
-      flexWrap: 'wrap',
-      gap: moderateScale(16),
-
-
-    },
-    category: {
-      height: 170,
-      width: 170,
-      backgroundColor: colors().secondaryColor,
-      borderRadius: moderateScale(8),
-      padding: moderateScale(11),
-      justifyContent: 'flex-end',
-    },
-    categoryText: {
-      fontFamily: fonts.type.semibold,
-      alignSelf: 'flex-end',
-      color: colors().white,
-      fontSize: moderateScale(14),
-      maxWidth: "80%",
-      textAlign: 'right'
-    },
-    filtersButton: {
-      backgroundColor: colors().dominant,
-      paddingRight: horizontalScale(8),
-      paddingLeft: horizontalScale(16),
-      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(8),
-      // backgroundColor: colors().primaryColor,
-      borderRadius: 0,
-      width: 'auto',
-      borderColor: colors().primaryColor,
-      borderBottomWidth: 3
-    },
-    selectedPillText: {
-      fontFamily: fonts.type.bold,
-      fontSize: moderateScale(14),
-      color: colors().recessive,
-    },
-    pillText: {
-      fontFamily: fonts.type.semibold,
-      fontSize: moderateScale(12),
-      color: colors().recessive,
-    },
-    filterCheckboxes: {
-      alignItems: 'flex-start',
-      flexDirection: 'column',
-      gap: moderateScale(8),
-
-    },
     listItemText: {
       fontFamily: fonts.type.medium,
       fontSize: moderateScale(14),
@@ -158,39 +66,6 @@ const SearchPage = props => {
     }
   })
 
-
-  const fetchCategories = () => {
-    getCategories().then(res => setCategories(res.data.body.results)).catch(err => console.log(err))
-  }
-
-  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))
-  }
-
-  const fetchFilters = () => {
-    getMenus()
-      .then(res => {
-        let filtersPayload = res.data.body.results
-        //Reduce Submenus into a object
-        setFiltersData(prev => ({ ...prev, "Category": filtersPayload.flatMap(item => item.heading.submenu.map(category => category.name)).reduce((current, value) => ({ ...current, [value]: false }), {}) }))
-        setFiltersData(prev => ({ ...prev, "Source": filtersPayload.flatMap(item => item.heading.submenu.map(category => category.name)).reduce((current, value) => ({ ...current, [value]: false }), {}) }))
-        setFiltersData(prev => ({ ...prev, "Hash Tags": filtersPayload.flatMap(item => item.heading.submenu.map(category => category.hash_tags.map(tag => tag.name))).reduce((current, value) => ({ ...current, [value]: false }), {}) }))
-
-      })
-  }
-
-  const getRecentSearches = () => {
-    getTrendingNews().then(res => setRecentSearches(res.data.body.results.slice(0, PAGINATE_BY))).catch(err => console.error(err))
-  }
-
-  useConstructor(() => {
-    fetchCategories()
-    fetchFilters()
-    getRecentSearches()
-  })
-
   const onChangeText = text => {
     if (text.length <= 0) {
       setSuggestedNews([])
@@ -204,45 +79,10 @@ const SearchPage = props => {
     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 (
     <PaperProvider>
       <SafeAreaView style={styles.container}>
-
         <ScrollView>
-          {/* <NewscoutTitleHeader title={"Search"} /> */}
-
           <View style={styles.inputTextContainer}>
             <TextInput
               returnKeyType='search'
@@ -267,48 +107,13 @@ const SearchPage = props => {
                 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}
               onSubmitEditing={onSearch}
             />
           </View>
-
-          <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)} />}
-
-                    />
-                  </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>
-
-
-
+          <RecentSearchesSection navigation={navigation} route={route} />
+          <CategorySearchSection navigation={navigation} route={route} />
         </ScrollView>
       </SafeAreaView>
     </PaperProvider>