Implementação do RoadtripDJ - Funcionalidades e UI
This commit is contained in:
211
src/screens/main/HomeScreen.tsx
Normal file
211
src/screens/main/HomeScreen.tsx
Normal file
@@ -0,0 +1,211 @@
|
||||
import React from 'react';
|
||||
import { View, Text, StyleSheet, ScrollView, TouchableOpacity, SafeAreaView, ImageBackground } from 'react-native';
|
||||
import { NavigationProp } from '@react-navigation/native';
|
||||
import { Navigation } from 'lucide-react-native'; // Closest to MapPin with outline
|
||||
import { Clock } from 'lucide-react-native';
|
||||
import { colors } from '../../utils/colors';
|
||||
import { useAuth } from '../../contexts/AuthContext';
|
||||
|
||||
interface Props {
|
||||
navigation: NavigationProp<any>;
|
||||
}
|
||||
|
||||
export default function HomeScreen({ navigation }: Props) {
|
||||
const { user } = useAuth();
|
||||
const userName = user?.user_metadata?.name || 'Viajante';
|
||||
const initial = userName.charAt(0).toUpperCase();
|
||||
|
||||
return (
|
||||
<SafeAreaView style={styles.container}>
|
||||
<ScrollView contentContainerStyle={styles.scrollContent}>
|
||||
|
||||
{/* Header Section */}
|
||||
<View style={styles.header}>
|
||||
<Text style={styles.title}>As Tuas Viagens</Text>
|
||||
<View style={styles.avatar}>
|
||||
<Text style={styles.avatarText}>{initial}</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* Main Trip Card (Removed hardcoded data - empty state below) */}
|
||||
{/* Prompt Card */}
|
||||
<View style={styles.promptCard}>
|
||||
<Text style={styles.promptTitle}>Pronto para a próxima?</Text>
|
||||
<Text style={styles.promptSubtitle}>
|
||||
Descobre a melhor rota e a banda sonora{'\n'}perfeita para o caminho.
|
||||
</Text>
|
||||
<TouchableOpacity
|
||||
style={styles.promptButton}
|
||||
onPress={() => navigation.navigate('NewTripModal')}
|
||||
>
|
||||
<Text style={styles.promptButtonText}>Criar Nova Viagem</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
</ScrollView>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: colors.background,
|
||||
},
|
||||
scrollContent: {
|
||||
paddingHorizontal: 20,
|
||||
paddingTop: 10,
|
||||
paddingBottom: 120, // Extra space for bottom tab bar and floating button
|
||||
},
|
||||
header: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
marginBottom: 24,
|
||||
},
|
||||
title: {
|
||||
fontSize: 26,
|
||||
fontWeight: '800',
|
||||
color: colors.textMain,
|
||||
},
|
||||
avatar: {
|
||||
width: 44,
|
||||
height: 44,
|
||||
borderRadius: 22,
|
||||
backgroundColor: '#FFE5D4', // Light orange
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
avatarText: {
|
||||
color: colors.primaryDark,
|
||||
fontWeight: 'bold',
|
||||
fontSize: 16,
|
||||
},
|
||||
mainTripCard: {
|
||||
backgroundColor: colors.white,
|
||||
borderRadius: 24,
|
||||
shadowColor: '#000',
|
||||
shadowOffset: { width: 0, height: 8 },
|
||||
shadowOpacity: 0.05,
|
||||
shadowRadius: 12,
|
||||
elevation: 4,
|
||||
marginBottom: 24,
|
||||
},
|
||||
tripImage: {
|
||||
height: 180,
|
||||
justifyContent: 'flex-end',
|
||||
},
|
||||
imageOverlay: {
|
||||
padding: 20,
|
||||
backgroundColor: 'rgba(0,0,0,0.3)',
|
||||
borderTopLeftRadius: 24,
|
||||
borderTopRightRadius: 24,
|
||||
},
|
||||
tripTitle: {
|
||||
color: colors.white,
|
||||
fontSize: 22,
|
||||
fontWeight: 'bold',
|
||||
marginBottom: 4,
|
||||
},
|
||||
tripDate: {
|
||||
color: colors.white,
|
||||
fontSize: 14,
|
||||
fontWeight: '600',
|
||||
},
|
||||
tripContent: {
|
||||
padding: 20,
|
||||
},
|
||||
statsRow: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
marginBottom: 20,
|
||||
},
|
||||
statItem: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
gap: 6,
|
||||
},
|
||||
statText: {
|
||||
fontSize: 15,
|
||||
fontWeight: 'bold',
|
||||
color: colors.textSecondary,
|
||||
},
|
||||
statDot: {
|
||||
width: 4,
|
||||
height: 4,
|
||||
borderRadius: 2,
|
||||
backgroundColor: colors.inputBorder,
|
||||
marginHorizontal: 12,
|
||||
},
|
||||
itinerarySnippet: {
|
||||
flexDirection: 'row',
|
||||
backgroundColor: colors.background,
|
||||
padding: 16,
|
||||
borderRadius: 16,
|
||||
},
|
||||
timeline: {
|
||||
alignItems: 'center',
|
||||
marginRight: 12,
|
||||
paddingVertical: 4,
|
||||
},
|
||||
dot: {
|
||||
width: 8,
|
||||
height: 8,
|
||||
borderRadius: 4,
|
||||
backgroundColor: colors.primary,
|
||||
},
|
||||
dotEmpty: {
|
||||
backgroundColor: 'transparent',
|
||||
borderWidth: 2,
|
||||
borderColor: colors.primary,
|
||||
},
|
||||
line: {
|
||||
width: 2,
|
||||
height: 20,
|
||||
backgroundColor: colors.inputBorder,
|
||||
marginVertical: 2,
|
||||
},
|
||||
locations: {
|
||||
justifyContent: 'space-between',
|
||||
},
|
||||
locationText: {
|
||||
fontSize: 15,
|
||||
fontWeight: '600',
|
||||
color: colors.textSecondary,
|
||||
},
|
||||
promptCard: {
|
||||
backgroundColor: '#FFF5EB', // Very light orange
|
||||
borderRadius: 24,
|
||||
padding: 24,
|
||||
borderWidth: 2,
|
||||
borderColor: '#FFD4B8', // Dashed border color approx
|
||||
borderStyle: 'dashed',
|
||||
alignItems: 'center',
|
||||
},
|
||||
promptTitle: {
|
||||
fontSize: 20,
|
||||
fontWeight: 'bold',
|
||||
color: '#8C3800', // Dark brownish orange
|
||||
marginBottom: 8,
|
||||
},
|
||||
promptSubtitle: {
|
||||
fontSize: 14,
|
||||
color: '#B34700',
|
||||
textAlign: 'center',
|
||||
marginBottom: 20,
|
||||
lineHeight: 20,
|
||||
},
|
||||
promptButton: {
|
||||
backgroundColor: colors.primary,
|
||||
paddingHorizontal: 24,
|
||||
paddingVertical: 14,
|
||||
borderRadius: 20,
|
||||
width: '100%',
|
||||
alignItems: 'center',
|
||||
},
|
||||
promptButtonText: {
|
||||
color: colors.white,
|
||||
fontWeight: 'bold',
|
||||
fontSize: 16,
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user