Skip to content

Commit

Permalink
Add Product Tab
Browse files Browse the repository at this point in the history
  • Loading branch information
rizbud committed Aug 23, 2020
1 parent bffe6b6 commit 137f4cf
Show file tree
Hide file tree
Showing 13 changed files with 264 additions and 47 deletions.
22 changes: 22 additions & 0 deletions App/Components/ListProduct.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React, { memo, useContext } from 'react'
import { TouchableOpacity,Image, View, Text } from 'react-native'
import styles from './Styles/ListProductStyle'
import { NavigationContext } from "react-navigation"
import Format from '../Lib/NumberFormat'

const ListProduct = (props) => {
const {thumb, title, price, press, ...restProps} = props
const navigation = useContext(NavigationContext)

return (
<TouchableOpacity onPress={press} activeOpacity={0.9} style={styles.card}>
<Image source={thumb} style={styles.thumb} resizeMode="cover" />
<View style={styles.content}>
<Text style={styles.title}>{title}</Text>
<Text style={styles.price}>{'Rp' + new Format().formatMoney(price)}</Text>
</View>
</TouchableOpacity>
)
}

export default memo(ListProduct)
11 changes: 11 additions & 0 deletions App/Components/Styles/ListProductStyle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { connect } from "../../Lib/OsmiProvider"

export default connect({
card: "bg-white rounded-md shadow-md p-3 row items-center justify-start mb-3",
thumb: "rounded-md mr-3 w-100 h-100 justify-center",
content: "flex flex-wrap",
title: "text-base font-bold mb-1 flex-wrap",
price: "text-sm",
btnBuy: "bg-blue-500 rounded-md px-3 py-1 self-start",
btnBuyLabel: "text-white"
})
2 changes: 1 addition & 1 deletion App/Config/ReactotronConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { reactotronRedux as reduxPlugin } from 'reactotron-redux'
import sagaPlugin from 'reactotron-redux-saga'

const reactotron = Reactotron
.configure({ name: 'Ignite App', host: '192.168.100.8' })
.configure({ name: 'Ignite App', host: '192.168.43.125' })
.useReactNative()
.use(reduxPlugin({ onRestore: Immutable }))
.use(sagaPlugin())
Expand Down
12 changes: 2 additions & 10 deletions App/Containers/Home.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
} from 'react-native'
import { connect } from "react-redux";
import ProductsActions from "../Redux/ProductsRedux";
import ListProduct from '../Components/ListProduct'

import styles from './Styles/HomeStyle'
import HeaderStyle from "../Navigation/Styles/NavigationStyles";
Expand All @@ -29,16 +30,7 @@ const Home = props => {
}

const renderItem = ({ item, index }) => (
<View style={styles.card}>
<Image source={{ uri: item.thumbnail }} style={styles.thumb} resizeMode="cover" />
<View style={styles.content}>
<Text style={styles.title}>{item?.title}</Text>
<Text style={styles.price}>{item?.price}</Text>
<TouchableOpacity activeOpacity={0.9} style={styles.btnBuy}>
<Text style={styles.btnBuyLabel}>Beli</Text>
</TouchableOpacity>
</View>
</View>
<ListProduct thumb={{uri: item.thumbnail}} title={item?.title} price={item?.price} press={() => alert('Beli')} />
)

const onEndReached = async (distance) => {
Expand Down
72 changes: 56 additions & 16 deletions App/Containers/Products.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,68 @@
import React from 'react'
import { ScrollView, Text } from 'react-native'
import React, {useEffect, useState} from 'react'
import { SafeAreaView, ActivityIndicator, RefreshControl, FlatList, Image, View, Text } from 'react-native'
import { connect } from 'react-redux'
// Add Actions - replace 'Your' with whatever your reducer is called :)
// import YourActions from '../Redux/YourRedux'
import CategoryActions from "../Redux/CategoryRedux";

// Styles
import styles from './Styles/ProductsStyle'
import { apply } from '../Lib/OsmiProvider';

const Products = props => {
const {category} = props
const [refreshing, setRefreshing] = useState(false)

useEffect(() => {
props.getCategory({})
}, [])

const pullToRefresh = () => {
props.getCategory({})
}

const renderItem = ({ item, index }) => (
<View style={styles.card}>
<Image source={{ uri: item.thumbnail }} style={styles.thumb} />
<View style={styles.content}>
<Text style={styles.title}>{item.title}</Text>
<Text style={styles.desc}>{item.desc}</Text>
</View>
</View>
)

console.tron.log("=== ini titid ===", props.category)

const Products = () => {
return (
<ScrollView style={styles.container}>
<Text>Products Container</Text>
</ScrollView>
<SafeAreaView style={apply('bg-gray-500 flex')}>
{category?.fetching ? (
<View>
<ActivityIndicator size="large" color="#fff" />
</View>
) : (
<FlatList
data={category.data}
initialNumToRender={3}
keyExtractor={(item, index) => index.toString()}
refreshControl={
<RefreshControl refreshing={refreshing} onRefresh={() => pullToRefresh()} />
}
renderItem={renderItem}
ListEmptyComponent={() =>(
<View>
<Text>Tidak ada data ditampilkam</Text>
</View>
)}
/>
)}
</SafeAreaView>
)
}

const mapStateToProps = (state) => {
return {
}
}
const mapStateToProps = (state) => ({
category: state.category.list
})

const mapDispatchToProps = (dispatch) => {
return {
}
}
const mapDispatchToProps = (dispatch) => ({
getCategory: value => dispatch(CategoryActions.getCategoryRequest(value))
})

export default connect(mapStateToProps, mapDispatchToProps)(Products)
9 changes: 1 addition & 8 deletions App/Containers/Styles/HomeStyle.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
import { connect } from "../../Lib/OsmiProvider"

export default connect({
emptyState: "flex items-center justify-center",
card: "bg-white rounded-md shadow-md p-3 row items-start mb-3",
thumb: "rounded-md mr-3 w-100 h-100",
content: "flex flex-wrap",
title: "text-base font-bold mb-1 flex-wrap",
price: "text-sm",
btnBuy: "bg-blue-500 rounded-md px-3 py-1 self-start",
btnBuyLabel: "text-white"
emptyState: "flex items-center justify-center"
})
16 changes: 7 additions & 9 deletions App/Containers/Styles/ProductsStyle.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { StyleSheet } from 'react-native'
import { Colors, Metrics } from '../../Themes/'
import { connect } from "../../Lib/OsmiProvider"

export default StyleSheet.create({
container: {
flex: 1,
marginTop: Metrics.navBarHeight,
backgroundColor: Colors.background
}
})
export default connect({
card: 'row p-5 bg-white m-3 rounded-md items-center justify-start',
thumb: 'w-100 h-100 mr-5 rounded',
content: 'flex flex-wrap',
title: 'text-lg font-bold mb-1'
})
101 changes: 101 additions & 0 deletions App/Lib/NumberFormat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
export default class TextUtil {
strReplace = (source, replace, replaceWith) => {
var value = source
var i = 0
for (i; i < value.length; i++) {
value = value.replace(replace, replaceWith)
}
console.log(value)
return value;
}

upperCaseString = (i) => {
if (typeof i === 'string') {
return i.toUpperCase()
}
return i
}

formattingNumber = (i) => {
if (typeof i === 'number') {
return i.toLocaleString(navigator.language, { minimumFractionDigits: 0 });
}
return i
}

validateEmail = (text) => {
let reg = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/;
if (reg.test(text) === false) {
return false;
} else {
return true;
}
}

getListYear() {
var currentYear = new Date().getFullYear(), years = [];
var startYear = 2000;
while (startYear <= currentYear) {
years.push(startYear++);
}
return years;
}

getDate(value, newFormat = null) {
if (newFormat == null) {
newFormat = 'DD MMMM YYYY'
}
let date = moment(value, formatDateDefault).format(newFormat)
return date
}

getCurrentDate() {
let date = moment(new Date, 'DD-MM-YYYY').format();
return date
}

getDateTime(value) {
let date = moment(value, formatDateDefault).format('DD MMMM YYYY HH:mm:ss')
return date
}

getDateTime2(value) {
let date = moment(value, formatDateDefault).format('DD MMMM YYYY HH:mm')
return date
}

getFullDay(value) {
let date = moment(value, formatDateDefault).format('dddd, DD MMMM YYYY')
return date
}

getTime(value) {
let date = moment(value, formatDateDefault).format('HH:mm:ss')
return date
}

getHour(value) {
let date = moment(value, formatDateDefault).format('HH:mm')
return date
}

formatMoney(num) {
num = num + ""

if (num == "" || num == "0")
return "";

num = num.replace(/\./g, "");
var num_parts = num.toString().split(".");
num_parts[0] = num_parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ".");
return num_parts.join(".");
}

moneytoInt(num) {
if (num) {
return num.replace(/\./g, "");
} else {
return 0;
}
}
}
40 changes: 40 additions & 0 deletions App/Redux/CategoryRedux.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { createReducer, createActions } from 'reduxsauce'
import Immutable from 'seamless-immutable'

/* ------------- Types and Action Creators ------------- */

const { Types, Creators } = createActions({
getCategoryRequest: ['data'],
getCategorySuccess: ['data'],
getCategoryFailure: ['error']
})

export const CategoryTypes = Types
export default Creators

/* ------------- Initial State ------------- */

export const INITIAL_STATE = Immutable({
list: { data: [], fetching: false, error: null },
detail: {data: null, fetching: false, error: null}
})

/* ------------- Reducers ------------- */

// request the data from an api
export const getCategoryRequest = (state, { data }) =>
state.merge({ ...state, list: {...state.list, fetching: true, error: null} })

export const getCategorySuccess = (state, { data }) =>
state.merge({ ...state, list: { ...state.list, data, fetching: false, error: null }})

export const getCategoryFailure = (state, { error }) =>
state.merge({ ...state, list: {...state.list, fetching: false, error} })

/* ------------- Hookup Reducers To Types ------------- */

export const reducer = createReducer(INITIAL_STATE, {
[Types.GET_CATEGORY_REQUEST]: getCategoryRequest,
[Types.GET_CATEGORY_SUCCESS]: getCategorySuccess,
[Types.GET_CATEGORY_FAILURE]: getCategoryFailure
})
3 changes: 2 additions & 1 deletion App/Redux/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ export const reducers = combineReducers({
nav: require('./NavigationRedux').reducer,
github: require('./GithubRedux').reducer,
search: require('./SearchRedux').reducer,
products: require('./ProductsRedux').reducer
products: require('./ProductsRedux').reducer,
category: require('./CategoryRedux').reducer
})

export default () => {
Expand Down
14 changes: 14 additions & 0 deletions App/Sagas/CategorySagas.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { call, put } from 'redux-saga/effects'
import CategoryActions from '../Redux/CategoryRedux'

export function * getCategory (api, action) {
const { data } = action
const response = yield call(api.getCategory, data)

if (response.ok) {
console.tron.log("=== titid ===", response)
yield put(CategoryActions.getCategorySuccess(response.data.data))
} else {
yield put(CategoryActions.getCategoryFailure(response))
}
}
7 changes: 5 additions & 2 deletions App/Sagas/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ import DebugConfig from '../Config/DebugConfig'

import { StartupTypes } from '../Redux/StartupRedux'
import { GithubTypes } from '../Redux/GithubRedux'
import { ProductsTypes } from "../Redux/ProductsRedux";
import { ProductsTypes } from "../Redux/ProductsRedux"
import { CategoryTypes } from "../Redux/CategoryRedux"

/* ------------- Sagas ------------- */

import { startup } from './StartupSagas'
import { getUserAvatar } from './GithubSagas'
import { getProducts, moreProducts } from "./ProductsSagas";
import { getProducts, moreProducts } from "./ProductsSagas"
import { getCategory } from "./CategorySagas";

/* ------------- API ------------- */

Expand All @@ -30,5 +32,6 @@ export default function * root () {

takeLatest(ProductsTypes.GET_PRODUCTS_REQUEST, getProducts, api),
takeLatest(ProductsTypes.MORE_PRODUCTS_REQUEST, moreProducts, api),
takeLatest(CategoryTypes.GET_CATEGORY_REQUEST, getCategory, api)
])
}
2 changes: 2 additions & 0 deletions App/Services/Api.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const create = (baseURL = 'https://api.alfredo.my.id/api/v1') => {
//

const getProducts = data => api.get(`/products${data.params}`)
const getCategory = data => api.get(`/category`)

// ------
// STEP 3
Expand All @@ -55,6 +56,7 @@ const create = (baseURL = 'https://api.alfredo.my.id/api/v1') => {
return {
// a list of the API functions from step 2
getProducts,
getCategory,

api
}
Expand Down

0 comments on commit 137f4cf

Please sign in to comment.