44import com .workingdead .meet .entity .*;
55import com .workingdead .meet .repository .*;
66import com .workingdead .meet .service .*;
7+ import com .workingdead .meet .dto .PriorityDtos .*;
78import io .swagger .v3 .oas .annotations .*;
89import io .swagger .v3 .oas .annotations .media .*;
910import io .swagger .v3 .oas .annotations .responses .*;
1011import io .swagger .v3 .oas .annotations .tags .Tag ;
1112import jakarta .validation .Valid ;
13+ import jakarta .servlet .http .HttpSession ;
1214import org .springframework .http .ResponseEntity ;
1315import org .springframework .web .bind .annotation .*;
1416
17+ import java .util .List ;
18+ import java .util .Map ;
19+ import java .lang .reflect .Field ;
20+ import org .springframework .util .ReflectionUtils ;
21+
1522@ Tag (name = "Participant" , description = "참여자 관리 API" )
1623@ RestController
1724@ RequestMapping ("" )
1825public class ParticipantController {
1926 private final ParticipantService participantService ;
20- public ParticipantController (ParticipantService participantService ) { this .participantService = participantService ; }
27+ private final PriorityService priorityService ;
28+ private final ParticipantRepository participantRepository ;
2129
30+ public ParticipantController (
31+ ParticipantService participantService ,
32+ PriorityService priorityService ,
33+ ParticipantRepository participantRepository ) {
34+ this .participantService = participantService ;
35+ this .priorityService = priorityService ;
36+ this .participantRepository = participantRepository ;
37+ }
2238
2339 // 0.2 참여자 추가/삭제
2440 @ Operation (
@@ -32,7 +48,9 @@ public class ParticipantController {
3248 @ ApiResponse (responseCode = "404" , description = "투표를 찾을 수 없음" , content = @ Content )
3349 })
3450 @ PostMapping ("/votes/{voteId}/participants" )
35- public ResponseEntity <ParticipantDtos .ParticipantRes > add (@ PathVariable Long voteId , @ RequestBody @ Valid ParticipantDtos .CreateParticipantReq req ) {
51+ public ResponseEntity <ParticipantDtos .ParticipantRes > add (
52+ @ PathVariable Long voteId ,
53+ @ RequestBody @ Valid ParticipantDtos .CreateParticipantReq req ) {
3654 var res = participantService .add (voteId , req .displayName ());
3755 return ResponseEntity .ok (res );
3856 }
@@ -50,4 +68,94 @@ public ResponseEntity<Void> remove(@PathVariable Long participantId) {
5068 participantService .remove (participantId );
5169 return ResponseEntity .noContent ().build ();
5270 }
71+
72+ @ Operation (
73+ summary = "참여자 목록 조회 (로그인 칩)" ,
74+ description = "어드민이 등록한 참여자 목록을 읽어와 로그인 칩 형태로 제공합니다. " +
75+ "현재 로그인한 참여자는 loggedIn 상태로 표시됩니다."
76+ )
77+ @ ApiResponses ({
78+ @ ApiResponse (responseCode = "200" , description = "참여자 목록 조회 성공" ),
79+ @ ApiResponse (responseCode = "404" , description = "투표를 찾을 수 없음" )
80+ })
81+ @ GetMapping ("/votes/{voteId}/participants" )
82+ public ResponseEntity <List <ParticipantDtos .ParticipantRes >> getParticipants (
83+ @ PathVariable Long voteId ,
84+ @ RequestParam (required = false ) Long currentParticipantId
85+ ) {
86+ List <ParticipantDtos .ParticipantRes > participants =
87+ participantService .getParticipantsForVote (voteId , currentParticipantId );
88+ return ResponseEntity .ok (participants );
89+ }
90+
91+ /**
92+ * PATCH /participants/{id}/info
93+ * 참여자 정보 부분 수정 (리플렉션)
94+ */
95+ @ PatchMapping ("/participants/{id}/info" )
96+ public ResponseEntity <ParticipantDtos .ParticipantRes > updateParticipant (
97+ @ PathVariable Long id ,
98+ @ RequestBody Map <String , Object > updates ) {
99+
100+ Participant participant = participantRepository .findById (id )
101+ .orElseThrow (() -> new RuntimeException ("Not found" ));
102+
103+ updates .forEach ((key , value ) -> {
104+ Field field = ReflectionUtils .findField (Participant .class , key );
105+ if (field != null ) {
106+ field .setAccessible (true );
107+ ReflectionUtils .setField (field , participant , value );
108+ }
109+ });
110+
111+ Participant saved = participantRepository .save (participant );
112+
113+ // DTO로 변환해서 반환!
114+ ParticipantDtos .ParticipantRes response = new ParticipantDtos .ParticipantRes (
115+ saved .getId (),
116+ saved .getDisplayName (),
117+ false // loggedIn 상태
118+ );
119+
120+ return ResponseEntity .ok (response );
53121}
122+
123+ /**
124+ * POST /participants/{participantId}
125+ * 우선순위 설정 (최대 3개)
126+ */
127+ @ PostMapping ("/participants/{participantId}" )
128+ public ResponseEntity <PriorityResponse > setPriorities (
129+ @ PathVariable Long participantId ,
130+ @ RequestParam Long voteId ,
131+ @ Valid @ RequestBody PriorityRequest request ,
132+ @ RequestParam (required = false , defaultValue = "db" ) String storage ,
133+ @ RequestParam (required = false , defaultValue = "false" ) boolean dryRun ,
134+ HttpSession session ) {
135+
136+ PriorityResponse response = priorityService .setPriorities (
137+ participantId ,
138+ voteId ,
139+ request ,
140+ storage ,
141+ dryRun ,
142+ session
143+ );
144+
145+ return ResponseEntity .ok (response );
146+ }
147+
148+ /**
149+ * PATCH /participants/{participantId}/schedule
150+ * 일정 제출
151+ */
152+ @ PatchMapping ("/participants/{participantId}/schedule" )
153+ public ResponseEntity <ParticipantDtos .ParticipantScheduleRes > submitSchedule (
154+ @ PathVariable Long participantId ,
155+ @ Valid @ RequestBody ParticipantDtos .SubmitScheduleReq request ) {
156+
157+ ParticipantDtos .ParticipantScheduleRes response =
158+ participantService .submitSchedule (participantId , request );
159+ return ResponseEntity .ok (response );
160+ }
161+ }
0 commit comments