import { useQuery } from '@tanstack/react-query'
import { useNavigate } from '@tanstack/react-router'
import { CalendarClock, Loader2, Plus, UserCheck, Users, Wallet, type LucideIcon } from 'lucide-react'
import type { HomeSummaryDto, NextClassDto, PaymentDto, UpcomingPaymentDto } from '@gruperly/shared'
import { Badge, Button } from '../components/ui'
import { getHomeSummary } from '../lib/api'
import {
formatPrice,
formatRelativeDateTime,
formatSchedule,
PAYMENT_STATUS_LABELS,
} from '../lib/format'
import { cn } from '../lib/utils'
const PAYMENT_BADGE_VARIANT: Record<
PaymentDto['status'],
'success' | 'warning' | 'danger' | 'neutral'
> = {
PENDING: 'warning',
OVERDUE: 'danger',
PAID: 'success',
CANCELLED: 'neutral',
}
function NextClassHero({ nextClass }: { nextClass: NextClassDto }) {
const navigate = useNavigate()
const hasSchedule = (nextClass.days?.length ?? 0) > 0
return (
{nextClass.isNow ? 'Clase en curso' : 'Próxima clase'}
{nextClass.name}
{hasSchedule ? (
{formatSchedule(nextClass.days ?? [], nextClass.time)}
) : null}
{nextClass.isNow ? 'En curso ahora' : formatRelativeDateTime(nextClass.occurrenceAt)}
)
}
function UpcomingPaymentRow({ payment }: { payment: UpcomingPaymentDto }) {
return (
{payment.attendeeName}
{payment.groupName} · {formatRelativeDateTime(payment.dueDate)}
{formatPrice(payment.amount)}
{PAYMENT_STATUS_LABELS[payment.status]}
)
}
function SummaryStats({ summary }: { summary: HomeSummaryDto }) {
const navigate = useNavigate()
const stats: {
label: string
value: string
sub?: string
icon: LucideIcon
to: '/groups' | '/payments'
}[] = [
{
label: 'Grupos activos',
value: String(summary.stats.groups),
icon: Users,
to: '/groups',
},
{
label: 'Cobros pendientes',
value: summary.stats.pendingAmount > 0 ? formatPrice(summary.stats.pendingAmount) : '0',
sub: `${summary.stats.pendingPayments} por cobrar`,
icon: Wallet,
to: '/payments',
},
{
label: 'Asistentes',
value: String(summary.stats.attendees),
icon: UserCheck,
to: '/groups',
},
]
return (
{stats.map((stat) => {
const Icon = stat.icon
return (
)
})}
)
}
export function HomeView() {
const navigate = useNavigate()
const summaryQuery = useQuery({
queryKey: ['home-summary'],
queryFn: getHomeSummary,
})
return (
Inicio
Tu actividad de cobros de un vistazo.
{summaryQuery.isPending ? (
) : null}
{summaryQuery.isError ? (
No pudimos cargar tu resumen.
) : null}
{summaryQuery.isSuccess && summaryQuery.data.stats.groups === 0 ? (
Todavía no tenés grupos
Crea tu primer grupo para empezar a cobrar.
) : null}
{summaryQuery.isSuccess && summaryQuery.data.stats.groups > 0 ? (
{summaryQuery.data.nextClass ? (
) : (
Sin clases programadas
Agregá días y horario a tus grupos para ver tu próxima clase acá.
)}
Próximos cobros
{summaryQuery.data.upcomingPayments.length > 0 ? (
{summaryQuery.data.upcomingPayments.map((payment) => (
))}
) : (
Sin cobros pendientes por ahora.
)}
) : null}
)
}