169 lines
6.2 KiB
TypeScript
169 lines
6.2 KiB
TypeScript
"use client";
|
|
import React, { useEffect, useState } from "react";
|
|
import classNames from "classnames";
|
|
import styles from "./PlanMetricsWidget.module.css";
|
|
import { ISubscriptionInfo } from "@core/Models/Subscription.Model";
|
|
import StorefrontOutlinedIcon from "@mui/icons-material/StorefrontOutlined";
|
|
import PeopleOutlineOutlinedIcon from "@mui/icons-material/PeopleOutlineOutlined";
|
|
import CalendarTodayOutlinedIcon from "@mui/icons-material/CalendarTodayOutlined";
|
|
import AssignmentIndOutlinedIcon from "@mui/icons-material/AssignmentIndOutlined";
|
|
import RepeatOutlinedIcon from "@mui/icons-material/RepeatOutlined";
|
|
import Button from "@core/app/components/Button/Button";
|
|
import { MP_SUBS_STATUS } from "@core/Models/Subscription.Model";
|
|
import dayjs from "dayjs";
|
|
|
|
export interface PlanMetricsWidgetProps {
|
|
subscription: ISubscriptionInfo;
|
|
metrics: {
|
|
organizationsCount: number;
|
|
employeesCount: number;
|
|
clientsCount: number;
|
|
appointmentsCount: number;
|
|
servicesCount: number;
|
|
repeatsCount: number;
|
|
};
|
|
onUpgrade: () => void;
|
|
onRenew?: () => void;
|
|
onCancel: () => void;
|
|
isOwner?: boolean;
|
|
}
|
|
|
|
const MetricRow = ({
|
|
icon,
|
|
title,
|
|
value,
|
|
maxValue,
|
|
}: {
|
|
icon: React.ReactNode;
|
|
title: string;
|
|
value: number;
|
|
maxValue: number;
|
|
}) => {
|
|
const [animatedWidth, setAnimatedWidth] = useState(0);
|
|
|
|
const isInfinite = maxValue === -1;
|
|
const formattedMax = isInfinite ? "∞" : maxValue;
|
|
const percentage = isInfinite ? 100 : Math.min(100, (value / maxValue) * 100);
|
|
|
|
let statusClass = styles.safe;
|
|
if (isInfinite) {
|
|
statusClass = styles.infinite;
|
|
} else {
|
|
if (percentage >= 100) {
|
|
statusClass = styles.danger;
|
|
} else if (percentage >= 80) {
|
|
statusClass = styles.warning;
|
|
}
|
|
}
|
|
|
|
useEffect(() => {
|
|
const timer = setTimeout(() => {
|
|
setAnimatedWidth(percentage);
|
|
}, 100);
|
|
return () => clearTimeout(timer);
|
|
}, [percentage]);
|
|
|
|
return (
|
|
<div className={styles.metricRow}>
|
|
<div className={styles.metricHeader}>
|
|
<div className={styles.metricTitleWrap}>
|
|
<span className={styles.metricIcon}>{icon}</span>
|
|
<span className={styles.metricTitle}>{title}</span>
|
|
</div>
|
|
<div className={styles.metricValue}>
|
|
<span className={styles.currentValue}>{value}</span>
|
|
<span className={styles.maxValue}>/ {formattedMax}</span>
|
|
</div>
|
|
</div>
|
|
<div className={styles.progressContainer}>
|
|
<div
|
|
className={classNames(styles.progressBar, statusClass)}
|
|
style={{ width: `${animatedWidth}%` }}
|
|
/>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default function PlanMetricsWidget({
|
|
subscription,
|
|
metrics,
|
|
onUpgrade,
|
|
onCancel,
|
|
isOwner = true,
|
|
}: PlanMetricsWidgetProps) {
|
|
const isCancelled = subscription.mpStatus === MP_SUBS_STATUS.CANCELLED;
|
|
|
|
return (
|
|
<div className={styles.widgetContainer}>
|
|
<div className={styles.widgetHeader}>
|
|
<h3 className={styles.title}>Métricas del Plan {subscription.plan.name}</h3>
|
|
<span className={styles.subtitle}>Uso actual de tu suscripción</span>
|
|
</div>
|
|
|
|
<div className={styles.metricsList}>
|
|
<MetricRow
|
|
icon={<StorefrontOutlinedIcon fontSize="small" />}
|
|
title="Organizaciones"
|
|
value={metrics.organizationsCount}
|
|
maxValue={subscription.plan.limitOrganizations}
|
|
/>
|
|
<MetricRow
|
|
icon={<PeopleOutlineOutlinedIcon fontSize="small" />}
|
|
title="Clientes"
|
|
value={metrics.clientsCount}
|
|
maxValue={subscription.plan.limitClients}
|
|
/>
|
|
<MetricRow
|
|
icon={<CalendarTodayOutlinedIcon fontSize="small" />}
|
|
title="Turnos"
|
|
value={metrics.appointmentsCount}
|
|
maxValue={subscription.plan.limitAppointments}
|
|
/>
|
|
<MetricRow
|
|
icon={<AssignmentIndOutlinedIcon fontSize="small" />}
|
|
title="Colaboradores"
|
|
value={metrics.employeesCount}
|
|
maxValue={subscription.plan.limitEmployees}
|
|
/>
|
|
<MetricRow
|
|
icon={<RepeatOutlinedIcon fontSize="small" />}
|
|
title="Repeticiones"
|
|
value={metrics.repeatsCount || 0}
|
|
maxValue={subscription.plan.limitRepeats}
|
|
/>
|
|
</div>
|
|
|
|
{isOwner && (
|
|
<div className={styles.actionsContainer}>
|
|
<Button
|
|
color="primary"
|
|
text="Mejorar mi plan"
|
|
width="custom"
|
|
style={{ width: "100%", padding: "12px 0", borderRadius: "8px", fontWeight: "600" }}
|
|
onClick={onUpgrade}
|
|
/>
|
|
<div className={styles.statusFooter}>
|
|
{isCancelled ? (
|
|
<div className={styles.cancelledInfo}>
|
|
<p className={styles.cancelledText}>La suscripción ha sido cancelada</p>
|
|
<p className={styles.validUntilText}>
|
|
Vigente hasta el {dayjs(subscription.endDate).format("DD/MM/YYYY")}
|
|
</p>
|
|
</div>
|
|
) : (
|
|
<Button
|
|
color="link"
|
|
text="Cancelar subscripción"
|
|
onClick={onCancel}
|
|
width="custom"
|
|
style={{ margin: 0, padding: 0, fontSize: "13px", color: "#6b7280", minHeight: "auto" }}
|
|
/>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|