"use client" import * as DialogPrimitive from "@radix-ui/react-dialog" import { useMutation, useQueryClient } from "@tanstack/react-query" import { Loader2, X } from "lucide-react" import { useEffect, useState } from "react" import { toast } from "sonner" import { $fetch } from "@lib/api" import { cn } from "@lib/utils" import { Dialog, DialogContent, DialogTitle } from "@ui/components/dialog" import { Granola } from "@ui/assets/icons" import { dmSans125ClassName } from "@/lib/fonts" import { INSET } from "./integrations/install-steps" function GranolaIconBox() { return (
) } export function GranolaConnectModal({ open, onOpenChange, containerTags, onSuccess, }: { open: boolean onOpenChange: (open: boolean) => void containerTags?: string[] onSuccess?: () => void }) { const queryClient = useQueryClient() const [apiKey, setApiKey] = useState("") const [errorMessage, setErrorMessage] = useState(null) // Reset form whenever the modal opens. useEffect(() => { if (open) { setApiKey("") setErrorMessage(null) } }, [open]) const connectMutation = useMutation({ mutationFn: async (key: string) => { const response = await $fetch("@post/connections/:provider", { params: { provider: "granola" }, body: { containerTags, metadata: { apiKey: key }, }, }) if (response.error) { const msg = (response.error as { message?: string })?.message || "Failed to connect" throw new Error(msg) } return response.data }, onSuccess: () => { toast.success("Granola connected") queryClient.invalidateQueries({ queryKey: ["connections"] }) onSuccess?.() onOpenChange(false) }, onError: (error) => { setErrorMessage( error instanceof Error ? error.message : "Failed to connect", ) }, }) const trimmedKey = apiKey.trim() const canConnect = trimmedKey.length > 0 && !connectMutation.isPending const handleConnect = () => { setErrorMessage(null) connectMutation.mutate(trimmedKey) } return ( Connect Granola

Connect Granola

Paste your API key to sync meeting notes.

{ setApiKey(e.target.value) if (errorMessage) setErrorMessage(null) }} onKeyDown={(e) => { if (e.key === "Enter" && canConnect) handleConnect() }} placeholder="grn_..." className={cn( dmSans125ClassName(), "w-full rounded-[10px] bg-[#0D121A] px-3 py-2.5 text-[13px] text-[#FAFAFA] placeholder:text-[#52525B] outline-none border border-white/[0.06] focus:border-white/[0.16]", )} />

Create one in Granola → Settings → Connectors → API keys. Requires a Business or Enterprise plan.

{errorMessage && (

{errorMessage}

)}
) }