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
53 changes: 53 additions & 0 deletions components/project/activity/action-icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { ActivityIcon, Plus, RefreshCw, Trash2 } from "lucide-react";
import { cn } from "@/lib/utils";

function CreatedIcon({ className }: { className?: string }) {
return (
<div className={cn("rounded-lg shrink-0 p-1.5 bg-emerald-500/10", className)}>
<Plus className="h-4 w-4 text-emerald-500" />
</div>
);
}

function UpdatedIcon({ className }: { className?: string }) {
return (
<div className={cn("rounded-lg shrink-0 p-1.5 bg-amber-500/10", className)}>
<RefreshCw className="h-4 w-4 text-amber-500" />
</div>
);
}

function DeletedIcon({ className }: { className?: string }) {
return (
<div className={cn("rounded-lg shrink-0 p-1.5 bg-red-500/10", className)}>
<Trash2 className="h-4 w-4 text-red-500" />
</div>
);
}

function DefaultIcon({ className }: { className?: string }) {
return (
<div className={cn("rounded-lg shrink-0 p-1.5 bg-muted", className)}>
<ActivityIcon className="h-4 w-4 text-muted-foreground" />
</div>
);
}

export function ActionIcon({
action,
className,
}: {
action: string;
className?: string;
}) {
switch (action) {
case "created":
return <CreatedIcon className={className} />;
case "updated":
return <UpdatedIcon className={className} />;
case "deleted":
return <DeletedIcon className={className} />;
default:
return <DefaultIcon className={className} />;
}
}
19 changes: 3 additions & 16 deletions components/project/activity/activity-detail-panel.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,18 @@
"use client";

import { useQuery } from "@tanstack/react-query";
import {
CalendarIcon,
CompassIcon,
RefreshCw,
UserIcon,
X,
} from "lucide-react";
import { CalendarIcon, CompassIcon, UserIcon, X } from "lucide-react";
import { useParams } from "next/navigation";
import { Panel } from "@/components/core/panel";
import { UserAvatar } from "@/components/core/user-avatar";
import { SpinnerWithSpacing } from "@/components/core/loaders";
import {
formatEventTypeLabel,
getActionIcon,
getEventDescription,
} from "@/lib/activity/message";
import { guessTimezone, toFullDateTimeString } from "@/lib/utils/date";
import { useTRPCClient } from "@/trpc/client";
import { ActionIcon } from "./action-icon";

function SectionLabel({
icon: Icon,
Expand Down Expand Up @@ -64,9 +58,6 @@ export function ActivityDetailPanel({
}),
});

const actionConfig = item ? getActionIcon(item.action) : null;
const ActionIcon = actionConfig?.icon ?? RefreshCw;

return (
<Panel
open={true}
Expand All @@ -87,11 +78,7 @@ export function ActivityDetailPanel({
<>
<div className="flex items-start justify-between p-4 border-b">
<div className="flex items-start gap-3">
<div className={`p-2 rounded-lg ${actionConfig?.bg}`}>
<ActionIcon
className={`h-5 w-5 ${actionConfig?.color}`}
/>
</div>
<ActionIcon action={item.action} />
<div>
<h2 className="font-semibold text-lg">
{formatEventTypeLabel(item.type, item.action)}
Expand Down
11 changes: 2 additions & 9 deletions components/project/activity/activity-feed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ import type { ActivityWithActor } from "@/drizzle/types";
import {
formatEventTypeLabel,
generateObjectDiffMessage,
getActionIcon,
} from "@/lib/activity/message";
import { guessTimezone, toDateTimeString } from "@/lib/utils/date";
import { useTRPCClient } from "@/trpc/client";
import { ActionIcon } from "./action-icon";
import { ActivityDetailPanel } from "./activity-detail-panel";

const ACTIVITIES_LIMIT = 25;
Expand All @@ -25,21 +25,14 @@ export function ActivityItem({
item,
onSelect,
}: { item: ActivityWithActor; onSelect: (id: number) => void }) {
const actionConfig = getActionIcon(item.action);
const ActionIcon = actionConfig.icon;

return (
<button
type="button"
onClick={() => onSelect(item.id)}
className="w-full text-left py-4 px-4 hover:bg-muted/40 rounded-lg transition-colors cursor-pointer"
>
<div className="flex items-start gap-3">
<div
className={`p-1.5 rounded-lg ${actionConfig.bg} mt-0.5 shrink-0`}
>
<ActionIcon className={`h-4 w-4 ${actionConfig.color}`} />
</div>
<ActionIcon action={item.action} className="mt-0.5" />

<div className="flex-1 min-w-0">
<div className="flex items-center justify-between gap-2">
Expand Down
14 changes: 0 additions & 14 deletions lib/activity/message.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,6 @@
import { ActivityIcon, Plus, RefreshCw, Trash2 } from "lucide-react";
import type { ActivityWithActor } from "@/drizzle/types";
import { guessTimezone, toDateStringWithDay } from "../utils/date";

export function getActionIcon(action: string) {
switch (action) {
case "created":
return { icon: Plus, color: "text-emerald-500", bg: "bg-emerald-500/10" };
case "updated":
return { icon: RefreshCw, color: "text-amber-500", bg: "bg-amber-500/10" };
case "deleted":
return { icon: Trash2, color: "text-red-500", bg: "bg-red-500/10" };
default:
return { icon: ActivityIcon, color: "text-muted-foreground", bg: "bg-muted" };
}
}

// biome-ignore lint/suspicious/noExplicitAny: flexible date parameter handling
function toDateString(date: any) {
if (!date) {
Expand Down
Loading