prisma migration + back auth/me/likes + front API add and get methods for liked song
This commit is contained in:
8210
back/package-lock.json
generated
8210
back/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
@@ -21,6 +21,7 @@ model User {
|
||||
SongHistory SongHistory[]
|
||||
searchHistory SearchHistory[]
|
||||
settings UserSettings?
|
||||
likedSongs Json?
|
||||
}
|
||||
|
||||
model UserSettings {
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
39
front/API.ts
39
front/API.ts
@@ -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
41
front/models/LikedSong.ts
Normal 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;
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user