4 changed files with 93 additions and 7 deletions
@ -0,0 +1,57 @@
@@ -0,0 +1,57 @@
|
||||
import { Icon, Icons } from "@/components/Icon"; |
||||
|
||||
interface StatusCircle { |
||||
type: "loading" | "done" | "error" | "pending" | "noresult"; |
||||
} |
||||
|
||||
interface StatusCircleLoading extends StatusCircle { |
||||
type: "loading"; |
||||
percentage: number; |
||||
} |
||||
|
||||
function statusIsLoading( |
||||
props: StatusCircle | StatusCircleLoading |
||||
): props is StatusCircleLoading { |
||||
return props.type === "loading"; |
||||
} |
||||
|
||||
export function StatusCircle(props: StatusCircle | StatusCircleLoading) { |
||||
let classes = ""; |
||||
if (props.type === "loading") classes = "text-video-scraping-loading"; |
||||
if (props.type === "noresult") |
||||
classes = "text-video-scraping-noresult text-opacity-50"; |
||||
if (props.type === "error") |
||||
classes = "text-video-scraping-error bg-video-scraping-error"; |
||||
|
||||
return ( |
||||
<div |
||||
className={[ |
||||
"p-0.5 border-current border-2 rounded-full h-6 w-6 relative", |
||||
classes || "", |
||||
].join(" ")} |
||||
> |
||||
<svg |
||||
width="100%" |
||||
height="100%" |
||||
viewBox="0 0 64 64" |
||||
xmlns="http://www.w3.org/2000/svg" |
||||
className="rounded-full -rotate-90" |
||||
> |
||||
{statusIsLoading(props) ? ( |
||||
<circle |
||||
strokeWidth="32" |
||||
strokeDasharray={`${props.percentage} 100`} |
||||
r="25%" |
||||
cx="50%" |
||||
cy="50%" |
||||
fill="transparent" |
||||
stroke="currentColor" |
||||
/> |
||||
) : null} |
||||
</svg> |
||||
{props.type === "error" ? ( |
||||
<Icon className="absolute inset-0 text-white" icon={Icons.X} /> |
||||
) : null} |
||||
</div> |
||||
); |
||||
} |
Loading…
Reference in new issue