Loading ui/src/components/DateSlider.vue +21 −11 Changes for ui/src/components/DateSlider.vue: 21 added lines, 11 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"> Loading @@ -11,21 +10,22 @@ :key="index" :ref="el => { if (item.estLePlusProche) elementPlusProche = el }" class="timeline-item" :class="{ 'is-closest': item.estLePlusProche }" :class="{ 'is-closest': item.estLePlusProche, 'error': item.status === 'error' }" > <div class="timeline-date"> {{ formaterDate(item.date) }} <strong class="date">{{ $filters.date(item.date) }}</strong> <small class="ago" v-if="item.status !== 'today'">{{ $filters.timeAgo(item.date) }}</small> <small class="ago" v-else>Aujourd'hui</small> </div> <div class="timeline-dot"> <div class="timeline-dot" :class="item.status"> <i class="icon-bank" v-if="item.type === 'payment'"></i> <i class="icon-location" v-else-if="item.status === 'today'"></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> Loading Loading @@ -173,9 +173,18 @@ const formaterDate = (dateString) => { padding: .25em 1em; border-radius: 20px; font-size: 0.85rem; text-align: center; box-shadow: 0 0px 8px rgba(0,0,0,0.25); margin-bottom: .25em; } .timeline-date .date { display: block; font-weight: bold; } .timeline-date .ago { display: block; font-weight: 200; } .timeline-dot { width: 32px; Loading @@ -189,16 +198,16 @@ const formaterDate = (dateString) => { } .timeline-dot i { position: absolute; transform: translate(1px, 0px); transform: translate(2px, 1px) scale(0.8); } /* Couleurs selon le type */ .timeline-dot.milestone { background: #ec4899; } .timeline-dot.payment { background: #10b981; } .timeline-dot.error { background: var(--bs-danger); } .timeline-dot.done { background: var(--bs-green); } .timeline-content { background: white; padding: 10px 15px; border-radius: 6px; padding: .5em 1em; text-align: center; box-shadow: 0 4px 6px -1px rgba(0,0,0,0.1); } Loading @@ -206,6 +215,7 @@ const formaterDate = (dateString) => { .timeline-content h4 { margin: 0 0 5px 0; font-size: 0.95rem; color: var(--bs-gray-700); } /* Boutons de navigation */ Loading ui/src/utils/MomentFilter.js +13 −1 Changes for ui/src/utils/MomentFilter.js: 13 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -65,7 +65,19 @@ moment.locale("fr", export default { timeAgo(date, nullDisplay = 'Non définie') { return date ? moment(date).fromNow() : nullDisplay; if (!date) return nullDisplay; const mDate = moment(date); // Si c'est aujourd'hui, on utilise calendar() if (mDate.isSame(moment(), 'day')) { return mDate.calendar(null, { sameDay: '[Aujourd\'hui]' }); } // Sinon, on garde le comportement classique fromNow() return mDate.fromNow(); }, time(date) { return date ? moment(date).format("H:m:s") : ''; Loading ui/src/views/Activity.vue +42 −16 Changes for ui/src/views/Activity.vue: 42 added lines, 16 removed lines. Original line number Diff line number Diff line Loading @@ -288,17 +288,7 @@ </nav> <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> {{ payments }} {{ milestones }} ----- {{ timeline }} </pre>--> </div> </div> <div class="tab-pane fade" id="nav-profile" role="tabpanel" aria-labelledby="nav-profile-tab" tabindex="0"> <div class="row"> Loading Loading @@ -983,28 +973,64 @@ export default { computed: { timeline(){ let timeline = []; let status, date; let eventToday = false; let today = (new Date()).toLocaleDateString('fr-CA'); console.log(today); if( this.milestones ){ this.milestones.forEach(item => { date = item.dateStart.substring(0, 10); status = 'default'; if( item.late ){ status = 'error'; } else if ( item.validable ){ status = 'done'; } if( date === today ){ eventToday = true; } timeline.push({ label: item.type.label, date: item.dateStart, date: date, late: item.late, status: item.late ? 'error' : 'autre', status: status, type: 'milestone' }) }) } if( this.payments ){ this.payments.forEach(item => { date = item.datePredicted; status = 'todo'; if( item.late ){ status = 'error'; } if(item.status === 2){ date = item.datePayment; status = 'done'; } date = date.substring(0, 10); if( date === today ){ eventToday = true; } timeline.push({ label: "Versement de " + item.amount + "€", date: item.status == 2 ? item.datePayment : item.datePredicted, label: item.amount + "€", date: date, late: item.late, status: 'test', status: status, type: 'payment' }) }) if( eventToday === false ){ timeline.push({ label: "Aujourd'hui", date: today, late: "false", status: "today", type: 'today' }) } } return timeline.sort((a,b) => new Date(a.date) - new Date(b.date)); }, Loading Loading
ui/src/components/DateSlider.vue +21 −11 Changes for ui/src/components/DateSlider.vue: 21 added lines, 11 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"> Loading @@ -11,21 +10,22 @@ :key="index" :ref="el => { if (item.estLePlusProche) elementPlusProche = el }" class="timeline-item" :class="{ 'is-closest': item.estLePlusProche }" :class="{ 'is-closest': item.estLePlusProche, 'error': item.status === 'error' }" > <div class="timeline-date"> {{ formaterDate(item.date) }} <strong class="date">{{ $filters.date(item.date) }}</strong> <small class="ago" v-if="item.status !== 'today'">{{ $filters.timeAgo(item.date) }}</small> <small class="ago" v-else>Aujourd'hui</small> </div> <div class="timeline-dot"> <div class="timeline-dot" :class="item.status"> <i class="icon-bank" v-if="item.type === 'payment'"></i> <i class="icon-location" v-else-if="item.status === 'today'"></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> Loading Loading @@ -173,9 +173,18 @@ const formaterDate = (dateString) => { padding: .25em 1em; border-radius: 20px; font-size: 0.85rem; text-align: center; box-shadow: 0 0px 8px rgba(0,0,0,0.25); margin-bottom: .25em; } .timeline-date .date { display: block; font-weight: bold; } .timeline-date .ago { display: block; font-weight: 200; } .timeline-dot { width: 32px; Loading @@ -189,16 +198,16 @@ const formaterDate = (dateString) => { } .timeline-dot i { position: absolute; transform: translate(1px, 0px); transform: translate(2px, 1px) scale(0.8); } /* Couleurs selon le type */ .timeline-dot.milestone { background: #ec4899; } .timeline-dot.payment { background: #10b981; } .timeline-dot.error { background: var(--bs-danger); } .timeline-dot.done { background: var(--bs-green); } .timeline-content { background: white; padding: 10px 15px; border-radius: 6px; padding: .5em 1em; text-align: center; box-shadow: 0 4px 6px -1px rgba(0,0,0,0.1); } Loading @@ -206,6 +215,7 @@ const formaterDate = (dateString) => { .timeline-content h4 { margin: 0 0 5px 0; font-size: 0.95rem; color: var(--bs-gray-700); } /* Boutons de navigation */ Loading
ui/src/utils/MomentFilter.js +13 −1 Changes for ui/src/utils/MomentFilter.js: 13 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -65,7 +65,19 @@ moment.locale("fr", export default { timeAgo(date, nullDisplay = 'Non définie') { return date ? moment(date).fromNow() : nullDisplay; if (!date) return nullDisplay; const mDate = moment(date); // Si c'est aujourd'hui, on utilise calendar() if (mDate.isSame(moment(), 'day')) { return mDate.calendar(null, { sameDay: '[Aujourd\'hui]' }); } // Sinon, on garde le comportement classique fromNow() return mDate.fromNow(); }, time(date) { return date ? moment(date).format("H:m:s") : ''; Loading
ui/src/views/Activity.vue +42 −16 Changes for ui/src/views/Activity.vue: 42 added lines, 16 removed lines. Original line number Diff line number Diff line Loading @@ -288,17 +288,7 @@ </nav> <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> {{ payments }} {{ milestones }} ----- {{ timeline }} </pre>--> </div> </div> <div class="tab-pane fade" id="nav-profile" role="tabpanel" aria-labelledby="nav-profile-tab" tabindex="0"> <div class="row"> Loading Loading @@ -983,28 +973,64 @@ export default { computed: { timeline(){ let timeline = []; let status, date; let eventToday = false; let today = (new Date()).toLocaleDateString('fr-CA'); console.log(today); if( this.milestones ){ this.milestones.forEach(item => { date = item.dateStart.substring(0, 10); status = 'default'; if( item.late ){ status = 'error'; } else if ( item.validable ){ status = 'done'; } if( date === today ){ eventToday = true; } timeline.push({ label: item.type.label, date: item.dateStart, date: date, late: item.late, status: item.late ? 'error' : 'autre', status: status, type: 'milestone' }) }) } if( this.payments ){ this.payments.forEach(item => { date = item.datePredicted; status = 'todo'; if( item.late ){ status = 'error'; } if(item.status === 2){ date = item.datePayment; status = 'done'; } date = date.substring(0, 10); if( date === today ){ eventToday = true; } timeline.push({ label: "Versement de " + item.amount + "€", date: item.status == 2 ? item.datePayment : item.datePredicted, label: item.amount + "€", date: date, late: item.late, status: 'test', status: status, type: 'payment' }) }) if( eventToday === false ){ timeline.push({ label: "Aujourd'hui", date: today, late: "false", status: "today", type: 'today' }) } } return timeline.sort((a,b) => new Date(a.date) - new Date(b.date)); }, Loading