From 237335dd68bf8de863ee89f52628ed7b2dd58948 Mon Sep 17 00:00:00 2001 From: Robbe Date: Wed, 26 Jun 2024 09:52:46 +0200 Subject: [PATCH 1/2] feat: functional cart --- layers/base/locales/nl.json | 3 +- layers/base/models/address/address.model.ts | 19 ++++ .../models/address/address.transformer.ts | 20 ++++ .../base/models/address/addressDto.model.ts | 19 ++++ .../base/models/address/addressType.model.ts | 8 ++ .../base/models/address/addressUuid.model.ts | 4 + layers/cart/api/cart/keys/cart.keys.ts | 7 ++ layers/cart/api/cart/queries/useCart.ts | 12 +++ layers/cart/api/cart/queries/useCartAdd.ts | 17 ++++ .../cart/api/cart/queries/useCartAddBulk.ts | 17 ++++ layers/cart/api/cart/queries/useCartRemove.ts | 17 ++++ layers/cart/api/cart/queries/useCartUpdate.ts | 17 ++++ layers/cart/api/cart/services/cart.service.ts | 63 ++++++++++++ layers/cart/api/order/keys/order.keys.ts | 20 ++++ layers/cart/api/order/queries/useOrder.ts | 17 ++++ layers/cart/api/order/queries/useOrders.ts | 19 ++++ .../api/order/queries/useOrdersInfinite.ts | 29 ++++++ .../cart/api/order/services/order.service.ts | 43 +++++++++ .../composables/cart/useOrderOrCartData.ts | 63 ++++++++++++ layers/cart/locales/en.json | 2 + layers/cart/locales/fr.json | 1 + layers/cart/locales/nl.json | 3 + .../cart/add-bulk/cartAddBulkDto.model.ts | 11 +++ .../cart/add-bulk/cartAddBulkForm.model.ts | 13 +++ .../cart/models/cart/add/cartAddDto.model.ts | 9 ++ .../cart/models/cart/add/cartAddForm.model.ts | 11 +++ layers/cart/models/cart/cart.transformer.ts | 50 ++++++++++ layers/cart/models/cart/cartUuid.model.ts | 4 + layers/cart/models/cart/get/cart.model.ts | 11 +++ layers/cart/models/cart/get/cartDto.model.ts | 11 +++ .../cart/remove/cartRemoveForm.model.ts | 10 ++ .../models/cart/update/cartUpdateDto.model.ts | 7 ++ .../cart/update/cartUpdateForm.model.ts | 11 +++ .../order-product/orderProduct.model.ts | 15 +++ .../order-product/orderProduct.transformer.ts | 15 +++ .../order-product/orderProductDto.model.ts | 15 +++ .../order-product/orderProductUuid.model.ts | 4 + .../cart/models/order/detail/order.model.ts | 21 ++++ .../models/order/detail/orderDto.model.ts | 21 ++++ .../models/order/index/orderIndex.model.ts | 16 ++++ .../models/order/index/orderIndexDto.model.ts | 16 ++++ layers/cart/models/order/order.transformer.ts | 37 +++++++ layers/cart/models/order/orderStatus.model.ts | 10 ++ layers/cart/models/order/orderUuid.model.ts | 4 + .../models/product/detail/product.model.ts | 12 +++ .../models/product/detail/productDto.model.ts | 11 +++ .../product/index/productIndex.model.ts | 11 +++ .../product/index/productIndexDto.model.ts | 11 +++ .../models/product/product.transformer.ts | 23 +++++ .../cart/models/product/productUuid.model.ts | 4 + layers/cart/nuxt.config.ts | 32 +++++++ layers/cart/stores/cart.store.ts | 96 +++++++++++++++++++ nuxt.config.ts | 1 + package.json | 1 + pnpm-lock.yaml | 35 ++++++- 55 files changed, 977 insertions(+), 2 deletions(-) create mode 100644 layers/base/models/address/address.model.ts create mode 100644 layers/base/models/address/address.transformer.ts create mode 100644 layers/base/models/address/addressDto.model.ts create mode 100644 layers/base/models/address/addressType.model.ts create mode 100644 layers/base/models/address/addressUuid.model.ts create mode 100644 layers/cart/api/cart/keys/cart.keys.ts create mode 100644 layers/cart/api/cart/queries/useCart.ts create mode 100644 layers/cart/api/cart/queries/useCartAdd.ts create mode 100644 layers/cart/api/cart/queries/useCartAddBulk.ts create mode 100644 layers/cart/api/cart/queries/useCartRemove.ts create mode 100644 layers/cart/api/cart/queries/useCartUpdate.ts create mode 100644 layers/cart/api/cart/services/cart.service.ts create mode 100644 layers/cart/api/order/keys/order.keys.ts create mode 100644 layers/cart/api/order/queries/useOrder.ts create mode 100644 layers/cart/api/order/queries/useOrders.ts create mode 100644 layers/cart/api/order/queries/useOrdersInfinite.ts create mode 100644 layers/cart/api/order/services/order.service.ts create mode 100644 layers/cart/composables/cart/useOrderOrCartData.ts create mode 100644 layers/cart/locales/en.json create mode 100644 layers/cart/locales/fr.json create mode 100644 layers/cart/locales/nl.json create mode 100644 layers/cart/models/cart/add-bulk/cartAddBulkDto.model.ts create mode 100644 layers/cart/models/cart/add-bulk/cartAddBulkForm.model.ts create mode 100644 layers/cart/models/cart/add/cartAddDto.model.ts create mode 100644 layers/cart/models/cart/add/cartAddForm.model.ts create mode 100644 layers/cart/models/cart/cart.transformer.ts create mode 100644 layers/cart/models/cart/cartUuid.model.ts create mode 100644 layers/cart/models/cart/get/cart.model.ts create mode 100644 layers/cart/models/cart/get/cartDto.model.ts create mode 100644 layers/cart/models/cart/remove/cartRemoveForm.model.ts create mode 100644 layers/cart/models/cart/update/cartUpdateDto.model.ts create mode 100644 layers/cart/models/cart/update/cartUpdateForm.model.ts create mode 100644 layers/cart/models/order-product/orderProduct.model.ts create mode 100644 layers/cart/models/order-product/orderProduct.transformer.ts create mode 100644 layers/cart/models/order-product/orderProductDto.model.ts create mode 100644 layers/cart/models/order-product/orderProductUuid.model.ts create mode 100644 layers/cart/models/order/detail/order.model.ts create mode 100644 layers/cart/models/order/detail/orderDto.model.ts create mode 100644 layers/cart/models/order/index/orderIndex.model.ts create mode 100644 layers/cart/models/order/index/orderIndexDto.model.ts create mode 100644 layers/cart/models/order/order.transformer.ts create mode 100644 layers/cart/models/order/orderStatus.model.ts create mode 100644 layers/cart/models/order/orderUuid.model.ts create mode 100644 layers/cart/models/product/detail/product.model.ts create mode 100644 layers/cart/models/product/detail/productDto.model.ts create mode 100644 layers/cart/models/product/index/productIndex.model.ts create mode 100644 layers/cart/models/product/index/productIndexDto.model.ts create mode 100644 layers/cart/models/product/product.transformer.ts create mode 100644 layers/cart/models/product/productUuid.model.ts create mode 100644 layers/cart/nuxt.config.ts create mode 100644 layers/cart/stores/cart.store.ts diff --git a/layers/base/locales/nl.json b/layers/base/locales/nl.json index d4cd7c7..5c8f15e 100644 --- a/layers/base/locales/nl.json +++ b/layers/base/locales/nl.json @@ -96,5 +96,6 @@ "shared.settings": "Instellingen", "locale.fr": "Frans", "locale.nl": "Nederlands", - "locale.en": "Engels" + "locale.en": "Engels", + "empty": "-" } diff --git a/layers/base/models/address/address.model.ts b/layers/base/models/address/address.model.ts new file mode 100644 index 0000000..c99f40f --- /dev/null +++ b/layers/base/models/address/address.model.ts @@ -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 diff --git a/layers/base/models/address/address.transformer.ts b/layers/base/models/address/address.transformer.ts new file mode 100644 index 0000000..1a1cfa0 --- /dev/null +++ b/layers/base/models/address/address.transformer.ts @@ -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, + } + } +} diff --git a/layers/base/models/address/addressDto.model.ts b/layers/base/models/address/addressDto.model.ts new file mode 100644 index 0000000..02c7b3c --- /dev/null +++ b/layers/base/models/address/addressDto.model.ts @@ -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 diff --git a/layers/base/models/address/addressType.model.ts b/layers/base/models/address/addressType.model.ts new file mode 100644 index 0000000..22d2a11 --- /dev/null +++ b/layers/base/models/address/addressType.model.ts @@ -0,0 +1,8 @@ +import { z } from 'zod' + +export const addressTypeSchema = z.enum([ + 'shipping', + 'delivery', +]) + +export type AddressType = z.infer diff --git a/layers/base/models/address/addressUuid.model.ts b/layers/base/models/address/addressUuid.model.ts new file mode 100644 index 0000000..a213e87 --- /dev/null +++ b/layers/base/models/address/addressUuid.model.ts @@ -0,0 +1,4 @@ +import { z } from 'zod' + +export const addressUuidSchema = z.string().uuid().brand('AddressUuid') +export type AddressUuid = z.infer diff --git a/layers/cart/api/cart/keys/cart.keys.ts b/layers/cart/api/cart/keys/cart.keys.ts new file mode 100644 index 0000000..1f329dd --- /dev/null +++ b/layers/cart/api/cart/keys/cart.keys.ts @@ -0,0 +1,7 @@ +import { createQueryKeys } from '@lukemorales/query-key-factory' + +export const cartKeys = createQueryKeys('cart', { + get: { + queryKey: null, + }, +}) diff --git a/layers/cart/api/cart/queries/useCart.ts b/layers/cart/api/cart/queries/useCart.ts new file mode 100644 index 0000000..1573e23 --- /dev/null +++ b/layers/cart/api/cart/queries/useCart.ts @@ -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() + }, + }) +}; diff --git a/layers/cart/api/cart/queries/useCartAdd.ts b/layers/cart/api/cart/queries/useCartAdd.ts new file mode 100644 index 0000000..0fe1c5b --- /dev/null +++ b/layers/cart/api/cart/queries/useCartAdd.ts @@ -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) + }, + }) +}; diff --git a/layers/cart/api/cart/queries/useCartAddBulk.ts b/layers/cart/api/cart/queries/useCartAddBulk.ts new file mode 100644 index 0000000..e1acd45 --- /dev/null +++ b/layers/cart/api/cart/queries/useCartAddBulk.ts @@ -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) + }, + }) +}; diff --git a/layers/cart/api/cart/queries/useCartRemove.ts b/layers/cart/api/cart/queries/useCartRemove.ts new file mode 100644 index 0000000..b67958a --- /dev/null +++ b/layers/cart/api/cart/queries/useCartRemove.ts @@ -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) + }, + }) +}; diff --git a/layers/cart/api/cart/queries/useCartUpdate.ts b/layers/cart/api/cart/queries/useCartUpdate.ts new file mode 100644 index 0000000..efa968f --- /dev/null +++ b/layers/cart/api/cart/queries/useCartUpdate.ts @@ -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) + }, + }) +}; diff --git a/layers/cart/api/cart/services/cart.service.ts b/layers/cart/api/cart/services/cart.service.ts new file mode 100644 index 0000000..13b8d5c --- /dev/null +++ b/layers/cart/api/cart/services/cart.service.ts @@ -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 { + 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 { + 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 { + const api = useApi() + const data = await api.get({ + responseSchema: cartDtoSchema, + url: `/cart`, + }) + + return CartTransformer.toCart(data) + } + + static async remove(removeForm: CartRemoveForm): Promise { + 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 { + 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) + } +} diff --git a/layers/cart/api/order/keys/order.keys.ts b/layers/cart/api/order/keys/order.keys.ts new file mode 100644 index 0000000..c1b3439 --- /dev/null +++ b/layers/cart/api/order/keys/order.keys.ts @@ -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) => ({ + queryKey: [ + page, + ], + }), + getByUuid: (uuid: MaybeRefOrGetter) => ({ + queryKey: [ + uuid, + ], + }), + infinite: (search: MaybeRefOrGetter) => ({ + queryKey: [ + search, + ], + }), +}) diff --git a/layers/cart/api/order/queries/useOrder.ts b/layers/cart/api/order/queries/useOrder.ts new file mode 100644 index 0000000..d095048 --- /dev/null +++ b/layers/cart/api/order/queries/useOrder.ts @@ -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) { + const ordersQuery = orderKeys.getByUuid(uuid) + + return useQuery({ + queryFn: async () => { + const data = await OrderService.getByUuid(uuid.value) + + return data + }, + queryKey: ordersQuery.queryKey, + }) +}; diff --git a/layers/cart/api/order/queries/useOrders.ts b/layers/cart/api/order/queries/useOrders.ts new file mode 100644 index 0000000..70a54b0 --- /dev/null +++ b/layers/cart/api/order/queries/useOrders.ts @@ -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 +}) { + const { page } = options + + return useQuery({ + queryFn: async () => { + const data = await OrderService.getAll(page.value) + + return data + }, + + queryKey: orderKeys.all(page).queryKey, + }) +}; diff --git a/layers/cart/api/order/queries/useOrdersInfinite.ts b/layers/cart/api/order/queries/useOrdersInfinite.ts new file mode 100644 index 0000000..e8c9b68 --- /dev/null +++ b/layers/cart/api/order/queries/useOrdersInfinite.ts @@ -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) { + const convertedSearch = computed(() => search.value ?? '') + + return useInfiniteQuery({ + getNextPageParam: (lastPage: PaginatedData, _, 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, + }) +}; diff --git a/layers/cart/api/order/services/order.service.ts b/layers/cart/api/order/services/order.service.ts new file mode 100644 index 0000000..cd997a9 --- /dev/null +++ b/layers/cart/api/order/services/order.service.ts @@ -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> { + 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 { + const api = useApi() + const response = await api.get({ + responseSchema: orderDtoSchema, + url: `/orders/${uuid}`, + }) + + return OrderTransformer.toOrder(response) + } +} diff --git a/layers/cart/composables/cart/useOrderOrCartData.ts b/layers/cart/composables/cart/useOrderOrCartData.ts new file mode 100644 index 0000000..043f671 --- /dev/null +++ b/layers/cart/composables/cart/useOrderOrCartData.ts @@ -0,0 +1,63 @@ +import { useGlobalI18n } from '@base/composables/i18n/useGlobaI18n' +import { formatPrice } from '@base/formatters/price.formatter' +import type { Price } from '@base/models/price/price.model' +import type { Cart } from '@cart/models/cart/get/cart.model' +import type { Order } from '@cart/models/order/detail/order.model' + +export function useOrderOrCartData(orderOrCart: MaybeRefOrGetter) { + const { t } = useGlobalI18n() + + const amountOfProducts = computed(() => { + return toValue(orderOrCart)?.orderProducts.reduce((acc, orderProduct) => acc + orderProduct.quantity, 0) ?? 0 + }) + + const productsPrice = computed(() => { + return toValue(orderOrCart)?.orderProducts.reduce((acc, orderProduct) => + acc + orderProduct.price * orderProduct.quantity, 0) as Price ?? null + }) + + const shippingPrice = computed(() => { + // TODO get real shipping from BE + return 1000 as Price + }) + + const totalPrice = computed(() => { + const total = (productsPrice.value ?? 0) + (shippingPrice.value ?? 0) as Price + + return total === 0 ? null : total + }) + + const formattedTotalPrice = computed(() => { + if (totalPrice.value == null) { + return t('empty') + } + + return formatPrice(totalPrice.value) + }) + + const formattedShippingPrice = computed(() => { + if (shippingPrice.value == null) { + return t('empty') + } + + return formatPrice(shippingPrice.value) + }) + + const formattedProductsPrice = computed(() => { + if (productsPrice.value == null) { + return t('empty') + } + + return formatPrice(productsPrice.value) + }) + + return { + amountOfProducts, + formattedProductsPrice, + formattedShippingPrice, + formattedTotalPrice, + productsPrice, + shippingPrice, + totalPrice, + } +} diff --git a/layers/cart/locales/en.json b/layers/cart/locales/en.json new file mode 100644 index 0000000..2c63c08 --- /dev/null +++ b/layers/cart/locales/en.json @@ -0,0 +1,2 @@ +{ +} diff --git a/layers/cart/locales/fr.json b/layers/cart/locales/fr.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/layers/cart/locales/fr.json @@ -0,0 +1 @@ +{} diff --git a/layers/cart/locales/nl.json b/layers/cart/locales/nl.json new file mode 100644 index 0000000..0db3279 --- /dev/null +++ b/layers/cart/locales/nl.json @@ -0,0 +1,3 @@ +{ + +} diff --git a/layers/cart/models/cart/add-bulk/cartAddBulkDto.model.ts b/layers/cart/models/cart/add-bulk/cartAddBulkDto.model.ts new file mode 100644 index 0000000..8ac91f8 --- /dev/null +++ b/layers/cart/models/cart/add-bulk/cartAddBulkDto.model.ts @@ -0,0 +1,11 @@ +import { productUuidSchema } from '@cart/models/product/productUuid.model' +import { z } from 'zod' + +export const cartAddBulkDtoSchema = z.object({ + items: z.object({ + productId: productUuidSchema, + quantity: z.number(), + }).array(), +}) + +export type CartAddBulkDto = z.infer diff --git a/layers/cart/models/cart/add-bulk/cartAddBulkForm.model.ts b/layers/cart/models/cart/add-bulk/cartAddBulkForm.model.ts new file mode 100644 index 0000000..582cd19 --- /dev/null +++ b/layers/cart/models/cart/add-bulk/cartAddBulkForm.model.ts @@ -0,0 +1,13 @@ +import { cartUuidSchema } from '@cart/models/cart/cartUuid.model' +import { productUuidSchema } from '@cart/models/product/productUuid.model' +import { z } from 'zod' + +export const cartAddBulkFormSchema = z.object({ + cartId: cartUuidSchema, + items: z.object({ + productId: productUuidSchema, + quantity: z.number(), + }).array(), +}) + +export type CartAddBulkForm = z.infer diff --git a/layers/cart/models/cart/add/cartAddDto.model.ts b/layers/cart/models/cart/add/cartAddDto.model.ts new file mode 100644 index 0000000..b599c70 --- /dev/null +++ b/layers/cart/models/cart/add/cartAddDto.model.ts @@ -0,0 +1,9 @@ +import { productUuidSchema } from '@cart/models/product/productUuid.model' +import { z } from 'zod' + +export const cartAddDtoSchema = z.object({ + productId: productUuidSchema, + quantity: z.number().min(1), +}) + +export type CartAddDto = z.infer diff --git a/layers/cart/models/cart/add/cartAddForm.model.ts b/layers/cart/models/cart/add/cartAddForm.model.ts new file mode 100644 index 0000000..35a9468 --- /dev/null +++ b/layers/cart/models/cart/add/cartAddForm.model.ts @@ -0,0 +1,11 @@ +import { cartUuidSchema } from '@cart/models/cart/cartUuid.model' +import { productUuidSchema } from '@cart/models/product/productUuid.model' +import { z } from 'zod' + +export const cartAddFormSchema = z.object({ + cartId: cartUuidSchema, + productId: productUuidSchema, + quantity: z.number().min(1), +}) + +export type CartAddForm = z.infer diff --git a/layers/cart/models/cart/cart.transformer.ts b/layers/cart/models/cart/cart.transformer.ts new file mode 100644 index 0000000..7769444 --- /dev/null +++ b/layers/cart/models/cart/cart.transformer.ts @@ -0,0 +1,50 @@ +import { AddressTransformer } from '@base/models/address/address.transformer' +import type { CartAddDto } from '@cart/models/cart/add/cartAddDto.model' +import type { CartAddForm } from '@cart/models/cart/add/cartAddForm.model' +import type { CartAddBulkDto } from '@cart/models/cart/add-bulk/cartAddBulkDto.model' +import type { CartAddBulkForm } from '@cart/models/cart/add-bulk/cartAddBulkForm.model' +import type { Cart } from '@cart/models/cart/get/cart.model' +import type { CartDto } from '@cart/models/cart/get/cartDto.model' +import type { CartUpdateDto } from '@cart/models/cart/update/cartUpdateDto.model' +import type { CartUpdateForm } from '@cart/models/cart/update/cartUpdateForm.model' +import { OrderProductTransformer } from '@cart/models/order-product/orderProduct.transformer' + +export class CartTransformer { + static toAddBulkDto = (payload: CartAddBulkForm): CartAddBulkDto => { + return { + items: payload.items.map((item) => ({ + productId: item.productId, + quantity: item.quantity, + })), + } + } + + static toUpdateDto = (payload: CartUpdateForm): CartUpdateDto => { + return { + quantity: payload.quantity, + } + } + + static toAddDto(payload: CartAddForm): CartAddDto { + return { + productId: payload.productId, + quantity: payload.quantity, + } + } + + static toCart(dto: CartDto): Cart { + return { + id: dto.id, + deliveryDate: dto.deliveryDate != null ? new Date(dto.deliveryDate) : null, + orderDate: dto.orderDate != null ? new Date(dto.orderDate) : null, + isDelivered: dto.isDelivered, + deliveryAddress: dto.deliveryAddress != null ? AddressTransformer.toAddress(dto.deliveryAddress) : null, + invoiceAddress: dto.invoiceAddress != null ? AddressTransformer.toAddress(dto.invoiceAddress) : null, + orderLineCount: dto.orderLineCount, + orderNumber: dto.orderNumber, + orderProducts: dto.orderProducts.map(OrderProductTransformer.toOrderProduct), + orderStatus: dto.orderStatus, + remarks: dto.remarks, + } + } +} diff --git a/layers/cart/models/cart/cartUuid.model.ts b/layers/cart/models/cart/cartUuid.model.ts new file mode 100644 index 0000000..b37e717 --- /dev/null +++ b/layers/cart/models/cart/cartUuid.model.ts @@ -0,0 +1,4 @@ +import { z } from 'zod' + +export const cartUuidSchema = z.string().uuid().brand('CartUuid') +export type CartUuid = z.infer diff --git a/layers/cart/models/cart/get/cart.model.ts b/layers/cart/models/cart/get/cart.model.ts new file mode 100644 index 0000000..fd8bd7c --- /dev/null +++ b/layers/cart/models/cart/get/cart.model.ts @@ -0,0 +1,11 @@ +import { cartUuidSchema } from '@cart/models/cart/cartUuid.model' +import { orderSchema } from '@cart/models/order/detail/order.model' +import { z } from 'zod' + +export const cartSchema = orderSchema.extend({ + id: cartUuidSchema, + orderDate: z.date().nullable(), + orderStatus: z.literal('cart'), +}) + +export type Cart = z.infer diff --git a/layers/cart/models/cart/get/cartDto.model.ts b/layers/cart/models/cart/get/cartDto.model.ts new file mode 100644 index 0000000..c770870 --- /dev/null +++ b/layers/cart/models/cart/get/cartDto.model.ts @@ -0,0 +1,11 @@ +import { cartUuidSchema } from '@cart/models/cart/cartUuid.model' +import { orderDtoSchema } from '@cart/models/order/detail/orderDto.model' +import { z } from 'zod' + +export const cartDtoSchema = orderDtoSchema.extend({ + id: cartUuidSchema, + orderDate: z.date().nullable(), + orderStatus: z.literal('cart'), +}) + +export type CartDto = z.infer diff --git a/layers/cart/models/cart/remove/cartRemoveForm.model.ts b/layers/cart/models/cart/remove/cartRemoveForm.model.ts new file mode 100644 index 0000000..887fb0f --- /dev/null +++ b/layers/cart/models/cart/remove/cartRemoveForm.model.ts @@ -0,0 +1,10 @@ +import { cartUuidSchema } from '@cart/models/cart/cartUuid.model' +import { orderProductUuidSchema } from '@cart/models/order-product/orderProductUuid.model' +import { z } from 'zod' + +export const cartRemoveFormSchema = z.object({ + cartId: cartUuidSchema, + orderProductId: orderProductUuidSchema, +}) + +export type CartRemoveForm = z.infer diff --git a/layers/cart/models/cart/update/cartUpdateDto.model.ts b/layers/cart/models/cart/update/cartUpdateDto.model.ts new file mode 100644 index 0000000..b793591 --- /dev/null +++ b/layers/cart/models/cart/update/cartUpdateDto.model.ts @@ -0,0 +1,7 @@ +import { z } from 'zod' + +export const cartUpdateDtoSchema = z.object({ + quantity: z.number().min(1), +}) + +export type CartUpdateDto = z.infer diff --git a/layers/cart/models/cart/update/cartUpdateForm.model.ts b/layers/cart/models/cart/update/cartUpdateForm.model.ts new file mode 100644 index 0000000..46c7c96 --- /dev/null +++ b/layers/cart/models/cart/update/cartUpdateForm.model.ts @@ -0,0 +1,11 @@ +import { cartUuidSchema } from '@cart/models/cart/cartUuid.model' +import { orderProductUuidSchema } from '@cart/models/order-product/orderProductUuid.model' +import { z } from 'zod' + +export const cartUpdateFormSchema = z.object({ + cartId: cartUuidSchema, + orderProductId: orderProductUuidSchema, + quantity: z.number().min(1), +}) + +export type CartUpdateForm = z.infer diff --git a/layers/cart/models/order-product/orderProduct.model.ts b/layers/cart/models/order-product/orderProduct.model.ts new file mode 100644 index 0000000..6850496 --- /dev/null +++ b/layers/cart/models/order-product/orderProduct.model.ts @@ -0,0 +1,15 @@ +import { priceSchema } from '@base/models/price/price.model' +import { orderProductUuidSchema } from '@cart/models/order-product/orderProductUuid.model' +import { productSchema } from '@cart/models/product/detail/product.model' +import { productUuidSchema } from '@cart/models/product/productUuid.model' +import { z } from 'zod' + +export const orderProductSchema = z.object({ + id: orderProductUuidSchema, + productId: productUuidSchema, + price: priceSchema, + product: productSchema, + quantity: z.number(), +}) + +export type OrderProduct = z.infer diff --git a/layers/cart/models/order-product/orderProduct.transformer.ts b/layers/cart/models/order-product/orderProduct.transformer.ts new file mode 100644 index 0000000..fd9c1df --- /dev/null +++ b/layers/cart/models/order-product/orderProduct.transformer.ts @@ -0,0 +1,15 @@ +import type { OrderProduct } from '@cart/models/order-product/orderProduct.model' +import type { OrderProductDto } from '@cart/models/order-product/orderProductDto.model' +import { ProductTransformer } from '@cart/models/product/product.transformer' + +export class OrderProductTransformer { + static toOrderProduct(dto: OrderProductDto): OrderProduct { + return { + id: dto.id, + productId: dto.productId, + price: dto.price, + product: ProductTransformer.toProduct(dto.product), + quantity: dto.quantity, + } + } +} diff --git a/layers/cart/models/order-product/orderProductDto.model.ts b/layers/cart/models/order-product/orderProductDto.model.ts new file mode 100644 index 0000000..8cbb14c --- /dev/null +++ b/layers/cart/models/order-product/orderProductDto.model.ts @@ -0,0 +1,15 @@ +import { priceSchema } from '@base/models/price/price.model' +import { orderProductUuidSchema } from '@cart/models/order-product/orderProductUuid.model' +import { productDtoSchema } from '@cart/models/product/detail/productDto.model' +import { productUuidSchema } from '@cart/models/product/productUuid.model' +import { z } from 'zod' + +export const orderProductDtoSchema = z.object({ + id: orderProductUuidSchema, + productId: productUuidSchema, + price: priceSchema, + product: productDtoSchema, + quantity: z.number(), +}) + +export type OrderProductDto = z.infer diff --git a/layers/cart/models/order-product/orderProductUuid.model.ts b/layers/cart/models/order-product/orderProductUuid.model.ts new file mode 100644 index 0000000..a19d8eb --- /dev/null +++ b/layers/cart/models/order-product/orderProductUuid.model.ts @@ -0,0 +1,4 @@ +import { z } from 'zod' + +export const orderProductUuidSchema = z.string().uuid().brand('OrderProductUuid') +export type OrderProductUuid = z.infer diff --git a/layers/cart/models/order/detail/order.model.ts b/layers/cart/models/order/detail/order.model.ts new file mode 100644 index 0000000..bb5b03b --- /dev/null +++ b/layers/cart/models/order/detail/order.model.ts @@ -0,0 +1,21 @@ +import { addressSchema } from '@base/models/address/address.model' +import { orderStatusSchema } from '@cart/models/order/orderStatus.model' +import { orderUuidSchema } from '@cart/models/order/orderUuid.model' +import { orderProductSchema } from '@cart/models/order-product/orderProduct.model' +import { z } from 'zod' + +export const orderSchema = z.object({ + id: orderUuidSchema, + deliveryDate: z.date().nullable(), + orderDate: z.date(), + isDelivered: z.boolean(), + deliveryAddress: addressSchema.nullable(), + invoiceAddress: addressSchema.nullable(), + orderLineCount: z.number(), + orderNumber: z.string(), + orderProducts: z.array(orderProductSchema), + orderStatus: orderStatusSchema, + remarks: z.string().nullable(), +}) + +export type Order = z.infer diff --git a/layers/cart/models/order/detail/orderDto.model.ts b/layers/cart/models/order/detail/orderDto.model.ts new file mode 100644 index 0000000..9f6bcfb --- /dev/null +++ b/layers/cart/models/order/detail/orderDto.model.ts @@ -0,0 +1,21 @@ +import { addressDtoSchema } from '@base/models/address/addressDto.model' +import { orderStatusSchema } from '@cart/models/order/orderStatus.model' +import { orderUuidSchema } from '@cart/models/order/orderUuid.model' +import { orderProductDtoSchema } from '@cart/models/order-product/orderProductDto.model' +import { z } from 'zod' + +export const orderDtoSchema = z.object({ + id: orderUuidSchema, + deliveryDate: z.string().nullable(), + orderDate: z.string(), + isDelivered: z.boolean(), + deliveryAddress: addressDtoSchema.nullable(), + invoiceAddress: addressDtoSchema.nullable(), + orderLineCount: z.number(), + orderNumber: z.string(), + orderProducts: z.array(orderProductDtoSchema), + orderStatus: orderStatusSchema, + remarks: z.string().nullable(), +}) + +export type OrderDto = z.infer diff --git a/layers/cart/models/order/index/orderIndex.model.ts b/layers/cart/models/order/index/orderIndex.model.ts new file mode 100644 index 0000000..d1a0c42 --- /dev/null +++ b/layers/cart/models/order/index/orderIndex.model.ts @@ -0,0 +1,16 @@ +import { orderStatusSchema } from '@cart/models/order/orderStatus.model' +import { orderUuidSchema } from '@cart/models/order/orderUuid.model' +import { z } from 'zod' + +export const orderIndexSchema = z.object({ + id: orderUuidSchema, + deliveryDate: z.date().nullable(), + orderDate: z.date(), + isDelivered: z.boolean(), + orderLineCount: z.number(), + orderNumber: z.string(), + orderStatus: orderStatusSchema, + remarks: z.string().nullable(), +}) + +export type OrderIndex = z.infer diff --git a/layers/cart/models/order/index/orderIndexDto.model.ts b/layers/cart/models/order/index/orderIndexDto.model.ts new file mode 100644 index 0000000..1225e55 --- /dev/null +++ b/layers/cart/models/order/index/orderIndexDto.model.ts @@ -0,0 +1,16 @@ +import { orderStatusSchema } from '@cart/models/order/orderStatus.model' +import { orderUuidSchema } from '@cart/models/order/orderUuid.model' +import { z } from 'zod' + +export const orderIndexDtoSchema = z.object({ + id: orderUuidSchema, + deliveryDate: z.string().nullable(), + orderDate: z.string(), + isDelivered: z.boolean(), + orderLineCount: z.number(), + orderNumber: z.string(), + orderStatus: orderStatusSchema, + remarks: z.string().nullable(), +}) + +export type OrderIndexDto = z.infer diff --git a/layers/cart/models/order/order.transformer.ts b/layers/cart/models/order/order.transformer.ts new file mode 100644 index 0000000..d6ccf09 --- /dev/null +++ b/layers/cart/models/order/order.transformer.ts @@ -0,0 +1,37 @@ +import { AddressTransformer } from '@base/models/address/address.transformer' +import type { Order } from '@cart/models/order/detail/order.model' +import type { OrderDto } from '@cart/models/order/detail/orderDto.model' +import type { OrderIndex } from '@cart/models/order/index/orderIndex.model' +import type { OrderIndexDto } from '@cart/models/order/index/orderIndexDto.model' +import { OrderProductTransformer } from '@cart/models/order-product/orderProduct.transformer' + +export class OrderTransformer { + static toOrder(dto: OrderDto): Order { + return { + id: dto.id, + deliveryDate: dto.deliveryDate != null ? new Date(dto.deliveryDate) : null, + orderDate: new Date(dto.orderDate), + isDelivered: dto.isDelivered, + deliveryAddress: dto.deliveryAddress != null ? AddressTransformer.toAddress(dto.deliveryAddress) : null, + invoiceAddress: dto.invoiceAddress != null ? AddressTransformer.toAddress(dto.invoiceAddress) : null, + orderLineCount: dto.orderLineCount, + orderNumber: dto.orderNumber, + orderProducts: dto.orderProducts.map(OrderProductTransformer.toOrderProduct), + orderStatus: dto.orderStatus, + remarks: dto.remarks, + } + } + + static toOrderIndex(dto: OrderIndexDto): OrderIndex { + return { + id: dto.id, + deliveryDate: dto.deliveryDate != null ? new Date(dto.deliveryDate) : null, + orderDate: new Date(dto.orderDate), + isDelivered: dto.isDelivered, + orderLineCount: dto.orderLineCount, + orderNumber: dto.orderNumber, + orderStatus: dto.orderStatus, + remarks: dto.remarks, + } + } +} diff --git a/layers/cart/models/order/orderStatus.model.ts b/layers/cart/models/order/orderStatus.model.ts new file mode 100644 index 0000000..631c2bc --- /dev/null +++ b/layers/cart/models/order/orderStatus.model.ts @@ -0,0 +1,10 @@ +import { z } from 'zod' + +export const orderStatusSchema = z.enum([ + 'ordered', + 'processing', + 'to_be_shipped', + 'delivered', +]) + +export type OrderStatus = z.infer diff --git a/layers/cart/models/order/orderUuid.model.ts b/layers/cart/models/order/orderUuid.model.ts new file mode 100644 index 0000000..78f13d7 --- /dev/null +++ b/layers/cart/models/order/orderUuid.model.ts @@ -0,0 +1,4 @@ +import { z } from 'zod' + +export const orderUuidSchema = z.string().uuid().brand('OrderUuid') +export type OrderUuid = z.infer diff --git a/layers/cart/models/product/detail/product.model.ts b/layers/cart/models/product/detail/product.model.ts new file mode 100644 index 0000000..67f1542 --- /dev/null +++ b/layers/cart/models/product/detail/product.model.ts @@ -0,0 +1,12 @@ +import { priceSchema } from '@base/models/price/price.model' +import { productUuidSchema } from '@cart/models/product/productUuid.model' +import { z } from 'zod' + +export const productSchema = z.object({ + id: productUuidSchema, + isDetail: z.literal(true).default(true), + name: z.string(), + price: priceSchema.nullable(), +}) + +export type Product = z.infer diff --git a/layers/cart/models/product/detail/productDto.model.ts b/layers/cart/models/product/detail/productDto.model.ts new file mode 100644 index 0000000..bbee049 --- /dev/null +++ b/layers/cart/models/product/detail/productDto.model.ts @@ -0,0 +1,11 @@ +import { priceSchema } from '@base/models/price/price.model' +import { productUuidSchema } from '@cart/models/product/productUuid.model' +import { z } from 'zod' + +export const productDtoSchema = z.object({ + id: productUuidSchema, + name: z.string(), + price: priceSchema.nullable(), +}) + +export type ProductDto = z.infer diff --git a/layers/cart/models/product/index/productIndex.model.ts b/layers/cart/models/product/index/productIndex.model.ts new file mode 100644 index 0000000..02cc3ab --- /dev/null +++ b/layers/cart/models/product/index/productIndex.model.ts @@ -0,0 +1,11 @@ +import { priceSchema } from '@base/models/price/price.model' +import { productUuidSchema } from '@cart/models/product/productUuid.model' +import { z } from 'zod' + +export const productIndexSchema = z.object({ + id: productUuidSchema, + name: z.string(), + price: priceSchema.nullable(), +}) + +export type ProductIndex = z.infer diff --git a/layers/cart/models/product/index/productIndexDto.model.ts b/layers/cart/models/product/index/productIndexDto.model.ts new file mode 100644 index 0000000..c37f415 --- /dev/null +++ b/layers/cart/models/product/index/productIndexDto.model.ts @@ -0,0 +1,11 @@ +import { priceSchema } from '@base/models/price/price.model' +import { productUuidSchema } from '@cart/models/product/productUuid.model' +import { z } from 'zod' + +export const productIndexDtoSchema = z.object({ + id: productUuidSchema, + name: z.string(), + price: priceSchema.nullable(), +}) + +export type ProductIndexDto = z.infer diff --git a/layers/cart/models/product/product.transformer.ts b/layers/cart/models/product/product.transformer.ts new file mode 100644 index 0000000..271b666 --- /dev/null +++ b/layers/cart/models/product/product.transformer.ts @@ -0,0 +1,23 @@ +import type { Product } from '@cart/models/product/detail/product.model' +import type { ProductDto } from '@cart/models/product/detail/productDto.model' +import type { ProductIndex } from '@cart/models/product/index/productIndex.model' +import type { ProductIndexDto } from '@cart/models/product/index/productIndexDto.model' + +export class ProductTransformer { + static toProduct(dto: ProductDto): Product { + return { + id: dto.id, + isDetail: true, + name: dto.name, + price: dto.price, + } + } + + static toProductIndex(dto: ProductIndexDto): ProductIndex { + return { + id: dto.id, + name: dto.name, + price: dto.price, + } + } +} diff --git a/layers/cart/models/product/productUuid.model.ts b/layers/cart/models/product/productUuid.model.ts new file mode 100644 index 0000000..6dbe62f --- /dev/null +++ b/layers/cart/models/product/productUuid.model.ts @@ -0,0 +1,4 @@ +import { z } from 'zod' + +export const productUuidSchema = z.string().uuid().brand('ProductUuid') +export type ProductUuid = z.infer diff --git a/layers/cart/nuxt.config.ts b/layers/cart/nuxt.config.ts new file mode 100644 index 0000000..20d2265 --- /dev/null +++ b/layers/cart/nuxt.config.ts @@ -0,0 +1,32 @@ +import path from 'node:path' + +export default defineNuxtConfig({ + alias: { + '@auth': path.resolve(__dirname, '../auth'), + '@base': path.resolve(__dirname, '../base'), + '@cart': path.resolve(__dirname, './cart'), + }, + components: [ + { + pathPrefix: false, + path: '@auth/components', + }, + { + pathPrefix: false, + path: '@auth/views', + }, + ], + + extends: [ + '../base', + '../auth', + ], + i18n: { + langDir: 'locales', + locales: [ + { iso: 'en-US', code: 'en', file: 'en.json' }, + { iso: 'nl-BE', code: 'nl', file: 'nl.json' }, + { iso: 'fr-FR', code: 'fr', file: 'fr.json' }, + ], + }, +}) diff --git a/layers/cart/stores/cart.store.ts b/layers/cart/stores/cart.store.ts new file mode 100644 index 0000000..9a83431 --- /dev/null +++ b/layers/cart/stores/cart.store.ts @@ -0,0 +1,96 @@ +import { useCart } from '@cart/api/cart/queries/useCart' +import { useCartAdd } from '@cart/api/cart/queries/useCartAdd' +import { useCartAddBulk } from '@cart/api/cart/queries/useCartAddBulk' +import { useCartRemove } from '@cart/api/cart/queries/useCartRemove' +import { useCartUpdate } from '@cart/api/cart/queries/useCartUpdate' +import { useOrderOrCartData } from '@cart/composables/cart/useOrderOrCartData' +import type { CartAddForm } from '@cart/models/cart/add/cartAddForm.model' +import type { CartAddBulkForm } from '@cart/models/cart/add-bulk/cartAddBulkForm.model' +import type { CartRemoveForm } from '@cart/models/cart/remove/cartRemoveForm.model' +import type { CartUpdateForm } from '@cart/models/cart/update/cartUpdateForm.model' +import { defineStore } from 'pinia' + +export const useCartStore = defineStore('cart', () => { + const cart = useCart() + const cartAdd = useCartAdd() + const cartRemove = useCartRemove() + const cartUpdate = useCartUpdate() + const cartAddBulk = useCartAddBulk() + + const { + amountOfProducts, + productsPrice, + shippingPrice, + totalPrice, + } = useOrderOrCartData(cart.data ?? null) + + async function addProduct(payload: Omit) { + if (cart.data.value == null) { + return + } + + await cartAdd.mutateAsync({ + ...payload, + cartId: cart.data.value?.id, + }) + } + + async function addProducts(payload: Omit) { + if (cart.data.value == null) { + return + } + + await cartAddBulk.mutateAsync({ + ...payload, + cartId: cart.data.value.id, + }) + } + + async function removeProduct(payload: Omit) { + if (cart.data.value == null) { + return + } + + await cartRemove.mutateAsync({ + cartId: cart.data.value.id, + orderProductId: payload.orderProductId, + }) + } + + async function updateProduct(payload: Omit) { + if (cart.data.value == null) { + return + } + + await cartUpdate.mutateAsync({ + cartId: cart.data.value.id, + orderProductId: payload.orderProductId, + quantity: payload.quantity, + }) + } + + const isCartUpdating = computed(() => { + return cartAdd.isPending.value + || cartAddBulk.isPending.value + || cartRemove.isPending.value + || cartUpdate.isPending.value + || cart.isPending.value + }) + + onServerPrefetch(async () => { + await cart.suspense() + }) + + return { + isCartUpdating, + addProduct, + addProducts, + amountOfProducts, + cart, + productsPrice, + removeProduct, + shippingPrice, + totalPrice, + updateProduct, + } +}) diff --git a/nuxt.config.ts b/nuxt.config.ts index 44e8320..7bd92ce 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -5,6 +5,7 @@ export default defineNuxtConfig({ '@@': path.resolve(__dirname, './disable'), '@auth': path.resolve(__dirname, './layers/auth'), '@base': path.resolve(__dirname, './layers/base'), + '@cart': path.resolve(__dirname, './layers/cart'), '~~': path.resolve(__dirname, './disable'), }, app: { diff --git a/package.json b/package.json index 9c2949e..76dabc7 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ }, "dependencies": { "@fontsource-variable/inter": "^5.0.18", + "@lukemorales/query-key-factory": "^1.3.4", "@nuxtjs/i18n": "8.3.1", "@pinia/nuxt": "^0.5.1", "@tanstack/vue-query": "^5.45.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 39d6e85..4c79cdd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ dependencies: '@fontsource-variable/inter': specifier: ^5.0.18 version: 5.0.18 + '@lukemorales/query-key-factory': + specifier: ^1.3.4 + version: 1.3.4(@tanstack/query-core@5.45.0)(@tanstack/react-query@5.48.0) '@nuxtjs/i18n': specifier: 8.3.1 version: 8.3.1(rollup@4.13.2)(vue@3.4.30) @@ -1589,6 +1592,17 @@ packages: /@kwsites/promise-deferred@1.1.1: resolution: {integrity: sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==} + /@lukemorales/query-key-factory@1.3.4(@tanstack/query-core@5.45.0)(@tanstack/react-query@5.48.0): + resolution: {integrity: sha512-A3frRDdkmaNNQi6mxIshsDk4chRXWoXa05US8fBo4kci/H+lVmujS6QrwQLLGIkNIRFGjMqp2uKjC4XsLdydRw==} + engines: {node: '>=14'} + peerDependencies: + '@tanstack/query-core': '>= 4.0.0' + '@tanstack/react-query': '>= 4.0.0' + dependencies: + '@tanstack/query-core': 5.45.0 + '@tanstack/react-query': 5.48.0(react@18.3.1) + dev: false + /@mapbox/node-pre-gyp@1.0.11: resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==} hasBin: true @@ -4189,6 +4203,19 @@ packages: resolution: {integrity: sha512-RVfIZQmFUTdjhSAAblvueimfngYyfN6HlwaJUPK71PKd7yi43Vs1S/rdimmZedPWX/WGppcq/U1HOj7O7FwYxw==} dev: false + /@tanstack/query-core@5.48.0: + resolution: {integrity: sha512-lZAfPPeVIqXCswE9SSbG33B6/91XOWt/Iq41bFeWb/mnHwQSIfFRbkS4bfs+WhIk9abRArF9Id2fp0Mgo+hq6Q==} + dev: false + + /@tanstack/react-query@5.48.0(react@18.3.1): + resolution: {integrity: sha512-GDExbjYWzvDokyRqMSWXdrPiYpp95Aig0oeMIrxTaruOJJgWiWfUP//OAaowm2RrRkGVsavSZdko/XmIrrV2Nw==} + peerDependencies: + react: ^18.0.0 + dependencies: + '@tanstack/query-core': 5.48.0 + react: 18.3.1 + dev: false + /@tanstack/virtual-core@3.7.0: resolution: {integrity: sha512-p0CWuqn+n8iZmsL7/l0Xg7kbyIKnHNqkEJkMDOkg4x3Ni3LohszmnJY8FPhTgG7Ad9ZFGcdKmn1R1mKUGEh9Xg==} dev: false @@ -8939,7 +8966,6 @@ packages: hasBin: true dependencies: js-tokens: 4.0.0 - dev: true /loupe@2.3.7: resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} @@ -11185,6 +11211,13 @@ packages: resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} dev: true + /react@18.3.1: + resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} + engines: {node: '>=0.10.0'} + dependencies: + loose-envify: 1.4.0 + dev: false + /read-cache@1.0.0: resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} dependencies: From 2a277b035a3761f5558ec243ba9d4bc28d195af2 Mon Sep 17 00:00:00 2001 From: Robbe Date: Wed, 26 Jun 2024 10:01:02 +0200 Subject: [PATCH 2/2] chore: linting / typecheck --- layers/base/components/core/icon/AppAsyncIcon.vue | 1 - package.json | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/layers/base/components/core/icon/AppAsyncIcon.vue b/layers/base/components/core/icon/AppAsyncIcon.vue index dfff40b..83bf819 100644 --- a/layers/base/components/core/icon/AppAsyncIcon.vue +++ b/layers/base/components/core/icon/AppAsyncIcon.vue @@ -23,7 +23,6 @@ const svgComponent = shallowRef(null) async function setIcon(): Promise { const resolvedComponent = await icons[props.icon] - // @ts-expect-error TODO fix this svgComponent.value = resolvedComponent.default } diff --git a/package.json b/package.json index 76dabc7..29ee305 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,8 @@ "lint": "eslint .", "postinstall": "nuxt prepare", "lint:fix": "eslint . --fix", - "clean": "rm -rf node_modules && rm -rf .output && rm -rf .nuxt" + "clean": "rm -rf node_modules && rm -rf .output && rm -rf .nuxt", + "precommit": "pnpm lint && pnpm typecheck && pnpm build" }, "dependencies": { "@fontsource-variable/inter": "^5.0.18",