169 lines
5.4 KiB
TypeScript

import React, { useState } from 'react';
import { View, Text, TouchableOpacity, ActivityIndicator, ScrollView } from 'react-native';
import { PieChart } from 'react-native-gifted-charts';
import Icon from 'react-native-vector-icons/Ionicons';
import { useTheme } from '@theme';
import { getStyles } from './leadDistribution.styles';
import { LeadDistributionProps } from './leadDistribution.props';
export const LeadDistribution = ({
data = [],
loading = false,
activeAction,
onActionChange,
}: LeadDistributionProps) => {
const { theme: colors, isDark } = useTheme();
const styles = getStyles(colors, isDark);
const [menuVisible, setMenuVisible] = useState(false);
const actions = [
{ label: 'Today', value: 'today' },
{ label: 'Week', value: 'week' },
{ label: 'Month', value: 'month' },
{ label: 'Quarter', value: 'quarter' },
{ label: 'Half year', value: 'halfyear' },
{ label: 'Year', value: 'year' },
{ label: 'All', value: 'all' },
];
const currentActionLabel =
actions.find((a) => a.value === activeAction)?.label || 'Month';
const totalLeadItem = data.find((item) => item.name === 'Total Lead');
const totalCount = totalLeadItem
? totalLeadItem.count
: data.reduce((sum, item) => sum + item.count, 0);
const displayData = data
.filter((item) => item.name !== 'Total Lead' && item.count > 0)
.map((item) => ({
...item,
percentage: totalCount > 0 ? Math.round((item.count / totalCount) * 100) : 0,
}));
const pieData = displayData.map((item) => ({
value: item.count,
color: item.color,
}));
const renderCenterLabel = () => {
return (
<View style={styles.centerLabelContainer}>
<Text style={styles.centerNumber}>{totalCount}</Text>
<Text style={styles.centerText}>Total</Text>
</View>
);
};
return (
<View style={[styles.card, menuVisible && { zIndex: 10, elevation: 10 }]}>
{/* Header */}
<View style={styles.header}>
<View style={styles.titleRow}>
<View style={styles.titleIconBadge}>
<Icon name="pie-chart" size={15} color="#FFFFFF" />
</View>
<View>
<Text style={styles.title}>Lead Distribution</Text>
<Text style={styles.subtitle}>by status · {currentActionLabel}</Text>
</View>
</View>
<TouchableOpacity
style={styles.dropdown}
onPress={() => setMenuVisible(!menuVisible)}
activeOpacity={0.7}
>
<View style={styles.dropdownDot} />
<Text style={styles.dropdownText}>{currentActionLabel}</Text>
<Icon
name={menuVisible ? 'chevron-up' : 'chevron-down'}
size={13}
color={colors.icon}
/>
</TouchableOpacity>
</View>
{/* Dropdown Menu */}
{menuVisible && (
<View style={styles.menuOverlay}>
{actions.map((act) => {
const isSelected = act.value === activeAction;
return (
<TouchableOpacity
key={act.value}
style={[styles.menuItem, isSelected && styles.menuItemActive]}
onPress={() => {
onActionChange(act.value);
setMenuVisible(false);
}}
>
<Text style={[styles.menuItemText, isSelected && styles.menuItemTextActive]}>
{act.label}
</Text>
{isSelected && (
<Icon name="checkmark" size={14} color={colors.icon} />
)}
</TouchableOpacity>
);
})}
</View>
)}
{/* Divider */}
<View style={styles.divider} />
{/* Body — fixed min-height so card never jumps */}
<View style={styles.body}>
{loading ? (
<View style={styles.loaderContainer}>
<ActivityIndicator size="large" color={colors.icon} />
</View>
) : displayData.length === 0 ? (
<View style={styles.loaderContainer}>
<Text style={{ color: colors.textSecondary, fontSize: 13 }}>
No lead data available
</Text>
</View>
) : (
<>
<View style={styles.chartContainer}>
<PieChart
data={pieData}
donut
radius={60}
innerRadius={45}
innerCircleColor={colors.card}
centerLabelComponent={renderCenterLabel}
/>
</View>
<ScrollView
style={styles.legendContainer}
showsVerticalScrollIndicator={false}
nestedScrollEnabled
>
{displayData.map((item, idx) => (
<View key={idx} style={styles.legendItem}>
<View style={styles.legendItemLeft}>
<View style={[styles.bullet, { backgroundColor: item.color }]} />
<Text style={styles.legendLabel} numberOfLines={1}>
{item.name}
</Text>
</View>
<View style={styles.legendItemRight}>
<Text style={styles.legendCount}>{item.count}</Text>
<Text style={styles.legendPercentage}>{item.percentage}%</Text>
</View>
</View>
))}
</ScrollView>
</>
)}
</View>
</View>
);
};