218 lines
6.2 KiB
TypeScript
218 lines
6.2 KiB
TypeScript
import {
|
|
LucideSend,
|
|
LucideUploadCloud,
|
|
LucideArrowUpRight,
|
|
LucideArrowDownLeft,
|
|
} from "lucide-react-native";
|
|
import React from "react";
|
|
import { View, Text, TouchableOpacity } from "react-native";
|
|
import { useTranslation } from "react-i18next";
|
|
import { Transaction } from "~/lib/services/transactionService";
|
|
|
|
interface TransactionCardProps {
|
|
transaction: Transaction;
|
|
onPress?: () => void;
|
|
}
|
|
|
|
export default function TransactionCard({
|
|
transaction,
|
|
onPress,
|
|
}: TransactionCardProps) {
|
|
const { t } = useTranslation();
|
|
|
|
const formatDate = (date: Date) => {
|
|
return date.toLocaleDateString("en-US", {
|
|
month: "short",
|
|
day: "numeric",
|
|
hour: "2-digit",
|
|
minute: "2-digit",
|
|
});
|
|
};
|
|
|
|
const formatAmount = (amountInCents: number) => {
|
|
return `$${(amountInCents / 100).toFixed(2)}`;
|
|
};
|
|
|
|
const getTransactionIcon = (transaction: Transaction) => {
|
|
switch (transaction.type) {
|
|
case "send":
|
|
return <LucideArrowUpRight className="text-white" size={16} />;
|
|
case "receive":
|
|
return <LucideArrowDownLeft className="text-white" size={16} />;
|
|
case "add_cash":
|
|
return <LucideUploadCloud className="text-white" size={16} />;
|
|
case "cash_out":
|
|
return <LucideArrowUpRight className="text-white" size={16} />;
|
|
default:
|
|
return <LucideSend className="text-white" size={16} />;
|
|
}
|
|
};
|
|
|
|
const getTransactionColor = (transaction: Transaction) => {
|
|
switch (transaction.type) {
|
|
case "send":
|
|
return "bg-red-500";
|
|
case "receive":
|
|
return "bg-green-500";
|
|
case "add_cash":
|
|
return "bg-blue-500";
|
|
case "cash_out":
|
|
return "bg-orange-500";
|
|
default:
|
|
return "bg-secondary";
|
|
}
|
|
};
|
|
|
|
const getAmountColor = (transaction: Transaction) => {
|
|
switch (transaction.type) {
|
|
case "send":
|
|
return "text-red-600";
|
|
case "receive":
|
|
return "text-green-600";
|
|
case "add_cash":
|
|
return "text-blue-600";
|
|
case "cash_out":
|
|
return "text-orange-600";
|
|
default:
|
|
return "text-primary";
|
|
}
|
|
};
|
|
|
|
const getTransactionDescription = (transaction: Transaction) => {
|
|
switch (transaction.type) {
|
|
case "send":
|
|
return t("components.transactioncard.descriptionSend", {
|
|
recipientName: transaction.recipientName,
|
|
});
|
|
case "receive":
|
|
return t("components.transactioncard.descriptionReceive", {
|
|
senderName: transaction.senderName,
|
|
});
|
|
case "add_cash":
|
|
return t("components.transactioncard.descriptionAddCash", {
|
|
lastFourDigits: transaction.lastFourDigits,
|
|
});
|
|
case "cash_out":
|
|
return t("components.transactioncard.descriptionCashOut", {
|
|
bankProvider:
|
|
transaction.bankProvider.charAt(0).toUpperCase() +
|
|
transaction.bankProvider.slice(1),
|
|
});
|
|
default:
|
|
return t("components.transactioncard.descriptionDefault");
|
|
}
|
|
};
|
|
|
|
const getTransactionDetails = (transaction: Transaction) => {
|
|
const details = [];
|
|
|
|
//@ts-ignore
|
|
if (transaction.note && transaction.note.trim()) {
|
|
//@ts-ignore
|
|
details.push(transaction.note);
|
|
}
|
|
|
|
switch (transaction.type) {
|
|
case "send":
|
|
if (transaction.recipientName) {
|
|
details.push(`Client: ${transaction.recipientName}`);
|
|
}
|
|
if (transaction.recipientPhoneNumber) {
|
|
details.push(
|
|
t("components.transactioncard.detailPhone", {
|
|
phoneNumber: transaction.recipientPhoneNumber,
|
|
})
|
|
);
|
|
}
|
|
break;
|
|
case "receive":
|
|
if (transaction.senderName) {
|
|
details.push(`Client: ${transaction.senderName}`);
|
|
}
|
|
if (transaction.senderPhoneNumber) {
|
|
details.push(
|
|
t("components.transactioncard.detailPhone", {
|
|
phoneNumber: transaction.senderPhoneNumber,
|
|
})
|
|
);
|
|
}
|
|
break;
|
|
case "add_cash":
|
|
if (transaction.cardId) {
|
|
details.push(
|
|
t("components.transactioncard.detailCard", {
|
|
lastFourDigits: transaction.lastFourDigits,
|
|
})
|
|
);
|
|
}
|
|
break;
|
|
case "cash_out":
|
|
if (transaction.accountNumber) {
|
|
details.push(
|
|
t("components.transactioncard.detailAccount", {
|
|
accountNumber: transaction.accountNumber,
|
|
})
|
|
);
|
|
}
|
|
details.push(
|
|
t("components.transactioncard.detailBankProvider", {
|
|
bankProvider:
|
|
transaction.bankProvider.charAt(0).toUpperCase() +
|
|
transaction.bankProvider.slice(1),
|
|
})
|
|
);
|
|
break;
|
|
}
|
|
|
|
return details;
|
|
};
|
|
|
|
return (
|
|
<TouchableOpacity
|
|
className="flex flex-row w-full justify-between items-center py-4 bg-green-50 rounded-md px-3 mb-2"
|
|
onPress={onPress}
|
|
>
|
|
<View className="flex flex-row space-x-3 items-center flex-1">
|
|
<View className={`${getTransactionColor(transaction)} p-2 rounded`}>
|
|
{getTransactionIcon(transaction)}
|
|
</View>
|
|
<View className="w-4" />
|
|
<View className="flex gap-[2px] flex-1">
|
|
<Text className="font-dmsans-bold text-primary" numberOfLines={1}>
|
|
{getTransactionDescription(transaction)}
|
|
</Text>
|
|
<Text
|
|
className="font-dmsans-medium text-secondary text-sm"
|
|
numberOfLines={1}
|
|
>
|
|
{formatDate(transaction.createdAt)}
|
|
</Text>
|
|
{getTransactionDetails(transaction).map((detail, index) => (
|
|
<Text
|
|
key={index}
|
|
className="font-dmsans-medium text-gray-500 text-xs"
|
|
numberOfLines={1}
|
|
>
|
|
{detail}
|
|
</Text>
|
|
))}
|
|
</View>
|
|
</View>
|
|
|
|
<View className="flex items-center space-y-1">
|
|
<Text
|
|
className={`font-dmsans-bold text-lg ${getAmountColor(transaction)}`}
|
|
>
|
|
{transaction.type === "send" || transaction.type === "cash_out"
|
|
? "-"
|
|
: "+"}
|
|
{formatAmount(transaction.amount)}
|
|
</Text>
|
|
<Text className="font-dmsans-medium text-xs text-gray-500">
|
|
{transaction.status}
|
|
</Text>
|
|
</View>
|
|
</TouchableOpacity>
|
|
);
|
|
}
|