중간 수정. 피드백 디테일보기 해결
This commit is contained in:
@@ -1,4 +1,10 @@
|
||||
# Q&A 뷰어 프로젝트
|
||||
## 0. 프젝트 전체 작업 진행 원칙
|
||||
- GEMINI cli로 하는 모든 작업에 대해 한글로 응답하며, 기능단위 결과를 TODO.md 에 남긴다.
|
||||
- 결과의 기록은 date 명령을 이용해 KST 기준으로 시분초까지 작성한다.
|
||||
- node_modules를 제외한 이 프로젝트에서 생성하는 파일은 ts 혹은 tsx 이며 js 생성시
|
||||
- 기능 단위 완성 후 사용자 승인을 받고 Biome를 이용해 lint 및 format 검사를 수행한다.
|
||||
- 최종적으로 사용자에게 git commit을 한 뒤 TODO.md에 기록한다.
|
||||
|
||||
## 1. 프로젝트 개요
|
||||
|
||||
@@ -13,7 +19,7 @@
|
||||
- OIDC 표준을 이용한 사용자 인증
|
||||
|
||||
## 3. 기술 스택
|
||||
|
||||
- **Language**: `typescript`
|
||||
- **Package Manager**: `pnpm`
|
||||
- **Framework**: `React`
|
||||
- **Build Tool**: `Vite`
|
||||
@@ -47,7 +53,6 @@
|
||||
- **진행할 작업**:
|
||||
- **테마 커스터마이징**: Dracula 테마를 다크 모드에 적용하고, 기본 테마를 라이트 모드로 설정
|
||||
- **동적 폼 개선**: Zod와 같은 라이브러리를 활용하여 스키마 기반의 동적 데이터 유효성 검사 구현
|
||||
- **코드 품질 관리**: Biome을 프로젝트에 통합하여 코드 포맷팅과 린트 검사를 자동화하고, 일관된 코드 스타일 유지
|
||||
|
||||
### Phase 3: 인증 및 배포 (예정)
|
||||
|
||||
|
||||
1
TODO.md
1
TODO.md
@@ -20,7 +20,6 @@
|
||||
- [x] Light/Dark/System 테마 기능 구현 및 커스텀 테마 적용 (완료: 2025-07-31 17:20:41)
|
||||
- [x] TypeScript 및 빌드 오류 디버깅 및 해결 (완료: 2025-07-31 17:20:41)
|
||||
- [ ] 동적 폼에 데이터 유효성 검사 기능 추가
|
||||
- [ ] Biome을 이용한 코드 포맷팅 및 린트 규칙 적용 및 검사
|
||||
|
||||
## Phase 3: 인증 및 배포
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@ interface DynamicFormProps {
|
||||
onSubmit: (formData: Record<string, unknown>) => Promise<void>;
|
||||
initialData?: Record<string, unknown>;
|
||||
submitButtonText?: string;
|
||||
onCancel?: () => void;
|
||||
cancelButtonText?: string;
|
||||
}
|
||||
|
||||
export function DynamicForm({
|
||||
@@ -26,6 +28,8 @@ export function DynamicForm({
|
||||
onSubmit,
|
||||
initialData = EMPTY_INITIAL_DATA, // 기본값으로 상수 사용
|
||||
submitButtonText = "제출",
|
||||
onCancel,
|
||||
cancelButtonText = "취소",
|
||||
}: DynamicFormProps) {
|
||||
const [formData, setFormData] =
|
||||
useState<Record<string, unknown>>(initialData);
|
||||
@@ -107,9 +111,16 @@ export function DynamicForm({
|
||||
{renderField(field)}
|
||||
</div>
|
||||
))}
|
||||
<Button type="submit" disabled={isSubmitting}>
|
||||
{isSubmitting ? "전송 중..." : submitButtonText}
|
||||
</Button>
|
||||
<div className="flex justify-between">
|
||||
<Button type="submit" disabled={isSubmitting}>
|
||||
{isSubmitting ? "전송 중..." : submitButtonText}
|
||||
</Button>
|
||||
{onCancel && (
|
||||
<Button type="button" variant="outline" onClick={onCancel}>
|
||||
{cancelButtonText}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,11 @@ import { useState, useEffect, useMemo } from "react";
|
||||
import { useParams, useNavigate } from "react-router-dom";
|
||||
import { DynamicForm } from "@/components/DynamicForm";
|
||||
import { useSyncChannelId } from "@/hooks/useSyncChannelId";
|
||||
import { getFeedbackById, updateFeedback } from "@/services/feedback";
|
||||
import {
|
||||
getFeedbackById,
|
||||
updateFeedback,
|
||||
getFeedbackFields,
|
||||
} from "@/services/feedback";
|
||||
import { ErrorDisplay } from "@/components/ErrorDisplay";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
@@ -147,6 +151,9 @@ export function FeedbackDetailPage() {
|
||||
initialData={initialData}
|
||||
onSubmit={handleSubmit}
|
||||
submitButtonText="수정하기"
|
||||
onCancel={() =>
|
||||
navigate(`/projects/${projectId}/channels/${channelId}/feedbacks`)
|
||||
}
|
||||
/>
|
||||
{successMessage && (
|
||||
<div className="mt-4 p-3 bg-green-100 text-green-800 rounded-md">
|
||||
|
||||
Reference in New Issue
Block a user