Skip to content
Snippets Groups Projects
Commit 6a306aa6 authored by Kenneth's avatar Kenneth
Browse files

Working code

parent 33419d5a
Branches
No related tags found
No related merge requests found
...@@ -25,6 +25,38 @@ Pour ce projet, nous allons utiliser pipenv pour créer un environnement virtuel ...@@ -25,6 +25,38 @@ Pour ce projet, nous allons utiliser pipenv pour créer un environnement virtuel
sudo apt-get update sudo apt-get update
sudo apt-get install build-essential libpq-dev python3-dev sudo apt-get install build-essential libpq-dev python3-dev
sudo apt install pipenv sudo apt install pipenv
```
Si vous rencontrer un pb :
AttributeError: module 'collections' has no attribute 'MutableMapping'
faire un
```
sudo apt remove pipenv
```
voila
installpython3.12-dev
```
I was getting the same error on ubuntu 22.04, This is how I solved it.
remove pipenv if you have installed it using apt
sudo apt remove pipenv
install pipenv unsing pip
pip3 install pipenv
activate virtual environment
python3 -m pipenv shell
install from pipfile
pipenv install
``` ```
Une fois cela fait, on entrer dans l'environnement virtuel. Une fois cela fait, on entrer dans l'environnement virtuel.
...@@ -39,7 +71,12 @@ pipenv shell ...@@ -39,7 +71,12 @@ pipenv shell
''' '''
sudo apt install postgresql postgresql-contrib
psql --version
sudo -u postgres psql sudo -u postgres psql
psql -U votre_utilisateur -d votre_base_de_donnees -h localhost -W
ALTER USER postgres WITH PASSWORD 'nouveau_mot_de_passe'; ALTER USER postgres WITH PASSWORD 'nouveau_mot_de_passe';
''' '''
## Run the app ## Run the app
......
...@@ -71,6 +71,16 @@ def index(): ...@@ -71,6 +71,16 @@ def index():
return render_template("index.html") return render_template("index.html")
# return "Hello, world" # return "Hello, world"
@app.route('/ePhone')
def ePhone():
return render_template("ePhone.html")
@app.route('/ePhone16ProMax')
def ePhone16ProMax():
return render_template("ePhone16ProMax.html")
# return "Hello, world"
@app.route('/admin', methods=['GET', 'POST']) @app.route('/admin', methods=['GET', 'POST'])
def admin(): def admin():
......
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="fr">
<head> <head>
<title>Admin - Ajouter des articles</title> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Administration - Gestion des Articles</title>
<style>
/* Réinitialisation des styles */
body, h1, p, nav, footer {
margin: 0;
padding: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
}
body {
background: #f9f9f9;
color: #333;
}
/* Bandeau en fond blanc */
header {
background: white;
width: 100%;
border-bottom: 1px solid #eaeaea;
padding: 10px 0;
display: flex;
justify-content: space-between;
align-items: center;
padding-left: 20px;
}
.logo {
display: flex;
align-items: center;
gap: 10px;
}
.logo img {
height: 30px;
width: auto;
}
nav {
display: flex;
justify-content: center;
gap: 20px;
flex-grow: 1;
text-align: center;
}
nav a {
text-decoration: none;
color: #333;
font-weight: normal;
font-size: 1em;
padding: 10px 15px;
}
nav a:hover {
text-decoration: underline;
}
/* Contenu principal */
main {
max-width: 800px;
margin: 50px auto;
background: #fff;
padding: 20px;
border-radius: 10px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}
h1 {
font-size: 2em;
text-align: center;
margin-bottom: 20px;
}
/* Styles du formulaire */
form {
margin-bottom: 30px;
display: flex;
flex-direction: column;
gap: 10px;
}
form input, form textarea, form button {
padding: 10px;
font-size: 1em;
}
form input, form textarea {
border: 1px solid #ccc;
border-radius: 5px;
width: 100%;
}
form button {
background: #0078d7;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
width: 150px;
align-self: flex-start;
}
form button:hover {
background: #005bb5;
}
/* Styles de la liste */
.article-list {
list-style: none;
padding: 0;
}
.article-list li {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 0;
border-bottom: 1px solid #eaeaea;
}
.article-list li:last-child {
border-bottom: none;
}
.article-list button {
background: #d9534f;
color: white;
border: none;
border-radius: 5px;
padding: 5px 10px;
cursor: pointer;
}
.article-list button:hover {
background: #c9302c;
}
</style>
</head> </head>
<body> <body>
<h1>Ajouter un article</h1>
<form method="POST"> <header>
<input type="text" name="title" placeholder="Titre" required> <div class="logo">
<textarea name="description" placeholder="Description" required></textarea> <!-- Remplacez l'URL ci-dessous par celle de votre logo -->
<input type="number" step="0.01" name="price" placeholder="Prix (€)" required> <img src="https://1.bp.blogspot.com/_TkI9VbsKljk/Sx1UNvbXWSI/AAAAAAAAA_4/H-27hwu9C-o/s400/birneKopie.jpg" alt="Logo Pear">
</div>
<nav>
<a href="/">Accueil</a>
<a href="/ePhone">ePhones</a>
</nav>
</header>
<main>
<h1>Gestion des Articles</h1>
<!-- Formulaire pour ajouter un nouvel article -->
<!-- (en front uniquement, pas d'envoi réel à un back-end dans cet exemple) -->
<form id="add-article-form">
<input type="text" id="article-title" placeholder="Titre de l'article" required />
<textarea id="article-description" placeholder="Description de l'article" required></textarea>
<input type="number" step="0.01" id="article-price" placeholder="Prix de l'article (€)" required />
<button type="submit">Ajouter</button> <button type="submit">Ajouter</button>
</form> </form>
<h2>Articles disponibles</h2> <!-- Liste des articles ajoutés -->
<ul> <ul class="article-list" id="article-list"></ul>
{% for article in articles %} </main>
<li>{{ article.title }} - {{ article.price }}€</li>
{% endfor %} <script>
</ul> // Tableau qui stocke nos articles temporairement
const articles = [];
// Fonction pour réafficher la liste complète
function renderArticles() {
const articleList = document.getElementById('article-list');
// On vide la liste avant de la reconstruire
articleList.innerHTML = '';
// Pour chaque article du tableau, on crée un <li> et on l'ajoute
articles.forEach((article, index) => {
const li = document.createElement('li');
li.innerHTML = `
<div>
<strong>${article.title}</strong> - ${article.price} €<br>
${article.description}
</div>
<button onclick="deleteArticle(${index})">Supprimer</button>
`;
articleList.appendChild(li);
});
}
// Supprimer un article en cliquant sur "Supprimer"
function deleteArticle(index) {
if (confirm('Voulez-vous vraiment supprimer cet article ?')) {
articles.splice(index, 1); // Retire l'article du tableau
renderArticles(); // Mets à jour l'affichage
}
}
// Gestionnaire du formulaire : ajouter un nouvel article
document.getElementById('add-article-form').addEventListener('submit', function (e) {
e.preventDefault();
const titleField = document.getElementById('article-title');
const descField = document.getElementById('article-description');
const priceField = document.getElementById('article-price');
const title = titleField.value.trim();
const description = descField.value.trim();
const price = parseFloat(priceField.value);
// Petite vérification
if (!title || !description || isNaN(price)) {
alert('Veuillez remplir tous les champs correctement.');
return;
}
// Ajout dans le tableau
articles.push({ title, description, price });
// Réaffiche la liste mise à jour
renderArticles();
// Réinitialise les champs
titleField.value = '';
descField.value = '';
priceField.value = '';
});
// Initialisation : on affiche la liste (vide) au chargement
renderArticles();
</script>
</body> </body>
</html> </html>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ePhone - Pear</title>
<style>
/* Réinitialisation des styles */
body, h1, p, nav, footer {
margin: 0;
padding: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
}
body {
background: #f4f4f4;
color: #333;
}
header {
background: white; /* Fond blanc */
width: 100%; /* S'étend sur toute la largeur */
border-bottom: 1px solid #eaeaea;
padding: 10px 0; /* Espacement vertical */
display: flex;
justify-content: space-between; /* Espacement entre le logo et le menu */
align-items: center;
padding-left: 20px; /* Espacement à gauche pour le logo */
}
.logo {
display: flex;
align-items: center;
gap: 10px;
}
.logo img {
height: 30px;
width: auto;
}
nav {
display: flex;
justify-content: center; /* Centre le contenu horizontalement */
gap: 20px; /* Espace entre les liens */
flex-grow: 1; /* Permet au nav de prendre toute la largeur restante */
text-align: center; /* Centre le texte des liens */
}
nav a {
text-decoration: none;
color: #333;
font-weight: normal;
font-size: 1em;
padding: 10px 15px;
}
nav a:hover {
text-decoration: underline;
}
.product-section {
text-align: center;
margin-top: 30px;
}
.product-list {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 30px;
margin-top: 30px;
}
.product-item {
border: 1px solid #ddd;
border-radius: 15px;
padding: 30px;
width: 300px;
background: #fff;
text-align: center;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
transition: transform 0.3s;
}
.product-item:hover {
transform: translateY(-5px);
}
.product-item img {
width: 100%;
height: auto;
max-height: 300px;
object-fit: cover;
margin-bottom: 15px;
border-radius: 10px;
}
.product-item h2 {
font-size: 1.4em;
margin-bottom: 15px;
}
.product-item p {
font-size: 1em;
color: #666;
margin-bottom: 20px;
}
.product-item a {
text-decoration: none;
color: #fff;
background: #0078d7;
padding: 10px 20px;
border-radius: 5px;
font-weight: bold;
transition: background 0.3s;
}
.product-item a:hover {
background: #005bb5;
}
footer {
text-align: center;
padding: 20px;
font-size: 0.9em;
color: #777;
border-top: 1px solid #ccc;
margin-top: 30px;
}
</style>
</head>
<body>
<header>
<div class="logo">
<img src="https://1.bp.blogspot.com/_TkI9VbsKljk/Sx1UNvbXWSI/AAAAAAAAA_4/H-27hwu9C-o/s400/birneKopie.jpg" alt="Logo Pear"> <!-- Remplace l'URL par celle de ton logo -->
</div>
<nav>
<a href="/">Accueil</a>
<a href="/admin">Administrateur</a>
</nav>
</header>
<section class="product-section">
<h1>Découvrez nos ePhones</h1>
<div class="product-list">
<div class="product-item">
<img src="https://store.storeimages.cdn-apple.com/4668/as-images.apple.com/is/iphone16promax-digitalmat-gallery-1-202409?wid=728&hei=666&fmt=p-jpg&qlt=95&.v=1723843667239" alt="ePhone 16 Pro Max">
<h2>ePhone 16 Pro Max</h2>
<p>A partir de 900 €</p>
<p>Le dernier modèle avec des fonctionnalités révolutionnaires.</p>
<a href="/ePhone16ProMax">Voir l'article</a>
</div>
<div class="product-item">
<img src="https://store.storeimages.cdn-apple.com/4668/as-images.apple.com/is/iphone16promax-digitalmat-gallery-1-202409?wid=728&hei=666&fmt=p-jpg&qlt=95&.v=1723843667239" alt="ePhone 16 Pro">
<h2>ePhone 16 Pro</h2>
<p>A partir de 800 €</p>
<p>Des performances élevées et une autonomie incroyable.</p>
<a href="/ePhone16Pro">Voir l'article</a>
</div>
<div class="product-item">
<img src="https://store.storeimages.cdn-apple.com/4668/as-images.apple.com/is/iphone16plus-digitalmat-gallery-1-202409?wid=728&hei=666&fmt=p-jpg&qlt=95&.v=1723669964512" alt="ePhone 16 Plus">
<h2>ePhone 16 Plus</h2>
<p>A partir de 700 €</p>
<p>Compact, puissant et abordable.</p>
<a href="/ePhone16Plus">Voir l'article</a>
</div>
<div class="product-item">
<img src="https://store.storeimages.cdn-apple.com/4668/as-images.apple.com/is/iphone16-digitalmat-gallery-1-202409?wid=728&hei=666&fmt=p-jpg&qlt=95&.v=1723669127470" alt="ePhone 16">
<h2>ePhone 16</h2>
<p>A partir de 600 €</p>
<p>Le modèle classique, revisité pour durer.</p>
<a href="/ePhone16">Voir l'article</a>
</div>
</div>
</section>
<footer>
© 2025 Pear Inc. Tous droits réservés.
</footer>
</body>
</html>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ePhone 16 Pro Max - Détails</title>
<style>
body, h1, p, form {
margin: 0;
padding: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
background: #f9f9f9;
color: #333;
}
header {
background: white;
width: 100%;
padding: 20px 40px;
border-bottom: 1px solid #eaeaea;
display: flex;
justify-content: space-between;
align-items: center;
}
.logo img {
height: 40px;
width: auto;
}
main {
max-width: 900px;
margin: 50px auto;
padding: 30px;
background: white;
border-radius: 20px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
h1 {
font-size: 2.5em;
font-weight: 600;
color: #333;
margin-bottom: 15px;
}
p {
font-size: 1.1em;
line-height: 1.6;
color: #555;
margin-bottom: 30px;
}
.price {
font-size: 1.7em;
color: #0078d7;
font-weight: 600;
margin-bottom: 25px;
}
.details img {
border-radius: 15px;
max-width: 100%;
height: auto;
display: block;
margin-bottom: 20px;
}
.form-container {
background: #f1f1f1;
padding: 20px;
border-radius: 10px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.form-container input {
padding: 12px;
width: 100%;
margin-bottom: 15px;
border: 1px solid #ccc;
border-radius: 10px;
font-size: 1em;
transition: border-color 0.3s ease;
}
.form-container input:focus {
border-color: #0078d7;
outline: none;
}
.form-container button {
padding: 12px;
width: 100%;
background-color: #0078d7;
color: white;
border: none;
border-radius: 10px;
font-size: 1.2em;
cursor: pointer;
transition: background-color 0.3s ease;
}
.form-container button:hover {
background-color: #005bb5;
}
</style>
</head>
<body>
<header>
<div class="logo">
<img src="https://1.bp.blogspot.com/_TkI9VbsKljk/Sx1UNvbXWSI/AAAAAAAAA_4/H-27hwu9C-o/s400/birneKopie.jpg" alt="Logo Pear">
</div>
</header>
<main>
<h1>ePhone 16 Pro Max</h1>
<div class="details">
<img src="https://store.storeimages.cdn-apple.com/4668/as-images.apple.com/is/iphone16pro-digitalmat-gallery-3-202409?wid=728&hei=666&fmt=p-jpg&qlt=95&.v=1723843057832" alt="ePhone 16 Pro Max">
<p>Découvrez l'ePhone 16 Pro Max, un smartphone révolutionnaire avec des fonctionnalités haut de gamme : un écran OLED 6,7 pouces, un processeur A15 Bionic, un appareil photo de 108 MP, et bien plus encore.</p>
</div>
<div class="price">
Prix : 900 €
</div>
<div class="form-container">
<h2>Acheter maintenant</h2>
<form id="purchase-form">
<input type="email" id="user-email" placeholder="Votre adresse email" required>
<button type="submit">Acheter</button>
</form>
</div>
</main>
<script>
document.getElementById('purchase-form').addEventListener('submit', function (e) {
e.preventDefault();
const email = document.getElementById('user-email').value;
const price = '900 €';
// Vérification de l'email
if (email) {
// Envoi d'une confirmation (simulé)
alert(`Confirmation d'achat envoyée à ${email}.\nPrix : ${price}`);
} else {
alert('Veuillez saisir une adresse email valide.');
}
});
</script>
</body>
</html>
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="fr">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1">
<title>Accueil</title> <title>Accueil - Style Apple</title>
<style> <style>
body { /* Réinitialisation de quelques styles de base */
font-family: Arial, sans-serif; body, h1, p, nav, footer {
text-align: center; margin: 0;
margin: 50px; padding: 0;
} }
h1 { body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
background: #fff;
color: #333; color: #333;
line-height: 1.6;
}
header {
padding: 10px 20px;
border-bottom: 1px solid #eaeaea;
display: flex;
align-items: center;
justify-content: space-between;
}
.logo {
display: flex;
align-items: center;
gap: 10px;
} }
.links { .logo img {
margin: 20px 0; height: 30px;
width: auto;
} }
.link { nav {
display: inline-block; flex-grow: 1;
margin: 10px; display: flex;
padding: 15px 25px; justify-content: center;
background-color: #007bff; gap: 20px;
color: white; font-size: 0.9em;
}
nav a {
text-decoration: none; text-decoration: none;
border-radius: 5px; color: #333;
transition: background-color 0.3s; padding: 10px;
} }
.link:hover { nav a:hover {
background-color: #0056b3; text-decoration: underline;
}
.hero {
text-align: center;
padding: 100px 20px;
background: #f9f9f9;
}
.hero h1 {
font-size: 3em;
margin-bottom: 20px;
}
.hero p {
font-size: 1.2em;
color: #555;
}
footer {
text-align: center;
padding: 20px;
font-size: 0.8em;
color: #777;
border-top: 1px solid #eaeaea;
}
.product-item img {
width: 100%;
height: auto;
max-height: 300px;
object-fit: cover;
margin-bottom: 15px;
border-radius: 10px;
} }
</style> </style>
</head> </head>
<body> <body>
<h1>Bienvenue sur l'application</h1> <header>
<p>Choisissez une action pour accéder à vos pages :</p> <div class="logo">
<img src="https://1.bp.blogspot.com/_TkI9VbsKljk/Sx1UNvbXWSI/AAAAAAAAA_4/H-27hwu9C-o/s400/birneKopie.jpg" alt="Logo Pear"> <!-- Remplace l'URL par celle de ton logo -->
<div class="links">
<a href="/admin" class="link">Page Administrateur</a>
<a href="/articles" class="link">Articles Disponibles</a>
</div> </div>
<nav>
<a href="ePhone">ePhone</a>
<a href="#">Moc</a>
<a href="#">ePad</a>
<a href="#">Watch</a>
<a href="#">TV</a>
<a href="#">Music</a>
<a href="#">Support</a>
<a href="admin">Administrateur</a>
</nav>
</header>
<section class="hero">
<h1>Bienvenue chez Pear</h1>
<p>Découvrez nos derniers produits et innovations.</p>
</section>
<footer>
© 2025 Pear Inc. Tous droits réservés.
</footer>
</body> </body>
</html> </html>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment