From 3d4c38a64b8468ed2b58e4aec06c6405313c9538 Mon Sep 17 00:00:00 2001 From: SeungWoo Ryu Date: Tue, 8 Jul 2025 23:53:18 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat=20:=20=ED=86=A0=EB=A1=A0=EA=B8=80=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20=EC=8B=9C=20languageI?= =?UTF-8?q?d=20=ED=95=84=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../community/dto/response/DiscussionResponse.java | 7 ++++++- .../domain/community/dto/DiscussionQueryResult.java | 4 ++++ .../codetest/domain/community/model/entity/Discussion.java | 3 +++ .../discussion/DiscussionQueryRepositoryImpl.java | 5 +---- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/ezcode/codetest/application/community/dto/response/DiscussionResponse.java b/src/main/java/org/ezcode/codetest/application/community/dto/response/DiscussionResponse.java index 48ae091a..a5871530 100644 --- a/src/main/java/org/ezcode/codetest/application/community/dto/response/DiscussionResponse.java +++ b/src/main/java/org/ezcode/codetest/application/community/dto/response/DiscussionResponse.java @@ -23,6 +23,9 @@ public record DiscussionResponse( @Schema(description = "관련 문제 ID", example = "45", requiredMode = REQUIRED) Long problemId, + @Schema(description = "언어 ID", example = "1", requiredMode = REQUIRED) + Long languageId, + @Schema(description = "토론 내용", example = "이 문제는 이렇게 풀 수 있습니다...", requiredMode = REQUIRED) String content, @@ -50,7 +53,8 @@ public static DiscussionResponse fromEntity(Discussion discussion) { return new DiscussionResponse( discussion.getId(), SimpleUserInfoResponse.fromEntity(discussion.getUser()), - discussion.getProblem().getId(), + discussion.getProblemId(), + discussion.getLanguageId(), discussion.getContent(), discussion.getCreatedAt(), null, @@ -66,6 +70,7 @@ public static DiscussionResponse from(DiscussionQueryResult result) { result.getDiscussionId(), result.getUserInfo(), result.getProblemId(), + result.getLanguageId(), result.getContent(), result.getCreatedAt(), result.getUpvoteCount(), diff --git a/src/main/java/org/ezcode/codetest/domain/community/dto/DiscussionQueryResult.java b/src/main/java/org/ezcode/codetest/domain/community/dto/DiscussionQueryResult.java index bbc7cec3..223c3981 100644 --- a/src/main/java/org/ezcode/codetest/domain/community/dto/DiscussionQueryResult.java +++ b/src/main/java/org/ezcode/codetest/domain/community/dto/DiscussionQueryResult.java @@ -18,6 +18,8 @@ public class DiscussionQueryResult { private final Long problemId; + private final Long languageId; + private final String content; private final LocalDateTime createdAt; @@ -37,6 +39,7 @@ public DiscussionQueryResult( Long discussionId, SimpleUserInfoResponse userInfo, Long problemId, + Long languageId, String content, LocalDateTime createdAt, Long upvoteCount, @@ -48,6 +51,7 @@ public DiscussionQueryResult( this.discussionId = discussionId; this.userInfo = userInfo; this.problemId = problemId; + this.languageId = languageId; this.content = content; this.createdAt = createdAt; this.upvoteCount = upvoteCount; diff --git a/src/main/java/org/ezcode/codetest/domain/community/model/entity/Discussion.java b/src/main/java/org/ezcode/codetest/domain/community/model/entity/Discussion.java index 042feec6..e9bde460 100644 --- a/src/main/java/org/ezcode/codetest/domain/community/model/entity/Discussion.java +++ b/src/main/java/org/ezcode/codetest/domain/community/model/entity/Discussion.java @@ -81,4 +81,7 @@ public Long getProblemId() { return this.problem.getId(); } + public Long getLanguageId() { + return this.language.getId(); + } } diff --git a/src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/community/discussion/DiscussionQueryRepositoryImpl.java b/src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/community/discussion/DiscussionQueryRepositoryImpl.java index c86e4fb7..50df51b5 100644 --- a/src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/community/discussion/DiscussionQueryRepositoryImpl.java +++ b/src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/community/discussion/DiscussionQueryRepositoryImpl.java @@ -41,10 +41,6 @@ public List findDiscussionIdsByProblemId(Long problemId, String sortBy, Pa NumberExpression bestScore = upvoteCount.subtract(downvoteCount); - long offset = pageable.getOffset(); - int pageNumber = pageable.getPageNumber(); - int pageSize = pageable.getPageSize(); - return jpaQueryFactory .select(discussion.id) .from(discussion) @@ -91,6 +87,7 @@ public List findDiscussionsByIds(List discussionIds user.profileImageUrl ), discussion.problem.id, + discussion.language.id, discussion.content, discussion.createdAt, upvoteCount, From e9ce4cc883cf867abe10103dffc4b54925e3eb76 Mon Sep 17 00:00:00 2001 From: SeungWoo Ryu Date: Wed, 9 Jul 2025 00:18:20 +0900 Subject: [PATCH 2/2] =?UTF-8?q?feat=20:=20=ED=94=84=EB=A1=A0=ED=8A=B8=20?= =?UTF-8?q?=ED=86=A0=EB=A1=A0=EA=B8=80=20=EC=83=9D=EC=84=B1,=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=EC=8B=9C=20=EC=96=B8=EC=96=B4=20=EC=84=A0=ED=83=9D?= =?UTF-8?q?=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/templates/test-submit.html | 106 +++++++++++++++--- 1 file changed, 92 insertions(+), 14 deletions(-) diff --git a/src/main/resources/templates/test-submit.html b/src/main/resources/templates/test-submit.html index d66e9c9c..db43c97a 100644 --- a/src/main/resources/templates/test-submit.html +++ b/src/main/resources/templates/test-submit.html @@ -372,16 +372,18 @@ } .discussion-item { - background: #222; - border-radius: 10px; + background: #23272f; + border-radius: 12px; margin-bottom: 18px; - padding: 18px 16px; - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.10); - transition: box-shadow 0.2s; + padding: 22px 18px 18px 18px; + box-shadow: 0 4px 18px rgba(0,0,0,0.18); + border: 1.5px solid #2d323c; + transition: box-shadow 0.2s, border 0.2s; } .discussion-item:hover { - box-shadow: 0 4px 16px rgba(0, 0, 0, 0.18); + box-shadow: 0 8px 28px rgba(0,0,0,0.28); + border-color: #00d084; } /* Header (profile/nickname) */ @@ -390,6 +392,7 @@ align-items: center; gap: 8px; margin-bottom: 2px; + margin-top: 8px; } .discussion-header img { @@ -779,6 +782,19 @@ border-color: #00d084; font-weight: 700; } + .lang-tag { + display: inline-block; + background: #2d323c; + color: #00e09e; + font-size: 13px; + font-weight: 600; + border-radius: 12px; + padding: 4px 16px; + margin-bottom: 14px; + margin-top: 2px; + margin-right: 0; + letter-spacing: 0.5px; + } @@ -800,6 +816,10 @@
  • 메모리 제한: -- KB
  • 카테고리: --
  • + +
    + 문제 이미지 +
    @@ -816,10 +836,6 @@
    -
    - 문제 이미지 -
    -
    @@ -873,12 +889,48 @@

    채점 결과

    const DEFAULT_PROFILE_IMG = "/static/images/user-icon.png"; // 임의 프사 경로 + // ====== 언어 목록 불러오기 및 전역 저장 ====== + async function loadLanguages() { + try { + const res = await fetch('/api/languages'); + const data = await res.json(); + if (data.success) { + window.languageList = data.result; + } else { + window.languageList = []; + } + } catch { + window.languageList = []; + } + } + // 언어 드롭다운 HTML 생성 + function getLanguageSelectHtml(selectedId) { + if (!window.languageList) return ''; + return ` + + `; + } + // 언어 id로 name+version 반환 + function getLanguageTagById(id) { + if (!window.languageList) return ''; + const lang = window.languageList.find(l => l.id === id); + return lang ? `${lang.name} ${lang.version}` : ''; + } + function tokenHeader() { const token = sessionStorage.getItem('accessToken'); return token ? { 'Authorization': token.startsWith('Bearer ') ? token : 'Bearer ' + token } : {}; } - window.addEventListener('DOMContentLoaded', () => { + window.addEventListener('DOMContentLoaded', async () => { + await loadLanguages(); + renderDiscussionCreateBox(); // 언어 목록 로드 후 호출 const pid = new URLSearchParams(location.search).get('problemId'); if (pid) { window.problemId = pid; @@ -1180,6 +1232,7 @@

    채점 결과

    listEl.innerHTML = discussions.map(d => { return `
    + ${getLanguageTagById(d.languageId)}
    profile ${d.userInfo.nickname} @@ -1409,10 +1462,22 @@

    채점 결과

    const oldContent = contentEl.textContent; // 이미 수정창이 열려있으면 return if (item.querySelector('.edit-input-box')) return; - // textarea + 취소/저장 버튼 + // 기존 언어 id (discussion-item만) + let oldLangId = 1; + if (item.classList.contains('discussion-item')) { + // lang-tag에서 id 추출 + const langTag = item.querySelector('.lang-tag'); + if (langTag) { + const text = langTag.textContent.trim(); + const found = window.languageList?.find(l => text.startsWith(l.name)); + if (found) oldLangId = found.id; + } + } + // textarea + 언어 드롭다운 + 취소/저장 버튼 const box = document.createElement('div'); box.className = 'edit-input-box'; box.innerHTML = ` +
    ${item.classList.contains('discussion-item') ? getLanguageSelectHtml(oldLangId) : ''}
    @@ -1431,13 +1496,19 @@

    채점 결과

    // 저장 box.querySelector('.edit-save-btn').onclick = async () => { const newContent = box.querySelector('.edit-input-text').value.trim(); + let newLangId = oldLangId; + if (item.classList.contains('discussion-item')) { + newLangId = +box.querySelector('.discussion-language-select').value; + } if (!newContent) return alert('내용을 입력하세요.'); - let url, method = 'PUT', payload = { languageId: 1, content: newContent }; + let url, method = 'PUT', payload = { languageId: newLangId, content: newContent }; if (item.classList.contains('discussion-item')) { url = `/api/problems/${window.problemId}/discussions/${e.target.dataset.id}`; } else { const discussionId = item.closest('.discussion-item').dataset.discussionId; url = `/api/problems/${window.problemId}/discussions/${discussionId}/replies/${e.target.dataset.id}`; + // 대댓글/댓글은 언어 변경 불가 (기존대로 1) + payload.languageId = 1; } const res = await fetch(url, { method, @@ -1659,7 +1730,13 @@

    채점 결과

    function renderDiscussionCreateBox() { const box = document.getElementById('discussion-create-box'); + if (!window.languageList || window.languageList.length === 0) { + box.innerHTML = '
    언어 목록을 불러오는 중...
    '; + return; + } + // 언어 드롭다운 + textarea box.innerHTML = ` +
    ${getLanguageSelectHtml(window.languageList?.[0]?.id || 1)}
    @@ -1673,6 +1750,7 @@

    채점 결과

    // 작성 box.querySelector('#discussion-create-submit').onclick = async () => { const content = box.querySelector('#discussion-create-text').value.trim(); + const langId = +box.querySelector('.discussion-language-select').value; if (!content) return alert('내용을 입력하세요.'); const token = sessionStorage.getItem('accessToken'); const res = await fetch(`/api/problems/${window.problemId}/discussions`, { @@ -1681,7 +1759,7 @@

    채점 결과

    'Content-Type': 'application/json', ...tokenHeader() }, - body: JSON.stringify({ languageId: 1, content }) + body: JSON.stringify({ languageId: langId, content }) }); if (res.ok) { // 성공: 입력창 비우고 목록 새로고침