Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | 'use client'; /** * DevStatsCards - Dashboard statistics overview cards */ import React from 'react'; import { Icon } from '@/components/ui/icons'; import { IconName } from '@/components/ui/icons/registry'; interface OverviewStats { totalTickets: number; openTickets: number; inProgressTickets: number; inReviewTickets: number; testingTickets: number; blockedTickets: number; completedThisWeek: number; createdThisWeek: number; overdueTickets: number; unassignedTickets: number; activeSprintsCount: number; hoursLoggedThisWeek: number; } export interface DevStatsCardsProps { /** Dashboard overview statistics */ stats: OverviewStats; } export default function DevStatsCards({ stats }: DevStatsCardsProps) { const cards: { label: string; value: string | number; icon: IconName; color: string }[] = [ { label: 'Total Tickets', value: stats.totalTickets, icon: 'ticket', color: 'indigo'}, { label: 'Open', value: stats.openTickets, icon: 'clock-circle', color: 'gray'}, { label: 'In Progress', value: stats.inProgressTickets, icon: 'bolt', color: 'blue'}, { label: 'Completed This Week', value: stats.completedThisWeek, icon: 'check-circle-filled', color: 'green'}, { label: 'Overdue', value: stats.overdueTickets, icon: 'warning', color: 'red'}, { label: 'Unassigned', value: stats.unassignedTickets, icon: 'user-circle', color: 'yellow'}, { label: 'Active Sprints', value: stats.activeSprintsCount, icon: 'calendar', color: 'purple'}, { label: 'Hours This Week', value: stats.hoursLoggedThisWeek.toFixed(1), icon: 'clock-circle', color: 'teal'}, ]; const colorStyles: Record<string, { bg: string; text: string; icon: string }> = { indigo: { bg: 'bg-indigo-50 dark:bg-indigo-900/20', text: 'text-indigo-600 dark:text-indigo-400', icon: 'bg-indigo-100 dark:bg-indigo-900/40 text-indigo-600 dark:text-indigo-400'}, gray: { bg: 'bg-gray-50 dark:bg-gray-700', text: 'text-gray-600 dark:text-gray-300', icon: 'bg-gray-100 dark:bg-gray-600 text-gray-600 dark:text-gray-300'}, blue: { bg: 'bg-blue-50 dark:bg-blue-900/20', text: 'text-blue-600 dark:text-blue-400', icon: 'bg-blue-100 dark:bg-blue-900/40 text-blue-600 dark:text-blue-400'}, green: { bg: 'bg-green-50 dark:bg-green-900/20', text: 'text-green-600 dark:text-green-400', icon: 'bg-green-100 dark:bg-green-900/40 text-green-600 dark:text-green-400'}, red: { bg: 'bg-red-50 dark:bg-red-900/20', text: 'text-red-600 dark:text-red-400', icon: 'bg-red-100 dark:bg-red-900/40 text-red-600 dark:text-red-400'}, yellow: { bg: 'bg-yellow-50 dark:bg-yellow-900/20', text: 'text-yellow-600 dark:text-yellow-400', icon: 'bg-yellow-100 dark:bg-yellow-900/40 text-yellow-600 dark:text-yellow-400'}, purple: { bg: 'bg-purple-50 dark:bg-purple-900/20', text: 'text-purple-600 dark:text-purple-400', icon: 'bg-purple-100 dark:bg-purple-900/40 text-purple-600 dark:text-purple-400'}, teal: { bg: 'bg-teal-50 dark:bg-teal-900/20', text: 'text-teal-600 dark:text-teal-400', icon: 'bg-teal-100 dark:bg-teal-900/40 text-teal-600 dark:text-teal-400'}}; return ( <div className="grid grid-cols-2 sm:grid-cols-4 lg:grid-cols-4 gap-4"> {cards.map((card) => { const style = colorStyles[card.color]; return ( <div key={card.label} className={`${style.bg} rounded-lg p-4 border border-gray-200 dark:border-gray-700`} > <div className="flex items-center justify-between"> <div> <p className="text-sm font-medium text-gray-600 dark:text-gray-400">{card.label}</p> <p className={`text-2xl font-bold ${style.text} mt-1`}> {card.value} </p> </div> <div className={`${style.icon} p-2 rounded-full`}> <Icon name={card.icon} size={24} /> </div> </div> </div> ); })} </div> ); } |