diff --git a/apps/valor-software-site/src/app/app.module.ts b/apps/valor-software-site/src/app/app.module.ts
index e42bbaff3..d0f9b64aa 100644
--- a/apps/valor-software-site/src/app/app.module.ts
+++ b/apps/valor-software-site/src/app/app.module.ts
@@ -17,6 +17,7 @@ import { articlesList, articlesRefactoringTitlesList } from '../../../../assets/
import { projectsList } from '../assets/portfolio/portfolio.list';
import { linksFromOldSite } from '../../../../assets/articles/brokenRoutes';
import { NotFoundComponent } from './404.component';
+import { RECAPTCHA_V3_SITE_KEY, RecaptchaV3Module } from 'ng-recaptcha';
@NgModule({
declarations: [
@@ -29,6 +30,7 @@ import { NotFoundComponent } from './404.component';
CommonDocsModule,
BrowserAnimationsModule,
ScullyLibModule,
+ RecaptchaV3Module,
],
providers: [
SeoService,
@@ -36,6 +38,7 @@ import { NotFoundComponent } from './404.component';
{ provide: ARTICLES_REFACTORED_TITLE_LIST, useValue: articlesRefactoringTitlesList },
{ provide: PORTFOLIO_LIST, useValue: projectsList },
{ provide: OLD_ROUTES_FROM_OLD_SITE, useValue: linksFromOldSite },
+ { provide: RECAPTCHA_V3_SITE_KEY, useValue: '6LeXDiUoAAAAABZ2FU4l2GZTJ0v5otDAQkC3UZxs' }
],
bootstrap: [AppComponent],
})
diff --git a/apps/valor-software-site/src/assets/img/bg-img/get_in_touch.svg b/apps/valor-software-site/src/assets/img/bg-img/get_in_touch.svg
deleted file mode 100644
index aa59ca3b8..000000000
--- a/apps/valor-software-site/src/assets/img/bg-img/get_in_touch.svg
+++ /dev/null
@@ -1,52 +0,0 @@
-
diff --git a/apps/valor-software-site/src/assets/styles/variables.scss b/apps/valor-software-site/src/assets/styles/variables.scss
index 78f30705b..d171207c4 100644
--- a/apps/valor-software-site/src/assets/styles/variables.scss
+++ b/apps/valor-software-site/src/assets/styles/variables.scss
@@ -1,6 +1,13 @@
$light_font_col: #E1E1E1;
$light_title_col: #E3E3E3;
+/* Breakpoints */
+$bp-small: 640px;
+$bp-medium: 768px;
+$bp-large: 1024px;
+$bp-xlarge: 1280px;
+$bp-2xlarge: 1536px;
+
:root {
--light_font_col: #E1E1E1;
}
diff --git a/libs/common-docs/src/common-docs.module.ts b/libs/common-docs/src/common-docs.module.ts
index fe8d05df8..2700d2a16 100644
--- a/libs/common-docs/src/common-docs.module.ts
+++ b/libs/common-docs/src/common-docs.module.ts
@@ -4,12 +4,12 @@ import { PopoverComponent } from './components/popover/popover.component';
import { TopMenuComponent } from './components/top-menu/top-menu.component';
import { RouterModule } from '@angular/router';
import { ImgHoverDirective } from './directives/img-hover.directive';
-import { ContactModalComponent } from './components/contact-modal/contactModal.components';
+import { ContactModalComponent } from './components/contact-modal/contact-modal.components';
import { ModalService } from './services/modal.service';
import { ReactiveFormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { FileUploaderModule } from '@valor-software/file-uploader';
-import { SendEmailService } from './services/senEmail.service';
+import { SendEmailService } from './services/send-email.service';
import { ResultModalComponent } from './components/result-modal/result-modal.component';
import { AppFooterComponent } from './components/app-footer/app-footer.component';
import { ServicesBlockComponent } from './components/services_block/services-block.component';
@@ -37,7 +37,7 @@ export { TopMenuComponent } from './components/top-menu/top-menu.component';
export { ImgHoverDirective } from './directives/img-hover.directive';
export { AppFooterComponent } from './components/app-footer/app-footer.component';
export { ServicesBlockComponent } from './components/services_block/services-block.component';
-export { ContactModalComponent } from './components/contact-modal/contactModal.components';
+export { ContactModalComponent } from './components/contact-modal/contact-modal.components';
export { ModalService } from './services/modal.service';
export { BreadCrumbsComponent } from './components/breadCrumbs/breadCrumbs.component';
export { ShowHideDirective } from './directives/showHide.directive';
diff --git a/libs/common-docs/src/components/app-footer/app-footer.component.ts b/libs/common-docs/src/components/app-footer/app-footer.component.ts
index 446c1df82..784271839 100644
--- a/libs/common-docs/src/components/app-footer/app-footer.component.ts
+++ b/libs/common-docs/src/components/app-footer/app-footer.component.ts
@@ -1,6 +1,6 @@
import { Component } from '@angular/core';
import { ModalService } from '../../services/modal.service';
-import { ContactModalComponent } from '../contact-modal/contactModal.components';
+import { ContactModalComponent } from '../contact-modal/contact-modal.components';
import { FormControl, Validators } from '@angular/forms';
@Component({
diff --git a/libs/common-docs/src/components/contact-modal/contact-modal.component.html b/libs/common-docs/src/components/contact-modal/contact-modal.component.html
new file mode 100644
index 000000000..83fc26a31
--- /dev/null
+++ b/libs/common-docs/src/components/contact-modal/contact-modal.component.html
@@ -0,0 +1,266 @@
+
diff --git a/libs/common-docs/src/components/contact-modal/contact-modal.component.scss b/libs/common-docs/src/components/contact-modal/contact-modal.component.scss
new file mode 100644
index 000000000..83f90379e
--- /dev/null
+++ b/libs/common-docs/src/components/contact-modal/contact-modal.component.scss
@@ -0,0 +1,100 @@
+// ToDo: add base styles import
+$bp-small: 640px;
+$bp-medium: 768px;
+
+:host {
+ font-family: 'Work Sans', 'Roboto', 'Arial', 'sans-serif';
+}
+
+.contact-body {
+ height: 100%;
+ width: 100%;
+ overflow-x: hidden;
+ overflow-y: auto;
+ top: 0;
+}
+
+.row {
+ display: flex;
+ justify-content: space-between;
+ width: 100%;
+
+ @media (max-width: $bp-small) {
+ flex-direction: column;
+ justify-content: start;
+ }
+}
+
+.option-background {
+ width: 100%;
+ border-radius: 0.25rem;
+ border-width: 1px;
+ border-color: transparent;
+ background-color: rgba(52, 52, 52, var(--tw-bg-opacity));
+ padding: 1rem;
+ font-size: 1rem;
+ color: rgba(255, 255, 255, var(--tw-text-opacity));
+}
+
+.form-control-wrapper {
+ display: flex;
+ flex-direction: column;
+ width: 48%;
+
+ @media (max-width: $bp-small) {
+ width: 100%;
+
+ &:first-child {
+ margin-bottom: 16px;
+ }
+ }
+}
+
+.radio-input {
+ width: 48%;
+ display: flex;
+ align-items: center;
+ color: white;
+ cursor: pointer;
+ padding: 12px;
+
+ @media (max-width: $bp-small) {
+ width: 100%;
+
+ &:first-child {
+ margin-bottom: 16px;
+ }
+ }
+}
+
+.checkbox-label {
+ display: flex;
+ align-items: center;
+ cursor: pointer;
+ width: 55%;
+ color: white;
+
+ @media (max-width: $bp-medium) {
+ width: 70%;
+ }
+
+ @media (max-width: $bp-small) {
+ width: 100%;
+ }
+}
+
+.checkbox {
+ width: 20px;
+ height: 20px;
+ background-color: #272727;
+ border: 1px solid #E24E63;
+ border-radius: 10%;
+
+ &:focus {
+ box-shadow: none;
+ }
+
+ &:checked {
+ background-color: #E24E63 !important;
+ }
+}
diff --git a/libs/common-docs/src/components/contact-modal/contact-modal.components.ts b/libs/common-docs/src/components/contact-modal/contact-modal.components.ts
new file mode 100644
index 000000000..7e2209797
--- /dev/null
+++ b/libs/common-docs/src/components/contact-modal/contact-modal.components.ts
@@ -0,0 +1,241 @@
+import { ChangeDetectionStrategy, ChangeDetectorRef, Component, HostListener, OnDestroy } from '@angular/core';
+import { ModalService } from '../../services/modal.service';
+import { Subscription } from 'rxjs';
+import { FormControl, FormGroup, Validators } from '@angular/forms';
+import { CompanyServiceName, ContactData, SendEmailService } from '../../services/send-email.service';
+import { ReCaptchaV3Service } from 'ng-recaptcha';
+import { errorVocabulary, IError } from './errors';
+import { Router } from '@angular/router';
+import { switchMap, tap } from 'rxjs/operators';
+
+interface ContactModalForm {
+ firstName: FormControl;
+ lastName: FormControl;
+ email: FormControl;
+ companyName: FormControl;
+ jobRole: FormControl;
+ companySize: FormControl;
+ companyServiceName: FormControl;
+ comment: FormControl;
+ hasAcceptedPrivacyPolicy: FormControl;
+ hasAcceptedContactAgreement: FormControl;
+ ['g-recaptcha-response']: FormControl;
+}
+
+const emailRegex = /^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$/;
+const textRegex = /^(?! +$)[a-zA-Z0-9\-_ ']+$/;
+const commentRegex = /^(?!\s*$).+/;
+
+@Component({
+ // eslint-disable-next-line @angular-eslint/component-selector
+ selector: 'contact-modal',
+ templateUrl: './contact-modal.component.html',
+ styleUrls: ['./contact-modal.component.scss'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class ContactModalComponent implements OnDestroy {
+ showSuccessModalState = false;
+ showErrorModalState = false;
+ submitErrorMessage = '';
+
+ form = this._createForm();
+ readonly validationMessages = {
+ firstName: [
+ { type: 'required', message: 'This field is required field' },
+ { type: 'minlength', message: 'Field must be longer than 2 characters' },
+ { type: 'maxlength', message: 'Field must be less than 30 characters' },
+ { type: 'pattern', message: 'Please enter valid data' }
+ ],
+ lastName: [
+ { type: 'required', message: 'This field is required field' },
+ { type: 'minlength', message: 'Field must be longer than 2 characters' },
+ { type: 'maxlength', message: 'Field must be less than 30 characters' },
+ { type: 'pattern', message: 'Please enter valid data' }
+ ],
+ companyName: [
+ { type: 'minlength', message: 'Field must be longer than 2 characters' },
+ { type: 'maxlength', message: 'Field must be less than 30 characters' },
+ { type: 'pattern', message: 'Please enter valid data' }
+ ],
+ jobRole: [
+ { type: 'minlength', message: 'Field must be longer than 2 characters' },
+ { type: 'maxlength', message: 'Field must be less than 30 characters' },
+ { type: 'pattern', message: 'Please enter valid data' }
+ ],
+ companySize: [
+ { type: 'minlength', message: 'Field must be longer than 2 characters' },
+ { type: 'maxlength', message: 'Field must be less than 30 characters' },
+ { type: 'pattern', message: 'Please enter valid data' }
+ ],
+ email: [
+ { type: 'required', message: 'This field is required field' },
+ { type: 'pattern', message: 'Please enter a valid email' }
+ ],
+ comment: [
+ { type: 'minlength', message: 'Field must be longer than 5 characters' },
+ { type: 'maxlength', message: 'Field must be less than 1000 characters' },
+ { type: 'pattern', message: 'Please enter valid data' }
+ ],
+ hasAcceptedPrivacyPolicy: [
+ { type: 'required', message: 'This field is required field' },
+ ],
+ hasAcceptedContactAgreement: [
+ { type: 'required', message: 'This field is required field' },
+ ],
+ };
+ readonly CompanyServiceName = CompanyServiceName;
+
+ private readonly _internalSub = new Subscription();
+
+ @HostListener('document:keydown.escape', ['$event']) onKeydownHandler() {
+ const focused: HTMLElement | null = document.querySelector(':focus-visible');
+ this.closeModal();
+ if (focused) {
+ focused.blur();
+ }
+ }
+
+ constructor(
+ readonly modalService: ModalService,
+ private readonly sendEmailService: SendEmailService,
+ private readonly recaptchaV3Service: ReCaptchaV3Service,
+ private readonly router: Router,
+ private readonly _cdRef: ChangeDetectorRef
+ ) {
+ const element = document.body.querySelector('.grecaptcha-badge') as HTMLElement;
+ if (element) {
+ element.style.display = 'block';
+ }
+ }
+
+ ngOnDestroy() {
+ const element = document.body.querySelector('.grecaptcha-badge') as HTMLElement;
+ if (element) {
+ element.style.display = 'none';
+ }
+
+ this._internalSub.unsubscribe();
+ }
+
+ closeModal() {
+ this.modalService.close();
+ }
+
+ onSubmit() {
+ this._internalSub.add(
+ this.recaptchaV3Service.execute('importantAction').pipe(
+ tap((token: string) => this.form.get('g-recaptcha-response')?.setValue(token)),
+ switchMap((token: string) =>
+ this.form.getRawValue().companyServiceName === CompanyServiceName.Career
+ ? this.sendEmailService.sendCareersEmail(this.getContactData())
+ : this.sendEmailService.sendSalesEmail(this.getContactData())
+ )
+ ).subscribe(() => {
+ this.form.reset();
+ this.showSuccessModal();
+ this.recaptchaV3Service.execute('');
+ }, (error: IError) => {
+ const code = error.error.errors[0].code === 'TYPE_EMAIL' ? 'INVALID_EMAIL' : error.error.errors[0].code;
+ const errorText = errorVocabulary[code as keyof typeof errorVocabulary] || error.error.errors[0].message;
+ this.showErrorModal(errorText);
+ })
+ );
+ }
+
+ showSuccessModal() {
+ this.showSuccessModalState = true;
+ this.showErrorModalState = false;
+ this.submitErrorMessage = '';
+ this._cdRef.detectChanges();
+ }
+
+ showErrorModal(error?: string) {
+ this.showSuccessModalState = false;
+ this.showErrorModalState = true;
+ this.submitErrorMessage = error ?? '';
+ this._cdRef.detectChanges();
+ }
+
+ resetError() {
+ this.showErrorModalState = false;
+ this.submitErrorMessage = '';
+ this._cdRef.detectChanges();
+ }
+
+ hasFieldError(validationType: string, field: string): boolean {
+ const formField = this.form.get(field);
+
+ return formField
+ ? formField.hasError(validationType) && (formField.dirty || formField.touched)
+ : false;
+ }
+
+ private _createForm() {
+ return new FormGroup({
+ firstName: new FormControl('', [
+ Validators.required,
+ Validators.maxLength(30),
+ Validators.minLength(2),
+ Validators.pattern(textRegex)
+ ]),
+ lastName: new FormControl('', [
+ Validators.required,
+ Validators.maxLength(30),
+ Validators.minLength(2),
+ Validators.pattern(textRegex)
+ ]),
+ email: new FormControl('', [
+ Validators.required, Validators.pattern(emailRegex)
+ ]),
+ companyName: new FormControl('', [
+ Validators.maxLength(30),
+ Validators.minLength(2),
+ Validators.pattern(textRegex)
+ ]),
+ jobRole: new FormControl('', [
+ Validators.maxLength(30),
+ Validators.minLength(2),
+ Validators.pattern(textRegex)
+ ]),
+ companySize: new FormControl('', [
+ Validators.maxLength(30),
+ Validators.minLength(2),
+ Validators.pattern(textRegex)
+ ]),
+ companyServiceName: new FormControl(this._getDefaultCompanyServiceName()),
+ comment: new FormControl('', [
+ Validators.maxLength(2000),
+ Validators.minLength(5),
+ Validators.pattern(commentRegex)
+ ]),
+ hasAcceptedPrivacyPolicy: new FormControl(false, [Validators.required]),
+ hasAcceptedContactAgreement: new FormControl(false, [Validators.required]),
+ 'g-recaptcha-response': new FormControl('')
+ });
+ }
+
+ private _getDefaultCompanyServiceName(): CompanyServiceName {
+ if (this.router.url.includes('/careers')) {
+ return CompanyServiceName.Career;
+ }
+
+ return CompanyServiceName.Service;
+ }
+
+ private getContactData(): ContactData {
+ const data = this.form.getRawValue();
+
+ return {
+ firstName: data.firstName?.trim() ?? '',
+ lastName: data.lastName?.trim() ?? '',
+ email: data.email?.trim() ?? '',
+ companyServiceName: data.companyServiceName ?? CompanyServiceName.Service,
+ 'g-recaptcha-response': data['g-recaptcha-response'] ?? '',
+ // optional fields
+ ...(data.companyName?.trim() && { companyName: data.companyName?.trim() }),
+ ...(data.jobRole?.trim() && { jobRole: data.jobRole?.trim() }),
+ ...(data.companySize?.trim() && { companySize: data.companySize?.trim() }),
+ ...(data.comment?.trim() && { comment: data.comment?.trim() }),
+ };
+ }
+}
diff --git a/libs/common-docs/src/components/contact-modal/contactModal.component.html b/libs/common-docs/src/components/contact-modal/contactModal.component.html
deleted file mode 100644
index c96275b30..000000000
--- a/libs/common-docs/src/components/contact-modal/contactModal.component.html
+++ /dev/null
@@ -1,89 +0,0 @@
-
diff --git a/libs/common-docs/src/components/contact-modal/contactModal.components.ts b/libs/common-docs/src/components/contact-modal/contactModal.components.ts
deleted file mode 100644
index 02a88bcc0..000000000
--- a/libs/common-docs/src/components/contact-modal/contactModal.components.ts
+++ /dev/null
@@ -1,128 +0,0 @@
-import { Component, HostListener, OnDestroy } from '@angular/core';
-import { ModalService } from '../../services/modal.service';
-import { Subscription } from 'rxjs';
-import { UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
-import { SendEmailService } from '../../services/senEmail.service';
-import { ReCaptchaV3Service } from 'ng-recaptcha';
-import { errorVocabulary, IError } from './errors';
-import { Router } from '@angular/router';
-
-@Component({
- // eslint-disable-next-line @angular-eslint/component-selector
- selector: 'contact-modal',
- templateUrl: './contactModal.component.html'
-})
-export class ContactModalComponent implements OnDestroy {
- _state?: Subscription;
- state?: boolean;
- form: UntypedFormGroup = new UntypedFormGroup({
- type: new UntypedFormControl('', [Validators.required]),
- email: new UntypedFormControl('', [Validators.required, Validators.email]),
- message: new UntypedFormControl('', [Validators.required, Validators.maxLength(1000), Validators.minLength(5)]),
- 'g-recaptcha-response': new UntypedFormControl('')
- });
- data?: FormData;
- files?: File[];
- showSuccess = false;
- showError = false;
- $reCaptchaSub?: Subscription;
- errorMessage?: string;
-
- readonly validationMessages = {
- email: [
- { type: 'required', message: 'required field' },
- { type: 'email', message: 'Please enter a valid email' }
- ],
- message: [
- { type: 'required', message: 'required field' },
- { type: 'minlength', message: 'The message must be longer than 5 characters' },
- { type: 'maxlength', message: 'The message must be less than 1000 characters' }
- ],
- };
-
- @HostListener('document:keydown.escape', ['$event']) onKeydownHandler() {
- const focused: HTMLElement | null = document.querySelector(':focus-visible');
- this.closeModal();
- if(focused){
- focused.blur();
- }
- }
-
- constructor(
- private modalService: ModalService,
- private sendEmailServ: SendEmailService,
- private recaptchaV3Service: ReCaptchaV3Service,
- private router: Router
- ) {
- this._state = this.modalService.state.subscribe((res: boolean) => {
- setTimeout(() => {
- this.state = res;
- });
- });
-
- const element = document.body.querySelector('.grecaptcha-badge') as HTMLElement;
- if (element) {
- element.style.display = 'block';
- }
-
- if (this.router.url.includes('/services') || this.router.url.includes('/clients')) {
- this.form.get('type')?.setValue('service');
- } else if (this.router.url.includes('/careers')) {
- this.form.get('type')?.setValue('career');
- }
- }
-
- closeModal() {
- this.modalService.close();
- }
-
- onSubmit() {
- this.$reCaptchaSub = this.recaptchaV3Service.execute('importantAction')
- .subscribe((token: string) => {
- this.form.get('g-recaptcha-response')?.setValue(token);
- this.sendEmailServ.sendEmail(this.form.value).subscribe(res => {
- this.form.reset();
- this.showSuccessModal();
- this.recaptchaV3Service.execute('');
- }, (error: IError) => {
- const code = error.error.errors[0].code === 'TYPE_EMAIL' ? 'INVALID_EMAIL' : error.error.errors[0].code;
- const errorText = errorVocabulary[code as keyof typeof errorVocabulary] || error.error.errors[0].message;
- this.showErrorModal(errorText);
- });
- });
- }
-
- showSuccessModal() {
- this.showSuccess = true;
- this.showError = false;
- this.errorMessage = '';
- }
-
- showErrorModal(error?: string) {
- this.showSuccess = false;
- this.showError = true;
- this.errorMessage = error;
- }
-
- resetError() {
- this.showError = false;
- this.errorMessage = '';
- }
-
- ngOnDestroy() {
- const element = document.body.querySelector('.grecaptcha-badge') as HTMLElement;
- if (element) {
- element.style.display = 'none';
- }
- this.$reCaptchaSub?.unsubscribe();
- }
-
- hasFieldError(validationType: string, field: string): boolean {
- const formField = this.form.get(field);
- if (formField) {
- return formField.hasError(validationType) && (formField.dirty || formField.touched);
- } else {
- return false;
- }
- }
-}
diff --git a/libs/common-docs/src/components/top-menu/top-menu.component.ts b/libs/common-docs/src/components/top-menu/top-menu.component.ts
index 13c15d143..0fd54afa3 100644
--- a/libs/common-docs/src/components/top-menu/top-menu.component.ts
+++ b/libs/common-docs/src/components/top-menu/top-menu.component.ts
@@ -1,6 +1,6 @@
import { Component } from '@angular/core';
import { ModalService } from "../../services/modal.service";
-import { ContactModalComponent } from "../contact-modal/contactModal.components";
+import { ContactModalComponent } from "../contact-modal/contact-modal.components";
@Component({
// eslint-disable-next-line @angular-eslint/component-selector
diff --git a/libs/common-docs/src/services/modal.service.ts b/libs/common-docs/src/services/modal.service.ts
index 5800e6343..70c565998 100644
--- a/libs/common-docs/src/services/modal.service.ts
+++ b/libs/common-docs/src/services/modal.service.ts
@@ -13,7 +13,7 @@ import { BehaviorSubject } from "rxjs";
})
export class ModalService {
private componentRef: ComponentRef | undefined;
- state: BehaviorSubject = new BehaviorSubject(false);
+ modalDisplayState: BehaviorSubject = new BehaviorSubject(false);
constructor(
private componentFactoryResolver: ComponentFactoryResolver,
@@ -32,14 +32,14 @@ export class ModalService {
this.appRef.attachView(this.componentRef.hostView);
document.body.appendChild(this.componentRef.location.nativeElement);
- this.state.next(true);
+ this.modalDisplayState.next(true);
}
close(): void {
if (!this.componentRef) {
return;
}
- this.state.next(false);
+ this.modalDisplayState.next(false);
setTimeout(()=> {
if(this.componentRef) {
this.appRef.detachView(this.componentRef.hostView);
diff --git a/libs/common-docs/src/services/senEmail.service.ts b/libs/common-docs/src/services/senEmail.service.ts
deleted file mode 100644
index 3879b8696..000000000
--- a/libs/common-docs/src/services/senEmail.service.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { Injectable } from '@angular/core';
-import { HttpClient, HttpHeaders } from '@angular/common/http';
-import { Observable } from 'rxjs';
-
-
-@Injectable({providedIn: 'platform'})
-export class SendEmailService {
-
- constructor(
- private http: HttpClient
- ){}
-
- public sendEmail(body: any): Observable {
- return this.http
- .post('https://formspree.io/f/xeqnjork', body, {
- headers: new HttpHeaders({
- 'Accept': 'application/json'
- })
- });
- }
-}
\ No newline at end of file
diff --git a/libs/common-docs/src/services/send-email.service.ts b/libs/common-docs/src/services/send-email.service.ts
new file mode 100644
index 000000000..c58b76e7c
--- /dev/null
+++ b/libs/common-docs/src/services/send-email.service.ts
@@ -0,0 +1,48 @@
+import { Injectable } from '@angular/core';
+import { HttpClient, HttpHeaders } from '@angular/common/http';
+import { Observable } from 'rxjs';
+
+export interface ContactData {
+ firstName: string;
+ lastName: string;
+ email: string;
+ companyName?: string;
+ jobRole?: string;
+ companySize?: string;
+ companyServiceName: CompanyServiceName;
+ comment?: string;
+ ['g-recaptcha-response']: string;
+}
+
+export enum CompanyServiceName {
+ Service = 'Service',
+ Career = 'Career',
+ Partner = 'Partner',
+ Other = 'Other',
+}
+
+@Injectable({ providedIn: 'platform' })
+export class SendEmailService {
+ constructor(
+ private readonly http: HttpClient
+ ) {
+ }
+
+ public sendSalesEmail(body: ContactData): Observable {
+ return this.http
+ .post('https://formspree.io/f/xeqbrkvo', body, {
+ headers: new HttpHeaders({
+ 'Accept': 'application/json'
+ })
+ });
+ }
+
+ public sendCareersEmail(body: ContactData): Observable {
+ return this.http
+ .post('https://formspree.io/f/xgejnyra', body, {
+ headers: new HttpHeaders({
+ 'Accept': 'application/json'
+ })
+ });
+ }
+}
\ No newline at end of file