- Updated various components to use consistent color tokens, improving visual coherence. - Refactored layout components to utilize the new PublicShell for better structure. - Enhanced error and status messaging styles for improved user feedback. - Standardized button usage across forms and modals for a unified interaction experience. - Introduced new UI design tokens and guidelines in documentation to support future development.
77 lines
2.3 KiB
TypeScript
77 lines
2.3 KiB
TypeScript
"use client";
|
|
|
|
import type { ComponentType, SVGProps } from "react";
|
|
import {
|
|
DocumentTextIcon,
|
|
CheckCircleIcon,
|
|
ServerIcon,
|
|
ChatBubbleLeftRightIcon,
|
|
ExclamationTriangleIcon,
|
|
} from "@heroicons/react/24/outline";
|
|
import type { Activity } from "@customer-portal/domain/dashboard";
|
|
import {
|
|
formatActivityDate,
|
|
formatActivityDescription,
|
|
getActivityIconGradient,
|
|
} from "../utils/dashboard.utils";
|
|
|
|
interface DashboardActivityItemProps {
|
|
activity: Activity;
|
|
onClick?: () => void;
|
|
}
|
|
|
|
const ICON_COMPONENTS: Record<Activity["type"], ComponentType<SVGProps<SVGSVGElement>>> = {
|
|
invoice_created: DocumentTextIcon,
|
|
invoice_paid: CheckCircleIcon,
|
|
service_activated: ServerIcon,
|
|
case_created: ChatBubbleLeftRightIcon,
|
|
case_closed: CheckCircleIcon,
|
|
};
|
|
|
|
const FALLBACK_ICON = ExclamationTriangleIcon;
|
|
|
|
export function DashboardActivityItem({ activity, onClick }: DashboardActivityItemProps) {
|
|
const Icon = ICON_COMPONENTS[activity.type] ?? FALLBACK_ICON;
|
|
const gradient = getActivityIconGradient(activity.type);
|
|
const description = formatActivityDescription(activity);
|
|
const formattedDate = formatActivityDate(activity.date);
|
|
|
|
const content = (
|
|
<>
|
|
<div className="flex-shrink-0">
|
|
<div
|
|
className={`w-10 h-10 rounded-full bg-gradient-to-r ${gradient} flex items-center justify-center shadow-[var(--cp-shadow-1)]`}
|
|
>
|
|
<Icon className="h-5 w-5 text-white" />
|
|
</div>
|
|
</div>
|
|
<div className="flex-1 min-w-0">
|
|
<p
|
|
className={[
|
|
"text-sm font-medium",
|
|
onClick ? "text-foreground group-hover:text-primary" : "text-foreground",
|
|
].join(" ")}
|
|
>
|
|
{activity.title}
|
|
</p>
|
|
<p className="text-sm text-muted-foreground mt-1">{description}</p>
|
|
<p className="text-xs text-muted-foreground/70 mt-2">{formattedDate}</p>
|
|
</div>
|
|
</>
|
|
);
|
|
|
|
if (onClick) {
|
|
return (
|
|
<button
|
|
type="button"
|
|
className="group flex items-start space-x-4 w-full text-left p-3 -m-3 rounded-lg hover:bg-muted transition-colors duration-[var(--cp-duration-normal)] cursor-pointer"
|
|
onClick={onClick}
|
|
>
|
|
{content}
|
|
</button>
|
|
);
|
|
}
|
|
|
|
return <div className="flex items-start space-x-4 w-full text-left">{content}</div>;
|
|
}
|