enzostvs's picture
enzostvs HF Staff
rework snippet card
f480cae
raw
history blame
4.5 kB
import { useState } from "react";
import { useCopyToClipboard } from "react-use";
import classNames from "classnames";
import Highlight from "react-highlight";
import { Options } from "redaxios";
import {
BiSolidCopy,
BiLogoJavascript,
BiLogoPython,
BiCodeCurly,
} from "react-icons/bi";
import { ApiRoute } from "@/utils/type";
const LANGUAGES = [
{
value: "curl",
icon: <BiCodeCurly className=" text-xl text-slate-300" />,
},
{
value: "javascript",
icon: <BiLogoJavascript className=" text-xl text-yellow-500" />,
},
{
value: "python",
icon: <BiLogoPython className=" text-xl text-blue-500" />,
},
];
export const Snippet = ({
endpoint,
parameters,
body,
}: {
endpoint: ApiRoute;
parameters?: Record<string, any>;
body?: Options | undefined;
}) => {
const [_, copyToClipboard] = useCopyToClipboard();
const [isCopied, setIsCopied] = useState<boolean>(false);
const generateRequestFromEndpoint = (language: string) => {
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 = (language: string) => {
copyToClipboard(generateRequestFromEndpoint(language));
setIsCopied(true);
setTimeout(() => {
setIsCopied(false);
}, 2000);
};
return (
<div className="mt-8 grid grid-cols-1 gap-4 w-full">
{LANGUAGES.map((lang, key) => (
<div key={key} className="bg-slate-950/50 rounded-xl overflow-hidden">
<header className="bg-slate-950 flex items-center justify-start px-5 py-4 uppercase gap-2">
{lang.icon}
<p className="text-slate-300 text-xs font-semibold">{lang.value}</p>
</header>
<main className="px-6 py-6">
<Highlight
className={`${lang.value} text-xs font-code !bg-transparent !p-0 !whitespace-pre-wrap break-all !leading-relaxed`}
>
{generateRequestFromEndpoint(lang.value)}
</Highlight>
<div
className="flex justify-end relative"
onClick={() => handleCopyToClipboard(lang.value)}
>
<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>
);
};