Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
5ea7ece
feat: chat 폴더 ꡬ쑰 μž¬μƒμ„±
Arin0303 Jan 19, 2026
83b3971
feat: μ±„νŒ…λ°© 생성/λ°˜ν™˜ λΌμš°ν„° μž‘μ„±
Arin0303 Jan 19, 2026
ce13456
add: λΌμš°ν„° 등둝 μ½”λ“œ μΆ”κ°€
Arin0303 Jan 19, 2026
a3a8a32
add: λΌμš°ν„° 등둝 μ½”λ“œ μΆ”κ°€
Arin0303 Jan 19, 2026
37aaa28
feat:μ±„νŒ…λ°© 생성 컨트둀러 μž‘μ„±
Arin0303 Jan 19, 2026
6914886
fix: controller에 dto 반영
Arin0303 Jan 19, 2026
1b4cb15
dto λ³€μˆ˜ 넀이밍 μˆ˜μ •
Arin0303 Jan 19, 2026
1ad8e88
controller에 응닡 νƒ€μž… 반영
Arin0303 Jan 19, 2026
ecc3ab6
feat: repository μ½”λ“œ μž‘μ„±
Arin0303 Jan 19, 2026
aa23750
feat: controller λ³€μˆ˜ 넀이밍 였λ₯˜ μˆ˜μ •
Arin0303 Jan 19, 2026
3a8693e
feat: service ν•¨μˆ˜ μž‘μ„±
Arin0303 Jan 19, 2026
2f57957
feat: μ±„νŒ… λΌμš°ν„° 등둝
Arin0303 Jan 19, 2026
b044064
feat: μ±„νŒ…λ°© 등둝 swagger 문법 였λ₯˜ μˆ˜μ •
Arin0303 Jan 19, 2026
ecfdd16
feat: μ±„νŒ…λ°© 등둝 swagger 문법 였λ₯˜ μˆ˜μ •
Arin0303 Jan 19, 2026
3aa7e4c
feat: μ±„νŒ…λ°© 상세 쑰회 dto 생성
Arin0303 Jan 19, 2026
5875e02
feat: μ±„νŒ…λ°© 생성 repositoryλ₯Ό class ν˜•μ‹μœΌλ‘œ λ³€ν™˜
Arin0303 Jan 19, 2026
cffb09c
feat: μ±„νŒ…λ°© 상세 쑰회 repository μž‘μ„±
Arin0303 Jan 19, 2026
170947c
fix: κΈ°μ‘΄ service계측을 class ν˜•νƒœλ‘œ λ¦¬νŒ©ν† λ§
Arin0303 Jan 20, 2026
7032b9d
feat: μ±„νŒ…λ°© 상세 쑰회, μ±„νŒ…λ°© 생성 κΈ°λŠ₯
Arin0303 Jan 20, 2026
4eb691d
fix: μ±„νŒ… μ°Έμ—¬μž μŠ€ν‚€λ§ˆμ— unread_count ν•„λ“œ μΆ”κ°€
Arin0303 Jan 21, 2026
534c7f4
fix: μ±„νŒ… μ°Έμ—¬μž μŠ€ν‚€λ§ˆμ— unread_count ν•„λ“œ μΆ”κ°€
Arin0303 Jan 21, 2026
91b73e4
feat: μ±„νŒ…λ°© 생성, 상세 쑰회, λͺ©λ‘ 쑰회 κ΅¬ν˜„ 1μ°¨ μ™„λ£Œ
Arin0303 Jan 21, 2026
3381aab
feat: 둜컬 μ‹€ν–‰ 슀크립트 μ‹€ν–‰μ‹œ .env.devλ₯Ό 바라보도둝 μˆ˜μ •
Arin0303 Jan 22, 2026
10c464e
fix: swagger 응닡 ꡬ쑰 μˆ˜μ •
Arin0303 Jan 22, 2026
bf49243
feat: μ±„νŒ…λ°© 생성, 상세 쑰회, λͺ©λ‘ 쑰회 2μ°¨ μˆ˜μ •
Arin0303 Jan 22, 2026
bed3ff7
feat: μ±„νŒ…λ°© 상세 μ‘°νšŒμ—μ„œ λ‚˜κ°„ μ‹œκ°„ μ΄ν›„μ˜ λ©”μ„Έμ§€λ“€λ§Œ 쑰회
Arin0303 Jan 22, 2026
47a9273
fix: swagger에 statusCode 응닡 μΆ”κ°€
Arin0303 Jan 22, 2026
a44036b
fix: profile_image_url 응닡 였λ₯˜ μˆ˜μ •
Arin0303 Jan 22, 2026
13835ae
feat: unread_count ν•„λ“œ 응닡 μˆ˜μ •
Arin0303 Jan 22, 2026
839b264
Merge pull request #388 from PromptPlace/feat/#387
Arin0303 Jan 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "1.0.0",
"main": "index.js",
"scripts": {
"dev": "ts-node-dev --respawn --transpile-only src/index.ts",
"dev": "dotenv -e .env.dev -- ts-node-dev --respawn --transpile-only src/index.ts",
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node dist/index.js",
"prebuild": "npm run generate:swagger",
Expand Down Expand Up @@ -68,6 +68,7 @@
"@types/swagger-jsdoc": "^6.0.4",
"@types/swagger-ui-express": "^4.1.8",
"@types/uuid": "^10.0.0",
"dotenv-cli": "^11.0.0",
"nodemon": "^3.1.10",
"prisma": "^6.11.1",
"ts-node": "^10.9.2",
Expand Down
22 changes: 22 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE `ChatParticipant` ADD COLUMN `unreadCount` INTEGER NOT NULL DEFAULT 0;
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
Warnings:

- You are about to drop the column `unreadCount` on the `ChatParticipant` table. All the data in the column will be lost.

*/
-- AlterTable
ALTER TABLE `ChatParticipant` DROP COLUMN `unreadCount`,
ADD COLUMN `unread_count` INTEGER NOT NULL DEFAULT 0;
3 changes: 2 additions & 1 deletion prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -515,11 +515,12 @@ model ChatParticipant {
room_id Int
user_id Int
last_read_message_id Int?
unread_count Int @default(0)

chatRoom ChatRoom @relation("RoomParticipants", fields: [room_id], references: [room_id], onDelete: Cascade)
user User @relation(fields: [user_id], references: [user_id], onDelete: Cascade)
lastReadMessage ChatMessage? @relation("LastReadMessage", fields: [last_read_message_id], references: [message_id], onDelete: SetNull)

@@unique([room_id, user_id])
}

Expand Down
107 changes: 107 additions & 0 deletions src/chat/controllers/chat.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import { Request, Response } from "express";
import { chatService } from "../services/chat.service";
import {
CreateChatRoomRequestDto,
GetChatRoomListRequestDto,
ChatFilterType
} from "../dtos/chat.dto";

export const createOrGetChatRoom = async (req: Request, res: Response): Promise<void> => {
if (!req.user) {
res.fail({
statusCode: 401,
error: "no user",
message: "둜그인이 ν•„μš”ν•©λ‹ˆλ‹€.",
});
return;
}

try {
const userId = (req.user as { user_id: number }).user_id;
const { partner_id } = req.body as CreateChatRoomRequestDto;

const result = await chatService.createOrGetChatRoomService(userId, partner_id);

res.success(result, "μ±„νŒ…λ°©μ„ μ„±κ³΅μ μœΌλ‘œ 생성/λ°˜ν™˜ν–ˆμŠ΅λ‹ˆλ‹€.");
} catch (err: any) {
console.error(err);
res.fail({
error: err.name || "InternalServerError",
message: err.message || "μ±„νŒ…λ°© 생성/λ°˜ν™˜ 쀑 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€.",
statusCode: err.statusCode || 500,
});
}
};

export const getChatRoomDetail = async (req: Request, res: Response): Promise<void> => {
if (!req.user) {
res.fail({
statusCode: 401,
error: "no user",
message: "둜그인이 ν•„μš”ν•©λ‹ˆλ‹€.",
});
return;
}

try{
const userId = (req.user as { user_id: number }).user_id;

const roomId = Number(req.params.roomId);
const cursor = req.query.cursor ? Number(req.query.cursor) : undefined;
const limit = req.query.limit ? Number(req.query.limit) : 20;

if (isNaN(roomId)) {
res.fail({ statusCode: 400, error: "BadRequest", message: "μ˜¬λ°”λ₯Έ roomId ν•„μš”ν•©λ‹ˆλ‹€." });
return;
}

const result = await chatService.getChatRoomDetailService(roomId, userId, cursor, limit);

res.success(result, "μ±„νŒ…λ°© 상세λ₯Ό μ„±κ³΅μ μœΌλ‘œ μ‘°νšŒν–ˆμŠ΅λ‹ˆλ‹€.");
} catch (err: any) {
console.error(err);
res.fail({
error: err.name || "InternalServerError",
message: err.message || "μ±„νŒ…λ°© 상세 쑰회 쀑 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€.",
statusCode: err.statusCode || 500,
});
}
}

// == μ±„νŒ…λ°© λͺ©λ‘
export const getChatRoomList = async(req: Request, res: Response) => {
if (!req.user) {
res.fail({
statusCode: 401,
error: "no user",
message: "둜그인이 ν•„μš”ν•©λ‹ˆλ‹€.",
});
return;
}

try{
const userId = (req.user as { user_id: number }).user_id;
const { cursor, limit, filter, search } = req.query as unknown as GetChatRoomListRequestDto;

if (filter && filter !== "all" && filter !== "unread" && filter !== "pinned") {
res.fail({ statusCode: 400, error: "BadRequest", message: "μ˜¬λ°”λ₯Έ filter값이 ν•„μš”ν•©λ‹ˆλ‹€." });
return;
}

const result = await chatService.getChatRoomListService(
userId,
cursor ? Number(cursor) : undefined,
limit ? Number(limit) : undefined,
filter,
search as string
);
res.success(result, "μ±„νŒ…λ°© λͺ©λ‘μ„ μ„±κ³΅μ μœΌλ‘œ μ‘°νšŒν–ˆμŠ΅λ‹ˆλ‹€.");
} catch (err: any) {
console.error(err);
res.fail({
error: err.name || "InternalServerError",
message: err.message || "μ±„νŒ…λ°© λͺ©λ‘ 쑰회 쀑 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€.",
statusCode: err.statusCode || 500,
});
}
}
Loading