Files
lms-fe/src/renderer/src/features/curriculum/LearningInfoCard.tsx
T
2026-08-20 16:52:45 +09:00

114 lines
4.4 KiB
TypeScript

import { BookOpen, Car, Clock3, FileText, Play } from 'lucide-react'
import type React from 'react'
type LearningInfoWeek = {
week: number
title: string
tags: string[]
progress: number
duration: string
}
type LearningInfoCardProps = {
week: LearningInfoWeek
studioDisabled: boolean
hasMaterials: boolean
onStartStudio: () => void
onOpenMaterials: () => void
}
export default function LearningInfoCard({
week,
studioDisabled,
hasMaterials,
onStartStudio,
onOpenMaterials
}: LearningInfoCardProps): React.JSX.Element {
return (
<article className="rounded-lg bg-white p-4">
<span className="flex items-center gap-1.5 text-[11px] font-semibold text-[#626b7a]">
<BookOpen size={13} className="text-[#714ef6]" />
학습 정보
</span>
<div className="mt-1.5 flex items-start justify-between gap-2.5">
<div className="min-w-0">
<strong className="block truncate text-[18px] font-bold">{week.week}주차</strong>
<span className="mt-1 block text-[12px] font-medium leading-snug text-[#4f596b]">{week.title}</span>
</div>
<em
className={[
'shrink-0 rounded-md px-2 py-1 text-[11px] not-italic font-bold',
week.tags[1] === '완료' ? 'bg-[#2fbda0]/15 text-[#178c78]' : 'bg-[#6f4df6]/15 text-[#6f4df6]'
].join(' ')}
>
{week.tags[1] ?? '미등록'}
</em>
</div>
<div className="mt-4">
<span className="block text-[12px] font-medium text-[#505b70]">진행률</span>
<div className="mt-1 flex items-center gap-2.5">
<span className="w-9 shrink-0 text-right text-[13px] font-bold">{week.progress}%</span>
<div className="h-1.5 flex-1 overflow-hidden rounded-full bg-[#d7dae3]">
<div className="h-full rounded-full bg-[linear-gradient(90deg,#a78bfa,#714ef6)]" style={{ width: `${week.progress}%` }} />
</div>
</div>
</div>
<div className="my-[17px] overflow-hidden rounded-lg border border-[#dfe3ed] bg-[#fbfcff] py-1">
{[
{ label: '플랫폼', value: week.tags[0] ?? '-', Icon: Car },
{ label: '예상 학습 시간', value: week.duration, Icon: Clock3 }
].map(({ label, value, Icon }) => (
<div
key={label}
className={[
'flex items-center justify-between gap-3 border-b border-[#edf0f5] px-3.5 last:border-b-0',
'min-h-[34px] py-0'
].join(' ')}
>
<span className="flex min-w-0 items-center gap-2 text-[12px] font-medium text-[#4f596b]">
<Icon size={14} className="shrink-0 text-[#6d7788]" />
<span className="truncate">{label}</span>
</span>
<strong className="shrink-0 text-right text-[12px] font-bold text-[#151827]">
{value}
</strong>
</div>
))}
</div>
<button
type="button"
data-help="curriculum-start"
disabled={studioDisabled}
onClick={onStartStudio}
className={[
'flex h-[39px] w-full items-center justify-center gap-2 rounded-md border-0 text-[14px] font-bold transition-all duration-150 ease-out',
studioDisabled
? 'cursor-not-allowed bg-[#d8dce5] text-[#8a91a0]'
: 'cursor-pointer bg-[#714ef6] text-white shadow-[0_8px_18px_rgba(113,78,246,0.20)] hover:-translate-y-px hover:bg-[#6040df] hover:shadow-[0_10px_20px_rgba(113,78,246,0.26)] active:translate-y-0 active:shadow-[0_6px_14px_rgba(113,78,246,0.18)]'
].join(' ')}
>
<Play size={15} fill="currentColor" strokeWidth={2.4} />
개발 스튜디오 시작
</button>
<button
type="button"
data-help="curriculum-materials"
disabled={!hasMaterials}
onClick={onOpenMaterials}
className={[
'mt-2.5 flex h-[39px] w-full items-center justify-center gap-2 rounded-md border text-[14px] font-bold transition-all duration-150 ease-out',
hasMaterials
? 'cursor-pointer border-[#714ef6] bg-white text-[#714ef6] hover:-translate-y-px hover:bg-[#f5f2ff] hover:shadow-[0_8px_16px_rgba(113,78,246,0.13)] active:translate-y-0 active:shadow-none'
: 'cursor-not-allowed border-[#d8dce5] bg-[#f3f4f7] text-[#9aa1af]'
].join(' ')}
>
<FileText size={15} strokeWidth={2.4} />
강의 자료
</button>
</article>
)
}