Compare commits

..

69 commits

Author SHA1 Message Date
Vincent BRIDIER
c5ef81f668 Merge branch 'trunk' 2026-10-23 15:30:00 +02:00
Vincent BRIDIER
4fcc529864 Merge branch 'develop' into trunk 2026-10-23 15:29:41 +02:00
Vincent BRIDIER
bfbf4e9e01 feat: Change Apache PID 2026-10-23 15:29:33 +02:00
K.
500f127090 Merge branch 'hotfix' into 'master'
Hotfix

See merge request ldc-web/projets/jeusselin!31
2026-10-22 15:51:59 +00:00
Jeremy Munsch
54848f4be6
chore: bump php deps to 8.5 2026-10-22 17:43:14 +02:00
Jeremy Munsch
23b40f4d63
build: bump php version 2026-10-22 17:43:05 +02:00
Noah Lancien
250058c085 Merge branch 'develop' into trunk 2026-10-22 17:37:30 +02:00
Noix
b52e4d2747 Merge branch 'bump-php' into 'develop'
Bump php

See merge request ldc-web/projets/jeusselin!30
2026-10-22 15:36:06 +00:00
Jeremy Munsch
883060e2dd
chore: bump php deps to 8.5 2026-10-22 17:23:08 +02:00
Jeremy Munsch
b8005a2a04
build: bump php version 2026-10-22 17:22:17 +02:00
K Muller
d8428b494e Merge branch 'develop' into trunk 2026-10-08 13:06:04 +02:00
Karl M'muller
470a84ae86 Merge branch 'fix-wysiwyg' into 'develop'
fix: 🐛 missing exclude sanitize html on news->content

See merge request ldc-web/projets/jeusselin!27
2026-10-08 11:05:04 +00:00
K Muller
8d281c2159 fix: 🐛 missing exclude sanitize html on news->content 2026-10-05 11:23:26 +02:00
Noah Lancien
a8426f80c6 Merge branch 'develop' into trunk 2026-10-01 10:37:41 +02:00
Noah Lancien
1c18491a86 Merge branch 'develop' into trunk 2026-09-28 11:08:04 +02:00
Noah Lancien
fcf49ba582 Merge branch 'develop' into trunk 2026-09-25 16:58:40 +02:00
Noah Lancien
c9178a139d Merge branch 'develop' into trunk 2026-09-10 12:32:28 +02:00
K Muller
09959e412b Merge branch 'trunk' 2026-07-31 14:04:46 +02:00
K Muller
76824459f8 Merge branch 'develop' into trunk 2026-07-31 14:04:30 +02:00
K Muller
6ea7a4117f Merge branch 'trunk' 2026-07-17 15:39:05 +02:00
K Muller
4ea9f35108 Merge branch 'develop' into trunk 2026-07-17 14:31:42 +02:00
Noix
702ea23e02 Merge branch 'hotfix' into 'master'
HOTFIX -> à répliquer sur Develop, fix: Fixes #23 correction sur l'affichage des dates isoFormat

See merge request ldc-web/projets/jeusselin!16
2026-05-04 15:16:31 +00:00
Noah Lancien
a10ff94d4a Merge branch 'trunk' 2026-04-24 11:36:44 +02:00
Noah Lancien
6583a8f01e Merge branch 'develop' into trunk 2026-04-24 11:36:31 +02:00
Noah Lancien
3c6762ae2d Merge branch 'trunk' 2026-04-21 16:51:27 +02:00
Noah Lancien
ee1e33e036 Merge branch 'develop' into trunk 2026-04-21 16:51:11 +02:00
Noah Lancien
8c52e52079 Merge branch 'develop' into trunk 2026-03-25 16:43:59 +01:00
Noah Lancien
2023eca826 Merge branch 'develop' into trunk 2026-03-24 15:27:39 +01:00
Noah Lancien
48a50d07f8 Merge branch 'develop' into trunk 2026-03-24 15:05:49 +01:00
Noah Lancien
81125b461e Merge branch 'develop' into trunk 2026-03-24 14:53:01 +01:00
Noah Lancien
f813cc214a Merge branch 'develop' into trunk 2026-03-24 14:46:41 +01:00
Noah Lancien
42da6618dc Merge branch 'develop' into trunk 2026-03-24 14:39:28 +01:00
Noah Lancien
6013663d73 Merge branch 'trunk' 2026-03-04 16:40:11 +01:00
Noah Lancien
ba79189293 Merge branch 'develop' into trunk 2026-03-04 16:25:08 +01:00
Noah Lancien
29ef828dbe Merge branch 'trunk' 2026-02-13 12:51:17 +01:00
Noah Lancien
ed8798ac66 Merge branch 'develop' into trunk 2026-02-13 12:50:53 +01:00
Noah Lancien
76edd08394 Merge branch 'develop' into trunk 2026-01-08 17:06:19 +01:00
Noah Lancien
a8d34cd23b Merge branch 'trunk' 2025-10-09 13:11:31 +02:00
Noah Lancien
eb51d562c1 Merge branch 'develop' into trunk 2025-10-09 13:02:12 +02:00
Noah Lancien
fa19527c3e Merge branch 'trunk' 2025-10-09 12:11:51 +02:00
Noah Lancien
e6b8b7402a Merge branch 'develop' into trunk 2025-10-09 12:11:35 +02:00
Noah Lancien
bc53526a08 Merge branch 'trunk' 2025-01-14 12:39:44 +01:00
Noah Lancien
86052f72b5 Merge branch 'develop' into trunk 2025-01-14 12:39:05 +01:00
Noah Lancien
e1275ecf96 Merge branch 'trunk' 2024-09-10 12:13:19 +02:00
Noah Lancien
52b80aba00 Merge branch 'develop' into trunk 2024-09-10 12:12:54 +02:00
Noah Lancien
13a1340a61 Merge branch 'trunk' 2024-09-10 11:41:26 +02:00
Noah Lancien
63548d0e3c Merge branch 'develop' into trunk 2024-09-10 11:27:26 +02:00
Noah Lancien
8d351fbc6c Merge branch 'develop' into trunk 2024-09-10 11:03:24 +02:00
Noah Lancien
b16c89eb88 Merge branch 'trunk' 2024-09-03 10:11:23 +02:00
Noah Lancien
6fa7f53714 Merge branch 'develop' into trunk 2024-09-03 10:11:07 +02:00
Noah Lancien
579eff439f Merge branch 'trunk' 2024-09-02 14:39:54 +02:00
Noah Lancien
6c47de0cf0 Merge branch 'develop' into trunk 2024-09-02 14:39:20 +02:00
Noah Lancien
3f7059e9fb Merge branch 'trunk' 2024-08-13 15:25:57 +02:00
Noah Lancien
4b522e7c21 Merge branch 'develop' into trunk 2024-08-13 15:25:32 +02:00
Vincent BRIDIER
66e0f1d523
Merge branch 'trunk' 2024-08-13 14:34:33 +02:00
Noah Lancien
456a5deeab Merge branch 'develop' into trunk 2024-08-13 12:55:53 +02:00
Noah Lancien
e35081cfa7 Merge branch 'develop' into trunk 2024-08-13 12:46:39 +02:00
Noah Lancien
c9ac965e74 Merge branch 'develop' into trunk 2024-08-05 10:50:37 +02:00
Noah Lancien
2bb81e7bcd Merge branch 'develop' into trunk 2024-08-05 09:44:27 +02:00
Jérémy Munsch
bfb62cf5ba
Merge branch 'develop' into trunk 2024-01-29 17:11:32 +01:00
Jérémy Munsch
df4db5fb5a
Merge branch 'develop' into trunk 2024-01-29 10:39:08 +01:00
Vincent BRIDIER
655eedb52e
Merge branch 'trunk' 2023-07-26 11:15:40 +02:00
Vincent BRIDIER
aec90d91e8
Merge branch 'develop' into trunk 2023-07-26 11:15:08 +02:00
Olivier Legat
a5c72b9cbe Merge branch 'trunk' 2022-03-15 14:12:34 +01:00
Olivier Legat
a473d4a49c Merge branch 'develop' into trunk 2022-03-15 14:12:18 +01:00
Olivier Legat
dbf2d39f8a Merge branch 'trunk' 2022-03-14 16:45:46 +01:00
Olivier Legat
1f1ccf0807 Merge branch 'develop' into trunk 2022-03-14 16:45:20 +01:00
Olivier Legat
194bf51032 Merge branch 'trunk' 2022-01-24 15:32:19 +01:00
Olivier Legat
90451c7a89 Merge branch 'develop' into trunk 2022-01-24 15:31:44 +01:00
8 changed files with 923 additions and 1146 deletions

View file

@ -1,5 +1,9 @@
ARG PHP_8_5_TAG=latest
FROM composer:2.9.2 AS vendor
WORKDIR /app
ARG GITLAB_USER
ARG GITLAB_PASSWORD
@ -8,7 +12,7 @@ COPY database/ database/
COPY composer.json composer.json
COPY composer.lock composer.lock
RUN composer config gitlab-token.lab.s-web.fr ${GITLAB_USER} ${GITLAB_PASSWORD}
RUN composer config gitlab-token.lab.s-web.fr "${GITLAB_USER}" "${GITLAB_PASSWORD}"
RUN composer install \
--ignore-platform-reqs \
--no-interaction \
@ -28,9 +32,10 @@ COPY resources/ /app/resources/
WORKDIR /app
RUN npm config set @ldc-web:registry https://lab.s-web.fr/api/v4/packages/npm/
RUN npm config set -- '//lab.s-web.fr/api/v4/packages/npm/:_authToken' "${GITLAB_PASSWORD}"
RUN npm ci && npm run prod
RUN npm ci --no-audit --no-fund --loglevel=error && npm run prod
FROM registry.s-web.fr/ldc-web/projets/ldc-web-images-docker/uwil-production-8.4:170625-130159
ARG PHP_8_5_TAG
FROM registry.s-web.fr/ldc-web/projets/ldc-web-images-docker/uwil-production-8.5:${PHP_8_5_TAG}
ARG USER=www-data

View file

@ -8,7 +8,7 @@
],
"license": "MIT",
"require": {
"php": "^8.4",
"php": "^8.5",
"24slides/laravel-saml2": "^2.4",
"guzzlehttp/guzzle": "^7.5.0",
"laravel/framework": "^12.0",
@ -46,7 +46,9 @@
"dealerdirect/phpcodesniffer-composer-installer": true,
"php-http/discovery": true
},
"gitlab-domains": ["lab.s-web.fr"]
"gitlab-domains": [
"lab.s-web.fr"
]
},
"extra": {
"laravel": {

1575
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -10,7 +10,8 @@ data:
APP_DEBUG: "${APP_APP_DEBUG}"
APP_URL: "https://${APP_DOMAIN}"
LOG_CHANNEL: "k8s"
DB_HOST: "${APP_DB_HOST}"
DB_HOST: "${APP_GLOBAL_OVH_MYSQL_HOST}"
DB_PORT: "${APP_GLOBAL_OVH_MYSQL_PORT}"
DB_DATABASE: "${APP_DB_DATABASE}"
DB_USERNAME: "${APP_DB_USERNAME}"
DB_PASSWORD: "${APP_DB_PASSWORD}"
@ -83,9 +84,9 @@ spec:
imagePullSecrets:
- name: docker-registry-credentials
securityContext:
runAsUser: 33
runAsGroup: 33
fsGroup: 33
runAsUser: 82
runAsGroup: 82
fsGroup: 82
fsGroupChangePolicy: "OnRootMismatch"
volumes:
- name: storage
@ -171,8 +172,8 @@ spec:
persistentVolumeClaim:
claimName: ${CI_PROJECT_PATH_SLUG}-pvc-storage
securityContext:
runAsUser: 33
runAsGroup: 33
fsGroup: 33
runAsUser: 82
runAsGroup: 82
fsGroup: 82
fsGroupChangePolicy: "OnRootMismatch"
restartPolicy: OnFailure

View file

@ -1,7 +1,7 @@
<template>
<div class="pro--objectifs">
<div class="objectifs--form">
<h2 class="post-title">Objectif de prix</h2>
<h2 class="post-title">Fixer un objectif de prix</h2>
<transition name="fade">
<div class="alert alert-success" v-show="processing">
@ -24,95 +24,50 @@
</div>
</transition>
<form @submit.prevent="saveData">
<div class="objectifs--grid">
<label for="produit" class="col-start">Produit * :</label>
<select name="produit" id="produit" v-model="objectif.produit" @change="populate">
<option value="--">Choisir un produit</option>
<option v-for="produit in enums.produit" :key="produit.value" :value="produit.value">
{{ produit.value }}
</option>
</select>
<form>
<div class="flex row">
<select name="produit" id="produit" v-model="objectif.produit" @change="populate">
<option value="--">Selectionner un produit*</option>
<option v-for="produit in enums.produit" :key="produit.value" :value="produit.value">
{{ produit.value }}
</option>
</select>
<label for="campagne">Campagne * :</label>
<select name="campagne" id="campagne" v-model="objectif.campagne" @change="populate">
<option value="--">Choisir une campagne</option>
<option v-for="campagne in campagneEnums" :key="campagne.value" :value="campagne.value">
{{ campagne.value }}
</option>
</select>
<select name="qualite" v-model="objectif.qualite">
<option value="--">Qualité*</option>
<option v-for="qualite in qualiteEnums" :key="qualite.value" :value="qualite.value">
{{ qualite.value }}
</option>
</select>
</div>
<label for="qualite" class="col-start">Qualité * :</label>
<select name="qualite" id="qualite" v-model="objectif.qualite">
<option value="--">Choisir une qualité</option>
<option v-for="qualite in qualiteEnums" :key="qualite.value" :value="qualite.value">
{{ qualite.value }}
</option>
</select>
<div class="flex row">
<select name="campagne" v-model="objectif.campagne" @change="populate">
<option value="--">Campagne*</option>
<option v-for="campagne in campagneEnums" :key="campagne.value" :value="campagne.value">
{{ campagne.value }}
</option>
</select>
<label for="quantite_liste" class="col-start">Quantité * :</label>
<select id="quantite_liste" name="quantite_liste" v-model.number="objectif.quantite">
<option :value="null">Multiple de 30 T</option>
<option v-for="q in QUANTITES" :key="q" :value="q">{{ q }} T</option>
</select>
<select name="echeance" v-model="objectif.echeance">
<option value="--">Échéance*</option>
<option v-for="echeance in echeanceEnums" :key="echeance.value" :value="echeance.value">
{{ echeance.value }}
</option>
</select>
</div>
<span class="objectifs--ou">ou</span>
<input type="number" name="quantite" class="objectifs--wide" v-model.number="objectif.quantite" min="0" placeholder="Saisie libre*">
<div class="flex row">
<input type="number" name="quantite" v-model.number="objectif.quantite" min="0" placeholder="Quantité*">
<input type="number" name="prix" v-model.number="objectif.prix" min="0" step="0.01" placeholder="Prix (€)*">
</div>
<label for="prix" class="col-start">Prix * :</label>
<div class="objectifs--prix">
<input type="number" id="prix" name="prix" class="objectifs--wide" v-model.number="objectif.prix" min="0" step="0.01" placeholder="Prix (€/TM)*">
<span>€/TM</span>
</div>
<label for="echeance">Échéance * :</label>
<select name="echeance" id="echeance" v-model="objectif.echeance">
<option value="--">Choisir une échéance</option>
<option v-for="echeance in echeanceEnums" :key="echeance.value" :value="echeance.value">
{{ echeance.value }}
</option>
</select>
</div>
<div class="objectifs--line">
<div class="objectifs--field">
<label for="volume_restant">Volume restant à commercialiser :</label>
<input type="number" id="volume_restant" name="volume_restant"
v-model.number="objectif.volume_restant" min="0" placeholder="Saisie libre">
</div>
</div>
<div class="objectifs--line">
<div class="objectifs--field grow">
<label for="observations">Observations :</label>
<input type="text" id="observations" name="observations"
v-model="objectif.observations" placeholder="Saisie libre">
</div>
<button type="submit" class="first-btn" :disabled="processing">OK</button>
</div>
</form>
</div>
<!-- RESUME -->
<div class="objectifs--resume" v-if="myobjectives.length">
<hr class="objectifs--divider">
<h3>Résumé :</h3>
<ul>
<li v-for="(item, i) in myobjectives" :key="item.id ?? i" class="objectif--ligne">
<span class="objectif--texte"
:class="{ editable: isEditable(item) }"
:title="isEditable(item) ? 'Cliquer pour modifier' : ''"
@click="editItem(item)">
Campagne {{ item.campagne }} {{ item.quantite }}TM {{ item.produit }} {{ item.prix }}€
</span>
<span class="objectif--statut" :class="statusClass(item)">
{{ statusLabel(item) }}
</span>
<button type="button" class="objectif--delete" @click="removeItem(i)" aria-label="Supprimer">X</button>
</li>
</ul>
<p class="objectifs--hint">(Modifiable en cliquant sur la ligne)</p>
<div class="validate">
<button class="first-btn" @click.prevent="saveData" :disabled="processing">
Enregistrer l'objectif
</button>
</div>
</form>
</div>
</div>
</template>
@ -121,21 +76,11 @@
import { ref } from "vue"
import axios from "axios"
import {
ObjectiveStatus,
OBJECTIVE_STATUS_LABELS,
OBJECTIVE_STATUS_CLASSES,
} from "../../types/ObjectiveStatus"
const props = defineProps<{ json: string }>()
const QUANTITES = Array.from({ length: 20 }, (_, i) => (i + 1) * 30)
const initial = JSON.parse(props.json)
initial.dbobjectif.quantite = null
initial.dbobjectif.volume_restant = null
initial.dbobjectif.observations ??= ""
const objectif = ref<any>(structuredClone(initial.dbobjectif))
const myobjectives = ref<any[]>(initial.dbmyObjectives)
@ -149,6 +94,7 @@ const success = ref(false)
const errors = ref<string[]>([])
const response = ref("")
function populate(event: Event) {
const target = event.target as HTMLSelectElement
@ -161,47 +107,14 @@ function populate(event: Event) {
campagneEnums.value = enums.value.campagne[target.value] || []
break
case "campagne": {
case "campagne":
const selectProduit = objectif.value.produit
echeanceEnums.value =
enums.value.echeance?.[selectProduit]?.[target.value] || []
break
}
}
}
function resetForm() {
objectif.value = structuredClone(initial.dbobjectif)
qualiteEnums.value = []
campagneEnums.value = []
echeanceEnums.value = []
}
function isEditable(item: any): boolean {
return statusId(item) === ObjectiveStatus.EnCours
}
function editItem(item: any) {
if (!isEditable(item)) return
objectif.value = JSON.parse(JSON.stringify(item))
qualiteEnums.value = enums.value.qualite?.[item.produit] || []
campagneEnums.value = enums.value.campagne?.[item.produit] || []
echeanceEnums.value = enums.value.echeance?.[item.produit]?.[item.campagne] || []
errors.value = []
}
function statusId(item: any): ObjectiveStatus {
return item.status?.id ?? item.status_id ?? ObjectiveStatus.EnCours
}
function statusLabel(item: any): string {
return OBJECTIVE_STATUS_LABELS[statusId(item)] ?? "En cours"
}
function statusClass(item: any): string {
return OBJECTIVE_STATUS_CLASSES[statusId(item)] ?? "en-cours"
}
function checkForm(): boolean {
errors.value = []
@ -245,7 +158,6 @@ function removeItem(index: number) {
if (result === 0 || result === 2) {
myobjectives.value.splice(index, 1)
if (String(objectif.value.id) === String(item.id)) resetForm()
response.value = "Suppression terminée !"
} else {
response.value = "Erreur : Suppression impossible"
@ -265,8 +177,6 @@ function removeItem(index: number) {
function saveData() {
if (!checkForm()) return
const editingId = objectif.value.id ?? null
processing.value = true
success.value = false
errors.value = []
@ -277,25 +187,17 @@ function saveData() {
objectif: objectif.value,
})
.then((res) => {
const savedId = editingId ?? res.data.id
const index = myobjectives.value.findIndex(
(o) => String(o.id) === String(savedId)
)
if (index !== -1) {
myobjectives.value[index] = res.data
} else {
myobjectives.value.unshift(res.data)
}
resetForm()
success.value = true
response.value = "Sauvegarde terminée !"
myobjectives.value.push(res.data)
objectif.value = structuredClone(initial.dbobjectif)
qualiteEnums.value = []
campagneEnums.value = []
echeanceEnums.value = []
setTimeout(() => (success.value = false), 3000)
})
.catch((err) => {
response.value = "Erreur lors de la sauvegarde :"
errors.value = [err.response?.data?.message ?? "Erreur lors de la sauvegarde."]
.catch(() => {
errors.value.push("Erreur lors de la sauvegarde.")
})
.finally(() => {
processing.value = false
@ -312,232 +214,4 @@ function saveData() {
.fade-leave-to {
opacity: 0;
}
.objectifs--required {
margin-left: 1.5rem;
font-size: .6em;
font-weight: normal;
color: #d00;
}
.objectifs--required span {
font-size: 1.5em;
vertical-align: middle;
}
.objectifs--grid {
display: grid;
grid-template-columns: max-content minmax(0, 1fr) max-content minmax(0, 1fr);
align-items: center;
gap: 1rem;
margin-bottom: 1rem;
}
.objectifs--grid > label {
margin: 0;
white-space: nowrap;
}
.objectifs--grid .col-start {
grid-column: 1;
}
.objectifs--grid select,
.objectifs--grid input {
width: 100%;
min-width: 0;
margin: 0;
}
/* Qualité sur toute la largeur */
.objectifs--grid #qualite {
grid-column: 2 / -1;
}
.objectifs--grid .objectifs--ou {
justify-self: end;
}
.objectifs--prix {
display: flex;
align-items: center;
gap: .5rem;
}
.pro--objectifs .objectifs--form form .objectifs--grid input[type="number"].objectifs--wide {
flex: 1;
width: 100%;
max-width: none;
min-width: 0;
}
.objectifs--line {
display: flex;
align-items: center;
gap: 1rem 2rem;
margin-bottom: 1rem;
}
.objectifs--field {
display: flex;
align-items: center;
gap: .5rem;
}
.objectifs--field.grow {
flex: 1;
min-width: 0;
}
.objectifs--field.grow input {
flex: 1;
min-width: 0;
}
.objectifs--field label {
margin: 0;
white-space: nowrap;
}
.objectifs--line .first-btn {
margin-left: auto;
}
.objectifs--resume {
margin-top: -25px;
padding: 20px;
}
.objectifs--divider {
margin: 0 0 1rem;
border: 0;
border-top: 2px solid #000;
opacity: 1;
}
.objectifs--resume h3 {
margin-top: 0;
text-decoration: underline;
}
.objectifs--resume ul {
list-style: none;
margin: 0;
padding: 0;
}
.objectif--ligne {
display: flex;
align-items: center;
gap: 1rem;
padding: .25rem 0;
}
.objectif--texte {
flex: 1;
}
.objectif--texte.editable {
cursor: pointer;
}
.objectif--texte.editable:hover {
text-decoration: underline;
}
.objectif--statut.en-cours {
color: #1a9a3c;
}
.objectif--statut.atteint {
color: #d00;
}
.objectif--statut.depassee {
color: #888;
}
.objectif--delete {
border: 0;
background: none;
color: #d00;
font-weight: bold;
cursor: pointer;
padding-inline: 5px;
}
.objectifs--hint {
margin-bottom: 0;
font-style: italic;
font-size: .9em;
}
/* Tablette */
@media (max-width: 768px) {
.objectifs--grid {
grid-template-columns: max-content minmax(0, 1fr);
}
/* Tous les libellés reviennent en colonne 1 */
.objectifs--grid > label {
grid-column: 1;
}
.objectifs--grid .objectifs--ou {
justify-self: start;
}
.objectifs--line {
flex-wrap: wrap;
}
.objectifs--line .first-btn {
margin-left: 0;
}
}
/* Mobile*/
@media (max-width: 480px) {
.objectifs--grid {
grid-template-columns: minmax(0, 1fr);
gap: .5rem;
}
.objectifs--grid > label,
.objectifs--grid .col-start,
.objectifs--grid #qualite {
grid-column: 1;
}
.objectifs--grid > label {
margin-top: .5rem;
}
.objectifs--field {
flex-direction: column;
align-items: stretch;
width: 100%;
}
.objectifs--field label {
white-space: normal;
}
.pro--objectifs .objectifs--form form #volume_restant {
width: 100%;
}
.objectifs--line .first-btn {
width: 100%;
}
.objectif--ligne {
flex-wrap: wrap;
gap: .25rem 1rem;
}
.objectif--texte {
flex: 1 1 100%;
}
}
</style>

View file

@ -1,22 +0,0 @@
export enum ObjectiveStatus {
EnCours = 1,
Atteint = 2,
EcheanceDepassee = 3,
}
export interface ObjectiveStatusData {
id: ObjectiveStatus
label: string
}
export const OBJECTIVE_STATUS_LABELS: Record<ObjectiveStatus, string> = {
[ObjectiveStatus.EnCours]: "En cours",
[ObjectiveStatus.Atteint]: "Atteint",
[ObjectiveStatus.EcheanceDepassee]: "Échéance dépassée",
}
export const OBJECTIVE_STATUS_CLASSES: Record<ObjectiveStatus, string> = {
[ObjectiveStatus.EnCours]: "en-cours",
[ObjectiveStatus.Atteint]: "atteint",
[ObjectiveStatus.EcheanceDepassee]: "depassee",
}

View file

@ -154,7 +154,7 @@
@endsection
@push('scripts')
<script nonce="{{ $nonce ?? '' }}">
<script>
document.addEventListener('DOMContentLoaded', () => {
const select = document.querySelector('select[name=mps]');
const blocs = document.querySelectorAll('.cotations--grid .mp--bloc');

View file

@ -35,18 +35,26 @@ Route::prefix('bo')->name('bo.')->middleware('admin-secure')->group(function ()
Route::get('/', [DashboardController::class, 'index'])->name('dashboard');
// * Utilisateurs BO
Route::resource('objectives', ObjectivesController::class)->except([
'create', 'edit'
'create',
'edit'
]);
Route::resources([
'users' => UsersController::class,
'employees' => EmployeesController::class,
'home-sliders' => HomeSlidersController::class,
'articles' => ArticlesController::class,
'cotations' => CotationsController::class,
'public-pdfs' => PublicPdfsController::class,
]);
// * ARTICLES
Route::resource(
'articles',
ArticlesController::class,
)->withoutMiddleware('htmlsanitize')
->middleware('htmlsanitize:content');
Route::resource('customers', CustomerController::class)
->only(['index', 'edit', 'update']);
->only(['index', 'edit', 'update']);
// *ordres
Route::get(