This commit is contained in:
Jonathan Chevalier
2022-09-27 17:47:09 +02:00
parent 3f9ddcac6d
commit c0ef555cea
9 changed files with 260 additions and 84 deletions

11
package-lock.json generated
View File

@@ -11,6 +11,7 @@
"@fortawesome/fontawesome-free": "^6.2.0",
"@vuepic/vue-datepicker": "^3.4.8",
"date-fns": "^2.29.3",
"lodash": "^4.17.21",
"pinia": "^2.0.22",
"vue": "^3.2.37",
"vue-router": "^4.1.5"
@@ -1076,6 +1077,11 @@
"node": ">=10"
}
},
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"node_modules/magic-string": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz",
@@ -2349,6 +2355,11 @@
"integrity": "sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==",
"dev": true
},
"lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"magic-string": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz",

View File

@@ -12,6 +12,7 @@
"@fortawesome/fontawesome-free": "^6.2.0",
"@vuepic/vue-datepicker": "^3.4.8",
"date-fns": "^2.29.3",
"lodash": "^4.17.21",
"pinia": "^2.0.22",
"vue": "^3.2.37",
"vue-router": "^4.1.5"

View File

@@ -1,9 +1,19 @@
import {defineStore} from 'pinia'
export const useMMCMStore = defineStore('counter', {
state: () => ({street: '', zipCode: '', city: '', productList: [], withPrescription: null, idProduct: null, dateDelivery:null}),
state: () => ({
street: '',
zipCode: '',
city: '',
productList: [],
withPrescription: null,
idProduct: null,
dateDelivery: null
}),
getters: {
fullAddress: (state) => state.street + ' ' + state.zipCode + '' + state.city,
deliveryMethod: (state) => state.productList.filter(p => p.id === state.idProduct)[0].name,
dateDeliveryString: (state) => new Date(state.dateDelivery).toLocaleDateString("fr-FR")
},
actions: {
setStreet(street) {

View File

@@ -1,11 +1,18 @@
<template>
<h1 class="product_name_area primary_color">Indiquez votre adresse de livraison (domicile, travail...) :</h1>
<div class="input-group mb-3">
<div class="input-group-text">
<i v-if="isSearching" class="fa-solid fa-circle-notch fa-spin fa-fw color-success"></i>
<i v-else class="fa-regular fa-location-dot fa-fw color-success"></i>
</div>
<input type="text" placeholder="Exemple : 2 rue de la Libération 78120 Rambouillet" class="form-control"
v-model="query"
@input="updateSearchResult" aria-describedby="button-addon">
<button class="btn btn-outline-secondary" type="button" id="button-addon" @click="checkIdAddressIsEligible">
<button class="btn btn-primary" type="button" id="button-addon" @click="checkIdAddressIsEligible">
<i v-if="isChecking" class="fa-solid fa-circle-notch fa-spin fa-fw"></i>
<i v-else class="fa-regular fa-circle-check fa-fw"></i>
Valider
</button>
</div>
@@ -19,14 +26,12 @@
<script>
import {useMMCMStore} from '../stores/mmcm.js'
import {storeToRefs} from 'pinia'
export default {
setup() {
const store = useMMCMStore()
return {
// you can return the whole store instance to use it in the template
store,
}
},
@@ -34,17 +39,21 @@ export default {
data() {
return {
query: "",
searchResults: []
searchResults: [],
isSearching: false,
isChecking: false,
}
},
methods: {
updateSearchResult: async function () {
this.isSearching = true
this.searchResults = await fetch('https://api-adresse.data.gouv.fr/search/?q=' + this.query)
.then(function (response) {
return response.json();
}).then(function (jsonObj) {
this.isSearching = false
return jsonObj.features;
});
}.bind(this));
},
selectChoice(item) {
this.searchResults = []
@@ -53,8 +62,10 @@ export default {
this.store.setZipCode(item.properties.postcode)
this.store.setCity(item.properties.city)
},
checkIdAddressIsEligible: async function () {
this.isChecking = true
const urlApi = '/php/api/v3/mmcm.php?EXEC=getEligibility&street=' + encodeURI(this.store.street)
+ '&zip_code=' + this.store.zipCode
@@ -68,9 +79,8 @@ export default {
}
})
console.log(productList);
this.store.setProductList(productList);
this.isChecking = false
this.$router.push({path: '/delivery-option-step-1'});
}
}

View File

@@ -1,9 +1,7 @@
<template>
<!--
<div class="form-register">
<div class="steps clearfix"><ul role="tablist"><li role="tab" aria-disabled="false" class="first current" aria-selected="true"><a id="form-total-t-0" href="#form-total-h-0" aria-controls="form-total-p-0"><span class="current-info audible"> </span><div class="title">
<span class="step-icon"> <i class="fa-solid fa-user"></i> </span>
<span class="step-text">Ordonnance</span>
@@ -18,34 +16,46 @@
<span class="step-text">Confirmation</span>
</div></a></li></ul></div>
</div>
-->
<div class="card">
<div class="card-header">Avec ou sans ordonnance ?</div>
<div class="card-body row">
<div class="card-header"><h2>Avec ou sans ordonnance ?</h2></div>
<div class="card-body">
<div class="row text-start">
<div class="col-lg-6">
Avec ordonnance (mon pharmacien n'a pas mon ordonnance) :<br/>
<ul>
<li>1 -Le livreur vient chercher loriginal de mon ordonnance, carte vitale et carte mutuelle (si jen ai
<h4>Avec ordonnance (mon pharmacien n'a pas mon ordonnance) :</h4>
<ol>
<li>Le livreur vient chercher loriginal de mon ordonnance, carte vitale et carte mutuelle (si jen ai
une) dans une enveloppe fermée.
</li>
<li>2 - Le livreur apportera lenveloppe fermée contenant mes documents de santé directement à mon
<li>Le livreur apportera lenveloppe fermée contenant mes documents de santé directement à mon
pharmacien.
</li>
<li>3 - Mon pharmacien remet mes médicaments et mes documents au livreur.</li>
<li> 4 - Le livreur me livre à mon adresse mes médicaments et mes documents originaux.</li>
</ul>
<li>Mon pharmacien remet mes médicaments et mes documents au livreur.</li>
<li>Le livreur me livre à mon adresse mes médicaments et mes documents originaux.</li>
</ol>
<button class="btn btn-primary" @click="goNextStep(true)">Choisir</button>
</div>
<div class="col-lg-6">
Sans ordonnance (mon pharmacien a déjà mon ordonnance) :<br/>
<ul>
<h4>Sans ordonnance (mon pharmacien a déjà mon ordonnance) :</h4>
<ol>
<li>Le livreur se rend chez mon pharmacien pour la collecte de mes médicaments.</li>
<li>Le livreur me livre à ladresse renseignée.</li>
</ul>
<button class="btn btn-primary" @click="goNextStep(false)">Choisir</button>
</ol>
</div>
</div>
<div class="row text-center">
<div class="col-lg-6">
<button class="btn btn-primary" @click="goNextStep(true)"><i class="fa-regular fa-circle-check fa-fw"></i>
Choisir
</button>
</div>
<div class="col-lg-6">
<button class="btn btn-primary" @click="goNextStep(false)"><i class="fa-regular fa-circle-check fa-fw"></i>Choisir
</button>
</div>
</div>
</div>
</div>
@@ -76,7 +86,7 @@ export default {
<style scoped>
.form-register{
.form-register {
width: 100%;
display: flex;
@@ -85,12 +95,14 @@ export default {
.form-register .steps {
margin-bottom: 33px;
}
.form-register .steps ul {
display: flex;
list-style: none;
padding-left: 108px;
text-align: left;
}
.form-register .steps li,
.form-register .steps li.current {
outline: none;
@@ -100,9 +112,11 @@ export default {
-webkit-outline: none;
position: relative;
}
.form-register .steps li .current-info {
display: none;
}
.form-register .steps li a {
text-decoration: none;
outline: none;
@@ -111,9 +125,11 @@ export default {
-moz-outline: none;
-webkit-outline: none;
}
.form-register .steps li a .title span {
display: block;
}
.form-register .steps li a .title .step-icon {
width: 60px;
height: 60px;
@@ -134,6 +150,7 @@ export default {
font-size: 25.6px;
margin-right: 108px;
}
.form-register .steps li a .step-icon i {
position: absolute;
top: 50%;
@@ -144,6 +161,7 @@ export default {
-moz-transform: translate(-50%, -50%);
-webkit-transform: translate(-50%, -50%);
}
.form-register .steps li .step-icon::before,
.form-register .steps li:last-child .step-icon::after {
position: absolute;
@@ -158,9 +176,11 @@ export default {
-moz-transform: translateY(-50%);
-webkit-transform: translateY(-50%);
}
.form-register .steps li .step-icon::before {
right: 100%;
}
.form-register .steps li:last-child .step-icon::after {
left: 100%;
}
@@ -171,17 +191,20 @@ export default {
.form-register .steps li.done a:active .step-icon {
background: #24c1e8;
}
.form-register .steps .current .step-icon::before,
.form-register .steps .current:last-child .step-icon::after,
.form-register .steps .done .step-icon::before {
background: #24c1e8;
}
.form-register .steps li a .step-text {
color: #999;
font-weight: 400;
font-size: 18px;
padding: 14px 0 8px;
}
.form-register .steps .current .step-text,
.form-register .steps .done .step-text {
color: #333;
@@ -190,6 +213,7 @@ export default {
.form-register .content h2 {
display: none;
}
.form-register .content .inner h3 {
font-size: 22px;
color: #333;
@@ -198,44 +222,54 @@ export default {
padding-bottom: 18px;
padding-top: 5px;
}
.form-register .content .form-total-p-1 .inner h3 {
padding-bottom: 13px;
padding-top: 0;
}
.form-register .content #form-total-p-3 .inner h3 {
padding-bottom: 5px;
}
.form-register .content .inner h4 {
font-size: 18px;
font-weight: 700;
color: #333;
margin: 0;
}
.inner .form-row {
display: flex;
margin: 0 -12px;
position: relative;
}
.form-row.form-row-date.form-row-date-1 {
margin-top: 50px;
margin-bottom: -18px;
}
.inner .form-row .form-holder {
width: 50%;
padding: 0 12px;
margin-bottom: 15px;
position: relative;
}
.inner .form-row .form-holder.form-holder-1 {
width: 84.1%;
}
.inner .form-row .form-holder.form-holder-2 {
width: 100%;
position: relative;
}
.inner .form-row .form-row-inner {
position: relative;
}
.inner .form-row .form-holder .label {
position: absolute;
top: -3px;
@@ -250,6 +284,7 @@ export default {
-o-transition: all .2s ease;
-ms-transition: all .2s ease;
}
.inner .form-row .form-holder .border {
position: absolute;
bottom: 31px;
@@ -269,18 +304,21 @@ export default {
-o-transition: all .15s ease;
-ms-transition: all .15s ease;
}
.inner .form-row #radio {
color: #666;
font-weight: 400;
font-size: 16px;
margin: 8px 12px;
}
.inner .form-row #checkbox {
margin: 10px 0 28px 11px;
font-size: 15px;
color: #666;
font-weight: 400;
}
.inner .form-row .form-holder label.special-label {
display: inline-block;
float: left;
@@ -290,6 +328,7 @@ export default {
font-size: 16px;
font-weight: 400;
}
.inner .form-row .form-holder label.pay-1-label,
.inner .form-row .form-holder label.pay-2-label {
width: 190px;
@@ -310,16 +349,19 @@ export default {
font-weight: 400;
margin-bottom: 5px;
}
.inner .form-row .form-holder label.pay-1-label img,
.inner .form-row .form-holder label.pay-2-label img {
padding-top: 15px;
padding-bottom: 8px;
}
.inner .form-row.form-row-date .form-holder select {
float: left;
width: 19%;
margin-right: 20px;
}
.inner .form-row .form-holder input,
.inner .form-row .form-holder select {
width: 100%;
@@ -344,15 +386,18 @@ export default {
-o-box-sizing: border-box;
-ms-box-sizing: border-box;
}
.inner .form-row .form-holder input {
font-size: 18px;
color: #333;
font-weight: 700;
}
.inner .form-row .form-holder input#pay-1,
.inner .form-row .form-holder input#pay-2 {
display: none;
}
.inner .form-row .form-holder select {
font-size: 15px;
color: #666;
@@ -362,14 +407,17 @@ export default {
cursor: pointer;
position: relative;
}
.inner .form-row .form-holder select:focus {
border-bottom: 2px solid #24c1e8;
}
.inner .form-row .form-holder .form-control:focus,
.inner .form-row .form-holder .form-control:valid {
border-bottom: 2px solid #24c1e8;
margin-top: 21px;
}
.inner .form-row .form-holder .form-control:focus + .label,
.inner .form-row .form-holder .form-control:valid + .label {
transform: translateY(-23px) scale(1);
@@ -379,6 +427,7 @@ export default {
-webkit-transform: translateY(-23px) scale(1);
color: #24c1e8;
}
.inner .form-row .form-holder .form-control:focus + .border,
.inner .form-row .form-holder .form-control:valid + .border {
transform: scaleX(1);
@@ -387,6 +436,7 @@ export default {
-moz-transform: scaleX(1);
-webkit-transform: scaleX(1);
}
.inner .form-row .form-holder input#pay-1:checked + label,
.inner .form-row .form-holder input#pay-2:checked + label {
border: none;
@@ -396,6 +446,7 @@ export default {
-moz-box-shadow: 0px 3px 10px 0px rgba(0, 0, 0, 0.15);
-webkit-box-shadow: 0px 3px 10px 0px rgba(0, 0, 0, 0.15);
}
.inner .form-row.table-responsive {
border: none;
border-radius: 5px;
@@ -405,32 +456,39 @@ export default {
-webkit-border-radius: 5px;
margin: 27px 0 -25px;
}
.inner .table-responsive .table {
width: 100%;
}
.inner .table-responsive tbody {
text-align: left;
}
.inner .table-responsive tr.space-row > td,
.inner .table-responsive tr.space-row > th {
padding: 17px 20px 14px;
border-top: 1px solid #e5e5e5;
}
.inner .table-responsive tr.space-row:last-child > td,
.inner .table-responsive tr.space-row:last-child > th {
border-bottom: none;
}
.inner .table-responsive tbody th {
color: #666;
font-size: 16px;
font-weight: 400;
width: 30%;
}
.inner .table-responsive tbody td {
color: #333;
font-size: 16px;
font-weight: 400;
}
.actions ul {
list-style: none;
padding-left: 0;
@@ -444,9 +502,11 @@ export default {
-moz-justify-content: space-between;
-webkit-justify-content: space-between;
}
.actions ul li.disabled {
opacity: 0;
}
.actions ul li {
padding: 0;
border: none;
@@ -474,16 +534,20 @@ export default {
font-weight: 400;
cursor: pointer;
}
.actions ul li:hover {
background: #1d97b5;
}
.actions ul li:first-child {
background: #999;
margin-left: 60.9%;
}
.actions ul li:first-child:hover {
background: #666;
}
.actions ul li a {
color: #fff;
text-decoration: none;
@@ -496,6 +560,7 @@ export default {
margin: 180px 20px;
}
}
@media screen and (max-width: 991px) {
.form-register .steps ul {
padding-left: 0;
@@ -505,38 +570,47 @@ export default {
-moz-justify-content: space-around;
-webkit-justify-content: space-around;
}
.form-register .steps li a .title {
text-align: center;
}
.form-register .steps li a .title .step-icon,
.form-register .steps li a .title .step-icon {
margin: 0 auto;
}
.form-register .steps li a .title .step-icon::before,
.form-register .steps li:last-child a .title .step-icon::after {
content: none;
}
.actions ul li:first-child {
margin-left: 0;
}
}
@media screen and (max-width: 767px) {
.inner .form-row.form-row-date .form-holder select {
width: 17.5%;
margin-right: 20px;
}
.inner .form-row .form-holder label.pay-1-label,
.inner .form-row .form-holder label.pay-2-label {
margin-bottom: 15px;
}
}
@media screen and (max-width: 575px) {
.wizard-v3-content {
width: 90%;
}
.wizard-form .wizard-header {
padding: 40px 20px 20px 20px;
}
.inner .form-row {
flex-direction: column;
-o-flex-direction: column;
@@ -545,18 +619,23 @@ export default {
-webkit-flex-direction: column;
margin: 0;
}
.inner .form-row .form-holder {
width: 100%;
}
.inner .form-row .form-holder.form-holder-1 {
width: 100%;
}
.inner .form-row .form-holder {
padding: 0;
}
.inner .form-row .form-holder label.special-label {
float: none;
}
.inner .form-row.form-row-date .form-holder select {
float: none;
width: 100%;
@@ -564,26 +643,33 @@ export default {
margin-right: 0;
display: block;
}
.form-register .steps li a .title .step-icon {
width: 40px;
height: 40px;
font-size: 20px;
}
.form-register .steps li a .step-text {
font-size: 12px;
}
.form-register .content {
padding: 35px 30px 60px;
}
.inner .form-row #radio {
margin-left: -2px;
}
.inner .form-row #checkbox {
margin-left: 0;
}
.actions ul li {
width: 120px;
}
.actions ul li a {
padding: 15px 24px;
}

View File

@@ -1,11 +1,12 @@
<template>
<div class="card">
<div class="card-header">Mode de livraison</div>
<div class="card-header"><h2>Mode de livraison</h2></div>
<div class="card-body row">
<div v-for="product in store.productList" class="col-lg-6">
<h1>{{ product.name }}</h1>
<p> {{ product.price }}</p>
<button @click="goNexStep(product.id)">Choisir</button>
<div v-for="(product, i) in store.productList" class="col-lg-6">
<h4>{{ product.name }}</h4>
<p>{{ text[i].short }}</p>
<p>{{ text[i].long }}</p>
<button class="btn btn-primary" @click="goNexStep(product.id)">{{ formatPrice(product.price)}} TTC</button>
</div>
</div>
</div>
@@ -14,12 +15,32 @@
<script>
import {useMMCMStore} from '../stores/mmcm.js'
export default {
setup() {
const text = [{
short: 'Dès aujourdhui en moins de 2 h.',
long: '\n' +
'En express\n' +
'dès aujourdhui en moins de 2 h.\n' +
'La collecte de lordonnance originale et des documents de santé dans une enveloppe fermée et la livraison des médicaments sont réalisées en moins de 2 heures, du lundi au samedi.'
},
{
short: 'Dès aujourdhui en moins de 2 h.',
long: '\n' +
'En express\n' +
'dès aujourdhui en moins de 2 h.\n' +
'La collecte de lordonnance originale et des documents de santé dans une enveloppe fermée et la livraison des médicaments sont réalisées en moins de 2 heures, du lundi au samedi.'
}
]
const store = useMMCMStore()
return {
store
store,
text
}
},
name: "delivery-option-step-2",
@@ -27,6 +48,13 @@ export default {
goNexStep: function (idProduct) {
this.store.setIdProduct(idProduct);
this.$router.push({path: '/delivery-option-step-3'});
},
formatPrice(price) {
return new Intl.NumberFormat('fr-FR', {
style: 'currency',
currency: 'EUR',
minimumFractionDigits: 2
}).format(price)
}
}
}

View File

@@ -1,24 +1,36 @@
<template>
<div class="card">
<div class="card-header">Date</div>
<div class="card-header"><h4>Date de livraison des médicaments :</h4></div>
<div class="card-body">
<Datepicker v-model="dateDelivery" :minDate="tomorrow" :enableTimePicker="false" :disabledWeekDays="[6, 0]" locale="fr-FR"/>
<p class="mt-4"><button class="btn btn-primary" @click="$router.push({path: '/delivery-option-summary'});">Valider</button></p>
<div class="input-group has-validation">
<Datepicker v-model="dateDelivery" autoApply @update:modelValue="isError = false" model-type="timestamp" select-text="Choisir" cancel-text="Annuler"
monthNameFormat="long" format="dd MMMM yyyy" :minDate="tomorrow" :enableTimePicker="false"
:disabledWeekDays="[6, 0]" :format-locale="fr" locale="fr-FR"/>
<button class="btn btn-primary" @click="gotToNextStep"><i class="fa-regular fa-circle-check fa-fw"></i> Valider
</button>
<div v-if="isError" class="invalid-feedback d-block text-start">
Merci de renseigner la date
</div>
</div>
</div>
</div>
</template>
<script>
import { storeToRefs } from 'pinia'
import {storeToRefs} from 'pinia'
import {useMMCMStore} from '../stores/mmcm.js'
import {ref} from 'vue';
import {add, endOfMonth, endOfYear, startOfMonth, startOfYear, subMonths} from 'date-fns';
import {fr} from 'date-fns/locale';
export default {
setup() {
const store = useMMCMStore()
const isError = ref(false);
const { dateDelivery } = storeToRefs(store)
const {dateDelivery} = storeToRefs(store)
const tomorrow =
add(new Date(), {
@@ -38,6 +50,8 @@ export default {
]);
return {
fr,
isError,
tomorrow,
dateDelivery,
presetRanges,
@@ -45,7 +59,19 @@ export default {
}
},
name: "delivery-option-step-3",
methods: {}
methods: {
gotToNextStep: function () {
if (this.dateDelivery !== null) {
this.isError = false
this.$router.push({path: '/delivery-option-summary'});
} else {
this.isError = true
}
}
}
}
</script>

View File

@@ -1,14 +1,15 @@
<template>
<div class="card">
<div class="card-header">Recapitulatif</div>
<div class="card-header"><h4>Recapitulatif</h4></div>
<div class="card-body">
<div v-if="store.widthPrescription">La pharmacie a mon ordo</div>
<div v-else>La pharmacie n'a pas mon ordo</div>
<div>{{store.idProduct}}</div>
<div>{{store.dateDelivery}}</div>
<div><strong>Adresse de livraison : </strong>{{ store.fullAddress }}</div>
<div><strong>Mode de livraison : </strong>{{ store.deliveryMethod }}</div>
<div><strong>Collecte de l'ordonnnace : </strong>
<span v-if="store.widthPrescription">Oui</span>
<span v-else>Non</span>
</div>
<div><strong>Date de livraison des medicaments : </strong>{{ store.dateDeliveryString }}</div>
<button class="btn btn-primary" @click="addToCart">Valider</button>
</div>
</div>
</template>
@@ -27,8 +28,11 @@ export default {
name: "delivery-option-summary",
methods: {
addToCart: async function (idProduct) {
const urlApi = '/php/api/v3/mmcm.php?EXEC=addToCart&ID_PRODUCT=' + idProduct;
console.log(urlApi)
const urlApi = '/php/api/v3/mmcm.php?EXEC=addToCart&ID_PRODUCT=' + this.store.idProduct
+'&with_prescription='+this.store.widthPrescription
+'&date_delivery='+this.store.dateDelivery
;
const result = await fetch(urlApi)
.then(response => {

View File

@@ -11,7 +11,7 @@
</div>
<router-link to="/address-check" class="btn btn-primary">
Je me fais livrer
Je me fais livrer <i class="fa-solid fa-circle-arrow-right"></i>
</router-link>
</template>