127 lines
4.3 KiB
TypeScript
127 lines
4.3 KiB
TypeScript
import { colors } from '@/assets/styles/colors';
|
|
import { Passageiro } from '@/assets/types';
|
|
import styles from '@/styles/screens/reserva/detail.styles';
|
|
import { FontAwesome } from '@expo/vector-icons';
|
|
import { useEffect, useState } from 'react';
|
|
import { Pressable, Text, View } from 'react-native';
|
|
import Animated, {
|
|
Easing,
|
|
useAnimatedStyle,
|
|
useSharedValue,
|
|
withTiming,
|
|
} from 'react-native-reanimated';
|
|
import { DashedDivider } from './DashedDivider';
|
|
import { FieldBox } from './FieldBox';
|
|
|
|
type Props = {
|
|
passageiro: Passageiro;
|
|
index: number;
|
|
isOpen: boolean;
|
|
isFirst: boolean;
|
|
onToggle: () => void;
|
|
};
|
|
|
|
const ANIM_DURATION = 280;
|
|
|
|
export function PassageiroCard({ passageiro, index, isOpen, onToggle }: Props) {
|
|
const progress = useSharedValue(isOpen ? 1 : 0);
|
|
const contentHeight = useSharedValue(0);
|
|
const [measuredHeight, setMeasuredHeight] = useState(0);
|
|
|
|
useEffect(() => {
|
|
if (measuredHeight > 0) {
|
|
contentHeight.value = measuredHeight;
|
|
}
|
|
}, [measuredHeight, contentHeight]);
|
|
|
|
useEffect(() => {
|
|
progress.value = withTiming(isOpen ? 1 : 0, {
|
|
duration: ANIM_DURATION,
|
|
easing: Easing.out(Easing.cubic),
|
|
});
|
|
}, [isOpen, progress]);
|
|
|
|
const bodyAnimatedStyle = useAnimatedStyle(() => ({
|
|
height: contentHeight.value * progress.value,
|
|
opacity: progress.value,
|
|
}));
|
|
|
|
const chevronAnimatedStyle = useAnimatedStyle(() => ({
|
|
transform: [{ rotate: `${progress.value * 180}deg` }],
|
|
}));
|
|
|
|
return (
|
|
<View>
|
|
<View style={styles.passageiroContainer}>
|
|
<Pressable onPress={onToggle} style={styles.passageiroHeaderRow}>
|
|
<View>
|
|
<Text style={styles.passageiroSubtitle}>Passageiro {index + 1}</Text>
|
|
<Text style={styles.passageiroName}>
|
|
{passageiro.nome} {passageiro.sobrenome}
|
|
</Text>
|
|
</View>
|
|
<Animated.View style={chevronAnimatedStyle}>
|
|
<FontAwesome name="chevron-down" size={14} color={colors.vermelho} />
|
|
</Animated.View>
|
|
</Pressable>
|
|
|
|
<Animated.View
|
|
style={[styles.passageiroBodyWrap, bodyAnimatedStyle]}
|
|
pointerEvents={isOpen ? 'auto' : 'none'}>
|
|
<View
|
|
style={styles.passageiroBodyMeasure}
|
|
onLayout={(e) => {
|
|
const h = Math.ceil(e.nativeEvent.layout.height);
|
|
if (h > 0) setMeasuredHeight(h);
|
|
}}>
|
|
<View style={styles.passageiroBody}>
|
|
<View style={styles.twoCol}>
|
|
<View style={styles.twoColItem}>
|
|
<FieldBox label="Nome" value={passageiro.nome} />
|
|
</View>
|
|
<View style={styles.twoColItem}>
|
|
<FieldBox label="Apelido" value={passageiro.sobrenome} />
|
|
</View>
|
|
</View>
|
|
|
|
<View style={styles.twoCol}>
|
|
<View style={styles.twoColItem}>
|
|
<FieldBox label="Data de Nasc." value={passageiro.dataNascimento} />
|
|
</View>
|
|
<View style={styles.twoColItem}>
|
|
<FieldBox label="Género" value={passageiro.genero} />
|
|
</View>
|
|
</View>
|
|
|
|
<View style={styles.twoCol}>
|
|
<View style={styles.twoColItem}>
|
|
<FieldBox label="Nacionalidade" value={passageiro.nacionalidade} />
|
|
</View>
|
|
<View style={styles.twoColItem}>
|
|
<FieldBox label="Telemóvel" value={passageiro.telemovel} />
|
|
</View>
|
|
</View>
|
|
|
|
<FieldBox label="Morada" value={passageiro.morada} />
|
|
<FieldBox label="Nacionalidade Doc." value={passageiro.paisEmissao} />
|
|
<FieldBox label="Nr Doc Identificação" value={passageiro.numeroDocumento} />
|
|
|
|
<View style={styles.twoCol}>
|
|
<View style={styles.twoColItem}>
|
|
<FieldBox label="Data Emissão" value={passageiro.dataDeEmissao} />
|
|
</View>
|
|
<View style={styles.twoColItem}>
|
|
<FieldBox label="Data Val./Exp." value={passageiro.dataDeValidade} />
|
|
</View>
|
|
</View>
|
|
|
|
<FieldBox label="Email" value={passageiro.email} />
|
|
</View>
|
|
</View>
|
|
</Animated.View>
|
|
</View>
|
|
<DashedDivider width={1} borderStyle="dashed" />
|
|
</View>
|
|
);
|
|
}
|