173 lines
3.6 KiB
TypeScript
173 lines
3.6 KiB
TypeScript
import "server-only";
|
|
|
|
import { formatCurrency, formatPercentage } from "@/app/utils/formatCurrency";
|
|
|
|
interface IHealthData {
|
|
total?: number;
|
|
successful?: number;
|
|
acceptance_rate?: number;
|
|
amount?: number;
|
|
atv?: number;
|
|
}
|
|
|
|
interface IStatItem {
|
|
label: string;
|
|
value: string | number;
|
|
change: string;
|
|
}
|
|
|
|
export const transformHealthDataToStats = (
|
|
healthData: IHealthData | null
|
|
): IStatItem[] => {
|
|
if (!healthData) {
|
|
return [
|
|
{ label: "TOTAL", value: 0, change: "0%" },
|
|
{ label: "SUCCESSFUL", value: 0, change: "0%" },
|
|
{ label: "ACCEPTANCE RATE", value: "0%", change: "0%" },
|
|
{ label: "AMOUNT", value: "€0.00", change: "0%" },
|
|
{ label: "ATV", value: "€0.00", change: "0%" },
|
|
];
|
|
}
|
|
|
|
return [
|
|
{
|
|
label: "TOTAL",
|
|
value: healthData.total ?? 0,
|
|
change: "0%",
|
|
},
|
|
{
|
|
label: "SUCCESSFUL",
|
|
value: healthData.successful ?? 0,
|
|
change: "0%",
|
|
},
|
|
{
|
|
label: "ACCEPTANCE RATE",
|
|
value: formatPercentage(healthData.acceptance_rate),
|
|
change: "0%",
|
|
},
|
|
{
|
|
label: "AMOUNT",
|
|
value: formatCurrency(healthData.amount),
|
|
change: "0%",
|
|
},
|
|
{
|
|
label: "ATV",
|
|
value: formatCurrency(healthData.atv),
|
|
change: "0%",
|
|
},
|
|
];
|
|
};
|
|
|
|
/**
|
|
* Map transaction state to color
|
|
*/
|
|
const getStateColor = (state: string): string => {
|
|
const normalizedState = state.toLowerCase();
|
|
|
|
switch (normalizedState) {
|
|
case "success":
|
|
case "completed":
|
|
case "successful":
|
|
return "#4caf50"; // green
|
|
case "pending":
|
|
case "waiting":
|
|
return "#ff9800"; // orange
|
|
case "failed":
|
|
case "error":
|
|
return "#f44336"; // red
|
|
case "cancelled":
|
|
case "canceled":
|
|
return "#9e9e9e"; // gray
|
|
default:
|
|
return "#9e9e9e"; // gray
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Calculate percentage for each state
|
|
*/
|
|
const calculatePercentages = (
|
|
items: Array<{ state: string; count: number }>
|
|
): Array<{
|
|
state: string;
|
|
count: number;
|
|
percentage: string;
|
|
}> => {
|
|
const total = items.reduce((sum, item) => sum + item.count, 0);
|
|
|
|
if (total === 0) {
|
|
return items.map(item => ({
|
|
...item,
|
|
percentage: "0%",
|
|
}));
|
|
}
|
|
|
|
return items.map(item => ({
|
|
...item,
|
|
percentage: `${Math.round((item.count / total) * 100)}%`,
|
|
}));
|
|
};
|
|
|
|
/**
|
|
* Transform API overview data to include colors
|
|
*/
|
|
const enrichOverviewData = (
|
|
data: Array<{
|
|
state: string;
|
|
count: number;
|
|
percentage: string;
|
|
color?: string;
|
|
}>
|
|
): Array<{
|
|
state: string;
|
|
count: number;
|
|
percentage: string;
|
|
color: string;
|
|
}> => {
|
|
return data.map(item => ({
|
|
...item,
|
|
color: item.color || getStateColor(item.state),
|
|
}));
|
|
};
|
|
|
|
/**
|
|
* Transform flat API overview response to enriched array format with percentages and colors
|
|
*/
|
|
export const transformOverviewResponse = (
|
|
data:
|
|
| {
|
|
cancelled_count?: number;
|
|
failed_count?: number;
|
|
successful_count?: number;
|
|
waiting_count?: number;
|
|
}
|
|
| null
|
|
| undefined
|
|
): Array<{
|
|
state: string;
|
|
count: number;
|
|
percentage: string;
|
|
color: string;
|
|
}> => {
|
|
if (!data) {
|
|
return [];
|
|
}
|
|
|
|
const states = [
|
|
{ key: "successful_count", label: "Successful" },
|
|
{ key: "waiting_count", label: "Waiting" },
|
|
{ key: "failed_count", label: "Failed" },
|
|
{ key: "cancelled_count", label: "Cancelled" },
|
|
];
|
|
|
|
const transformed = states
|
|
.map(({ key, label }) => ({
|
|
state: label,
|
|
count: data[key as keyof typeof data] || 0,
|
|
}))
|
|
.filter(item => item.count > 0); // Only include states with counts > 0
|
|
|
|
const withPercentages = calculatePercentages(transformed);
|
|
return enrichOverviewData(withPercentages);
|
|
};
|