components | index
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { View, Text } from "react-native";
|
/*import { View, Text, ScrollView } from "react-native";
|
||||||
|
|
||||||
export default function HomeScreen() {
|
export default function HomeScreen() {
|
||||||
return (
|
return (
|
||||||
@@ -12,4 +12,91 @@ export default function HomeScreen() {
|
|||||||
<Text>Inicio</Text>
|
<Text>Inicio</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
import { View, ScrollView } from 'react-native';
|
||||||
|
|
||||||
|
import EtaCard from '../components/EtaCard';
|
||||||
|
import QuickAction from '../components/QuickAction';
|
||||||
|
import SectionTitle from '../components/SectionTitle';
|
||||||
|
import AlertItem from '../components/Alertltem';
|
||||||
|
|
||||||
|
export default function Home() {
|
||||||
|
return (
|
||||||
|
<ScrollView
|
||||||
|
style={{ flex: 1, backgroundColor: '#ffffff' }}
|
||||||
|
showsVerticalScrollIndicator={false}
|
||||||
|
>
|
||||||
|
|
||||||
|
{/*ETA*/}
|
||||||
|
<EtaCard
|
||||||
|
minutes={12}
|
||||||
|
status="Camión en ruta 🚛"
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/*ACCIONES RÁPIDAS*/}
|
||||||
|
<SectionTitle title="Acciones rápidas" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'space-around',
|
||||||
|
paddingHorizontal: 10,
|
||||||
|
marginTop: 10,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<QuickAction title="Mapa" icon="🗺️" />
|
||||||
|
<QuickAction title="Reportar" icon="🚨" />
|
||||||
|
<QuickAction title="Horarios" icon="🕒" />
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/*IMPACTO SEMANAL*/}
|
||||||
|
<SectionTitle title="Impacto semanal" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
marginHorizontal: 15,
|
||||||
|
backgroundColor: '#F0F0F3',
|
||||||
|
padding: 20,
|
||||||
|
borderRadius: 16,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AlertItem
|
||||||
|
message="🚛 5 recolecciones completadas"
|
||||||
|
type="success"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<AlertItem
|
||||||
|
message="⏱ Sin retrasos esta semana"
|
||||||
|
type="success"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<AlertItem
|
||||||
|
message="📍 Cobertura completa en tu zona"
|
||||||
|
type="success"
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{/* 🔔 ALERTAS RECIENTES */}
|
||||||
|
<SectionTitle title="Alertas recientes" />
|
||||||
|
|
||||||
|
<View style={{ marginBottom: 40 }}>
|
||||||
|
<AlertItem
|
||||||
|
message="🚛 Ruta iniciada"
|
||||||
|
type="success"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<AlertItem
|
||||||
|
message="📍 Camión cerca de tu zona"
|
||||||
|
type="warning"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<AlertItem
|
||||||
|
message="⏳ Retraso detectado"
|
||||||
|
type="danger"
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
</ScrollView>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
import { View, Text, StyleSheet } from 'react-native';
|
||||||
|
import { Colors, Spacing } from '../constants/theme';
|
||||||
|
|
||||||
|
type AlertItemProps = {
|
||||||
|
message: string;
|
||||||
|
type?: 'success' | 'warning' | 'danger';
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function AlertItem({
|
||||||
|
message,
|
||||||
|
type = 'success',
|
||||||
|
}: AlertItemProps) {
|
||||||
|
|
||||||
|
const theme = Colors.light;
|
||||||
|
|
||||||
|
const getColor = () => {
|
||||||
|
switch (type) {
|
||||||
|
case 'success':
|
||||||
|
return '#22C55E';
|
||||||
|
case 'warning':
|
||||||
|
return '#FACC15';
|
||||||
|
case 'danger':
|
||||||
|
return '#EF4444';
|
||||||
|
default:
|
||||||
|
return theme.textSecondary;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
<View style={[styles.bar, { backgroundColor: getColor() }]} />
|
||||||
|
<Text style={[styles.text, { color: theme.text }]}>
|
||||||
|
{message}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
padding: Spacing.three,
|
||||||
|
marginHorizontal: Spacing.three,
|
||||||
|
marginVertical: Spacing.one,
|
||||||
|
borderRadius: 12,
|
||||||
|
backgroundColor: '#F0F0F3',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
bar: {
|
||||||
|
width: 6,
|
||||||
|
height: '100%',
|
||||||
|
borderRadius: 4,
|
||||||
|
marginRight: Spacing.two,
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
fontSize: 14,
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import { View, TextInput, StyleSheet } from 'react-native';
|
||||||
|
import { Colors, Spacing } from '../constants/theme';
|
||||||
|
|
||||||
|
type InputFieldProps = {
|
||||||
|
placeholder?: string;
|
||||||
|
value?: string;
|
||||||
|
onChangeText?: (text: string) => void;
|
||||||
|
secureTextEntry?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function InputField({
|
||||||
|
placeholder,
|
||||||
|
value,
|
||||||
|
onChangeText,
|
||||||
|
secureTextEntry,
|
||||||
|
}: InputFieldProps) {
|
||||||
|
|
||||||
|
const theme = Colors.light;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
styles.container,
|
||||||
|
{ backgroundColor: theme.backgroundElement },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<TextInput
|
||||||
|
placeholder={placeholder}
|
||||||
|
placeholderTextColor={theme.textSecondary}
|
||||||
|
value={value}
|
||||||
|
onChangeText={onChangeText}
|
||||||
|
secureTextEntry={secureTextEntry}
|
||||||
|
style={[styles.input, { color: theme.text }]}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
paddingHorizontal: Spacing.three,
|
||||||
|
paddingVertical: Spacing.two,
|
||||||
|
borderRadius: 12,
|
||||||
|
marginVertical: 8,
|
||||||
|
},
|
||||||
|
input: {
|
||||||
|
fontSize: 16,
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import { Pressable, Text, StyleSheet } from 'react-native';
|
||||||
|
import { Colors, Spacing } from '../constants/theme';
|
||||||
|
|
||||||
|
type PrimaryButtonProps = {
|
||||||
|
title: string;
|
||||||
|
onPress?: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function PrimaryButton({
|
||||||
|
title,
|
||||||
|
onPress,
|
||||||
|
}: PrimaryButtonProps) {
|
||||||
|
|
||||||
|
const theme = Colors.light;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Pressable
|
||||||
|
style={[styles.button, { backgroundColor: theme.backgroundElement }]}
|
||||||
|
onPress={onPress}
|
||||||
|
>
|
||||||
|
<Text style={[styles.text, { color: theme.text }]}>
|
||||||
|
{title}
|
||||||
|
</Text>
|
||||||
|
</Pressable>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
button: {
|
||||||
|
padding: Spacing.three,
|
||||||
|
borderRadius: 12,
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: '600',
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
import {
|
||||||
|
Pressable,
|
||||||
|
Text,
|
||||||
|
StyleSheet,
|
||||||
|
View,
|
||||||
|
} from 'react-native';
|
||||||
|
|
||||||
|
import { Colors, Spacing } from '../constants/theme';
|
||||||
|
|
||||||
|
type QuickActionProps = {
|
||||||
|
title: string;
|
||||||
|
icon: string;
|
||||||
|
onPress?: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function QuickAction({
|
||||||
|
title,
|
||||||
|
icon,
|
||||||
|
onPress,
|
||||||
|
}: QuickActionProps) {
|
||||||
|
|
||||||
|
const theme = Colors.light;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Pressable
|
||||||
|
style={[
|
||||||
|
styles.container,
|
||||||
|
{
|
||||||
|
backgroundColor: theme.backgroundElement,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
onPress={onPress}
|
||||||
|
>
|
||||||
|
<View style={styles.iconContainer}>
|
||||||
|
<Text style={styles.icon}>
|
||||||
|
{icon}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
styles.title,
|
||||||
|
{
|
||||||
|
color: theme.text,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{title}
|
||||||
|
</Text>
|
||||||
|
</Pressable>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
width: 100,
|
||||||
|
padding: Spacing.three,
|
||||||
|
borderRadius: 16,
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
|
||||||
|
iconContainer: {
|
||||||
|
marginBottom: Spacing.two,
|
||||||
|
},
|
||||||
|
|
||||||
|
icon: {
|
||||||
|
fontSize: 28,
|
||||||
|
},
|
||||||
|
|
||||||
|
title: {
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: '600',
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { Text, StyleSheet } from 'react-native';
|
||||||
|
import { Colors, Spacing } from '../constants/theme';
|
||||||
|
|
||||||
|
type SectionTitleProps = {
|
||||||
|
title: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function SectionTitle({ title }: SectionTitleProps) {
|
||||||
|
|
||||||
|
const theme = Colors.light;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Text style={[styles.title, { color: theme.text }]}>
|
||||||
|
{title}
|
||||||
|
</Text>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
title: {
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: '700',
|
||||||
|
marginTop: Spacing.four,
|
||||||
|
marginBottom: Spacing.two,
|
||||||
|
marginLeft: Spacing.three,
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
import { View, Text, StyleSheet } from 'react-native';
|
||||||
|
import { Colors, Spacing } from '../constants/theme';
|
||||||
|
|
||||||
|
type StatusType = 'success' | 'warning' | 'danger';
|
||||||
|
|
||||||
|
type StatusBadgeProps = {
|
||||||
|
label: string;
|
||||||
|
type?: StatusType;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function StatusBadge({
|
||||||
|
label,
|
||||||
|
type = 'success',
|
||||||
|
}: StatusBadgeProps) {
|
||||||
|
|
||||||
|
const theme = Colors.light;
|
||||||
|
|
||||||
|
const getColor = () => {
|
||||||
|
switch (type) {
|
||||||
|
case 'success':
|
||||||
|
return '#22C55E';
|
||||||
|
case 'warning':
|
||||||
|
return '#FACC15';
|
||||||
|
case 'danger':
|
||||||
|
return '#EF4444';
|
||||||
|
default:
|
||||||
|
return theme.textSecondary;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={[styles.badge, { backgroundColor: getColor() }]}>
|
||||||
|
<Text style={styles.text}>{label}</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
badge: {
|
||||||
|
paddingHorizontal: Spacing.two,
|
||||||
|
paddingVertical: 4,
|
||||||
|
borderRadius: 20,
|
||||||
|
alignSelf: 'flex-start',
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: '600',
|
||||||
|
},
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user