Copie propre du code final de Folliow (projet d'équipe DWWM)
This commit is contained in:
commit
eed64cfeb6
67 changed files with 17897 additions and 0 deletions
112
views/_partial/apigeo.tpl
Normal file
112
views/_partial/apigeo.tpl
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
<!-- Script d'autocomplétion ville/département — API Géo (gouvernement français) -->
|
||||
<script>
|
||||
(function () {
|
||||
const input = document.getElementById('user_location');
|
||||
const suggestions = document.getElementById('location-suggestions');
|
||||
let debounceTimer = null;
|
||||
|
||||
// Ferme la liste si on clique ailleurs
|
||||
document.addEventListener('click', function (e) {
|
||||
if (!input.contains(e.target) && !suggestions.contains(e.target)) {
|
||||
hideSuggestions();
|
||||
}
|
||||
});
|
||||
|
||||
input.addEventListener('input', function () {
|
||||
const query = this.value.trim();
|
||||
|
||||
clearTimeout(debounceTimer);
|
||||
|
||||
if (query.length < 2) {
|
||||
hideSuggestions();
|
||||
return;
|
||||
}
|
||||
|
||||
// Délai de 300 ms pour éviter trop d'appels API
|
||||
debounceTimer = setTimeout(function () {
|
||||
fetchCities(query);
|
||||
}, 300);
|
||||
});
|
||||
|
||||
// Navigation clavier dans la liste
|
||||
input.addEventListener('keydown', function (e) {
|
||||
const items = suggestions.querySelectorAll('.list-group-item');
|
||||
const active = suggestions.querySelector('.list-group-item.active');
|
||||
let index = Array.from(items).indexOf(active);
|
||||
|
||||
if (e.key === 'ArrowDown') {
|
||||
e.preventDefault();
|
||||
if (index < items.length - 1) setActive(items, index + 1);
|
||||
} else if (e.key === 'ArrowUp') {
|
||||
e.preventDefault();
|
||||
if (index > 0) setActive(items, index - 1);
|
||||
} else if (e.key === 'Enter' && active) {
|
||||
e.preventDefault();
|
||||
selectItem(active.dataset.value);
|
||||
} else if (e.key === 'Escape') {
|
||||
hideSuggestions();
|
||||
}
|
||||
});
|
||||
|
||||
function fetchCities(query) {
|
||||
// On cherche par nom de commune, on récupère aussi le département
|
||||
const url = 'https://geo.api.gouv.fr/communes?nom=' + encodeURIComponent(query)
|
||||
+ '&fields=nom,departement&boost=population&limit=8';
|
||||
|
||||
fetch(url)
|
||||
.then(function (res) { return res.json(); })
|
||||
.then(function (data) { renderSuggestions(data); })
|
||||
.catch(function () { hideSuggestions(); });
|
||||
}
|
||||
|
||||
function renderSuggestions(cities) {
|
||||
suggestions.innerHTML = '';
|
||||
|
||||
if (!cities || cities.length === 0) {
|
||||
hideSuggestions();
|
||||
return;
|
||||
}
|
||||
|
||||
cities.forEach(function (city) {
|
||||
const dept = city.departement
|
||||
? city.departement.nom + ' (' + city.departement.code + ')'
|
||||
: '';
|
||||
const label = city.nom + (dept ? ' — ' + dept : '');
|
||||
// Valeur stockée : "Ville (Département)"
|
||||
const value = city.nom + (city.departement ? ' (' + city.departement.nom + ')' : '');
|
||||
|
||||
const li = document.createElement('li');
|
||||
li.className = 'list-group-item list-group-item-action py-2 px-3';
|
||||
li.style.cursor = 'pointer';
|
||||
li.dataset.value = value;
|
||||
li.textContent = label;
|
||||
|
||||
li.addEventListener('mousedown', function (e) {
|
||||
// mousedown avant blur pour éviter que la liste disparaisse avant le clic
|
||||
e.preventDefault();
|
||||
selectItem(value);
|
||||
});
|
||||
|
||||
suggestions.appendChild(li);
|
||||
});
|
||||
|
||||
suggestions.style.display = 'block';
|
||||
}
|
||||
|
||||
function selectItem(value) {
|
||||
input.value = value;
|
||||
hideSuggestions();
|
||||
}
|
||||
|
||||
function hideSuggestions() {
|
||||
suggestions.style.display = 'none';
|
||||
suggestions.innerHTML = '';
|
||||
}
|
||||
|
||||
function setActive(items, index) {
|
||||
items.forEach(function (item) { item.classList.remove('active'); });
|
||||
items[index].classList.add('active');
|
||||
input.value = items[index].dataset.value;
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
31
views/_partial/delphoto.tpl
Normal file
31
views/_partial/delphoto.tpl
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
<script>
|
||||
const defaultAvatar = "{$smarty.env.IMG_USER_PATH}images.jpg";
|
||||
|
||||
// Suppression du listener précédent avant d'en ajouter un nouveau
|
||||
const inputImage = document.getElementById('image');
|
||||
const btnDelete = document.getElementById('btn-delete-image');
|
||||
const previewAvatar = document.getElementById('preview-avatar');
|
||||
const deleteInput = document.getElementById('delete_image');
|
||||
|
||||
inputImage?.addEventListener('change', function () {
|
||||
const file = this.files[0];
|
||||
if (!file) return;
|
||||
const reader = new FileReader();
|
||||
reader.onload = e => {
|
||||
previewAvatar.src = e.target.result;
|
||||
previewAvatar.style.opacity = '1';
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
deleteInput.value = '0';
|
||||
if (btnDelete) {
|
||||
btnDelete.disabled = false;
|
||||
}
|
||||
});
|
||||
|
||||
btnDelete?.addEventListener('click', function () {
|
||||
deleteInput.value = '1';
|
||||
previewAvatar.src = defaultAvatar;
|
||||
previewAvatar.style.opacity = '0.5';
|
||||
this.disabled = true;
|
||||
});
|
||||
</script>
|
||||
23
views/_partial/footer.tpl
Normal file
23
views/_partial/footer.tpl
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
|
||||
<footer class="py-3 mt-3 text-center" >
|
||||
<p>Créé par YaLaGuBe</a></p>
|
||||
<nav aria-label="Navigation pied de page">
|
||||
<ul class="list-inline">
|
||||
<li class="list-inline-item">
|
||||
<a href="{$smarty.env.BASE_URL}/page/about">A propos</a>
|
||||
</li>
|
||||
<li class="list-inline-item" aria-hidden="true">|</li>
|
||||
<li class="list-inline-item">
|
||||
<a href="{$smarty.env.BASE_URL}/page/help">Aide et support</a>
|
||||
</li>
|
||||
<li class="list-inline-item" aria-hidden="true">|</li>
|
||||
<li class="list-inline-item">
|
||||
<a href="{$smarty.env.BASE_URL}/page/mentions">Mentions légales</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</footer>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
|
||||
<script src="{$smarty.env.BASE_URL}/assests/js/scripts.js"></script>
|
||||
|
||||
|
||||
110
views/_partial/header.tpl
Normal file
110
views/_partial/header.tpl
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="{$smarty.env.BASE_URL}/assests/css/style.css">
|
||||
<link rel="shortcut icon" href="{$smarty.env.BASE_URL}/assests/img/Group-49.ico" type="image/x-icon">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous">
|
||||
<script src="https://use.fontawesome.com/releases/v6.3.0/js/all.js" crossorigin="anonymous"></script>
|
||||
<title>Folliow{block name="title"}{/block}</title>
|
||||
</head>
|
||||
<body class="d-flex flex-column min-vh-100">
|
||||
|
||||
<nav class="navbar navbar-expand-lg navbar-light">
|
||||
<div class="container-fluid">
|
||||
|
||||
<!-- Logo -->
|
||||
<a class="navbar-brand d-flex align-items-center" href="{$smarty.env.BASE_URL}">
|
||||
<img src="{$smarty.env.BASE_URL}/assests/img/logo.png" alt="Logo" class="logo-image">
|
||||
</a>
|
||||
|
||||
<!-- Bouton hamburger mobile -->
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav"
|
||||
aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<!-- Liens de navigation -->
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
|
||||
<!-- Liens gauche -->
|
||||
<ul class="navbar-nav me-auto mb-0">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{$smarty.env.BASE_URL}/page/about">À propos</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{$smarty.env.BASE_URL}/project/search">Rechercher</a>
|
||||
</li>
|
||||
{if isset($smarty.session.user)}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{$smarty.env.BASE_URL}/project/addedit_project">Ajouter un projet</a>
|
||||
</li>
|
||||
{if $smarty.session.user.authorisation_name == "Administrateur"}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{$smarty.env.BASE_URL}/admin/admin">Admin</a>
|
||||
</li>
|
||||
{/if}
|
||||
{/if}
|
||||
</ul>
|
||||
|
||||
<!-- Liens droite (connexion / profil) -->
|
||||
<nav aria-label="Connexion utilisateur">
|
||||
{if !isset($smarty.session.user)}
|
||||
<ul class="navbar-nav d-flex flex-row align-items-center gap-1 mb-0">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{$smarty.env.BASE_URL}/user/signup"
|
||||
title="Créer un compte" aria-label="Créer un compte">
|
||||
S'inscrire
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{$smarty.env.BASE_URL}/user/login"
|
||||
title="Se connecter" aria-label="Se connecter">
|
||||
Se connecter
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{else}
|
||||
<ul class="navbar-nav d-flex flex-row align-items-center gap-2 mb-0">
|
||||
<li class="nav-item d-flex align-items-center">
|
||||
<a class="nav-link p-0" href="{$smarty.env.BASE_URL}/user/user/{$smarty.session.user.user_pseudo}"
|
||||
title="Modifier mon compte" aria-label="Modifier mon compte">
|
||||
<img
|
||||
src="{$smarty.env.BASE_URL}/{$smarty.env.IMG_USER_PATH}{if ($smarty.env.IMG_USER_PATH|cat:($smarty.session.user.user_image))|file_exists}{$smarty.session.user.user_image}{else}images.jpg{/if}"
|
||||
class="nav-avatar"
|
||||
alt="Photo de profil"
|
||||
>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item d-flex align-items-center">
|
||||
<a class="nav-link" href="{$smarty.env.BASE_URL}/user/logout"
|
||||
title="Se déconnecter" aria-label="Se déconnecter">
|
||||
Se déconnecter
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{/if}
|
||||
</nav>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
{include file="views/_partial/messages.tpl"}
|
||||
|
||||
|
||||
<main id="main-content" class="container my-4" {block name="display"}{/block}>
|
||||
<section class="p-4 mb-4 text-center txt_title" aria-labelledby="page-title">
|
||||
<div class="col-lg-8 mx-auto">
|
||||
<h2 id="page-title" class="display-5 fw-semibold mb-3">
|
||||
{block name="h2"}{/block}
|
||||
</h2>
|
||||
<p class="lead mb-2">
|
||||
{block name="p"}{/block}
|
||||
</p>
|
||||
<p class="text-muted small mb-0">
|
||||
{block name="date_maj"}{/block}
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
14
views/_partial/messages.tpl
Normal file
14
views/_partial/messages.tpl
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
{if ($success_message != '')}
|
||||
<div class="alert alert-success">
|
||||
<p>{$success_message}</p>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{if (isset($arrError) && count($arrError) > 0) }
|
||||
<div class="alert alert-danger">
|
||||
{foreach $arrError as $strError}
|
||||
<p>{$strError}</p>
|
||||
{/foreach}
|
||||
</div>
|
||||
{/if}
|
||||
111
views/_partial/preview.tpl
Normal file
111
views/_partial/preview.tpl
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
<article class="col-md-3 mb-5 {if isset($smarty.session.user) and $smarty.session.user.user_status == 2} pb-5 {/if}" style="border-radius: 100px ;">
|
||||
<div class="card h-100 shadow article-card rounded-4" style="border-width: 2px; overflow: hidden;">
|
||||
|
||||
|
||||
<div class="ratio ratio-4x3">
|
||||
<a href="{$smarty.env.BASE_URL}/project/display/{$objProject->getId()}">
|
||||
<img src="{$smarty.env.BASE_URL}/{$smarty.env.IMG_PROJECT_PATH}{if ($smarty.env.IMG_PROJECT_PATH|cat:$objProject->getThumbnail())|file_exists}{$objProject->getThumbnail()}{else}{math equation="rand(1,4)"}.jpg{/if}"
|
||||
class="w-100 h-100 object-fit-cover"
|
||||
{if $objProject->getCreatorName()|stripos:'minou' !== false}
|
||||
style =" box-shadow: 0 0 0 4px #000; "{/if}
|
||||
alt=""
|
||||
loading="lazy">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="card-body p-3 bg-light" {if $objProject->getCreatorName()|stripos:'minou' !== false}style=" background-color: #ff8c00 !important; /* Orange tigre */
|
||||
background-image: repeating-linear-gradient(
|
||||
45deg,
|
||||
transparent,
|
||||
transparent 30px,
|
||||
rgba(0, 0, 0, 0.15) 30px,
|
||||
rgba(0, 0, 0, 0.15) 60px
|
||||
) !important;
|
||||
color: #000 !important;
|
||||
position: relative;
|
||||
z-index: 1;"{/if}>
|
||||
<div class="d-flex align-items-start gap-3">
|
||||
<a href="{$smarty.env.BASE_URL}/user/user/{$objProject->getCreatorname()}">
|
||||
<img src="{$smarty.env.BASE_URL}/{$smarty.env.IMG_USER_PATH}{if ($smarty.env.IMG_USER_PATH|cat:($objProject->getUser_image()))|file_exists}{$objProject->getUser_image()}{else}images.jpg{/if}"
|
||||
class="rounded-circle flex-shrink-0 border border-2 border-white"
|
||||
style="width: 64px; height: 64px; object-fit: cover; margin-top: 8px;{if $objProject->getCreatorName()|stripos:'minou' !== false}
|
||||
box-shadow: 0 0 0 4px #000; {/if}"
|
||||
alt="Photo de profil">
|
||||
</a>
|
||||
<div class="flex-grow-1">
|
||||
<h3 class="h6 fw-bold mb-2 mt-1">{$objProject->getTitle()}</h3>
|
||||
<p class="small text-muted mb-1">
|
||||
<i class="bi bi-person"></i>
|
||||
<a href="{$smarty.env.BASE_URL}/user/user/{$objProject->getCreatorname()}"
|
||||
class="text-decoration-none text-muted"
|
||||
style="position: relative; z-index: 2;
|
||||
{if $objProject->getCreatorName()|stripos:'minou' !== false}font-weight: 800 !important;
|
||||
text-transform: uppercase;
|
||||
color: #000 !important;{/if}">
|
||||
{$objProject->getCreatorname()}
|
||||
</a>
|
||||
</p>
|
||||
<p class="small text-muted mb-0">
|
||||
<i class="bi bi-geo-alt">Colmar</i>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mt-3">
|
||||
<small class="text-muted">
|
||||
<i class="bi bi-clock"><time>{$objProject->getCreation_date()}</time></i>
|
||||
</small>
|
||||
{if $objProject->getStatus() != "refusé" && $objProject->getStatus() != "supprimé"}
|
||||
<a href="{$smarty.env.BASE_URL}/project/display/{$objProject->getId()}"
|
||||
class="btn btn-sm btn-primary" {if $objProject->getCreatorName()|stripos:'minou' !== false}style="
|
||||
background-color: #000 !important;
|
||||
color: #ff8c00 !important;
|
||||
border: none !important;
|
||||
font-weight: bold !important;
|
||||
transition: transform 0.2s;"{/if}>
|
||||
Voir →
|
||||
</a>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{if isset($smarty.session.user)}
|
||||
{if ($smarty.session.user.user_id == $objProject->getUser_id()) && $objProject->getStatus() == "en_attente" && $objProject->getStatus() == "accepté"}
|
||||
<a href="{$smarty.env.BASE_URL}/project/addedit_project/{$objProject->getId()}"
|
||||
class="btn btn-sm btn-outline-secondary mt-2 w-100"
|
||||
style="position: relative; z-index: 2;">
|
||||
Editer
|
||||
</a>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{if isset($smarty.session.user)
|
||||
and $smarty.session.user.user_status == 2
|
||||
and $objProject->getStatus() == "en_attente"}
|
||||
<div class="card-footer bg-white border-top-0 p-2">
|
||||
<div class="d-flex gap-2">
|
||||
<a class="btn btn-sm btn-success flex-fill"
|
||||
href="{$smarty.env.BASE_URL}/project/accept/{$objProject->getId()}"
|
||||
name="toPublished">Accepter</a>
|
||||
<a class="btn btn-sm btn-warning flex-fill"
|
||||
href="{$smarty.env.BASE_URL}/project/refuse/{$objProject->getId()}"
|
||||
name="toRefused">Refuser</a>
|
||||
<a class="btn btn-sm btn-danger flex-fill"
|
||||
href="{$smarty.env.BASE_URL}/project/delete/{$objProject->getId()}"
|
||||
name="toDelete"
|
||||
onclick="return confirm('Attention ! Êtes-vous sûr de vouloir supprimer ce projet ? Cette action est irréversible.');">
|
||||
Supprimer</a>
|
||||
</div>
|
||||
</div>
|
||||
{elseif $objProject->getStatus() == "refusé"}
|
||||
<div class="card-footer bg-white border-top-0 p-2">
|
||||
<p class="text-danger fw-bold text-center mb-0 small">Projet refusé</p>
|
||||
</div>
|
||||
{elseif $objProject->getStatus() == "supprimé"}
|
||||
<div class="card-footer bg-white border-top-0 p-2">
|
||||
<p class="text-danger fw-bold text-center mb-0 small">Projet archivé</p>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</article>
|
||||
Loading…
Add table
Add a link
Reference in a new issue