reza added all of things

master
Reza_ashrafi 3 years ago
parent 3c7c2a0df0
commit 8139d8c6a7
  1. 60
      navigation/index.js
  2. 1
      package.json
  3. BIN
      src/assets/sound.mp3
  4. BIN
      src/assets/video.mp4
  5. 3
      src/components/MusicPlayer.js
  6. 2
      src/components/Pressable.js
  7. 21
      src/constants/fontSize.js
  8. 9
      src/redux/actions/user.js
  9. 32
      src/redux/proxy.js
  10. 1
      src/redux/reducers/public.js
  11. 21
      src/redux/reducers/user.js
  12. 10
      src/redux/store.js
  13. BIN
      src/screens/Home/assets/ar.png
  14. BIN
      src/screens/Home/assets/arrow.png
  15. BIN
      src/screens/Home/assets/bookFeatureIcon.png
  16. BIN
      src/screens/Home/assets/food.png
  17. BIN
      src/screens/Home/assets/olum1.png
  18. BIN
      src/screens/Home/assets/packageFeatureIcon.png
  19. BIN
      src/screens/Home/assets/qr.png
  20. BIN
      src/screens/Home/assets/responsive-bg.png
  21. BIN
      src/screens/Home/assets/shoe.png
  22. BIN
      src/screens/Home/assets/testFeatureIcon.png
  23. BIN
      src/screens/Home/assets/videoFeatureIcon.png
  24. 71
      src/screens/Home/components/Blogs.js
  25. 10
      src/screens/Home/components/Header.js
  26. 30
      src/screens/Home/components/MyBooks.js
  27. 67
      src/screens/Home/components/Scroll.js
  28. 87
      src/screens/Home/components/Videos.js
  29. 40
      src/screens/Home/index.js
  30. 20
      src/screens/Login/index.js
  31. 86
      src/screens/Product/components/Book.js
  32. 10
      src/screens/Product/components/Comments.js
  33. 5
      src/screens/Product/components/Description.js
  34. 3
      src/screens/Product/components/LinkBox.js
  35. 9
      src/screens/Product/components/Rates.js
  36. 73
      src/screens/Product/index.js
  37. 35
      src/screens/Products/components/Book.js
  38. 9
      src/screens/Products/components/Video.js
  39. 58
      src/screens/Products/index.js
  40. 4
      src/screens/QR/Content/Voice.js
  41. 2
      src/screens/QR/Scan/index.js
  42. 2
      src/screens/QR/index.js
  43. 24
      src/screens/ShoppingCart/components/Code.js
  44. 63
      src/screens/ShoppingCart/components/Product.js
  45. 46
      src/screens/ShoppingCart/index.js
  46. 14
      src/screens/Splash/index.js
  47. 69
      src/screens/Video/components/Season.js
  48. 77
      src/screens/Video/index.js
  49. 58
      src/screens/VideoDisplay/components/Season/index.js
  50. 75
      src/screens/VideoDisplay/index.js
  51. 44
      src/screens/Videos/components/MostViewedVideo.js
  52. 30
      src/screens/Videos/components/NewestVideo.js
  53. 14
      src/screens/Videos/components/VerticalGradeFilter.js
  54. 32
      src/screens/Videos/index.js
  55. 12
      src/utils/fontSizeResponsive.js
  56. 7
      yarn.lock

@ -1,4 +1,4 @@
import React from "react";
import React, { useEffect } from "react";
import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
@ -27,6 +27,7 @@ import Exams from "../src/screens/Exams";
import ShoppingCart from "../src/screens/ShoppingCart";
import Video from "../src/screens/Video";
import VideoDisplay from "../src/screens/VideoDisplay";
import { user } from "../src/redux/actions";
const width = Dimensions.get("window").width;
@ -41,6 +42,7 @@ const BottomTabNavigator = () => {
tabBarInactiveTintColor: "grey",
tabBarStyle: {
backgroundColor: "#CCE6FF",
zIndex: 10,
},
tabBarLabelStyle: {
fontSize: width / 39,
@ -50,15 +52,6 @@ const BottomTabNavigator = () => {
// tabBarLabel : 'reza'
}}
>
{/* <Tab.Screen
name="SplashTab"
component={AuthStackScreen}
options={{
tabBarIcon: ({ focused, color }) => (
<FontAwesome name="user" size={focused ? 27 : 23} color={color} />
),
}}
/> */}
<Tab.Screen
name="ShoppingCartTab"
component={ShoppingCart}
@ -119,11 +112,7 @@ const HomeStackScreen = () => {
initialRouteName="Home"
>
<HomeStack.Screen name="Home" component={Home} />
<HomeStack.Screen name="QR" component={QR} />
<HomeStack.Screen name="Product" component={Product} />
<Stack.Screen name="Orders" component={OrderStackScreen} />
<Stack.Screen name="Faq" component={Faq} />
<Stack.Screen name="Activation" component={Activation} />
</HomeStack.Navigator>
);
};
@ -133,11 +122,7 @@ const ProductsStackScreen = () => {
return (
<ProductsStack.Navigator screenOptions={{ headerShown: false }}>
<ProductsStack.Screen name="Products" component={Products} />
<ProductsStack.Screen name="QR" component={QR} />
<ProductsStack.Screen name="Product" component={Product} />
<ProductsStack.Screen name="Orders" component={OrderStackScreen} />
<ProductsStack.Screen name="Faq" component={Faq} />
<ProductsStack.Screen name="Activation" component={Activation} />
</ProductsStack.Navigator>
);
};
@ -149,10 +134,6 @@ const VODStackScreen = () => {
<VODStack.Screen name="VOD" component={Videos} />
<VODStack.Screen name="Video" component={Video} />
<VODStack.Screen name="VideoDisplay" component={VideoDisplay} />
<VODStack.Screen name="QR" component={QR} />
<VODStack.Screen name="Orders" component={OrderStackScreen} />
<VODStack.Screen name="Faq" component={Faq} />
<VODStack.Screen name="Activation" component={Activation} />
</VODStack.Navigator>
);
};
@ -171,21 +152,12 @@ const AuthStackScreen = () => {
);
};
const OrderStack = createNativeStackNavigator();
const OrderStackScreen = () => {
return (
<OrderStack.Navigator
screenOptions={{ headerShown: false }}
initialRouteName="Orders"
>
<OrderStack.Screen name="Orders" component={OrdersFollowUp} />
<OrderStack.Screen name="Order" component={OrderDetails} />
</OrderStack.Navigator>
);
};
const Stack = createNativeStackNavigator();
const Navigation = ({}) => {
const Navigation = ({ getStatus, isLogin }) => {
useEffect(() => {
getStatus();
}, []);
return (
<NavigationContainer>
<Stack.Navigator
@ -193,17 +165,23 @@ const Navigation = ({}) => {
screenOptions={{ headerShown: false }}
>
<Stack.Screen name="Splash" component={Splash} />
<Stack.Screen name="QR" component={QR} />
<Stack.Screen name="Root" component={BottomTabNavigator} />
<Stack.Screen name="Login" component={Login} />
<Stack.Screen name="Otp" component={Otp} />
<Stack.Screen name="Root" component={BottomTabNavigator} />
<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.Navigator>
</NavigationContainer>
);
};
const mapStateToProps = (state) => {
return {};
const mapStateToProps = (state) => ({
isLogin: state.user.status,
});
const mapDispatchToProps = {
getStatus: user.getStatus,
};
export default connect(mapStateToProps)(Navigation);
export default connect(mapStateToProps, mapDispatchToProps)(Navigation);

@ -25,6 +25,7 @@
"expo-camera": "~12.1.0",
"expo-device": "~4.1.0",
"expo-font": "^10.0.4",
"expo-screen-orientation": "~4.1.1",
"expo-status-bar": "~1.2.0",
"i18next": "^21.6.3",
"install": "^0.13.0",

Binary file not shown.

Binary file not shown.

@ -2,14 +2,13 @@ import React, { useState, useEffect } from "react";
import { StyleSheet, TouchableOpacity, View, Image, Text } from "react-native";
import { Ionicons } from "@expo/vector-icons";
import { Audio } from "expo-av";
import sound from '../assets/sound.mp3';
const audioBookPlaylist = [
{
title: "Hamlet - Act I",
author: "William Shakespeare",
source: "Librivox",
uri: sound,
uri: "",
imageSource:
"http://www.archive.org/download/LibrivoxCdCoverArt8/hamlet_1104.jpg",
},

@ -10,9 +10,11 @@ export default function Pressable1({
color,
border,
width,
onPress,
}) {
return (
<Pressable
onPress={() => onPress()}
style={[
tw.style('rounded-md py-3 flex flex-row justify-center mb-3'),
{

@ -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;

@ -1,13 +1,16 @@
import proxy from "../proxy";
const user = {
getStatus: () => async (dispatch) => {
await proxy.getStatus({ dispatch });
},
otp: (data) => async (dispatch) => {
console.log(data);
await proxy.post("public/sendOTP", data, { dispatch });
},
otp_login: (data) => async (dispatch) =>
await proxy.login("user/otp/login", data, { dispatch }),
otp_login: (data = {}) => async (dispatch) => {
await proxy.login("user/otp/login", data, { dispatch });
},
login: (data) => async (dispatch) =>
await proxy.login("user/login", data, { dispatch }),

@ -33,12 +33,7 @@ class Proxy {
post = (url, params, opt, data) => {
try {
this.check(
url,
opt,
() => Axios.post(url, params, opt),
data || params
);
this.check(url, opt, () => Axios.post(url, params, opt), data || params);
} catch (error) {
console.log("proxy post error! : ", error);
}
@ -46,12 +41,7 @@ class Proxy {
put = (url, params, opt, data) => {
try {
this.check(
url,
opt,
() => Axios.put(url, params, opt),
data || params
);
this.check(url, opt, () => Axios.put(url, params, opt), data || params);
} catch (error) {
console.log("proxy put error! : ", error);
}
@ -70,11 +60,11 @@ class Proxy {
}
};
check = (url, { dispatch }, fetch, params) => {
check = async (url, { dispatch }, fetch, params) => {
try {
dispatch = dispatch || (() => {});
dispatch({ type: url.split("/")[0] + "/" + "loading" });
let response = fetch();
let response = await fetch();
switch (response.status) {
case 200:
dispatch({ type: url, data: response.data.data, params });
@ -82,6 +72,7 @@ class Proxy {
case 401:
if (this.refresh()) {
let response = fetch();
console.log('check 401', response )
dispatch({ type: url, data: response.data.data, params });
return response.data.data;
}
@ -116,13 +107,14 @@ class Proxy {
};
login = (url, params, { dispatch }) => {
console.log('login called');
try {
console.log('------------------------------login---------------------------------');
this.post(url, params, {
dispatch: (obj) => {
let login = obj.data;
console.log('login data: ',login);
if (!login || !login.refreshToken) return false;
if (!login || !login.refreshToken){
return false;
}
const refresh = ["refresh", login.refreshToken];
const access = ["access", login.accessToken];
const userData = ["userData", JSON.stringify(login.profile)];
@ -163,9 +155,13 @@ class Proxy {
return userData || null;
} catch (error) {
console.log("proxy status error : ", error);
return nulll;
}
};
getStatus = async ({ dispatch }) => {
let status = await this.status();
dispatch({ type: "user/getStatus", data: {status}})
}
}
const _proxy = new Proxy();
export default _proxy;

@ -105,6 +105,7 @@ const publicApi = (state = initialState, action) => {
allCats = Array.from(
new Set(data.vods.map((item) => item.categoryId && item.categoryId))
);
allCats.sort((a , b) => a - b);
return {
...state,
loading: false,

@ -1,13 +1,8 @@
import proxy from "../proxy";
import AsyncStorage from "@react-native-async-storage/async-storage";
const checkStatus = async () => {
let status = await proxy.status();
return status;
}
let initialState = {
status: checkStatus(),
status: null,
loading: false,
error: null,
list: null,
@ -16,7 +11,7 @@ let initialState = {
profileStatus: false,
setDone: false,
setLogin: false,
check : 'check'
check: "check",
};
const user = (state = initialState, action) => {
@ -27,6 +22,8 @@ const user = (state = initialState, action) => {
// case "user/switchRole":
case "public/sendOTP":
return { ...state, loading: false, error: null };
case "user/getStatus":
return { ...state, status: data.status, error: null };
case "user/login":
case "user/otp/login":
return {
@ -38,10 +35,10 @@ const user = (state = initialState, action) => {
};
case "user/getProfile":
const myData = JSON.stringify(data);
try{
try {
AsyncStorage.setItem("userData", myData);
}catch(error){
console.log('user/getProfile', error);
} catch (error) {
console.log("user/getProfile", error);
}
return {
...state,
@ -51,7 +48,7 @@ const user = (state = initialState, action) => {
setDone: false,
};
case "user/logout":
return { ...state, loading: false, status: proxy.status(), error: null };
return { ...state, loading: false, status: null, error: null };
case "user/getUserRole":
return { ...state, loading: false, userRoles: data, error: null };
case "user/setProfile":
@ -64,6 +61,6 @@ const user = (state = initialState, action) => {
default:
return state;
}
}
};
export default user;

@ -25,10 +25,10 @@ const initialState = {};
const middleWare = [thunk];
const loggerMiddleware = createLogger({
predicate: () => process.env.NODE_ENV === "development",
});
middleWare.push(loggerMiddleware);
// const loggerMiddleware = createLogger({
// predicate: () => process.env.NODE_ENV === "development",
// });
// middleWare.push(loggerMiddleware);
const store = createStore(
persistReducer(
@ -59,6 +59,6 @@ try {
// console.log(e);
}
console.disableYellowBox = true;
// console.disableYellowBox = true;
export default store;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 780 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 242 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 800 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 956 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 853 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 591 B

@ -7,35 +7,32 @@ import {
TouchableOpacity,
FlatList,
} from "react-native";
const width = Dimensions.get("window").width;
const height = Dimensions.get("window").height;
import { connect } from "react-redux";
import Header from "../components/Header";
import fontSize from "../../../constants/fontSize";
import tw from "tailwind-rn";
import { connect } from "react-redux";
//asssets
import foodImage from "../assets/food.png";
import userImage from "../assets/user.png";
import messageIcon from "../assets/message.png";
//Color
import Color from "../../../constants/Colors";
function Blogs({ products }) {
const { width} = Dimensions.get("window");
function Blogs({ blogs }) {
return (
<View style={[tw("flex flex-col pr-3 mb-5")]}>
<View style={tw("w-full pl-3")}>
<Header title={"خواندنیها"} route={"Blogs"} />
</View>
<FlatList
showsHorizontalScrollIndicator={false}
horizontal={true}
inverted={true}
style={[tw("flex flex-row mt-3")]}
data={products}
data={blogs}
renderItem={({ item }) => <Blog blog={item} />}
keyExtractor={item => item.id}
keyExtractor={(item) => item.id}
/>
</View>
);
@ -44,10 +41,16 @@ function Blogs({ products }) {
const Blog = ({ blog }) => {
return (
<TouchableOpacity
style={[tw("rounded-md ml-3 rounded-md relative")]}
style={[
tw("rounded-md ml-3 rounded-md relative"),
{ width: width / 1.5},
]}
// onPress={() => navigation.navigate('Product')}
>
<Image source={foodImage} style={{ width: 227, height: 133 }} />
<Image
source={{ uri: `https://dnvn.ir/api/v1/file/${blog.fileIds}` }}
style={[tw("rounded-md"), {width : '100%', height : width / 1.5 * 9 / 16}]}
/>
<View
style={[
{ transform: [{ translateY: -20 }], marginHorizontal: 10 },
@ -60,11 +63,11 @@ const Blog = ({ blog }) => {
{
color: Color.theme1.light.blue7,
fontFamily: "bold",
fontSize: width / 36,
fontSize: fontSize.sm,
},
]}
>
آیا مواد غذای پر فیبر مفید هستند؟
{blog.title}
</Text>
<View style={tw("flex flex-row-reverse justify-between")}>
<View style={tw("flex-row-reverse items-center")}>
@ -77,7 +80,7 @@ const Blog = ({ blog }) => {
{
color: Color.theme1.light.blue5,
fontFamily: "light",
fontSize: width / 40,
fontSize: fontSize.xs,
},
]}
>
@ -90,7 +93,7 @@ const Blog = ({ blog }) => {
{
color: Color.theme1.light.blue5,
fontFamily: "light",
fontSize: width / 40,
fontSize: fontSize.xs,
},
]}
>
@ -112,39 +115,3 @@ const mapStateToProps = (state) => ({
});
export default connect(mapStateToProps, {})(Blogs);
Blogs.defaultProps = {
products: [
{
imageUrl: foodImage,
id: 0,
},
{
imageUrl: foodImage,
id: 1,
},
{
imageUrl: foodImage,
id: 2,
},
{
imageUrl: foodImage,
id: 3,
},
{
imageUrl: foodImage,
id: 4,
},
{
imageUrl: foodImage,
id: 5,
},
{
imageUrl: foodImage,
id: 6,
},
{
imageUrl: foodImage,
id: 7,
},
],
};

@ -1,15 +1,13 @@
import React from "react";
import { View, Text, Image, Pressable, Dimensions } from "react-native";
import { View, Text, Pressable } from "react-native";
import {Entypo} from '@expo/vector-icons';
import { useNavigation } from "@react-navigation/native";
import fontSize from '../../../constants/fontSize';
import tw from "tailwind-rn";
//assets
import arrowIcon from "../assets/arrow.png";
//Color
import Color from "../../../constants/Colors";
const width = Dimensions.get('window').width;
const Header = ({ title, route }) => {
const navigation = useNavigation();
return (
@ -19,7 +17,7 @@ const Header = ({ title, route }) => {
{
color: Color.theme1.light.blue5,
fontFamily : 'bold',
fontSize : width / 30
fontSize : fontSize.base
},
]}
>

@ -8,12 +8,12 @@ import {
FlatList,
} from "react-native";
import tw from "tailwind-rn";
import fontSize from '../../../constants/fontSize';
import {useNavigation} from '@react-navigation/native';
import { connect } from "react-redux";
import Progress from "../../../components/Progress";
//assets
import bookImage from "../assets/zist11.png";
//Color
import Color from "../../../constants/Colors";
@ -21,7 +21,7 @@ import Color from "../../../constants/Colors";
const width = Dimensions.get("window").width;
const height = Dimensions.get("window").height;
function MyBooks({ getList, list, grades }) {
function MyBooks({ books, grades }) {
return (
<View style={[tw("w-full px-4 mb-5")]}>
<View
@ -39,18 +39,19 @@ function MyBooks({ getList, list, grades }) {
{
color: Color.theme1.light.blue5,
fontFamily: "bold",
fontSize: width / 30,
fontSize: fontSize.base,
},
]}
>
کتابهای من
</Text>
<FlatList
showsHorizontalScrollIndicator={false}
style={[tw("py-3")]}
horizontal={true}
inverted={true}
data={list}
renderItem={({ item }) => <Book book={item} />}
data={books}
renderItem={({ item }) => <Book book={item} grades={grades} />}
keyExtractor={(book) => book.name}
/>
</View>
@ -66,7 +67,7 @@ const Book = ({ book, grades }) => {
onPress={() => navigation.navigate("Product")}
>
<Image
source={bookImage}
source={{uri : `https://dnvn.ir/api/v1/file/${book.product.book.fileIds}` }}
style={[
tw("rounded-md"),
{
@ -81,11 +82,11 @@ const Book = ({ book, grades }) => {
{
color: Color.theme1.light.blue6,
fontFamily: "bold",
fontSize: width / 36,
fontSize: fontSize.sm,
},
]}
>
{"نام کتاب"}
{book.product.book.name}
</Text>
<Text
style={[
@ -93,22 +94,17 @@ const Book = ({ book, grades }) => {
{
color: Color.theme1.light.blue5,
fontFamily: "light",
fontSize: width / 40,
fontSize: fontSize.xs,
},
]}
>{`پایه ${"اول"}`}</Text>
>{'پایه' + ' ' + grades[book.product.book.gradeId]}</Text>
<Progress percent={60} alignItems={'items-end'} />
</TouchableOpacity>
);
};
const mapStateToProps = (state) => ({
// list: state.book.list,
// grades : state.publicApi.grades
grades : state.publicApi.grades
});
export default connect(mapStateToProps, {})(MyBooks);
MyBooks.defaultProps = {
list: [{ name: 1 }, { name: 2 }, { name: 3 }, { name: 4 }, { name: 5 }],
};
export default connect(mapStateToProps)(MyBooks);

@ -2,7 +2,6 @@ import React from "react";
import {
View,
Image,
Dimensions,
TouchableOpacity,
FlatList,
} from "react-native";
@ -12,28 +11,24 @@ import tw from "tailwind-rn";
import { connect } from "react-redux";
import olum1Image from "../assets/olum1.png";
const width = Dimensions.get("window").width;
const height = Dimensions.get("window").height;
function Scroll({ products }) {
function Scroll({ books }) {
return (
<View style={[tw("flex flex-col px-3 mb-5")]}>
<Header title={"فروشگاه"} route={"Products"} />
<FlatList
showsHorizontalScrollIndicator={false}
horizontal={true}
inverted={true}
style={[tw("mt-3 pb-2")]}
data={[{id : 0}]}
renderItem={({}) => <Box products={products} />}
data={[{ id: 0 }]}
renderItem={({}) => <Box books={books} />}
keyExtractor={(item) => item.id}
/>
</View>
);
}
const Box = ({ products }) => {
const Box = ({ books }) => {
return (
<View
style={[
@ -41,18 +36,18 @@ const Box = ({ products }) => {
{ height: 245, direction: "rtl" },
]}
>
{products.map((item, index) => (
<Product product={item} position={Number(item.id)} key={index} />
{books.map((book, index) => (
<Product book={book} position={Number(index)} key={index} />
))}
</View>
);
};
const Product = ({ product, position }) => {
const Product = ({ book, position }) => {
const navigation = useNavigation();
return (
<TouchableOpacity
onPress={() => navigation.navigate('Product')}
onPress={() => navigation.navigate("Product")}
style={[
tw("rounded-md mx-1 overflow-hidden rounded-md"),
{
@ -60,9 +55,12 @@ const Product = ({ product, position }) => {
height: position === 0 ? 245 : 118,
},
]}
// onPress={() => navigation.navigate('Product')}
onPress={() => navigation.navigate('Product')}
>
<Image source={olum1Image} style={{ width: "100%", height: "100%" }} />
<Image
source={{ uri: `https://dnvn.ir/api/v1/file/${book.fileIds}` }}
style={{ width: "100%", height: "100%" }}
/>
</TouchableOpacity>
);
};
@ -71,40 +69,3 @@ const mapStateToProps = (state) => ({
// features: state.publicApi.home?.features,
});
export default connect(mapStateToProps, {})(Scroll);
Scroll.defaultProps = {
products: [
{
imageUrl: olum1Image,
id: 0,
},
{
imageUrl: olum1Image,
id: 1,
},
{
imageUrl: olum1Image,
id: 2,
},
{
imageUrl: olum1Image,
id: 3,
},
{
imageUrl: olum1Image,
id: 4,
},
{
imageUrl: olum1Image,
id: 5,
},
{
imageUrl: olum1Image,
id: 6,
},
{
imageUrl: olum1Image,
id: 7,
},
],
};

@ -1,57 +1,49 @@
import React, {useState, useEffect} from 'react';
import {
View,
Text,
Image,
TouchableOpacity,
Dimensions,
FlatList,
} from 'react-native';
import tw from 'tailwind-rn';
import {connect} from 'react-redux';
// import { book } from "../../../../../redux/actions";
import Progress from '../../../components/Progress';
import Header from '../components/Header';
//assets
import bookImage from '../assets/zist11.png';
} from "react-native";
import tw from "tailwind-rn";
import fontSize from "../../../constants/fontSize";
import { connect } from "react-redux";
import Progress from "../../../components/Progress";
import Header from "../components/Header";
//Color
import Color from '../../../constants/Colors';
const width = Dimensions.get('window').width;
const height = Dimensions.get('window').height;
import Color from "../../../constants/Colors";
function Videos({getList, list, grades}) {
function Videos({ videos, grades }) {
return (
<View style={[tw('w-full px-2 mb-5')]}>
<View style={[tw("w-full px-2 mb-5")]}>
<View
style={[
tw(
'w-full flex flex-col rounded-md pt-2 px-2 overflow-hidden',
),
]}>
<Header title="دورههای ویدئویی شما" route={'Videos'} />
tw("w-full flex flex-col rounded-md pt-2 px-2 overflow-hidden"),
]}
>
<Header title="دورههای ویدئویی شما" route={"Videos"} />
<FlatList
style={[tw('py-3')]}
showsHorizontalScrollIndicator={false}
style={[tw("py-3")]}
horizontal={true}
inverted={true}
data={list}
renderItem={(item) => <Video video={item} />}
keyExtractor={item => item.name}
data={videos}
renderItem={({item}) => <Video video={item} grades={grades} />}
keyExtractor={(item) => item.id}
/>
</View>
</View>
);
}
const Video = ({book, grades}) => {
const Video = ({ video, grades }) => {
return (
<TouchableOpacity style={tw('flex flex-col ml-3')}>
<TouchableOpacity style={tw("flex flex-col ml-3")}>
<Image
source={bookImage}
source={{uri : `https://dnvn.ir/api/v1/file/${video.fileIds}`}}
style={[
tw('rounded-md'),
tw("rounded-md"),
{
height: 160,
width: 110,
@ -60,28 +52,33 @@ const Video = ({book, grades}) => {
/>
<Text
style={[
tw('mt-2 pr-1'),
{color: Color.theme1.light.blue6, fontFamily : 'bold', fontSize : width / 36},
]}>
{'نام کتاب'}
tw("mt-2 pr-1"),
{
color: Color.theme1.light.blue6,
fontFamily: "bold",
fontSize: fontSize.sm,
},
]}
>
{video.name}
</Text>
<Text
style={[
tw('mt-1 pr-1'),
{color: Color.theme1.light.blue5, fontFamily : 'light', fontSize : width / 40},
]}>{`پایه ${'اول'}`}</Text>
<Progress percent={60} alignItems={'items-end'} />
tw("mt-1 pr-1"),
{
color: Color.theme1.light.blue5,
fontFamily: "light",
fontSize: fontSize.xs,
},
]}
>{grades[video.gradeId]}</Text>
<Progress percent={60} alignItems={"items-end"} />
</TouchableOpacity>
);
};
const mapStateToProps = state => ({
// list: state.book.list,
// grades : state.publicApi.grades
const mapStateToProps = (state) => ({
grades : state.publicApi.grades
});
export default connect(mapStateToProps, {})(Videos);
Videos.defaultProps = {
list: [{name: 1}, {name: 2}, {name: 3}, {name: 4}, {name: 5}],
};

@ -1,6 +1,6 @@
import React, { useState, useEffect } from "react";
import { connect } from "react-redux";
import { publicApi } from "../../redux/actions";
import { blog, book, userProduct } from "../../redux/actions";
import {
View,
StyleSheet,
@ -22,9 +22,25 @@ import Drawer from "../../components/Drawer";
// import { SafeAreaView } from 'react-native-safe-area-context';
// Within your render function
const Home = ({ isLogi, setHeaderOptions }) => {
const Home = ({
blogs,
getBlogs,
books,
getBooks,
videos,
getVideos,
userProducts,
getUserProducts,
}) => {
const [position, setPosition] = useState("100%");
useEffect(() => {
getBlogs();
getBooks();
getUserProducts();
// getVideos();
}, []);
const setBoxPosition = () => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
setPosition(position === "100%" ? "0%" : "100%");
@ -54,10 +70,10 @@ const Home = ({ isLogi, setHeaderOptions }) => {
contentContainerStyle={styles.contentContainerStyle}
style={[styles.container, tw("w-full flex flex-col")]}
>
<MyBooks />
<Scroll />
<Videos />
<Blogs />
{userProducts.length > 0 && <MyBooks books={userProducts} />}
{books.length > 0 && <Scroll books={books} />}
{books.length > 0 && <Videos videos={books} />}
{blogs.length > 0 && <Blogs blogs={blogs} />}
</ScrollView>
</SafeAreaView>
);
@ -78,9 +94,17 @@ const styles = StyleSheet.create({
});
const mapStateToProps = (state) => ({
isLogin: state.user.status,
blogs: state.blog.list,
books: state.book.list,
userProducts: state.userProduct.list,
videos: state.product.listVOD,
});
const mapDispatchToProps = {};
const mapDispatchToProps = {
getBlogs: blog.list,
getBooks: book.list,
getUserProducts: userProduct.list,
// getVideos: product.listVOD
};
export default connect(mapStateToProps, mapDispatchToProps)(Home);

@ -32,16 +32,16 @@ function Login(props) {
};
const submit = async () => {
// setLoading(true);
// if (!checkPhoneNumber()) {
// setLoading(false);
// return asyncAwesomeAlert("خطا", "شماره وارد شده اشتباه است", {
// showCancelButton: false,
// });
// }
// props.sendPhoneNumber({cellphone : phone});
props.navigation.navigate("Otp", { phone: '09360467907' });
// setLoading(false);
setLoading(true);
if (!checkPhoneNumber()) {
setLoading(false);
return asyncAwesomeAlert("خطا", "شماره وارد شده اشتباه است", {
showCancelButton: false,
});
}
props.sendPhoneNumber({cellphone : phone});
props.navigation.navigate("Otp", { phone : phone});
setLoading(false);
};
return (

@ -1,5 +1,4 @@
import { t } from "i18next";
import React from "react";
import React, { useState } from "react";
import {
View,
Text,
@ -8,24 +7,28 @@ import {
ScrollView,
Pressable,
} from "react-native";
import { Entypo } from '@expo/vector-icons';
import { Entypo } from "@expo/vector-icons";
import CustomPressable from "../../../components/Pressable";
import Description from "./Description";
import LinkBox from "./LinkBox";
import Comments from "./Comments";
import Rates from "./Rates";
import tw from "tailwind-react-native-classnames";
import fontSize from "../../../constants/fontSize";
import { product, userProduct } from "../../../redux/actions";
import { connect } from "react-redux";
const width = Dimensions.get("window").width;
const height = Dimensions.get("window").height;
export default function Book({ product }) {
function Book({ book, grades, pushToCart, userId }) {
const [type, setType] = useState(1);
return (
<ScrollView style={[tw.style("flex flex-col flex-1")]}>
<View style={tw.style("flex flex-row-reverse")}>
<View style={[tw.style("rounded-md"), { height: 160, width: 110 }]}>
<Image
source={{ uri: product.imageUrl }}
source={{ uri: `https://dnvn.ir/api/v1/file/${book.fileIds}` }}
style={[tw.style("rounded-md h-full w-full")]}
/>
</View>
@ -42,30 +45,30 @@ export default function Book({ product }) {
<Text
style={{
color: "#05335F",
fontSize: width / 18,
fontSize: fontSize.xl2,
marginBottom: 5,
fontFamily: "bold",
}}
>
{product.name}
{book.product[type].name}
</Text>
<Text
style={{
color: "#196EC0",
fontSize: width / 37,
fontSize: fontSize.sm,
fontFamily: "light",
}}
>
{product.grade}
{"پایه" + " " + grades[book.gradeId]}
</Text>
</View>
<Text
style={[
tw.style("text-right w-full"),
{ color: "#323232", fontSize: width / 38, fontFamily: "light" },
{ color: "#323232", fontSize: fontSize.sm, fontFamily: "light" },
]}
>
{product.text}
{book.text}
</Text>
</View>
</View>
@ -79,12 +82,12 @@ export default function Book({ product }) {
style={{
color: "#196EC0",
textAlign: "center",
fontSize: width / 37,
fontSize: fontSize.sm,
fontFamily: "light",
}}
>
{" "}
{473 + "\n" + "صفحه"}
{book.pagesNum + "\n" + "صفحه"}
</Text>
</View>
<View
@ -95,7 +98,7 @@ export default function Book({ product }) {
style={{
color: "#196EC0",
textAlign: "center",
fontSize: width / 37,
fontSize: fontSize.sm,
fontFamily: "light",
}}
>
@ -111,7 +114,7 @@ export default function Book({ product }) {
style={{
color: "#196EC0",
textAlign: "center",
fontSize: width / 37,
fontSize: fontSize.sm,
fontFamily: "light",
}}
>
@ -124,7 +127,7 @@ export default function Book({ product }) {
<Text
style={[
tw.style("w-full text-right font-medium"),
{ color: "#196EC0", fontSize: width / 36, fontFamily: "regular" },
{ color: "#196EC0", fontSize: fontSize.sm, fontFamily: "regular" },
]}
>
نسخه محصول را انتخاب کنید
@ -136,24 +139,33 @@ export default function Book({ product }) {
>
<CustomPressable
title={"نسخه فیزیکی"}
backgroundColor="transparent"
color={"#196EC0"}
onPress={() => setType(1)}
backgroundColor={type === 0 ? "transparent" : "#196EC0"}
color={type === 0 ? "#196EC0" : "white"}
border={{ color: "#196EC0", width: 1 }}
width={"49%"}
/>
<CustomPressable
onPress={() => setType(0)}
title={"نسخه دیجیتال"}
backgroundColor="transparent"
color={"#196EC0"}
backgroundColor={type === 1 ? "transparent" : "#196EC0"}
color={type === 1 ? "#196EC0" : "white"}
border={{ color: "#196EC0", width: 1 }}
width={"49%"}
/>
<CustomPressable
title={"خرید با قیمت 245.000 تومان"}
title={`خرید با قیمت ${book.product[type].price} تومان`}
backgroundColor="#196EC0"
color={"white"}
border={{ color: "#196EC0", width: 0 }}
width={"65%"}
onPress={() =>
pushToCart({
productId: book?.product[type]?.id,
userId: userId,
count: 1,
})
}
/>
<CustomPressable
title={"مشاهده نمونه"}
@ -174,31 +186,53 @@ export default function Book({ product }) {
<Text
style={[
tw.style(""),
{ color: "#275077", fontSize: width / 36, fontFamily: "light" },
{ color: "#275077", fontSize: fontSize.sm, fontFamily: "light" },
]}
>
مشاهده دوره ویدئویی این محصول
</Text>
</Pressable>
</View>
<Description description={product.description} />
{book.product[type].description && (
<Description description={book.description} />
)}
<LinkBox title="مشخصات محصول" path="" />
<LinkBox title="نقد بررسی و توضیحات تکمیلی محصول" path="" />
<LinkBox title="پرسش و پاسخ" path="" />
{product.rates && (
<View
style={tw.style(
"flex flex-row-reverse justify-between items-center my-6"
)}
>
<Text
style={[{ fontSize: width / 36, color: "#275077", fontFamily: "regular"}, tw.style("")]}
style={[
{
fontSize: fontSize.sm,
color: "#275077",
fontFamily: "regular",
},
tw.style(""),
]}
>
امتیازات و نظرات
</Text>
<Entypo name="chevron-small-left" size={20} color="#196EC0" />
</View>
<Rates rates={product.rates} />
<Comments comments={product.comments} />
)}
{/* <Rates rates={book.rates} /> */}
<Comments comments={book.comments} />
</ScrollView>
);
}
const mapStateToProps = (state) => ({
userId: state.user.status.id,
});
const mapDispatchToProps = {
pushToCart: userProduct.add,
};
export default connect(mapStateToProps, mapDispatchToProps)(Book);

@ -1,12 +1,14 @@
import React from "react";
import { View, Text, FlatList, Image, Dimensions } from "react-native";
import tw from "tailwind-rn";
import fontSize from '../../../constants/fontSize';
const width = Dimensions.get("window").width;
export default function Commnets({ comments }) {
return (
<FlatList
showsHorizontalScrollIndicator={false}
horizontal={true}
inverted={true}
style={{ marginTop: 20, paddingBottom: 10 }}
@ -33,7 +35,7 @@ const Comment = ({ comment }) => {
/>
<Text
style={[
{ fontSize: width / 36, color: "#132F52", fontFamily: "bold" },
{ fontSize: fontSize.sm, color: "#132F52", fontFamily: "bold" },
,
]}
>
@ -43,7 +45,7 @@ const Comment = ({ comment }) => {
<View style={tw("flex flex-row items-center")}>
<Text
style={{
fontSize: width / 40,
fontSize: fontSize.xs,
color: "#196EC0",
fontFamily: "light",
}}
@ -60,7 +62,7 @@ const Comment = ({ comment }) => {
></View>
<Text
style={{
fontSize: width / 40,
fontSize: fontSize.xs,
color: "#196EC0",
fontFamily: "light",
}}
@ -71,7 +73,7 @@ const Comment = ({ comment }) => {
</View>
<Text
style={[
{ fontSize: width / 40, lineHeight: 20, color: "#132F52", fontFamily: "light",},
{ fontSize: fontSize.sm, lineHeight: 20, color: "#132F52", fontFamily: "light",},
tw("mt-2"),
]}
>

@ -1,6 +1,7 @@
import React from 'react';
import {View, Text, Dimensions, Image} from 'react-native';
import tw from 'tailwind-react-native-classnames';
import fontSize from '../../../constants/fontSize';
import {Entypo} from '@expo/vector-icons';
const width = Dimensions.get('window').width;
@ -13,7 +14,7 @@ export default function Description({description}) {
style={tw.style('flex flex-row-reverse justify-between items-center mb-2')}>
<Text
style={[
{fontSize: width / 36, color: '#275077', fontFamily: 'regular'},
{fontSize: fontSize.sm, color: '#275077', fontFamily: 'regular'},
tw.style(''),
]}>
توضیحات
@ -23,7 +24,7 @@ export default function Description({description}) {
<Text
style={[
tw.style('w-full text-right mt-2'),
{fontSize: width / 36, color: '#323232bb', lineHeight: 20, fontFamily : 'light'},
{fontSize: fontSize.sm, color: '#323232bb', lineHeight: 20, fontFamily : 'light'},
]}>
{description}
</Text>

@ -1,6 +1,7 @@
import React from 'react';
import {View, Text, Dimensions, Image} from 'react-native';
import tw from 'tailwind-react-native-classnames';
import fontSize from '../../../constants/fontSize';
import {Entypo} from '@expo/vector-icons';
const width = Dimensions.get('window').width;
@ -17,7 +18,7 @@ export default function Description({title, path}) {
]}>
<Text
style={[
{fontSize: width / 36, color: '#275077', fontFamily: 'regular'},
{fontSize: fontSize.sm, color: '#275077', fontFamily: 'regular'},
tw.style(''),
]}>
{title}

@ -1,6 +1,7 @@
import React from 'react';
import {View, Text, Dimensions} from 'react-native';
import tw from 'tailwind-react-native-classnames';
import fontSize from '../../../constants/fontSize';
const width = Dimensions.get('window').width;
@ -14,11 +15,11 @@ export default function Rates({rates}) {
]}>
<Text
style={[
{fontSize: width / 13, color: '#05335F', fontFamily: 'bold'},
{fontSize: fontSize.xl6, color: '#05335F', fontFamily: 'bold'},
]}>
{rates.mid}
</Text>
<Text style={{fontSize: width / 36, color: '#707070', fontFamily: 'light'}}>
<Text style={{fontSize: fontSize.sm, color: '#707070', fontFamily: 'light'}}>
{'از' + ' ' + rates.allRates + ' ' + 'نفر'}
</Text>
</View>
@ -34,7 +35,7 @@ export default function Rates({rates}) {
const Progress = ({data}) => {
return (
<View style={[tw.style('flex flex-1 flex-row items-center py-0.5')]}>
<Text style={{fontSize: width / 36, color: '#05335F', fontFamily: 'regular'}}>{data.name}</Text>
<Text style={{fontSize: fontSize.sm, color: '#05335F', fontFamily: 'regular'}}>{data.name}</Text>
<View
style={[
tw.style('rounded-md ml-2 flex-1'),
@ -48,7 +49,7 @@ const Progress = ({data}) => {
</View>
<Text
style={{
fontSize: width / 40,
fontSize: fontSize.xs,
fontFamily: 'light',
width: width / 7.5,
textAlign: 'center',

@ -1,4 +1,4 @@
import React, { useState } from "react";
import React, { useState, useEffect } from "react";
import {
View,
StyleSheet,
@ -11,57 +11,23 @@ import {
import Book from "./components/Book";
import Video from "./components/Video";
import { connect } from "react-redux";
import {book} from "../../redux/actions";
import userImage from "./assets/user.png";
import poster from "./assets/poster.png";
import Navbar from "../../components/Navbar";
import Drawer from "../../components/Drawer";
function Product({
product = {
type: "کتاب ها",
name: "ریاضی",
price: "145.000 تومان",
imageUrl: "https://dnvn.ir/api/v1/file/2105",
poster: poster,
grade: "پایه هفتم ابتدایی",
text: "خالد حسینی تو رمان باد بادک باز مینویسه : ﻣﺮﺩ ﺁﻫﺴﺘﻪ ﺩﺭ ﮔﻮﺵ ﻓﺮﺯﻧﺪ ﺗﺎﺯﻩ ﺑﻪ ﺑﻠﻮﻍ ﺭﺳﯿﺪﻩ ﺍﺵ ﺑﺮﺍﯼ ﭘﻨﺪ ﭼﻨﯿﻦ ﻧﺠﻮﺍ ﮐﺮﺩ : ” ﭘﺴﺮﻡ ﺩﺭ ﺯﻧﺪﮔﯽ ﻫﺮﮔﺰ ﺩﺯﺩﯼ ﻧﮑﻦ ” ﭘﺴﺮ ﻣﺘﻌﺠﺐ ﻭ ﻣﺒﻬﻮﺕ ﺑﻪ ﭘﺪﺭ ﻧﮕﺎﻩ ﮐﺮﺩ ﺑﺪﯾﻦ ",
description:
"خالد حسینی تو رمان باد بادک باز مینویسه : ﻣﺮﺩ ﺁﻫﺴﺘﻪ ﺩﺭ ﮔﻮﺵ ﻓﺮﺯﻧﺪ ﺗﺎﺯﻩ ﺑﻪ ﺑﻠﻮﻍ ﺭﺳﯿﺪﻩ ﺍﺵ ﺑﺮﺍﯼ ﭘﻨﺪ ﭼﻨﯿﻦ ﻧﺠﻮﺍ ﮐﺮﺩ : ” ﭘﺴﺮﻡ ﺩﺭ ﺯﻧﺪﮔﯽ ﻫﺮﮔﺰ ﺩﺯﺩﯼ ﻧﮑﻦ ” ﭘﺴﺮ ﻣﺘﻌﺠﺐ ﻭ ﻣﺒﻬﻮﺕ ﺑﻪ ﭘﺪﺭ ﻧﮕﺎﻩ ﮐﺮﺩ ﺑﺪﯾﻦ ﻣﻌﻨﺎ ﮐﻪ ﺍﻭ ﻫﺮﮔﺰ ﺩﺳﺖ ﮐﺞ ﻧﺪﺍﺷﺘﻪ ﭘﺪﺭ ﺑﻪ ﻧﮕﺎﻩ ﻣﺘﻌﺠﺐ ﻓﺮﺯﻧﺪ ﻟﺒﺨﻨﺪﯼ ﺯﺩ ﻭ ﺍﺩﺍﻣﻪ ﺩﺍﺩ : ﺩﺭ ﺯﻧﺪﮔﯽ ﺩﺭﻭﻍ ﻧﮕﻮ ﭼﺮﺍ ﮐﻪ ﺍﮔﺮ ﮔﻔﺘﯽ ﺻﺪﺍﻗﺖ ﺭﺍ ﺩﺯﺩﯾﺪﻩ ﺍﯼ، ﺧﯿﺎﻧﺖ ﻧﮑﻦ ﮐﻪ ﺍﮔﺮ ﮐﺮﺩﯼ ﻋﺸﻖ ﺭﺍ ﺩﺯﺩﯾﺪﻩ ﺍﯼ، ﺧﺸﻮﻧﺖ ﻧﮑﻦ ﺍﮔﺮ ﮐﺮﺩﯼ ﻣﺤﺒﺖ ﺭﺍ ﺩﺯﺩﯾﺪﻩ ﺍﯼ، ﻧﺎ ﺣﻖ ﻧﮕﻮ ﺍﮔﺮ ﮔﻔﺘﯽ ﺣﻖ ﺭﺍ ﺩﺯﺩﯾﺪﻩ ﺍﯼ، ﺑﯽ ﺣﯿﺎﯾﯽ ﻧﮑﻦ ﺍﮔﺮ ﮐﺮﺩﯼ ﺷﺮﺍﻓﺖ ﺭﺍ ﺩﺯﺩﯾﺪﻩ ﺍی... ﭘﺲ ﺩﺭ ﺯﻧﺪﮔﯽ ﻓﻘﻂ ﺩﺯﺩﯼ نکن ",
rates: {
mid: 4.5,
allRates: 2456,
fields: [
{ name: "field1", value: 49 },
{ name: "field2", value: 31 },
{ name: "field3", value: 9 },
{ name: "field4", value: 5 },
{ name: "field5", value: 4 },
],
},
comments: [
{
id: 0,
name: "سورنا عابدی",
imageUrl: userImage,
vote: 4,
date: new Date(),
message:
"خالد حسینی تو رمان باد بادک باز مینویسه : ﻣﺮﺩ ﺁﻫﺴﺘﻪ ﺩﺭ ﮔﻮﺵ ﻓﺮﺯﻧﺪ ﺗﺎﺯﻩ ﺑﻪ ﺑﻠﻮﻍ ﺭﺳﯿﺪﻩ ﺍﺵ ﺑﺮﺍﯼ ﭘﻨﺪ ﭼﻨﯿﻦ ﻧﺠﻮﺍ ﮐﺮﺩ : ” ﭘﺴﺮﻡ ﺩﺭ ﺯﻧﺪﮔﯽ ﻫﺮﮔﺰ ﺩﺯﺩﯼ ﻧﮑﻦ ” ﭘﺴﺮ ﻣﺘﻌﺠﺐ ﻭ ﻣﺒﻬﻮﺕ ﺑﻪ ﭘﺪﺭ ﻧﮕﺎﻩ ﮐﺮﺩ ﺑﺪﯾﻦ ﻣﻌﻨﺎ ﮐﻪ ﺍﻭ ﻫﺮﮔﺰ ﺩﺳﺖ ﮐﺞ ﻧﺪﺍﺷﺘﻪ ﭘﺪﺭ ﺑﻪ ﻧﮕﺎﻩ ﻣﺘﻌﺠﺐ ﻓﺮﺯﻧﺪ ﻟﺒﺨﻨﺪﯼ ﺯﺩ ﻭ ﺍﺩﺍﻣﻪ ",
},
{
id: 1,
name: "سورنا عابدی",
imageUrl: userImage,
vote: 4,
date: new Date(),
message:
"خالد حسینی تو رمان باد بادک باز مینویسه : ﻣﺮﺩ ﺁﻫﺴﺘﻪ ﺩﺭ ﮔﻮﺵ ﻓﺮﺯﻧﺪ ﺗﺎﺯﻩ ﺑﻪ ﺑﻠﻮﻍ ﺭﺳﯿﺪﻩ ﺍﺵ ﺑﺮﺍﯼ ﭘﻨﺪ ﭼﻨﯿﻦ ﻧﺠﻮﺍ ﮐﺮﺩ : ” ﭘﺴﺮﻡ ﺩﺭ ﺯﻧﺪﮔﯽ ﻫﺮﮔﺰ ﺩﺯﺩﯼ ﻧﮑﻦ ” ﭘﺴﺮ ﻣﺘﻌﺠﺐ ﻭ ﻣﺒﻬﻮﺕ ﺑﻪ ﭘﺪﺭ ﻧﮕﺎﻩ ﮐﺮﺩ ﺑﺪﯾﻦ ﻣﻌﻨﺎ ﮐﻪ ﺍﻭ ﻫﺮﮔﺰ ﺩﺳﺖ ﮐﺞ ﻧﺪﺍﺷﺘﻪ ﭘﺪﺭ ﺑﻪ ﻧﮕﺎﻩ ﻣﺘﻌﺠﺐ ﻓﺮﺯﻧﺪ ﻟﺒﺨﻨﺪﯼ ﺯﺩ ﻭ ﺍﺩﺍﻣﻪ ",
},
],
},
route,
book,
getBook,
grades,
}) {
const [position, setPosition] = useState("100%");
useEffect(() => {
getBook({id : route.params.id});
},[]);
const setBoxPosition = () => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
setPosition(position === "100%" ? "0%" : "100%");
@ -90,11 +56,12 @@ function Product({
contentContainerStyle={styles.contentContainerStyle}
style={styles.container}
>
{product.type === "ویدئوها" ? (
<Video product={product} />
{book && (route.params.type === 'video' ? (
<Video />
) : (
<Book product={product} />
)}
<Book book={book} grades={grades} />
))}
</ScrollView>
</SafeAreaView>
);
@ -112,4 +79,14 @@ const styles = StyleSheet.create({
paddingHorizontal: 16,
},
});
export default Product;
const mapStateToProps = (state) => ({
book : state.book.info,
grades : state.publicApi.grades
});
const mapDispatchToProps = {
getBook : book.info
}
export default connect(mapStateToProps, mapDispatchToProps)(Product);

@ -2,23 +2,16 @@ import React from "react";
import { View, Image, Text, Dimensions, Pressable } from "react-native";
import { useNavigation } from "@react-navigation/native";
import tw from "tailwind-react-native-classnames";
import fontSize from '../../../constants/fontSize';
const width = Dimensions.get("window").width;
const height = Dimensions.get("window").height;
function Book({
item = {
name: "ریاضی",
price: "145.000 تومان",
grade: "4",
imageUrl: "https://dnvn.ir/api/v1/file/2105",
},
}) {
function Book({book, grades, type}) {
const navigation = useNavigation();
return (
<Pressable
style={[
{
width: width / 2 - 20,
width: width / 2 - 25,
// shadowColor : "#000",
// shadowOffset : {width : 0, height : 2},
// shadowRadius : 20,
@ -27,34 +20,34 @@ function Book({
borderWidth: 1,
borderColor: "#ddd",
},
tw.style("flex flex-col items-end p-2 rounded-md"),
tw.style("flex flex-col items-end px-2 pt-2 rounded-md"),
]}
onPress={() => navigation.navigate("Product")}
onPress={() => navigation.navigate("Product", { id : book.id, type : 'book'})}
>
<Image
source={{ uri: item.imageUrl }}
style={[tw.style("w-full rounded-md"), { height: height / 3.8 }]}
source={{ uri: `https://dnvn.ir/api/v1/file/${book.fileIds}` }}
style={[tw.style("w-full rounded-md"), { height: (width / 2 - 25) * 16 / 14 }]}
/>
<Text
style={{
fontSize: width / 31,
fontSize: fontSize.lg,
marginTop: 5,
color: "#05335F",
fontFamily: "bold",
}}
>
{item.name}
{ (type === 1 ? 'کتاب فیزیکی' : 'کتاب دیجیتال') + ' ' + book.name}
</Text>
<Text style={{ color: "#196EC0", fontSize: width / 37, marginTop: 5, fontFamily : 'light' }}>
{"پایه" + " " + item.grade}
<Text style={{ color: "#196EC0", fontSize: fontSize.sm, marginTop: 5, fontFamily : 'light' }}>
{'پایه' + ' ' + grades[book.gradeId]}
</Text>
<Text
style={[
tw.style("w-full text-center"),
{ marginTop: 10, color: "#132F52", fontFamily : 'bold', fontSize: width / 31 },
tw.style("w-full text-center mb-1"),
{ marginTop: 10, color: "#132F52", fontFamily : 'bold', fontSize: fontSize.base },
]}
>
{item.price}
{( type=== 1 ? book.product[1].price : book.product[0].price ) + ' ' + 'تومان'}
</Text>
</Pressable>
);

@ -2,6 +2,7 @@ import React from "react";
import { View, Image, Text, Dimensions, Pressable } from "react-native";
import { useNavigation } from "@react-navigation/native";
import tw from "tailwind-react-native-classnames";
import fontSize from '../../../constants/fontSize';
import posterImage from "../assets/poster.png";
const width = Dimensions.get("window").width;
@ -56,7 +57,7 @@ function Video({
</View>
<Text
style={{
fontSize: width / 31,
fontSize: fontSize.lg,
marginTop: 5,
color: "#05335F",
fontFamily: "bold",
@ -74,8 +75,8 @@ function Video({
{
marginTop: 10,
color: "#132F52",
fontFamily: "light",
fontSize: width / 37,
fontFamily: "bold",
fontSize: fontSize.base,
},
]}
>
@ -85,7 +86,7 @@ function Video({
style={{
color: "#196EC0",
fontFamily: "light",
fontSize: width / 37,
fontSize: fontSize.sm,
marginTop: 5,
}}
>

@ -1,4 +1,4 @@
import React, { useState } from "react";
import React, { useState, useEffect } from "react";
import {
View,
@ -9,26 +9,27 @@ import {
StatusBar,
LayoutAnimation,
} from "react-native";
import tw from "tailwind-react-native-classnames";
import { connect } from "react-redux";
import { book } from "../../redux/actions";
import tw from "tailwind-react-native-classnames";
import Book from "./components/Book";
import Video from "./components/Video";
import Search from "../../components/Search";
import Select from "../../components/Select";
import Navbar from "../../components/Navbar";
import Drawer from "../../components/Drawer";
function Products({ grades, productTypes }) {
function Products({ grades, productTypes, books }) {
const [position, setPosition] = useState("100%");
const [productType, setProductType] = useState("کتاب فیزیکی");
const [grade, setGrade] = useState("");
const [search, setSearch] = useState("");
useEffect(() => {}, []);
const setBoxPosition = () => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
setPosition(position === "100%" ? "0%" : "100%");
};
const [productType, setProductType] = useState("");
const [grade, setGrade] = useState("");
const [search, setSearch] = useState("");
const onChange = (name, value) => {};
return (
<SafeAreaView
@ -73,13 +74,14 @@ function Products({ grades, productTypes }) {
"flex flex-1 w-full py-5 flex-row flex-wrap justify-between bg-white"
)}
>
{[0, 1, 2, 3, 4, 5, 6, 7].map((item, index) =>
productType === "ویدئوها" ? (
<Video key={index} />
) : (
<Book key={index} />
)
)}
{productType === "کتاب فیزیکی" &&
books.map((book, index) => (
<Book book={book} key={index} grades={grades} type={1} />
))}
{productType === "کتاب دیجیتال" &&
books.map((book, index) => (
<Book book={book} key={index} grades={grades} type={0} />
))}
</View>
</ScrollView>
</SafeAreaView>
@ -99,23 +101,17 @@ const styles = StyleSheet.create({
},
});
export default Products;
const mapStateToProps = (state) => ({
grades: state.publicApi.grades,
books: state.book.list,
});
const mapDispatchToProps = {
getBooks: book.list,
};
export default connect(mapStateToProps, mapDispatchToProps)(Products);
Products.defaultProps = {
grades: [
"پیش دبستان",
"اول",
"دوم",
"سوم",
"چهارم",
"پنجم",
"ششم",
"هفتم",
"هشتم",
"نهم",
"دهم",
"یازدهم",
"دوازدهم",
],
productTypes: ["کتاب فیزیکی", "کتاب دیجیتال", "ویدئوها", "اشتراک"],
};

@ -1,7 +1,7 @@
import React from "react";
import { View, Text, Dimensions } from "react-native";
import tw from "tailwind-rn";
import MusicPlayer from "../../../components/MusicPlayer";
// import MusicPlayer from "../../../components/MusicPlayer";
const { width } = Dimensions.get("window");
@ -16,7 +16,7 @@ export default function Voice({ name, file }) {
>
{name}
</Text>
<MusicPlayer />
{/* <MusicPlayer /> */}
</View>
);
}

@ -45,7 +45,7 @@ export default function Scan({}) {
<ImageBackground
source={laptopImage}
resizeMode="cover"
style={[tw("w-full"), { height: height - 78 }]}
style={[tw("w-full"), { height: height }]}
>
<View
style={tw(

@ -60,5 +60,5 @@ const styles = StyleSheet.create({
});
QR.defaultProps = {
page: "scan",
page: "content",
};

@ -7,10 +7,18 @@ import {
Dimensions,
KeyboardAvoidingView,
} from "react-native";
import { connect } from "react-redux";
import { userFactor } from "../../../redux/actions";
import tw from "tailwind-react-native-classnames";
const width = Dimensions.get("window").width;
export default function Code({}) {
function Code({ codeId, setCodeId, userId, factorId }) {
const [value, setValue] = React.useState(codeId || "");
const setOff = () => {
setCodeId({ offCodeValue: value, userId: userId, id: factorId });
};
return (
<KeyboardAvoidingView
enabled
@ -22,6 +30,7 @@ export default function Code({}) {
)}
>
<TextInput
onChaneText={(text) => setValue(text)}
style={[
tw.style("border-0 flex-1 text-right pr-4"),
{ fontSize: width / 36, fontFamily: "light" },
@ -30,6 +39,7 @@ export default function Code({}) {
placeholderTextColor="#707070"
/>
<Pressable
onClick={() => setOff()}
style={[
tw.style("py-2 px-5"),
{
@ -52,3 +62,15 @@ export default function Code({}) {
</KeyboardAvoidingView>
);
}
const mapStateToProps = (state) => ({
codeId: state.userFactor.info?.codeId,
userId: state.user.status.id,
factorId: state.userFactor.info?.id,
});
const mapDispatchToProps = {
setCodeId: userFactor.update,
};
export default connect(mapStateToProps, mapDispatchToProps)(Code);

@ -1,5 +1,7 @@
import React from "react";
import { View, Text, Image, Dimensions, Pressable } from "react-native";
import { connect } from "react-redux";
import { userProduct } from "../../../redux/actions";
import { AntDesign } from "@expo/vector-icons";
import tw from "tailwind-react-native-classnames";
import bookImage from "../assets/book.png";
@ -8,7 +10,7 @@ import deleteIcon from "../assets/delete.png";
const width = Dimensions.get("window").width;
const height = Dimensions.get("window").height;
export default function Product({ product }) {
function Product({ product, grades, pushToCart }) {
return (
<View
style={[
@ -18,7 +20,9 @@ export default function Product({ product }) {
>
<View style={tw.style("flex flex-row-reverse")}>
<Image
source={bookImage}
source={{
uri: "https://dnvn.ir/api/v1/file/" + product.product.book.fileIds,
}}
style={[tw.style("rounded-md"), { width: 60, height: 90 }]}
/>
<View style={tw.style("flex flex-col items-end pr-2")}>
@ -30,7 +34,7 @@ export default function Product({ product }) {
fontFamily: "bold",
}}
>
علوم اجتماعی
{product.product.book.name}
</Text>
<Text
style={{
@ -40,7 +44,7 @@ export default function Product({ product }) {
fontFamily: "light",
}}
>
پایه دوم
{"پایه" + " " + grades[product.product.book.gradeId]}
</Text>
<Text
style={{
@ -49,15 +53,37 @@ export default function Product({ product }) {
fontFamily: "light",
}}
>
نسخه فیزیکی
{product.productType === 2 ? "نسخه فیزیکی" : "نسخه دیجیتال"}
</Text>
</View>
</View>
<View style={tw.style("flex flex-col justify-between items-start")}>
<AntDesign name="close" size={20} color="black" />
<AntDesign
name="close"
size={20}
color="black"
onPress={() =>
pushToCart(
{
productId: product?.productId,
userId: product?.userId,
count: product?.productType === 1 ? -1 : -product?.count,
},
{},
{ id: product?.factorId }
)
}
/>
<View style={tw.style("flex flex-col items-center mt-2")}>
<View style={tw.style("flex flex-row-reverse items-center mb-3")}>
<Pressable
onPress={() =>
pushToCart({
productId: product?.productId,
userId: product?.userId,
count: 1,
})
}
style={[
tw.style(
"rounded-md py-0 px-2 flex flex-row justify-center items-center border"
@ -87,9 +113,16 @@ export default function Product({ product }) {
},
]}
>
1
{product.count}
</Text>
<Pressable
onPress={() =>
pushToCart({
productId: product?.productId,
userId: product?.userId,
count: -1,
})
}
style={[
tw.style(
"rounded-md py-0 px-2.5 flex flex-row justify-center items-center border"
@ -110,11 +143,23 @@ export default function Product({ product }) {
</Text>
</Pressable>
</View>
<Text style={[tw.style("", { fontSize: width / 25, fontFamily: "bold"})]}>
145.000
<Text
style={[tw.style("", { fontSize: width / 25, fontFamily: "bold" })]}
>
{product.product.price + ' ' + 'تومان'}
</Text>
</View>
</View>
</View>
);
}
const mapStateToProps = (state) => ({
grades: state.publicApi.grades,
});
const mapDispatchToProps = {
pushToCart: userProduct.add,
};
export default connect(mapStateToProps, mapDispatchToProps)(Product);

@ -1,4 +1,4 @@
import React, { useState } from "react";
import React, { useState, useEffect } from "react";
import {
View,
Text,
@ -11,6 +11,8 @@ import {
StatusBar,
LayoutAnimation,
} from "react-native";
import { connect } from "react-redux";
import { userProduct, userFactor, publicApi } from "../../redux/actions";
import { Ionicons } from "@expo/vector-icons";
import Product from "./components/Product";
import Code from "./components/Code";
@ -19,8 +21,6 @@ import Navbar from "../../components/Navbar";
import Drawer from "../../components/Drawer";
import tw from "tailwind-react-native-classnames";
import { connect } from "react-redux";
const width = Dimensions.get("window").width;
const PriceStatus = ({ name, value, type }) => {
@ -50,9 +50,14 @@ const PriceStatus = ({ name, value, type }) => {
);
};
function ShoppingCart({}) {
function ShoppingCart({ userId, list, factorInfo, getList, getFactorInfo }) {
const [position, setPosition] = useState("100%");
useEffect(() => {
getList();
getFactorInfo({ userId });
}, []);
const setBoxPosition = () => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
setPosition(position === "100%" ? "0%" : "100%");
@ -74,7 +79,7 @@ function ShoppingCart({}) {
title: "سبد خرید",
bookmark: false,
qr: false,
back: true,
back: false,
}}
/>
<Drawer setBoxPosition={setBoxPosition} position={position} />
@ -82,7 +87,7 @@ function ShoppingCart({}) {
contentContainerStyle={styles.contentContainerStyle}
style={styles.container}
>
{[0, 1].map((product, index) => (
{list.length > 0 && list.map((product, index) => (
<Product key={index} product={product} />
))}
<Code />
@ -93,13 +98,17 @@ function ShoppingCart({}) {
>
<PriceStatus
name="مبلغ سبد خرید"
value="265000 تومان"
value={factorInfo?.sumPrice}
type="normal"
/>
<PriceStatus name="میزان تخفیف" value="0 تومان" type="error" />
<PriceStatus
name="میزان تخفیف"
value={factorInfo?.offPrice}
type="error"
/>
<PriceStatus
name="مالیات بر ارزش افزوده"
value="0 تومان"
value={factorInfo?.sumPrice * 0.009}
type="error"
/>
</View>
@ -122,7 +131,7 @@ function ShoppingCart({}) {
{ fontSize: width / 31, color: "#246E8A", fontFamily: "bold" },
]}
>
235.000 تومان
{factorInfo?.payPrice + ' ' + 'تومان'}
</Text>
</View>
<Pressable
@ -155,7 +164,22 @@ function ShoppingCart({}) {
);
}
export default ShoppingCart;
const mapStateToProps = (state) => ({
list: state.userProduct.list,
payPrice: state.userProduct.sum,
factorInfo: state.userFactor.info,
userId: state.user.status.id,
hasPhysical: state.userProduct.hasPhysical,
});
const mapDispatchToProps = {
getList: userProduct.list,
getInfo: userProduct.info,
getFactorInfo: userFactor.info,
payFactor: userFactor.payment,
};
export default connect(mapStateToProps, mapDispatchToProps)(ShoppingCart);
const styles = StyleSheet.create({
contentContainerStyle: {

@ -5,17 +5,17 @@ import Logo from "../../assets/images/logo.png";
const { width, height } = Dimensions.get("window");
function Splash({ navigation, isLogin}) {
function Splash({ navigation, isLogin }) {
useEffect(() => {
if (isLogin !== null) {
setTimeout(() => {
!isLogin
? navigation.navigate('Login')
: navigation.navigate('Root');
}, 2000);
isLogin === false
? navigation.navigate("Login")
: navigation.navigate("Root");
}, 3000);
}
}, [isLogin]);
return (
<View style={{ justifyContent: "center", alignItems: "center", flex: 1 }}>
<Image

@ -6,14 +6,22 @@ import {
Pressable,
TouchableOpacity,
} from "react-native";
import { connect } from "react-redux";
import { publicApi } from "../../../redux/actions";
import tw from "tailwind-rn";
import fontSize from "../../../constants/fontSize";
import Colors from "../../../constants/Colors";
import { useNavigation } from "@react-navigation/native";
const { width, height } = Dimensions.get("window");
const Season = ({ season }) => {
const duration = (value) => {
const minute = value % 60;
const hour = Math.round(value / 60);
return (hour > 0 ? hour + " " + "ساعت" : "") + " " + minute + " " + "دقیقه";
};
const Season = ({ season, toggle, activeSeason, realSeasons, seasonName }) => {
// const [selectedSeason, setSelectedSeason] = useState(null);
const navigation = useNavigation();
const [activeSeason, setActiveSeason] = useState(null);
const Unit = ({ unit }) => {
return (
<View
@ -37,7 +45,7 @@ const Season = ({ season }) => {
style={[
{
fontFamily: "regular",
fontSize: width / 34,
fontSize: fontSize.sm,
color: Colors.theme1.light.blue5,
},
]}
@ -48,16 +56,16 @@ const Season = ({ season }) => {
style={[
{
fontFamily: "regular",
fontSize: width / 36,
fontSize: fontSize.sm,
color: Colors.theme1.light.blue5,
},
]}
>
{unit.duration}
{duration(unit.duration)}
</Text>
</View>
<View style={[tw("w-full flex flex-row-reverse")]}>
{unit.play && (
{1 && (
<Pressable
style={[
tw("flex flex-1 flex-row items-center py-1.5 px-2"),
@ -66,14 +74,20 @@ const Season = ({ season }) => {
borderColor: Colors.theme1.light.blue3,
},
]}
onPress={() => navigation.navigate("VideoDisplay")}
onPress={() =>
navigation.navigate("VideoDisplay", {
season : season,
unit : unit,
name : seasonName
})
}
>
<Text
style={{
width: "100%",
textAlign: "center",
fontFamily: "regular",
fontSize: width / 34,
fontSize: fontSize.sm,
color: Colors.theme1.light.blue5,
}}
>
@ -81,7 +95,7 @@ const Season = ({ season }) => {
</Text>
</Pressable>
)}
{unit.download && (
{1 && (
<Pressable
style={tw("flex flex-1 flex-row items-center py-1.5 px-2")}
>
@ -90,7 +104,7 @@ const Season = ({ season }) => {
width: "100%",
textAlign: "center",
fontFamily: "regular",
fontSize: width / 34,
fontSize: fontSize.sm,
color: Colors.theme1.light.blue5,
}}
>
@ -111,38 +125,49 @@ const Season = ({ season }) => {
),
{ backgroundColor: Colors.theme1.light.blue5 },
]}
onPress={() =>
setActiveSeason(season.name === activeSeason ? null : season.name)
}
onPress={() => toggle(season[0].categoryId)}
>
<Text
style={[
{
fontFamily: "regular",
fontSize: width / 34,
fontSize: fontSize.sm,
color: "white",
},
]}
>
{season.name}
{
realSeasons.filter((item) => item.id === season[0].categoryId)[0]
.name
}
</Text>
<Text
{/* <Text
style={[
{
fontFamily: "regular",
fontSize: width / 36,
fontSize: fontSize.sm,
color: "white",
},
]}
>
{season.duration}
</Text>
</Text> */}
</TouchableOpacity>
{season.name === activeSeason &&
season.units.map((unit, index) => <Unit unit={unit} key={index} />)}
{season[0].categoryId === activeSeason &&
season.map((unit, index) => <Unit unit={unit} key={index} />)}
</View>
);
};
export default Season;
const mapStateToProps = (state) => ({
activeSeason: state.publicApi.activeCategory,
realSeasons: state.publicApi.bookInfo?.categories,
vodDuration: state.publicApi.bookInfo?.vodDuration,
});
const mapDispatchToProps = {
toggle: publicApi.activeCategory,
};
export default connect(mapStateToProps, mapDispatchToProps)(Season);

@ -1,4 +1,4 @@
import React, { useState } from "react";
import React, { useState, useEffect } from "react";
import {
View,
StyleSheet,
@ -11,54 +11,29 @@ import {
Text,
} from "react-native";
import { connect } from "react-redux";
import userImage from "./assets/user.png";
import poster from "./assets/poster.png";
import {publicApi} from '../../redux/actions';
import Navbar from "../../components/Navbar";
import Drawer from "../../components/Drawer";
import Divider from "../../components/Divider";
import Season from "./components/Season";
import tw from "tailwind-rn";
import fontSize from '../../constants/fontSize';
const { height, width } = Dimensions.get("window");
function Product({
product = {
type: "کتاب ها",
name: "ریاضی",
price: "145.000 تومان",
imageUrl: "https://dnvn.ir/api/v1/file/2105",
poster: poster,
grade: "پایه هفتم ابتدایی",
seasons: [
{
name: "فصل اول: مباحث جوشش مواد مذاب در مرکز زمین",
duration: "2:30:13",
units: [
{
name: "مقدمه جالب توجه نویسنده کتاب برای شما",
duration: "14:30",
download: true,
play: true,
},
{
name: "چگونگی ساخت نیروگاههای برقی ",
duration: "14:30",
download: false,
play: true,
},
{
name: "آیا گوگل از ما دزدی میکند ؟",
duration: "14:30",
download: true,
play: true,
},
],
},
],
},
route,
getBook,
book,
seasons,
grades,
}) {
const [position, setPosition] = useState("100%");
useEffect(() => {
getBook({bookId : route.params.id });
},[]);
const setBoxPosition = () => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
setPosition(position === "100%" ? "0%" : "100%");
@ -97,11 +72,11 @@ function Product({
]}
>
<Image
source={product.poster}
source={{uri : `https://dnvn.ir/api/v1/file/${book?.fileIds}`}}
style={tw("w-full rounded-md h-full absolute left-0 top-0")}
/>
<Image
source={{ uri: product.imageUrl }}
source={{ uri: `https://dnvn.ir/api/v1/file/${book?.fileIds}` }}
style={[
tw("rounded-md h-full rounded-md ml-2"),
{ width: 70, height: 100 },
@ -121,30 +96,30 @@ function Product({
style={{
marginTop: 5,
color: "#05335F",
fontSize: width / 21,
fontSize: fontSize.xl,
marginBottom: 0,
fontFamily: "bold",
}}
>
{product.name}
{book?.name}
</Text>
<Text
style={{
color: "#196EC0",
fontSize: width / 37,
fontSize: fontSize.sm,
marginBottom: 5,
fontFamily: "light",
}}
>
{product.grade}
{'پایه' + ' ' + grades[book?.gradeId]}
</Text>
</View>
<Divider type={"vertical"} />
</View>
</View>
<View style={tw("flex flex-col")}>
{product.seasons.map((season, index) => (
<Season season={season} key={index} />
{seasons?.map((season, index) => (
<Season season={season} key={index} id={route.params.id} seasonName={book?.name} />
))}
</View>
</ScrollView>
@ -164,4 +139,14 @@ const styles = StyleSheet.create({
paddingHorizontal: 16,
},
});
export default Product;
const mapStateToProps = (state) => ({
book : state.publicApi.bookInfo,
seasons : state.publicApi.categories,
grades : state.publicApi.grades
});
const mapDispatchToProps = {
getBook: publicApi.bookInfo
}
export default connect(mapStateToProps, mapDispatchToProps)(Product);

@ -1,23 +1,23 @@
import React, { useState } from "react";
import {
View,
Text,
Dimensions,
Pressable,
} from "react-native";
import { View, Text, Dimensions, Pressable } from "react-native";
import { connect } from "react-redux";
import { publicApi } from "../../../../redux/actions";
import tw from "tailwind-rn";
import Colors from "../../../../constants/Colors";
import { useNavigation } from "@react-navigation/native";
const { width, height } = Dimensions.get("window");
const Season = ({ season }) => {
const Season = ({ season, activeUnit, name }) => {
const navigation = useNavigation();
const Unit = ({ unit }) => {
return (
<View
style={[
tw("w-full flex flex-col rounded-md overflow-hidden mb-3"),
{ borderWidth: 1, borderColor: Colors.theme1.light.blue3 },
{
borderWidth: 1,
borderColor: Colors.theme1.light.blue3,
},
]}
>
<View
@ -28,6 +28,7 @@ const Season = ({ season }) => {
{
borderBottomWidth: 1,
borderColor: Colors.theme1.light.blue3,
backgroundColor: activeUnit === unit ? "#aaa" : "transparent",
},
]}
>
@ -36,37 +37,44 @@ const Season = ({ season }) => {
{
fontFamily: "regular",
fontSize: width / 34,
color: Colors.theme1.light.blue5,
color:
activeUnit === unit ? "white" : Colors.theme1.light.blue5,
},
]}
>
{unit.name}
</Text>
<Text
{/* <Text
style={[
{
fontFamily: "regular",
fontSize: width / 36,
color: Colors.theme1.light.blue5,
backgroundColor : 'white',
backgroundColor: "white",
},
]}
>
{unit.duration}
</Text>
</Text> */}
</View>
<View style={[tw("w-full flex flex-row-reverse")]}>
{unit.play && (
{1 && (
<Pressable
style={[
tw("flex flex-1 flex-row items-center py-1.5 px-2"),
{
borderLeftWidth: 1,
borderColor: Colors.theme1.light.blue3,
backgroundColor: 'white',
backgroundColor: "white",
},
]}
onPress={() => navigation.navigate("VideoDisplay")}
onPress={() =>
navigation.navigate("VideoDisplay", {
season: season,
unit: unit,
name: name,
})
}
>
<Text
style={{
@ -81,7 +89,7 @@ const Season = ({ season }) => {
</Text>
</Pressable>
)}
{unit.download && (
{1 && (
<Pressable
style={tw("flex flex-1 flex-row items-center py-1.5 px-2")}
>
@ -121,7 +129,7 @@ const Season = ({ season }) => {
},
]}
>
{season.name}
{name}
</Text>
<Text
style={[
@ -135,12 +143,22 @@ const Season = ({ season }) => {
{season.duration}
</Text>
</Pressable>
{season.units.map((unit, index) => (
{season.map((unit, index) => (
<Unit unit={unit} key={index} />
))}
</View>
);
};
export default Season;
const mapStateToProps = (state) => ({
selectedVideo: state.publicApi.selectedVideo,
realSeasons: state.publicApi.bookInfo?.categories,
vods: state.publicApi.bookSection?.vods,
userid: state.user.status.id,
});
const mapDispatchToProps = {
setVideoActive: publicApi.setVideoActive,
};
export default connect(mapStateToProps, mapDispatchToProps)(Season);

@ -1,4 +1,4 @@
import React, { useState } from "react";
import React, { useState, useEffect } from "react";
import {
View,
StyleSheet,
@ -9,54 +9,39 @@ import {
LayoutAnimation,
} from "react-native";
import { connect } from "react-redux";
import { book, publicApi } from "../../redux/actions";
import Navbar from "../../components/Navbar";
import Drawer from "../../components/Drawer";
import { Video, AVPlaybackStatus } from "expo-av";
import tw from "tailwind-rn";
import tw from 'tailwind-rn';
import * as ScreenOrientation from 'expo-screen-orientation';
import Season from "./components/Season";
import movie from "../../assets/video.mp4";
const { height, width } = Dimensions.get("window");
function VideoDisplay({
product = {
type: "کتاب ها",
name: "ریاضی",
grade: "پایه هفتم ابتدایی",
video: movie,
season: {
name: "فصل اول: مباحث جوشش مواد مذاب در مرکز زمین",
duration: "2:30:13",
units: [
{
name: "مقدمه جالب توجه نویسنده کتاب برای شما",
duration: "14:30",
download: true,
play: true,
},
{
name: "چگونگی ساخت نیروگاههای برقی ",
duration: "14:30",
download: false,
play: true,
},
{
name: "آیا گوگل از ما دزدی میکند ؟",
duration: "14:30",
download: true,
play: true,
},
],
},
},
}) {
function VideoDisplay({ route, selectedVideo }) {
const video = React.useRef(null);
const [status, setStatus] = React.useState({});
const [position, setPosition] = useState("100%");
useEffect(() => {}, []);
const setBoxPosition = () => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
setPosition(position === "100%" ? "0%" : "100%");
};
function setOrientation() {
if (Dimensions.get('window').height > Dimensions.get('window').width) {
//Device is in portrait mode, rotate to landscape mode.
ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.LANDSCAPE);
}
else {
//Device is in landscape mode, rotate to portrait mode.
ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.PORTRAIT);
}
}
return (
<SafeAreaView
style={{
@ -85,13 +70,20 @@ function VideoDisplay({
<Video
ref={video}
style={{ width: "100%", height: (width * 9) / 16 - 16 }}
source={product.video}
source={{
uri: `https://dnvn.ir/api/v1/file/${selectedVideo?.fileIds}`,
}}
useNativeControls
resizeMode="cover"
onFullscreenUpdate={setOrientation}
isLooping
onPlaybackStatusUpdate={(status) => setStatus(() => status)}
/>
<Season season={product.season} />
<Season
season={route.params.season}
activeUnit={route.params.unit}
name={route.params.name}
/>
</View>
</ScrollView>
</SafeAreaView>
@ -110,4 +102,11 @@ const styles = StyleSheet.create({
paddingHorizontal: 16,
},
});
export default VideoDisplay;
const mapStateToProps = (state) => ({
selectedVideo: state.publicApi.selectedVideo,
});
const mapDispatchToProps = {};
export default connect(mapStateToProps, mapDispatchToProps)(VideoDisplay);

@ -2,39 +2,39 @@ import React from "react";
import { View, FlatList, Pressable, Image, Dimensions, Text } from "react-native";
import {useNavigation} from '@react-navigation/native';
import tw from "tailwind-rn";
import fontSize from '../../../constants/fontSize';
const { width, height } = Dimensions.get("window");
import Header from "../../Home/components/Header";
import posterImage from "../../Products/assets/poster.png";
function MostViewedVideo({}) {
function MostViewedVideo({videos, grades}) {
const navigation = useNavigation();
const Video = ({ video }) => {
return (
<Pressable
style={[
{
width : 320,
width : width / 1.5,
},
tw("flex flex-col items-end rounded-md ml-4"),
tw("flex flex-col items-end rounded-md ml-6"),
]}
onPress={() => navigation.navigate("Video")}
onPress={() => navigation.navigate("Video", {id: video.id})}
>
<View
style={[
tw(
"w-full flex flex-row flex-1 justify-between items-center relative overflow-hidden"
),
{ height: height / 3.8 },
{ height: height / 4 },
]}
>
<Image
source={video.poster}
source={{uri : `https://dnvn.ir/api/v1/file/${video.fileIds}`}}
style={tw("w-full h-full absolute left-0 top-0 rounded-md")}
/>
<Image
source={{ uri: video.imageUrl }}
source={{ uri: `https://dnvn.ir/api/v1/file/${video.fileIds}` }}
style={[
tw("rounded-md h-full absolute left-2 inset-y-1/4 rounded-md"),
{ width: 70, height: 100 },
@ -43,8 +43,9 @@ function MostViewedVideo({}) {
</View>
<Text
style={{
fontSize: width / 27,
fontSize: fontSize.lg,
marginTop: 5,
paddingRight : 4,
color: "#05335F",
fontFamily: "bold",
}}
@ -53,7 +54,7 @@ function MostViewedVideo({}) {
</Text>
<View
style={tw("w-full flex flex-row justify-between items-center")}
style={tw("w-full flex flex-row justify-between items-center px-1")}
>
<Text
style={[
@ -61,22 +62,22 @@ function MostViewedVideo({}) {
{
marginTop: 10,
color: "#132F52",
fontFamily: "light",
fontSize: width / 37,
fontFamily: "bold",
fontSize: fontSize.sm,
},
]}
>
{video.price}
{video.product[0].price + ' ' + 'تومان'}
</Text>
<Text
style={{
color: "#196EC0",
fontFamily: "light",
fontSize: width / 37,
fontSize: fontSize.sm,
marginTop: 5,
}}
>
{"پایه" + " " + video.grade}
{"پایه" + " " + grades[video.gradeId]}
</Text>
</View>
</Pressable>
@ -86,22 +87,17 @@ function MostViewedVideo({}) {
<View style={tw("w-full flex flex-col w-full")}>
<Header title="پربازدیدترین" />
<FlatList
showsHorizontalScrollIndicator={false}
horizontal={true}
inverted={true}
style={tw("pb-1.5 mt-3 flex flex-row w-full")}
data={[0,1,2]}
data={videos}
renderItem={({ item }) => (
<Video
video={{
name: "ریاضی",
price: "145.000 تومان",
grade: "4",
imageUrl: "https://dnvn.ir/api/v1/file/2105",
poster: posterImage,
}}
video={item}
/>
)}
keyExtractor={(item) => item}
keyExtractor={(item) => item.id}
/>
</View>
);

@ -2,13 +2,14 @@ import React from "react";
import { View, Pressable, Image, Dimensions, Text } from "react-native";
import { useNavigation } from "@react-navigation/native";
import tw from "tailwind-rn";
import fontSize from "../../../constants/fontSize";
const { width, height } = Dimensions.get("window");
import Header from "../../Home/components/Header";
import posterImage from "../../Products/assets/poster.png";
const NewestVideo = () => {
const NewestVideo = ({ videos, grades }) => {
const navigation = useNavigation();
const Video = ({ video }) => {
return (
@ -19,18 +20,18 @@ const NewestVideo = () => {
},
tw("flex flex-col items-end mb-4"),
]}
onPress={() => navigation.navigate("Video")}
onPress={() => navigation.navigate("Video", { id: video.id })}
>
<Image
source={video.poster}
source={{ uri: `https://dnvn.ir/api/v1/file/${video.fileIds}` }}
style={[
tw("rounded-sm"),
{ width: '100%', height: ((width / 2.5 * 3 / 4)) },
tw("rounded-md"),
{ width: "100%", height: ((width / 2.5) * 3) / 4 },
]}
/>
<Text
style={{
fontSize: width / 27,
fontSize: fontSize.base,
marginTop: 5,
color: "#05335F",
fontFamily: "bold",
@ -42,11 +43,11 @@ const NewestVideo = () => {
style={{
color: "#196EC0",
fontFamily: "light",
fontSize: width / 37,
fontSize: fontSize.sm,
marginTop: 5,
}}
>
{"پایه" + " " + video.grade}
{"پایه" + " " + grades[video.gradeId]}
</Text>
</Pressable>
);
@ -55,17 +56,8 @@ const NewestVideo = () => {
<View style={tw("w-full flex flex-col w-full")}>
<Header title="جدیدترین دورهها" />
<View style={tw("w-full flex flex-row flex-wrap justify-between mt-3")}>
{[0, 1, 2, 3].map((video, index) => (
<Video
video={{
name: "ریاضی",
price: "145.000 تومان",
grade: "4",
imageUrl: "https://dnvn.ir/api/v1/file/2105",
poster: posterImage,
}}
key={index}
/>
{videos.map((video, index) => (
<Video video={video} key={index} />
))}
</View>
</View>

@ -2,6 +2,8 @@ import React from "react";
import { View, Text, FlatList, TouchableOpacity } from "react-native";
import { connect } from "react-redux";
import tw from "tailwind-rn";
import fontSize from '../../../constants/fontSize';
import Header from "../../Home/components/Header";
const VerticalGradeFilter = ({ grades }) => {
@ -9,11 +11,11 @@ const VerticalGradeFilter = ({ grades }) => {
return (
<TouchableOpacity
style={[
tw("p-3 rounded-sm border border-gray-300 mt-2 ml-2"),
tw("px-3 py-1.5 rounded-sm border border-gray-300 mt-2 ml-2"),
{ backgroundColor: "#f9f9f9" },
]}
>
<Text style={[tw("text-xs text-gray-600"), { fontFamily: "light" }]}>
<Text style={[tw("text-gray-600"), { fontFamily: "light", fontSize: fontSize.sm }]}>
{grades[grade]}
</Text>
</TouchableOpacity>
@ -23,6 +25,7 @@ const VerticalGradeFilter = ({ grades }) => {
<View style={tw("w-full flex flex-col mt-3")}>
<Header title={"پایه تحصیلی"} />
<FlatList
showsHorizontalScrollIndicator={false}
style={tw("flex flex-row w-full pb-1.5")}
horizontal={true}
inverted={true}
@ -30,14 +33,9 @@ const VerticalGradeFilter = ({ grades }) => {
renderItem={({ item }) => <Grade grade={item} />}
keyExtractor={(item) => item}
/>
</View>
);
};
const mapStateToProps = (state) => ({
grades: state.publicApi.grades,
});
export default connect(mapStateToProps)(VerticalGradeFilter);
export default VerticalGradeFilter;

@ -1,4 +1,4 @@
import React, { useState } from "react";
import React, { useState, useEffect } from "react";
import {
View,
StyleSheet,
@ -9,7 +9,8 @@ import {
Platform,
LayoutAnimation,
} from "react-native";
import tw from "tailwind-rn";
import { connect } from "react-redux";
import {book} from '../../redux/actions';
import Navbar from "../../components/Navbar";
import Drawer from "../../components/Drawer";
import Search from "../../components/Search";
@ -21,10 +22,14 @@ import NewestVideo from "./components/NewestVideo";
const width = Dimensions.get("window").width;
function Videos(props) {
function Videos({ grades, videos, getVideos }) {
const [search, setSearch] = useState("");
const [position, setPosition] = useState("100%");
useEffect(() => {
getVideos();
},[]);
const setBoxPosition = () => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
setPosition(position === "100%" ? "0%" : "100%");
@ -59,11 +64,15 @@ function Videos(props) {
onChange={setSearch}
placeholder={"نام کتاب یا دوره را جستجو کنید"}
/>
<VerticalGradeFilter />
<VerticalGradeFilter grades={grades} />
<Divider type={"vertical"} />
<MostViewedVideo />
{videos.length > 0 && (
<>
<MostViewedVideo videos={videos} grades={grades} />
<Divider type={"vertical"} />
<NewestVideo />
<NewestVideo videos={videos.sort((a,b) => a.updatedAt - b.updatedAt).slice(0,4)} grades={grades} />
</>
)}
</ScrollView>
</SafeAreaView>
);
@ -84,4 +93,13 @@ const styles = StyleSheet.create({
},
});
export default Videos;
const mapStateToProps = (state) => ({
grades: state.publicApi.grades,
videos: state.book.list,
grades: state.publicApi.grades,
});
const mapDispatchToProps = {
getVideos : book.list
}
export default connect(mapStateToProps, mapDispatchToProps)(Videos);

@ -0,0 +1,12 @@
export const fontSizeHandler = (
currentWidth,
minimumFontSize,
maximumFontSize,
minimumWidth,
maximumWidth
) => {
const alpha = (currentWidth - minimumWidth) / (maximumWidth - minimumWidth);
const deltaFontSize = maximumFontSize - minimumFontSize;
const currentFontSize = minimumFontSize + deltaFontSize * alpha;
return currentFontSize;
};

@ -2946,6 +2946,13 @@ expo-modules-core@0.6.3:
compare-versions "^3.4.0"
invariant "^2.2.4"
expo-screen-orientation@~4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/expo-screen-orientation/-/expo-screen-orientation-4.1.1.tgz#f61c241da8266baeb6e7e2c3427b5ca97e0c889b"
integrity sha512-qfJzgJ78wyG+BBVv5gdmAA6PUOY8FM++PFb0osAcAn2v4qSlz0V8rBCBpeBvFXc3fIhzspoGZdpEsnGtlqFQ5g==
dependencies:
"@expo/config-plugins" "^4.0.2"
expo-splash-screen@~0.14.0:
version "0.14.1"
resolved "https://registry.yarnpkg.com/expo-splash-screen/-/expo-splash-screen-0.14.1.tgz#7647c8b98c679b8313d24a7c14729402c3c16631"

Loading…
Cancel
Save