diff --git a/jest.config.js b/jest.config.js index 0d04200..9b9fc0a 100644 --- a/jest.config.js +++ b/jest.config.js @@ -13,7 +13,7 @@ module.exports = { shop_ctx: { api_url: 'https://api-storefront.dchomolog.dooca.store/', token: - 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzaG9wX2lkIjoxMDM3NzksInR5cGUiOiJhZG1pbiIsImVtYWlsIjoic2ltYW8ubWV5cmVyQGJhZ3kuY29tLmJyIiwiZmlyc3RfbmFtZSI6IlNpbVx1MDBlM28iLCJhY3RpdmUiOnRydWUsImlhdCI6MTY5NTE1MjU2NX0.56NBX4cX4-fAt0CehPUNqCSMs3OTa617ImXlyZQ8nRA', + 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzaG9wX2lkIjoxMDM3Nzl9.aN9JQNFDsB2bZ56KuTSg9F0G8lmOqK59XEd_VXhaa5M', domain: 'sapato-do-simon.homolog.bagypro.com', mock: {} } diff --git a/src/env.d.ts b/src/env.d.ts index 7dd5fd3..d0f08f4 100644 --- a/src/env.d.ts +++ b/src/env.d.ts @@ -28,6 +28,7 @@ interface shop { shop?: any products?: any user?: any + live_shop?: any } } diff --git a/src/index.ts b/src/index.ts index d018dde..1a9d686 100644 --- a/src/index.ts +++ b/src/index.ts @@ -23,6 +23,7 @@ import { ProductService } from './modules/product/ProductService' import { UserService } from './modules/user/UserService' import { FreightService } from './modules/freight/FreightService' import { BuyTogetherService } from './modules/buy-together/BuyTogetherService' +import { LiveShopService } from './modules/live-shop/LiveShopService' import { SeoServiceFactory } from './services/seo/SeoServiceFactory' import { CookieService } from './services/CookieService' @@ -56,5 +57,6 @@ export { CookieService, Socket, NavigationService, - BuyTogetherService + BuyTogetherService, + LiveShopService } diff --git a/src/mocks/live-shop/live-shop.json b/src/mocks/live-shop/live-shop.json new file mode 100644 index 0000000..e3743b6 --- /dev/null +++ b/src/mocks/live-shop/live-shop.json @@ -0,0 +1,64 @@ +[ + { + "id": 1, + "hashRoom": "abc123", + "name": "Super Live Shop", + "slug": "super-live-shop", + "status": "inLive", + "urlLive": "https://www.youtube.com/watch?v=Tii6ljAdSm0", + "title": "Bem vindo a Super Live Shop!", + "banner": { + "src": "https://picsum.photos/200", + "alt": "Banner Image" + }, + "products": [ + { + "productId": 2915719, + "discount": { + "type": "markup", + "value": 10 + }, + "variations": [ + { + "id": 1001, + "discount": { + "type": "fixed", + "value": 5 + } + } + ] + }, + { + "productId": 2915788, + "discount": { + "type": "markup", + "value": 10 + }, + "variations": [ + { + "id": 1001, + "discount": { + "type": "fixed", + "value": 5 + } + } + ] + } + ], + "messages": [ + { + "title": "Boas vindas!", + "content": "Bem vindo a primeira live shop!" + }, + { + "title": "Os menores precos!", + "content": "Bem vindo que tá bombando!" + } + ], + "alertVisible": true, + "chatVisible": false, + "isActive": true, + "createdAt": "2024-07-03T12:00:00Z", + "updatedAt": "2024-07-03T12:00:00Z" + } +] diff --git a/src/modules/live-shop/LiveShopQueries.ts b/src/modules/live-shop/LiveShopQueries.ts new file mode 100644 index 0000000..fc445ef --- /dev/null +++ b/src/modules/live-shop/LiveShopQueries.ts @@ -0,0 +1,68 @@ +export class LiveShopQueries { + fields: null | string[] + + constructor(fields: string[]) { + this.fields = fields || this.defaultFields() + } + + private getImageFields() { + return '{alt, src}' + } + + private getMessageFields() { + return '{id, title, content, status}' + } + + private getDiscountFields() { + return '{type, value}' + } + + private getVariationFields() { + return ` + { + variationId, + discount ${this.getDiscountFields()} + }` + } + + private getProductFields() { + return ` + { + productId, + discount ${this.getDiscountFields()}, + variations ${this.getVariationFields()}, + status + }` + } + + defaultFields() { + return [ + 'id', + 'name', + 'status', + 'urlLive', + 'title', + `banner ${this.getImageFields()}`, + `messages ${this.getMessageFields()}`, + `products ${this.getProductFields()}`, + 'alertVisible', + 'chatVisible', + 'isActive', + 'createdAt', + 'updatedAt' + ] + } + + getFields() { + return this.fields.join() + } + + getOneFullQuery() { + return ` + query LiveShop($filter: FilterLiveShop){ + liveShop(filter: $filter){ + ${this.getFields()} + } + }` + } +} diff --git a/src/modules/live-shop/LiveShopRepositoryGql.ts b/src/modules/live-shop/LiveShopRepositoryGql.ts new file mode 100644 index 0000000..4d68d69 --- /dev/null +++ b/src/modules/live-shop/LiveShopRepositoryGql.ts @@ -0,0 +1,13 @@ +import { getClient } from '../../services/GraphqlService' +import { LiveShopQueries } from './LiveShopQueries' +import { LiveShop, LiveShopFields, LiveShopFilter, LiveShopResponse } from './LiveShopTypes' + +export class LiveShopRepositoryGql { + static async getOne(filter: { filter: LiveShopFilter }, fields?: LiveShopFields[]): Promise { + const liveShopQuery = new LiveShopQueries(fields) + const fullQuery: string = liveShopQuery.getOneFullQuery() + const { liveShop }: LiveShopResponse = await getClient().query(fullQuery, { ...filter }) + + return liveShop + } +} diff --git a/src/modules/live-shop/LiveShopRepositoryJson.ts b/src/modules/live-shop/LiveShopRepositoryJson.ts new file mode 100644 index 0000000..f7a9472 --- /dev/null +++ b/src/modules/live-shop/LiveShopRepositoryJson.ts @@ -0,0 +1,17 @@ +import { LiveShop, LiveShopFilter } from './LiveShopTypes' + +export class LiveShopRepositoryJson { + static async getOne({ filter }: { filter: LiveShopFilter }, fields?: string[]): Promise { + const liveShop = shop_ctx.mock?.live_shop + const liveShopResult = liveShop.find( + item => + (filter.hashRoom && item.hashRoom === filter.hashRoom) || + (filter.id && item.id === filter.id) || + (filter.slug && item.slug === filter.slug) + ) + if (!liveShopResult) { + throw new Error('Live Shop not found') + } + return liveShopResult + } +} diff --git a/src/modules/live-shop/LiveShopService.ts b/src/modules/live-shop/LiveShopService.ts new file mode 100644 index 0000000..fe24a48 --- /dev/null +++ b/src/modules/live-shop/LiveShopService.ts @@ -0,0 +1,29 @@ +import { BroadcastService } from '../../services/broadcast/broadcast-service' +import { LiveShopRepositoryGql } from './LiveShopRepositoryGql' +import { LiveShopRepositoryJson } from './LiveShopRepositoryJson' +import { LiveShop, LiveShopFields } from './LiveShopTypes' + +const Repository = () => (shop_ctx.mock?.live_shop ? LiveShopRepositoryJson : LiveShopRepositoryGql) + +export class LiveShopService { + static async getByHash(hashRoom: string, fields?: LiveShopFields[]): Promise { + try { + const result: LiveShop = await Repository().getOne({ filter: { hashRoom } }, fields) + BroadcastService.emit('LiveShop', result) + + return result + } catch (error) { + throw new Error(error?.message) + } + } + static async getById(id: number, fields?: LiveShopFields[]): Promise { + try { + const result: LiveShop = await Repository().getOne({ filter: { id } }, fields) + BroadcastService.emit('LiveShop', result) + + return result + } catch (error) { + throw new Error(error?.message) + } + } +} diff --git a/src/modules/live-shop/LiveShopTypes.ts b/src/modules/live-shop/LiveShopTypes.ts new file mode 100644 index 0000000..323b7bd --- /dev/null +++ b/src/modules/live-shop/LiveShopTypes.ts @@ -0,0 +1,71 @@ +export type LiveShopItemStatus = 'displaying' | 'hidden' | 'highlighting' + +export type LiveShopFields = + | 'id' + | 'hashRoom' + | 'name' + | 'status' + | 'urlLive' + | 'title' + | 'banner' + | 'products' + | 'messages' + | 'alertVisible' + | 'chatVisible' + | 'isActive' + | 'createdAt' + | 'updatedAt' + +export interface LiveShopFilter { + id?: number + hashRoom?: string + slug?: string +} +export interface LiveShopImage { + src: string + alt: string +} + +export interface LiveShopDiscount { + type: string + value: number +} + +export interface LiveShopMessage { + title: string + content: string + status: LiveShopItemStatus + id?: string +} + +export interface LiveShopVariation { + id: number + discount: LiveShopDiscount +} +export interface LiveShopProduct { + productId: number + discount: LiveShopDiscount + variations: LiveShopVariation[] + status: LiveShopItemStatus +} + +export interface LiveShop { + id: number + hashRoom: string + slug: string + name: string + status: 'inLive' | 'finished' | 'warmup' | string + urlLive: string + title: string + banner: LiveShopImage + products: LiveShopProduct[] + messages: LiveShopMessage[] + alertVisible: boolean + chatVisible: boolean + isActive: boolean + createdAt: string + updatedAt: string +} +export interface LiveShopResponse { + liveShop: LiveShop +} diff --git a/src/modules/live-shop/__test__/live-shop.test.ts b/src/modules/live-shop/__test__/live-shop.test.ts new file mode 100644 index 0000000..2e8b331 --- /dev/null +++ b/src/modules/live-shop/__test__/live-shop.test.ts @@ -0,0 +1,18 @@ +import 'isomorphic-fetch' +import { LiveShop } from '../LiveShopTypes' +import { LiveShopService } from '../LiveShopService' + +const HASH_FILTER = 'abc123' +const ID_FILTER = 1 + +describe('Live Shop Module', () => { + it('Should get live shop by id with all fields successfully', async () => { + const liveShop: LiveShop = await LiveShopService.getById(ID_FILTER) + expect(liveShop.hashRoom).toEqual(HASH_FILTER) + }) + + it('Should get live shop by hash with all fields successfully', async () => { + const liveShop: LiveShop = await LiveShopService.getByHash(HASH_FILTER) + expect(liveShop.hashRoom).toEqual(HASH_FILTER) + }) +}) diff --git a/src/modules/product/ProductTypes.ts b/src/modules/product/ProductTypes.ts index ada8bfc..a0c0a4b 100644 --- a/src/modules/product/ProductTypes.ts +++ b/src/modules/product/ProductTypes.ts @@ -224,11 +224,11 @@ export interface Aggregator { } export interface OptionsGetProductList { filter: ProductPaginationFilter - fields?: ProductFields[] + fields?: Partial[] agg?: Aggregator } -export interface ProductListFilter extends Omit { +export interface ProductListFilter extends ProductPaginationFilter { items?: number } @@ -288,3 +288,4 @@ export type ProductFields = | 'variations' | 'components' | 'componentGroups' + | string diff --git a/src/services/broadcast/broadcast-service.ts b/src/services/broadcast/broadcast-service.ts index 9ae6542..afb8911 100644 --- a/src/services/broadcast/broadcast-service.ts +++ b/src/services/broadcast/broadcast-service.ts @@ -6,6 +6,7 @@ export type BroadcastEvents = | 'Category' | 'Freight' | 'LandingPages' + | 'LiveShop' | 'Menu' | 'Newsletter' | 'Pages'