From cdfa62958fa0930b227282f9cf3e067d834cfbf7 Mon Sep 17 00:00:00 2001 From: Nevo David Date: Fri, 9 Aug 2024 21:51:33 +0700 Subject: [PATCH 1/4] feat: agencies --- apps/backend/src/api/api.module.ts | 2 + .../src/api/routes/agencies.controller.ts | 15 ++++++ .../prisma/agencies/agencies.repository.ts | 19 +++++++ .../prisma/agencies/agencies.service.ts | 11 ++++ .../src/database/prisma/database.module.ts | 4 ++ .../src/database/prisma/schema.prisma | 54 +++++++++++++++++++ 6 files changed, 105 insertions(+) create mode 100644 apps/backend/src/api/routes/agencies.controller.ts create mode 100644 libraries/nestjs-libraries/src/database/prisma/agencies/agencies.repository.ts create mode 100644 libraries/nestjs-libraries/src/database/prisma/agencies/agencies.service.ts diff --git a/apps/backend/src/api/api.module.ts b/apps/backend/src/api/api.module.ts index 9bd5b14c..be829065 100644 --- a/apps/backend/src/api/api.module.ts +++ b/apps/backend/src/api/api.module.ts @@ -26,6 +26,7 @@ import { OpenaiService } from '@gitroom/nestjs-libraries/openai/openai.service'; import { ExtractContentService } from '@gitroom/nestjs-libraries/openai/extract.content.service'; import { CodesService } from '@gitroom/nestjs-libraries/services/codes.service'; import { CopilotController } from '@gitroom/backend/api/routes/copilot.controller'; +import { AgenciesController } from '@gitroom/backend/api/routes/agencies.controller'; const authenticatedController = [ UsersController, @@ -40,6 +41,7 @@ const authenticatedController = [ MarketplaceController, MessagesController, CopilotController, + AgenciesController, ]; @Module({ imports: [ diff --git a/apps/backend/src/api/routes/agencies.controller.ts b/apps/backend/src/api/routes/agencies.controller.ts new file mode 100644 index 00000000..94ae5013 --- /dev/null +++ b/apps/backend/src/api/routes/agencies.controller.ts @@ -0,0 +1,15 @@ +import { Controller, Get } from '@nestjs/common'; +import { User } from '@prisma/client'; +import { ApiTags } from '@nestjs/swagger'; +import { AgenciesService } from '@gitroom/nestjs-libraries/database/prisma/agencies/agencies.service'; +import { GetUserFromRequest } from '@gitroom/nestjs-libraries/user/user.from.request'; + +@ApiTags('Agencies') +@Controller('/agencies') +export class AgenciesController { + constructor(private _agenciesService: AgenciesService) {} + @Get('/') + async generateImage(@GetUserFromRequest() user: User) { + return this._agenciesService.getAgencyByUser(user); + } +} diff --git a/libraries/nestjs-libraries/src/database/prisma/agencies/agencies.repository.ts b/libraries/nestjs-libraries/src/database/prisma/agencies/agencies.repository.ts new file mode 100644 index 00000000..79a67f02 --- /dev/null +++ b/libraries/nestjs-libraries/src/database/prisma/agencies/agencies.repository.ts @@ -0,0 +1,19 @@ +import { PrismaRepository } from '@gitroom/nestjs-libraries/database/prisma/prisma.service'; +import { Injectable } from '@nestjs/common'; +import { User } from '@prisma/client'; + +@Injectable() +export class AgenciesRepository { + constructor( + private _socialMediaAgencies: PrismaRepository<'socialMediaAgency'> + ) {} + + getAgencyByUser(user: User) { + return this._socialMediaAgencies.model.socialMediaAgency.findFirst({ + where: { + userId: user.id, + deletedAt: null, + }, + }); + } +} diff --git a/libraries/nestjs-libraries/src/database/prisma/agencies/agencies.service.ts b/libraries/nestjs-libraries/src/database/prisma/agencies/agencies.service.ts new file mode 100644 index 00000000..3dd136dc --- /dev/null +++ b/libraries/nestjs-libraries/src/database/prisma/agencies/agencies.service.ts @@ -0,0 +1,11 @@ +import { Injectable } from '@nestjs/common'; +import { AgenciesRepository } from '@gitroom/nestjs-libraries/database/prisma/agencies/agencies.repository'; +import { User } from '@prisma/client'; + +@Injectable() +export class AgenciesService { + constructor(private _agenciesRepository: AgenciesRepository) {} + getAgencyByUser(user: User) { + return this._agenciesRepository.getAgencyByUser(user); + } +} diff --git a/libraries/nestjs-libraries/src/database/prisma/database.module.ts b/libraries/nestjs-libraries/src/database/prisma/database.module.ts index 736c49b1..99b56385 100644 --- a/libraries/nestjs-libraries/src/database/prisma/database.module.ts +++ b/libraries/nestjs-libraries/src/database/prisma/database.module.ts @@ -27,6 +27,8 @@ import { MessagesRepository } from '@gitroom/nestjs-libraries/database/prisma/ma import { StripeService } from '@gitroom/nestjs-libraries/services/stripe.service'; import { ExtractContentService } from '@gitroom/nestjs-libraries/openai/extract.content.service'; import { OpenaiService } from '@gitroom/nestjs-libraries/openai/openai.service'; +import { AgenciesService } from '@gitroom/nestjs-libraries/database/prisma/agencies/agencies.service'; +import { AgenciesRepository } from '@gitroom/nestjs-libraries/database/prisma/agencies/agencies.repository'; @Global() @Module({ @@ -55,6 +57,8 @@ import { OpenaiService } from '@gitroom/nestjs-libraries/openai/openai.service'; MediaRepository, CommentsRepository, ItemUserRepository, + AgenciesService, + AgenciesRepository, ItemUserService, MessagesService, CommentsService, diff --git a/libraries/nestjs-libraries/src/database/prisma/schema.prisma b/libraries/nestjs-libraries/src/database/prisma/schema.prisma index 19321234..349b34d4 100644 --- a/libraries/nestjs-libraries/src/database/prisma/schema.prisma +++ b/libraries/nestjs-libraries/src/database/prisma/schema.prisma @@ -62,6 +62,7 @@ model User { orderSeller Orders[] @relation("orderSeller") payoutProblems PayoutProblems[] lastOnline DateTime @default(now()) + agencies SocialMediaAgency[] @@unique([email, providerName]) @@index([lastReadNotifications]) @@ -165,10 +166,63 @@ model Media { createdAt DateTime @default(now()) updatedAt DateTime @updatedAt userPicture User[] + agencies SocialMediaAgency[] @@index([organizationId]) } +model SocialMediaAgency { + id String @id @default(uuid()) + user User @relation(fields: [userId], references: [id]) + userId String + name String + logoId String? + logo Media? @relation(fields: [logoId], references: [id]) + tagline String? + address String? + phoneNumber String? + emailAddress String? + website String? + + facebook String? + instagram String? + twitter String? + linkedIn String? + youtube String? + otherSocialMedia String? + + primaryServices String + specialties String? + packages String? + caseStudies String? + + yearEstablished Int? + teamSize Int? + languagesSupported String? + clientTypes String? + clientTestimonials String? + + certifications String? + awards String? + + blog String? + faqs String? + events String? + freeConsultation Boolean @default(false) + + businessHours String? + serviceArea String? + termsAndConditions String? + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + deletedAt DateTime? + + @@index([userId]) + @@index([deletedAt]) + @@index([id]) +} + model Credits { id String @id @default(uuid()) organization Organization @relation(fields: [organizationId], references: [id]) From 728a2a7a7883f9d3fb803d9958c047e12de477fa Mon Sep 17 00:00:00 2001 From: Nevo David Date: Fri, 16 Aug 2024 23:35:32 +0700 Subject: [PATCH 2/4] feat: agencies --- .../src/api/routes/agencies.controller.ts | 8 +- apps/frontend/src/app/auth/layout.tsx | 3 + .../src/app/auth/return.url.component.tsx | 27 ++++++ .../src/components/layout/layout.context.tsx | 18 ++++ .../prisma/agencies/agencies.repository.ts | 87 ++++++++++++++++++- .../prisma/agencies/agencies.service.ts | 5 ++ .../src/database/prisma/schema.prisma | 41 +++------ .../src/dtos/agencies/create.agency.dto.ts | 43 +++++++++ 8 files changed, 203 insertions(+), 29 deletions(-) create mode 100644 apps/frontend/src/app/auth/return.url.component.tsx create mode 100644 libraries/nestjs-libraries/src/dtos/agencies/create.agency.dto.ts diff --git a/apps/backend/src/api/routes/agencies.controller.ts b/apps/backend/src/api/routes/agencies.controller.ts index 94ae5013..3b556cd1 100644 --- a/apps/backend/src/api/routes/agencies.controller.ts +++ b/apps/backend/src/api/routes/agencies.controller.ts @@ -1,8 +1,9 @@ -import { Controller, Get } from '@nestjs/common'; +import { Controller, Get, Post } from '@nestjs/common'; import { User } from '@prisma/client'; import { ApiTags } from '@nestjs/swagger'; import { AgenciesService } from '@gitroom/nestjs-libraries/database/prisma/agencies/agencies.service'; import { GetUserFromRequest } from '@gitroom/nestjs-libraries/user/user.from.request'; +import { CreateAgencyDto } from '@gitroom/nestjs-libraries/dtos/agencies/create.agency.dto'; @ApiTags('Agencies') @Controller('/agencies') @@ -12,4 +13,9 @@ export class AgenciesController { async generateImage(@GetUserFromRequest() user: User) { return this._agenciesService.getAgencyByUser(user); } + + @Post('/') + async createAgency(@GetUserFromRequest() user: User, body: CreateAgencyDto) { + return this._agenciesService.createAgency(user, body); + } } diff --git a/apps/frontend/src/app/auth/layout.tsx b/apps/frontend/src/app/auth/layout.tsx index 2fe0c572..affad792 100644 --- a/apps/frontend/src/app/auth/layout.tsx +++ b/apps/frontend/src/app/auth/layout.tsx @@ -5,6 +5,8 @@ export const dynamic = 'force-dynamic'; import { ReactNode } from 'react'; import Image from 'next/image'; import clsx from 'clsx'; +import loadDynamic from 'next/dynamic'; +const ReturnUrlComponent = loadDynamic(() => import('./return.url.component')); export default async function AuthLayout({ children, @@ -13,6 +15,7 @@ export default async function AuthLayout({ }) { return ( <> +
diff --git a/apps/frontend/src/app/auth/return.url.component.tsx b/apps/frontend/src/app/auth/return.url.component.tsx new file mode 100644 index 00000000..9e0303a8 --- /dev/null +++ b/apps/frontend/src/app/auth/return.url.component.tsx @@ -0,0 +1,27 @@ +'use client'; +import { useSearchParams } from 'next/navigation'; +import { useCallback, useEffect } from 'react'; + +const ReturnUrlComponent = () => { + const params = useSearchParams(); + const url = params.get('returnUrl'); + useEffect(() => { + if (url?.indexOf?.('http')! > -1) { + localStorage.setItem('returnUrl', url!); + } + }, [url]); + + return null; +} + +export const useReturnUrl = () => { + return { + getAndClear: useCallback(() => { + const data = localStorage.getItem('returnUrl'); + localStorage.removeItem('returnUrl'); + return data; + }, []) + } +} + +export default ReturnUrlComponent; \ No newline at end of file diff --git a/apps/frontend/src/components/layout/layout.context.tsx b/apps/frontend/src/components/layout/layout.context.tsx index a44f94db..451bd408 100644 --- a/apps/frontend/src/components/layout/layout.context.tsx +++ b/apps/frontend/src/components/layout/layout.context.tsx @@ -4,6 +4,7 @@ import { ReactNode, useCallback } from 'react'; import { FetchWrapperComponent } from '@gitroom/helpers/utils/custom.fetch'; import { deleteDialog } from '@gitroom/react/helpers/delete.dialog'; import { isGeneral } from '@gitroom/react/helpers/is.general'; +import { useReturnUrl } from '@gitroom/frontend/app/auth/return.url.component'; export default function LayoutContext(params: { children: ReactNode }) { if (params?.children) { @@ -14,16 +15,33 @@ export default function LayoutContext(params: { children: ReactNode }) { return <>; } function LayoutContextInner(params: { children: ReactNode }) { + const returnUrl = useReturnUrl(); + const afterRequest = useCallback( async (url: string, options: RequestInit, response: Response) => { + const reloadOrOnboarding = + response?.headers?.get('reload') || + response?.headers?.get('onboarding'); + + if (reloadOrOnboarding) { + const getAndClear = returnUrl.getAndClear(); + if (getAndClear) { + window.location.href = getAndClear; + return true; + } + } + if (response?.headers?.get('onboarding')) { window.location.href = isGeneral() ? '/launches?onboarding=true' : '/analytics?onboarding=true'; + + return true; } if (response?.headers?.get('reload')) { window.location.reload(); + return true; } if (response.status === 401) { diff --git a/libraries/nestjs-libraries/src/database/prisma/agencies/agencies.repository.ts b/libraries/nestjs-libraries/src/database/prisma/agencies/agencies.repository.ts index 79a67f02..44860c3d 100644 --- a/libraries/nestjs-libraries/src/database/prisma/agencies/agencies.repository.ts +++ b/libraries/nestjs-libraries/src/database/prisma/agencies/agencies.repository.ts @@ -1,11 +1,13 @@ import { PrismaRepository } from '@gitroom/nestjs-libraries/database/prisma/prisma.service'; import { Injectable } from '@nestjs/common'; import { User } from '@prisma/client'; +import { CreateAgencyDto } from '@gitroom/nestjs-libraries/dtos/agencies/create.agency.dto'; @Injectable() export class AgenciesRepository { constructor( - private _socialMediaAgencies: PrismaRepository<'socialMediaAgency'> + private _socialMediaAgencies: PrismaRepository<'socialMediaAgency'>, + private _socialMediaAgenciesNiche: PrismaRepository<'socialMediaAgencyNiche'> ) {} getAgencyByUser(user: User) { @@ -16,4 +18,87 @@ export class AgenciesRepository { }, }); } + + async createAgency(user: User, body: CreateAgencyDto) { + const insertAgency = + await this._socialMediaAgencies.model.socialMediaAgency.upsert({ + where: { + userId: user.id, + }, + update: { + userId: user.id, + name: body.name, + website: body.website, + facebook: body.facebook, + instagram: body.instagram, + twitter: body.twitter, + linkedIn: body.linkedin, + youtube: body.youtube, + tiktok: body.tiktok, + logoId: body.logo, + shortDescription: body.shortDescription, + description: body.description, + niches: { + create: body.niche.map((n) => ({ + niche: n, + })), + }, + }, + create: { + userId: user.id, + name: body.name, + website: body.website, + facebook: body.facebook, + instagram: body.instagram, + twitter: body.twitter, + linkedIn: body.linkedin, + youtube: body.youtube, + tiktok: body.tiktok, + logoId: body.logo, + shortDescription: body.shortDescription, + description: body.description, + }, + select: { + id: true, + }, + }); + + await this._socialMediaAgenciesNiche.model.socialMediaAgencyNiche.deleteMany( + { + where: { + agencyId: insertAgency.id, + niche: { + notIn: body.niche, + }, + }, + } + ); + + const currentNiche = + await this._socialMediaAgenciesNiche.model.socialMediaAgencyNiche.findMany( + { + where: { + agencyId: insertAgency.id, + }, + select: { + niche: true, + }, + } + ); + + const addNewNiche = body.niche.filter( + (n) => !currentNiche.some((c) => c.niche === n) + ); + + await this._socialMediaAgenciesNiche.model.socialMediaAgencyNiche.createMany( + { + data: addNewNiche.map((n) => ({ + agencyId: insertAgency.id, + niche: n, + })), + } + ); + + return insertAgency; + } } diff --git a/libraries/nestjs-libraries/src/database/prisma/agencies/agencies.service.ts b/libraries/nestjs-libraries/src/database/prisma/agencies/agencies.service.ts index 3dd136dc..29d580ac 100644 --- a/libraries/nestjs-libraries/src/database/prisma/agencies/agencies.service.ts +++ b/libraries/nestjs-libraries/src/database/prisma/agencies/agencies.service.ts @@ -1,6 +1,7 @@ import { Injectable } from '@nestjs/common'; import { AgenciesRepository } from '@gitroom/nestjs-libraries/database/prisma/agencies/agencies.repository'; import { User } from '@prisma/client'; +import { CreateAgencyDto } from '@gitroom/nestjs-libraries/dtos/agencies/create.agency.dto'; @Injectable() export class AgenciesService { @@ -8,4 +9,8 @@ export class AgenciesService { getAgencyByUser(user: User) { return this._agenciesRepository.getAgencyByUser(user); } + + createAgency(user: User, body: CreateAgencyDto) { + return this._agenciesRepository.createAgency(user, body); + } } diff --git a/libraries/nestjs-libraries/src/database/prisma/schema.prisma b/libraries/nestjs-libraries/src/database/prisma/schema.prisma index 41a59d39..35f8832d 100644 --- a/libraries/nestjs-libraries/src/database/prisma/schema.prisma +++ b/libraries/nestjs-libraries/src/database/prisma/schema.prisma @@ -174,14 +174,10 @@ model Media { model SocialMediaAgency { id String @id @default(uuid()) user User @relation(fields: [userId], references: [id]) - userId String + userId String @unique() name String logoId String? logo Media? @relation(fields: [logoId], references: [id]) - tagline String? - address String? - phoneNumber String? - emailAddress String? website String? facebook String? @@ -189,30 +185,13 @@ model SocialMediaAgency { twitter String? linkedIn String? youtube String? + tiktok String? otherSocialMedia String? - primaryServices String - specialties String? - packages String? - caseStudies String? - - yearEstablished Int? - teamSize Int? - languagesSupported String? - clientTypes String? - clientTestimonials String? - - certifications String? - awards String? - - blog String? - faqs String? - events String? - freeConsultation Boolean @default(false) - - businessHours String? - serviceArea String? - termsAndConditions String? + shortDescription String + description String + niches SocialMediaAgencyNiche[] + approved Boolean @default(false) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@ -223,6 +202,14 @@ model SocialMediaAgency { @@index([id]) } +model SocialMediaAgencyNiche { + agencyId String + agency SocialMediaAgency @relation(fields: [agencyId], references: [id]) + niche String + + @@id([agencyId, niche]) +} + model Credits { id String @id @default(uuid()) organization Organization @relation(fields: [organizationId], references: [id]) diff --git a/libraries/nestjs-libraries/src/dtos/agencies/create.agency.dto.ts b/libraries/nestjs-libraries/src/dtos/agencies/create.agency.dto.ts new file mode 100644 index 00000000..3f6d62fd --- /dev/null +++ b/libraries/nestjs-libraries/src/dtos/agencies/create.agency.dto.ts @@ -0,0 +1,43 @@ +import { IsDefined, IsString, IsUrl, MinLength } from 'class-validator'; + +export class CreateAgencyDto { + @IsString() + @MinLength(3) + name: string; + + @IsUrl() + @IsDefined() + website: string; + + @IsUrl() + facebook: string; + + @IsString() + instagram: string; + + @IsString() + twitter: string; + + @IsUrl() + linkedin: string; + + @IsUrl() + youtube: string; + + @IsUrl() + tiktok: string; + + @IsString() + logo: string; + + @IsString() + shortDescription: string; + + @IsString() + description: string; + + @IsString({ + each: true + }) + niche: string[]; +} \ No newline at end of file From da524bdc3eee14073b9705eecf9baa75788fc5b7 Mon Sep 17 00:00:00 2001 From: Nevo David Date: Sat, 17 Aug 2024 11:26:34 +0700 Subject: [PATCH 3/4] feat: agency --- .../nestjs-libraries/src/dtos/agencies/create.agency.dto.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/nestjs-libraries/src/dtos/agencies/create.agency.dto.ts b/libraries/nestjs-libraries/src/dtos/agencies/create.agency.dto.ts index 3f6d62fd..54978e46 100644 --- a/libraries/nestjs-libraries/src/dtos/agencies/create.agency.dto.ts +++ b/libraries/nestjs-libraries/src/dtos/agencies/create.agency.dto.ts @@ -1,4 +1,4 @@ -import { IsDefined, IsString, IsUrl, MinLength } from 'class-validator'; +import { ArrayMaxSize, ArrayMinSize, IsDefined, IsString, IsUrl, MinLength } from 'class-validator'; export class CreateAgencyDto { @IsString() @@ -39,5 +39,7 @@ export class CreateAgencyDto { @IsString({ each: true }) + @ArrayMinSize(1) + @ArrayMaxSize(3) niche: string[]; } \ No newline at end of file From c3f656f54e50155d9e4035909200738e4faadee2 Mon Sep 17 00:00:00 2001 From: Nevo David Date: Tue, 20 Aug 2024 16:21:21 +0700 Subject: [PATCH 4/4] feat: agencies --- apps/backend/src/api/api.module.ts | 3 +- .../src/api/routes/agencies.controller.ts | 9 +- .../src/api/routes/public.controller.ts | 30 ++++ .../prisma/agencies/agencies.repository.ts | 72 ++++++-- .../prisma/agencies/agencies.service.ts | 155 +++++++++++++++++- .../src/database/prisma/schema.prisma | 1 + .../src/dtos/agencies/create.agency.dto.ts | 26 ++- .../src/services/email.service.ts | 2 +- 8 files changed, 273 insertions(+), 25 deletions(-) create mode 100644 apps/backend/src/api/routes/public.controller.ts diff --git a/apps/backend/src/api/api.module.ts b/apps/backend/src/api/api.module.ts index be829065..803db821 100644 --- a/apps/backend/src/api/api.module.ts +++ b/apps/backend/src/api/api.module.ts @@ -27,6 +27,7 @@ import { ExtractContentService } from '@gitroom/nestjs-libraries/openai/extract. import { CodesService } from '@gitroom/nestjs-libraries/services/codes.service'; import { CopilotController } from '@gitroom/backend/api/routes/copilot.controller'; import { AgenciesController } from '@gitroom/backend/api/routes/agencies.controller'; +import { PublicController } from '@gitroom/backend/api/routes/public.controller'; const authenticatedController = [ UsersController, @@ -62,7 +63,7 @@ const authenticatedController = [ ] : []), ], - controllers: [StripeController, AuthController, ...authenticatedController], + controllers: [StripeController, AuthController, PublicController, ...authenticatedController], providers: [ AuthService, StripeService, diff --git a/apps/backend/src/api/routes/agencies.controller.ts b/apps/backend/src/api/routes/agencies.controller.ts index 3b556cd1..882841c5 100644 --- a/apps/backend/src/api/routes/agencies.controller.ts +++ b/apps/backend/src/api/routes/agencies.controller.ts @@ -1,4 +1,4 @@ -import { Controller, Get, Post } from '@nestjs/common'; +import { Body, Controller, Get, Post } from '@nestjs/common'; import { User } from '@prisma/client'; import { ApiTags } from '@nestjs/swagger'; import { AgenciesService } from '@gitroom/nestjs-libraries/database/prisma/agencies/agencies.service'; @@ -10,12 +10,15 @@ import { CreateAgencyDto } from '@gitroom/nestjs-libraries/dtos/agencies/create. export class AgenciesController { constructor(private _agenciesService: AgenciesService) {} @Get('/') - async generateImage(@GetUserFromRequest() user: User) { + async getAgencyByUser(@GetUserFromRequest() user: User) { return this._agenciesService.getAgencyByUser(user); } @Post('/') - async createAgency(@GetUserFromRequest() user: User, body: CreateAgencyDto) { + async createAgency( + @GetUserFromRequest() user: User, + @Body() body: CreateAgencyDto + ) { return this._agenciesService.createAgency(user, body); } } diff --git a/apps/backend/src/api/routes/public.controller.ts b/apps/backend/src/api/routes/public.controller.ts new file mode 100644 index 00000000..e2098b7f --- /dev/null +++ b/apps/backend/src/api/routes/public.controller.ts @@ -0,0 +1,30 @@ +import { Controller, Get, Param } from '@nestjs/common'; +import { ApiTags } from '@nestjs/swagger'; +import { AgenciesService } from '@gitroom/nestjs-libraries/database/prisma/agencies/agencies.service'; + +@ApiTags('Public') +@Controller('/public') +export class PublicController { + constructor(private _agenciesService: AgenciesService) {} + @Get('/agencies-list') + async getAgencyByUser() { + return this._agenciesService.getAllAgencies(); + } + + @Get('/agencies-list-slug') + async getAgencySlug() { + return this._agenciesService.getAllAgenciesSlug(); + } + + @Get('/agencies-information/:agency') + async getAgencyInformation( + @Param('agency') agency: string, + ) { + return this._agenciesService.getAgencyInformation(agency); + } + + @Get('/agencies-list-count') + async getAgenciesCount() { + return this._agenciesService.getCount(); + } +} diff --git a/libraries/nestjs-libraries/src/database/prisma/agencies/agencies.repository.ts b/libraries/nestjs-libraries/src/database/prisma/agencies/agencies.repository.ts index 44860c3d..27eab628 100644 --- a/libraries/nestjs-libraries/src/database/prisma/agencies/agencies.repository.ts +++ b/libraries/nestjs-libraries/src/database/prisma/agencies/agencies.repository.ts @@ -10,12 +10,64 @@ export class AgenciesRepository { private _socialMediaAgenciesNiche: PrismaRepository<'socialMediaAgencyNiche'> ) {} + getAllAgencies() { + return this._socialMediaAgencies.model.socialMediaAgency.findMany({ + where: { + deletedAt: null, + approved: true, + }, + include: { + logo: true, + niches: true, + }, + }); + } + + getCount() { + return this._socialMediaAgencies.model.socialMediaAgency.count({ + where: { + deletedAt: null, + approved: true, + }, + }); + } + + getAllAgenciesSlug() { + return this._socialMediaAgencies.model.socialMediaAgency.findMany({ + where: { + deletedAt: null, + approved: true, + }, + select: { + slug: true, + }, + }); + } + + getAgencyInformation(agency: string) { + return this._socialMediaAgencies.model.socialMediaAgency.findFirst({ + where: { + slug: agency, + deletedAt: null, + approved: true, + }, + include: { + logo: true, + niches: true, + }, + }); + } + getAgencyByUser(user: User) { return this._socialMediaAgencies.model.socialMediaAgency.findFirst({ where: { userId: user.id, deletedAt: null, }, + include: { + logo: true, + niches: true, + }, }); } @@ -32,17 +84,13 @@ export class AgenciesRepository { facebook: body.facebook, instagram: body.instagram, twitter: body.twitter, - linkedIn: body.linkedin, + linkedIn: body.linkedIn, youtube: body.youtube, tiktok: body.tiktok, - logoId: body.logo, + logoId: body.logo.id, shortDescription: body.shortDescription, description: body.description, - niches: { - create: body.niche.map((n) => ({ - niche: n, - })), - }, + approved: false, }, create: { userId: user.id, @@ -51,12 +99,14 @@ export class AgenciesRepository { facebook: body.facebook, instagram: body.instagram, twitter: body.twitter, - linkedIn: body.linkedin, + linkedIn: body.linkedIn, youtube: body.youtube, tiktok: body.tiktok, - logoId: body.logo, + logoId: body.logo.id, shortDescription: body.shortDescription, description: body.description, + slug: body.name.toLowerCase().replace(/ /g, '-'), + approved: false, }, select: { id: true, @@ -68,7 +118,7 @@ export class AgenciesRepository { where: { agencyId: insertAgency.id, niche: { - notIn: body.niche, + notIn: body.niches, }, }, } @@ -86,7 +136,7 @@ export class AgenciesRepository { } ); - const addNewNiche = body.niche.filter( + const addNewNiche = body.niches.filter( (n) => !currentNiche.some((c) => c.niche === n) ); diff --git a/libraries/nestjs-libraries/src/database/prisma/agencies/agencies.service.ts b/libraries/nestjs-libraries/src/database/prisma/agencies/agencies.service.ts index 29d580ac..0c0cd70c 100644 --- a/libraries/nestjs-libraries/src/database/prisma/agencies/agencies.service.ts +++ b/libraries/nestjs-libraries/src/database/prisma/agencies/agencies.service.ts @@ -2,15 +2,164 @@ import { Injectable } from '@nestjs/common'; import { AgenciesRepository } from '@gitroom/nestjs-libraries/database/prisma/agencies/agencies.repository'; import { User } from '@prisma/client'; import { CreateAgencyDto } from '@gitroom/nestjs-libraries/dtos/agencies/create.agency.dto'; +import { EmailService } from '@gitroom/nestjs-libraries/services/email.service'; @Injectable() export class AgenciesService { - constructor(private _agenciesRepository: AgenciesRepository) {} + constructor( + private _agenciesRepository: AgenciesRepository, + private _emailService: EmailService + ) {} getAgencyByUser(user: User) { return this._agenciesRepository.getAgencyByUser(user); } - createAgency(user: User, body: CreateAgencyDto) { - return this._agenciesRepository.createAgency(user, body); + getCount() { + return this._agenciesRepository.getCount(); + } + + getAllAgencies() { + return this._agenciesRepository.getAllAgencies(); + } + + getAllAgenciesSlug() { + return this._agenciesRepository.getAllAgenciesSlug(); + } + + getAgencyInformation(agency: string) { + return this._agenciesRepository.getAgencyInformation(agency); + } + + async createAgency(user: User, body: CreateAgencyDto) { + const agency = await this._agenciesRepository.createAgency(user, body); + await this._emailService.sendEmail( + 'nevo@postiz.com', + 'New agency created', + ` + + + + + + Email Template + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + ${ + body.website + } +
+ +

+ Social Medias: + ${ + body.facebook + }
+ ${ + body.instagram + }
+ ${ + body.twitter + }
+ ${ + body.linkedIn + }
+ ${ + body.youtube + }
+ ${ + body.tiktok + } +

+
+ +

Logo

+

+ +

+
+ +

Name

+

${ + body.name + }

+
+ +

Short Description

+

${ + body.shortDescription + }

+
+ +

Description

+

${ + body.description + }

+
+ +

Niches

+

${body.niches.join( + ',' + )}

+
+ To approve click here


+ To decline click here


+
+

© 2024 Your Gitroom Limited All rights reserved.

+
+ + + + ` + ); + return agency; } } diff --git a/libraries/nestjs-libraries/src/database/prisma/schema.prisma b/libraries/nestjs-libraries/src/database/prisma/schema.prisma index 35f8832d..079e0e74 100644 --- a/libraries/nestjs-libraries/src/database/prisma/schema.prisma +++ b/libraries/nestjs-libraries/src/database/prisma/schema.prisma @@ -179,6 +179,7 @@ model SocialMediaAgency { logoId String? logo Media? @relation(fields: [logoId], references: [id]) website String? + slug String? facebook String? instagram String? diff --git a/libraries/nestjs-libraries/src/dtos/agencies/create.agency.dto.ts b/libraries/nestjs-libraries/src/dtos/agencies/create.agency.dto.ts index 54978e46..045f75df 100644 --- a/libraries/nestjs-libraries/src/dtos/agencies/create.agency.dto.ts +++ b/libraries/nestjs-libraries/src/dtos/agencies/create.agency.dto.ts @@ -1,5 +1,13 @@ -import { ArrayMaxSize, ArrayMinSize, IsDefined, IsString, IsUrl, MinLength } from 'class-validator'; +import { ArrayMaxSize, ArrayMinSize, IsDefined, IsOptional, IsString, IsUrl, MinLength, ValidateIf } from 'class-validator'; +import { Type } from 'class-transformer'; +export class CreateAgencyLogoDto { + @IsString() + @IsDefined() + id: string; + + path: string; +} export class CreateAgencyDto { @IsString() @MinLength(3) @@ -10,25 +18,31 @@ export class CreateAgencyDto { website: string; @IsUrl() + @ValidateIf((o) => o.facebook) facebook: string; @IsString() + @IsOptional() instagram: string; @IsString() + @IsOptional() twitter: string; @IsUrl() - linkedin: string; + @ValidateIf((o) => o.linkedIn) + linkedIn: string; @IsUrl() + @ValidateIf((o) => o.youtube) youtube: string; - @IsUrl() + @IsString() + @IsOptional() tiktok: string; - @IsString() - logo: string; + @Type(() => CreateAgencyLogoDto) + logo: CreateAgencyLogoDto; @IsString() shortDescription: string; @@ -41,5 +55,5 @@ export class CreateAgencyDto { }) @ArrayMinSize(1) @ArrayMaxSize(3) - niche: string[]; + niches: string[]; } \ No newline at end of file diff --git a/libraries/nestjs-libraries/src/services/email.service.ts b/libraries/nestjs-libraries/src/services/email.service.ts index b128d101..a847ed93 100644 --- a/libraries/nestjs-libraries/src/services/email.service.ts +++ b/libraries/nestjs-libraries/src/services/email.service.ts @@ -13,7 +13,7 @@ export class EmailService { console.log('Sending email to', to); const sends = await resend.emails.send({ - from: process.env.IS_GENERAL === 'true' ? 'Nevo ' : 'Nevo ', + from: process.env.IS_GENERAL === 'true' ? 'Nevo ' : 'Nevo ', to, subject, html,