Skip to content

Commit d9bc084

Browse files
committed
[fix]: 낱말 수정 api에서 userCategoryId만 사용하도록 수정
1 parent 3497b1e commit d9bc084

File tree

5 files changed

+36
-18
lines changed

5 files changed

+36
-18
lines changed

src/words/controllers/words.controller.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ export class WordsController {
9797
const updateDto = new UpdateWordDto({
9898
word: req.body.word,
9999
imageUrl: req.body.imageUrl,
100-
categoryId: req.body.categoryId
100+
userCategoryId: req.body.categoryId
101101
});
102102

103103
// 유효성 검증
@@ -108,7 +108,7 @@ export class WordsController {
108108
cardId,
109109
updateDto.word,
110110
updateDto.imageUrl,
111-
updateDto.categoryId
111+
updateDto.userCategoryId
112112
);
113113

114114
return res.success({ word: updatedWord }, '낱말 카드 수정 성공');

src/words/dto/words.dto.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,14 @@ export class UpdateFavoriteDto {
7171
* PATCH /api/words/:cardId - Update Word Request DTO
7272
*/
7373
export class UpdateWordDto {
74-
constructor({ word, imageUrl, categoryId }) {
74+
constructor({ word, imageUrl, userCategoryId }) {
7575
this.word = word;
7676
this.imageUrl = imageUrl;
77-
this.categoryId = categoryId ? String(categoryId) : null;
77+
this.userCategoryId = userCategoryId ? String(userCategoryId) : null;
7878
}
7979

8080
validate() {
81-
if (!this.word && !this.imageUrl && !this.categoryId) {
81+
if (!this.word && !this.imageUrl && !this.userCategoryId) {
8282
throw new Error('word, imageUrl, categoryId 중 하나는 필수입니다');
8383
}
8484
}

src/words/repositories/words.repository.js

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -301,18 +301,20 @@ export class WordsRepository {
301301
}
302302

303303
/**
304-
* UserWord 업데이트 (customWord, customImageUrl, categoryId)
305-
* @param {string} userWordId - UserWord.id
306-
* @param {string|null} customWord
307-
* @param {string|null} customImageUrl
308-
* @param {string|null} categoryId
309-
* @returns {Promise<Object>}
310-
*/
311-
async updateUserWord(userWordId, customWord, customImageUrl, categoryId) {
304+
* UserWord 업데이트 (customWord, customImageUrl, userCategoryId, displayOrder)
305+
* @param {string} userWordId - UserWord.id
306+
* @param {string|null} customWord
307+
* @param {string|null} customImageUrl
308+
* @param {string|null} userCategoryId
309+
* @param {number|undefined} displayOrder
310+
* @returns {Promise<Object>}
311+
*/
312+
async updateUserWord(userWordId, customWord, customImageUrl, userCategoryId, displayOrder) {
312313
const data = {};
313314
if (customWord !== undefined) data.customWord = customWord;
314315
if (customImageUrl !== undefined) data.customImageUrl = customImageUrl;
315-
if (categoryId !== undefined && categoryId !== null) data.categoryId = categoryId;
316+
if (userCategoryId !== undefined && userCategoryId !== null) data.userCategoryId = userCategoryId;
317+
if (displayOrder !== undefined) data.displayOrder = displayOrder;
316318

317319
return await prisma.userWord.update({
318320
where: { id: userWordId },

src/words/routes/words.route.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,6 @@ router.get('/', optionalAuthenticate, wordsController.getWords.bind(wordsControl
8080
* summary: 개인 낱말 카드 추가
8181
* description: 사용자가 직접 낱말 카드를 추가합니다. NLP로 품사를 자동 분석합니다.
8282
* tags: [Words]
83-
* security:
84-
* - bearerAuth: []
8583
* requestBody:
8684
* required: true
8785
* content:

src/words/services/words.service.js

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,13 +224,31 @@ export class WordsService {
224224
* @param {string|undefined} categoryId - 변경할 카테고리 ID
225225
* @returns {Promise<WordCardResponseDto>}
226226
*/
227-
async updateWord(userId, cardId, word, imageUrl, categoryId) {
227+
async updateWord(userId, cardId, word, imageUrl, userCategoryId) {
228228
// 무조건 UserWord만 수정: 기본 Word 복사/생성 로직 제거
229229
const userWord = await wordsRepository.findUserWordById(cardId);
230230
if (!userWord) {
231231
throw new Error('존재하지 않는 UserWord입니다');
232232
}
233-
const updatedUserWord = await wordsRepository.updateUserWord(cardId, word, imageUrl, categoryId);
233+
234+
let displayOrder = undefined;
235+
// 카테고리 변경 시 displayOrder 맨 뒤로 이동 및 기존 카테고리 재정렬
236+
if (userCategoryId && userWord.userCategoryId !== userCategoryId) {
237+
// 1. 이동될 카테고리 맨 뒤로
238+
displayOrder = await this.getNextDisplayOrder(userId, null, userCategoryId);
239+
240+
// 2. 기존 카테고리 displayOrder 재정렬
241+
const prevCategoryId = userWord.userCategoryId;
242+
if (prevCategoryId) {
243+
const prevWords = await wordsRepository.findUserWords(userId, prevCategoryId, false, false);
244+
// 이동된 단어 제외
245+
const filtered = prevWords.filter(w => w.id !== cardId);
246+
const updates = filtered.map((w, idx) => ({ userWordId: w.id, displayOrder: idx }));
247+
await wordsRepository.bulkUpdateDisplayOrders(updates);
248+
}
249+
}
250+
251+
const updatedUserWord = await wordsRepository.updateUserWord(cardId, word, imageUrl, userCategoryId, displayOrder);
234252
return new WordCardResponseDto({
235253
cardId: updatedUserWord.id,
236254
categoryId: updatedUserWord.userCategoryId,

0 commit comments

Comments
 (0)