agenda + parcourir

This commit is contained in:
Omar El Alaoui El Ismaili 2025-04-09 03:39:27 +02:00
parent 8d62ebf0af
commit 66338ee020

View File

@ -1,5 +1,10 @@
<template> <template>
<div class="ade-agenda-container"> <div class="ade-agenda-container">
<!-- Import ICS -->
<div style="margin-bottom: 15px; text-align: center;">
<input type="file" @change="handleFileUpload" accept=".ics" />
</div>
<!-- Le tableau ADE en haut, inchangé --> <!-- Le tableau ADE en haut, inchangé -->
<table class="ade-table"> <table class="ade-table">
<thead> <thead>
@ -29,61 +34,40 @@
</thead> </thead>
<tbody> <tbody>
<!-- Lignes pour les créneaux horaires -->
<tr v-for="(slot, slotIndex) in timeSlots" :key="slotIndex"> <tr v-for="(slot, slotIndex) in timeSlots" :key="slotIndex">
<td class="time-col"> <td class="time-col">{{ slot.start }} - {{ slot.end }}</td>
{{ slot.start }} - {{ slot.end }}
</td>
<td <td
v-for="(day, dayIndex) in daysOfWeek" v-for="(day, dayIndex) in daysOfWeek"
:key="dayIndex" :key="dayIndex"
class="agenda-cell" class="agenda-cell"
> >
<!-- On affiche les events qui commencent pile sur ce créneau -->
<div <div
v-for="(evt, eIndex) in eventsForSlot(day, slot)" v-for="(evt, eIndex) in eventsForSlot(day, slot)"
:key="eIndex" :key="eIndex"
class="event-card" class="event-card"
:style="eventStyle(evt)" :style="eventStyle(evt)"
> >
<div class="event-title"> <div class="event-title">{{ evt.title }}</div>
{{ evt.title }} <div class="event-info">{{ evt.start }} - {{ evt.end }}</div>
</div>
<div class="event-info">
{{ evt.start }} - {{ evt.end }}
</div>
</div> </div>
</td> </td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
<!-- Barre d'onglets en bas, AVEC flèches gauche/droite -->
<div class="week-tabs"> <div class="week-tabs">
<!-- Flèche "précédent" --> <button class="arrow-btn" @click="prevPage" :disabled="startIndex === 0"></button>
<button
class="arrow-btn"
@click="prevPage"
:disabled="startIndex === 0"
>
</button>
<!-- Onglets affichés : seulement 'weeksToShow' semaines, via displayedWeeks -->
<button <button
v-for="(week, idx) in displayedWeeks" v-for="(week, idx) in displayedWeeks"
:key="idx" :key="idx"
class="week-tab-button" class="week-tab-button"
@click="goToWeek(week.monday)" @click="goToWeek(week.monday)"
> >
<!-- Affiche Sxx + JJ/MM, par ex. "S14 31/03" -->
S{{ week.isoWeek }} {{ formatDDMM(week.monday) }} S{{ week.isoWeek }} {{ formatDDMM(week.monday) }}
</button> </button>
<button
<!-- Flèche "suivant" --> class="arrow-btn"
<button @click="nextPage"
class="arrow-btn"
@click="nextPage"
:disabled="startIndex + weeksToShow >= allWeeks.length" :disabled="startIndex + weeksToShow >= allWeeks.length"
> >
@ -93,19 +77,15 @@
</template> </template>
<script> <script>
/**
* Calcule le numéro de semaine ISO pour une date donnée (1-53).
*/
function getIsoWeekNumber(date) { function getIsoWeekNumber(date) {
const tempDate = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate())); const tempDate = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
const dayNum = tempDate.getUTCDay() || 7; const dayNum = tempDate.getUTCDay() || 7;
tempDate.setUTCDate(tempDate.getUTCDate() + 4 - dayNum); tempDate.setUTCDate(tempDate.getUTCDate() + 4 - dayNum);
const yearStart = new Date(Date.UTC(tempDate.getUTCFullYear(), 0, 1)); const yearStart = new Date(Date.UTC(tempDate.getUTCFullYear(), 0, 1));
return Math.ceil(((tempDate - yearStart) / 86400000 + 1) / 7); return Math.ceil(((tempDate - yearStart) / 86400000 + 1) / 7);
} }
function formatDate(dateObj) { function formatDate(dateObj) {
// "2025-04-01"
const yyyy = dateObj.getFullYear(); const yyyy = dateObj.getFullYear();
const mm = String(dateObj.getMonth() + 1).padStart(2, "0"); const mm = String(dateObj.getMonth() + 1).padStart(2, "0");
const dd = String(dateObj.getDate()).padStart(2, "0"); const dd = String(dateObj.getDate()).padStart(2, "0");
@ -115,12 +95,10 @@ function formatDate(dateObj) {
export default { export default {
name: "AdeLikeAgenda", name: "AdeLikeAgenda",
data() { data() {
const currentMonday = new Date(2025, 2, 31); // Lundi 31/03/2025 const currentMonday = new Date(2025, 2, 31);
return { return {
currentMonday, currentMonday,
resourceName: "El Alaoui El Ismaili Omar", resourceName: "El Alaoui El Ismaili Omar",
// Créneaux horaires
timeSlots: [ timeSlots: [
{ start: "08:00", end: "08:30" }, { start: "08:00", end: "08:30" },
{ start: "08:30", end: "09:00" }, { start: "08:30", end: "09:00" },
@ -147,102 +125,13 @@ export default {
{ start: "19:00", end: "19:30" }, { start: "19:00", end: "19:30" },
{ start: "19:30", end: "20:00" }, { start: "19:30", end: "20:00" },
], ],
events: [],
// Exemples d'événements
events: [
{
day: "2025-03-31",
start: "09:30",
end: "10:40",
title: "Systèmes d'exploitation DS",
color: "#f44", // ex. rouge
},
{
day: "2025-03-31",
start: "10:40",
end: "11:15",
title: "Systèmes d'exploitation (suite)",
color: "#f44",
},
{
day: "2025-04-01",
start: "08:00",
end: "09:00",
title: "2A ESPAGNOL GPE 1",
color: "#f6f112",
},
{
day: "2025-04-01",
start: "09:00",
end: "10:10",
title: "Projet de Génie Logiciel",
color: "#ffe",
},
{
day: "2025-04-01",
start: "14:00",
end: "16:00",
title: "INFO ANGLAIS TOEIC",
color: "#0bc",
},
{
day: "2025-04-02",
start: "11:00",
end: "12:20",
title: "Intelligence artificielle",
color: "#ff7",
},
{
day: "2025-04-02",
start: "10:20",
end: "12:20",
title: "Projet Sys. exploitation",
color: "#f4a",
},
{
day: "2025-04-03",
start: "08:10",
end: "10:10",
title: "Projet de Réseaux",
color: "#aff",
},
{
day: "2025-04-04",
start: "14:00",
end: "16:00",
title: "Programmation Fonct.",
color: "#cca",
},
{
day: "2025-04-05",
start: "16:10",
end: "18:10",
title: "TD Intelligence Art.",
color: "#fa4",
},
{
day: "2025-04-06",
start: "13:00",
end: "14:00",
title: "À planifier",
color: "#ddd",
},
],
/* Tableau complet de semaines quon veut afficher dans la barre du bas. */
allWeeks: [], allWeeks: [],
/* On affiche 7 semaines à la fois. */
weeksToShow: 7, weeksToShow: 7,
/* Index de la première semaine affichée dans la barre. */
startIndex: 0, startIndex: 0,
}; };
}, },
computed: { computed: {
/**
* daysOfWeek : 7 jours (lundidimanche) depuis currentMonday
*/
daysOfWeek() { daysOfWeek() {
const result = []; const result = [];
for (let i = 0; i < 7; i++) { for (let i = 0; i < 7; i++) {
@ -252,88 +141,50 @@ export default {
} }
return result; return result;
}, },
/**
* isoWeekNumber : ex. 14 pour 31/03/2025.
*/
isoWeekNumber() { isoWeekNumber() {
return getIsoWeekNumber(this.currentMonday); return getIsoWeekNumber(this.currentMonday);
}, },
/**
* Les semaines réellement affichées dans la barre (7 à la fois).
*/
displayedWeeks() { displayedWeeks() {
return this.allWeeks.slice(this.startIndex, this.startIndex + this.weeksToShow); return this.allWeeks.slice(this.startIndex, this.startIndex + this.weeksToShow);
}, },
}, },
methods: { methods: {
/**
* Crée la liste allWeeks pour X semaines (par ex. 15),
* depuis la date initiale currentMonday.
*/
initWeeks() { initWeeks() {
// On définit par ex. 15 semaines à partir de currentMonday
const totalCount = 15; const totalCount = 15;
const baseDate = new Date(this.currentMonday); const baseDate = new Date(this.currentMonday);
// Pour s'assurer qu'on part du lundi "31/03/2025" dans allWeeks[0]
// (ou un autre point de départ si tu veux).
// Sinon, tu peux partir d'une autre date plus ancienne.
for (let i = 0; i < totalCount; i++) { for (let i = 0; i < totalCount; i++) {
const temp = new Date(baseDate); const temp = new Date(baseDate);
temp.setDate(baseDate.getDate() + i * 7); temp.setDate(baseDate.getDate() + i * 7);
this.allWeeks.push({ this.allWeeks.push({
monday: temp, monday: temp,
isoWeek: getIsoWeekNumber(temp), isoWeek: getIsoWeekNumber(temp),
}); });
} }
}, },
/**
* Retourne les événements (ou un seul) pour un jour + créneau.
*/
eventsForSlot(dayDate, slot) { eventsForSlot(dayDate, slot) {
const dayStr = formatDate(dayDate); const dayStr = formatDate(dayDate);
return this.events.filter( return this.events.filter(
(evt) => evt.day === dayStr && evt.start === slot.start (evt) => evt.day === dayStr && evt.start === slot.start
); );
}, },
/**
* Style d'un event (couleur, etc.)
*/
eventStyle(evt) { eventStyle(evt) {
return { return {
backgroundColor: evt.color || "#cef", backgroundColor: evt.color || "#cef",
}; };
}, },
/**
* Format "dd/mm/yyyy"
*/
formatDateShort(dateObj) { formatDateShort(dateObj) {
const dd = String(dateObj.getDate()).padStart(2, "0"); const dd = String(dateObj.getDate()).padStart(2, "0");
const mm = String(dateObj.getMonth() + 1).padStart(2, "0"); const mm = String(dateObj.getMonth() + 1).padStart(2, "0");
const yyyy = dateObj.getFullYear(); const yyyy = dateObj.getFullYear();
return `${dd}/${mm}/${yyyy}`; return `${dd}/${mm}/${yyyy}`;
}, },
/**
* Format "JJ/MM" (sans l'année)
*/
formatDDMM(dateObj) { formatDDMM(dateObj) {
const dd = String(dateObj.getDate()).padStart(2, "0"); const dd = String(dateObj.getDate()).padStart(2, "0");
const mm = String(dateObj.getMonth() + 1).padStart(2, "0"); const mm = String(dateObj.getMonth() + 1).padStart(2, "0");
return `${dd}/${mm}`; return `${dd}/${mm}`;
}, },
/**
* Renvoie "Lundi", "Mardi", etc.
*/
weekdayLabel(dateObj) { weekdayLabel(dateObj) {
const dayIndex = dateObj.getDay(); const dayIndex = dateObj.getDay();
const labels = [ const labels = [
"Dimanche", "Dimanche",
"Lundi", "Lundi",
@ -345,10 +196,6 @@ export default {
]; ];
return labels[dayIndex]; return labels[dayIndex];
}, },
/**
* Aller à la semaine week.monday dans le planning
*/
goToWeek(mondayDate) { goToWeek(mondayDate) {
this.currentMonday = new Date( this.currentMonday = new Date(
mondayDate.getFullYear(), mondayDate.getFullYear(),
@ -356,24 +203,69 @@ export default {
mondayDate.getDate() mondayDate.getDate()
); );
}, },
/* Flèche gauche : on recule le startIndex si possible */
prevPage() { prevPage() {
if (this.startIndex > 0) { if (this.startIndex > 0) this.startIndex--;
this.startIndex--; },
} nextPage() {
if (this.startIndex + this.weeksToShow < this.allWeeks.length) this.startIndex++;
}, },
/* Flèche droite : on avance le startIndex si on peut encore afficher plus */ // 💡 NOUVELLE MÉTHODE : lecture .ics
nextPage() { handleFileUpload(event) {
if (this.startIndex + this.weeksToShow < this.allWeeks.length) { const file = event.target.files[0];
this.startIndex++; if (!file) return;
const reader = new FileReader();
reader.onload = (e) => {
const content = e.target.result;
this.parseICS(content);
};
reader.readAsText(file);
},
parseICS(text) {
const lines = text.split(/\r?\n/);
let currentEvent = null;
const events = [];
for (const line of lines) {
if (line === "BEGIN:VEVENT") {
currentEvent = {};
} else if (line === "END:VEVENT") {
if (currentEvent) events.push(currentEvent);
currentEvent = null;
} else if (currentEvent) {
if (line.startsWith("DTSTART")) {
currentEvent.start = this.parseICSTime(line);
} else if (line.startsWith("DTEND")) {
currentEvent.end = this.parseICSTime(line);
} else if (line.startsWith("SUMMARY")) {
currentEvent.title = line.split(":")[1] || "Sans titre";
}
}
} }
this.events = events.map((e) => ({
title: e.title,
day: e.start.date,
start: e.start.time,
end: e.end.time,
color: "#acf",
}));
},
parseICSTime(line) {
const match = line.match(/:(\d{8})T(\d{4})/);
if (!match) return { date: "", time: "" };
const dateStr = match[1];
const timeStr = match[2];
return {
date: `${dateStr.slice(0, 4)}-${dateStr.slice(4, 6)}-${dateStr.slice(6, 8)}`,
time: `${timeStr.slice(0, 2)}:${timeStr.slice(2, 4)}`,
};
}, },
}, },
/**
* Au montage, on initialise la liste allWeeks
*/
mounted() { mounted() {
this.initWeeks(); this.initWeeks();
}, },