173 lines
5.9 KiB
TypeScript
173 lines
5.9 KiB
TypeScript
import ImgTotalSvg from "@/assets/icons/svg/imgTotal.svg";
|
|
import LiveTotalSvg from "@/assets/icons/svg/liveTotal.svg";
|
|
import TimeTotalSvg from "@/assets/icons/svg/timeTotal.svg";
|
|
import VideoTotalSvg from "@/assets/icons/svg/videoTotal.svg";
|
|
import { Counter, UserCountData } from "@/types/user";
|
|
import * as React from "react";
|
|
import { Dimensions, StyleSheet, View, ViewStyle } from "react-native";
|
|
import Carousel from "react-native-reanimated-carousel";
|
|
import { ThemedText } from "../ThemedText";
|
|
import { formatDuration } from "../utils/time";
|
|
import CategoryComponent from "./category";
|
|
interface Props {
|
|
data: Counter
|
|
}
|
|
|
|
interface CarouselData {
|
|
key: string,
|
|
value: UserCountData
|
|
|
|
}[]
|
|
const width = Dimensions.get("window").width;
|
|
|
|
function CarouselComponent(props: Props) {
|
|
const { data } = props;
|
|
const [currentIndex, setCurrentIndex] = React.useState(0);
|
|
const [carouselDataValue, setCarouselDataValue] = React.useState<CarouselData[]>([]);
|
|
const dataHandle = () => {
|
|
const carouselData = { ...data?.category_count, total_count: data?.total_count }
|
|
// 1. 转换为数组并过滤掉 'total'
|
|
const entries = Object?.entries(carouselData)
|
|
?.filter(([key]) => key !== 'total_count')
|
|
?.map(([key, value]) => ({ key, value }));
|
|
|
|
// 2. 找到 total 数据
|
|
const totalEntry = {
|
|
key: 'total_count',
|
|
value: carouselData?.total_count
|
|
};
|
|
|
|
// 3. 插入到中间位置
|
|
const middleIndex = Math.floor((entries || [])?.length / 2);
|
|
entries?.splice(middleIndex, 0, totalEntry);
|
|
setCarouselDataValue(entries)
|
|
return entries;
|
|
}
|
|
|
|
const totleItem = (data: UserCountData) => {
|
|
return <View style={[styles.container, { width: width * 0.7 }]}>
|
|
{Object?.entries(data)?.filter(([key]) => key !== 'cover_url')?.map((item, index) => (
|
|
<View style={styles.item} key={index}>
|
|
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 8, width: "75%", overflow: 'hidden' }}>
|
|
<View style={styles.icon}>
|
|
{
|
|
item?.[0]?.includes('video_count') ? <VideoTotalSvg /> : item?.[0]?.includes('photo') ? <ImgTotalSvg /> : item?.[0]?.includes('live') ? <LiveTotalSvg /> : <TimeTotalSvg />
|
|
}
|
|
</View>
|
|
<ThemedText style={styles.title}>{item[0]}</ThemedText>
|
|
</View>
|
|
<ThemedText style={styles.number}>{item[1]}</ThemedText>
|
|
</View>
|
|
))}
|
|
</View>
|
|
}
|
|
|
|
React.useEffect(() => {
|
|
if (data) {
|
|
dataHandle()
|
|
}
|
|
}, [data]);
|
|
|
|
return (
|
|
<View
|
|
style={{
|
|
flex: 1
|
|
}}>
|
|
<Carousel
|
|
width={width}
|
|
height={width}
|
|
data={carouselDataValue || []}
|
|
mode="parallax"
|
|
onSnapToItem={(index) => setCurrentIndex(index)}
|
|
defaultIndex={
|
|
carouselDataValue?.length
|
|
? Math.max(0, Math.min(
|
|
carouselDataValue.length - 1,
|
|
carouselDataValue.findIndex((item) => item?.key === 'total_count') - 1
|
|
))
|
|
: 0
|
|
}
|
|
modeConfig={{
|
|
parallaxScrollingScale: 1,
|
|
parallaxScrollingOffset: 130,
|
|
parallaxAdjacentItemScale: 0.7
|
|
}}
|
|
renderItem={({ item, index }) => {
|
|
const style: ViewStyle = {
|
|
width: width,
|
|
height: width * 0.7,
|
|
alignItems: "center"
|
|
};
|
|
return (
|
|
<View key={index} style={[style]}>
|
|
{item?.key === 'total_count' ? (
|
|
totleItem(item.value)
|
|
) : (
|
|
<View>
|
|
{CategoryComponent({
|
|
title: item?.key,
|
|
data: [
|
|
{ title: 'Video', number: item?.value?.video_count },
|
|
{ title: 'Photo', number: item?.value?.photo_count },
|
|
{ title: 'Length', number: formatDuration(item?.value?.video_length || 0) }
|
|
],
|
|
bgSvg: item?.value?.cover_url,
|
|
width: width
|
|
})}
|
|
</View>
|
|
)}
|
|
</View>
|
|
)
|
|
}}
|
|
/>
|
|
</View>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
icon: {
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
backgroundColor: '#fff',
|
|
borderRadius: 32,
|
|
padding: 6
|
|
},
|
|
container: {
|
|
backgroundColor: "#FFB645",
|
|
paddingVertical: 8,
|
|
paddingLeft: 32,
|
|
borderRadius: 32,
|
|
display: "flex",
|
|
flexDirection: "column",
|
|
position: 'relative',
|
|
width: width * 0.7
|
|
},
|
|
image: {
|
|
position: 'absolute',
|
|
bottom: 0,
|
|
right: 0,
|
|
left: 0,
|
|
alignItems: 'center',
|
|
justifyContent: 'flex-end',
|
|
},
|
|
item: {
|
|
flexDirection: "row",
|
|
alignItems: "center",
|
|
paddingVertical: 16
|
|
},
|
|
title: {
|
|
color: "#4C320C",
|
|
fontWeight: "500",
|
|
fontSize: 22,
|
|
},
|
|
number: {
|
|
color: "#fff",
|
|
fontWeight: "700",
|
|
fontSize: 28,
|
|
lineHeight: 30,
|
|
textAlign: 'left',
|
|
flex: 1
|
|
}
|
|
})
|
|
|
|
export default CarouselComponent; |