feat: 이슈 API 연동 및 UI 개선
- 이슈 목록/상세 API 연동 - 테이블 컬럼 너비 조정 - Biome 린터 설정 수정
This commit is contained in:
@@ -4,18 +4,15 @@
|
||||
"enabled": true,
|
||||
"rules": {
|
||||
"recommended": true
|
||||
},
|
||||
"ignore": ["node_modules"]
|
||||
}
|
||||
},
|
||||
"formatter": {
|
||||
"enabled": true,
|
||||
"indentStyle": "tab",
|
||||
"ignore": ["node_modules"]
|
||||
"indentStyle": "tab"
|
||||
},
|
||||
"javascript": {
|
||||
"formatter": {
|
||||
"quoteStyle": "double"
|
||||
},
|
||||
"organizeImports": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -193,9 +193,9 @@ export function DynamicTable<TData extends BaseData>({
|
||||
field.id === "id"
|
||||
? 50
|
||||
: field.id === "name" || field.id === "title"
|
||||
? 150
|
||||
? 300
|
||||
: field.id === "description" || field.id === "contents"
|
||||
? 200
|
||||
? 500
|
||||
: field.id === "createdAt" || field.id === "updatedAt"
|
||||
? 120 // 10글자 너비
|
||||
: undefined,
|
||||
|
||||
@@ -2,127 +2,45 @@
|
||||
import { handleApiError } from "./error";
|
||||
|
||||
export interface Issue {
|
||||
id: string;
|
||||
id: number;
|
||||
name: string;
|
||||
description: string;
|
||||
status: string;
|
||||
category: string;
|
||||
priority?: string;
|
||||
category?: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
|
||||
feedbackCount: number;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export interface IssueField {
|
||||
id: string;
|
||||
name: string;
|
||||
type: "text" | "textarea" | "number" | "select";
|
||||
type: "text" | "textarea" | "number" | "select" | "date";
|
||||
readOnly?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 이슈 목록에 표시할 필드 스키마를 반환합니다.
|
||||
* 순서: Status, ID, Name, Description, Category
|
||||
*/
|
||||
export async function getIssues(projectId: string): Promise<Issue[]> {
|
||||
console.log(`Fetching issues for project: ${projectId}`);
|
||||
// ... 실제 API 호출 로직 ...
|
||||
return [
|
||||
{
|
||||
id: "1",
|
||||
name: "로그인 버튼 실종",
|
||||
description: "메인 화면에서 로그인 버튼이 보이지 않는 버그 발생",
|
||||
status: "Open",
|
||||
priority: "High",
|
||||
createdAt: "2023-10-01T10:00:00Z",
|
||||
updatedAt: "2023-10-01T11:00:00Z",
|
||||
const url = `/api/projects/${projectId}/issues/search`;
|
||||
const response = await fetch(url, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
name: "데이터 로딩 속도 저하",
|
||||
description: "대시보드 로딩 시 5초 이상 소요됨",
|
||||
status: "In Progress",
|
||||
priority: "Medium",
|
||||
createdAt: "2023-10-02T14:00:00Z",
|
||||
updatedAt: "2023-10-02T15:30:00Z",
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
name: "모바일 화면 깨짐",
|
||||
description: "iPhone 14 Pro에서 프로필 페이지 레이아웃이 깨져 보임",
|
||||
status: "Open",
|
||||
priority: "High",
|
||||
createdAt: "2023-10-03T09:00:00Z",
|
||||
updatedAt: "2023-10-03T09:00:00Z",
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
name: "API 요청 실패",
|
||||
description: "특정 조건에서 사용자 정보 업데이트 시 500 에러 발생",
|
||||
status: "Closed",
|
||||
priority: "Critical",
|
||||
createdAt: "2023-09-28T11:00:00Z",
|
||||
updatedAt: "2023-10-01T18:00:00Z",
|
||||
},
|
||||
{
|
||||
id: "5",
|
||||
name: "오타 수정",
|
||||
description: "이용약관 페이지의 '개인정보'가 '개인정ㅂ'로 표시됨",
|
||||
status: "Closed",
|
||||
priority: "Low",
|
||||
createdAt: "2023-10-04T16:00:00Z",
|
||||
updatedAt: "2023-10-04T16:30:00Z",
|
||||
},
|
||||
{
|
||||
id: "6",
|
||||
name: "다크 모드 지원",
|
||||
description: "사용자 편의를 위해 다크 모드 기능 추가 필요",
|
||||
status: "Open",
|
||||
priority: "Medium",
|
||||
createdAt: "2023-10-05T11:20:00Z",
|
||||
updatedAt: "2023-10-05T11:20:00Z",
|
||||
},
|
||||
];
|
||||
body: JSON.stringify({}),
|
||||
});
|
||||
if (!response.ok) {
|
||||
await handleApiError("이슈 목록을 불러오는 데 실패했습니다.", response);
|
||||
}
|
||||
const data = await response.json();
|
||||
return data.items;
|
||||
}
|
||||
|
||||
export async function getIssueById(
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
): Promise<Issue> {
|
||||
console.log(
|
||||
`Fetching issue ${issueId} for project: ${projectId}`,
|
||||
);
|
||||
// 실제 API 호출에서는 projectId와 issueId를 사용해야 합니다.
|
||||
// 여기서는 모든 이슈를 가져온 후 ID로 필터링하여 모의합니다.
|
||||
const issues = await getIssues(projectId);
|
||||
const issue = issues.find((i) => i.id === issueId);
|
||||
if (!issue) {
|
||||
throw new Error("Issue not found");
|
||||
}
|
||||
return issue;
|
||||
}
|
||||
|
||||
export async function getIssueFields(): Promise<IssueField[]> {
|
||||
// ... 기존 코드 ...
|
||||
return [
|
||||
{ id: "id", name: "ID", type: "text" },
|
||||
{ id: "name", name: "이름", type: "text" },
|
||||
{ id: "description", name: "설명", type: "text" },
|
||||
{ id: "status", name: "상태", type: "text" },
|
||||
{ id: "priority", name: "우선순위", type: "text" },
|
||||
{ id: "createdAt", name: "생성일", type: "date" },
|
||||
{ id: "updatedAt", name: "수정일", type: "date" },
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 특정 프로젝트의 단일 이슈 상세 정보를 가져옵니다.
|
||||
*/
|
||||
export const getIssue = async (
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
): Promise<Issue> => {
|
||||
const url = `/api/projects/${projectId}/issues/${issueId}`;
|
||||
const response = await fetch(url);
|
||||
|
||||
@@ -133,6 +51,18 @@ export const getIssue = async (
|
||||
);
|
||||
}
|
||||
|
||||
// API 응답을 그대로 사용합니다.
|
||||
return response.json();
|
||||
};
|
||||
}
|
||||
|
||||
export async function getIssueFields(): Promise<IssueField[]> {
|
||||
// This is mock data, but it's used by other components.
|
||||
return [
|
||||
{ id: "id", name: "ID", type: "text" },
|
||||
{ id: "name", name: "이름", type: "text" },
|
||||
{ id: "description", name: "설명", type: "text" },
|
||||
{ id: "status", name: "상태", type: "text" },
|
||||
{ id: "priority", name: "우선순위", type: "text" },
|
||||
{ id: "createdAt", name: "생성일", type: "date" },
|
||||
{ id: "updatedAt", name: "수정일", type: "date" },
|
||||
];
|
||||
}
|
||||
Reference in New Issue
Block a user