Files
kandev/apps/web/components/task/chat/messages/permission-request-message.tsx
T

110 lines
3.4 KiB
TypeScript

"use client";
import { IconAlertTriangle, IconCheck, IconX } from "@tabler/icons-react";
import { cn } from "@/lib/utils";
import type { Message } from "@/lib/types/http";
import { PermissionActionRow } from "./permission-action-row";
import { summarizePermissionAction } from "./permission-action-summary";
import {
parsePermission,
usePermissionResponseHandlers,
type PermissionRequestMetadata,
} from "./use-permission-handlers";
function getPermissionStatusBadge(status: PermissionRequestMetadata["status"]) {
switch (status) {
case "approved":
return (
<span className="inline-flex items-center gap-1 text-xs text-green-600 dark:text-green-400">
<IconCheck className="h-3 w-3" /> Approved
</span>
);
case "rejected":
return (
<span className="inline-flex items-center gap-1 text-xs text-red-600 dark:text-red-400">
<IconX className="h-3 w-3" /> Rejected
</span>
);
case "expired":
return (
<span className="inline-flex items-center gap-1 text-xs text-muted-foreground">
Expired
</span>
);
default:
return (
<span className="inline-flex items-center gap-1 text-xs text-amber-600 dark:text-amber-400">
Pending Approval
</span>
);
}
}
type PermissionRequestMessageProps = {
comment: Message;
};
export function PermissionRequestMessage({ comment }: PermissionRequestMessageProps) {
const { permissionMetadata, permissionStatus, isPermissionPending } = parsePermission(comment);
const { isResponding, handleApprove, handleAllowAlways, hasAllowAlways, handleReject } =
usePermissionResponseHandlers({
permissionMetadata,
permissionMessage: comment,
});
const statusBadge = getPermissionStatusBadge(permissionStatus);
const titleText = comment.content || "Permission Required";
const detailSummary = summarizePermissionAction(permissionMetadata?.action_details, titleText);
return (
<div className="w-full">
<div className="flex items-start gap-3 w-full">
<div className="flex-shrink-0 mt-0.5">
<IconAlertTriangle
className={cn(
"h-4 w-4",
isPermissionPending ? "text-amber-600 dark:text-amber-400" : "text-muted-foreground",
)}
/>
</div>
<div className="flex-1 min-w-0 pt-0.5">
<div className="flex items-center gap-2 text-xs">
<span
className={cn(
"font-mono text-xs",
isPermissionPending
? "text-amber-600 dark:text-amber-400"
: "text-muted-foreground",
)}
>
{titleText}
</span>
{statusBadge}
</div>
{detailSummary && (
<div
className="mt-1 font-mono text-xs text-muted-foreground break-all"
data-testid="permission-action-detail"
>
{detailSummary}
</div>
)}
{isPermissionPending && (
<div className="mt-2">
<PermissionActionRow
onApprove={handleApprove}
onReject={handleReject}
onAllowAlways={hasAllowAlways ? handleAllowAlways : undefined}
isResponding={isResponding}
/>
</div>
)}
</div>
</div>
</div>
);
}