@ -0,0 +1,11 @@ |
||||
> Why do I have a folder named ".expo-shared" in my project? |
||||
|
||||
The ".expo-shared" folder is created when running commands that produce state that is intended to be shared with all developers on the project. For example, "npx expo-optimize". |
||||
|
||||
> What does the "assets.json" file contain? |
||||
|
||||
The "assets.json" file describes the assets that have been optimized through "expo-optimize" and do not need to be processed again. |
||||
|
||||
> Should I commit the ".expo-shared" folder? |
||||
|
||||
Yes, you should share the ".expo-shared" folder with your collaborators. |
@ -1,4 +1 @@ |
||||
{ |
||||
"12bb71342c6255bbf50437ec8f4441c083f47cdb74bd89160c15e4f43e52a1cb": true, |
||||
"40b842e832070c58deac6aa9e08fa459302ee3f9da492c7e77d93d2fbf4a56fd": true |
||||
} |
||||
{} |
||||
|
@ -1,20 +1,69 @@ |
||||
import { StatusBar } from 'expo-status-bar'; |
||||
import { StyleSheet, Text, View } from 'react-native'; |
||||
import { StyleSheet, View } from "react-native"; |
||||
import { useFonts } from "expo-font"; |
||||
import Navigation from "./navigation/index"; |
||||
import AlertModal from "./src/components/AlertModal"; |
||||
import { Provider } from "react-redux"; |
||||
import { store, persistor } from "./src/redux/store"; |
||||
import * as SplashScreen from 'expo-splash-screen'; |
||||
import React from "react"; |
||||
import { PersistGate } from "redux-persist/integration/react"; |
||||
|
||||
const App = () => { |
||||
const [appIsReady, setAppIsReady] = React.useState(false); |
||||
let [fontsLoaded] = useFonts({ |
||||
light: require("./assets/fonts/Farsi/Light.ttf"), |
||||
regular: require("./assets/fonts/Farsi/Regular.ttf"), |
||||
bold: require("./assets/fonts/Farsi/Medium.ttf"), |
||||
demi: require("./assets/fonts/Farsi/DemiBold.ttf"), |
||||
}); |
||||
|
||||
React.useEffect(() => { |
||||
async function prepare() { |
||||
try { |
||||
// Keep the splash screen visible while we fetch resources
|
||||
await SplashScreen.preventAutoHideAsync(); |
||||
// Pre-load fonts, make any API calls you need to do here
|
||||
// Artificially delay for two seconds to simulate a slow loading
|
||||
// experience. Please remove this if you copy and paste the code!
|
||||
await new Promise((resolve) => setTimeout(resolve, 2000)); |
||||
} catch (e) { |
||||
console.warn(e); |
||||
} finally { |
||||
// Tell the application to render
|
||||
setAppIsReady(true); |
||||
} |
||||
} |
||||
|
||||
prepare(); |
||||
}, []); |
||||
|
||||
const onLayoutRootView = React.useCallback(async () => { |
||||
if (fontsLoaded) { |
||||
// This tells the splash screen to hide immediately! If we call this after
|
||||
// `setAppIsReady`, then we may see a blank screen while the app is
|
||||
// loading its initial state and rendering its first pixels. So instead,
|
||||
// we hide the splash screen once we know the root view has already
|
||||
// performed layout.
|
||||
await SplashScreen.hideAsync(); |
||||
} |
||||
}, [fontsLoaded]); |
||||
|
||||
if (!fontsLoaded) { |
||||
return null; |
||||
} |
||||
|
||||
export default function App() { |
||||
return ( |
||||
<View style={styles.container}> |
||||
<Text>Open up App.js to start working on your app!</Text> |
||||
<StatusBar style="auto" /> |
||||
<View style={{ flex: 1 }} onLayout={onLayoutRootView}> |
||||
<Provider store={store}> |
||||
<PersistGate loading={null} persistor={persistor}> |
||||
<Navigation /> |
||||
<AlertModal /> |
||||
</PersistGate> |
||||
</Provider> |
||||
</View> |
||||
); |
||||
} |
||||
}; |
||||
|
||||
const styles = StyleSheet.create({}); |
||||
|
||||
const styles = StyleSheet.create({ |
||||
container: { |
||||
flex: 1, |
||||
backgroundColor: '#fff', |
||||
alignItems: 'center', |
||||
justifyContent: 'center', |
||||
}, |
||||
}); |
||||
export default App; |
||||
|
Before Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 162 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 46 KiB |
@ -0,0 +1,18 @@ |
||||
{ |
||||
"cli": { |
||||
"version": ">= 0.52.0" |
||||
}, |
||||
"build": { |
||||
"development": { |
||||
"developmentClient": true, |
||||
"distribution": "internal" |
||||
}, |
||||
"preview": { |
||||
"distribution": "internal" |
||||
}, |
||||
"production": {} |
||||
}, |
||||
"submit": { |
||||
"production": {} |
||||
} |
||||
} |
@ -0,0 +1,10 @@ |
||||
{ |
||||
"sort": ["مرتب سازی", "مرتب سازی", "محبوب ترین", "جدیدترین"], |
||||
"productTypes" : [ |
||||
"نوع محصول", |
||||
"کتاب فیزیکی", |
||||
"کتاب دیجیتال", |
||||
"دوره ویدئویی", |
||||
"بسته های آموزشی" |
||||
] |
||||
} |
@ -0,0 +1,668 @@ |
||||
import React, { useEffect } from "react"; |
||||
import { Restart } from "fiction-expo-restart"; |
||||
import { I18nManager, StatusBar } from "react-native"; |
||||
import * as Linking from "expo-linking"; |
||||
import Svg, { G, Path } from "react-native-svg"; |
||||
import { NavigationContainer } from "@react-navigation/native"; |
||||
import { createNativeStackNavigator } from "@react-navigation/native-stack"; |
||||
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs"; |
||||
import { connect } from "react-redux"; |
||||
import { user, publicApi } from "../src/redux/actions"; |
||||
import { useSafeAreaInsets } from "react-native-safe-area-context"; |
||||
import bottomNavigationList from "./bottomNavigation"; |
||||
|
||||
//components
|
||||
import OrderDetails from "../src/screens/OrderDetails"; |
||||
import OrdersFollowUp from "../src/screens/OrdersFollowUp"; |
||||
import Splash from "../src/screens/Splash"; |
||||
import Home from "../src/screens/Home"; |
||||
import Products from "../src/screens/Products"; |
||||
import Login from "../src/screens/Login"; |
||||
import Otp from "../src/screens/Otp"; |
||||
import Product from "../src/screens/Product"; |
||||
import AR from "../src/screens/AR"; |
||||
import QR from "../src/screens/QR"; |
||||
import QRContent from "../src/screens/QRContent"; |
||||
import Faq from "../src/screens/Faq"; |
||||
import Activation from "../src/screens/Activation"; |
||||
import Videos from "../src/screens/Videos"; |
||||
import Video from "../src/screens/Video"; |
||||
import VideoDisplay from "../src/screens/VideoDisplay"; |
||||
import Contact from "../src/screens/Contact"; |
||||
import Tests from "../src/screens/Tests"; |
||||
import ShoppingCart from "../src/screens/ShoppingCart"; |
||||
import DeliveryForm from "../src/screens/DeliveryForm"; |
||||
import Address from "../src/screens/Address"; |
||||
import Profile from "../src/screens/Profile"; |
||||
import ProfileBookmark from "../src/screens/Profile/components/ProfileBookmark"; |
||||
import ProfileAddress from "../src/screens/Profile/components/ProfileAddress"; |
||||
import Blogs from "../src/screens/Blogs"; |
||||
import Blog from "../src/screens/Blog"; |
||||
import Sample from "../src/screens/Product/components/Sample"; |
||||
import Info from "../src/screens/Product/components/Info"; |
||||
import Rules from "../src/screens/Rules/index"; |
||||
import MyCourses from "../src/screens/Profile/components/MyCourses"; |
||||
import Ticket from "../src/screens/Contact/layouts/Ticket"; |
||||
import Tickets from "../src/screens/Contact/layouts/Tickets"; |
||||
import TicketStatus from "../src/screens/Contact/layouts/TicketStatus"; |
||||
import MoreBlog from "../src/screens/Blogs/layouts/More"; |
||||
|
||||
//style
|
||||
import Colors from "../src/constants/Colors"; |
||||
import fontSize from "../src/constants/fontSize"; |
||||
|
||||
const Tab = createBottomTabNavigator(); |
||||
const BottomTabNavigator = ({ theme, userProducts }) => { |
||||
const insets = useSafeAreaInsets(); |
||||
const [headerShown, setHeaderShown] = React.useState(true); |
||||
React.useEffect(() => { |
||||
setTimeout(() => { |
||||
setHeaderShown(false); |
||||
}, 600); |
||||
}, []); |
||||
|
||||
return ( |
||||
<Tab.Navigator |
||||
initialRouteName="HomeTab" |
||||
screenOptions={{ |
||||
tabBarHideOnKeyboard: true, |
||||
headerShown, |
||||
headerStyle: { |
||||
backgroundColor: |
||||
theme === "light" ? Colors.theme1.white : Colors.theme1.dark, |
||||
}, |
||||
tabBarIconStyle: { |
||||
transform: [{ scaleX: -1 }], |
||||
}, |
||||
tabBarLabelPosition: "below-icon", |
||||
tabBarActiveTintColor: |
||||
theme === "light" ? Colors.theme1.green79 : Colors.theme1.greenCF, |
||||
tabBarInactiveTintColor: |
||||
theme === "light" ? Colors.theme1.gray20 : Colors.theme1.white, |
||||
tabBarStyle: { |
||||
backgroundColor: |
||||
theme === "light" ? Colors.theme1.white : Colors.theme1.dark, |
||||
transform: [{ scaleX: -1 }], |
||||
height: 65 + insets.bottom, |
||||
borderWidth: 0, |
||||
}, |
||||
tabBarLabelStyle: { |
||||
transform: [{ scaleX: -1 }, { translateY: -5 }], |
||||
fontSize: fontSize.xs, |
||||
fontFamily: "bold", |
||||
}, |
||||
tabBarShowLabel: true, |
||||
}} |
||||
> |
||||
{bottomNavigationList.home.isActive ? ( |
||||
<Tab.Screen |
||||
name="HomeTab" |
||||
children={() => <HomeStackScreen theme={theme} />} |
||||
options={{ |
||||
title: bottomNavigationList.home.label, |
||||
tabBarIcon: ({ focused, color }) => |
||||
focused ? ( |
||||
<Svg |
||||
xmlns="http://www.w3.org/2000/svg" |
||||
width={33.58} |
||||
height={33.579} |
||||
> |
||||
<Path |
||||
d="M12.62 3.974 5.079 9.85a6.658 6.658 0 0 0-2.281 4.645v10.368a5.912 5.912 0 0 0 5.89 5.9h16.2a5.909 5.909 0 0 0 5.89-5.89V14.691a6.609 6.609 0 0 0-2.518-4.827l-8.644-6.058a6.278 6.278 0 0 0-6.996.168Z" |
||||
fill={ |
||||
theme === "light" |
||||
? Colors.theme1.green79 |
||||
: Colors.theme1.greenCF |
||||
} |
||||
/> |
||||
<Path |
||||
data-name="Vector" |
||||
d="M16.79 25.471v-6.693" |
||||
fill="none" |
||||
stroke={theme === "light" ? "#fff" : Colors.theme1.dark} |
||||
strokeLinecap="round" |
||||
strokeLinejoin="round" |
||||
strokeWidth={1.5} |
||||
/> |
||||
</Svg> |
||||
) : ( |
||||
<Svg |
||||
xmlns="http://www.w3.org/2000/svg" |
||||
width={33.58} |
||||
height={33.579} |
||||
style={{ |
||||
transform: [{ scale: 0.7 }], |
||||
}} |
||||
> |
||||
<Path |
||||
d="M12.62 3.974 5.079 9.85a6.658 6.658 0 0 0-2.281 4.645v10.368a5.912 5.912 0 0 0 5.89 5.9h16.2a5.909 5.909 0 0 0 5.89-5.89V14.691a6.609 6.609 0 0 0-2.518-4.827l-8.644-6.058a6.278 6.278 0 0 0-6.996.168Z" |
||||
fill="none" |
||||
stroke={ |
||||
theme === "light" |
||||
? Colors.theme1.green79 |
||||
: Colors.theme1.white |
||||
} |
||||
strokeLinecap="round" |
||||
strokeLinejoin="round" |
||||
strokeWidth={1.5} |
||||
/> |
||||
<Path |
||||
data-name="Vector" |
||||
d="M16.79 25.471v-6.693" |
||||
fill="none" |
||||
stroke={ |
||||
theme === "light" |
||||
? Colors.theme1.green79 |
||||
: Colors.theme1.white |
||||
} |
||||
strokeLinecap="round" |
||||
strokeLinejoin="round" |
||||
strokeWidth={1.5} |
||||
/> |
||||
</Svg> |
||||
), |
||||
}} |
||||
/> |
||||
) : null} |
||||
|
||||
{bottomNavigationList.products.isActive ? ( |
||||
<Tab.Screen |
||||
name="ProductsTab" |
||||
children={() => <ProductsStackScreen theme={theme} />} |
||||
options={{ |
||||
title: bottomNavigationList.products.label, |
||||
tabBarIcon: ({ focused, color }) => |
||||
focused ? ( |
||||
<Svg |
||||
xmlns="http://www.w3.org/2000/svg" |
||||
width={35.135} |
||||
height={34.763} |
||||
> |
||||
<Path |
||||
d="M32.207 24.227V6.798a2.869 2.869 0 0 0-3.179-2.875h-.088a27.857 27.857 0 0 0-10.35 3.422l-.249.159a1.641 1.641 0 0 1-1.552 0l-.361-.216A27.72 27.72 0 0 0 6.09 3.909a2.864 2.864 0 0 0-3.162 2.874v17.444a2.981 2.981 0 0 0 2.547 2.859l.425.058a37.976 37.976 0 0 1 10.892 3.524l.059.029a1.6 1.6 0 0 0 1.405 0 37.631 37.631 0 0 1 10.921-3.552l.483-.058a2.981 2.981 0 0 0 2.547-2.86Z" |
||||
fill={ |
||||
theme === "light" |
||||
? Colors.theme1.green79 |
||||
: Colors.theme1.greenCF |
||||
} |
||||
/> |
||||
<Path |
||||
data-name="Vector" |
||||
d="M17.567 8.851v20.774M29.213 12.298h-3.294M29.159 16.643h-4.392" |
||||
fill="none" |
||||
stroke={theme === "light" ? "#fff" : Colors.theme1.dark} |
||||
strokeLinecap="round" |
||||
strokeLinejoin="round" |
||||
strokeWidth={1.5} |
||||
/> |
||||
</Svg> |
||||
) : ( |
||||
<Svg |
||||
xmlns="http://www.w3.org/2000/svg" |
||||
width={35.135} |
||||
height={34.763} |
||||
style={{ |
||||
transform: [{ scale: 0.7 }], |
||||
}} |
||||
> |
||||
<G |
||||
fill="none" |
||||
stroke={ |
||||
theme === "light" |
||||
? Colors.theme1.green79 |
||||
: Colors.theme1.white |
||||
} |
||||
strokeLinecap="round" |
||||
strokeLinejoin="round" |
||||
strokeWidth={1.5} |
||||
> |
||||
<Path d="M32.207 24.227V6.798a2.869 2.869 0 0 0-3.179-2.875h-.088a27.857 27.857 0 0 0-10.35 3.422l-.249.159a1.641 1.641 0 0 1-1.552 0l-.361-.216A27.72 27.72 0 0 0 6.09 3.909a2.864 2.864 0 0 0-3.162 2.874v17.444a2.981 2.981 0 0 0 2.547 2.859l.425.058a37.976 37.976 0 0 1 10.892 3.524l.059.029a1.6 1.6 0 0 0 1.405 0 37.631 37.631 0 0 1 10.921-3.552l.483-.058a2.981 2.981 0 0 0 2.547-2.86Z" /> |
||||
<Path |
||||
data-name="Vector" |
||||
d="M17.567 7.666v21.959M29.213 12.298h-3.294M29.159 16.643h-4.392" |
||||
/> |
||||
</G> |
||||
</Svg> |
||||
), |
||||
}} |
||||
/> |
||||
) : null} |
||||
|
||||
{bottomNavigationList.vod.isActive ? ( |
||||
<Tab.Screen |
||||
name="VODTab" |
||||
children={() => <VODStackScreen theme={theme} />} |
||||
options={{ |
||||
unmountOnExit: true, |
||||
unmountOnBlur: true, |
||||
title: bottomNavigationList.vod.label, |
||||
tabBarIcon: ({ focused, color }) => |
||||
focused ? ( |
||||
<Svg |
||||
xmlns="http://www.w3.org/2000/svg" |
||||
width={35} |
||||
height={31.1} |
||||
> |
||||
<G data-name="Group 2000"> |
||||
<Path |
||||
d="M25.421 29.241H8.974C4.04 29.241.75 26.392.75 19.744V10.25c0-6.651 3.29-9.5 8.224-9.5h16.447c4.935 0 8.229 2.849 8.229 9.5v9.5c0 6.642-3.294 9.491-8.229 9.491Z" |
||||
fill={ |
||||
theme === "light" |
||||
? Colors.theme1.green79 |
||||
: Colors.theme1.greenCF |
||||
} |
||||
stroke={ |
||||
theme === "light" |
||||
? Colors.theme1.green79 |
||||
: Colors.theme1.greenCF |
||||
} |
||||
strokeLinecap="round" |
||||
strokeLinejoin="round" |
||||
strokeWidth={1.5} |
||||
data-name="vuesax/linear/music-playlist" |
||||
/> |
||||
<Path |
||||
data-name="Vector" |
||||
d="M12.427 14.995v-2.083c0-2.673 1.892-3.766 4.2-2.43l1.805 1.042 1.806 1.041c2.308 1.336 2.308 3.523 0 4.86l-1.806 1.041-1.805 1.046c-2.308 1.332-4.2.239-4.2-2.434v-2.083Z" |
||||
fill="none" |
||||
stroke={theme === "light" ? "#fff" : Colors.theme1.dark} |
||||
strokeLinecap="round" |
||||
strokeLinejoin="round" |
||||
strokeWidth={1.5} |
||||
/> |
||||
</G> |
||||
</Svg> |
||||
) : ( |
||||
<Svg |
||||
xmlns="http://www.w3.org/2000/svg" |
||||
width={35} |
||||
height={32} |
||||
style={{ |
||||
transform: [{ scale: 0.7 }], |
||||
}} |
||||
> |
||||
<G data-name="Group 1999"> |
||||
<Path |
||||
d="M25.421 29.241H8.974C4.04 29.241.75 26.392.75 19.744V10.25c0-6.651 3.29-9.5 8.224-9.5h16.447c4.935 0 8.229 2.849 8.229 9.5v9.5c0 6.642-3.294 9.491-8.229 9.491Z" |
||||
fill="none" |
||||
stroke={ |
||||
theme === "light" |
||||
? Colors.theme1.green79 |
||||
: Colors.theme1.white |
||||
} |
||||
strokeLinecap="round" |
||||
strokeLinejoin="round" |
||||
strokeWidth={1.5} |
||||
data-name="vuesax/linear/music-playlist" |
||||
/> |
||||
<Path |
||||
data-name="Vector" |
||||
d="M12.427 14.995v-2.083c0-2.673 1.892-3.766 4.2-2.43l1.805 1.042 1.806 1.041c2.308 1.336 2.308 3.523 0 4.86l-1.806 1.041-1.805 1.046c-2.308 1.332-4.2.239-4.2-2.434v-2.083Z" |
||||
fill="none" |
||||
stroke={ |
||||
theme === "light" |
||||
? Colors.theme1.green79 |
||||
: Colors.theme1.white |
||||
} |
||||
strokeLinecap="round" |
||||
strokeLinejoin="round" |
||||
strokeWidth={1.5} |
||||
/> |
||||
</G> |
||||
</Svg> |
||||
), |
||||
}} |
||||
/> |
||||
) : null} |
||||
|
||||
{bottomNavigationList.cart.isActive ? ( |
||||
<Tab.Screen |
||||
name="ShoppingCartTab" |
||||
children={() => <CARTStackScreen theme={theme} />} |
||||
options={{ |
||||
tabBarBadge: userProducts.filter((product) => product.condition < 2) |
||||
.length |
||||
? userProducts.filter((product) => product.condition < 2).length |
||||
: null, |
||||
tabBarBadgeStyle: { |
||||
color: "white", |
||||
backgroundColor: |
||||
theme === "light" |
||||
? Colors.theme1.greenCF |
||||
: Colors.theme1.greenCF, |
||||
fontSize: fontSize.sm, |
||||
paddingTop: 2, |
||||
color: |
||||
theme === "light" ? Colors.theme1.white : Colors.theme1.dark, |
||||
borderWidth: 1, |
||||
borderColor: |
||||
theme === "light" ? Colors.theme1.greenCF : Colors.theme1.dark, |
||||
fontFamily: "bold", |
||||
}, |
||||
title: bottomNavigationList.cart.label, |
||||
tabBarIcon: ({ focused, color }) => |
||||
focused ? ( |
||||
<Svg |
||||
xmlns="http://www.w3.org/2000/svg" |
||||
width={31.017} |
||||
height={31.017} |
||||
style={{ transform: [{ scale: 1.2 }] }} |
||||
> |
||||
<G |
||||
fill={ |
||||
theme === "light" |
||||
? Colors.theme1.green79 |
||||
: Colors.theme1.greenCF |
||||
} |
||||
stroke={theme === "light" ? "white" : Colors.theme1.dark} |
||||
strokeLinecap="round" |
||||
strokeLinejoin="round" |
||||
strokeWidth={1.5} |
||||
data-name="vuesax/linear/bag-2" |
||||
> |
||||
<Path d="M9.693 9.912V8.659a6.168 6.168 0 0 1 5.247-6.036 5.816 5.816 0 0 1 6.384 5.79v1.782" /> |
||||
<Path |
||||
data-name="Vector" |
||||
d="M11.631 28.433h7.754c5.2 0 6.126-2.081 6.4-4.614l.969-7.754c.345-3.154-.555-5.726-6.076-5.726H10.339c-5.519 0-6.423 2.572-6.074 5.725l.969 7.754c.271 2.534 1.202 4.615 6.397 4.615ZM20.027 15.509h.011M10.979 15.509h.011" |
||||
/> |
||||
</G> |
||||
</Svg> |
||||
) : ( |
||||
<Svg |
||||
xmlns="http://www.w3.org/2000/svg" |
||||
width={31.017} |
||||
height={31.017} |
||||
style={{ |
||||
transform: [{ scale: 0.8 }], |
||||
}} |
||||
> |
||||
<G |
||||
fill="none" |
||||
stroke={ |
||||
theme === "light" |
||||
? Colors.theme1.green79 |
||||
: Colors.theme1.white |
||||
} |
||||
strokeLinecap="round" |
||||
strokeLinejoin="round" |
||||
strokeWidth={1.5} |
||||
data-name="vuesax/linear/bag-2" |
||||
> |
||||
<Path d="M9.693 9.912V8.659a6.168 6.168 0 0 1 5.247-6.036 5.816 5.816 0 0 1 6.384 5.79v1.782" /> |
||||
<Path |
||||
data-name="Vector" |
||||
d="M11.631 28.433h7.754c5.2 0 6.126-2.081 6.4-4.614l.969-7.754c.345-3.154-.555-5.726-6.076-5.726H10.339c-5.519 0-6.423 2.572-6.074 5.725l.969 7.754c.271 2.534 1.202 4.615 6.397 4.615ZM20.027 15.509h.011M10.979 15.509h.011" |
||||
/> |
||||
</G> |
||||
</Svg> |
||||
), |
||||
}} |
||||
/> |
||||
) : null} |
||||
|
||||
{bottomNavigationList.profile.isActive ? ( |
||||
<Tab.Screen |
||||
name="ProfileTab" |
||||
children={() => <PROFILEStackScreen theme={theme} />} |
||||
options={{ |
||||
title: bottomNavigationList.profile.label, |
||||
tabBarIcon: ({ focused, color }) => |
||||
focused ? ( |
||||
<Svg |
||||
xmlns="http://www.w3.org/2000/svg" |
||||
width={31.192} |
||||
height={31.192} |
||||
> |
||||
<G |
||||
fill={ |
||||
theme === "light" |
||||
? Colors.theme1.green79 |
||||
: Colors.theme1.greenCF |
||||
} |
||||
> |
||||
<Path d="M15.803 14.127a2.363 2.363 0 0 0-.429 0 5.777 5.777 0 1 1 .429 0Z" /> |
||||
<Path |
||||
data-name="Vector" |
||||
d="M9.306 18.923c-3.145 2.105-3.145 5.537 0 7.629a12.693 12.693 0 0 0 13.01 0c3.145-2.105 3.145-5.537 0-7.629a12.752 12.752 0 0 0-13.01 0Z" |
||||
/> |
||||
</G> |
||||
</Svg> |
||||
) : ( |
||||
<Svg |
||||
xmlns="http://www.w3.org/2000/svg" |
||||
width={31.192} |
||||
height={31.192} |
||||
style={{ |
||||
transform: [{ scale: 0.8 }], |
||||
}} |
||||
> |
||||
<G |
||||
fill="none" |
||||
stroke={ |
||||
theme === "light" |
||||
? Colors.theme1.green79 |
||||
: Colors.theme1.white |
||||
} |
||||
strokeLinecap="round" |
||||
strokeLinejoin="round" |
||||
strokeWidth={1.5} |
||||
> |
||||
<Path d="M15.803 14.127a2.363 2.363 0 0 0-.429 0 5.777 5.777 0 1 1 .429 0Z" /> |
||||
<Path |
||||
data-name="Vector" |
||||
d="M9.306 18.923c-3.145 2.105-3.145 5.537 0 7.629a12.693 12.693 0 0 0 13.01 0c3.145-2.105 3.145-5.537 0-7.629a12.752 12.752 0 0 0-13.01 0Z" |
||||
/> |
||||
</G> |
||||
</Svg> |
||||
), |
||||
contentStyle: { |
||||
backgroundColor: "white", |
||||
}, |
||||
}} |
||||
/> |
||||
) : null} |
||||
</Tab.Navigator> |
||||
); |
||||
}; |
||||
|
||||
const HomeStack = createNativeStackNavigator(); |
||||
const HomeStackScreen = ({ theme }) => { |
||||
return ( |
||||
<HomeStack.Navigator |
||||
screenOptions={{ |
||||
headerShown: false, |
||||
contentStyle: { |
||||
backgroundColor: |
||||
theme === "light" ? Colors.theme1.white : Colors.theme1.dark, |
||||
}, |
||||
}} |
||||
initialRouteName="Home" |
||||
> |
||||
<HomeStack.Screen name="Home" component={Home} /> |
||||
<HomeStack.Screen name="VOD" component={Videos} /> |
||||
<HomeStack.Screen name="Video" component={Video} unmountOnExit={true} /> |
||||
<HomeStack.Screen name="VideoDisplay" component={VideoDisplay} /> |
||||
<HomeStack.Screen name="Products" component={Products} /> |
||||
<HomeStack.Screen name="Product" component={Product} /> |
||||
<HomeStack.Screen name="Sample" component={Sample} /> |
||||
<HomeStack.Screen name="Blogs" component={Blogs} /> |
||||
<HomeStack.Screen name="MoreBlog" component={MoreBlog} /> |
||||
<HomeStack.Screen name="Blog" component={Blog} /> |
||||
<HomeStack.Screen name="Info" component={Info} /> |
||||
</HomeStack.Navigator> |
||||
); |
||||
}; |
||||
|
||||
const ProductsStack = createNativeStackNavigator(); |
||||
const ProductsStackScreen = ({ theme }) => { |
||||
return ( |
||||
<ProductsStack.Navigator |
||||
screenOptions={{ |
||||
headerShown: false, |
||||
contentStyle: { |
||||
backgroundColor: |
||||
theme === "light" ? Colors.theme1.white : Colors.theme1.dark, |
||||
}, |
||||
}} |
||||
initialRouteName="Products" |
||||
> |
||||
<ProductsStack.Screen name="Products" component={Products} /> |
||||
<ProductsStack.Screen name="Product" component={Product} /> |
||||
<ProductsStack.Screen name="Sample" component={Sample} /> |
||||
<ProductsStack.Screen name="Info" component={Info} /> |
||||
</ProductsStack.Navigator> |
||||
); |
||||
}; |
||||
|
||||
const VODStack = createNativeStackNavigator(); |
||||
const VODStackScreen = ({ theme }) => { |
||||
return ( |
||||
<VODStack.Navigator |
||||
screenOptions={{ |
||||
headerShown: false, |
||||
contentStyle: { |
||||
backgroundColor: |
||||
theme === "light" ? Colors.theme1.white : Colors.theme1.dark, |
||||
}, |
||||
}} |
||||
initialRouteName="VOD" |
||||
> |
||||
<VODStack.Screen name="VOD" component={Videos} /> |
||||
<VODStack.Screen name="Video" component={Video} unmountOnExit={true} /> |
||||
<VODStack.Screen name="VideoDisplay" component={VideoDisplay} /> |
||||
</VODStack.Navigator> |
||||
); |
||||
}; |
||||
|
||||
const CARTStack = createNativeStackNavigator(); |
||||
const CARTStackScreen = ({ theme }) => { |
||||
return ( |
||||
<CARTStack.Navigator |
||||
screenOptions={{ |
||||
headerShown: false, |
||||
contentStyle: { |
||||
backgroundColor: |
||||
theme === "light" ? Colors.theme1.white : Colors.theme1.dark, |
||||
}, |
||||
}} |
||||
initialRouteName="ShoppingCart" |
||||
> |
||||
<CARTStack.Screen name="ShoppingCart" component={ShoppingCart} /> |
||||
<CARTStack.Screen name="DeliveryForm" component={DeliveryForm} /> |
||||
<CARTStack.Screen name="Info" component={Info} /> |
||||
</CARTStack.Navigator> |
||||
); |
||||
}; |
||||
|
||||
const PROFILEStack = createNativeStackNavigator(); |
||||
const PROFILEStackScreen = ({ theme }) => { |
||||
return ( |
||||
<PROFILEStack.Navigator |
||||
screenOptions={{ |
||||
headerShown: false, |
||||
contentStyle: { |
||||
backgroundColor: |
||||
theme === "light" ? Colors.theme1.white : Colors.theme1.dark, |
||||
}, |
||||
}} |
||||
> |
||||
<PROFILEStack.Screen name="Profile" component={Profile} /> |
||||
<PROFILEStack.Screen name="ProfileBookmark" component={ProfileBookmark} /> |
||||
<PROFILEStack.Screen name="Products" component={Products} /> |
||||
<PROFILEStack.Screen name="Product" component={Product} /> |
||||
<PROFILEStack.Screen name="Blogs" component={Blogs} /> |
||||
<PROFILEStack.Screen name="MoreBlog" component={MoreBlog} /> |
||||
<PROFILEStack.Screen name="Blog" component={Blog} /> |
||||
<PROFILEStack.Screen name="MyCourses" component={MyCourses} /> |
||||
</PROFILEStack.Navigator> |
||||
); |
||||
}; |
||||
|
||||
const prefix = Linking.createURL("/"); |
||||
|
||||
const Stack = createNativeStackNavigator(); |
||||
const Navigation = ({ |
||||
getStatus, |
||||
isLogin, |
||||
userProducts, |
||||
ltr, |
||||
setLTR, |
||||
theme, |
||||
}) => { |
||||
const linking = { |
||||
prefixes: [prefix], |
||||
}; |
||||
|
||||
const setDirection = async () => { |
||||
setLTR(); |
||||
await I18nManager.allowRTL(false); |
||||
}; |
||||
|
||||
useEffect(() => { |
||||
if (I18nManager.isRTL && !ltr) { |
||||
setDirection(); |
||||
Restart(); |
||||
} |
||||
getStatus(); |
||||
StatusBar.setBarStyle( |
||||
`${theme === "light" ? "dark" : "light"}-content`, |
||||
true |
||||
); |
||||
return () => { |
||||
console.log("This will be logged on unmount"); |
||||
}; |
||||
}, []); |
||||
|
||||
return ( |
||||
<NavigationContainer linking={linking}> |
||||
<Stack.Navigator |
||||
// initialRouteName="Root"
|
||||
screenOptions={{ |
||||
headerShown: false, |
||||
contentStyle: { |
||||
backgroundColor: |
||||
theme === "light" ? Colors.theme1.white : Colors.theme1.dark, |
||||
}, |
||||
}} |
||||
> |
||||
<Stack.Screen name="Splash" component={Splash} /> |
||||
<Stack.Screen name="Login" component={Login} /> |
||||
<Stack.Screen name="Rules" component={Rules} /> |
||||
<Stack.Screen name="Otp" component={Otp} /> |
||||
<Stack.Screen |
||||
name="Root" |
||||
children={() => ( |
||||
<BottomTabNavigator theme={theme} userProducts={userProducts} /> |
||||
)} |
||||
/> |
||||
<Stack.Screen name="QR" component={QR} /> |
||||
<Stack.Screen name="Orders" component={OrdersFollowUp} /> |
||||
<Stack.Screen name="Order" component={OrderDetails} /> |
||||
<Stack.Screen name="Faq" component={Faq} /> |
||||
<Stack.Screen name="Activation" component={Activation} /> |
||||
<Stack.Screen name="QRContent" component={QRContent} /> |
||||
<Stack.Screen name="Contact" component={Contact} /> |
||||
<Stack.Screen name="AR" component={AR} /> |
||||
<Stack.Screen name="CreateAddress" component={Address} /> |
||||
<Stack.Screen name="ProfileAddress" component={ProfileAddress} /> |
||||
<Stack.Screen name="Info" component={Info} /> |
||||
<Stack.Screen name="Ticket" component={Ticket} /> |
||||
<Stack.Screen name="Tickets" component={Tickets} /> |
||||
<Stack.Screen name="TicketStatus" component={TicketStatus} /> |
||||
</Stack.Navigator> |
||||
</NavigationContainer> |
||||
); |
||||
}; |
||||
|
||||
const mapStateToProps = (state) => ({ |
||||
isLogin: state.user.status, |
||||
userProducts: state.userProduct.list, |
||||
theme: state.publicApi.theme, |
||||
ltr: state.publicApi.ltr, |
||||
}); |
||||
const mapDispatchToProps = { |
||||
getStatus: user.getStatus, |
||||
setLTR: publicApi.setLTR, |
||||
}; |
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(Navigation); |
After Width: | Height: | Size: 7.7 KiB |
After Width: | Height: | Size: 834 B |
After Width: | Height: | Size: 271 B |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 24 KiB |
@ -0,0 +1,172 @@ |
||||
import React, { useState } from "react"; |
||||
import { Dimensions } from "react-native"; |
||||
import { connect } from "react-redux"; |
||||
import AwesomeAlert from "react-native-awesome-alerts"; |
||||
|
||||
//style
|
||||
import Colors from "../constants/Colors"; |
||||
|
||||
//variables
|
||||
const { width } = Dimensions.get("window"); |
||||
|
||||
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 ( |
||||
<> |
||||
<AwesomeAlert |
||||
show={alert.show} |
||||
progressColor="red" |
||||
showProgress={alert.showProgress} |
||||
title={alert.title} |
||||
titleStyle={{ |
||||
fontFamily: "bold", |
||||
color: |
||||
props.theme === "light" |
||||
? Colors.theme1.gray20 |
||||
: Colors.theme1.white, |
||||
}} |
||||
message={alert.message} |
||||
messageStyle={{ |
||||
textAlign: "right", |
||||
fontFamily: "regular", |
||||
color: |
||||
props.theme === "light" |
||||
? Colors.theme1.gray20 |
||||
: Colors.theme1.white, |
||||
}} |
||||
closeOnTouchOutside={alert.closeOnTouchOutside} |
||||
closeOnHardwareBackPress={alert.closeOnHardwareBackPress} |
||||
showCancelButton={alert.showCancelButton} |
||||
showConfirmButton={alert.showConfirmButton} |
||||
cancelText={alert.cancelText} |
||||
confirmText={alert.confirmText} |
||||
confirmButtonColor={alert.confirmButtonColor} |
||||
onCancelPressed={onCancelPressed} |
||||
onConfirmPressed={onConfirmPressed} |
||||
cancelButtonTextStyle={{ |
||||
color: props.theme === "light" ? "#777" : Colors.theme1.grayE3, |
||||
fontFamily: "regular", |
||||
}} |
||||
confirmButtonTextStyle={{ |
||||
fontFamily: "regular", |
||||
}} |
||||
contentStyle={{ |
||||
width: width / 1.5, |
||||
}} |
||||
cancelButtonStyle={{ |
||||
fontFamily: "regular", |
||||
borderColor: props.theme === "light" ? "#777" : Colors.theme1.grayE3, |
||||
borderWidth: 1, |
||||
backgroundColor: |
||||
props.theme === "light" ? Colors.theme1.white : Colors.theme1.black, |
||||
}} |
||||
confirmButtonStyle={{ |
||||
alignItems: "center", |
||||
justifyContent: "center", |
||||
fontFamily: "regular", |
||||
borderColor: "#2980b9", |
||||
borderWidth: 1, |
||||
}} |
||||
contentContainerStyle={{ |
||||
backgroundColor: |
||||
props.theme === "light" ? "white" : Colors.theme1.black, |
||||
}} |
||||
useNativeDriver={true} |
||||
/> |
||||
<AwesomeAlert |
||||
show={apiAlert.show} |
||||
progressColor="red" |
||||
showProgress={apiAlert.showProgress} |
||||
title={apiAlert.title} |
||||
message={apiAlert.message} |
||||
closeOnTouchOutside={apiAlert.closeOnTouchOutside} |
||||
closeOnHardwareBackPress={apiAlert.closeOnHardwareBackPress} |
||||
showCancelButton={apiAlert.showCancelButton} |
||||
showConfirmButton={apiAlert.showConfirmButton} |
||||
cancelText={apiAlert.cancelText} |
||||
confirmText={apiAlert.confirmText} |
||||
confirmButtonColor={apiAlert.confirmButtonColor} |
||||
onCancelPressed={onApiCancelPressed} |
||||
onConfirmPressed={onApiConfirmPressed} |
||||
contentStyle={{ |
||||
width: width / 1.5, |
||||
}} |
||||
confirmButtonStyle={{ |
||||
width: width / 4, |
||||
alignItems: "center", |
||||
justifyContent: "center", |
||||
}} |
||||
useNativeDriver={true} |
||||
/> |
||||
</> |
||||
); |
||||
}; |
||||
|
||||
const mapStateToProps = (state) => ({ |
||||
theme: state.publicApi.theme, |
||||
}); |
||||
|
||||
export default connect(mapStateToProps)(AlertModal); |
@ -0,0 +1,62 @@ |
||||
import React from "react"; |
||||
import { Image, View } from "react-native"; |
||||
import Svg, { G, Path } from "react-native-svg"; |
||||
import { connect } from "react-redux"; |
||||
|
||||
//style
|
||||
import tw from "tailwind-rn"; |
||||
import Colors from "../constants/Colors"; |
||||
|
||||
function Avatar({ source, size, theme }) { |
||||
return ( |
||||
<View |
||||
style={[ |
||||
tw("rounded-full overflow-hidden flex justify-center items-center"), |
||||
{ |
||||
minWidth: size, |
||||
minHeight: size, |
||||
backgroundColor: |
||||
theme === "light" |
||||
? Colors.theme1.grayE3 |
||||
: Colors.theme1.white + '55', |
||||
}, |
||||
]} |
||||
> |
||||
{source ? ( |
||||
<Image |
||||
source={{ uri: `https:dnvn.ir/api/v1/file/${source}` }} |
||||
style={{ minWidth: "100%", minHeight: "100%" }} |
||||
resizeMode="contain" |
||||
/> |
||||
) : ( |
||||
<Svg |
||||
data-name="vuesax/bold/frame" |
||||
xmlns="http://www.w3.org/2000/svg" |
||||
width={36.975} |
||||
height={36.975} |
||||
> |
||||
<G fill="none"> |
||||
<Path d="M18.488 3.081a7.311 7.311 0 0 0-.185 14.621 1.243 1.243 0 0 1 .339 0h.108a7.313 7.313 0 0 0-.262-14.621Z" /> |
||||
<Path |
||||
d="M18.488 5.081a5.324 5.324 0 0 0-5.318 5.318c0 1.395.528 2.705 1.486 3.689.94.965 2.215 1.535 3.6 1.61.165-.011.328-.01.484.002a5.31 5.31 0 0 0 5.066-5.304 5.324 5.324 0 0 0-5.318-5.315m0-2a7.325 7.325 0 0 1 7.318 7.318 7.3 7.3 0 0 1-7.056 7.303h-.108a1.243 1.243 0 0 0-.339 0c-4.036-.14-7.133-3.344-7.133-7.303a7.325 7.325 0 0 1 7.318-7.318Z" |
||||
fill={theme === 'light' ? "#818181" : Colors.theme1.white} |
||||
/> |
||||
<G data-name="Vector"> |
||||
<Path d="M26.314 21.8a15.3 15.3 0 0 0-15.637 0 6.081 6.081 0 0 0-3.035 4.976 6.03 6.03 0 0 0 3.02 4.945 14.234 14.234 0 0 0 7.826 2.172 14.234 14.234 0 0 0 7.826-2.172 6.078 6.078 0 0 0 3.02-4.976 6.066 6.066 0 0 0-3.02-4.945Z" /> |
||||
<Path |
||||
d="M18.507 21.651c-2.528 0-4.977.661-6.721 1.814-1.383.926-2.144 2.102-2.144 3.311 0 1.201.756 2.366 2.129 3.282l.006.003c1.734 1.165 4.18 1.833 6.711 1.833 2.53 0 4.977-.668 6.708-1.83 1.762-1.189 2.136-2.455 2.138-3.31-.01-.862-.388-2.129-2.129-3.29-1.729-1.152-4.17-1.813-6.698-1.813m0-2c2.831 0 5.658.716 7.807 2.15 1.942 1.293 3.005 3.05 3.02 4.945 0 1.91-1.078 3.666-3.02 4.976-4.313 2.896-11.339 2.896-15.652 0-1.942-1.294-3.02-3.05-3.02-4.946 0-1.895 1.078-3.666 3.035-4.976 2.165-1.433 5-2.149 7.83-2.149Z" |
||||
fill={theme === 'light' ? "#818181" : Colors.theme1.white} |
||||
/> |
||||
</G> |
||||
</G> |
||||
</Svg> |
||||
)} |
||||
</View> |
||||
); |
||||
} |
||||
|
||||
const mapStateToProps = (state) => ({ |
||||
theme: state.publicApi.theme, |
||||
}); |
||||
|
||||
export default connect(mapStateToProps)(Avatar); |
@ -0,0 +1,26 @@ |
||||
import React from "react"; |
||||
import { BlurView } from "expo-blur"; |
||||
import { ActivityIndicator } from "react-native"; |
||||
import { connect } from "react-redux"; |
||||
import tw from "tailwind-rn"; |
||||
|
||||
function Blur({ theme }) { |
||||
return ( |
||||
<BlurView |
||||
intensity={280} |
||||
tint="dark" |
||||
style={[ |
||||
{ width: "100%", height: "100%" }, |
||||
tw("flex-1 flex justify-center items-center"), |
||||
]} |
||||
> |
||||
<ActivityIndicator size="large" color="#12CF7F" /> |
||||
</BlurView> |
||||
); |
||||
} |
||||
|
||||
const mapStateToProps = (state) => ({ |
||||
theme: state.publicApi.theme, |
||||
}); |
||||
|
||||
export default connect(mapStateToProps)(Blur); |
@ -0,0 +1,107 @@ |
||||
import React from "react"; |
||||
import { TextInput, View, Text, StyleSheet } from "react-native"; |
||||
import { connect } from "react-redux"; |
||||
|
||||
import tw from "tailwind-rn"; |
||||
import Colors from "../constants/Colors"; |
||||
import fontSize from "../constants/fontSize"; |
||||
|
||||
const FloatingLabelInput = ({ |
||||
label, |
||||
textAlign, |
||||
direction, |
||||
labelBackgroundColor, |
||||
onChange, |
||||
name, |
||||
value, |
||||
textColor, |
||||
placeholder, |
||||
maxLength, |
||||
autoFocus, |
||||
regex, |
||||
mobile, |
||||
keyboardType, |
||||
multiline, |
||||
theme, |
||||
editable = true, |
||||
...props |
||||
}) => { |
||||
const [isFocused, setIsFocused] = React.useState(false); |
||||
|
||||
const styles = StyleSheet.create({ |
||||
labelStyle: { |
||||
fontFamily: "regular", |
||||
top: !isFocused ? "50%" : 1, |
||||
fontSize: !isFocused |
||||
? Math.floor(fontSize.base) |
||||
: Math.floor(fontSize.sm), |
||||
transform: [ |
||||
{ |
||||
translateY: !isFocused |
||||
? -Math.floor(fontSize.base - 2) |
||||
: -Math.floor(fontSize.sm), |
||||
}, |
||||
], |
||||
backgroundColor : theme === 'light' ? Colors.theme1.white : Colors.theme1.dark, |
||||
color: !isFocused ? theme === 'light' ? Colors.theme1.gray2077 : Colors.theme1.white + 'aa' : Colors.theme1.green79, |
||||
}, |
||||
inputStyle: { |
||||
fontSize: fontSize.lg, |
||||
color: theme === 'light' ? Colors.theme1.black : Colors.theme1.white, |
||||
borderWidth: 1, |
||||
borderColor: isFocused |
||||
? Colors.theme1.greenC8 |
||||
: theme === "light" ? Colors.theme1.gray2077 + "66" : Colors.theme1.white + 'aa', |
||||
textAlign: textAlign, |
||||
fontFamily: "regular", |
||||
direction: direction ? direction : "rtl", |
||||
}, |
||||
}); |
||||
|
||||
React.useEffect(() => { |
||||
if (value) { |
||||
setIsFocused(true); |
||||
} else { |
||||
setIsFocused(false); |
||||
} |
||||
}, [value]); |
||||
|
||||
return ( |
||||
<View style={tw("mt-4 pb-1")}> |
||||
<Text |
||||
style={[ |
||||
styles.labelStyle, |
||||
tw("px-1 z-10 absolute right-3 text-center"), |
||||
]} |
||||
onPress={() => setIsFocused(true)} |
||||
> |
||||
{label} |
||||
</Text> |
||||
<TextInput |
||||
style={[ |
||||
styles.inputStyle, |
||||
tw(`rounded-sm ${mobile ? "py-2" : "py-3"} px-4`), |
||||
]} |
||||
onChangeText={(text) => onChange(name, (text = regex(text)))} |
||||
placeholder={placeholder} |
||||
onFocus={() => setIsFocused(true)} |
||||
autoFocus={autoFocus} |
||||
underlineColorAndroid={"transparent"} |
||||
maxLength={maxLength} |
||||
value={value} |
||||
onBlur={() => (value ? {} : setIsFocused(() => false))} |
||||
keyboardType={keyboardType} |
||||
multiline={multiline} |
||||
editable={editable} |
||||
placeholderTextColor={theme === 'light' ? Colors.theme1.gray20 + 'aa' : Colors.theme1.white + '55'} |
||||
/> |
||||
</View> |
||||
); |
||||
}; |
||||
|
||||
const mapStateToProps = (state) => ({ |
||||
mobile: state.publicApi.mobile, |
||||
theme: state.publicApi.theme, |
||||
}); |
||||
|
||||
export default connect(mapStateToProps)(FloatingLabelInput); |
@ -0,0 +1,24 @@ |
||||
import React from "react"; |
||||
import { View, Text } from "react-native"; |
||||
import { connect } from "react-redux"; |
||||
import tw from "tailwind-rn"; |
||||
|
||||
const Divider = ({ type, theme }) => { |
||||
return ( |
||||
<View |
||||
style={[ |
||||
tw(`bg-gray-100 ${theme === "light" ? "" : "bg-opacity-40"} my-4`), |
||||
{ |
||||
height: type === "horizontal" ? "100%" : 1, |
||||
width: type === "horizontal" ? 1 : "100%", |
||||
}, |
||||
]} |
||||
></View> |
||||
); |
||||
}; |
||||
|
||||
const mapStateToProps = (state) => ({ |
||||
theme: state.publicApi.theme, |
||||
}); |
||||
|
||||
export default connect(mapStateToProps)(Divider); |
@ -0,0 +1,539 @@ |
||||
import React, { useState, useEffect } from "react"; |
||||
import { |
||||
View, |
||||
Platform, |
||||
UIManager, |
||||
Dimensions, |
||||
Pressable, |
||||
Text, |
||||
TouchableOpacity, |
||||
Image, |
||||
LayoutAnimation, |
||||
Animated, |
||||
} from "react-native"; |
||||
import { useNavigation } from "@react-navigation/native"; |
||||
import { asyncAwesomeAlert } from "../utils/AsyncWrappers"; |
||||
import { connect } from "react-redux"; |
||||
import { user, publicApi } from "../redux/actions"; |
||||
import Svg, { Path, G } from "react-native-svg"; |
||||
import { AntDesign } from "@expo/vector-icons"; |
||||
|
||||
//components
|
||||
import Avatar from "../components/Avatar"; |
||||
|
||||
//style
|
||||
import tw from "tailwind-rn"; |
||||
import fontSize from "../constants/fontSize"; |
||||
import Colors from "../constants/Colors"; |
||||
|
||||
//variables
|
||||
const ios = Platform.OS === "ios"; |
||||
|
||||
if ( |
||||
Platform.OS === "android" && |
||||
UIManager.setLayoutAnimationEnabledExperimental |
||||
) { |
||||
UIManager.setLayoutAnimationEnabledExperimental(true); |
||||
} |
||||
|
||||
const Drawer = ({ |
||||
route, |
||||
position, |
||||
setBoxPosition, |
||||
user, |
||||
mobile, |
||||
theme, |
||||
setIsDark, |
||||
}) => { |
||||
const [height, setHeight] = useState(Dimensions.get("window").height); |
||||
const [width, setWidth] = useState(Dimensions.get("window").width); |
||||
const fadeAnim = React.useRef(new Animated.Value(0)).current; // Initial value for opacity: 0
|
||||
const [dropdown, setDropdown] = useState(false); |
||||
const [dropdownHeight, setDropdownHeight] = useState(0); |
||||
const navigation = useNavigation(); |
||||
|
||||
const routes = React.useMemo(() => { |
||||
return [ |
||||
{ |
||||
name: "صفحه اصلی", |
||||
route: "Home", |
||||
icon: ( |
||||
<Svg |
||||
data-name="vuesax/linear/home-2" |
||||
xmlns="http://www.w3.org/2000/svg" |
||||
width={24} |
||||
height={24} |
||||
> |
||||
<G |
||||
fill="none" |
||||
stroke={ |
||||
theme === "light" ? Colors.theme1.gray20 : Colors.theme1.white |
||||
} |
||||
strokeLinecap="round" |
||||
strokeLinejoin="round" |
||||
strokeWidth={1.5} |
||||
> |
||||
<Path d="m9.02 2.84-5.39 4.2A4.759 4.759 0 0 0 2 10.36v7.41a4.225 4.225 0 0 0 4.21 4.22h11.58A4.223 4.223 0 0 0 22 17.78V10.5a4.723 4.723 0 0 0-1.8-3.45l-6.18-4.333a4.487 4.487 0 0 0-5 .123Z" /> |
||||
<Path data-name="Vector" d="M12 17.99v-3" /> |
||||
</G> |
||||
</Svg> |
||||
), |
||||
|
||||
message: "", |
||||
}, |
||||
{ |
||||
name: "فعال سازی", |
||||
route: "Activation", |
||||
icon: ( |
||||
<Svg |
||||
xmlns="http://www.w3.org/2000/svg" |
||||
width={21.431} |
||||
height={21.431} |
||||
> |
||||
<G |
||||
data-name="Group 1" |
||||
fill="none" |
||||
stroke={theme === "light" ? "#292d32" : Colors.theme1.white} |
||||
strokeLinecap="round" |
||||
strokeLinejoin="round" |
||||
strokeWidth={1.5} |
||||
> |
||||
<Path d="M20.681 13.705V7.726c0-4.983-1.993-6.976-6.976-6.976H7.726C2.743.75.75 2.743.75 7.726v5.979c0 4.983 1.993 6.976 6.976 6.976h5.979c4.983 0 6.976-1.993 6.976-6.976Z" /> |
||||
<Path |
||||
data-name="Vector" |
||||
d="m6.558 10.716 2.776 2.776 5.538-5.552" |
||||
/> |
||||
</G> |
||||
</Svg> |
||||
), |
||||
|
||||
message: "", |
||||
}, |
||||
{ |
||||
name: "واقعیت افزوده", |
||||
route: "AR", |
||||
icon: ( |
||||
<Svg |
||||
data-name="vuesax/linear/3dcube" |
||||
xmlns="http://www.w3.org/2000/svg" |
||||
width={24} |
||||
height={24} |
||||
> |
||||
<G |
||||
data-name="3dcube" |
||||
fill="none" |
||||
stroke={theme === "light" ? "#292d32" : Colors.theme1.white} |
||||
strokeLinecap="round" |
||||
strokeLinejoin="round" |
||||
strokeWidth={1.5} |
||||
> |
||||
<Path d="m12.92 2.26 6.51 3.51a1.153 1.153 0 0 1 0 1.99l-6.51 3.51a1.936 1.936 0 0 1-1.84 0L4.57 7.76a1.153 1.153 0 0 1 0-1.99l6.51-3.51a1.936 1.936 0 0 1 1.84 0Z" /> |
||||
<Path |
||||
data-name="Vector" |
||||
d="m3.61 10.13 6.05 3.03a2.238 2.238 0 0 1 1.23 1.99v5.72a1.109 1.109 0 0 1-1.61.99l-6.05-3.03A2.238 2.238 0 0 1 2 16.84v-5.72a1.109 1.109 0 0 1 1.61-.99ZM20.39 10.13l-6.05 3.03a2.238 2.238 0 0 0-1.23 1.99v5.72a1.109 1.109 0 0 0 1.61.99l6.05-3.03A2.238 2.238 0 0 0 22 16.84v-5.72a1.109 1.109 0 0 0-1.61-.99Z" |
||||
/> |
||||
</G> |
||||
</Svg> |
||||
), |
||||
|
||||
message: "", |
||||
}, |
||||
{ |
||||
name: "وبلاگ", |
||||
route: "Blogs", |
||||
icon: ( |
||||
<Svg |
||||
xmlns="http://www.w3.org/2000/svg" |
||||
width={24.055} |
||||
height={24.055} |
||||
> |
||||
<G |
||||
fill="none" |
||||
stroke={theme === "light" ? "#292d32" : Colors.theme1.white} |
||||
strokeLinecap="round" |
||||
strokeWidth={1.5} |
||||
strokeLinejoin="round" |
||||
data-name="vuesax/linear/note-2" |
||||
> |
||||
<Path d="m21.709 10.463-.982 4.19c-.842 3.618-2.506 5.081-5.633 4.781a10.538 10.538 0 0 1-1.624-.274l-1.684-.4c-4.178-.99-5.471-3.053-4.489-7.244l.982-4.2a10.5 10.5 0 0 1 .742-2.209c1.173-2.421 3.164-3.073 6.515-2.281l1.674.391c4.2.982 5.482 3.057 4.499 7.246Z" /> |
||||
<Path |
||||
data-name="Vector" |
||||
d="M15.091 19.435a9.394 9.394 0 0 1-2.352 1.083l-1.583.521c-3.979 1.283-6.074.21-7.367-3.767l-1.283-3.96c-1.283-3.98-.221-6.085 3.759-7.368l1.583-.521a10.247 10.247 0 0 1 1.173-.311 10.5 10.5 0 0 0-.742 2.205l-.982 4.195c-.982 4.19.31 6.255 4.487 7.247l1.684.4a10.538 10.538 0 0 0 1.626.271ZM12.669 8.549l4.862 1.233M13.641 12.428l2.906.742" |
||||
/> |
||||
</G> |
||||
</Svg> |
||||
), |
||||
|
||||
message: "", |
||||
}, |
||||
{ |
||||
name: "سفارشات", |
||||
route: "Orders", |
||||
icon: ( |
||||
<Svg |
||||
data-name="vuesax/linear/ranking" |
||||
xmlns="http://www.w3.org/2000/svg" |
||||
width={24} |
||||
height={24} |
||||
> |
||||
<Path |
||||
d="M8.67 14H4a2.006 2.006 0 0 0-2 2v6h6.67Z" |
||||
fill="none" |
||||
stroke={theme === "light" ? "#292d32" : Colors.theme1.white} |
||||
strokeLinecap="round" |
||||
strokeLinejoin="round" |
||||
strokeWidth={1.5} |
||||
/> |
||||
<Path |
||||
data-name="Vector" |
||||
d="M13.33 10h-2.67a2.006 2.006 0 0 0-2 2v10h6.67V12a2 2 0 0 0-2-2ZM20 17h-4.67v5H22v-3a2.006 2.006 0 0 0-2-2ZM12.52 2.07l.53 1.06a.6.6 0 0 0 .42.31l.96.16c.61.1.76.55.32.98l-.75.75a.639.639 0 0 0-.16.54l.21.92c.17.73-.22 1.01-.86.63l-.9-.53a.618.618 0 0 0-.59 0l-.9.53c-.64.38-1.03.1-.86-.63l.21-.92a.63.63 0 0 0-.156-.54l-.74-.74c-.44-.44-.3-.88.32-.98l.96-.16a.666.666 0 0 0 .42-.31l.53-1.06c.286-.58.746-.58 1.036-.01Z" |
||||
fill="none" |
||||
stroke={theme === "light" ? "#292d32" : Colors.theme1.white} |
||||
strokeLinecap="round" |
||||
strokeLinejoin="round" |
||||
strokeWidth={1.5} |
||||
/> |
||||
</Svg> |
||||
), |
||||
|
||||
message: "", |
||||
}, |
||||
{ |
||||
name: "سوالات متداول", |
||||
route: "Faq", |
||||
icon: ( |
||||
<Svg |
||||
data-name="vuesax/linear/lamp-on" |
||||
xmlns="http://www.w3.org/2000/svg" |
||||
width={24} |
||||
height={24} |
||||
> |
||||
<G |
||||
fill="none" |
||||
stroke={theme === "light" ? "#292d32" : Colors.theme1.white} |
||||
strokeLinecap="round" |
||||
strokeLinejoin="round" |
||||
strokeWidth={1.5} |
||||
> |
||||
<Path d="M8.3 18.04v-1.16a8.579 8.579 0 0 1-4.19-6.984A7.919 7.919 0 0 1 13.8 2.19a7.784 7.784 0 0 1 5.27 4.07c2.09 4.2-.11 8.66-3.34 10.61v1.16c0 .29.11.96-.96.96H9.26c-1.1.006-.96-.42-.96-.95Z" /> |
||||
<Path |
||||
data-name="Vector" |
||||
d="M8.5 21.999a12.808 12.808 0 0 1 7 0" |
||||
/> |
||||
</G> |
||||
</Svg> |
||||
), |
||||
|
||||
message: "", |
||||
}, |
||||
{ |
||||
name: "تماس با ما", |
||||
route: "Contact", |
||||
icon: ( |
||||
<Svg |
||||
data-name="vuesax/linear/call-calling" |
||||
xmlns="http://www.w3.org/2000/svg" |
||||
width={24} |
||||
height={24} |
||||
> |
||||
<G |
||||
data-name="call-calling" |
||||
fill="none" |
||||
stroke={theme === "light" ? "#292d32" : Colors.theme1.white} |
||||
strokeWidth={1.5} |
||||
> |
||||
<Path d="M21.97 18.33a2.545 2.545 0 0 1-.25 1.09 4.126 4.126 0 0 1-.68 1.02 4.508 4.508 0 0 1-1.64 1.18 5.022 5.022 0 0 1-1.95.38 8.334 8.334 0 0 1-3.26-.73 17.564 17.564 0 0 1-3.44-1.98 28.75 28.75 0 0 1-3.28-2.8 28.414 28.414 0 0 1-2.79-3.27 17.828 17.828 0 0 1-1.96-3.41A8.423 8.423 0 0 1 2 6.54a5.173 5.173 0 0 1 .36-1.93 4.6 4.6 0 0 1 1.15-1.67A2.93 2.93 0 0 1 5.59 2a1.879 1.879 0 0 1 .81.18 1.63 1.63 0 0 1 .67.56l2.32 3.27a3.422 3.422 0 0 1 .4.7 1.581 1.581 0 0 1 .14.61 1.357 1.357 0 0 1-.21.71 3.4 3.4 0 0 1-.56.71l-.76.79a.535.535 0 0 0-.16.4.908.908 0 0 0 .03.23c.03.08.06.14.08.2a8.3 8.3 0 0 0 .93 1.28c.45.52.93 1.05 1.45 1.58.54.53 1.06 1.02 1.59 1.47a7.675 7.675 0 0 0 1.29.92c.05.02.11.05.18.08a.69.69 0 0 0 .25.04.55.55 0 0 0 .41-.17l.76-.75a3.068 3.068 0 0 1 .72-.56 1.332 1.332 0 0 1 .71-.21 1.6 1.6 0 0 1 .61.13 3.868 3.868 0 0 1 .7.39l3.31 2.35a1.517 1.517 0 0 1 .55.64 2.052 2.052 0 0 1 .16.78Z" /> |
||||
<Path |
||||
data-name="Vector" |
||||
d="M18.5 9a3.965 3.965 0 0 0-1.17-2.27A3.416 3.416 0 0 0 15 5.5M22 9a7 7 0 0 0-7-7" |
||||
strokeLinecap="round" |
||||
strokeLinejoin="round" |
||||
/> |
||||
</G> |
||||
</Svg> |
||||
), |
||||
|
||||
message: "", |
||||
}, |
||||
]; |
||||
}, [user, theme]); |
||||
|
||||
const Route = React.useCallback( |
||||
({ route }) => { |
||||
return ( |
||||
<TouchableOpacity |
||||
style={[ |
||||
tw( |
||||
`w-full flex flex-row-reverse justify-start items-end ${ |
||||
mobile ? "mt-6" : "mt-10" |
||||
}` |
||||
), |
||||
{}, |
||||
]} |
||||
onPress={() => { |
||||
setBoxPosition(); |
||||
setTimeout(() => { |
||||
navigation.navigate(route.route); |
||||
}, 300); |
||||
}} |
||||
> |
||||
{route.icon} |
||||
<Text |
||||
style={[ |
||||
tw("mr-2"), |
||||
{ |
||||
fontFamily: "regular", |
||||
fontSize: mobile ? fontSize.base : fontSize.lg, |
||||
color: |
||||
theme === "light" |
||||
? Colors.theme1.gray20 |
||||
: Colors.theme1.white, |
||||
}, |
||||
]} |
||||
> |
||||
{route.name} |
||||
</Text> |
||||
</TouchableOpacity> |
||||
); |
||||
}, |
||||
[mobile, position, theme] |
||||
); |
||||
|
||||
React.useEffect(() => { |
||||
if (position === "0%") { |
||||
setTimeout(() => { |
||||
Animated.timing(fadeAnim, { |
||||
toValue: 0.7, |
||||
duration: 300, |
||||
useNativeDriver: true, // Add This line
|
||||
}).start(); |
||||
}, 300); |
||||
} |
||||
if (position === "100%") { |
||||
Animated.timing(fadeAnim, { |
||||
toValue: 0, |
||||
duration: 10, |
||||
useNativeDriver: true, // Add This line
|
||||
}).start(); |
||||
} |
||||
}, [position]); |
||||
|
||||
const onLayout = React.useCallback(() => { |
||||
setHeight(Dimensions.get("window").height); |
||||
setWidth(Dimensions.get("window").width); |
||||
}, [mobile]); |
||||
|
||||
const animateDropdown = React.useCallback(() => { |
||||
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut); |
||||
setDropdown(() => !dropdown); |
||||
setDropdownHeight(dropdownHeight === 0 ? fontSize.base + 30 : 0); |
||||
}, [position]); |
||||
|
||||
return ( |
||||
<View |
||||
style={[ |
||||
tw(`absolute top-0 flex flex-row justify-end`), |
||||
{ |
||||
left: position, |
||||
width: width, |
||||
height: height, |
||||
zIndex: 10000, |
||||
}, |
||||
]} |
||||
onLayout={() => onLayout()} |
||||
> |
||||
<Animated.View |
||||
style={[tw("w-1/5 h-full bg-black"), { opacity: fadeAnim }]} |
||||
> |
||||
<Pressable |
||||
style={tw("flex-1 items-center pt-12")} |
||||
onPress={() => setBoxPosition()} |
||||
> |
||||
<AntDesign |
||||
name="close" |
||||
size={mobile ? 25 : 30} |
||||
color={Colors.theme1.white} |
||||
onPress={() => setBoxPosition()} |
||||
/> |
||||
</Pressable> |
||||
</Animated.View> |
||||
<View |
||||
style={[ |
||||
tw("w-4/5 h-full flex"), |
||||
{ |
||||
backgroundColor: |
||||
theme === "light" ? Colors.theme1.white : Colors.theme1.dark, |
||||
}, |
||||
]} |
||||
> |
||||
<View |
||||
style={[ |
||||
tw("flex items-end pt-12 px-4"), |
||||
{ |
||||
backgroundColor: |
||||
theme === "light" |
||||
? Colors.theme1.greenCF |
||||
: Colors.theme1.blue90, |
||||
}, |
||||
]} |
||||
> |
||||
<View |
||||
style={tw( |
||||
"flex flex-row-reverse items-center w-full justify-between" |
||||
)} |
||||
> |
||||
<Avatar souce={user?.picFileIds} size={width / 6} /> |
||||
{theme === "light" ? ( |
||||
<Svg |
||||
xmlns="http://www.w3.org/2000/svg" |
||||
onPress={() => setIsDark("dark")} |
||||
width={24} |
||||
height={24} |
||||
style={{ padding: 10 }} |
||||
> |
||||
<Path |
||||
d="M2.03 12.42a10.506 10.506 0 0 0 18.93 5.3c.82-1.11.38-1.85-.99-1.6a9.494 9.494 0 0 1-2.08.14 9.324 9.324 0 0 1-8.91-9.12 8.9 8.9 0 0 1 .75-3.65c.54-1.24-.11-1.83-1.36-1.3a10.3 10.3 0 0 0-6.34 10.23Z" |
||||
fill="#fff" |
||||
data-name="vuesax/linear/moon" |
||||
/> |
||||
</Svg> |
||||
) : ( |
||||
<Svg |
||||
xmlns="http://www.w3.org/2000/svg" |
||||
onPress={() => setIsDark("light")} |
||||
width={24} |
||||
height={24} |
||||
style={{ padding: 10 }} |
||||
> |
||||
<G data-name="vuesax/linear/sun"> |
||||
<Path |
||||
d="M18.5 12A6.5 6.5 0 1 1 12 5.5a6.5 6.5 0 0 1 6.5 6.5Z" |
||||
fill="#fff" |
||||
/> |
||||
<Path |
||||
data-name="Vector" |
||||
d="m19.01 4.99.13-.13ZM4.86 19.14l.13-.13ZM12 2.08h0ZM12 22h0ZM2.08 12h0ZM22 12h0ZM4.99 4.99l-.13-.13Zm14.15 14.15-.13-.13" |
||||
fill="none" |
||||
stroke="#fff" |
||||
strokeLinecap="round" |
||||
strokeLinejoin="round" |
||||
strokeWidth={2} |
||||
/> |
||||
</G> |
||||
</Svg> |
||||
)} |
||||
</View> |
||||
|
||||
<View |
||||
style={tw( |
||||
"flex flex-row-reverse w-full justify-between px-2 pb-1 mt-2" |
||||
)} |
||||
> |
||||
<View style={tw("flex")}> |
||||
<Text |
||||
style={{ |
||||
fontSize: mobile ? fontSize.lg : fontSize.xl, |
||||
color: "white", |
||||
fontFamily: "demi", |
||||
textAlign: ios ? "right" : "auto", |
||||
}} |
||||
> |
||||
{user?.firstName + " " + user?.lastName} |
||||
</Text> |
||||
<Text |
||||
style={{ |
||||
fontSize: mobile ? fontSize.tiny : fontSize.lg, |
||||
color: "white", |
||||
fontFamily: "bold", |
||||
marginTop: 5, |
||||
textAlign: "right", |
||||
}} |
||||
> |
||||
{user?.cellphone} |
||||
</Text> |
||||
</View> |
||||
{/* <Svg |
||||
data-name="vuesax/linear/arrow-left" |
||||
xmlns="http://www.w3.org/2000/svg" |
||||
width={24} |
||||
height={24} |
||||
style={{ |
||||
transform: [{ rotate: dropdown ? "90deg" : "-90deg" }], |
||||
padding: 10, |
||||
}} |
||||
onPress={() => animateDropdown()} |
||||
> |
||||
<Path |
||||
d="M15.002 19.92 8.479 13.4a1.986 1.986 0 0 1 0-2.8l6.523-6.52" |
||||
fill="none" |
||||
stroke="#fff" |
||||
strokeLinecap="round" |
||||
strokeLinejoin="round" |
||||
strokeWidth={2} |
||||
/> |
||||
</Svg> */} |
||||
</View> |
||||
</View> |
||||
<View style={tw("flex-1 flex")}> |
||||
{/* <Pressable |
||||
style={[ |
||||
tw( |
||||
`flex flex-row justify-between items-center w-full flex-row-reverse px-4 overflow-hidden` |
||||
), |
||||
{ |
||||
borderBottomWidth: 1, |
||||
borderColor: Colors.theme1.grayE3, |
||||
height: dropdownHeight, |
||||
}, |
||||
]} |
||||
onPress={() => |
||||
asyncAwesomeAlert("نتیجه", "این قابلیت در حال توسعه است.", { |
||||
showCancelButton: false, |
||||
confirmText: "باشه", |
||||
}) |
||||
} |
||||
> |
||||
<Text |
||||
style={{ |
||||
fontSize: mobile ? fontSize.base : fontSize.xl, |
||||
fontFamily: "regular", |
||||
color: Colors.theme1.gray20, |
||||
}} |
||||
> |
||||
افزودن حساب کاربری جدید |
||||
</Text> |
||||
<Text |
||||
style={{ |
||||
marginRight: 5, |
||||
marginTop: 3, |
||||
fontSize: fontSize.xl4, |
||||
fontFamily: "bold", |
||||
color: Colors.theme1.gray20 + "77", |
||||
}} |
||||
> |
||||
+ |
||||
</Text> |
||||
</Pressable> */} |
||||
<View style={tw("flex w-full px-4")}> |
||||
{routes.map((route, index) => ( |
||||
<Route route={route} key={index} /> |
||||
))} |
||||
</View> |
||||
</View> |
||||
</View> |
||||
</View> |
||||
); |
||||
}; |
||||
|
||||
const mapStateToProps = (state) => ({ |
||||
user: state.user.status, |
||||
mobile: state.publicApi.mobile, |
||||
theme: state.publicApi.theme, |
||||
}); |
||||
|
||||
const mapDispatchToProps = { |
||||
logout: user.logout, |
||||
setIsDark: publicApi.setIsDark, |
||||
}; |
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(Drawer); |
@ -0,0 +1,63 @@ |
||||
import { View, Text, Pressable } from "react-native"; |
||||
import React from "react"; |
||||
import { connect } from "react-redux"; |
||||
|
||||
//style
|
||||
import Colors from "../constants/Colors"; |
||||
import tw from "tailwind-rn"; |
||||
import fontSize from "../constants/fontSize"; |
||||
|
||||
const Empty = ({ text, buttonText, buttonAction, theme }) => { |
||||
return ( |
||||
<View style={tw("flex-1 flex justify-center items-center")}> |
||||
<Text |
||||
style={[ |
||||
{ |
||||
fontFamily: "regular", |
||||
fontSize: fontSize.tiny, |
||||
transform: [{ translateY: -50 }], |
||||
color: |
||||
theme === "light" ? Colors.theme1.gray20 : Colors.theme1.white, |
||||
}, |
||||
]} |
||||
> |
||||
{text + " " + ":("} |
||||
</Text> |
||||
{buttonText ? ( |
||||
<Pressable |
||||
style={[ |
||||
tw("py-2 px-5 rounded-sm"), |
||||
{ |
||||
backgroundColor: theme === "light" ? Colors.theme1.greenCF : null, |
||||
borderWidth: theme === "light" ? 0 : 1, |
||||
borderColor: Colors.theme1.greenCF, |
||||
}, |
||||
]} |
||||
onPress={() => buttonAction()} |
||||
> |
||||
<Text |
||||
style={[ |
||||
tw("text-white"), |
||||
{ |
||||
fontFamily: "regular", |
||||
fontSize: fontSize.tiny, |
||||
color: |
||||
theme === "light" |
||||
? Colors.theme1.white |
||||
: Colors.theme1.greenCF, |
||||
}, |
||||
]} |
||||
> |
||||
{buttonText} |
||||
</Text> |
||||
</Pressable> |
||||
) : null} |
||||
</View> |
||||
); |
||||
}; |
||||
|
||||
const mapStateToProps = (state) => ({ |
||||
theme: state.publicApi.theme, |
||||
}); |
||||
|
||||
export default connect(mapStateToProps)(Empty); |
@ -0,0 +1,30 @@ |
||||
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, |
||||
color: 'white', |
||||
}, |
||||
}); |
||||
return ( |
||||
<Pressable |
||||
color={color} |
||||
style={styles.button} |
||||
onPress={() => onPress} |
||||
> |
||||
<Text style={styles.text}>{text}</Text> |
||||
</Pressable> |
||||
); |
||||
} |
@ -0,0 +1,58 @@ |
||||
import { View, Text, Dimensions, ImageBackground } from "react-native"; |
||||
import { connect } from "react-redux"; |
||||
|
||||
//style
|
||||
import tw from "tailwind-rn"; |
||||
import fontSize from "../constants/fontSize"; |
||||
import Colors from "../constants/Colors"; |
||||
|
||||
const height = Dimensions.get("window").height; |
||||
|
||||
function Header({ title, description, background }) { |
||||
return ( |
||||
<View |
||||
style={[ |
||||
tw(`w-full flex items-center pb-7`), |
||||
{ |
||||
height: height / 4.5, |
||||
backgroundColor: Colors.theme1.greenCF + "0F", |
||||
}, |
||||
]} |
||||
> |
||||
<ImageBackground |
||||
source={background} |
||||
resizeMode="contain" |
||||
style={[tw("w-full"), { height: "80%" }]} |
||||
></ImageBackground> |
||||
<Text |
||||
style={[ |
||||
{ |
||||
fontSize: fontSize.xl, |
||||
color: Colors.theme1.greenCF, |
||||
fontFamily: "bold", |
||||
}, |
||||
]} |
||||
> |
||||
{title} |
||||
</Text> |
||||
<Text |
||||
style={[ |
||||
{ |
||||
color: Colors.theme1.greenCF, |
||||
fontSize: fontSize.sm, |
||||
fontFamily: "regular", |
||||
marginTop: 5 |
||||
}, |
||||
]} |
||||
> |
||||
{description} |
||||
</Text> |
||||
</View> |
||||
); |
||||
} |
||||
|
||||
const mapStateToProps = (state) => ({ |
||||
mobile: state.publicApi.mobile, |
||||
}); |
||||
|
||||
export default connect(mapStateToProps)(Header); |
@ -0,0 +1,18 @@ |
||||
import { View, Dimensions } from "react-native"; |
||||
import React from "react"; |
||||
import tw from "tailwind-rn"; |
||||
|
||||
const { width, height } = Dimensions.get("window"); |
||||
|
||||
const ImageSlider = ({}) => { |
||||
return ( |
||||
<View |
||||
style={[ |
||||
tw("flex flex-row justify-center items-center absolute left-0 top-0"), |
||||
{ width : width, height : height, backgroundColor: "black", zIndex : 1 }, |
||||
]} |
||||
></View> |
||||
); |
||||
}; |
||||
|
||||
export default ImageSlider; |
@ -0,0 +1,35 @@ |
||||
import React from "react"; |
||||
import { StyleSheet } from "react-native"; |
||||
// import MapboxGL from '@rnmapbox/maps';
|
||||
|
||||
// MapboxGL.setAccessToken('pk.eyJ1IjoicmV6YS1hc2hyYWZpNzciLCJhIjoiY2tsdXRxaGxjMjl3azJ2cW1wNDl4MWdpNCJ9.0EIgtsWEuemb7IpGtGhraw');
|
||||
|
||||
|
||||
export default function MapSelector() { |
||||
onRegionDidChange = (e) => {}; |
||||
return ( |
||||
// <View style={styles.page}>
|
||||
// <View style={styles.container}>
|
||||
// <MapboxGL.MapView style={styles.map} />
|
||||
// </View>
|
||||
// </View>
|
||||
<></> |
||||
); |
||||
} |
||||
|
||||
const styles = StyleSheet.create({ |
||||
page: { |
||||
flex: 1, |
||||
justifyContent: 'center', |
||||
alignItems: 'center', |
||||
backgroundColor: '#F5FCFF' |
||||
}, |
||||
container: { |
||||
height: 300, |
||||
width: 300, |
||||
backgroundColor: 'tomato' |
||||
}, |
||||
map: { |
||||
flex: 1 |
||||
} |
||||
}); |
@ -0,0 +1,28 @@ |
||||
import * as React from 'react'; |
||||
import { View, Button } from 'react-native'; |
||||
import { Audio } from 'expo-av'; |
||||
|
||||
export default function VoicePlayer({fileIds}) { |
||||
const [sound, setSound] = React.useState(); |
||||
|
||||
async function playSound() { |
||||
const { sound } = await Audio.Sound.createAsync( |
||||
{uri : `https://dnvn.ir/api/v1/file/${fileIds}`} |
||||
); |
||||
setSound(sound); |
||||
|
||||
await sound.playAsync(); } |
||||
|
||||
React.useEffect(() => { |
||||
return sound |
||||
? () => { |
||||
sound.unloadAsync(); } |
||||
: undefined; |
||||
}, [sound]); |
||||
|
||||
return ( |
||||
<View style={styles.container}> |
||||
<Button title="Play Sound" onPress={playSound} /> |
||||
</View> |
||||
); |
||||
} |
@ -0,0 +1,726 @@ |
||||
import React, { useCallback } from "react"; |
||||
import { |
||||
View, |
||||
Pressable, |
||||
Text, |
||||
Appearance, |
||||
TouchableOpacity, |
||||
ActivityIndicator, |
||||
} from "react-native"; |
||||
|
||||
import Svg, { |
||||
G, |
||||
Defs, |
||||
Pattern, |
||||
Image as Imagee, |
||||
Path, |
||||
Text as Textt, |
||||
TSpan, |
||||
LinearGradient, |
||||
Stop, |
||||
ClipPath, |
||||
Circle, |
||||
} from "react-native-svg"; |
||||
|
||||
import { useNavigation } from "@react-navigation/native"; |
||||
import { Ionicons, Entypo } from "@expo/vector-icons"; |
||||
|
||||
import { connect } from "react-redux"; |
||||
import { userFavorite } from "../redux/actions"; |
||||
|
||||
//style
|
||||
import Colors from "../constants/Colors"; |
||||
import tw from "tailwind-rn"; |
||||
import fontSize from "../constants/fontSize"; |
||||
|
||||
const Navbar = ({ |
||||
notification, |
||||
setBoxPosition, |
||||
headerOptions, |
||||
addToBookmark, |
||||
deleteBookmark, |
||||
userFavoriteList, |
||||
theme, |
||||
bookmarkLoading, |
||||
}) => { |
||||
const navigation = useNavigation(); |
||||
|
||||
const isActiveBookmark = React.useMemo(() => { |
||||
return userFavoriteList.filter((object) => |
||||
headerOptions.bookmarkItem?.productId |
||||
? object.productId === headerOptions.bookmarkItem?.productId |
||||
: object.contentId === headerOptions.bookmarkItem?.contentId |
||||
).length; |
||||
}, [headerOptions, userFavoriteList]); |
||||
|
||||
const Button = useCallback( |
||||
({ icon, route, state }) => { |
||||
return ( |
||||
<TouchableOpacity |
||||
style={[ |
||||
tw("rounded-md p-1"), |
||||
{ |
||||
backgrounds: Colors.theme1.greenCF + "05", |
||||
borderColor: |
||||
theme === "light" ? Colors.theme1.green79 : Colors.theme1.white, |
||||
borderWidth: 1, |
||||
marginLeft: route === "AR" ? 10 : 0, |
||||
}, |
||||
]} |
||||
onPress={() => navigation.navigate(route, { page: state })} |
||||
> |
||||
{icon} |
||||
</TouchableOpacity> |
||||
); |
||||
}, |
||||
[theme] |
||||
); |
||||
return ( |
||||
<View |
||||
style={[ |
||||
tw("w-full flex flex-row-reverse justify-between items-center px-0"), |
||||
{ |
||||
backgroundColor: headerOptions?.backgroundColor |
||||
? headerOptions?.backgroundColor |
||||
: theme === "light" |
||||
? Colors.theme1.white |
||||
: Colors.theme1.dark, |
||||
height: 64, |
||||
}, |
||||
]} |
||||
> |
||||
{!headerOptions?.title ? ( |
||||
headerOptions?.back ? ( |
||||
<Ionicons |
||||
name="arrow-forward" |
||||
style={tw("mr-2")} |
||||
size={24} |
||||
color={ |
||||
theme === "light" ? Colors.theme1.green79 : Colors.theme1.white |
||||
} |
||||
onPress={() => navigation.goBack()} |
||||
/> |
||||
) : null |
||||
) : null} |
||||
{headerOptions?.title ? ( |
||||
<Text |
||||
style={{ |
||||
fontFamily: "demi", |
||||
fontSize: fontSize.xl, |
||||
color: |
||||
theme === "light" ? Colors.theme1.green79 : Colors.theme1.white, |
||||
paddingRight: 16, |
||||
}} |
||||
> |
||||
{headerOptions?.title} |
||||
</Text> |
||||
) : null} |
||||
{headerOptions?.hamburgerMenu ? ( |
||||
<Pressable style={tw("relative mr-4")} onPress={() => setBoxPosition()}> |
||||
<Svg |
||||
xmlns="http://www.w3.org/2000/svg" |
||||
width={31.567} |
||||
height={29.996} |
||||
> |
||||
<G |
||||
fill="none" |
||||
stroke={ |
||||
theme === "light" ? Colors.theme1.green79 : Colors.theme1.white |
||||
} |
||||
strokeLinecap="round" |
||||
strokeLinejoin="round" |
||||
strokeWidth={2} |
||||
> |
||||
<Path d="M1 1h29.567" /> |
||||
<Path |
||||
data-name="Vector" |
||||
d="M1 9.999h29.567M1 18.998h29.567M1 27.996h29.567" |
||||
/> |
||||
</G> |
||||
</Svg> |
||||
{notification ? ( |
||||
<View |
||||
style={tw("h-2.5 w-2.5 absolute -left-1 -top-1 rounded-full")} |
||||
></View> |
||||
) : null} |
||||
</Pressable> |
||||
) : null} |
||||
|
||||
{headerOptions?.logo ? ( |
||||
<Pressable |
||||
onPress={() => navigation.navigate("Home")} |
||||
style={tw("absolute right-1/2 top-1/2")} |
||||
> |
||||
<Svg |
||||
xmlns="http://www.w3.org/2000/svg" |
||||
xmlnsXlink="http://www.w3.org/1999/xlink" |
||||
width={26.198} |
||||
height={40.393} |
||||
style={{ transform: [{ translateX: -13 }, { translateY: -21 }] }} |
||||
> |
||||
<Defs> |
||||
<LinearGradient |
||||
id="a" |
||||
y1={0.5} |
||||
x2={1} |
||||
y2={0.5} |
||||
gradientUnits="objectBoundingBox" |
||||
> |
||||
<Stop offset={0} stopColor="#5a595d" /> |
||||
<Stop offset={1} stopColor="#515254" /> |
||||
</LinearGradient> |
||||
<LinearGradient |
||||
id="c" |
||||
x1={0.226} |
||||
y1={0.051} |
||||
x2={0.802} |
||||
y2={0.929} |
||||
gradientUnits="objectBoundingBox" |
||||
> |
||||
<Stop offset={0} stopColor="#fff" /> |
||||
<Stop offset={0.461} stopColor="#636466" /> |
||||
<Stop offset={1} stopColor="#4a4a4c" /> |
||||
</LinearGradient> |
||||
<LinearGradient |
||||
id="e" |
||||
x1={0.118} |
||||
y1={0.331} |
||||
x2={1.017} |
||||
y2={0.638} |
||||
gradientUnits="objectBoundingBox" |
||||
> |
||||
<Stop offset={0} stopColor="#c3e14b" /> |
||||
<Stop offset={0.528} stopColor="#4cdb60" /> |
||||
<Stop offset={1} stopColor="#4fb84a" /> |
||||
</LinearGradient> |
||||
<LinearGradient |
||||
id="f" |
||||
y1={0.5} |
||||
x2={1} |
||||
y2={0.5} |
||||
gradientUnits="objectBoundingBox" |
||||
> |
||||
<Stop offset={0} stopColor="#8bc540" /> |
||||
<Stop offset={1} stopColor="#4fb84a" /> |
||||
</LinearGradient> |
||||
<LinearGradient |
||||
id="b" |
||||
x1={0.177} |
||||
y1={0.211} |
||||
x2={0.923} |
||||
y2={0.878} |
||||
gradientUnits="objectBoundingBox" |
||||
> |
||||
<Stop offset={0.156} stopColor="#c3e14b" /> |
||||
<Stop offset={0.628} stopColor="#4cdb60" /> |
||||
<Stop offset={1} stopColor="#4fb84a" /> |
||||
</LinearGradient> |
||||
<LinearGradient |
||||
id="g" |
||||
x1={0} |
||||
y1={0.5} |
||||
x2={1} |
||||
y2={0.5} |
||||
xlinkHref="#b" |
||||
/> |
||||
<ClipPath id="d"> |
||||
<Path |
||||
data-name="Path 11452" |
||||
d="M752.773 683.017c0-1.668.08-8.506-.023-8.462-.33 3.666-3.285 6.412-8.535 6.412a6.347 6.347 0 0 1-5.966-3.826c-3.262-2.317-3.731-4.787-3.731-4.787l.058 13.66v.011h15.133a2.759 2.759 0 0 0 3.064-3.008Z" |
||||
transform="translate(-734.518 -672.354)" |
||||
fill="url(#a)" |
||||
/> |
||||
</ClipPath> |
||||
</Defs> |
||||
<G data-name="Group 2024"> |
||||
<G data-name="Layer 10"> |
||||
<G data-name="Group 2013"> |
||||
<G data-name="Group 2009"> |
||||
<Path |
||||
data-name="Path 11446" |
||||
d="M2.534 4.411H.053s-.255 1.422.328 2.005 2.151.534 2.151.862Z" |
||||
fill="#7f8083" |
||||
/> |
||||
</G> |
||||
<Path |
||||
data-name="Path 11447" |
||||
d="M758.141 245.564h-1.422a3.668 3.668 0 0 0-3.937 3.718l-.009 26.913a2.759 2.759 0 0 1-3.062 3.008h-11.462v-8.884a10.446 10.446 0 0 1-1.033-4.34v-16.915c0-2.552-2.7-3.172-2.7-3.172v19.64l.108 13.671h-.049c.014.113.032.221.052.325v.006c.4 2.152 1.868 2.339 3.57 2.339h14.509c2.953 0 2.771-2.552 2.771-4.229V250.23c0-2.078.984-1.677 1.969-2.005s.695-2.661.695-2.661Z" |
||||
transform="translate(-731.983 -241.481)" |
||||
fill="url(#c)" |
||||
/> |
||||
<G data-name="Group 2010"> |
||||
<Path |
||||
data-name="Path 11448" |
||||
d="M2.593 37.722Z" |
||||
fill="#4b4b4d" |
||||
/> |
||||
</G> |
||||
<G data-name="Group 2012"> |
||||
<Path |
||||
data-name="Path 11449" |
||||
d="M752.773 683.017c0-1.668.08-8.506-.023-8.462-.33 3.666-3.285 6.412-8.535 6.412a6.347 6.347 0 0 1-5.966-3.826c-3.262-2.317-3.731-4.787-3.731-4.787l.058 13.66v.011h15.133a2.759 2.759 0 0 0 3.064-3.008Z" |
||||
transform="translate(-731.983 -648.303)" |
||||
fill="url(#a)" |
||||
/> |
||||
<G |
||||
data-name="Group 2011" |
||||
clipPath="url(#d)" |
||||
fill="#fff" |
||||
transform="translate(2.535 24.051)" |
||||
> |
||||
<Path data-name="Path 11450" d="M0 0Z" /> |
||||
<Path data-name="Path 11451" d="M18.392 13.671Z" /> |
||||
</G> |
||||
</G> |
||||
</G> |
||||
</G> |
||||
<G data-name="Layer 7"> |
||||
<Path |
||||
data-name="Path 11453" |
||||
d="M802.306 400.555v12.358c0 1.6 1.9 6.854 7.036 6.854a7.19 7.19 0 0 0 7.437-6.562v-12.65a4.138 4.138 0 0 0-3.1-1.495c-1.969 0-4.393 1.566-6.289 2.149a5.78 5.78 0 0 1-4.024.094 3.059 3.059 0 0 1-1.06-.748Z" |
||||
transform="translate(-796.6 -387.795)" |
||||
fill="url(#e)" |
||||
/> |
||||
</G> |
||||
<G data-name="Layer 8"> |
||||
<Path |
||||
data-name="Path 11454" |
||||
d="M816.779 400.576a5.934 5.934 0 0 0-4.63.115c-3.017 1.611-6.088 5.171-7.546 7.376s-2.3 3.664-2.3 3.664v-11.155a3.594 3.594 0 0 0 2.012 1 8.558 8.558 0 0 0 4.794-1.044 11.537 11.537 0 0 1 4.476-1.449 3.977 3.977 0 0 1 2.433.784c.67.417.761.709.761.709Z" |
||||
transform="translate(-796.6 -387.816)" |
||||
fill="url(#f)" |
||||
/> |
||||
</G> |
||||
<G data-name="Layer 9"> |
||||
<G data-name="Group 2014"> |
||||
<Path |
||||
data-name="Path 11455" |
||||
d="M12.751 12.6a6.145 6.145 0 0 0-3.727-1.335 4.267 4.267 0 0 0-3.317 1.495 3.672 3.672 0 0 0 2.232 1.029 8.888 8.888 0 0 0 4.812-1.189Z" |
||||
fill="#09793e" |
||||
/> |
||||
</G> |
||||
</G> |
||||
<G data-name="Layer 5" transform="translate(12.159 5.432)"> |
||||
<Circle |
||||
data-name="Ellipse 177" |
||||
cx={2.06} |
||||
cy={2.06} |
||||
r={2.06} |
||||
fill="url(#b)" |
||||
/> |
||||
<G data-name="Group 2018"> |
||||
<G data-name="Group 2015" transform="translate(2.394 1.041)"> |
||||
<Circle |
||||
data-name="Ellipse 178" |
||||
cx={0.361} |
||||
cy={0.361} |
||||
r={0.361} |
||||
fill="#6c3b41" |
||||
/> |
||||
</G> |
||||
<G data-name="Group 2016" transform="translate(.973 1.041)"> |
||||
<Circle |
||||
data-name="Ellipse 179" |
||||
cx={0.361} |
||||
cy={0.361} |
||||
r={0.361} |
||||
fill="#6c3b41" |
||||
/> |
||||
</G> |
||||
<G data-name="Group 2017"> |
||||
<Path |
||||
data-name="Path 11456" |
||||
d="M2.068 3.185a1.594 1.594 0 0 1-1.286-.923l.194-.091c0 .008.386.8 1.092.8.706 0 1.073-.791 1.077-.8l.195.088a1.562 1.562 0 0 1-1.272.926Z" |
||||
fill="#6c3b41" |
||||
/> |
||||
</G> |
||||
</G> |
||||
</G> |
||||
<G data-name="Layer 3" transform="translate(8.294 3.336)"> |
||||
<Circle |
||||
data-name="Ellipse 180" |
||||
cx={1.075} |
||||
cy={1.075} |
||||
r={1.075} |
||||
fill="url(#g)" |
||||
/> |
||||
</G> |
||||
<G data-name="Layer 4"> |
||||
<G data-name="Group 2019" transform="translate(12.778)"> |
||||
<Circle |
||||
data-name="Ellipse 181" |
||||
cx={0.547} |
||||
cy={0.547} |
||||
r={0.547} |
||||
fill="url(#g)" |
||||
/> |
||||
</G> |
||||
</G> |
||||
<G data-name="Layer 6"> |
||||
<G data-name="Group 2020" transform="translate(12.158 23.751)"> |
||||
<Circle |
||||
data-name="Ellipse 182" |
||||
cx={2.06} |
||||
cy={2.06} |
||||
r={2.06} |
||||
fill="#fff" |
||||
/> |
||||
</G> |
||||
<G data-name="Group 2021" transform="translate(9.743 21.162)"> |
||||
<Circle |
||||
data-name="Ellipse 183" |
||||
cx={1.075} |
||||
cy={1.075} |
||||
r={1.075} |
||||
fill="#fff" |
||||
/> |
||||
</G> |
||||
<G data-name="Group 2022" transform="translate(12.532 18.571)"> |
||||
<Circle |
||||
data-name="Ellipse 184" |
||||
cx={0.547} |
||||
cy={0.547} |
||||
r={0.547} |
||||
fill="#fff" |
||||
/> |
||||
</G> |
||||
<G data-name="Group 2023" transform="translate(11.247 34.222)"> |
||||
<Circle |
||||
data-name="Ellipse 185" |
||||
cx={1.777} |
||||
cy={1.777} |
||||
r={1.777} |
||||
fill="#fff" |
||||
/> |
||||
</G> |
||||
</G> |
||||
</G> |
||||
</Svg> |
||||
</Pressable> |
||||
) : null} |
||||
|
||||
<View style={tw("flex flex-row items-center ml-4")}> |
||||
{headerOptions?.back ? ( |
||||
headerOptions?.title ? ( |
||||
<Ionicons |
||||
name="arrow-back" |
||||
style={tw("mr-2")} |
||||
size={24} |
||||
color={ |
||||
theme === "light" ? Colors.theme1.green79 : Colors.theme1.white |
||||
} |
||||
onPress={() => navigation.goBack()} |
||||
/> |
||||
) : null |
||||
) : null} |
||||
{headerOptions?.qr ? ( |
||||
<> |
||||
<Button |
||||
icon={ |
||||
<Svg xmlns="http://www.w3.org/2000/svg" width={30} height={30}> |
||||
<G |
||||
fill={ |
||||
theme === "light" |
||||
? Colors.theme1.green79 |
||||
: Colors.theme1.white |
||||
} |
||||
> |
||||
<Path |
||||
data-name="Path 11446" |
||||
d="M2.131.275A3.177 3.177 0 0 0 .114 2.841 24.849 24.849 0 0 0 .045 5.98l.069 2.177h8.02V.137L5.499.091a18.649 18.649 0 0 0-3.368.184Zm4.973 3.873v2.979H1.146V4.973c0-2.452.229-3.277.962-3.575a13.17 13.17 0 0 1 2.773-.206l2.223-.023Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11447" |
||||
d="M2.521 4.263v1.742l1.673-.069 1.65-.069.069-1.673.068-1.65h-3.46Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11448" |
||||
d="M9.77.161a1.028 1.028 0 0 0-.16.6c0 .3.16.412.6.412.481 0 .573-.092.5-.5-.069-.535-.619-.81-.94-.512Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11449" |
||||
d="M16.888.71c0 .573-.092.687-.573.687-.412 0-.573.115-.573.458s.16.458.573.458c.481 0 .573.115.573.687 0 .665-.023.687-1.146.687-.985 0-1.146.069-1.146.458s.16.458 1.146.458c1.123 0 1.146.023 1.146.687s.023.687 1.146.687h1.146v1.146c0 1.077.046 1.146.573 1.146.55 0 .573-.046.573-1.719s-.023-1.719-.573-1.719c-.458 0-.573-.115-.573-.573s-.115-.573-.573-.573c-.55 0-.573-.069-.573-1.26v-1.26h1.169c1.077 0 1.146-.046 1.077-.527-.069-.458-.206-.5-1.719-.573l-1.673-.069Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11450" |
||||
d="M21.842.298a39.658 39.658 0 0 0-.069 4.079l.069 3.781h8.02V5.294c0-4.721-.367-5.087-4.973-5.225-2.36-.069-2.956-.023-3.047.229Zm6.325 1.306c.5.412.55.642.619 2.979l.092 2.544h-6V1.166h2.383c1.989 0 2.47.072 2.905.438Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11451" |
||||
d="M24.248 4.263v1.719h3.208V2.544h-3.208Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11452" |
||||
d="M11.966 1.856c0 .39.16.458 1.146.458s1.146-.069 1.146-.458-.16-.458-1.146-.458-1.146.069-1.146.458Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11453" |
||||
d="M10.735 3.117c0 .458-.115.573-.573.573h-.573v5.729H8.444c-1.077 0-1.146.046-1.146.573 0 .458.115.573.573.573s.573.115.573.573.115.573.573.573.573-.115.573-.573c0-.527.069-.573 1.146-.573h1.146V9.419c0-1.077-.046-1.146-.573-1.146s-.573-.069-.573-1.146V5.981h2.292V4.835c0-1.077-.046-1.146-.573-1.146-.458 0-.573-.115-.573-.573s-.116-.572-.574-.572-.573.115-.573.573Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11454" |
||||
d="M14.517 7.284c0 1.077-.046 1.146-.573 1.146-.55 0-.573.046-.573 1.719 0 1.558.046 1.719.458 1.719.344 0 .458-.16.458-.573 0-.458.115-.573.573-.573h.573V8.43c0-2.131-.023-2.292-.458-2.292-.389 0-.458.16-.458 1.146Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11455" |
||||
d="M12.046 7.628c-.183.458.092.8.619.8.321 0 .435-.16.435-.573s-.114-.571-.463-.571a.674.674 0 0 0-.591.344Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11456" |
||||
d="M16.876 7.884c0 .481.092.573.527.5a.638.638 0 0 0 .573-.6c.069-.412-.023-.5-.5-.5s-.6.115-.6.6Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11457" |
||||
d="M.16 9.795A2.612 2.612 0 0 0 0 10.941v.985h1.146c1.077 0 1.146-.046 1.146-.573 0-.458-.115-.573-.573-.573s-.573-.115-.573-.573c0-.412-.115-.573-.412-.573a.9.9 0 0 0-.574.161Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11458" |
||||
d="M4.812 10.198c0 .5.092.6.527.527a.512.512 0 0 0 .5-.527.512.512 0 0 0-.5-.527c-.435-.068-.527.023-.527.527Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11459" |
||||
d="M17.145 11.164c0 1.1-.046 1.169-.573 1.169-.458 0-.573.115-.573.573v.573h4.583v-.573c0-.458.115-.573.573-.573s.573-.115.573-.573c0-.55.069-.573 1.26-.573s1.26.046 1.26.55c0 .435-.137.573-.619.642-.5.046-.665.206-.71.687-.069.5-.206.642-.642.642s-.55.115-.55.573-.115.573-.573.573-.573.115-.573.573-.115.573-.573.573-.573-.115-.573-.573-.115-.573-.573-.573-.573.115-.573.573-.115.573-.573.573c-.412 0-.573.115-.573.458s.16.458.573.458c.481 0 .573.115.573.687s-.092.687-.573.687c-.458 0-.573.115-.573.573 0 .527.069.573 1.146.573h1.146v5.729h1.146c1.123 0 1.146.023 1.146.687s-.023.687-1.146.687c-.985 0-1.146.069-1.146.458s.16.458 1.146.458c1.077 0 1.146.046 1.146.573v.573h4.812v1.4l1.673-.069c1.512-.069 1.65-.115 1.719-.6.069-.435-.023-.5-.619-.5-.71 0-.71 0-.71-1.26s0-1.26.687-1.26h.71l-.069-1.673-.069-1.65-2.336-.071-2.36-.069V20.58h1.146c1.077 0 1.146-.046 1.146-.573 0-.458.115-.573.573-.573s.573-.115.573-.573-.115-.573-.573-.573-.573-.115-.573-.573c0-.527-.069-.573-1.146-.573s-1.146-.046-1.146-.573c0-.412-.115-.573-.458-.573s-.458.16-.458.573c0 .481-.115.573-.687.573s-.687.092-.687.573c0 .458-.115.573-.573.573s-.573.115-.573.573-.115.573-.573.573-.573-.115-.573-.573-.115-.573-.573-.573c-.481 0-.573-.115-.573-.687 0-.665.023-.687 1.146-.687 1.077 0 1.146-.046 1.146-.573 0-.458.115-.573.573-.573s.573-.115.573-.573.115-.573.573-.573.573-.115.573-.573c0-.55.069-.573 1.26-.573 1.237 0 1.26 0 1.26.687 0 .573-.092.687-.573.687-.412 0-.573.115-.573.458 0 .39.16.458 1.146.458 1.077 0 1.146.046 1.146.573 0 .756.848.8.962.046.046-.367.252-.527.71-.573.435-.046.619-.206.619-.527s-.16-.435-.687-.435c-.573 0-.687-.092-.687-.573 0-.458-.115-.573-.573-.573-.481 0-.573-.115-.573-.687s-.092-.687-.573-.687c-.527 0-.573-.069-.573-1.146v-1.146h-5.73v.573a.6.6 0 0 1-1.192.046c-.069-.435-.229-.5-1.146-.573l-1.1-.069Zm9.4 7.7c0 .481-.115.573-.687.573s-.687-.092-.687-.573.115-.573.687-.573.682.091.682.572Zm-2.346 3.482-.069 1.787-1.764.069-1.787.069v-3.689h3.689Zm2.337 3.391c0 .458.115.573.573.573.481 0 .573.115.573.687 0 .619-.069.687-.687.687-.573 0-.687-.092-.687-.573 0-.412-.115-.573-.458-.573s-.458.16-.458.573c0 .55-.069.573-1.26.573-1.237 0-1.26 0-1.26-.687 0-.573.092-.687.573-.687.458 0 .573-.115.573-.573 0-.55.069-.573 1.26-.573s1.262.024 1.262.574Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11460" |
||||
d="M21.725 21.73a.9.9 0 0 0-.16.573c0 .3.16.412.573.412.458 0 .573-.115.573-.573 0-.412-.115-.573-.412-.573a.9.9 0 0 0-.574.161Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11461" |
||||
d="M28.831 10.176c0 .481.115.6.6.6s.573-.092.5-.527a.636.636 0 0 0-.573-.573c-.435-.073-.527.019-.527.5Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11462" |
||||
d="M3.667 11.391c0 .458-.115.573-.573.573-.527 0-.573.069-.573 1.146 0 .985.069 1.146.458 1.146.344 0 .458-.16.458-.573v-.573h2.429c2.383 0 2.406 0 2.337-.527-.069-.458-.206-.5-1.833-.573-1.719-.069-1.787-.092-1.787-.619 0-.412-.115-.573-.458-.573s-.458.16-.458.573Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11463" |
||||
d="M27.686 11.37c0 .412.115.573.458.573s.458-.16.458-.573-.116-.573-.458-.573-.458.16-.458.573Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11464" |
||||
d="M9.77 12.106a1.027 1.027 0 0 0-.16.6c0 .3.16.412.6.412.481 0 .573-.092.5-.5-.069-.535-.619-.81-.94-.512Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11465" |
||||
d="M0 14.996v1.6h1.719c1.558 0 1.719-.046 1.719-.458 0-.344-.16-.458-.573-.458-.458 0-.573-.115-.573-.573s-.115-.573-.573-.573-.573-.115-.573-.573-.115-.565-.573-.565c-.55 0-.573.046-.573 1.6Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11466" |
||||
d="M8.438 13.829c0 .344.16.458.573.458s.573-.115.573-.458-.161-.458-.573-.458-.573.115-.573.458Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11467" |
||||
d="M13.371 14.414c0 .871.069 1.031.458 1.031.344 0 .458-.16.458-.573 0-.458.115-.573.573-.573.412 0 .573-.115.573-.458 0-.39-.16-.458-1.031-.458h-1.031Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11468" |
||||
d="M6.1 15c0 .39.16.458 1.146.458s1.146-.069 1.146-.458-.161-.458-1.146-.458S6.1 14.611 6.1 15Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11469" |
||||
d="M9.61 15c0 .344.16.458.573.458s.573-.115.573-.458-.161-.458-.573-.458-.573.115-.573.458Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11470" |
||||
d="M8.438 16.171c0 .344.16.458.573.458s.573-.115.573-.458-.161-.458-.573-.458-.573.115-.573.458Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11471" |
||||
d="M11.954 16.171c0 .344.16.458.573.458s.573-.115.573-.458-.161-.458-.573-.458-.573.115-.573.458Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11472" |
||||
d="M14.517 16.318c0 .458-.115.573-.573.573-.527 0-.573.069-.573 1.146 0 .985.069 1.146.458 1.146.344 0 .458-.16.458-.573 0-.458.115-.573.573-.573.527 0 .573-.069.573-1.146 0-.985-.069-1.146-.458-1.146-.344 0-.458.16-.458.573Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11473" |
||||
d="M3.666 17.459c0 .412.115.573.458.573s.458-.16.458-.573-.116-.573-.458-.573-.458.16-.458.573Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11474" |
||||
d="M7.104 17.53c0 .458-.115.573-.573.573s-.573.115-.573.573v.55l-2.91.069c-2.75.069-2.933.092-2.933.527s.183.458 4.652.527l4.629.046v2.292h3.437v-1.17c0-1.077-.046-1.146-.5-1.077a.638.638 0 0 0-.6.573.6.6 0 0 1-1.192-.046c0-.458-.115-.573-.573-.573s-.573-.115-.573-.573c0-.527-.069-.573-1.146-.573-1.054 0-1.146-.046-1.146-.55 0-.412.137-.573.527-.642a.638.638 0 0 0 .573-.6c.069-.412-.023-.5-.5-.5s-.599.116-.599.574Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11475" |
||||
d="m9.665 17.979.069 1.1 1.1.069 1.077.069v-2.315H9.596Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11476" |
||||
d="M14.53 19.801c0 .412.115.573.458.573s.458-.16.458-.573-.116-.573-.458-.573-.458.16-.458.573Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11477" |
||||
d="M15.702 21.564c0 .985.069 1.146.458 1.146s.458-.16.458-1.146-.068-1.146-.458-1.146-.458.16-.458 1.146Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11478" |
||||
d="M.092 22.072a20.5 20.5 0 0 0-.046 3.025c.137 4.377.573 4.766 5.225 4.766h2.864v-8.02l-3.964-.069c-3.369-.049-3.965 0-4.079.298Zm7.012 3.781v2.979H4.72c-3.346 0-3.437-.069-3.529-3.414l-.092-2.544h6Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11479" |
||||
d="M2.521 25.848v1.6h3.437v-3.2H2.521Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11480" |
||||
d="M14.53 23.314c0 .412.115.573.458.573s.458-.16.458-.573-.116-.573-.458-.573-.458.16-.458.573Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11481" |
||||
d="M9.61 24.706c0 .344.16.458.573.458s.573-.115.573-.458-.161-.458-.573-.458-.573.115-.573.458Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11482" |
||||
d="M13.358 24.706a.411.411 0 0 0 .458.458.411.411 0 0 0 .458-.458.411.411 0 0 0-.458-.458.411.411 0 0 0-.458.458Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11483" |
||||
d="M15.694 24.706c0 .344.16.458.573.458.481 0 .573.115.573.687 0 .619-.069.687-.687.687-.573 0-.687-.092-.687-.573 0-.412-.115-.573-.458-.573s-.458.16-.458.573c0 .458-.115.573-.573.573-.527 0-.573.092-.573 1.031 0 .871.069 1.031.458 1.031.344 0 .458-.16.458-.573 0-.481.115-.573.687-.573.619 0 .687.069.687.687 0 .573-.092.687-.573.687-.458 0-.573.115-.573.573 0 .527.092.573 1.031.573h1.031v-1.26c0-1.237 0-1.26.687-1.26h.687v-3.206h-1.145c-.985 0-1.145.069-1.145.458Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11484" |
||||
d="M10.792 26.994c0 1.558.023 1.6.573 1.6.527 0 .573-.069.573-1.146s.046-1.146.573-1.146c.412 0 .573-.115.573-.458 0-.39-.16-.458-1.146-.458h-1.146Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11485" |
||||
d="M18.048 28.855c0 1.077.046 1.146.527 1.077.435-.069.5-.229.573-1.169.069-1.031.046-1.077-.5-1.077s-.6.069-.6 1.169Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11486" |
||||
d="M9.657 29.331a.641.641 0 0 0 .6.6c.412.069.5-.023.5-.5s-.115-.6-.6-.6-.569.092-.5.5Z" |
||||
/> |
||||
<Path |
||||
data-name="Path 11487" |
||||
d="M12.001 29.331a.641.641 0 0 0 .6.6c.412.069.5-.023.5-.5s-.115-.6-.6-.6-.569.092-.5.5Z" |
||||
/> |
||||
</G> |
||||
</Svg> |
||||
} |
||||
route={"QR"} |
||||
state={"book"} |
||||
/> |
||||
<Button |
||||
icon={ |
||||
<Svg |
||||
xmlns="http://www.w3.org/2000/svg" |
||||
width={29.9} |
||||
height={30.908} |
||||
> |
||||
<G |
||||
data-name="Group 419" |
||||
fill={ |
||||
theme === "light" |
||||
? Colors.theme1.green79 |
||||
: Colors.theme1.white |
||||
} |
||||
> |
||||
<Path |
||||
data-name="Path 1864" |
||||
d="M1.694 1.694h5.081V0H0v6.775h1.694Zm0 0" |
||||
/> |
||||
<Path |
||||
data-name="Path 1863" |
||||
d="M22.132 0v1.694h5.081v5.081h1.694V0Zm0 0" |
||||
/> |
||||
<Path |
||||
data-name="Path 1862" |
||||
d="M27.213 27.214h-5.081v1.694h6.775v-6.775h-1.694Zm0 0" |
||||
/> |
||||
<Path |
||||
data-name="Path 1861" |
||||
d="M1.694 22.133H0v6.775h6.775v-1.694H1.694Zm0 0" |
||||
/> |
||||
<Textt |
||||
transform="translate(15 19)" |
||||
fontSize={14} |
||||
// fontFamily="regular"
|
||||
> |
||||
<TSpan x={-8.841} y={0}> |
||||
{"AR"} |
||||
</TSpan> |
||||
</Textt> |
||||
</G> |
||||
</Svg> |
||||
} |
||||
route={"AR"} |
||||
state={"AR"} |
||||
/> |
||||
</> |
||||
) : null} |
||||
{headerOptions?.bookmark ? ( |
||||
bookmarkLoading ? ( |
||||
<ActivityIndicator |
||||
size={20} |
||||
color={ |
||||
theme === "light" ? Colors.theme1.green79 : Colors.theme1.white |
||||
} |
||||
/> |
||||
) : isActiveBookmark ? ( |
||||
<Ionicons |
||||
name="bookmark" |
||||
style={tw("mr-2")} |
||||
size={24} |
||||
color={ |
||||
theme === "light" ? Colors.theme1.green79 : Colors.theme1.white |
||||
} |
||||
onPress={() => |
||||
headerOptions?.bookmarkItem?.contentId |
||||
? deleteBookmark({ |
||||
id: userFavoriteList.filter( |
||||
(object) => |
||||
object.contentId === |
||||
headerOptions.bookmarkItem?.contentId |
||||
)[0].id, |
||||
}) |
||||
: deleteBookmark({ |
||||
id: userFavoriteList.filter( |
||||
(object) => |
||||
object.productId === |
||||
headerOptions.bookmarkItem?.productId |
||||
)[0].id, |
||||
}) |
||||
} |
||||
/> |
||||
) : ( |
||||
<Ionicons |
||||
name="bookmark-outline" |
||||
style={tw("mr-2")} |
||||
size={24} |
||||
color={ |
||||
theme === "light" ? Colors.theme1.green79 : Colors.theme1.white |
||||
} |
||||
onPress={() => |
||||
headerOptions?.bookmarkItem?.contentId |
||||
? addToBookmark({ |
||||
contentId: headerOptions?.bookmarkItem?.contentId, |
||||
}) |
||||
: addToBookmark({ |
||||
productId: headerOptions?.bookmarkItem?.productId, |
||||
}) |
||||
} |
||||
/> |
||||
) |
||||
) : null} |
||||
{headerOptions?.menu ? ( |
||||
<Entypo |
||||
name="dots-three-vertical" |
||||
size={24} |
||||
color={theme === "light" ? "#52796F" : Colors.theme1.white} |
||||
/> |
||||
) : null} |
||||
</View> |
||||
</View> |
||||
); |
||||
}; |
||||
|
||||
const mapStateToProps = (state) => ({ |
||||
userFavoriteList: state.userFavorite.list, |
||||
theme: state.publicApi.theme, |
||||
bookmarkLoading: state.userFavorite.loading, |
||||
}); |
||||
|
||||
const mapDispatchToProps = { |
||||
addToBookmark: userFavorite.add, |
||||
deleteBookmark: userFavorite.del, |
||||
}; |
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(Navbar); |
@ -0,0 +1,20 @@ |
||||
import React, {useState} from 'react'; |
||||
import {View, Text, Dimensions} from 'react-native'; |
||||
import tw from 'tailwind-rn'; |
||||
|
||||
const width = Dimensions.get('window').width; |
||||
|
||||
function Or(props) { |
||||
return ( |
||||
<View |
||||
style={[tw('w-full flex flex-row justify-between items-center my-3')]}> |
||||
<View |
||||
style={{width: '43%', height: 1, backgroundColor: '#EFEFEF'}}></View> |
||||
<Text style={{fontSize: width / 27, color: '#C2C2C2'}}>یا</Text> |
||||
<View |
||||
style={{width: '43%', height: 1, backgroundColor: '#EFEFEF'}}></View> |
||||
</View> |
||||
); |
||||
} |
||||
|
||||
export default Or; |
@ -0,0 +1,62 @@ |
||||
import React from "react"; |
||||
import { TouchableOpacity, Text, ActivityIndicator } from "react-native"; |
||||
import { connect } from "react-redux"; |
||||
|
||||
//style
|
||||
import tw from "tailwind-rn"; |
||||
import fontSize from "../constants/fontSize"; |
||||
|
||||
function Pressable1({ |
||||
title, |
||||
backgroundColor, |
||||
color, |
||||
border, |
||||
width, |
||||
onPress, |
||||
loading, |
||||
mobile, |
||||
theme, |
||||
textFontSize, |
||||
}) { |
||||
return ( |
||||
<TouchableOpacity |
||||
onPress={() => onPress()} |
||||
style={[ |
||||
tw("rounded-sm py-3 flex flex-row justify-center mb-3"), |
||||
{ |
||||
backgroundColor: backgroundColor, |
||||
borderWidth: border.width, |
||||
borderColor: border.color, |
||||
width: width, |
||||
}, |
||||
]} |
||||
> |
||||
{loading ? ( |
||||
<ActivityIndicator size="small" color={color} /> |
||||
) : ( |
||||
<Text |
||||
style={{ |
||||
fontSize: mobile |
||||
? textFontSize |
||||
? textFontSize |
||||
: fontSize.tiny |
||||
: textFontSize |
||||
? textFontSize |
||||
: fontSize.xl, |
||||
color: color, |
||||
fontFamily: "bold", |
||||
}} |
||||
> |
||||
{title} |
||||
</Text> |
||||
)} |
||||
</TouchableOpacity> |
||||
); |
||||
} |
||||
|
||||
const mapStateToProps = (state) => ({ |
||||
mobile: state.publicApi.mobile, |
||||
theme: state.publicApi.theme, |
||||
}); |
||||
|
||||
export default connect(mapStateToProps)(Pressable1); |
@ -0,0 +1,38 @@ |
||||
import React from "react"; |
||||
import { View } from "react-native"; |
||||
import {connect} from "react-redux"; |
||||
|
||||
//assets
|
||||
import tw from "tailwind-rn"; |
||||
import Colors from "../constants/Colors"; |
||||
|
||||
function Progress({ percent, alignItems, theme }) { |
||||
return ( |
||||
<></> |
||||
// <View
|
||||
// style={[
|
||||
// tw(
|
||||
// `w-full h-1.5 rounded-full overflow-hidden my-3 flex ${alignItems}`
|
||||
// ),
|
||||
// { backgroundColor: Colors.theme1.green79 + "22" },
|
||||
// ]}
|
||||
// >
|
||||
// <View
|
||||
// style={[
|
||||
// tw("h-full rounded-full"),
|
||||
// {
|
||||
// backgroundColor: Colors.theme1.greenCF,
|
||||
// width: percent + "%",
|
||||
// // backgroundColor: Color.theme1.light.blue4,
|
||||
// },
|
||||
// ]}
|
||||
// ></View>
|
||||
// </View>
|
||||
); |
||||
} |
||||
|
||||
const mapStateToProps = (state) => ({ |
||||
theme: state.publicApi.theme, |
||||
}) |
||||
|
||||
export default connect(mapStateToProps)(Progress); |
@ -0,0 +1,32 @@ |
||||
import React from "react"; |
||||
import { View, Text, Dimensions, Image } from "react-native"; |
||||
import tw from "tailwind-rn"; |
||||
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 ( |
||||
<View |
||||
style={[ |
||||
tw("w-full flex flex-row-reverse items-center p-4 rounded-md mb-5"), |
||||
{ backgroundColor: "#196EC0" }, |
||||
]} |
||||
> |
||||
<View style={tw("flex-1 flex ")}> |
||||
<Text |
||||
style={[ |
||||
tw("font-medium text-right"), |
||||
{ fontSize: width / 30, color: "white" }, |
||||
]} |
||||
> |
||||
{text} |
||||
</Text> |
||||
</View> |
||||
<View style={tw("p-0")}> |
||||
<Image source={leftIcon} style={{ width: 24, height: 24 }} /> |
||||
</View> |
||||
</View> |
||||
); |
||||
} |
@ -0,0 +1,39 @@ |
||||
import React, { useState, useEffect } from "react"; |
||||
import { Text, View, StyleSheet, Button } from "react-native"; |
||||
import { BarCodeScanner } from "expo-barcode-scanner"; |
||||
|
||||
export default function App() { |
||||
const [hasPermission, setHasPermission] = useState(null); |
||||
const [scanned, setScanned] = useState(false); |
||||
|
||||
useEffect(() => { |
||||
(async () => { |
||||
const { status } = await BarCodeScanner.requestPermissionsAsync(); |
||||
setHasPermission(status === "granted"); |
||||
})(); |
||||
}, []); |
||||
|
||||
const handleBarCodeScanned = ({ type, data }) => { |
||||
setScanned(true); |
||||
alert(`Bar code with type ${type} and data ${data} has been scanned!`); |
||||
}; |
||||
|
||||
if (hasPermission === null) { |
||||
return <Text>Requesting for camera permission</Text>; |
||||
} |
||||
if (hasPermission === false) { |
||||
return <Text>No access to camera</Text>; |
||||
} |
||||
|
||||
return ( |
||||
<> |
||||
<BarCodeScanner |
||||
onBarCodeScanned={scanned ? undefined : handleBarCodeScanned} |
||||
style={{ width: "100%", height: 300 }} |
||||
/> |
||||
{scanned ? ( |
||||
<Button title={"Tap to Scan Again"} onPress={() => setScanned(false)} /> |
||||
) : null} |
||||
</> |
||||
); |
||||
} |
@ -0,0 +1,63 @@ |
||||
import React, { useState } from "react"; |
||||
import { TextInput, View, StyleSheet, Pressable } from "react-native"; |
||||
import { connect } from "react-redux"; |
||||
import tw from "tailwind-rn"; |
||||
import { AntDesign } from "@expo/vector-icons"; |
||||
|
||||
//style
|
||||
import Colors from "../constants/Colors"; |
||||
import fontSize from "../constants/fontSize"; |
||||
|
||||
const Search = ({ |
||||
placeholder, |
||||
textAlign, |
||||
direction, |
||||
onChange, |
||||
value, |
||||
theme, |
||||
}) => { |
||||
const styles = StyleSheet.create({ |
||||
inputStyle: { |
||||
fontSize: fontSize.tiny, |
||||
color: theme === "light" ? Colors.theme1.gray2077 : Colors.theme1.white, |
||||
borderWidth: 0.5, |
||||
borderColor: Colors.theme1.gray20 + "88", |
||||
paddingVertical: 10, |
||||
paddingHorizontal: 10, |
||||
direction: direction, |
||||
textAlign: textAlign, |
||||
backgroundColor: |
||||
theme === "light" ? Colors.theme1.white : Colors.theme1.gray2077, |
||||
fontFamily: "regular", |
||||
}, |
||||
}); |
||||
return ( |
||||
<View style={[{ marginTop: 18 }, tw("w-full relative")]}> |
||||
<TextInput |
||||
style={[styles.inputStyle, tw("rounded-sm")]} |
||||
onChangeText={(text) => onChange(text)} |
||||
placeholder={placeholder} |
||||
placeholderTextColor={ |
||||
theme === "light" |
||||
? Colors.theme1.gray20 + "88" |
||||
: Colors.theme1.white + "aa" |
||||
} |
||||
value={value} |
||||
/> |
||||
<Pressable style={tw("absolute left-3 top-3")}> |
||||
<AntDesign name="search1" size={20} color="#52796F" /> |
||||
</Pressable> |
||||
</View> |
||||
); |
||||
}; |
||||
|
||||
const mapStateToProps = (state) => ({ |
||||
theme: state.publicApi.theme, |
||||
}); |
||||
|
||||
export default connect(mapStateToProps)(Search); |
||||
|
||||
Search.defaultProps = { |
||||
direction: "rtl", |
||||
textAlign: "right", |
||||
}; |
@ -0,0 +1,91 @@ |
||||
import React from "react"; |
||||
import { connect } from "react-redux"; |
||||
import Svg, { Path } from "react-native-svg"; |
||||
import SelectDropdown from "react-native-select-dropdown"; |
||||
|
||||
//styles
|
||||
import fontSize from "../constants/fontSize"; |
||||
import Colors from "../constants/Colors"; |
||||
function Select({ |
||||
iconPosition, |
||||
options, |
||||
onChange, |
||||
name, |
||||
width, |
||||
defaultValue, |
||||
theme, |
||||
disabled, |
||||
}) { |
||||
return ( |
||||
<SelectDropdown |
||||
data={options} |
||||
disabled={disabled} |
||||
buttonStyle={{ |
||||
width: width, |
||||
borderWidth: 1, |
||||
borderColor: Colors.theme1.gray2077 + "66", |
||||
borderRadius: 2, |
||||
height: 48, |
||||
backgroundColor: |
||||
theme === "light" ? Colors.theme1.white : Colors.theme1.gray2077, |
||||
fontFamily: "regular", |
||||
}} |
||||
rowTextStyle={{ |
||||
fontSize: fontSize.sm, |
||||
fontFamily: "regular", |
||||
color: theme === "light" ? Colors.theme1.gray20 : Colors.theme1.grayF9, |
||||
}} |
||||
defaultButtonText={defaultValue} |
||||
statusBarTranslucent={true} |
||||
buttonTextStyle={{ |
||||
textAlign: "center", |
||||
justifyContent: "flex-end", |
||||
flex: 0, |
||||
fontSize: fontSize.tiny, |
||||
color: theme === "light" ? Colors.theme1.gray2077 + (disabled ? "aa" : "") : Colors.theme1.white + (disabled ? "aa" : ""), |
||||
fontFamily: "regular", |
||||
// display: 'inline'
|
||||
}} |
||||
dropdownIconPosition={iconPosition} |
||||
onSelect={(selectedItem) => { |
||||
onChange(name, selectedItem); |
||||
}} |
||||
renderDropdownIcon={() => ( |
||||
<Svg |
||||
data-name="vuesax/linear/arrow-down" |
||||
xmlns="http://www.w3.org/2000/svg" |
||||
width={16.081} |
||||
height={16.081} |
||||
> |
||||
<Path |
||||
d="m13.347 5.997-4.368 4.369a1.331 1.331 0 0 1-1.876 0L2.734 5.997" |
||||
fill="none" |
||||
stroke={ |
||||
theme === "light" |
||||
? Colors.theme1.gray2077 + "66" |
||||
: Colors.theme1.white + (disabled ? "aa" : "") |
||||
} |
||||
strokeLinecap="round" |
||||
strokeLinejoin="round" |
||||
strokeWidth={1.5} |
||||
/> |
||||
</Svg> |
||||
)} |
||||
dropdownStyle={{ |
||||
backgroundColor: |
||||
theme === "light" ? Colors.theme1.white : Colors.theme1.gray2077, |
||||
}} |
||||
/> |
||||
); |
||||
} |
||||
|
||||
const mapStateToProps = (state) => ({ |
||||
theme: state.publicApi.theme, |
||||
}); |
||||
|
||||
export default connect(mapStateToProps)(Select); |
||||
|
||||
Select.defaultProps = { |
||||
options: ["1", "2", "3"], |
||||
iconPosition: "left", |
||||
}; |
@ -0,0 +1,46 @@ |
||||
const Colors = { |
||||
theme1: { |
||||
//green
|
||||
green79: "#52796F", |
||||
greenBA: "#06BAC0", |
||||
greenC8: "#76C893", |
||||
greenCF: "#12CF7F", |
||||
greenD9: "#99D98C", |
||||
greenDD: "#D5DDBC", |
||||
greenFF: "#00FF80", |
||||
greenFF1: "#DEFFF1", |
||||
//blue
|
||||
blue90: "#235A90", |
||||
blueCB: "#98B2CB", |
||||
blueEB: "#2B8DEB", |
||||
blueFA: "#F8F9FA", |
||||
blueFA1: "#9CF1FA", |
||||
blueFD: "#F6F9FD", |
||||
blueFD1: "#F4F8FD", |
||||
blueFDOP: "rgba(6, 146, 255, 0.36)", |
||||
blueFF: "#E8FCFF", |
||||
blueFF1: "#E9F0FF", |
||||
//gray
|
||||
gray20: "#202020", |
||||
gray2077: "#2F3E46", |
||||
grayE3: "#E3E3E3", |
||||
grayF9: "#F9F9F9", |
||||
grayCC: "#CCC", |
||||
//red
|
||||
redC0: "#C01919", |
||||
redFF: "#FFE6E6", |
||||
redFF1: "#FF2020", |
||||
//yellow
|
||||
yellow2: "#FDFFDA", |
||||
yellow3: "#EFFF00", |
||||
yellow4: "#FFEE00", |
||||
//orange
|
||||
orange1: "#FF6600", |
||||
//black
|
||||
black: "#000000", |
||||
white: "#FFFFFF", |
||||
dark : '#061B30', |
||||
}, |
||||
}; |
||||
|
||||
export default Colors; |
@ -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', |
||||
}; |
@ -0,0 +1,21 @@ |
||||
import { Dimensions } from "react-native" |
||||
import { fontSizeHandler } from "../utils/fontSizeResponsive" |
||||
|
||||
const {width} = Dimensions.get("window"); |
||||
const minWidth = 320; |
||||
const maxWidth = 1200; |
||||
|
||||
const fontSize = { |
||||
xs : fontSizeHandler(width, 10, 12, minWidth, maxWidth), |
||||
sm : fontSizeHandler(width,12, 14, minWidth, maxWidth), |
||||
base : fontSizeHandler(width, 14, 16, minWidth, maxWidth), |
||||
lg : fontSizeHandler(width, 16 , 18, minWidth, maxWidth), |
||||
xl : fontSizeHandler(width, 18, 20, minWidth, maxWidth), |
||||
xl2 : fontSizeHandler(width, 20, 22, minWidth, maxWidth), |
||||
xl3 : fontSizeHandler(width, 22, 24, minWidth, maxWidth), |
||||
xl4 : fontSizeHandler(width, 24, 26, minWidth, maxWidth), |
||||
xl5 : fontSizeHandler(width, 26, 28, minWidth, maxWidth), |
||||
xl6 : fontSizeHandler(width, 28, 30, minWidth, maxWidth) |
||||
}; |
||||
|
||||
export default fontSize; |
@ -0,0 +1,27 @@ |
||||
import proxy from "../proxy"; |
||||
|
||||
const activation = { |
||||
list: |
||||
(data = {}) => |
||||
async (dispatch) => |
||||
await proxy.get("activation/list", data, { dispatch }), |
||||
update: |
||||
(data = {}, data2 = {}) => |
||||
async (dispatch) => { |
||||
await proxy.put("activation/update", data); |
||||
await proxy.get("activation/list", data2, { dispatch }); |
||||
}, |
||||
add: |
||||
(data = {}) => |
||||
async (dispatch) => { |
||||
await proxy.post("activation/add", data); |
||||
}, |
||||
del: |
||||
(data = {}, data2 = {}) => |
||||
async (dispatch) => { |
||||
await proxy.delete("activation/delete", data); |
||||
await proxy.get("activation/list", data2, { dispatch }); |
||||
}, |
||||
}; |
||||
|
||||
export default activation; |
@ -0,0 +1,13 @@ |
||||
import proxy from "../proxy"; |
||||
const blog = { |
||||
list: |
||||
(data = {}) => |
||||
async (dispatch) => |
||||
await proxy.get("public/blogList", data, { dispatch }), |
||||
info: (data) => async (dispatch) => |
||||
await proxy.get("public/blogInfo", data, { dispatch }), |
||||
setHashtag: (data) => async (dispatch) => |
||||
await dispatch({ type: "public/setHashtag", data }), |
||||
}; |
||||
|
||||
export default blog; |
@ -0,0 +1,18 @@ |
||||
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 }), |
||||
setFilterOptions: (data) => async (dispatch) => { |
||||
dispatch({ type: "book/setFilterOptions", data: data }); |
||||
}, |
||||
}; |
||||
|
||||
export default book; |
@ -0,0 +1,32 @@ |
||||
import proxy from "../proxy"; |
||||
const comment = { |
||||
list: |
||||
(data = {}) => |
||||
async (dispatch) => |
||||
await proxy.get("comment/list", data, { dispatch }), |
||||
info: |
||||
(data = {}) => |
||||
async (dispatch) => { |
||||
await proxy.get("comment/info", data, { dispatch }); |
||||
}, |
||||
add: |
||||
(data = {}, data2) => |
||||
async (dispatch) => { |
||||
await proxy.post("comment/add", data, { dispatch }); |
||||
// if (data2) await proxy.get("book/info", data2, { dispatch });
|
||||
}, |
||||
del: |
||||
(data = {}, data2 = {}) => |
||||
async (dispatch) => { |
||||
await proxy.delete("comment/delete", data); |
||||
await proxy.get("comment/list", data2, { dispatch }); |
||||
}, |
||||
update: |
||||
(data = {}, data2 = {}) => |
||||
async (dispatch) => { |
||||
await proxy.put("comment/update", data); |
||||
await proxy.get("comment/list", data2, { dispatch }); |
||||
}, |
||||
}; |
||||
|
||||
export default comment; |
@ -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; |
@ -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; |
@ -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; |
@ -0,0 +1,8 @@ |
||||
const form = { |
||||
setTicket: |
||||
(data = {}) => |
||||
async (dispatch) => |
||||
await dispatch({ type: "form/ticket", data }), |
||||
}; |
||||
|
||||
export default form; |
@ -0,0 +1,19 @@ |
||||
// @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"; |
||||
export { default as qr } from "./qr"; |
||||
export {default as userAddress} from "./userAddress"; |
||||
export {default as userFavorite} from "./userFavorite"; |
||||
export { default as transport } from "./transport"; |
||||
export { default as activation } from "./activation"; |
||||
export { default as form } from "./form"; |
||||
export { default as comment } from "./comment"; |
||||
export { default as vote } from "./vote"; |
@ -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; |
@ -0,0 +1,54 @@ |
||||
import proxy from "../proxy"; |
||||
const publicApi = { |
||||
setLTR: (data) => async (dispatch) => |
||||
await dispatch({ type: "public/setLtr", data: data }), |
||||
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 = {}, data2 = {}) => |
||||
async (dispatch) => { |
||||
await proxy.get("public/vod/bookCourse", data, { dispatch }); |
||||
await proxy.get("book/info", data2, { 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 }), |
||||
getArList: (data, history) => async (dispatch) => |
||||
await proxy.get("public/ar", data, { history, dispatch }), |
||||
}; |
||||
|
||||
export default publicApi; |
@ -0,0 +1,33 @@ |
||||
import proxy from "../proxy"; |
||||
|
||||
const qr = { |
||||
list: |
||||
(data = {}) => |
||||
async (dispatch) => |
||||
await proxy.get("qr/list", data, { dispatch }), |
||||
info: |
||||
(data = {}) => |
||||
async (dispatch) => { |
||||
await proxy.get("qr/info", data, { dispatch }); |
||||
}, |
||||
add: |
||||
(data = {}, data2 = {}) => |
||||
async (dispatch) => { |
||||
await proxy.post("qr/add", data); |
||||
await proxy.get("qr/list", data2, { dispatch }); |
||||
}, |
||||
del: |
||||
(data = {}, data2 = {}) => |
||||
async (dispatch) => { |
||||
await proxy.delete("ar/delete", data); |
||||
await proxy.get("ar/list", data2, { dispatch }); |
||||
}, |
||||
update: |
||||
(data = {}, data2 = {}) => |
||||
async (dispatch) => { |
||||
await proxy.put("ar/update", data); |
||||
await proxy.get("ar/list", data2, { dispatch }); |
||||
}, |
||||
}; |
||||
|
||||
export default qr; |
@ -0,0 +1,17 @@ |
||||
import proxy from "../proxy"; |
||||
|
||||
const transport = { |
||||
list: |
||||
(data = {}) => |
||||
async (dispatch) => { |
||||
await proxy.get("transport/list", data, { dispatch }); |
||||
}, |
||||
set: |
||||
(data = {}, data2 = {}, data3 = {}) => |
||||
async (dispatch) => { |
||||
await proxy.post("transport/setTransport", data, { dispatch }); |
||||
await proxy.get("userFactor/info", data2, { dispatch }); |
||||
}, |
||||
}; |
||||
|
||||
export default transport; |
@ -0,0 +1,61 @@ |
||||
import proxy from "../proxy"; |
||||
|
||||
const user = { |
||||
getStatus: () => async (dispatch) => { |
||||
await proxy.getStatus({ dispatch }); |
||||
}, |
||||
otp: (data) => async (dispatch) => { |
||||
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 }), |
||||
|
||||
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 }); |
||||
}, |
||||
setProfileFields: |
||||
(data = {}) => |
||||
async (dispatch) => { |
||||
await dispatch({ type: "user/setProfileFields", data }); |
||||
}, |
||||
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; |
@ -0,0 +1,36 @@ |
||||
import proxy from "../proxy"; |
||||
|
||||
const userAddress = { |
||||
list: |
||||
(data = {}) => |
||||
async (dispatch) => { |
||||
await proxy.get("userAddress/list", data, { dispatch }); |
||||
}, |
||||
info: |
||||
(data = {}) => |
||||
async (dispatch) => { |
||||
await dispatch({ type: "userAddress/info", data }); |
||||
}, |
||||
update: |
||||
(data = {}, data2 = {}) => |
||||
async (dispatch) => { |
||||
await proxy.put("userAddress/update", data); |
||||
await proxy.get("userAddress/list", data2, { dispatch }); |
||||
}, |
||||
add: |
||||
(data = {}, data2 = {}, data3 = {}) => |
||||
async (dispatch) => { |
||||
await proxy.post("userAddress/add", data); |
||||
setTimeout(() => { |
||||
proxy.get("userAddress/list", data2, { dispatch }); |
||||
}, 600); |
||||
}, |
||||
del: |
||||
(data = {}, data2 = {}) => |
||||
async (dispatch) => { |
||||
await proxy.delete("userAddress/delete", data); |
||||
await proxy.get("userAddress/list", data2, { dispatch }); |
||||
}, |
||||
}; |
||||
|
||||
export default userAddress; |
@ -0,0 +1,59 @@ |
||||
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 }); |
||||
}, |
||||
fullList: |
||||
(data = {}) => |
||||
async (dispatch) => |
||||
await proxy.get("userFactor/fullList", data, { dispatch }), |
||||
}; |
||||
|
||||
export default userFactor; |
@ -0,0 +1,27 @@ |
||||
import proxy from "../proxy"; |
||||
|
||||
const userFavorite = { |
||||
list: |
||||
(data = {}) => |
||||
async (dispatch) => { |
||||
await proxy.get("userFavorite/list", data, { dispatch }); |
||||
}, |
||||
update: |
||||
(data = {}, data2 = {}) => |
||||
async (dispatch) => { |
||||
await proxy.put("userFavorite/update", data); |
||||
await proxy.get("userFavorite/list", data2, { dispatch }); |
||||
}, |
||||
add: |
||||
(data = {}, data2 = {}, data3 = {}) => |
||||
async (dispatch) => { |
||||
await proxy.post("userFavorite/add", data, { dispatch }); |
||||
}, |
||||
del: |
||||
(data = {}, data2 = {}) => |
||||
async (dispatch) => { |
||||
await proxy.delete("userFavorite/delete", data, { dispatch }); |
||||
}, |
||||
}; |
||||
|
||||
export default userFavorite; |
@ -0,0 +1,42 @@ |
||||
import proxy from "../proxy"; |
||||
const userProduct = { |
||||
arList: |
||||
(data = {}) => |
||||
async (dispatch) => { |
||||
await proxy.get("userProduct/arList", data, { dispatch }); |
||||
}, |
||||
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("userFactor/info", data3, { dispatch }); |
||||
}, |
||||
del: |
||||
(data = {}, data2 = {}) => |
||||
async (dispatch) => { |
||||
await proxy.delete("userProduct/delete", data); |
||||
await proxy.get("userProduct/list", data2, { dispatch }); |
||||
}, |
||||
myList: |
||||
(data = {}) => |
||||
async (dispatch) => { |
||||
await proxy.get("userProduct/myList", data, { dispatch }); |
||||
}, |
||||
}; |
||||
|
||||
export default userProduct; |
@ -0,0 +1,11 @@ |
||||
import proxy from "../proxy"; |
||||
const vote = { |
||||
add: |
||||
(data = {}, data2) => |
||||
async (dispatch) => { |
||||
await proxy.post("userVote/add", data, { dispatch }); |
||||
}, |
||||
|
||||
}; |
||||
|
||||
export default vote; |
@ -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'; |
@ -0,0 +1,153 @@ |
||||
import { ApiConfig } from "../constants/defaultValues"; |
||||
import axios from "axios"; |
||||
import AsyncStorage from "@react-native-async-storage/async-storage"; |
||||
import { useNavigation } from "@react-navigation/native"; |
||||
import { asyncAwesomeAlert } from "../utils/AsyncWrappers"; |
||||
|
||||
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) {} |
||||
}; |
||||
|
||||
post = (url, params, opt, data) => { |
||||
try { |
||||
this.check(url, opt, () => Axios.post(url, params, opt), data || params); |
||||
} catch (error) {} |
||||
}; |
||||
|
||||
put = (url, params, opt, data) => { |
||||
try { |
||||
this.check(url, opt, () => Axios.put(url, params, opt), data || params); |
||||
} catch (error) {} |
||||
}; |
||||
|
||||
delete = (url, params, opt, data) => { |
||||
try { |
||||
this.check( |
||||
url, |
||||
opt, |
||||
() => Axios.delete(url, { ...opt, data: params }), |
||||
data || params |
||||
); |
||||
} catch (error) {} |
||||
}; |
||||
|
||||
check = async (url, { dispatch }, fetch, params) => { |
||||
try { |
||||
dispatch = dispatch || (() => {}); |
||||
dispatch({ type: url.split("/")[0] + "/" + "loading" }); |
||||
let response = await 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; |
||||
} |
||||
return; |
||||
case 403: |
||||
asyncAwesomeAlert("", 'خطای ورود اطلاعات', { |
||||
showCancelButton: false, |
||||
}); |
||||
default: |
||||
dispatch({ |
||||
type: url.split("/")[0] + "/" + "error", |
||||
data: response.data, |
||||
params, |
||||
}); |
||||
} |
||||
return false; |
||||
} catch (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) {} |
||||
}; |
||||
|
||||
login = (url, params, { dispatch }) => { |
||||
try { |
||||
this.post(url, params, { |
||||
dispatch: (obj) => { |
||||
let login = obj.data; |
||||
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) {} |
||||
}; |
||||
|
||||
logout = (url, params, { dispatch }) => { |
||||
try { |
||||
this.post(url, params, { |
||||
dispatch: (obj) => { |
||||
const keys = ["refresh", "access", "userData"]; |
||||
AsyncStorage.multiRemove(keys); |
||||
dispatch(obj); |
||||
}, |
||||
}); |
||||
} catch (error) {} |
||||
}; |
||||
status = async () => { |
||||
try { |
||||
let refresh = await AsyncStorage.getItem("refresh"); |
||||
let userData = await 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) { |
||||
return nulll; |
||||
} |
||||
}; |
||||
getStatus = async ({ dispatch }) => { |
||||
let status = await this.status(); |
||||
dispatch({ type: "user/getStatus", data: { status } }); |
||||
}; |
||||
} |
||||
const _proxy = new Proxy(); |
||||
export default _proxy; |
@ -0,0 +1,39 @@ |
||||
import { asyncAwesomeAlert } from "../../utils/AsyncWrappers"; |
||||
|
||||
const initialState = { |
||||
loading: false, |
||||
error: null, |
||||
list: [], |
||||
message: null, |
||||
}; |
||||
export default function activation(state = initialState, action) { |
||||
let { type, data } = action; |
||||
switch (type) { |
||||
case "activation/list": |
||||
return { ...state, loading: false, list: data, error: null }; |
||||
case "activation/update": |
||||
return { ...state, loading: false, error: null, message: data.message }; |
||||
case "activation/add": |
||||
asyncAwesomeAlert("نتیجه", data.message, { |
||||
showCancelButton: false, |
||||
}); |
||||
return { ...state, loading: false, error: null }; |
||||
case "activation/delete": |
||||
return { ...state, loading: false, error: null }; |
||||
case "loading": |
||||
return { ...state, loading: true }; |
||||
case "error": |
||||
asyncAwesomeAlert("خطا", data.message, { |
||||
showCancelButton: false, |
||||
confirmText: "باشه" |
||||
}); |
||||
return { |
||||
...state, |
||||
loading: false, |
||||
error: data.message, |
||||
message: data.message, |
||||
}; |
||||
default: |
||||
return state; |
||||
} |
||||
} |
@ -0,0 +1,36 @@ |
||||
const initialState = { |
||||
loading: false, |
||||
error: null, |
||||
list: [], |
||||
info: null, |
||||
hashtags : [], |
||||
hashtag : null, |
||||
}; |
||||
export default function blog(state = initialState, action) { |
||||
let { type, data } = action; |
||||
switch (type) { |
||||
case "public/setHashtag": |
||||
return { |
||||
...state, |
||||
loading: false, |
||||
hashtag: data, |
||||
error: null, |
||||
}; |
||||
case "public/blogList": |
||||
return { |
||||
...state, |
||||
loading: false, |
||||
list: data, |
||||
hashtags: [...new Set(data.map((object) => object.tag))], |
||||
error: null, |
||||
}; |
||||
case "public/blogInfo": |
||||
return { ...state, loading: false, error: null, blog: data }; |
||||
case "blog/loading": |
||||
return { ...state, loading: true }; |
||||
case "blog/error": |
||||
return { ...state, loading: false, error: data.message }; |
||||
default: |
||||
return state; |
||||
} |
||||
} |
@ -0,0 +1,96 @@ |
||||
import {asyncAwesomeAlert} from '../../utils/AsyncWrappers'; |
||||
|
||||
const initialState = { |
||||
loading: false, |
||||
error: null, |
||||
list: [], |
||||
info: null, |
||||
searchResult: [], |
||||
filterResult: [], |
||||
subjects: [], |
||||
levels: [], |
||||
sortFilters: ["مرتب سازی", "محبوب ترین", "جدیدترین"], |
||||
selectedVideo: null, |
||||
gradeFilterBooks: null, |
||||
sortFilterCourse: null, |
||||
selectedGrade: null, |
||||
selectedSort: "پربازدید ترین ها", |
||||
filterOptions: { |
||||
grade: "", |
||||
subject: "", |
||||
productType: '', |
||||
available: false, |
||||
sort: null, |
||||
search: "", |
||||
}, |
||||
productTypes: [ |
||||
"نوع محصول", |
||||
"کتاب فیزیکی", |
||||
"کتاب دیجیتال", |
||||
"دوره ویدئویی", |
||||
"بسته های آموزشی", |
||||
], |
||||
}; |
||||
|
||||
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 |
||||
); |
||||
itemsSubject.unshift("نام کتاب"); |
||||
|
||||
let itemsLevel = (Array.isArray(data) ? data : []) |
||||
.map((item) => item.gradeId * 1) |
||||
.sort((a, b) => a - b) |
||||
.map((e) => grades[e]); |
||||
itemsLevel.unshift("پایه تحصیلی"); |
||||
|
||||
return { |
||||
...state, |
||||
loading: false, |
||||
list: data, |
||||
subjects: Array.from(new Set(itemsSubject)), |
||||
levels: Array.from(new Set(itemsLevel)), |
||||
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/setFilterOptions": |
||||
return { ...state, loading: false, error: null, filterOptions: data }; |
||||
case "book/loading": |
||||
return { ...state, loading: true }; |
||||
case "book/error": |
||||
asyncAwesomeAlert("خطا", data.message, { |
||||
showCancelButton: false, |
||||
confirmText: "باشه" |
||||
}); |
||||
return { ...state, loading: false, error: data.message }; |
||||
default: |
||||
return state; |
||||
} |
||||
} |
@ -0,0 +1,37 @@ |
||||
const initialState = { |
||||
loading: false, |
||||
error: null, |
||||
list: null, |
||||
}; |
||||
|
||||
export default function comment(state = initialState, action) { |
||||
let { type, data } = action; |
||||
switch (type) { |
||||
case "comment/list": |
||||
return { ...state, loading: false, error: null }; |
||||
case "comment/update": |
||||
return { ...state, loading: false, error: null }; |
||||
case "comment/add": |
||||
return { ...state, loading: false, error: null }; |
||||
case "comment/delete": |
||||
return { ...state, loading: false, error: null }; |
||||
case "comment/info": |
||||
return { |
||||
...state, |
||||
loading: false, |
||||
list: data, |
||||
error: null, |
||||
}; |
||||
case "comment/loading": |
||||
return { ...state, loading: true }; |
||||
case "comment/error": |
||||
asyncAwesomeAlert("خطا", data.message, { |
||||
showCancelButton: false, |
||||
confirmText: "باشه" |
||||
|
||||
}); |
||||
return { ...state, loading: false, error: data.message }; |
||||
default: |
||||
return state; |
||||
} |
||||
} |
@ -0,0 +1,55 @@ |
||||
const initialState = { |
||||
loading: false, |
||||
error: null, |
||||
list: [], |
||||
searchResult: [], |
||||
search: "", |
||||
}; |
||||
|
||||
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": |
||||
return { ...state, loading: false, error: data.message }; |
||||
default: |
||||
return state; |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -0,0 +1,24 @@ |
||||
const initialState = { |
||||
loading: false, |
||||
error: null, |
||||
ticket: {}, |
||||
}; |
||||
|
||||
export default function form(state = initialState, action) { |
||||
let { type, data } = action; |
||||
switch (type) { |
||||
case "form/ticket": |
||||
return { |
||||
...state, |
||||
loading: false, |
||||
ticket: { ...state.ticket, [data.name]: data.value }, |
||||
error: null, |
||||
}; |
||||
case "form/loading": |
||||
return { ...state, loading: true }; |
||||
case "form/error": |
||||
return { ...state, loading: false, error: data.message }; |
||||
default: |
||||
return state; |
||||
} |
||||
} |
@ -0,0 +1,18 @@ |
||||
// @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"; |
||||
import { default as qr } from "./qr"; |
||||
export { default as userAddress } from "./userAddress"; |
||||
export { default as userFavorite } from "./userFavorite"; |
||||
export { default as transport } from "./transport"; |
||||
export { default as activation } from "./activation"; |
||||
export { default as form } from "./form"; |
||||
export { default as comment } from "./comment"; |
||||
export { default as vote } from "./vote"; |
@ -0,0 +1,31 @@ |
||||
import {asyncAwesomeAlert} from '../../utils/AsyncWrappers'; |
||||
|
||||
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": |
||||
asyncAwesomeAlert("خطا", data.message, { |
||||
showCancelButton: false, |
||||
confirmText: "باشه" |
||||
}); |
||||
return { ...state, loading: false, error: data.message }; |
||||
default: |
||||
return state; |
||||
} |
||||
} |
@ -0,0 +1,33 @@ |
||||
const initialState = { |
||||
loading: false, |
||||
error: null, |
||||
list: null, |
||||
}; |
||||
|
||||
export default function qr(state = initialState, action) { |
||||
let { type, data } = action; |
||||
switch (type) { |
||||
case "qr/list": |
||||
return { ...state, loading: false, error: null }; |
||||
case "qr/update": |
||||
return { ...state, loading: false, error: null }; |
||||
case "qr/add": |
||||
return { ...state, loading: false, error: null }; |
||||
case "qr/delete": |
||||
return { ...state, loading: false, error: null }; |
||||
case "qr/info": |
||||
return { |
||||
...state, |
||||
loading: false, |
||||
list: data, |
||||
error: null, |
||||
}; |
||||
/////////////
|
||||
case "loading": |
||||
return { ...state, loading: true }; |
||||
case "error": |
||||
return { ...state, loading: false, error: data.message }; |
||||
default: |
||||
return state; |
||||
} |
||||
} |
@ -0,0 +1,25 @@ |
||||
const initialState = { |
||||
loading: false, |
||||
error: null, |
||||
list: [], |
||||
}; |
||||
export default function transport(state = initialState, action) { |
||||
let { type, data } = action; |
||||
switch (type) { |
||||
case "transport/list": |
||||
return { |
||||
...state, |
||||
loading: false, |
||||
list: data, |
||||
error: null, |
||||
}; |
||||
case "transport/info": |
||||
return { ...state, loading: false, error: null}; |
||||
case "transport/loading": |
||||
return { ...state, loading: true }; |
||||
case "transport/error": |
||||
return { ...state, loading: false, error: data.message }; |
||||
default: |
||||
return state; |
||||
} |
||||
} |
@ -0,0 +1,75 @@ |
||||
import proxy from "../proxy"; |
||||
import AsyncStorage from "@react-native-async-storage/async-storage"; |
||||
import {asyncAwesomeAlert} from '../../utils/AsyncWrappers'; |
||||
|
||||
let initialState = { |
||||
status: null, |
||||
loading: false, |
||||
error: null, |
||||
list: null, |
||||
domains: [], |
||||
mothers: [], |
||||
profileStatus: false, |
||||
setDone: false, |
||||
setLogin: false, |
||||
check: "check", |
||||
profileFields : { |
||||
|
||||
}, |
||||
}; |
||||
|
||||
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/getStatus": |
||||
return { ...state, status: JSON.parse(data.status), 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) { |
||||
("user/getProfile", error); |
||||
} |
||||
return { |
||||
...state, |
||||
loading: false, |
||||
status: data, |
||||
error: null, |
||||
setDone: false, |
||||
}; |
||||
case "user/logout": |
||||
return { ...state, loading: false, status: null, error: null }; |
||||
case "user/getUserRole": |
||||
return { ...state, loading: false, userRoles: data, error: null }; |
||||
case "user/setProfile": |
||||
return { ...state, loading: false, error: null, setDone: true }; |
||||
case "user/setProfileFields": |
||||
return { ...state, loading: false, error: null, profileFields: data }; |
||||
case "user/loading": |
||||
return { ...state, loading: true }; |
||||
case "user/error": |
||||
asyncAwesomeAlert("خطا", data.message, { |
||||
showCancelButton: false, |
||||
confirmText: "باشه" |
||||
}); |
||||
return { ...state, error : true }; |
||||
default: |
||||
return state; |
||||
} |
||||
}; |
||||
|
||||
export default user; |
@ -0,0 +1,32 @@ |
||||
const initialState = { |
||||
loading: false, |
||||
error: null, |
||||
list: [], |
||||
info : null, |
||||
}; |
||||
export default function userAddress(state = initialState, action) { |
||||
let { type, data } = action; |
||||
switch (type) { |
||||
case "userAddress/list": |
||||
return { |
||||
...state, |
||||
loading: false, |
||||
list: data, |
||||
error: null, |
||||
}; |
||||
case "userAddress/info": |
||||
return { ...state, loading: false, info: data, error: null }; |
||||
case "userAddress/update": |
||||
return { ...state, loading: false, error: null }; |
||||
case "userAddress/add": |
||||
return { ...state, loading: false, error: null}; |
||||
case "userAddress/delete": |
||||
return { ...state, loading: false, error: null }; |
||||
case "userAddress/loading": |
||||
return { ...state, loading: true }; |
||||
case "userAddress/error": |
||||
return { ...state, loading: false, error: data.message }; |
||||
default: |
||||
return state; |
||||
} |
||||
} |
@ -0,0 +1,67 @@ |
||||
import { asyncAwesomeAlert } from "../../utils/AsyncWrappers"; |
||||
|
||||
const initialState = { |
||||
loading: false, |
||||
error: null, |
||||
list: null, |
||||
info: null, |
||||
sum: null, |
||||
checkEmpty: false, |
||||
isVerified: null, |
||||
fullList: [], |
||||
}; |
||||
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/fullList": |
||||
return { |
||||
...state, |
||||
loading: false, |
||||
fullList: data, |
||||
error: null, |
||||
}; |
||||
case "userFactor/info": |
||||
return { ...state, loading: false, info: data, error: null }; |
||||
case "userFactor/add": |
||||
return { ...state, loading: false, error: null, sum: data.payPrice }; |
||||
case "userFactor/delete": |
||||
return { ...state, loading: false, error: null }; |
||||
case "userFactor/payment": |
||||
return { ...state, loading: false, error: null }; |
||||
//vod
|
||||
case "userFactor/myList": |
||||
return { ...state, loading: false, list: data, error: null }; |
||||
case "userFactor/update": |
||||
return { ...state, loading: false, error: null }; |
||||
case "userFactor/deleteUserOffCode": |
||||
return { ...state, loading: false, error: null }; |
||||
case "userFactor/paymentVOD": |
||||
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": |
||||
asyncAwesomeAlert("خطا", data.message, { |
||||
showCancelButton: false, |
||||
confirmText: "باشه" |
||||
}); |
||||
return { ...state, loading: false, error: data.message }; |
||||
default: |
||||
return state; |
||||
} |
||||
} |
@ -0,0 +1,41 @@ |
||||
import { toastMessage } from "../../utils/message"; |
||||
import { asyncAwesomeAlert } from "../../utils/AsyncWrappers"; |
||||
|
||||
const initialState = { |
||||
loading: false, |
||||
error: null, |
||||
list: [], |
||||
}; |
||||
export default function userFavorite(state = initialState, action) { |
||||
let { type, data } = action; |
||||
switch (type) { |
||||
case "userFavorite/list": |
||||
return { |
||||
...state, |
||||
loading: false, |
||||
list: data, |
||||
error: null, |
||||
}; |
||||
case "userFavorite/update": |
||||
return { ...state, loading: false, error: null }; |
||||
case "userFavorite/add": |
||||
return { |
||||
...state, |
||||
list: data.userFavorites, |
||||
loading: false, |
||||
error: null, |
||||
}; |
||||
case "userFavorite/delete": |
||||
return { ...state, list : data.userFavorites, loading: false, error: null }; |
||||
case "userFavorite/loading": |
||||
return { ...state, loading: true }; |
||||
case "userFavorite/error": |
||||
asyncAwesomeAlert("خطا", data.message, { |
||||
showCancelButton: false, |
||||
confirmText: "باشه" |
||||
}); |
||||
return { ...state, loading: false, error: data.message }; |
||||
default: |
||||
return state; |
||||
} |
||||
} |
@ -0,0 +1,62 @@ |
||||
import { asyncAwesomeAlert } from "../../utils/AsyncWrappers"; |
||||
|
||||
const initialState = { |
||||
loading: false, |
||||
error: null, |
||||
list: [], |
||||
myList: [], |
||||
info: null, |
||||
sum: null, |
||||
checkEmpty: false, |
||||
hasPhysical: false, |
||||
arList : [], |
||||
}; |
||||
export default function userFactor(state = initialState, action) { |
||||
let { type, data } = action; |
||||
switch (type) { |
||||
case "userProduct/arList": |
||||
return { ...state, loading: false, arList: data, error: null }; |
||||
case "userProduct/myList": |
||||
return { ...state, loading: false, myList: data, error: null }; |
||||
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": |
||||
return { |
||||
...state, |
||||
loading: false, |
||||
error: null, |
||||
list: data.products, |
||||
sum: data.payPrice, |
||||
}; |
||||
case "userProduct/delete": |
||||
return { ...state, loading: false, error: null }; |
||||
case "userProduct/loading": |
||||
return { ...state, loading: true }; |
||||
case "userProduct/error": |
||||
asyncAwesomeAlert("خطا", data.message, { |
||||
showCancelButton: false, |
||||
confirmText: "باشه" |
||||
}); |
||||
return { ...state, loading: false, error: data.message }; |
||||
default: |
||||
return state; |
||||
} |
||||
} |
@ -0,0 +1,27 @@ |
||||
import { asyncApiAwesomeAlert } from "../../utils/AsyncWrappers"; |
||||
|
||||
const initialState = { |
||||
loading: false, |
||||
error: null, |
||||
}; |
||||
|
||||
export default function vote(state = initialState, action) { |
||||
let { type, data } = action; |
||||
switch (type) { |
||||
case "userVote/add": |
||||
asyncAwesomeAlert("نتیجه", "رای شما با موفقیت ثبت شد.", { |
||||
showCancelButton: false, |
||||
}); |
||||
return { ...state, loading: false, error: null }; |
||||
case "userVote/loading": |
||||
return { ...state, loading: true }; |
||||
case "userVote/error": |
||||
asyncAwesomeAlert("خطا", data.message, { |
||||
showCancelButton: false, |
||||
confirmText: "باشه" |
||||
}); |
||||
return { ...state, loading: false, error: data.message }; |
||||
default: |
||||
return state; |
||||
} |
||||
} |
@ -0,0 +1,65 @@ |
||||
import AsyncStorage from "@react-native-async-storage/async-storage"; |
||||
import { applyMiddleware, createStore, compose, combineReducers } from "redux"; |
||||
import thunk from "redux-thunk"; |
||||
import { persistStore, persistReducer } from "redux-persist"; |
||||
import autoMergeLevel2 from "redux-persist/lib/stateReconciler/autoMergeLevel2"; |
||||
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"; |
||||
import qr from "./reducers/qr"; |
||||
import userAddress from "./reducers/userAddress"; |
||||
import transport from "./reducers/transport"; |
||||
import comment from "./reducers/comment"; |
||||
import form from "./reducers/form"; |
||||
import userFavorite from "./reducers/userFavorite"; |
||||
import vote from "./reducers/vote"; |
||||
|
||||
const persistConfig = { |
||||
key: "root", |
||||
storage: AsyncStorage, |
||||
stateReconciler: autoMergeLevel2, // see "Merge Process" section for details.
|
||||
whitelist: ["profile"], |
||||
}; |
||||
|
||||
const initialState = {}; |
||||
|
||||
const middleWare = [thunk]; |
||||
|
||||
const persistedReducer = persistReducer( |
||||
persistConfig, |
||||
combineReducers({ |
||||
publicApi, |
||||
user, |
||||
book, |
||||
blog, |
||||
product, |
||||
faq, |
||||
file, |
||||
userFactor, |
||||
userProduct, |
||||
qr, |
||||
userAddress, |
||||
transport, |
||||
comment, |
||||
form, |
||||
userFavorite, |
||||
vote, |
||||
}) |
||||
); |
||||
|
||||
console.disableYellowBox = true; |
||||
|
||||
export const store = createStore( |
||||
persistedReducer, |
||||
initialState, |
||||
compose(applyMiddleware(...middleWare)) |
||||
); |
||||
|
||||
export const persistor = persistStore(store); |
||||
|
@ -0,0 +1,55 @@ |
||||
import { Pressable, Text, Image, Dimensions } from "react-native"; |
||||
import React from "react"; |
||||
import { connect } from "react-redux"; |
||||
import * as Linking from "expo-linking"; |
||||
|
||||
//style
|
||||
import tw from "tailwind-rn"; |
||||
import fontSize from "../../../constants/fontSize"; |
||||
import Colors from "../../../constants/Colors"; |
||||
|
||||
const { width, height } = Dimensions.get("window"); |
||||
|
||||
const Book = ({ book, mobile, theme }) => { |
||||
return ( |
||||
<Pressable |
||||
style={[ |
||||
tw("flex items-end rounded-md p-2 my-2"), |
||||
{ width: mobile ? "48%" : width / 4.2 }, |
||||
]} |
||||
onPress={() => Linking.openURL(`https://ar.dnvn.ir/lunch?id=${book.id}`)} |
||||
> |
||||
<Image |
||||
source={{ uri: `https://dnvn.ir/api/v1/file/${book.fileId}` }} |
||||
resizeMode="contain" |
||||
style={[ |
||||
tw("rounded-sm w-full"), |
||||
{ |
||||
height: mobile ? (width - 32) / 1.5 : 200, |
||||
flex: 1, |
||||
}, |
||||
]} |
||||
/> |
||||
<Text |
||||
style={[ |
||||
{ |
||||
fontFamily: "bold", |
||||
fontSize: fontSize.lg, |
||||
marginTop: 10, |
||||
color: |
||||
theme === "light" ? Colors.theme1.green79 : Colors.theme1.white, |
||||
}, |
||||
]} |
||||
> |
||||
{book.title} |
||||
</Text> |
||||
</Pressable> |
||||
); |
||||
}; |
||||
|
||||
const mapStateToProps = (state) => ({ |
||||
mobile: state.publicApi.mobile, |
||||
theme: state.publicApi.theme, |
||||
}); |
||||
|
||||
export default connect(mapStateToProps)(Book); |
@ -0,0 +1,111 @@ |
||||
import React, { useState, useEffect } from "react"; |
||||
import { |
||||
SafeAreaView, |
||||
ScrollView, |
||||
StatusBar, |
||||
LayoutAnimation, |
||||
Platform, |
||||
Dimensions, |
||||
View, |
||||
} from "react-native"; |
||||
import { connect } from "react-redux"; |
||||
import { userProduct } from "../../redux/actions"; |
||||
|
||||
//components
|
||||
import Navbar from "../../components/Navbar"; |
||||
import Drawer from "../../components/Drawer"; |
||||
import Book from "./components/Book"; |
||||
import Empty from "../../components/Empty"; |
||||
|
||||
//style
|
||||
import tw from "tailwind-rn"; |
||||
|
||||
const { height } = Dimensions.get("window"); |
||||
const ios = Platform.OS === "ios"; |
||||
|
||||
function AR({ getArList, arList, mobile, theme }) { |
||||
const [position, setPosition] = useState("100%"); |
||||
|
||||
useEffect(() => { |
||||
getArList(); |
||||
StatusBar.setBarStyle( |
||||
`${theme === "light" ? "dark" : "light"}-content`, |
||||
true |
||||
); |
||||
}, []); |
||||
|
||||
useEffect(() => { |
||||
StatusBar.setBarStyle( |
||||
`${theme === "light" ? "dark" : "light"}-content`, |
||||
true |
||||
); |
||||
}, [theme]); |
||||
|
||||
const setBoxPosition = () => { |
||||
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut); |
||||
setPosition(position === "100%" ? "0%" : "100%"); |
||||
}; |
||||
|
||||
return ( |
||||
<SafeAreaView |
||||
style={{ |
||||
paddingTop: Platform.OS === "android" ? StatusBar.currentHeight : 0, |
||||
position: "relative", |
||||
flex: 1, |
||||
}} |
||||
> |
||||
<Navbar |
||||
setBoxPosition={setBoxPosition} |
||||
headerOptions={{ |
||||
logo: false, |
||||
menu: false, |
||||
hamburgerMenu: false, |
||||
title: "واقعیت افزوده", |
||||
bookmark: false, |
||||
qr: false, |
||||
back: true, |
||||
}} |
||||
/> |
||||
<Drawer setBoxPosition={setBoxPosition} position={position} /> |
||||
{arList?.length ? ( |
||||
<ScrollView |
||||
style={{ |
||||
paddingHorizontal: 16, |
||||
height: height, |
||||
}} |
||||
contentContainerStyle={{ paddingBottom: 60 }} |
||||
> |
||||
<View |
||||
style={tw( |
||||
`flex justify-between flex-wrap ${ |
||||
ios ? "flex-row-reverse" : "flex-row" |
||||
}` |
||||
)} |
||||
> |
||||
{arList?.map((book, index) => ( |
||||
<Book book={book} key={index} /> |
||||
))} |
||||
</View> |
||||
</ScrollView> |
||||
) : ( |
||||
<Empty |
||||
text="هیچ موردی برای شما وجود ندارد." |
||||
buttonText={"رفتن به فروشگاه"} |
||||
buttonAction={() => navigation.push("Products")} |
||||
/> |
||||
)} |
||||
</SafeAreaView> |
||||
); |
||||
} |
||||
|
||||
const mapStateToProps = (state) => ({ |
||||
arList: state.userProduct.arList, |
||||
mobile: state.publicApi.mobile, |
||||
theme: state.publicApi.theme |
||||
}); |
||||
|
||||
const mapDispatchToProps = { |
||||
getArList: userProduct.arList, |
||||
}; |
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(AR); |
After Width: | Height: | Size: 16 KiB |
@ -0,0 +1,618 @@ |
||||
import { |
||||
View, |
||||
Text, |
||||
SafeAreaView, |
||||
ScrollView, |
||||
StyleSheet, |
||||
StatusBar, |
||||
Platform, |
||||
Dimensions, |
||||
Appearance, |
||||
KeyboardAvoidingView, |
||||
TextInput, |
||||
TouchableWithoutFeedback, |
||||
} from "react-native"; |
||||
import React, { useEffect, useState } from "react"; |
||||
import { connect } from "react-redux"; |
||||
import { publicApi, user, userAddress } from "../../redux/actions"; |
||||
import onInput from "../../utils/onInput"; |
||||
import { useNavigation } from "@react-navigation/native"; |
||||
import { asyncAwesomeAlert } from "../../utils/AsyncWrappers"; |
||||
|
||||
//components
|
||||
import Navbar from "../../components/Navbar"; |
||||
import CustomPressable from "../../components/Pressable"; |
||||
import CustomTextInput from "../../components/CustomTextInput"; |
||||
import Select from "../../components/Select"; |
||||
import MapSelector from "../../components/MapSelector"; |
||||
|
||||
//style
|
||||
import tw from "tailwind-rn"; |
||||
import Colors from "../../constants/Colors"; |
||||
import fontSize from "../../constants/fontSize"; |
||||
|
||||
//variables
|
||||
const ios = Platform.OS === "ios"; |
||||
const { height } = Dimensions.get("window"); |
||||
|
||||
const Address = ({ |
||||
user, |
||||
route, |
||||
city, |
||||
province, |
||||
getCity, |
||||
getProvince, |
||||
provinces, |
||||
cities, |
||||
createAddress, |
||||
profileFields, |
||||
setProfileFields, |
||||
setProfile, |
||||
loading, |
||||
setPhase, |
||||
cityLoading, |
||||
mobile, |
||||
theme, |
||||
}) => { |
||||
const [addressFields, setAddressFields] = useState({}); |
||||
const [mapAddress, setMapAddress] = useState(null); |
||||
const colorScheme = Appearance.getColorScheme(); |
||||
const navigation = useNavigation(); |
||||
|
||||
const profilePage = React.useMemo(() => { |
||||
return route.params?.type === "profile"; |
||||
}); |
||||
|
||||
useEffect(() => { |
||||
getProvince(); |
||||
setProfileFields({ |
||||
file: user?.picFileId, |
||||
picFileId: user?.picFileId, |
||||
docFileIds: user?.docFileIds, |
||||
cellphone: user?.cellphone, |
||||
firstName: user?.firstName, |
||||
lastName: user?.lastName, |
||||
password: user?.password, |
||||
username: user?.username, |
||||
address: user?.address, |
||||
email: user?.email, |
||||
birthDate: user?.birthDate, |
||||
gender: user?.gender, |
||||
status: user?.status, |
||||
nationalId: user?.nationalId, |
||||
phone: user?.phone, |
||||
schools: user?.schools, |
||||
zoneId: user?.zoneId, |
||||
schoolId: user?.schoolId, |
||||
postalCode: user?.postalCode, |
||||
gradeIds: user?.gradeIds, |
||||
provinceId: user?.provinceId, |
||||
cityId: user?.cityId, |
||||
}); |
||||
}, []); |
||||
|
||||
useEffect(() => { |
||||
StatusBar.setBarStyle( |
||||
`${theme === "light" ? "dark" : "light"}-content`, |
||||
true |
||||
); |
||||
}, [theme]); |
||||
|
||||
useEffect(() => { |
||||
if (addressFields?.provinceId) { |
||||
getCity({ |
||||
provinceId: provinces.filter( |
||||
(province) => province.name === addressFields?.provinceId |
||||
)[0].id, |
||||
}); |
||||
} |
||||
}, [addressFields]); |
||||
|
||||
const onChange = (name, value) => { |
||||
setAddressFields({ ...addressFields, [name]: value }); |
||||
}; |
||||
|
||||
const submit = () => { |
||||
const { |
||||
firstName, |
||||
lastName, |
||||
cellphone, |
||||
phone, |
||||
address, |
||||
provinceId, |
||||
cityId, |
||||
postalCode, |
||||
} = addressFields; |
||||
|
||||
if (!firstName) { |
||||
return asyncAwesomeAlert("خطا", "نام خود را وارد کنید.", { |
||||
showCancelButton: false, |
||||
confirmText: "باشه", |
||||
}); |
||||
} |
||||
if (!lastName) { |
||||
return asyncAwesomeAlert("خطا", "نام خانوادگی خود را وارد کنید", { |
||||
showCancelButton: false, |
||||
confirmText: "باشه", |
||||
}); |
||||
} |
||||
if (!cellphone) { |
||||
return asyncAwesomeAlert("خطا", "شماره موبایل خود را وارد کنید.", { |
||||
showCancelButton: false, |
||||
confirmText: "باشه", |
||||
}); |
||||
} else { |
||||
if (cellphone.slice(0, 2) !== "09") { |
||||
return asyncAwesomeAlert( |
||||
"خطا", |
||||
"فرمت شماره موبایل وارد شده اشتباه است.", |
||||
{ |
||||
showCancellphoneButton: false, |
||||
confirmText: "باشه", |
||||
} |
||||
); |
||||
} |
||||
if (cellphone.length !== 11) { |
||||
return asyncAwesomeAlert( |
||||
"خطا", |
||||
"شماره موبایل میبایست یازده رقم باشد.", |
||||
{ |
||||
showCancelButton: false, |
||||
confirmText: "باشه", |
||||
} |
||||
); |
||||
} |
||||
} |
||||
|
||||
if (!phone) { |
||||
return asyncAwesomeAlert("خطا", "شماره تلفن خود را وارد کنید.", { |
||||
showCancelButton: false, |
||||
confirmText: "باشه", |
||||
}); |
||||
} else { |
||||
if (phone.slice(0, 1) !== "0") { |
||||
return asyncAwesomeAlert( |
||||
"خطا", |
||||
"فرمت شماره تلفن وارد شده اشتباه است.", |
||||
{ |
||||
showCancelButton: false, |
||||
confirmText: "باشه", |
||||
} |
||||
); |
||||
} |
||||
if (phone.length !== 11) { |
||||
return asyncAwesomeAlert("خطا", "شماره تلفن میبایست یازده رقم باشد.", { |
||||
showCancelButton: false, |
||||
confirmText: "باشه", |
||||
}); |
||||
} |
||||
} |
||||
|
||||
if (!provinceId) { |
||||
return asyncAwesomeAlert("خطا", "نام استان خود را وارد کنید.", { |
||||
showCancelButton: false, |
||||
confirmText: "باشه", |
||||
}); |
||||
} |
||||
if (!cityId) { |
||||
return asyncAwesomeAlert("خطا", "نام شهرستان خود را وارد کنید.", { |
||||
showCancelButton: false, |
||||
confirmText: "باشه", |
||||
}); |
||||
} |
||||
if (!postalCode) { |
||||
return asyncAwesomeAlert("خطا", "کد پستی خود را وارد کنید.", { |
||||
showCancelButton: false, |
||||
confirmText: "باشه", |
||||
}); |
||||
} else { |
||||
if (postalCode.length !== 10) { |
||||
return asyncAwesomeAlert("خطا", "کد ملی میبایست ده رقم باشد.", { |
||||
showCancelButton: false, |
||||
confirmText: "باشه", |
||||
}); |
||||
} |
||||
} |
||||
|
||||
if (!mapAddress) { |
||||
return asyncAwesomeAlert("خطا", "آدرس خود را از روی نقشه انتخاب کن", { |
||||
showCancelButton: false, |
||||
confirmText: "باشه", |
||||
}); |
||||
} |
||||
|
||||
createAddress({ |
||||
firstName, |
||||
lastName, |
||||
cellphone, |
||||
phone, |
||||
address: mapAddress, |
||||
provinceId: provinces.filter( |
||||
(province) => province.name === provinceId |
||||
)[0].id, |
||||
cityId: cities.filter((city) => city.name === cityId)[0]?.id, |
||||
postalCode, |
||||
location: null, |
||||
}); |
||||
|
||||
navigation.goBack(); |
||||
}; |
||||
|
||||
const submitProfile = () => { |
||||
const { |
||||
firstName, |
||||
lastName, |
||||
username, |
||||
password, |
||||
postalCode, |
||||
address, |
||||
email, |
||||
phone, |
||||
picFileId, |
||||
gender, |
||||
nationalId, |
||||
birthDate, |
||||
schools, |
||||
gradeIds, |
||||
status, |
||||
provinceId, |
||||
cityId, |
||||
docFileIds, |
||||
} = profileFields; |
||||
|
||||
if (phone) { |
||||
if (phone.slice(0, 1) !== "0") { |
||||
return asyncAwesomeAlert( |
||||
"خطا", |
||||
"فرمت شماره تلفن وارد شده اشتباه است.", |
||||
{ |
||||
showCancelButton: false, |
||||
confirmText: "باشه", |
||||
} |
||||
); |
||||
} |
||||
if (phone.length !== 11) { |
||||
return asyncAwesomeAlert("خطا", "شماره تلفن میبایست یازده رقم باشد.", { |
||||
showCancelButton: false, |
||||
confirmText: "باشه", |
||||
}); |
||||
} |
||||
} |
||||
|
||||
const data = { |
||||
firstName: firstName, |
||||
lastName: lastName, |
||||
username: username, |
||||
cellphone: user.cellphone, |
||||
password: password, |
||||
postalCode: postalCode, |
||||
address: address, |
||||
email: email, |
||||
phone: phone, |
||||
nationalId: nationalId, |
||||
picFileId: picFileId, |
||||
gender: gender, |
||||
birthDate: birthDate, |
||||
schools: schools, |
||||
gradeIds: gradeIds, |
||||
status: status, |
||||
provinceId: provinceId, |
||||
cityId: cityId, |
||||
docFileIds: docFileIds, |
||||
}; |
||||
setProfile(data); |
||||
navigation.goBack(); |
||||
}; |
||||
|
||||
const Header = ({ title, text }) => { |
||||
return ( |
||||
<View style={tw(`flex ${mobile ? "mt-2" : "mt-8"}`)}> |
||||
<Text |
||||
style={{ |
||||
fontFamily: "bold", |
||||
fontSize: mobile ? fontSize.lg : fontSize.xl2, |
||||
color: |
||||
theme === "light" ? Colors.theme1.gray20 : Colors.theme1.white, |
||||
textAlign: ios ? "right" : "auto", |
||||
}} |
||||
> |
||||
{title} |
||||
</Text> |
||||
<Text |
||||
style={{ |
||||
fontFamily: "regular", |
||||
fontSize: mobile ? fontSize.sm : fontSize.base, |
||||
color: |
||||
theme === "light" |
||||
? Colors.theme1.gray20 + "aa" |
||||
: Colors.theme1.white + "aa", |
||||
textAlign: ios ? "right" : "auto", |
||||
}} |
||||
> |
||||
{text} |
||||
</Text> |
||||
</View> |
||||
); |
||||
}; |
||||
|
||||
console.log(mapAddress); |
||||
|
||||
return ( |
||||
<SafeAreaView |
||||
style={{ |
||||
paddingTop: Platform.OS === "android" ? StatusBar.currentHeight : 0, |
||||
// position: "relative",
|
||||
flex: 1, |
||||
}} |
||||
> |
||||
<Navbar |
||||
headerOptions={{ |
||||
logo: false, |
||||
menu: profilePage ? false : false, |
||||
hamburgerMenu: false, |
||||
title: profilePage ? "اطلاعات کاربری" : "", |
||||
bookmark: profilePage ? false : false, |
||||
qr: false, |
||||
back: true, |
||||
}} |
||||
/> |
||||
<ScrollView style={tw("flex-1 px-4")}> |
||||
<KeyboardAvoidingView> |
||||
<TouchableWithoutFeedback> |
||||
<View style={tw("flex-1")}> |
||||
<Header |
||||
title="اطلاعات هویتی" |
||||
text="( لطفا نام و نام خانوادگی خود را به طور کامل وارد نمایید )" |
||||
/> |
||||
<CustomTextInput |
||||
label={profilePage ? "نام" : "نام تحویل گیرنده"} |
||||
placeholder="" |
||||
textAlign="right" |
||||
name="firstName" |
||||
maxlength="40" |
||||
value={ |
||||
profilePage |
||||
? profileFields.firstName |
||||
: addressFields?.firstName |
||||
} |
||||
onChange={(name, value) => |
||||
profilePage |
||||
? setProfileFields({ ...profileFields, firstName: value }) |
||||
: onChange(name, value) |
||||
} |
||||
autoFocus={false} |
||||
regex={(val) => val} |
||||
/> |
||||
<CustomTextInput |
||||
label={ |
||||
profilePage ? "نام خانوادگی" : "نام خانوادگی تحویل گیرنده" |
||||
} |
||||
placeholder="" |
||||
textAlign="right" |
||||
name="lastName" |
||||
maxlength="60" |
||||
value={ |
||||
profilePage ? profileFields.lastName : addressFields?.lastName |
||||
} |
||||
onChange={(name, value) => |
||||
profilePage |
||||
? setProfileFields({ ...profileFields, lastName: value }) |
||||
: onChange(name, value) |
||||
} |
||||
autoFocus={false} |
||||
regex={(val) => val} |
||||
/> |
||||
{profilePage ? ( |
||||
<CustomTextInput |
||||
keyboardType="numeric" |
||||
label="کد ملی" |
||||
placeholder="" |
||||
textAlign="left" |
||||
name="nationalId" |
||||
maxLength={10} |
||||
value={profileFields.nationalId} |
||||
onChange={(name, value) => |
||||
setProfileFields({ ...profileFields, nationalId: value }) |
||||
} |
||||
autoFocus={false} |
||||
regex={(text) => onInput.numberOnly(text)} |
||||
/> |
||||
) : null} |
||||
<View style={tw("mt-4")}></View> |
||||
<Header |
||||
title="شماره تماس" |
||||
text="( شماره موبایل و شماره تلفن ثابت خود را
|
||||
به همراه پیش شماره وارد کنید )" |
||||
/> |
||||
<CustomTextInput |
||||
keyboardType="numeric" |
||||
label={ |
||||
profilePage ? "شماره موبایل" : "شماره موبایل تحویل گیرنده" |
||||
} |
||||
placeholder="" |
||||
textAlign="left" |
||||
name="cellphone" |
||||
maxLength={11} |
||||
value={ |
||||
profilePage |
||||
? profileFields.cellphone |
||||
: addressFields?.cellphone |
||||
} |
||||
onChange={(name, value) => |
||||
profilePage |
||||
? setProfileFields({ ...profileFields, cellphone: value }) |
||||
: onChange(name, value) |
||||
} |
||||
autoFocus={false} |
||||
regex={(text) => onInput.numberOnly(text)} |
||||
/> |
||||
<CustomTextInput |
||||
keyboardType="numeric" |
||||
label={profilePage ? "شماره تلفن" : "شماره تلفن تحویل گیرنده"} |
||||
placeholder="" |
||||
textAlign="left" |
||||
name="phone" |
||||
maxLength={11} |
||||
value={profilePage ? profileFields.phone : addressFields?.phone} |
||||
onChange={(name, value) => |
||||
profilePage |
||||
? setProfileFields({ ...profileFields, phone: value }) |
||||
: onChange(name, value) |
||||
} |
||||
autoFocus={false} |
||||
regex={(text) => onInput.numberOnly(text)} |
||||
/> |
||||
<View style={tw("mt-4")}></View> |
||||
<Header |
||||
title="آدرس" |
||||
text="( لطفا نام استان و شهرستان و آدرس |
||||
خود را با دقت تکمیل نمایید )" |
||||
/> |
||||
<View style={tw("w-full mt-4")}> |
||||
<Select |
||||
defaultValue={ |
||||
profilePage |
||||
? provinces?.filter( |
||||
(province) => province.id === profileFields.provinceId |
||||
)[0]?.name || province[0] |
||||
: province[0] |
||||
} |
||||
onChange={(name, value) => |
||||
value === "استان" ? {} : onChange(name, value) |
||||
} |
||||
options={province} |
||||
width={"100%"} |
||||
name="provinceId" |
||||
/> |
||||
</View> |
||||
<View style={tw("w-full mt-4")}> |
||||
<Select |
||||
defaultValue={ |
||||
profilePage |
||||
? cities?.filter( |
||||
(city) => city.id === profileFields.cityId |
||||
)[0]?.name || city[0] |
||||
: city[0] |
||||
} |
||||
onChange={(name, value) => |
||||
value === "شهرستان" ? {} : onChange(name, value) |
||||
} |
||||
options={city} |
||||
width={"100%"} |
||||
name="cityId" |
||||
/> |
||||
</View> |
||||
{!profilePage ? ( |
||||
<TextInput |
||||
style={[ |
||||
tw("w-full mt-4 py-4 px-2 rounded-md h-40"), |
||||
{ |
||||
backgroundColor: |
||||
theme === "light" ? Colors.theme1.grayF9 : null, |
||||
color: |
||||
theme === "light" |
||||
? Colors.theme1.gray20 |
||||
: Colors.theme1.white, |
||||
fontSize: fontSize.tiny, |
||||
textAlign: "right", |
||||
fontFamily: "light", |
||||
borderWidth: 1, |
||||
|
||||
borderColor: |
||||
theme === "light" |
||||
? Colors.theme1.grayE3 |
||||
: Colors.theme1.white + "55", |
||||
}, |
||||
]} |
||||
value={mapAddress} |
||||
multiline={true} |
||||
textAlignVertical="top" |
||||
placeholder="آدرس مورد نظر ..." |
||||
onChangeText={(text) => setMapAddress(text)} |
||||
placeholderTextColor={ |
||||
theme === "light" |
||||
? Colors.theme1.gray2077 |
||||
: Colors.theme1.white + "aa" |
||||
} |
||||
/> |
||||
) : null} |
||||
<View style={tw("mb-4")}> |
||||
<CustomTextInput |
||||
keyboardType="numeric" |
||||
label="کد پستی" |
||||
placeholder="" |
||||
textAlign="left" |
||||
name="postalCode" |
||||
maxLength={10} |
||||
value={ |
||||
profilePage |
||||
? profileFields.postalCode |
||||
: addressFields?.postalCode |
||||
} |
||||
onChange={(name, value) => |
||||
profilePage |
||||
? setProfileFields({ |
||||
...profileFields, |
||||
postalCode: value, |
||||
}) |
||||
: onChange(name, value) |
||||
} |
||||
autoFocus={false} |
||||
regex={(text) => onInput.numberOnly(text)} |
||||
/> |
||||
</View> |
||||
|
||||
<CustomPressable |
||||
title={ |
||||
profilePage |
||||
? "ذخیره اطلاعات و بازگشت به صفحه قبل" |
||||
: "ثبت آدرس" |
||||
} |
||||
backgroundColor={Colors.theme1.greenCF} |
||||
color={"white"} |
||||
border={{ color: "#196EC0", width: 0 }} |
||||
width={"100%"} |
||||
onPress={() => (profilePage ? submitProfile() : submit())} |
||||
/> |
||||
</View> |
||||
</TouchableWithoutFeedback> |
||||
</KeyboardAvoidingView> |
||||
</ScrollView> |
||||
</SafeAreaView> |
||||
); |
||||
}; |
||||
|
||||
const styles = StyleSheet.create({ |
||||
contentContainerStyle: { |
||||
paddingBottom: 0, |
||||
}, |
||||
container: { |
||||
flexDirection: "column", |
||||
paddingVertical: 5, |
||||
paddingHorizontal: 16, |
||||
flex: 1, |
||||
}, |
||||
}); |
||||
|
||||
const mapStateToProps = (state) => ({ |
||||
provinces: state.publicApi.provinces, |
||||
province: state.publicApi.province, |
||||
cities: state.publicApi.cities, |
||||
city: state.publicApi.city, |
||||
loading: state.userAddress.loading, |
||||
cityLoading: state.publicApi.loading, |
||||
user: state.user.status, |
||||
profileFields: state.user.profileFields, |
||||
mobile: state.publicApi.mobile, |
||||
theme: state.publicApi.theme, |
||||
}); |
||||
|
||||
const mapDispatchToProps = { |
||||
getProvince: publicApi.getProvince, |
||||
getCity: publicApi.getCity, |
||||
createAddress: userAddress.add, |
||||
setProfileFields: user.setProfileFields, |
||||
setProfile: user.setProfile, |
||||
}; |
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(Address); |
@ -0,0 +1,323 @@ |
||||
import React, { useEffect } from "react"; |
||||
import { |
||||
View, |
||||
Text, |
||||
FlatList, |
||||
Image, |
||||
SafeAreaView, |
||||
ScrollView, |
||||
StyleSheet, |
||||
Platform, |
||||
Dimensions, |
||||
StatusBar, |
||||
} from "react-native"; |
||||
import { connect } from "react-redux"; |
||||
import { blog, publicApi } from "../../redux/actions"; |
||||
import { LinearGradient } from "expo-linear-gradient"; |
||||
import HTMLView from "react-native-htmlview"; |
||||
import moment from "jalali-moment"; |
||||
|
||||
//components
|
||||
import Header from "../Blogs/layouts/Header"; |
||||
import New from "../Blogs/layouts/New"; |
||||
import Navbar from "../../components/Navbar"; |
||||
|
||||
//assets
|
||||
import tw from "tailwind-rn"; |
||||
import fontSize from "../../constants/fontSize"; |
||||
import Colors from "../../constants/Colors"; |
||||
|
||||
//variables
|
||||
const ios = Platform.OS === "ios"; |
||||
const { width } = Dimensions.get("window"); |
||||
|
||||
//func
|
||||
const renderNode = (node, index, siblings, parent, defaultRenderer) => { |
||||
if (node.name == "img") { |
||||
const a = node.attribs; |
||||
return ( |
||||
<Image |
||||
style={{ width: 300, height: 300 }} |
||||
source={{ uri: node.attribs.src }} |
||||
/> |
||||
); |
||||
} |
||||
}; |
||||
|
||||
export const Blog = ({ getInfo, blog, getList, blogs, route, theme }) => { |
||||
useEffect(() => { |
||||
getInfo({ id: route.params.id }); |
||||
if (blogs.length === 0) { |
||||
getList(); |
||||
} |
||||
}, []); |
||||
|
||||
useEffect(() => { |
||||
StatusBar.setBarStyle( |
||||
`${theme === "light" ? "dark" : "light"}-content`, |
||||
true |
||||
); |
||||
}, [theme]); |
||||
|
||||
console.log(blog); |
||||
|
||||
return ( |
||||
<SafeAreaView |
||||
style={{ |
||||
paddingTop: Platform.OS === "android" ? StatusBar.currentHeight : 0, |
||||
position: "relative", |
||||
}} |
||||
> |
||||
<Navbar |
||||
headerOptions={{ |
||||
logo: false, |
||||
menu: false, |
||||
hamburgerMenu: false, |
||||
title: "", |
||||
bookmark: true, |
||||
qr: false, |
||||
back: true, |
||||
bookmarkItem: { contentId: blog?.id }, |
||||
}} |
||||
/> |
||||
<ScrollView |
||||
contentContainerStyle={styles.contentContainerStyle} |
||||
style={[styles.container, tw("flex")]} |
||||
> |
||||
<View style={tw("flex px-4 pb-24")}> |
||||
<View |
||||
style={[ |
||||
tw("w-full rounded-sm overflow-hidden relative"), |
||||
{ height: ((width - 32) / 4) * 2.8 }, |
||||
]} |
||||
> |
||||
<Image |
||||
source={{ uri: `https:dnvn.ir/api/v1/file/${blog?.fileIds}` }} |
||||
resizeMode="contain" |
||||
style={tw("w-full h-full absolute left-0 top-0")} |
||||
/> |
||||
<LinearGradient |
||||
colors={["transparent", "rgba(0,0,0,0.9)"]} |
||||
start={{ x: 0.0, y: 0.0 }} |
||||
end={{ x: 0.0, y: 1.1 }} |
||||
style={tw( |
||||
"flex justify-end absolute top-0 left-0 z-10 w-full h-full pb-2 px-0" |
||||
)} |
||||
> |
||||
<View |
||||
style={tw( |
||||
"flex justify-end absolute top-0 left-0 z-10 w-full h-full pb-0 px-2" |
||||
)} |
||||
> |
||||
<View |
||||
style={tw( |
||||
"w-full flex flex-row-reverse items-center justify-between" |
||||
)} |
||||
> |
||||
<View style={tw("flex")}> |
||||
<View style={tw("flex py-2 justify-center")}> |
||||
<Text |
||||
style={{ |
||||
fontFamily: "regular", |
||||
color: Colors.theme1.white, |
||||
fontSize: fontSize.tiny, |
||||
textAlign: ios ? "right" : "auto", |
||||
}} |
||||
> |
||||
{/* {"نوشته از:" + " " + "کامران ایزدی"} */} |
||||
</Text> |
||||
<Text |
||||
style={{ |
||||
fontFamily: "regular", |
||||
color: Colors.theme1.white, |
||||
fontSize: fontSize.tiny, |
||||
textAlign: ios ? "right" : "auto", |
||||
}} |
||||
> |
||||
{"سردبیر بخش وبلاگ دانوین"} |
||||
</Text> |
||||
</View> |
||||
</View> |
||||
<View style="flex justify-center items-end"> |
||||
{ |
||||
blog.duration ? <Text |
||||
style={{ |
||||
fontFamily: "regular", |
||||
color: Colors.theme1.white, |
||||
fontSize: fontSize.sm, |
||||
textAlign: ios ? "left" : "left", |
||||
}} |
||||
> |
||||
{"زمان مطالعه" + " " + blog.duration + " دقیقه"} |
||||
</Text> : null |
||||
} |
||||
|
||||
<Text |
||||
style={{ |
||||
fontFamily: "regular", |
||||
color: Colors.theme1.white, |
||||
fontSize: fontSize.sm, |
||||
textAlign: ios ? "left" : "left", |
||||
}} |
||||
> |
||||
{ |
||||
moment(blog.createdAt).format('jYYYY/jMM/jDD') |
||||
} |
||||
</Text> |
||||
</View> |
||||
</View> |
||||
</View> |
||||
</LinearGradient> |
||||
</View> |
||||
<View |
||||
style={[tw("flex my-5"), { textAlign: "right", marginBottom: 50 }]} |
||||
> |
||||
<Text |
||||
style={{ |
||||
fontFamily: "bold", |
||||
fontSize: fontSize.base, |
||||
textAlign: ios ? "right" : "auto", |
||||
marginBottom: 60, |
||||
color: |
||||
theme === "light" |
||||
? Colors.theme1.gray20 |
||||
: Colors.theme1.grayF9, |
||||
}} |
||||
> |
||||
{blog?.title} |
||||
</Text> |
||||
<View |
||||
style={{ |
||||
flex: 1, |
||||
justifyContent: "center", |
||||
alignItems: "center", |
||||
}} |
||||
> |
||||
<HTMLView |
||||
value={blog?.text} |
||||
renderNode={renderNode} |
||||
stylesheet={{ |
||||
h1 : { |
||||
color: |
||||
theme === "light" |
||||
? Colors.theme1.gray20 |
||||
: Colors.theme1.grayF9, |
||||
textAlign: "right", |
||||
fontFamily: "bold", |
||||
lineHeight: 25, |
||||
fontSize: fontSize.xl4, |
||||
marginVertical: -15, |
||||
paddingTop: 5, |
||||
}, |
||||
h2 : { |
||||
color: |
||||
theme === "light" |
||||
? Colors.theme1.gray20 |
||||
: Colors.theme1.grayF9, |
||||
textAlign: "right", |
||||
fontFamily: "bold", |
||||
lineHeight: 25, |
||||
fontSize: fontSize.xl, |
||||
marginVertical: -10, |
||||
}, |
||||
h3 : { |
||||
color: |
||||
theme === "light" |
||||
? Colors.theme1.gray20 |
||||
: Colors.theme1.grayF9, |
||||
textAlign: "right", |
||||
fontFamily: "bold", |
||||
lineHeight: 25, |
||||
fontSize: fontSize.lg, |
||||
marginVertical: -10, |
||||
}, |
||||
p: { |
||||
color: |
||||
theme === "light" |
||||
? Colors.theme1.gray20 |
||||
: Colors.theme1.grayF9, |
||||
textAlign: "right", |
||||
fontFamily: "light", |
||||
lineHeight: 25, |
||||
marginVertical: -20, |
||||
}, |
||||
strong: { |
||||
color: |
||||
theme === "light" |
||||
? Colors.theme1.gray20 |
||||
: Colors.theme1.grayF9, |
||||
textAlign: "right", |
||||
fontFamily: "bold", |
||||
lineHeight: 25, |
||||
}, |
||||
ul: { |
||||
textAlign: "right", |
||||
marginVertical: -35, |
||||
}, |
||||
li: { |
||||
color: |
||||
theme === "light" |
||||
? Colors.theme1.gray20 |
||||
: Colors.theme1.grayF9, |
||||
textAlign: "right", |
||||
fontFamily: "light", |
||||
lineHeight: 25, |
||||
}, |
||||
span : { |
||||
color : 'red' |
||||
} |
||||
}} |
||||
/> |
||||
</View> |
||||
</View> |
||||
<Header title={"پیشنهادی "} /> |
||||
{blogs.length ? ( |
||||
<FlatList |
||||
showsHorizontalScrollIndicator={false} |
||||
horizontal={true} |
||||
inverted={true} |
||||
style={[tw("flex flex-row mt-3 pb-3")]} |
||||
data={blogs.filter((blog) => blog.id !== route.params.id)} |
||||
renderItem={({ item }) => <New blog={item} />} |
||||
keyExtractor={(item, index) => { |
||||
return item.id; |
||||
}} |
||||
/> |
||||
) : null} |
||||
</View> |
||||
</ScrollView> |
||||
</SafeAreaView> |
||||
); |
||||
}; |
||||
|
||||
const mapStateToProps = (state) => ({ |
||||
blog: state.blog.blog, |
||||
blogs: state.blog.list, |
||||
theme: state.publicApi.theme, |
||||
}); |
||||
|
||||
const mapDispatchToProps = { |
||||
getInfo: blog.info, |
||||
getList: blog.list, |
||||
setHeaderOptions: publicApi.setHeaderOptions, |
||||
}; |
||||
|
||||
const Tag = ({ tag }) => { |
||||
return; |
||||
}; |
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(Blog); |
||||
|
||||
const styles = StyleSheet.create({ |
||||
contentContainerStyle: { |
||||
paddingBottom: 40, |
||||
}, |
||||
container: { |
||||
paddingVertical: 0, |
||||
paddingHorizontal: 0, |
||||
}, |
||||
font: { |
||||
textAlign: "center", |
||||
fontFamily: "render", |
||||
}, |
||||
}); |