[FE-08] 게스트 초대 REST 엔드포인트 + Query 훅

작업 내용 (설계 의도)

변경 사항

근거: 20260704-채팅시스템고도화-design-fe-app.md “API 연동 표”·BE TDD “REST API 계약”·상태 전이 표(RoomInvitation).

게스트 초대 REST 함수와 훅을 신설한다. 신규 파일 api/invitation.ts·lib/useInvitations.ts. 컴포넌트는 훅 경유.

  • api/invitation.ts: inviteGuest(roomId, req) (POST /rooms/{roomId}/invitations), acceptInvitation(id) (POST /rooms/invitations/{id}/accept), rejectInvitation(id) (POST /rooms/invitations/{id}/reject), listMyInvitations() (GET /rooms/invitations/me 역제안).
  • lib/useInvitations.ts: useInviteGuest(멱등 응답 처리 — 기존 PENDING 초대면 그대로 반환), useMyInvitations, useAcceptInvitation(성공 시 방목록·해당 방 캐시 무효화 후 방 이동 신호), useRejectInvitation(성공 시 수신함 캐시 갱신).

InviteGuestRequest{inviteeUserId,canSpeak,expiresInDays} 계약 일치. 역제안 GET /rooms/invitations/me는 “BE 확정 대기” 주석. getBeClient() 경유.

롤백: 초대 관련 화면 진입점은 chat.community.enabled 플래그로 숨김 가능.

의존

  • FE-02 (chat-types)

다이어그램

처리 흐름

sequenceDiagram
    participant Screen
    participant Hook as useAcceptInvitation
    participant Api as api/invitation.ts
    participant Cache as queryClient
    Screen->>Hook: accept(id)
    Hook->>Api: POST /rooms/invitations/{id}/accept
    Api-->>Hook: InvitationResponse
    Hook->>Cache: invalidate(rooms/me, invitations/me)

테스트 케이스

  • useInviteGuest{inviteeUserId,canSpeak,expiresInDays}를 계약대로 전송한다
  • 동일 (roomId, inviteeUserId) 재초대 시 기존 PENDING 초대를 멱등하게 반환한다
  • useAcceptInvitation 성공 시 방목록·수신함 캐시가 무효화된다
  • useRejectInvitation 성공 시 수신함에서 해당 초대가 제거된다
  • 이미 종료된(EXPIRED/REVOKED) 초대 수락 시 서버 거부를 전파한다(상태 보호)