Files
stats/apps/public/components/flow-step.tsx
Carl-Gerhard Lindesvärd 790801b728 feat: revenue tracking
* wip

* wip

* wip

* wip

* show revenue better on overview

* align realtime and overview counters

* update revenue docs

* always return device id

* add project settings, improve projects charts,

* fix: comments

* fixes

* fix migration

* ignore sql files

* fix comments
2025-11-19 14:27:34 +01:00

80 lines
2.2 KiB
TypeScript

import { CheckCircle, CreditCard, Globe, Server, User } from 'lucide-react';
import type { ReactNode } from 'react';
interface FlowStepProps {
step: number;
actor: string;
description: string;
children?: ReactNode;
icon?: 'visitor' | 'website' | 'backend' | 'payment' | 'success';
isLast?: boolean;
}
const iconMap = {
visitor: User,
website: Globe,
backend: Server,
payment: CreditCard,
success: CheckCircle,
};
const iconColorMap = {
visitor: 'text-blue-500',
website: 'text-green-500',
backend: 'text-purple-500',
payment: 'text-yellow-500',
success: 'text-green-600',
};
const iconBorderColorMap = {
visitor: 'border-blue-500',
website: 'border-green-500',
backend: 'border-purple-500',
payment: 'border-yellow-500',
success: 'border-green-600',
};
export function FlowStep({
step,
actor,
description,
children,
icon = 'visitor',
isLast = false,
}: FlowStepProps) {
const Icon = iconMap[icon];
return (
<div className="relative flex gap-4 mb-4 min-w-0">
{/* Step number and icon */}
<div className="flex flex-col items-center flex-shrink-0">
<div className="relative z-10 bg-background">
<div className="flex items-center justify-center size-10 rounded-full bg-primary text-primary-foreground font-semibold text-sm shadow-sm">
{step}
</div>
<div
className={`absolute -bottom-2 -right-2 flex items-center justify-center w-6 h-6 rounded-full bg-background border shadow-sm ${iconBorderColorMap[icon] || 'border-primary'}`}
>
<Icon
className={`size-3.5 ${iconColorMap[icon] || 'text-primary'}`}
/>
</div>
</div>
{/* Connector line - extends from badge through content to next step */}
{!isLast && (
<div className="w-0.5 bg-border mt-2 flex-1 min-h-[2rem]" />
)}
</div>
{/* Content */}
<div className="flex-1 pt-1 min-w-0">
<div className="mb-2">
<span className="font-semibold text-foreground mr-2">{actor}:</span>{' '}
<span className="text-muted-foreground">{description}</span>
</div>
{children && <div className="mt-3 min-w-0">{children}</div>}
</div>
</div>
);
}