Vector Motion
Medical

Bed Turnover Card - Hospital Efficiency

Monitor bed turnover efficiency and patient flow. Track discharge rates and bed utilization metrics.

Bed Turnover Card

The Bed Turnover Card Monitor bed turnover efficiency metrics and patient flow.

Preview

Installation

ash npx shadcn@latest add https://vectormotion.vercel.app/registry/bed-turnover-card.json

Bed Turnover Card
'use client'import React from 'react';import { Sparkles, Clock, TrendingDown } from 'lucide-react';import { motion } from 'motion/react';import { clsx, type ClassValue } from "clsx";import { twMerge } from "tailwind-merge";import { LineChart, Line, ResponsiveContainer, XAxis, Tooltip } from 'recharts';function cn(...inputs: ClassValue[]) {   return twMerge(clsx(inputs));}interface TrendData {   time: string;   minutes: number;   [key: string]: any;}interface BedTurnoverCardProps {   className?: string;   title?: string;   subtitle?: string;   avgTurnoverTime?: string;   trendImprovement?: string;   pendingCount?: number;   activeCount?: number;   data?: TrendData[];}const DEFAULT_DATA: TrendData[] = [   { time: '8AM', minutes: 45 },   { time: '10AM', minutes: 42 },   { time: '12PM', minutes: 38 },   { time: '2PM', minutes: 35 },   { time: '4PM', minutes: 32 },];const DEFAULT_TITLE = "Turnover";const DEFAULT_SUBTITLE = "Housekeeping Stats";const DEFAULT_AVG_TURNOVER_TIME = "32m";const DEFAULT_TREND_IMPROVEMENT = "5m";const DEFAULT_PENDING_COUNT = 12;const DEFAULT_ACTIVE_COUNT = 4;export const BedTurnoverCard: React.FC<BedTurnoverCardProps> = ({   className = "",   title = DEFAULT_TITLE,   subtitle = DEFAULT_SUBTITLE,   avgTurnoverTime = DEFAULT_AVG_TURNOVER_TIME,   trendImprovement = DEFAULT_TREND_IMPROVEMENT,   pendingCount = DEFAULT_PENDING_COUNT,   activeCount = DEFAULT_ACTIVE_COUNT,   data = DEFAULT_DATA,}) => {   const isInteractive = true;   const index = 19;   return (      <motion.div         layoutId={isInteractive ? `card-${index}-${title}` : undefined}         transition={{ duration: 0.4, ease: "easeOut" }}         className={cn(            "relative overflow-hidden rounded-2xl border border-border bg-card text-card-foreground shadow-sm transition-all flex flex-col h-full",            isInteractive ? "hover:border-sky-300 dark:hover:border-sky-700 hover:shadow-md" : "",            className         )}      >         <div className="p-5 flex flex-col h-full relative z-10">            <div className="mb-4 flex items-start justify-between">               <div>                  <h3 className="font-bold text-lg text-foreground">                     {title}                  </h3>                  <div className="flex items-center gap-1.5 mt-1">                     <span className="relative flex h-2 w-2">                        <span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-sky-400 opacity-75"></span>                        <span className="relative inline-flex rounded-full h-2 w-2 bg-sky-500"></span>                     </span>                     <p className="text-sm text-muted-foreground font-medium">                        {subtitle}                     </p>                  </div>               </div>               <div className="rounded-xl bg-sky-50 dark:bg-sky-900/20 p-2.5 text-sky-600 dark:text-sky-400 flex items-center justify-center ring-1 ring-sky-100 dark:ring-sky-800">                  <Sparkles className="h-5 w-5" />               </div>            </div>            <div className="flex-1">               <div className="flex items-end justify-between mb-4">                  <div>                     <div className="flex items-baseline gap-1">                        <span className="text-3xl font-bold text-foreground tracking-tight">{avgTurnoverTime}</span>                        <span className="text-sm font-medium text-emerald-500 bg-emerald-500/10 px-1.5 rounded flex items-center transform translate-y-[-2px]">                           <TrendingDown className="h-3 w-3 mr-0.5" /> {trendImprovement}                        </span>                     </div>                     <p className="text-xs text-muted-foreground font-medium">Avg Turnover Time</p>                  </div>               </div>               <div className="h-16 w-full mb-4 -ml-2">                  <ResponsiveContainer width="100%" height="100%">                     <LineChart data={data}>                        <Line type="monotone" dataKey="minutes" stroke="#0ea5e9" strokeWidth={2} dot={{ r: 2, fill: '#0ea5e9' }} />                        <Tooltip                           labelStyle={{ display: 'none' }}                           contentStyle={{ borderRadius: '8px', border: 'none', boxShadow: '0 4px 6px -1px rgb(0 0 0 / 0.1)', padding: '4px 8px' }}                        />                     </LineChart>                  </ResponsiveContainer>               </div>               <div className="flex gap-2">                  <div className="flex-1 bg-muted p-2 rounded-lg border border-border flex items-center justify-between">                     <span className="text-[10px] text-muted-foreground font-semibold uppercase">Pending</span>                     <span className="text-sm font-bold text-red-500">{pendingCount}</span>                  </div>                  <div className="flex-1 bg-muted p-2 rounded-lg border border-border flex items-center justify-between">                     <span className="text-[10px] text-muted-foreground font-semibold uppercase">Active</span>                     <span className="text-sm font-bold text-amber-500">{activeCount}</span>                  </div>               </div>            </div>         </div>      </motion.div>   );};

Usage

This component is a demo card displaying medical metrics with animated visualizations and dark mode support.

Prop

Type