[UI] merchant registration

This commit is contained in:
Andi Firwansyah 2022-12-03 23:19:15 +07:00
parent bbe30a67eb
commit bdca218c7f
25 changed files with 516 additions and 6 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

View File

@ -1,10 +1,12 @@
import React from 'react'; import React from 'react';
import {View, Text, TouchableOpacity} from 'react-native'; import {View, Text, TouchableOpacity} from 'react-native';
import {Icon} from 'components'; import {Icon} from 'components';
import {useTranslation} from 'react-i18next';
import styles from './styles'; import styles from './styles';
const Header = props => { const Header = props => {
const {navigation, smTitle, lgTitle, subTitle} = props; const {t} = useTranslation();
const {navigation, smTitle, lgTitle, subTitle, onButtonPress} = props;
return ( return (
<View style={styles.container}> <View style={styles.container}>
<View style={styles.section}> <View style={styles.section}>
@ -36,6 +38,11 @@ const Header = props => {
</Text> </Text>
</View> </View>
)} )}
{onButtonPress && (
<TouchableOpacity onPress={onButtonPress} style={styles.button}>
<Text style={styles.buttonTitle}>{t('change_text')}</Text>
</TouchableOpacity>
)}
</View> </View>
</View> </View>
); );
@ -43,6 +50,7 @@ const Header = props => {
Header.defaultProps = { Header.defaultProps = {
subTitle: undefined, subTitle: undefined,
onButtonPress: undefined,
}; };
export default Header; export default Header;

View File

@ -51,4 +51,18 @@ export default StyleSheet.create({
color: Colors.TEXT, color: Colors.TEXT,
marginTop: width * 0.005, marginTop: width * 0.005,
}, },
button: {
borderWidth: 1,
borderColor: Colors.PRIMARY,
paddingHorizontal: width * 0.04,
paddingVertical: width * 0.015,
borderRadius: width * 0.015,
alignItems: 'center',
justifyContent: 'center',
},
buttonTitle: {
fontFamily: FONTS.poppins[600],
fontSize: RFValue(12),
color: Colors.PRIMARY,
},
}); });

View File

@ -20,7 +20,7 @@ const _Currency = props => {
<View style={styles.inputSection(editable)}> <View style={styles.inputSection(editable)}>
<CurrencyInput <CurrencyInput
{...props} {...props}
prefix="Rp" prefix=""
delimiter="." delimiter="."
minValue={0} minValue={0}
precision={0} precision={0}

View File

@ -6,7 +6,7 @@ import {Icon} from 'components';
const {width} = Dimensions.get('window'); const {width} = Dimensions.get('window');
const _Text = props => { const _Text = props => {
const {label, editable, note, error, required} = props; const {label, editable, note, error, required, counter} = props;
const [isFocused, setIsFocused] = useState(false); const [isFocused, setIsFocused] = useState(false);
return ( return (
<View style={styles.container}> <View style={styles.container}>
@ -21,10 +21,15 @@ const _Text = props => {
{...props} {...props}
style={styles.input(isFocused)} style={styles.input(isFocused)}
editable={editable} editable={editable}
maxLength={counter ? counter : undefined}
onChange={e => setIsFocused(e.nativeEvent.text.length > 0)} onChange={e => setIsFocused(e.nativeEvent.text.length > 0)}
placeholderTextColor={Colors.GREY} placeholderTextColor={Colors.GREY}
/> />
</View> </View>
{counter && (
<Text
style={styles.counterText}>{`${props.value.length}/${counter}`}</Text>
)}
{note && <Text style={styles.note}>{note}</Text>} {note && <Text style={styles.note}>{note}</Text>}
{error && ( {error && (
<View style={styles.errorSection}> <View style={styles.errorSection}>
@ -41,6 +46,8 @@ _Text.defaultProps = {
note: undefined, note: undefined,
error: undefined, error: undefined,
required: false, required: false,
counter: false,
value: '',
}; };
const styles = StyleSheet.create({ const styles = StyleSheet.create({
@ -86,6 +93,12 @@ const styles = StyleSheet.create({
marginTop: -width * 0.001, marginTop: -width * 0.001,
marginLeft: width * 0.01, marginLeft: width * 0.01,
}, },
counterText: {
fontFamily: FONTS.poppins[400],
fontSize: RFValue(10),
color: Colors.TEXT_LIGHT,
alignSelf: 'flex-end',
},
}); });
export default _Text; export default _Text;

View File

@ -53,7 +53,7 @@ export default StyleSheet.create({
marginHorizontal: width * 0.02, marginHorizontal: width * 0.02,
}, },
inputSection: { inputSection: {
width: width * 0.23, width: Platform.OS === 'ios' ? undefined : width * 0.23,
// borderWidth: 1, // borderWidth: 1,
// borderColor: Colors.LINE_STROKE, // borderColor: Colors.LINE_STROKE,
alignItems: 'center', alignItems: 'center',

View File

@ -29,6 +29,7 @@ const styles = StyleSheet.create({
}, },
messageSection: { messageSection: {
paddingLeft: width * 0.02, paddingLeft: width * 0.02,
marginRight: width * 0.02,
marginTop: -width * 0.004, marginTop: -width * 0.004,
}, },
message: { message: {

View File

@ -0,0 +1,23 @@
import React from 'react';
import {View, Text, Image} from 'react-native';
import styles from './styles';
const ProductRaw = props => {
return (
<View style={styles.container}>
<Image
source={require('assets/images/product-1.png')}
style={styles.image}
/>
<View style={styles.section}>
<Text style={styles.title}>Mie Ayam Yamin</Text>
<Text numberOfLines={2} style={styles.description}>
Mie ayam dengan kecap manis khas Jawa
</Text>
<Text style={styles.price}>Rp15.000</Text>
</View>
</View>
);
};
export default ProductRaw;

View File

@ -0,0 +1,36 @@
import {StyleSheet, Dimensions, Platform} from 'react-native';
import {RFValue} from 'react-native-responsive-fontsize';
import {Colors, FONTS} from 'global-styles';
const {width} = Dimensions.get('window');
export default StyleSheet.create({
container: {
flexDirection: 'row',
},
image: {
width: width * 0.2,
height: width * 0.2,
borderRadius: width * 0.02,
},
section: {
flex: 1,
paddingLeft: width * 0.04,
justifyContent: 'space-between',
},
title: {
fontFamily: FONTS.poppins[600],
fontSize: RFValue(13),
color: Colors.TEXT,
},
description: {
fontFamily: FONTS.poppins[400],
fontSize: RFValue(11.5),
color: Colors.TEXT,
flexWrap: 'wrap',
},
price: {
fontFamily: FONTS.poppins[600],
fontSize: RFValue(12),
color: Colors.TEXT,
},
});

View File

@ -9,6 +9,7 @@ import Header from './Header';
import Input from './Input'; import Input from './Input';
import Note from './Note'; import Note from './Note';
import ModalSetHours from './Modal/ModalSetHours'; import ModalSetHours from './Modal/ModalSetHours';
import ProductRaw from './Product/ProductRaw';
export { export {
Container, Container,
@ -22,4 +23,5 @@ export {
Input, Input,
Note, Note,
ModalSetHours, ModalSetHours,
ProductRaw,
}; };

View File

@ -45,4 +45,18 @@ export default {
operational_time_title: 'Operational Time', operational_time_title: 'Operational Time',
operational_hours_same_every_day_text: 'The operating hours are the same every day', operational_hours_same_every_day_text: 'The operating hours are the same every day',
set_hours_text: 'Set Hours', set_hours_text: 'Set Hours',
menu_category_title: 'Menu Category',
category_list_text: 'Category list',
add_category_title: 'Add Category',
category_name_text: 'Category name',
change_text: 'Change',
add_new_menu_title: 'Add Menus',
menu_photo_text: 'Menu photo',
menu_photo_note: 'Upload attractive photos to make potential customers more interested.',
upload_image_text: 'Upload photos',
name_text: 'Name',
description_text: 'Description',
price_text: 'Price (Rp)',
name_food_placeholder: 'Ex: Chicken Teriyaki Rice Set',
description_food_placeholder: 'Ex: Chicken Katsu + Steam Rice + Salad + Katsu Sauce + Spicy Mayonnaise',
}; };

View File

@ -45,4 +45,18 @@ export default {
operational_time_title: 'Jam Operasional', operational_time_title: 'Jam Operasional',
operational_hours_same_every_day_text: 'Jam operasional yang sama setiap hari', operational_hours_same_every_day_text: 'Jam operasional yang sama setiap hari',
set_hours_text: 'Atur Jam', set_hours_text: 'Atur Jam',
menu_category_title: 'Kategori Menu',
category_list_text: 'Daftar kategori',
add_category_title: 'Tambah Kategori',
category_name_text: 'Nama kategori',
change_text: 'Ubah',
add_new_menu_title: 'Tambah Menu',
menu_photo_text: 'Foto menu',
menu_photo_note: 'Upload foto yang menarik agar calon pelangganmu makin tertarik.',
upload_image_text: 'Upload foto',
name_text: 'Nama',
description_text: 'Deskripsi',
price_text: 'Harga (Rp)',
name_food_placeholder: 'Cth: Chicken Teriyaki Rice Set',
description_food_placeholder: 'Cth: Chicken Katsu + Steam Rice + Salad + Katsu Sauce + Spicy Mayonnaise',
}; };

View File

@ -9,6 +9,10 @@ import {
OutletSummary, OutletSummary,
BankAccount, BankAccount,
OperationalTime, OperationalTime,
MenuCategory,
AddMenuCategory,
ProductList,
AddProduct,
} from 'scenes'; } from 'scenes';
const AuthStack = createNativeStackNavigator(); const AuthStack = createNativeStackNavigator();
@ -23,6 +27,10 @@ const AuthStackScreen = () => {
<AuthStack.Screen name="OutletSummary" component={OutletSummary} /> <AuthStack.Screen name="OutletSummary" component={OutletSummary} />
<AuthStack.Screen name="BankAccount" component={BankAccount} /> <AuthStack.Screen name="BankAccount" component={BankAccount} />
<AuthStack.Screen name="OperationalTime" component={OperationalTime} /> <AuthStack.Screen name="OperationalTime" component={OperationalTime} />
<AuthStack.Screen name="MenuCategory" component={MenuCategory} />
<AuthStack.Screen name="AddMenuCategory" component={AddMenuCategory} />
<AuthStack.Screen name="ProductList" component={ProductList} />
<AuthStack.Screen name="AddProduct" component={AddProduct} />
</AuthStack.Navigator> </AuthStack.Navigator>
); );
}; };

View File

@ -0,0 +1,33 @@
import React, {useState} from 'react';
import {View, ScrollView} from 'react-native';
import {Container, Header, Button, Input} from 'components';
import {Colors} from 'global-styles';
import {useTranslation} from 'react-i18next';
import styles from './styles';
const AddMenuCategory = ({navigation}) => {
const {t} = useTranslation();
const [category, setCategory] = useState('');
return (
<Container backgroundColor={Colors.WHITE}>
<Header navigation={navigation} smTitle={t('add_category_title')} />
<View style={styles.container}>
<ScrollView>
<View style={styles.spacing} />
<Input
type="text"
keyboardType="decimal-pad"
required
counter={30}
label={t('category_name_text')}
value={category}
onChangeText={val => setCategory(val)}
/>
</ScrollView>
<Button title="Simpan" onPress={() => navigation.goBack()} />
</View>
</Container>
);
};
export default AddMenuCategory;

View File

@ -0,0 +1,19 @@
import {StyleSheet, Dimensions, Platform} from 'react-native';
import {RFValue} from 'react-native-responsive-fontsize';
import {Colors, FONTS} from 'global-styles';
const {width} = Dimensions.get('window');
export default StyleSheet.create({
container: {
flex: 1,
paddingHorizontal: width * 0.05,
paddingBottom: width * 0.04,
},
infoSection: {
marginTop: width * 0.03,
marginBottom: width * 0.04,
},
spacing: {
marginVertical: width * 0.02,
},
});

View File

@ -0,0 +1,50 @@
import React, {useState} from 'react';
import {View, ScrollView, Text, TouchableOpacity} from 'react-native';
import {Container, Header, Note, Icon} from 'components';
import {Colors} from 'global-styles';
import {useTranslation} from 'react-i18next';
import styles from './styles';
const MenuCategory = ({navigation}) => {
const {t} = useTranslation();
return (
<Container backgroundColor={Colors.WHITE}>
<Header navigation={navigation} smTitle={t('menu_category_title')} />
<View style={styles.container}>
<ScrollView>
<View style={[styles.infoSection, styles.horizontal]}>
<Note message="Tambahkan 1 karegori dengan menu makanan agar mempermudah saat verifikasi data outlet anda." />
</View>
<View style={styles.spacing} />
<View style={[styles.sceneTopSection, styles.horizontal]}>
<Text style={styles.sceneLabel}>{t('category_list_text')}</Text>
<TouchableOpacity
onPress={() => navigation.navigate('AddMenuCategory')}
style={styles.buttonAddCategory}>
<Text style={styles.buttonAddCategoryTitle}>Tambah</Text>
</TouchableOpacity>
</View>
<TouchableOpacity
activeOpacity={0.5}
onPress={() => navigation.navigate('ProductList')}
style={styles.categoryItem}>
<Text style={styles.categoryTitle}>Mie Ayam</Text>
<View style={styles.categoryBadgeSection}>
<View style={styles.categoryBadge}>
<Text style={styles.categoryBadgeTitle}>10</Text>
</View>
<Icon
name="chevron-right"
type="Feather"
style={styles.categoryIcon}
/>
</View>
</TouchableOpacity>
</ScrollView>
</View>
</Container>
);
};
export default MenuCategory;

View File

@ -0,0 +1,81 @@
import {StyleSheet, Dimensions, Platform} from 'react-native';
import {RFValue} from 'react-native-responsive-fontsize';
import {Colors, FONTS} from 'global-styles';
const {width} = Dimensions.get('window');
export default StyleSheet.create({
container: {
flex: 1,
paddingBottom: width * 0.04,
},
horizontal: {
paddingHorizontal: width * 0.05,
},
infoSection: {
marginTop: width * 0.03,
marginBottom: width * 0.04,
},
spacing: {
marginVertical: width * 0.02,
},
sceneTopSection: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingBottom: width * 0.04,
borderBottomWidth: 1,
borderBottomColor: Colors.LINE_STROKE,
},
sceneLabel: {
fontFamily: FONTS.poppins[600],
fontSize: RFValue(13),
color: Colors.TEXT,
},
buttonAddCategory: {
backgroundColor: Colors.RED_SHADOW,
paddingHorizontal: width * 0.028,
paddingVertical: width * 0.012,
borderRadius: width,
},
buttonAddCategoryTitle: {
fontFamily: FONTS.poppins[600],
fontSize: RFValue(10.5),
color: Colors.PRIMARY,
},
categoryItem: {
borderBottomWidth: 1,
borderBottomColor: Colors.LINE_STROKE,
marginLeft: width * 0.05,
paddingTop: width * 0.05,
paddingBottom: width * 0.03,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingRight: width * 0.05,
},
categoryTitle: {
fontFamily: FONTS.poppins[600],
fontSize: RFValue(11.5),
color: Colors.TEXT,
},
categoryBadgeSection: {
flexDirection: 'row',
alignItems: 'center',
},
categoryBadge: {
paddingHorizontal: width * 0.02,
paddingVertical: width * 0.008,
backgroundColor: Colors.GREY,
borderRadius: width * 0.01,
marginRight: width * 0.02,
},
categoryBadgeTitle: {
fontFamily: FONTS.poppins[500],
fontSize: RFValue(9),
color: Colors.TEXT,
},
categoryIcon: {
fontSize: RFValue(14),
color: Colors.TEXT,
},
});

View File

@ -0,0 +1,69 @@
import React, {useState} from 'react';
import {View, ScrollView, Text, TouchableOpacity} from 'react-native';
import {Container, Header, Button, Icon, Input} from 'components';
import {Colors} from 'global-styles';
import {useTranslation} from 'react-i18next';
import styles from './styles';
const AddProduct = ({navigation}) => {
const {t} = useTranslation();
const [price, setPrice] = useState('0');
return (
<Container backgroundColor={Colors.WHITE}>
<Header navigation={navigation} smTitle={t('add_new_menu_title')} />
<View style={styles.container}>
<ScrollView>
<View style={styles.spacing} />
<View style={styles.imageUploadSection}>
<Text style={styles.imageUploadLabel}>
{t('menu_photo_text')}
<Text style={{color: Colors.RED}}>*</Text>
</Text>
<Text style={styles.imageUploadNote}>{t('menu_photo_note')}</Text>
<TouchableOpacity activeOpacity={0.5} style={styles.imageUpload}>
<View style={styles.imageUploadIconWrap}>
<Icon
name="camera"
type="Feather"
style={styles.imageUploadIcon}
/>
</View>
<Text style={styles.imgaeUploadText}>
{t('upload_image_text')}
</Text>
</TouchableOpacity>
</View>
<View style={styles.spacing} />
<View style={styles.spacing} />
<Input
type="text"
required
label={t('name_text')}
counter={30}
placeholder={t('name_food_placeholder')}
/>
<View style={styles.spacing} />
<Input
type="text"
required
label={t('description_text')}
counter={50}
placeholder={t('description_food_placeholder')}
/>
<View style={styles.spacing} />
<Input
type="currency"
required
value={price}
onChangeValue={val => setPrice(val)}
label={t('price_text')}
placeholder="0"
/>
</ScrollView>
<Button title="Simpan" onPress={() => navigation.goBack()} />
</View>
</Container>
);
};
export default AddProduct;

View File

@ -0,0 +1,55 @@
import {StyleSheet, Dimensions, Platform} from 'react-native';
import {RFValue} from 'react-native-responsive-fontsize';
import {Colors, FONTS} from 'global-styles';
const {width} = Dimensions.get('window');
export default StyleSheet.create({
container: {
flex: 1,
paddingHorizontal: width * 0.05,
paddingBottom: width * 0.04,
},
spacing: {
marginVertical: width * 0.02,
},
imageUploadSection: {},
imageUploadLabel: {
fontFamily: FONTS.poppins[600],
fontSize: RFValue(11.5),
color: Colors.TEXT,
},
imageUploadNote: {
fontFamily: FONTS.poppins[400],
fontSize: RFValue(11),
color: Colors.TEXT_LIGHT,
marginTop: width * 0.005,
},
imageUpload: {
width: width * 0.26,
height: width * 0.25,
borderWidth: 1,
borderColor: Colors.PRIMARY,
borderRadius: width * 0.025,
alignItems: 'center',
justifyContent: 'center',
marginTop: width * 0.03,
},
imageUploadIconWrap: {
width: width * 0.08,
height: width * 0.08,
backgroundColor: Colors.PRIMARY,
borderRadius: width,
alignItems: 'center',
justifyContent: 'center',
},
imageUploadIcon: {
color: Colors.WHITE,
fontSize: RFValue(14),
},
imgaeUploadText: {
fontFamily: FONTS.poppins[500],
fontSize: RFValue(9),
color: Colors.PRIMARY,
marginTop: width * 0.03,
},
});

View File

@ -0,0 +1,34 @@
import React, {useState} from 'react';
import {View, ScrollView} from 'react-native';
import {Container, Header, Button, ProductRaw} from 'components';
import {Colors} from 'global-styles';
import {useTranslation} from 'react-i18next';
import styles from './styles';
const ProductList = ({navigation}) => {
const {t} = useTranslation();
return (
<Container backgroundColor={Colors.WHITE}>
<Header
navigation={navigation}
smTitle={'Mie Ayam'}
onButtonPress={() => navigation.navigate('AddProduct')}
/>
<View style={styles.container}>
<ScrollView>
<View style={styles.spacing} />
<ProductRaw />
<View style={styles.separator} />
<ProductRaw />
</ScrollView>
<Button
title="Tambah"
onPress={() => navigation.navigate('AddProduct')}
/>
</View>
</Container>
);
};
export default ProductList;

View File

@ -0,0 +1,24 @@
import {StyleSheet, Dimensions, Platform} from 'react-native';
import {RFValue} from 'react-native-responsive-fontsize';
import {Colors, FONTS} from 'global-styles';
const {width} = Dimensions.get('window');
export default StyleSheet.create({
container: {
flex: 1,
paddingHorizontal: width * 0.05,
paddingBottom: width * 0.04,
},
infoSection: {
marginTop: width * 0.03,
marginBottom: width * 0.04,
},
spacing: {
marginVertical: width * 0.02,
},
separator: {
borderBottomWidth: 1,
borderBottomColor: Colors.LINE_STROKE,
marginVertical: width * 0.04,
},
});

View File

@ -45,6 +45,7 @@ const BusinessSummary = ({navigation}) => {
label={t('business_category_text')} label={t('business_category_text')}
data={BUSINESS_CATEGORY} data={BUSINESS_CATEGORY}
value={categorySelected} value={categorySelected}
searchable
onChangeValue={val => setCategorySelected(val)} onChangeValue={val => setCategorySelected(val)}
/> />
<View style={styles.spacing} /> <View style={styles.spacing} />

View File

@ -117,7 +117,10 @@ const OperationalTime = ({navigation}) => {
<View style={styles.spacing} /> <View style={styles.spacing} />
<View style={styles.is24HoursSection}> <View style={styles.is24HoursSection}>
<TouchableOpacity <TouchableOpacity
onPress={() => setChecked(!checked)} onPress={() => {
setChecked(!checked);
setIsEnabled(false);
}}
activeOpacity={0.5} activeOpacity={0.5}
style={styles.checkboxSection}> style={styles.checkboxSection}>
<View style={styles.checkbox(checked)}> <View style={styles.checkbox(checked)}>

View File

@ -29,7 +29,7 @@ const BUSINESS_PROFILE = [
{ {
name: 'Kategori dan Menu makanan', name: 'Kategori dan Menu makanan',
completed: false, completed: false,
route: 'BusinessSummary', route: 'MenuCategory',
}, },
]; ];

View File

@ -5,6 +5,10 @@ import BusinessSummary from './Register/BusinessProfileRegistration/BusinessSumm
import OutletSummary from './Register/BusinessProfileRegistration/OutletSummary'; import OutletSummary from './Register/BusinessProfileRegistration/OutletSummary';
import BankAccount from './Register/BusinessProfileRegistration/BankAccount'; import BankAccount from './Register/BusinessProfileRegistration/BankAccount';
import OperationalTime from './Register/BusinessProfileRegistration/OperationalTime'; import OperationalTime from './Register/BusinessProfileRegistration/OperationalTime';
import MenuCategory from './Products/MenuCategory';
import AddMenuCategory from './Products/MenuCategory/AddMenuCategory';
import ProductList from './Products/ProductList';
import AddProduct from './Products/ProductList/AddProduct';
export { export {
Login, Login,
@ -14,4 +18,8 @@ export {
OutletSummary, OutletSummary,
BankAccount, BankAccount,
OperationalTime, OperationalTime,
MenuCategory,
AddMenuCategory,
ProductList,
AddProduct,
}; };