Skip to content

[feat] 기기 관리#9

Merged
LeeSangHyeok0731 merged 3 commits into
developfrom
feat/machine-manage
Apr 21, 2026
Merged

[feat] 기기 관리#9
LeeSangHyeok0731 merged 3 commits into
developfrom
feat/machine-manage

Conversation

@LeeSangHyeok0731

Copy link
Copy Markdown
Contributor

개요 💡

기기 관리 페이지를 제작했습니다.

작업내용 ⌨️

다음과 같은 내용을 작업했습니다,

  • 기기 조회
  • 기기 상태 변경
  • 기기 삭제

@LeeSangHyeok0731 LeeSangHyeok0731 self-assigned this Apr 20, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request transitions the machine management system from mock data to real API integration, introducing hooks for machine operations and a new status management modal. It also implements a reservation countdown timer and updates various UI components. Review feedback primarily addresses an N+1 API call inefficiency, suggesting that reservation details be included in the list response to avoid multiple individual requests. Other feedback includes correcting a potential runtime error in data access, improving naming conventions for better clarity, and ensuring the new modal is responsive and uses intuitive iconography.

Comment on lines 35 to 40
export interface ReservationItem {
id: number;
machineId: number;
machine: string;
type: ReservationMachineType;
badgeStatus: BadgeStatus;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

N+1 API 호출 문제를 해결하기 위해 ReservationItem 인터페이스에 사용자 정보와 예약 상태 관련 필드들을 추가하는 것이 좋습니다. 이렇게 하면 목록 조회 시 이미 포함된 데이터를 활용할 수 있어, 각 기기마다 상세 정보를 조회하기 위한 추가 API 호출을 제거할 수 있습니다.

export interface ReservationItem {
  id: number;
  machineId: number;
  machine: string;
  type: ReservationMachineType;
  badgeStatus: BadgeStatus;
  userName?: string;
  userRoomNumber?: string;
  expectedCompletionTime?: string;
  status?: ReservationDTOStatus;
  createdAt?: string;

Comment on lines 91 to 96
return {
id: dto.id,
machineId: dto.machineId,
machine: dto.machineName,
type: getMachineType(dto.machineName),
badgeStatus,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

DTO에서 추출한 사용자 및 예약 상세 정보를 ReservationItem에 매핑하여, 목록 데이터만으로도 화면에 필요한 정보를 표시할 수 있도록 합니다.

  return {
    id: dto.id,
    machineId: dto.machineId,
    machine: dto.machineName,
    type: getMachineType(dto.machineName),
    badgeStatus,
    userName: dto.userName,
    userRoomNumber: dto.userRoomNumber,
    expectedCompletionTime: dto.expectedCompletionTime,
    status: dto.status,
    createdAt: dto.createdAt,

Comment on lines +56 to +62
// 실제 예약 ID를 사용하여 상세 정보 조회
const { data: reservationResponse } = useGetReservationDetail(
matchingReservation?.id ?? 0,
Boolean(matchingReservation),
);

const reservation = reservationResponse?.data;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

MachineRow 내부에서 useGetReservationDetail을 호출하는 것은 N+1 API 호출 문제를 발생시킵니다. 부모 컴포넌트에서 전달받은 reservations 목록에 이미 필요한 정보가 포함되어 있으므로(또는 포함되도록 수정하여), 이를 직접 사용하도록 변경해야 합니다.

Suggested change
// 실제 예약 ID를 사용하여 상세 정보 조회
const { data: reservationResponse } = useGetReservationDetail(
matchingReservation?.id ?? 0,
Boolean(matchingReservation),
);
const reservation = reservationResponse?.data;
const reservation = matchingReservation;

<MachineRow
key={item.id}
item={item}
reservations={reservations ?? []}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

useGetReservations가 반환하는 reservations는 API 응답 객체일 가능성이 높습니다. MachinesPage에서와 마찬가지로 reservations?.data.reservations와 같이 실제 배열 데이터에 접근해야 합니다. 현재 코드대로라면 reservations ?? []는 배열이 아닌 객체를 전달하게 되어 런타임 에러가 발생할 수 있습니다.

Suggested change
reservations={reservations ?? []}
reservations={reservations?.data.reservations ?? []}

prev === item.name ? null : item.name,
)
}
onDelete={() =>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

onDelete라는 이름은 즉각적인 삭제 동작을 의미하는 것처럼 보이지만, 실제로는 관리 모달을 열고 있습니다. 가독성을 위해 onManage 또는 onOpenSettings 등으로 이름을 변경하는 것이 좋습니다.

Comment on lines +73 to +76
const overlayPositionClass =
side === "right"
? "absolute left-[calc(100%+16px)] top-0 h-full w-full"
: "absolute right-[calc(100%+16px)] top-0 h-full w-full";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

absoluteleft-[calc(100%+16px)]를 이용한 배치는 화면 너비가 좁은 환경(모바일 등)에서 모달이 화면 밖으로 나가는 문제를 일으킵니다. 반응형 디자인을 고려하여 작은 화면에서는 중앙 정렬되거나 바텀 시트 형태로 보이도록 개선이 필요합니다.

className="inline-flex h-9 w-9 items-center justify-center rounded-full cursor-pointer border-2 border-[#EF4B4F] text-[#EF4B4F] disabled:cursor-not-allowed disabled:opacity-50"
>
<Trash2 size={16} strokeWidth={2.2} />
<Gavel size={16} strokeWidth={2.2} />

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

삭제 버튼에 Gavel 아이콘을 사용하는 것은 직관적이지 않습니다. 일반적인 Trash2 아이콘을 사용하거나, 이 버튼이 설정 모달을 여는 용도라면 Settings 아이콘을 사용하는 것이 UX 측면에서 더 바람직합니다.

@LeeSangHyeok0731 LeeSangHyeok0731 merged commit 33b425c into develop Apr 21, 2026
1 check passed
@LeeSangHyeok0731 LeeSangHyeok0731 deleted the feat/machine-manage branch April 21, 2026 01:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant