@ -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, View } from "react-native"; |
||||||
import { StyleSheet, Text, 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 ( |
return ( |
||||||
<View style={styles.container}> |
<View style={{ flex: 1 }} onLayout={onLayoutRootView}> |
||||||
<Text>Open up App.js to start working on your app!</Text> |
<Provider store={store}> |
||||||
<StatusBar style="auto" /> |
<PersistGate loading={null} persistor={persistor}> |
||||||
|
<Navigation /> |
||||||
|
<AlertModal /> |
||||||
|
</PersistGate> |
||||||
|
</Provider> |
||||||
</View> |
</View> |
||||||
); |
); |
||||||
} |
}; |
||||||
|
|
||||||
|
const styles = StyleSheet.create({}); |
||||||
|
|
||||||
const styles = StyleSheet.create({ |
export default App; |
||||||
container: { |
|
||||||
flex: 1, |
|
||||||
backgroundColor: '#fff', |
|
||||||
alignItems: 'center', |
|
||||||
justifyContent: 'center', |
|
||||||
}, |
|
||||||
}); |
|
||||||
|
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", |
||||||
|
}, |
||||||
|
}); |