diff --git a/angular.json b/angular.json
index c7f1b72897114d596a9b9899f170910ed7a9db06..fa0ff11aab15cdf6e20a2d5aef528a2a5157b897 100644
--- a/angular.json
+++ b/angular.json
@@ -31,10 +31,12 @@
           },
           "configurations": {
             "local": {
-              "fileReplacements": [{
-                "replace": "src/environments/environment.ts",
-                "with": "src/environments/environment.local.ts"
-              }]
+              "fileReplacements": [
+                {
+                  "replace": "src/environments/environment.ts",
+                  "with": "src/environments/environment.local.ts"
+                }
+              ]
             },
             "dev-production": {
               "optimization": true,
@@ -58,10 +60,12 @@
               "extractLicenses": true,
               "vendorChunk": false,
               "buildOptimizer": true,
-              "fileReplacements": [{
-                "replace": "src/environments/environment.ts",
-                "with": "src/environments/environment.prod.ts"
-              }]
+              "fileReplacements": [
+                {
+                  "replace": "src/environments/environment.ts",
+                  "with": "src/environments/environment.prod.ts"
+                }
+              ]
             }
           }
         },
@@ -116,7 +120,7 @@
           }
         }
       }
-    },
+    }
   },
   "defaultProject": "oser-app",
   "schematics": {
diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts
index 3827c734abf4b3ca2f70a49422946e5c5b11d17d..ed74bf7bb8c5e0aa1fe1719a9e62912aca4835ae 100644
--- a/src/app/app-routing.module.ts
+++ b/src/app/app-routing.module.ts
@@ -1,7 +1,7 @@
 import { NgModule } from '@angular/core';
 import { RouterModule, Routes } from '@angular/router';
 import { SignupPageComponent } from './signup-page/signup-page.component';
-import { LoginComponent, UiGalleryComponent } from './ui';
+import { LoginComponent, UiGalleryComponent } from './shared';
 import { InternalErrorComponent, NotFoundComponent, AuthGuard, MapsAPIResolver } from './core';
 
 import {
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 2137af6d5921c444f02569ca550477997f9e85f8..1466987d20afdefce859fbee32347a9b31033f7f 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -13,7 +13,7 @@ import { MomentModule } from 'ngx-moment';
 
 // App modules
 import { CoreModule } from './core';
-import { UiModule } from './ui';
+import { SharedModule } from './shared';
 import { AppRoutingModule } from './app-routing.module';
 import { ShowcaseSiteModule } from './showcase-site/showcase-site.module';
 import { VisitsModule } from './visits';
@@ -40,7 +40,7 @@ registerLocaleData(localeFR);
     HttpModule,
     MomentModule,
     CoreModule,
-    UiModule,
+    SharedModule,
     HttpClientModule,
     ShowcaseSiteModule,
     VisitsModule,
diff --git a/src/app/core/auth/models.ts b/src/app/core/auth/models.ts
index 23ff1aa4e9b61f0987bbba977e88c57cc8bb9d5b..827c970b6784e14000eb8d178a2f397fc0ca6947 100644
--- a/src/app/core/auth/models.ts
+++ b/src/app/core/auth/models.ts
@@ -26,4 +26,8 @@ export class User {
     this.phoneNumber = opts.phoneNumber;
     this.dateOfBirth = opts.dateOfBirth;
   }
+
+  get fullName(): string {
+    return [this.firstName, this.lastName].filter(x => x).join(' ');
+  }
 }
diff --git a/src/app/ui/footer/footer.component.html b/src/app/shared/footer/footer.component.html
similarity index 100%
rename from src/app/ui/footer/footer.component.html
rename to src/app/shared/footer/footer.component.html
diff --git a/src/app/ui/footer/footer.component.scss b/src/app/shared/footer/footer.component.scss
similarity index 100%
rename from src/app/ui/footer/footer.component.scss
rename to src/app/shared/footer/footer.component.scss
diff --git a/src/app/ui/footer/footer.component.ts b/src/app/shared/footer/footer.component.ts
similarity index 100%
rename from src/app/ui/footer/footer.component.ts
rename to src/app/shared/footer/footer.component.ts
diff --git a/src/app/ui/index.ts b/src/app/shared/index.ts
similarity index 84%
rename from src/app/ui/index.ts
rename to src/app/shared/index.ts
index f2174ea2b8f9751930f7687fad670e160c38b2d2..acf317b382677876290c0c30bdf583e5b1a32012 100644
--- a/src/app/ui/index.ts
+++ b/src/app/shared/index.ts
@@ -1,4 +1,4 @@
-export * from './ui.module';
+export * from './shared.module';
 export * from './navbar/navbar.component';
 export * from './footer/footer.component';
 export * from './login/login.component';
diff --git a/src/app/ui/load-spinner/load-spinner.component.html b/src/app/shared/load-spinner/load-spinner.component.html
similarity index 100%
rename from src/app/ui/load-spinner/load-spinner.component.html
rename to src/app/shared/load-spinner/load-spinner.component.html
diff --git a/src/app/ui/load-spinner/load-spinner.component.scss b/src/app/shared/load-spinner/load-spinner.component.scss
similarity index 100%
rename from src/app/ui/load-spinner/load-spinner.component.scss
rename to src/app/shared/load-spinner/load-spinner.component.scss
diff --git a/src/app/ui/load-spinner/load-spinner.component.ts b/src/app/shared/load-spinner/load-spinner.component.ts
similarity index 100%
rename from src/app/ui/load-spinner/load-spinner.component.ts
rename to src/app/shared/load-spinner/load-spinner.component.ts
diff --git a/src/app/ui/login/login.component.html b/src/app/shared/login/login.component.html
similarity index 100%
rename from src/app/ui/login/login.component.html
rename to src/app/shared/login/login.component.html
diff --git a/src/app/ui/login/login.component.scss b/src/app/shared/login/login.component.scss
similarity index 100%
rename from src/app/ui/login/login.component.scss
rename to src/app/shared/login/login.component.scss
diff --git a/src/app/ui/login/login.component.ts b/src/app/shared/login/login.component.ts
similarity index 100%
rename from src/app/ui/login/login.component.ts
rename to src/app/shared/login/login.component.ts
diff --git a/src/app/ui/navbar/navbar.component.html b/src/app/shared/navbar/navbar.component.html
similarity index 100%
rename from src/app/ui/navbar/navbar.component.html
rename to src/app/shared/navbar/navbar.component.html
diff --git a/src/app/ui/navbar/navbar.component.scss b/src/app/shared/navbar/navbar.component.scss
similarity index 100%
rename from src/app/ui/navbar/navbar.component.scss
rename to src/app/shared/navbar/navbar.component.scss
diff --git a/src/app/ui/navbar/navbar.component.ts b/src/app/shared/navbar/navbar.component.ts
similarity index 100%
rename from src/app/ui/navbar/navbar.component.ts
rename to src/app/shared/navbar/navbar.component.ts
diff --git a/src/app/ui/reveal/reveal.component.html b/src/app/shared/reveal/reveal.component.html
similarity index 100%
rename from src/app/ui/reveal/reveal.component.html
rename to src/app/shared/reveal/reveal.component.html
diff --git a/src/app/ui/reveal/reveal.component.scss b/src/app/shared/reveal/reveal.component.scss
similarity index 100%
rename from src/app/ui/reveal/reveal.component.scss
rename to src/app/shared/reveal/reveal.component.scss
diff --git a/src/app/ui/reveal/reveal.component.ts b/src/app/shared/reveal/reveal.component.ts
similarity index 100%
rename from src/app/ui/reveal/reveal.component.ts
rename to src/app/shared/reveal/reveal.component.ts
diff --git a/src/app/ui/ui.module.ts b/src/app/shared/shared.module.ts
similarity index 97%
rename from src/app/ui/ui.module.ts
rename to src/app/shared/shared.module.ts
index a1ff8043a2cb6548d7363d5343a029f60fc7e655..c6ae17fd6be81b01fe45e74c4e03319ded2b9f32 100644
--- a/src/app/ui/ui.module.ts
+++ b/src/app/shared/shared.module.ts
@@ -33,4 +33,4 @@ import { RevealComponent } from './reveal/reveal.component';
     RevealComponent,
   ]
 })
-export class UiModule { }
+export class SharedModule { }
diff --git a/src/app/ui/ui-gallery/ui-gallery.component.html b/src/app/shared/ui-gallery/ui-gallery.component.html
similarity index 100%
rename from src/app/ui/ui-gallery/ui-gallery.component.html
rename to src/app/shared/ui-gallery/ui-gallery.component.html
diff --git a/src/app/ui/ui-gallery/ui-gallery.component.scss b/src/app/shared/ui-gallery/ui-gallery.component.scss
similarity index 100%
rename from src/app/ui/ui-gallery/ui-gallery.component.scss
rename to src/app/shared/ui-gallery/ui-gallery.component.scss
diff --git a/src/app/ui/ui-gallery/ui-gallery.component.ts b/src/app/shared/ui-gallery/ui-gallery.component.ts
similarity index 100%
rename from src/app/ui/ui-gallery/ui-gallery.component.ts
rename to src/app/shared/ui-gallery/ui-gallery.component.ts
diff --git a/src/app/showcase-site/showcase-site.component.ts b/src/app/showcase-site/showcase-site.component.ts
index 5a92b48604a80aaa4db47f70f9af101edc7bb578..5ef44aea274ee5341b573c49e015b73c2c863ebb 100644
--- a/src/app/showcase-site/showcase-site.component.ts
+++ b/src/app/showcase-site/showcase-site.component.ts
@@ -1,5 +1,5 @@
 import { Component, OnInit, Renderer } from '@angular/core';
-import { Link } from 'app/ui';
+import { Link } from 'app/shared';
 
 @Component({
   selector: 'app-showcase-site',
diff --git a/src/app/showcase-site/showcase-site.module.ts b/src/app/showcase-site/showcase-site.module.ts
index e43aa0912340399d0d67ca7064acc8666729d386..6d702a5d5954817cc4159cf79aefaccfac6f99f3 100644
--- a/src/app/showcase-site/showcase-site.module.ts
+++ b/src/app/showcase-site/showcase-site.module.ts
@@ -4,7 +4,7 @@ import { NgModule } from '@angular/core';
 import { CommonModule } from '@angular/common';
 import { RouterModule } from '@angular/router';
 import { CoreModule } from 'app/core';
-import { UiModule } from 'app/ui';
+import { SharedModule } from 'app/shared';
 import { Ng2EmojiModule } from 'ng2-emoji';
 
 // Components
@@ -41,7 +41,7 @@ import { MentionsComponent } from './mentions/mentions.component';
     CommonModule,
     RouterModule,
     CoreModule,
-    UiModule,
+    SharedModule,
     Ng2EmojiModule.forRoot(),
   ],
   declarations: [
diff --git a/src/app/visits/organizer-card/organizer-card.component.html b/src/app/visits/organizer-card/organizer-card.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..61471ec368da661ea4b7a9df0a0d9d2d4ea94615
--- /dev/null
+++ b/src/app/visits/organizer-card/organizer-card.component.html
@@ -0,0 +1,11 @@
+<div class="container drop-shadow-sm">
+  <label class="name">
+    <strong>
+      {{ organizer.fullName }}
+    </strong>
+  </label>
+  <div *ngIf="organizer.phoneNumber" class="text-muted-sm">
+    <label>Téléphone</label>
+    <app-reveal [content]="organizer.phoneNumber"></app-reveal>
+  </div>
+</div>
diff --git a/src/app/visits/organizer-card/organizer-card.component.scss b/src/app/visits/organizer-card/organizer-card.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..b19b01d66736f784437c355e21d8629b4876e697
--- /dev/null
+++ b/src/app/visits/organizer-card/organizer-card.component.scss
@@ -0,0 +1,12 @@
+@import '~sass/variables';
+
+.container {
+  text-align: center;
+  padding: 1em;
+  background: white;
+  width: 8em;
+  label {
+    display: block;
+    margin: .5em 0;
+  }
+}
diff --git a/src/app/visits/organizer-card/organizer-card.component.ts b/src/app/visits/organizer-card/organizer-card.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..12d6e0213f350f7e315d03ca3f5620e0cab70fa0
--- /dev/null
+++ b/src/app/visits/organizer-card/organizer-card.component.ts
@@ -0,0 +1,13 @@
+import { Component, Input } from '@angular/core';
+import { User } from 'app/core';
+
+@Component({
+  selector: 'app-organizer-card',
+  templateUrl: './organizer-card.component.html',
+  styleUrls: ['./organizer-card.component.scss']
+})
+export class OrganizerCardComponent {
+
+  @Input() organizer: User;
+
+}
diff --git a/src/app/visits/participant-number-badge/participant-number-badge.component.html b/src/app/visits/participant-number-badge/participant-number-badge.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..d8e954991f590e482208e86767c361f6bc807afe
--- /dev/null
+++ b/src/app/visits/participant-number-badge/participant-number-badge.component.html
@@ -0,0 +1,7 @@
+<span *ngIf="number > 0" class="badge badge-default badge-lg">
+  <i class="fa fa-user"></i> {{ number }}
+  <span [ngPlural]="number">
+    <ng-template ngPluralCase="=1">participant</ng-template>
+    <ng-template ngPluralCase="other">participants</ng-template>
+  </span>
+</span>
diff --git a/src/app/visits/participant-number-badge/participant-number-badge.component.scss b/src/app/visits/participant-number-badge/participant-number-badge.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/app/visits/participant-number-badge/participant-number-badge.component.ts b/src/app/visits/participant-number-badge/participant-number-badge.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..55aa5eb0b55d301c52f1aadd3e0176fc0f28bb8c
--- /dev/null
+++ b/src/app/visits/participant-number-badge/participant-number-badge.component.ts
@@ -0,0 +1,12 @@
+import { Component, Input } from '@angular/core';
+
+@Component({
+  selector: 'app-participant-number-badge',
+  templateUrl: './participant-number-badge.component.html',
+  styleUrls: ['./participant-number-badge.component.scss']
+})
+export class ParticipantNumberBadgeComponent {
+
+  @Input() number: number;
+
+}
diff --git a/src/app/visits/participation-badge/participation-badge.component.html b/src/app/visits/participation-badge/participation-badge.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..469b3adb8c6b7195255fa0ef8e4f405d6d26c5b2
--- /dev/null
+++ b/src/app/visits/participation-badge/participation-badge.component.html
@@ -0,0 +1,14 @@
+<span [ngSwitch]="accepted">
+  <span *ngSwitchCase="true" class="badge badge-success badge-lg">
+    <i class="fa fa-ticket"></i> Tu <span [ngSwitch]="passed">
+      <span *ngSwitchCase="true">as participé</span>
+      <span *ngSwitchDefault>participes</span>
+    </span> à cette sortie.
+  </span>
+  <span *ngSwitchCase="false" class="badge badge-danger badge-lg">
+    <i class="fa fa-times"></i> Ton inscription a été rejetée.
+  </span>
+  <span *ngSwitchDefault class="badge badge-info badge-lg">
+    <i class="fa fa-info"></i> Ton inscription est en attente de validation par les organisateurs.
+  </span>
+</span>
diff --git a/src/app/visits/participation-badge/participation-badge.component.scss b/src/app/visits/participation-badge/participation-badge.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/app/visits/participation-badge/participation-badge.component.ts b/src/app/visits/participation-badge/participation-badge.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..92b7c42435f1edb250d9906ad31fd26429c8f6c8
--- /dev/null
+++ b/src/app/visits/participation-badge/participation-badge.component.ts
@@ -0,0 +1,13 @@
+import { Component, Input } from '@angular/core';
+
+@Component({
+  selector: 'app-participation-badge',
+  templateUrl: './participation-badge.component.html',
+  styleUrls: ['./participation-badge.component.scss']
+})
+export class ParticipationBadgeComponent {
+
+  @Input() accepted: boolean;
+  @Input() passed: boolean;
+
+}
diff --git a/src/app/visits/registration-badge/registration-badge.component.html b/src/app/visits/registration-badge/registration-badge.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..5ba04e9eae313ef33d49ca0340925dde165add2b
--- /dev/null
+++ b/src/app/visits/registration-badge/registration-badge.component.html
@@ -0,0 +1,11 @@
+<span *ngIf="open" class="badge badge-warning badge-lg"><i class="fa fa-clock-o"></i>
+  Inscriptions avant le {{ deadline | date:"dd/MM à HH:mm" }}
+</span>
+
+<span *ngIf="!open && !passed" class="badge badge-danger badge-lg" [ngClass]="{'tooltip bottom': !passed}">
+  <i class="fa fa-times"></i> Inscriptions fermées {{ deadline | amLocale:'fr' | amTimeAgo }}
+  <span class="tooltip-text drop-shadow-sm" *ngIf="!passed">
+    Tu peux encore tenter de t'inscrire
+    <a href="mailto:oser.sortie@gmail.com?subject=Inscription à la sortie : {{ title }}">par email</a>.
+  </span>
+</span>
diff --git a/src/app/visits/registration-badge/registration-badge.component.scss b/src/app/visits/registration-badge/registration-badge.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/app/visits/registration-badge/registration-badge.component.ts b/src/app/visits/registration-badge/registration-badge.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a547d6e9483a6a1b81603fd4f0926ad36636026f
--- /dev/null
+++ b/src/app/visits/registration-badge/registration-badge.component.ts
@@ -0,0 +1,16 @@
+import { Component, Input } from '@angular/core';
+import { Visit } from '../shared';
+
+@Component({
+  selector: 'app-registration-badge',
+  templateUrl: './registration-badge.component.html',
+  styleUrls: ['./registration-badge.component.scss']
+})
+export class RegistrationBadgeComponent {
+
+  @Input() title: string;
+  @Input() open: boolean;
+  @Input() passed: boolean;
+  @Input() deadline: Date;
+
+}
diff --git a/src/app/visits/useful-information/useful-information.component.html b/src/app/visits/useful-information/useful-information.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..cc764ffad9af9a2c0809e3b0acc75544a08a7d46
--- /dev/null
+++ b/src/app/visits/useful-information/useful-information.component.html
@@ -0,0 +1,26 @@
+<table>
+  <tr>
+    <td>Lieu</td>
+    <td>{{ visit.place.name }}</td>
+  </tr>
+  <tr>
+    <td>Adresse</td>
+    <td>{{ visit.place.address.toString() }}</td>
+  </tr>
+  <tr>
+    <td>Date</td>
+    <td>{{ visit.date | date:"fullDate" }}</td>
+  </tr>
+  <tr>
+    <td>Heure de début</td>
+    <td>{{ visit.startTime | date:"shortTime"}}</td>
+  </tr>
+  <tr>
+    <td>Heure de fin estimée</td>
+    <td>{{ visit.endTime | date:"shortTime"}}</td>
+  </tr>
+  <tr>
+    <td>Lieu de rendez-vous</td>
+    <td>{{ visit.meetingPlace }}</td>
+  </tr>
+</table>
diff --git a/src/app/visits/useful-information/useful-information.component.scss b/src/app/visits/useful-information/useful-information.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..31da90a97549013c7c0f4af8dffd6470261244ea
--- /dev/null
+++ b/src/app/visits/useful-information/useful-information.component.scss
@@ -0,0 +1,11 @@
+@import '~sass/media-queries';
+
+table {
+  width: 100%;
+  border: none;
+  border-spacing: .5em;
+
+  td:nth-child(1) {
+    font-weight: bold;
+  }
+}
diff --git a/src/app/visits/useful-information/useful-information.component.ts b/src/app/visits/useful-information/useful-information.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c291dedc75672a94dd5063396645fd557f4c45dc
--- /dev/null
+++ b/src/app/visits/useful-information/useful-information.component.ts
@@ -0,0 +1,13 @@
+import { Component, Input } from '@angular/core';
+import { Visit } from '../shared';
+
+@Component({
+  selector: 'app-useful-information',
+  templateUrl: './useful-information.component.html',
+  styleUrls: ['./useful-information.component.scss']
+})
+export class UsefulInformationComponent {
+
+  @Input() visit: Visit;
+
+}
diff --git a/src/app/visits/visit-detail/visit-detail.component.html b/src/app/visits/visit-detail/visit-detail.component.html
index 71ebe83a18180519797b0ec680c85c266a08a68b..21cfd6af38a246655d5380c541901e84b78acb70 100644
--- a/src/app/visits/visit-detail/visit-detail.component.html
+++ b/src/app/visits/visit-detail/visit-detail.component.html
@@ -15,32 +15,18 @@
 
     <!-- Metadata badges -->
     <div>
-      <span *ngIf="visit.registrationsOpen" class="badge badge-warning badge-lg"><i class="fa fa-clock-o"></i>
-        Inscriptions avant le {{ visit.deadline | date:"dd/MM à HH:mm" }}
-      </span>
-      <span *ngIf="!visit.registrationsOpen" class="badge badge-danger badge-lg" [ngClass]="{'tooltip bottom': !visit.passed}">
-        <i class="fa fa-times"></i> Inscriptions fermées <span *ngIf="!visit.passed">{{ visit.deadline | amLocale:'fr' | amTimeAgo }}</span>
-        <span class="tooltip-text drop-shadow-sm" *ngIf="!visit.passed">
-          Tu peux encore tenter de t'inscrire
-          <a href="mailto:oser.sortie@gmail.com?subject=Inscription à la sortie : {{ visit.title }}">par email</a>.
-        </span>
-      </span>
-      <span *ngIf="acceptedParticipants > 0" class="badge badge-default badge-lg">
-        <i class="fa fa-user"></i> {{ acceptedParticipants }} participants
-      </span>
+      <app-registration-badge
+        [title]="visit.title"
+        [open]="visit.registrationsOpen"
+        [passed]="visit.passed"
+        [deadline]="visit.deadline"></app-registration-badge>
+      <app-participant-number-badge
+        [number]="acceptedParticipants"></app-participant-number-badge>
+
       <span *ngIf="participant">
-        <span *ngIf="participant.accepted" class="badge badge-success badge-lg">
-          <i class="fa fa-ticket"></i> Tu <span [ngSwitch]="visit.passed">
-            <span *ngSwitchCase="true">as participé</span>
-            <span *ngSwitchDefault>participes</span>
-          </span> à cette sortie.
-        </span>
-        <span *ngIf="participant.accepted === null" class="badge badge-info badge-lg">
-          <i class="fa fa-info"></i> Ton inscription est en attente de validation par les organisateurs.
-        </span>
-        <span *ngIf="participant.accepted === false" class="badge badge-danger badge-lg">
-          <i class="fa fa-times"></i> Ton inscription a été rejetée.
-        </span>
+        <app-participation-badge
+          [accepted]="participant.accepted"
+          [passed]="visit.passed"></app-participation-badge>
       </span>
     </div>
 
@@ -52,12 +38,16 @@
     <div *ngIf="participant && !visit.passed">
 
       <!-- And a shy-ish unregister link -->
-      <p class="text-muted-sm">Tu as un empêchement et souhaites <span class="link-muted" (click)="leaveFormActive = true">te désinscrire ?</span></p>
+      <p class="text-muted-sm">
+        Tu as un empêchement et souhaites
+        <span class="link-muted" (click)="leaveFormActive = true">
+          te désinscrire ?
+        </span>
+      </p>
 
       <!-- Related documents -->
       <p class="alert alert-info" *ngIf="visit.permissionSheet">
-        {{ visit.permissionSheet }}
-        <i class="fa fa-exclamation-triangle"></i> Avant de te rendre à la sortie, télécharge <a [href]="visit.permissionSheet">l'autorisation de sortie</a>. Fais-la remplir par tes parents et remet-la aux tuteurs le jour de la sortie.
+        <i class="fa fa-exclamation-triangle"></i>Avant de te rendre à la sortie, télécharge <a [href]="visit.permissionSheet">l'autorisation de sortie</a>. Fais-la remplir par tes parents et remets-la aux tuteurs le jour de la sortie.
       </p>
       <p class="alert alert-default" *ngIf="visit.factSheet">
         <i class="fa fa-file-text"></i> Les organisateurs ont rédigé une <a [href]="visit.factSheet">fiche sortie</a>. N'hésite pas à en prendre connaissance avant de te rendre à la sortie !
@@ -78,50 +68,19 @@
   </div>
 
   <h2>Informations pratiques</h2>
-
-  <table class="tips">
-    <tr>
-      <td>Lieu</td>
-      <td>{{ visit.place.name }}</td>
-    </tr>
-    <tr>
-      <td>Adresse</td>
-      <td>{{ visit.place.address.toString() }}</td>
-    </tr>
-    <tr>
-      <td>Date</td>
-      <td>{{ visit.date | date:"fullDate" }}</td>
-    </tr>
-    <tr>
-      <td>Heure de début</td>
-      <td>{{ visit.startTime | date:"shortTime"}}</td>
-    </tr>
-    <tr>
-      <td>Heure de fin estimée</td>
-      <td>{{ visit.endTime | date:"shortTime"}}</td>
-    </tr>
-    <tr>
-      <td>Lieu de rendez-vous</td>
-      <td>{{ visit.meetingPlace }}</td>
-    </tr>
-  </table>
+  <app-useful-information [visit]="visit"></app-useful-information>
 
   <h2>Se rendre à cette sortie</h2>
-  <agm-map [latitude]="lat" [longitude]="lng" [zoom]="17">
-    <agm-marker [latitude]="lat" [longitude]="lng"></agm-marker>
-  </agm-map>
+  <app-visit-location-map
+    [geocoder]="geocoder"
+    [address]="visit.address"></app-visit-location-map>
 
   <div *ngIf="visit.organizers.length > 0">
     <h2>Tuteurs organisateurs</h2>
 
-    <ul>
-      <li *ngFor="let organizer of visit.organizers">
-        {{ organizer.user.firstName }} {{ organizer.user.lastName}}
-        <span *ngIf="organizer.user.phoneNumber">
-          (tél. : <app-reveal [content]="organizer.user.phoneNumber"></app-reveal>)
-        </span>
-      </li>
-    </ul>
+    <div class="organizers">
+      <app-organizer-card *ngFor="let organizer of visit.organizers" [organizer]="organizer.user"></app-organizer-card>
+    </div>
   </div>
 
 </div>
diff --git a/src/app/visits/visit-detail/visit-detail.component.scss b/src/app/visits/visit-detail/visit-detail.component.scss
index ec603cc2cc350dccde866ab7aac1069f5a6e8512..db849a895ace9be539f1a83784189e119de6a438 100644
--- a/src/app/visits/visit-detail/visit-detail.component.scss
+++ b/src/app/visits/visit-detail/visit-detail.component.scss
@@ -19,10 +19,6 @@
   }
 }
 
-agm-map {
-  height: 400px;
-}
-
 #participate-btn {
   margin-top: 1em;
 }
@@ -48,11 +44,10 @@ img {
   height: auto;
 }
 
-.tips {
-  width: 100%;
-  border: none;
-
-  td:nth-child(1) {
-    font-weight: bold;
+.organizers {
+  display: flex;
+  flex-flow: row wrap;
+  app-organizer-card {
+    margin: .5em;
   }
 }
diff --git a/src/app/visits/visit-detail/visit-detail.component.ts b/src/app/visits/visit-detail/visit-detail.component.ts
index 28dddeb9a8ff1b85c191ba27f8ff35a8baf7455a..fbb0f713ddb272fea684da8515c706f701fcfe9c 100644
--- a/src/app/visits/visit-detail/visit-detail.component.ts
+++ b/src/app/visits/visit-detail/visit-detail.component.ts
@@ -1,7 +1,7 @@
 import { Component, OnInit } from '@angular/core';
 import { Observable, Subject } from 'rxjs';
 import { ActivatedRoute } from '@angular/router';
-import { AuthService, GeocodingService, Location } from 'app/core';
+import { AuthService, Geocoder } from 'app/core';
 import { Visit, Participant } from '../shared';
 
 @Component({
@@ -12,38 +12,26 @@ import { Visit, Participant } from '../shared';
 export class VisitDetailComponent implements OnInit {
 
   visit: Visit;
-  lat = 50.350;
-  lng = 3.520;
   userId: number;
   participant: Participant;
   acceptedParticipants = 0;
   registerFormActive = false;
   formLoading: boolean = false;
   leaveFormActive = false;
-  private geocoder: any;
+  geocoder: Geocoder;
 
   constructor(
     private route: ActivatedRoute,
     private auth: AuthService,
-    private geocoding: GeocodingService,
   ) { }
 
   ngOnInit() {
     this.visit = this.route.snapshot.data['visit'];
     this.geocoder = this.route.snapshot.data['geocoder'];
+    console.log(this.geocoder);
     this.userId = this.auth.getUser().id;
     this.getParticipant();
     this.getAcceptedParticipants();
-    this.getVisitLocation();
-  }
-
-  getVisitLocation() {
-    this.geocoding.locate(this.geocoder, this.visit.address).subscribe(
-      location => {
-        this.lat = location.lat;
-        this.lng = location.lng;
-      }
-    );
   }
 
   getParticipant() {
diff --git a/src/app/visits/visit-location-map/visit-location-map.component.html b/src/app/visits/visit-location-map/visit-location-map.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..1181c5cbaff3cd2be4138c067725f400cea5ecf9
--- /dev/null
+++ b/src/app/visits/visit-location-map/visit-location-map.component.html
@@ -0,0 +1,3 @@
+<agm-map [latitude]="lat" [longitude]="lng" [zoom]="17">
+  <agm-marker [latitude]="lat" [longitude]="lng"></agm-marker>
+</agm-map>
diff --git a/src/app/visits/visit-location-map/visit-location-map.component.scss b/src/app/visits/visit-location-map/visit-location-map.component.scss
new file mode 100644
index 0000000000000000000000000000000000000000..e9d4133784d1d279a2c79fb0402eca8632b6d5b5
--- /dev/null
+++ b/src/app/visits/visit-location-map/visit-location-map.component.scss
@@ -0,0 +1,3 @@
+agm-map {
+  height: 400px;
+}
diff --git a/src/app/visits/visit-location-map/visit-location-map.component.ts b/src/app/visits/visit-location-map/visit-location-map.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fd360cc003186580d1a925af00446afa6c409115
--- /dev/null
+++ b/src/app/visits/visit-location-map/visit-location-map.component.ts
@@ -0,0 +1,35 @@
+import { Component, OnInit, Input } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
+import { GeocodingService, Geocoder } from 'app/core';
+
+@Component({
+  selector: 'app-visit-location-map',
+  templateUrl: './visit-location-map.component.html',
+  styleUrls: ['./visit-location-map.component.scss']
+})
+export class VisitLocationMapComponent implements OnInit {
+
+  @Input() address: string;
+  @Input() geocoder: Geocoder;
+  lat = 50;
+  lng = 3;
+
+  constructor(
+    private geocoding: GeocodingService,
+    private route: ActivatedRoute,
+  ) { }
+
+  ngOnInit() {
+    this.getVisitLocation();
+  }
+
+  getVisitLocation() {
+    this.geocoding.locate(this.geocoder, this.address).subscribe(
+      location => {
+        this.lat = location.lat;
+        this.lng = location.lng;
+      }
+    );
+  }
+
+}
diff --git a/src/app/visits/visits.component.ts b/src/app/visits/visits.component.ts
index 3b9e3e766c48c847f6e18cd46d0ccaccf78051f9..8373df36644ce3ed58cdbe4c14bf061605a31d3b 100644
--- a/src/app/visits/visits.component.ts
+++ b/src/app/visits/visits.component.ts
@@ -1,7 +1,7 @@
 import { Component, OnInit } from '@angular/core';
 import { Router } from '@angular/router';
 import { AuthService } from 'app/core';
-import { Link } from 'app/ui';
+import { Link } from 'app/shared';
 
 @Component({
   selector: 'app-visits',
diff --git a/src/app/visits/visits.module.ts b/src/app/visits/visits.module.ts
index b0c69a71e4db2efaec2ca5cbf84798d571d280b8..02a7b7c034b2d292dd67c9042ae33a1786422c89 100644
--- a/src/app/visits/visits.module.ts
+++ b/src/app/visits/visits.module.ts
@@ -5,7 +5,7 @@ import { CommonModule } from '@angular/common';
 import { FormsModule } from '@angular/forms';
 import { RouterModule } from '@angular/router';
 import { CoreModule } from '../core';
-import { UiModule } from '../ui';
+import { SharedModule } from '../shared';
 import { AgmCoreModule } from '@agm/core';
 import { MomentModule } from 'ngx-moment';
 
@@ -23,6 +23,12 @@ import { RegisterFormComponent } from './register-form/register-form.component';
 
 // Resolvers
 import { VisitsResolver, VisitResolver } from './shared';
+import { RegistrationBadgeComponent } from './registration-badge/registration-badge.component';
+import { ParticipantNumberBadgeComponent } from './participant-number-badge/participant-number-badge.component';
+import { ParticipationBadgeComponent } from './participation-badge/participation-badge.component';
+import { UsefulInformationComponent } from './useful-information/useful-information.component';
+import { VisitLocationMapComponent } from './visit-location-map/visit-location-map.component';
+import { OrganizerCardComponent } from './organizer-card/organizer-card.component';
 
 @NgModule({
   imports: [
@@ -31,7 +37,7 @@ import { VisitsResolver, VisitResolver } from './shared';
     MomentModule,
     CoreModule,
     RouterModule,
-    UiModule,
+    SharedModule,
     AgmCoreModule.forRoot({
       apiKey: 'AIzaSyDXPxwZpx9EiwarLAZ3yzUANK9D4q0X9cI',
     }),
@@ -44,6 +50,12 @@ import { VisitsResolver, VisitResolver } from './shared';
     VisitDetailComponent,
     LeaveFormComponent,
     RegisterFormComponent,
+    RegistrationBadgeComponent,
+    ParticipantNumberBadgeComponent,
+    ParticipationBadgeComponent,
+    UsefulInformationComponent,
+    VisitLocationMapComponent,
+    OrganizerCardComponent,
   ],
   providers: [
     VisitService,