govsearch / frontend /components /answer-list.tsx
hizeny's picture
fix(frontend): override plugin-defined max width
248dd27
import { Badge } from "~/components/ui/badge"
import { ScrollArea } from "~/components/ui/scroll-area"
import type { AnswersQuery } from "~/generated/graphql"
import { cn } from "~/lib/utils"
type AnswerListProps = {
items: NonNullable<NonNullable<AnswersQuery["answers"]>["answers"]>
}
export function AnswerList({ items }: AnswerListProps) {
return (
<ScrollArea className="h-screen">
{0 < items.length ? (
<div className="flex flex-col gap-2 p-4 pt-0">
{items.map((item) => (
<div
key={item.docId}
className={cn(
"flex flex-col items-start gap-5 rounded-lg border p-3 text-left text-sm transition-all hover:bg-accent",
)}
>
<div className="flex w-full flex-col gap-1">
<div className="flex items-center">
<div className="flex items-center gap-2">
<div className="font-semibold">{item.question}</div>
</div>
</div>
</div>
<article className="prose prose-sm max-w-none">
<div
className="whitespace-pre-line"
/* biome-ignore lint/security/noDangerouslySetInnerHtml: */
dangerouslySetInnerHTML={{
__html: unsafeConvertToAnchorTag(item.answer),
}}
/>
</article>
{(item.categoryMajor ??
item.categoryMinor ??
item.categoryMedium) && (
<div className="flex text-xs items-center gap-2">
{item.categoryMajor && (
<Badge variant={"default"}>{item.categoryMajor}</Badge>
)}
{item.categoryMedium && (
<Badge variant={"secondary"}>{item.categoryMedium}</Badge>
)}
</div>
)}
</div>
))}
</div>
) : (
<div className="pt-4 md:pt-8 text-center text-muted-foreground text-sm leading-6">
<p className="mb-2">ใƒ’ใƒณใƒˆ:</p>
<ul>
<li>ๅ…็ซฅๆ‰‹ๅฝ“ใฎ็”ณ่ซ‹ๆœŸ้™ใ‚’ๆ•™ใˆใฆใใ ใ•ใ„</li>
<li>ใƒžใ‚คใƒŠใƒณใƒใƒผใ‚ซใƒผใƒ‰ใซ่จ˜่ผ‰ใ•ใ‚Œใฆใ„ใ‚‹้›ปๅญ่จผๆ˜Žๆ›ธใจใฏ๏ผŸ</li>
<li>ๅนด้‡‘ใฏใ€Œใ„ใคใ‹ใ‚‰ใ€ใ€Œใ„ใใ‚‰ใ€ๅ—ใ‘ๅ–ใ‚Œใพใ™ใ‹๏ผŸ</li>
</ul>
</div>
)}
</ScrollArea>
)
}
// FIXME: This function is not safe. It should be replaced with a safer
// implementation.
function unsafeConvertToAnchorTag(inputText: string) {
const regex = /<([^,]+),(http[^>]+)>/g
return inputText.replace(regex, (_match, text, url) => {
const escapedText = text
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
return `<a target="_brank" href="${url.trim()}">${escapedText.trim()}</a>`
})
}