Skip to content

Commit

Permalink
feat: checkRequiredFields 미들웨어 추가, schema.ts수정(#11)
Browse files Browse the repository at this point in the history
- checkRequiredFields 미들웨어 추가, schema.ts수정, travel.route.ts 수정
- checkRequiredFields 미들웨어 추가. 필수 필드를 체크하는 미들웨어 추가
- schema.ts 수정. travel schema에 필수 필드 추가
- travel.route.ts 수정. checkRequiredFields 미들웨어 추가
  • Loading branch information
nakyeonko3 committed Oct 18, 2024
1 parent 91feab1 commit 540231b
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 55 deletions.
141 changes: 87 additions & 54 deletions src/api/travel/travel.route.ts
Original file line number Diff line number Diff line change
@@ -1,60 +1,47 @@
import { Router } from 'express';
// import { Router } from 'express';
import { Team, Travel } from '../../db/schema';
import { ResponseDTO } from '../../ResponseDTO';
import { checkRequiredFields } from '../../checkRequiredFields';
import { Router } from 'express';

const travelRouter = Router();

/**
* 새로운 여행 계획하기
* POST /api/v1/travels
curl -X POST http://localhost:3000/api/v1/travels -H "Content-Type: application/json" -d '{
"userId": "user456",
"thumbnail": "https://example.com/busan-image.jpg",
"travelTitle": "부산 여행",
"travelContent": "부산의 해변과 명소를 둘러보는 여행",
"travelCourse": ["해운대", "광안리", "감천문화마을"],
"tag": ["부산", "바다", "문화"],
"team": [
{
"personLimit": 8,
"travelStartDate": "2024-07-15",
"travelEndDate": "2024-07-18"
}
],
"travelPrice": 350000,
"includedItems": ["숙박", "가이드", "해변 액티비티"],
"excludedItems": ["식사", "교통비", "개인 경비"],
"meetingTime": ["10:00", "15:00"],
}'
* POST /api/v1/travels/add-travel
*/
travelRouter.post('/add-travel', async (req, res) => {
try {
const travelId = crypto.randomUUID();
const teamId = crypto.randomUUID();
await Team.collection.insertOne({
...req.body.team,
_id: teamId,
id: teamId,
});
const travel = await Travel.collection.insertOne({
...req.body,
_id: travelId,
id: travelId,
teamId: [teamId],
createAt: new Date(),
updateAt: new Date(),
});
const newTravel = await Travel.find({ id: travel.insertedId.toString() });
res.json(
ResponseDTO.success({
newTravel,
}),
);
} catch (error) {
console.error(error);
res.status(500).json(ResponseDTO.fail((error as Error).message));
}
});
travelRouter.post(
'/add-travel',
checkRequiredFields(['team', 'title', 'content']),
async (req, res) => {
try {
const travelId = crypto.randomUUID();
const teamId = crypto.randomUUID();
await Team.collection.insertOne({
...req.body.team,
_id: teamId,
id: teamId,
});
const travel = await Travel.collection.insertOne({
...req.body,
_id: travelId,
id: travelId,
teamId: [teamId],
createAt: new Date(),
updateAt: new Date(),
});
const newTravel = await Travel.find({ id: travel.insertedId.toString() });
res.json(
ResponseDTO.success({
newTravel,
}),
);
} catch (error) {
console.error(error);
res.status(500).json(ResponseDTO.fail((error as Error).message));
}
},
);

/**
* 여행 목록 조회
Expand All @@ -73,13 +60,11 @@ curl -X POST http://localhost:3000/api/v1/travels/home-travel-list -H "Content-T
"userId": "user123"
}'
*/
travelRouter.post('/home-travel-list', async (req, res) => {
travelRouter.post('/home-travel-list', checkRequiredFields(['userId']), async (req, res) => {
const { userId } = req.body;
try {
const travels = await Travel.find().sort({ createAt: -1 }).limit(20);
console.log(userId);
const userBookmarkTravels = travels.map((travel) => {
console.log(travel.bookmark);
return {
...travel.toObject(),
bookmark: travel.bookmark?.includes(userId) || false,
Expand All @@ -100,11 +85,11 @@ travelRouter.post('/home-travel-list', async (req, res) => {
* 북마크 리스트 조회
* POST /api/v1/travels/bookmark-list
*/

travelRouter.post('/bookmark-list', async (req, res) => {
travelRouter.post('/bookmark-list', checkRequiredFields(['userId']), async (req, res) => {
const { userId } = req.body;
try {
const travels = await Travel.find({ bookmark: { $in: [userId] } });
console.log();
res.json(
ResponseDTO.success({
bookmarks: travels,
Expand All @@ -116,4 +101,52 @@ travelRouter.post('/bookmark-list', async (req, res) => {
}
});

/**
* 내여행-참여한 여행 목록 조회
* /api/v1/travels/my-travel-list
*/
travelRouter.post('/my-travel-list', checkRequiredFields(['userId']), async (req, res) => {
const { userId } = req.body;
try {
const travels = await Travel.find({ team: { $elemMatch: { userId: userId } } });
res.json(
ResponseDTO.success({
travels: travels,
}),
);
} catch (error) {
console.error(error);
res.status(500).json(ResponseDTO.fail((error as Error).message));
}
});

/**
* 여행 북마크 추가
* POST/api/v1/travels/bookmark-check
*/
travelRouter.post(
'/bookmark-check',
checkRequiredFields(['userId', 'travelId']),
async (req, res) => {
const { userId, travelId } = req.body;
try {
const travel = await Travel.findOne({ id: travelId });
if (!travel) {
res.status(404).json(ResponseDTO.fail('Travel not found'));
return;
}
if (travel?.bookmark?.includes(userId)) {
res.status(400).json(ResponseDTO.fail('Already bookmarked'));
return;
}
travel?.bookmark?.push(userId);
await travel?.save();
res.json(ResponseDTO.success(travel));
} catch (error) {
console.error(error);
res.status(500).json(ResponseDTO.fail((error as Error).message));
}
},
);

export { travelRouter };
14 changes: 14 additions & 0 deletions src/checkRequiredFields.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Request, Response, NextFunction } from 'express';
import { ResponseDTO } from './ResponseDTO';

export const checkRequiredFields = (fields: string[]) => {
return (req: Request, res: Response, next: NextFunction) => {
for (const field of fields) {
if (!req.body[field]) {
res.status(400).json(ResponseDTO.fail(`${field} is required`));
return;
}
}
next();
};
};
11 changes: 10 additions & 1 deletion src/db/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,13 @@ export interface ITravel extends Document {
teamId?: string[];
travelTotalScore?: number;
travelActive: boolean;
reviewWrite: boolean;
isDeleted: boolean;
}

const TravelSchema: Schema = new Schema(
{
_id: { type: String, required: true },
id: { type: String, required: true, unique: true },
userId: { type: [String], required: true, ref: 'User' },
thumbnail: { type: String, required: true },
Expand All @@ -39,12 +42,14 @@ const TravelSchema: Schema = new Schema(
travelPrice: { type: Number, required: true },
travelFAQ: { type: [Object], default: [] },
reviews: [{ type: String, ref: 'Review', default: [] }],
bookmark: [{ type: String, ref: 'User', default: [] }],
bookmark: [{ type: String }],
createAt: { type: Date, default: Date.now, required: true },
updateAt: { type: Date, default: Date.now, required: true },
teamId: [{ type: [String], ref: 'Team', default: [] }],
travelTotalScore: { type: Number },
travelActive: { type: Boolean, default: true },
reviewWrite: { type: Boolean, default: false },
isDeleted: { type: Boolean, default: false },
},
{ timestamps: true },
);
Expand Down Expand Up @@ -94,6 +99,7 @@ export const AppliedUserSchema = new Schema({
});

export interface ITeam extends Document {
_id: string;
id: string;
travelId: string;
personLimit: number;
Expand All @@ -104,6 +110,7 @@ export interface ITeam extends Document {

const TeamSchema: Schema = new Schema(
{
_id: { type: String, required: true },
id: { type: String, required: true, unique: true },
travelId: { type: String, required: true, ref: 'Travel' },
personLimit: { type: Number, required: true },
Expand All @@ -117,6 +124,7 @@ const TeamSchema: Schema = new Schema(
export const Team = mongoose.model<ITeam>('Team', TeamSchema);

export interface IUser extends Document {
_id: string;
id: string;
userProfileImage: string;
userName: string;
Expand All @@ -132,6 +140,7 @@ export interface IUser extends Document {

const UserSchema: Schema = new Schema(
{
_id: { type: String, required: true },
id: { type: String, required: true, unique: true },
userProfileImage: { type: String },
userName: { type: String, required: true },
Expand Down

0 comments on commit 540231b

Please sign in to comment.