Files
cruiseLovers/assets/components/reserva/VooCard.tsx

159 lines
5.5 KiB
TypeScript

import PlaneArrivalIcon from '@/assets/icons/plane-arrival-solid-full.svg';
import PlaneDepartureIcon from '@/assets/icons/plane-departure-solid-full.svg';
import { colors } from '@/assets/styles/colors';
import { Escala, VooSegment } from '@/assets/types';
import styles from '@/styles/screens/reserva/detail.styles';
import { FontAwesome } from '@expo/vector-icons';
import { Alert, Image, Linking, Platform, Pressable, Text, View } from 'react-native';
import { formatDateLong } from './formatters';
type SegmentProps = {
voo: Escala | VooSegment;
tipo: 'ida' | 'volta';
isLast: boolean;
onMapaPress?: () => void;
};
const planeIconProps = { width: 16, height: 16, fill: colors.vermelho } as const;
function abrirMapaAeroporto(lat: number, lng: number, nome: string) {
const url = Platform.OS === 'ios'
? `maps://?ll=${lat},${lng}&q=${encodeURIComponent(nome)}`
: `geo:${lat},${lng}?q=${encodeURIComponent(nome)}`;
Linking.openURL(url).catch(() =>
Alert.alert('Erro', 'Não foi possível abrir a aplicação de mapas.'),
);
}
function VooSegmentCard({ voo, tipo }: Omit<SegmentProps, 'onMapaPress' | 'isLast'>) {
const legLabel = tipo === 'ida' ? 'DATA DE IDA' : 'DATA DE REGRESSO';
const LegPlaneIcon = tipo === 'ida' ? PlaneDepartureIcon : PlaneArrivalIcon;
const escala = voo as Escala;
const gps = escala.infoAeroportoDeparture?.gps;
const nomeAeroporto = escala.infoAeroportoDeparture?.name ?? voo.departureAirport ?? voo.departureAirportCode;
const handleMapaPress = () => {
if (gps?.lat != null && gps?.lng != null) {
abrirMapaAeroporto(Number(gps.lat), Number(gps.lng), nomeAeroporto);
} else {
Alert.alert('Sem coordenadas', 'Não há informação de localização para este aeroporto.');
}
};
return (
<View>
<View style={styles.vooRouteRow}>
<View style={styles.vooSideCol}>
<Text style={styles.vooCode}>{voo.departureAirportCode}</Text>
<Text style={styles.vooTime}>{voo.departureTime}</Text>
<Text style={styles.vooAirport}>
{voo.departureAirportCode}-{voo.departureAirport}
</Text>
</View>
<View style={styles.vooMidCol}>
<Text style={styles.vooDuration}>{voo.flightTime}</Text>
<View style={styles.vooPathWrap}>
<View style={styles.vooPathLine} />
<View style={styles.vooPathIcon}>
<FontAwesome
name="plane"
size={16}
color={colors.cinza}
style={{ transform: [{ rotate: '45deg' }] }}
/>
</View>
</View>
</View>
<View style={[styles.vooSideCol, styles.vooSideColRight]}>
<Text style={[styles.vooCode, styles.vooCodeRight]}>{voo.arrivalAirportCode}</Text>
<Text style={[styles.vooTime, styles.vooTimeRight]}>{voo.arrivalTime}</Text>
<Text style={[styles.vooAirport, styles.vooAirportRight]}>
{voo.arrivalAirportCode}-{voo.arrivalAirport}
</Text>
</View>
</View>
<View style={styles.vooInfoBox}>
<View style={styles.vooInfoColLeft}>
<Text style={styles.vooInfoDate}>{formatDateLong(voo.departureDate)}</Text>
<View style={styles.vooLegRow}>
<LegPlaneIcon {...planeIconProps} />
<Text style={styles.vooLegLabel}>{legLabel}</Text>
</View>
</View>
<View style={styles.vooInfoColRight}>
{!!voo.malaLabel && (
<Text style={styles.vooMetaLine}>
<Text style={styles.vooMetaLabel}>Bagagem: </Text>
<Text style={styles.vooMetaValue}>{voo.malaLabel}</Text>
</Text>
)}
{!!voo.class && (
<Text style={styles.vooMetaLine}>
<Text style={styles.vooMetaLabel}>Classe: </Text>
<Text style={styles.vooMetaValue}>{voo.class}</Text>
</Text>
)}
</View>
</View>
<Pressable style={styles.mapaBtn} onPress={handleMapaPress}>
<Text style={styles.mapaBtnText}>
Mapa {voo.departureAirportCode}
</Text>
<Image source={require('@/assets/icons/seta-up.png')} style={styles.mapaBtnIcon} />
</Pressable>
</View>
);
}
type GroupProps = {
segmentos: (Escala | VooSegment)[];
tipo: 'ida' | 'volta';
};
export function VooCard({ segmentos, tipo }: GroupProps) {
if (!segmentos.length) return null;
const temEscalas = segmentos.length > 1;
return (
<View style={styles.vooCard}>
{temEscalas && (
<View style={styles.vooEscalasBadge}>
<FontAwesome name="random" size={14} color={colors.azul} />
<Text style={styles.vooEscalasBadgeText}>
{segmentos.length - 1} {segmentos.length - 1 === 1 ? 'escala' : 'escalas'}
</Text>
</View>
)}
{segmentos.map((voo, idx) => (
<View key={`seg-${idx}`}>
<VooSegmentCard
voo={voo}
tipo={tipo}
/>
{idx < segmentos.length - 1 && (
<View style={styles.vooEscalaDivider}>
<View style={styles.vooEscalaLine} />
<View style={styles.vooEscalaChip}>
<FontAwesome name="clock-o" size={10} color="#4A6592" />
<Text style={styles.vooEscalaChipText}>
Escala em {voo.arrivalAirportCode}
</Text>
</View>
<View style={styles.vooEscalaLine} />
</View>
)}
</View>
))}
</View>
);
}