reza added something

temp
Reza_ashrafi 3 years ago
parent 51258aa00b
commit 5b9c20a9f6
  1. 16
      src/components/Empty/index.js
  2. 7
      src/components/FloatingButton/index.js
  3. 2
      src/components/Navbar/index.js
  4. 1
      src/redux/actions/index.js
  5. 29
      src/redux/actions/userFavorite.js
  6. 1
      src/redux/reducers/index.js
  7. 33
      src/redux/reducers/userFavorite.js
  8. 61
      src/router.js
  9. 4
      src/views/AR/index.js
  10. 11
      src/views/AR/layouts/Book.js
  11. 12
      src/views/Address/index.js
  12. 6
      src/views/Dashboard/layouts/Mobile/List.js
  13. 316
      src/views/Dashboard/layouts/Mobile/ProfileAddress/index.js
  14. 61
      src/views/Favorites/index.js
  15. 13
      src/views/Orders/index.js

@ -0,0 +1,16 @@
import React from "react";
import { connect } from "react-redux";
export const Empty = ({ text, buttonText, buttonAction }) => {
return (
<div className="flex-1 flex flex-col justify-center items-center">
<strong className="text-tiny font-medium text-gray1">{text}</strong>
</div>
);
};
const mapStateToProps = (state) => ({});
const mapDispatchToProps = {};
export default connect(mapStateToProps, mapDispatchToProps)(Empty);

@ -4,14 +4,14 @@ import { connect } from "react-redux";
//assets
import plusIcon from "./plus.svg";
export const FloatingButton = ({ action, position, icon }) => {
export const FloatingButton = ({ action, position, icon, size }) => {
return (
<button
onClick={() => action()}
className={`fixed bg-blueC0 w-20 h-20 rounded-full transform transition-all hover:scale-110 active:scale-90 flex justify-center items-center shadow-xl z-10`}
className={`fixed bg-blueC0 rounded-full w-${size} h-${size} transform transition-all hover:scale-110 active:scale-90 flex justify-center items-center shadow-xl z-10`}
style={position}
>
<img src={icon} alt="" className="w-7" style={{transform: 'translateX(-0px) translateY(3px)'}} />
<img src={icon} alt="" style={{transform: 'translateX(-0px) translateY(3px)', width : size * 1.3}} />
</button>
);
};
@ -24,4 +24,5 @@ export default connect(mapStateToProps, mapDispatchToProps)(FloatingButton);
FloatingButton.defaultProps = {
icon: plusIcon,
size : 20
};

@ -179,7 +179,7 @@ function Navbar({
<img
src={isDark ? arrowWhiteIcon : arrowBlueIcon}
alt="back"
className={`w-6 ${isDark ? "" : "transform -rotate-180"}`}
className={`w-6 transform ${isDark ? "" : "-rotate-180"}`}
onClick={() => navigation(-1)}
/>
) : null}

@ -7,6 +7,7 @@ export { default as product } from "./product";
export { default as userFactor } from "./userFactor";
export { default as userProduct } from "./userProduct";
export { default as userAddress } from "./userAddress";
export { default as userFavorite } from "./userFavorite";
export { default as transport } from "./transport";
export { default as content } from "./content";
export { default as faq } from "./faq";

@ -0,0 +1,29 @@
import proxy from "../proxy";
const userFavorite = {
list:
(data = {}) =>
async (dispatch) => {
await proxy.get("userFavorite/list", data, { dispatch });
},
update:
(data = {}, data2 = {}) =>
async (dispatch) => {
await proxy.put("userFavorite/update", data);
await proxy.get("userFavorite/list", data2, { dispatch });
},
add:
(data = {}, data2 = {}, data3 = {}) =>
async (dispatch) => {
await proxy.post("userFavorite/add", data, { dispatch });
await proxy.get("userFavorite/list", data2, { dispatch });
},
del:
(data = {}, data2 = {}) =>
async (dispatch) => {
await proxy.delete("userFavorite/delete", data);
await proxy.get("userFavorite/list", data2, { dispatch });
},
};
export default userFavorite;

@ -6,6 +6,7 @@ export { default as blog } from "./blog";
export { default as product } from "./product";
export { default as content } from "./content";
export { default as userAddress } from "./userAddress";
export { default as userFavorite } from "./userFavorite";
export { default as transport } from "./transport";
export { default as faq } from "./faq";
export { default as file } from "./file";

@ -0,0 +1,33 @@
import {toast} from 'react-toastify';
const initialState = {
loading: false,
error: null,
list: [],
};
export default function userAddress(state = initialState, action) {
let { type, data } = action;
switch (type) {
case "userAddress/list":
return {
...state,
loading: false,
list: data,
error: null,
};
case "userAddress/update":
return { ...state, loading: false, error: null };
case "userAddress/add":
toast.success('به لیست علاقهمندیها اضافه شد.');
return { ...state, loading: false, error: null };
case "userAddress/delete":
return { ...state, loading: false, error: null };
case "userAddress/loading":
return { ...state, loading: true };
case "userAddress/error":
toast.error(data.message);
return { ...state, loading: false, error: data.message };
default:
return state;
}
}

@ -31,6 +31,9 @@ import Blogs from "./views/Blogs";
import Blog from "./views/Blog";
import About from "./views/About";
import Dialog from "./components/Dialog";
import Address from "./views/Address";
import Favorites from "./views/Favorites";
import Addresses from "./views/Dashboard/layouts/Mobile/ProfileAddress";
function Router({ isDark, isMobile, headerOptions, dialog }) {
useEffect(() => {
@ -236,13 +239,13 @@ function Router({ isDark, isMobile, headerOptions, dialog }) {
}
/>
<Route
path="/orders"
path="/Orders"
exact
element={
<Orders
headerOptions={{
shown: "true",
title: "سفارش من",
shown: true,
title: "سفارشات من",
back: true,
logo: false,
menu: false,
@ -354,6 +357,58 @@ function Router({ isDark, isMobile, headerOptions, dialog }) {
/>
}
/>
<Route
path="/editProfile"
exact
element={
<Address
profilePage={true}
headerOptions={{
logo: false,
hamburgerMenu: false,
qr: false,
title: "مشخصات کاربری",
shown: true,
menu: false,
back: true,
}}
/>
}
/>
<Route
path="/favorites"
exact
element={
<Favorites
headerOptions={{
logo: false,
hamburgerMenu: false,
qr: false,
title: "علاقهمندیها",
shown: true,
menu: false,
back: true,
}}
/>
}
/>
<Route
path="/addresses"
exact
element={
<Addresses
headerOptions={{
logo: false,
hamburgerMenu: false,
qr: false,
title: "آدرس ها",
shown: true,
menu: false,
back: true,
}}
/>
}
/>
<Route
path="/ar"
exact

@ -4,15 +4,13 @@ import { publicApi } from "../../redux/actions";
import Book from "./layouts/Book";
function AR({ getArList, arList, headerOptions, setHeaderOptions }) {
useEffect(() => {
setHeaderOptions(headerOptions);
getArList();
}, []);
return (
<div className="flex flex-col flex-1 gap-4 px-4 lg:w-1/2 lg:min-h-screen lg:py-24 lg:mx-auto">
<div className="flex flex-wrap justify-between flex-1 gap-4 px-4 lg:w-1/2 lg:min-h-screen lg:py-24 lg:mx-auto">
{arList.length > 0 &&
arList.map((book, index) => <Book book={book} key={index} />)}
</div>

@ -5,17 +5,18 @@ const Book = ({ book }) => {
<a
href={`https://ar.dnvn.ir/lunch?id=${book.id}`}
target="_blank"
className="w-full flex flex-row rounded-md p-2 shadow-lg"
className="w-1/2 flex flex-col rounded-md px-2 pt-2 pb-10 shadow-lg"
style={{ width : 'calc(100vw / 2 - 30px)' }}
>
<img
src={`https://dnvn.ir/api/v1/file/${book.fileId}`}
className="rounded-md"
className="rounded-sm"
style={{
width: "calc(100vh / 10)",
height: "calc(100vh / 10 * 3 / 2)",
width: "100%",
// objectFit : 'contain'
}}
/>
<storng className="mr-2 mt-2 text-tiny text-blue5F font-semibold">
<storng className="mr-1 mt-3 text-tiny text-blue5F font-semibold">
{book.title}
</storng>
</a>

@ -32,6 +32,8 @@ export const Address = ({
profileFields,
setProfile,
user,
setHeaderOptions,
headerOptions,
}) => {
const [addressFields, setAddressFields] = useState({});
const [mapAddress, setMapAddress] = useState(null);
@ -40,6 +42,9 @@ export const Address = ({
if (province.length <= 1) {
getProvince();
}
if(isMobile){
setHeaderOptions(headerOptions);
}
}, []);
useEffect(() => {
@ -201,7 +206,7 @@ export const Address = ({
};
return (
<div
className="flex flex-col lg:flex-row-reverse flex-1 pt-10 lg:pt-0 pb-20 gap-5 lg:divide-x lg:divide-solid lg:divide-gray-200"
className="flex flex-col lg:flex-row-reverse px-4 flex-1 lg:pt-0 pb-20 gap-5 lg:divide-x lg:divide-solid lg:divide-gray-200"
// style={{ minHeight: "calc(100vh - 500px)" }}
>
{!profilePage && (
@ -484,7 +489,7 @@ export const Address = ({
)}
</div>
</div>
{isMobile && (
{/* {isMobile && (
<div
className="fixed top-0 left-0 flex justify-between items-center py-3 px-4 w-full"
style={{
@ -501,7 +506,7 @@ export const Address = ({
onClick={() => setPhase("deliveryForm")}
/>
</div>
)}
)} */}
</div>
);
};
@ -526,6 +531,7 @@ const mapDispatchToProps = {
setDialog: dialog.set,
setProfileFields: user.setProfileFields,
setProfile: user.setProfile,
setHeaderOptions : publicApi.setHeaderOptions
};
export default connect(mapStateToProps, mapDispatchToProps)(Address);

@ -16,7 +16,7 @@ const List = ({ mobile }) => {
{
icon: <img src={userGreenIcon} alt="" />,
name: "اطلاعات حساب کاربری",
link: "/CreateAddress",
link: "/editProfile",
},
{
icon: <img src={cartGreenIcon} />,
@ -36,12 +36,12 @@ const List = ({ mobile }) => {
{
icon: <img src={bookmarkGreenIcon} />,
name: "لیست علاقهمندیها",
link: "/ProfileBookmark",
link: "/favorites",
},
{
icon: <img src={addressGreenIcon} />,
name: "آدرسها",
link: "/ProfileAddress",
link: "/addresses",
},
];

@ -1,35 +1,12 @@
import {
View,
Text,
Pressable,
TouchableOpacity,
Appearance,
ActivityIndicator,
SafeAreaView,
ScrollView,
StyleSheet,
Platform,
Dimensions,
StatusBar,
} from "react-native";
import React from "react";
import { connect } from "react-redux";
import { useNavigation } from "@react-navigation/native";
import { userAddress, userFactor } from "../../../../redux/actions";
import Svg, { G, Path } from "react-native-svg";
import { userAddress, userFactor } from "../../../../../redux/actions";
import { Link, useNavigate } from "react-router-dom";
//components
import Navbar from "../../../../components/Navbar";
import CustomPressable from "../../../../components/Pressable";
import Empty from "../../../../components/Empty";
//style
import tw from "tailwind-rn";
import Colors from "../../../../constants/Colors";
import fontSize from "../../../../constants/fontSize";
const { height, width } = Dimensions.get("window");
const ios = Platform.OS === "ios";
import Empty from "../../../../../components/Empty";
import Button from "../../../../../components/Button";
import FloatingButton from "../../../../../components/FloatingButton";
const ProfileAddress = ({
addresses,
@ -41,156 +18,81 @@ const ProfileAddress = ({
loading,
closeBottomSheet,
mobile,
isDark,
}) => {
const colorScheme = Appearance.getColorScheme();
const navigation = useNavigation();
const [height, setHeight] = React.useState(Dimensions.get("window").height);
const navigation = useNavigate();
const Location = ({ address, active }) => {
return (
<Pressable
style={[
{
backgroundColor:
userAddressId === address?.id
? Colors.theme1[colorScheme].greenCF + "0a"
: Colors.theme1[colorScheme].grayE3 + "44",
borderWidth: 2,
borderColor:
userAddressId === address?.id
? Colors.theme1[colorScheme].greenCF + "aa"
: Colors.theme1[colorScheme].grayE3,
},
tw(
`flex flex-row-reverse items-center w-full px-3 py-2 rounded-md mt-2`
),
]}
onPress={() =>
<div
className={`bg-opacity-5 border border-solid flex flex-row items-center w-full px-3 py-2 rounded-md mt-2 ${
active ? "bg-blueC0 border-blueC0" : "bg-gray-300 border-gray-300"
}`}
onClick={() =>
userAddressId === address?.id
? {}
: update({ userAddressId: address.id, userId })
}
>
<View style={tw("flex flex-1 mr-2")}>
<div className={"flex flex-col flex-1 mr-2"}>
{active && (
<View
style={tw("w-full flex flex-row-reverse justify-between mb-3")}
>
<View style={tw("flex flex-row-reverse items-center")}>
<Text
style={{
fontSize: fontSize.base,
fontFamily: "bold",
color: Colors.theme1[colorScheme].gray20,
}}
>
<div className={"w-full flex flex-row justify-between mb-3"}>
<div className={"flex flex-row items-center"}>
<strong className={"text-base font-bold text-gray1"}>
آدرس انتخابی شما
</Text>
<Text
style={{
fontSize: fontSize.xs,
fontFamily: "regular",
color: Colors.theme1[colorScheme].gray20,
marginRight: 10,
}}
>
فعال
</Text>
</View>
<Svg xmlns="http://www.w3.org/2000/svg" width={24} height={24}>
<G fill="#07612c" data-name="vuesax/linear/more">
<Path d="M10 19a2 2 0 1 0 2-2 2.006 2.006 0 0 0-2 2Z" />
<Path
</strong>
<span className={"text-xs text-gray1 mr-2.5"}>فعال</span>
</div>
<svg xmlns="http://www.w3.org/2000/svg" width={24} height={24}>
<g fill="#07612c" data-name="vuesax/linear/more">
<path d="M10 19a2 2 0 1 0 2-2 2.006 2.006 0 0 0-2 2Z" />
<path
data-name="Vector"
d="M10 5a2 2 0 1 0 2-2 2.006 2.006 0 0 0-2 2ZM10 12a2 2 0 1 0 2-2 2.006 2.006 0 0 0-2 2Z"
/>
</G>
</Svg>
</View>
</g>
</svg>
</div>
)}
<View style={tw(`flex w-full ${active ? "" : "flex-row-reverse"}`)}>
<View style={tw("flex flex-1 mb-4")}>
<Text
style={[
{
fontFamily: "regular",
fontSize: mobile ? fontSize.sm : fontSize.lg,
lineHeight: 22,
textAlign: ios ? "right" : "auto",
},
]}
>
<div className={`flex w-full ${active ? "" : "flex-row"}`}>
<div className={"flex flex-col flex-1 mb-4"}>
<span className={"text-sm leading-6"}>
{"آدرس:" + " " + address.address}
</Text>
<Text
style={[
{
marginTop: mobile ? 4 : 8,
fontFamily: "regular",
fontSize: mobile ? fontSize.sm : fontSize.lg,
lineHeight: 22,
textAlign: ios ? "right" : "auto",
},
]}
>
</span>
<span className={"text-sm leading-6 mt-1.5"}>
{"نام:" + " " + address.firstName + " " + address.lastName}
</Text>
<Text
style={[
{
marginTop: mobile ? 4 : 8,
fontFamily: "regular",
fontSize: mobile ? fontSize.sm : fontSize.lg,
lineHeight: 22,
textAlign: ios ? "right" : "auto",
},
]}
>
</span>
<span className={"text-sm leading-6 mt-1.5"}>
{"کد پستی:" + " " + address.postalCode}
</Text>
<Text
style={[
{
marginTop: mobile ? 4 : 8,
fontFamily: "regular",
fontSize: mobile ? fontSize.sm : fontSize.lg,
lineHeight: 22,
textAlign: ios ? "right" : "auto",
},
]}
>
</span>
<span className={"text-sm leading-6 mt-1.5"}>
{"شماره تماس:" + " " + address.cellphone}
</Text>
</View>
</span>
</div>
{!active && (
<Svg xmlns="http://www.w3.org/2000/svg" width={24} height={24}>
<G
fill={Colors.theme1[colorScheme].gray20}
data-name="vuesax/linear/more"
>
<Path d="M10 19a2 2 0 1 0 2-2 2.006 2.006 0 0 0-2 2Z" />
<Path
<svg xmlns="http://www.w3.org/2000/svg" width={24} height={24}>
<g fill={"#aaa"} data-name="vuesax/linear/more">
<path d="M10 19a2 2 0 1 0 2-2 2.006 2.006 0 0 0-2 2Z" />
<path
data-name="Vector"
d="M10 5a2 2 0 1 0 2-2 2.006 2.006 0 0 0-2 2ZM10 12a2 2 0 1 0 2-2 2.006 2.006 0 0 0-2 2Z"
/>
</G>
</Svg>
</g>
</svg>
)}
</View>
<CustomPressable
title={"مشاهده روی نقشه"}
backgroundColor={
active
? Colors.theme1[colorScheme].greenCF
: Colors.theme1[colorScheme].gray20 + "66"
}
color={"white"}
border={{ color: "#196EC0", width: 0 }}
width={"100%"}
onPress={() => {}}
</div>
<Button
title="نمایش روی نقشه"
backgroundColor={isDark ? "bg-transparent" : "bg-blueC0"}
border={{
color: isDark ? "#ffffff55" : "#196EC055",
width: "0px",
}}
width="100%"
color={isDark ? "text-blueC0" : "text-white"}
onClick={() => {}}
/>
</View>
</Pressable>
</div>
</div>
);
};
@ -200,84 +102,28 @@ const ProfileAddress = ({
}, []);
return (
<SafeAreaView
style={{
paddingTop: Platform.OS === "android" ? StatusBar.currentHeight : 0,
position: "relative",
backgroundColor: "white",
flex: 1,
paddingBottom: 20,
}}
>
<Navbar
headerOptions={{
logo: false,
menu: false,
hamburgerMenu: false,
title: "آدرسها",
bookmark: false,
qr: false,
back: true,
}}
/>
<div className="flex-1 flex flex-col relative">
{addresses.length > 0 ? (
<ScrollView
contentContainerStyle={styles.contentContainerStyle}
style={[styles.container]}
onLayout={() => setHeight(Dimensions.get("window").height)}
>
<View style={tw("w-full mt-2 px-4")}>
<View style={tw("p-0 m-0 flex ")}>
{addresses.map((address, index) => (
<Location
address={address}
key={index}
active={userAddressId === address?.id}
/>
))}
</View>
</View>
</ScrollView>
<div className="w-full mt-2 px-4">
<div className="p-0 m-0 flex ">
{addresses.map((address, index) => (
<Location
address={address}
key={index}
active={userAddressId === address?.id}
/>
))}
</div>
</div>
) : (
<Empty text="هیچ آدرسی ثبت نشده :(" />
)}
<View style={tw("w-full px-4")}>
<TouchableOpacity
style={[
{
backgroundColor: Colors.theme1[colorScheme].greenCF + "05",
borderColor: Colors.theme1[colorScheme].greenCF,
borderWidth: 1.5,
},
tw(
`flex flex-row-reverse self-end justify-center py-2 rounded-md items-center mt-4 w-full`
),
]}
onPress={() => navigation.push("CreateAddress")}
>
<Text
style={{
fontFamily: "bold",
fontSize: fontSize.tiny,
color: Colors.theme1[colorScheme].greenCF,
}}
>
یک آدرس جدید اضافه کنید
</Text>
<Text
style={{
marginTop: 3,
marginRight: 5,
fontSize: fontSize.xl3,
color: Colors.theme1[colorScheme].greenCF,
fontFamily: "bold",
}}
>
+
</Text>
</TouchableOpacity>
</View>
</SafeAreaView>
<FloatingButton
action={() => navigation("/createAddress")}
position={{ bottom: 100, right: 16 }}
size={16}
/>
</div>
);
};
@ -287,6 +133,7 @@ const mapStateToProps = (state) => ({
loading: state.userFactor.loading,
addresses: state.userAddress.list,
mobile: state.publicApi.mobile,
isDark: state.publicApi.isDark,
});
const mapDispatchToProps = {
@ -296,16 +143,3 @@ const mapDispatchToProps = {
};
export default connect(mapStateToProps, mapDispatchToProps)(ProfileAddress);
const styles = StyleSheet.create({
contentContainerStyle: {
paddingBottom: 100,
position: "relative",
},
container: {
backgroundColor: "white",
flexDirection: "column",
paddingVertical: 0,
paddingHorizontal: 0,
},
});

@ -1,28 +1,24 @@
import React from "react";
import { connect } from "react-redux";
import { publicApi, userFavorite } from "../../redux/actions";
//assets
import bookImage from "./book.svg";
import bookmarkIcon from "./bookmark.svg";
const Favorites = ({ bookmarkList, isMobile }) => {
const Bookmark = ({ bookmark }) => {
return (
<div className="lg:w-1/2 xl:w-1/3 p-2 mb-4">
<div
className={`flex justify-between px-3.5 py-2 border-2 border-gray-300 border-solid rounded-md relative`}
>
<div className={"flex w-full"}>
<img src={bookmark.image} alt="" className="w-1/5" />
<div className={`flex flex-col mr-2 pt-2`}>
<strong className="text-base text-gray1">{bookmark.name}</strong>
<span className="text-sm mt-2 text-green7B font-bold">{bookmark.grade}</span>
</div>
</div>
<img src={bookmarkIcon} alt="" className="w-7 absolute left-2 top-2" />
</div>
</div>
);
};
const Favorites = ({
bookmarkList,
isMobile,
headerOptions,
setHeaderOptions,
getList,
}) => {
React.useEffect(() => {
if (isMobile) {
setHeaderOptions(headerOptions);
}
getList();
}, []);
return (
<div className="flex flex-row flex-wrap">
@ -33,12 +29,37 @@ const Favorites = ({ bookmarkList, isMobile }) => {
);
};
const Bookmark = ({ bookmark }) => {
return (
<div className="w-full lg:w-1/2 xl:w-1/3 px-4 lg:p-2 mb-4">
<div
className={`flex justify-between px-3.5 py-2 border-2 border-gray-200 border-solid rounded-md relative`}
>
<div className={"flex w-full"}>
<img src={bookmark.image} alt="" className="w-1/5" />
<div className={`flex flex-col mr-2 pt-2`}>
<strong className="text-base text-gray1">{bookmark.name}</strong>
<span className="text-sm mt-2 text-green7B font-bold">
{bookmark.grade}
</span>
</div>
</div>
<img src={bookmarkIcon} alt="" className="w-7 absolute left-2 top-2" />
</div>
</div>
);
};
const mapStateToProps = (state) => ({
loading: state.userFactor.loading,
isMobile: state.publicApi.isMobile,
bookmarkList: state.userFavorite.list,
});
const mapDispatchToProps = {};
const mapDispatchToProps = {
setHeaderOptions: publicApi.setHeaderOptions,
getList: userFavorite.list,
};
export default connect(mapStateToProps, mapDispatchToProps)(Favorites);

@ -1,10 +1,15 @@
import React from "react";
import Order from "./components/Order";
import { connect } from "react-redux";
import {publicApi} from '../../redux/actions';
//assets
import bookImage from "../../assets/images/book-mini.svg";
function Orders({ orders }) {
function Orders({ orders, headerOptions, setHeaderOptions }) {
React.useEffect(() => {
setHeaderOptions(headerOptions);
},[]);
return (
<div className="flex flex-col px-4">
{orders.map((order, index) => (
@ -14,9 +19,13 @@ function Orders({ orders }) {
);
}
const mapStateToProps = () => ({});
const mapStateToProps = (state) => ({
isMobile : state.publicApi.isMobile,
});
const mapDispatchToProps = {
setHeaderOptions: publicApi.setHeaderOptions,
};
export default connect(mapStateToProps, mapDispatchToProps)(Orders);

Loading…
Cancel
Save