mirror of
https://github.com/Floriansylvain/projet_programmation_web.git
synced 2026-08-19 11:43:16 +02:00
🎨 Better and safer error handling, general overhaul
This commit is contained in:
@@ -3,18 +3,24 @@
|
|||||||
require_once("class/dump.php");
|
require_once("class/dump.php");
|
||||||
|
|
||||||
if (!isset($_GET['q']) || !isset($_GET['author'])) {
|
if (!isset($_GET['q']) || !isset($_GET['author'])) {
|
||||||
print_r(json_encode(array("status" => 400, "message" => "Missing query type or attributs.")));
|
print_r(json_encode(array("status" => 400, "message" => "Missing query type or attributes.")));
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
$author_name = $_GET['author'];
|
$author_name = filter_var($_GET['author'], FILTER_SANITIZE_ADD_SLASHES);
|
||||||
$q = $_GET['q'];
|
$q = $_GET['q'];
|
||||||
|
|
||||||
|
if (strlen($author_name) < 3) {
|
||||||
|
print_r(json_encode(array("status" => 400, "message" => "Le nom de l'auteur doit comporter un minimum de 3 caractères.")));
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
$json_object = match ($q) {
|
$json_object = match ($q) {
|
||||||
"theses" => dump::getTheseByAuthor($author_name),
|
"theses" => dump::getTheseByAuthor($author_name),
|
||||||
"authors" => dump::getAuthorsByAuthors($author_name),
|
"authors" => dump::getAuthorsByAuthors($author_name),
|
||||||
default => NULL,
|
default => NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO : Rajouter la structure status message data
|
||||||
$json = json_encode($json_object);
|
$json = json_encode($json_object);
|
||||||
print_r($json);
|
print_r($json);
|
||||||
|
|||||||
+42
-15
@@ -3,15 +3,24 @@ let searchBar = document.querySelector('#searchbar')
|
|||||||
let searchBarButton = document.querySelector('#search-button')
|
let searchBarButton = document.querySelector('#search-button')
|
||||||
let suggestions = document.querySelector('#suggestions')
|
let suggestions = document.querySelector('#suggestions')
|
||||||
let loader = document.querySelector('.loader')
|
let loader = document.querySelector('.loader')
|
||||||
|
let error = document.querySelector("#error")
|
||||||
|
let errorMessage = document.querySelector("#error-message")
|
||||||
|
let errorButton = document.querySelector("#error-button")
|
||||||
|
|
||||||
let authorName = "";
|
let authorName = "";
|
||||||
|
let lastRequest = null
|
||||||
|
|
||||||
function requestToApi(author) {
|
function requestToApi(author) {
|
||||||
loader.style.display = "block"
|
if (lastRequest === null || (new Date().getTime() - lastRequest) > 1000) {
|
||||||
authorName = author
|
lastRequest = new Date().getTime()
|
||||||
fetch(`api.php?q=theses&author=${author}`)
|
loader.style.display = "block"
|
||||||
.then(response => response.json())
|
authorName = author
|
||||||
.then(data => displayResults(data))
|
fetch(`api.php?q=theses&author=${author}`)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => displayResults(data))
|
||||||
|
} else {
|
||||||
|
alert('Veuillez attendre une seconde entre chaque recherche.')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let elementsToFade = null
|
let elementsToFade = null
|
||||||
@@ -26,6 +35,17 @@ function fadeIn() {
|
|||||||
|
|
||||||
// TODO : Faire un système de page plutôt que de charger 10000 résultats en une fois s'il y en a 10000..
|
// TODO : Faire un système de page plutôt que de charger 10000 résultats en une fois s'il y en a 10000..
|
||||||
function displayResults(results) {
|
function displayResults(results) {
|
||||||
|
|
||||||
|
if (results.status === 400) {
|
||||||
|
loader.style.display = "none"
|
||||||
|
error.classList.add("fade-in");
|
||||||
|
errorMessage.innerHTML = results.message
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.querySelector('#results-count').innerHTML = ""
|
||||||
|
document.querySelector('#results').innerHTML = ""
|
||||||
|
|
||||||
let count = 0
|
let count = 0
|
||||||
|
|
||||||
results.forEach(elem => {
|
results.forEach(elem => {
|
||||||
@@ -54,15 +74,15 @@ function displayResults(results) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let lastSearch = ""
|
let lastSearch = ""
|
||||||
let last = new Date().getTime()
|
let lastSuggestion = new Date().getTime()
|
||||||
let suggestionsDisplayed = false
|
let suggestionsDisplayed = false
|
||||||
|
|
||||||
function realTimeDisplay() {
|
function realTimeDisplay() {
|
||||||
let search = document.getElementsByName("author")[0].value
|
let search = document.getElementsByName("author")[0].value
|
||||||
if (search.length > 3 && (search !== lastSearch || (new Date().getTime() - last) > 500)) {
|
if (search.length > 3 && (search !== lastSearch || (new Date().getTime() - lastSuggestion) > 500)) {
|
||||||
showSuggestions()
|
showSuggestions()
|
||||||
lastSearch = search
|
lastSearch = search
|
||||||
last = new Date().getTime()
|
lastSuggestion = new Date().getTime()
|
||||||
fetch(`api.php?q=authors&author=${search}`)
|
fetch(`api.php?q=authors&author=${search}`)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(function(data) {
|
.then(function(data) {
|
||||||
@@ -71,8 +91,6 @@ function realTimeDisplay() {
|
|||||||
let name = document.createElement('p')
|
let name = document.createElement('p')
|
||||||
name.innerHTML = elem
|
name.innerHTML = elem
|
||||||
name.addEventListener('click', () => {
|
name.addEventListener('click', () => {
|
||||||
document.querySelector('#results-count').innerHTML = ""
|
|
||||||
document.querySelector('#results').innerHTML = ""
|
|
||||||
searchBar.value = elem
|
searchBar.value = elem
|
||||||
requestToApi(elem)
|
requestToApi(elem)
|
||||||
})
|
})
|
||||||
@@ -87,20 +105,18 @@ function showSuggestions() {
|
|||||||
navbarForm.style.borderRadius = '15px 15px 0 0'
|
navbarForm.style.borderRadius = '15px 15px 0 0'
|
||||||
suggestions.style.display = 'block'
|
suggestions.style.display = 'block'
|
||||||
searchBarButton.style.boxShadow = 'none'
|
searchBarButton.style.boxShadow = 'none'
|
||||||
searchBarButton.classList.remove('animation-in')
|
searchBarButton.classList.replace('animation-in', 'animation-out')
|
||||||
searchBarButton.classList.add('animation-out')
|
|
||||||
suggestionsDisplayed = true
|
suggestionsDisplayed = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener('click', function (e){
|
document.addEventListener('click', e => {
|
||||||
if (e.target.id !== 'suggestions' && e.target !== searchBar && e.target !== searchBarButton) {
|
if (e.target.id !== 'suggestions' && e.target !== searchBar && e.target !== searchBarButton) {
|
||||||
if (suggestionsDisplayed) {
|
if (suggestionsDisplayed) {
|
||||||
navbarForm.style.borderRadius = '15px'
|
navbarForm.style.borderRadius = '15px'
|
||||||
suggestions.style.display = 'none'
|
suggestions.style.display = 'none'
|
||||||
searchBarButton.style.boxShadow = 'rgba(0, 0, 0, 0.15) 4px 2px 5px'
|
searchBarButton.style.boxShadow = 'rgba(0, 0, 0, 0.15) 4px 2px 5px'
|
||||||
searchBarButton.classList.remove('animation-out')
|
searchBarButton.classList.replace('animation-out', 'animation-in')
|
||||||
searchBarButton.classList.add('animation-in')
|
|
||||||
suggestionsDisplayed = false
|
suggestionsDisplayed = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,5 +132,16 @@ document.addEventListener('click', function (e){
|
|||||||
cross.classList.remove('spin-fade')
|
cross.classList.remove('spin-fade')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (e.target === errorButton) {
|
||||||
|
error.classList.replace('fade-in', 'fade-out')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
navbarForm.addEventListener('submit', e => {
|
||||||
|
e.preventDefault()
|
||||||
|
let data = new FormData(navbarForm)
|
||||||
|
searchBar.blur()
|
||||||
|
requestToApi(data.get('author'))
|
||||||
|
})
|
||||||
|
|||||||
+8
-13
@@ -6,7 +6,7 @@
|
|||||||
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||||
<link rel="stylesheet" href="stylesheet.css">
|
<link rel="stylesheet" href="stylesheet.css">
|
||||||
<title>Document</title>
|
<title>Theses FR</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<?php
|
<?php
|
||||||
@@ -32,19 +32,14 @@
|
|||||||
<div id="results-count"></div>
|
<div id="results-count"></div>
|
||||||
<div id="results"></div>
|
<div id="results"></div>
|
||||||
|
|
||||||
<script src="app.js"></script>
|
<div id="error">
|
||||||
|
<div id="error-message"></div>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="error-button">
|
||||||
|
<path d="M23.954 21.03l-9.184-9.095 9.092-9.174-2.832-2.807-9.09 9.179-9.176-9.088-2.81 2.81 9.186 9.105-9.095 9.184 2.81 2.81 9.112-9.192 9.18 9.1z"/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
|
||||||
<?php
|
<script src="app.js"></script>
|
||||||
if (isset($_GET['author'])) {
|
|
||||||
if (strlen($_GET['author']) < 3) {
|
|
||||||
echo "<p class='error'>Veuillez entrer 3 caractères minimum.</p>";
|
|
||||||
} else {
|
|
||||||
echo "<script>requestToApi('" . filter_var($_GET['author'], FILTER_SANITIZE_ADD_SLASHES) . "')</script>";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
echo "<script>document.getElementsByClassName('loader')[0].style.display = \"none\"</script>";
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -9,10 +9,10 @@
|
|||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
<div class="research-section">
|
<div class="research-section">
|
||||||
<form action="index.php" method="GET" class="navbar-form">
|
<form class="navbar-form">
|
||||||
<input type="text" name="author" placeholder="nom auteur" onkeyup="realTimeDisplay()" id="searchbar">
|
<input type="text" name="author" placeholder="nom auteur" onkeyup="realTimeDisplay()" id="searchbar">
|
||||||
<button>
|
<button id="form-button">
|
||||||
<img src="assets/search.svg" alt="search" id="search-button">
|
<img src="assets/search.svg" alt="search" id="search-button" class="animation-in">
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
<div id="suggestions"></div>
|
<div id="suggestions"></div>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
* {
|
* {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
font-family: sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
@@ -23,7 +24,6 @@ body {
|
|||||||
height: 75px;
|
height: 75px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
font-family: sans-serif;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.research-section {
|
.research-section {
|
||||||
@@ -139,7 +139,6 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#results {
|
#results {
|
||||||
font-family: sans-serif;
|
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -147,7 +146,6 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#results-count {
|
#results-count {
|
||||||
font-family: sans-serif;
|
|
||||||
opacity: 50%;
|
opacity: 50%;
|
||||||
margin: 0 15px 0 15px;
|
margin: 0 15px 0 15px;
|
||||||
}
|
}
|
||||||
@@ -168,14 +166,49 @@ body {
|
|||||||
transform: translateX(0px);
|
transform: translateX(0px);
|
||||||
animation-fill-mode: forwards;
|
animation-fill-mode: forwards;
|
||||||
}
|
}
|
||||||
|
.fade-out {
|
||||||
|
animation: fade-out 250ms linear;
|
||||||
|
transition: 250ms;
|
||||||
|
transform: translateX(0px);
|
||||||
|
animation-fill-mode: forwards;
|
||||||
|
}
|
||||||
@keyframes fade-in {
|
@keyframes fade-in {
|
||||||
from { opacity: 0 }
|
from { opacity: 0 }
|
||||||
to { opacity: 100% }
|
to { opacity: 100% }
|
||||||
}
|
}
|
||||||
|
@keyframes fade-out {
|
||||||
|
from { opacity: 100% }
|
||||||
|
to { opacity: 0 }
|
||||||
|
}
|
||||||
|
|
||||||
/*TODO : Faire une belle erreur*/
|
#error {
|
||||||
.error {
|
opacity: 0;
|
||||||
color: red;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #FF6F6F;
|
||||||
|
border: solid 3px #DE6161;
|
||||||
|
border-radius: 5px;
|
||||||
|
color: #302B2B;
|
||||||
|
width: 90%;
|
||||||
|
padding: 10px;
|
||||||
|
position: fixed;
|
||||||
|
bottom: 10px;
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#error-button {
|
||||||
|
fill: #302B2B;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
background: #DE6161;
|
||||||
|
border-radius: 1px;
|
||||||
|
padding: 2px;
|
||||||
|
margin-left: auto;
|
||||||
|
border: 1px solid #824D4D;
|
||||||
|
}
|
||||||
|
|
||||||
|
#error-button:hover {
|
||||||
|
background: #CA5D5D;
|
||||||
}
|
}
|
||||||
|
|
||||||
.loader {
|
.loader {
|
||||||
|
|||||||
Reference in New Issue
Block a user