diff --git a/app.json b/app.json index d3d545e..6a61d6a 100644 --- a/app.json +++ b/app.json @@ -4,9 +4,9 @@ "slug": "RnDanovinExpo", "version": "1.0.0", "orientation": "portrait", - "icon": "./assets/icon.png", + "icon": "", "splash": { - "image": "./assets/splash.png", + "image": "", "resizeMode": "contain", "backgroundColor": "#ffffff" }, @@ -21,13 +21,13 @@ }, "android": { "adaptiveIcon": { - "foregroundImage": "./assets/adaptive-icon.png", + "foregroundImage": "", "backgroundColor": "#FFFFFF" }, "package": "com.appsazz.RnDanovinExpo" }, "web": { - "favicon": "./assets/favicon.png" + "favicon": "" } } } diff --git a/assets/adaptive-icon.png b/assets/adaptive-icon.png deleted file mode 100644 index 03d6f6b..0000000 Binary files a/assets/adaptive-icon.png and /dev/null differ diff --git a/assets/favicon.png b/assets/favicon.png deleted file mode 100644 index e75f697..0000000 Binary files a/assets/favicon.png and /dev/null differ diff --git a/assets/icon.png b/assets/icon.png deleted file mode 100644 index a0b1526..0000000 Binary files a/assets/icon.png and /dev/null differ diff --git a/assets/splash.png b/assets/splash.png deleted file mode 100644 index 0e89705..0000000 Binary files a/assets/splash.png and /dev/null differ diff --git a/navigation.js b/navigation.js deleted file mode 100644 index 62350d3..0000000 --- a/navigation.js +++ /dev/null @@ -1,116 +0,0 @@ -import * as React from 'react'; -import {NavigationContainer} from '@react-navigation/native'; -import {createNativeStackNavigator} from '@react-navigation/native-stack'; -import {createBottomTabNavigator} from '@react-navigation/bottom-tabs'; -import Splash from './src/screens/Splash'; -import Home from './src/screens/Home'; -import Login from './src/screens/Login'; -import Otp from './src/screens/Otp'; -import Product from './src/screens/Product'; -import Products from './src/screens/Products'; -import ShoppingCart from './src/screens/ShoppingCart'; -import QR from './src/screens/QR/index'; -import i18n from './src/services/i18n'; -import {useTranslation} from 'react-i18next'; -import Profile from './src/screens/Profile'; -import Videos from './src/screens/Videos'; -import Exams from './src/screens/Exams'; -import OrderDetails from './src/screens/OrderDetails'; - -const mapStateToProps = state => { - return { - profile: state.profile, - config: state.config, - }; -}; - -const Stack = createNativeStackNavigator(); -const Tab = createBottomTabNavigator(); - -function BottomTab(props) { - - return ( - - - - - - - - ); -} - -function Navigator(props) { - React.useEffect(() => { - // i18n.changeLanguage(props.config.lan); - }, [props.config]); - - return ( - - - - - {/* */} - - - - - - - - - ); -} - -export default Navigator; diff --git a/navigation/index.js b/navigation/index.js index 1e3003e..c3d012a 100644 --- a/navigation/index.js +++ b/navigation/index.js @@ -2,7 +2,7 @@ import React from "react"; import { NavigationContainer } from "@react-navigation/native"; import { createNativeStackNavigator } from "@react-navigation/native-stack"; import { createBottomTabNavigator } from "@react-navigation/bottom-tabs"; -import { Entypo, FontAwesome, Ionicons } from "@expo/vector-icons"; +import { Entypo, FontAwesome, Ionicons, MaterialIcons } from "@expo/vector-icons"; import OrderDetails from "../src/screens/OrderDetails"; import OrdersFollowUp from "../src/screens/OrdersFollowUp"; import { Dimensions } from "react-native"; @@ -16,8 +16,6 @@ import QR from "../src/screens/QR"; import Faq from "../src/screens/Faq" import Activation from "../src/screens/Activation"; import { connect } from "react-redux"; -import i18n from "../src/services/i18n"; -import { useTranslation } from "react-i18next"; import Profile from "../src/screens/Profile"; import Videos from "../src/screens/Videos"; import Exams from "../src/screens/Exams"; @@ -29,7 +27,7 @@ const Tab = createBottomTabNavigator(); const BottomTabNavigator = () => { return ( { }} > ( @@ -55,7 +53,7 @@ const BottomTabNavigator = () => { }} /> ( @@ -68,7 +66,16 @@ const BottomTabNavigator = () => { }} /> ( + + ), + }} + /> + ( @@ -77,7 +84,7 @@ const BottomTabNavigator = () => { }} /> ( @@ -115,24 +122,38 @@ const ProductsStackScreen = () => { return ( - - - + + + ); }; +const VODStack = createNativeStackNavigator(); +const VODStackScreen = () => { + return ( + + + + + + + + ); +}; + const AuthStack = createNativeStackNavigator(); const AuthStackScreen = () => { return ( @@ -155,7 +176,7 @@ const OrderStackScreen = () => { } const Stack = createNativeStackNavigator(); -const Navigation = ({ profile }) => { +const Navigation = ({ }) => { return ( { const mapStateToProps = (state) => { return { - profile: state.profile, - config: state.config, + }; }; diff --git a/package.json b/package.json index 1ac3f82..b43b309 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "@react-navigation/drawer": "^6.1.8", "@react-navigation/native": "^6.0.6", "@react-navigation/native-stack": "^6.2.5", + "axios": "^0.24.0", "expo": "^44.0.1", "expo-app-loading": "~1.3.0", "expo-barcode-scanner": "~11.2.0", @@ -48,5 +49,6 @@ "devDependencies": { "@babel/core": "^7.12.9" }, + "private": true } diff --git a/src/actions/actionTypes.js b/src/actions/actionTypes.js deleted file mode 100644 index 170cedd..0000000 --- a/src/actions/actionTypes.js +++ /dev/null @@ -1,2 +0,0 @@ -export const PROFILE_RECORD = 'PROFILE_RECORD'; -export const APP_CONFIG = 'APP_CONFIG'; diff --git a/src/components/CustomTextInput.js b/src/components/CustomTextInput.js index 64e63cb..c0d8f28 100644 --- a/src/components/CustomTextInput.js +++ b/src/components/CustomTextInput.js @@ -15,6 +15,7 @@ const FloatingLabelInput = ({ color, maxLength, autoFocus, + regex, ...props }) => { const [isFocused, setIsFocused] = useState(false); @@ -43,7 +44,7 @@ const FloatingLabelInput = ({ onChange(name, text)} + onChangeText={text => onChange(name, text = regex(text))} placeholder={'09123456789'} onFocus={() => setIsFocused(true)} autoFocus={autoFocus} diff --git a/src/components/Drawer.js b/src/components/Drawer.js index 3e024ea..f3d845b 100644 --- a/src/components/Drawer.js +++ b/src/components/Drawer.js @@ -62,7 +62,7 @@ const Drawer = ({ position, setBoxPosition }) => { { name: "سوالات متداول", route: "Faq", - icon: , + icon: , toast: "", message: "", } @@ -72,7 +72,7 @@ const Drawer = ({ position, setBoxPosition }) => { return ( navigation.navigate(route.route)} diff --git a/src/components/Search.js b/src/components/Search.js index e8d1803..9e2f0a7 100644 --- a/src/components/Search.js +++ b/src/components/Search.js @@ -8,7 +8,7 @@ import { Image, } from 'react-native'; import tw from 'tailwind-react-native-classnames'; -import searchIcon from '../assets/icons/search.png'; +import { AntDesign } from '@expo/vector-icons'; const width = Dimensions.get('window').width; const Search = ({ @@ -42,7 +42,7 @@ const Search = ({ value={value} /> - + ); diff --git a/src/constants/defaultValues.js b/src/constants/defaultValues.js new file mode 100644 index 0000000..2591544 --- /dev/null +++ b/src/constants/defaultValues.js @@ -0,0 +1,9 @@ +export const ApiConfig = { + apiKey: 'AIzaSyBBksq-Asxq2M4Ot-75X19IyrEYJqNBPcg', + authDomain: 'dnvn.ir', + baseUrl: 'https://dnvn.ir/api/v1', + //baseUrl: 'http://localhost:3030/api/v1', + loginURL: 'user/login', + otploginURL: 'user/otp/login', + logoutURL: 'user/logout', +}; \ No newline at end of file diff --git a/src/reducers/DefaultReducer.js b/src/reducers/DefaultReducer.js deleted file mode 100644 index c00c1a3..0000000 --- a/src/reducers/DefaultReducer.js +++ /dev/null @@ -1,29 +0,0 @@ -export function DefaultReducer(key, initialState = {}) { - return (state = initialState, {type = '', payload = {}}) => { - switch (type) { - case key: - return {...state, ...payload}; - } - return state; - }; -} - -export function buildAction(id) { - return function(payload) { - return { - type: id, - payload: payload, - }; - }; -} - -export function buildActionForKey(id, key) { - return function(payload) { - let result = { - type: id, - payload: {}, - }; - result.payload[key] = payload; - return result; - }; -} diff --git a/src/reducers/index.js b/src/reducers/index.js deleted file mode 100644 index 1d0c85e..0000000 --- a/src/reducers/index.js +++ /dev/null @@ -1,14 +0,0 @@ -import {combineReducers} from 'redux'; -import {DefaultReducer} from './DefaultReducer'; -import * as action from '../actions/actionTypes'; - -const allReducers = combineReducers({ - profile: DefaultReducer(action.PROFILE_RECORD, { - isLogin: false, - }), - config: DefaultReducer(action.APP_CONFIG, { - lan: 'fa', - }), -}); - -export default allReducers; \ No newline at end of file diff --git a/src/redux/actions/blog.js b/src/redux/actions/blog.js new file mode 100644 index 0000000..d873065 --- /dev/null +++ b/src/redux/actions/blog.js @@ -0,0 +1,27 @@ +import proxy from "../proxy"; +const blog = { + list: + (data = {}) => + async (dispatch) => + await proxy.get("public/blogList", data, { dispatch }), + // update: + // (data = {}, data2 = {}) => + // async (dispatch : Dispatch) => { + // await proxy.put("blog/update", data); + // await proxy.get("blog/list", data2, { dispatch }); + // }, + // add: + // (data = {}, data2 = {}) => + // async (dispatch : Dispatch) => { + // await proxy.post("blog/add", data); + // await proxy.get("blog/list", data2, { dispatch }); + // }, + // del: + // (data = {}, data2 = {}) => + // async (dispatch : Dispatch) => { + // await proxy.delete("blog/delete", data); + // await proxy.get("blog/list", data2, { dispatch }); + // }, +}; + +export default blog; diff --git a/src/redux/actions/book.js b/src/redux/actions/book.js new file mode 100644 index 0000000..f74ec70 --- /dev/null +++ b/src/redux/actions/book.js @@ -0,0 +1,44 @@ +import proxy from "../proxy"; +const book = { + list: + (data = {}) => + async (dispatch) => + await proxy.get("book/list", data, { dispatch }), + info: + (data = {}) => + async (dispatch) => + await proxy.get("book/info", data, { dispatch }), + setLessonActive: (data) => async (dispatch) => + await dispatch({ type: "book/lesson/active", data: data }), + gradeFilter: (data) => async (dispatch) => + await dispatch({ type: "book/gradeFilter", data: data }), + sortFilter: (data) => async (dispatch) => + await dispatch({ type: "book/sortFilter", data: data }), + + // update: + // (data = {}, data2 = {}) => + // async (dispatch : Dispatch) => { + // await proxy.put("book/update", data); + // await proxy.get("book/list", data2, { dispatch }); + // }, + // add: + // (data = {}, data2 = {}) => + // async (dispatch) => { + // await proxy.post("book/add", data); + // await proxy.get("book/list", data2, { dispatch }); + // }, + // del: + // (data = {}, data2 = {}) => + // async (dispatch) => { + // await proxy.delete("book/delete", data); + // await proxy.get("book/list", data2, { dispatch }); + // }, + // searchBook: (data) => async (dispatch) => { + // dispatch({ type: "book/search", data: data }); + // }, + // filterBook: (data) => async (dispatch) => { + // dispatch({ type: "book/filter", data: data }); + // }, +}; + +export default book; diff --git a/src/redux/actions/content.js b/src/redux/actions/content.js new file mode 100644 index 0000000..e09c8c8 --- /dev/null +++ b/src/redux/actions/content.js @@ -0,0 +1,14 @@ +import proxy from "../proxy"; +import { Dispatch } from "redux"; +const content = { + listVOD: + (data = {}) => + async (dispatch) => + await proxy.get("content/listVOD", data, { dispatch }), + infoVOD: + (data = {}) => + async (dispatch) => + await proxy.get("content/infoVOD", data, { dispatch }), +}; + +export default content; diff --git a/src/redux/actions/faq.js b/src/redux/actions/faq.js new file mode 100644 index 0000000..aaf031b --- /dev/null +++ b/src/redux/actions/faq.js @@ -0,0 +1,20 @@ +import proxy from "../proxy"; +import { Dispatch } from "redux"; +const faq = { + list: + (data = {}) => + async (dispatch) => + await proxy.get("faq/list", data, { dispatch }), + add: + (data = {}) => + async (dispatch) => + await proxy.post("faq/add", data, { dispatch }), + selectFaq: + (data = {}) => + async (dispatch) => + await dispatch({ type: "faq/selectFaq", data: data }), + searchFaq: (data) => async (dispatch) => + await dispatch({ type: "faq/search", data: data }), +}; + +export default faq; diff --git a/src/redux/actions/file.js b/src/redux/actions/file.js new file mode 100644 index 0000000..02090a1 --- /dev/null +++ b/src/redux/actions/file.js @@ -0,0 +1,22 @@ +import proxy from "../proxy"; +const file = { + upload: + (data = {}) => + async (dispatch) => { + var formData = new FormData(); + for (let key in data) formData.append(key, data[key]); + return await proxy.post( + "file/upload", + formData, + { + dispatch, + headers: { + "Content-Type": "multipart/form-data", + }, + }, + data + ); + }, +}; + +export default file; diff --git a/src/redux/actions/index.js b/src/redux/actions/index.js new file mode 100644 index 0000000..9fd9385 --- /dev/null +++ b/src/redux/actions/index.js @@ -0,0 +1,16 @@ +// @create-index +export { default as publicApi } from "./public"; +export { default as user } from "./user"; +export { default as book } from "./book"; +export { default as blog } from "./blog"; +export { default as product } from "./product"; +export { default as userFactor } from "./userFactor"; +export { default as userProduct } from "./userProduct"; +export { default as content } from "./content"; +export { default as faq } from "./faq"; +export { default as file } from "./file"; + + + + + diff --git a/src/redux/actions/product.js b/src/redux/actions/product.js new file mode 100644 index 0000000..7a770ad --- /dev/null +++ b/src/redux/actions/product.js @@ -0,0 +1,26 @@ +import proxy from "../proxy"; +const product = { + listVOD: + (data = {}) => + async (dispatch) => + await proxy.get("product/listVOD", data, { dispatch }), + addVOD: + (data = {}, data2 = {}) => + async (dispatch) => { + await proxy.post("product/addVOD", data); + await proxy.get("product/listVOD", data2, { dispatch }); + }, + deleteVOD: + (data = {}, data2 = {}) => + async (dispatch) => { + await proxy.delete("product/deleteVOD", data); + await proxy.get("product/listVOD", data2, { dispatch }); + }, + selectVOD: + (data = {}) => + async (dispatch) => { + await dispatch({ type: "product/selectVOD", data }); + }, +}; + +export default product; diff --git a/src/redux/actions/public.js b/src/redux/actions/public.js new file mode 100644 index 0000000..dc69d7b --- /dev/null +++ b/src/redux/actions/public.js @@ -0,0 +1,50 @@ +import proxy from "../proxy"; +const publicApi = { + setIsDark: (data) => async (dispatch) => + await dispatch({ type: "public/setIsDark", data: data }), + getHomeData: (data) => async (dispatch) => + await proxy.get("public/homePage", data, { dispatch }), + + setFaqActive: (data) => async (dispatch) => + await dispatch({ type: "public/faq/activate", data: data }), + bookInfo: + (data = {}) => + async (dispatch) => + await proxy.get("public/vod/bookCourse", data, { dispatch }), + bookSection: + (data = {}) => + async (dispatch) => + await proxy.get("public/vod/bookSection", data, { dispatch }), + getContactData: + (data = {}) => + async (dispatch) => + await proxy.get("public/contact", data, { dispatch }), + + getBlogList: (data) => async (dispatch) => + await proxy.get("public/blogList", data, { dispatch }), + + getBlogInfo: (data) => async (dispatch) => + await proxy.get("public/blogInfo", data, { dispatch }), + setSubscribe: (data) => async (dispatch) => + await dispatch({ type: "public/setSubscribe", data: data }), + getProvince: + (data = {}) => + async (dispatch) => + await proxy.get("public/province", data, { dispatch }), + getCity: + (data = {}) => + async (dispatch) => + await proxy.get("public/city", data, { dispatch }), + selectMenu: (data) => async (dispatch) => + await dispatch({ type: "public/selectMenu", data: data }), + getHeader: + (data = {}) => + async (dispatch) => + await proxy.get("public/VOD/homePage", data, { dispatch }), + activeCategory: (data) => async (dispatch) => + await dispatch({ type: "active/category", data: data }), + setVideoActive: (data) => async (dispatch) => + await dispatch({ type: "active/video", data: data }), +}; + +export default publicApi; diff --git a/src/redux/actions/user.js b/src/redux/actions/user.js new file mode 100644 index 0000000..effe838 --- /dev/null +++ b/src/redux/actions/user.js @@ -0,0 +1,65 @@ +import proxy from "../proxy"; + +const user = { + otp: (data) => async (dispatch) => { + console.log(data); + await proxy.post("public/sendOTP", data, { dispatch }); + }, + + otp_login: (data) => async (dispatch) => + await proxy.login("user/otp/login", data, { dispatch }), + + login: (data) => async (dispatch) => + await proxy.login("user/login", data, { dispatch }), + + // register: (data : undefined) => async (dispatch : Dispatch) => + // await proxy.login("user/register", data, { dispatch }), + + // switchRole: (data : String) => async (dispatch : Dispatch) => + // await proxy.login("user/switchRole", data, { dispatch }), + + logout: (data) => async (dispatch) => + await proxy.logout("user/logout", data, { dispatch }), + + getUserRole: (data) => async (dispatch) => + await proxy.get("user/getUserRole", data, { dispatch }), + + // list: + // (data = {}) => + // async (dispatch : Dispatch) => + // await proxy.get("user/list", data, { dispatch }), + // domains: + // (data = {}) => + // async (dispatch : Dispatch) => + // await proxy.get("user/domains", data, { dispatch }), + // getmothers: + // (data = {}) => + // async (dispatch : Dispatch) => + // await proxy.get("mothers/list", data, { + // dispatch, + // }), + getProfile: + (data = {}) => + async (dispatch) => + await proxy.get("user/getProfile", data, { dispatch }), + setProfile: + (data = {}, data2 = {}) => + async (dispatch) => { + await proxy.put("user/setProfile", data, { dispatch }); + await proxy.get("user/getProfile", data2, { dispatch }); + }, + add: + (data = {}, data2 = {}) => + async (dispatch) => { + await proxy.post("user/add", data); + await proxy.get("user/list", data2, { dispatch }); + }, + del: + (data = {}, data2 = {}) => + async (dispatch) => { + await proxy.delete("user/delete", data); + await proxy.get("user/list", data2, { dispatch }); + }, +}; + +export default user; diff --git a/src/redux/actions/userFactor.js b/src/redux/actions/userFactor.js new file mode 100644 index 0000000..a46962c --- /dev/null +++ b/src/redux/actions/userFactor.js @@ -0,0 +1,55 @@ +import proxy from "../proxy"; +const userFactor = { + //dnvn + list: + (data = {}) => + async (dispatch) => + await proxy.get("userFactor/list", data, { dispatch }), + payment: + (data = {}, data2 = {}) => + async (dispatch) => { + await proxy.post("userFactor/payment", data, { dispatch }); + }, + add: + (data = {}, data2 = {}) => + async (dispatch) => { + await proxy.post("userFactor/add", data, { dispatch }); + await proxy.get("userFactor/list", data2, { dispatch }); + }, + del: + (data = {}, data2 = {}) => + async (dispatch) => { + await proxy.delete("userFactor/delete", data); + await proxy.get("userFactor/list", data2, { dispatch }); + }, + + //vod + payment: + (data1 = {}, data2 = {}) => + async (dispatch) => { + await proxy.post("userProduct/addVOD", data1, { dispatch }); + await proxy.post("userFactor/paymentVOD", data2, { dispatch }); + }, + verify: + (data = {}) => + async (dispatch) => + await proxy.post("userFactor/verifyVOD", data, { dispatch }), + info: + (data = {}) => + async (dispatch) => + await proxy.get("userFactor/info", data, { dispatch }), + update: + (data = {}, data2 = {}) => + async (dispatch) => { + await proxy.put("userFactor/update", data, { dispatch }); + await proxy.get("userFactor/info", data2, { dispatch }); + }, + deleteUserOffCode: + (data = {}, data2 = {}) => + async (dispatch) => { + await proxy.delete("userFactor/deleteUserOffCode", data, { dispatch }); + await proxy.get("userFactor/info", data2, { dispatch }); + }, +}; + +export default userFactor; diff --git a/src/redux/actions/userProduct.js b/src/redux/actions/userProduct.js new file mode 100644 index 0000000..2436d7f --- /dev/null +++ b/src/redux/actions/userProduct.js @@ -0,0 +1,33 @@ +import proxy from "../proxy"; +const userProduct = { + list: + (data = {}) => + async (dispatch) => { + await proxy.get("userProduct/list", data, { dispatch }); + }, + info: + (data = {}) => + async (dispatch) => + await proxy.get("userProduct/info", data, { dispatch }), + update: + (data = {}, data2 = {}) => + async (dispatch) => { + await proxy.put("userProduct/update", data); + await proxy.get("userProduct/list", data2, { dispatch }); + }, + add: + (data = {}, data2 = {}, data3 = {}) => + async (dispatch) => { + await proxy.post("userProduct/add", data, { dispatch }); + await proxy.get("userProduct/list", data2, { dispatch }); + await proxy.get("userFactor/info", data3, { dispatch }); + }, + del: + (data = {}, data2 = {}) => + async (dispatch) => { + await proxy.delete("userProduct/delete", data); + await proxy.get("userProduct/list", data2, { dispatch }); + }, +}; + +export default userProduct; diff --git a/src/redux/index.js b/src/redux/index.js new file mode 100644 index 0000000..5b58979 --- /dev/null +++ b/src/redux/index.js @@ -0,0 +1,6 @@ +// @create-index + +export { default as actions } from './actions'; +export { default as proxy } from './proxy.js'; +export { default as reducers } from './reducers'; +export { default as store } from './store.js'; \ No newline at end of file diff --git a/src/redux/proxy.js b/src/redux/proxy.js new file mode 100644 index 0000000..962faee --- /dev/null +++ b/src/redux/proxy.js @@ -0,0 +1,171 @@ +import { ApiConfig } from "../constants/defaultValues"; +import axios from "axios"; +import AsyncStorage from "@react-native-async-storage/async-storage"; +import { useNavigation } from "@react-navigation/native"; + +let { baseUrl } = ApiConfig; +let access; +() => { + access = AsyncStorage.getItem("access"); +}; + +baseUrl = baseUrl + "/"; + +const Axios = axios.create({ + withCredentials: true, + validateStatus: null, + baseURL: baseUrl, + //headers: access ? { Authorization: `Bearer ${access}` } : {}, +}); +class Proxy { + get = (url, params, opt, data) => { + try { + this.check( + url, + opt, + () => Axios.get(url, { params, ...opt }), + data || params + ); + } catch (error) { + console.log("proxy get error! : ", error); + } + }; + + post = (url, params, opt, data) => { + try { + this.check( + url, + opt, + () => Axios.post(url, params, opt), + data || params + ); + } catch (error) { + console.log("proxy post error! : ", error); + } + }; + + put = (url, params, opt, data) => { + try { + this.check( + url, + opt, + () => Axios.put(url, params, opt), + data || params + ); + } catch (error) { + console.log("proxy put error! : ", error); + } + }; + + delete = (url, params, opt, data) => { + try { + this.check( + url, + opt, + () => Axios.delete(url, { ...opt, data: params }), + data || params + ); + } catch (error) { + console.log("proxy delete error! : ", error); + } + }; + + check = (url, { dispatch }, fetch, params) => { + try { + dispatch = dispatch || (() => {}); + dispatch({ type: url.split("/")[0] + "/" + "loading" }); + let response = fetch(); + switch (response.status) { + case 200: + dispatch({ type: url, data: response.data.data, params }); + return response.data.data; + case 401: + if (this.refresh()) { + let response = fetch(); + dispatch({ type: url, data: response.data.data, params }); + return response.data.data; + } + break; + default: + dispatch({ + type: url.split("/")[0] + "/" + "error", + data: response.data, + params, + }); + } + return false; + } catch (error) { + console.log("proxy check error! : ", error); + } + }; + + refresh = () => { + try { + const navigation = useNavigation(); + let refresh = AsyncStorage.getItem("refresh"); + if (!refresh) navigation.push("Root"); + let login = this.login( + "user/login", + {}, + { headers: { Authorization: `Bearer ${refresh}` } } + ); + return login ? true : false; + } catch (error) { + console.log("proxy refresh error! : ", error); + } + }; + + login = (url, params, { dispatch }) => { + try { + console.log('------------------------------login---------------------------------'); + this.post(url, params, { + dispatch: (obj) => { + let login = obj.data; + console.log('login data: ',login); + if (!login || !login.refreshToken) return false; + const refresh = ["refresh", login.refreshToken]; + const access = ["access", login.accessToken]; + const userData = ["userData", JSON.stringify(login.profile)]; + AsyncStorage.multiSet([refresh, access, userData]); + delete login.refreshToken; + delete login.accessToken; + dispatch(obj); + }, + }); + } catch (error) { + console.log("proxy login error! : ", error); + } + }; + + logout = (url, params, { dispatch }) => { + try { + this.post(url, params, { + dispatch: (obj) => { + const keys = ["refresh", "access", "userData"]; + AsyncStorage.multiRemove(keys); + dispatch(obj); + }, + }); + } catch (error) { + console.log("proxy logout error : ", error); + } + }; + status = () => { + try { + let refresh = AsyncStorage.getItem("refresh"); + let userData = AsyncStorage.getItem("userData"); + if (!refresh) return false; + if (refresh == "undefined") { + const keys = ["refresh", "access", "userData"]; + AsyncStorage.multiRemove(keys); + return false; + } + return userData || null; + } catch (error) { + console.log("proxy status error : ", error); + } + }; +} +const _proxy = new Proxy(); + +export default _proxy; \ No newline at end of file diff --git a/src/redux/reducers/blog.js b/src/redux/reducers/blog.js new file mode 100644 index 0000000..9f3005c --- /dev/null +++ b/src/redux/reducers/blog.js @@ -0,0 +1,26 @@ +const initialState = { + loading: false, + error: null, + list: [], +}; +export default function blog(state = initialState, action) { + let { type, data } = action; + switch (type) { + case "public/blogList": + return { ...state, loading: false, list: data, error: null }; + // case "blog/update": + // return { ...state, loading: false, error: null }; + // case "blog/add": + // return { ...state, loading: false, error: null }; + // case "blog/delete": + // return { ...state, loading: false, error: null }; + ///////////// + case "blog/loading": + return { ...state, loading: true }; + case "blog/error": + // toast.error(data.message); + return { ...state, loading: false, error: data.message }; + default: + return state; + } +} diff --git a/src/redux/reducers/book.js b/src/redux/reducers/book.js new file mode 100644 index 0000000..98d2457 --- /dev/null +++ b/src/redux/reducers/book.js @@ -0,0 +1,167 @@ + +const initialState = { + loading: false, + error: null, + list: [], + info: null, + searchResult: [], + filterResult: [], + subjects: [], + levels: [], + sortFilters: ["مرتب سازی", "محبوب ترین", "جدیدترین"], + selectedVideo: null, + gradeFilterBooks: null, + sortFilterCourse: null, + selectedGrade: null, + selectedSort: "پربازدید ترین ها", +}; + +const grades = [ + "پیش دبستان", + "اول", + "دوم", + "سوم", + "چهارم", + "پنجم", + "ششم", + "هفتم", + "هشتم", + "نهم", + "دهم", + "یازدهم", + "دوازدهم", +]; + +export default function book(state = initialState, action) { + let { type, data } = action; + switch (type) { + case "book/list": + let itemsSubject = (Array.isArray(data) ? data : []).map( + (item, index) => item.name + ); + if (window.innerWidth < 1000) { + itemsSubject.unshift("نام کتاب"); + } + let itemsLevel = (Array.isArray(data) ? data : []) + .map((item) => item.gradeId * 1) + .sort((a, b) => a - b) + .map((e) => grades[e]); + if (window.innerWidth < 1000) { + itemsLevel.unshift("پایه تحصیلی"); + } + return { + ...state, + loading: false, + list: data, + subjects: Array.from(new Set(itemsSubject)), + levels: Array.from(new Set(itemsLevel)), + filterResult: data, + error: null, + }; + case "book/info": + return { ...state, loading: false, info: data, error: null }; + case "book/lesson/active": + return { + ...state, + loading: false, + error: null, + }; + case "book/gradeFilter": + if (data === state.selectedGrade) { + return { ...state, gradeFilterBooks: null, selectedGrade: null }; + } else { + return { + ...state, + gradeFilterBooks: state.list.filter( + (item, i) => grades[item.gradeId] === data + ), + selectedGrade: data, + }; + } + case "book/sortFilter": + const search = state.list.filter( + (item) => item.name.indexOf(data.search) !== -1 + ); + if (data.sort === "تمامی دوره‌ها") { + return { ...state, sortFilterCourse: search, selectedSort: data.sort }; + } else if (data.sort === "جدیدترین‌ها") { + return { + ...state, + sortFilterCourse: search.sort((item1, item2) => { + return item1.publishYear - item2.publishYear; + }), + selectedSort: data.sort, + }; + } + return { ...state, sortFilterCourse: search, selectedSort: data.sort }; + + // case "book/update": + // return { ...state, loading: false, error: null }; + // case "book/add": + // return { ...state, loading: false, error: null }; + // case "book/delete": + // return { ...state, loading: false, error: null }; + // case "book/search": + // return { ...state }; + // case "book/filter": + // const realList = state.list; + // const level = data.level; + // const subject = data.subject; + // const sort = data.sort; + // const search = data.search; + // if (level.length > 0 || subject.length > 0 || sort || search) { + // localStorage.setItem("filter", "ON"); + // } + // let finalSort; + // let byLevelFilter = []; + // if (level.length > 0) { + // level.map((item1) => { + // for (let i = 0; i < realList.length; i++) { + // if (grades[realList[i].gradeId] === item1) { + // byLevelFilter.push(realList[i]); + // } + // } + // }); + // } else { + // byLevelFilter = realList; + // } + + // let bySubjectFilter = []; + // if (subject.length > 0) { + // subject.map((item1) => { + // for (let i = 0; i < byLevelFilter.length; i++) { + // if (byLevelFilter[i].name === item1) { + // bySubjectFilter.push(byLevelFilter[i]); + // } + // } + // }); + // } else { + // bySubjectFilter = byLevelFilter; + // } + + // const bySearchFilter = search + // ? bySubjectFilter.filter((item1) => item1.name.indexOf(search) !== -1) + // : bySubjectFilter; + + // if (sort === "گران ترین") { + // finalSort = bySearchFilter.sort((item1, item2) => { + // return item1.product[0].price - item2.product[0].price; + // }); + // } else { + // finalSort = bySearchFilter; + // } + // return { + // ...state, + // loading: false, + // error: null, + // filterResult: finalSort, + // }; + case "book/loading": + return { ...state, loading: true }; + case "book/error": + // toast.error(data.message); + return { ...state, loading: false, error: data.message }; + default: + return state; + } +} diff --git a/src/redux/reducers/faq.js b/src/redux/reducers/faq.js new file mode 100644 index 0000000..4102b8d --- /dev/null +++ b/src/redux/reducers/faq.js @@ -0,0 +1,56 @@ +const initialState = { + loading: false, + error: null, + list: [], + searchResult: [], + search: null, +}; + +export default function faq(state = initialState, action) { + let { type, data } = action; + switch (type) { + case "faq/list": + return { ...state, loading: false, list: data, error: null }; + case "faq/add": + return { ...state, loading: false, error: null }; + case "faq/selectFaq": + return { + ...state, + loading: false, + error: null, + list: !state.search + ? state.list.map((item) => + item.id === data + ? { ...item, active: !item.active } + : { ...item, active: false } + ) + : state.list, + searchResult: state.search + ? state.searchResult.map((item) => + item.id === data + ? { ...item, active: !item.active } + : { ...item, active: false } + ) + : state.searchResult, + }; + case "faq/search": + return { + ...state, + loading: false, + error: null, + search: data, + searchResult: state.list.filter( + (item) => + item.title.indexOf(data) !== -1 || + item.description.indexOf(data) !== -1 + ), + }; + case "faq/loading": + return { ...state, loading: true }; + case "faq/error": + // toast.error(data.message); + return { ...state, loading: false, error: data.message }; + default: + return state; + } +} diff --git a/src/redux/reducers/file.js b/src/redux/reducers/file.js new file mode 100644 index 0000000..164494c --- /dev/null +++ b/src/redux/reducers/file.js @@ -0,0 +1,26 @@ +const initialState = { + loading: false, + error: null, + uploads: {}, + lastUpload: null, +}; + +export default function file(state = initialState, action) { + let { type, data, params } = action; + switch (type) { + case "file/upload": + return { + ...state, + loading: false, + error: null, + uploads: { ...state.uploads, [params?.target || "last"]: data.id }, + lastUpload: data.id, + }; + case "file/loading": + return { ...state, loading: true }; + case "file/error": + return { ...state, loading: false, error: data.message }; + default: + return state; + } +} diff --git a/src/redux/reducers/index.js b/src/redux/reducers/index.js new file mode 100644 index 0000000..7d836fc --- /dev/null +++ b/src/redux/reducers/index.js @@ -0,0 +1,10 @@ +// @create-index +export { default as publicApi } from "./public"; +export { default as user } from "./user"; +export { default as book } from "./book"; +export { default as blog } from "./blog"; +export { default as product } from "./product"; +export { default as faq } from "./faq"; +export { default as file } from "./file"; +export { default as userFactor } from "./userFactor"; +export { default as userProduct } from "./userProduct"; diff --git a/src/redux/reducers/product.js b/src/redux/reducers/product.js new file mode 100644 index 0000000..23cb8fc --- /dev/null +++ b/src/redux/reducers/product.js @@ -0,0 +1,26 @@ +const initialState = { + loading: false, + error: null, + listVOD: [], + selectedVOD: null, +}; +export default function product(state = initialState, action) { + let { type, data } = action; + switch (type) { + case "product/listVOD": + return { ...state, loading: false, listVOD: data, error: null }; + case "product/addVOD": + return { ...state, loading: false, error: null }; + case "product/deleteVOD": + return { ...state, loading: false, error: null }; + case "product/selectVOD": + return {...state, selectedVOD : data}; + case "product/loading": + return { ...state, loading: true }; + case "product/error": + // toast.error(data.message); + return { ...state, loading: false, error: data.message }; + default: + return state; + } +} diff --git a/src/redux/reducers/public.js b/src/redux/reducers/public.js new file mode 100644 index 0000000..ebcc014 --- /dev/null +++ b/src/redux/reducers/public.js @@ -0,0 +1,169 @@ +import AsyncStorage from "@react-native-async-storage/async-storage"; +import { Dimensions } from "react-native"; + +const width = Dimensions.get("window").width; + +const initialState = { + // isDark: (await AsyncStorage.getItem("isDark")) || false, + homeData: [], + newProducts: [], + levels: [], + loading: false, + error: null, + searchResult: [], + arList: [], + blogList: [], + blog: null, + province: null, + city: null, + departmans: [ + { + id: 0, + name: "محتوا", + }, + { + id: 0, + name: "دیزاین", + }, + { + id: 0, + name: "برنامه نویسی", + }, + ], + header: [], + selectedMenu: null, + contactData: null, + selectedVideo: null, + bookInfo: null, + activeCategory: null, + categories: null, + bookSection: null, + grades: { + 0: "پیش دبستان", + 1: "اول", + 2: "دوم", + 3: "سوم", + 4: "چهارم", + 5: "پنجم", + 6: "ششم", + 7: "هفتم", + 8: "هشتم", + 9: "نهم", + 10: "دهم", + 11: "یازدهم", + 12: "دوازدهم", + }, +}; + +const grades = [ + "پیش دبستان", + "اول", + "دوم", + "سوم", + "چهارم", + "پنجم", + "ششم", + "هفتم", + "هشتم", + "نهم", + "دهم", + "یازدهم", + "دوازدهم", +]; +const publicApi = (state = initialState, action) => { + let { type, data } = action; + switch (type) { + case "public/setIsDark": + // AsyncStorage.setItem("isDark", data); + return { ...state, location: false, error: null, isDark: data }; + case "active/video": + return { + ...state, + loading: false, + error: null, + selectedVideo: data, + }; + case "active/category": + return { + ...state, + loading: false, + activeCategory: state.activeCategory === data ? null : data, + error: null, + }; + case "public/vod/bookSection": + const videoId = location.getId(); + return { + ...state, + loading: false, + bookSection: data, + error: null, + selectedVideo: data.vods?.filter((item) => item.id !== videoId)[0], + }; + + case "public/vod/bookCourse": + let allCats; + allCats = Array.from( + new Set(data.vods.map((item) => item.categoryId && item.categoryId)) + ); + return { + ...state, + loading: false, + bookInfo: { + ...data, + vods: data.vods.map((item) => { + return { ...item, active: false }; + }), + }, + error: null, + categories: allCats.map((item) => + data.vods.filter((item1) => item1.categoryId === item) + ), + selectedVideo: data.vods.filter((item) => item.id !== 1)[0], + }; + case "public/homePage": + let itemsLevel; + if (width > 1000) { + const jadidTarin = data.filter( + (item) => item.title === "جدیدترین کتاب‌های دانوین" + ); + itemsLevel = jadidTarin[0].data + .map((item) => item.book.gradeId * 1) + .sort((a, b) => a - b) + .map((e) => grades[e]); + itemsLevel.unshift("همه"); + } + + return { + ...state, + loading: false, + levels: width > 1000 ? Array.from(new Set(itemsLevel)) : [], + error: null, + homeData: data, + }; + + case "public/contact": + return { ...state, loading: false, error: null, contactData: data }; + case "public/blogList": + return { ...state, loading: false, error: null, blogList: data }; + case "public/blogInfo": + return { ...state, loading: false, error: null, blog: data }; + case "public/setSubscribe": + return { ...state, loading: false, error: null, selectedSubscribe: data }; + case "public/province": + return { ...state, loading: false, error: null, province: data }; + case "public/city": + return { ...state, loading: false, error: null, city: data }; + case "public/selectMenu": + return { ...state, loading: false, error: null, selectedMenu: data }; + case "public/VOD/homePage": + return { ...state, loading: false, error: null, header: data }; + case "loading": + return { ...state, loading: true }; + case "error": + return { ...state, loading: false, error: data.message }; + default: + return state; + } +}; + +export default publicApi; \ No newline at end of file diff --git a/src/redux/reducers/user.js b/src/redux/reducers/user.js new file mode 100644 index 0000000..a0b8d2c --- /dev/null +++ b/src/redux/reducers/user.js @@ -0,0 +1,64 @@ +import proxy from "../proxy"; +import AsyncStorage from "@react-native-async-storage/async-storage"; + +let initialState = { + status: proxy.status(), + loading: false, + error: null, + list: null, + domains: [], + mothers: [], + profileStatus: false, + setDone: false, + setLogin: false, + check : 'check' +}; + +const user = (state = initialState, action) => { + let { type, data } = action; + switch (type) { + // case "user/login": + // case "user/register": + // case "user/switchRole": + case "public/sendOTP": + return { ...state, loading: false, error: null }; + case "user/login": + case "user/otp/login": + return { + ...state, + loading: false, + status: data.profile, + error: null, + setLogin: !state.setLogin, + }; + case "user/getProfile": + const myData = JSON.stringify(data); + try{ + AsyncStorage.setItem("userData", myData); + }catch(error){ + console.log('user/getProfile', error); + } + return { + ...state, + loading: false, + status: data, + error: null, + setDone: false, + }; + case "user/logout": + return { ...state, loading: false, status: proxy.status(), error: null }; + case "user/getUserRole": + return { ...state, loading: false, userRoles: data, error: null }; + case "user/setProfile": + // toast.success("تغییرات اعمال شد."); + return { ...state, loading: false, error: null, setDone: true }; + case "loading": + return { ...state, loading: true }; + case "error": + return { ...state, loading: false, error: data.message }; + default: + return state; + } +} + +export default user; \ No newline at end of file diff --git a/src/redux/reducers/userFactor.js b/src/redux/reducers/userFactor.js new file mode 100644 index 0000000..8598ee5 --- /dev/null +++ b/src/redux/reducers/userFactor.js @@ -0,0 +1,60 @@ +import {useNavigation} from '@react-navigation/native'; + +const initialState = { + loading: false, + error: null, + list: null, + info: null, + sum: null, + checkEmpty: false, + isVerified: null, +}; +export default function userFactor(state = initialState, action) { + // const navigation = useNavigation(); + + let { type, data } = action; + switch (type) { + //dnvn + case "userFactor/list": + const checkEmpty = data.filter( + (item) => item.condition === 2 && item.product.productType === (1 || 3) + ); + return { + ...state, + loading: false, + list: data, + checkEmpty: checkEmpty.length > 0 ? false : true, + error: null, + }; + case "userFactor/info": + return { ...state, loading: false, info: data, error: null }; + case "userFactor/add": + // toast.success("درخواست شما با موفقیت انجام شد."); + return { ...state, loading: false, error: null, sum: data.payPrice }; + case "userFactor/delete": + return { ...state, loading: false, error: null }; + case "userFactor/payment": + // navigation.push(data); + return { ...state, loading: false, error: null }; + //vod + case "userFactor/myList": + return { ...state, loading: false, list: data, error: null }; + case "userFactor/update": + // toast.success("درخواست شما با موفقیت انجام شد."); + return { ...state, loading: false, error: null }; + case "userFactor/deleteUserOffCode": + return { ...state, loading: false, error: null }; + case "userFactor/paymentVOD": + // navigation.push(data); + return { ...state, loading: false, error: null, isVerified: false }; + case "userFactor/verifyVOD": + return { ...state, loading: false, error: null, isVerified: true }; + case "userFactor/loading": + return { ...state, loading: true }; + case "userFactor/error": + // toast.error(data.message); + return { ...state, loading: false, error: data.message }; + default: + return state; + } +} diff --git a/src/redux/reducers/userProduct.js b/src/redux/reducers/userProduct.js new file mode 100644 index 0000000..7524513 --- /dev/null +++ b/src/redux/reducers/userProduct.js @@ -0,0 +1,48 @@ +const initialState = { + loading: false, + error: null, + list: [], + info: null, + sum: null, + checkEmpty: false, + hasPhysical: false, +}; +export default function userFactor(state = initialState, action) { + let { type, data } = action; + switch (type) { + case "userProduct/list": + const checkEmpty = data.filter( + (item) => item.condition === 2 && item.product.productType === (1 || 3) + ); + const hasPhysical = + data.filter((item) => item.product.productType === 2).length > 0 + ? true + : false; + return { + ...state, + loading: false, + list: data, + checkEmpty: checkEmpty.length > 0 ? false : true, + error: null, + hasPhysical: hasPhysical, + }; + case "userProduct/info": + return { ...state, loading: false, info: data, error: null }; + case "userProduct/update": + return { ...state, loading: false, error: null }; + case "userProduct/add": + // if (window.location.pathname.indexOf("products") !== -1) { + // toast.success("درخواست شما با موفقیت انجام شد."); + // } + return { ...state, loading: false, error: null, sum: data.payPrice }; + case "userProduct/delete": + return { ...state, loading: false, error: null }; + case "userProduct/loading": + return { ...state, loading: true }; + case "userProduct/error": + // toast.error(data.message); + return { ...state, loading: false, error: data.message }; + default: + return state; + } +} diff --git a/src/redux/store.js b/src/redux/store.js index 32172bb..1b8b3b7 100644 --- a/src/redux/store.js +++ b/src/redux/store.js @@ -1,10 +1,18 @@ import AsyncStorage from "@react-native-async-storage/async-storage"; -import { applyMiddleware, createStore, compose } from "redux"; +import { applyMiddleware, createStore, compose, combineReducers } from "redux"; import { createLogger } from "redux-logger"; import thunk from "redux-thunk"; import { persistStore, persistReducer } from "redux-persist"; import autoMergeLevel2 from "redux-persist/lib/stateReconciler/autoMergeLevel2"; -import allReducers from "../reducers"; +import publicApi from "./reducers/public"; +import user from "./reducers/user"; +import book from "./reducers/book"; +import blog from "./reducers/blog"; +import product from "./reducers/product"; +import faq from "./reducers/faq"; +import file from "./reducers/file"; +import userFactor from "./reducers/userFactor"; +import userProduct from "./reducers/userProduct"; const persistConfig = { key: "root", @@ -12,18 +20,34 @@ const persistConfig = { stateReconciler: autoMergeLevel2, // see "Merge Process" section for details. whitelist: ["profile"], }; -const pReducer = persistReducer(persistConfig, allReducers); -const middleWare = []; +const initialState = {}; -middleWare.push(thunk); +const middleWare = [thunk]; const loggerMiddleware = createLogger({ predicate: () => process.env.NODE_ENV === "development", }); middleWare.push(loggerMiddleware); -const store = createStore(pReducer, compose(applyMiddleware(...middleWare))); +const store = createStore( + persistReducer( + persistConfig, + combineReducers({ + publicApi, + user, + book, + blog, + product, + faq, + file, + userFactor, + userProduct, + }) + ), + initialState, + compose(applyMiddleware(...middleWare)) +); const persistor = persistStore(store); @@ -32,9 +56,9 @@ try { ReactNative.I18nManager.allowRTL(true); // enableScreens(); } catch (e) { - console.log(e); + // console.log(e); } -console.disableYellowBox = true; +// console.disableYellowBox = true; -export default store; \ No newline at end of file +export default store; diff --git a/src/screens/Home/components/Scroll.js b/src/screens/Home/components/Scroll.js index 753d938..bbe34c6 100644 --- a/src/screens/Home/components/Scroll.js +++ b/src/screens/Home/components/Scroll.js @@ -25,7 +25,7 @@ function Scroll({ products }) { horizontal={true} inverted={true} style={[tw("mt-3 pb-2")]} - data={[{}]} + data={[{id : 0}]} renderItem={({}) => } keyExtractor={(item) => item.id} /> diff --git a/src/screens/Login/index.js b/src/screens/Login/index.js index 994fe5e..bed06f3 100644 --- a/src/screens/Login/index.js +++ b/src/screens/Login/index.js @@ -1,57 +1,46 @@ import React, { useState } from "react"; +import {connect} from 'react-redux'; + import { View, Text, Image, ActivityIndicator, Dimensions, - TextInput, TouchableHighlight, } from "react-native"; import Logo from "./assets/logo.png"; import CustomTextInput from "../../components/CustomTextInput"; -import { digitToEn, digitToPersian } from "../../utils"; -import services from "./services"; +import onInput from '../../utils/onInput'; import { asyncAwesomeAlert } from "../../utils/AsyncWrappers"; import tw from "tailwind-rn"; +import {user} from '../../redux/actions'; const { width, height } = Dimensions.get("window"); -let faNums = ["۱", "۲", "۳", "۴", "۵", "۶", "۷", "۸", "۹", "۰"]; function Login(props) { const [phone, setPhone] = useState(""); const [loading, setLoading] = useState(false); const onChangePhone = (name, value) => { - let items = digitToPersian(value).split(""); - for (let item of items) { - if (!faNums.includes(item)) { - return; - } - } - setPhone(digitToPersian(value)); + setPhone(() => value); }; const checkPhoneNumber = () => { - return phone.split("").length === 11; + return phone.split("").length === 11 && phone.slice(0, 2) === '09'; }; const submit = async () => { - setLoading(true); - if (!checkPhoneNumber()) { - setLoading(false); - return asyncAwesomeAlert("خطا", "شماره وارد شده اشتباه است", { - showCancelButton: false, - }); - } - let res = await services.getSmsCode({ - cellphone: digitToEn(phone), - }); - if (res.ok) { - setLoading(false); - props.navigation.navigate("Otp", { phone: digitToEn(phone) }); - } - setLoading(false); + // setLoading(true); + // if (!checkPhoneNumber()) { + // setLoading(false); + // return asyncAwesomeAlert("خطا", "شماره وارد شده اشتباه است", { + // showCancelButton: false, + // }); + // } + // props.sendPhoneNumber({cellphone : phone}); + props.navigation.navigate("Otp", { phone: '09360467907' }); + // setLoading(false); }; return ( @@ -99,6 +88,7 @@ function Login(props) { value={phone} onChange={onChangePhone} autoFocus={true} + regex={onInput.phonenumber} /> ({ + +}) + +const mapDispatchToProps = { + sendPhoneNumber : user.otp +} + +export default connect(mapStateToProps, mapDispatchToProps)(Login); + diff --git a/src/screens/Login/services/index.js b/src/screens/Login/services/index.js deleted file mode 100644 index 60ef7d3..0000000 --- a/src/screens/Login/services/index.js +++ /dev/null @@ -1,10 +0,0 @@ -import mocks from './mocks'; -import mainServices from './services'; - -const mock = false; - -let services = {...mainServices}; -if (mock) { - services = mocks; -} -export default services; diff --git a/src/screens/Login/services/mocks.js b/src/screens/Login/services/mocks.js deleted file mode 100644 index 73017ff..0000000 --- a/src/screens/Login/services/mocks.js +++ /dev/null @@ -1,18 +0,0 @@ -import { asyncAwesomeAlert, randomApiSleep } from '../../../utils/AsyncWrappers'; - -const data = { - -}; - -const getSmsCode = async () => { - await randomApiSleep(); - return { - ok: true, - data: data - }; -}; - - - -const mocks = {getSmsCode}; -export default mocks; diff --git a/src/screens/Login/services/services.js b/src/screens/Login/services/services.js deleted file mode 100644 index 8f59758..0000000 --- a/src/screens/Login/services/services.js +++ /dev/null @@ -1,13 +0,0 @@ -import {nextFetchApi} from '../../../services/api'; -const getSmsCode = async (obj) => { - return await nextFetchApi('/public/sendOTP', { - method: 'POST', - payload: obj - }); -}; - -const mainServices = { - getSmsCode, -}; - -export default mainServices; diff --git a/src/screens/Otp/index.js b/src/screens/Otp/index.js index 3845097..e5bc624 100644 --- a/src/screens/Otp/index.js +++ b/src/screens/Otp/index.js @@ -4,21 +4,16 @@ import { Text, Image, TextInput, - TouchableHighlight, Dimensions, - StyleSheet, TouchableOpacity, ActivityIndicator, } from "react-native"; import tw from "tailwind-rn"; -import AsyncStorage from "@react-native-async-storage/async-storage"; import { connect } from "react-redux"; import Logo from "../Login/assets/logo.png"; -import IranFlag from "../Login/components/IranFlag"; -import { digitToEn, digitToPersian } from "../../utils"; -import services from "./services"; -import { buildAction } from "../../reducers/DefaultReducer"; -import { PROFILE_RECORD } from "../../actions/actionTypes"; +import { digitToEn } from "../../utils"; +import onInput from "../../utils/onInput"; +import {user} from '../../redux/actions'; const { width } = Dimensions.get("window"); let ref1; @@ -28,15 +23,7 @@ let ref4; let timer = 60; -const mapStateToProps = (state) => { - return { - profile: state.profile, - }; -}; - function Otp(props) { - let faNums = ["۱", "۲", "۳", "۴", "۵", "۶", "۷", "۸", "۹", "۰"]; - const [firstCode, setFirstCode] = useState(""); const [secondCode, setSecondCode] = useState(""); const [thirdCode, setThirdCode] = useState(""); @@ -44,20 +31,7 @@ function Otp(props) { const [time, setTime] = useState(60); const [loading, setLoading] = useState(false); - // useEffect(() => { - // if (fourthCode) { - // submit(); - // } - // }, [fourthCode]); - - const checkValue = (value) => { - return faNums.includes(digitToPersian(value)); - }; - const onChangeCode = (value, key) => { - // if (!checkValue()) { - // return - // } switch (key) { case "1": setFirstCode(value); @@ -104,39 +78,17 @@ function Otp(props) { const submit = async () => { setLoading(true); - let res = await services.sendOtpCode({ + props.sendOtp({ cellphone: props.route.params.phone, otp: String(getEnCode()), applicationToken: "1", userToken: "1", }); - console.log( - digitToEn(firstCode) + - digitToEn(secondCode) + - digitToEn(thirdCode) + - digitToEn(fourthCode) - ); - if (res.ok) { - setLoading(false); - await AsyncStorage.setItem("accessToken", res.data.accessToken); - await AsyncStorage.setItem("refreshToken", res.data.refreshToken); - let action = buildAction(PROFILE_RECORD); - await props.dispatch( - action({ - accessToken: res.data.accessToken, - refreshToken: res.data.refreshToken, - ...res.data.profile, - }) - ); - props.navigation.reset({ - index: 0, - routes: [{ name: "Root" }], - }); - } setLoading(false); }; useEffect(() => { + ref1.focus(); let interval = setInterval(() => { if (time > 0) { setTime(timer - 1); @@ -152,6 +104,12 @@ function Otp(props) { }; }, []); + // useEffect(() => { + // if (props.isLogin) { + // props.navigation.navigate('Root'); + // } + // }, [props.isLogin]); + return ( (ref1 = ref)} - onChangeText={(text) => onChangeCode(text, "1")} + onChangeText={(text) => + onChangeCode(text, "1") + } /> (ref2 = ref)} - onChangeText={(text) => onChangeCode(text, "2")} + onChangeText={(text) => + onChangeCode(text, "2") + } /> (ref3 = ref)} - onChangeText={(text) => onChangeCode(text, "3")} + onChangeText={(text) => + onChangeCode(text, "3") + } /> (ref4 = ref)} - onChangeText={(text) => onChangeCode(text, "4")} + onChangeText={(text) => + onChangeCode(text, "4") + } /> { - props.navigation.reset({ - index: 0, - routes: [{ name: "Login" }], - }); - }} + onPress={() => props.navigation.navigate("Login")} > ({ + isLogin: state.user.status, +}); + +const mapDispatchToProps = { + sendOtp: user.otp_login, +}; + +export default connect(mapStateToProps, mapDispatchToProps)(Otp); diff --git a/src/screens/Otp/services/index.js b/src/screens/Otp/services/index.js deleted file mode 100644 index 60ef7d3..0000000 --- a/src/screens/Otp/services/index.js +++ /dev/null @@ -1,10 +0,0 @@ -import mocks from './mocks'; -import mainServices from './services'; - -const mock = false; - -let services = {...mainServices}; -if (mock) { - services = mocks; -} -export default services; diff --git a/src/screens/Otp/services/mocks.js b/src/screens/Otp/services/mocks.js deleted file mode 100644 index 726bd43..0000000 --- a/src/screens/Otp/services/mocks.js +++ /dev/null @@ -1,18 +0,0 @@ -import { asyncAwesomeAlert, randomApiSleep } from '../../../utils/AsyncWrappers'; - -const data = { - -}; - -const sendOtpCode = async () => { - await randomApiSleep(); - return { - ok: true, - data: data - }; -}; - - - -const mocks = {sendOtpCode}; -export default mocks; diff --git a/src/screens/Otp/services/services.js b/src/screens/Otp/services/services.js deleted file mode 100644 index 599f685..0000000 --- a/src/screens/Otp/services/services.js +++ /dev/null @@ -1,13 +0,0 @@ -import {nextFetchApi} from '../../../services/api'; -const sendOtpCode = async (obj) => { - return await nextFetchApi('/user/otp/login', { - method: 'POST', - payload: obj - }); -}; - -const mainServices = { - sendOtpCode, -}; - -export default mainServices; diff --git a/src/screens/Product/components/Comments.js b/src/screens/Product/components/Comments.js index c887d45..dd2e4f1 100644 --- a/src/screens/Product/components/Comments.js +++ b/src/screens/Product/components/Comments.js @@ -5,7 +5,6 @@ import tw from "tailwind-rn"; const width = Dimensions.get("window").width; export default function Commnets({ comments }) { - console.log(comments); return ( { - console.log(comment); return ( { - return { - profile: state.profile, - }; -}; - -function Splash({ navigation, profile }) { +function Splash({ navigation, isLogin, loading}) { + useEffect(() => { setTimeout(() => { - !profile.accessToken - ? navigation.reset({ - index: 0, - routes: [{ name: "Login" }], - }) - : navigation.reset({ - index: 0, - routes: [{ name: "Root" }], - }); + !isLogin + ? navigation.navigate('Login') + : navigation.navigate('Root'); }, 2000); - }, [profile]); + + }, [isLogin]); + return ( @@ -40,4 +31,11 @@ function Splash({ navigation, profile }) { ); } -export default connect(mapStateToProps)(Splash); +const mapStateToProps = (state) => ({ + isLogin: state.user.status, + loading : state.userProduct.loading, +}); + +const mapDispatchToProps = {}; + +export default connect(mapStateToProps, mapDispatchToProps)(Splash); diff --git a/src/screens/Videos/index.js b/src/screens/Videos/index.js index e42b80d..43a1710 100644 --- a/src/screens/Videos/index.js +++ b/src/screens/Videos/index.js @@ -1,13 +1,68 @@ -import React from 'react' -import { View, Text } from 'react-native'; -import {connect} from 'react-redux'; - -function Videos({}) { - return ( - - - - ) +import React, { useState } from "react"; +import { + View, + StyleSheet, + Dimensions, + ScrollView, + SafeAreaView, + StatusBar, + Platform, + LayoutAnimation +} from "react-native"; +import tw from "tailwind-react-native-classnames"; +import Navbar from "../../components/Navbar"; +import Drawer from "../../components/Drawer"; +import Search from "../../components/Search"; + +//assets + +const width = Dimensions.get("window").width; + +function Videos(props) { + const [search, setSearch] = useState(""); + const [position, setPosition] = useState("100%"); + + const setBoxPosition = () => { + LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut); + setPosition(position === "100%" ? "0%" : "100%"); + }; + + return ( + + + + + + + + ); } +// Later on in your styles.. +const styles = StyleSheet.create({ + contentContainerStyle: { + paddingBottom: 100, + alignItems: "flex-end", + }, + container: { + width: Dimensions.get("window").width, + backgroundColor: "white", + flexDirection: "column", + paddingVertical: 0, + paddingHorizontal: 16, + }, +}); + export default Videos; diff --git a/src/services/api/config.js b/src/services/api/config.js deleted file mode 100644 index d57c317..0000000 --- a/src/services/api/config.js +++ /dev/null @@ -1,3 +0,0 @@ -export default { - dev: 'https://dnvn.ir/api/v1', -}; diff --git a/src/services/api/fetch-retry.js b/src/services/api/fetch-retry.js deleted file mode 100644 index 0af96dc..0000000 --- a/src/services/api/fetch-retry.js +++ /dev/null @@ -1,118 +0,0 @@ -'use strict'; - -module.exports = function (fetch, defaults) { - defaults = defaults || {}; - if (typeof fetch !== 'function') { - throw new ArgumentError('fetch must be a function'); - } - - if (typeof defaults !== 'object') { - throw new ArgumentError('defaults must be an object'); - } - - if (defaults.retries !== undefined && !isPositiveInteger(defaults.retries)) { - throw new ArgumentError('retries must be a positive integer'); - } - - if (defaults.retryDelay !== undefined && !isPositiveInteger(defaults.retryDelay) && typeof defaults.retryDelay !== 'function') { - throw new ArgumentError('retryDelay must be a positive integer or a function returning a positive integer'); - } - - if (defaults.retryOn !== undefined && !Array.isArray(defaults.retryOn) && typeof defaults.retryOn !== 'function') { - throw new ArgumentError('retryOn property expects an array or function'); - } - - var baseDefaults = { - retries: 3, - retryDelay: 1000, - retryOn: [500, 502, 503, 504], - }; - - defaults = Object.assign(baseDefaults, defaults); - - return function fetchRetry(input, init) { - var retries = defaults.retries; - var retryDelay = defaults.retryDelay; - var retryOn = defaults.retryOn; - - if (init && init.retries !== undefined) { - if (isPositiveInteger(init.retries)) { - retries = init.retries; - } else { - throw new ArgumentError('retries must be a positive integer'); - } - } - - if (init && init.retryDelay !== undefined) { - if (isPositiveInteger(init.retryDelay) || (typeof init.retryDelay === 'function')) { - retryDelay = init.retryDelay; - } else { - throw new ArgumentError('retryDelay must be a positive integer or a function returning a positive integer'); - } - } - - if (init && init.retryOn) { - if (Array.isArray(init.retryOn) || (typeof init.retryOn === 'function')) { - retryOn = init.retryOn; - } else { - throw new ArgumentError('retryOn property expects an array or function'); - } - } - - // eslint-disable-next-line no-undef - return new Promise(function (resolve, reject) { - var wrappedFetch = function (attempt) { - fetch(input, init) - .then(function (response) { - if (Array.isArray(retryOn) && retryOn.indexOf(response.status) === -1) { - resolve(response); - } else if (typeof retryOn === 'function') { - if (retryOn(attempt, null, response)) { - retry(attempt, null, response); - } else { - resolve(response); - } - } else { - if (attempt < retries) { - retry(attempt, null, response); - } else { - resolve(response); - } - } - }) - .catch(function (error) { - if (typeof retryOn === 'function') { - if (retryOn(attempt, error, null)) { - retry(attempt, error, null); - } else { - reject(error); - } - } else if (attempt < retries) { - retry(attempt, error, null); - } else { - reject(error); - } - }); - }; - - function retry(attempt, error, response) { - var delay = (typeof retryDelay === 'function') ? - retryDelay(attempt, error, response) : retryDelay; - setTimeout(function () { - wrappedFetch(++attempt); - }, delay); - } - - wrappedFetch(0); - }); - }; -}; - -function isPositiveInteger(value) { - return Number.isInteger(value) && value >= 0; -} - -function ArgumentError(message) { - this.name = 'ArgumentError'; - this.message = message; -} \ No newline at end of file diff --git a/src/services/api/index.js b/src/services/api/index.js deleted file mode 100644 index 138586b..0000000 --- a/src/services/api/index.js +++ /dev/null @@ -1,149 +0,0 @@ -import {Alert} from 'react-native'; -import {toastMessage} from '../../utils/message'; -import { - restartApp, - getToken, - deviceHeaders, - getUrl, - isUnexpected, - renewTokenHandler, - resetApp, - networkAlert, - unexpectedAlert, -} from './utils'; -import FetchRetry from './fetch-retry'; -import {asyncApiAwesomeAlert} from '../../utils/AsyncWrappers'; - -const fetchRetry = FetchRetry(fetch, {}); -let deviceInfo; - -export async function fetchApi( - endPoint, - payload = {}, - method = 'GET', - headers = {}, - isS = false, - splash = false, - dev = 'production', -) { - var timeout = setTimeout(() => { - console.log(endPoint, ' TIMEOUT '); - asyncApiAwesomeAlert('خطای ارتباط', '. لطفا اینترنت خود را بررسی کنید .').then( - async () => await fetchApi(endPoint, payload, method, headers, isS), - ); - }, 30000); - if (!deviceInfo) { - deviceInfo = await deviceHeaders(); - if (!deviceInfo) { - deviceInfo = []; - } - } - let options = { - method, - headers: { - Accept: 'application/json;charset=utf-8', - 'Content-Type': 'application/json;charset=utf-8', - Authorization: await getToken(), - ...deviceInfo, - ...headers, - }, - }; - if (['POST', 'PUT'].includes(method)) { - options.body = JSON.stringify(payload); - } - console.log('===========================') - console.log(await getUrl(endPoint, dev)) - console.log(options) - console.log('===========================') - try { - // console.log('req', await getUrl(endPoint), options) - let res = await fetchRetry(await getUrl(endPoint, dev), options); - - clearTimeout(timeout); - let statusCode = res.status; - // console.log('RES', { statusCode, url: await getUrl(endPoint) }) - if (isUnexpected(statusCode)) { - console.log('unexpected', await res.json()); - console.log('RES-unexpected', {statusCode, url: await getUrl(endPoint)}); - let check = await unexpectedAlert(); - - return await fetchApi( - endPoint, - payload, - method, - headers, - isS, - false, - true, - ); - } - let {data, error, status} = await res.json(); - if (res.ok) { - return data; - } - if (!res.ok) { - // if (data.hasOwnProperty('message')) { - // toastMessage(data.message); - // } - console.log('=====================') - console.log(statusCode) - console.log(data) - console.log(error) - console.log('=====================') - if (statusCode === 403) { - console.log('req-401', await getUrl(endPoint), options); - - return resetApp(); - } - if (statusCode === 401) { - let checkRenew = await renewTokenHandler(); - if (!checkRenew.ok && checkRenew.restart) { - console.log('req-401', await getUrl(endPoint), options); - - resetApp(); - } else if (!checkRenew.ok) { - console.log('req-401', await getUrl(endPoint), options); - - restartApp(); - } - return await fetchApi(endPoint, payload, method, headers, isS, splash); - } - if (statusCode === 400) { - return error; - } - return data; - } - } catch (err) { - clearTimeout(timeout); - console.log('catch', endPoint, err); - // global.globalAlert({ - // show: true - // }) - let check = await networkAlert(); - return await fetchApi(endPoint, payload, method, headers, isS); - } -} -/** - * next version of fetch API - * @param {String} endPoint - * @param {Object} options - * @param {string} options.method - * @param {string} options.payload - * @param {string} options.headers - * @param {Boolean} options.splash - */ -export async function nextFetchApi(endPoint, options = {}) { - let {payload, method, headers, isS, splash} = options; - try { - let res = await fetchApi(endPoint, payload, method, headers, isS, splash); - return { - ok: true, - data: res, - }; - } catch (error) { - return { - ok: false, - data: error, - }; - } -} diff --git a/src/services/api/oldindex.js b/src/services/api/oldindex.js deleted file mode 100644 index 3c1cc4d..0000000 --- a/src/services/api/oldindex.js +++ /dev/null @@ -1,203 +0,0 @@ -/* global fetch */ - -import apiConfig from './config'; -import { - Alert, - AlertIOS, - Platform, - ToastAndroid, -} from 'react-native'; -import AsyncStorage from '@react-native-async-storage/async-storage'; -import {toastMessage} from '../../utils/message'; - -import RNRestart from 'react-native-restart'; -import config from './config'; -import Refresh from './fetch-retry'; -import FetchRetry from './fetch-retry'; -let fetchRetry = FetchRetry(fetch, {}); - -function restartApp() { - AsyncStorage.setItem('UID_USER', JSON.stringify({}), () => { - RNRestart.Restart(); - }); -} - -export function fetchApi( - endPoint, - payload = {}, - method = 'GET', - headers = {}, - isS = false, - splash = false, -) { - return new Promise((resolve, reject) => { - var timeout = setTimeout(() => { - console.log(endPoint, ' TIMEOUT '); - Alert.alert('خطای ارتباط', 'خطایی ارتباط با سرور پیش امده .', [ - { - text: 'تلاش مجدد', - onPress: () => - resolve(fetchApi(endPoint, payload, method, headers, isS)), - }, - ]); - }, 10000); - - AsyncStorage.getItem('UID_USER', (err, result) => { - var tokens = ''; - var refreshTokens = ''; - var userDATA = JSON.parse(result); - var headrsRequest = {}; - - if ( - userDATA != null && - userDATA.token != null && - userDATA.token != '' && - isS - ) { - tokens = userDATA.token; - - refreshTokens = userDATA.refresh_token; - headers = { - Authorization: 'Bearer ' + tokens, - }; - } - - if (method === 'POST' || method === 'PUT') { - headrsRequest = { - method: method, - headers: { - Accept: 'application/json;charset=utf-8', - 'Content-Type': 'application/json;charset=utf-8', - ...headers, - }, - body: JSON.stringify(payload), - }; - } else { - headrsRequest = { - method: method, - headers: { - Accept: 'application/json;charset=utf-8', - 'Content-Type': 'application/json;charset=utf-8', - ...headers, - }, - }; - } - - AsyncStorage.getItem('SPLASH_DATA', (err, result) => { - var splashDATA = JSON.parse(result); - - var baseUrl; - - if (endPoint.includes('splash')) { - baseUrl = apiConfig.splash; - } else { - var baseUrl = splashDATA.base_urls.backend + '/v1.1'; - } - - fetchRetry(`${baseUrl}${endPoint}`, headrsRequest) - .then(response => { - const statusCode = response.status; - const data = response.json(); - return Promise.all([statusCode, data]); - }) - .then(([statusCode, data]) => { - console.log(baseUrl + endPoint, statusCode, data); - if (data.hasOwnProperty('message')) { - toastMessage(data.message); - } - - if (statusCode === 403) { - clearTimeout(timeout); - restartApp(); - } - - if (statusCode === 401) { - clearTimeout(timeout); - - var dataaaaa = { - method: 'POST', - body: JSON.stringify({ - refresh_token: refreshTokens, - }), - headers: { - Accept: 'application/json;charset=utf-8', - 'Content-Type': 'application/json;charset=utf-8', - }, - }; - - fetchRetry(`${baseUrl}/auth/renew-token`, dataaaaa) - .then(response1 => { - const statusCode1 = response1.status; - const data1 = response1.json(); - return Promise.all([statusCode1, data1]); - }) - .then(([statusCode1, data1]) => { - console.log( - 'refresh token call and response is ', - statusCode1, - data1, - refreshTokens, - ); - - if (statusCode1 == 200) { - userDATA.token = data1.data.token; - AsyncStorage.setItem( - 'UID_USER', - JSON.stringify(userDATA), - () => { - resolve( - fetchApi(endPoint, payload, method, headers, isS), - ); - }, - ); - } else { - restartApp(); - } - }) - .catch(e => restartApp()); - } - - if (statusCode === 400) { - toastMessage(data.error.message); - clearTimeout(timeout); - - reject(data.error); - } - - if (statusCode === 200) { - clearTimeout(timeout); - resolve(data.data); - } - - if (statusCode === 201) { - clearTimeout(timeout); - resolve(data.data); - } - - return data; - }) - .catch(async e => { - console.log('e', error.message); - let res = await neto(); - if (e.networkError) { - toastMessage('اشکال در اتصال اینترنت دوباره تلاش کنید .'); - Alert.alert( - 'اینترنت', - 'اشکال در اتصال اینترنت دوباره تلاش کنید .', - [ - { - text: 'تلاش مجدد', - onPress: () => - resolve( - fetchApi(endPoint, payload, method, headers, isS), - ), - }, - {text: 'بیخیال', onPress: () => reject(e)}, - ], - ); - } - }); - }); - }); - }); -} diff --git a/src/services/api/utils.js b/src/services/api/utils.js deleted file mode 100644 index 605b433..0000000 --- a/src/services/api/utils.js +++ /dev/null @@ -1,145 +0,0 @@ -import RNRestart from 'react-native-restart'; -import { toastMessage } from "../../utils/message" -import { asyncAlert, asyncAwesomeAlert, asyncApiAwesomeAlert } from "../../utils/AsyncWrappers"; -import * as Device from 'expo-device'; -import { - ImageBackground, - Text, - Image, - View, - SafeAreaView, - StyleSheet, - BackHandler, - Platform, -} from 'react-native'; -import AsyncStorage from '@react-native-async-storage/async-storage'; -import apiConfig from './config'; -import FetchRetry from './fetch-retry' -import { nextFetchApi } from '.'; - -const fetchRetry = FetchRetry(fetch, {}) - -export const restartApp = () => { - RNRestart.Restart() -} -export const resetApp = () => { - AsyncStorage.setItem('UID_USER', JSON.stringify({}), () => { - RNRestart.Restart() - }); -} -export const networkAlert = async () => { - return await asyncApiAwesomeAlert("خطا", "خطا در اتصال به اینترنت", { - confirmText: "تلاش مجدد" - }) -} -export const unexpectedAlert = async () => { - return await asyncApiAwesomeAlert("خطا", "خطای داخلی سرور!", { - confirmText: "تلاش مجدد" - }) - // return await asyncAlert("خطا","خطای داخلی سرور!", [ - // { text: "تلاش مجدد", value: 'retry' }, - // // { text: "بیخیال", value: 'ignore' } - // ]) -} -export const getToken = async () => { - let token = await AsyncStorage.getItem('accessToken') - if (!token) { - return '' - } - return 'Bearer ' + token -} -export const deviceHeaders = async () => { - return { - 'dev-os': Platform.OS, - 'dev-app-version': '1.6.0', - 'dev-os-version': Platform.Version + '', - 'dev-phone-manufacturer': Device.brand, - 'dev-phone-model': Device.modelName, - 'dev-phone-hash': Device.modelId, - } -} -export const getUrl = async (endpoint, dev) => { - if (endpoint.includes('splash')) { - if (dev === 'dev') { - return apiConfig.dev + endpoint - } - return apiConfig.splash + endpoint - } - let base_urls = await getBaseUrls() - return base_urls + endpoint -} - -export const isUnexpected = (statusCode) => { - if (![200, 201, 400, 401, 403].includes(statusCode)) return true - return false -} -export const renewTokenHandler = async () => { - try { - let refreshToken = JSON.parse(await AsyncStorage.getItem('refreshToken')) - if (!refreshToken) { - return { - ok: false, - restart: true - } - } - const options = { - method: 'POST', - body: JSON.stringify({ - refresh_token: refreshToken - }), - headers: { - Accept: 'application/json;charset=utf-8', - 'Content-Type': 'application/json;charset=utf-8' - } - } - let res = await fetchRetry(await getUrl('/user/login'), options) - let { data } = await res.json() - const statusCode = res.status - if (statusCode == 200) { - await AsyncStorage.setItem('refreshToken', JSON.stringify(data.refreshToken)) - await AsyncStorage.setItem('accessToken', JSON.stringify(data.accessToken)) - return { - ok: true - } - } - if (statusCode == 400) { - return { - ok: false, - restart: true - } - } - return { - ok: false - } - } catch (error) { - return { - ok: false - } - } -} -export const getBaseUrls = async () => { - // let { base_urls } = JSON.parse((await AsyncStorage.getItem('SPLASH_DATA'))) - return apiConfig.dev -} -export const getCachedProfile = async () => { - return JSON.parse(await AsyncStorage.getItem('UID_USER')) -} - -export const cacheProfile = async () => { - let data = await getProfile() - let oldData = await getCachedProfile() - if (data) { - await AsyncStorage.removeItem('UID_USER') - - await AsyncStorage.setItem('UID_USER', JSON.stringify({ - ...oldData, - ...data - })) - } - -} -export const getProfile = async () => { - let { ok, data } = await nextFetchApi('/profile?with_details=1&no_cache=1') - if (!ok) return null - return data -} diff --git a/src/services/i18n/index.js b/src/services/i18n/index.js deleted file mode 100644 index a8531e8..0000000 --- a/src/services/i18n/index.js +++ /dev/null @@ -1,16 +0,0 @@ -import i18n from "i18next"; -import { initReactI18next } from "react-i18next"; -import { Platform } from "react-native"; -import resources from './locales' - -i18n.use(initReactI18next).init({ - resources: resources, - lng: "fa", - fallbackLng: "fa", - compatibilityJSON: Platform.OS === 'android' ? 'v3' : '', - interpolation: { - escapeValue: false - } -}); - -export default i18n; \ No newline at end of file diff --git a/src/services/i18n/locales/en/translation.json b/src/services/i18n/locales/en/translation.json deleted file mode 100644 index b012430..0000000 --- a/src/services/i18n/locales/en/translation.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "main": { - "home": "Home", - "settings": "Settings", - "profile": "Profile", - "filter": "filter" - }, - "filter": { - "newest": "newest", - "oldest": "oldest" - }, - "profile": { - "first name": "first name", - "last name": "last name", - "birthday": "birthday", - "gender": "gender", - "addresses": "addresses", - "day": "day", - "month": "month", - "year": "year", - "male": "male", - "female": "female", - "submit changes": "submit changes" - }, - "settings": { - "language": "language" - } -} diff --git a/src/services/i18n/locales/fa/translation.json b/src/services/i18n/locales/fa/translation.json deleted file mode 100644 index 9dddd3a..0000000 --- a/src/services/i18n/locales/fa/translation.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "main": { - "home": "صفحه اصلی", - "books": "کتاب ها", - "videos": "ویدئوها", - "exams": "آزمون ها", - "profile": "حساب کاربری" - }, - "filter": { - "newest": "جدیدترین", - "oldest": "قدیمی ترین" - }, - "profile": { - "first name": "نام", - "last name": "نام خانوادگی", - "birthday": "تاریخ تولد", - "gender": "جنسیت", - "addresses": "آدرس ها", - "day": "روز", - "month": "ماه", - "year": "سال", - "male": "آقا", - "female": "خانم", - "submit changes": "ثبت تغییرات" - }, - "settings": { - "language": "زبان" - } -} diff --git a/src/services/i18n/locales/index.js b/src/services/i18n/locales/index.js deleted file mode 100644 index 41bce38..0000000 --- a/src/services/i18n/locales/index.js +++ /dev/null @@ -1,11 +0,0 @@ -import en from './en/translation.json'; -import fa from './fa/translation.json'; - -export default { - en: { - translation: en - }, - fa: { - translation: fa - } -} \ No newline at end of file diff --git a/src/utils/message.js b/src/utils/message.js index 011e971..07d92f9 100644 --- a/src/utils/message.js +++ b/src/utils/message.js @@ -1,4 +1,4 @@ -import { AsyncStorage, AlertIOS, Platform, ToastAndroid, } from "react-native" +import { AlertIOS, Platform, ToastAndroid, } from "react-native" export const toastMessage = (msg) => { if (Platform.OS === 'android') { diff --git a/src/utils/onInput.js b/src/utils/onInput.js new file mode 100644 index 0000000..8da5361 --- /dev/null +++ b/src/utils/onInput.js @@ -0,0 +1,280 @@ +class onInput { + persianOnly = (txt) => { + let newText = txt; + newText = newText.replace(/`/g, ""); + newText = newText.replace(/0/g, ""); + newText = newText.replace(/1/g, ""); + newText = newText.replace(/2/g, ""); + newText = newText.replace(/3/g, ""); + newText = newText.replace(/4/g, ""); + newText = newText.replace(/5/g, ""); + newText = newText.replace(/6/g, ""); + newText = newText.replace(/7/g, ""); + newText = newText.replace(/8/g, ""); + newText = newText.replace(/9/g, ""); + newText = newText.replace(/0/g, ""); + newText = newText.replace(/q/g, ""); + newText = newText.replace(/w/g, ""); + newText = newText.replace(/e/g, ""); + newText = newText.replace(/r/g, ""); + newText = newText.replace(/t/g, ""); + newText = newText.replace(/y/g, ""); + newText = newText.replace(/u/g, ""); + newText = newText.replace(/i/g, ""); + newText = newText.replace(/o/g, ""); + newText = newText.replace(/p/g, ""); + newText = newText.replace(/\[/g, ""); + newText = newText.replace(/\]/g, ""); + newText = newText.replace(/a/g, ""); + newText = newText.replace(/s/g, ""); + newText = newText.replace(/d/g, ""); + newText = newText.replace(/f/g, ""); + newText = newText.replace(/g/g, ""); + newText = newText.replace(/h/g, ""); + newText = newText.replace(/j/g, ""); + newText = newText.replace(/k/g, ""); + newText = newText.replace(/l/g, ""); + newText = newText.replace(/;/g, ""); + newText = newText.replace(/'/g, ""); + newText = newText.replace(/z/g, ""); + newText = newText.replace(/x/g, ""); + newText = newText.replace(/c/g, ""); + newText = newText.replace(/v/g, ""); + newText = newText.replace(/b/g, ""); + newText = newText.replace(/n/g, ""); + newText = newText.replace(/m/g, ""); + newText = newText.replace(/,/g, ""); + newText = newText.replace(/./g, ""); + newText = newText.replace(/\//g, ""); + newText = newText.replace(/~/g, " "); + newText = newText.replace(/Q/g, ""); + newText = newText.replace(/W/g, ""); + newText = newText.replace(/E/g, ""); + newText = newText.replace(/R/g, ""); + newText = newText.replace(/T/g, ""); + newText = newText.replace(/Y/g, ""); + newText = newText.replace(/U/g, ""); + newText = newText.replace(/I/g, ""); + newText = newText.replace(/O/g, ""); + newText = newText.replace(/P/g, ""); + newText = newText.replace(/A/g, ""); + newText = newText.replace(/S/g, ""); + newText = newText.replace(/G/g, ""); + newText = newText.replace(/H/g, ""); + newText = newText.replace(/J/g, ""); + newText = newText.replace(/K/g, ""); + newText = newText.replace(/L/g, ""); + newText = newText.replace(/Z/g, ""); + newText = newText.replace(/X/g, ""); + newText = newText.replace(/B/g, ""); + newText = newText.replace(/N/g, ""); + newText = newText.replace(/M/g, ""); + newText = newText.replace(/\?/g, ""); + if (!newText && newText.length !== 0) { + // toast.info("از کاراکتر فارسی استفاده کنید"); + } + return newText; + }; + englishAndNumberWithoutSpace = (txt) => { + let newText = txt; + newText = newText.replace(/`/g, ""); + newText = newText.replace(/0/g, "0"); + newText = newText.replace(/1/g, "1"); + newText = newText.replace(/2/g, "2"); + newText = newText.replace(/3/g, "3"); + newText = newText.replace(/4/g, "4"); + newText = newText.replace(/5/g, "5"); + newText = newText.replace(/6/g, "6"); + newText = newText.replace(/7/g, "7"); + newText = newText.replace(/8/g, "8"); + newText = newText.replace(/9/g, "9"); + newText = newText.replace(/ا/g, ""); + newText = newText.replace(/ب/g, ""); + newText = newText.replace(/پ/g, ""); + newText = newText.replace(/ت/g, ""); + newText = newText.replace(/ث/g, ""); + newText = newText.replace(/ج/g, ""); + newText = newText.replace(/چ/g, ""); + newText = newText.replace(/ح/g, ""); + newText = newText.replace(/خ/g, ""); + newText = newText.replace(/د/g, ""); + newText = newText.replace(/\[/g, ""); + newText = newText.replace(/\]/g, ""); + newText = newText.replace(/ذ/g, ""); + newText = newText.replace(/ر/g, ""); + newText = newText.replace(/ز/g, ""); + newText = newText.replace(/ژ/g, ""); + newText = newText.replace(/ط/g, ""); + newText = newText.replace(/ظ/g, ""); + newText = newText.replace(/ع/g, ""); + newText = newText.replace(/غ/g, ""); + newText = newText.replace(/ف/g, ""); + newText = newText.replace(/;/g, ""); + newText = newText.replace(/'/g, ""); + newText = newText.replace(/ق/g, ""); + newText = newText.replace(/س/g, ""); + newText = newText.replace(/ش/g, ""); + newText = newText.replace(/ص/g, ""); + newText = newText.replace(/ض/g, ""); + newText = newText.replace(/ک/g, ""); + newText = newText.replace(/گ/g, ""); + newText = newText.replace(/,/g, ""); + newText = newText.replace(/\./g, ""); + newText = newText.replace(/\//g, ""); + newText = newText.replace(/~/g, " "); + newText = newText.replace(/ل/g, ""); + newText = newText.replace(/م/g, ""); + newText = newText.replace(/ن/g, ""); + newText = newText.replace(/و/g, ""); + newText = newText.replace(/ه/g, ""); + newText = newText.replace(/ی/g, ""); + newText = newText.replace(/\?/g, ""); + if (!newText && newText.length !== 0) { + // toast.info("از کاراکتر انگلیسی واعداداستفاده کنید"); + } + return newText; + }; + numberOnly = (txt) => { + let newText = txt; + newText = newText.replace(/`/g, ""); + newText = newText.replace(/0/g, "0"); + newText = newText.replace(/1/g, "1"); + newText = newText.replace(/2/g, "2"); + newText = newText.replace(/3/g, "3"); + newText = newText.replace(/4/g, "4"); + newText = newText.replace(/5/g, "5"); + newText = newText.replace(/6/g, "6"); + newText = newText.replace(/7/g, "7"); + newText = newText.replace(/8/g, "8"); + newText = newText.replace(/9/g, "9"); + newText = newText.replace(/ا/g, ""); + newText = newText.replace(/ب/g, ""); + newText = newText.replace(/پ/g, ""); + newText = newText.replace(/ت/g, ""); + newText = newText.replace(/ث/g, ""); + newText = newText.replace(/ج/g, ""); + newText = newText.replace(/چ/g, ""); + newText = newText.replace(/ح/g, ""); + newText = newText.replace(/خ/g, ""); + newText = newText.replace(/د/g, ""); + newText = newText.replace(/\[/g, ""); + newText = newText.replace(/\]/g, ""); + newText = newText.replace(/ذ/g, ""); + newText = newText.replace(/ر/g, ""); + newText = newText.replace(/ز/g, ""); + newText = newText.replace(/ژ/g, ""); + newText = newText.replace(/ط/g, ""); + newText = newText.replace(/ظ/g, ""); + newText = newText.replace(/ع/g, ""); + newText = newText.replace(/غ/g, ""); + newText = newText.replace(/ف/g, ""); + newText = newText.replace(/;/g, ""); + newText = newText.replace(/'/g, ""); + newText = newText.replace(/ق/g, ""); + newText = newText.replace(/س/g, ""); + newText = newText.replace(/ش/g, ""); + newText = newText.replace(/ص/g, ""); + newText = newText.replace(/ض/g, ""); + newText = newText.replace(/ک/g, ""); + newText = newText.replace(/گ/g, ""); + newText = newText.replace(/\,/g, ""); + newText = newText.replace(/\./g, ""); + newText = newText.replace(/\//g, ""); + newText = newText.replace(/~/g, " "); + newText = newText.replace(/ل/g, ""); + newText = newText.replace(/م/g, ""); + newText = newText.replace(/ن/g, ""); + newText = newText.replace(/و/g, ""); + newText = newText.replace(/ه/g, ""); + newText = newText.replace(/ی/g, ""); + newText = newText.replace(/\?/g, ""); + newText = newText.replace(/q/g, ""); + newText = newText.replace(/w/g, ""); + newText = newText.replace(/e/g, ""); + newText = newText.replace(/r/g, ""); + newText = newText.replace(/t/g, ""); + newText = newText.replace(/y/g, ""); + newText = newText.replace(/u/g, ""); + newText = newText.replace(/i/g, ""); + newText = newText.replace(/o/g, ""); + newText = newText.replace(/p/g, ""); + newText = newText.replace(/a/g, ""); + newText = newText.replace(/s/g, ""); + newText = newText.replace(/d/g, ""); + newText = newText.replace(/f/g, ""); + newText = newText.replace(/g/g, ""); + newText = newText.replace(/h/g, ""); + newText = newText.replace(/j/g, ""); + newText = newText.replace(/k/g, ""); + newText = newText.replace(/l/g, ""); + newText = newText.replace(/z/g, ""); + newText = newText.replace(/x/g, ""); + newText = newText.replace(/c/g, ""); + newText = newText.replace(/v/g, ""); + newText = newText.replace(/b/g, ""); + newText = newText.replace(/n/g, ""); + newText = newText.replace(/m/g, ""); + newText = newText.replace(/Q/g, ""); + newText = newText.replace(/W/g, ""); + newText = newText.replace(/E/g, ""); + newText = newText.replace(/R/g, ""); + newText = newText.replace(/T/g, ""); + newText = newText.replace(/Y/g, ""); + newText = newText.replace(/U/g, ""); + newText = newText.replace(/I/g, ""); + newText = newText.replace(/O/g, ""); + newText = newText.replace(/P/g, ""); + newText = newText.replace(/A/g, ""); + newText = newText.replace(/S/g, ""); + newText = newText.replace(/G/g, ""); + newText = newText.replace(/H/g, ""); + newText = newText.replace(/J/g, ""); + newText = newText.replace(/K/g, ""); + newText = newText.replace(/L/g, ""); + newText = newText.replace(/Z/g, ""); + newText = newText.replace(/X/g, ""); + newText = newText.replace(/B/g, ""); + newText = newText.replace(/N/g, ""); + newText = newText.replace(/M/g, ""); + if (!newText && newText.length !== 0) { + // toast.info("از اعداداستفاده کنید"); + } + return newText; + }; + dayHandler = (num) => { + let newNum = this.numberOnly(num); + if (newNum > 31) { + // toast.error("روز نباید بزرگتر از 31 باشد."); + return Math.floor(newNum / 10); + } + return newNum; + }; + monthHandler = (num) => { + let newNum = this.numberOnly(num); + if (newNum > 12 || newNum < 0) { + // toast.error("ماه باید بین 1 تا 12 باشد."); + return Math.floor(newNum / 10); + } + return newNum; + }; + yearHandler = (num) => { + let newNum = this.numberOnly(num); + if (newNum > 1395) { + // toast.error("سال باید کوچک‌تر از 1395 باشد."); + return Math.floor(newNum / 10); + } + return newNum; + }; + phonenumber = (value) => { + let formattedValue = value + .replace(/[\u0660-\u0669\u06f0-\u06f9]/g, function (c) { + return c.charCodeAt(0) & 0xf; + }) + .replace(/[^\d]/, ""); + return formattedValue; + }; +} + +const _onInput = new onInput(); + +export default _onInput; diff --git a/yarn.lock b/yarn.lock index b047327..a22da5d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1845,6 +1845,13 @@ atob@^2.1.2: resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== +axios@^0.24.0: + version "0.24.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.24.0.tgz#804e6fa1e4b9c5288501dd9dff56a7a0940d20d6" + integrity sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA== + dependencies: + follow-redirects "^1.14.4" + babel-core@^7.0.0-bridge.0: version "7.0.0-bridge.0" resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-7.0.0-bridge.0.tgz#95a492ddd90f9b4e9a4a1da14eb335b87b634ece" @@ -3143,6 +3150,11 @@ flow-parser@^0.121.0: resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.121.0.tgz#9f9898eaec91a9f7c323e9e992d81ab5c58e618f" integrity sha512-1gIBiWJNR0tKUNv8gZuk7l9rVX06OuLzY9AoGio7y/JT4V1IZErEMEq2TJS+PFcw/y0RshZ1J/27VfK1UQzYVg== +follow-redirects@^1.14.4: + version "1.14.6" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.6.tgz#8cfb281bbc035b3c067d6cd975b0f6ade6e855cd" + integrity sha512-fhUl5EwSJbbl8AR+uYL2KQDxLkdSjZGR36xy46AO7cOMTrCMON6Sa28FmAnC2tRTDbd/Uuzz3aJBv7EBN7JH8A== + fontfaceobserver@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fontfaceobserver/-/fontfaceobserver-2.1.0.tgz#e2705d293e2c585a6531c2a722905657317a2991"