107 lines
3.8 KiB
Plaintext
107 lines
3.8 KiB
Plaintext
---
|
|
import { Schema } from 'astro-seo-schema'
|
|
|
|
import { cn } from '../lib/cn'
|
|
import { KYCNOTME_SCHEMA_MINI } from '../lib/schema'
|
|
import { transformCase } from '../lib/strings'
|
|
|
|
import type { HTMLAttributes } from 'astro/types'
|
|
|
|
export type Props = HTMLAttributes<'div'> & {
|
|
score: number
|
|
label: string
|
|
total?: number
|
|
itemReviewedId?: string
|
|
}
|
|
|
|
const { score, label, total = 10, class: className, itemReviewedId, ...htmlProps } = Astro.props
|
|
|
|
export function makeOverallScoreInfo(score: number, total = 10) {
|
|
const classNamesByColor = {
|
|
red: 'bg-score-1 text-black',
|
|
orange: 'bg-score-2 text-black',
|
|
yellow: 'bg-score-3 text-black',
|
|
blue: 'bg-score-4 text-black',
|
|
green: 'bg-score-5 text-black',
|
|
} as const satisfies Record<string, string>
|
|
|
|
const formattedScore = Math.round(score).toLocaleString()
|
|
const n = score / total
|
|
|
|
if (n > 1) return { text: '', classNameBg: classNamesByColor.green, formattedScore }
|
|
if (n >= 0.9 && n <= 1) return { text: 'Excellent', classNameBg: classNamesByColor.green, formattedScore }
|
|
if (n >= 0.8 && n < 0.9) return { text: 'Very Good', classNameBg: classNamesByColor.blue, formattedScore }
|
|
if (n >= 0.7 && n < 0.8) return { text: 'Good', classNameBg: classNamesByColor.blue, formattedScore }
|
|
if (n >= 0.6 && n < 0.7) return { text: 'Okay', classNameBg: classNamesByColor.yellow, formattedScore }
|
|
if (n >= 0.5 && n < 0.6) {
|
|
return { text: 'Acceptable', classNameBg: classNamesByColor.yellow, formattedScore }
|
|
}
|
|
if (n >= 0.4 && n < 0.5) return { text: 'Bad', classNameBg: classNamesByColor.orange, formattedScore }
|
|
if (n >= 0.3 && n < 0.4) return { text: 'Very Bad', classNameBg: classNamesByColor.orange, formattedScore }
|
|
if (n >= 0.2 && n < 0.3) return { text: 'Really Bad', classNameBg: classNamesByColor.red, formattedScore }
|
|
if (n >= 0 && n < 0.2) return { text: 'Terrible', classNameBg: classNamesByColor.red, formattedScore }
|
|
return { text: '', classNameBg: undefined, formattedScore }
|
|
}
|
|
|
|
const { text, classNameBg, formattedScore } = makeOverallScoreInfo(score, total)
|
|
---
|
|
|
|
<div
|
|
{...htmlProps}
|
|
class={cn(
|
|
'2xs:size-24 relative flex aspect-square size-18 flex-col items-center justify-start text-white',
|
|
className
|
|
)}
|
|
role="group"
|
|
>
|
|
{
|
|
!!itemReviewedId && (
|
|
<Schema
|
|
item={{
|
|
'@context': 'https://schema.org',
|
|
'@type': 'Review',
|
|
reviewAspect: label,
|
|
name: `${text} ${transformCase(label, 'lower')}`,
|
|
itemReviewed: { '@id': itemReviewedId },
|
|
reviewRating: {
|
|
'@type': 'Rating',
|
|
ratingValue: score,
|
|
worstRating: 0,
|
|
bestRating: total,
|
|
},
|
|
author: KYCNOTME_SCHEMA_MINI,
|
|
}}
|
|
/>
|
|
)
|
|
}
|
|
<!-- <svg
|
|
class="absolute top-0.5 left-[calc(50%+48px/2+2px)] size-3 text-current/60"
|
|
viewBox="0 0 12 12"
|
|
fill="currentColor"
|
|
>
|
|
<path
|
|
d="M6 11C3.23857 11 1 8.7614 1 6C1 3.23857 3.23857 1 6 1C8.7614 1 11 3.23857 11 6C11 8.7614 8.7614 11 6 11ZM6 10C8.20915 10 10 8.20915 10 6C10 3.79086 8.20915 2 6 2C3.79086 2 2 3.79086 2 6C2 8.20915 3.79086 10 6 10ZM5.5 3.5H6.5V4.5H5.5V3.5ZM5.5 5.5H6.5V8.5H5.5V5.5Z"
|
|
></path>
|
|
</svg> -->
|
|
|
|
<div
|
|
class={cn(
|
|
'2xs:mt-2 2xs:size-12 mt-0.5 mb-1 flex size-10 shrink-0 items-center justify-center rounded-md leading-none font-bold tracking-tight text-black',
|
|
classNameBg,
|
|
{
|
|
'text-[1.75rem] leading-[calc(2/1.75)] tracking-tighter': formattedScore.length > 2,
|
|
}
|
|
)}
|
|
>
|
|
<span class="2xs:text-[2rem] text-[1.5rem] leading-none font-bold tracking-tight text-black">
|
|
{formattedScore}
|
|
</span>
|
|
</div>
|
|
|
|
<div class="2xs:mb-0.5 text-base leading-none font-bold tracking-wide uppercase">
|
|
{label}
|
|
</div>
|
|
|
|
<span class="text-xs leading-none tracking-wide text-current/80">{text}</span>
|
|
</div>
|