20 changed files with 1654 additions and 624 deletions
@ -0,0 +1,23 @@
|
||||
// 推荐图标
|
||||
|
||||
import React from 'react'; |
||||
import Svg, { Path } from 'react-native-svg'; |
||||
|
||||
const LocationPinIcon = ({size = 20}:{size?:number}) => ( |
||||
<Svg |
||||
viewBox="0 0 1024 1024" |
||||
width={size} |
||||
height={size} |
||||
> |
||||
<Path |
||||
d="M914.432 818.389333l-114.858667 16.362667-72.533333 91.733333a43.242667 43.242667 0 0 1-59.093333-15.829333l-109.226667-189.162667a339.392 339.392 0 0 1-48.021333 3.776 343.872 343.872 0 0 1-49.941334-4.053333l-109.525333 189.696a42.666667 42.666667 0 0 1-58.282667 15.616l-71.466666-90.517333-113.28-16.149334a42.666667 42.666667 0 0 1-15.616-58.282666l121.109333-209.770667a341.333333 341.333333 0 1 1 595.413333-2.368l121.130667 209.792a43.264 43.264 0 0 1-15.808 59.157333zM158.72 775.168l94.805333 5.461333 52.992 79.872 89.6-155.285333a341.525333 341.525333 0 0 1-141.589333-96zM510.741333 106.666667a277.333333 277.333333 0 1 0 277.333334 277.333333 277.333333 277.333333 0 0 0-277.333334-277.333333zM768 608a341.333333 341.333333 0 0 1-143.488 97.6l88.917333 154.026667 53.76-81.066667 96.128-5.546667z" |
||||
fill="#d81e06" |
||||
/> |
||||
<Path |
||||
d="M512 576a192 192 0 1 1 192-192 192 192 0 0 1-192 192z m-0.661333-320.661333a128 128 0 1 0 128 128 128 128 0 0 0-128-128z" |
||||
fill="#d81e06" |
||||
/> |
||||
</Svg> |
||||
); |
||||
|
||||
export default LocationPinIcon; |
@ -0,0 +1,293 @@
|
||||
import React from "react"; |
||||
import { |
||||
View, |
||||
Text, |
||||
Image, |
||||
TouchableOpacity, |
||||
StyleSheet, |
||||
ScrollView, |
||||
} from "react-native"; |
||||
|
||||
export const PaymentSuccessScreen = () => { |
||||
return ( |
||||
<ScrollView style={styles.container}> |
||||
<View style={styles.header}> |
||||
<View style={styles.headerSuccess}> |
||||
<View style={styles.headerSuccessImg}></View> |
||||
<View style={styles.headerSuccessText}> |
||||
<Text style={styles.headerSuccessTextTitle}>支付成功</Text> |
||||
</View> |
||||
<View style={styles.headerPriceText}> |
||||
<Text style={styles.headerPriceTextTitle}>73800FCFA</Text> |
||||
</View> |
||||
</View> |
||||
|
||||
<View style={styles.headerSuccessInfo}> |
||||
<View style={styles.headerSuccessInfoItem}> |
||||
<Text style={styles.headerSuccessInfoItemText}>现代电话</Text> |
||||
<Text style={styles.headerSuccessInfoItemText1}>17088752341</Text> |
||||
</View> |
||||
<View style={styles.headerSuccessInfoItem1}> |
||||
<Text style={styles.headerSuccessInfoItemText}>地址</Text> |
||||
<Text style={styles.headerSuccessInfoItemText1}>河南省</Text> |
||||
</View> |
||||
</View> |
||||
<View style={styles.headerSuccessInfoItem2}> |
||||
<Text>货到仓库后,打电话联系您</Text> |
||||
</View> |
||||
<View style={styles.button}> |
||||
<View style={styles.buttonItem}> |
||||
<Text style={styles.buttonText}>查看订单</Text> |
||||
</View> |
||||
<View style={styles.buttonItem}> |
||||
<Text style={styles.buttonText}>订单详情</Text> |
||||
</View> |
||||
</View> |
||||
</View> |
||||
|
||||
<View style={styles.recommend}> |
||||
<Text style={styles.footerItemText1}>1234567890</Text> |
||||
<View style={styles.productContainer}> |
||||
<View style={styles.productRow}> |
||||
<View style={styles.productItem}> |
||||
<View style={styles.productImageContainer}> |
||||
<View style={styles.productImage} /> |
||||
</View> |
||||
<Text style={styles.productName}>商品名称</Text> |
||||
<Text style={styles.productPrice}>¥199</Text> |
||||
</View> |
||||
|
||||
<View style={styles.productItem}> |
||||
<View style={styles.productImageContainer}> |
||||
<View style={styles.productImage} /> |
||||
</View> |
||||
<Text style={styles.productName}>商品名称</Text> |
||||
<Text style={styles.productPrice}>¥299</Text> |
||||
</View> |
||||
</View> |
||||
|
||||
<View style={styles.productRow}> |
||||
<View style={styles.productItem}> |
||||
<View style={styles.productImageContainer}> |
||||
<View style={styles.productImage} /> |
||||
</View> |
||||
<Text style={styles.productName}>商品名称</Text> |
||||
<Text style={styles.productPrice}>¥399</Text> |
||||
</View> |
||||
|
||||
<View style={styles.productItem}> |
||||
<View style={styles.productImageContainer}> |
||||
<View style={styles.productImage} /> |
||||
</View> |
||||
<Text style={styles.productName}>商品名称</Text> |
||||
<Text style={styles.productPrice}>¥499</Text> |
||||
</View> |
||||
</View> |
||||
|
||||
<View style={styles.productRow}> |
||||
<View style={styles.productItem}> |
||||
<View style={styles.productImageContainer}> |
||||
<View style={styles.productImage} /> |
||||
</View> |
||||
<Text style={styles.productName}>商品名称</Text> |
||||
<Text style={styles.productPrice}>¥599</Text> |
||||
</View> |
||||
|
||||
<View style={styles.productItem}> |
||||
<View style={styles.productImageContainer}> |
||||
<View style={styles.productImage} /> |
||||
</View> |
||||
<Text style={styles.productName}>商品名称</Text> |
||||
<Text style={styles.productPrice}>¥699</Text> |
||||
</View> |
||||
</View> |
||||
|
||||
<View style={styles.productRow}> |
||||
<View style={styles.productItem}> |
||||
<View style={styles.productImageContainer}> |
||||
<View style={styles.productImage} /> |
||||
</View> |
||||
<Text style={styles.productName}>商品名称</Text> |
||||
<Text style={styles.productPrice}>¥799</Text> |
||||
</View> |
||||
|
||||
<View style={styles.productItem}> |
||||
<View style={styles.productImageContainer}> |
||||
<View style={styles.productImage} /> |
||||
</View> |
||||
<Text style={styles.productName}>商品名称</Text> |
||||
<Text style={styles.productPrice}>¥899</Text> |
||||
</View> |
||||
</View> |
||||
|
||||
<View style={styles.productRow}> |
||||
<View style={styles.productItem}> |
||||
<View style={styles.productImageContainer}> |
||||
<View style={styles.productImage} /> |
||||
</View> |
||||
<Text style={styles.productName}>商品名称</Text> |
||||
<Text style={styles.productPrice}>¥999</Text> |
||||
</View> |
||||
|
||||
<View style={styles.productItem}> |
||||
<View style={styles.productImageContainer}> |
||||
<View style={styles.productImage} /> |
||||
</View> |
||||
<Text style={styles.productName}>商品名称</Text> |
||||
<Text style={styles.productPrice}>¥1099</Text> |
||||
</View> |
||||
</View> |
||||
</View> |
||||
</View> |
||||
</ScrollView> |
||||
); |
||||
}; |
||||
|
||||
const styles = StyleSheet.create({ |
||||
container: { |
||||
flex: 1, |
||||
backgroundColor: "#f1f5f9", |
||||
}, |
||||
header: { |
||||
padding: 30, |
||||
backgroundColor: "white", |
||||
}, |
||||
headerSuccess: { |
||||
width: "100%", |
||||
marginBottom: 5, |
||||
}, |
||||
headerSuccessImg: { |
||||
width: 60, |
||||
height: 60, |
||||
alignSelf: "center", |
||||
}, |
||||
headerSuccessText: { |
||||
fontSize: 20, |
||||
color: "#000000", |
||||
alignSelf: "center", |
||||
marginTop: 10, |
||||
}, |
||||
headerSuccessTextTitle: { |
||||
fontSize: 16, |
||||
color: "#000000", |
||||
alignSelf: "center", |
||||
}, |
||||
headerPriceText: { |
||||
fontSize: 20, |
||||
color: "#000000", |
||||
alignSelf: "center", |
||||
}, |
||||
headerPriceTextTitle: { |
||||
fontSize: 20, |
||||
color: "#000000", |
||||
alignSelf: "center", |
||||
marginTop: 10, |
||||
}, |
||||
headerSuccessInfo: { |
||||
width: "100%", |
||||
backgroundColor: "#f0f6ff", |
||||
borderRadius: 5, |
||||
borderWidth: 1, |
||||
borderColor: "#dafcff", |
||||
marginTop: 10, |
||||
padding: 10, |
||||
}, |
||||
headerSuccessInfoItem: { |
||||
flexDirection: "row", |
||||
fontSize: 16, |
||||
color: "#0046bf", |
||||
fontWeight: "600", |
||||
alignItems: "center", |
||||
}, |
||||
headerSuccessInfoItem1: { |
||||
flexDirection: "row", |
||||
fontSize: 16, |
||||
color: "#0046bf", |
||||
fontWeight: "600", |
||||
alignItems: "center", |
||||
marginTop: 5, |
||||
}, |
||||
headerSuccessInfoItemText: { |
||||
fontSize: 16, |
||||
color: "#0046bf", |
||||
width: "20%", |
||||
fontWeight: "600", |
||||
alignItems: "center", |
||||
}, |
||||
headerSuccessInfoItemText1: { |
||||
fontSize: 16, |
||||
color: "#0046bf", |
||||
marginLeft: 10, |
||||
fontWeight: "600", |
||||
alignItems: "center", |
||||
}, |
||||
headerSuccessInfoItem2: { |
||||
marginTop: 5, |
||||
flexDirection: "row", |
||||
}, |
||||
button: { |
||||
flex: 1, |
||||
flexDirection: "row", |
||||
justifyContent: "space-between", |
||||
paddingLeft: 20, |
||||
paddingRight: 20, |
||||
marginTop: 20, |
||||
}, |
||||
buttonItem: { |
||||
width: "40%", |
||||
height: 40, |
||||
backgroundColor: "#0030a7", |
||||
borderRadius: 20, |
||||
justifyContent: "center", |
||||
alignItems: "center", |
||||
}, |
||||
buttonText: { |
||||
fontSize: 16, |
||||
color: "white", |
||||
}, |
||||
recommend: { |
||||
padding: 20, |
||||
}, |
||||
footerItemText1: { |
||||
fontSize: 16, |
||||
color: "#000000", |
||||
fontWeight: "600", |
||||
marginBottom: 15, |
||||
}, |
||||
productContainer: { |
||||
marginTop: 10, |
||||
}, |
||||
productRow: { |
||||
flexDirection: "row", |
||||
justifyContent: "space-between", |
||||
marginBottom: 15, |
||||
}, |
||||
productItem: { |
||||
width: "48%", |
||||
backgroundColor: "white", |
||||
borderRadius: 8, |
||||
padding: 10, |
||||
}, |
||||
productImageContainer: { |
||||
alignItems: "center", |
||||
marginBottom: 8, |
||||
width: "100%", |
||||
}, |
||||
productImage: { |
||||
width: "100%", |
||||
height: 120, |
||||
backgroundColor: "#f1f5f9", |
||||
borderRadius: 4, |
||||
}, |
||||
productName: { |
||||
fontSize: 14, |
||||
color: "#333", |
||||
marginTop: 5, |
||||
marginBottom: 5, |
||||
}, |
||||
productPrice: { |
||||
fontSize: 16, |
||||
color: "#E53935", |
||||
fontWeight: "bold", |
||||
}, |
||||
}); |
@ -0,0 +1,228 @@
|
||||
import { |
||||
View, |
||||
Text, |
||||
StyleSheet, |
||||
ScrollView, |
||||
TouchableOpacity, |
||||
} from "react-native"; |
||||
import BackIcon from "../../components/BackIcon"; |
||||
import FileEditIcon from "../../components/FileEditIcon"; |
||||
import { useNavigation } from "@react-navigation/native"; |
||||
import { addressApi, AddressItem, } from "../../services/api/addressApi"; |
||||
import { useState ,useEffect,useCallback} from "react"; |
||||
import { NativeStackNavigationProp } from "@react-navigation/native-stack"; |
||||
import { useFocusEffect } from '@react-navigation/native'; |
||||
import fontSize from "../../utils/fontsizeUtils"; |
||||
import widthUtils from "../../utils/widthUtils"; |
||||
export function MyAddress() { |
||||
const navigation = useNavigation<NativeStackNavigationProp<any>>(); |
||||
const [addressList, setAddressList] = useState<AddressItem[]>(); |
||||
const [address, setAddress] = useState<number>(); |
||||
const getAddress = async () => { |
||||
const response = await addressApi.getAddress(); |
||||
setAddressList(response.items); |
||||
}; |
||||
useEffect(() => { |
||||
getAddress(); |
||||
}, []); |
||||
const deleteAddress = async (address_id: number) => { |
||||
setAddressList(addressList?.filter((item) => item.address_id !== address_id)); |
||||
addressApi.deleteAddress(address_id) |
||||
} |
||||
useFocusEffect( |
||||
useCallback(() => { |
||||
getAddress(); |
||||
}, []) |
||||
); |
||||
|
||||
const setAddressId = (address_id: number) => { |
||||
setAddress(address_id); |
||||
} |
||||
return ( |
||||
<View style={styles.container}> |
||||
<View style={styles.header}> |
||||
<TouchableOpacity onPress={() => navigation.goBack()}> |
||||
<BackIcon /> |
||||
</TouchableOpacity> |
||||
</View> |
||||
<ScrollView style={{flex:1}} showsVerticalScrollIndicator={false}>
|
||||
{ |
||||
addressList?.map((item) => ( |
||||
<TouchableOpacity |
||||
key={item.address_id} |
||||
onPress={() => { |
||||
setAddressId(item.address_id); |
||||
}} |
||||
> |
||||
<View |
||||
|
||||
style={[ |
||||
styles.userCardContainer, |
||||
item.address_id === address ? styles.addressItemSelected : styles.addressItemNoSelected |
||||
]} |
||||
> |
||||
<View style={styles.userInfoCard}> |
||||
<View style={styles.userCardInfo2}> |
||||
<Text |
||||
style={styles.userCardInfo} |
||||
numberOfLines={1} |
||||
ellipsizeMode="tail" |
||||
> |
||||
{item.receiver_first_name} .{" "} |
||||
{item.receiver_last_name} |
||||
</Text> |
||||
<Text |
||||
style={styles.userCardInfo1} |
||||
numberOfLines={1} |
||||
ellipsizeMode="tail" |
||||
> |
||||
{item.receiver_phone} |
||||
</Text> |
||||
<View style={styles.addressEmit}> |
||||
<Text>设置默认地址</Text> |
||||
<TouchableOpacity |
||||
onPress={() => deleteAddress(item.address_id)} |
||||
> |
||||
<Text>删除</Text> |
||||
</TouchableOpacity> |
||||
</View> |
||||
</View> |
||||
{item.is_default === 1 && ( |
||||
<View style={styles.centeredBoxWithText}> |
||||
<Text style={styles.blueHeadingTextStyle}>默认</Text> |
||||
</View> |
||||
)} |
||||
</View> |
||||
<TouchableOpacity |
||||
onPress={() => { |
||||
navigation.navigate("AddRess", { |
||||
address: item, |
||||
}); |
||||
}} |
||||
> |
||||
<View style={styles.svgContainer}> |
||||
<FileEditIcon size={24} /> |
||||
</View> |
||||
</TouchableOpacity> |
||||
</View> |
||||
</TouchableOpacity> |
||||
)) |
||||
} |
||||
|
||||
</ScrollView> |
||||
<TouchableOpacity
|
||||
style={styles.addButton} |
||||
onPress={() => navigation.navigate("AddRess")} |
||||
> |
||||
<Text style={styles.addButtonText}>添加新地址</Text> |
||||
</TouchableOpacity> |
||||
</View> |
||||
); |
||||
} |
||||
|
||||
const styles = StyleSheet.create({ |
||||
container: { |
||||
flex: 1, |
||||
padding: 16, |
||||
backgroundColor: "#f8f8f8", |
||||
}, |
||||
header: { |
||||
paddingVertical: 16, |
||||
}, |
||||
userCardContainer1: { |
||||
marginTop: 20, |
||||
}, |
||||
addressItemSelected: { |
||||
borderColor: "#002fa7", |
||||
borderWidth: 2, |
||||
}, |
||||
addressItemNoSelected: { |
||||
borderColor: "#d0d0d0", |
||||
borderWidth: 2, |
||||
}, |
||||
userCardContainer: { |
||||
flexDirection: "row", |
||||
gap: 8, |
||||
alignItems: "flex-start", |
||||
justifyContent: "space-between", |
||||
width: "100%", |
||||
paddingTop: 15, |
||||
paddingRight: 10, |
||||
paddingBottom: 10, |
||||
paddingLeft: 11, |
||||
backgroundColor: "white", |
||||
borderRadius: 5, |
||||
marginBottom: 10, |
||||
}, |
||||
userInfoCard: { |
||||
flexDirection: "row", |
||||
alignItems: "flex-start", |
||||
justifyContent: "flex-start", |
||||
flex: 1, |
||||
marginRight: 8, |
||||
}, |
||||
userCardInfo2: { |
||||
flex: 1, |
||||
marginRight: 8, |
||||
}, |
||||
userCardInfo: { |
||||
fontSize: fontSize(18), |
||||
lineHeight: 22, |
||||
fontFamily: "PingFang SC", |
||||
fontWeight: "500", |
||||
color: "black", |
||||
flex: 1, |
||||
}, |
||||
userCardInfo1: { |
||||
fontSize: fontSize(18), |
||||
lineHeight: 22, |
||||
fontFamily: "PingFang SC", |
||||
fontWeight: "500", |
||||
color: "#6b7280", |
||||
marginTop: 10, |
||||
flex: 1, |
||||
width: "100%", |
||||
}, |
||||
centeredBoxWithText: { |
||||
flexDirection: "column", |
||||
alignItems: "stretch", |
||||
justifyContent: "center", |
||||
height: 26, |
||||
paddingRight: 11, |
||||
paddingLeft: 11, |
||||
marginLeft: 8, |
||||
backgroundColor: "#edf3ff", |
||||
borderRadius: 5, |
||||
}, |
||||
blueHeadingTextStyle: { |
||||
fontSize: fontSize(13), |
||||
fontFamily: "PingFang SC", |
||||
fontWeight: "500", |
||||
color: "#002fa7", |
||||
}, |
||||
svgContainer: { |
||||
width: widthUtils(24,24).width, |
||||
height: widthUtils(24,24).height, |
||||
color: "#0051ff", |
||||
marginLeft: "auto", |
||||
}, |
||||
addressEmit: { |
||||
paddingTop: 10, |
||||
flexDirection: "row", |
||||
gap: 10, |
||||
}, |
||||
addButton: { |
||||
width: "100%", |
||||
height: widthUtils(60,60).height, |
||||
backgroundColor: "#002fa7", |
||||
justifyContent: "center", |
||||
alignItems: "center", |
||||
borderRadius: 5, |
||||
marginTop: 10, |
||||
}, |
||||
addButtonText: { |
||||
color: "white", |
||||
fontSize: fontSize(16), |
||||
fontWeight: "500", |
||||
}, |
||||
}); |
@ -0,0 +1,75 @@
|
||||
import apiService from './apiClient'; |
||||
|
||||
|
||||
// 地址类型
|
||||
interface Address { |
||||
address_id: number; |
||||
user_id: number; |
||||
receiver_first_name: string; |
||||
receiver_last_name: string; |
||||
country: string; |
||||
receiver_phone: string; |
||||
whatsapp_phone: string; |
||||
province: string | null; |
||||
city: string | null; |
||||
district: string | null; |
||||
detail_address: string | null; |
||||
is_default: number; |
||||
create_time: string; |
||||
update_time: string; |
||||
} |
||||
|
||||
// 订单商品项类型
|
||||
interface OrderItem { |
||||
offer_id: number; |
||||
sku_id: number; |
||||
product_name: string; |
||||
sku_image_url: string; |
||||
product_name_en: string; |
||||
product_name_fr: string; |
||||
product_name_ar: string; |
||||
quantity: number; |
||||
unit_price: number; |
||||
total_price: number; |
||||
attributes:{ |
||||
attribute_name:string; |
||||
attribute_name_trans:string, |
||||
attribute_value:string, |
||||
attribute_value_trans:string, |
||||
value:string, |
||||
value_trans:string, |
||||
value_trans_ar:string, |
||||
value_trans_fr:string, |
||||
}[] |
||||
} |
||||
|
||||
// 订单汇总类型
|
||||
interface OrderSummary { |
||||
total_amount: number; |
||||
shipping_fee: number; |
||||
discount_amount: number; |
||||
actual_amount: number; |
||||
currency: string; |
||||
} |
||||
|
||||
// 完整订单数据类型
|
||||
export interface OrderData { |
||||
address: Address; |
||||
items: OrderItem[]; |
||||
total_amount: number; |
||||
shipping_fee: number; |
||||
discount_amount: number; |
||||
actual_amount: number; |
||||
currency: string; |
||||
} |
||||
|
||||
export interface OrderPreviewData { |
||||
"items":
|
||||
{ |
||||
"cart_item_id": number |
||||
}[], |
||||
} |
||||
|
||||
export const ordersApi = { |
||||
getOrders: (data:OrderPreviewData) => apiService.post<OrderData>("/api/orders/preview",data), |
||||
}; |
After Width: | Height: | Size: 386 KiB |
After Width: | Height: | Size: 7.5 KiB |
After Width: | Height: | Size: 402 KiB |
After Width: | Height: | Size: 256 KiB |
After Width: | Height: | Size: 265 KiB |
After Width: | Height: | Size: 960 KiB |
Loading…
Reference in new issue