diff --git a/.gitignore b/.gitignore index 86d943a9b2e8f3bb69fbe37fd8363962646b1d92..b1b6bcc815c1b0c4b26e93c5c5dfd67f44fa1505 100644 --- a/.gitignore +++ b/.gitignore @@ -44,3 +44,6 @@ testem.log # System Files .DS_Store Thumbs.db + +# apiMock +api/db.json diff --git a/package-lock.json b/package-lock.json index b09f84a5aa6a646b8c9638db21f9a1b951f914a0..da8384e00f03050052857af50dc2296371b85d68 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8942,6 +8942,11 @@ "yallist": "^4.0.0" } }, + "luxon": { + "version": "1.25.0", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.25.0.tgz", + "integrity": "sha512-hEgLurSH8kQRjY6i4YLey+mcKVAWXbDNlZRmM6AgWDJ1cY3atl8Ztf5wEY7VBReFbmGnwQPz7KYJblL8B2k0jQ==" + }, "magic-string": { "version": "0.25.7", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", diff --git a/package.json b/package.json index 97ef23241ba615626898db7c843b1122f14ccdd0..fe8dccab6d06468a17a239d7892aa77da817a0ba 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "@angular/platform-browser-dynamic": "~10.1.3", "@angular/router": "~10.1.3", "json-server": "^0.16.2", + "luxon": "^1.25.0", "rxjs": "~6.6.0", "tslib": "^2.0.0", "zone.js": "~0.10.2" diff --git a/src/app/structure/components/card/card.component.html b/src/app/structure/components/card/card.component.html index db49c0aef9c91985ef57855e2072f0238c4d4b28..e2443b8c8794dd8d1998a26b13661ad8eb4ef049 100644 --- a/src/app/structure/components/card/card.component.html +++ b/src/app/structure/components/card/card.component.html @@ -1,17 +1,25 @@ -<span class="divider"></span> -<span class="nbStructuresLabel">140 structures</span> +<span class="nbStructuresLabel">{{ structures.length }} structures</span> +<div class="structure" fxLayout="column" *ngFor="let structure of structures"> + <span class="nomStructure">{{ structure.nom }}</span> -<div class="structure"> - <span class="typeStructure">Bibliothèque</span> <div class="headerStructure" fxLayout="row" fxLayoutAlign="space-between center"> - <span class="nomStructure">Nom de la structure</span> - <div class="distanceStructure"> - <span>|-----| 63 m</span> - </div> + <span class="typeStructure">{{ structure.type_de_structure }}</span> + <span class="distanceStructure">|-| 63 m</span> </div> <br /> <div class="statusStructure" fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="1vw"> - <span class="dot"></span> - <span>Ouvert actuellement</span> + <div *ngIf="structure.estOuvert; else closed"> + <span class="ico-dot-available"></span> + <span> Ouvert actuellement</span> + </div> + <ng-template #closed> + <span class="ico-dot-unavailable"></span> + <span *ngIf="structure.ouvreLe.jour; else noTime"> + Fermé - Ouvre {{ structure.ouvreLe.jour }} à {{ structure.ouvreLe.horaire }}</span + > + </ng-template> </div> </div> +<ng-template #noTime> + <span> Fermé - Aucun horaire disponible</span> +</ng-template> diff --git a/src/app/structure/components/card/card.component.scss b/src/app/structure/components/card/card.component.scss index 18648a32900fd086ae8747997bbfbe2c72851a2c..f3f3748014fad362523696315a02fe31a89967e8 100644 --- a/src/app/structure/components/card/card.component.scss +++ b/src/app/structure/components/card/card.component.scss @@ -1,22 +1,52 @@ +@import '../../../../assets/scss/icons'; .nbStructuresLabel { color: #828282; - padding: 10px; - font-size: 14px; + font-family: Trebuchet MS; + font-style: normal; + font-weight: normal; + font-size: 16px; + line-height: 19px; + display: flex; + align-items: center; } .structure { padding: 12px 0 12px 0; border-bottom: 1px dashed #bdbdbd; .typeStructure { color: #828282; + font-family: Times New Roman; + font-style: normal; + font-weight: normal; + font-size: 16px; + line-height: 100%; } - .headerStructure { - .nomStructure { - font-weight: bold; - color: #594d59; - font-size: 22px; - } + .nomStructure { + padding-top: 13px; + color: #594d59; + font-family: Trebuchet MS; + font-style: normal; + font-weight: bold; + font-size: 20px; + line-height: 103%; + padding-bottom: 5px; + } + .distanceStructure { + font-family: Times New Roman; + font-style: normal; + font-size: 16px; + line-height: 103%; + color: #594d59; } &:last-child { border-bottom: none; } } +.statusStructure { + span { + font-family: Trebuchet MS; + font-style: normal; + font-weight: normal; + font-size: 15px; + line-height: 103%; + } +} diff --git a/src/app/structure/components/card/card.component.ts b/src/app/structure/components/card/card.component.ts index 57820f6a3ed81c69f5d360f0ee9e73b18bd56de1..093bdde339cdc9acbfc16cb69da6225e751da7db 100644 --- a/src/app/structure/components/card/card.component.ts +++ b/src/app/structure/components/card/card.component.ts @@ -1,5 +1,6 @@ import { Component, OnInit } from '@angular/core'; import { Structure } from '../../models/structure.model'; +import { StructureService } from '../../services/structure.service'; @Component({ selector: 'app-card', @@ -7,14 +8,14 @@ import { Structure } from '../../models/structure.model'; styleUrls: ['./card.component.scss'], }) export class CardComponent implements OnInit { - structure: Structure[] = []; - servicesProposes: any = [ - { val: 'CAF', text: 'Droits à la CAF' }, - { val: 'Pôle Emploi', text: 'Droits à Pôle Emploi' }, - { val: 'Impôts', text: 'Droits aux Impots' }, - { val: 'CPAM', text: 'Droits à la CPAM (AMELI)' }, - ]; - constructor() {} + structures: Structure[] = []; + constructor(private _structureService: StructureService) {} - ngOnInit(): void {} + ngOnInit(): void { + this._structureService.recupererStructures().subscribe((structures: Structure[]) => { + structures.forEach((s: Structure) => { + this.structures.push(this._structureService.majOuvertureStructure(s)); + }); + }); + } } diff --git a/src/app/structure/models/structure.model.ts b/src/app/structure/models/structure.model.ts index bf0a5b70a9268aa57bab67bc42df06be542710dd..d64b5b3adc7a456a0b81ab1ccedb727c49ed451c 100644 --- a/src/app/structure/models/structure.model.ts +++ b/src/app/structure/models/structure.model.ts @@ -1,13 +1,13 @@ export class Structure { - id: string; - created_on: string; - last_modif: string; - owner: string; - status: string; - nom: string; - type_structure: string; + numero: string; + date_de_creation: string; + derniere_modification: string; + nom_de_lusager: string; + votre_structure_est_elle: string; + nom_de_votre_structure: string; + type_de_structure: string; description: string; - num: string; + n: string; voie: string; telephone: string; courriel: string; @@ -15,13 +15,30 @@ export class Structure { facebook: string; twitter: string; instagram: string; - civilite_contact: string; - nom_contact: string; - prenom_contact: string; + civilite: string; + nom: string; + prenom: string; email_contact: string; - fonction_contact: string; - pmr: boolean; - je_fais_a_la_place_de_lusager: boolean; - accompagnement_aux_demarches: string[]; + fonction: string; + accessibilite_personnes_a_mobilite_reduite_pmr: boolean; + jaccompagne_les_usagers_dans_leurs_demarches_en_ligne: boolean; + accompagnement_des_demarches: string[]; wifi: boolean; + horaires: horaireStructure; + estOuvert: boolean; + ouvreLe: { jour: string; horaire: string }; +} + +export class horaireStructure { + lundi: Jour; + mardi: Jour; + mercredi: Jour; + jeudi: Jour; + vendredi: Jour; + samedi: Jour; + dimanche: Jour; +} +export class Jour { + open: boolean; + time: [{ openning: number; closing: number }]; } diff --git a/src/app/structure/services/structure.service.ts b/src/app/structure/services/structure.service.ts index 8a09d6adbdfb3567211e8223e541f32837311e69..a72138d7e776ae3a813e7e55f9a0955993e9ac3d 100644 --- a/src/app/structure/services/structure.service.ts +++ b/src/app/structure/services/structure.service.ts @@ -1,9 +1,144 @@ +import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; +import { Jour, Structure } from '../models/structure.model'; +const { DateTime } = require('luxon'); @Injectable({ - providedIn: 'root' + providedIn: 'root', }) export class StructureService { + constructor(private http: HttpClient) {} - constructor() { } + recupererStructures() { + return this.http.get('/api/Structures'); + } + + majOuvertureStructure(structure: Structure) { + //Récupère le jour de la semaine. + var dt = DateTime.local(); + var jourSemaine: number = dt.weekday; + + //Vérifie si les minutes commencent par zéro pour éviter la suppression. + var now: number; + if (dt.minute.toString().length != 1) { + now = parseInt('' + dt.hour + dt.minute, 10); + } else { + now = parseInt('' + dt.hour + 0 + dt.minute, 10); + } + + //Récupérer les horaires d'une structure en fonction de son jour pour indiquer si elle est ouverte. + var horaireStructure: Jour = this.recupererHoraire(structure, jourSemaine); + structure.estOuvert = false; + if (horaireStructure.open) { + horaireStructure.time.forEach((periode) => { + if (this.comparerHoraire(periode.openning, periode.closing, now)) { + structure.estOuvert = true; + } + }); + } + structure.ouvreLe = this.recupererProchaineOuverture(structure, jourSemaine, jourSemaine, now); + + return structure; + } + + //Récupère les horaires d'une structure en fonction du jour de la semaine + recupererHoraire(structure: Structure, jourActuel: number) { + switch (jourActuel) { + case 1: + return structure.horaires.lundi; + case 2: + return structure.horaires.mardi; + case 3: + return structure.horaires.mercredi; + case 4: + return structure.horaires.jeudi; + case 5: + return structure.horaires.vendredi; + case 6: + return structure.horaires.samedi; + case 7: + return structure.horaires.dimanche; + } + } + //Vérifie si l'heure actuelle est dans l'interval des horaires de la structure + comparerHoraire(heureDeb: number, heureFin: number, heureActuelle: number) { + return heureActuelle >= heureDeb && heureActuelle <= heureFin; + } + + recupererProchaineOuverture(s: Structure, j: number, baseJour: number, baseHeure: number) { + //Récupérer horaire du jour en cours + var horaires = this.recupererHoraire(s, j); + //Condition pour stopper la récursion (Si le jour du compteur est égal au jour en cours) + if (j + 1 != baseJour) { + if (horaires.open) { + //Vérifie si le compteur correspond au jour en cours pour éviter de proposer + //les horaires déjà passés. + if (j != baseJour) { + var jourOuverture = null; + horaires.time.every((periode) => { + if (periode.openning) { + jourOuverture = { jour: this.numberToDay(j), horaire: this.numberToHour(periode.openning) }; + return false; + } + return true; + }); + //Si pas de période trouvée, on réitère. + if (!jourOuverture) { + return this.recupererProchaineOuverture(s, j + 1, baseJour, baseHeure); + } + return jourOuverture; + } else { + var jourOuverture = null; + horaires.time.every((periode) => { + if (periode.openning >= baseHeure) { + jourOuverture = { jour: ' ', horaire: this.numberToHour(periode.openning) }; + return false; + } + return true; + }); + //Si pas de période trouvée, on réitère. + if (!jourOuverture) { + return this.recupererProchaineOuverture(s, j + 1, baseJour, baseHeure); + } + return jourOuverture; + } + } else { + //Si le jour est égal à Dimanche, on le positionne sur Lundi. + if (j != 7) { + return this.recupererProchaineOuverture(s, j + 1, baseJour, baseHeure); + } + return this.recupererProchaineOuverture(s, 1, baseJour, baseHeure); + } + } + return 'Aucun horaire disponible'; + } + + numberToDay(n: number) { + switch (n) { + case 1: + return 'lundi'; + case 2: + return 'mardi'; + case 3: + return 'mercredi'; + case 4: + return 'jeudi'; + case 5: + return 'vendredi'; + case 6: + return 'samedi'; + case 7: + return 'dimanche'; + } + } + + numberToHour(n: number) { + if (n.toString().length == 3) { + var tabNum = n.toString().match(/.{1,1}/g); + return tabNum[0] + 'h' + tabNum[1] + tabNum[2]; + } else if (n.toString().length == 4) { + var tabNum = n.toString().match(/.{1,2}/g); + return tabNum[0] + 'h' + tabNum[1]; + } + } } diff --git a/src/app/structure/structure.module.ts b/src/app/structure/structure.module.ts index 027e623017631d7e4f98c374323364cf5c541cd9..335604aefd4c2a8673c6a9058d4ea5c9906eabc9 100644 --- a/src/app/structure/structure.module.ts +++ b/src/app/structure/structure.module.ts @@ -4,10 +4,11 @@ import { StructureComponent } from './structure.component'; import { CardComponent } from './components/card/card.component'; import { RechercheComponent } from './components/recherche/recherche.component'; import { HttpClientModule } from '@angular/common/http'; +import { FlexLayoutModule } from '@angular/flex-layout'; @NgModule({ declarations: [StructureComponent, CardComponent, RechercheComponent], - imports: [CommonModule, HttpClientModule], + imports: [CommonModule, HttpClientModule, FlexLayoutModule], exports: [StructureComponent], }) export class StructureModule {} diff --git a/src/assets/scss/_icons.scss b/src/assets/scss/_icons.scss index b1dcb9ac71b2a68e6b57b51cffeb4c8bce009c9d..a44fae8f271cda12de030929b3e484a15b984426 100644 --- a/src/assets/scss/_icons.scss +++ b/src/assets/scss/_icons.scss @@ -64,3 +64,17 @@ background: $orange; } } +.ico-dot-available { + height: 12px; + width: 12px; + background-color: #41c29c; + border-radius: 50%; + display: inline-block; +} +.ico-dot-unavailable { + height: 12px; + width: 12px; + background-color: #b7b7b7; + border-radius: 50%; + display: inline-block; +}