diff --git a/App.js b/App.js
index 09f879b..9ee597f 100644
--- a/App.js
+++ b/App.js
@@ -1,20 +1,58 @@
-import { StatusBar } from 'expo-status-bar';
-import { StyleSheet, Text, View } from 'react-native';
+import React from "react";
+import { StyleSheet, useColorScheme } from "react-native";
+import AsyncStorage from "@react-native-async-storage/async-storage";
+import { Provider } from "react-redux";
+import { applyMiddleware, createStore, compose } 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 "./src/reducers";
+import Navigator from "./navigation";
+import AlertModal from "./src/components/AlertModal";
+
+const persistConfig = {
+ key: "root",
+ storage: AsyncStorage,
+ stateReconciler: autoMergeLevel2, // see "Merge Process" section for details.
+ whitelist: ["profile"],
+};
+const pReducer = persistReducer(persistConfig, allReducers);
+
+const middleWare = [];
+
+middleWare.push(thunk);
+
+const loggerMiddleware = createLogger({
+ predicate: () => process.env.NODE_ENV === "development",
+});
+middleWare.push(loggerMiddleware);
+
+const store = createStore(pReducer, compose(applyMiddleware(...middleWare)));
+
+const persistor = persistStore(store);
+
+const ReactNative = require("react-native");
+try {
+ ReactNative.I18nManager.allowRTL(true);
+ // enableScreens();
+} catch (e) {
+ console.log(e);
+}
+
+console.disableYellowBox = true;
+
+const App = () => {
+ const isDarkMode = useColorScheme() === "dark";
-export default function App() {
return (
-
- Open up App.js to start working on your app!
-
-
+
+
+
+
);
-}
+};
-const styles = StyleSheet.create({
- container: {
- flex: 1,
- backgroundColor: '#fff',
- alignItems: 'center',
- justifyContent: 'center',
- },
-});
+const styles = StyleSheet.create({});
+
+export default App;
diff --git a/app.json b/app.json
index d0413a6..d3d545e 100644
--- a/app.json
+++ b/app.json
@@ -23,7 +23,8 @@
"adaptiveIcon": {
"foregroundImage": "./assets/adaptive-icon.png",
"backgroundColor": "#FFFFFF"
- }
+ },
+ "package": "com.appsazz.RnDanovinExpo"
},
"web": {
"favicon": "./assets/favicon.png"
diff --git a/navigation.js b/navigation.js
new file mode 100644
index 0000000..6dc6560
--- /dev/null
+++ b/navigation.js
@@ -0,0 +1,130 @@
+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 {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';
+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) {
+ const {t} = useTranslation('translation', {keyPrefix: 'main'});
+
+ return (
+
+
+
+
+
+
+
+ );
+}
+
+function Navigator(props) {
+ React.useEffect(() => {
+ i18n.changeLanguage(props.config.lan);
+ }, [props.config]);
+
+ return (
+
+
+
+
+ {/* */}
+
+
+
+
+
+
+
+
+ );
+}
+
+export default connect(mapStateToProps)(Navigator);
diff --git a/package.json b/package.json
index a8f084b..ca0522a 100644
--- a/package.json
+++ b/package.json
@@ -10,12 +10,32 @@
"eject": "expo eject"
},
"dependencies": {
+ "@react-native-async-storage/async-storage": "~1.15.0",
+ "@react-navigation/bottom-tabs": "^6.0.9",
+ "@react-navigation/native": "^6.0.6",
+ "@react-navigation/native-stack": "^6.2.5",
"expo": "~44.0.0",
+ "expo-device": "~4.1.0",
"expo-status-bar": "~1.2.0",
+ "i18next": "^21.6.3",
+ "lodash": "^4.17.21",
"react": "17.0.1",
"react-dom": "17.0.1",
+ "react-i18next": "^11.15.1",
"react-native": "0.64.3",
- "react-native-web": "0.17.1"
+ "react-native-awesome-alerts": "^1.5.2",
+ "react-native-restart": "^0.0.22",
+ "react-native-safe-area-context": "3.3.2",
+ "react-native-screens": "~3.10.1",
+ "react-native-select-dropdown": "^1.6.0",
+ "react-native-web": "0.17.1",
+ "react-redux": "^7.2.6",
+ "redux": "^4.1.2",
+ "redux-logger": "^3.0.6",
+ "redux-persist": "^6.0.0",
+ "redux-thunk": "^2.4.1",
+ "tailwind-react-native-classnames": "^1.5.1",
+ "tailwind-rn": "^3.0.1"
},
"devDependencies": {
"@babel/core": "^7.12.9"
diff --git a/src/actions/actionTypes.js b/src/actions/actionTypes.js
new file mode 100644
index 0000000..170cedd
--- /dev/null
+++ b/src/actions/actionTypes.js
@@ -0,0 +1,2 @@
+export const PROFILE_RECORD = 'PROFILE_RECORD';
+export const APP_CONFIG = 'APP_CONFIG';
diff --git a/src/assets/icons/activation.png b/src/assets/icons/activation.png
new file mode 100644
index 0000000..f368c64
Binary files /dev/null and b/src/assets/icons/activation.png differ
diff --git a/src/assets/icons/ar-light.png b/src/assets/icons/ar-light.png
new file mode 100644
index 0000000..1961afb
Binary files /dev/null and b/src/assets/icons/ar-light.png differ
diff --git a/src/assets/icons/bookmark.png b/src/assets/icons/bookmark.png
new file mode 100644
index 0000000..cc45130
Binary files /dev/null and b/src/assets/icons/bookmark.png differ
diff --git a/src/assets/icons/dropdown.png b/src/assets/icons/dropdown.png
new file mode 100644
index 0000000..69d6468
Binary files /dev/null and b/src/assets/icons/dropdown.png differ
diff --git a/src/assets/icons/hamburger-light.png b/src/assets/icons/hamburger-light.png
new file mode 100644
index 0000000..a482a9e
Binary files /dev/null and b/src/assets/icons/hamburger-light.png differ
diff --git a/src/assets/icons/leftWhite.png b/src/assets/icons/leftWhite.png
new file mode 100644
index 0000000..913c78b
Binary files /dev/null and b/src/assets/icons/leftWhite.png differ
diff --git a/src/assets/icons/link.png b/src/assets/icons/link.png
new file mode 100644
index 0000000..b328dc1
Binary files /dev/null and b/src/assets/icons/link.png differ
diff --git a/src/assets/icons/logo.png b/src/assets/icons/logo.png
new file mode 100644
index 0000000..af3b208
Binary files /dev/null and b/src/assets/icons/logo.png differ
diff --git a/src/assets/icons/pdf.png b/src/assets/icons/pdf.png
new file mode 100644
index 0000000..7f3bd1e
Binary files /dev/null and b/src/assets/icons/pdf.png differ
diff --git a/src/assets/icons/ppt.png b/src/assets/icons/ppt.png
new file mode 100644
index 0000000..80965ba
Binary files /dev/null and b/src/assets/icons/ppt.png differ
diff --git a/src/assets/icons/qr-light.png b/src/assets/icons/qr-light.png
new file mode 100644
index 0000000..34595b0
Binary files /dev/null and b/src/assets/icons/qr-light.png differ
diff --git a/src/assets/icons/search.png b/src/assets/icons/search.png
new file mode 100644
index 0000000..02bc530
Binary files /dev/null and b/src/assets/icons/search.png differ
diff --git a/src/assets/images/logo.png b/src/assets/images/logo.png
new file mode 100644
index 0000000..42ea219
Binary files /dev/null and b/src/assets/images/logo.png differ
diff --git a/src/assets/video.mp4 b/src/assets/video.mp4
new file mode 100644
index 0000000..fd6954b
Binary files /dev/null and b/src/assets/video.mp4 differ
diff --git a/src/components/AlertModal.js b/src/components/AlertModal.js
new file mode 100644
index 0000000..fac4a33
--- /dev/null
+++ b/src/components/AlertModal.js
@@ -0,0 +1,137 @@
+import React, { useState } from "react"
+import AwesomeAlert from 'react-native-awesome-alerts';
+const ReactNative = require('react-native');
+
+const AlertModal = props => {
+ const [alert, setAlert] = useState({
+ show: false,
+ showProgress: false,
+ title: "خطا",
+ message: "خطای ناشناخته",
+ closeOnTouchOutside: false,
+ closeOnHardwareBackPress: false,
+ showCancelButton: true,
+ showConfirmButton: true,
+ cancelText: "بیخیال",
+ confirmText: "باشه",
+ confirmButtonColor: "#2980b9",
+ onCancel: () => {
+ },
+ onConfirm: () => {
+
+ },
+ })
+ const [apiAlert, setApiAlert] = useState({
+ show: false,
+ showProgress: false,
+ title: "خطا",
+ message: "خطای ناشناخته",
+ closeOnTouchOutside: false,
+ closeOnHardwareBackPress: false,
+ showCancelButton: true,
+ showConfirmButton: true,
+ cancelText: "بیخیال",
+ confirmText: "باشه",
+ confirmButtonColor: "#2980b9",
+ onCancel: () => {
+ },
+ onConfirm: () => {
+ },
+ })
+
+ global.globalAlert = (params) => {
+ setAlert({
+ ...alert,
+ ...params
+ })
+ }
+ global.globalApiAlert = (params) => {
+
+ setApiAlert({
+ ...apiAlert,
+ ...params
+ })
+ }
+
+ function hideAlert() {
+ setAlert({ ...alert, show: false })
+ }
+ function onApiCancelPressed(){
+ globalApiAlert({ show: false })
+
+ apiAlert.onCancel()
+ }
+ function onApiConfirmPressed(){
+ globalApiAlert({ show: false })
+ apiAlert.onConfirm()
+ }
+ function onCancelPressed(){
+ hideAlert()
+ alert.onCancel()
+ }
+ function onConfirmPressed(){
+ hideAlert()
+ alert.onConfirm()
+ }
+ return <>
+
+
+ >
+
+}
+
+export default AlertModal;
diff --git a/src/components/CustomTextInput.js b/src/components/CustomTextInput.js
new file mode 100644
index 0000000..4d84604
--- /dev/null
+++ b/src/components/CustomTextInput.js
@@ -0,0 +1,59 @@
+import React, {useState} from 'react';
+import {TextInput, View, Text, Dimensions, StyleSheet} from 'react-native';
+import tw from 'tailwind-react-native-classnames';
+
+const FloatingLabelInput = ({
+ label,
+ textAlign,
+ direction,
+ labelBackgroundColor,
+ onChange,
+ value,
+ name,
+ ...props
+}) => {
+ const [isFocused, setIsFocused] = useState(false);
+ const styles = StyleSheet.create({
+ labelStyle: {
+ position: 'absolute',
+ right: 15,
+ backgroundColor: 'white',
+ zIndex: 100,
+ paddingHorizontal: 5,
+ textAlign: 'center',
+ top: !isFocused ? '50%' : 0,
+ fontSize: !isFocused ? Dimensions.get('window').width / 27 : 14,
+ transform: [{translateY: -Dimensions.get('window').width / 35}],
+ color: !isFocused ? '#555' : '#6CBE44',
+ // transition: Transitions.all(Transitions.)
+ },
+ inputStyle: {
+ fontSize: Dimensions.get('window').width / 25,
+ color: '#000',
+ borderWidth: 0.5,
+ borderColor: isFocused ? '#6CBE44' : '#555',
+ paddingVertical: 15,
+ paddingHorizontal: 10,
+ direction: 'rtl',
+ textAlign: 'right',
+ },
+ });
+ return (
+
+
+ {label}
+
+ onChange(name, text)}
+ onFocus={() => setIsFocused(true)}
+ onBlur={() =>
+ value ? setIsFocused(() => true) : setIsFocused(() => false)
+ }
+ />
+
+ );
+};
+
+export default FloatingLabelInput;
diff --git a/src/components/FormButton.js b/src/components/FormButton.js
new file mode 100644
index 0000000..6d4af07
--- /dev/null
+++ b/src/components/FormButton.js
@@ -0,0 +1,31 @@
+import React from 'react';
+import {StyleSheet, Text, Pressable, Dimensions } from 'react-native';
+
+export default function FormButton({text, color, onPress}) {
+ const styles = StyleSheet.create({
+ button: {
+ width : '100%',
+ alignItems: 'center',
+ justifyContent: 'center',
+ paddingVertical: 12,
+ paddingHorizontal: 0,
+ borderRadius: 6,
+ elevation: 3,
+ backgroundColor: color,
+ },
+ text: {
+ fontSize: Dimensions.get('window').width / 25,
+ fontWeight: '300',
+ color: 'white',
+ },
+ });
+ return (
+ onPress}
+ >
+ {text}
+
+ );
+}
diff --git a/src/components/Header.js b/src/components/Header.js
new file mode 100644
index 0000000..9aa2911
--- /dev/null
+++ b/src/components/Header.js
@@ -0,0 +1,33 @@
+import React from 'react';
+import {View, Text, Dimensions, Image} from 'react-native';
+import tw from 'tailwind-react-native-classnames';
+
+const width = Dimensions.get('window').width;
+const height = Dimensions.get('window').height;
+
+export default function Header({icon, title, description, background}) {
+ return (
+
+
+
+
+ {title}
+
+
+ {description}
+
+
+ );
+}
diff --git a/src/components/Navbar.js b/src/components/Navbar.js
new file mode 100644
index 0000000..1260892
--- /dev/null
+++ b/src/components/Navbar.js
@@ -0,0 +1,69 @@
+import React, {useCallback} from 'react';
+import {Image, StyleSheet, View, TouchableOpacity} from 'react-native';
+import {useNavigation} from '@react-navigation/native';
+import tw from 'tailwind-rn';
+
+//colors
+import Color from '../constants/Colors';
+
+//assets
+import hamburgerLightIcon from '../assets/icons/hamburger-light.png';
+import logoIcon from '../assets/icons/logo.png';
+import qrLightIcon from '../assets/icons/qr-light.png';
+import arLightIcon from '../assets/icons/ar-light.png';
+
+const Navbar = ({notification}) => {
+ const navigation = useNavigation();
+ const Button = useCallback(({icon, route}) => {
+ return (
+ navigation.navigate(route)}>
+
+
+ );
+ }, []);
+ return (
+
+
+
+ {notification && (
+
+ )}
+
+
+
+
+
+
+
+ );
+};
+
+export default Navbar;
+
+const styles = StyleSheet.create({});
diff --git a/src/components/Or.js b/src/components/Or.js
new file mode 100644
index 0000000..760506d
--- /dev/null
+++ b/src/components/Or.js
@@ -0,0 +1,20 @@
+import React, {useState} from 'react';
+import {View, Text, Dimensions} from 'react-native';
+import tw from 'tailwind-react-native-classnames';
+
+const width = Dimensions.get('window').width;
+
+function Or(props) {
+ return (
+
+
+ یا
+
+
+ );
+}
+
+export default Or;
diff --git a/src/components/Pressable.js b/src/components/Pressable.js
new file mode 100644
index 0000000..cd52ce7
--- /dev/null
+++ b/src/components/Pressable.js
@@ -0,0 +1,28 @@
+import React from 'react';
+import {Pressable, Text, Dimensions} from 'react-native';
+import tw from 'tailwind-react-native-classnames';
+
+const fullWidth = Dimensions.get('window').width;
+
+export default function Pressable1({
+ title,
+ backgroundColor,
+ color,
+ border,
+ width,
+}) {
+ return (
+
+ {title}
+
+ );
+}
diff --git a/src/components/Progress.js b/src/components/Progress.js
new file mode 100644
index 0000000..989fa78
--- /dev/null
+++ b/src/components/Progress.js
@@ -0,0 +1,34 @@
+import React, {useState, useEffect} from 'react';
+import {View} from 'react-native';
+import tw from 'tailwind-rn';
+
+//Color
+import Color from '../constants/Colors';
+
+function Progress({percent}) {
+ const [delayPercent, setDelayPercent] = useState(0);
+ useEffect(() => {
+ setTimeout(() => {
+ setDelayPercent(() => percent);
+ }, 1000);
+ }, [percent]);
+ return (
+
+
+
+ );
+}
+
+export default Progress;
diff --git a/src/components/Redirect.js b/src/components/Redirect.js
new file mode 100644
index 0000000..85af824
--- /dev/null
+++ b/src/components/Redirect.js
@@ -0,0 +1,30 @@
+import React from 'react';
+import {View, Text, Dimensions, Image} from 'react-native';
+import tw from 'tailwind-react-native-classnames';
+import leftIcon from '../assets/icons/leftWhite.png';
+
+const width = Dimensions.get('window').width;
+const height = Dimensions.get('window').height;
+
+export default function Redirect({text}) {
+ return (
+
+
+
+ {text}
+
+
+
+
+
+
+ );
+}
diff --git a/src/components/Search.js b/src/components/Search.js
new file mode 100644
index 0000000..72843df
--- /dev/null
+++ b/src/components/Search.js
@@ -0,0 +1,55 @@
+import React, {useState} from 'react';
+import {
+ TextInput,
+ View,
+ Dimensions,
+ StyleSheet,
+ Pressable,
+ Image,
+} from 'react-native';
+import tw from 'tailwind-react-native-classnames';
+import searchIcon from '../assets/icons/search.png';
+
+const width = Dimensions.get('window').width;
+const Search = ({
+ placeholder,
+ textAlign,
+ direction,
+ onChange,
+ value,
+}) => {
+ const styles = StyleSheet.create({
+ inputStyle: {
+ fontSize: width / 30,
+ color: '#000',
+ borderWidth: 0.5,
+ borderColor: '#DBDBDB',
+ paddingVertical: 16,
+ paddingHorizontal: 10,
+ direction: direction,
+ textAlign: textAlign,
+ backgroundColor: '#F9F9F9',
+ },
+ });
+ return (
+
+ onChange(text)}
+ placeholder={placeholder}
+ placeholderTextColor={'#cccccc'}
+ value={value}
+ />
+
+
+
+
+ );
+};
+
+export default Search;
+
+Search.defaultProps = {
+ direction: 'rtl',
+ textAlign: 'right',
+};
\ No newline at end of file
diff --git a/src/components/Select.js b/src/components/Select.js
new file mode 100644
index 0000000..4f38377
--- /dev/null
+++ b/src/components/Select.js
@@ -0,0 +1,46 @@
+import React from 'react';
+import {Image, Dimensions} from 'react-native';
+import SelectDropdown from 'react-native-select-dropdown';
+import dropdownIcon from '../assets/icons/dropdown.png';
+import tw from 'tailwind-react-native-classnames';
+
+function Select({iconPosition, options, onChange, value, width, defaultValue}) {
+ return (
+ {
+ onChange(selectedItem);
+ }}
+ renderDropdownIcon={() => (
+
+ )}
+ />
+ );
+}
+
+export default Select;
+
+Select.defaultProps = {
+ options: ['1', '2', '3'],
+ iconPosition: 'left',
+};
diff --git a/src/components/Video.js b/src/components/Video.js
new file mode 100644
index 0000000..257844a
--- /dev/null
+++ b/src/components/Video.js
@@ -0,0 +1,23 @@
+import {StyleSheet} from 'react-native';
+import Video from 'react-native-video';
+import file from '../assets/video.mp4';
+
+// Within your render function, assuming you have a file called
+// "background.mp4" in your project. You can include multiple videos
+// on a single screen if you like.
+import React from 'react';
+
+export default function CustomVideo() {
+ return (
+