build: 444813b5-5daf-49b2-bf1a-7e4caeab4e17
This commit is contained in:
@@ -0,0 +1,210 @@
|
||||
import React from 'react';
|
||||
import { IonIcon } from '@ionic/react';
|
||||
import {
|
||||
cartOutline,
|
||||
medkitOutline,
|
||||
flashOutline,
|
||||
phonePortraitOutline,
|
||||
timeOutline,
|
||||
checkmarkCircleOutline,
|
||||
removeCircleOutline,
|
||||
} from 'ionicons/icons';
|
||||
import momImage from '../assets/mom.jpg';
|
||||
import dadImage from '../assets/dad.jpg';
|
||||
|
||||
interface ActivityListItemProps {
|
||||
id: string;
|
||||
eventType: string;
|
||||
title: string;
|
||||
subtitle: string;
|
||||
amount?: number;
|
||||
statusText?: string;
|
||||
isSuccess?: boolean;
|
||||
avatarLabel?: string;
|
||||
avatarTone?: string;
|
||||
avatarImage?: string;
|
||||
redeemedAmount?: number;
|
||||
remainingAmount?: number;
|
||||
onClick?: (id: string) => void;
|
||||
}
|
||||
|
||||
const ActivityListItem: React.FC<ActivityListItemProps> = ({
|
||||
id,
|
||||
eventType,
|
||||
title,
|
||||
subtitle,
|
||||
amount,
|
||||
statusText,
|
||||
isSuccess = true,
|
||||
avatarLabel,
|
||||
avatarTone = 'brand',
|
||||
avatarImage,
|
||||
redeemedAmount,
|
||||
remainingAmount,
|
||||
onClick,
|
||||
}) => {
|
||||
const getIconAndColor = () => {
|
||||
if (
|
||||
eventType.includes('grocery') ||
|
||||
title.toLowerCase().includes('grocer')
|
||||
) {
|
||||
return {
|
||||
icon: cartOutline,
|
||||
badgeClass: 'grocery',
|
||||
};
|
||||
}
|
||||
if (
|
||||
eventType.includes('medication') ||
|
||||
title.toLowerCase().includes('medic')
|
||||
) {
|
||||
return {
|
||||
icon: medkitOutline,
|
||||
badgeClass: 'medication',
|
||||
};
|
||||
}
|
||||
if (
|
||||
eventType.includes('airtime') ||
|
||||
title.toLowerCase().includes('airtime')
|
||||
) {
|
||||
return {
|
||||
icon: phonePortraitOutline,
|
||||
badgeClass: 'airtime',
|
||||
};
|
||||
}
|
||||
return {
|
||||
icon: flashOutline,
|
||||
badgeClass: 'electricity',
|
||||
};
|
||||
};
|
||||
|
||||
const { icon, badgeClass } = getIconAndColor();
|
||||
|
||||
const getStatusTheme = () => {
|
||||
const text = statusText?.toLowerCase() ?? '';
|
||||
if (
|
||||
text.includes('delivered') ||
|
||||
text.includes('ready') ||
|
||||
(text.includes('redeemed') && !text.includes('partial'))
|
||||
) {
|
||||
return 'success';
|
||||
}
|
||||
if (
|
||||
text.includes('awaiting') ||
|
||||
text.includes('ready') ||
|
||||
text.includes('collect')
|
||||
) {
|
||||
return 'info';
|
||||
}
|
||||
if (text.includes('expir') || text.includes('warn')) {
|
||||
return 'warning';
|
||||
}
|
||||
if (text.includes('cancel') || text.includes('fail')) {
|
||||
return 'danger';
|
||||
}
|
||||
return 'brand';
|
||||
};
|
||||
|
||||
const statusTheme = getStatusTheme();
|
||||
|
||||
const getStatusIcon = () => {
|
||||
switch (statusTheme) {
|
||||
case 'success':
|
||||
return checkmarkCircleOutline;
|
||||
case 'info':
|
||||
case 'warning':
|
||||
return timeOutline;
|
||||
case 'danger':
|
||||
return removeCircleOutline;
|
||||
default:
|
||||
return timeOutline;
|
||||
}
|
||||
};
|
||||
|
||||
const statusIcon = getStatusIcon();
|
||||
|
||||
const resolvedAvatar =
|
||||
avatarImage ??
|
||||
(title.toLowerCase().includes('mum')
|
||||
? momImage
|
||||
: title.toLowerCase().includes('dad')
|
||||
? dadImage
|
||||
: undefined);
|
||||
|
||||
const hasVoucherBreakdown =
|
||||
redeemedAmount !== undefined || remainingAmount !== undefined;
|
||||
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onClick && onClick(id)}
|
||||
className="activity-feed-item"
|
||||
disabled={!onClick}
|
||||
>
|
||||
<div className="activity-feed-avatar-wrap">
|
||||
<div
|
||||
className={`activity-feed-avatar activity-feed-avatar-${avatarTone}`}
|
||||
>
|
||||
{resolvedAvatar ? (
|
||||
<img
|
||||
src={resolvedAvatar}
|
||||
alt=""
|
||||
className="activity-feed-avatar-image"
|
||||
/>
|
||||
) : (
|
||||
<span>{avatarLabel ?? 'KU'}</span>
|
||||
)}
|
||||
<div
|
||||
className={`activity-feed-avatar-badge activity-feed-avatar-badge-${badgeClass}`}
|
||||
>
|
||||
<IonIcon icon={icon} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="activity-feed-main">
|
||||
<div className="activity-feed-row">
|
||||
<div className="activity-feed-copy">
|
||||
<p className="activity-feed-title">{title}</p>
|
||||
<p className="activity-feed-subtitle">{subtitle}</p>
|
||||
</div>
|
||||
|
||||
<div className="activity-feed-right">
|
||||
{amount !== undefined && (
|
||||
<p className="activity-feed-amount">${amount.toFixed(2)}</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{statusText && !hasVoucherBreakdown && (
|
||||
<div
|
||||
className={`activity-feed-status activity-feed-status-${statusTheme}`}
|
||||
>
|
||||
<IonIcon icon={statusIcon} />
|
||||
<span>{statusText}</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{hasVoucherBreakdown && (
|
||||
<div className="activity-feed-breakdown">
|
||||
<div className="activity-feed-breakdown-summary">
|
||||
{redeemedAmount !== undefined && (
|
||||
<div className="activity-feed-breakdown-pill is-redeemed">
|
||||
<IonIcon icon={checkmarkCircleOutline} />
|
||||
<span>${redeemedAmount.toFixed(2)} redeemed</span>
|
||||
</div>
|
||||
)}
|
||||
{remainingAmount !== undefined && (
|
||||
<div className="activity-feed-breakdown-pill is-remaining">
|
||||
<IonIcon icon={removeCircleOutline} />
|
||||
<span>${remainingAmount.toFixed(2)} left</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
export default ActivityListItem;
|
||||
Reference in New Issue
Block a user