SeriesRankingItem.tsx 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. import React from 'react';
  2. import { Text, TouchableOpacity, View, Image, Dimensions } from 'react-native';
  3. import * as FileSystem from 'expo-file-system';
  4. import { AvatarWithInitials } from '../../../../components';
  5. import { API_HOST } from 'src/constants';
  6. import { getFontSize } from 'src/utils';
  7. import { Colors } from 'src/theme';
  8. import { SeriesRanking } from '../utils/types';
  9. import { ProfileStyles, ScoreStyles } from './styles';
  10. import { useConnection } from 'src/contexts/ConnectionContext';
  11. import formatNumber from '../../TravelsScreen/utils/formatNumber';
  12. import TickIcon from 'assets/icons/tick.svg';
  13. import UNIcon from 'assets/icons/un_icon.svg';
  14. import NMIcon from 'assets/icons/nm_icon.svg';
  15. import ArrowIcon from 'assets/icons/arrow-bold.svg';
  16. const SeriesRankingItem = React.memo(
  17. ({
  18. item,
  19. index,
  20. onPress
  21. }: {
  22. item: SeriesRanking;
  23. index: number;
  24. onPress: (userId: number) => void;
  25. }) => {
  26. const netInfo = useConnection();
  27. const isSmallScreen = Dimensions.get('window').width < 383;
  28. const avatarBaseUri = netInfo?.isInternetReachable
  29. ? API_HOST + item.avatar
  30. : `${FileSystem.documentDirectory}avatars/${item.user_id}.webp`;
  31. const flagBaseUri = (flag: string) =>
  32. netInfo?.isInternetReachable
  33. ? API_HOST + flag
  34. : `${FileSystem.documentDirectory}flags/${flag.split('/').pop()}`;
  35. return (
  36. <TouchableOpacity
  37. onPress={() => onPress(item.user_id)}
  38. style={[
  39. ProfileStyles.profileContainer,
  40. { backgroundColor: Colors.FILL_LIGHT, padding: 6, borderRadius: 8, marginBottom: 12 }
  41. ]}
  42. >
  43. <View style={[ProfileStyles.profileRoot, { marginBottom: 0 }]}>
  44. <View style={{ flexDirection: 'row' }}>
  45. <View
  46. style={{
  47. alignItems: 'center',
  48. justifyContent: 'center',
  49. width: index + 1 < 100 ? 26 : index + 1 < 1000 ? 38 : 50
  50. }}
  51. >
  52. <Text style={ScoreStyles.rankText}>{index + 1}</Text>
  53. </View>
  54. <View style={{ marginLeft: 4 }}>
  55. {item.avatar ? (
  56. <Image style={ProfileStyles.profileAvatar} source={{ uri: avatarBaseUri }} />
  57. ) : (
  58. <AvatarWithInitials
  59. text={`${item.first_name[0] ?? ''}${item.last_name[0] ?? ''}`}
  60. flag={flagBaseUri(item.flag1)}
  61. size={48}
  62. />
  63. )}
  64. </View>
  65. </View>
  66. <View style={{ gap: 5, flex: 1 }}>
  67. <Text
  68. style={[ProfileStyles.profileFirstLastName, { fontSize: getFontSize(14), flex: 0 }]}
  69. >
  70. {item.first_name ?? ''} {item.last_name ?? ''}
  71. </Text>
  72. <View style={[ProfileStyles.profileDataContainer, { flex: 1 }]}>
  73. <View style={[ProfileStyles.profileDataWrapper, isSmallScreen ? { gap: 6 } : {}]}>
  74. <Text style={ProfileStyles.profileAge}>Age: {item.age ?? ''}</Text>
  75. <Image
  76. source={{ uri: flagBaseUri(item.flag1) }}
  77. style={ProfileStyles.countryFlag}
  78. />
  79. {item.flag2 && item.flag2 !== item.flag1 ? (
  80. <Image
  81. source={{ uri: flagBaseUri(item.flag2) }}
  82. style={[ProfileStyles.countryFlag, { marginLeft: -15 }]}
  83. />
  84. ) : null}
  85. <View style={[ProfileStyles.badgesWrapper, isSmallScreen ? { marginLeft: 4 } : {}]}>
  86. {item.authenticated === 1 ? <TickIcon /> : null}
  87. {item.badge_un === 1 ? <UNIcon /> : null}
  88. {item.badge_nm === 1 ? <NMIcon /> : null}
  89. </View>
  90. </View>
  91. <View style={[ProfileStyles.rightScore, { flex: 1, justifyContent: 'flex-end' }]}>
  92. <Text
  93. style={[
  94. {
  95. fontWeight: 'bold',
  96. fontSize: isSmallScreen ? 12 : 16
  97. },
  98. item.recent_score_increase
  99. ? { color: Colors.ORANGE }
  100. : { color: Colors.DARK_BLUE }
  101. ]}
  102. >
  103. {isSmallScreen ? formatNumber(item.score) : item.score}
  104. </Text>
  105. {item.recent_score_increase ? (
  106. <ArrowIcon stroke={Colors.ORANGE} />
  107. ) : (
  108. <View style={{ width: 10 }}></View>
  109. )}
  110. </View>
  111. </View>
  112. </View>
  113. </View>
  114. </TouchableOpacity>
  115. );
  116. }
  117. );
  118. export default SeriesRankingItem;