338 lines
9.1 KiB
TypeScript
338 lines
9.1 KiB
TypeScript
/*
|
|
* File: FeedbackAnalysisPieChart.tsx
|
|
* Description: Pie chart component for feedback analysis using react-native-chart-kit
|
|
* Design & Developed by Tech4Biz Solutions
|
|
* Copyright (c) Spurrin Innovations. All rights reserved.
|
|
*/
|
|
|
|
import React from 'react';
|
|
import { View, Text, StyleSheet, Dimensions } from 'react-native';
|
|
import { PieChart } from 'react-native-chart-kit';
|
|
import { theme } from '../../../theme/theme';
|
|
|
|
// ============================================================================
|
|
// TYPES
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Feedback Analysis Data Interface
|
|
*
|
|
* Purpose: Defines the structure of feedback analysis data for pie chart
|
|
*/
|
|
interface FeedbackAnalysisData {
|
|
positive: number;
|
|
negative: number;
|
|
total: number;
|
|
}
|
|
|
|
/**
|
|
* FeedbackAnalysisPieChart Props Interface
|
|
*
|
|
* Purpose: Defines the props required by the FeedbackAnalysisPieChart component
|
|
*
|
|
* Props:
|
|
* - data: Feedback analysis data containing positive, negative, and total counts
|
|
* - title: Optional title for the chart
|
|
* - width: Chart width (defaults to screen width - 32)
|
|
* - height: Chart height (defaults to 220)
|
|
*/
|
|
interface FeedbackAnalysisPieChartProps {
|
|
data: FeedbackAnalysisData;
|
|
title?: string;
|
|
width?: number;
|
|
height?: number;
|
|
}
|
|
|
|
// ============================================================================
|
|
// COMPONENT
|
|
// ============================================================================
|
|
|
|
/**
|
|
* FeedbackAnalysisPieChart Component
|
|
*
|
|
* Purpose: Renders a pie chart showing feedback analysis distribution
|
|
*
|
|
* Features:
|
|
* - Pie chart visualization of positive vs negative feedback
|
|
* - Custom colors for different feedback types
|
|
* - Responsive sizing
|
|
* - Legend with percentages
|
|
* - Empty state handling
|
|
*/
|
|
export const FeedbackAnalysisPieChart: React.FC<FeedbackAnalysisPieChartProps> = ({
|
|
data,
|
|
title = 'Feedback Analysis Overview',
|
|
width = Dimensions.get('window').width - 32,
|
|
height = 220,
|
|
}) => {
|
|
// ============================================================================
|
|
// DATA PROCESSING
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Process data for pie chart
|
|
*
|
|
* Purpose: Convert feedback data into chart-kit format
|
|
*/
|
|
const chartData = React.useMemo(() => {
|
|
const { positive, negative } = data;
|
|
|
|
// Only show data if there are actual feedbacks
|
|
if (positive === 0 && negative === 0) {
|
|
return [];
|
|
}
|
|
|
|
const chartDataArray = [];
|
|
|
|
// Add positive feedback data
|
|
if (positive > 0) {
|
|
chartDataArray.push({
|
|
name: 'Positive',
|
|
population: positive,
|
|
color: theme.colors.success,
|
|
legendFontColor: theme.colors.textPrimary,
|
|
legendFontSize: 12,
|
|
});
|
|
}
|
|
|
|
// Add negative feedback data
|
|
if (negative > 0) {
|
|
chartDataArray.push({
|
|
name: 'Negative',
|
|
population: negative,
|
|
color: theme.colors.error,
|
|
legendFontColor: theme.colors.textPrimary,
|
|
legendFontSize: 12,
|
|
});
|
|
}
|
|
|
|
return chartDataArray;
|
|
}, [data]);
|
|
|
|
// ============================================================================
|
|
// CHART CONFIGURATION
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Chart configuration object
|
|
*
|
|
* Purpose: Configure pie chart appearance and behavior
|
|
*/
|
|
const chartConfig = {
|
|
backgroundColor: theme.colors.background,
|
|
backgroundGradientFrom: theme.colors.background,
|
|
backgroundGradientTo: theme.colors.background,
|
|
decimalPlaces: 0,
|
|
color: (opacity = 1) => theme.colors.primary,
|
|
labelColor: (opacity = 1) => theme.colors.textPrimary,
|
|
style: {
|
|
borderRadius: theme.borderRadius.medium,
|
|
},
|
|
propsForDots: {
|
|
r: '6',
|
|
strokeWidth: '2',
|
|
stroke: theme.colors.primary,
|
|
},
|
|
};
|
|
|
|
// ============================================================================
|
|
// RENDER FUNCTIONS
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Render empty state
|
|
*
|
|
* Purpose: Show message when no feedback data is available
|
|
*/
|
|
const renderEmptyState = () => (
|
|
<View style={styles.emptyState}>
|
|
<Text style={styles.emptyStateText}>No feedback data available</Text>
|
|
<Text style={styles.emptyStateSubtext}>
|
|
Feedback will appear here once received
|
|
</Text>
|
|
</View>
|
|
);
|
|
|
|
/**
|
|
* Render chart legend
|
|
*
|
|
* Purpose: Display custom legend with percentages
|
|
*/
|
|
const renderLegend = () => {
|
|
const { positive, negative, total } = data;
|
|
|
|
if (total === 0) return null;
|
|
|
|
const positivePercentage = ((positive / total) * 100).toFixed(1);
|
|
const negativePercentage = ((negative / total) * 100).toFixed(1);
|
|
|
|
return (
|
|
<View style={styles.legendContainer}>
|
|
<View style={styles.legendItem}>
|
|
<View style={[styles.legendColor, { backgroundColor: theme.colors.success }]} />
|
|
<Text style={styles.legendText}>
|
|
Positive: {positive} ({positivePercentage}%)
|
|
</Text>
|
|
</View>
|
|
<View style={styles.legendItem}>
|
|
<View style={[styles.legendColor, { backgroundColor: theme.colors.error }]} />
|
|
<Text style={styles.legendText}>
|
|
Negative: {negative} ({negativePercentage}%)
|
|
</Text>
|
|
</View>
|
|
<View style={styles.totalContainer}>
|
|
<Text style={styles.totalText}>
|
|
Total Feedback: {total}
|
|
</Text>
|
|
</View>
|
|
</View>
|
|
);
|
|
};
|
|
|
|
// ============================================================================
|
|
// MAIN RENDER
|
|
// ============================================================================
|
|
|
|
return (
|
|
<View style={styles.container}>
|
|
{/* Chart Title */}
|
|
{/* {title && (
|
|
<Text style={styles.title}>{title}</Text>
|
|
)} */}
|
|
|
|
{/* Chart Container */}
|
|
<View style={styles.chartContainer}>
|
|
{chartData.length > 0 ? (
|
|
<>
|
|
{/* Pie Chart */}
|
|
<PieChart
|
|
data={chartData}
|
|
width={width}
|
|
height={height}
|
|
chartConfig={chartConfig}
|
|
accessor="population"
|
|
backgroundColor="transparent"
|
|
paddingLeft="0"
|
|
center={[width/4, 0]}
|
|
absolute
|
|
hasLegend={false}
|
|
/>
|
|
|
|
{/* Custom Legend */}
|
|
{renderLegend()}
|
|
</>
|
|
) : (
|
|
renderEmptyState()
|
|
)}
|
|
</View>
|
|
</View>
|
|
);
|
|
};
|
|
|
|
// ============================================================================
|
|
// STYLES
|
|
// ============================================================================
|
|
|
|
const styles = StyleSheet.create({
|
|
// Main container
|
|
container: {
|
|
backgroundColor: theme.colors.background,
|
|
borderRadius: theme.borderRadius.medium,
|
|
paddingHorizontal: theme.spacing.md,
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
minHeight: 250,
|
|
},
|
|
|
|
// Chart title styling
|
|
title: {
|
|
fontSize: theme.typography.fontSize.displaySmall,
|
|
fontFamily: theme.typography.fontFamily.bold,
|
|
color: theme.colors.textPrimary,
|
|
marginBottom: theme.spacing.md,
|
|
textAlign: 'center',
|
|
},
|
|
|
|
// Chart container
|
|
chartContainer: {
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
width: '100%',
|
|
flex: 1,
|
|
},
|
|
|
|
// Empty state styling
|
|
emptyState: {
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
paddingVertical: theme.spacing.xl,
|
|
minHeight: 150,
|
|
},
|
|
|
|
// Empty state text styling
|
|
emptyStateText: {
|
|
fontSize: theme.typography.fontSize.bodyMedium,
|
|
fontFamily: theme.typography.fontFamily.medium,
|
|
color: theme.colors.textSecondary,
|
|
marginBottom: theme.spacing.xs,
|
|
},
|
|
|
|
// Empty state subtext styling
|
|
emptyStateSubtext: {
|
|
fontSize: theme.typography.fontSize.bodySmall,
|
|
fontFamily: theme.typography.fontFamily.regular,
|
|
color: theme.colors.textMuted,
|
|
textAlign: 'center',
|
|
},
|
|
|
|
// Legend container styling
|
|
legendContainer: {
|
|
marginTop: theme.spacing.md,
|
|
alignItems: 'center',
|
|
},
|
|
|
|
// Legend item styling
|
|
legendItem: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
marginBottom: theme.spacing.sm,
|
|
},
|
|
|
|
// Legend color indicator styling
|
|
legendColor: {
|
|
width: 16,
|
|
height: 16,
|
|
borderRadius: 8,
|
|
marginRight: theme.spacing.sm,
|
|
},
|
|
|
|
// Legend text styling
|
|
legendText: {
|
|
fontSize: theme.typography.fontSize.bodyMedium,
|
|
fontFamily: theme.typography.fontFamily.medium,
|
|
color: theme.colors.textPrimary,
|
|
},
|
|
|
|
// Total container styling
|
|
totalContainer: {
|
|
marginTop: theme.spacing.sm,
|
|
paddingTop: theme.spacing.sm,
|
|
borderTopWidth: 1,
|
|
borderTopColor: theme.colors.border,
|
|
alignItems: 'center',
|
|
},
|
|
|
|
// Total text styling
|
|
totalText: {
|
|
fontSize: theme.typography.fontSize.bodyMedium,
|
|
fontFamily: theme.typography.fontFamily.bold,
|
|
color: theme.colors.textPrimary,
|
|
},
|
|
});
|
|
|
|
/*
|
|
* End of File: FeedbackAnalysisPieChart.tsx
|
|
* Design & Developed by Tech4Biz Solutions
|
|
* Copyright (c) Spurrin Innovations. All rights reserved.
|
|
*/
|