• Non-Surf
  • hackeur, creation d'un mysession par gemini

<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Journal de Sessions de Surf</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
<style>
body {
font-family: 'Inter', sans-serif;
background-color: #f0f9ff; /* Tailwind's sky-50 /
}
.calendar-day.has-session {
background-color: #2563eb; /
Tailwind's blue-600 /
color: white;
border-radius: 50%;
position: relative;
}
.calendar-day.has-session::after {
content: '';
position: absolute;
bottom: 2px;
left: 50%;
transform: translateX(-50%);
width: 4px;
height: 4px;
background-color: white;
border-radius: 50%;
}
.calendar-day:hover {
background-color: #dbeafe; /
Tailwind's blue-100 /
}
.rating input[type="radio"] {
display: none;
}
.rating label {
cursor: pointer;
color: #cbd5e1; /
Tailwind's slate-300 /
font-size: 1.75rem; /
text-2xl or 3xl /
transition: color 0.2s;
}
.rating input[type="radio"]:checked ~ label,
.rating label:hover,
.rating label:hover ~ label {
color: #facc15; /
Tailwind's yellow-400 /
}
/
Custom scrollbar for session list /
.session-list-container::-webkit-scrollbar {
width: 8px;
}
.session-list-container::-webkit-scrollbar-track {
background: #e0f2fe; /
sky-100 /
}
.session-list-container::-webkit-scrollbar-thumb {
background-color: #38bdf8; /
sky-500 /
border-radius: 10px;
border: 2px solid #e0f2fe; /
sky-100 */
}
</style>
</head>
<body class="text-slate-800">
<div class="container mx-auto p-4 md:p-8 max-w-6xl">
<header class="mb-8 text-center">
<h1 class="text-4xl font-bold text-sky-700">🏄 Mon Journal de Surf 🌊</h1>
</header>

    <div class="grid grid-cols-1 md:grid-cols-3 gap-6">
        <div class="md:col-span-1 bg-white p-6 rounded-xl shadow-lg">
            <h2 class="text-2xl font-semibold mb-6 text-sky-600">Nouvelle Session</h2>
            <form id="sessionForm" class="space-y-4">
                <div>
                    <label for="sessionDate" class="block text-sm font-medium text-slate-700">Date</label>
                    <input type="date" id="sessionDate" name="sessionDate" required class="mt-1 block w-full rounded-md border-slate-300 shadow-sm focus:border-sky-500 focus:ring-sky-500 sm:text-sm p-2">
                </div>
                <div>
                    <label for="surfSpot" class="block text-sm font-medium text-slate-700">Spot de Surf</label>
                    <input type="text" id="surfSpot" name="surfSpot" required class="mt-1 block w-full rounded-md border-slate-300 shadow-sm focus:border-sky-500 focus:ring-sky-500 sm:text-sm p-2" placeholder="Ex: Parlementia">
                </div>
                <div>
                    <label for="waveSize" class="block text-sm font-medium text-slate-700">Taille des Vagues</label>
                    <input type="text" id="waveSize" name="waveSize" class="mt-1 block w-full rounded-md border-slate-300 shadow-sm focus:border-sky-500 focus:ring-sky-500 sm:text-sm p-2" placeholder="Ex: 1.5m, épaule...">
                </div>
                <div>
                    <label class="block text-sm font-medium text-slate-700">Note de la Session</label>
                    <div class="rating flex flex-row-reverse justify-end mt-1" id="sessionRating">
                        <input type="radio" id="star5" name="rating" value="5"><label for="star5" title="5 étoiles"><i class="fas fa-star"></i></label>
                        <input type="radio" id="star4" name="rating" value="4"><label for="star4" title="4 étoiles"><i class="fas fa-star"></i></label>
                        <input type="radio" id="star3" name="rating" value="3"><label for="star3" title="3 étoiles"><i class="fas fa-star"></i></label>
                        <input type="radio" id="star2" name="rating" value="2"><label for="star2" title="2 étoiles"><i class="fas fa-star"></i></label>
                        <input type="radio" id="star1" name="rating" value="1" checked><label for="star1" title="1 étoile"><i class="fas fa-star"></i></label>
                    </div>
                </div>

                <h3 class="text-lg font-medium text-sky-600 pt-2">Conditions Windguru (manuel)</h3>
                <div>
                    <label for="windSpeed" class="block text-sm font-medium text-slate-700">Vent (vitesse, direction)</label>
                    <div class="flex space-x-2">
                        <input type="text" id="windSpeed" name="windSpeed" class="mt-1 block w-1/2 rounded-md border-slate-300 shadow-sm focus:border-sky-500 focus:ring-sky-500 sm:text-sm p-2" placeholder="Ex: 15kts">
                        <input type="text" id="windDirection" name="windDirection" class="mt-1 block w-1/2 rounded-md border-slate-300 shadow-sm focus:border-sky-500 focus:ring-sky-500 sm:text-sm p-2" placeholder="Ex: NO">
                    </div>
                </div>
                 <div>
                    <label for="swellHeight" class="block text-sm font-medium text-slate-700">Houle (taille, période, direction)</label>
                    <div class="flex space-x-2">
                        <input type="text" id="swellHeight" name="swellHeight" class="mt-1 block w-1/3 rounded-md border-slate-300 shadow-sm focus:border-sky-500 focus:ring-sky-500 sm:text-sm p-2" placeholder="Ex: 2m">
                        <input type="text" id="swellPeriod" name="swellPeriod" class="mt-1 block w-1/3 rounded-md border-slate-300 shadow-sm focus:border-sky-500 focus:ring-sky-500 sm:text-sm p-2" placeholder="Ex: 10s">
                        <input type="text" id="swellDirection" name="swellDirection" class="mt-1 block w-1/3 rounded-md border-slate-300 shadow-sm focus:border-sky-500 focus:ring-sky-500 sm:text-sm p-2" placeholder="Ex: O">
                    </div>
                </div>
                <div>
                    <label for="notes" class="block text-sm font-medium text-slate-700">Notes</label>
                    <textarea id="notes" name="notes" rows="3" class="mt-1 block w-full rounded-md border-slate-300 shadow-sm focus:border-sky-500 focus:ring-sky-500 sm:text-sm p-2" placeholder="Planche utilisée, sensations..."></textarea>
                </div>
                <button type="submit" class="w-full bg-sky-600 hover:bg-sky-700 text-white font-semibold py-2 px-4 rounded-md shadow-md transition duration-150 ease-in-out">
                    <i class="fas fa-plus-circle mr-2"></i>Ajouter Session
                </button>
            </form>
        </div>

        <div class="md:col-span-2 space-y-6">
            <div class="bg-white p-6 rounded-xl shadow-lg">
                <div class="flex justify-between items-center mb-4">
                    <button id="prevMonth" class="p-2 rounded-md hover:bg-sky-100 text-sky-600"><i class="fas fa-chevron-left"></i></button>
                    <h2 id="calendarMonthYear" class="text-xl font-semibold text-sky-600"></h2>
                    <button id="nextMonth" class="p-2 rounded-md hover:bg-sky-100 text-sky-600"><i class="fas fa-chevron-right"></i></button>
                </div>
                <div id="calendarGrid" class="grid grid-cols-7 gap-1 text-center">
                    <div class="font-medium text-xs text-slate-500">Dim</div>
                    <div class="font-medium text-xs text-slate-500">Lun</div>
                    <div class="font-medium text-xs text-slate-500">Mar</div>
                    <div class="font-medium text-xs text-slate-500">Mer</div>
                    <div class="font-medium text-xs text-slate-500">Jeu</div>
                    <div class="font-medium text-xs text-slate-500">Ven</div>
                    <div class="font-medium text-xs text-slate-500">Sam</div>
                    </div>
            </div>

            <div class="bg-white p-6 rounded-xl shadow-lg">
                <h2 class="text-2xl font-semibold mb-4 text-sky-600">Sessions Enregistrées</h2>
                <div id="sessionList" class="space-y-4 session-list-container max-h-[600px] overflow-y-auto pr-2">
                    <p class="text-slate-500 italic">Aucune session pour le moment.</p>
                </div>
            </div>
        </div>
    </div>
    
    <div id="sessionModal" class="fixed inset-0 bg-gray-600 bg-opacity-50 overflow-y-auto h-full w-full hidden z-50">
        <div class="relative top-20 mx-auto p-5 border w-full max-w-lg shadow-lg rounded-md bg-white">
            <div class="mt-3 text-center">
                <h3 class="text-2xl leading-6 font-medium text-sky-700 mb-4" id="modalSessionTitle">Détails de la Session</h3>
                <div class="mt-2 px-7 py-3 space-y-3 text-left" id="modalSessionDetails">
                    </div>
                <div class="items-center px-4 py-3">
                    <button id="closeModal" class="px-4 py-2 bg-sky-600 text-white text-base font-medium rounded-md w-full shadow-sm hover:bg-sky-700 focus:outline-none focus:ring-2 focus:ring-sky-500">
                        Fermer
                    </button>
                </div>
            </div>
        </div>
    </div>

</div>

<script>
    // Attend que le DOM soit entièrement chargé
    document.addEventListener('DOMContentLoaded', () => {
        const sessionForm = document.getElementById('sessionForm');
        const sessionList = document.getElementById('sessionList');
        const calendarGrid = document.getElementById('calendarGrid');
        const calendarMonthYear = document.getElementById('calendarMonthYear');
        const prevMonthButton = document.getElementById('prevMonth');
        const nextMonthButton = document.getElementById('nextMonth');
        const sessionModal = document.getElementById('sessionModal');
        const closeModalButton = document.getElementById('closeModal');
        const modalSessionTitle = document.getElementById('modalSessionTitle');
        const modalSessionDetails = document.getElementById('modalSessionDetails');

        // Définit la date actuelle dans le champ de date par défaut
        const today = new Date().toISOString().split('T')[0];
        document.getElementById('sessionDate').value = today;
        
        let currentDate = new Date(); // Date pour la navigation du calendrier
        let sessions = JSON.parse(localStorage.getItem('surfSessions')) || [];

        // Fonction pour sauvegarder les sessions dans localStorage
        const saveSessions = () => {
            localStorage.setItem('surfSessions', JSON.stringify(sessions));
        };

        // Fonction pour afficher les sessions
        const renderSessions = (sessionsToRender = sessions) => {
            sessionList.innerHTML = ''; // Vide la liste actuelle
            if (sessionsToRender.length === 0) {
                sessionList.innerHTML = '<p class="text-slate-500 italic">Aucune session pour le moment ou pour cette date.</p>';
                return;
            }

            // Trie les sessions par date (plus récente en premier)
            const sortedSessions = [...sessionsToRender].sort((a, b) => new Date(b.date) - new Date(a.date));

            sortedSessions.forEach((session, index) => {
                const sessionElement = document.createElement('div');
                sessionElement.classList.add('p-4', 'bg-sky-50', 'rounded-lg', 'shadow');
                
                // Formatte la date pour l'affichage
                const sessionDateFormatted = new Date(session.date).toLocaleDateString('fr-FR', { year: 'numeric', month: 'long', day: 'numeric' });
                
                // Génère les étoiles pour la note
                let ratingStars = '';
                for (let i = 0; i < 5; i++) {
                    ratingStars += `<i class="fas fa-star ${i < session.rating ? 'text-yellow-400' : 'text-slate-300'}"></i>`;
                }

                sessionElement.innerHTML = `
                    <div class="flex justify-between items-start">
                        <div>
                            <h3 class="text-lg font-semibold text-sky-700">${session.spot} - ${sessionDateFormatted}</h3>
                            <p class="text-sm text-slate-600">Vagues: ${session.waveSize || 'N/A'}</p>
                            <p class="text-sm text-slate-600">Note: <span class="ml-1">${ratingStars}</span></p>
                        </div>
                        <div>
                            <button data-id="${session.id}" class="view-button text-sky-500 hover:text-sky-700 mr-2"><i class="fas fa-eye"></i></button>
                            <button data-id="${session.id}" class="delete-button text-red-500 hover:text-red-700"><i class="fas fa-trash"></i></button>
                        </div>
                    </div>
                `;
                sessionList.appendChild(sessionElement);
            });
        };

        // Fonction pour afficher le calendrier
        const renderCalendar = () => {
            calendarGrid.innerHTML = ''; // Vide la grille actuelle
             // Ajoute les jours de la semaine en en-tête
            const daysOfWeek = ['Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam'];
            daysOfWeek.forEach(day => {
                const dayEl = document.createElement('div');
                dayEl.className = 'font-medium text-xs text-slate-500 py-2';
                dayEl.textContent = day;
                calendarGrid.appendChild(dayEl);
            });

            const year = currentDate.getFullYear();
            const month = currentDate.getMonth(); // 0-11

            calendarMonthYear.textContent = `${currentDate.toLocaleDateString('fr-FR', { month: 'long' })} ${year}`;

            const firstDayOfMonth = new Date(year, month, 1).getDay(); // 0 (Dim) - 6 (Sam)
            const daysInMonth = new Date(year, month + 1, 0).getDate();

            // Remplit les jours vides au début du mois
            for (let i = 0; i < firstDayOfMonth; i++) {
                const emptyCell = document.createElement('div');
                calendarGrid.appendChild(emptyCell);
            }

            // Remplit les jours du mois
            for (let day = 1; day <= daysInMonth; day++) {
                const dayCell = document.createElement('div');
                dayCell.textContent = day;
                dayCell.classList.add('p-2', 'cursor-pointer', 'calendar-day', 'rounded-full', 'text-sm');
                
                const cellDate = new Date(year, month, day);
                const cellDateString = cellDate.toISOString().split('T')[0];

                // Vérifie s'il y a des sessions pour ce jour
                if (sessions.some(session => session.date === cellDateString)) {
                    dayCell.classList.add('has-session');
                }
                
                // Met en évidence le jour actuel
                if (cellDateString === new Date().toISOString().split('T')[0]) {
                    dayCell.classList.add('bg-sky-200', 'text-sky-700', 'font-bold');
                }

                dayCell.addEventListener('click', () => {
                    document.getElementById('sessionDate').value = cellDateString;
                    // Filtre les sessions pour le jour cliqué
                    const sessionsForDay = sessions.filter(session => session.date === cellDateString);
                    if (sessionsForDay.length > 0) {
                        renderSessions(sessionsForDay);
                    } else {
                        sessionList.innerHTML = `<p class="text-slate-500 italic">Aucune session enregistrée pour le ${cellDate.toLocaleDateString('fr-FR')}.</p>`;
                    }
                });
                calendarGrid.appendChild(dayCell);
            }
        };
        
        // Gestionnaire de soumission du formulaire
        sessionForm.addEventListener('submit', (e) => {
            e.preventDefault();
            const formData = new FormData(sessionForm);
            const ratingInput = document.querySelector('input[name="rating"]:checked');

            const newSession = {
                id: Date.now().toString(), // ID unique basé sur le timestamp
                date: formData.get('sessionDate'),
                spot: formData.get('surfSpot'),
                waveSize: formData.get('waveSize'),
                rating: ratingInput ? parseInt(ratingInput.value) : 1,
                windSpeed: formData.get('windSpeed'),
                windDirection: formData.get('windDirection'),
                swellHeight: formData.get('swellHeight'),
                swellPeriod: formData.get('swellPeriod'),
                swellDirection: formData.get('swellDirection'),
                notes: formData.get('notes')
            };

            sessions.push(newSession);
            saveSessions();
            renderSessions();
            renderCalendar(); // Met à jour le calendrier pour marquer le nouveau jour
            sessionForm.reset(); // Réinitialise le formulaire
            document.getElementById('sessionDate').value = today; // Remet la date du jour
            // Réinitialise les étoiles à 1
            document.getElementById('star1').checked = true; 
        });

        // Gestionnaire pour les boutons de suppression et de vue
        sessionList.addEventListener('click', (e) => {
            if (e.target.closest('.delete-button')) {
                const button = e.target.closest('.delete-button');
                const sessionId = button.dataset.id;
                if (confirm('Êtes-vous sûr de vouloir supprimer cette session ?')) {
                    sessions = sessions.filter(session => session.id !== sessionId);
                    saveSessions();
                    renderSessions();
                    renderCalendar();
                }
            }
            if (e.target.closest('.view-button')) {
                const button = e.target.closest('.view-button');
                const sessionId = button.dataset.id;
                const session = sessions.find(s => s.id === sessionId);
                if (session) {
                    showSessionModal(session);
                }
            }
        });
        
        // Fonction pour afficher la modale avec les détails de la session
        const showSessionModal = (session) => {
            const sessionDateFormatted = new Date(session.date).toLocaleDateString('fr-FR', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' });
            modalSessionTitle.textContent = `Session à ${session.spot}`;
            
            let ratingStarsModal = '';
            for (let i = 0; i < 5; i++) {
                ratingStarsModal += `<i class="fas fa-star ${i < session.rating ? 'text-yellow-400' : 'text-slate-300'}"></i>`;
            }

            modalSessionDetails.innerHTML = `
                <p><strong>Date :</strong> ${sessionDateFormatted}</p>
                <p><strong>Spot :</strong> ${session.spot}</p>
                <p><strong>Taille des vagues :</strong> ${session.waveSize || 'N/A'}</p>
                <p><strong>Note :</strong> <span class="ml-1">${ratingStarsModal}</span></p>
                <hr class="my-2">
                <p class="font-semibold text-sky-600">Conditions Windguru :</p>
                <p><strong>Vent :</strong> ${session.windSpeed || 'N/A'} ${session.windDirection || ''}</p>
                <p><strong>Houle :</strong> ${session.swellHeight || 'N/A'} - ${session.swellPeriod || 'N/A'} - ${session.swellDirection || ''}</p>
                <hr class="my-2">
                <p><strong>Notes :</strong></p>
                <p class="whitespace-pre-wrap">${session.notes || 'Aucune note.'}</p>
            `;
            sessionModal.classList.remove('hidden');
        };

        // Fermer la modale
        closeModalButton.addEventListener('click', () => {
            sessionModal.classList.add('hidden');
        });
        // Fermer la modale en cliquant à l'extérieur
        sessionModal.addEventListener('click', (e) => {
            if (e.target === sessionModal) {
                sessionModal.classList.add('hidden');
            }
        });

        // Navigation du calendrier
        prevMonthButton.addEventListener('click', () => {
            currentDate.setMonth(currentDate.getMonth() - 1);
            renderCalendar();
        });

        nextMonthButton.addEventListener('click', () => {
            currentDate.setMonth(currentDate.getMonth() + 1);
            renderCalendar();
        });

        // Initialisation de l'affichage
        renderSessions();
        renderCalendar();
    });
</script>

</body>
</html>

Squares77

tu prends le code tu l'enregistre dans note sous un .html et apres ça lance sur un naviigateur

je l'ai rebossé
je renvoi le code

Squares77 C'est parce que ça tourne sur son NAS

<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Journal de Sessions de Surf</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
<style>
body {
font-family: 'Inter', sans-serif;
background-color: #f0f9ff; /* Tailwind's sky-50 /
}
.calendar-day.has-session {
background-color: #2563eb; /
Tailwind's blue-600 /
color: white;
border-radius: 50%;
position: relative;
}
.calendar-day.has-session::after {
content: '';
position: absolute;
bottom: 2px;
left: 50%;
transform: translateX(-50%);
width: 4px;
height: 4px;
background-color: white;
border-radius: 50%;
}
.calendar-day:hover {
background-color: #dbeafe; /
Tailwind's blue-100 /
}
.rating input[type="radio"] {
display: none;
}
.rating label {
cursor: pointer;
color: #cbd5e1; /
Tailwind's slate-300 /
font-size: 1.75rem; /
text-2xl or 3xl /
transition: color 0.2s;
}
.rating input[type="radio"]:checked ~ label,
.rating label:hover,
.rating label:hover ~ label {
color: #facc15; /
Tailwind's yellow-400 /
}
/
Custom scrollbar for session list and stats /
.scrollable-container::-webkit-scrollbar {
width: 8px;
}
.scrollable-container::-webkit-scrollbar-track {
background: #e0f2fe; /
sky-100 /
}
.scrollable-container::-webkit-scrollbar-thumb {
background-color: #38bdf8; /
sky-500 /
border-radius: 10px;
border: 2px solid #e0f2fe; /
sky-100 /
}
.stat-item {
padding: 0.5rem;
background-color: #f0f9ff; /
sky-50 /
border-radius: 0.375rem; /
rounded-md */
margin-bottom: 0.5rem;
}
</style>
</head>
<body class="text-slate-800">
<div class="container mx-auto p-4 md:p-8 max-w-6xl">
<header class="mb-8 text-center">
<h1 class="text-4xl font-bold text-sky-700">🏄 Mon Journal de Surf 🌊</h1>
</header>

    <div class="grid grid-cols-1 md:grid-cols-3 gap-6">
        <div class="md:col-span-1 bg-white p-6 rounded-xl shadow-lg">
            <h2 class="text-2xl font-semibold mb-6 text-sky-600">Nouvelle Session</h2>
            <form id="sessionForm" class="space-y-4">
                <div>
                    <label for="sessionDate" class="block text-sm font-medium text-slate-700">Date</label>
                    <input type="date" id="sessionDate" name="sessionDate" required class="mt-1 block w-full rounded-md border-slate-300 shadow-sm focus:border-sky-500 focus:ring-sky-500 sm:text-sm p-2">
                </div>
                <div>
                    <label for="surfSpot" class="block text-sm font-medium text-slate-700">Spot de Surf</label>
                    <input type="text" id="surfSpot" name="surfSpot" required class="mt-1 block w-full rounded-md border-slate-300 shadow-sm focus:border-sky-500 focus:ring-sky-500 sm:text-sm p-2" placeholder="Ex: Parlementia">
                </div>
                <div>
                    <label for="waveSize" class="block text-sm font-medium text-slate-700">Taille des Vagues</label>
                    <input type="text" id="waveSize" name="waveSize" class="mt-1 block w-full rounded-md border-slate-300 shadow-sm focus:border-sky-500 focus:ring-sky-500 sm:text-sm p-2" placeholder="Ex: 1.5m, épaule...">
                </div>
                <div>
                    <label class="block text-sm font-medium text-slate-700">Note de la Session</label>
                    <div class="rating flex flex-row-reverse justify-end mt-1" id="sessionRating">
                        <input type="radio" id="star5" name="rating" value="5"><label for="star5" title="5 étoiles"><i class="fas fa-star"></i></label>
                        <input type="radio" id="star4" name="rating" value="4"><label for="star4" title="4 étoiles"><i class="fas fa-star"></i></label>
                        <input type="radio" id="star3" name="rating" value="3"><label for="star3" title="3 étoiles"><i class="fas fa-star"></i></label>
                        <input type="radio" id="star2" name="rating" value="2"><label for="star2" title="2 étoiles"><i class="fas fa-star"></i></label>
                        <input type="radio" id="star1" name="rating" value="1" checked><label for="star1" title="1 étoile"><i class="fas fa-star"></i></label>
                    </div>
                </div>

                <h3 class="text-lg font-medium text-sky-600 pt-2">Conditions Windguru (manuel)</h3>
                <div>
                    <label for="windSpeed" class="block text-sm font-medium text-slate-700">Vent (vitesse, direction)</label>
                    <div class="flex space-x-2">
                        <input type="text" id="windSpeed" name="windSpeed" class="mt-1 block w-1/2 rounded-md border-slate-300 shadow-sm focus:border-sky-500 focus:ring-sky-500 sm:text-sm p-2" placeholder="Ex: 15kts">
                        <input type="text" id="windDirection" name="windDirection" class="mt-1 block w-1/2 rounded-md border-slate-300 shadow-sm focus:border-sky-500 focus:ring-sky-500 sm:text-sm p-2" placeholder="Ex: NO">
                    </div>
                </div>
                 <div>
                    <label for="swellHeight" class="block text-sm font-medium text-slate-700">Houle (taille, période, direction)</label>
                    <div class="flex space-x-2">
                        <input type="text" id="swellHeight" name="swellHeight" class="mt-1 block w-1/3 rounded-md border-slate-300 shadow-sm focus:border-sky-500 focus:ring-sky-500 sm:text-sm p-2" placeholder="Ex: 2m">
                        <input type="text" id="swellPeriod" name="swellPeriod" class="mt-1 block w-1/3 rounded-md border-slate-300 shadow-sm focus:border-sky-500 focus:ring-sky-500 sm:text-sm p-2" placeholder="Ex: 10s">
                        <input type="text" id="swellDirection" name="swellDirection" class="mt-1 block w-1/3 rounded-md border-slate-300 shadow-sm focus:border-sky-500 focus:ring-sky-500 sm:text-sm p-2" placeholder="Ex: O">
                    </div>
                </div>
                <div>
                    <label for="notes" class="block text-sm font-medium text-slate-700">Notes</label>
                    <textarea id="notes" name="notes" rows="3" class="mt-1 block w-full rounded-md border-slate-300 shadow-sm focus:border-sky-500 focus:ring-sky-500 sm:text-sm p-2" placeholder="Planche utilisée, sensations..."></textarea>
                </div>
                <button type="submit" class="w-full bg-sky-600 hover:bg-sky-700 text-white font-semibold py-2 px-4 rounded-md shadow-md transition duration-150 ease-in-out">
                    <i class="fas fa-plus-circle mr-2"></i>Ajouter Session
                </button>
            </form>
        </div>

        <div class="md:col-span-2 space-y-6">
            <div class="bg-white p-6 rounded-xl shadow-lg">
                <div class="flex justify-between items-center mb-4">
                    <button id="prevMonth" class="p-2 rounded-md hover:bg-sky-100 text-sky-600"><i class="fas fa-chevron-left"></i></button>
                    <h2 id="calendarMonthYear" class="text-xl font-semibold text-sky-600"></h2>
                    <button id="nextMonth" class="p-2 rounded-md hover:bg-sky-100 text-sky-600"><i class="fas fa-chevron-right"></i></button>
                </div>
                <div id="calendarGrid" class="grid grid-cols-7 gap-1 text-center">
                    <div class="font-medium text-xs text-slate-500">Dim</div>
                    <div class="font-medium text-xs text-slate-500">Lun</div>
                    <div class="font-medium text-xs text-slate-500">Mar</div>
                    <div class="font-medium text-xs text-slate-500">Mer</div>
                    <div class="font-medium text-xs text-slate-500">Jeu</div>
                    <div class="font-medium text-xs text-slate-500">Ven</div>
                    <div class="font-medium text-xs text-slate-500">Sam</div>
                    </div>
            </div>

            <div class="bg-white p-6 rounded-xl shadow-lg">
                <h2 class="text-2xl font-semibold mb-4 text-sky-600">Sessions Enregistrées</h2>
                <div id="sessionList" class="space-y-4 scrollable-container max-h-[400px] overflow-y-auto pr-2">
                    <p class="text-slate-500 italic">Aucune session pour le moment.</p>
                </div>
            </div>

            <div class="bg-white p-6 rounded-xl shadow-lg">
                <h2 class="text-2xl font-semibold mb-4 text-sky-600">Statistiques</h2>
                <div id="statsContainer" class="space-y-4 scrollable-container max-h-[400px] overflow-y-auto pr-2">
                    <div>
                        <h3 class="text-lg font-medium text-sky-500 mb-2">Sessions par Mois :</h3>
                        <div id="statsByMonth" class="text-sm text-slate-700"></div>
                    </div>
                    <div>
                        <h3 class="text-lg font-medium text-sky-500 mb-2">Sessions par Spot :</h3>
                        <div id="statsBySpot" class="text-sm text-slate-700"></div>
                    </div>
                    <div>
                        <h3 class="text-lg font-medium text-sky-500 mb-2">Spots par Note :</h3>
                        <div id="statsByRatingSpot" class="text-sm text-slate-700"></div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    
    <div id="sessionModal" class="fixed inset-0 bg-gray-600 bg-opacity-50 overflow-y-auto h-full w-full hidden z-50">
        <div class="relative top-20 mx-auto p-5 border w-full max-w-lg shadow-lg rounded-md bg-white">
            <div class="mt-3 text-center">
                <h3 class="text-2xl leading-6 font-medium text-sky-700 mb-4" id="modalSessionTitle">Détails de la Session</h3>
                <div class="mt-2 px-7 py-3 space-y-3 text-left" id="modalSessionDetails">
                    </div>
                <div class="items-center px-4 py-3">
                    <button id="closeModal" class="px-4 py-2 bg-sky-600 text-white text-base font-medium rounded-md w-full shadow-sm hover:bg-sky-700 focus:outline-none focus:ring-2 focus:ring-sky-500">
                        Fermer
                    </button>
                </div>
            </div>
        </div>
    </div>

</div>

<script>
    // Attend que le DOM soit entièrement chargé
    document.addEventListener('DOMContentLoaded', () => {
        const sessionForm = document.getElementById('sessionForm');
        const sessionList = document.getElementById('sessionList');
        const calendarGrid = document.getElementById('calendarGrid');
        const calendarMonthYear = document.getElementById('calendarMonthYear');
        const prevMonthButton = document.getElementById('prevMonth');
        const nextMonthButton = document.getElementById('nextMonth');
        const sessionModal = document.getElementById('sessionModal');
        const closeModalButton = document.getElementById('closeModal');
        const modalSessionTitle = document.getElementById('modalSessionTitle');
        const modalSessionDetails = document.getElementById('modalSessionDetails');

        const statsByMonthDiv = document.getElementById('statsByMonth');
        const statsBySpotDiv = document.getElementById('statsBySpot');
        const statsByRatingSpotDiv = document.getElementById('statsByRatingSpot');


        // Définit la date actuelle dans le champ de date par défaut
        const today = new Date().toISOString().split('T')[0];
        document.getElementById('sessionDate').value = today;
        
        let currentDate = new Date(); // Date pour la navigation du calendrier
        let sessions = JSON.parse(localStorage.getItem('surfSessions')) || [];

        // Fonction pour sauvegarder les sessions dans localStorage
        const saveSessions = () => {
            localStorage.setItem('surfSessions', JSON.stringify(sessions));
        };

        // Fonction pour afficher les sessions
        const renderSessions = (sessionsToRender = sessions) => {
            sessionList.innerHTML = ''; // Vide la liste actuelle
            if (sessionsToRender.length === 0) {
                sessionList.innerHTML = '<p class="text-slate-500 italic">Aucune session pour le moment ou pour cette date.</p>';
                return;
            }

            // Trie les sessions par date (plus récente en premier)
            const sortedSessions = [...sessionsToRender].sort((a, b) => new Date(b.date) - new Date(a.date));

            sortedSessions.forEach((session) => {
                const sessionElement = document.createElement('div');
                sessionElement.classList.add('p-4', 'bg-sky-50', 'rounded-lg', 'shadow');
                
                const sessionDateFormatted = new Date(session.date).toLocaleDateString('fr-FR', { year: 'numeric', month: 'long', day: 'numeric' });
                
                let ratingStars = '';
                for (let i = 0; i < 5; i++) {
                    ratingStars += `<i class="fas fa-star ${i < session.rating ? 'text-yellow-400' : 'text-slate-300'}"></i>`;
                }

                sessionElement.innerHTML = `
                    <div class="flex justify-between items-start">
                        <div>
                            <h3 class="text-lg font-semibold text-sky-700">${session.spot} - ${sessionDateFormatted}</h3>
                            <p class="text-sm text-slate-600">Vagues: ${session.waveSize || 'N/A'}</p>
                            <p class="text-sm text-slate-600">Note: <span class="ml-1">${ratingStars}</span></p>
                        </div>
                        <div>
                            <button data-id="${session.id}" class="view-button text-sky-500 hover:text-sky-700 mr-2"><i class="fas fa-eye"></i></button>
                            <button data-id="${session.id}" class="delete-button text-red-500 hover:text-red-700"><i class="fas fa-trash"></i></button>
                        </div>
                    </div>
                `;
                sessionList.appendChild(sessionElement);
            });
        };

        // Fonction pour afficher le calendrier
        const renderCalendar = () => {
            calendarGrid.innerHTML = ''; 
            const daysOfWeek = ['Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam'];
            daysOfWeek.forEach(day => {
                const dayEl = document.createElement('div');
                dayEl.className = 'font-medium text-xs text-slate-500 py-2';
                dayEl.textContent = day;
                calendarGrid.appendChild(dayEl);
            });

            const year = currentDate.getFullYear();
            const month = currentDate.getMonth(); 

            calendarMonthYear.textContent = `${currentDate.toLocaleDateString('fr-FR', { month: 'long' })} ${year}`;

            const firstDayOfMonth = new Date(year, month, 1).getDay(); 
            const daysInMonth = new Date(year, month + 1, 0).getDate();

            for (let i = 0; i < firstDayOfMonth; i++) {
                const emptyCell = document.createElement('div');
                calendarGrid.appendChild(emptyCell);
            }

            for (let day = 1; day <= daysInMonth; day++) {
                const dayCell = document.createElement('div');
                dayCell.textContent = day;
                dayCell.classList.add('p-2', 'cursor-pointer', 'calendar-day', 'rounded-full', 'text-sm');
                
                const cellDate = new Date(year, month, day);
                const cellDateString = cellDate.toISOString().split('T')[0];

                if (sessions.some(session => session.date === cellDateString)) {
                    dayCell.classList.add('has-session');
                }
                
                if (cellDateString === new Date().toISOString().split('T')[0]) {
                    dayCell.classList.add('bg-sky-200', 'text-sky-700', 'font-bold');
                }

                dayCell.addEventListener('click', () => {
                    document.getElementById('sessionDate').value = cellDateString;
                    const sessionsForDay = sessions.filter(session => session.date === cellDateString);
                    if (sessionsForDay.length > 0) {
                        renderSessions(sessionsForDay);
                    } else {
                        sessionList.innerHTML = `<p class="text-slate-500 italic">Aucune session enregistrée pour le ${cellDate.toLocaleDateString('fr-FR')}.</p>`;
                    }
                });
                calendarGrid.appendChild(dayCell);
            }
        };

        // Fonctions pour calculer et afficher les statistiques
        const renderStatistics = () => {
            if (sessions.length === 0) {
                statsByMonthDiv.innerHTML = '<p class="italic">Aucune donnée.</p>';
                statsBySpotDiv.innerHTML = '<p class="italic">Aucune donnée.</p>';
                statsByRatingSpotDiv.innerHTML = '<p class="italic">Aucune donnée.</p>';
                return;
            }

            // Stats par mois
            const sessionsByMonth = sessions.reduce((acc, session) => {
                const monthYear = new Date(session.date).toLocaleDateString('fr-FR', { year: 'numeric', month: 'long' });
                acc[monthYear] = (acc[monthYear] || 0) + 1;
                return acc;
            }, {});
            statsByMonthDiv.innerHTML = Object.entries(sessionsByMonth)
                .sort((a,b) => new Date(b[0].split(" ")[1], getMonthIndex(b[0].split(" ")[0])) - new Date(a[0].split(" ")[1], getMonthIndex(a[0].split(" ")[0]))) // Trie par date décroissante
                .map(([key, value]) => `<div class="stat-item">${key}: ${value} session(s)</div>`).join('');

            // Stats par spot
            const sessionsBySpot = sessions.reduce((acc, session) => {
                acc[session.spot] = (acc[session.spot] || 0) + 1;
                return acc;
            }, {});
            statsBySpotDiv.innerHTML = Object.entries(sessionsBySpot)
                .sort((a,b) => b[1] - a[1]) // Trie par nombre de sessions décroissant
                .map(([key, value]) => `<div class="stat-item">${key}: ${value} session(s)</div>`).join('');

            // Stats spots par note
            let statsByRatingHtml = '';
            for (let i = 5; i >= 1; i--) { // De 5 étoiles à 1 étoile
                const sessionsWithRating = sessions.filter(s => s.rating === i);
                if (sessionsWithRating.length > 0) {
                    const spotsForRating = sessionsWithRating.reduce((acc, session) => {
                        acc[session.spot] = (acc[session.spot] || 0) + 1;
                        return acc;
                    }, {});
                    
                    const spotsList = Object.entries(spotsForRating)
                        .sort((a,b) => b[1] - a[1]) // Trie par nombre de sessions décroissant
                        .map(([spot, count]) => `${spot} (${count})`)
                        .join(', ');
                    
                    if (spotsList) {
                         statsByRatingHtml += `<div class="stat-item"><strong>${i} étoile(s):</strong> ${spotsList}</div>`;
                    }
                }
            }
            statsByRatingSpotDiv.innerHTML = statsByRatingHtml || '<p class="italic">Aucune donnée de note.</p>';
        };
        
        // Helper function to get month index for sorting
        const getMonthIndex = (monthName) => {
            const months = ["janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre"];
            return months.indexOf(monthName.toLowerCase());
        };
        
        // Gestionnaire de soumission du formulaire
        sessionForm.addEventListener('submit', (e) => {
            e.preventDefault();
            const formData = new FormData(sessionForm);
            const ratingInput = document.querySelector('input[name="rating"]:checked');

            const newSession = {
                id: Date.now().toString(), 
                date: formData.get('sessionDate'),
                spot: formData.get('surfSpot').trim() || "Spot inconnu", // Ajout d'une valeur par défaut
                waveSize: formData.get('waveSize'),
                rating: ratingInput ? parseInt(ratingInput.value) : 1,
                windSpeed: formData.get('windSpeed'),
                windDirection: formData.get('windDirection'),
                swellHeight: formData.get('swellHeight'),
                swellPeriod: formData.get('swellPeriod'),
                swellDirection: formData.get('swellDirection'),
                notes: formData.get('notes')
            };

            sessions.push(newSession);
            saveSessions();
            renderSessions();
            renderCalendar(); 
            renderStatistics(); // Met à jour les statistiques
            sessionForm.reset(); 
            document.getElementById('sessionDate').value = today; 
            document.getElementById('star1').checked = true; 
        });

        // Gestionnaire pour les boutons de suppression et de vue
        sessionList.addEventListener('click', (e) => {
            if (e.target.closest('.delete-button')) {
                const button = e.target.closest('.delete-button');
                const sessionId = button.dataset.id;
                if (confirm('Êtes-vous sûr de vouloir supprimer cette session ?')) {
                    sessions = sessions.filter(session => session.id !== sessionId);
                    saveSessions();
                    renderSessions();
                    renderCalendar();
                    renderStatistics(); // Met à jour les statistiques
                }
            }
            if (e.target.closest('.view-button')) {
                const button = e.target.closest('.view-button');
                const sessionId = button.dataset.id;
                const session = sessions.find(s => s.id === sessionId);
                if (session) {
                    showSessionModal(session);
                }
            }
        });
        
        const showSessionModal = (session) => {
            const sessionDateFormatted = new Date(session.date).toLocaleDateString('fr-FR', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' });
            modalSessionTitle.textContent = `Session à ${session.spot}`;
            
            let ratingStarsModal = '';
            for (let i = 0; i < 5; i++) {
                ratingStarsModal += `<i class="fas fa-star ${i < session.rating ? 'text-yellow-400' : 'text-slate-300'}"></i>`;
            }

            modalSessionDetails.innerHTML = `
                <p><strong>Date :</strong> ${sessionDateFormatted}</p>
                <p><strong>Spot :</strong> ${session.spot}</p>
                <p><strong>Taille des vagues :</strong> ${session.waveSize || 'N/A'}</p>
                <p><strong>Note :</strong> <span class="ml-1">${ratingStarsModal}</span></p>
                <hr class="my-2">
                <p class="font-semibold text-sky-600">Conditions Windguru :</p>
                <p><strong>Vent :</strong> ${session.windSpeed || 'N/A'} ${session.windDirection || ''}</p>
                <p><strong>Houle :</strong> ${session.swellHeight || 'N/A'} - ${session.swellPeriod || 'N/A'} - ${session.swellDirection || ''}</p>
                <hr class="my-2">
                <p><strong>Notes :</strong></p>
                <p class="whitespace-pre-wrap">${session.notes || 'Aucune note.'}</p>
            `;
            sessionModal.classList.remove('hidden');
        };

        closeModalButton.addEventListener('click', () => {
            sessionModal.classList.add('hidden');
        });
        sessionModal.addEventListener('click', (e) => {
            if (e.target === sessionModal) {
                sessionModal.classList.add('hidden');
            }
        });

        prevMonthButton.addEventListener('click', () => {
            currentDate.setMonth(currentDate.getMonth() - 1);
            renderCalendar();
        });

        nextMonthButton.addEventListener('click', () => {
            currentDate.setMonth(currentDate.getMonth() + 1);
            renderCalendar();
        });

        // Initialisation de l'affichage
        renderSessions();
        renderCalendar();
        renderStatistics(); // Affiche les statistiques au chargement
    });
</script>

</body>
</html>

fais péter un Screenshot pour voir?

    Squares77
    c'est complétement taré...ça m'a pris 5 minutes, et je peux lui demander de me modifier le code...ça enregistre aussi...

      Squares77

      non mais imagine, moi le roi des gogols de l'informatique, je viens de pondre une app qui fonctionne Oo

        pezronf Oui, il va être ravi @Mitirapa avec des fichiers JSON obèses partout sur le serveur

          Tu peux en faire une pour le sexe. C'est pour Greenwood. Merci.