Skip to content

Commit

Permalink
Merge pull request #11 from Adoptaunpeludo/user_favs
Browse files Browse the repository at this point in the history
User favs
  • Loading branch information
JoseAlbDR authored Feb 16, 2024
2 parents 626ce6b + bb6570e commit 987caac
Show file tree
Hide file tree
Showing 12 changed files with 146 additions and 39 deletions.
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"typescript.tsdk": "node_modules\\typescript\\lib",
"cSpell.words": ["RABBITMQ"]
"cSpell.words": ["Favs", "RABBITMQ"]
}
2 changes: 2 additions & 0 deletions prisma/migrations/20240215231249_num_favs/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "Animal" ADD COLUMN "numFavs" INTEGER NOT NULL DEFAULT 0;
1 change: 1 addition & 0 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ model Animal {
adoptedBy String?
createdBy String
cityId Int
numFavs Int @default(0)
images String[]
easyTrain Boolean
numFavs Int @default(0)
Expand Down
8 changes: 5 additions & 3 deletions src/domain/entities/animals.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@ export class AnimalEntity {
}

static fromObject(animalResponse: AnimalResponse) {
const { name: cityName } = animalResponse.city!;
const { name: city } = animalResponse.city!;
const { avatar, username, isOnline } = animalResponse.shelter!.user!;

const { id, images, name, age, gender, size, type, slug } = animalResponse;
const { id, images, name, age, gender, size, type, slug, numFavs } =
animalResponse;

return {
id,
Expand All @@ -41,8 +42,9 @@ export class AnimalEntity {
gender,
size,
type,
cityName,
city,
images,
numFavs,
shelter: { avatar, username, isOnline },
};
}
Expand Down
1 change: 1 addition & 0 deletions src/domain/interfaces/animal.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export interface AnimalResponse {
breed: string;
size: animalSize;
publishStatus: animalPublishStatus;
numFavs: number;
status: string;
easyTrain: boolean;
energyLevel: animalEnergy;
Expand Down
12 changes: 10 additions & 2 deletions src/presentation/animals/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,18 @@ export class AnimalController {
res.status(HttpCodes.OK).json({ message: 'Images updated successfully' });
};

addToFavorites = async (req: Request, res: Response) => {
addFavorite = async (req: Request, res: Response) => {
const { id } = req.params;

const response = await this.animalService.addToFavorites(id, req.user.id!);
const response = await this.animalService.addFavorite(req.user.id!, id);

res.status(HttpCodes.OK).json(response);
};

removeFavorite = async (req: Request, res: Response) => {
const { id } = req.params;

const response = await this.animalService.removeFavorite(req.user.id!, id);

res.status(HttpCodes.OK).json(response);
};
Expand Down
12 changes: 12 additions & 0 deletions src/presentation/animals/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,18 @@ export class AnimalRoutes {

router.get('/:term', animalController.getSingle);

router.post(
'/add-favorite/:id',
authMiddleware.authenticateUser,
animalController.addFavorite
);

router.post(
'/remove-favorite/:id',
authMiddleware.authenticateUser,
animalController.removeFavorite
);

router.post(
'/upload-images/:term',
authMiddleware.authenticateUser,
Expand Down
3 changes: 1 addition & 2 deletions src/presentation/routes.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { AuthMiddleware } from './middlewares/auth.middleware';
import { Response, Router } from 'express';
import { Router } from 'express';
import { AuthRoutes } from './auth/routes';
import { UserRoutes } from './users/routes';
import { AnimalRoutes } from './animals/routes';
Expand Down
69 changes: 63 additions & 6 deletions src/presentation/services/animal.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { UUID } from '../../config/uuid.adapter';
import { prismaWithSlugExtension as prisma } from '../../data/postgres';
import { NotFoundError } from '../../domain';
import { BadRequestError, NotFoundError } from '../../domain';
import {
AnimalFilterDto,
CreateCatDto,
Expand Down Expand Up @@ -299,20 +299,77 @@ export class AnimalService {
});
}

public async addToFavorites(animalId: string, userId: string) {
public async addFavorite(userId: string, animalId: string) {

const animal = await prisma.animal.findUnique({ where: { id: animalId } });

if (!animal) throw new NotFoundError('Animal not found');

if (animal.createdBy === userId)
throw new BadRequestError('Cant add own animal to favorites');

const alreadyFav = await prisma.animal.findUnique({
where: { id: animalId },
include: {
userFav: {
where: { id: userId },
},
},
});

if (alreadyFav && alreadyFav.userFav.length > 0)
throw new BadRequestError('Already in favorites');

//* TODO: Prisma transition
await prisma.animal.update({
where: { id: animalId },
data: {
userFav: {
connect: { id: userId },
},
},
});

const updatedFavs = await prisma.animal.update({
where: { id: animalId },
data: { numFavs: { increment: 1 } },
});

return updatedFavs;
}

public async removeFavorite(userId: string, animalId: string) {
const animal = await prisma.animal.findUnique({ where: { id: animalId } });

if (!animal) throw new NotFoundError('Animal not found');

const newFav = await prisma.user.update({
where: { id: userId },
const notFav = await prisma.animal.findUnique({
where: { id: animalId },
include: {
userFav: {
where: { id: userId },
},
},
});

if (notFav && notFav.userFav.length === 0)
throw new BadRequestError('Not in favorites yet');

//* TODO: Prisma transition
await prisma.animal.update({
where: { id: animalId },
data: {
userFav: {
connect: { id: animalId },
disconnect: { id: userId },
},
},
});

return newFav;
const updatedFavs = await prisma.animal.update({
where: { id: animalId },
data: { numFavs: { decrement: 1 } },
});

return updatedFavs;
}
}
36 changes: 28 additions & 8 deletions src/presentation/services/user.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { PrismaClient } from '@prisma/client';
import { prismaWithPasswordExtension as prisma } from '../../data/postgres';
import {
BadRequestError,
Expand Down Expand Up @@ -33,7 +32,7 @@ export class UserService {
});
}

public async getCurrentUser(email: string, role: UserRoles) {
public async getCurrentUser(email: string) {
const user = await prisma.user.findUnique({
where: {
email,
Expand All @@ -55,11 +54,34 @@ export class UserService {

if (!user) throw new NotFoundError('User not found');

const viewUser = await prisma.userInfo.findUnique({
where: { id: user.id },
// const viewUser = await prisma.userInfo.findUnique({
// where: { id: user.id },
// });

// console.log({ viewUser });

return user;
}

public async getSingleUser(id: string) {
const user = await prisma.user.findUnique({
where: { id },
include: {
contactInfo: {
include: {
city: true,
},
},
shelter: {
include: {
socialMedia: true,
animals: { include: { cat: true, dog: true } },
},
},
},
});

console.log({ viewUser });
if (!user) throw new NotFoundError('User not found');

return user;
}
Expand Down Expand Up @@ -233,9 +255,7 @@ export class UserService {
},
});

const userEntity = UserEntity.fromObject(updatedUser);

return userEntity;
return updatedUser;
}

private async buildImages(
Expand Down
20 changes: 16 additions & 4 deletions src/presentation/users/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,20 @@ export class UserController {
res.status(HttpCodes.OK).json(userEntities);
};

getUser = async (req: Request, res: Response) => {
const { email, role } = req.user;
getCurrentUser = async (req: Request, res: Response) => {
const { email } = req.user;

const user = await this.userService.getCurrentUser(email, role!);
const user = await this.userService.getCurrentUser(email);

const userEntity = UserEntity.fromObject(user);

res.status(HttpCodes.OK).json(userEntity);
};

getSingleUser = async (req: Request, res: Response) => {
const { id } = req.params;

const user = await this.userService.getSingleUser(id);

const userEntity = UserEntity.fromObject(user);

Expand Down Expand Up @@ -46,9 +56,11 @@ export class UserController {

const updatedUser = await this.userService.updateUser(updates, user);

const userEntity = UserEntity.fromObject(updatedUser);

res
.status(HttpCodes.OK)
.json({ message: 'User updated successfully', user: updatedUser });
.json({ message: 'User updated successfully', user: userEntity });
};

changePassword = async (req: Request, res: Response) => {
Expand Down
19 changes: 6 additions & 13 deletions src/presentation/users/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,48 +27,41 @@ export class UserRoutes {
const userController = new UserController(userService);
const fileUploadMiddleware = new FileUploadMiddleware(s3Service);

router.get('/me', authMiddleware.authenticateUser, userController.getUser);
router.use(authMiddleware.authenticateUser);

router.get('/me', userController.getCurrentUser);

router.get('/:id', userController.getSingleUser);

router.get(
'/',
authMiddleware.authenticateUser,
// authMiddleware.authorizePermissions('admin'),
userController.getAllUsers
);

//* TODO: getSingle

router.delete(
'/',
authMiddleware.authenticateUser,
userController.deleteUser
);
router.delete('/', userController.deleteUser);

router.put(
'/',
authMiddleware.authenticateUser,
ValidationMiddleware.validate(UpdateUserDto),
userController.updateUser
);

router.post(
'/upload-images',
authMiddleware.authenticateUser,
ValidationMiddleware.validate(FileUploadDto),
fileUploadMiddleware.multiple('users'),
userController.uploadImages
);

router.put(
'/change-password',
authMiddleware.authenticateUser,
ValidationMiddleware.validate(UpdatePasswordDto),
userController.changePassword
);

router.put(
'/update-social-media',
authMiddleware.authenticateUser,
authMiddleware.authorizePermissions('shelter'),
ValidationMiddleware.validate(UpdateSocialMediaDto),
userController.updateSocialMedia
Expand Down

0 comments on commit 987caac

Please sign in to comment.