mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-14 21:59:30 +02:00
feat(inbox): add one-click Done button to inbox items
Add a hover-visible "Mark as done" button (CircleCheck icon) to each inbox item that has an associated issue not yet in done/cancelled status. Clicking it sets the issue status to "done" and archives the inbox item in one action, replacing the previous multi-step flow of opening the issue detail sidebar to change status.
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
import { StatusIcon } from "../../issues/components";
|
||||
import { ActorAvatar } from "../../common/actor-avatar";
|
||||
import { Archive } from "lucide-react";
|
||||
import { Archive, CircleCheck } from "lucide-react";
|
||||
import type { InboxItem } from "@multica/core/types";
|
||||
import { InboxDetailLabel } from "./inbox-detail-label";
|
||||
import { getInboxDisplayTitle } from "./inbox-display";
|
||||
@@ -25,11 +25,13 @@ export function InboxListItem({
|
||||
isSelected,
|
||||
onClick,
|
||||
onArchive,
|
||||
onDone,
|
||||
}: {
|
||||
item: InboxItem;
|
||||
isSelected: boolean;
|
||||
onClick: () => void;
|
||||
onArchive: () => void;
|
||||
onDone?: () => void;
|
||||
}) {
|
||||
const displayTitle = getInboxDisplayTitle(item);
|
||||
|
||||
@@ -59,6 +61,26 @@ export function InboxListItem({
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex shrink-0 items-center gap-1">
|
||||
{onDone && (
|
||||
<span
|
||||
role="button"
|
||||
tabIndex={-1}
|
||||
title="Mark as done"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
onDone();
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Enter" || e.key === " ") {
|
||||
e.stopPropagation();
|
||||
onDone();
|
||||
}
|
||||
}}
|
||||
className="hidden rounded p-0.5 text-muted-foreground hover:bg-accent hover:text-info group-hover:inline-flex"
|
||||
>
|
||||
<CircleCheck className="h-3.5 w-3.5" />
|
||||
</span>
|
||||
)}
|
||||
<span
|
||||
role="button"
|
||||
tabIndex={-1}
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
useArchiveAllReadInbox,
|
||||
useArchiveCompletedInbox,
|
||||
} from "@multica/core/inbox/mutations";
|
||||
import { useUpdateIssue } from "@multica/core/issues/mutations";
|
||||
import { IssueDetail } from "../../issues/components";
|
||||
import { useNavigation } from "../../navigation";
|
||||
import { toast } from "sonner";
|
||||
@@ -117,6 +118,7 @@ export function InboxPage() {
|
||||
const archiveAllMutation = useArchiveAllInbox();
|
||||
const archiveAllReadMutation = useArchiveAllReadInbox();
|
||||
const archiveCompletedMutation = useArchiveCompletedInbox();
|
||||
const updateIssueMutation = useUpdateIssue();
|
||||
|
||||
// Auto-mark-read whenever a selected item is unread — covers both click-
|
||||
// to-select and URL-param-select (e.g. OS notification click on desktop).
|
||||
@@ -145,6 +147,18 @@ export function InboxPage() {
|
||||
});
|
||||
};
|
||||
|
||||
const handleDone = (item: InboxItem) => {
|
||||
if (!item.issue_id) return;
|
||||
setSelectedKey("");
|
||||
updateIssueMutation.mutate(
|
||||
{ id: item.issue_id, status: "done" },
|
||||
{ onError: () => toast.error("Failed to mark as done") },
|
||||
);
|
||||
archiveMutation.mutate(item.id, {
|
||||
onError: () => toast.error("Failed to archive"),
|
||||
});
|
||||
};
|
||||
|
||||
// Batch operations
|
||||
const handleMarkAllRead = () => {
|
||||
markAllReadMutation.mutate(undefined, {
|
||||
@@ -235,6 +249,11 @@ export function InboxPage() {
|
||||
isSelected={(item.issue_id ?? item.id) === selectedKey}
|
||||
onClick={() => handleSelect(item)}
|
||||
onArchive={() => handleArchive(item.id)}
|
||||
onDone={
|
||||
item.issue_id && item.issue_status !== "done" && item.issue_status !== "cancelled"
|
||||
? () => handleDone(item)
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user