MineRecordScreen.tsx 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. import { StackScreenProps } from '@react-navigation/stack';
  2. import * as React from 'react';
  3. import * as Animatable from 'react-native-animatable';
  4. import { Div, Button, Image, Text, Avatar, Icon } from 'react-native-magnus';
  5. import { FlatList } from 'react-native-gesture-handler';
  6. import { RefreshControl } from 'react-native';
  7. import { useTranslation } from 'react-i18next';
  8. import { useRequest } from 'ahooks';
  9. import { FinancialType } from '../utils/MoneyUtils';
  10. import { MonthDate, getSearchDate } from '../utils/TimeUtils';
  11. import request from '../utils/RequestUtils';
  12. import ReacordCom from './ReacordCom';
  13. import { PopoverPicker } from '../utils/SystemUtils';
  14. // import { PopoverPicker } from 'teaset';
  15. interface Result {
  16. list: Item[];
  17. last: boolean;
  18. current: number;
  19. }
  20. export default function MineRecordScreen({ navigation }: StackScreenProps) {
  21. const { t } = useTranslation();
  22. const [type, settype] = React.useState<string>('all');
  23. const [show, setshow] = React.useState<boolean>(false);
  24. const monthDate = new MonthDate();
  25. const [showDate, setshowDate] = React.useState<string>(monthDate.showList[0]);
  26. const [layout, setLayout] = React.useState<any>();
  27. const { data, loading, loadMore, loadingMore, reload } = useRequest(
  28. (d: Result | undefined) => {
  29. let current = 0;
  30. if (d && d.current) {
  31. current = Number(d.current) + 1;
  32. }
  33. return request.get(__DEV__ ? '/moneyRecord/all' : '/moneyRecord/my', {
  34. params: {
  35. query: {
  36. time: getSearchDate(showDate),
  37. type: type != 'all' ? type : '',
  38. },
  39. size: 10,
  40. page: current,
  41. },
  42. });
  43. },
  44. {
  45. refreshDeps: [showDate, type],
  46. formatResult: (response) => {
  47. return {
  48. list: response.content,
  49. current: response.number.toString(),
  50. last: response.last,
  51. empty: response.empty,
  52. };
  53. },
  54. isNoMore: (r: Result) => {
  55. if (r.last) {
  56. return true;
  57. } else {
  58. return false;
  59. }
  60. },
  61. defaultLoading: false,
  62. debounceInterval: 1000,
  63. loadMore: true,
  64. }
  65. );
  66. navigation.setOptions({
  67. headerTitle: () => {
  68. let name = t('wo-de-dui-zhang-dan');
  69. if (type !== 'all') {
  70. name += '(' + t(FinancialType.get(type).name) + ')';
  71. }
  72. return (
  73. <Button bg="yellow500" onPress={() => setshow(!show)}>
  74. {name}
  75. </Button>
  76. );
  77. },
  78. });
  79. return (
  80. <Div bg="gray100" flex={1}>
  81. {show && (
  82. <Div
  83. position="absolute"
  84. bg="black600"
  85. top={0}
  86. left={0}
  87. right={0}
  88. bottom={0}
  89. zIndex={2}
  90. >
  91. <Animatable.View animation="slideInDown" duration={300}>
  92. <Div bg="white">
  93. {[...FinancialType.keys()].map((item, index) => {
  94. const info = FinancialType.get(item);
  95. return (
  96. <Button
  97. bg="white"
  98. block
  99. key={index}
  100. onPress={() => {
  101. settype(item);
  102. setshow(false);
  103. }}
  104. >
  105. <Div row flex={1} alignItems="center">
  106. <Icon
  107. name={info.icon}
  108. fontSize="6xl"
  109. fontFamily="FontAwesome5"
  110. color={type == item ? 'yellow500' : 'gray200'}
  111. />
  112. <Text fontSize="lg" ml={10} flex={1}>
  113. {t(info.name)}
  114. </Text>
  115. {type == item && (
  116. <Div p={2} rounded="circle" bg="yellow500">
  117. <Icon
  118. name="check"
  119. fontSize="md"
  120. color="white"
  121. fontFamily="FontAwesome5"
  122. />
  123. </Div>
  124. )}
  125. </Div>
  126. </Button>
  127. );
  128. })}
  129. </Div>
  130. </Animatable.View>
  131. </Div>
  132. )}
  133. <FlatList
  134. refreshControl={
  135. <RefreshControl refreshing={loading} onRefresh={reload} />
  136. }
  137. onEndReached={() => {
  138. if (!data.last && !loading && !loadingMore) {
  139. loadMore();
  140. }
  141. }}
  142. onEndReachedThreshold={0.5}
  143. contentContainerStyle={{
  144. flexGrow: 1,
  145. backgroundColor: '#f2f2f2',
  146. }}
  147. data={data.list}
  148. renderItem={({ item }) => {
  149. return (
  150. <Div px={15} bg="white">
  151. <ReacordCom info={item} />
  152. </Div>
  153. );
  154. }}
  155. keyExtractor={(item) => item.id.toString()}
  156. onLayout={(e) => {
  157. console.log(e);
  158. }}
  159. ListFooterComponent={() => {
  160. return (
  161. <>
  162. {!data.empty && (
  163. <Text p={15} textAlign="center">
  164. {data.last ? t('dao-di-le') : t('jia-zai-zhong')}
  165. </Text>
  166. )}
  167. </>
  168. );
  169. }}
  170. stickyHeaderIndices={[0]}
  171. ListEmptyComponent={() => {
  172. return (
  173. <>
  174. {data.empty && (
  175. <Text textAlign="center" p={15}>
  176. {t('wu-shu-ju')}
  177. </Text>
  178. )}
  179. </>
  180. );
  181. }}
  182. ListHeaderComponent={() => {
  183. return (
  184. <Div px={15} py={10} bg="gray100">
  185. <Button
  186. bg="gray100"
  187. borderWidth={1}
  188. borderColor="yellow500"
  189. color="yellow500"
  190. fontSize="sm"
  191. onPress={(e) => {
  192. const { nativeEvent } = e;
  193. PopoverPicker.show(
  194. {
  195. x: nativeEvent.pageX,
  196. y: nativeEvent.pageY,
  197. width: 120,
  198. },
  199. monthDate.showList,
  200. showDate,
  201. (item, index) => setshowDate(item)
  202. );
  203. }}
  204. >
  205. {showDate}
  206. </Button>
  207. </Div>
  208. );
  209. }}
  210. />
  211. </Div>
  212. );
  213. }