Subscription Home Screen

This commit is contained in:
CalebChen768 2024-03-19 14:23:45 +08:00
parent c52ec09119
commit 3c3b84c3bd
5 changed files with 189 additions and 5 deletions

View File

@ -1,5 +1,7 @@
PODS: PODS:
- boost (1.83.0) - boost (1.83.0)
- BVLinearGradient (2.8.3):
- React-Core
- CocoaAsyncSocket (7.6.5) - CocoaAsyncSocket (7.6.5)
- DoubleConversion (1.1.6) - DoubleConversion (1.1.6)
- FBLazyVector (0.73.6) - FBLazyVector (0.73.6)
@ -1132,6 +1134,7 @@ PODS:
DEPENDENCIES: DEPENDENCIES:
- boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`) - boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`)
- BVLinearGradient (from `../node_modules/react-native-linear-gradient`)
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
- FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`) - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`)
- FBReactNativeSpec (from `../node_modules/react-native/React/FBReactNativeSpec`) - FBReactNativeSpec (from `../node_modules/react-native/React/FBReactNativeSpec`)
@ -1229,6 +1232,8 @@ SPEC REPOS:
EXTERNAL SOURCES: EXTERNAL SOURCES:
boost: boost:
:podspec: "../node_modules/react-native/third-party-podspecs/boost.podspec" :podspec: "../node_modules/react-native/third-party-podspecs/boost.podspec"
BVLinearGradient:
:path: "../node_modules/react-native-linear-gradient"
DoubleConversion: DoubleConversion:
:podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec" :podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec"
FBLazyVector: FBLazyVector:
@ -1337,6 +1342,7 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS: SPEC CHECKSUMS:
boost: d3f49c53809116a5d38da093a8aa78bf551aed09 boost: d3f49c53809116a5d38da093a8aa78bf551aed09
BVLinearGradient: 880f91a7854faff2df62518f0281afb1c60d49a3
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
DoubleConversion: fea03f2699887d960129cc54bba7e52542b6f953 DoubleConversion: fea03f2699887d960129cc54bba7e52542b6f953
FBLazyVector: f64d1e2ea739b4d8f7e4740cde18089cd97fe864 FBLazyVector: f64d1e2ea739b4d8f7e4740cde18089cd97fe864

View File

@ -20,6 +20,7 @@
"react-i18next": "^14.1.0", "react-i18next": "^14.1.0",
"react-native": "0.73.6", "react-native": "0.73.6",
"react-native-gesture-handler": "^2.15.0", "react-native-gesture-handler": "^2.15.0",
"react-native-linear-gradient": "^2.8.3",
"react-native-safe-area-context": "^4.9.0", "react-native-safe-area-context": "^4.9.0",
"react-native-screens": "^3.29.0", "react-native-screens": "^3.29.0",
"react-native-sqlite-storage": "^6.0.1", "react-native-sqlite-storage": "^6.0.1",

View File

@ -4,7 +4,7 @@ import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
import {NavigationContainer} from '@react-navigation/native'; import {NavigationContainer} from '@react-navigation/native';
import Icon from 'react-native-vector-icons/Ionicons'; import Icon from 'react-native-vector-icons/Ionicons';
import {useTranslation} from 'react-i18next'; import {useTranslation} from 'react-i18next';
import { RootTabParamList } from "./type.ts"; import {RootTabParamList} from './type.ts';
import OverviewPage from '../pages/OverviewPage'; import OverviewPage from '../pages/OverviewPage';
import SubscriptionPage from '../pages/SubscriptionPage'; import SubscriptionPage from '../pages/SubscriptionPage';
@ -48,7 +48,11 @@ const BottomTabNavigator: React.FC = () => {
tabBarInactiveTintColor: 'gray', tabBarInactiveTintColor: 'gray',
})}> })}>
<Tab.Screen name="Overview" component={OverviewPage} /> <Tab.Screen name="Overview" component={OverviewPage} />
<Tab.Screen name="Subscription" component={SubscriptionPage} /> <Tab.Screen
name="Subscription"
component={SubscriptionPage}
options={{headerShown: false}}
/>
<Tab.Screen name="Saving" component={SavingPage} /> <Tab.Screen name="Saving" component={SavingPage} />
<Tab.Screen name="Profile" component={ProfilePage} /> <Tab.Screen name="Profile" component={ProfilePage} />
</Tab.Navigator> </Tab.Navigator>

View File

@ -1,10 +1,100 @@
import React from 'react'; import React, {useState, useEffect} from 'react';
import { View, Text, StyleSheet } from 'react-native'; import {View, Text, StyleSheet, FlatList, TouchableOpacity} from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';
import LinearGradient from 'react-native-linear-gradient';
type Subscription = {
id: number;
name: string;
amount: number;
startDate: string;
endDate: string;
color: string[];
};
const mockSubscriptions: Subscription[] = [
{
id: 1,
name: 'Netflix',
amount: 12.99,
startDate: '2021-01-01',
endDate: '2022-01-01',
color: ['#e52d27', '#b31217'],
},
{
id: 2,
name: 'Spotify',
amount: 9.99,
startDate: '2021-02-01',
endDate: '2022-02-01',
color: ['#1db954', '#1ed760'],
},
{
id: 3,
name: 'Amazon Prime',
amount: 14.99,
startDate: '2021-03-01',
endDate: '2022-03-01',
color: ['#f90', '#ff9900'],
},
{
id: 4,
name: 'Disney+',
amount: 7.99,
startDate: '2021-04-01',
endDate: '2022-04-01',
color: ['#113ccf', '#5e91f2'],
},
// 更多示例数据...
];
const SubscriptionPage: React.FC = () => { const SubscriptionPage: React.FC = () => {
const [subscriptions, setSubscriptions] =
useState<Subscription[]>(mockSubscriptions);
const fetchSubscriptions = () => {
setSubscriptions(mockSubscriptions);
};
useEffect(() => {
fetchSubscriptions();
}, []);
const renderItem = ({item}: {item: Subscription}) => {
return (
<LinearGradient
colors={item.color}
style={styles.card}
start={{x: 0, y: 0}}
end={{x: 1, y: 1}}>
<View style={styles.iconPlaceholder} />
<View style={styles.textContainer}>
<Text style={styles.name}>{item.name}</Text>
<Text style={styles.date}>{item.endDate}</Text>
</View>
<Text style={styles.amount}>${item.amount}</Text>
<TouchableOpacity style={styles.editButton}>
<Icon name="pencil" size={20} color="#fff" />
</TouchableOpacity>
</LinearGradient>
);
};
return ( return (
<View style={styles.container}> <View style={styles.container}>
<Text>Subscription Page</Text> <View style={styles.header}>
<Text style={styles.headerTitle}>Subscriptions</Text>
</View>
<FlatList
contentContainerStyle={styles.listContainer}
data={subscriptions}
renderItem={renderItem}
keyExtractor={item => item.id.toString()}
numColumns={2}
columnWrapperStyle={styles.row}
/>
<TouchableOpacity style={styles.addButton}>
<Icon name="add" size={30} color="#fff" />
</TouchableOpacity>
</View> </View>
); );
}; };
@ -12,9 +102,87 @@ const SubscriptionPage: React.FC = () => {
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
flex: 1, flex: 1,
backgroundColor: '#f7f7f7',
},
listContainer: {
paddingHorizontal: 16,
},
row: {
justifyContent: 'space-between',
marginBottom: 16,
},
card: {
borderRadius: 15,
padding: 15,
width: '48%',
shadowColor: '#000',
shadowOpacity: 0.1,
shadowRadius: 10,
shadowOffset: {width: 0, height: 4},
elevation: 5,
},
iconPlaceholder: {
width: 50,
height: 50,
borderRadius: 25,
backgroundColor: '#fff',
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center', alignItems: 'center',
}, },
textContainer: {
flexDirection: 'column',
marginTop: 10,
},
name: {
fontSize: 18,
fontWeight: 'bold',
color: '#fff',
},
date: {
fontSize: 14,
color: '#fff',
marginTop: 5,
},
amount: {
fontSize: 16,
fontWeight: 'bold',
color: '#fff',
position: 'absolute',
top: 10,
right: 10,
},
editButton: {
position: 'absolute',
bottom: 10,
right: 10,
},
addButton: {
backgroundColor: '#4F8EF7',
position: 'absolute',
bottom: 30,
right: 30,
width: 50,
height: 50,
borderRadius: 25,
justifyContent: 'center',
alignItems: 'center',
shadowColor: '#000',
shadowOffset: {width: 0, height: 2},
shadowOpacity: 0.2,
shadowRadius: 8,
elevation: 5,
},
header: {
paddingTop: 70,
paddingBottom: 15,
paddingLeft: 15,
alignItems: 'flex-start',
},
headerTitle: {
fontSize: 27,
fontWeight: 'bold',
color: '#333',
},
}); });
export default SubscriptionPage; export default SubscriptionPage;

View File

@ -5839,6 +5839,11 @@ react-native-gesture-handler@^2.15.0, "react-native-gesture-handler@>= 1.0.0":
lodash "^4.17.21" lodash "^4.17.21"
prop-types "^15.7.2" prop-types "^15.7.2"
react-native-linear-gradient@^2.8.3:
version "2.8.3"
resolved "https://registry.npmjs.org/react-native-linear-gradient/-/react-native-linear-gradient-2.8.3.tgz"
integrity sha512-KflAXZcEg54PXkLyflaSZQ3PJp4uC4whM7nT/Uot9m0e/qxFV3p6uor1983D1YOBJbJN7rrWdqIjq0T42jOJyA==
react-native-safe-area-context@^4.9.0, "react-native-safe-area-context@>= 3.0.0": react-native-safe-area-context@^4.9.0, "react-native-safe-area-context@>= 3.0.0":
version "4.9.0" version "4.9.0"
resolved "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-4.9.0.tgz" resolved "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-4.9.0.tgz"