Files
CBS-Mobile-App/src/modules/insurance/components/InsurancePlanCard.tsx
T

231 lines
5.9 KiB
TypeScript

import React, { memo } from 'react';
import { Pressable, StyleSheet, Text, View } from 'react-native';
import Ionicons from '@react-native-vector-icons/ionicons';
import { Button, Card } from '../../../components';
import { useTheme, fontFamily } from '../../../theme';
import type { InsurancePlan } from '../types';
import { formatCompactCurrency, formatCurrency } from '../../../utils/formatters';
interface InsurancePlanCardProps {
plan: InsurancePlan;
selected?: boolean;
compared?: boolean;
onSelect?: () => void;
onCompare?: () => void;
}
const InsurancePlanCardComponent = ({
plan,
selected = false,
compared = false,
onSelect,
onCompare,
}: InsurancePlanCardProps) => {
const theme = useTheme();
return (
<Card
style={[
styles.card,
{
borderColor: selected ? theme.colors.primary : theme.colors.cardBorder,
borderWidth: selected ? 2 : 1,
},
]}
>
<View style={styles.header}>
<View style={styles.copy}>
<Text style={[styles.title, { color: theme.colors.textPrimary }]}>{plan.name}</Text>
<Text style={[styles.subtitle, { color: theme.colors.textSecondary }]}>
{plan.insurerName}
</Text>
</View>
<View
style={[styles.ratioBadge, { backgroundColor: `${theme.colors.accent}14` }]}
>
<Text style={[styles.ratioValue, { color: theme.colors.accent }]}>
{plan.claimSettlementRatio}%
</Text>
<Text style={[styles.ratioLabel, { color: theme.colors.textSecondary }]}>
CSR
</Text>
</View>
</View>
<Text style={[styles.summary, { color: theme.colors.textMuted }]}>{plan.summary}</Text>
<View style={styles.metrics}>
<View style={[styles.metricCard, { backgroundColor: theme.colors.surfaceMuted }]}>
<Text style={[styles.metricLabel, { color: theme.colors.textSecondary }]}>
Premium
</Text>
<Text style={[styles.metricValue, { color: theme.colors.textPrimary }]}>
{formatCurrency(plan.premium)}
</Text>
<Text style={[styles.metricCaption, { color: theme.colors.textMuted }]}>
{plan.premiumFrequency}
</Text>
</View>
<View style={[styles.metricCard, { backgroundColor: theme.colors.surfaceMuted }]}>
<Text style={[styles.metricLabel, { color: theme.colors.textSecondary }]}>
Coverage
</Text>
<Text style={[styles.metricValue, { color: theme.colors.textPrimary }]}>
{formatCompactCurrency(plan.coverAmount)}
</Text>
<Text style={[styles.metricCaption, { color: theme.colors.textMuted }]}>
{plan.tenureYears} year tenure
</Text>
</View>
</View>
<View style={styles.listWrap}>
{plan.benefits.slice(0, 3).map((benefit) => (
<View key={benefit} style={styles.listRow}>
<Ionicons name="checkmark-circle" size={16} color={theme.colors.accent} />
<Text style={[styles.listText, { color: theme.colors.textPrimary }]}>{benefit}</Text>
</View>
))}
</View>
<View style={styles.actionRow}>
<Pressable
onPress={onCompare}
style={({ pressed }) => [
styles.compareButton,
{
backgroundColor: compared ? `${theme.colors.info}12` : theme.colors.surfaceMuted,
opacity: pressed ? 0.9 : 1,
},
]}
>
<Ionicons
name={compared ? 'checkbox' : 'square-outline'}
size={18}
color={compared ? theme.colors.info : theme.colors.textMuted}
/>
<Text
style={[
styles.compareLabel,
{ color: compared ? theme.colors.info : theme.colors.textSecondary },
]}
>
Compare
</Text>
</Pressable>
<Button
title={selected ? 'Selected' : 'Select Plan'}
onPress={onSelect}
variant={selected ? 'secondary' : 'primary'}
fullWidth={false}
style={styles.selectButton}
/>
</View>
</Card>
);
};
const styles = StyleSheet.create({
card: {
gap: 14,
},
header: {
flexDirection: 'row',
gap: 12,
},
copy: {
flex: 1,
gap: 2,
},
title: {
fontSize: 16,
fontFamily: fontFamily.bold,
},
subtitle: {
fontSize: 12,
fontFamily: fontFamily.semibold,
},
ratioBadge: {
minWidth: 68,
borderRadius: 14,
paddingHorizontal: 10,
paddingVertical: 8,
alignItems: 'center',
justifyContent: 'center',
},
ratioValue: {
fontSize: 16,
fontFamily: fontFamily.bold,
},
ratioLabel: {
fontSize: 10,
fontFamily: fontFamily.bold,
letterSpacing: 0.5,
},
summary: {
fontSize: 13,
lineHeight: 18,
},
metrics: {
flexDirection: 'row',
gap: 10,
},
metricCard: {
flex: 1,
borderRadius: 14,
padding: 12,
gap: 4,
},
metricLabel: {
fontSize: 11,
fontFamily: fontFamily.bold,
textTransform: 'uppercase',
letterSpacing: 0.5,
},
metricValue: {
fontSize: 18,
fontFamily: fontFamily.bold,
},
metricCaption: {
fontSize: 11,
fontFamily: fontFamily.semibold,
},
listWrap: {
gap: 8,
},
listRow: {
flexDirection: 'row',
alignItems: 'center',
gap: 8,
},
listText: {
flex: 1,
fontSize: 12,
fontFamily: fontFamily.semibold,
lineHeight: 17,
},
actionRow: {
flexDirection: 'row',
gap: 10,
alignItems: 'center',
},
compareButton: {
flexDirection: 'row',
alignItems: 'center',
gap: 8,
borderRadius: 12,
paddingHorizontal: 12,
paddingVertical: 12,
},
compareLabel: {
fontSize: 12,
fontFamily: fontFamily.bold,
},
selectButton: {
flex: 1,
},
});
export const InsurancePlanCard = memo(InsurancePlanCardComponent);