From 2c2dfba45357bbd205a59145ae55a2779c911ae0 Mon Sep 17 00:00:00 2001 From: Lucas Faria Mendes Date: Fri, 14 Aug 2026 15:06:35 -0300 Subject: remake Signed-off-by: Lucas Faria Mendes --- src/app/(app)/(tabs)/_layout.tsx | 169 +++++++++++++++++++++++++++++++++++++ src/app/(app)/(tabs)/expenses.tsx | 2 + src/app/(app)/(tabs)/index.tsx | 2 + src/app/(app)/(tabs)/recurring.tsx | 2 + src/app/(app)/(tabs)/salary.tsx | 2 + 5 files changed, 177 insertions(+) create mode 100644 src/app/(app)/(tabs)/_layout.tsx create mode 100644 src/app/(app)/(tabs)/expenses.tsx create mode 100644 src/app/(app)/(tabs)/index.tsx create mode 100644 src/app/(app)/(tabs)/recurring.tsx create mode 100644 src/app/(app)/(tabs)/salary.tsx (limited to 'src/app/(app)/(tabs)') diff --git a/src/app/(app)/(tabs)/_layout.tsx b/src/app/(app)/(tabs)/_layout.tsx new file mode 100644 index 0000000..5033232 --- /dev/null +++ b/src/app/(app)/(tabs)/_layout.tsx @@ -0,0 +1,169 @@ +import React from 'react'; +import { Platform, StyleSheet, TouchableOpacity, View } from 'react-native'; +import { Tabs } from 'expo-router'; +import { BlurView } from 'expo-blur'; +import { Feather } from '@expo/vector-icons'; +import Animated, { + useAnimatedStyle, + withSpring, + withTiming, +} from 'react-native-reanimated'; +import * as Haptics from 'expo-haptics'; +import { Colors, Spacing } from '@/constants/theme'; + +function TabBarIcon({ + name, + isFocused, +}: { + name: keyof typeof Feather.glyphMap; + isFocused: boolean; +}) { + const animatedIconStyle = useAnimatedStyle(() => { + return { + transform: [ + { scale: withSpring(isFocused ? 1.15 : 1, { damping: 12, stiffness: 300 }) }, + ], + }; + }); + + const animatedIndicatorStyle = useAnimatedStyle(() => { + return { + opacity: withTiming(isFocused ? 1 : 0, { duration: 200 }), + transform: [ + { scale: withSpring(isFocused ? 1 : 0.5, { damping: 15, stiffness: 300 }) }, + ], + }; + }); + + return ( + + + + + + + ); +} + +function CustomTabBar({ state, descriptors, navigation }: any) { + return ( + + + {state.routes.map((route: any, index: number) => { + const { options } = descriptors[route.key]; + const isFocused = state.index === index; + + const onPress = () => { + const event = navigation.emit({ + type: 'tabPress', + target: route.key, + canPreventDefault: true, + }); + + if (!isFocused && !event.defaultPrevented) { + Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light); + navigation.navigate(route.name); + } + }; + + let iconName: keyof typeof Feather.glyphMap = 'home'; + if (route.name === 'index') iconName = 'pie-chart'; + else if (route.name === 'salary') iconName = 'dollar-sign'; + else if (route.name === 'recurring') iconName = 'repeat'; + else if (route.name === 'expenses') iconName = 'plus-square'; + + return ( + + + + ); + })} + + + ); +} + +export default function TabsLayout() { + return ( + } + screenOptions={{ + headerShown: false, + }} + > + + + + + + ); +} + +const styles = StyleSheet.create({ + tabBarContainer: { + position: 'absolute', + bottom: Platform.OS === 'ios' ? 30 : 20, + left: 24, + right: 24, + borderRadius: 32, + ...Platform.select({ + ios: { + shadowColor: '#000', + shadowOffset: { width: 0, height: 8 }, + shadowOpacity: 0.5, + shadowRadius: 16, + }, + android: { + elevation: 10, + }, + }), + }, + blurView: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-around', + borderRadius: 32, + backgroundColor: 'rgba(22, 27, 34, 0.75)', + borderWidth: 1, + borderColor: 'rgba(255, 255, 255, 0.08)', + overflow: 'hidden', + height: 64, + paddingHorizontal: Spacing.sm, + }, + tabItem: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + height: '100%', + }, + iconContainer: { + alignItems: 'center', + justifyContent: 'center', + width: 44, + height: 44, + }, + indicator: { + position: 'absolute', + bottom: -2, + width: 4, + height: 4, + borderRadius: 2, + backgroundColor: Colors.primaryLight, + }, +}); diff --git a/src/app/(app)/(tabs)/expenses.tsx b/src/app/(app)/(tabs)/expenses.tsx new file mode 100644 index 0000000..c313dc6 --- /dev/null +++ b/src/app/(app)/(tabs)/expenses.tsx @@ -0,0 +1,2 @@ +import OneTimeExpensesScreen from '@/screens/one-time-expenses-screen'; +export default OneTimeExpensesScreen; diff --git a/src/app/(app)/(tabs)/index.tsx b/src/app/(app)/(tabs)/index.tsx new file mode 100644 index 0000000..73bede0 --- /dev/null +++ b/src/app/(app)/(tabs)/index.tsx @@ -0,0 +1,2 @@ +import DashboardScreen from '@/screens/dashboard-screen'; +export default DashboardScreen; diff --git a/src/app/(app)/(tabs)/recurring.tsx b/src/app/(app)/(tabs)/recurring.tsx new file mode 100644 index 0000000..c5340ed --- /dev/null +++ b/src/app/(app)/(tabs)/recurring.tsx @@ -0,0 +1,2 @@ +import RecurringExpensesScreen from '@/screens/recurring-expenses-screen'; +export default RecurringExpensesScreen; diff --git a/src/app/(app)/(tabs)/salary.tsx b/src/app/(app)/(tabs)/salary.tsx new file mode 100644 index 0000000..1d30bb1 --- /dev/null +++ b/src/app/(app)/(tabs)/salary.tsx @@ -0,0 +1,2 @@ +import SalaryScreen from '@/screens/salary-screen'; +export default SalaryScreen; -- cgit v1.2.3