Skip to content

Commit

Permalink
Merge pull request #10 from wisemen-digital/feature/cart_layer
Browse files Browse the repository at this point in the history
[FEATURE]: Cart layer
  • Loading branch information
Robbe95 authored Jun 26, 2024
2 parents 5f29166 + 3f20911 commit 0f101a8
Show file tree
Hide file tree
Showing 55 changed files with 979 additions and 3 deletions.
3 changes: 2 additions & 1 deletion layers/base/locales/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,5 +96,6 @@
"shared.settings": "Instellingen",
"locale.fr": "Frans",
"locale.nl": "Nederlands",
"locale.en": "Engels"
"locale.en": "Engels",
"empty": "-"
}
19 changes: 19 additions & 0 deletions layers/base/models/address/address.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { addressTypeSchema } from '@base/models/address/addressType.model'
import { addressUuidSchema } from '@base/models/address/addressUuid.model'
import { z } from 'zod'

export const addressSchema = z.object({
id: addressUuidSchema,
box: z.string().nullable(),
city: z.string(),
country: z.string(),
email: z.string().nullable(),
label: z.string(),
number: z.number(),
phone: z.string().nullable(),
postalCode: z.string(),
street: z.string(),
types: addressTypeSchema.array(),
})

export type Address = z.infer<typeof addressSchema>
20 changes: 20 additions & 0 deletions layers/base/models/address/address.transformer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { Address } from '@base/models/address/address.model'
import type { AddressDto } from '@base/models/address/addressDto.model'

export class AddressTransformer {
static toAddress(dto: AddressDto): Address {
return {
id: dto.id,
box: dto.box,
city: dto.city,
country: dto.country,
email: dto.email,
label: dto.label,
number: dto.number,
phone: dto.phone,
postalCode: dto.postalCode,
street: dto.street,
types: dto.types,
}
}
}
19 changes: 19 additions & 0 deletions layers/base/models/address/addressDto.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { addressTypeSchema } from '@base/models/address/addressType.model'
import { addressUuidSchema } from '@base/models/address/addressUuid.model'
import { z } from 'zod'

export const addressDtoSchema = z.object({
id: addressUuidSchema,
box: z.string().nullable(),
city: z.string(),
country: z.string(),
email: z.string().nullable(),
label: z.string(),
number: z.number(),
phone: z.string().nullable(),
postalCode: z.string(),
street: z.string(),
types: addressTypeSchema.array(),
})

export type AddressDto = z.infer<typeof addressDtoSchema>
8 changes: 8 additions & 0 deletions layers/base/models/address/addressType.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { z } from 'zod'

export const addressTypeSchema = z.enum([
'shipping',
'delivery',
])

export type AddressType = z.infer<typeof addressTypeSchema>
4 changes: 4 additions & 0 deletions layers/base/models/address/addressUuid.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { z } from 'zod'

export const addressUuidSchema = z.string().uuid().brand('AddressUuid')
export type AddressUuid = z.infer<typeof addressUuidSchema>
7 changes: 7 additions & 0 deletions layers/cart/api/cart/keys/cart.keys.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { createQueryKeys } from '@lukemorales/query-key-factory'

export const cartKeys = createQueryKeys('cart', {
get: {
queryKey: null,
},
})
12 changes: 12 additions & 0 deletions layers/cart/api/cart/queries/useCart.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { useQuery } from '@base/composables/query/useQuery'
import { cartKeys } from '@cart/api/cart/keys/cart.keys'
import { CartService } from '@cart/api/cart/services/cart.service'

export function useCart() {
return useQuery({
...cartKeys.get,
queryFn: async () => {
return await CartService.get()
},
})
};
17 changes: 17 additions & 0 deletions layers/cart/api/cart/queries/useCartAdd.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { cartKeys } from '@cart/api/cart/keys/cart.keys'
import { CartService } from '@cart/api/cart/services/cart.service'
import type { CartAddForm } from '@cart/models/cart/add/cartAddForm.model'
import { useMutation, useQueryClient } from '@tanstack/vue-query'

export function useCartAdd() {
const queryClient = useQueryClient()

return useMutation({
mutationFn: async (form: CartAddForm) => {
return await CartService.add(form)
},
onSuccess(data) {
queryClient.setQueryData(cartKeys.get.queryKey, data)
},
})
};
17 changes: 17 additions & 0 deletions layers/cart/api/cart/queries/useCartAddBulk.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { cartKeys } from '@cart/api/cart/keys/cart.keys'
import { CartService } from '@cart/api/cart/services/cart.service'
import type { CartAddBulkForm } from '@cart/models/cart/add-bulk/cartAddBulkForm.model'
import { useMutation, useQueryClient } from '@tanstack/vue-query'

export function useCartAddBulk() {
const queryClient = useQueryClient()

return useMutation({
mutationFn: async (form: CartAddBulkForm) => {
return await CartService.addBulk(form)
},
onSuccess(data) {
queryClient.setQueryData(cartKeys.get.queryKey, data)
},
})
};
17 changes: 17 additions & 0 deletions layers/cart/api/cart/queries/useCartRemove.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { cartKeys } from '@cart/api/cart/keys/cart.keys'
import { CartService } from '@cart/api/cart/services/cart.service'
import type { CartRemoveForm } from '@cart/models/cart/remove/cartRemoveForm.model'
import { useMutation, useQueryClient } from '@tanstack/vue-query'

export function useCartRemove() {
const queryClient = useQueryClient()

return useMutation({
mutationFn: async (form: CartRemoveForm) => {
return await CartService.remove(form)
},
onSuccess(data) {
queryClient.setQueryData(cartKeys.get.queryKey, data)
},
})
};
17 changes: 17 additions & 0 deletions layers/cart/api/cart/queries/useCartUpdate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { cartKeys } from '@cart/api/cart/keys/cart.keys'
import { CartService } from '@cart/api/cart/services/cart.service'
import type { CartUpdateForm } from '@cart/models/cart/update/cartUpdateForm.model'
import { useMutation, useQueryClient } from '@tanstack/vue-query'

export function useCartUpdate() {
const queryClient = useQueryClient()

return useMutation({
mutationFn: async (form: CartUpdateForm) => {
return await CartService.update(form)
},
onSuccess(data) {
queryClient.setQueryData(cartKeys.get.queryKey, data)
},
})
};
63 changes: 63 additions & 0 deletions layers/cart/api/cart/services/cart.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { useApi } from '@base/composables/api/useApi'
import type { CartAddForm } from '@cart/models/cart/add/cartAddForm.model'
import type { CartAddBulkForm } from '@cart/models/cart/add-bulk/cartAddBulkForm.model'
import { CartTransformer } from '@cart/models/cart/cart.transformer'
import type { Cart } from '@cart/models/cart/get/cart.model'
import { cartDtoSchema } from '@cart/models/cart/get/cartDto.model'
import type { CartRemoveForm } from '@cart/models/cart/remove/cartRemoveForm.model'
import type { CartUpdateForm } from '@cart/models/cart/update/cartUpdateForm.model'

export class CartService {
static async add(addForm: CartAddForm): Promise<Cart> {
const api = useApi()
const data = await api.post({
body: CartTransformer.toAddDto(addForm),
responseSchema: cartDtoSchema,
url: `/cart/${addForm.cartId}/items`,
})

return CartTransformer.toCart(data)
}

static async addBulk(addForm: CartAddBulkForm): Promise<Cart> {
const api = useApi()
const data = await api.post({
body: CartTransformer.toAddBulkDto(addForm),
responseSchema: cartDtoSchema,
url: `/cart/${addForm.cartId}/items/bulk`,
})

return CartTransformer.toCart(data)
}

static async get(): Promise<Cart> {
const api = useApi()
const data = await api.get({
responseSchema: cartDtoSchema,
url: `/cart`,
})

return CartTransformer.toCart(data)
}

static async remove(removeForm: CartRemoveForm): Promise<Cart> {
const api = useApi()
const data = await api.delete({
responseSchema: cartDtoSchema,
url: `/cart/${removeForm.cartId}/items/${removeForm.orderProductId}`,
})

return CartTransformer.toCart(data)
}

static async update(updateForm: CartUpdateForm): Promise<Cart> {
const api = useApi()
const data = await api.post({
body: CartTransformer.toUpdateDto(updateForm),
responseSchema: cartDtoSchema,
url: `/cart/${updateForm.cartId}/items/${updateForm.orderProductId}`,
})

return CartTransformer.toCart(data)
}
}
20 changes: 20 additions & 0 deletions layers/cart/api/order/keys/order.keys.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { OrderUuid } from '@cart/models/order/orderUuid.model'
import { createQueryKeys } from '@lukemorales/query-key-factory'

export const orderKeys = createQueryKeys('order', {
all: (page: MaybeRefOrGetter<number>) => ({
queryKey: [
page,
],
}),
getByUuid: (uuid: MaybeRefOrGetter<OrderUuid>) => ({
queryKey: [
uuid,
],
}),
infinite: (search: MaybeRefOrGetter<string>) => ({
queryKey: [
search,
],
}),
})
17 changes: 17 additions & 0 deletions layers/cart/api/order/queries/useOrder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { useQuery } from '@base/composables/query/useQuery'
import { orderKeys } from '@cart/api/order/keys/order.keys'
import { OrderService } from '@cart/api/order/services/order.service'
import type { OrderUuid } from '@cart/models/order/orderUuid.model'

export function useOrder(uuid: Ref<OrderUuid>) {
const ordersQuery = orderKeys.getByUuid(uuid)

return useQuery({
queryFn: async () => {
const data = await OrderService.getByUuid(uuid.value)

return data
},
queryKey: ordersQuery.queryKey,
})
};
19 changes: 19 additions & 0 deletions layers/cart/api/order/queries/useOrders.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { useQuery } from '@base/composables/query/useQuery'
import { orderKeys } from '@cart/api/order/keys/order.keys'
import { OrderService } from '@cart/api/order/services/order.service'

export function useOrders(options: {
page: Ref<number>
}) {
const { page } = options

return useQuery({
queryFn: async () => {
const data = await OrderService.getAll(page.value)

return data
},

queryKey: orderKeys.all(page).queryKey,
})
};
29 changes: 29 additions & 0 deletions layers/cart/api/order/queries/useOrdersInfinite.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import type { PaginatedData } from '@base/models/paginated-data/paginatedData.model'
import { orderKeys } from '@cart/api/order/keys/order.keys'
import { OrderService } from '@cart/api/order/services/order.service'
import type { OrderIndex } from '@cart/models/order/index/orderIndex.model'
import { useInfiniteQuery } from '@tanstack/vue-query'

export function useOrdersInfinite(search: Ref<null | string>) {
const convertedSearch = computed<string>(() => search.value ?? '')

return useInfiniteQuery({
getNextPageParam: (lastPage: PaginatedData<OrderIndex>, _, lastPageParams) => {
const perPage = lastPage.pagination.per_page
const total = lastPage.pagination.total

if (perPage * lastPageParams < total) {
return lastPageParams + 1
}

return undefined
},
initialPageParam: 1,
queryFn: async ({ pageParam }) => {
const data = await OrderService.getAll(pageParam, search.value)

return data
},
queryKey: orderKeys.infinite(convertedSearch).queryKey,
})
};
43 changes: 43 additions & 0 deletions layers/cart/api/order/services/order.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { useApi } from '@base/composables/api/useApi'
import {
type PaginatedData,
paginatedDataSchema,
} from '@base/models/paginated-data/paginatedData.model'
import type { Order } from '@cart/models/order/detail/order.model'
import { orderDtoSchema } from '@cart/models/order/detail/orderDto.model'
import type { OrderIndex } from '@cart/models/order/index/orderIndex.model'
import { orderIndexDtoSchema } from '@cart/models/order/index/orderIndexDto.model'
import { OrderTransformer } from '@cart/models/order/order.transformer'
import type { OrderUuid } from '@cart/models/order/orderUuid.model'

export class OrderService {
static async getAll(page: number, search?: null | string): Promise<PaginatedData<OrderIndex>> {
const api = useApi()
const response = await api.get({
config: {
params: {
page,
per_page: 20,
search: search == null || search === '' ? undefined : search,
},
},
responseSchema: paginatedDataSchema(orderIndexDtoSchema),
url: `/orders`,
})

return {
...response,
data: response.data.map(OrderTransformer.toOrderIndex),
}
}

static async getByUuid(uuid: OrderUuid): Promise<Order> {
const api = useApi()
const response = await api.get({
responseSchema: orderDtoSchema,
url: `/orders/${uuid}`,
})

return OrderTransformer.toOrder(response)
}
}
Loading

0 comments on commit 0f101a8

Please sign in to comment.