오..
This commit is contained in:
@@ -69,7 +69,9 @@ export default function AccountPage() {
|
||||
onSubmit={() => {
|
||||
// TODO: integrate API
|
||||
}}
|
||||
devVerificationState={verificationState}
|
||||
devVerificationState={
|
||||
verificationState === 'changed' ? 'verified' : verificationState
|
||||
}
|
||||
/>
|
||||
|
||||
<MenuAccountOption
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import Image from "next/image";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
import ChevronDownSvg from "../../svgs/chevrondownsvg";
|
||||
|
||||
@@ -36,14 +37,15 @@ function ProgressBar({ value }: { value: number }) {
|
||||
|
||||
export default function CourseCard({ course, defaultOpen = false }: { course: Course; defaultOpen?: boolean }) {
|
||||
const [open, setOpen] = useState(defaultOpen);
|
||||
const router = useRouter();
|
||||
|
||||
const totalMinutes = course.lessons.reduce((sum, l) => sum + (l.durationMin || 0), 0);
|
||||
const totalHours = Math.floor(totalMinutes / 60);
|
||||
const restMinutes = totalMinutes % 60;
|
||||
const firstIncomplete = course.lessons.find((l) => !l.isCompleted)?.id;
|
||||
const cardClassName = [
|
||||
"rounded-xl border bg-white shadow-[0_2px_8px_rgba(0,0,0,0.02)]",
|
||||
open ? "border-[#384fbf]" : "border-[#ecf0ff]",
|
||||
"rounded-xl bg-white shadow-[0_2px_8px_rgba(0,0,0,0.02)]",
|
||||
open ? "border-[3px] border-[#384fbf]" : "border border-[#ecf0ff]",
|
||||
].join(" ");
|
||||
|
||||
const formatDuration = (m: number) => {
|
||||
@@ -54,33 +56,33 @@ export default function CourseCard({ course, defaultOpen = false }: { course: Co
|
||||
|
||||
return (
|
||||
<article className={cardClassName}>
|
||||
<header className="flex items-center gap-4 p-4">
|
||||
<div className="relative h-[76px] w-[120px] overflow-hidden rounded-md bg-[#f1f3f5]">
|
||||
<header className="flex items-center gap-6 px-8 py-6">
|
||||
<div className="relative h-[120px] w-[180px] overflow-hidden rounded-[8px] bg-[#f1f3f5]">
|
||||
<Image
|
||||
src={`https://picsum.photos/seed/${encodeURIComponent(course.id)}/240/152`}
|
||||
alt=""
|
||||
fill
|
||||
sizes="120px"
|
||||
sizes="180px"
|
||||
unoptimized
|
||||
className="object-cover"
|
||||
/>
|
||||
</div>
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="rounded bg-[#e5f5ec] px-2 py-0.5 text-[12px] font-semibold leading-[1.4] text-[#0c9d61]">
|
||||
<span className="flex h-[20px] items-center justify-center rounded-[4px] bg-[#e5f5ec] px-[4px] text-[13px] font-semibold leading-[1.4] text-[#0c9d61]">
|
||||
{course.status}
|
||||
</span>
|
||||
<h2 className="truncate text-[18px] font-bold leading-[1.5] text-[#1b2027]">
|
||||
<h2 className="truncate text-[18px] font-semibold leading-normal text-[#333c47]">
|
||||
{course.title}
|
||||
</h2>
|
||||
</div>
|
||||
<p className="mt-1 line-clamp-2 text-[14px] leading-[1.5] text-[#4c5561]">{course.description}</p>
|
||||
<p className="mt-1 line-clamp-2 text-[14px] leading-normal text-basic-text">{course.description}</p>
|
||||
<div className="mt-2 flex items-center justify-between gap-3">
|
||||
<p className="text-[13px] leading-[1.4] text-[#8c95a1]">
|
||||
VOD · 총 {course.lessons.length}강 · {totalHours}시간 {restMinutes}분
|
||||
</p>
|
||||
<p className="text-[13px] font-semibold leading-[1.4] text-[#384fbf]">
|
||||
진행도 {course.progressPct}%
|
||||
전체 진도율: {course.progressPct}%
|
||||
</p>
|
||||
</div>
|
||||
<div className="mt-2">
|
||||
@@ -105,20 +107,15 @@ export default function CourseCard({ course, defaultOpen = false }: { course: Co
|
||||
</header>
|
||||
|
||||
{open ? (
|
||||
<div className="px-4 pb-4">
|
||||
<div className="px-6 pb-6">
|
||||
<ul className="flex flex-col gap-2">
|
||||
{course.lessons.map((lesson, idx) => (
|
||||
<li key={lesson.id} className="rounded-lg border border-[#ecf0ff] bg-white">
|
||||
<div className="flex items-center justify-between gap-4 px-4 py-3">
|
||||
<li key={lesson.id} className="rounded-lg border border-[#dee1e6] bg-white">
|
||||
<div className="flex items-center justify-between gap-4 px-[24px] py-[16px]">
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="flex items-center gap-3">
|
||||
<span className="w-[20px] text-[13px] font-semibold leading-[1.4] text-[#8c95a1]">
|
||||
{idx + 1}.
|
||||
</span>
|
||||
<p className="truncate text-[14px] font-medium leading-[1.5] text-[#333c47]">
|
||||
{lesson.title}
|
||||
</p>
|
||||
</div>
|
||||
<p className="truncate text-[16px] font-semibold leading-normal text-[#333c47]">
|
||||
{`${idx + 1}. ${lesson.title}`}
|
||||
</p>
|
||||
<div className="mt-2 flex items-center gap-3">
|
||||
<span className="text-[13px] leading-[1.4] text-[#8c95a1]">
|
||||
{formatDuration(lesson.durationMin)}
|
||||
@@ -129,29 +126,59 @@ export default function CourseCard({ course, defaultOpen = false }: { course: Co
|
||||
<button
|
||||
type="button"
|
||||
className={[
|
||||
"rounded-md px-3 py-2 text-[14px] font-medium leading-[1.5]",
|
||||
"inline-flex h-[32px] w-[140px] items-center justify-center gap-[6px] rounded-[6px] px-4 text-center whitespace-nowrap cursor-pointer",
|
||||
lesson.isCompleted
|
||||
? "text-[#384fbf] border border-transparent bg-white"
|
||||
: "text-[#4c5561] border border-[#8c95a1] bg-white",
|
||||
? "bg-white text-[13px] font-medium leading-[1.4] text-[#384fbf]"
|
||||
: "bg-white text-[14px] font-medium leading-normal text-basic-text border border-[#8c95a1]",
|
||||
].join(" ")}
|
||||
>
|
||||
{lesson.isCompleted ? "학습 제출 완료" : "학습 제출 하기"}
|
||||
{lesson.isCompleted ? (
|
||||
<>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="10"
|
||||
height="7"
|
||||
viewBox="0 0 10 7"
|
||||
fill="none"
|
||||
aria-hidden
|
||||
>
|
||||
<path
|
||||
d="M8.75 0.75L3.25 6.25L0.75 3.75"
|
||||
stroke="#384FBF"
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
<span>학습 제출 완료</span>
|
||||
</>
|
||||
) : (
|
||||
"학습 제출 하기"
|
||||
)}
|
||||
</button>
|
||||
{lesson.isCompleted ? (
|
||||
<button
|
||||
type="button"
|
||||
className="rounded-md border border-[#dee1e6] px-3 py-2 text-[14px] font-medium leading-[1.5] text-[#4c5561] hover:bg-[#f9fafb]"
|
||||
onClick={() => router.push(`/menu/courses/lessons/${lesson.id}/review`)}
|
||||
className="inline-flex h-[32px] w-[140px] items-center justify-center rounded-[6px] bg-[#f1f3f5] px-4 text-center text-[14px] font-medium leading-normal text-basic-text whitespace-nowrap cursor-pointer"
|
||||
>
|
||||
복습하기
|
||||
</button>
|
||||
) : (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() =>
|
||||
router.push(
|
||||
lesson.id === firstIncomplete
|
||||
? `/menu/courses/lessons/${lesson.id}/continue`
|
||||
: `/menu/courses/lessons/${lesson.id}/start`,
|
||||
)
|
||||
}
|
||||
className={[
|
||||
"rounded-md px-3 py-2 text-[14px] font-medium leading-[1.5]",
|
||||
"inline-flex h-[32px] w-[140px] items-center justify-center rounded-[6px] px-4 text-center text-[14px] font-medium leading-normal whitespace-nowrap cursor-pointer",
|
||||
lesson.id === firstIncomplete
|
||||
? "bg-[#ecf0ff] text-[#384fbf]"
|
||||
: "border border-[#dee1e6] text-[#4c5561] hover:bg-[#f9fafb]",
|
||||
: "border border-[#dee1e6] text-basic-text",
|
||||
].join(" ")}
|
||||
>
|
||||
{lesson.id === firstIncomplete ? "이어서 수강하기" : "수강하기"}
|
||||
|
||||
168
src/app/menu/courses/lessons/FigmaSelectedLessonPage.tsx
Normal file
168
src/app/menu/courses/lessons/FigmaSelectedLessonPage.tsx
Normal file
@@ -0,0 +1,168 @@
|
||||
'use client';
|
||||
|
||||
const imgImage2 = "/imgs/image-2.png";
|
||||
const imgLine58 = "/imgs/line-58.svg";
|
||||
const img = "/imgs/asset-base.svg";
|
||||
const imgArrowsDiagramsArrow = "/imgs/arrows-diagrams-arrow.svg";
|
||||
const imgIcon = "/imgs/icon.svg";
|
||||
const imgGroup = "/imgs/group.svg";
|
||||
const imgEllipse2 = "/imgs/ellipse-2.svg";
|
||||
const imgMusicAudioPlay = "/imgs/music-audio-play.svg";
|
||||
const imgIcon1 = "/imgs/icon-1.svg";
|
||||
const imgIcon2 = "/imgs/icon-2.svg";
|
||||
const imgIcon3 = "/imgs/icon-3.svg";
|
||||
const imgIcon4 = "/imgs/icon-4.svg";
|
||||
|
||||
export default function FigmaSelectedLessonPage() {
|
||||
return (
|
||||
<div className="bg-white content-stretch flex flex-col items-center relative size-full">
|
||||
<div className="content-stretch flex flex-col items-start max-w-[1440px] relative shrink-0 w-[1440px]">
|
||||
<div className="box-border content-stretch flex gap-[10px] h-[100px] items-center px-[32px] py-0 relative shrink-0 w-full">
|
||||
<div className="basis-0 content-stretch flex gap-[12px] grow items-center min-h-px min-w-px relative shrink-0">
|
||||
<div className="relative shrink-0 size-[32px]">
|
||||
<img alt="" className="block max-w-none size-full" src={imgArrowsDiagramsArrow} />
|
||||
</div>
|
||||
<div className="basis-0 content-stretch flex flex-col grow items-start justify-center leading-[1.5] min-h-px min-w-px not-italic relative shrink-0">
|
||||
<p className="font-['Pretendard:SemiBold',sans-serif] relative shrink-0 text-[#6c7682] text-[16px] w-full">
|
||||
원자로 운전 및 계통
|
||||
</p>
|
||||
<p className="font-['Pretendard:Bold',sans-serif] relative shrink-0 text-[#1b2027] text-[24px] w-full">
|
||||
6. 원자로 시동, 운전 및 정지 절차
|
||||
</p>
|
||||
</div>
|
||||
<div className="content-stretch flex gap-[20px] h-[81px] items-center justify-center relative shrink-0">
|
||||
<div className="relative shrink-0 w-[52px]">
|
||||
<div className="bg-clip-padding border-0 border-[transparent] border-solid box-border content-stretch flex flex-col gap-[4px] items-center relative w-[52px]">
|
||||
<div className="bg-[#384fbf] relative rounded-[2.23696e+07px] shrink-0 size-[32px]">
|
||||
<div className="bg-clip-padding border-0 border-[transparent] border-solid box-border content-stretch flex items-center justify-center relative size-[32px]">
|
||||
<p className="font-['Pretendard:Bold',sans-serif] leading-[18px] not-italic relative shrink-0 text-[14px] text-nowrap text-white whitespace-pre">
|
||||
1
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<p className="font-['Pretendard:SemiBold',sans-serif] leading-[1.5] not-italic relative shrink-0 text-[#384fbf] text-[14px] text-nowrap whitespace-pre">
|
||||
강좌 수강
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative shrink-0 size-[24px]">
|
||||
<img alt="" className="block max-w-none size-full" src={imgIcon} />
|
||||
</div>
|
||||
<div className="relative shrink-0 w-[52px]">
|
||||
<div className="bg-clip-padding border-0 border-[transparent] border-solid box-border content-stretch flex flex-col gap-[4px] items-center relative w-[52px]">
|
||||
<div className="bg-[#dee1e6] relative rounded-[2.23696e+07px] shrink-0 size-[32px]">
|
||||
<div className="bg-clip-padding border-0 border-[transparent] border-solid box-border content-stretch flex items-center justify-center relative size-[32px]">
|
||||
<p className="font-['Pretendard:Bold',sans-serif] leading-[18px] not-italic relative shrink-0 text-[#6c7682] text-[14px] text-nowrap whitespace-pre">
|
||||
2
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<p className="font-['Pretendard:SemiBold',sans-serif] leading-[1.5] not-italic relative shrink-0 text-[#6c7682] text-[14px] text-nowrap whitespace-pre">
|
||||
XR 실습
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative shrink-0 size-[24px]">
|
||||
<img alt="" className="block max-w-none size-full" src={imgIcon} />
|
||||
</div>
|
||||
<div className="relative shrink-0 w-[52px]">
|
||||
<div className="bg-clip-padding border-0 border-[transparent] border-solid box-border content-stretch flex flex-col gap-[4px] items-center relative w-[52px]">
|
||||
<div className="bg-[#dee1e6] relative rounded-[2.23696e+07px] shrink-0 size-[32px]">
|
||||
<div className="bg-clip-padding border-0 border-[transparent] border-solid box-border content-stretch flex items-center justify-center relative size-[32px]">
|
||||
<p className="font-['Pretendard:Bold',sans-serif] leading-[18px] not-italic relative shrink-0 text-[#6c7682] text-[14px] text-nowrap whitespace-pre">
|
||||
3
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<p className="font-['Pretendard:SemiBold',sans-serif] leading-[1.5] not-italic relative shrink-0 text-[#6c7682] text-[14px] text-nowrap whitespace-pre">
|
||||
문제 풀기
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="box-border content-stretch flex flex-col gap-[24px] items-center overflow-clip pb-[80px] pt-[24px] px-8 relative rounded-[8px] shrink-0 w-full">
|
||||
<div className="aspect-[1920/1080] bg-black overflow-clip relative rounded-[8px] shrink-0 w-full">
|
||||
<div className="absolute left-1/2 size-[120px] top-1/2 translate-x-[-50%] translate-y-[-50%]">
|
||||
<div className="absolute contents inset-0">
|
||||
<img alt="" className="block max-w-none size-full" src={imgGroup} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="absolute bg-gradient-to-t bottom-0 box-border content-stretch flex flex-col from-[rgba(0,0,0,0.8)] gap-[20px] items-center justify-center left-[-0.5px] px-[16px] py-[24px] to-[rgba(0,0,0,0)] w-[1376px]">
|
||||
<div className="bg-[#333c47] h-[4px] relative rounded-[3.35544e+07px] shrink-0 w-full">
|
||||
<div className="absolute left-0 size-[12px] top-1/2 translate-y-[-50%]">
|
||||
<img alt="" className="block max-w-none size-full" src={imgEllipse2} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="content-stretch flex h-[32px] items-center justify-between relative shrink-0 w-full">
|
||||
<div className="relative shrink-0">
|
||||
<div className="bg-clip-padding border-0 border-[transparent] border-solid box-border content-stretch flex gap-[8px] items-center relative">
|
||||
<div className="content-stretch flex gap-[16px] items-center relative shrink-0">
|
||||
<div className="relative shrink-0 size-[32px]">
|
||||
<img alt="" className="block max-w-none size-full" src={imgMusicAudioPlay} />
|
||||
</div>
|
||||
<div className="content-stretch flex gap-[8px] h-[32px] items-center relative shrink-0 w-[120px]">
|
||||
<div className="relative rounded-[4px] shrink-0 size-[32px]">
|
||||
<div className="bg-clip-padding border-0 border-[transparent] border-solid box-border content-stretch flex items-center justify-center relative size-[32px]">
|
||||
<div className="relative shrink-0 size-[18px]">
|
||||
<img alt="" className="block max-w-none size-full" src={imgIcon1} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="basis-0 grow h-[4px] min-h-px min-w-px relative rounded-[3.35544e+07px] shrink-0">
|
||||
<div className="bg-clip-padding border-0 border-[transparent] border-solid box-border h-[4px] w-full" />
|
||||
</div>
|
||||
</div>
|
||||
<p className="font-['Pretendard:Medium',sans-serif] leading-[19.5px] not-italic relative shrink-0 text-[13px] text-nowrap text-white whitespace-pre">
|
||||
0:00 / 12:26
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative shrink-0">
|
||||
<div className="bg-clip-padding border-0 border-[transparent] border-solid box-border content-stretch flex gap-[12px] items-center relative">
|
||||
<div className="bg-[#333c47] box-border content-stretch flex gap-[4px] h-[32px] items-center justify-center px-[16px] py-[3px] relative rounded-[6px] shrink-0 w-[112px]">
|
||||
<div className="relative shrink-0 size-[16px]">
|
||||
<img alt="" className="block max-w-none size-full" src={imgIcon2} />
|
||||
</div>
|
||||
<p className="font-['Pretendard:Medium',sans-serif] leading-[1.5] not-italic relative shrink-0 text-[14px] text-center text-nowrap text-white whitespace-pre">
|
||||
이전 강의
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-[#333c47] box-border content-stretch flex gap-[4px] h-[32px] items-center justify-center px-[16px] py-[3px] relative rounded-[6px] shrink-0 w-[112px]">
|
||||
<p className="font-['Pretendard:Medium',sans-serif] leading-[1.5] not-italic relative shrink-0 text-[14px] text-center text-nowrap text-white whitespace-pre">
|
||||
다음 강의
|
||||
</p>
|
||||
<div className="flex items-center justify-center relative shrink-0">
|
||||
<div className="flex-none rotate-[180deg] scale-y-[-100%]">
|
||||
<div className="relative size-[16px]">
|
||||
<img alt="" className="block max-w-none size-full" src={imgIcon3} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="content-stretch flex items-center justify-center relative rounded-[4px] shrink-0 size-[32px]">
|
||||
<div className="relative shrink-0 size-[18px]">
|
||||
<img alt="" className="block max-w-none size-full" src={imgIcon4} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-[#fff9ee] border border-[#ffdd82] border-solid box-border content-stretch flex flex-col h-[55px] items-start pb-px pt-[17px] px-[17px] relative rounded-[8px] shrink-0 w-full">
|
||||
<ul className="[white-space-collapse:collapse] block font-['Pretendard:Medium',sans-serif] leading-[0] not-italic relative shrink-0 text-[#333c47] text-[14px] text-nowrap">
|
||||
<li className="ms-[21px]">
|
||||
<span className="leading-[1.5]">강좌 수강 완료 후 문제를 풀어야 하니 집중해서 강좌 수강해 주세요.</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
'use client';
|
||||
import FigmaSelectedLessonPage from '../../FigmaSelectedLessonPage';
|
||||
|
||||
export default function ContinueLessonPage() {
|
||||
return <FigmaSelectedLessonPage />;
|
||||
}
|
||||
|
||||
|
||||
7
src/app/menu/courses/lessons/[lessonId]/review/page.tsx
Normal file
7
src/app/menu/courses/lessons/[lessonId]/review/page.tsx
Normal file
@@ -0,0 +1,7 @@
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
export default function ReviewLessonPage({ params }: { params: { lessonId: string } }) {
|
||||
redirect(`/${params.lessonId}/review`);
|
||||
}
|
||||
|
||||
|
||||
8
src/app/menu/courses/lessons/[lessonId]/start/page.tsx
Normal file
8
src/app/menu/courses/lessons/[lessonId]/start/page.tsx
Normal file
@@ -0,0 +1,8 @@
|
||||
'use client';
|
||||
import FigmaSelectedLessonPage from '../../FigmaSelectedLessonPage';
|
||||
|
||||
export default function StartLessonPage() {
|
||||
return <FigmaSelectedLessonPage />;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,10 +7,10 @@ type Props = {
|
||||
onClose: () => void;
|
||||
};
|
||||
|
||||
const imgImage1 = "http://localhost:3845/assets/89fda8e949171025b1232bae70fc9d442e4e70c8.png";
|
||||
const imgContainer = "http://localhost:3845/assets/d04df6bb7fe1bd29946d04be9442029bca1503b0.png";
|
||||
const img = "http://localhost:3845/assets/7adf9a5e43b6c9e5f9bee6adfee64e85eabac44a.svg";
|
||||
const img1 = "http://localhost:3845/assets/9e3b52939dbaa99088659a82db437772ef1ad40e.svg";
|
||||
const imgImage1 = "/imgs/image-1.png";
|
||||
const imgContainer = "/imgs/certificate-container.png";
|
||||
const img = "/imgs/certificate-asset.svg";
|
||||
const img1 = "/imgs/certificate-asset-1.svg";
|
||||
|
||||
export default function FigmaCertificateContent({ onClose }: Props) {
|
||||
return (
|
||||
|
||||
@@ -10,8 +10,8 @@ type Props = {
|
||||
scoreText?: string;
|
||||
};
|
||||
|
||||
const img = "http://localhost:3845/assets/7adf9a5e43b6c9e5f9bee6adfee64e85eabac44a.svg";
|
||||
const img1 = "http://localhost:3845/assets/498f1d9877c6da3dadf581f98114a7f15bfc6769.svg";
|
||||
const img = "/imgs/feedback-asset.svg";
|
||||
const img1 = "/imgs/feedback-asset-1.svg";
|
||||
|
||||
export default function FigmaFeedbackContent({
|
||||
onClose,
|
||||
|
||||
Reference in New Issue
Block a user