Added API .env and removed "Menu" from navbar

This commit is contained in:
Alexis
2023-04-28 17:27:16 +02:00
parent 9905dc6d8c
commit 8573fe0549
9 changed files with 264 additions and 31 deletions

1
.env.development Normal file
View File

@@ -0,0 +1 @@
VITE_API_URL = "http://localhost:3000"

1
.env.production Normal file
View File

@@ -0,0 +1 @@
VITE_API_URL = "https://api-deputes.alexcreates.fr"

View File

@@ -5,7 +5,7 @@ import Navbar from "./components/navbar/Navbar.vue";
<template> <template>
<div id="wrapper"> <div id="wrapper">
<Navbar /> <Navbar />
<div id="content"> <div class="flex justify-center items-center">
<RouterView /> <RouterView />
</div> </div>
</div> </div>

View File

@@ -0,0 +1,21 @@
<script lang="ts" setup>
import { useRepStore } from "@/stores/repStore";
import { useGeolocation } from "@vueuse/core";
const { coords } = useGeolocation();
const { getRep, setRep } = useRepStore();
async function handleGeolocClick() {
const rep = await getRep(coords.value.longitude, coords.value.latitude);
setRep(rep);
}
</script>
<template>
<button
class="py-2 px-4 rounded-sm bg-white text-sm text-slate-950"
@click="handleGeolocClick"
>
Trouver mon député
</button>
</template>

View File

@@ -0,0 +1,45 @@
<script lang="ts" setup>
import type { Depute } from "@/models/rep";
import { computed } from "vue";
const props = defineProps<{
rep: Depute;
}>();
const repImage = computed(() => {
const imageRef = props.rep.acteur.uid["#text"].replace("PA", "");
return `https://www2.assemblee-nationale.fr/static/tribun/16/photos/carre/${imageRef}.jpg`;
});
const repFullName = computed(
() =>
`${props.rep.acteur.etatCivil.ident.prenom} ${props.rep.acteur.etatCivil.ident.nom}`
);
const repMandate = computed(() => {
const parliamentMandate = props.rep.acteur.mandats.mandat.find(
(mandate) => mandate["@xsi:type"] === "MandatParlementaire_type"
);
return parliamentMandate;
});
</script>
<template>
<article>
<figure class="mb-8 mx-auto w-60 h-60 rounded-full overflow-hidden">
<img
:src="repImage"
:alt="repFullName"
class="w-full h-full object-contain"
/>
</figure>
<h1 class="mb-4 text-center font-bold text-3xl">
{{ repFullName }}
</h1>
<h2 class="text-center font-bold text-xl">
{{ repMandate?.election?.lieu.departement }} -
{{ repMandate?.election?.lieu.numCirco }}e circonscription
</h2>
</article>
</template>

View File

@@ -1,5 +1,5 @@
<template> <template>
<nav class="bg-slate-900"> <nav class="bg-slate-900">
<div class="container py-4">Menu</div> <div class="container py-4">Mon Député</div>
</nav> </nav>
</template> </template>

146
src/models/rep.ts Normal file
View File

@@ -0,0 +1,146 @@
export interface Depute {
acteur: Acteur;
}
export interface Acteur {
"@xmlns:xsi": string;
uid: Uid;
etatCivil: EtatCivil;
profession: Profession;
uri_hatvp: string;
adresses: Adresses;
mandats: Mandats;
}
export interface Adresses {
adresse: { [key: string]: null | string }[];
}
export interface EtatCivil {
ident: Ident;
infoNaissance: InfoNaissance;
dateDeces: null;
}
export interface Ident {
civ: string;
prenom: string;
nom: string;
alpha: string;
trigramme: string;
}
export interface InfoNaissance {
dateNais: Date;
villeNais: string;
depNais: string;
paysNais: string;
}
export interface Mandats {
mandat: Mandat[];
}
export interface Mandat {
"@xsi:type": XsiType;
uid: string;
acteurRef: Text;
legislature: null | string;
typeOrgane: string;
dateDebut: Date;
datePublication: Date | null;
dateFin: Date | null;
preseance: string;
nominPrincipale: string;
infosQualite: InfosQualite;
organes: Organes;
suppleants?: Suppleants | null;
libelle?: null;
missionSuivanteRef?: null;
missionPrecedenteRef?: null;
chambre?: null;
election?: Election;
mandature?: Mandature;
collaborateurs?: Collaborateurs;
}
export enum XsiType {
MandatAvecSuppleantType = "MandatAvecSuppleant_Type",
MandatMissionType = "MandatMission_Type",
MandatParlementaireType = "MandatParlementaire_type",
MandatSimpleType = "MandatSimple_Type",
}
export enum Text {
Pa794094 = "PA794094",
}
export interface Collaborateurs {
collaborateur: Collaborateur[];
}
export interface Collaborateur {
qualite: string;
prenom: string;
nom: string;
dateDebut: null;
dateFin: null;
}
export interface Election {
lieu: Lieu;
causeMandat: string;
refCirconscription: string;
}
export interface Lieu {
region: string;
regionType: string;
departement: string;
numDepartement: string;
numCirco: string;
}
export interface InfosQualite {
codeQualite: string;
libQualite: string;
libQualiteSex: string;
}
export interface Mandature {
datePriseFonction: Date;
causeFin: null;
premiereElection: string;
placeHemicycle: string;
matriculeVote: string;
mandatRemplaceRef: null;
}
export interface Organes {
organeRef: string;
}
export interface Suppleants {
suppleant: Suppleant;
}
export interface Suppleant {
dateDebut: Date;
dateFin: null;
suppleantRef: string;
}
export interface Profession {
libelleCourant: string;
socProcINSEE: SocProcINSEE;
}
export interface SocProcINSEE {
catSocPro: string;
famSocPro: string;
}
export interface Uid {
"@xsi:type": string;
"#text": Text;
}

View File

@@ -1,11 +1,21 @@
import type { Depute } from "@/models/rep";
import { defineStore } from "pinia"; import { defineStore } from "pinia";
import { ref } from "vue";
export const useCirStore = defineStore("repStore", () => { const apiUrl = import.meta.env.VITE_API_URL;
async function getRep(lon: number, lat: number): Promise<any> {
return fetch(`http://localhost:3000/rep?lat=${lat}&lon=${lon}`).then((t) => export const useRepStore = defineStore("repStore", () => {
t.json() const currentRep = ref<Depute | null>(null);
);
async function getRep(lon: number, lat: number): Promise<Depute> {
return fetch(`${apiUrl}/rep?lat=${lat}&lon=${lon}`)
.then((t) => t.json())
.catch((err) => console.log(err));
} }
return { getRep }; function setRep(rep: Depute) {
currentRep.value = rep;
}
return { getRep, setRep, currentRep };
}); });

View File

@@ -1,33 +1,42 @@
<script lang="ts" setup> <script lang="ts" setup>
import { useCirStore } from "@/stores/repStore"; import GeolocRequest from "@/components/GeolocRequest.vue";
import { useGeolocation } from "@vueuse/core"; import RepInfo from "@/components/RepInfo.vue";
import { ref } from "vue"; import { useRepStore } from "@/stores/repStore";
import { storeToRefs } from "pinia";
const { coords } = useGeolocation(); const { currentRep } = storeToRefs(useRepStore());
const { getRep } = useCirStore();
const currentRepValue = ref<any>();
async function handleGeolocClick() {
currentRepValue.value = await getRep(
coords.value.longitude,
coords.value.latitude
);
}
</script> </script>
<template> <template>
<div> <div>
<main class="container py-4"> <main class="container py-4">
<button <Transition name="fade" mode="out-in">
class="py-2 px-4 rounded-sm bg-white text-sm text-slate-950" <GeolocRequest v-if="!currentRep" />
@click="handleGeolocClick" <Suspense v-else>
> <RepInfo :rep="currentRep" />
Trouver mon député </Suspense>
</button> </Transition>
<pre>
{{ currentRepValue }}
</pre>
</main> </main>
</div> </div>
</template> </template>
<style scoped>
.fade-enter-from {
opacity: 0;
}
.fade-enter-to {
opacity: 1;
}
.fade-enter-active {
transition: all 0.3s ease;
}
.fade-leave-from {
opacity: 1;
}
.fade-leave-to {
opacity: 0;
}
.fade-leave-active {
transition: all 0.3s ease;
}
</style>