prisma migration + back auth/me/likes + front API add and get methods for liked song

This commit is contained in:
danis
2023-08-30 13:06:25 +02:00
parent a3676fabf8
commit c81f8df61c
9 changed files with 998 additions and 7339 deletions

8210
back/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
/*
Warnings:
- Added the required column `likedSongs` to the `User` table without a default value. This is not possible if the table is not empty.
*/
-- AlterTable
ALTER TABLE "User" ADD COLUMN "likedSongs" JSONB NOT NULL DEFAULT '{}'::jsonb;

View File

@@ -21,6 +21,7 @@ model User {
SongHistory SongHistory[]
searchHistory SearchHistory[]
settings UserSettings?
likedSongs Json?
}
model UserSettings {

View File

@@ -18,6 +18,7 @@ import {
HttpStatus,
ParseFilePipeBuilder,
Response,
Param,
} from '@nestjs/common';
import { AuthService } from './auth.service';
import { JwtAuthGuard } from './jwt-auth.guard';
@@ -199,4 +200,20 @@ export class AuthController {
if (!result) throw new NotFoundException();
return result;
}
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@ApiOkResponse({ description: 'Successfully added liked song'})
@ApiUnauthorizedResponse({ description: 'Invalid token' })
@Post('me/likes:id')
addLikedSong(
@Request() req: any,
@Body() data: any,
) {
return this.usersService.addLikedSong(
req.user.id,
data.songId,
);
}
}

View File

@@ -1,4 +1,4 @@
import { Controller, Get, Param, NotFoundException, Response } from '@nestjs/common';
import { Controller, Get, Post, Param, NotFoundException, Response } from '@nestjs/common';
import { UsersService } from './users.service';
import { ApiNotFoundResponse, ApiTags } from '@nestjs/swagger';
import { User } from 'src/models/user';

View File

@@ -99,4 +99,21 @@ export class UsersService {
resp.headers.set(k, v);
resp.body!.pipe(res);
}
async addLikedSong(
where: Prisma.UserWhereUniqueInput,
songId: number,
) {
return this.prisma.user.update({
where,
data: {
likedSongs: {
merde: {
songId: songId,
time: Date()
}
}
}
})
}
}

View File

@@ -4,6 +4,7 @@ import Chapter from './models/Chapter';
import Lesson from './models/Lesson';
import Genre, { GenreHandler } from './models/Genre';
import LessonHistory from './models/LessonHistory';
import likedSong, { LikedSongHandler } from './models/LikedSong';
import Song, { SongHandler } from './models/Song';
import { SongHistoryHandler, SongHistoryItem, SongHistoryItemHandler } from './models/SongHistory';
import User, { UserHandler } from './models/User';
@@ -608,4 +609,42 @@ export default class API {
formData,
});
}
public static async addLikedSong(songId: number): Promise<void> {
const data = await API.fetch(
{
route: `/auth/me/likes${songId}`,
method: 'POST',
body: {
songId: songId
}
}
)
}
public static getLikedSongs(): Query<likedSong[]> {
return {
key: ['liked songs'],
exec: () =>
API.fetch(
{
route: '/auth/me/likes',
},
{ handler: ListHandler(LikedSongHandler)}
),
};
}
public static getUserPlaayHistory(): Query<SongHistoryItem[]> {
return {
key: ['history'],
exec: () =>
API.fetch(
{
route: '/history',
},
{ handler: ListHandler(SongHistoryItemHandler) }
),
};
}
}

41
front/models/LikedSong.ts Normal file
View File

@@ -0,0 +1,41 @@
import * as yup from 'yup';
import ResponseHandler from './ResponseHandler';
export const LikedSongItemValidator = yup.object({
songId: yup.number().required(),
addedDate: yup.date().required(),
});
export const LikedSongItemHandler: ResponseHandler<
yup.InferType<typeof LikedSongItemValidator>,
LikedSongItem
> = {
validator: LikedSongItemValidator,
transformer: (value) => ({
...value,
}),
};
export const LikedSongValidator = yup.object({
songId: yup.number().required(),
history: yup.array(LikedSongItemValidator).required(),
});
export type LikedSong = yup.InferType<typeof LikedSongValidator>;
export const LikedSongHandler: ResponseHandler<LikedSong> = {
validator: LikedSongValidator,
transformer: (value) => ({
...value,
history: value.history.map((item) =>
LikedSongItemHandler.transformer(item)
),
}),
};
export type LikedSongItem = {
songId: number;
addedDate: Date;
};
export default LikedSong;

View File

@@ -2,7 +2,7 @@ import Model, { ModelValidator } from './Model';
import * as yup from 'yup';
import ResponseHandler from './ResponseHandler';
export const SearchType = ['song', 'artist', 'album'] as const;
export const SearchType = ['song', 'artist', 'album', 'genre'] as const;
export type SearchType = (typeof SearchType)[number];
const SearchHistoryValidator = yup