reza added blogs page

master
Reza_ashrafi 3 years ago
parent d13297bd6f
commit dbd05f287a
  1. 4
      navigation/index.js
  2. 1
      package.json
  3. 20
      src/redux/actions/blog.js
  4. 41
      src/redux/reducers/blog.js
  5. 119
      src/screens/Blogs/index.js
  6. 65
      src/screens/Blogs/layouts/Hashtags.js
  7. 36
      src/screens/Blogs/layouts/Header.js
  8. 68
      src/screens/Blogs/layouts/New.js
  9. 134
      src/screens/Blogs/layouts/Single.js
  10. 164
      src/screens/Blogs/layouts/Target.js
  11. 5
      yarn.lock

@ -32,6 +32,8 @@ import Address from "../src/screens/Address";
import Profile from "../src/screens/Profile"; import Profile from "../src/screens/Profile";
import ProfileBookmark from "../src/screens/Profile/components/ProfileBookmark"; import ProfileBookmark from "../src/screens/Profile/components/ProfileBookmark";
import ProfileAddress from "../src/screens/Profile/components/ProfileAddress"; import ProfileAddress from "../src/screens/Profile/components/ProfileAddress";
import Blogs from "../src/screens/Blogs";
import Blog from "../src/screens/Blog";
//style //style
import fontSize from "../src/constants/fontSize"; import fontSize from "../src/constants/fontSize";
@ -343,6 +345,8 @@ const HomeStackScreen = () => {
<HomeStack.Screen name="Products" component={Products} /> <HomeStack.Screen name="Products" component={Products} />
<HomeStack.Screen name="Video" component={Video} /> <HomeStack.Screen name="Video" component={Video} />
<HomeStack.Screen name="Product" component={Product} /> <HomeStack.Screen name="Product" component={Product} />
<HomeStack.Screen name="Blogs" component={Blogs} />
<HomeStack.Screen name="Blog" component={Blog} />
</HomeStack.Navigator> </HomeStack.Navigator>
); );
}; };

@ -26,6 +26,7 @@
"expo-camera": "~12.1.0", "expo-camera": "~12.1.0",
"expo-device": "~4.1.0", "expo-device": "~4.1.0",
"expo-font": "^10.0.4", "expo-font": "^10.0.4",
"expo-linear-gradient": "~11.0.3",
"expo-screen-orientation": "~4.1.1", "expo-screen-orientation": "~4.1.1",
"expo-status-bar": "~1.2.0", "expo-status-bar": "~1.2.0",
"i18next": "^21.6.3", "i18next": "^21.6.3",

@ -4,24 +4,8 @@ const blog = {
(data = {}) => (data = {}) =>
async (dispatch) => async (dispatch) =>
await proxy.get("public/blogList", data, { dispatch }), await proxy.get("public/blogList", data, { dispatch }),
// update: info: (data) => async (dispatch) =>
// (data = {}, data2 = {}) => await proxy.get("public/blogInfo", data, { dispatch }),
// async (dispatch : Dispatch) => {
// await proxy.put("blog/update", data);
// await proxy.get("blog/list", data2, { dispatch });
// },
// add:
// (data = {}, data2 = {}) =>
// async (dispatch : Dispatch) => {
// await proxy.post("blog/add", data);
// await proxy.get("blog/list", data2, { dispatch });
// },
// del:
// (data = {}, data2 = {}) =>
// async (dispatch : Dispatch) => {
// await proxy.delete("blog/delete", data);
// await proxy.get("blog/list", data2, { dispatch });
// },
}; };
export default blog; export default blog;

@ -2,23 +2,48 @@ const initialState = {
loading: false, loading: false,
error: null, error: null,
list: [], list: [],
info: null,
hashtags: [
{
title: "فناوری اطلاعات",
color: "#019BC3",
},
{
title: "سخت افزار",
color: "#7CC301",
},
{
title: "آموزشی",
color: "#C5B90C",
},
{
title: "فرهنگی",
color: "#C2684D",
},
{
title: "معرفی کتاب",
color: "#8B4DC2",
},
{
title: "مهارت آموزی",
color: "#780D6D",
},
{
title: "پیشرفت شخصی",
color: "#E63F15",
},
],
}; };
export default function blog(state = initialState, action) { export default function blog(state = initialState, action) {
let { type, data } = action; let { type, data } = action;
switch (type) { switch (type) {
case "public/blogList": case "public/blogList":
return { ...state, loading: false, list: data, error: null }; return { ...state, loading: false, list: data, error: null };
// case "blog/update": case "public/blogInfo":
// return { ...state, loading: false, error: null }; return { ...state, loading: false, error: null, blog: data };
// case "blog/add":
// return { ...state, loading: false, error: null };
// case "blog/delete":
// return { ...state, loading: false, error: null };
/////////////
case "blog/loading": case "blog/loading":
return { ...state, loading: true }; return { ...state, loading: true };
case "blog/error": case "blog/error":
// toast.error(data.message);
return { ...state, loading: false, error: data.message }; return { ...state, loading: false, error: data.message };
default: default:
return state; return state;

@ -1,13 +1,114 @@
import React from 'react' import React from "react";
import { View, Text } from 'react-native'; import {
import {connect} from 'react-redux'; View,
StyleSheet,
ScrollView,
SafeAreaView,
Platform,
StatusBar,
LayoutAnimation,
FlatList,
} from "react-native";
import { connect } from "react-redux";
import { blog } from "../../redux/actions";
//components
import Navbar from "../../components/Navbar";
import Drawer from "../../components/Drawer";
import Hashtags from "./layouts/Hashtags";
import Header from "./layouts/Header";
import Single from "./layouts/Single";
import New from "./layouts/New";
import Target from "./layouts/Target";
//style
import tw from "tailwind-rn";
import fontSize from "../../constants/fontSize";
import Colors from "../../constants/Colors";
function Blogs({ getList, blogs }) {
const [position, setPosition] = React.useState("100%");
React.useEffect(() => {
getList();
}, []);
const setBoxPosition = () => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
setPosition(position === "100%" ? "0%" : "100%");
};
function Blogs({}) {
return ( return (
<View> <SafeAreaView
<Text></Text> style={{
</View> paddingTop: Platform.OS === "android" ? StatusBar.currentHeight : 0,
) position: "relative",
}}
>
<Navbar
setBoxPosition={setBoxPosition}
headerOptions={{
logo: true,
menu: false,
hamburgerMenu: true,
title: "",
bookmark: false,
qr: true,
back: false,
}}
/>
<Drawer setBoxPosition={setBoxPosition} position={position} />
<ScrollView
contentContainerStyle={styles.contentContainerStyle}
style={[styles.container, tw("flex px-4")]}
>
<Hashtags />
<Single />
<Header title={"تازهترینها از وبلاگ"} />
<FlatList
showsHorizontalScrollIndicator={false}
horizontal={true}
inverted={true}
style={[tw("flex flex-row mt-3 pb-3")]}
data={blogs}
renderItem={({ item }) => <New blog={item} />}
keyExtractor={(item) => item.id}
/>
<Header title={"پیشنهاد سردبیر"} />
<FlatList
showsHorizontalScrollIndicator={false}
horizontal={true}
inverted={true}
style={[tw("flex flex-row mt-3 pb-3")]}
data={blogs}
renderItem={({ item }) => <New blog={item} />}
keyExtractor={(item) => item.id}
/>
<Header title={"از دنیای آموزش"} />
<Target blogs={blogs.slice(0,3)} />
</ScrollView>
</SafeAreaView>
);
} }
export default Blogs; const mapStateToProps = (state) => ({
blogs: state.blog.list,
});
const mapDispatchToProps = {
getList: blog.list,
};
export default connect(mapStateToProps, mapDispatchToProps)(Blogs);
const styles = StyleSheet.create({
contentContainerStyle: {
paddingBottom: 100,
},
container: {
backgroundColor: "white",
paddingVertical: 0,
paddingHorizontal: 0,
},
});

@ -0,0 +1,65 @@
import React from "react";
import { View, Text, FlatList, Appearance } from "react-native";
import { connect } from "react-redux";
import Svg, { Path } from "react-native-svg";
//style
import tw from "tailwind-rn";
import fontSize from "../../../constants/fontSize";
import Colors from "../../../constants/Colors";
export const Hashtags = ({ hashtags }) => {
const colorScheme = Appearance.getColorScheme();
const Hashtag = ({ hashtag }) => {
return (
<Text
style={{
fontFamily: "bold",
fontSize: fontSize.base,
color: hashtag.color,
marginHorizontal: 8,
}}
>
{"#" + " " + hashtag.title}
</Text>
);
};
return (
<View
style={[
tw(
"flex flex-row-reverse py-1 pl-3 rounded-full items-center w-full mb-7"
),
{borderWidth : 2, borderColor : Colors.theme1[colorScheme].greenFF1}
]}
>
<Svg xmlns="http://www.w3.org/2000/svg" width={31.486} height={19.692}>
<Path
d="M29.012 2.475 16.628 14.859 11.91 7.782l-9.435 9.436"
fill="none"
stroke="#5db916"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={3.5}
/>
</Svg>
<FlatList
showsHorizontalScrollIndicator={false}
horizontal={true}
inverted={true}
style={[tw("flex flex-row mt-3 pb-3 mr-2")]}
data={hashtags}
renderItem={({ item }) => <Hashtag hashtag={item} />}
keyExtractor={(item) => item.id}
/>
</View>
);
};
const mapStateToProps = (state) => ({
hashtags: state.blog.hashtags,
});
const mapDispatchToProps = {};
export default connect(mapStateToProps, mapDispatchToProps)(Hashtags);

@ -0,0 +1,36 @@
import React from "react";
import { View, Text, Appearance } from "react-native";
import { connect } from "react-redux";
//style
import tw from "tailwind-rn";
import fontSize from "../../../constants/fontSize";
import Colors from "../../../constants/Colors";
export const Header = ({ title }) => {
const colorScheme = Appearance.getColorScheme();
return (
<View style={tw("flex flex-row-reverse w-full items-center mt-5 mb-4")}>
<Text
style={[
tw("py-2.5 pr-2.5 pl-5"),
{
fontSize: fontSize.base,
color: Colors.theme1[colorScheme].white,
backgroundColor: Colors.theme1[colorScheme].black,
fontFamily : 'bold'
},
]}
>
{title}
</Text>
<View style={{ width : '100%', backgroundColor : Colors.theme1[colorScheme].grayE3, height : 2 }}></View>
</View>
);
};
const mapStateToProps = (state) => ({});
const mapDispatchToProps = {};
export default connect(mapStateToProps, mapDispatchToProps)(Header);

@ -0,0 +1,68 @@
import React from "react";
import {
View,
Text,
Dimensions,
Pressable,
Image,
Appearance,
Platform,
} from "react-native";
import { connect } from "react-redux";
import { useNavigation } from "@react-navigation/native";
//style
import tw from "tailwind-rn";
import fontSize from "../../../constants/fontSize";
import Colors from "../../../constants/Colors";
const { height, width } = Dimensions.get("window");
const ios = Platform.OS === "ios";
export const New = ({ blog }) => {
const navigation = useNavigation();
const colorScheme = Appearance.getColorScheme();
return (
<Pressable
style={[
tw(`flex flex-col ml-4 ${ios ? "items-end" : ""}`),
{
width: width / 2,
},
]}
onPress={() => navigation.push("Blog", { id: blog.id })}
>
<Image
source={{ uri: `https://dnvn.ir/api/v1/file/${blog?.fileIds}` }}
style={[
tw("rounded-md"),
{ width: "100%", height: ((width / 2) * 3) / 4 },
]}
/>
<Text
style={{
fontSize: fontSize.base,
fontFamily: "bold",
color: Colors.theme1[colorScheme].gray20,
marginTop: 5,
textAlign: ios ? "right" : "",
}}
>
{blog?.title}
</Text>
<Text
style={{
fontSize: fontSize.sm,
fontFamily: "regular",
color: Colors.theme1[colorScheme].gray2077,
textAlign: ios ? "right" : "",
marginTop: 5,
}}
>
هر نفسی که فرو می بریم، مرگی را که مدام به ما دست اندازی میکند پس
</Text>
</Pressable>
);
};
export default New;

@ -0,0 +1,134 @@
import React from "react";
import {
Pressable,
View,
Text,
Dimensions,
Image,
Appearance,
} from "react-native";
import { connect } from "react-redux";
import { LinearGradient } from "expo-linear-gradient";
import { useNavigation } from "@react-navigation/native";
//style
import tw from "tailwind-rn";
import fontSize from "../../../constants/fontSize";
import Colors from "../../../constants/Colors";
const { height, width } = Dimensions.get("window");
export const Single = ({ blog }) => {
const navigation = useNavigation();
const colorScheme = Appearance.getColorScheme();
return (
<Pressable
style={tw("flex flex-col")}
onPress={() => navigation.push("Blog", { id: blog?.id })}
>
<View
style={[
tw("w-full rounded-md overflow-hidden relative"),
{
height: ((width - 32) * 3) / 4.5,
},
]}
>
<Image
source={{ uri: `https://dnvn.ir/api/v1/file/${blog?.fileIds}` }}
style={[tw("absolute left-0 top-0 w-full h-full ml-2")]}
/>
<LinearGradient
colors={["transparent", "rgba(0,0,0,0.8)"]}
start={{ x: 0.0, y: 0.0 }}
end={{ x: 0.0, y: 1.1 }}
style={tw(
"flex flex-col justify-end absolute top-0 left-0 z-10 w-full h-full pb-2 px-2"
)}
>
<View style={tw("w-full flex flex-row-reverse justify-between")}>
<View style={tw("flex flex-row-reverse")}>
<View
style={[
{ width: 50, height: 50, backgroundColor: "#aaa" },
tw("rounded-full ml-1"),
]}
></View>
<View style="flex flex-col py-2 justify-center">
<Text
style={[
tw("text-gray-100"),
{ fontFamily: "bold", fontSize: fontSize.tiny },
]}
>
{"نوشته از:" + " " + "کامران ایزدی"}
</Text>
<Text
style={[
tw("text-gray-100 mt-2"),
{ fontFamily: "bold", fontSize: fontSize.sm },
]}
>
{"سردبیر بخش وبلاگ دانوین"}
</Text>
</View>
</View>
<View style={tw("flex flex-col justify-center items-start")}>
<Text
style={[
tw("text-gray-100"),
{ fontFamily: "bold", fontSize: fontSize.sm },
]}
>
{"زمان مطالعه" + " " + "۳۰ دقیقه"}
</Text>
<Text
style={[
tw("mt-2 text-gray-100"),
{ fontFamily: "bold", fontSize: fontSize.sm },
]}
>
{"1400/11/24"}
</Text>
</View>
</View>
</LinearGradient>
</View>
<View style={tw("flex flex-col justify-between")}>
<View style={tw("flex flex-col mt-3")}>
<Text
style={{
fontFamily: "bold",
fontSize: fontSize.xl,
color: Colors.theme1[colorScheme].gray20,
}}
>
{blog?.title}
</Text>
<Text
style={{
fontFamily: "regular",
fontSize: fontSize.tiny,
color: Colors.theme1[colorScheme].gray2077,
lineHeight: 25,
marginTop: 10,
}}
>
هر نفسی که فرو می بریم، مرگی را که مدام به ما دست اندازی میکند پس
میزند... در نهایت این مرگ است که باید پیروز شود، زیرا از هنگام تولد
بخشی از سرنوشت ما شده و فقط مدت کوتاهی پیش از بلعیدن طعمه اش، با آن
بازی می کند. با این همه، ما تا آنجا که ممکن است، با علاقه فراوان{" "}
</Text>
</View>
</View>
</Pressable>
);
};
const mapStateToProps = (state) => ({
blog: state.blog.list[0],
});
const mapDispatchToProps = {};
export default connect(mapStateToProps, mapDispatchToProps)(Single);

@ -0,0 +1,164 @@
import React from "react";
import {
View,
Text,
Dimensions,
Pressable,
Image,
Appearance,
Platform,
} from "react-native";
import { connect } from "react-redux";
import { useNavigation } from "@react-navigation/native";
import { LinearGradient } from "expo-linear-gradient";
//style
import tw from "tailwind-rn";
import fontSize from "../../../constants/fontSize";
import Colors from "../../../constants/Colors";
const { height, width } = Dimensions.get("window");
const ios = Platform.OS === "ios";
const Target = ({ blogs }) => {
const navigation = useNavigation();
const colorScheme = Appearance.getColorScheme();
const Large = ({ blog }) => {
return (
<Pressable style={tw("flex flex-col w-full")}>
<View
className="relative w-full rounded-md overflow-hidden"
style={{ height: ((width - 32) / 4) * 3 }}
>
<Image
source={{ uri: `https://dnvn.ir/api/v1/file/${blog?.fileIds}` }}
style={tw("w-full h-full absolute left-0 top-0 rounded-md")}
/>
<LinearGradient
colors={["transparent", "rgba(0,0,0,0.8)"]}
start={{ x: 0.0, y: 0.0 }}
end={{ x: 0.0, y: 1.1 }}
style={tw(
"flex flex-col justify-end rounded-md absolute top-0 left-0 z-10 w-full h-full pb-2 px-2"
)}
></LinearGradient>
</View>
<Text
style={[
tw("my-3"),
{
fontFamily: "bold",
fontSize: fontSize.xl,
textAlign: ios ? "right" : "",
},
]}
>
{blog?.title}
</Text>
<View style={tw("w-full flex flex-row-reverse justify-between")}>
<View style={tw("flex flex-row-reverse")}>
<View
style={[
{ width: 40, height: 40, backgroundColor: "#ddd" },
tw("rounded-full ml-1"),
]}
></View>
<View
style={tw(
`flex flex-col py-2 justify-center ${ios ? "items-end" : ""}`
)}
>
<Text
style={[
{
fontFamily: "bold",
color: Colors.theme1[colorScheme].gray20,
fontSize: fontSize.tiny,
},
]}
>
{"نوشته از:" + " " + "کامران ایزدی"}
</Text>
<Text
style={[
{
fontFamily: "regular",
color: Colors.theme1[colorScheme].gray20,
fontSize: fontSize.xs,
},
]}
>
{"سردبیر بخش وبلاگ دانوین"}
</Text>
</View>
</View>
<View style={tw("flex flex-col justify-center items-start")}>
<Text
style={[
{
fontFamily: "bold",
color: Colors.theme1[colorScheme].gray20,
fontSize: fontSize.sm,
},
]}
>
{"زمان مطالعه" + " " + "۳۰ دقیقه"}
</Text>
<Text
style={[
tw("mt-0"),
{
fontFamily: "bold",
color: Colors.theme1[colorScheme].gray20,
fontSize: fontSize.sm,
},
]}
>
{"1400/11/24"}
</Text>
</View>
</View>
</Pressable>
);
};
const Small = ({ blog }) => {
return (
<Pressable style={[tw("flex flex-col"), { width: "48%" }]}>
<Image
source={{ uri: `https://dnvn.ir/api/v1/file/${blog?.fileIds}` }}
style={[
tw("w-full rounded-md"),
{ height: ((((width - 32) * 48) / 100) * 3) / 4 },
]}
/>
<View style={tw("flex flex-col justify-center")}>
<Text
style={[
tw("my-2"),
{
fontFamily: "bold",
fontSize: fontSize.lg,
textAlign: ios ? "right" : "",
},
]}
>
{blog?.title}
</Text>
</View>
</Pressable>
);
};
return (
<View style={tw("flex flex-col")}>
<Large blog={blogs[0]} />
<View style={tw("flex flex-row justify-between mt-3")}>
{blogs?.slice(1, 3).map((blog, index) => (
<Small blog={blog} key={index} />
))}
</View>
</View>
);
};
export default Target;

@ -3058,6 +3058,11 @@ expo-keep-awake@~10.0.1:
resolved "https://registry.yarnpkg.com/expo-keep-awake/-/expo-keep-awake-10.0.1.tgz#9f1176216c41eee20843c8232acfdca2bc32d334" resolved "https://registry.yarnpkg.com/expo-keep-awake/-/expo-keep-awake-10.0.1.tgz#9f1176216c41eee20843c8232acfdca2bc32d334"
integrity sha512-kcBtoDGkm3RRe6BpKDvR7gof/ErajEia38u92pRvNRctdh+p8AFO7GQuiipyg3iMfhcCFVTCIV7h3tuA0g/yDw== integrity sha512-kcBtoDGkm3RRe6BpKDvR7gof/ErajEia38u92pRvNRctdh+p8AFO7GQuiipyg3iMfhcCFVTCIV7h3tuA0g/yDw==
expo-linear-gradient@~11.0.3:
version "11.0.3"
resolved "https://registry.yarnpkg.com/expo-linear-gradient/-/expo-linear-gradient-11.0.3.tgz#bc559b9a251c9dc8aa37fb6c66c7a497fe92993c"
integrity sha512-LuzTM5+iEHCQfC2TBHAAI+ZjPvf0TvGiA7GYMsyTnakGA2r4JtsV8Ah/miQPKhfG06jLDOo4grUoSMGqbmSrEw==
expo-modules-autolinking@0.5.2: expo-modules-autolinking@0.5.2:
version "0.5.2" version "0.5.2"
resolved "https://registry.yarnpkg.com/expo-modules-autolinking/-/expo-modules-autolinking-0.5.2.tgz#fb8812a88d6e22d014188c8252ea0c17c1ef4893" resolved "https://registry.yarnpkg.com/expo-modules-autolinking/-/expo-modules-autolinking-0.5.2.tgz#fb8812a88d6e22d014188c8252ea0c17c1ef4893"

Loading…
Cancel
Save