Vector Motion
Medical

Imaging Status Card - Radiology Services

Monitor imaging order status and radiology queue. Track MRI, CT, and X-ray turnaround times.

Imaging Status Card

The Imaging Status Card Track medical imaging orders, scheduling, and completion status.

Preview

Installation

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

Imaging Status Card
'use client'import React from 'react';import { Scan, Activity, Zap } from 'lucide-react';import { motion } from 'motion/react';import { clsx, type ClassValue } from "clsx";import { twMerge } from "tailwind-merge";import { PieChart, Pie, Cell, ResponsiveContainer, Tooltip } from 'recharts';function cn(...inputs: ClassValue[]) {   return twMerge(clsx(inputs));}interface ImagingData {   name: string;   value: number;   color: string;   [key: string]: any;}interface ImagingStatusCardProps {   className?: string;   title?: string;   subtitle?: string;   totalScans?: number;   activeScanner?: string;   activeScannerStatus?: string;   data?: ImagingData[];}const DEFAULT_DATA: ImagingData[] = [   { name: 'X-Ray', value: 8, color: '#3b82f6' },  // blue-500   { name: 'CT', value: 5, color: '#a855f7' },     // purple-500   { name: 'MRI', value: 3, color: '#ec4899' },    // pink-500   { name: 'US', value: 2, color: '#10b981' },     // emerald-500];const DEFAULT_TITLE = "Imaging";const DEFAULT_SUBTITLE = "Modality Queue";const DEFAULT_TOTAL_SCANS = 18;const DEFAULT_ACTIVE_SCANNER = "CT Scanner 2";const DEFAULT_ACTIVE_SCANNER_STATUS = "Busy";export const ImagingStatusCard: React.FC<ImagingStatusCardProps> = ({   className = "",   title = DEFAULT_TITLE,   subtitle = DEFAULT_SUBTITLE,   totalScans = DEFAULT_TOTAL_SCANS,   activeScanner = DEFAULT_ACTIVE_SCANNER,   activeScannerStatus = DEFAULT_ACTIVE_SCANNER_STATUS,   data = DEFAULT_DATA,}) => {   const isInteractive = true;   const index = 18;   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-primary/50 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-blue-500"></span>                     </span>                     <p className="text-sm text-muted-foreground font-medium">                        {subtitle}                     </p>                  </div>               </div>               <div className="rounded-xl bg-blue-500/10 p-2.5 text-blue-500 flex items-center justify-center ring-1 ring-blue-100 dark:ring-blue-800">                  <Scan className="h-5 w-5" />               </div>            </div>            <div className="flex-1 flex gap-2 items-center">               <div className="relative h-24 w-24 flex-shrink-0">                  <ResponsiveContainer width="100%" height="100%">                     <PieChart>                        <Pie                           data={data}                           innerRadius={30}                           outerRadius={42}                           paddingAngle={2}                           dataKey="value"                           stroke="none"                        >                           {data.map((entry, index) => (                              <Cell key={`cell-${index}`} fill={entry.color} />                           ))}                        </Pie>                     </PieChart>                  </ResponsiveContainer>                  <div className="absolute inset-0 flex flex-col items-center justify-center">                     <span className="text-xl font-bold text-foreground">{totalScans}</span>                     <span className="text-[9px] text-muted-foreground uppercase font-bold">Total</span>                  </div>               </div>               <div className="flex-1 grid grid-cols-2 gap-2">                  {data.map((item, i) => (                     <div key={i} className="flex flex-col p-1.5 rounded-lg bg-muted">                        <div className="flex items-center gap-1 mb-1">                           <div className="w-1.5 h-1.5 rounded-full" style={{ backgroundColor: item.color }} />                           <span className="text-[10px] font-semibold text-muted-foreground uppercase">{item.name}</span>                        </div>                        <span className="text-sm font-bold text-foreground">{item.value}</span>                     </div>                  ))}               </div>            </div>            <div className="mt-2 flex justify-between items-center p-2 bg-blue-50 dark:bg-blue-900/10 rounded-lg border border-blue-100 dark:border-blue-900/30">               <div className="flex items-center gap-2">                  <Zap className="h-4 w-4 text-blue-500" />                  <span className="text-xs font-medium text-blue-700 dark:text-blue-300">{activeScanner}</span>               </div>               <span className="text-[10px] font-bold text-blue-500 bg-card text-card-foreground px-1.5 py-0.5 rounded border border-blue-200 dark:border-blue-800">{activeScannerStatus}</span>            </div>         </div>      </motion.div>   );};

Usage

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

Prop

Type