mirror of
https://github.com/ThisIsBenny/wishlist-app.git
synced 2025-06-07 05:57:41 +00:00
Merge branch 'release/v1.0.0' of github.com:ThisIsBenny/wishlist-app into release/v1.0.0
This commit is contained in:
commit
ca593fc9ff
17 changed files with 474 additions and 96 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -30,5 +30,4 @@ dist/
|
|||
coverage
|
||||
.env
|
||||
data
|
||||
prisma/seed.ts
|
||||
public/*.jpeg
|
||||
|
|
73
examples.http
Normal file
73
examples.http
Normal file
|
@ -0,0 +1,73 @@
|
|||
@BASE_URL=http://localhost:5000/api
|
||||
|
||||
|
||||
###
|
||||
# @name createWishlistFirst
|
||||
POST {{BASE_URL}}/wishlist
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"title": "Junior",
|
||||
"imageSrc": "https://unsplash.com/photos/JZ51o_-UOY8/download?force=true&w=200",
|
||||
"slugUrlText": "junior"
|
||||
}
|
||||
|
||||
###
|
||||
# @name createWishlistSecond
|
||||
POST {{BASE_URL}}/wishlist
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"title": "Wedding",
|
||||
"imageSrc": "https://unsplash.com/photos/8vaQKYnawHw/download?ixid=MnwxMjA3fDB8MXxhbGx8fHx8fHx8fHwxNjQ0MDQ4MTIy&force=true&w=200",
|
||||
"description": "We are getting married",
|
||||
"slugUrlText": "wedding"
|
||||
}
|
||||
|
||||
###
|
||||
# @name getWishlists
|
||||
GET {{BASE_URL}}/wishlist
|
||||
|
||||
###
|
||||
# @name getFirstWishlist
|
||||
GET {{BASE_URL}}/wishlist/{{getWishlists.response.body.0.slugUrlText}}
|
||||
|
||||
###
|
||||
# @name updateFirstWishlist
|
||||
PUT {{BASE_URL}}/wishlist/{{getWishlists.response.body.0.id}}
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"title": "Junior",
|
||||
"imageSrc": "https://unsplash.com/photos/JZ51o_-UOY8/download?force=true&w=200",
|
||||
"description": "Juniors Wishlist",
|
||||
"slugUrlText": "junior"
|
||||
}
|
||||
|
||||
###
|
||||
# @name addItemToFirstWishlist
|
||||
POST {{BASE_URL}}/wishlist/{{getWishlists.response.body.0.id}}/item
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"title": "Goldfish 40442 | BrickHeadz",
|
||||
"url": "https://www.lego.com/en-de/product/goldfish-40442",
|
||||
"imageSrc": "https://www.lego.com/cdn/cs/set/assets/blt1fc37afef51cfa9f/40442.jpg?fit=bounds&format=jpg&quality=80&width=1500&height=1500&dpr=1",
|
||||
"description": "Cute goldfish and fry, build-and-display BrickHeadz™ model"
|
||||
}
|
||||
|
||||
###
|
||||
# @name updateItemOnFirstWishlist
|
||||
PUT {{BASE_URL}}/wishlist/{{getWishlists.response.body.0.id}}/item/1
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"title": "Goldfish | BrickHeadz",
|
||||
"url": "https://www.lego.com/en-de/product/goldfish-40442",
|
||||
"imageSrc": "https://www.lego.com/cdn/cs/set/assets/blt1fc37afef51cfa9f/40442.jpg?fit=bounds&format=jpg&quality=80&width=1500&height=1500&dpr=1",
|
||||
"description": "Cute goldfish and fry, build-and-display BrickHeadz™ model"
|
||||
}
|
||||
|
||||
###
|
||||
# @name deleteItemToFirstWishlist
|
||||
DELETE {{BASE_URL}}/wishlist/{{getWishlists.response.body.0.id}}/item/2
|
|
@ -4,17 +4,17 @@ CREATE TABLE "Wishlist" (
|
|||
"title" TEXT NOT NULL,
|
||||
"imageSrc" TEXT NOT NULL,
|
||||
"slugUrlText" TEXT NOT NULL,
|
||||
"description" TEXT
|
||||
"description" TEXT NOT NULL DEFAULT ''
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Item" (
|
||||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"title" TEXT NOT NULL,
|
||||
"url" TEXT,
|
||||
"imageSrc" TEXT,
|
||||
"url" TEXT NOT NULL DEFAULT '',
|
||||
"imageSrc" TEXT NOT NULL DEFAULT '',
|
||||
"description" TEXT NOT NULL,
|
||||
"comment" TEXT,
|
||||
"comment" TEXT NOT NULL DEFAULT '',
|
||||
"bought" BOOLEAN NOT NULL DEFAULT false,
|
||||
"wishlistId" TEXT NOT NULL,
|
||||
CONSTRAINT "Item_wishlistId_fkey" FOREIGN KEY ("wishlistId") REFERENCES "Wishlist" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
|
@ -15,18 +15,18 @@ model Wishlist {
|
|||
title String
|
||||
imageSrc String
|
||||
slugUrlText String @unique
|
||||
description String?
|
||||
description String @default("")
|
||||
items Item[]
|
||||
}
|
||||
|
||||
model Item {
|
||||
id Int @id @default(autoincrement())
|
||||
id Int @id @default(autoincrement())
|
||||
title String
|
||||
url String?
|
||||
imageSrc String?
|
||||
url String @default("")
|
||||
imageSrc String @default("")
|
||||
description String
|
||||
comment String?
|
||||
comment String @default("")
|
||||
bought Boolean @default(false)
|
||||
wishlist Wishlist @relation(fields: [wishlistId], references: [id])
|
||||
wishlist Wishlist @relation(fields: [wishlistId], references: [id])
|
||||
wishlistId String
|
||||
}
|
||||
|
|
60
prisma/seed.ts
Normal file
60
prisma/seed.ts
Normal file
|
@ -0,0 +1,60 @@
|
|||
import { PrismaClient, Prisma } from '@prisma/client'
|
||||
|
||||
const prisma = new PrismaClient()
|
||||
|
||||
const wishlistData: Prisma.WishlistCreateInput[] = [
|
||||
{
|
||||
title: 'Junior',
|
||||
imageSrc:
|
||||
'https://unsplash.com/photos/JZ51o_-UOY8/download?force=true&w=200',
|
||||
description: '',
|
||||
slugUrlText: 'junior',
|
||||
items: {
|
||||
create: [
|
||||
{
|
||||
title: 'Goldfish 40442 | BrickHeadz',
|
||||
url: 'https://www.lego.com/en-de/product/goldfish-40442',
|
||||
imageSrc:
|
||||
'https://www.lego.com/cdn/cs/set/assets/blt1fc37afef51cfa9f/40442.jpg?fit=bounds&format=jpg&quality=80&width=1500&height=1500&dpr=1',
|
||||
description:
|
||||
'Cute goldfish and fry, build-and-display BrickHeadz™ model',
|
||||
comment: '',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Wedding',
|
||||
imageSrc:
|
||||
'https://unsplash.com/photos/8vaQKYnawHw/download?ixid=MnwxMjA3fDB8MXxhbGx8fHx8fHx8fHwxNjQ0MDQ4MTIy&force=true&w=200',
|
||||
description: 'We are getting married',
|
||||
slugUrlText: 'wedding',
|
||||
},
|
||||
{
|
||||
title: '40th birthday',
|
||||
imageSrc:
|
||||
'https://unsplash.com/photos/poH6OvcEeXE/download?ixid=MnwxMjA3fDB8MXxzZWFyY2h8NHx8YmlydGhkYXl8fDB8fHx8MTY0NDA1NDEzNA&force=true&w=200',
|
||||
description: 'We are getting married',
|
||||
slugUrlText: '40th-birthday',
|
||||
},
|
||||
]
|
||||
|
||||
async function main() {
|
||||
console.log(`Start seeding ...`)
|
||||
for (const u of wishlistData) {
|
||||
const wishlist = await prisma.wishlist.create({
|
||||
data: u,
|
||||
})
|
||||
console.log(`Created wishlist with id: ${wishlist.id}`)
|
||||
}
|
||||
console.log(`Seeding finished.`)
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((e) => {
|
||||
console.error(e)
|
||||
process.exit(1)
|
||||
})
|
||||
.finally(async () => {
|
||||
await prisma.$disconnect()
|
||||
})
|
56
src/api/config/errors/index.ts
Normal file
56
src/api/config/errors/index.ts
Normal file
|
@ -0,0 +1,56 @@
|
|||
import { FastifyRequest, FastifyReply, FastifyError } from 'fastify'
|
||||
import { Prisma } from '@prisma/client'
|
||||
|
||||
const errorIs = (e: unknown, c: string) =>
|
||||
e instanceof Prisma.PrismaClientKnownRequestError && e.code === c
|
||||
|
||||
export const defaultErrorHandler = (
|
||||
error: FastifyError,
|
||||
request: FastifyRequest,
|
||||
reply: FastifyReply
|
||||
) => {
|
||||
if (error.validation) {
|
||||
error.code = '400'
|
||||
reply.send(error)
|
||||
} else if (errorIs(error, 'P2002')) {
|
||||
reply.send(
|
||||
uniqueKeyError(
|
||||
// @ts-expect-error: Object is possibly 'undefined'
|
||||
`${error.meta.target[0] || 'One of the fields'} has to be unique`
|
||||
)
|
||||
)
|
||||
} else if (errorIs(error, 'P2025')) {
|
||||
reply.callNotFound()
|
||||
} else {
|
||||
request.log.error(error)
|
||||
const e = new httpError('unexpected error', 500, '500')
|
||||
reply.send(e)
|
||||
}
|
||||
}
|
||||
|
||||
export const notFoundHandler = (
|
||||
request: FastifyRequest,
|
||||
reply: FastifyReply
|
||||
) => {
|
||||
reply.send(notFoundError())
|
||||
}
|
||||
|
||||
class httpError extends Error {
|
||||
code: string
|
||||
statusCode: number
|
||||
constructor(message: string, statusCode: number, code: string) {
|
||||
super(message)
|
||||
this.name = this.constructor.name
|
||||
Error.captureStackTrace(this, this.constructor)
|
||||
this.statusCode = statusCode
|
||||
this.code = code
|
||||
}
|
||||
}
|
||||
|
||||
const notFoundError = () => {
|
||||
return new httpError('Not Found', 404, '404')
|
||||
}
|
||||
|
||||
const uniqueKeyError = (msg: string, code = '4001') => {
|
||||
return new httpError(msg, 422, code)
|
||||
}
|
1
src/api/config/schemas/index.ts
Normal file
1
src/api/config/schemas/index.ts
Normal file
|
@ -0,0 +1 @@
|
|||
export * from './wishlist'
|
53
src/api/config/schemas/wishlist.ts
Normal file
53
src/api/config/schemas/wishlist.ts
Normal file
|
@ -0,0 +1,53 @@
|
|||
export const wishlistItemRequestSchema = {
|
||||
type: 'object',
|
||||
additionalProperties: false,
|
||||
required: ['title', 'description'],
|
||||
properties: {
|
||||
title: { type: 'string' },
|
||||
url: { type: 'string' },
|
||||
imageSrc: { type: 'string' },
|
||||
description: { type: 'string' },
|
||||
comment: { type: 'string' },
|
||||
bought: { type: 'boolean' },
|
||||
},
|
||||
}
|
||||
|
||||
export const wishlistItemResponseSchema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'number' },
|
||||
title: { type: 'string' },
|
||||
url: { type: 'string' },
|
||||
imageSrc: { type: 'string' },
|
||||
description: { type: 'string' },
|
||||
comment: { type: 'string' },
|
||||
bought: { type: 'boolean' },
|
||||
wishlistId: { type: 'string' },
|
||||
},
|
||||
}
|
||||
|
||||
export const wishlistRequestSchema = {
|
||||
type: 'object',
|
||||
additionalProperties: false,
|
||||
required: ['title', 'imageSrc', 'slugUrlText'],
|
||||
properties: {
|
||||
title: { type: 'string' },
|
||||
imageSrc: { type: 'string' },
|
||||
description: { type: 'string' },
|
||||
slugUrlText: { type: 'string' },
|
||||
},
|
||||
}
|
||||
export const wishlistResponseSchema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string' },
|
||||
title: { type: 'string' },
|
||||
imageSrc: { type: 'string' },
|
||||
description: { type: 'string' },
|
||||
slugUrlText: { type: 'string' },
|
||||
items: {
|
||||
type: 'array',
|
||||
items: wishlistItemResponseSchema,
|
||||
},
|
||||
},
|
||||
}
|
|
@ -1,15 +1,13 @@
|
|||
import { prisma } from '../../services'
|
||||
import { Wishlist, WishlistItem } from '@/types'
|
||||
|
||||
export default {
|
||||
getAll: async (): Promise<any> => {
|
||||
return await prisma.client.wishlist.findMany({
|
||||
getAll: async (): Promise<Wishlist[]> => {
|
||||
return (await prisma.client.wishlist.findMany({
|
||||
include: { items: false },
|
||||
})
|
||||
})) as Wishlist[]
|
||||
},
|
||||
getBySlugUrlText: async (
|
||||
value: string,
|
||||
includeItems = false
|
||||
): Promise<any> => {
|
||||
getBySlugUrlText: async (value: string, includeItems = false) => {
|
||||
return await prisma.client.wishlist.findUnique({
|
||||
where: {
|
||||
slugUrlText: value,
|
||||
|
@ -17,6 +15,44 @@ export default {
|
|||
include: { items: includeItems },
|
||||
})
|
||||
},
|
||||
create: async (payload: Wishlist) => {
|
||||
return await prisma.client.wishlist.create({
|
||||
data: payload,
|
||||
})
|
||||
},
|
||||
update: async (id: string, payload: Wishlist) => {
|
||||
return await prisma.client.wishlist.update({
|
||||
where: {
|
||||
id: id,
|
||||
},
|
||||
data: {
|
||||
...payload,
|
||||
},
|
||||
})
|
||||
},
|
||||
delete: async (id: string) => {
|
||||
return await prisma.client.wishlist.delete({
|
||||
where: {
|
||||
id: id,
|
||||
},
|
||||
})
|
||||
},
|
||||
createItem: async (wishlistId: string, payload: WishlistItem) => {
|
||||
const wishlist = await prisma.client.wishlist.update({
|
||||
where: {
|
||||
id: wishlistId,
|
||||
},
|
||||
data: {
|
||||
items: {
|
||||
create: {
|
||||
...payload,
|
||||
},
|
||||
},
|
||||
},
|
||||
include: { items: true },
|
||||
})
|
||||
return wishlist.items.pop()
|
||||
},
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
updateItem: async (itemId: number, payload: any) => {
|
||||
return await prisma.client.item.update({
|
||||
|
@ -28,4 +64,11 @@ export default {
|
|||
},
|
||||
})
|
||||
},
|
||||
deleteItem: async (itemId: number) => {
|
||||
return await prisma.client.item.delete({
|
||||
where: {
|
||||
id: itemId,
|
||||
},
|
||||
})
|
||||
},
|
||||
}
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
import { FastifyInstance } from 'fastify'
|
||||
import { default as wishlistRoute } from './wishlist/'
|
||||
import { defaultErrorHandler, notFoundHandler } from '../config/errors'
|
||||
|
||||
export default {
|
||||
register: (app: FastifyInstance) => {
|
||||
return app.register(
|
||||
async (app) => {
|
||||
await app.setNotFoundHandler(notFoundHandler)
|
||||
await app.setErrorHandler(defaultErrorHandler)
|
||||
await app.register(wishlistRoute, { prefix: '/wishlist' })
|
||||
},
|
||||
{ prefix: '/api' }
|
||||
|
|
56
src/api/routes/wishlist/create.ts
Normal file
56
src/api/routes/wishlist/create.ts
Normal file
|
@ -0,0 +1,56 @@
|
|||
import { Wishlist, WishlistItem } from '@/types'
|
||||
import { FastifyRequest, FastifyReply, RouteOptions } from 'fastify'
|
||||
import { wishlist } from '../../models'
|
||||
import {
|
||||
wishlistItemRequestSchema,
|
||||
wishlistItemResponseSchema,
|
||||
wishlistRequestSchema,
|
||||
wishlistResponseSchema,
|
||||
} from '../../config/schemas'
|
||||
|
||||
interface createItemRequest extends FastifyRequest {
|
||||
params: {
|
||||
wishlistId: string
|
||||
}
|
||||
}
|
||||
|
||||
export const createList = <RouteOptions>{
|
||||
method: 'POST',
|
||||
url: '/',
|
||||
schema: {
|
||||
body: wishlistRequestSchema,
|
||||
response: {
|
||||
201: wishlistResponseSchema,
|
||||
},
|
||||
},
|
||||
handler: async (request: FastifyRequest, reply: FastifyReply) => {
|
||||
request.log.debug(request.body)
|
||||
const item = await wishlist.create(request.body as Wishlist)
|
||||
reply.code(201).send(item)
|
||||
},
|
||||
}
|
||||
|
||||
export const createItem = <RouteOptions>{
|
||||
method: 'POST',
|
||||
url: '/:wishlistId/item',
|
||||
schema: {
|
||||
body: wishlistItemRequestSchema,
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
wishlistId: { type: 'string' },
|
||||
},
|
||||
},
|
||||
response: {
|
||||
201: wishlistItemResponseSchema,
|
||||
},
|
||||
},
|
||||
handler: async (request: createItemRequest, reply: FastifyReply) => {
|
||||
request.log.debug(request.body)
|
||||
const item = await wishlist.createItem(
|
||||
request.params.wishlistId,
|
||||
request.body as WishlistItem
|
||||
)
|
||||
reply.code(201).send(item)
|
||||
},
|
||||
}
|
50
src/api/routes/wishlist/delete.ts
Normal file
50
src/api/routes/wishlist/delete.ts
Normal file
|
@ -0,0 +1,50 @@
|
|||
import { FastifyRequest, FastifyReply, RouteOptions } from 'fastify'
|
||||
import { wishlist } from '../../models'
|
||||
|
||||
interface deleteRequest extends FastifyRequest {
|
||||
params: {
|
||||
wishlistId: string
|
||||
}
|
||||
}
|
||||
|
||||
interface deleteItemRequest extends FastifyRequest {
|
||||
params: {
|
||||
wishlistId: string
|
||||
itemId: number
|
||||
}
|
||||
}
|
||||
|
||||
export const deleteList = <RouteOptions>{
|
||||
method: 'DELETE',
|
||||
url: '/:wishlistId',
|
||||
schema: {
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
wishlistId: { type: 'string' },
|
||||
},
|
||||
},
|
||||
},
|
||||
handler: async (request: deleteRequest, reply: FastifyReply) => {
|
||||
await wishlist.delete(request.params.wishlistId)
|
||||
reply.code(204).send()
|
||||
},
|
||||
}
|
||||
|
||||
export const deleteItem = <RouteOptions>{
|
||||
method: 'DELETE',
|
||||
url: '/:wishlistId/item/:itemId',
|
||||
schema: {
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
wishlistId: { type: 'string' },
|
||||
itemId: { type: 'number' },
|
||||
},
|
||||
},
|
||||
},
|
||||
handler: async (request: deleteItemRequest, reply: FastifyReply) => {
|
||||
await wishlist.deleteItem(request.params.itemId)
|
||||
reply.code(204).send()
|
||||
},
|
||||
}
|
|
@ -1,9 +1,16 @@
|
|||
import { FastifyInstance } from 'fastify'
|
||||
import { getAll, getBySlugUrl } from './read'
|
||||
import { updateItem } from './update'
|
||||
import { updateList, updateItem } from './update'
|
||||
import { createList, createItem } from './create'
|
||||
import { deleteList, deleteItem } from './delete'
|
||||
|
||||
export default async (app: FastifyInstance) => {
|
||||
await app.route(getAll)
|
||||
await app.route(getBySlugUrl)
|
||||
await app.route(createList)
|
||||
await app.route(createItem)
|
||||
await app.route(updateList)
|
||||
await app.route(updateItem)
|
||||
await app.route(deleteList)
|
||||
await app.route(deleteItem)
|
||||
}
|
||||
|
|
|
@ -1,22 +1,15 @@
|
|||
import { FastifyRequest, FastifyReply, RouteOptions } from 'fastify'
|
||||
import { wishlist } from '../../models'
|
||||
import { wishlistResponseSchema } from '../../config/schemas'
|
||||
|
||||
export const getAll = <any>{
|
||||
export const getAll = <RouteOptions>{
|
||||
method: 'GET',
|
||||
url: '/',
|
||||
schema: {
|
||||
response: {
|
||||
200: {
|
||||
type: 'array',
|
||||
items: {
|
||||
properties: {
|
||||
id: { type: 'string' },
|
||||
title: { type: 'string' },
|
||||
imageSrc: { type: 'string' },
|
||||
description: { type: 'string' },
|
||||
slugUrlText: { type: 'string' },
|
||||
},
|
||||
},
|
||||
items: wishlistResponseSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -36,31 +29,7 @@ export const getBySlugUrl = <RouteOptions>{
|
|||
url: '/:slugText',
|
||||
schema: {
|
||||
response: {
|
||||
200: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string' },
|
||||
title: { type: 'string' },
|
||||
imageSrc: { type: 'string' },
|
||||
description: { type: 'string' },
|
||||
slugUrlText: { type: 'string' },
|
||||
items: {
|
||||
type: 'array',
|
||||
items: {
|
||||
properties: {
|
||||
id: { type: 'number' },
|
||||
title: { type: 'string' },
|
||||
url: { type: 'string' },
|
||||
imageSrc: { type: 'string' },
|
||||
description: { type: 'string' },
|
||||
comment: { type: 'string' },
|
||||
bought: { type: 'boolean' },
|
||||
wishlistId: { type: 'string' },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
200: wishlistResponseSchema,
|
||||
},
|
||||
},
|
||||
handler: async (request: GetBySlugUrlTextRequest, reply: FastifyReply) => {
|
||||
|
@ -68,10 +37,7 @@ export const getBySlugUrl = <RouteOptions>{
|
|||
if (list) {
|
||||
return list
|
||||
} else {
|
||||
return reply.code(404).send({
|
||||
error: 'notFound',
|
||||
http: 404,
|
||||
})
|
||||
return reply.callNotFound()
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
|
@ -1,58 +1,69 @@
|
|||
import { Wishlist } from '@/types'
|
||||
import { FastifyRequest, FastifyReply, RouteOptions } from 'fastify'
|
||||
import { wishlist } from '../../models'
|
||||
import {
|
||||
wishlistRequestSchema,
|
||||
wishlistResponseSchema,
|
||||
wishlistItemRequestSchema,
|
||||
wishlistItemResponseSchema,
|
||||
} from '../../config/schemas'
|
||||
|
||||
interface GetBySlugUrlTextRequest extends FastifyRequest {
|
||||
interface updateRequest extends FastifyRequest {
|
||||
params: {
|
||||
wishlistId: string
|
||||
}
|
||||
}
|
||||
|
||||
interface updateItemRequest extends FastifyRequest {
|
||||
params: {
|
||||
wishlistId: string
|
||||
itemId: number
|
||||
}
|
||||
}
|
||||
|
||||
export const updateList = <RouteOptions>{
|
||||
method: 'PUT',
|
||||
url: '/:wishlistId',
|
||||
schema: {
|
||||
body: wishlistRequestSchema,
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
wishlistId: { type: 'string' },
|
||||
},
|
||||
},
|
||||
response: {
|
||||
200: wishlistResponseSchema,
|
||||
},
|
||||
},
|
||||
handler: async (request: updateRequest, reply: FastifyReply) => {
|
||||
request.log.debug(request.body)
|
||||
const item = await wishlist.update(
|
||||
request.params.wishlistId,
|
||||
request.body as Wishlist
|
||||
)
|
||||
reply.code(201).send(item)
|
||||
},
|
||||
}
|
||||
|
||||
export const updateItem = <RouteOptions>{
|
||||
method: 'PUT',
|
||||
url: '/:wishlistId/item/:itemId',
|
||||
schema: {
|
||||
body: {
|
||||
body: wishlistItemRequestSchema,
|
||||
params: {
|
||||
type: 'object',
|
||||
additionalProperties: false,
|
||||
properties: {
|
||||
title: { type: 'string' },
|
||||
url: { type: 'string' },
|
||||
image: { type: 'string' },
|
||||
description: { type: 'string' },
|
||||
comment: { type: 'string' },
|
||||
bought: { type: 'boolean' },
|
||||
wishlistId: { type: 'string' },
|
||||
itemId: { type: 'number' },
|
||||
},
|
||||
},
|
||||
response: {
|
||||
204: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'number' },
|
||||
title: { type: 'string' },
|
||||
url: { type: 'string' },
|
||||
image: { type: 'string' },
|
||||
description: { type: 'string' },
|
||||
comment: { type: 'string' },
|
||||
bought: { type: 'boolean' },
|
||||
wishlistId: { type: 'string' },
|
||||
},
|
||||
},
|
||||
200: wishlistItemResponseSchema,
|
||||
},
|
||||
},
|
||||
handler: async (request: GetBySlugUrlTextRequest, reply: FastifyReply) => {
|
||||
handler: async (request: updateItemRequest, reply: FastifyReply) => {
|
||||
request.log.debug(request.body)
|
||||
const item = await wishlist.updateItem(
|
||||
Number(request.params.itemId),
|
||||
request.body
|
||||
)
|
||||
if (item) {
|
||||
return item
|
||||
} else {
|
||||
return reply.code(404).send({
|
||||
error: 'notFound',
|
||||
http: 404,
|
||||
})
|
||||
}
|
||||
reply.send(await wishlist.updateItem(request.params.itemId, request.body))
|
||||
},
|
||||
}
|
||||
|
|
|
@ -9,12 +9,12 @@ export interface WishlistItem {
|
|||
wishlistId: boolean
|
||||
}
|
||||
export interface Wishlist {
|
||||
id: string
|
||||
id?: string
|
||||
title: string
|
||||
description: string
|
||||
imageSrc: string
|
||||
slugUrlText: string
|
||||
items: WishlistItem[]
|
||||
items?: WishlistItem[]
|
||||
}
|
||||
export interface TileProp {
|
||||
title: string
|
||||
|
|
|
@ -16,7 +16,7 @@ const { list, fetch, updateItem } = useWishlistStore()
|
|||
await fetch(route.params.slug as string)
|
||||
|
||||
const notBoughtItems = computed(() => {
|
||||
return list.value?.items.filter(
|
||||
return list.value?.items?.filter(
|
||||
(item: WishlistItemType) => item.bought === false
|
||||
)
|
||||
})
|
||||
|
|
Loading…
Add table
Reference in a new issue