Files
address-verification-app/src/screens/MapView/CasesMap/UserCard.tsx
2025-06-09 14:56:45 +05:30

176 lines
5.6 KiB
TypeScript

import React, { useEffect, useRef } from 'react';
import { StyleSheet, View, TouchableOpacity, Pressable } from 'react-native';
import Animated, { SharedValue, useAnimatedStyle } from 'react-native-reanimated';
import { COLORS } from '@rn-ui-lib/colors';
import { useAppSelector } from '@hooks';
import RightChevronIcon from '@assets/icons/RightChevronIcon';
import FeedbackStatus from '@screens/allCases/CaseItem/FeedbackStatus';
import ProfileHeader from '../ProfileHeader';
import { AddressTabType } from '@screens/addressGeolocation/constant';
import { navigateToScreen } from '@components/utlis/navigationUtlis';
import { PageRouteEnum } from '@screens/auth/ProtectedRouter';
import { CaseDetailStackEnum } from '@screens/caseDetails/CaseDetailStack';
import { GenericStyles } from '@rn-ui-lib/styles';
import { CASE_CARD_Z_INDEX } from '../constants';
import { CLICKSTREAM_EVENT_NAMES } from '@common/Constants';
import { addClickstreamEvent } from '@services/clickstreamEventService';
import CopyOutlineIcon from '@assets/icons/CopyOutlineIcon';
import { copyAddressToClipboard } from '@screens/addressGeolocation/utils/copyAddressText';
import Text from '@rn-ui-lib/components/Text';
interface UserCardProps {
selectedCase: string;
cardPosition: SharedValue<number>;
}
const UserCard: React.FC<UserCardProps> = ({ selectedCase, cardPosition }) => {
const caseDetail = useAppSelector((state) => state.allCases?.caseDetails?.[selectedCase]) || {};
const addressItemRef = useRef(null);
const cardAnimatedStyle = useAnimatedStyle(() => {
const positionValue = Number.isNaN(cardPosition.value) ? 1 : cardPosition.value;
return {
transform: [
{
translateY: (1 - positionValue) * 220, // 220 is the height of the card here as the profile picture takes the extra space
},
],
};
});
const onTopAddressesPress = () => {
addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_MAP_CASE_CARD_TOP_ADDRESSES_CLICKED, {
markerId: selectedCase,
});
navigateToScreen(PageRouteEnum.CASE_DETAIL_STACK, {
screen: CaseDetailStackEnum.MAP_VIEW_TOP_ADDRESS,
params: { caseId: selectedCase },
});
};
const handleCardPress = () => {
addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_MAP_CASE_CARD_CLICKED, {
markerId: selectedCase,
});
navigateToScreen(PageRouteEnum.CASE_DETAIL_STACK, {
screen: CaseDetailStackEnum.COLLECTION_CASE_DETAIL,
params: { caseId: selectedCase },
});
};
const handleCopyAddress = () => {
if (!caseDetail?.addressString) return;
addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_MAP_COPY_ADDRESS_CLICKED, {
caseId: selectedCase,
addressText: caseDetail?.addressString,
});
copyAddressToClipboard(caseDetail?.addressString);
};
const isGeolocation = caseDetail?.addressStringType === AddressTabType.GEO_LOCATION;
useEffect(() => {
addClickstreamEvent(CLICKSTREAM_EVENT_NAMES.FA_MAP_CASE_CARD_LOADED, {
markerId: selectedCase,
});
}, []);
return (
<Animated.View style={[styles.cardContainer, cardAnimatedStyle]}>
<Pressable
style={({ pressed }) => [pressed && { opacity: 0.9 }]}
ref={addressItemRef}
onPress={handleCardPress}
>
<ProfileHeader
caseId={selectedCase}
showDirections={true}
addressItemRef={addressItemRef}
/>
<View style={styles.dashedBorder} />
<View style={styles.cardContent}>
<View style={styles.h66}>
<View style={styles.addressContainer}>
<Text numberOfLines={2} ellipsizeMode="tail" style={styles.addressText}>
{!isGeolocation && (
<Text dark style={[GenericStyles.lh18, GenericStyles.fontSize12]}>
{caseDetail?.currentPinCode}
{' - '}
</Text>
)}
{caseDetail?.addressString}
</Text>
{!isGeolocation && (
<Pressable
onPress={handleCopyAddress}
hitSlop={{ top: 12, right: 12, bottom: 12, left: 12 }}
>
<CopyOutlineIcon />
</Pressable>
)}
</View>
<TouchableOpacity
activeOpacity={0.8}
style={[GenericStyles.row, GenericStyles.alignSelfStart]}
hitSlop={{ top: 8, right: 8, bottom: 8, left: 8 }}
onPress={onTopAddressesPress}
>
<Text style={styles.topaddressesButtonText}>All addresses</Text>
<RightChevronIcon />
</TouchableOpacity>
</View>
<FeedbackStatus caseListItemDetailObj={caseDetail} isMapView={true} />
</View>
</Pressable>
</Animated.View>
);
};
const styles = StyleSheet.create({
addressContainer: {
alignItems: 'flex-start',
flexDirection: 'row',
justifyContent: 'space-between',
marginBottom: 4,
},
h66: {
height: 66,
},
addressText: {
color: COLORS.TEXT.LIGHT,
flex: 1,
fontSize: 12,
lineHeight: 18,
},
cardContainer: {
backgroundColor: COLORS.BACKGROUND.PRIMARY,
bottom: 0,
left: 0,
paddingBottom: 16,
paddingTop: 16,
position: 'absolute',
right: 0,
zIndex: CASE_CARD_Z_INDEX,
},
cardContent: {
flex: 1,
paddingHorizontal: 16,
},
dashedBorder: {
borderColor: COLORS.BORDER.PRIMARY,
borderStyle: 'dashed',
borderTopWidth: 1,
marginBottom: 8,
marginTop: 4,
},
topaddressesButtonText: {
color: COLORS.TEXT.BLUE,
fontSize: 12,
fontWeight: '500',
lineHeight: 18,
},
});
export default UserCard;