Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
import { useState } from "react"; | |
import { useCopyToClipboard } from "react-use"; | |
import classNames from "classnames"; | |
import Highlight from "react-highlight"; | |
import { Options } from "redaxios"; | |
import { BiSolidCopy } from "react-icons/bi"; | |
import { ApiRoute } from "@/utils/type"; | |
const LANGUAGES = ["curl", "javascript", "python"]; | |
export const Snippet = ({ | |
endpoint, | |
parameters, | |
body, | |
}: { | |
endpoint: ApiRoute; | |
parameters?: Record<string, any>; | |
body?: Options | undefined; | |
}) => { | |
const [language, setLanguage] = useState<string>(LANGUAGES[0]); | |
const [_, copyToClipboard] = useCopyToClipboard(); | |
const [isCopied, setIsCopied] = useState<boolean>(false); | |
const generateRequestFromEndpoint = () => { | |
const { method, path } = endpoint; | |
const needBody = ["post", "put", "patch", "delete"].includes( | |
method.toLocaleLowerCase() | |
); | |
if (language === "curl") { | |
if (needBody && body) { | |
return ( | |
`curl -X ${method.toLocaleUpperCase()} ${path} \\` + | |
"\n" + | |
` -H "Content-Type: application/json" \\` + | |
"\n" + | |
` -d '${JSON.stringify(body, null, 2)}'` | |
); | |
} | |
if (parameters) { | |
return ( | |
`curl -X ${method.toLocaleUpperCase()} ${path}?` + | |
Object.entries(parameters) | |
.map(([key, value]) => `${key}=${value}`) | |
.join("&") | |
); | |
} | |
return `curl -X ${method.toLocaleUpperCase()} ${path}`; | |
} | |
if (language === "javascript") { | |
if (needBody && body) { | |
return `const response = await fetch("${path}", { | |
method: "${method.toLocaleUpperCase()}", | |
headers: { | |
"Content-Type": "application/json", | |
}, | |
body: JSON.stringify(${JSON.stringify(body, null, 2)}), | |
});`; | |
} | |
if (parameters) { | |
return `const response = await fetch("${path}?${Object.entries( | |
parameters | |
) | |
.map(([key, value]) => `${key}=${value}`) | |
.join("&")}", { | |
method: "${method.toLocaleUpperCase()}", | |
});`; | |
} | |
} | |
if (language === "python") { | |
if (needBody && body) { | |
return `import requests | |
response = requests.${method.toLocaleLowerCase()}("${path}", json=${JSON.stringify( | |
body, | |
null, | |
2 | |
)})`; | |
} | |
if (parameters) { | |
return `import requests | |
response = requests.${method.toLocaleLowerCase()}("${path}", params={ | |
${Object.entries(parameters) | |
.map(([key, value]) => `${key}: ${value}`) | |
.join(",\n ")} | |
})`; | |
} | |
} | |
return ""; | |
}; | |
const handleCopyToClipboard = () => { | |
copyToClipboard(generateRequestFromEndpoint()); | |
setIsCopied(true); | |
setTimeout(() => { | |
setIsCopied(false); | |
}, 2000); | |
}; | |
return ( | |
<div className="mt-8 grid grid-cols-1 gap-4 w-full"> | |
<p className="text-slate-200 uppercase text-xs font-semibold">Snippet</p> | |
<div className="bg-slate-950/50 rounded-xl overflow-hidden"> | |
<ul className="bg-slate-950 flex items-center justify-start"> | |
{LANGUAGES.map((lang, key) => ( | |
<li | |
key={key} | |
className={classNames( | |
"py-4 text-slate-300 text-xs font-semibold px-6 border-r border-slate-900 cursor-pointer hover:bg-slate-900/80 transition-all duration-75", | |
{ | |
"bg-slate-900/50 hover:!bg-slate-900/50": lang === language, | |
} | |
)} | |
onClick={() => setLanguage(lang)} | |
> | |
{lang} | |
</li> | |
))} | |
</ul> | |
<main className="px-6 py-6"> | |
<Highlight | |
className={`${language} text-xs font-code !bg-transparent !p-0 !whitespace-pre-wrap break-all !leading-relaxed`} | |
> | |
{generateRequestFromEndpoint()} | |
</Highlight> | |
<div | |
className="flex justify-end relative" | |
onClick={handleCopyToClipboard} | |
> | |
<BiSolidCopy className="text-slate-500 cursor-pointer hover:text-slate-300 transition-all duration-75" /> | |
<div | |
className={classNames( | |
"bg-indigo-500/60 text-slate-100 text-xs font-semibold absolute bottom-0 right-0 z-10 rounded-lg px-2 py-1 pointer-events-none -translate-y-full transition-all duration-200", | |
{ | |
"opacity-0": !isCopied, | |
} | |
)} | |
> | |
Copied! | |
</div> | |
</div> | |
</main> | |
</div> | |
</div> | |
); | |
}; | |