Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | 3x 17x 17x 17x 17x 17x 17x 17x 8x 8x 8x 8x 17x 17x 17x 17x 17x 46x 46x 46x 46x 46x 46x 17x | import { JSX, useEffect, useState } from 'react';
import { SharedValue, useSharedValue } from 'react-native-reanimated';
import { StyleSheet, View } from 'react-native';
import { makeStyles } from '@repo/ui/themes/makeStyles';
import { AnimatedPendingRequestCardData, CardAction } from '@/types/card';
import { AnimatedPendingRequestItem } from './AnimatedPendingRequestItem';
import { CARD_TYPE_NEW_REQUEST, getShadowStyle } from './constants';
interface AnimatedListProps {
items: AnimatedPendingRequestCardData[];
component: (props: AnimatedPendingRequestCardData) => JSX.Element;
onSwipeLeftEnd?: (item: AnimatedPendingRequestCardData) => void;
onSwipeRightEnd?: (item: AnimatedPendingRequestCardData) => void;
maxItemDisplay?: number;
ListEmptyComponent?: JSX.Element;
action?: CardAction;
onMoveToBack?: (item: AnimatedPendingRequestCardData) => void;
onMoveToNewRequest?: () => void;
onPressCard?: (item: AnimatedPendingRequestCardData) => void;
onImageAnimationProgress?: (progress: SharedValue<number>) => void;
onActionComplete?: () => void;
}
export const AnimatedPendingRequestList = ({
maxItemDisplay = 3,
items,
component,
onSwipeLeftEnd,
onSwipeRightEnd,
ListEmptyComponent,
action,
onMoveToBack,
onMoveToNewRequest,
onPressCard,
onImageAnimationProgress,
onActionComplete,
}: AnimatedListProps) => {
const [currentIndex, setCurrentIndex] = useState(0);
const animatedValue = useSharedValue(0);
const imageAnimationProgress = useSharedValue(1);
const [prevTopId, setPrevTopId] = useState<string | null>(null);
useEffect(() => {
const currentTopId = items[0]?.id || null;
if (currentTopId !== prevTopId) {
setCurrentIndex(0);
animatedValue.value = 0;
imageAnimationProgress.value = 1;
setPrevTopId(currentTopId);
}
}, [items, animatedValue, imageAnimationProgress, prevTopId]);
useEffect(() => {
onImageAnimationProgress?.(imageAnimationProgress);
}, [onImageAnimationProgress, imageAnimationProgress]);
const visibleItems = items.slice(currentIndex, currentIndex + Math.min(maxItemDisplay, 3));
const styles = useStyles();
return (
<View className="flex-1">
<View style={styles.listContainer}>
{visibleItems.map((item, index) => {
const actualIndex = currentIndex + index;
const isCurrentItem = actualIndex === currentIndex;
const nextItem = items[actualIndex + 1];
const isNextItemNewRequest = nextItem?.type === CARD_TYPE_NEW_REQUEST;
const isCurrentItemNewRequest = item.type === CARD_TYPE_NEW_REQUEST;
return (
<AnimatedPendingRequestItem
key={item.id}
index={actualIndex}
dataLength={items.length}
currentIndex={currentIndex}
animatedValue={animatedValue}
data={item}
component={component}
onSwipeLeftEnd={onSwipeLeftEnd}
onSwipeRightEnd={onSwipeRightEnd}
action={action}
onMoveToBack={onMoveToBack}
onMoveToNewRequest={onMoveToNewRequest}
onPressCard={onPressCard}
imageAnimationProgress={isCurrentItem ? imageAnimationProgress : undefined}
isNextItemNewRequest={isCurrentItem ? isNextItemNewRequest : false}
isCurrentItemNewRequest={isCurrentItem ? isCurrentItemNewRequest : false}
onActionComplete={onActionComplete}
/>
);
})}
</View>
{ListEmptyComponent}
</View>
);
};
const useStyles = makeStyles(theme => ({
listContainer: {
...StyleSheet.absoluteFillObject,
borderRadius: theme.metrics.borderRadius[6],
...getShadowStyle(theme),
zIndex: 10,
},
}));
|