Files
CBS-Mobile-App/src/modules/loan/components/LoanTimelineCard.tsx
T

110 lines
3.6 KiB
TypeScript

import React, { memo } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import Ionicons from '@react-native-vector-icons/ionicons';
import { useTheme } from '../../../theme';
import { formatDate } from '../../../utils/formatters';
import { Card } from '../../../components';
interface TimelineStep {
stage: string;
timestamp: string;
active: boolean;
}
interface LoanTimelineCardProps {
title: string;
subtitle?: string;
timeline: TimelineStep[];
}
const LoanTimelineCardComponent = ({ title, subtitle, timeline }: LoanTimelineCardProps) => {
const theme = useTheme();
return (
<Card style={styles.card}>
<View style={styles.header}>
<Text style={[styles.title, { color: theme.colors.textPrimary }]}>{title}</Text>
{subtitle && (
<Text style={[styles.subtitle, { color: theme.colors.textSecondary }]}>{subtitle}</Text>
)}
</View>
<View style={styles.timeline}>
{timeline.map((step, index) => {
const isLast = index === timeline.length - 1;
const isCompleted = step.active && step.timestamp !== '';
const isCurrent = step.active && step.timestamp === '' && index > 0
? false
: step.active && !timeline[index + 1]?.active;
const isPending = !step.active;
let dotColor = theme.colors.textMuted;
let iconName = 'ellipse-outline';
if (isCompleted) {
dotColor = theme.colors.success;
iconName = 'checkmark-circle';
} else if (isCurrent) {
dotColor = theme.colors.primary;
iconName = 'radio-button-on';
}
return (
<View key={index} style={styles.stepRow}>
<View style={styles.stepIndicator}>
<Ionicons name={iconName as any} size={20} color={dotColor} />
{!isLast && (
<View
style={[
styles.connector,
{
backgroundColor: isCompleted ? theme.colors.success : theme.colors.cardBorder,
},
]}
/>
)}
</View>
<View style={[styles.stepContent, !isLast && styles.stepContentSpaced]}>
<Text
style={[
styles.stepLabel,
{
color: isPending ? theme.colors.textMuted : theme.colors.textPrimary,
fontWeight: isCurrent ? '800' : '600',
},
]}
>
{step.stage}
</Text>
{step.timestamp ? (
<Text style={[styles.stepTime, { color: theme.colors.textMuted }]}>
{formatDate(step.timestamp)}
</Text>
) : (
<Text style={[styles.stepTime, { color: theme.colors.textMuted }]}>Pending</Text>
)}
</View>
</View>
);
})}
</View>
</Card>
);
};
const styles = StyleSheet.create({
card: { gap: 14 },
header: { gap: 4 },
title: { fontSize: 16, fontWeight: '800' },
subtitle: { fontSize: 13, lineHeight: 18 },
timeline: { gap: 0 },
stepRow: { flexDirection: 'row', gap: 12 },
stepIndicator: { alignItems: 'center', width: 24 },
connector: { width: 2, flex: 1, minHeight: 20 },
stepContent: { flex: 1, paddingTop: 1 },
stepContentSpaced: { paddingBottom: 16 },
stepLabel: { fontSize: 14 },
stepTime: { fontSize: 12, marginTop: 2 },
});
export const LoanTimelineCard = memo(LoanTimelineCardComponent);