From f5b79b1d9348aa004bfd5b9034fb30f6f8853e3b Mon Sep 17 00:00:00 2001
From: Antonin COQUET <ext.sopra.acoquet@grandlyon.com>
Date: Thu, 8 Apr 2021 11:16:21 +0200
Subject: [PATCH] feat: add newsletter subscription from footer and
 registration

---
 src/app/admin/admin.module.ts                 |  4 +-
 .../delete-user/delete-user.component.scss    |  8 ---
 .../delete-user/delete-user.component.ts      |  1 -
 .../newsletter-users.component.html           | 25 +++++++
 .../newsletter-users.component.spec.ts        | 27 ++++++++
 .../newsletter-users.component.ts             | 48 +++++++++++++
 .../components/panel/panel.component.html     |  5 ++
 src/app/admin/services/admin.service.ts       |  9 +++
 src/app/app-routing.module.ts                 | 11 +++
 src/app/app.module.ts                         |  2 +
 src/app/footer/footer.component.html          |  1 +
 src/app/form/form.component.html              |  9 +++
 src/app/form/form.component.ts                | 18 ++++-
 src/app/models/subscription-model.ts          |  4 ++
 .../newsletter-subscription.component.html    | 34 ++++++++++
 .../newsletter-subscription.component.scss    | 18 +++++
 .../newsletter-subscription.component.spec.ts | 28 ++++++++
 .../newsletter-subscription.component.ts      | 67 +++++++++++++++++++
 src/app/services/newsletter.service.ts        | 18 +++++
 src/app/shared/enum/adminPanel.enum.ts        |  1 +
 src/styles.scss                               |  9 +++
 21 files changed, 336 insertions(+), 11 deletions(-)
 delete mode 100644 src/app/admin/components/delete-user/delete-user.component.scss
 create mode 100644 src/app/admin/components/newsletter-users/newsletter-users.component.html
 create mode 100644 src/app/admin/components/newsletter-users/newsletter-users.component.spec.ts
 create mode 100644 src/app/admin/components/newsletter-users/newsletter-users.component.ts
 create mode 100644 src/app/models/subscription-model.ts
 create mode 100644 src/app/newsletter-subscription/newsletter-subscription.component.html
 create mode 100644 src/app/newsletter-subscription/newsletter-subscription.component.scss
 create mode 100644 src/app/newsletter-subscription/newsletter-subscription.component.spec.ts
 create mode 100644 src/app/newsletter-subscription/newsletter-subscription.component.ts
 create mode 100644 src/app/services/newsletter.service.ts

diff --git a/src/app/admin/admin.module.ts b/src/app/admin/admin.module.ts
index 05b87149d..e808d3c49 100644
--- a/src/app/admin/admin.module.ts
+++ b/src/app/admin/admin.module.ts
@@ -4,9 +4,11 @@ import { PanelComponent } from './components/panel/panel.component';
 import { ClaimStructureComponent } from './components/claim-structure/claim-structure.component';
 import { DeleteUserComponent } from './components/delete-user/delete-user.component';
 import { SharedModule } from '../shared/shared.module';
+import { NewsComponent } from '../post/news.component';
+import { NewsletterUsersComponent } from './components/newsletter-users/newsletter-users.component';
 
 @NgModule({
-  declarations: [PanelComponent, ClaimStructureComponent, DeleteUserComponent],
+  declarations: [PanelComponent, ClaimStructureComponent, DeleteUserComponent, NewsletterUsersComponent],
   imports: [CommonModule, SharedModule],
 })
 export class AdminModule {}
diff --git a/src/app/admin/components/delete-user/delete-user.component.scss b/src/app/admin/components/delete-user/delete-user.component.scss
deleted file mode 100644
index 39b7a0741..000000000
--- a/src/app/admin/components/delete-user/delete-user.component.scss
+++ /dev/null
@@ -1,8 +0,0 @@
-.userList {
-    max-width: 50%;
-}
-
-.userBlock {
-    max-width: 50%;
-    margin: 0 auto;
-}
\ No newline at end of file
diff --git a/src/app/admin/components/delete-user/delete-user.component.ts b/src/app/admin/components/delete-user/delete-user.component.ts
index 00e5c943b..293324fe7 100644
--- a/src/app/admin/components/delete-user/delete-user.component.ts
+++ b/src/app/admin/components/delete-user/delete-user.component.ts
@@ -6,7 +6,6 @@ import { AdminService } from '../../services/admin.service';
 @Component({
   selector: 'app-admin-delete-user',
   templateUrl: './delete-user.component.html',
-  styleUrls: ['./delete-user.component.scss'],
 })
 export class DeleteUserComponent {
   public users: User[];
diff --git a/src/app/admin/components/newsletter-users/newsletter-users.component.html b/src/app/admin/components/newsletter-users/newsletter-users.component.html
new file mode 100644
index 000000000..8a82446d7
--- /dev/null
+++ b/src/app/admin/components/newsletter-users/newsletter-users.component.html
@@ -0,0 +1,25 @@
+<div fxLayout="column" fxLayoutGap="5px" fxLayoutAlign="center center" class="userBlock">
+  <h2>Gestion abonnement newsletter</h2>
+  <div fxLayout="row">
+    <button (click)="copySubscription()">Copier les adresses dans le presse papier</button>
+  </div>
+  <div fxLayout="row">
+    <input #searchstring (keyup)="(0)" />
+    <button (click)="searchSubscribedEmail(searchstring.value)">Rechercher</button>
+  </div>
+  <div class="userList">
+    <tr *ngFor="let subscription of subscriptions">
+      <td>{{ subscription.email }}</td>
+      <td>
+        <button (click)="toggleUnsubscribeModal(subscription.email)">Désabonner</button>
+      </td>
+    </tr>
+    <app-modal-confirmation
+      *ngIf="emailToUnsubscribe"
+      [openned]="deleteModalOpenned"
+      [content]="'Voulez-vous vraiment supprimer ' + emailToUnsubscribe + ' de la newsletter &nbsp;?'"
+      (closed)="unsubscribeEmail(emailToUnsubscribe, $event)"
+    ></app-modal-confirmation>
+    <div *ngIf="subscriptions && subscriptions.length == 0">Aucun résultat</div>
+  </div>
+</div>
diff --git a/src/app/admin/components/newsletter-users/newsletter-users.component.spec.ts b/src/app/admin/components/newsletter-users/newsletter-users.component.spec.ts
new file mode 100644
index 000000000..119aadb28
--- /dev/null
+++ b/src/app/admin/components/newsletter-users/newsletter-users.component.spec.ts
@@ -0,0 +1,27 @@
+import { HttpClientModule } from '@angular/common/http';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { NewsletterUsersComponent } from './newsletter-users.component';
+
+describe('DeleteUserComponent', () => {
+  let component: NewsletterUsersComponent;
+  let fixture: ComponentFixture<NewsletterUsersComponent>;
+  let USERS;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [HttpClientModule],
+      declarations: [NewsletterUsersComponent],
+    }).compileComponents();
+  });
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(NewsletterUsersComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/src/app/admin/components/newsletter-users/newsletter-users.component.ts b/src/app/admin/components/newsletter-users/newsletter-users.component.ts
new file mode 100644
index 000000000..66290faae
--- /dev/null
+++ b/src/app/admin/components/newsletter-users/newsletter-users.component.ts
@@ -0,0 +1,48 @@
+import { Component } from '@angular/core';
+import { NewsletterSubscription } from '../../../models/subscription-model';
+import { AdminService } from '../../services/admin.service';
+
+@Component({
+  selector: 'app-admin-newsletter-users',
+  templateUrl: './newsletter-users.component.html',
+})
+export class NewsletterUsersComponent {
+  public subscriptions: NewsletterSubscription[];
+  public deleteModalOpenned = false;
+  public emailToUnsubscribe: string = null;
+
+  constructor(private adminService: AdminService) {}
+
+  public toggleUnsubscribeModal(emailToUnsubscribe: string): void {
+    this.emailToUnsubscribe = emailToUnsubscribe;
+    this.deleteModalOpenned = !this.deleteModalOpenned;
+  }
+
+  public searchSubscribedEmail(searchString: string): void {
+    this.adminService.searchNewsletterSubscriptions(searchString).subscribe((emails) => {
+      this.subscriptions = emails;
+    });
+  }
+
+  public unsubscribeEmail(email: string, shouldUnsubscribe: boolean): void {
+    this.toggleUnsubscribeModal(email);
+    if (shouldUnsubscribe) {
+      this.adminService.unsubscribeEmail(email).subscribe((data) => {
+        this.subscriptions = this.subscriptions.filter((obj) => obj.email !== email);
+      });
+    }
+  }
+
+  public copySubscription(): void {
+    this.adminService.searchNewsletterSubscriptions('').subscribe((emails) => {
+      let emailsToBeCopied = emails.map((e) => e.email).join(';');
+      let copyElement = document.createElement('textarea');
+      copyElement.textContent = decodeURI(emailsToBeCopied);
+      let body = document.getElementsByTagName('body')[0];
+      body.appendChild(copyElement);
+      copyElement.select();
+      document.execCommand('copy');
+      body.removeChild(copyElement);
+    });
+  }
+}
diff --git a/src/app/admin/components/panel/panel.component.html b/src/app/admin/components/panel/panel.component.html
index 252986fc6..1ee88741e 100644
--- a/src/app/admin/components/panel/panel.component.html
+++ b/src/app/admin/components/panel/panel.component.html
@@ -3,6 +3,7 @@
   <div fxLayout="row" fxLayoutGap="20px" fxLayoutAlign="center center">
     <button (click)="changeActiveFeature(features.pendingStructures)">Gestion structure</button>
     <button (click)="changeActiveFeature(features.deleteUsers)">Suppression d'utilisateurs</button>
+    <button (click)="changeActiveFeature(features.newsletterUsers)">Désabonnement newsletter</button>
     <a target="_blank" class="custom-link" rel="noopener noreferrer" [href]="ghostLink">Ghost</a>
   </div>
   <div *ngIf="selectedFeature === features.deleteUsers">
@@ -11,4 +12,8 @@
   <div *ngIf="selectedFeature === features.pendingStructures">
     <app-admin-claim-structure></app-admin-claim-structure>
   </div>
+  <div *ngIf="selectedFeature === features.newsletterUsers">
+    <app-admin-newsletter-users></app-admin-newsletter-users>
+  </div>
+  
 </div>
diff --git a/src/app/admin/services/admin.service.ts b/src/app/admin/services/admin.service.ts
index adc590b8d..d71c89ef9 100644
--- a/src/app/admin/services/admin.service.ts
+++ b/src/app/admin/services/admin.service.ts
@@ -1,6 +1,7 @@
 import { HttpClient } from '@angular/common/http';
 import { Injectable } from '@angular/core';
 import { Observable } from 'rxjs';
+import { NewsletterSubscription } from '../../models/subscription-model';
 import { User } from '../../models/user.model';
 import { DemandAttachment } from '../models/demandAttachment.model';
 
@@ -28,6 +29,14 @@ export class AdminService {
     return this.http.delete<User>(`api/admin/user/` + id);
   }
 
+  public searchNewsletterSubscriptions(searchString: string): Observable<NewsletterSubscription[]> {
+    return this.http.post<NewsletterSubscription[]>(`api/admin/searchNewsletterSubscriptions`, { searchString });
+  }
+
+  public unsubscribeEmail(email: string): Observable<string> {
+    return this.http.delete<string>(`api/admin/newsletterSubscription/` + email);
+  }
+
   public acceptStructureClaim(
     userEmail: string,
     structureId: number,
diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts
index a67351971..46da7c87e 100644
--- a/src/app/app-routing.module.ts
+++ b/src/app/app-routing.module.ts
@@ -16,6 +16,7 @@ import { StructureJoinComponent } from './structure-join/structure-join.componen
 import { StructureDetailsComponent } from './structure-list/components/structure-details/structure-details.component';
 import { StructureListComponent } from './structure-list/structure-list.component';
 import { UserVerificationComponent } from './user-verification/user-verification.component';
+import { NewsletterSubscriptionComponent } from './newsletter-subscription/newsletter-subscription.component';
 
 const routes: Routes = [
   { path: 'print', outlet: 'print', children: [{ path: 'structure', component: StructureDetailsComponent }] },
@@ -79,6 +80,16 @@ const routes: Routes = [
     component: FormComponent,
     canDeactivate: [DeactivateGuard],
   },
+  {
+    path: 'newsletter',
+    component: NewsletterSubscriptionComponent,
+  },
+
+  {
+    path: 'newsletter-unsubscribe',
+    component: NewsletterSubscriptionComponent,
+  },
+
   {
     path: 'news',
     loadChildren: () => import('./post/post.module').then((m) => m.PostModule),
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 1aebde846..960ec8793 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -33,6 +33,7 @@ import { FooterFormComponent } from './form/footer-form/footer-form.component';
 import { TempUserResolver } from './resolvers/temp-user.resolver';
 import { StructureJoinComponent } from './structure-join/structure-join.component';
 import { RouterListenerService } from './services/routerListener.service';
+import { NewsletterSubscriptionComponent } from './newsletter-subscription/newsletter-subscription.component';
 
 @NgModule({
   declarations: [
@@ -54,6 +55,7 @@ import { RouterListenerService } from './services/routerListener.service';
     FormComponent,
     FooterFormComponent,
     StructureJoinComponent,
+    NewsletterSubscriptionComponent,
   ],
   imports: [BrowserModule, HttpClientModule, AppRoutingModule, SharedModule, MapModule, ProfileModule, AdminModule],
   providers: [
diff --git a/src/app/footer/footer.component.html b/src/app/footer/footer.component.html
index 6cc2485c7..b6de16278 100644
--- a/src/app/footer/footer.component.html
+++ b/src/app/footer/footer.component.html
@@ -1,6 +1,7 @@
 <div class="footer" fxLayout="row" fxLayoutAlign="center">
   <div fxLayout="row">
     <a class="clickable text-align-center" routerLink="/legal-notice" i18n>Mentions légales</a>
+    <a class="clickable text-align-center" routerLink="/newsletter" i18n>Newsletter</a>
     <!-- <a class="clickable text-align-center" routerLink="/sitemap" i18n>Plan du site</a> -->
     <a class="clickable text-align-center" href="mailto:inclusionnumerique@grandlyon.com">Contact</a>
   </div>
diff --git a/src/app/form/form.component.html b/src/app/form/form.component.html
index d0d588e89..e464ce3ba 100644
--- a/src/app/form/form.component.html
+++ b/src/app/form/form.component.html
@@ -1074,6 +1074,15 @@
         (checkEvent)="acceptDataBeSaved($event)"
       >
       </app-checkbox-form>
+      <div class="title">
+        <h3>Acceptez-vous de recevoir des mails d'informations de la part de Res'in ?</h3>
+      </div>
+      <app-checkbox-form
+        [isChecked]="userAcceptNewsletter"
+        [text]="'J\'accepte'"
+        (checkEvent)="acceptReceiveNewsletter($event)"
+      >
+      </app-checkbox-form>
       <p class="informationEndForm">
         <span class="asterisk">*</span> Les informations recueillies sont enregistrées dans un fichier par la Métropole
         de Lyon en vue de l'animation du réseau des acteurs de la médiation numérique. Elles sont conservées pendant 24
diff --git a/src/app/form/form.component.ts b/src/app/form/form.component.ts
index 10a41c2d9..aeb849541 100644
--- a/src/app/form/form.component.ts
+++ b/src/app/form/form.component.ts
@@ -20,6 +20,7 @@ import { PageTypeEnum } from './pageType.enum';
 import { CustomRegExp } from '../utils/CustomRegExp';
 import { StructureWithOwners } from '../models/structureWithOwners.model';
 import { RouterListenerService } from '../services/routerListener.service';
+import { NewsletterService } from '../services/newsletter.service';
 const { DateTime } = require('luxon');
 @Component({
   selector: 'app-structureForm',
@@ -66,6 +67,7 @@ export class FormComponent implements OnInit {
   public isShowConfirmPassword = false;
   public isShowPassword = false;
   public userAcceptSavedDate = false;
+  public userAcceptNewsletter = false;
   public showMenu = false;
   public isEditMode = false;
   public isClaimMode = false;
@@ -82,7 +84,8 @@ export class FormComponent implements OnInit {
     private authService: AuthService,
     private router: Router,
     private route: ActivatedRoute,
-    private routerListener: RouterListenerService
+    private routerListener: RouterListenerService,
+    private newsletterService: NewsletterService
   ) {}
 
   async ngOnInit(): Promise<void> {
@@ -574,6 +577,9 @@ export class FormComponent implements OnInit {
       const user = new User(this.accountForm.value);
       // Create user and claim structure
       this.authService.register(user).subscribe(() => {
+        if (this.userAcceptNewsletter) {
+          this.newsletterService.newsletterSubscribe(user.email).subscribe(() => {});
+        }
         // If joinMode, send join request, if not send claim request;
         if (this.isJoinMode) {
           this.structureService.joinStructure(this.claimStructure._id, user.email).subscribe(() => {
@@ -824,6 +830,10 @@ export class FormComponent implements OnInit {
     this.setValidationsForm();
   }
 
+  public acceptReceiveNewsletter(isAccepted: boolean): void {
+    this.userAcceptNewsletter = isAccepted;
+  }
+
   public validateForm(): void {
     if (this.structureForm.valid && this.hoursForm.valid) {
       let structure: Structure = this.structureForm.value;
@@ -839,6 +849,9 @@ export class FormComponent implements OnInit {
           user = this.profile;
           structure.accountVerified = true;
           this.createStructure(structure, user);
+          if (this.userAcceptNewsletter) {
+            this.newsletterService.newsletterSubscribe(user.email).subscribe(() => {});
+          }
         } else {
           if (this.accountForm.valid) {
             user = new User(this.accountForm.value);
@@ -848,6 +861,9 @@ export class FormComponent implements OnInit {
               .subscribe(() => {
                 this.createStructure(structure, user);
               });
+            if (this.userAcceptNewsletter) {
+              this.newsletterService.newsletterSubscribe(user.email).subscribe(() => {});
+            }
           }
         }
       }
diff --git a/src/app/models/subscription-model.ts b/src/app/models/subscription-model.ts
new file mode 100644
index 000000000..4657f29d6
--- /dev/null
+++ b/src/app/models/subscription-model.ts
@@ -0,0 +1,4 @@
+export class NewsletterSubscription {
+  email: string;
+  _id: string;
+}
diff --git a/src/app/newsletter-subscription/newsletter-subscription.component.html b/src/app/newsletter-subscription/newsletter-subscription.component.html
new file mode 100644
index 000000000..445ca0a46
--- /dev/null
+++ b/src/app/newsletter-subscription/newsletter-subscription.component.html
@@ -0,0 +1,34 @@
+<div fxLayout="column" class="content-container full-screen">
+  <div class="section-container" fxLayout="column" fxLayoutAlign="center center">
+    <div class="subscriptionForm">
+      <div *ngIf="subscriptionMod"><h1>Inscription à la newsletter</h1></div>
+      <div *ngIf="!subscriptionMod"><h1>Désinscription de la newsletter</h1></div>
+      <form [formGroup]="subscriptionForm" (ngSubmit)="onSubmit()">
+        <div class="form-group">
+          <label for="email">Courriel personnel</label>
+          <div fxLayout="row" fxLayoutGap="13px">
+            <input
+              type="email"
+              autocomplete="on"
+              formControlName="email"
+              class="form-input"
+              [ngClass]="{ 'is-invalid': submitted && f.email.errors }"
+            />
+          </div>
+          <div *ngIf="submitted && f.email.errors" class="invalid-feedback">
+            <div *ngIf="f.email.errors.required">L'adresse e-mail est requise</div>
+            <div *ngIf="f.email.errors.pattern">L'adresse e-mail doit être valide</div>
+          </div>
+        </div>
+        <div class="button" fxLayout="row" fxLayoutAlign="space-around center">
+          <a routerLink="../home" class="btn btn-link">Annuler</a>
+          <button [disabled]="loading" class="btn btn-primary">
+            <span *ngIf="loading" class="spinner-border spinner-border-sm mr-1"></span>
+            <div *ngIf="subscriptionMod">S'inscrire</div>
+            <div *ngIf="!subscriptionMod">Se désinscrire</div>
+          </button>
+        </div>
+      </form>
+    </div>
+  </div>
+</div>
diff --git a/src/app/newsletter-subscription/newsletter-subscription.component.scss b/src/app/newsletter-subscription/newsletter-subscription.component.scss
new file mode 100644
index 000000000..01eb52d26
--- /dev/null
+++ b/src/app/newsletter-subscription/newsletter-subscription.component.scss
@@ -0,0 +1,18 @@
+@import '../../assets/scss/color';
+
+.subscriptionPasswordForm {
+  max-width: 500px;
+}
+
+.button {
+  margin-top: 20px;
+}
+
+.form-input {
+  background-color: white;
+  width: 100%;
+}
+
+.existingEmail {
+  color: $orange-warning;
+}
diff --git a/src/app/newsletter-subscription/newsletter-subscription.component.spec.ts b/src/app/newsletter-subscription/newsletter-subscription.component.spec.ts
new file mode 100644
index 000000000..a39ffc169
--- /dev/null
+++ b/src/app/newsletter-subscription/newsletter-subscription.component.spec.ts
@@ -0,0 +1,28 @@
+import { HttpClientTestingModule } from '@angular/common/http/testing';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+import { RouterTestingModule } from '@angular/router/testing';
+
+import { NewsletterSubscriptionComponent } from './newsletter-subscription.component';
+
+describe('ResetPasswordComponent', () => {
+  let component: NewsletterSubscriptionComponent;
+  let fixture: ComponentFixture<NewsletterSubscriptionComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [NewsletterSubscriptionComponent],
+      imports: [ReactiveFormsModule, HttpClientTestingModule, RouterTestingModule],
+    }).compileComponents();
+  });
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(NewsletterSubscriptionComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/src/app/newsletter-subscription/newsletter-subscription.component.ts b/src/app/newsletter-subscription/newsletter-subscription.component.ts
new file mode 100644
index 000000000..2239fc70f
--- /dev/null
+++ b/src/app/newsletter-subscription/newsletter-subscription.component.ts
@@ -0,0 +1,67 @@
+import { Component, OnInit } from '@angular/core';
+import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms';
+import { Router } from '@angular/router';
+import { NewsletterService } from '../services/newsletter.service';
+import { CustomRegExp } from '../utils/CustomRegExp';
+
+@Component({
+  selector: 'app-newsletter-subscription',
+  templateUrl: './newsletter-subscription.component.html',
+  styleUrls: ['./newsletter-subscription.component.scss'],
+})
+export class NewsletterSubscriptionComponent implements OnInit {
+  public subscriptionForm: FormGroup;
+  public loading = false;
+  public submitted = false;
+  public subscriptionFailed = false;
+  public subscriptionMod: boolean;
+
+  constructor(private formBuilder: FormBuilder, private newsletterService: NewsletterService, private router: Router) {}
+
+  ngOnInit(): void {
+    this.subscriptionForm = this.formBuilder.group({
+      email: ['', [Validators.required, Validators.pattern(CustomRegExp.EMAIL)]],
+    });
+    if (this.router.url === '/newsletter') {
+      this.subscriptionMod = true;
+    }
+    if (this.router.url === '/newsletter-unsubscription') {
+      this.subscriptionMod = false;
+    }
+  }
+
+  get f(): { [key: string]: AbstractControl } {
+    return this.subscriptionForm.controls;
+  }
+
+  public onSubmit(): void {
+    this.submitted = true;
+
+    if (this.subscriptionForm.invalid) {
+      return;
+    }
+    this.loading = true;
+    if (this.subscriptionMod) {
+      this.newsletterService.newsletterSubscribe(this.f.email.value).subscribe(
+        () => {
+          this.router.navigate(['']);
+        },
+        () => {
+          this.loading = false;
+          this.subscriptionFailed = true;
+        }
+      );
+    }
+    if (!this.subscriptionMod) {
+      this.newsletterService.newsletterUnsubscribe(this.f.email.value).subscribe(
+        () => {
+          this.router.navigate(['']);
+        },
+        () => {
+          this.loading = false;
+          this.subscriptionFailed = true;
+        }
+      );
+    }
+  }
+}
diff --git a/src/app/services/newsletter.service.ts b/src/app/services/newsletter.service.ts
new file mode 100644
index 000000000..d90bd565d
--- /dev/null
+++ b/src/app/services/newsletter.service.ts
@@ -0,0 +1,18 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+import { Observable, of } from 'rxjs';
+
+@Injectable({
+  providedIn: 'root',
+})
+export class NewsletterService {
+  constructor(private http: HttpClient) {}
+
+  public newsletterSubscribe(email: string): Observable<any> {
+    return this.http.post('/api/newsletter/subscribe', {email});
+  }
+
+  public newsletterUnsubscribe(email: string): Observable<any> {
+    return this.http.post('/api/newsletter/unsubscribe', {email});
+  }
+}
diff --git a/src/app/shared/enum/adminPanel.enum.ts b/src/app/shared/enum/adminPanel.enum.ts
index 39dbc605f..293c64c4d 100644
--- a/src/app/shared/enum/adminPanel.enum.ts
+++ b/src/app/shared/enum/adminPanel.enum.ts
@@ -1,4 +1,5 @@
 export enum AdminPannelEnum {
   deleteUsers,
   pendingStructures,
+  newsletterUsers
 }
diff --git a/src/styles.scss b/src/styles.scss
index 08c7d2ff6..97e279390 100644
--- a/src/styles.scss
+++ b/src/styles.scss
@@ -269,3 +269,12 @@ button {
 .no-margin {
   margin: 0 !important;
 }
+
+.userList {
+  max-width: 50%;
+}
+
+.userBlock {
+  max-width: 50%;
+  margin: 0 auto;
+}
-- 
GitLab