Skip to content

Commit

Permalink
internationalization and configurable options wip
Browse files Browse the repository at this point in the history
  • Loading branch information
roncodes committed Nov 29, 2021
1 parent f263e86 commit e355acd
Show file tree
Hide file tree
Showing 11 changed files with 717 additions and 42 deletions.
61 changes: 61 additions & 0 deletions config/defaults.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* ----------------------------------------------------------
* Storefront App Default Configurations
* ----------------------------------------------------------
*
* Overwritable configurations.
*
* !!! Do not touch this file unless you know what you're doing.
*
* @type {object}
*/
const DefaultConfig = {
InterfaceConfig: {
storefront: {
defaultHeaderComponent: 'ui/headers/StorefrontHeader',
},

network: {
defaultHeaderComponent: 'ui/headers/NetworkHeader',
exploreScreen: {
defaultCategoryComponent: 'ui/NetworkCategoryBlock',
defaultCategoryComponentProps: {
containerStyle: {},
},
},
},
},
};

const configure = (target, ...sources) => {
const isObject = (item) => item && typeof item === 'object' && !Array.isArray(item);

if (typeof target === 'string') {
target = DefaultConfig[target];
}

if (!sources.length) {
return target;
}

const source = sources.shift();

if (isObject(target) && isObject(source)) {
for (const key in source) {
if (isObject(source[key])) {
if (!target[key]) {
Object.assign(target, { [key]: {} });
}

configure(target[key], source[key]);
} else {
Object.assign(target, { [key]: source[key] });
}
}
}

return configure(target, ...sources);
};

export { configure };
export default DefaultConfig;
15 changes: 5 additions & 10 deletions src/config/interface.js → config/interface.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import DefaultConfig, { configure } from './defaults';
import { tailwind } from '../src/tailwind';

/**
* ----------------------------------------------------------
* Storefront App Interface Configuration
Expand All @@ -9,14 +12,6 @@
*
* @type {object}
*/
const InterfaceConfig = {
storefront: {
defaultHeaderComponent: 'ui/headers/StorefrontHeader'
},

network: {
defaultHeaderComponent: 'ui/headers/NetworkHeader'
}
};
const InterfaceConfig = configure('InterfaceConfig', {});

export default InterfaceConfig;
export default InterfaceConfig;
6 changes: 6 additions & 0 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,8 @@ PODS:
- React-Core
- RNGestureHandler (1.10.3):
- React-Core
- RNLocalize (2.1.5):
- React-Core
- RNPermissions (3.0.5):
- React-Core
- RNReanimated (2.2.2):
Expand Down Expand Up @@ -418,6 +420,7 @@ DEPENDENCIES:
- "RNCPushNotificationIOS (from `../node_modules/@react-native-community/push-notification-ios`)"
- RNDeviceInfo (from `../node_modules/react-native-device-info`)
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
- RNLocalize (from `../node_modules/react-native-localize`)
- RNPermissions (from `../node_modules/react-native-permissions`)
- RNReanimated (from `../node_modules/react-native-reanimated`)
- RNScreens (from `../node_modules/react-native-screens`)
Expand Down Expand Up @@ -520,6 +523,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native-device-info"
RNGestureHandler:
:path: "../node_modules/react-native-gesture-handler"
RNLocalize:
:path: "../node_modules/react-native-localize"
RNPermissions:
:path: "../node_modules/react-native-permissions"
RNReanimated:
Expand Down Expand Up @@ -581,6 +586,7 @@ SPEC CHECKSUMS:
RNCPushNotificationIOS: 87b8d16d3ede4532745e05b03c42cff33a36cc45
RNDeviceInfo: cc7de0772378f85d8f36ae439df20f05c590a651
RNGestureHandler: a479ebd5ed4221a810967000735517df0d2db211
RNLocalize: 74b82db20cc3895ccc25af992c644879bcec2815
RNPermissions: 7043bacbf928eae25808275cfe73799b8f618911
RNReanimated: 241c586663f44f19a53883c63375fdd041253960
RNScreens: 6e1ea5787989f92b0671049b808aef64fa1ef98c
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"autoprefixer": "^10.2.6",
"axios": "^0.21.1",
"countries-list": "^2.6.1",
"i18n-js": "^3.8.0",
"postcss": "^8.3.5",
"react": "17.0.1",
"react-native": "0.64.2",
Expand All @@ -38,6 +39,7 @@
"react-native-geolocation-service": "^5.3.0-beta.1",
"react-native-gesture-handler": "^1.10.3",
"react-native-google-places-autocomplete": "^2.2.0",
"react-native-localize": "^2.1.5",
"react-native-maps": "0.28.0",
"react-native-mmkv-storage": "^0.6.3",
"react-native-modal": "^12.0.2",
Expand Down
2 changes: 1 addition & 1 deletion src/config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Environment from 'react-native-config';
import InterfaceConfig from 'config/interface';
import InterfaceConfig from '../config/interface';

/**
* ----------------------------------------------------------
Expand Down
4 changes: 3 additions & 1 deletion src/features/Network/screens/ExploreScreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Store, Category } from '@fleetbase/storefront';
import useStorefront, { adapter as StorefrontAdapter } from 'hooks/use-storefront';
import { NetworkInfoService } from 'services';
import { useResourceCollection } from 'utils/Storage';
import { config } from 'utils';
import NetworkHeader from 'ui/headers/NetworkHeader';
import NetworkCategoryBlock from 'ui/NetworkCategoryBlock';
import tailwind from 'tailwind';
Expand All @@ -26,6 +27,7 @@ const ExploreScreen = ({ navigation, route }) => {
};

const transitionToCategory = (category, actionSheet) => {
console.log('[ transitionToCategory() ]', category)
navigation.navigate('NetworkCategoryScreen', { data: category.serialize() });
actionSheet?.setModalVisible(false);
};
Expand All @@ -43,7 +45,7 @@ const ExploreScreen = ({ navigation, route }) => {
<ScrollView showsVerticalScrollIndicator={false} style={tailwind('w-full h-full')}>
<View style={tailwind('py-2')}>
<View style={tailwind('py-2 px-4')}>
<NetworkCategoryBlock containerStyle={tailwind('mb-2 p-2')} onCategoriesLoaded={setNetworkCategories} onPress={transitionToCategory} />
<NetworkCategoryBlock containerStyle={tailwind('mb-2 p-2')} onCategoriesLoaded={setNetworkCategories} onPress={transitionToCategory} {...config('ui.network.exploreScreen.defaultCategoryComponentProps')} />
</View>

{stores.map((store) => (
Expand Down
101 changes: 81 additions & 20 deletions src/interface/NetworkCategoryBlock.js
Original file line number Diff line number Diff line change
@@ -1,39 +1,49 @@
import React, { useState, useEffect, useRef } from 'react';
import { ScrollView, View, Text, TouchableOpacity, TextInput, Image } from 'react-native';
import React, { useState, useEffect, useRef, createRef } from 'react';
import { ScrollView, View, Text, TouchableOpacity, TextInput, Image, Dimensions } from 'react-native';
import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome';
import { faFolder } from '@fortawesome/free-solid-svg-icons';
import { faFolder, faTimes, faEllipsisH } from '@fortawesome/free-solid-svg-icons';
import { Collection } from '@fleetbase/sdk';
import { Category } from '@fleetbase/storefront';
import { useNavigation } from '@react-navigation/native';
import useStorefront, { adapter as StorefrontAdapter } from 'hooks/use-storefront';
import { formatCurrency, logError } from 'utils';
import { useResourceCollection } from 'utils/Storage';
import ActionSheet from 'react-native-actions-sheet';
import tailwind from 'tailwind';

const windowHeight = Dimensions.get('window').height;
const dialogHeight = windowHeight / 1.12;

const NetworkCategoryBlock = (props) => {
const navigation = useNavigation();
const storefront = useStorefront();
const actionSheetRef = createRef();

const [networkCategories, setNetworkCategories] = useResourceCollection('category', Category, StorefrontAdapter, new Collection());
const [isLoading, setIsLoading] = useState(true);

const onPress = (category) => {
if (typeof props?.onPress === 'function') {
props.onPress(category);
const on = (action = 'press', ...params) => {
const capitalize = ([first, ...rest]) => first.toUpperCase() + rest.join('');
const actionName = `on${capitalize(action)}`;
const fn = props[actionName];

if (actionName === 'onPressMore') {
actionSheetRef.current?.setModalVisible();
}

if (typeof fn === 'function') {
fn(...params);
}
}

useEffect(() => {
setIsLoading(true);

storefront.categories
.findAll()
.query({ parents_only: true })
.then((categories) => {
setNetworkCategories(categories);

if (typeof props?.onCategoriesLoaded === 'function') {
props.onCategoriesLoaded(categories);
}
on('categoriesLoaded', categories);
})
.catch(logError)
.finally(() => {
Expand All @@ -42,23 +52,74 @@ const NetworkCategoryBlock = (props) => {
}, []);

if (!networkCategories || networkCategories?.length === 0) {
return <View />
return <View />;
}

const categories = networkCategories?.length > 7 ? networkCategories.slice(0, 7) : networkCategories;

return (
<View style={[props.containerStyle ?? {}, tailwind('rounded-md border border-gray-200 p-4 drop-shadow-lg')]}>
<View style={tailwind('flex flex-row flex-wrap justify-evenly w-full -mb-5')}>
{networkCategories.map((category) => (
<TouchableOpacity key={category.id} onPress={() => onPress(category)} style={tailwind('w-1/4 flex items-center justify-center mb-5')}>
<View style={tailwind('flex items-center justify-center mb-2')}>
<View style={tailwind('rounded-full flex items-center justify-center w-12 h-12 bg-blue-50')}>
<FontAwesomeIcon icon={faFolder} size={23} style={tailwind('text-blue-900')} />
<View style={[tailwind('rounded-md border border-gray-200 drop-shadow-lg'), props.containerStyle]}>
<View style={tailwind('flex flex-row flex-wrap justify-evenly w-full')}>
{categories.map((category) => (
<TouchableOpacity key={category.id} onPress={() => on('press', category)} style={[tailwind('w-1/4 flex items-center text-center mb-3'), props.categoryStyle]}>
<View style={[tailwind('flex items-center justify-center mb-1 h-16 w-20'), props.iconContainerStyle]}>
<View style={[tailwind('rounded-full flex items-center justify-center w-12 h-12 bg-blue-50'), props.iconWrapperStyle]}>
<FontAwesomeIcon icon={faFolder} size={23} style={[tailwind('text-blue-900'), props.iconStyle]} />
</View>
</View>
<Text style={tailwind('font-semibold')}>{category.getAttribute('name')}</Text>
<Text style={[tailwind('font-semibold flex items-center justify-center text-center w-20'), props.labelStyle]} numberOfLines={2}>
{category.getAttribute('name')}
</Text>
</TouchableOpacity>
))}
{networkCategories.length > 7 && (
<TouchableOpacity onPress={() => on('pressMore')} style={[tailwind('w-1/4 flex items-center mb-3'), props.categoryStyle]}>
<View style={[tailwind('flex items-center justify-center mb-1 h-18 w-20'), props.iconContainerStyle]}>
<View style={[tailwind('rounded-full flex items-center justify-center w-12 h-12 bg-blue-50'), props.iconWrapperStyle, props.moreIconWrapperStyle]}>
<FontAwesomeIcon icon={faEllipsisH} size={23} style={[tailwind('text-blue-900'), props.iconStyle, props.moreIconStyle]} />
</View>
</View>
<Text style={[tailwind('font-semibold flex items-center justify-center text-center w-20'), props.labelStyle]} numberOfLines={2}>
More
</Text>
</TouchableOpacity>
)}
</View>
<ActionSheet
containerStyle={[{ height: dialogHeight }]}
gestureEnabled={true}
bounceOnOpen={true}
nestedScrollEnabled={true}
onMomentumScrollEnd={() => actionSheetRef.current?.handleChildScrollEnd()}
ref={actionSheetRef}
>
<View>
<View style={tailwind('px-5 py-2 flex flex-row items-center justify-between mb-2')}>
<View style={tailwind('flex flex-row items-center')}>
<FontAwesomeIcon icon={faFolder} style={[tailwind(`text-gray-900 mr-2`), props.buttonIconStyle]} />
<Text style={tailwind('text-lg font-semibold')}>Categories</Text>
</View>

<View>
<TouchableOpacity onPress={() => actionSheetRef.current?.hide()}>
<View style={tailwind('rounded-full bg-red-50 w-8 h-8 flex items-center justify-center')}>
<FontAwesomeIcon icon={faTimes} style={tailwind('text-red-900')} />
</View>
</TouchableOpacity>
</View>
</View>
<ScrollView showsHorizontalScrollIndicator={false} showsVerticalScrollIndicator={false}>
{networkCategories.map((category, index) => (
<TouchableOpacity key={index} onPress={() => on('press', category, actionSheetRef?.current)}>
<View style={tailwind('px-5 py-4 border-b border-gray-100')}>
<Text style={tailwind('font-semibold')}>{category.getAttribute('name')}</Text>
</View>
</TouchableOpacity>
))}
<View style={tailwind('w-full h-40')}></View>
</ScrollView>
</View>
</ActionSheet>
</View>
);
};
Expand Down
Loading

0 comments on commit e355acd

Please sign in to comment.