From 0999ef563a6fcf80f9d806da5b8abda5d7468437 Mon Sep 17 00:00:00 2001 From: Maarten Date: Thu, 1 Aug 2024 14:21:09 +0200 Subject: [PATCH] Categories select + modal --- app/(tabs)/explore.tsx | 121 ++++++++++++++++++++++++++++++++++----- app/explore/category.tsx | 26 +++++---- package-lock.json | 41 +++++++++++++ package.json | 1 + services/request.tsx | 42 ++++++++++---- yarn.lock | 19 +++++- 6 files changed, 210 insertions(+), 40 deletions(-) diff --git a/app/(tabs)/explore.tsx b/app/(tabs)/explore.tsx index 323f607..cf81f5f 100644 --- a/app/(tabs)/explore.tsx +++ b/app/(tabs)/explore.tsx @@ -4,12 +4,14 @@ import { SafeAreaView, StatusBar, Image, - TouchableOpacity, + TouchableOpacity, View, } from 'react-native'; -import React, {useState} from 'react'; +import React, {useState, useEffect, useRef} from 'react'; import {router} from 'expo-router'; +import type {AutocompleteDropdownRef} from 'react-native-autocomplete-dropdown' import {AutocompleteDropdown} from 'react-native-autocomplete-dropdown'; +import Modal from "react-native-modal"; import AsyncStorage from '@react-native-async-storage/async-storage'; import {ThemedText} from '@/components/ThemedText'; @@ -21,14 +23,46 @@ import List from '@/components/List'; export default function ExploreScreen() { const colorScheme = useColorScheme() ?? 'light'; + const [categories, setCategories] = useState([]); const [types, setTypes] = useState([]); + const [activeCategory, setActiveCategory] = useState(null); + const searchRef = useRef(null); + const dropdownController = useRef(null) - // Load waste types - Request.get('waste-types').then((responseData) => { - const response = responseData.data; + useEffect(() => { + // Load categories + Request.get('categories').then((response) => { + const list: any = []; - setTypes(response); - }); + response.forEach((category: any, index: any) => { + list.push({ + id: index, + title: category.name, + category: category, + }) + }); + + setCategories(list); + }) + + // Load waste types + Request.get('waste-types').then((response) => { + setTypes(response); + }); + }, []); + + // View selected item in modal + const selectItem = (item: any | null) => { + if (item == null) { + return; + } + + // Clear select + dropdownController.current?.clear() + + const {category} = item; + setActiveCategory(category); + } // View item in sub screen const viewItem = async (item: any) => { @@ -52,15 +86,22 @@ export default function ExploreScreen() { Wat wilt u scheiden? { + dropdownController.current = controller + }} + textInputProps={{ + placeholder: 'Wat wilt u scheiden?', + autoCorrect: false, + autoCapitalize: 'none', + }} clearOnFocus={false} - closeOnBlur={true} + closeOnBlur={false} closeOnSubmit={false} emptyResultText={'Niks gevonden'} - dataSet={[ - {id: '1', title: 'Alpha'}, - {id: '2', title: 'Beta'}, - {id: '3', title: 'Gamma'}, - ]} + onSelectItem={selectItem} + dataSet={categories} + showClear={false} /> @@ -81,6 +122,28 @@ export default function ExploreScreen() { + + + + {activeCategory?.name} + + + + {activeCategory?.type?.name} + + + + Opmerking: + {activeCategory?.description} + + + setActiveCategory(null)} + style={{...styles.modalClose, backgroundColor: Colors[colorScheme].tint}}> + Sluiten + + + ); } @@ -121,5 +184,35 @@ const styles = StyleSheet.create({ height: 30, borderRadius: 5, marginRight: 8, - } + }, + modalView: { + margin: 20, + borderRadius: 5, + padding: 35, + alignItems: 'center', + textAlign: 'center', + }, + modalType: { + flex: 1, + display: 'flex', + gap: 8, + flexDirection: 'row', + alignItems: 'center', + paddingBottom: 10, + marginBottom: 30, + }, + modalTypeImage: { + width: 40, + height: 40, + borderRadius: 5, + marginRight: 8, + }, + modalClose: { + borderRadius: 5, + paddingTop: 10, + paddingBottom: 10, + paddingLeft: 40, + paddingRight: 40, + marginTop: 30, + }, }); diff --git a/app/explore/category.tsx b/app/explore/category.tsx index fdafc93..3c2cd2d 100644 --- a/app/explore/category.tsx +++ b/app/explore/category.tsx @@ -5,7 +5,7 @@ import { Dimensions } from 'react-native'; -import {useState} from 'react'; +import {useEffect, useState} from 'react'; import RenderHtml from 'react-native-render-html'; import {useNavigation} from '@react-navigation/native'; import AsyncStorage from '@react-native-async-storage/async-storage'; @@ -20,20 +20,22 @@ export default function CategoryScreen() { const [description, setDescription] = useState(''); // Load item from storage - AsyncStorage.getItem('activeCategory').then((data) => { - const itemData: any = JSON.parse(data ?? '{}'); + useEffect(() => { + AsyncStorage.getItem('activeCategory').then((data) => { + const itemData: any = JSON.parse(data ?? '{}'); - if (itemData != null) { - const {name, description} = itemData; + if (itemData != null) { + const {name, description} = itemData; - // Set description - // @ts-ignore - setDescription(description); + // Set description + // @ts-ignore + setDescription(description); - // Set page title - navigation.setOptions({title: name}); - } - }); + // Set page title + navigation.setOptions({title: name}); + } + }); + }, []); // HTML render props const source = {html: description}; diff --git a/package-lock.json b/package-lock.json index 64ebaaa..f0ae1b3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,6 +35,7 @@ "react-native-gesture-handler": "~2.16.1", "react-native-leaflet-view": "^0.1.2", "react-native-maps": "1.14.0", + "react-native-modal": "^13.0.1", "react-native-reanimated": "~3.10.1", "react-native-render-html": "^6.3.4", "react-native-safe-area-context": "4.10.5", @@ -16272,6 +16273,27 @@ } } }, + "node_modules/react-native-modal": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/react-native-modal/-/react-native-modal-13.0.1.tgz", + "integrity": "sha512-UB+mjmUtf+miaG/sDhOikRfBOv0gJdBU2ZE1HtFWp6UixW9jCk/bhGdHUgmZljbPpp0RaO/6YiMmQSSK3kkMaw==", + "dependencies": { + "prop-types": "^15.6.2", + "react-native-animatable": "1.3.3" + }, + "peerDependencies": { + "react": "*", + "react-native": ">=0.65.0" + } + }, + "node_modules/react-native-modal/node_modules/react-native-animatable": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/react-native-animatable/-/react-native-animatable-1.3.3.tgz", + "integrity": "sha512-2ckIxZQAsvWn25Ho+DK3d1mXIgj7tITkrS4pYDvx96WyOttSvzzFeQnM2od0+FUMzILbdHDsDEqZvnz1DYNQ1w==", + "dependencies": { + "prop-types": "^15.7.2" + } + }, "node_modules/react-native-reanimated": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.10.1.tgz", @@ -30838,6 +30860,25 @@ "@types/geojson": "^7946.0.13" } }, + "react-native-modal": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/react-native-modal/-/react-native-modal-13.0.1.tgz", + "integrity": "sha512-UB+mjmUtf+miaG/sDhOikRfBOv0gJdBU2ZE1HtFWp6UixW9jCk/bhGdHUgmZljbPpp0RaO/6YiMmQSSK3kkMaw==", + "requires": { + "prop-types": "^15.6.2", + "react-native-animatable": "1.3.3" + }, + "dependencies": { + "react-native-animatable": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/react-native-animatable/-/react-native-animatable-1.3.3.tgz", + "integrity": "sha512-2ckIxZQAsvWn25Ho+DK3d1mXIgj7tITkrS4pYDvx96WyOttSvzzFeQnM2od0+FUMzILbdHDsDEqZvnz1DYNQ1w==", + "requires": { + "prop-types": "^15.7.2" + } + } + } + }, "react-native-reanimated": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.10.1.tgz", diff --git a/package.json b/package.json index 428fc1b..c4970ef 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "react-native-gesture-handler": "~2.16.1", "react-native-leaflet-view": "^0.1.2", "react-native-maps": "1.14.0", + "react-native-modal": "^13.0.1", "react-native-reanimated": "~3.10.1", "react-native-render-html": "^6.3.4", "react-native-safe-area-context": "4.10.5", diff --git a/services/request.tsx b/services/request.tsx index d29b152..300670a 100644 --- a/services/request.tsx +++ b/services/request.tsx @@ -14,10 +14,16 @@ export class Request { * @returns {Promise>} */ static get(url: string, headers = {}) { - return axios.get(API_URL + url, { - ...CONFIG, - ...headers, - }); + return axios + .get(API_URL + url, { + ...CONFIG, + ...headers, + }) + .then(response => response.data) + .catch(error => { + // Handle error + throw error; + }); } /** @@ -29,10 +35,16 @@ export class Request { * @returns {Promise>} */ static post(url: string, body = {}, headers = {}) { - return axios.post(API_URL + url, body, { - ...CONFIG, - ...headers, - }); + return axios + .post(API_URL + url, body, { + ...CONFIG, + ...headers, + }) + .then(response => response.data) + .catch(error => { + // Handle error + throw error; + }); } /** @@ -44,10 +56,16 @@ export class Request { * @returns {Promise>} */ static put(url: string, body = {}, headers = {}) { - return axios.put(API_URL + url, body, { - ...CONFIG, - ...headers, - }); + return axios + .put(API_URL + url, body, { + ...CONFIG, + ...headers, + }) + .then(response => response.data) + .catch(error => { + // Handle error + throw error; + }); } } diff --git a/yarn.lock b/yarn.lock index 30ece20..ae6c607 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7377,7 +7377,7 @@ prompts@^2.0.1, prompts@^2.2.1, prompts@^2.3.2, prompts@^2.4.2: kleur "^3.0.3" sisteransi "^1.0.5" -prop-types@^15.5.7, prop-types@^15.6.0, prop-types@^15.7.2, prop-types@^15.8.1: +prop-types@^15.5.7, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -7531,6 +7531,13 @@ react-native-animatable@^1.3.3: dependencies: prop-types "^15.8.1" +react-native-animatable@1.3.3: + version "1.3.3" + resolved "https://registry.npmjs.org/react-native-animatable/-/react-native-animatable-1.3.3.tgz" + integrity sha512-2ckIxZQAsvWn25Ho+DK3d1mXIgj7tITkrS4pYDvx96WyOttSvzzFeQnM2od0+FUMzILbdHDsDEqZvnz1DYNQ1w== + dependencies: + prop-types "^15.7.2" + react-native-autocomplete-dropdown@3.1.5: version "3.1.5" resolved "https://registry.npmjs.org/react-native-autocomplete-dropdown/-/react-native-autocomplete-dropdown-3.1.5.tgz" @@ -7587,6 +7594,14 @@ react-native-maps@*, react-native-maps@1.14.0: dependencies: "@types/geojson" "^7946.0.13" +react-native-modal@^13.0.1: + version "13.0.1" + resolved "https://registry.npmjs.org/react-native-modal/-/react-native-modal-13.0.1.tgz" + integrity sha512-UB+mjmUtf+miaG/sDhOikRfBOv0gJdBU2ZE1HtFWp6UixW9jCk/bhGdHUgmZljbPpp0RaO/6YiMmQSSK3kkMaw== + dependencies: + prop-types "^15.6.2" + react-native-animatable "1.3.3" + react-native-reanimated@*, react-native-reanimated@~3.10.1: version "3.10.1" resolved "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.10.1.tgz" @@ -7665,7 +7680,7 @@ react-native-webview@^13.10.5: escape-string-regexp "2.0.0" invariant "2.2.4" -react-native@*, react-native@^*, "react-native@^0.0.0-0 || >=0.60 <1.0", "react-native@>= 0.30.0", "react-native@>= 0.64.3", react-native@>=0.46, react-native@>=0.60.0, react-native@0.74.3: +react-native@*, react-native@^*, "react-native@^0.0.0-0 || >=0.60 <1.0", "react-native@>= 0.30.0", "react-native@>= 0.64.3", react-native@>=0.46, react-native@>=0.60.0, react-native@>=0.65.0, react-native@0.74.3: version "0.74.3" resolved "https://registry.npmjs.org/react-native/-/react-native-0.74.3.tgz" integrity sha512-UFutCC6WEw6HkxlcpQ2BemKqi0JkwrgDchYB5Svi8Sp4Xwt4HA6LGEjNQgZ+3KM44bjyFRpofQym0uh0jACGng==