372372 }
373373
374374 .discussion-item {
375- background : # 222 ;
376- border-radius : 10 px ;
375+ background : # 23272f ;
376+ border-radius : 12 px ;
377377 margin-bottom : 18px ;
378- padding : 18px 16px ;
379- box-shadow : 0 2px 8px rgba (0 , 0 , 0 , 0.10 );
380- transition : box-shadow 0.2s ;
378+ padding : 22px 18px 18px 18px ;
379+ box-shadow : 0 4px 18px rgba (0 , 0 , 0 , 0.18 );
380+ border : 1.5px solid # 2d323c ;
381+ transition : box-shadow 0.2s , border 0.2s ;
381382 }
382383
383384 .discussion-item : hover {
384- box-shadow : 0 4px 16px rgba (0 , 0 , 0 , 0.18 );
385+ box-shadow : 0 8px 28px rgba (0 , 0 , 0 , 0.28 );
386+ border-color : # 00d084 ;
385387 }
386388
387389 /* Header (profile/nickname) */
390392 align-items : center;
391393 gap : 8px ;
392394 margin-bottom : 2px ;
395+ margin-top : 8px ;
393396 }
394397
395398 .discussion-header img {
779782 border-color : # 00d084 ;
780783 font-weight : 700 ;
781784 }
785+ .lang-tag {
786+ display : inline-block;
787+ background : # 2d323c ;
788+ color : # 00e09e ;
789+ font-size : 13px ;
790+ font-weight : 600 ;
791+ border-radius : 12px ;
792+ padding : 4px 16px ;
793+ margin-bottom : 14px ;
794+ margin-top : 2px ;
795+ margin-right : 0 ;
796+ letter-spacing : 0.5px ;
797+ }
782798 </ style >
783799</ head >
784800
800816 < li > 메모리 제한: < span id ="prob-mem "> --</ span > KB</ li >
801817 < li > 카테고리: < span id ="prob-cats "> --</ span > </ li >
802818 </ ul >
819+
820+ < div id ="prob-image-wrapper ">
821+ < img id ="prob-image " src ="" alt ="문제 이미지 " style ="max-width: 100%; height: auto; " />
822+ </ div >
803823 </ div >
804824
805825 < div id ="discussion-content " class ="left-content ">
816836 < div id ="discussion-pagination "> </ div >
817837 </ div >
818838
819- < div id ="prob-image-wrapper ">
820- < img id ="prob-image " src ="" alt ="문제 이미지 " style ="max-width: 100%; height: auto; " />
821- </ div >
822-
823839 </ div >
824840 < div class ="right ">
825841 < div class ="section ">
@@ -873,12 +889,48 @@ <h3>채점 결과</h3>
873889
874890 const DEFAULT_PROFILE_IMG = "/static/images/user-icon.png" ; // 임의 프사 경로
875891
892+ // ====== 언어 목록 불러오기 및 전역 저장 ======
893+ async function loadLanguages ( ) {
894+ try {
895+ const res = await fetch ( '/api/languages' ) ;
896+ const data = await res . json ( ) ;
897+ if ( data . success ) {
898+ window . languageList = data . result ;
899+ } else {
900+ window . languageList = [ ] ;
901+ }
902+ } catch {
903+ window . languageList = [ ] ;
904+ }
905+ }
906+ // 언어 드롭다운 HTML 생성
907+ function getLanguageSelectHtml ( selectedId ) {
908+ if ( ! window . languageList ) return '' ;
909+ return `
910+ <select class="discussion-language-select">
911+ ${ window . languageList . map ( lang =>
912+ `<option value="${ lang . id } " ${ lang . id === selectedId ? 'selected' : '' } >
913+ ${ lang . name } ${ lang . version }
914+ </option>`
915+ ) . join ( '' ) }
916+ </select>
917+ ` ;
918+ }
919+ // 언어 id로 name+version 반환
920+ function getLanguageTagById ( id ) {
921+ if ( ! window . languageList ) return '' ;
922+ const lang = window . languageList . find ( l => l . id === id ) ;
923+ return lang ? `${ lang . name } ${ lang . version } ` : '' ;
924+ }
925+
876926 function tokenHeader ( ) {
877927 const token = sessionStorage . getItem ( 'accessToken' ) ;
878928 return token ? { 'Authorization' : token . startsWith ( 'Bearer ' ) ? token : 'Bearer ' + token } : { } ;
879929 }
880930
881- window . addEventListener ( 'DOMContentLoaded' , ( ) => {
931+ window . addEventListener ( 'DOMContentLoaded' , async ( ) => {
932+ await loadLanguages ( ) ;
933+ renderDiscussionCreateBox ( ) ; // 언어 목록 로드 후 호출
882934 const pid = new URLSearchParams ( location . search ) . get ( 'problemId' ) ;
883935 if ( pid ) {
884936 window . problemId = pid ;
@@ -1180,6 +1232,7 @@ <h3>채점 결과</h3>
11801232 listEl . innerHTML = discussions . map ( d => {
11811233 return `
11821234 <div class="discussion-item" data-discussion-id="${ d . discussionId } ">
1235+ <span class="lang-tag">${ getLanguageTagById ( d . languageId ) } </span>
11831236 <div class="discussion-header">
11841237 <img src="${ d . userInfo . profileImageUrl || DEFAULT_PROFILE_IMG } " alt="profile">
11851238 <span class="nickname">${ d . userInfo . nickname } </span>
@@ -1409,10 +1462,22 @@ <h3>채점 결과</h3>
14091462 const oldContent = contentEl . textContent ;
14101463 // 이미 수정창이 열려있으면 return
14111464 if ( item . querySelector ( '.edit-input-box' ) ) return ;
1412- // textarea + 취소/저장 버튼
1465+ // 기존 언어 id (discussion-item만)
1466+ let oldLangId = 1 ;
1467+ if ( item . classList . contains ( 'discussion-item' ) ) {
1468+ // lang-tag에서 id 추출
1469+ const langTag = item . querySelector ( '.lang-tag' ) ;
1470+ if ( langTag ) {
1471+ const text = langTag . textContent . trim ( ) ;
1472+ const found = window . languageList ?. find ( l => text . startsWith ( l . name ) ) ;
1473+ if ( found ) oldLangId = found . id ;
1474+ }
1475+ }
1476+ // textarea + 언어 드롭다운 + 취소/저장 버튼
14131477 const box = document . createElement ( 'div' ) ;
14141478 box . className = 'edit-input-box' ;
14151479 box . innerHTML = `
1480+ <div style="margin-bottom:8px;">${ item . classList . contains ( 'discussion-item' ) ? getLanguageSelectHtml ( oldLangId ) : '' } </div>
14161481 <textarea class="edit-input-text" style="width:100%;min-height:60px;">${ oldContent } </textarea>
14171482 <div style="display:flex;gap:8px;justify-content:flex-end;">
14181483 <button class="edit-cancel-btn">취소</button>
@@ -1431,13 +1496,19 @@ <h3>채점 결과</h3>
14311496 // 저장
14321497 box . querySelector ( '.edit-save-btn' ) . onclick = async ( ) => {
14331498 const newContent = box . querySelector ( '.edit-input-text' ) . value . trim ( ) ;
1499+ let newLangId = oldLangId ;
1500+ if ( item . classList . contains ( 'discussion-item' ) ) {
1501+ newLangId = + box . querySelector ( '.discussion-language-select' ) . value ;
1502+ }
14341503 if ( ! newContent ) return alert ( '내용을 입력하세요.' ) ;
1435- let url , method = 'PUT' , payload = { languageId : 1 , content : newContent } ;
1504+ let url , method = 'PUT' , payload = { languageId : newLangId , content : newContent } ;
14361505 if ( item . classList . contains ( 'discussion-item' ) ) {
14371506 url = `/api/problems/${ window . problemId } /discussions/${ e . target . dataset . id } ` ;
14381507 } else {
14391508 const discussionId = item . closest ( '.discussion-item' ) . dataset . discussionId ;
14401509 url = `/api/problems/${ window . problemId } /discussions/${ discussionId } /replies/${ e . target . dataset . id } ` ;
1510+ // 대댓글/댓글은 언어 변경 불가 (기존대로 1)
1511+ payload . languageId = 1 ;
14411512 }
14421513 const res = await fetch ( url , {
14431514 method,
@@ -1659,7 +1730,13 @@ <h3>채점 결과</h3>
16591730
16601731 function renderDiscussionCreateBox ( ) {
16611732 const box = document . getElementById ( 'discussion-create-box' ) ;
1733+ if ( ! window . languageList || window . languageList . length === 0 ) {
1734+ box . innerHTML = '<div style="color:#aaa;">언어 목록을 불러오는 중...</div>' ;
1735+ return ;
1736+ }
1737+ // 언어 드롭다운 + textarea
16621738 box . innerHTML = `
1739+ <div style="margin-bottom:8px;">${ getLanguageSelectHtml ( window . languageList ?. [ 0 ] ?. id || 1 ) } </div>
16631740 <textarea id="discussion-create-text" class="reply-input-text" rows="4" placeholder="토론글을 작성해보세요"></textarea>
16641741 <div style="display:flex;gap:10px;justify-content:flex-end;">
16651742 <button id="discussion-create-cancel" class="reply-cancel-btn">취소</button>
@@ -1673,6 +1750,7 @@ <h3>채점 결과</h3>
16731750 // 작성
16741751 box . querySelector ( '#discussion-create-submit' ) . onclick = async ( ) => {
16751752 const content = box . querySelector ( '#discussion-create-text' ) . value . trim ( ) ;
1753+ const langId = + box . querySelector ( '.discussion-language-select' ) . value ;
16761754 if ( ! content ) return alert ( '내용을 입력하세요.' ) ;
16771755 const token = sessionStorage . getItem ( 'accessToken' ) ;
16781756 const res = await fetch ( `/api/problems/${ window . problemId } /discussions` , {
@@ -1681,7 +1759,7 @@ <h3>채점 결과</h3>
16811759 'Content-Type' : 'application/json' ,
16821760 ...tokenHeader ( )
16831761 } ,
1684- body : JSON . stringify ( { languageId : 1 , content } )
1762+ body : JSON . stringify ( { languageId : langId , content } )
16851763 } ) ;
16861764 if ( res . ok ) {
16871765 // 성공: 입력창 비우고 목록 새로고침
0 commit comments