Browse Source

浏览历史和收藏的ui

main
Mac 1 month ago
parent
commit
cec61f7ce0
  1. 38
      App.tsx
  2. 13
      app/components/TiktokIcon.tsx
  3. 189
      app/screens/CategoryScreen.tsx
  4. 1
      app/screens/CountrySelect.tsx
  5. 2
      app/screens/HomeScreen.tsx
  6. 2
      app/screens/MyAccount/myAccount.tsx
  7. 36
      app/screens/ProfileScreen.tsx
  8. 0
      app/screens/banner/InquiryScreen.tsx
  9. 20
      app/screens/banner/ShippingDetailsSection.tsx
  10. 290
      app/screens/banner/TikTokScreen.tsx
  11. 199
      app/screens/function/BrowseHistoryScreen.tsx
  12. 207
      app/screens/function/Collection.tsx
  13. 2
      app/screens/pay/PaySuccess.tsx
  14. 122
      app/screens/setting/MyAddress.tsx
  15. BIN
      assets/img/Mask group (1).png
  16. BIN
      assets/img/Mask group.png
  17. 4
      package-lock.json
  18. 1
      package.json
  19. 1052
      yarn.lock

38
App.tsx

@ -15,9 +15,9 @@ import { SearchScreen } from "./app/screens/SearchScreen";
import { SearchResultScreen } from "./app/screens/SearchResultScreen";
import { ProductDetailScreen } from "./app/screens/ProductDetailScreen";
import { BalanceScreen } from "./app/screens/BalanceScreen";
import { ShippingDetailsSection } from "./app/screens/ShippingDetailsSection";
import { ShippingDetailsSection } from "./app/screens/banner/ShippingDetailsSection";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import { InquiryScreen } from "./app/screens/InquiryScreen/InquiryScreen";
import { InquiryScreen } from "./app/screens/banner/InquiryScreen";
import { Recipient } from "./app/screens/Recipient/Recipient";
import { AddRess } from "./app/screens/Recipient/Address";
import { SettingList } from "./app/screens/setting/SettingList";
@ -31,7 +31,9 @@ import { ConfirmOrder } from "./app/screens/Recipient/ConfirmOrder";
import { Pay } from "./app/screens/pay/Pay";
import { Status } from "./app/screens/productStatus/Status";
import { OrderDetails } from "./app/screens/productStatus/OrderDatails";
import { TikTokScreen } from "./app/screens/banner/TikTokScreen";
import { BrowseHistoryScreen } from "./app/screens/function/BrowseHistoryScreen";
import { Collection } from "./app/screens/function/Collection";
export type RootStackParamList = {
CountrySelect: undefined;
MainApp: undefined;
@ -57,6 +59,9 @@ export type RootStackParamList = {
Pay: undefined;
Status: undefined;
OrderDetails: undefined;
TikTokScreen: undefined;
BrowseHistoryScreen: undefined;
Collection: undefined;
};
const Stack = createNativeStackNavigator<RootStackParamList>();
@ -274,6 +279,33 @@ export default function App() {
gestureDirection: "horizontal",
}}
/>
<Stack.Screen
name="TikTokScreen"
component={TikTokScreen}
options={{
animation: "slide_from_right",
gestureEnabled: true,
gestureDirection: "horizontal",
}}
/>
<Stack.Screen
name="BrowseHistoryScreen"
component={BrowseHistoryScreen}
options={{
animation: "slide_from_right",
gestureEnabled: true,
gestureDirection: "horizontal",
}}
/>
<Stack.Screen
name="Collection"
component={Collection}
options={{
animation: "slide_from_right",
gestureEnabled: true,
gestureDirection: "horizontal",
}}
/>
</Stack.Navigator>
</NavigationContainer>
</AuthProvider>

13
app/components/TiktokIcon.tsx

@ -0,0 +1,13 @@
import React from 'react';
import Svg, { Path } from 'react-native-svg';
const TiktokIcon = ({color,size}:{color:string,size:number}) => (
<Svg width={size} height={size} viewBox="0 0 22 22" fill="none">
<Path
d="M17.4167 9.53425C16.0839 9.53425 14.7492 9.11533 13.6676 8.27842V13.9737C13.6676 16.8208 11.4997 19.25 8.66625 19.25C5.83283 19.25 3.66675 16.9052 3.66675 13.9737C3.66675 11.0422 5.83375 8.69642 8.66716 8.69642C8.9165 8.69642 9.25016 8.69642 9.50041 8.78075V11.7957C9.25016 11.7122 8.99991 11.6279 8.66625 11.6279C7.41683 11.6279 6.50016 12.7169 6.50016 13.8893C6.50016 15.2295 7.49933 16.1508 8.66716 16.1508C9.83316 16.1508 10.8332 15.0618 10.8332 13.8893V2.75H13.5832C13.5832 4.928 15.2497 6.68617 17.2499 6.68617L17.4167 9.53425Z"
fill={color}
/>
</Svg>
);
export default TiktokIcon;

189
app/screens/CategoryScreen.tsx

@ -1,71 +1,162 @@
import React, { useState } from 'react';
import { View, Text, StyleSheet, Button, Modal, TouchableOpacity, Dimensions } from 'react-native';
import {
View,
Text,
FlatList,
TouchableOpacity,
StyleSheet,
Image,
Dimensions,
ListRenderItem,
} from 'react-native';
import fontSize from '../utils/fontsizeUtils';
import widthUtils from '../utils/widthUtils';
export const CategoryScreen = () => {
const [isModalVisible, setIsModalVisible] = useState(false);
type Category = {
id: string;
name: string;
};
type Product = {
name: string;
img: string;
};
const categories: Category[] = [
{ id: 'fruit', name: '水果' },
{ id: 'snacks', name: '零食' },
{ id: 'clothes', name: '服饰' },
{ id: 'home', name: '家居' },
];
const productsData: Record<string, Product[]> = {
fruit: [
{ name: '苹果', img: 'https://via.placeholder.com/100?text=苹果' },
{ name: '香蕉', img: 'https://via.placeholder.com/100?text=香蕉' },
{ name: '西瓜', img: 'https://via.placeholder.com/100?text=西瓜' },
],
snacks: [
{ name: '薯片', img: 'https://via.placeholder.com/100?text=薯片' },
{ name: '饼干', img: 'https://via.placeholder.com/100?text=饼干' },
{ name: '巧克力', img: 'https://via.placeholder.com/100?text=巧克力' },
],
clothes: [
{ name: 'T恤', img: 'https://via.placeholder.com/100?text=T恤' },
{ name: '牛仔裤', img: 'https://via.placeholder.com/100?text=牛仔裤' },
{ name: '外套', img: 'https://via.placeholder.com/100?text=外套' },
],
home: [
{ name: '毛巾fdfd一定要人盯人一天的玉兔捣药', img: 'https://via.placeholder.com/100?text=毛巾' },
{ name: '椅子', img: 'https://via.placeholder.com/100?text=椅子' },
{ name: '灯具', img: 'https://via.placeholder.com/100?text=灯具' },
],
};
const toggleModal = () => {
setIsModalVisible(!isModalVisible);
};
export function CategoryScreen() {
const [activeCategory, setActiveCategory] = useState<string>('fruit');
const renderCategoryItem: ListRenderItem<Category> = ({ item }) => (
<TouchableOpacity
style={[
styles.menuItem,
item.id === activeCategory && styles.menuItemActive,
]}
onPress={() => setActiveCategory(item.id)}
>
<Text
style={[
styles.menuText,
item.id === activeCategory && styles.menuTextActive,
]}
numberOfLines={1}
ellipsizeMode="tail"
>
{item.name}
</Text>
</TouchableOpacity>
);
const renderProductItem: ListRenderItem<Product> = ({ item }) => (
<View style={styles.productCard}>
<Image source={{ uri: item.img }} style={styles.productImage} />
<Text style={styles.productName} numberOfLines={1} ellipsizeMode="tail">{item.name}</Text>
</View>
);
return (
<View style={styles.container}>
<Button title="Category Screen" onPress={toggleModal} />
<Modal
visible={isModalVisible}
transparent={true}
animationType="slide"
onRequestClose={toggleModal}
>
<TouchableOpacity
style={styles.modalOverlay}
activeOpacity={1}
onPress={toggleModal}
>
<View style={styles.modalContent}>
<View style={styles.modalHeader}>
<View style={styles.modalHandle} />
</View>
{/* 这里可以添加模态框的内容 */}
</View>
</TouchableOpacity>
</Modal>
<View style={styles.leftMenu}>
<FlatList
data={categories}
renderItem={renderCategoryItem}
keyExtractor={(item) => item.id}
/>
</View>
<View style={styles.rightContent}>
<FlatList
data={productsData[activeCategory]}
renderItem={renderProductItem}
keyExtractor={(_, index) => `${activeCategory}-${index}`}
numColumns={3}
contentContainerStyle={styles.productGrid}
/>
</View>
</View>
);
};
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
flexDirection: 'row',
},
leftMenu: {
width: widthUtils(100,100).width,
backgroundColor: '#fff',
borderRightWidth: 1,
borderColor: '#eee',
},
text: {
fontSize: 20,
menuItem: {
paddingVertical: 16,
alignItems: 'center',
borderBottomWidth: 1,
borderColor: '#f0f0f0',
},
menuItemActive: {
backgroundColor: '#f5f5f5',
},
menuText: {
fontSize: fontSize(14),
color: '#333',
},
modalOverlay: {
menuTextActive: {
color: '#e60012',
fontWeight: 'bold',
},
rightContent: {
flex: 1,
backgroundColor: 'rgba(0, 0, 0, 0.5)',
justifyContent: 'flex-end',
backgroundColor: '#f8f8f8',
paddingHorizontal: 10,
paddingTop: 12,
},
modalContent: {
height: '70%',
backgroundColor: 'white',
borderTopLeftRadius: 20,
borderTopRightRadius: 20,
padding: 20,
productGrid: {
paddingBottom: 20,
},
modalHeader: {
productCard: {
flexBasis: '33.33%',
padding: 6,
alignItems: 'center',
paddingBottom: 10,
},
modalHandle: {
width: 40,
height: 4,
backgroundColor: '#ccc',
borderRadius: 2,
productImage: {
width: '100%',
aspectRatio: 1,
borderRadius: 6,
backgroundColor: '#eee',
},
productName: {
fontSize: fontSize(13),
color: '#333',
marginTop: 6,
textAlign: 'center',
},
});
});

1
app/screens/CountrySelect.tsx

@ -1,3 +1,4 @@
// 国家选择
import React, { useState, useEffect } from 'react';
import {
View,

2
app/screens/HomeScreen.tsx

@ -317,7 +317,7 @@ export const HomeScreen = () => {
style={styles.bannerIcon}
/>
</TouchableOpacity>
<TouchableOpacity style={styles.leftBottomItem}>
<TouchableOpacity style={styles.leftBottomItem} onPress={() => navigation.navigate("TikTokScreen")}>
<Image
source={require("../../assets/img/a_tiktok.png")}
style={styles.bannerIcon}

2
app/screens/MyAccount/myAccount.tsx

@ -171,7 +171,7 @@ export function MyAccount() {
<View style={styles.FeaturesHeader}>
<View>
<MyFavoriteIcon size={20}/>
<MyFavoriteIcon size={20} color="#707070"/>
</View>
<View style={styles.FeaturesHeaderItem}>
<Text style={styles.FeaturesHeaderItemText}>My Favorite</Text>

36
app/screens/ProfileScreen.tsx

@ -26,7 +26,11 @@ type RootStackParamList = {
Home: undefined;
MyAccount: undefined;
Login: undefined;
Status: { status: number };
Status: { status: number | null };
BrowseHistoryScreen: undefined;
MyAddress: undefined;
Collection: undefined;
Balance: undefined;
};
export const ProfileScreen = () => {
@ -103,7 +107,7 @@ export const ProfileScreen = () => {
ID: {userInfo?.user_id}
</Text>
</View>
<TouchableOpacity style={styles.transactionSummaryBox} onPress={() => navigation.navigate("MyAccount")}>
<TouchableOpacity style={styles.transactionSummaryBox} onPress={() => navigation.navigate("Balance")}>
<View style={styles.svgContainer}>
<BookmarkIcon size={fontSize(24)} />
</View>
@ -155,10 +159,10 @@ export const ProfileScreen = () => {
<Text style={styles.groupItemTitleText}>
Mes commandes en cours
</Text>
<View style={styles.groupItemTitleTextTout}>
<TouchableOpacity style={styles.groupItemTitleTextTout} onPress={() => navigation.navigate("Status",{status:null})}>
<Text style={styles.groupItemTitleTextTout1}>tout</Text>
<LeftArrowIcon size={fontSize(14)} color="#8f8684" />
</View>
</TouchableOpacity>
</View>
<View style={styles.groupItem}>
@ -186,30 +190,24 @@ export const ProfileScreen = () => {
<View style={styles.groupItem}>
<View style={styles.groupItemContent}>
<View style={styles.groupItemContentIcon}>
<TouchableOpacity style={styles.groupItemContentIcon} onPress={() => navigation.navigate("BrowseHistoryScreen")}>
<DocumentApprovedIcon size={fontSize(38)} color="#707070" />
</View>
<Text style={styles.groupItemContentText}></Text>
</TouchableOpacity>
<Text style={styles.groupItemContentText}></Text>
</View>
<View style={styles.groupItemContent}>
<View style={styles.groupItemContentIcon}>
<TouchableOpacity style={styles.groupItemContentIcon} onPress={() => navigation.navigate("Collection")}>
<PdfDocumentIcon size={fontSize(38)} color="#707070" />
</View>
<Text style={styles.groupItemContentText}></Text>
</View>
<View style={styles.groupItemContent}>
<View style={styles.groupItemContentIcon}>
<DocumentClockIcon size={fontSize(38)} color="#707070" />
</View>
<Text style={styles.groupItemContentText}></Text>
</TouchableOpacity>
<Text style={styles.groupItemContentText}></Text>
</View>
<View style={styles.groupItemContent}>
<TouchableOpacity style={styles.groupItemContent} onPress={() => navigation.navigate("MyAddress")}>
<View style={styles.groupItemContentIcon}>
<DocumentClockIcon size={fontSize(38)} color="#707070" />
</View>
<Text style={styles.groupItemContentText}></Text>
</View>
<Text style={styles.groupItemContentText}></Text>
</TouchableOpacity>
</View>
</View>
</View>

0
app/screens/InquiryScreen/InquiryScreen.tsx → app/screens/banner/InquiryScreen.tsx

20
app/screens/ShippingDetailsSection.tsx → app/screens/banner/ShippingDetailsSection.tsx

@ -1,8 +1,8 @@
import React, { useState, useEffect } from 'react';
import { View, Text, Image, TouchableOpacity, StyleSheet, ImageBackground, ActivityIndicator } from 'react-native';
import BackIcon from '../components/BackIcon';
import fontSize from '../utils/fontsizeUtils';
import widthUtils from '../utils/widthUtils';
import BackIcon from '../../components/BackIcon';
import fontSize from '../../utils/fontsizeUtils';
import widthUtils from '../../utils/widthUtils';
import { useNavigation } from '@react-navigation/native';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
@ -25,8 +25,8 @@ export const ShippingDetailsSection = () => {
const preloadImages = async () => {
try {
await Promise.all([
Image.prefetch(Image.resolveAssetSource(require('../../assets/img/image_f67fe9bc.png')).uri),
Image.prefetch(Image.resolveAssetSource(require('../../assets/img/feijiback.png')).uri)
Image.prefetch(Image.resolveAssetSource(require('../../../assets/img/image_f67fe9bc.png')).uri),
Image.prefetch(Image.resolveAssetSource(require('../../../assets/img/feijiback.png')).uri)
]);
setIsLoading(false);
} catch (error) {
@ -45,8 +45,8 @@ export const ShippingDetailsSection = () => {
// Get background image based on shipping method
const getBackgroundImage = () => {
return shippingMethod === 'maritime'
? require('../../assets/img/image_f67fe9bc.png')
: require('../../assets/img/feijiback.png');
? require('../../../assets/img/image_f67fe9bc.png')
: require('../../../assets/img/feijiback.png');
};
return (
@ -92,7 +92,7 @@ export const ShippingDetailsSection = () => {
>
<View style={styles.svgContainer1}>
<Image
source={require('../../assets/img/海运 (1) 1.png')}
source={require('../../../assets/img/海运 (1) 1.png')}
style={{width: widthUtils(24, 24).width, height: widthUtils(24, 24).height,
tintColor: shippingMethod === 'maritime' ? '#fff' : '#747474'}}
/>
@ -113,7 +113,7 @@ export const ShippingDetailsSection = () => {
>
<View style={styles.svgContainer2}>
<Image
source={require('../../assets/img/空运 1.png')}
source={require('../../../assets/img/空运 1.png')}
style={{width: widthUtils(24, 24).width, height: widthUtils(24, 24).height, tintColor: shippingMethod === 'airway' ? '#fff' : '#747474'}}
/>
</View>
@ -171,7 +171,7 @@ const styles = StyleSheet.create({
},
contentContainer: {
flex: 1,
padding: 20,
padding: 15,
},
timeShippingSection: {
flexDirection: 'column',

290
app/screens/banner/TikTokScreen.tsx

@ -0,0 +1,290 @@
import {
View,
Text,
StyleSheet,
ImageBackground,
Dimensions,
ScrollView,
} from "react-native";
import BackIcon from "../../components/BackIcon";
import fontSize from "../../utils/fontsizeUtils";
import TiktokIcon from "../../components/TiktokIcon";
import widthUtils from "../../utils/widthUtils";
import Carousel from "react-native-reanimated-carousel";
import { useState } from "react";
export const TikTokScreen = () => {
const { width: screenWidth } = Dimensions.get("window");
const [currentIndex, setCurrentIndex] = useState(0);
const carouselItems = [
{
id: 1,
image: require("../../../assets/img/Mask group.png"),
liveText: "视频",
subTitle: "LIVE",
},
{
id: 2,
image: require("../../../assets/img/Mask group (1).png"),
liveText: "LIVE",
subTitle: "SHORTS",
},
];
const renderItem = ({ item }: { item: (typeof carouselItems)[0] }) => {
return (
<View style={styles.maskGroup}>
<ImageBackground
source={item.image}
style={styles.maskGroupImage}
resizeMode="contain"
>
<View style={styles.content}>
<View style={styles.titleContainer}>
<View style={styles.titleLogo}>
<TiktokIcon color="#fff" size={22} />
<Text style={styles.tikTokText}>TikTok</Text>
<Text style={styles.LiveText}>{item.liveText}</Text>
</View>
<View style={styles.titleText}>
<Text style={styles.titleTextTitle}>Section</Text>
<Text style={styles.titleTextSubTitle}>{item.subTitle}</Text>
</View>
</View>
</View>
</ImageBackground>
</View>
);
};
const onSnapToItem = (index: number) => {
setCurrentIndex(index);
};
return (
<View style={styles.container}>
<View style={styles.header}>
<BackIcon color="#fff" />
<Text style={styles.title}> tiktok</Text>
</View>
<View style={styles.maskGroup}>
<Carousel
data={carouselItems}
renderItem={renderItem}
width={screenWidth}
loop={true}
autoPlayInterval={3000}
onSnapToItem={onSnapToItem}
/>
<View
style={[styles.Instruction, { top: widthUtils(210, 210).height }]}
>
<View
style={[
styles.instructionLine1,
currentIndex === 0 && styles.instructionLine3,
]}
/>
<View
style={[
styles.instructionLine2,
currentIndex === 1 && styles.instructionLine3,
]}
/>
</View>
</View>
<ScrollView
style={styles.productContainer}
showsVerticalScrollIndicator={false}
>
<View style={styles.productList}>
<View style={styles.productItem}>
<View style={styles.productItemImage}></View>
<View style={styles.productItemInfo}>
<View style={styles.priceInfo}></View>
<View style={styles.priceTitle}>
<Text
style={styles.priceTitleText}
numberOfLines={2}
ellipsizeMode="tail"
>1231231131231231221323123123123123123123123121231231212311232</Text>
</View>
<View style={styles.ventes}></View>
</View>
</View>
</View>
</ScrollView>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
header: {
width: "100%",
padding: 19,
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
position: "absolute",
top: 0,
left: 0,
zIndex: 1,
},
title: {
color: "#fff",
fontSize: fontSize(22),
fontWeight: "700",
textAlign: "center",
flex: 1,
},
maskGroup: {
width: "100%",
height: widthUtils(321, 321).height,
backgroundColor: "#000",
position: "relative",
top: 0,
left: 0,
},
maskGroupImage: {
width: "100%",
height: "100%",
resizeMode: "contain",
},
content: {
width: "100%",
flex: 1,
justifyContent: "center",
},
titleContainer: {
width: "100%",
alignItems: "center",
},
titleLogo: {
width: "100%",
paddingLeft: 22,
paddingRight: 22,
flexDirection: "row",
alignItems: "center",
},
tikTokText: {
color: "#fff",
fontSize: fontSize(26),
fontWeight: "600",
},
LiveText: {
marginLeft: 5,
backgroundColor: "#ff188a",
paddingLeft: 5,
paddingRight: 5,
fontSize: fontSize(16),
fontWeight: "600",
color: "#fff",
},
titleText: {
width: "100%",
paddingTop: widthUtils(19, 19).height,
paddingBottom: widthUtils(19, 19).height,
paddingLeft: widthUtils(22, 22).height,
paddingRight: widthUtils(22, 22).height,
},
Instruction: {
width: "100%",
paddingTop: widthUtils(19, 19).height,
paddingBottom: widthUtils(19, 19).height,
paddingLeft: widthUtils(22, 22).height,
paddingRight: widthUtils(22, 22).height,
flexDirection: "row",
gap: 6,
position: "absolute",
bottom: widthUtils(50, 50).height,
left: 0,
zIndex: 2,
},
instructionLine1: {
width: 10,
height: 6,
backgroundColor: "#52595f",
borderRadius: 10,
},
instructionLine2: {
width: 10,
height: 6,
backgroundColor: "#52595f",
borderRadius: 10,
},
instructionLine3: {
width: 20,
height: 6,
backgroundColor: "#ffff",
borderRadius: 10,
},
titleTextTitle: {
color: "#fff",
fontSize: fontSize(26),
fontWeight: "900",
fontFamily: "Montserrat-Bold",
},
titleTextSubTitle: {
color: "#fff",
fontSize: fontSize(30),
fontWeight: "900",
fontFamily: "Montserrat-Bold",
},
productContainer: {
flex: 1,
width: "100%",
position: "absolute",
top: widthUtils(321, 321).height,
left: 0,
right: 0,
bottom: 0,
zIndex: 1,
backgroundColor: "#000",
marginTop: -10,
paddingLeft: 19,
paddingRight: 19,
},
productList: {
width: "100%",
flexDirection: "row",
flexWrap: "wrap",
gap: 10,
},
productItem: {
width: "48%",
height: widthUtils(298, 298).height,
borderRadius: 10,
},
productItemImage:{
width: "100%",
height:widthUtils(190, 190).height,
borderRadius: 10,
},
productItemInfo:{
width: "100%",
flex: 1,
},
priceInfo:{
width: "100%",
padding: 10,
},
priceTitle: {
width: "100%",
padding: 10,
},
priceTitleText: {
color: "#fff",
fontSize: fontSize(14),
lineHeight: fontSize(20),
},
ventes:{
width: "100%",
padding: 10,
}
});

199
app/screens/function/BrowseHistoryScreen.tsx

@ -0,0 +1,199 @@
import React, { useState } from "react";
import {
View,
Text,
FlatList,
Image,
TouchableOpacity,
Platform,
StyleSheet,
} from "react-native";
import BackIcon from "../../components/BackIcon";
import fontSize from "../../utils/fontsizeUtils";
import { useNavigation } from "@react-navigation/native";
import DateTimePicker, { DateTimePickerEvent } from '@react-native-community/datetimepicker';
import widthUtils from "../../utils/widthUtils";
const browseData = [
{
id: "1",
name: "商品名称示例",
time: "14:32",
price: 199.0,
image: "https://via.placeholder.com/60",
},
{
id: "2",
name: "另一商品示例",
time: "09:15",
price: 89.9,
image: "https://via.placeholder.com/60",
},
];
export function BrowseHistoryScreen() {
const navigation = useNavigation();
const [date, setDate] = useState(new Date());
const [show, setShow] = useState(false);
const onChange = (event: DateTimePickerEvent, selectedDate?: Date) => {
setShow(Platform.OS === "ios"); // iOS 会保持显示
if (selectedDate) {
setDate(selectedDate);
}
};
return (
<View style={styles.container}>
<View style={styles.header}>
<TouchableOpacity
onPress={() => navigation.goBack()}
style={styles.backButton}
>
<BackIcon size={fontSize(22)} />
</TouchableOpacity>
<Text style={styles.title}></Text>
<View style={styles.placeholder} />
</View>
<TouchableOpacity
style={styles.dateInput}
onPress={() => setShow(true)}
>
<Text style={styles.dateText}></Text>
</TouchableOpacity>
{show && (
<DateTimePicker
value={date}
mode="date"
is24Hour={true}
display="default"
onChange={onChange}
/>
)}
<FlatList
data={browseData}
keyExtractor={(item) => item.id}
contentContainerStyle={styles.list}
renderItem={({ item }) => (
<View style={styles.item}>
<Image source={{ uri: item.image }} style={styles.image} />
<View style={styles.info}>
<View style={styles.row}>
<Text style={styles.name}>{item.name}</Text>
<Text style={styles.price}>¥{item.price.toFixed(2)}</Text>
</View>
<Text style={styles.time}>{item.time}</Text>
</View>
</View>
)}
ListEmptyComponent={
<Text style={styles.empty}></Text>
}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
backgroundColor: "#f8f8f8",
flex: 1,
},
header: {
paddingInline: 19,
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
backgroundColor: "white",
width: "100%",
paddingVertical: 15,
borderBottomWidth: 1,
borderBottomColor: "#e9ecef",
shadowColor: "#000",
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 4,
elevation: 3,
},
backButton: {
width: widthUtils(24,24).width,
},
title: {
fontSize: fontSize(20),
fontWeight: "600",
flex: 1,
textAlign: "center",
},
placeholder: {
width: widthUtils(24,24).width,
},
dateInput: {
padding: 20,
backgroundColor: "#fff",
marginBottom: 16,
},
dateText: {
fontSize: 16,
color: "#333",
},
list: {
gap: 12,
paddingHorizontal: 20,
},
item: {
flexDirection: "row",
backgroundColor: "#fff",
padding: 12,
borderRadius: 8,
gap: 12,
},
image: {
width: widthUtils(60,60).width,
height: widthUtils(60,60).height,
borderRadius: 6,
backgroundColor: "#eee",
},
info: {
flex: 1,
justifyContent: "center",
},
row: {
flexDirection: "row",
justifyContent: "space-between",
},
name: {
fontSize: 16,
fontWeight: "500",
flex: 1,
},
price: {
fontSize: 14,
fontWeight: "bold",
color: "#e60012",
marginLeft: 8,
},
time: {
fontSize: 12,
color: "#888",
marginTop: 4,
},
empty: {
textAlign: "center",
color: "#aaa",
fontSize: 15,
marginTop: 40,
},
});

207
app/screens/function/Collection.tsx

@ -0,0 +1,207 @@
import React from "react";
import {
View,
Text,
Image,
StyleSheet,
ScrollView,
TouchableOpacity,
} from "react-native";
import widthUtils from "../../utils/widthUtils";
import fontSize from "../../utils/fontsizeUtils";
import BackIcon from "../../components/BackIcon";
import { useNavigation } from "@react-navigation/native";
const FavoriteItem = ({
image,
title,
price,
}: {
image: string;
title: string;
price: number;
}) => {
return (
<View style={styles.item}>
<Image source={{ uri: image }} style={styles.image} />
<View style={styles.info}>
<Text style={styles.title} numberOfLines={2}>
{title}
</Text>
<Text style={styles.price}>{price}</Text>
<View style={styles.actions}>
<TouchableOpacity style={[styles.btn, styles.cart]}>
<Text style={styles.cartText}></Text>
</TouchableOpacity>
<TouchableOpacity style={[styles.btn, styles.delete]}>
<Text style={styles.deleteText}></Text>
</TouchableOpacity>
</View>
</View>
</View>
);
};
export const Collection = () => {
const navigation = useNavigation();
const data = [
{
id: "1",
image: "https://img.alicdn.com/imgextra/i1/1234567890/O1CN01Item1.jpg",
title: "韩版宽松休闲卫衣女春秋款薄款学生ins潮",
price: 89.0,
},
{
id: "2",
image: "https://img.alicdn.com/imgextra/i2/2234567890/O1CN01Item2.jpg",
title: "小米无线蓝牙耳机半入耳式 轻巧便携",
price: 129.0,
},
{
id: "3",
image: "https://img.alicdn.com/imgextra/i3/3234567890/O1CN01Item3.jpg",
title: "华为MateBook X Pro 2020款 13.9英寸全面屏笔记本电脑",
price: 10999.0,
},
{
id: "4",
image: "https://img.alicdn.com/imgextra/i2/2234567890/O1CN01Item2.jpg",
title: "小米无线蓝牙耳机半入耳式 轻巧便携",
price: 129.0,
},
{
id: "5",
image: "https://img.alicdn.com/imgextra/i2/2234567890/O1CN01Item2.jpg",
title: "小米无线蓝牙耳机半入耳式 轻巧便携",
price: 129.0,
},
{
id: "6",
image: "https://img.alicdn.com/imgextra/i2/2234567890/O1CN01Item2.jpg",
title: "小米无线蓝牙耳机半入耳式 轻巧便携",
price: 129.0,
},
{
id: "7",
image: "https://img.alicdn.com/imgextra/i2/2234567890/O1CN01Item2.jpg",
title: "小米无线蓝牙耳机半入耳式 轻巧便携",
price: 129.0,
},
{
id: "82",
image: "https://img.alicdn.com/imgextra/i2/2234567890/O1CN01Item2.jpg",
title: "小米无线蓝牙耳机半入耳式 轻巧便携",
price: 129.0,
},
// 可以继续添加更多商品
];
return (
<View style={styles.containerBox}>
<View style={styles.header}>
<TouchableOpacity
onPress={() => navigation.goBack()}
style={styles.backButton}
>
<BackIcon size={fontSize(22)} />
</TouchableOpacity>
<Text style={styles.titles}></Text>
<View style={styles.placeholder} />
</View>
<ScrollView style={styles.container} showsVerticalScrollIndicator={false}>
{data.map((item) => (
<FavoriteItem key={item.id} {...item} />
))}
</ScrollView>
</View>
);
};
const styles = StyleSheet.create({
containerBox: {
flex: 1,
backgroundColor: "#f5f5f5",
},
header: {
paddingInline: 19,
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
backgroundColor: "white",
width: "100%",
paddingVertical: 15,
},
titles: {
fontSize: fontSize(20),
fontWeight: "600",
flex: 1,
textAlign: "center",
},
backButton: {
width: widthUtils(24, 24).width,
},
placeholder: {
width: widthUtils(24, 24).width,
},
container: {
backgroundColor: "#f5f5f5",
paddingLeft: 20,
paddingRight: 20,
paddingBottom: 20,
marginTop: 20,
flex: 1,
},
item: {
flexDirection: "row",
padding: 12,
backgroundColor: "#fff",
borderBottomWidth: 1,
borderBottomColor: "#eee",
},
image: {
width: widthUtils(100, 100).width,
height: widthUtils(100, 100).height,
borderRadius: 4,
marginRight: 12,
},
info: {
flex: 1,
justifyContent: "space-between",
},
title: {
fontSize: fontSize(15),
color: "#333",
lineHeight: 20,
marginBottom: 6,
},
price: {
color: "#f40",
fontSize: fontSize(16),
marginBottom: 10,
},
actions: {
flexDirection: "row",
gap: 8,
},
btn: {
paddingVertical: 4,
paddingHorizontal: 10,
borderRadius: 3,
borderWidth: 1,
},
cart: {
borderColor: "#ff5000",
},
delete: {
borderColor: "#ccc",
},
cartText: {
fontSize: fontSize(12),
color: "#ff5000",
},
deleteText: {
fontSize: fontSize(12),
color: "#999",
},
});

2
app/screens/pay/PaySuccess.tsx

@ -10,7 +10,7 @@ import {
export const PaymentSuccessScreen = () => {
return (
<ScrollView style={styles.container}>
<ScrollView style={styles.container} showsVerticalScrollIndicator={false} >
<View style={styles.header}>
<View style={styles.headerSuccess}>
<View style={styles.headerSuccessImg}></View>

122
app/screens/setting/MyAddress.tsx

@ -4,31 +4,37 @@ import {
StyleSheet,
ScrollView,
TouchableOpacity,
ActivityIndicator,
} from "react-native";
import React, { Fragment } from "react";
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 { 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 { 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 [loading, setLoading] = useState(true);
const getAddress = async () => {
const response = await addressApi.getAddress();
setAddressList(response.items);
setLoading(false);
};
useEffect(() => {
getAddress();
}, []);
const deleteAddress = async (address_id: number) => {
setAddressList(addressList?.filter((item) => item.address_id !== address_id));
addressApi.deleteAddress(address_id)
}
setAddressList(
addressList?.filter((item) => item.address_id !== address_id)
);
addressApi.deleteAddress(address_id);
};
useFocusEffect(
useCallback(() => {
getAddress();
@ -37,28 +43,43 @@ export function MyAddress() {
const setAddressId = (address_id: number) => {
setAddress(address_id);
}
};
return (
<View style={styles.container}>
<View style={styles.header}>
<TouchableOpacity onPress={() => navigation.goBack()}>
<BackIcon />
<TouchableOpacity
onPress={() => navigation.goBack()}
style={styles.backButton}
>
<BackIcon size={fontSize(22)} />
</TouchableOpacity>
<Text style={styles.titles}></Text>
<View style={styles.placeholder} />
</View>
<ScrollView style={{flex:1}} showsVerticalScrollIndicator={false}>
{
addressList?.map((item) => (
<TouchableOpacity
{loading ? (
<View style={styles.loadingContainer}>
<ActivityIndicator size="large" color="#f77f3a" />
</View>
) : (
<Fragment>
<ScrollView
style={{ flex: 1, padding: 19 }}
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
item.address_id === address
? styles.addressItemSelected
: styles.addressItemNoSelected,
]}
>
<View style={styles.userInfoCard}>
@ -68,8 +89,7 @@ export function MyAddress() {
numberOfLines={1}
ellipsizeMode="tail"
>
{item.receiver_first_name} .{" "}
{item.receiver_last_name}
{item.receiver_first_name} . {item.receiver_last_name}
</Text>
<Text
style={styles.userCardInfo1}
@ -95,9 +115,9 @@ export function MyAddress() {
</View>
<TouchableOpacity
onPress={() => {
navigation.navigate("AddRess", {
address: item,
});
navigation.navigate("AddRess", {
address: item,
});
}}
>
<View style={styles.svgContainer}>
@ -106,16 +126,18 @@ export function MyAddress() {
</TouchableOpacity>
</View>
</TouchableOpacity>
))
}
</ScrollView>
<TouchableOpacity
style={styles.addButton}
onPress={() => navigation.navigate("AddRess")}
>
<Text style={styles.addButtonText}></Text>
</TouchableOpacity>
))}
</ScrollView>
<View style={{ paddingLeft: 19, paddingRight: 19 }}>
<TouchableOpacity
style={styles.addButton}
onPress={() => navigation.navigate("AddRess")}
>
<Text style={styles.addButtonText}></Text>
</TouchableOpacity>
</View>
</Fragment>
)}
</View>
);
}
@ -123,11 +145,36 @@ export function MyAddress() {
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 16,
backgroundColor: "#f8f8f8",
},
header: {
paddingVertical: 16,
paddingInline: 19,
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
backgroundColor: "white",
width: "100%",
paddingVertical: 15,
},
backButton: {
width: widthUtils(24, 24).width,
},
titles: {
fontSize: fontSize(20),
fontWeight: "600",
flex: 1,
textAlign: "center",
},
placeholder: {
width: widthUtils(24, 24).width,
},
title: {
fontSize: fontSize(20),
fontWeight: "600",
textAlign: "center",
position: "absolute",
width: "100%",
left: 0,
},
userCardContainer1: {
marginTop: 20,
@ -201,8 +248,8 @@ const styles = StyleSheet.create({
color: "#002fa7",
},
svgContainer: {
width: widthUtils(24,24).width,
height: widthUtils(24,24).height,
width: widthUtils(24, 24).width,
height: widthUtils(24, 24).height,
color: "#0051ff",
marginLeft: "auto",
},
@ -213,7 +260,7 @@ const styles = StyleSheet.create({
},
addButton: {
width: "100%",
height: widthUtils(60,60).height,
height: widthUtils(60, 60).height,
backgroundColor: "#002fa7",
justifyContent: "center",
alignItems: "center",
@ -225,4 +272,9 @@ const styles = StyleSheet.create({
fontSize: fontSize(16),
fontWeight: "500",
},
loadingContainer: {
flex: 1,
justifyContent: "center",
alignItems: "center",
},
});

BIN
assets/img/Mask group (1).png

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

BIN
assets/img/Mask group.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

4
package-lock.json generated

@ -10093,9 +10093,7 @@
}
},
"node_modules/npm/node_modules/chalk": {
"version": "5.4.1",
"resolved": "https://registry.npmmirror.com/chalk/-/chalk-5.4.1.tgz",
"integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==",
"version": "5.3.0",
"inBundle": true,
"license": "MIT",
"engines": {

1
package.json

@ -13,6 +13,7 @@
"@expo/metro-runtime": "~4.0.1",
"@react-native-async-storage/async-storage": "^2.1.2",
"@react-native-community/checkbox": "^0.5.17",
"@react-native-community/datetimepicker": "8.2.0",
"@react-native-picker/picker": "^2.11.0",
"@react-navigation/bottom-tabs": "^7.3.3",
"@react-navigation/native": "^7.0.19",

1052
yarn.lock

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save