import { AuthenticationError } from 'apollo-server-express'; import { Arg, Authorized, Ctx, Mutation, Query, Resolver } from 'type-graphql'; import { getCustomRepository, getRepository, In } from 'typeorm'; import { ContextType, UserStatus } from '@/types'; import { AggregateProductVariantSavesListRepository } from '@/repositories'; import { AggregateProductVariant, AggregateProductVariantSavesList, } from '@/entities'; import { AggregateProductVariantConnection } from '../AggregateProductVariant/types'; import { connectionFromQuery } from '../shared/pagination/utils'; import { AggregateProductVariantSavesListConnection, CreateSavesListInput, CreateSavesListPayload, SavedProductsInput, UpdateSavesListInput, UpdateSavesListPayload, UpdateVariantsInListInput, UpdateVariantsInListPayload, } from './types'; @Resolver(AggregateProductVariantSavesList) export class AggregateProductVariantSavesListResolver { @Authorized([UserStatus.ANONYMOUS]) @Mutation(() => UpdateVariantsInListPayload, { nullable: false, description: `Update variants in list.`, }) async updateVariantsInList( @Ctx() { user }: ContextType, @Arg('input') input: UpdateVariantsInListInput ): Promise { if (!user) { throw new AuthenticationError( 'You cannot Update variants in list without being signed in.' ); } const savesList = input.listId ? await AggregateProductVariantSavesList.findOneOrFail(input.listId, { relations: ['variants'], }) : (await AggregateProductVariantSavesList.findOne({ where: { createdBy: user }, order: { createdAt: 'DESC' }, relations: ['variants'], })) || AggregateProductVariantSavesList.create({ createdBy: user, variants: [], }); const variantIds = savesList.variants .map(({ id }) => id) .filter((id) => input.variantIdsToRemove ? !input.variantIdsToRemove.includes(id) : true ) .concat(input.variantIdsToAdd ? input.variantIdsToAdd : []); const updatedSavesList = await getCustomRepository( AggregateProductVariantSavesListRepository ).updateListFieldsAndSave( savesList, { variantIds, }, user ); return { savesList: updatedSavesList }; } @Authorized([UserStatus.ANONYMOUS]) @Query(() => AggregateProductVariantSavesListConnection, { nullable: false, }) async savesLists( @Ctx() { user }: ContextType, @Arg('first', { nullable: true }) first?: number, @Arg('last', { nullable: true }) last?: number, @Arg('before', { nullable: true }) before?: string, @Arg('after', { nullable: true }) after?: string ): Promise { if (!user) { throw new AuthenticationError( 'You cannot view Saves lists without being signed in.' ); } const query = getRepository(AggregateProductVariantSavesList) .createQueryBuilder('AggregateProductVariantSavesList') .leftJoin( 'AggregateProductVariantSavesList.collaborators', 'collaborators' ) .where('"createdById" = :userId', { userId: user.id }) .orWhere('collaborators.id = :userId', { userId: user.id }); return connectionFromQuery({ first, last, before, after }, query); } @Authorized([UserStatus.ANONYMOUS]) @Mutation(() => CreateSavesListPayload, { nullable: false, description: `Create saves list.`, }) async createSavesList( @Ctx() { user }: ContextType, @Arg('input') input: CreateSavesListInput ): Promise { if (!user) { throw new AuthenticationError( 'You cannot Create saves list without being signed in.' ); } const savesList = await getCustomRepository( AggregateProductVariantSavesListRepository ).create( { collaboratorIds: input.collaboratorIds, variantIds: input.variantIds }, user ); return { savesList }; } @Authorized([UserStatus.ANONYMOUS]) @Mutation(() => UpdateSavesListPayload, { nullable: false, description: `Update saves list.`, }) async updateSavesList( @Ctx() { user }: ContextType, @Arg('input') input: UpdateSavesListInput ): Promise { if (!user) { throw new AuthenticationError( 'You cannot Update saves list without being signed in.' ); } const savesList = await getCustomRepository( AggregateProductVariantSavesListRepository ).update( { collaboratorIds: input.collaboratorIds, variantIds: input.variantIds, id: input.listId, }, user ); return { savesList }; } @Authorized([UserStatus.ANONYMOUS]) @Query(() => AggregateProductVariantConnection, { nullable: true }) async savedProducts( @Ctx() { user }: ContextType, @Arg('input', { nullable: true }) { listId }: SavedProductsInput, @Arg('first', { nullable: true }) first?: number, @Arg('last', { nullable: true }) last?: number, @Arg('before', { nullable: true }) before?: string, @Arg('after', { nullable: true }) after?: string ): Promise { if (!user) { throw new AuthenticationError( 'You must be signed in to get product lists.' ); } const list = listId ? await AggregateProductVariantSavesList.findOneOrFail(listId, { relations: ['variants'], }) : await AggregateProductVariantSavesList.findOneOrFail({ where: { createdBy: user }, order: { createdAt: 'DESC' }, relations: ['variants'], }); const aggregateProductVariantIds = list.variants.map( (variant) => variant.id ); const query = getRepository(AggregateProductVariant) .createQueryBuilder('AggregateProductVariant') .where({ id: In(aggregateProductVariantIds), }); return connectionFromQuery({ first, last, before, after }, query); } }