Something went wrong. Try again.
because I got bored of customising my CV for every job
Something went wrong. Try again.
6.4 kB · 206 lines
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207import type { User as DomainUser } from "@cv/core";import { AuthorizationService } from "@cv/core";import { JwtAuthGuard, VerifiedScopeGuard } from "@cv/auth";import { PrismaService } from "@cv/core";import { UseGuards } from "@nestjs/common";import { Args, Mutation, Parent, Query, ResolveField, Resolver,} from "@nestjs/graphql";import { CurrentUser } from "@/modules/current-user/current-user.decorator";import { CVDataLoaderService } from "@/modules/cv-template/cv.dataloader";import { CV } from "@/modules/cv-template/graphql/cv.type";import { Vacancy } from "@/modules/vacancies/graphql/vacancy.type";import { VacancyDataLoaderService } from "@/modules/vacancies/vacancy.dataloader";import { Application as ApplicationEntity } from "../application.entity";import { ApplicationMapper } from "../application.mapper";import { ApplicationService } from "../application.service";import { ApplicationStatusDataLoaderService } from "../application-status.dataloader";import { CreateApplicationInput, UpdateApplicationStatusInput,} from "./application.input";import { Application, ApplicationStatus } from "./application.type";
@Resolver(() => Application)@UseGuards(JwtAuthGuard, VerifiedScopeGuard)export class ApplicationResolver { constructor( private readonly applicationService: ApplicationService, private readonly applicationMapper: ApplicationMapper, private readonly statusDataLoader: ApplicationStatusDataLoaderService, private readonly vacancyDataLoader: VacancyDataLoaderService, private readonly cvDataLoader: CVDataLoaderService, private readonly prisma: PrismaService, private readonly authorizationService: AuthorizationService, ) {}
@Query(() => Application, { nullable: true }) async application( @Args("id", { type: () => String }) id: string, @CurrentUser() user: DomainUser, ): Promise<Application | null> { const application = await this.applicationService.findById(id);
if (!application) { return null; }
await this.authorizationService.canView( user, application, ApplicationEntity, );
return Application.fromDomain(application); }
@Mutation(() => Application) async createApplication( @Args("input") input: CreateApplicationInput, @CurrentUser() user: DomainUser, ): Promise<Application> { await this.authorizationService.canCreate(user, ApplicationEntity, { userId: user.id, });
const appliedStatus = await this.prisma.applicationStatus.findFirst({ where: { name: "Applied" }, });
if (!appliedStatus) { throw new Error("Application status 'Applied' not found"); }
const existingApplication = await this.prisma.application.findFirst({ where: { userId: user.id, vacancyId: input.vacancyId, }, });
if (existingApplication) { throw new Error("User has already applied to this vacancy"); }
const application = await this.prisma.application.create({ data: { userId: user.id, profileId: input.profileId, vacancyId: input.vacancyId, statusId: appliedStatus.id, cvId: input.cvId ?? null, coverLetter: input.coverLetter ?? null, }, include: this.applicationService.applicationInclude, });
const domainApplication = this.applicationMapper.toDomain(application); if (!domainApplication) { throw new Error("Failed to map application to domain"); } return Application.fromDomain(domainApplication); }
@Mutation(() => Application) async updateApplicationStatus( @Args("input") input: UpdateApplicationStatusInput, @CurrentUser() user: DomainUser, ): Promise<Application> { const existingApplication = await this.applicationService.findByIdOrFail( input.applicationId, ); await this.authorizationService.canUpdate( user, existingApplication, ApplicationEntity, );
const status = await this.prisma.applicationStatus.findUnique({ where: { id: input.statusId }, });
if (!status) { throw new Error("Application status not found"); }
const updatedApplication = new ApplicationEntity( existingApplication.id, existingApplication.userId, existingApplication.profileId, existingApplication.vacancy, input.statusId, { id: status.id, name: status.name, description: status.description, createdAt: status.createdAt, updatedAt: status.updatedAt, }, existingApplication.appliedAt, existingApplication.createdAt, new Date(), existingApplication.cv, existingApplication.coverLetter, );
const application = await this.applicationService.save(updatedApplication); return Application.fromDomain(application); }
@Mutation(() => Boolean) async deleteApplication( @Args("id", { type: () => String }) id: string, @CurrentUser() user: DomainUser, ): Promise<boolean> { const existingApplication = await this.applicationService.findByIdOrFail(id); await this.authorizationService.canDelete( user, existingApplication, ApplicationEntity, );
await this.applicationService.destroy(existingApplication); return true; }
@ResolveField(() => ApplicationStatus) async status(@Parent() application: Application): Promise<ApplicationStatus> { const status = await this.statusDataLoader.load(application.statusId); if (!status) { throw new Error( `Application status with id ${application.statusId} not found`, ); } return new ApplicationStatus({ id: status.id, name: status.name, description: status.description, createdAt: status.createdAt, updatedAt: status.updatedAt, }); }
@ResolveField(() => Vacancy) async vacancy(@Parent() application: Application): Promise<Vacancy> { const vacancy = await this.vacancyDataLoader.load(application.vacancyId); if (!vacancy) { throw new Error(`Vacancy with id ${application.vacancyId} not found`); } return Vacancy.fromDomain(vacancy); }
@ResolveField(() => CV, { nullable: true }) async cv(@Parent() application: Application): Promise<CV | null> { if (!application.cvId) { return null; } const cv = await this.cvDataLoader.load(application.cvId); return cv; }}