Vector Motion
Finance

Aging Receivables Card - Collections Management

Monitor outstanding customer invoices and payment collections. Track receivables aging and cash flow management.

Finance Aging Receivables Card

The Finance Aging Receivables Card tracks outstanding customer payments categorized by aging periods, helping businesses manage cash flow and identify overdue accounts.

Preview

Installation

npx shadcn@latest add https://vectormotion.vercel.app/registry/finance-aging-receivables-card.json
Finance Aging Receivables Card
'use client';import React from 'react';import { Hourglass, AlertTriangle } from 'lucide-react';import { ResponsiveContainer, BarChart, Bar, XAxis, Tooltip, Cell, YAxis } from 'recharts';import { motion } from 'motion/react';import { clsx, type ClassValue } from "clsx"import { twMerge } from "tailwind-merge"function cn(...inputs: ClassValue[]) {  return twMerge(clsx(inputs))}interface DataItem {  range: string;  amount: number;  color: string;}interface AgingReceivablesCardProps {  isInteractive?: boolean;  className?: string;  title?: string;  totalAmount?: string;  statusText?: string;  riskAmount?: string;  data?: DataItem[];}const DEFAULT_TITLE = "A/R Aging";const DEFAULT_TOTAL_AMOUNT = "$19.4k";const DEFAULT_STATUS_TEXT = "On Track";const DEFAULT_RISK_AMOUNT = "$950";const DEFAULT_DATA: DataItem[] = [  { range: '0-30d', amount: 12500, color: '#10b981' }, // Emerald  { range: '31-60d', amount: 4200, color: '#f59e0b' }, // Amber  { range: '61-90d', amount: 1800, color: '#f97316' }, // Orange  { range: '90d+', amount: 950, color: '#ef4444' },   // Red];export const AgingReceivablesCard: React.FC<AgingReceivablesCardProps> = ({  isInteractive = true,  className = "",  title = DEFAULT_TITLE,  totalAmount = DEFAULT_TOTAL_AMOUNT,  statusText = DEFAULT_STATUS_TEXT,  riskAmount = DEFAULT_RISK_AMOUNT,  data = DEFAULT_DATA,}) => {  const index = 20;  return (    <motion.div      layoutId={isInteractive ? `card-${index}-${title}` : undefined}      transition={{ duration: 0.4, ease: "easeOut" }}      className={cn(        "relative overflow-hidden rounded-xl border border-border bg-card text-card-foreground p-5 shadow-sm transition-all flex flex-col h-full group",        isInteractive ? "cursor-pointer hover:border-primary/50 hover:shadow-md" : "",        className      )}    >      <div className="mb-2 flex items-start justify-between relative z-10">        <div>          <h3 className="font-semibold text-lg text-foreground">            {title}          </h3>          <div className="flex items-center gap-2 mt-1">            <span className="text-2xl font-bold text-foreground">{totalAmount}</span>            <span className="text-xs bg-emerald-500/10 text-emerald-600 px-1.5 py-0.5 rounded-full flex items-center gap-0.5">              {statusText}            </span>          </div>        </div>        <div className="rounded-lg bg-emerald-500/10 p-2 text-emerald-500">          <Hourglass className="h-5 w-5" />        </div>      </div>      <div className="relative z-10 flex-1 min-h-[140px]">        <div className="absolute inset-0">          <ResponsiveContainer width="100%" height="100%">            <BarChart data={data} layout="vertical" margin={{ left: 20 }}>              <XAxis type="number" hide />              <YAxis                dataKey="range"                type="category"                width={45}                tick={{ fontSize: 10, fill: '#71717a' }}                axisLine={false}                tickLine={false}              />              <Tooltip                cursor={{ fill: 'transparent' }}                contentStyle={{ backgroundColor: 'var(--tooltip-bg)', borderRadius: '8px', border: 'none', color: 'var(--tooltip-text)' }}                formatter={(value: number) => [`$${value.toLocaleString()}`, 'Outstanding']}              />              <Bar                dataKey="amount"                radius={[0, 4, 4, 0]}                barSize={16}                animationDuration={1200}              >                {data.map((entry, index) => (                  <Cell key={`cell-${index}`} fill={entry.color} />                ))}              </Bar>            </BarChart>          </ResponsiveContainer>        </div>      </div>      <div className="z-10 mt-2 flex items-center justify-between text-xs pt-2 border-t border-border">        <span className="text-muted-foreground">At Risk (&gt;90d)</span>        <span className="font-bold text-red-500 flex items-center gap-1"><AlertTriangle className="w-3 h-3" /> {riskAmount}</span>      </div>    </motion.div>  );};

Props

Prop

Type