73 lines · 2.8 KB · TypeScript
RawDownload
import type {  ApprovalRequestId,  ProviderApprovalDecision,  ProviderApprovalOption,} from "@t3tools/contracts";import { Pressable, View } from "react-native"; import { AppText as Text } from "../../components/AppText";import type { PendingApproval } from "../../lib/threadActivity"; export interface PendingApprovalCardProps {  readonly approval: PendingApproval;  readonly respondingApprovalId: ApprovalRequestId | null;  readonly onRespond: (    requestId: ApprovalRequestId,    decision: ProviderApprovalDecision,  ) => Promise<unknown>;} const DEFAULT_APPROVAL_OPTIONS = [  { decision: "accept", label: "Allow once" },  { decision: "acceptForSession", label: "Allow session" },  { decision: "decline", label: "Decline" },] satisfies ReadonlyArray<ProviderApprovalOption>; export function PendingApprovalCard(props: PendingApprovalCardProps) {  const options = props.approval.options ?? DEFAULT_APPROVAL_OPTIONS;  // Opaque for the same reason as PendingUserInputCard: nothing blurs the feed  // behind this card, so a translucent surface bleeds messages through it.  return (    <View className="gap-2.5 rounded-[20px] border border-adaptive-neutral-200-white-a6 bg-adaptive-neutral-100-900 p-4">      <Text className="font-t3-bold text-2xs uppercase tracking-[1.1px] text-adaptive-sky-700-300">        Approval needed      </Text>      <Text className="font-t3-bold text-lg text-adaptive-neutral-950-50">        {props.approval.appName ?? props.approval.requestKind}      </Text>      {props.approval.detail ? (        <Text className="font-sans text-sm leading-normal text-adaptive-neutral-600-400">          {props.approval.detail}        </Text>      ) : null}      <View className="flex-row flex-wrap gap-2.5">        {options.map((option) => (          <Pressable            key={option.decision}            className={`items-center justify-center rounded-[14px] px-3.5 py-3 ${              option.decision === "accept"                ? "bg-blue-500"                : option.decision === "decline"                  ? "bg-adaptive-rose-100-500-a18"                  : "bg-adaptive-neutral-200-800"            }`}            disabled={props.respondingApprovalId === props.approval.requestId}            onPress={() => void props.onRespond(props.approval.requestId, option.decision)}          >            <Text              className={`text-sm ${                option.decision === "accept"                  ? "font-t3-extrabold text-white"                  : option.decision === "decline"                    ? "font-t3-bold text-adaptive-rose-700-300"                    : "font-t3-bold text-adaptive-neutral-950-50"              }`}            >              {option.label}            </Text>          </Pressable>        ))}      </View>    </View>  );}