Commit 6a92486c authored by Stephane Bouvry's avatar Stephane Bouvry
Browse files

Backup soucis de batterie

parent c4f94795
Loading
Loading
Loading
Loading
Loading
+3 −1
Changes for module/Oscar/src/Oscar/Service/ProjectGrantApiService.php: 3 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -916,6 +916,7 @@ class ProjectGrantApiService implements
        $dates = $activityDateRepository->getMilestonesByIdsActivity([$activity->getId()]);

        $now = date('Y-m-d');
        $nowDt = new \DateTime($now);

        /** @var ActivityDate $data */
        foreach ($dates as $data) {
@@ -929,7 +930,8 @@ class ProjectGrantApiService implements
                'type_id' => $data->getType()->getId(),
                'finished' => $data->getFinished(),
                'finishedBy' => $data->getFinishedBy(),
                'validable' => $data->getType()->isFinishable()
                'validable' => $data->getType()->isFinishable(),
                'late' => $data->isLate($nowDt)
                //'hasProgression' => $data->getProgressInfo()
            ];
            $out['entities'][] = $data;
+239 −0
Changes for ui/src/components/DateSlider.vue: 239 added lines, 0 removed lines.
Original line number Diff line number Diff line
<template>
  <div class="timeline-container">
    TOTO
    <button @click="scroll('gauche')" class="nav-btn left">◀</button>

    <div ref="scrollContainer" class="timeline-scroll">
      <div class="timeline-line"></div>

      <div
          v-for="(item, index) in itemsTries"
          :key="index"
          :ref="el => { if (item.estLePlusProche) elementPlusProche = el }"
          class="timeline-item"
          :class="{ 'is-closest': item.estLePlusProche }"
      >
        <div class="timeline-date">
          {{ formaterDate(item.date) }}
        </div>

        <div class="timeline-dot">
          <i class="icon-bank" v-if="item.type === 'payment'"></i>
          <i class="icon-calendar" v-else></i>
        </div>

        <div class="timeline-content">
          <h4>{{ item.label }}</h4>
          {{ item.status }} / {{ item.late }}
          <!-- <span class="badge" :class="item.status">{{ item.status }}</span> -->
        </div>
      </div>
    </div>

    <button @click="scroll('droite')" class="nav-btn right">▶</button>
  </div>
</template>

<script setup>
import { computed, ref, onMounted, nextTick } from 'vue'

// Vos données initiales passées en Props
const props = defineProps({
  donnees: {
    type: Array,
    required: true
  }
})

const scrollContainer = ref(null)
const elementPlusProche = ref(null)

// 1. Trier les dates et identifier la plus proche d'aujourd'hui
const itemsTries = computed(() => {
  const aujourdhui = new Date()

  // On trie d'abord le tableau par date
  const listeTriee = [...props.donnees].sort((a, b) => new Date(a.date) - new Date(b.date))

  // On cherche l'index de l'élément le plus proche d'aujourd'hui
  let indexPlusProche = 0
  let differenceMinimale = Infinity

  listeTriee.forEach((item, index) => {
    const diff = Math.abs(new Date(item.date) - aujourdhui)
    if (diff < differenceMinimale) {
      differenceMinimale = diff
      indexPlusProche = index
    }
  })

  // On retourne le tableau en ajoutant un drapeau "estLePlusProche"
  return listeTriee.map((item, index) => ({
    ...item,
    estLePlusProche: index === indexPlusProche
  }))
})

// 2. Centrer automatiquement sur l'élément le plus proche au chargement
onMounted(async () => {
  await nextTick() // On attend que le DOM soit rendu
  if (elementPlusProche.value) {
    elementPlusProche.value.scrollIntoView({
      behavior: 'smooth',
      block: 'nearest',
      inline: 'center' // Centre l'élément horizontalement
    })
  }
})

// 3. Gestion du défilement des boutons
const scroll = (direction) => {
  if (scrollContainer.value) {
    const valeurDefilement = 300
    scrollContainer.value.scrollBy({
      left: direction === 'gauche' ? -valeurDefilement : valeurDefilement,
      behavior: 'smooth'
    })
  }
}

// Outil pour afficher joliment la date
const formaterDate = (dateString) => {
  return new Date(dateString).toLocaleDateString('fr-FR', {
    day: 'numeric',
    month: 'short',
    year: 'numeric'
  })
}
</script>

<style scoped>
/* Conteneur principal */
.timeline-container {
  display: flex;
  align-items: center;
  position: relative;
  width: 100%;
  padding: 40px 0;
  background: #f9f9f9;
  border-radius: 8px;
}

/* Zone de défilement masquant la scrollbar */
.timeline-scroll {
  display: flex;
  overflow-x: auto;
  scroll-behavior: smooth;
  width: 100%;
  padding: 20px 50px;
  position: relative;
  scrollbar-width: none; /* Firefox */
}
.timeline-scroll::-webkit-scrollbar {
  display: none; /* Chrome, Safari, Opera */
}

/* La ligne horizontale */
.timeline-line {
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  height: 4px;
  background: #ddd;
  transform: translateY(-50%);
  z-index: 1;
}

/* Un bloc d'événement */
.timeline-item {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  min-width: 150px;
  margin: 0 1em;
  z-index: 2;
  transition: transform 0.3s ease;
}

/* Style de mise en valeur de la date la plus proche */
.timeline-item.is-closest {
  transform: scale(1.1);
}
.timeline-item.is-closest .timeline-date {
  background: #3b82f6;
  color: white;
  font-weight: bold;
}

/* Éléments internes */
.timeline-date {
  background: #fff;
  padding: .25em 1em;
  border-radius: 20px;
  font-size: 0.85rem;
  box-shadow: 0 0px 8px rgba(0,0,0,0.25);
  margin-bottom: .25em;
}

.timeline-dot {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: #94a3b8;
  border: 3px solid #fff;
  box-shadow: 0 2px 4px rgba(0,0,0,0.2);
  margin-bottom: 0px;
  color: white;
}
.timeline-dot i {
  position: absolute;
  transform: translate(1px, 0px);
}
/* Couleurs selon le type */
.timeline-dot.milestone { background: #ec4899; }
.timeline-dot.payment { background: #10b981; }

.timeline-content {
  background: white;
  padding: 10px 15px;
  border-radius: 6px;
  text-align: center;
  box-shadow: 0 4px 6px -1px rgba(0,0,0,0.1);
}

.timeline-content h4 {
  margin: 0 0 5px 0;
  font-size: 0.95rem;
}

/* Boutons de navigation */
.nav-btn {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  background: white;
  border: 1px solid #ddd;
  border-radius: 50%;
  width: 40px;
  height: 40px;
  cursor: pointer;
  z-index: 10;
  box-shadow: 0 2px 5px rgba(0,0,0,0.15);
  display: flex;
  align-items: center;
  justify-content: center;
}
.nav-btn:hover { background: #f0f0f0; }
.left { left: 10px; }
.right { right: 10px; }

/* Badges de statut */
.badge {
  font-size: 0.75rem;
  padding: 2px 6px;
  border-radius: 4px;
  background: #e2e8f0;
}
</style>
 No newline at end of file
+12 −5
Changes for ui/src/views/Activity.vue: 12 added lines, 5 removed lines.
Original line number Diff line number Diff line
@@ -289,12 +289,15 @@
      <div class="tab-content" id="nav-tabContent">
        <div class="tab-pane fade show active" id="nav-home" role="tabpanel" aria-labelledby="nav-home-tab" tabindex="0">
          Générale
          {{ milestones }}
          <DateSlider :donnees="timeline" />
          <div class="date-slider">
        <pre>
        <!--<pre>
          {{ payments }}
          {{ milestones }}
          -----
          {{ timeline }}
        </pre>
        </pre>-->
          </div>
        </div>
        <div class="tab-pane fade" id="nav-profile" role="tabpanel" aria-labelledby="nav-profile-tab" tabindex="0">
@@ -872,6 +875,7 @@ import WorkpackagesActivity from "./WorkpackagesActivity.vue";
import 'vue-json-pretty/lib/styles.css';
import PersonDisplay from "../components/PersonDisplay.vue";
import vScrollStatus from "../directives/vScrollStatus.js";
import DateSlider from "../components/DateSlider.vue";

axios.defaults.headers.common['Accept'] = 'application/json';
axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
@@ -887,6 +891,7 @@ export default {
    ActivityLogs,
    ActivityDocument,
    ActivitySpentSynthesis,
    DateSlider,
    EntityWithRole,
    Loader,
    Payments,
@@ -983,7 +988,8 @@ export default {
          timeline.push({
            label: item.type.label,
            date: item.dateStart,
            status: 'test',
            late: item.late,
            status: item.late ? 'error' : 'autre',
            type: 'milestone'
          })
        })
@@ -991,15 +997,16 @@ export default {
      if( this.payments ){
        this.payments.forEach(item => {
          timeline.push({
            label: "Versement " + item.statusLabel,
            label: "Versement de " + item.amount + "€",
            date: item.status == 2 ? item.datePayment : item.datePredicted,
            late: item.late,
            status: 'test',
            type: 'payment'
          })

        })
      }
      return timeline;
      return timeline.sort((a,b) => new Date(a.date) - new Date(b.date));
    },
    personsWP() {
      if (!this.persons) {