diff --git a/package-lock.json b/package-lock.json index 5310cbd..2bb544b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "react": "18.3.1", "react-native": "0.75.5", "react-native-chart-kit": "^6.12.0", + "react-native-linear-gradient": "^2.8.3", "react-native-safe-area-context": "^5.5.1", "react-native-screens": "^4.5.0", "react-native-svg": "^15.12.0", @@ -13357,6 +13358,16 @@ "react-native": "*" } }, + "node_modules/react-native-linear-gradient": { + "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==", + "license": "MIT", + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, "node_modules/react-native-safe-area-context": { "version": "5.5.1", "resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-5.5.1.tgz", diff --git a/package.json b/package.json index 69e2da6..ab39b6c 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "react": "18.3.1", "react-native": "0.75.5", "react-native-chart-kit": "^6.12.0", + "react-native-linear-gradient": "^2.8.3", "react-native-safe-area-context": "^5.5.1", "react-native-screens": "^4.5.0", "react-native-svg": "^15.12.0", @@ -47,4 +48,4 @@ "engines": { "node": ">=18" } -} \ No newline at end of file +} diff --git a/src/components/common/WaveBackground.tsx b/src/components/common/WaveBackground.tsx new file mode 100644 index 0000000..6a50ea6 --- /dev/null +++ b/src/components/common/WaveBackground.tsx @@ -0,0 +1,73 @@ +import React from 'react'; +import {View, StyleSheet, Dimensions} from 'react-native'; +import LinearGradient from 'react-native-linear-gradient'; +import Svg, {Path} from 'react-native-svg'; + +const {width} = Dimensions.get('window'); + +interface WaveBackgroundProps { + height: number; + gradientColors: string[]; +} + +export const WaveBackground: React.FC = ({ + height, + gradientColors, +}) => { + return ( + + + + + + + + + + + + + ); +}; + +const styles = StyleSheet.create({ + container: { + width: '100%', + overflow: 'hidden', + }, + waveContainer: { + position: 'absolute', + bottom: -1, + left: 0, + right: 0, + }, + wave: { + backgroundColor: 'transparent', + }, + wave2: { + position: 'absolute', + bottom: 15, + }, +}); \ No newline at end of file diff --git a/src/constants/theme.ts b/src/constants/theme.ts index 1e62af2..ab19f60 100644 --- a/src/constants/theme.ts +++ b/src/constants/theme.ts @@ -3,19 +3,41 @@ export const theme = { colors: { - primary: '#05dcef', // 主题色 (0xff05dcef) - background: '#ffffff', // 背景色 (0xffffffff) - text: '#333333', // 文本颜色 (0xff333333) - accent: '#03a9f4', // 强调色 (0xff03a9f4) - - // 派生的颜色 - primaryLight: '#66e5f3', // 主题色亮色版 - primaryDark: '#04b0be', // 主题色暗色版 - textLight: '#666666', // 次要文本颜色 - border: '#dddddd', // 边框颜色 - error: '#ff3b30', // 错误颜色 - success: '#4cd964', // 成功颜色 - warning: '#ff9500', // 警告颜色 + // 基础颜色 + primary: '#4158D0', // 主色调 + secondary: '#C850C0', // 次要色调 + tertiary: '#FFCC70', // 第三色调 + background: '#ffffff', // 背景色 + text: '#333333', // 文本颜色 + textLight: '#666666', // 次要文本颜色 + border: '#dddddd', // 边框颜色 + error: '#ff3b30', // 错误颜色 + success: '#4cd964', // 成功颜色 + warning: '#ff9500', // 警告颜色 + cyan: '#00FFFF', // 青色背景 + + // 渐变色配置 + gradients: { + primary: ['#4158D0', '#C850C0', '#FFCC70'], // 主要渐变(蓝紫金) + contrast: ['#00F5A0', '#00D9F5'], // 对比渐变(绿青) + card: ['#9795F0', '#E3C3F1'], // 卡片渐变(柔和紫色) + login: ['#4158D0', '#C850C0', '#FFCC70'], // 登录页面专用渐变 + loginWave: ['rgba(255, 255, 255, 0.3)', 'rgba(255, 255, 255, 0.2)'], // 登录页面波浪渐变 + header: ['#4158D0', '#C850C0'], // 头部渐变 + button: ['#4158D0', '#C850C0'], // 按钮渐变 + // 波浪背景渐变 + wave: { + start: 'rgba(255, 255, 255, 0.3)', + middle: 'rgba(255, 255, 255, 0.2)', + end: 'rgba(255, 255, 255, 0.1)' + } + }, + + // 图表颜色 + chart: { + blue: '#0077B6', // 深蓝色 + orange: '#FB8500', // 明亮的橙色 + }, }, // 字体大小 @@ -25,6 +47,8 @@ export const theme = { medium: 16, large: 18, xlarge: 20, + xxlarge: 24, + title: 32, }, // 间距 @@ -41,7 +65,8 @@ export const theme = { small: 4, medium: 8, large: 12, - round: 999, + xl: 16, + circle: 999, }, // 阴影 @@ -77,6 +102,12 @@ export const theme = { elevation: 6, }, }, + + // 波浪效果配置 + wave: { + height: 60, + opacity: 1, + }, }; // 类型定义 diff --git a/src/screens/auth/LoginScreen.tsx b/src/screens/auth/LoginScreen.tsx index 146954a..be15b39 100644 --- a/src/screens/auth/LoginScreen.tsx +++ b/src/screens/auth/LoginScreen.tsx @@ -5,11 +5,19 @@ import { StyleSheet, TouchableOpacity, InteractionManager, + Image, + Dimensions, } from 'react-native'; import {useNavigation, useIsFocused} from '@react-navigation/native'; import {NativeStackNavigationProp} from '@react-navigation/native-stack'; import {RootStackParamList} from '../../navigation/types'; import {Screen} from '../../components/common/Screen'; +import {WaveBackground} from '../../components/common/WaveBackground'; +import LinearGradient from 'react-native-linear-gradient'; +import Svg, {Path, Defs, LinearGradient as SvgLinearGradient, Stop} from 'react-native-svg'; +import {useTheme} from '../../contexts/ThemeContext'; + +const {width} = Dimensions.get('window'); type LoginScreenNavigationProp = NativeStackNavigationProp< RootStackParamList, @@ -19,6 +27,7 @@ type LoginScreenNavigationProp = NativeStackNavigationProp< export const LoginScreen: React.FC = () => { const navigation = useNavigation(); const isFocused = useIsFocused(); + const theme = useTheme(); const handleLogin = useCallback(() => { if (!isFocused) return; @@ -32,53 +41,219 @@ export const LoginScreen: React.FC = () => { }, [navigation, isFocused]); return ( - - {/* 头部导航栏 */} - - 请登录(景旺冷冻仓) + + {/* 头部背景 */} + + + {/* 半透明波浪效果 */} + + + + + + + + + + 景旺冷冻仓 + + + 智能仓储管理系统 + + + + + {/* 不规则曲线背景 */} + + + + + + + + + + {/* 主体内容 */} - - {/* 登录按钮 */} - - 进入系统 - + + + + {/* Logo占位 */} + + + + JW + + + + + {/* 登录按钮 */} + + + + 进入系统 + + + + + + {/* 底部版权信息 */} + + + © 2024 景旺电子 + + ); }; const styles = StyleSheet.create({ - header: { - height: 56, - justifyContent: 'center', + screen: { + flex: 1, + }, + headerContainer: { + height: 280, + position: 'relative', + overflow: 'hidden', + }, + headerContent: { + position: 'absolute', + top: 60, + left: 0, + right: 0, alignItems: 'center', - backgroundColor: '#1890ff', }, headerTitle: { - color: '#fff', + fontSize: 32, + fontWeight: 'bold', + textShadowColor: 'rgba(0, 0, 0, 0.2)', + textShadowOffset: {width: 1, height: 1}, + textShadowRadius: 3, + }, + headerSubtitle: { fontSize: 18, - fontWeight: '600', + marginTop: 8, + opacity: 0.9, + }, + curveContainer: { + position: 'absolute', + top: 200, + left: 0, + right: 0, + zIndex: 1, + }, + curve: { + position: 'absolute', + top: 0, + }, + contentWrapper: { + flex: 1, + marginTop: 160, }, content: { flex: 1, alignItems: 'center', - paddingTop: 15, + paddingTop: 40, + }, + logoContainer: { + marginBottom: 40, + }, + logoCircle: { + width: 120, + height: 120, + borderRadius: 60, + justifyContent: 'center', + alignItems: 'center', + }, + logoText: { + fontSize: 40, + fontWeight: 'bold', + }, + loginButtonContainer: { + width: width * 0.8, + maxWidth: 300, + height: 50, + borderRadius: 25, + overflow: 'hidden', }, loginButton: { - backgroundColor: '#1890ff', - width: 250, - height: 44, - borderRadius: 4, - alignItems: 'center', + width: '100%', + height: '100%', justifyContent: 'center', + alignItems: 'center', }, loginButtonText: { - color: '#fff', - fontSize: 16, + fontSize: 18, fontWeight: '600', }, + footer: { + padding: 20, + alignItems: 'center', + }, + footerText: { + fontSize: 12, + }, + gradientBackground: { + opacity: 0.95, + }, + waveOverlay: { + position: 'absolute', + width: '100%', + height: '100%', + opacity: 0.6, + }, + waveSvg: { + position: 'absolute', + top: 0, + }, }); \ No newline at end of file diff --git a/src/screens/home/HomeScreen.tsx b/src/screens/home/HomeScreen.tsx index f2c8e17..1274ffe 100644 --- a/src/screens/home/HomeScreen.tsx +++ b/src/screens/home/HomeScreen.tsx @@ -14,6 +14,10 @@ import { RootStackParamList } from '../../navigation/types'; import { PieChart } from 'react-native-chart-kit'; import Icon from 'react-native-vector-icons/MaterialIcons'; import { useTheme } from '../../contexts/ThemeContext'; +import LinearGradient from 'react-native-linear-gradient'; +import Svg, { Path } from 'react-native-svg'; + +const { width } = Dimensions.get('window'); type HomeScreenNavigationProp = NativeStackNavigationProp< RootStackParamList, @@ -33,12 +37,14 @@ export const HomeScreen: React.FC = () => { const [fontLoaded, setFontLoaded] = useState(false); useEffect(() => { - Icon.loadFont().then(() => { - console.log('Icon fonts loaded'); - setFontLoaded(true); - }).catch(error => { - console.error('Failed to load icon fonts:', error); - }); + Icon.loadFont() + .then(() => { + console.log('Icon fonts loaded'); + setFontLoaded(true); + }) + .catch(error => { + console.error('Failed to load icon fonts:', error); + }); }, []); const menuItems: MenuItem[] = [ @@ -50,16 +56,16 @@ export const HomeScreen: React.FC = () => { { name: '空闲', population: 40, - color: theme.colors.success || '#4CAF50', + color: theme.colors.chart.blue, legendFontColor: theme.colors.textLight, - legendFontSize: 15, + legendFontSize: theme.fontSize.regular, }, { name: '占用', population: 60, - color: theme.colors.warning || '#FF9800', + color: theme.colors.chart.orange, legendFontColor: theme.colors.textLight, - legendFontSize: 15, + legendFontSize: theme.fontSize.regular, }, ]; @@ -69,94 +75,162 @@ export const HomeScreen: React.FC = () => { color: (opacity = 1) => `rgba(0, 0, 0, ${opacity})`, }; - const screenWidth = Dimensions.get('window').width; - if (!fontLoaded) { return ( - - 加载图标中... + + 加载图标中... ); } return ( - - {/* 头部导航栏 */} - - setIsDrawerOpen(!isDrawerOpen)} - style={styles.menuButton}> - - - - 景旺WMS移动终端(冷冻) - - + + {/* 头部区域 */} + + {/* 渐变背景 */} + + {/* 半透明波浪效果 */} + + + + + + + + {/* 头部内容 */} + + setIsDrawerOpen(!isDrawerOpen)} + style={styles.menuButton}> + + + + 景旺WMS移动终端(冷冻) + + {/* 主体内容 */} + + + + {/* 快捷操作区 */} + + {menuItems.map((item, index) => ( + navigation.navigate(item.route)}> + + + + + + {item.title} + + + ))} + + + {/* 图表区域 */} + + + 库存占用情况 + + + + + + + + {/* 侧边菜单 */} {isDrawerOpen && ( - - - - 景旺电子 - - - 欢迎使用WMS移动终端 - - - {menuItems.map((item, index) => ( - { - setIsDrawerOpen(false); - navigation.navigate(item.route); - }}> - - - - - {item.title} + <> + + + + 景旺电子 - - ))} - - )} - - {/* 主体内容 */} - - - 库存占用情况: - - - + 欢迎使用WMS移动终端 + + + {menuItems.map((item, index) => ( + { + setIsDrawerOpen(false); + navigation.navigate(item.route); + }}> + + + + + {item.title} + + + ))} + + setIsDrawerOpen(false)} /> - - - - {/* 遮罩层 */} - {isDrawerOpen && ( - setIsDrawerOpen(false)} - /> + )} ); @@ -166,45 +240,96 @@ const styles = StyleSheet.create({ container: { flex: 1, }, + mainContent: { + flex: 1, + position: 'relative', + }, + scrollContent: { + flexGrow: 1, + paddingVertical: 20, + }, loadingContainer: { flex: 1, justifyContent: 'center', alignItems: 'center', }, - header: { - height: 56, + headerSection: { + height: 160, + position: 'relative', + overflow: 'hidden', + }, + waveOverlay: { + position: 'absolute', + width: '100%', + height: '100%', + opacity: 0.6, + }, + waveSvg: { + position: 'absolute', + top: 0, + }, + headerContent: { flexDirection: 'row', alignItems: 'center', paddingHorizontal: 16, + paddingTop: 16, justifyContent: 'space-between', + height: 160, }, menuButton: { padding: 8, }, headerTitle: { + flex: 1, fontSize: 18, fontWeight: '600', textAlign: 'center', }, - headerRight: { - width: 40, - flexDirection: 'row', - justifyContent: 'flex-end', - }, iconButton: { padding: 8, }, content: { flex: 1, + marginTop: -20, + }, + quickActions: { + flexDirection: 'row', + justifyContent: 'space-around', + paddingHorizontal: 16, + marginTop: 20, + }, + actionCard: { + width: width / 2 - 24, + borderRadius: 12, padding: 20, + alignItems: 'center', + overflow: 'hidden', + }, + iconGradient: { + width: 64, + height: 64, + borderRadius: 32, + justifyContent: 'center', + alignItems: 'center', + marginBottom: 12, + }, + actionTitle: { + fontSize: 16, + textAlign: 'center', + }, + chartSection: { + borderRadius: 12, + margin: 16, + padding: 16, + overflow: 'hidden', }, chartTitle: { - fontSize: 16, - marginBottom: 10, + fontSize: 18, + fontWeight: '600', + marginBottom: 16, }, chartContainer: { alignItems: 'center', - marginTop: 20, }, drawer: { position: 'absolute', @@ -227,6 +352,7 @@ const styles = StyleSheet.create({ }, drawerSubtitle: { fontSize: 14, + opacity: 0.9, }, drawerItem: { flexDirection: 'row', @@ -234,7 +360,7 @@ const styles = StyleSheet.create({ padding: 16, borderBottomWidth: 1, }, - iconContainer: { + drawerIconContainer: { width: 32, height: 32, justifyContent: 'center', diff --git a/src/screens/stockIn/StockInEmpty.tsx b/src/screens/stockIn/StockInEmpty.tsx index 2695632..69c17af 100644 --- a/src/screens/stockIn/StockInEmpty.tsx +++ b/src/screens/stockIn/StockInEmpty.tsx @@ -15,6 +15,8 @@ import {useNavigation} from '@react-navigation/native'; import {RootStackParamList} from '../../navigation/types'; import {useTheme} from '../../contexts/ThemeContext'; import Icon from 'react-native-vector-icons/MaterialIcons'; +import LinearGradient from 'react-native-linear-gradient'; +import Svg, {Path} from 'react-native-svg'; interface StockInEmptyResponse { code: number; @@ -83,7 +85,11 @@ export const StockInEmpty: React.FC = () => { return ( {/* 头部导航栏 */} - + navigation.goBack()} style={styles.backButton}> @@ -91,12 +97,33 @@ export const StockInEmpty: React.FC = () => { 空载具入库 + + + {/* 波浪效果 */} + + + + {/* 主体内容 */} + {/* 说明文字 */} - + 请扫描或输入载具号进行空载具入库操作 @@ -108,7 +135,10 @@ export const StockInEmpty: React.FC = () => { 载具号 * - + { {/* 提交按钮 */} - - {loading ? ( - - ) : ( - <> - - - 确认入库 - - - )} - + + + {loading ? ( + + ) : ( + <> + + + 确认入库 + + + )} + + ); @@ -169,6 +201,19 @@ const styles = StyleSheet.create({ shadowOpacity: 0.2, shadowRadius: 2, }, + waveContainer: { + height: 100, + backgroundColor: 'transparent', + position: 'absolute', + top: 56, + left: 0, + right: 0, + zIndex: -1, + }, + waveSvg: { + position: 'absolute', + top: 0, + }, backButton: { padding: 8, }, @@ -186,7 +231,6 @@ const styles = StyleSheet.create({ infoSection: { flexDirection: 'row', alignItems: 'center', - backgroundColor: 'rgba(24, 144, 255, 0.1)', padding: 16, borderRadius: 8, marginBottom: 24, @@ -214,7 +258,6 @@ const styles = StyleSheet.create({ borderRadius: 8, height: 48, paddingHorizontal: 12, - backgroundColor: 'rgba(255, 255, 255, 0.8)', }, inputIcon: { marginRight: 8, @@ -231,9 +274,6 @@ const styles = StyleSheet.create({ submitButton: { height: 48, borderRadius: 24, - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', marginTop: 32, elevation: 2, shadowColor: '#000', @@ -241,6 +281,12 @@ const styles = StyleSheet.create({ shadowOpacity: 0.1, shadowRadius: 2, }, + submitButtonContent: { + flex: 1, + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + }, submitButtonDisabled: { opacity: 0.6, }, diff --git a/src/screens/stockIn/StockInWheelManual.tsx b/src/screens/stockIn/StockInWheelManual.tsx index 6fff546..44e9958 100644 --- a/src/screens/stockIn/StockInWheelManual.tsx +++ b/src/screens/stockIn/StockInWheelManual.tsx @@ -12,6 +12,8 @@ import { import {useNavigation} from '@react-navigation/native'; import Icon from 'react-native-vector-icons/MaterialIcons'; import {useTheme} from '../../contexts/ThemeContext'; +import LinearGradient from 'react-native-linear-gradient'; +import Svg, {Path} from 'react-native-svg'; interface PackageDataItem { id: string; @@ -236,7 +238,11 @@ const StockInWheelManual: React.FC = () => { return ( {/* 头部导航栏 */} - + navigation.goBack()}> @@ -246,285 +252,326 @@ const StockInWheelManual: React.FC = () => { 手动码盘入库 + + + {/* 波浪效果 */} + + + + - - {/* 信息提示区 */} - - - - 请先扫描载具号,然后添加物料信息进行码盘入库 - - - - {/* 载具号输入区 */} - - 载具号 - - - - {vehicleCode.length > 0 && ( - setVehicleCode('')} - style={styles.clearButton}> - - - )} + + + + {/* 信息提示区 */} + + + + 请先扫描载具号,然后添加物料信息进行码盘入库 + - - {/* 条码输入区 */} - - 物料条码 - - - - {goodsCode.length > 0 && ( - setGoodsCode('')} - style={styles.clearButton}> - - - )} - - - - {/* 选项区域 */} - - {/* 区域选择 */} - - 区域 - - setAreaID('有卤')}> - - 有卤 - - - setAreaID('无卤')}> - - 无卤 - - + {/* 载具号输入区 */} + + 载具号 + + + + {vehicleCode.length > 0 && ( + setVehicleCode('')} + style={styles.clearButton}> + + + )} - {/* 工厂选择 */} - - 工厂 - - setFactory('二厂')}> - - 二厂 - - - setFactory('三厂')}> - - 三厂 - - + {/* 条码输入区 */} + + 物料条码 + + + + {goodsCode.length > 0 && ( + setGoodsCode('')} + style={styles.clearButton}> + + + )} - {/* 状态选择 - 改为与区域、工厂相同的样式 */} - - 状态 - - - - {['合格', '不合格', '封存', '待检', '进口物料'].map((item) => ( - setStatus(item)}> - + {/* 区域选择 */} + + 区域 + + setAreaID('有卤')}> + + 有卤 + + + setAreaID('无卤')}> + + 无卤 + + + + + + {/* 工厂选择 */} + + 工厂 + + setFactory('二厂')}> + + 二厂 + + + setFactory('三厂')}> + + 三厂 + + + + + + {/* 状态选择 - 改为与区域、工厂相同的样式 */} + + 状态 + + + + {['合格', '不合格', '封存', '待检', '进口物料'].map((item) => ( + - {item} - - - ))} - - + styles.radioButton, + {borderColor: theme.colors.border}, + status === item && styles.radioButtonActive, + status === item && {backgroundColor: theme.colors.primary}, + ]} + onPress={() => setStatus(item)}> + + {item} + + + ))} + + + - - {/* 操作按钮区 */} - - - - - 添加物料 - - + {/* 操作按钮区 */} + + + + + + 添加物料 + + + - - - - 码盘完成 - - - - - {/* 物料列表 */} - - - - - 已添加物料 ({packageData.length}) - + + + + + 码盘完成 + + + - {packageData.map((item, index) => ( - - {/* 卡片头部 */} - - - - 序号:{item.id} - - - 采购单号:{item.segment1} - - - - showDetails(item)}> - - - deleteItem(item.id)}> - - - - + {/* 物料列表 */} + + + + + 已添加物料 ({packageData.length}) + + - {/* 卡片内容 */} - - - - 物料号 - {item.itemId} + {packageData.map((item, index) => ( + + + {/* 卡片头部 */} + + + + 序号:{item.id} + + + 采购单号:{item.segment1} + - - 批次号 - {item.batch} - - - - - - 数量 + modifyNumber(item.id)}> - - {item.quantity} - - + style={[styles.cardActionButton, {backgroundColor: `${theme.colors.primary}15`}]} + onPress={() => showDetails(item)}> + + + deleteItem(item.id)}> + - - - 重量 - {item.weight} - - - 生产日期 - {item.productData} + {/* 卡片内容 */} + + + + 物料号 + {item.itemId} + + + 批次号 + {item.batch} + + + + + + 数量 + modifyNumber(item.id)}> + + {item.quantity} + + + + + + 重量 + {item.weight} + + + + + + 生产日期 + {item.productData} + - - ))} - - + ))} + + + {loading && ( @@ -544,6 +591,14 @@ const styles = StyleSheet.create({ container: { flex: 1, }, + mainContent: { + flex: 1, + position: 'relative', + }, + scrollContent: { + flexGrow: 1, + padding: 16, + }, header: { height: 56, flexDirection: 'row', @@ -556,6 +611,19 @@ const styles = StyleSheet.create({ shadowOpacity: 0.2, shadowRadius: 2, }, + waveContainer: { + height: 100, + backgroundColor: 'transparent', + position: 'absolute', + top: 56, + left: 0, + right: 0, + zIndex: -1, + }, + waveSvg: { + position: 'absolute', + top: 0, + }, backButton: { padding: 8, }, @@ -566,10 +634,6 @@ const styles = StyleSheet.create({ headerRight: { width: 40, }, - content: { - flex: 1, - padding: 16, - }, infoSection: { flexDirection: 'row', alignItems: 'center', @@ -650,15 +714,18 @@ const styles = StyleSheet.create({ flex: 1, height: 48, borderRadius: 24, - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', elevation: 2, shadowColor: '#000', shadowOffset: {width: 0, height: 2}, shadowOpacity: 0.1, shadowRadius: 2, }, + buttonContent: { + flex: 1, + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + }, buttonIcon: { marginRight: 8, }, @@ -683,13 +750,8 @@ const styles = StyleSheet.create({ }, card: { borderRadius: 12, - borderWidth: 1, marginBottom: 12, - elevation: 2, - shadowColor: '#000', - shadowOffset: {width: 0, height: 2}, - shadowOpacity: 0.1, - shadowRadius: 2, + overflow: 'hidden', }, cardHeader: { flexDirection: 'row',