Categories select + modal
This commit is contained in:
parent
aaedcec4a6
commit
0999ef563a
6 changed files with 210 additions and 40 deletions
|
@ -4,12 +4,14 @@ import {
|
||||||
SafeAreaView,
|
SafeAreaView,
|
||||||
StatusBar,
|
StatusBar,
|
||||||
Image,
|
Image,
|
||||||
TouchableOpacity,
|
TouchableOpacity, View,
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
|
|
||||||
import React, {useState} from 'react';
|
import React, {useState, useEffect, useRef} from 'react';
|
||||||
import {router} from 'expo-router';
|
import {router} from 'expo-router';
|
||||||
|
import type {AutocompleteDropdownRef} from 'react-native-autocomplete-dropdown'
|
||||||
import {AutocompleteDropdown} 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 AsyncStorage from '@react-native-async-storage/async-storage';
|
||||||
|
|
||||||
import {ThemedText} from '@/components/ThemedText';
|
import {ThemedText} from '@/components/ThemedText';
|
||||||
|
@ -21,14 +23,46 @@ import List from '@/components/List';
|
||||||
|
|
||||||
export default function ExploreScreen() {
|
export default function ExploreScreen() {
|
||||||
const colorScheme = useColorScheme() ?? 'light';
|
const colorScheme = useColorScheme() ?? 'light';
|
||||||
|
const [categories, setCategories] = useState([]);
|
||||||
const [types, setTypes] = useState([]);
|
const [types, setTypes] = useState([]);
|
||||||
|
const [activeCategory, setActiveCategory] = useState<any | null>(null);
|
||||||
|
const searchRef = useRef(null);
|
||||||
|
const dropdownController = useRef<AutocompleteDropdownRef | null>(null)
|
||||||
|
|
||||||
// Load waste types
|
useEffect(() => {
|
||||||
Request.get('waste-types').then((responseData) => {
|
// Load categories
|
||||||
const response = responseData.data;
|
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
|
// View item in sub screen
|
||||||
const viewItem = async (item: any) => {
|
const viewItem = async (item: any) => {
|
||||||
|
@ -52,15 +86,22 @@ export default function ExploreScreen() {
|
||||||
<ThemedView style={styles.searchContainer}>
|
<ThemedView style={styles.searchContainer}>
|
||||||
<ThemedText type="defaultSemiBold">Wat wilt u scheiden?</ThemedText>
|
<ThemedText type="defaultSemiBold">Wat wilt u scheiden?</ThemedText>
|
||||||
<AutocompleteDropdown
|
<AutocompleteDropdown
|
||||||
|
ref={searchRef}
|
||||||
|
controller={controller => {
|
||||||
|
dropdownController.current = controller
|
||||||
|
}}
|
||||||
|
textInputProps={{
|
||||||
|
placeholder: 'Wat wilt u scheiden?',
|
||||||
|
autoCorrect: false,
|
||||||
|
autoCapitalize: 'none',
|
||||||
|
}}
|
||||||
clearOnFocus={false}
|
clearOnFocus={false}
|
||||||
closeOnBlur={true}
|
closeOnBlur={false}
|
||||||
closeOnSubmit={false}
|
closeOnSubmit={false}
|
||||||
emptyResultText={'Niks gevonden'}
|
emptyResultText={'Niks gevonden'}
|
||||||
dataSet={[
|
onSelectItem={selectItem}
|
||||||
{id: '1', title: 'Alpha'},
|
dataSet={categories}
|
||||||
{id: '2', title: 'Beta'},
|
showClear={false}
|
||||||
{id: '3', title: 'Gamma'},
|
|
||||||
]}
|
|
||||||
/>
|
/>
|
||||||
</ThemedView>
|
</ThemedView>
|
||||||
|
|
||||||
|
@ -81,6 +122,28 @@ export default function ExploreScreen() {
|
||||||
</ThemedView>
|
</ThemedView>
|
||||||
</ThemedView>
|
</ThemedView>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
|
<Modal isVisible={activeCategory !== null}>
|
||||||
|
<ThemedView style={{...styles.modalView, backgroundColor: Colors[colorScheme].background}}>
|
||||||
|
<ThemedText type="subtitle" style={{marginBottom: 30, textAlign: 'center'}}>{activeCategory?.name}</ThemedText>
|
||||||
|
|
||||||
|
<View style={styles.modalType}>
|
||||||
|
<Image source={require('@/assets/images/paper.png')} style={styles.modalTypeImage}/>
|
||||||
|
<ThemedText>{activeCategory?.type?.name}</ThemedText>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={{alignItems: 'center'}}>
|
||||||
|
<ThemedText type="defaultSemiBold">Opmerking:</ThemedText>
|
||||||
|
<ThemedText>{activeCategory?.description}</ThemedText>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress={() => setActiveCategory(null)}
|
||||||
|
style={{...styles.modalClose, backgroundColor: Colors[colorScheme].tint}}>
|
||||||
|
<ThemedText style={{color: '#fff'}}>Sluiten</ThemedText>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</ThemedView>
|
||||||
|
</Modal>
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -121,5 +184,35 @@ const styles = StyleSheet.create({
|
||||||
height: 30,
|
height: 30,
|
||||||
borderRadius: 5,
|
borderRadius: 5,
|
||||||
marginRight: 8,
|
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,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,7 +5,7 @@ import {
|
||||||
Dimensions
|
Dimensions
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
|
|
||||||
import {useState} from 'react';
|
import {useEffect, useState} from 'react';
|
||||||
import RenderHtml from 'react-native-render-html';
|
import RenderHtml from 'react-native-render-html';
|
||||||
import {useNavigation} from '@react-navigation/native';
|
import {useNavigation} from '@react-navigation/native';
|
||||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||||
|
@ -20,20 +20,22 @@ export default function CategoryScreen() {
|
||||||
const [description, setDescription] = useState('');
|
const [description, setDescription] = useState('');
|
||||||
|
|
||||||
// Load item from storage
|
// Load item from storage
|
||||||
AsyncStorage.getItem('activeCategory').then((data) => {
|
useEffect(() => {
|
||||||
const itemData: any = JSON.parse(data ?? '{}');
|
AsyncStorage.getItem('activeCategory').then((data) => {
|
||||||
|
const itemData: any = JSON.parse(data ?? '{}');
|
||||||
|
|
||||||
if (itemData != null) {
|
if (itemData != null) {
|
||||||
const {name, description} = itemData;
|
const {name, description} = itemData;
|
||||||
|
|
||||||
// Set description
|
// Set description
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
setDescription(description);
|
setDescription(description);
|
||||||
|
|
||||||
// Set page title
|
// Set page title
|
||||||
navigation.setOptions({title: name});
|
navigation.setOptions({title: name});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
// HTML render props
|
// HTML render props
|
||||||
const source = {html: description};
|
const source = {html: description};
|
||||||
|
|
41
package-lock.json
generated
41
package-lock.json
generated
|
@ -35,6 +35,7 @@
|
||||||
"react-native-gesture-handler": "~2.16.1",
|
"react-native-gesture-handler": "~2.16.1",
|
||||||
"react-native-leaflet-view": "^0.1.2",
|
"react-native-leaflet-view": "^0.1.2",
|
||||||
"react-native-maps": "1.14.0",
|
"react-native-maps": "1.14.0",
|
||||||
|
"react-native-modal": "^13.0.1",
|
||||||
"react-native-reanimated": "~3.10.1",
|
"react-native-reanimated": "~3.10.1",
|
||||||
"react-native-render-html": "^6.3.4",
|
"react-native-render-html": "^6.3.4",
|
||||||
"react-native-safe-area-context": "4.10.5",
|
"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": {
|
"node_modules/react-native-reanimated": {
|
||||||
"version": "3.10.1",
|
"version": "3.10.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.10.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.10.1.tgz",
|
||||||
|
@ -30838,6 +30860,25 @@
|
||||||
"@types/geojson": "^7946.0.13"
|
"@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": {
|
"react-native-reanimated": {
|
||||||
"version": "3.10.1",
|
"version": "3.10.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.10.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.10.1.tgz",
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
"react-native-gesture-handler": "~2.16.1",
|
"react-native-gesture-handler": "~2.16.1",
|
||||||
"react-native-leaflet-view": "^0.1.2",
|
"react-native-leaflet-view": "^0.1.2",
|
||||||
"react-native-maps": "1.14.0",
|
"react-native-maps": "1.14.0",
|
||||||
|
"react-native-modal": "^13.0.1",
|
||||||
"react-native-reanimated": "~3.10.1",
|
"react-native-reanimated": "~3.10.1",
|
||||||
"react-native-render-html": "^6.3.4",
|
"react-native-render-html": "^6.3.4",
|
||||||
"react-native-safe-area-context": "4.10.5",
|
"react-native-safe-area-context": "4.10.5",
|
||||||
|
|
|
@ -14,10 +14,16 @@ export class Request {
|
||||||
* @returns {Promise<AxiosResponse<any>>}
|
* @returns {Promise<AxiosResponse<any>>}
|
||||||
*/
|
*/
|
||||||
static get(url: string, headers = {}) {
|
static get(url: string, headers = {}) {
|
||||||
return axios.get(API_URL + url, {
|
return axios
|
||||||
...CONFIG,
|
.get(API_URL + url, {
|
||||||
...headers,
|
...CONFIG,
|
||||||
});
|
...headers,
|
||||||
|
})
|
||||||
|
.then(response => response.data)
|
||||||
|
.catch(error => {
|
||||||
|
// Handle error
|
||||||
|
throw error;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -29,10 +35,16 @@ export class Request {
|
||||||
* @returns {Promise<AxiosResponse<any>>}
|
* @returns {Promise<AxiosResponse<any>>}
|
||||||
*/
|
*/
|
||||||
static post(url: string, body = {}, headers = {}) {
|
static post(url: string, body = {}, headers = {}) {
|
||||||
return axios.post(API_URL + url, body, {
|
return axios
|
||||||
...CONFIG,
|
.post(API_URL + url, body, {
|
||||||
...headers,
|
...CONFIG,
|
||||||
});
|
...headers,
|
||||||
|
})
|
||||||
|
.then(response => response.data)
|
||||||
|
.catch(error => {
|
||||||
|
// Handle error
|
||||||
|
throw error;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -44,10 +56,16 @@ export class Request {
|
||||||
* @returns {Promise<AxiosResponse<any>>}
|
* @returns {Promise<AxiosResponse<any>>}
|
||||||
*/
|
*/
|
||||||
static put(url: string, body = {}, headers = {}) {
|
static put(url: string, body = {}, headers = {}) {
|
||||||
return axios.put(API_URL + url, body, {
|
return axios
|
||||||
...CONFIG,
|
.put(API_URL + url, body, {
|
||||||
...headers,
|
...CONFIG,
|
||||||
});
|
...headers,
|
||||||
|
})
|
||||||
|
.then(response => response.data)
|
||||||
|
.catch(error => {
|
||||||
|
// Handle error
|
||||||
|
throw error;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
19
yarn.lock
19
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"
|
kleur "^3.0.3"
|
||||||
sisteransi "^1.0.5"
|
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"
|
version "15.8.1"
|
||||||
resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz"
|
resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz"
|
||||||
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
|
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
|
||||||
|
@ -7531,6 +7531,13 @@ react-native-animatable@^1.3.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
prop-types "^15.8.1"
|
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:
|
react-native-autocomplete-dropdown@3.1.5:
|
||||||
version "3.1.5"
|
version "3.1.5"
|
||||||
resolved "https://registry.npmjs.org/react-native-autocomplete-dropdown/-/react-native-autocomplete-dropdown-3.1.5.tgz"
|
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:
|
dependencies:
|
||||||
"@types/geojson" "^7946.0.13"
|
"@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:
|
react-native-reanimated@*, react-native-reanimated@~3.10.1:
|
||||||
version "3.10.1"
|
version "3.10.1"
|
||||||
resolved "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.10.1.tgz"
|
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"
|
escape-string-regexp "2.0.0"
|
||||||
invariant "2.2.4"
|
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"
|
version "0.74.3"
|
||||||
resolved "https://registry.npmjs.org/react-native/-/react-native-0.74.3.tgz"
|
resolved "https://registry.npmjs.org/react-native/-/react-native-0.74.3.tgz"
|
||||||
integrity sha512-UFutCC6WEw6HkxlcpQ2BemKqi0JkwrgDchYB5Svi8Sp4Xwt4HA6LGEjNQgZ+3KM44bjyFRpofQym0uh0jACGng==
|
integrity sha512-UFutCC6WEw6HkxlcpQ2BemKqi0JkwrgDchYB5Svi8Sp4Xwt4HA6LGEjNQgZ+3KM44bjyFRpofQym0uh0jACGng==
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue