Vector Motion
Medical

Infection Control Card - Healthcare Safety

Monitor infection rates and control measures. Track healthcare-associated infections and prevention effectiveness.

Infection Control Card

The Infection Control Card Monitor hospital-acquired infection rates and control measures.

Preview

Installation

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

Infection Control Card
'use client'import React from 'react';import { Bug, CheckCircle2, ShieldCheck } from 'lucide-react';import { motion } from 'motion/react';import { clsx, type ClassValue } from "clsx";import { twMerge } from "tailwind-merge";import { BarChart, Bar, Cell, ResponsiveContainer, XAxis } from 'recharts';function cn(...inputs: ClassValue[]) {   return twMerge(clsx(inputs));}interface InfectionHistory {   day: string;   cases: number;   [key: string]: any;}interface InfectionStatus {   name: string;   status: string;   count?: number;   isClean: boolean;}interface InfectionControlCardProps {   className?: string;   title?: string;   subtitle?: string;   statusItems?: InfectionStatus[];   historyData?: InfectionHistory[];}const DEFAULT_HISTORY_DATA: InfectionHistory[] = [   { day: 'M', cases: 0 },   { day: 'T', cases: 0 },   { day: 'W', cases: 1 },   { day: 'T', cases: 0 },   { day: 'F', cases: 0 },   { day: 'S', cases: 0 },   { day: 'S', cases: 0 },];const DEFAULT_STATUS_ITEMS: InfectionStatus[] = [   { name: "C. Diff", status: "Clean", isClean: true },   { name: "MRSA", status: "1 New", count: 1, isClean: false },];const DEFAULT_TITLE = "Infection Ctrl";const DEFAULT_SUBTITLE = "HAI Surveillance";export const InfectionControlCard: React.FC<InfectionControlCardProps> = ({   className = "",   title = DEFAULT_TITLE,   subtitle = DEFAULT_SUBTITLE,   statusItems = DEFAULT_STATUS_ITEMS,   historyData = DEFAULT_HISTORY_DATA,}) => {   const isInteractive = true;   const index = 21;   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-purple-300 dark:hover:border-purple-700 hover:shadow-md" : "",            className         )}      >         <div className="p-5 flex flex-col h-full relative z-10">            <div className="mb-2 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="relative inline-flex rounded-full h-2 w-2 bg-purple-500"></span>                     </span>                     <p className="text-sm text-muted-foreground font-medium">                        {subtitle}                     </p>                  </div>               </div>               <div className="rounded-xl bg-purple-50 dark:bg-purple-900/20 p-2.5 text-purple-600 dark:text-purple-400 flex items-center justify-center ring-1 ring-purple-100 dark:ring-purple-800">                  <Bug className="h-5 w-5" />               </div>            </div>            <div className="flex-1 flex flex-col justify-between">               <div className="space-y-3">                  {statusItems.map((item, i) => (                     <div key={i} className="flex justify-between items-center p-2 rounded-lg bg-muted">                        <span className="text-xs font-semibold text-foreground">{item.name}</span>                        {item.isClean ? (                           <div className="flex items-center gap-1.5 text-[10px] font-bold text-emerald-600 bg-emerald-100 dark:bg-emerald-900/30 px-2 py-0.5 rounded-full">                              <CheckCircle2 className="h-3 w-3" />                              {item.status}                           </div>                        ) : (                           <div className="flex items-center gap-1.5 text-[10px] font-bold text-red-600 bg-red-100 dark:bg-red-900/30 px-2 py-0.5 rounded-full">                              <Bug className="h-3 w-3" />                              {item.status}                           </div>                        )}                     </div>                  ))}               </div>               <div className="mt-4">                  <p className="text-[10px] text-zinc-400 font-bold uppercase mb-2">Weekly Incident Trend</p>                  <div className="h-10 w-full">                     <ResponsiveContainer width="100%" height="100%">                        <BarChart data={historyData}>                           <Bar dataKey="cases" radius={[2, 2, 2, 2]}>                              {historyData.map((entry, index) => (                                 <Cell key={`cell-${index}`} fill={entry.cases > 0 ? '#ef4444' : '#e4e4e7'} />                              ))}                           </Bar>                        </BarChart>                     </ResponsiveContainer>                  </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