Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 17 additions & 14 deletions src/app/member/member-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ type Member = RouterOutputs["organization"]["getMembers"][number];
type DashboardCharts = RouterOutputs["dashboard"]["getDashboardCharts"];
type Role = RouterOutputs["role"]["getByUser"][number];

const CHART_HEIGHT = "h-[280px]";

interface MemberCardProps {
member: Member;
dashboardCharts: DashboardCharts;
Expand Down Expand Up @@ -172,17 +174,17 @@ export function MemberCard({ member, dashboardCharts }: MemberCardProps) {
</div>

{uniqueTeams.length > 0 && (
<div className="space-y-1.5">
<div className="text-muted-foreground flex items-center gap-1.5">
<div className="mt-1 space-y-1.5">
<div className="text-foreground flex items-center gap-1.5">
<LayoutGrid className="h-3.5 w-3.5" />
<span className="text-xs font-medium">Teams</span>
<span className="text-sm font-semibold">Teams</span>
</div>
<ul className="space-y-1 pl-5">
{uniqueTeams.map((team) => (
<li key={team.id}>
<Link
href={`/teams/${team.id}`}
className="hover:text-primary text-sm font-medium underline-offset-2 transition-colors hover:underline"
className="text-muted-foreground hover:text-primary text-xs underline-offset-2 transition-colors hover:underline"
>
{team.name}
</Link>
Expand Down Expand Up @@ -211,13 +213,13 @@ export function MemberCard({ member, dashboardCharts }: MemberCardProps) {
<div className="grid flex-1 grid-cols-1 gap-4 md:grid-cols-2">
{isLoading ? (
<>
<Skeleton className="h-[320px] w-full" />
<Skeleton className="h-[320px] w-full" />
<Skeleton className={`${CHART_HEIGHT} w-full`} />
<Skeleton className={`${CHART_HEIGHT} w-full`} />
</>
) : (
<>
<div className="border-border/40 flex h-[340px] flex-col rounded-lg border p-4">
<span className="text-muted-foreground mb-2 text-xs font-semibold tracking-wider uppercase">
<div className={`flex ${CHART_HEIGHT} flex-col`}>
<span className="text-muted-foreground mb-1 text-xs font-semibold tracking-wider uppercase">
Effort Distribution
</span>
{rolesWithEffort.length > 0 ? (
Expand All @@ -232,7 +234,7 @@ export function MemberCard({ member, dashboardCharts }: MemberCardProps) {
value: totalEffortPoints,
label: "Total",
}}
className="h-[260px] w-full"
className="h-full w-full"
/>
) : (
<div className="text-muted-foreground flex flex-1 items-center justify-center text-sm">
Expand All @@ -245,7 +247,8 @@ export function MemberCard({ member, dashboardCharts }: MemberCardProps) {
metricIds={metricIdsWithGoals}
showHeader={false}
simpleLegend={true}
className="h-[340px] rounded-lg"
className={CHART_HEIGHT}
noBorder={true}
/>
</>
)}
Expand All @@ -257,19 +260,19 @@ export function MemberCard({ member, dashboardCharts }: MemberCardProps) {
<Collapsible open={isExpanded} onOpenChange={setIsExpanded}>
<CollapsibleTrigger asChild>
<Button
variant="outline"
variant={isExpanded ? "outline" : "secondary"}
size="sm"
className="text-muted-foreground hover:text-foreground mt-4 w-full justify-center gap-2"
className="mt-4 w-full justify-center gap-2"
>
{isExpanded ? (
<>
<ChevronUp className="h-4 w-4" />
<span className="text-xs font-medium">Hide Roles & KPIs</span>
<span className="text-sm font-medium">Hide Roles & KPIs</span>
</>
) : (
<>
<ChevronDown className="h-4 w-4" />
<span className="text-xs font-medium">Show Roles & KPIs</span>
<span className="text-sm font-medium">Show Roles & KPIs</span>
</>
)}
</Button>
Expand Down
51 changes: 34 additions & 17 deletions src/components/charts/goals-bar-chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
TrendingDown,
TrendingUp,
} from "lucide-react";
import { Bar, BarChart, Cell, XAxis, YAxis } from "recharts";
import { Bar, BarChart, CartesianGrid, Cell, XAxis, YAxis } from "recharts";

import { Badge } from "@/components/ui/badge";
import {
Expand All @@ -35,10 +35,13 @@ import { api } from "@/trpc/react";
interface GoalsBarChartProps {
/** Array of metric IDs to display goal progress for */
metricIds: string[];
/** Show header with title and goal count (default: true) */
showHeader?: boolean;
className?: string;
/** Use simplified legend with only colored dots and names (no status badges, percentages, or tooltips) */
/** Use simplified legend with only colored dots and names (default: false) */
simpleLegend?: boolean;
/** Remove border and background styling (default: false) */
noBorder?: boolean;
}

const STATUS_CONFIG: Record<
Expand Down Expand Up @@ -119,10 +122,10 @@ function formatTimeRemaining(
}

const STATUS_COLORS = {
exceeded: "hsl(142, 76%, 36%)",
onTrack: "hsl(217, 91%, 60%)",
behind: "hsl(38, 92%, 50%)",
atRisk: "hsl(0, 84%, 60%)",
exceeded: "#22c55e", // green-500
onTrack: "#3b82f6", // blue-500
behind: "#f59e0b", // amber-500
atRisk: "#ef4444", // red-500
} as const;

function getBarColor(progress: number, expectedProgress: number): string {
Expand Down Expand Up @@ -291,6 +294,7 @@ export function GoalsBarChart({
showHeader = true,
className,
simpleLegend = false,
noBorder = false,
}: GoalsBarChartProps) {
// Fetch dashboard charts from cache (parent already fetched this)
const { data: allCharts } = api.dashboard.getDashboardCharts.useQuery();
Expand Down Expand Up @@ -334,7 +338,8 @@ export function GoalsBarChart({
return (
<div
className={cn(
"border-border/60 bg-card flex flex-col border",
"flex flex-col",
!noBorder && "border-border/60 bg-card border",
className,
)}
>
Expand Down Expand Up @@ -366,7 +371,11 @@ export function GoalsBarChart({

return (
<div
className={cn("border-border/60 bg-card flex flex-col border", className)}
className={cn(
"flex flex-col",
!noBorder && "border-border/60 bg-card border",
className,
)}
>
{showHeader && (
<div className="border-border/60 flex items-center justify-between border-b px-4 py-3">
Expand All @@ -383,20 +392,28 @@ export function GoalsBarChart({
</span>
</div>
)}
<div className="flex flex-1 flex-col p-4">
<ChartContainer
config={chartConfig}
className="mx-auto h-[220px] w-full"
>
<div className={cn("flex flex-1 flex-col", !noBorder && "p-4")}>
{noBorder && (
<span className="text-muted-foreground mb-1 text-xs font-semibold tracking-wider uppercase">
Goal Progress
</span>
)}
<ChartContainer config={chartConfig} className="mx-auto h-full w-full">
<BarChart
data={chartData}
margin={{
top: 20,
right: 20,
top: 10,
right: 10,
left: 0,
bottom: simpleLegend ? 10 : 60,
bottom: simpleLegend ? 5 : 60,
}}
>
<CartesianGrid
strokeDasharray="3 3"
vertical={false}
stroke="hsl(var(--border))"
strokeOpacity={0.5}
/>
<XAxis
dataKey="goal"
tick={
Expand Down Expand Up @@ -442,7 +459,7 @@ export function GoalsBarChart({
</ChartContainer>

{simpleLegend ? (
<div className="border-border/40 mt-4 flex flex-wrap justify-center gap-3 border-t pt-3">
<div className="mt-2 flex flex-wrap justify-center gap-3">
{chartData.map((item) => (
<div key={item.goal} className="flex items-center gap-1.5">
<div
Expand Down
10 changes: 5 additions & 5 deletions src/components/charts/pie-chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export function MetricPieChart({
return (
<ChartContainer
config={chartConfig}
className={cn("mx-auto h-[250px] w-full", className)}
className={cn("mx-auto h-full w-full", className)}
>
<PieChart>
{showTooltip && (
Expand All @@ -41,8 +41,8 @@ export function MetricPieChart({
data={chartData}
dataKey={dataKey}
nameKey={xAxisKey}
innerRadius="40%"
outerRadius="70%"
innerRadius="50%"
outerRadius="85%"
strokeWidth={2}
isAnimationActive={true}
animationDuration={800}
Expand Down Expand Up @@ -92,8 +92,8 @@ export function MetricPieChart({
<ChartLegend
content={<ChartLegendContent nameKey={xAxisKey} />}
wrapperStyle={{
paddingTop: 8,
maxHeight: "80px",
paddingTop: 4,
maxHeight: "60px",
overflowY: "auto",
}}
/>
Expand Down