diff --git a/apps/frontend/app/(client)/(main)/(create)/problem/create/_components/ExecutionCard.tsx b/apps/frontend/app/(client)/(main)/(create)/problem/create/_components/ExecutionCard.tsx new file mode 100644 index 0000000000..e5ff0b141a --- /dev/null +++ b/apps/frontend/app/(client)/(main)/(create)/problem/create/_components/ExecutionCard.tsx @@ -0,0 +1,175 @@ +'use client' + +import { Button } from '@/components/shadcn/button' +import { cn, dateFormatter } from '@/libs/utils' +import CheckCircle from '@/public/icons/check-circle.svg' + +export type StateType = 'SUCCESS' | 'FAIL' | 'NONE' + +const STATE_MAP = { + SUCCESS: { + container: 'border-primary-light bg-color-blue-95', + icon: 'text-primary', + text: 'text-primary-strong', + description: 'text-primary', + dot: 'bg-primary', + title: '아웃풋 생성 성공' + }, + FAIL: { + container: 'border-error bg-color-red-95', + icon: 'text-error', + text: 'text-error', + description: 'text-error', + dot: 'bg-error', + title: '아웃풋 생성 실패' + }, + NONE: { + container: 'border-line bg-color-neutral-99', + icon: 'text-color-neutral-50', + text: 'text-color-neutral-30', + description: '', + dot: 'bg-color-neutral-30', + title: '파일 업로드 이후 실행 필요' + } +} as const satisfies Record< + StateType, + { + container: string + icon: string + text: string + description: string + dot: string + title: string + } +> + +export interface GeneratedResult { + state: StateType + date?: Date + totalCnt: number + successCnt: number +} + +interface ExecutionCardProps { + disabled?: boolean + loading: boolean + onGenerate: () => void + canDownload?: boolean + onDownload?: () => void + genResult: GeneratedResult +} + +export function ExecutionCard({ + disabled = false, + loading, + onGenerate, + canDownload = false, + onDownload, + genResult +}: ExecutionCardProps) { + return ( +
+
+
+

+ 자동 생성 실행하기 +

+ + 업로드한 파일을 이용해서 생성을 시도합니다 + +
+
+ + {canDownload && ( + + )} +
+
+ {loading ? ( + + ) : ( +
+ +
+ + {STATE_MAP[genResult.state].title} + +
+ {genResult.state !== 'NONE' ? ( + <> + {genResult.date && ( + {dateFormatter(genResult.date, 'YYYY-MM-DD')} + )} +
+
+
+ + {genResult.successCnt}/{genResult.totalCnt} 솔루션 테스트 + 통과 + {genResult.state === 'SUCCESS' ? ' 완료' : ' 실패'} + + + ) : ( + <> + - +
+
+
+ - + + )} +
+
+
+ )} +
+ ) +} + +function StateSkeleton() { + return ( +
+
+
+
+
+
+
+ ) +} diff --git a/apps/frontend/app/(client)/(main)/(create)/problem/create/_components/TCDownloadCard.tsx b/apps/frontend/app/(client)/(main)/(create)/problem/create/_components/TCDownloadCard.tsx new file mode 100644 index 0000000000..13df24b6a4 --- /dev/null +++ b/apps/frontend/app/(client)/(main)/(create)/problem/create/_components/TCDownloadCard.tsx @@ -0,0 +1,48 @@ +'use client' + +import { Button } from '@/components/shadcn/button' + +interface TCDownloadCardProps { + onDelete: () => void + onDownload: () => void + disabled?: boolean +} + +export function TCDownloadCard({ + onDelete, + onDownload, + disabled = false +}: TCDownloadCardProps) { + return ( +
+
+
+

+ TC 삭제 및 다운로드 +

+

+ 생성한 TC 파일을 삭제 및 다운로드 할 수 있어요 +

+
+
+ + +
+
+
+ ) +} diff --git a/apps/frontend/app/(client)/(main)/(create)/problem/create/test/page.tsx b/apps/frontend/app/(client)/(main)/(create)/problem/create/test/page.tsx new file mode 100644 index 0000000000..bf93c066db --- /dev/null +++ b/apps/frontend/app/(client)/(main)/(create)/problem/create/test/page.tsx @@ -0,0 +1,56 @@ +'use client' + +import { useState } from 'react' +import { + ExecutionCard, + type GeneratedResult, + type StateType +} from '../_components/ExecutionCard' +import { TCDownloadCard } from '../_components/TCDownloadCard' + +export default function Page() { + const [genResult, setGenResult] = useState({ + state: 'FAIL', + date: new Date(2020, 1, 1), + totalCnt: 2, + successCnt: 2 + }) + + const [loading, setLoading] = useState(false) + + // 임시 생성하기 버튼 동작 함수: 문제 생성 상태 변경 + const onGenerate = () => { + setLoading(true) + setTimeout(() => { + setGenResult((prev) => { + const nextState: StateType = ( + { + SUCCESS: 'FAIL', + FAIL: 'NONE', + NONE: 'SUCCESS' + } as const + )[prev.state] + + return { ...prev, state: nextState } + }) + setLoading(false) + }, 1000) + } + + return ( +
+ + alert('Delete')} + onDownload={() => alert('Download')} + disabled={loading} + /> +
+ ) +}