7 changed files with 119 additions and 28 deletions
@ -0,0 +1,78 @@
@@ -0,0 +1,78 @@
|
||||
import { Icon, Icons } from "@/components/Icon"; |
||||
import { ScrapeEventLog } from "@/hooks/useScrape"; |
||||
|
||||
interface MediaScrapeLogProps { |
||||
events: ScrapeEventLog[]; |
||||
} |
||||
|
||||
interface MediaScrapePillProps { |
||||
event: ScrapeEventLog; |
||||
} |
||||
|
||||
function MediaScrapePillSkeleton() { |
||||
return <div className="h-9 w-[220px] rounded-full bg-slate-800 opacity-50" />; |
||||
} |
||||
|
||||
function MediaScrapePill({ event }: MediaScrapePillProps) { |
||||
return ( |
||||
<div className="flex h-9 w-[220px] items-center rounded-full bg-slate-800 p-3 text-denim-700"> |
||||
<div className="mr-2"> |
||||
{!event.errored ? ( |
||||
<svg className="h-[18px] w-[18px] -rotate-90" viewBox="0 0 100 100"> |
||||
<circle |
||||
className="fill-transparent stroke-denim-700 stroke-[15] transition-[stroke-dashoffset] duration-150" |
||||
r="40" |
||||
cx="50" |
||||
cy="50" |
||||
style={{ |
||||
strokeDasharray: `${2 * Math.PI * 40} ${2 * Math.PI * 40}`, |
||||
strokeDashoffset: `${ |
||||
2 * Math.PI * 40 - |
||||
(event.percentage / 100) * (2 * Math.PI * 40) |
||||
}`,
|
||||
}} |
||||
/> |
||||
</svg> |
||||
) : ( |
||||
<Icon icon={Icons.X} className="text-[0.85em] text-rose-400" /> |
||||
)} |
||||
</div> |
||||
<div className="flex-1 overflow-hidden"> |
||||
<p |
||||
className={`overflow-hidden text-ellipsis whitespace-nowrap ${ |
||||
event.errored ? "text-rose-400" : "" |
||||
}`}
|
||||
> |
||||
{event.id} |
||||
</p> |
||||
</div> |
||||
</div> |
||||
); |
||||
} |
||||
|
||||
export function MediaScrapeLog(props: MediaScrapeLogProps) { |
||||
return ( |
||||
<div className="relative h-16 w-[400px] overflow-hidden"> |
||||
<div className="absolute inset-0 flex items-center justify-center"> |
||||
<div className="relative flex h-full w-[220px] items-center"> |
||||
<div |
||||
className="absolute inset-y-0 left-0 flex items-center gap-[16px] transition-transform duration-200" |
||||
style={{ |
||||
transform: `translateX(${ |
||||
-1 * (220 + 16) * props.events.length |
||||
}px)`,
|
||||
}} |
||||
> |
||||
<MediaScrapePillSkeleton /> |
||||
{props.events.map((v) => ( |
||||
<MediaScrapePill event={v} key={v.id} /> |
||||
))} |
||||
<MediaScrapePillSkeleton /> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div className="absolute inset-y-0 left-0 w-40 bg-gradient-to-r from-denim-100 to-transparent" /> |
||||
<div className="absolute inset-y-0 right-0 w-40 bg-gradient-to-l from-denim-100 to-transparent" /> |
||||
</div> |
||||
); |
||||
} |
Loading…
Reference in new issue