Restructuration majeure du projet: migration de flutt vers app, ajout de l'API et mise à jour du site web

This commit is contained in:
d6soft
2025-05-16 09:19:03 +02:00
parent b5aafc424b
commit 5c2620de30
391 changed files with 19780 additions and 7233 deletions

View File

@@ -0,0 +1,58 @@
<script>
import { onMount, createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
// Fonction pour accepter les cookies
function acceptCookies() {
// Créer un cookie qui expire dans 2 jours
const expiryDate = new Date();
expiryDate.setDate(expiryDate.getDate() + 2);
// Définir le cookie avec la date d'expiration
document.cookie = `geosector_cookies_accepted=true; expires=${expiryDate.toUTCString()}; path=/; SameSite=Lax`;
// Informer le composant parent que l'utilisateur a accepté
dispatch('consent', { accepted: true });
}
// Fonction pour refuser les cookies
function refuseCookies() {
// Définir un cookie de refus qui expire dans 2 jours aussi
const expiryDate = new Date();
expiryDate.setDate(expiryDate.getDate() + 2);
// Définir le cookie avec la date d'expiration
document.cookie = `geosector_cookies_refused=true; expires=${expiryDate.toUTCString()}; path=/; SameSite=Lax`;
// Informer le composant parent que l'utilisateur a refusé
dispatch('consent', { accepted: false });
}
</script>
<div class="fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center p-4">
<div class="cookie-modal bg-white rounded-lg shadow-xl p-6 max-w-md w-full">
<h2 class="text-2xl font-bold text-gray-800 mb-4">Gestion des cookies</h2>
<p class="text-gray-600 mb-6">
Nous utilisons des cookies pour suivre de façon anonyme l'activité sur ce site.
Ces informations nous aident à améliorer votre expérience utilisateur.
Les données sont collectées une fois tous les 2 jours. Vous pouvez les accepter ou les refuser.
</p>
<div class="flex flex-col sm:flex-row gap-4 justify-end">
<button
on:click={refuseCookies}
class="bg-gray-200 hover:bg-gray-300 text-gray-800 font-semibold py-2 px-4 rounded transition-colors"
>
Refuser
</button>
<button
on:click={acceptCookies}
class="bg-blue-600 hover:bg-blue-700 text-white font-semibold py-2 px-4 rounded transition-colors"
>
Accepter
</button>
</div>
</div>
</div>

View File

@@ -0,0 +1,103 @@
<script>
// Fonction pour gérer la navigation et faire défiler la page vers le haut
function handleNavigation(hash) {
window.location.hash = hash;
window.scrollTo(0, 0);
}
</script>
<footer class="bg-gray-800 text-white py-8">
<div class="container mx-auto px-4">
<div class="grid grid-cols-1 md:grid-cols-3 gap-8">
<div>
<div class="flex items-center mb-4">
<img src="/images/icon-geosector.svg" alt="Geosector" class="h-8 mr-3" />
<h3 class="text-xl font-bold">Geosector</h3>
</div>
<p class="text-gray-300 mb-6">Une application puissante et intuitive, pour une gestion efficace de vos distributions.</p>
<div class="space-y-3">
<p class="text-gray-300 font-semibold">Téléchargez notre application :</p>
<div class="flex flex-wrap gap-3">
<a href="https://apps.apple.com/store" class="inline-flex items-center bg-black text-white rounded-lg px-4 py-2 hover:bg-gray-700 transition-colors">
<svg class="w-5 h-5 mr-2" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path
d="M17.5615 12.5514C17.5615 9.17603 20.3113 7.76353 20.4318 7.69478C18.9985 5.58978 16.7857 5.29103 16.0032 5.26978C14.1546 5.07353 12.3675 6.34603 11.432 6.34603C10.4753 6.34603 9.0315 5.29103 7.4663 5.32103C5.4392 5.35103 3.5495 6.51978 2.5292 8.32603C0.4292 11.9997 2.0047 17.3989 4.0197 20.2014C5.029 21.5785 6.2018 23.1104 7.739 23.0483C9.2232 22.9768 9.769 22.0924 11.5667 22.0924C13.3432 22.0924 13.856 23.0483 15.4107 23.006C17.011 22.9768 18.0313 21.6318 19.01 20.2439C20.171 18.6273 20.6447 17.0429 20.666 16.9489C20.6235 16.9277 17.5933 15.7166 17.5615 12.5514Z"
/>
<path d="M14.2855 3.77006C15.0787 2.80256 15.6037 1.48381 15.4407 0.144806C14.3157 0.187306 12.876 0.912306 12.0402 1.85856C11.295 2.69631 10.6542 4.06256 10.8385 5.35631C12.1002 5.44381 13.45 4.72381 14.2855 3.77006Z" />
</svg>
App Store
</a>
<a href="https://play.google.com/store" class="inline-flex items-center bg-black text-white rounded-lg px-4 py-2 hover:bg-gray-700 transition-colors">
<svg class="w-5 h-5 mr-2" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path d="M17.5231 8.74664L14.4231 6.41914L2.33563 18.5066C2.52813 18.9391 2.91063 19.2826 3.40563 19.3441L17.5231 8.74664Z" />
<path d="M22.0002 11.3651C22.0002 10.7066 21.6602 10.0988 21.0692 9.76762L18.6927 8.31262L15.3302 10.8338L19.0327 13.5388L21.0402 12.3666C21.6367 12.0363 22.0002 11.7313 22.0002 11.3651Z" />
<path d="M2.00031 4.68721V19.3134C2.00031 19.6454 2.10531 19.9077 2.27406 20.1097L14.8628 7.52096L2.93156 0.572206C2.38406 0.906706 2.00031 1.71046 2.00031 2.59046V4.68721Z" />
<path d="M14.4234 6.41895L14.7697 6.18945L3.81094 0.141445C3.55969 0.0294453 3.28469 -0.0145547 3.01719 0.00294531L14.4234 6.41895Z" />
</svg>
Play Store
</a>
</div>
</div>
</div>
<div>
<h3 class="text-xl font-bold mb-4">Liens rapides</h3>
<ul class="space-y-2">
<li class="flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-2 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" />
</svg>
<a href="#accueil" class="text-gray-300 hover:text-white transition-colors" on:click|preventDefault={() => handleNavigation('accueil')}>Accueil</a>
</li>
<li class="flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-2 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" />
</svg>
<a href="#fonctionnalites" class="text-gray-300 hover:text-white transition-colors" on:click|preventDefault={() => handleNavigation('fonctionnalites')}>Fonctionnalités</a>
</li>
<li class="flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-2 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
</svg>
<a href="#contact" class="text-gray-300 hover:text-white transition-colors" on:click|preventDefault={() => handleNavigation('contact')}>Contact</a>
</li>
<li class="mt-4 pt-4 border-t border-gray-700"></li>
<li class="flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-2 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
<a href="#mentions-legales" class="text-gray-300 hover:text-white transition-colors" on:click|preventDefault={() => handleNavigation('mentions-legales')}>Mentions légales</a>
</li>
<li class="flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-2 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" />
</svg>
<a href="#politique-confidentialite" class="text-gray-300 hover:text-white transition-colors" on:click|preventDefault={() => handleNavigation('politique-confidentialite')}>Politique de confidentialité</a>
</li>
<li class="flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-2 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z" />
</svg>
<a href="#conditions-utilisation" class="text-gray-300 hover:text-white transition-colors" on:click|preventDefault={() => handleNavigation('conditions-utilisation')}>Conditions d'utilisation</a>
</li>
</ul>
</div>
<div>
<h3 class="text-xl font-bold mb-4">Contact</h3>
<address class="not-italic text-gray-300">
<p>Email: contactgeosector@gmail.com</p>
<p>Téléphone: +33 (0)7 69 09 17 06</p>
</address>
</div>
</div>
<div class="border-t border-gray-700 mt-8 pt-8 text-gray-400">
<div class="flex justify-between items-center">
<p>&copy; {new Date().getFullYear()} Geosector. Tous droits réservés.</p>
<a href="https://d6soft.fr" class="text-blue-400 hover:text-blue-300 font-medium transition-colors" target="_blank" rel="noopener noreferrer">Conception D6SOFT</a>
</div>
</div>
</div>
</footer>

View File

@@ -0,0 +1,173 @@
<script>
import { onMount } from 'svelte';
// État actif pour la navigation
let activePage = window.location.hash.slice(1) || 'accueil';
let mobileMenuOpen = false;
let baseAppUrl = '';
// Déterminer les URLs en fonction de l'environnement
function getEnvironmentUrls() {
const hostname = window.location.hostname;
let appPrefix = '';
if (hostname === 'dev.geosector.fr' || hostname.includes('localhost')) {
appPrefix = 'dapp';
} else if (hostname === 'rec.geosector.fr') {
appPrefix = 'rapp';
} else {
// Production ou autres environnements
appPrefix = 'app';
}
// Construire l'URL de base de l'application
const domainParts = hostname.split('.');
if (domainParts.length >= 2) {
// Remplacer le sous-domaine ou ajouter un nouveau préfixe
const domain = domainParts.slice(Math.max(domainParts.length - 2, 0)).join('.');
return `https://${appPrefix}.${domain}`;
}
// Fallback pour localhost ou cas non prévus
return `https://${appPrefix}.geosector.fr`;
}
// Fonction pour changer de page
function changePage(page) {
activePage = page;
window.history.pushState({}, '', `/${page}`);
closeMobileMenu();
}
// Fonctions pour le menu mobile
function toggleMobileMenu() {
mobileMenuOpen = !mobileMenuOpen;
}
function closeMobileMenu() {
mobileMenuOpen = false;
}
// Écouter les événements popstate pour mettre à jour la page active
if (typeof window !== 'undefined') {
window.addEventListener('popstate', () => {
activePage = window.location.pathname.slice(1) || 'accueil';
});
}
// Initialiser les URLs et configurer les événements
onMount(() => {
// Déterminer l'URL de base de l'application
baseAppUrl = getEnvironmentUrls();
const handleClickOutside = (event) => {
const mobileMenu = document.getElementById('mobile-menu');
const burgerButton = document.getElementById('burger-button');
if (mobileMenuOpen && mobileMenu && burgerButton &&
!mobileMenu.contains(event.target) &&
!burgerButton.contains(event.target)) {
closeMobileMenu();
}
};
document.addEventListener('click', handleClickOutside);
return () => {
document.removeEventListener('click', handleClickOutside);
};
});
</script>
<header class="text-white bg-transparent backdrop-blur-sm z-50 relative">
<div class="container mx-auto px-4 py-4">
<div class="flex justify-between items-center">
<div class="flex items-center">
<div class="mr-3">
<a href="/accueil" on:click|preventDefault={() => changePage('accueil')}>
<img src="/images/Logo-geosector-horizontal.svg" alt="Geosector" class="h-12" />
</a>
</div>
</div>
<!-- Burger menu pour mobile -->
<button id="burger-button" class="xl:hidden z-50" on:click={toggleMobileMenu}>
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-[#002C66]" fill="none" viewBox="0 0 24 24" stroke="currentColor">
{#if mobileMenuOpen}
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
{:else}
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
{/if}
</svg>
</button>
<!-- Menu desktop -->
<div class="hidden xl:flex items-center gap-6">
<nav>
<ul class="flex space-x-6">
<li>
<a href="/accueil" class={`text-[#002C66] hover:text-blue-500 transition-colors ${activePage === 'accueil' ? 'font-bold border-b-2 border-[#002C66]' : ''}`} on:click|preventDefault={() => changePage('accueil')}> Accueil </a>
</li>
<li>
<a href="/fonctionnalites" class={`text-[#002C66] hover:text-blue-500 transition-colors ${activePage === 'fonctionnalites' ? 'font-bold border-b-2 border-[#002C66]' : ''}`} on:click|preventDefault={() => changePage('fonctionnalites')}> Fonctionnalités </a>
</li>
<li>
<a href="/contact" class={`text-[#002C66] hover:text-blue-500 transition-colors ${activePage === 'contact' ? 'font-bold border-b-2 border-[#002C66]' : ''}`} on:click|preventDefault={() => changePage('contact')}> Contact </a>
</li>
</ul>
</nav>
<div class="flex gap-3 items-center">
<a href="{baseAppUrl}/login/user" class="border-2 border-[#4CAF50] text-[#4CAF50] hover:bg-[#4CAF50] hover:text-white font-medium py-1.5 px-3 rounded-full transition-colors" on:click={() => { sessionStorage.setItem('loginType', 'user'); }}> Connexion Utilisateur </a>
<a href="{baseAppUrl}/login" class="border-2 border-red-600 text-red-600 hover:bg-red-600 hover:text-white font-medium py-1.5 px-3 rounded-full transition-colors" on:click={() => { sessionStorage.setItem('loginType', 'admin'); }}> Connexion Administrateur </a>
<a href="{baseAppUrl}/register" class="bg-[#E3170A] hover:bg-red-700 text-white font-medium py-2 px-4 rounded-full transition-colors"> S'inscrire </a>
</div>
</div>
</div>
</div>
<!-- Menu mobile -->
<div id="mobile-menu" class={`fixed top-0 right-0 h-screen w-4/5 max-w-xs bg-white shadow-lg transform transition-transform duration-300 ease-in-out z-40 ${mobileMenuOpen ? 'translate-x-0' : 'translate-x-full'}`}>
<div class="p-6">
<div class="flex justify-end mb-8">
<button on:click={closeMobileMenu} class="text-gray-600" aria-label="Fermer le menu">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
<nav class="mb-8">
<ul class="space-y-4">
<li>
<a href="/accueil" class={`block text-lg text-[#002C66] hover:text-blue-500 transition-colors ${activePage === 'accueil' ? 'font-bold' : ''}`} on:click|preventDefault={() => changePage('accueil')}> Accueil </a>
</li>
<li>
<a href="/fonctionnalites" class={`block text-lg text-[#002C66] hover:text-blue-500 transition-colors ${activePage === 'fonctionnalites' ? 'font-bold' : ''}`} on:click|preventDefault={() => changePage('fonctionnalites')}> Fonctionnalités </a>
</li>
<li>
<a href="/contact" class={`block text-lg text-[#002C66] hover:text-blue-500 transition-colors ${activePage === 'contact' ? 'font-bold' : ''}`} on:click|preventDefault={() => changePage('contact')}> Contact </a>
</li>
</ul>
</nav>
<div class="space-y-4">
<a href="{baseAppUrl}/login/user" class="block w-full border-2 border-[#4CAF50] text-[#4CAF50] hover:bg-[#4CAF50] hover:text-white font-medium py-2 px-4 rounded-full transition-colors text-center mb-3" on:click={() => { sessionStorage.setItem('loginType', 'user'); }}> Connexion Utilisateur </a>
<a href="{baseAppUrl}/login" class="block w-full border-2 border-red-600 text-red-600 hover:bg-red-600 hover:text-white font-medium py-2 px-4 rounded-full transition-colors text-center mb-3" on:click={() => { sessionStorage.setItem('loginType', 'admin'); }}> Connexion Administrateur </a>
<a href="{baseAppUrl}/register" class="block w-full bg-[#E3170A] hover:bg-red-700 text-white font-medium py-2 px-4 rounded-full transition-colors text-center"> S'inscrire </a>
</div>
</div>
</div>
<!-- Overlay pour le fond lorsque le menu mobile est ouvert -->
{#if mobileMenuOpen}
<div
class="fixed inset-0 bg-black bg-opacity-50 z-30"
on:click={closeMobileMenu}
on:keydown={(e) => e.key === 'Escape' && closeMobileMenu()}
role="button"
tabindex="0"
aria-label="Fermer le menu"
></div>
{/if}
</header>