diff --git a/App/Components/ListProduct.js b/App/Components/ListProduct.js
new file mode 100644
index 0000000..1f35679
--- /dev/null
+++ b/App/Components/ListProduct.js
@@ -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 (
+
+
+
+ {title}
+ {'Rp' + new Format().formatMoney(price)}
+
+
+ )
+}
+
+export default memo(ListProduct)
diff --git a/App/Components/Styles/ListProductStyle.js b/App/Components/Styles/ListProductStyle.js
new file mode 100644
index 0000000..698ed3c
--- /dev/null
+++ b/App/Components/Styles/ListProductStyle.js
@@ -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"
+})
\ No newline at end of file
diff --git a/App/Config/ReactotronConfig.js b/App/Config/ReactotronConfig.js
index 8762a3f..44c1338 100644
--- a/App/Config/ReactotronConfig.js
+++ b/App/Config/ReactotronConfig.js
@@ -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())
diff --git a/App/Containers/Home.js b/App/Containers/Home.js
index 5e0a5b7..5d8be40 100644
--- a/App/Containers/Home.js
+++ b/App/Containers/Home.js
@@ -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";
@@ -29,16 +30,7 @@ const Home = props => {
}
const renderItem = ({ item, index }) => (
-
-
-
- {item?.title}
- {item?.price}
-
- Beli
-
-
-
+ alert('Beli')} />
)
const onEndReached = async (distance) => {
diff --git a/App/Containers/Products.js b/App/Containers/Products.js
index 93ca590..ff3d73a 100644
--- a/App/Containers/Products.js
+++ b/App/Containers/Products.js
@@ -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 }) => (
+
+
+
+ {item.title}
+ {item.desc}
+
+
+ )
+
+ console.tron.log("=== ini titid ===", props.category)
-const Products = () => {
return (
-
- Products Container
-
+
+ {category?.fetching ? (
+
+
+
+ ) : (
+ index.toString()}
+ refreshControl={
+ pullToRefresh()} />
+ }
+ renderItem={renderItem}
+ ListEmptyComponent={() =>(
+
+ Tidak ada data ditampilkam
+
+ )}
+ />
+ )}
+
)
}
-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)
diff --git a/App/Containers/Styles/HomeStyle.js b/App/Containers/Styles/HomeStyle.js
index 2fb2f4f..40529a2 100644
--- a/App/Containers/Styles/HomeStyle.js
+++ b/App/Containers/Styles/HomeStyle.js
@@ -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"
})
\ No newline at end of file
diff --git a/App/Containers/Styles/ProductsStyle.js b/App/Containers/Styles/ProductsStyle.js
index 3144a3e..37faf37 100644
--- a/App/Containers/Styles/ProductsStyle.js
+++ b/App/Containers/Styles/ProductsStyle.js
@@ -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'
+})
\ No newline at end of file
diff --git a/App/Lib/NumberFormat.js b/App/Lib/NumberFormat.js
new file mode 100644
index 0000000..6e5db96
--- /dev/null
+++ b/App/Lib/NumberFormat.js
@@ -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;
+ }
+ }
+}
\ No newline at end of file
diff --git a/App/Redux/CategoryRedux.js b/App/Redux/CategoryRedux.js
new file mode 100644
index 0000000..70b1bd7
--- /dev/null
+++ b/App/Redux/CategoryRedux.js
@@ -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
+})
diff --git a/App/Redux/index.js b/App/Redux/index.js
index 9602c1d..c9d50d3 100644
--- a/App/Redux/index.js
+++ b/App/Redux/index.js
@@ -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 () => {
diff --git a/App/Sagas/CategorySagas.js b/App/Sagas/CategorySagas.js
new file mode 100644
index 0000000..926d74a
--- /dev/null
+++ b/App/Sagas/CategorySagas.js
@@ -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))
+ }
+}
diff --git a/App/Sagas/index.js b/App/Sagas/index.js
index e55d296..a69d88c 100644
--- a/App/Sagas/index.js
+++ b/App/Sagas/index.js
@@ -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 ------------- */
@@ -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)
])
}
diff --git a/App/Services/Api.js b/App/Services/Api.js
index d832e72..76c0ea7 100644
--- a/App/Services/Api.js
+++ b/App/Services/Api.js
@@ -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
@@ -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
}