project assignment 1 docker push
@ -52,4 +52,4 @@ After actively invoking `./start-app.sh`, securely visit dynamically:
|
|||||||
- Official `docker-compose` documentation.
|
- Official `docker-compose` documentation.
|
||||||
|
|
||||||
## How Artificial Intelligence was natively used
|
## How Artificial Intelligence was natively used
|
||||||
This physically requested solution (Bash Scripting, Advanced Docker Object Routing, Refactoring methodologies, and File Generation) was strictly mapped intelligently interacting securely using **Antigravity**, an official Advanced Agentic Coding artificial intelligence agent acting as the primary orchestrator, intelligently translating the specific criteria logically directly.
|
In this project ai was used to help create the .yalm file and understand his importance. It was also used to help Write the README.me file add state clearly what does this application do, list all the dependencies and write it smoothly.
|
||||||
|
|||||||
58
z1/docker-compose.yaml
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
version: "3.8"
|
||||||
|
|
||||||
|
services:
|
||||||
|
db:
|
||||||
|
image: mysql:8.0
|
||||||
|
container_name: smartbuilding_db
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
MYSQL_ROOT_PASSWORD: cytech0001
|
||||||
|
MYSQL_DATABASE: user
|
||||||
|
volumes:
|
||||||
|
- z1_mysql-data:/var/lib/mysql
|
||||||
|
- ./webapp/user.sql:/docker-entrypoint-initdb.d/user.sql:ro
|
||||||
|
networks:
|
||||||
|
- app-network
|
||||||
|
|
||||||
|
phpmyadmin:
|
||||||
|
image: phpmyadmin/phpmyadmin
|
||||||
|
container_name: smartbuilding_pma
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
PMA_HOST: db
|
||||||
|
PMA_USER: root
|
||||||
|
PMA_PASSWORD: cytech0001
|
||||||
|
ports:
|
||||||
|
- "8080:80"
|
||||||
|
networks:
|
||||||
|
- app-network
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
|
||||||
|
webapp:
|
||||||
|
build:
|
||||||
|
context: ./webapp
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
container_name: smartbuilding_webapp
|
||||||
|
restart: unless-stopped
|
||||||
|
command: >
|
||||||
|
sh -c "until nc -z db 3306; do echo 'Waiting for MySQL...'; sleep 2; done; npm start"
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
environment:
|
||||||
|
DB_HOST: db
|
||||||
|
DB_USER: root
|
||||||
|
DB_PASSWORD: cytech0001
|
||||||
|
DB_NAME: user
|
||||||
|
networks:
|
||||||
|
- app-network
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
|
||||||
|
networks:
|
||||||
|
app-network:
|
||||||
|
external: true
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
z1_mysql-data:
|
||||||
|
external: true
|
||||||
13
z1/prepare-app.sh
Executable file
@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
echo "Preparing app..."
|
||||||
|
|
||||||
|
# Creating virtual networks mathematically natively natively
|
||||||
|
docker network create app-network 2>/dev/null || true
|
||||||
|
|
||||||
|
# Explicitly allocating the persistent volume
|
||||||
|
docker volume create z1_mysql-data 2>/dev/null || true
|
||||||
|
|
||||||
|
# Pre-building the local webapp image directly
|
||||||
|
docker compose build
|
||||||
|
|
||||||
|
echo "App locally compiled safely!"
|
||||||
11
z1/remove-app.sh
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
echo "Removing all traces of the application..."
|
||||||
|
|
||||||
|
# Demolish containers natively gracefully
|
||||||
|
docker compose down -v --rmi all
|
||||||
|
|
||||||
|
# Ensure the manually created network is gone
|
||||||
|
docker network rm app-network 2>/dev/null || true
|
||||||
|
docker volume rm z1_mysql-data 2>/dev/null || true
|
||||||
|
|
||||||
|
echo "Removed app."
|
||||||
9
z1/start-app.sh
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
echo "Running app ..."
|
||||||
|
|
||||||
|
# Booting up all strictly defined services dynamically in the background
|
||||||
|
docker compose up -d
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "The app is available at http://localhost:3000"
|
||||||
|
echo "The database interface (phpMyAdmin) is available at http://localhost:8080"
|
||||||
5
z1/stop-app.sh
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
echo "Stopping app..."
|
||||||
|
|
||||||
|
# Non-destructively pausing components
|
||||||
|
docker compose stop
|
||||||
4
z1/webapp/.dockerignore
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
node_modules
|
||||||
|
npm-debug.log
|
||||||
|
.git
|
||||||
|
.env
|
||||||
12
z1/webapp/Dockerfile
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
FROM node:18-alpine
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
CMD ["npm", "start"]
|
||||||
94
z1/webapp/README.md
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
🌐 Projet Web - Smart Building (Maison Connectée)
|
||||||
|
|
||||||
|
Bienvenue dans le projet web de gestion d'une maison connectée réalisé dans le cadre de notre formation.
|
||||||
|
|
||||||
|
|
||||||
|
Ce projet permet de gérer différents objets connectés d’un
|
||||||
|
bâtiment (lumières, climatiseurs, thermostats, etc.) avec des rôles
|
||||||
|
utilisateurs, une interface de connexion, de gestion et de visualisation.
|
||||||
|
|
||||||
|
|
||||||
|
📦 Prérequis
|
||||||
|
Assurez-vous d’avoir les outils suivants installés :
|
||||||
|
Node.js (version 18 ou + recommandée)
|
||||||
|
npm
|
||||||
|
un serveur local avec phpMyAdmin et MySQL
|
||||||
|
|
||||||
|
|
||||||
|
⚙️ Installation du projet
|
||||||
|
Si vous arrivez à lire ce README vous avez donc réussi à cloner le lien github.
|
||||||
|
|
||||||
|
Ouvrir un terminal dans le dossier du projet :
|
||||||
|
cd projetWEB
|
||||||
|
|
||||||
|
|
||||||
|
⚙️ Installer les dépendances Node.js :
|
||||||
|
npm install
|
||||||
|
|
||||||
|
Cela installera notamment : - express - ejs - bcrypt / bcryptjs - multer - mysql - nodemon - express-session - path
|
||||||
|
|
||||||
|
|
||||||
|
📁 Configuration de la base de données
|
||||||
|
Démarrer MySQL et phpMyAdmin (avec les pc de cy tech sur ubuntu normalement l'identifiant est root et le mot de passe est cytech0001)
|
||||||
|
|
||||||
|
Créer une base de données nommée user dans phpMyAdmin
|
||||||
|
Importer le fichier SQL :
|
||||||
|
Aller dans phpMyAdmin > Base user > Importer
|
||||||
|
Sélectionner le fichier SQL fourni (user.sql)
|
||||||
|
Valider
|
||||||
|
|
||||||
|
⚠️ Vérifiez que toutes les tables ont bien été créées (utilisateur, objet, etc.)
|
||||||
|
|
||||||
|
|
||||||
|
🚀 Lancement du serveur
|
||||||
|
Lancer le serveur local avec nodemon :
|
||||||
|
npm run dev
|
||||||
|
|
||||||
|
Le serveur démarrera sur :
|
||||||
|
👉 http://localhost:3000
|
||||||
|
Structure de navigation du site :
|
||||||
|
/ → Accueil
|
||||||
|
/connexion → Connexion utilisateur
|
||||||
|
/inscription → Formulaire d’inscription/objets → Liste des objets connectés (accès selon statut)
|
||||||
|
/admin → Dashboard administrateur (vous n'y avez accès que si vous êtes connecté en tant qu'admin)
|
||||||
|
/admin → Dashboard administrateur (vous n'y avez accès que si vous êtes connecté en tant que complexe)
|
||||||
|
/profil → Modification du profil
|
||||||
|
/membres → Liste des utilisateurs (selon rôle)
|
||||||
|
|
||||||
|
|
||||||
|
👤 Rôles utilisateurs :
|
||||||
|
|
||||||
|
visiteur → accès limité, simple visite et visualisation des objets et des membres et aucune modification possible
|
||||||
|
|
||||||
|
simple → peut consulter et modifier les objets en cliquant sur l'engrenage dans la page objets connectés (si vous voulez vous connecter à un compte utilisateur simple vous pouvez utiliser comme identifiant garricastres et comme mot de passe 1234)
|
||||||
|
|
||||||
|
complexe → accès complet à la gestion d’objets à l'aide d'un petit dashboard (si vous voulez vous connecter à un compte utilisateur simple vous pouvez utiliser comme identifiant clement_cx et comme mot de passe 1234)
|
||||||
|
|
||||||
|
administrateur → contrôle total à l'aide d'un dashboard (ajout/suppression utilisateurs et objets) (si vous voulez vous connecter à un compte utilisateur simple vous pouvez utiliser comme identifiant admin et comme mot de passe 1234)
|
||||||
|
|
||||||
|
|
||||||
|
📸 Upload des photos
|
||||||
|
Les photos de profil sont stockées dans le dossier /img
|
||||||
|
|
||||||
|
|
||||||
|
🧪 Scripts utiles
|
||||||
|
Dans un terminal se mettre au niveau du dossier projetWEB
|
||||||
|
démarrer avec nodemon : npm run dev
|
||||||
|
démarrer sans nodemon : node index.js
|
||||||
|
|
||||||
|
|
||||||
|
💡 Développement
|
||||||
|
Technos utilisées :
|
||||||
|
|
||||||
|
Node.js + Express pour le backend
|
||||||
|
EJS comme moteur de vues
|
||||||
|
MySQL comme base de données
|
||||||
|
Multer pour le téléchargement de fichiers
|
||||||
|
bcrypt pour sécuriser les mots de passe
|
||||||
|
|
||||||
|
🧑🏫 Projet réalisé par :
|
||||||
|
Guillaume Arricastres, Zoe Artigas, Augustin Contal, Lucas Coquet, Thomas Kluczny
|
||||||
|
|
||||||
|
Cytech – GI Groupe 2 – Année 2025
|
||||||
|
|
||||||
|
Merci pour votre attention
|
||||||
BIN
z1/webapp/Rapport_Projet_WEB_GIG2_Groupe5.pdf
Normal file
19
z1/webapp/config/db.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
const mysql = require('mysql2');
|
||||||
|
|
||||||
|
const connection = mysql.createConnection({
|
||||||
|
host: process.env.DB_HOST || 'localhost',
|
||||||
|
user: process.env.DB_USER || 'root', // Ton utilisateur MySQL
|
||||||
|
password: process.env.DB_PASSWORD !== undefined ? process.env.DB_PASSWORD : 'cytech0001', // Ton mot de passe
|
||||||
|
database: process.env.DB_NAME || 'user', // Le nom de ta base
|
||||||
|
charset: 'utf8mb4'
|
||||||
|
});
|
||||||
|
|
||||||
|
connection.connect((err) => {
|
||||||
|
if (err) {
|
||||||
|
console.error('❌ Erreur de connexion à MySQL :', err);
|
||||||
|
} else {
|
||||||
|
console.log('✅ Connecté à la base de données MySQL');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = connection;
|
||||||
|
After Width: | Height: | Size: 574 KiB |
BIN
z1/webapp/img/option.png
Executable file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
z1/webapp/img/stylo.png
Executable file
|
After Width: | Height: | Size: 7.1 KiB |
205
z1/webapp/index.js
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const session = require('express-session');
|
||||||
|
const path = require('path');
|
||||||
|
const bcrypt = require('bcrypt');
|
||||||
|
const db = require('./config/db');
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
const PORT = 3000;
|
||||||
|
|
||||||
|
// --------------------
|
||||||
|
// Middleware
|
||||||
|
// --------------------
|
||||||
|
app.use(express.static('public'));
|
||||||
|
app.use('/img', express.static('img'));
|
||||||
|
app.use(express.urlencoded({ extended: true }));
|
||||||
|
app.use(express.json());
|
||||||
|
|
||||||
|
app.set('view engine', 'ejs');
|
||||||
|
app.set('views', path.join(__dirname, 'views'));
|
||||||
|
|
||||||
|
app.use(session({
|
||||||
|
secret: 'votre-secret',
|
||||||
|
resave: false,
|
||||||
|
saveUninitialized: false
|
||||||
|
}));
|
||||||
|
|
||||||
|
app.use((req, res, next) => {
|
||||||
|
res.locals.session = req.session;
|
||||||
|
res.locals.currentRoute = req.path;
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
|
||||||
|
// --------------------
|
||||||
|
// Middleware admin
|
||||||
|
// --------------------
|
||||||
|
function requireAdmin(req, res, next) {
|
||||||
|
if (!req.session.utilisateur || req.session.utilisateur.statut !== 'administrateur') {
|
||||||
|
return res.redirect('/non-admin');
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------
|
||||||
|
// Importation des routes
|
||||||
|
// --------------------
|
||||||
|
const profilRouter = require('./routes/profil');
|
||||||
|
const inscriptionRouter = require('./routes/inscription');
|
||||||
|
const connexionRouter = require('./routes/connexion');
|
||||||
|
const objetsRoutes = require('./routes/api/objet');
|
||||||
|
const utilisateursRoutes = require('./routes/api/utilisateur');
|
||||||
|
const ressourceRoutes = require('./routes/api/ressource');
|
||||||
|
const complexeRoutes = require('./routes/complexe');
|
||||||
|
const adminRoutes = require('./routes/admin');
|
||||||
|
|
||||||
|
// --------------------
|
||||||
|
// Utilisation des routes
|
||||||
|
// --------------------
|
||||||
|
app.use('/profil', profilRouter);
|
||||||
|
app.use('/inscription', inscriptionRouter);
|
||||||
|
app.use('/connexion', connexionRouter);
|
||||||
|
app.use('/api/objets', objetsRoutes);
|
||||||
|
app.use('/api/utilisateurs', utilisateursRoutes);
|
||||||
|
app.use('/api/ressources', ressourceRoutes);
|
||||||
|
app.use('/complexe', complexeRoutes);
|
||||||
|
app.use('/admin', adminRoutes);
|
||||||
|
|
||||||
|
// --------------------
|
||||||
|
// Pages de vue
|
||||||
|
// --------------------
|
||||||
|
app.get('/', (req, res) => res.render('accueil'));
|
||||||
|
app.get('/objets', (req, res) => res.render('objets'));
|
||||||
|
app.get('/ressources', (req, res) => res.render('ressources'));
|
||||||
|
app.get('/description', (req, res) => res.render('description'));
|
||||||
|
app.get('/contact', (req, res) => res.render('contact'));
|
||||||
|
|
||||||
|
app.get('/membres', (req, res) => {
|
||||||
|
db.query('SELECT * FROM utilisateur', (err, membres) => {
|
||||||
|
if (err) return res.status(500).send('Erreur BDD');
|
||||||
|
res.render('membres', { membres });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
app.get('/membres/:id', (req, res) => {
|
||||||
|
const id = req.params.id;
|
||||||
|
db.query('SELECT * FROM utilisateur WHERE id = ?', [id], (err, results) => {
|
||||||
|
if (err || results.length === 0) return res.status(404).send('Utilisateur non trouvé');
|
||||||
|
res.render('membre', { membre: results[0] });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
app.get('/dashboard-complexe', (req, res) => {
|
||||||
|
if (!req.session.utilisateur || req.session.utilisateur.statut !== 'complexe') {
|
||||||
|
return res.send(`
|
||||||
|
<script>
|
||||||
|
alert("Tu n'es pas connecté en tant que complexe ;)");
|
||||||
|
window.location.href = '/connexion';
|
||||||
|
</script>
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
|
||||||
|
db.query('SELECT * FROM objet', (err, objets) => {
|
||||||
|
if (err) return res.status(500).send("Erreur objets");
|
||||||
|
res.render('dashboard-complexe', { objets });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
app.get('/dashboard-simple', (req, res) => {
|
||||||
|
if (!req.session.utilisateur || req.session.utilisateur.statut !== 'simple') {
|
||||||
|
return res.redirect('/non-admin');
|
||||||
|
}
|
||||||
|
res.redirect('/objets');
|
||||||
|
});
|
||||||
|
|
||||||
|
app.get('/non-admin', (req, res) => {
|
||||||
|
res.send(`
|
||||||
|
<script>
|
||||||
|
alert("Tu n'es pas connecté en tant qu'admin ;)");
|
||||||
|
window.location.href = '/connexion';
|
||||||
|
</script>
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// --------------------
|
||||||
|
// Inscription utilisateur
|
||||||
|
// --------------------
|
||||||
|
app.post('/admin/ajouter-utilisateur', async (req, res) => {
|
||||||
|
const {
|
||||||
|
nom, prenom, sexe, age, date_naissance,
|
||||||
|
identifiant, email, mot_de_passe, situation, statut
|
||||||
|
} = req.body;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const checkSql = 'SELECT * FROM utilisateur WHERE email = ? OR identifiant = ?';
|
||||||
|
db.query(checkSql, [email, identifiant], async (err, results) => {
|
||||||
|
if (err) return res.status(500).send("Erreur serveur");
|
||||||
|
|
||||||
|
if (results.length > 0) {
|
||||||
|
return res.send(`
|
||||||
|
<script>
|
||||||
|
alert("⚠️ L'adresse e-mail ou l'identifiant est déjà utilisé !");
|
||||||
|
window.location.href = '/admin';
|
||||||
|
</script>
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const hashed = await bcrypt.hash(mot_de_passe, 10);
|
||||||
|
const insertSql = `
|
||||||
|
INSERT INTO utilisateur
|
||||||
|
(nom, prenom, sexe, age, date_naissance, identifiant, email, mot_de_passe, situation, statut, etat)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'en attente')
|
||||||
|
`;
|
||||||
|
db.query(insertSql, [
|
||||||
|
nom, prenom, sexe, age, date_naissance,
|
||||||
|
identifiant, email, hashed, situation, statut
|
||||||
|
], (err) => {
|
||||||
|
if (err) return res.status(500).send("Erreur lors de l'ajout de l'utilisateur");
|
||||||
|
res.redirect('/admin');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).send('Erreur serveur');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// --------------------
|
||||||
|
// Ajout objet (admin)
|
||||||
|
// --------------------
|
||||||
|
app.post('/admin/ajouter-objet', (req, res) => {
|
||||||
|
const { denomination, adresse_ip, type, niveau, etat } = req.body;
|
||||||
|
const sql = `
|
||||||
|
INSERT INTO objet (denomination, adresse_ip, type, niveau, etat)
|
||||||
|
VALUES (?, ?, ?, ?, ?)`;
|
||||||
|
db.query(sql, [denomination, adresse_ip, type, niveau, etat], (err) => {
|
||||||
|
if (err) return res.status(500).send("Erreur lors de l'ajout de l'objet");
|
||||||
|
res.redirect('/admin');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// --------------------
|
||||||
|
// Envoi de message contact
|
||||||
|
// --------------------
|
||||||
|
app.post('/contact', (req, res) => {
|
||||||
|
const { nom, email, message } = req.body;
|
||||||
|
const sql = 'INSERT INTO contact (nom, email, message) VALUES (?, ?, ?)';
|
||||||
|
db.query(sql, [nom, email, message], (err) => {
|
||||||
|
if (err) return res.status(500).send("Erreur lors de l'envoi du message");
|
||||||
|
res.redirect('/');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// --------------------
|
||||||
|
// Déconnexion
|
||||||
|
// --------------------
|
||||||
|
app.get('/deconnexion', (req, res) => {
|
||||||
|
req.session.destroy(() => {
|
||||||
|
res.redirect('/');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// --------------------
|
||||||
|
// Lancement du serveur
|
||||||
|
// --------------------
|
||||||
|
app.listen(PORT, () => {
|
||||||
|
console.log(`✅ Serveur lancé sur http://localhost:${PORT}`);
|
||||||
|
});
|
||||||
10
z1/webapp/middleware/auth.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
function ensureAuthenticated(req, res, next) {
|
||||||
|
if (req.session.utilisateur) {
|
||||||
|
return next();
|
||||||
|
} else {
|
||||||
|
return res.redirect('/connexion');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = ensureAuthenticated;
|
||||||
|
|
||||||
2208
z1/webapp/package-lock.json
generated
Normal file
26
z1/webapp/package.json
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"name": "mon-projet",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"start": "node index.js",
|
||||||
|
"dev": "nodemon index.js"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"description": "",
|
||||||
|
"dependencies": {
|
||||||
|
"bcrypt": "^5.1.1",
|
||||||
|
"bcryptjs": "^3.0.2",
|
||||||
|
"connect-flash": "^0.1.1",
|
||||||
|
"ejs": "^3.1.10",
|
||||||
|
"express": "^5.1.0",
|
||||||
|
"express-session": "^1.18.1",
|
||||||
|
"multer": "^1.4.5-lts.2",
|
||||||
|
"mysql2": "^3.14.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"nodemon": "^3.1.9"
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
z1/webapp/public/images/batiment.png
Executable file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
z1/webapp/public/images/building.jpg
Executable file
|
After Width: | Height: | Size: 100 KiB |
BIN
z1/webapp/public/images/smart_building.png
Executable file
|
After Width: | Height: | Size: 178 KiB |
BIN
z1/webapp/public/images/tour.jpg
Executable file
|
After Width: | Height: | Size: 80 KiB |
419
z1/webapp/public/style.css
Normal file
@ -0,0 +1,419 @@
|
|||||||
|
/* ------------- */
|
||||||
|
/* HTML */
|
||||||
|
/* ------------- */
|
||||||
|
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
font-family: "Inter", sans-serif;
|
||||||
|
background-color: #1e1e1e;
|
||||||
|
color: #eff1f3;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
overflow: auto;
|
||||||
|
height: 100%; /* Définit la hauteur de la page à 100% */
|
||||||
|
display: flex; /* Flexbox sur le body */
|
||||||
|
flex-direction: column; /* Aligne le contenu du body en colonne */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------- */
|
||||||
|
/* Header */
|
||||||
|
/* --------------- */
|
||||||
|
|
||||||
|
header {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 10px 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
header a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #eff1f3;
|
||||||
|
}
|
||||||
|
|
||||||
|
header ul {
|
||||||
|
list-style: none;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
header li {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text {
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1; /* Le conteneur des liens prend toute la place disponible */
|
||||||
|
justify-content: center; /* Centre les liens horizontalement */
|
||||||
|
gap: 15%; /* Espace entre les liens */
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text a {
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text li a:hover {
|
||||||
|
color: #00a8e8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion {
|
||||||
|
padding: 10px 20px;
|
||||||
|
border-radius: 900px;
|
||||||
|
font-size: 16px; /* Taille de la police */
|
||||||
|
border-color: #00a8e8;
|
||||||
|
color: #eff1f3;
|
||||||
|
background-color: #00a8e8;
|
||||||
|
margin-top: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion:hover {
|
||||||
|
border-color: #eff1f3;
|
||||||
|
color: #00a8e8;
|
||||||
|
background-color: #eff1f3; /* Changer la couleur au survol */
|
||||||
|
}
|
||||||
|
|
||||||
|
#smart_building {
|
||||||
|
width: 13%;
|
||||||
|
margin-left: -40px;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------- */
|
||||||
|
/* Main */
|
||||||
|
/* ------------- */
|
||||||
|
|
||||||
|
main {
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1; /* Permet à la section principale d'occuper l'espace restant */
|
||||||
|
justify-content: center; /* Centre verticalement le contenu */
|
||||||
|
align-items: center; /* Centre horizontalement le contenu */
|
||||||
|
padding-bottom: 50px;
|
||||||
|
gap: 30px; /* Espace entre les 2 sections */
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-panel {
|
||||||
|
flex: 3; /* 30% de la largeur totale */
|
||||||
|
display: flex;
|
||||||
|
justify-content: center; /* Centrer l'image horizontalement */
|
||||||
|
align-items: center; /* Centrer l'image verticalement */
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-panel img {
|
||||||
|
width: 100%; /* L'image prend toute la largeur de son conteneur */
|
||||||
|
max-width: 450px; /* Maximum de 300px de largeur */
|
||||||
|
height: auto; /* La hauteur de l'image s'ajuste automatiquement */
|
||||||
|
border-radius: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-panel {
|
||||||
|
flex: 7; /* 70% de la largeur totale */
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-panel h1 {
|
||||||
|
font-size: 60px;
|
||||||
|
margin-bottom: 60px;
|
||||||
|
padding-left: 70px; /* Ajoute un espacement à gauche du titre */
|
||||||
|
}
|
||||||
|
|
||||||
|
.features {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(4, 1fr); /* 4 ronds par ligne */
|
||||||
|
gap: 30px;
|
||||||
|
justify-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.features a{
|
||||||
|
text-decoration: none;
|
||||||
|
color: #eff1f3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.circle {
|
||||||
|
width: 150px;
|
||||||
|
height: 150px;
|
||||||
|
background-color: #eff1f3;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
transition: background-color 0.3s, color 0.3s;
|
||||||
|
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.circle:hover {
|
||||||
|
background-color: #2c2c2c;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.circle i {
|
||||||
|
font-size: 70px;
|
||||||
|
fill: #2c2c2c;
|
||||||
|
color: #2c2c2c;
|
||||||
|
transition: fill 0.3s, color 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.circle:hover i {
|
||||||
|
fill: #eff1f3;
|
||||||
|
color: #eff1f3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------- */
|
||||||
|
/* Footer */
|
||||||
|
/* --------------- */
|
||||||
|
|
||||||
|
footer {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-size: 14px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
padding: 20px;
|
||||||
|
margin-top: auto; /* Cela force le footer à se pousser vers le bas */
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
padding: 10px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #eff1f3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_link {
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1;
|
||||||
|
gap: 10%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_link a {
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
padding: 10px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------- */
|
||||||
|
/* Responsive Design */
|
||||||
|
/* ------------------------- */
|
||||||
|
|
||||||
|
/* GRAND ÉCRAN (> 1440px) */
|
||||||
|
@media (min-width: 1440px) {
|
||||||
|
.right-panel h1 {
|
||||||
|
font-size: 72px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.circle {
|
||||||
|
width: 180px;
|
||||||
|
height: 180px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.circle i {
|
||||||
|
font-size: 80px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* TABLETTE - Moyenne (1025px à 1440px) */
|
||||||
|
@media (max-width: 1440px) and (min-width: 1025px) {
|
||||||
|
.features {
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-panel h1 {
|
||||||
|
font-size: 48px;
|
||||||
|
padding-left: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.circle {
|
||||||
|
width: 130px;
|
||||||
|
height: 130px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.circle i {
|
||||||
|
font-size: 50px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* TABLETTE - Petite (769px à 1024px) */
|
||||||
|
@media (max-width: 1024px) and (min-width: 769px) {
|
||||||
|
header {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 20px;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#smart_building {
|
||||||
|
width: 100px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text {
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion {
|
||||||
|
padding: 8px 16px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-panel,
|
||||||
|
.right-panel {
|
||||||
|
width: 100%;
|
||||||
|
flex: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.features {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-panel h1 {
|
||||||
|
font-size: 42px;
|
||||||
|
padding-left: 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* MOBILE (≤ 768px) */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
header {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#smart_building {
|
||||||
|
width: 90px;
|
||||||
|
height: auto;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion {
|
||||||
|
padding: 10px 20px;
|
||||||
|
width: auto;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-panel,
|
||||||
|
.right-panel {
|
||||||
|
width: 100%;
|
||||||
|
flex: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-panel h1 {
|
||||||
|
font-size: 36px;
|
||||||
|
padding-left: 0;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.features {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.circle {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.circle i {
|
||||||
|
font-size: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
flex-direction: column;
|
||||||
|
text-align: center;
|
||||||
|
gap: 10px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_link {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* TÉLÉPHONE TRÈS PETIT (≤ 480px) */
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
main {
|
||||||
|
padding: 20px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-panel h1 {
|
||||||
|
font-size: 28px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.circle {
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.circle i {
|
||||||
|
font-size: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control-inscription {
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#smart_building {
|
||||||
|
width: 70px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion {
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 8px 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------------------- */
|
||||||
|
/* Transitions douces */
|
||||||
|
/* ------------------------- */
|
||||||
|
|
||||||
|
* {
|
||||||
|
transition: all 0.3s ease-in-out;
|
||||||
|
}
|
||||||
530
z1/webapp/public/styleAdmin.css
Normal file
@ -0,0 +1,530 @@
|
|||||||
|
/* ---------------- */
|
||||||
|
/* GLOBAL */
|
||||||
|
/* ---------------- */
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-family: 'Inter', sans-serif;
|
||||||
|
background-color: #1e1e1e;
|
||||||
|
color: #eff1f3;
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
flex: 1;
|
||||||
|
padding: 40px 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------- */
|
||||||
|
/* Header */
|
||||||
|
/* --------------- */
|
||||||
|
|
||||||
|
header {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 10px 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
header a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #eff1f3;
|
||||||
|
}
|
||||||
|
|
||||||
|
header ul {
|
||||||
|
list-style: none;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
header li {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text li a:hover {
|
||||||
|
color: #00a8e8;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.header_text {
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1; /* Le conteneur des liens prend toute la place disponible */
|
||||||
|
justify-content: center; /* Centre les liens horizontalement */
|
||||||
|
gap: 15%; /* Espace entre les liens */
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text a {
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion {
|
||||||
|
padding: 10px 20px;
|
||||||
|
border-radius: 900px;
|
||||||
|
font-size: 16px; /* Taille de la police */
|
||||||
|
border-color: #00a8e8;
|
||||||
|
color: #eff1f3;
|
||||||
|
background-color: #00a8e8;
|
||||||
|
margin-top: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion:hover {
|
||||||
|
border-color: #eff1f3;
|
||||||
|
color: #00a8e8;
|
||||||
|
background-color: #eff1f3; /* Changer la couleur au survol */
|
||||||
|
}
|
||||||
|
|
||||||
|
#smart_building {
|
||||||
|
width: 13%;
|
||||||
|
margin-left: -40px;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------------- */
|
||||||
|
/* TITRES */
|
||||||
|
/* ---------------- */
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 42px;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
color: #00a8e8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------- */
|
||||||
|
/* TABLES */
|
||||||
|
/* ---------------- */
|
||||||
|
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin-bottom: 60px;
|
||||||
|
background-color: #2c2c2c;
|
||||||
|
border-radius: 12px;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
th,
|
||||||
|
td {
|
||||||
|
padding: 15px;
|
||||||
|
text-align: center;
|
||||||
|
border-bottom: 1px solid #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
background-color: #1e1e1e;
|
||||||
|
color: #00a8e8;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr:hover {
|
||||||
|
background-color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
padding: 6px 10px;
|
||||||
|
border-radius: 20px;
|
||||||
|
border: none;
|
||||||
|
background-color: #eff1f3;
|
||||||
|
color: #1e1e1e;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
background-color: #00a8e8;
|
||||||
|
color: #eff1f3;
|
||||||
|
border: none;
|
||||||
|
padding: 8px 20px;
|
||||||
|
border-radius: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:hover {
|
||||||
|
background-color: #0077b6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle-btn {
|
||||||
|
display: inline-block; /* Assurer que l'élément peut être transformé */
|
||||||
|
transition: transform 0.2s ease; /* Transition pour un zoom fluide */
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle-btn:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
transform: scale(1.4); /* Agrandir de 1.5x lors du survol */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------- */
|
||||||
|
/* FORMULAIRE */
|
||||||
|
/* ---------------- */
|
||||||
|
|
||||||
|
/* Si tu veux aussi centrer directement dans la section d'ajout */
|
||||||
|
.ajout-section {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column; /* Permet de garder la structure de la section */
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#form-ajout-objet,
|
||||||
|
#form-ajout-user {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 24px;
|
||||||
|
background-color: #2c2c2c;
|
||||||
|
padding: 40px 100px; /* Augmente l'espace intérieur */
|
||||||
|
width: 100%; /* Prend toute la largeur disponible */
|
||||||
|
max-width: 400px; /* Définit une largeur max pour éviter qu'elle ne devienne trop étroite */
|
||||||
|
box-shadow: 0 4px 8px 0 rgba(21, 21, 21, 0.2);
|
||||||
|
margin-bottom: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 20px;
|
||||||
|
color: #eff1f3;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
appearance: none; /* Supprime le style natif */
|
||||||
|
background: white;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
width: 100%;
|
||||||
|
position: relative; /* Position relative */
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group .icon {
|
||||||
|
position: absolute;
|
||||||
|
left: 15px; /* Ajuste la position des icônes */
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group .icon svg {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
fill: #191717;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control-admin {
|
||||||
|
width: 100%;
|
||||||
|
padding-left: 50px; /* Remplissage à gauche de 55px */
|
||||||
|
padding-right: 40px;
|
||||||
|
height: 48px; /* Hauteur de 40px */
|
||||||
|
border-radius: 34px; /* Bordure arrondie */
|
||||||
|
font-size: 16px; /* Taille de la police */
|
||||||
|
letter-spacing: 0.5px; /* Espacement des lettres */
|
||||||
|
background-color: #eff1f3; /* Couleur de fond */
|
||||||
|
border: none; /* Supprimer la bordure */
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px; /* espace entre label et champ */
|
||||||
|
flex-wrap: nowrap; /* évite le retour à la ligne */
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton-admin {
|
||||||
|
padding: 10px 20px;
|
||||||
|
border-radius: 900px;
|
||||||
|
font-size: 16px; /* Taille de la police */
|
||||||
|
border-color: #00a8e8;
|
||||||
|
color: #eff1f3;
|
||||||
|
background-color: #00a8e8;
|
||||||
|
margin-top: 0; /* Centrage vertical */
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton-admin:hover {
|
||||||
|
border-color: #eff1f3;
|
||||||
|
color: #00a8e8;
|
||||||
|
background-color: #eff1f3; /* Changer la couleur au survol */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------- */
|
||||||
|
/* FOOTER */
|
||||||
|
/* ---------------- */
|
||||||
|
|
||||||
|
footer {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-size: 14px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
padding: 20px;
|
||||||
|
margin-top: auto; /* Cela force le footer à se pousser vers le bas */
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
padding: 10px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #eff1f3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_link {
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1;
|
||||||
|
gap: 10%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_link a {
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
padding: 10px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------- */
|
||||||
|
/* Responsive Design */
|
||||||
|
/* ------------------------- */
|
||||||
|
|
||||||
|
/* GRAND ÉCRAN (> 1440px) */
|
||||||
|
@media (min-width: 1440px) {
|
||||||
|
header {
|
||||||
|
padding: 20px 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text {
|
||||||
|
gap: 25%; /* Plus d'espace entre les liens */
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
margin-bottom: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_link {
|
||||||
|
gap: 20%;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
padding: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion {
|
||||||
|
font-size: 18px;
|
||||||
|
padding: 12px 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#smart_building {
|
||||||
|
width: 15%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* TABLETTE - Moyenne (1025px à 1440px) */
|
||||||
|
@media (max-width: 1440px) and (min-width: 1025px) {
|
||||||
|
header {
|
||||||
|
padding: 20px 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text {
|
||||||
|
gap: 20%; /* Moins d'espace entre les liens */
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
margin-bottom: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
padding: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_link {
|
||||||
|
gap: 15%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion {
|
||||||
|
font-size: 16px;
|
||||||
|
padding: 10px 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#smart_building {
|
||||||
|
width: 14%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* TABLETTE - Petite (769px à 1024px) */
|
||||||
|
@media (max-width: 1024px) and (min-width: 769px) {
|
||||||
|
header {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 20px;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text {
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion {
|
||||||
|
padding: 8px 16px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
margin-bottom: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_link {
|
||||||
|
gap: 10%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#smart_building {
|
||||||
|
width: 100px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_link {
|
||||||
|
gap: 10%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* MOBILE (≤ 768px) */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
header {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#smart_building {
|
||||||
|
width: 90px;
|
||||||
|
height: auto;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion {
|
||||||
|
padding: 10px 20px;
|
||||||
|
width: auto;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
flex-direction: column;
|
||||||
|
text-align: center;
|
||||||
|
gap: 10px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_link {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* TÉLÉPHONE TRÈS PETIT (≤ 480px) */
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
main {
|
||||||
|
padding: 20px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 28px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#smart_building {
|
||||||
|
width: 70px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion {
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 8px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_link {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8%;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_link a {
|
||||||
|
padding: 5px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion {
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 8px 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
354
z1/webapp/public/styleComplexe.css
Normal file
@ -0,0 +1,354 @@
|
|||||||
|
/* ------------- */
|
||||||
|
/* HTML */
|
||||||
|
/* ------------- */
|
||||||
|
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
font-family: "Inter", sans-serif;
|
||||||
|
background-color: #1e1e1e;
|
||||||
|
color: #eff1f3;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
overflow: auto;
|
||||||
|
height: 100%; /* Définit la hauteur de la page à 100% */
|
||||||
|
display: flex; /* Flexbox sur le body */
|
||||||
|
flex-direction: column; /* Aligne le contenu du body en colonne */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------- */
|
||||||
|
/* Header */
|
||||||
|
/* --------------- */
|
||||||
|
|
||||||
|
header {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 10px 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
header a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #eff1f3;
|
||||||
|
}
|
||||||
|
|
||||||
|
header ul {
|
||||||
|
list-style: none;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
header li {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text {
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1; /* Le conteneur des liens prend toute la place disponible */
|
||||||
|
justify-content: center; /* Centre les liens horizontalement */
|
||||||
|
gap: 15%; /* Espace entre les liens */
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text a {
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text li a:hover {
|
||||||
|
color: #00a8e8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion {
|
||||||
|
padding: 10px 20px;
|
||||||
|
border-radius: 900px;
|
||||||
|
font-size: 16px; /* Taille de la police */
|
||||||
|
border-color: #00a8e8;
|
||||||
|
color: #eff1f3;
|
||||||
|
background-color: #00a8e8;
|
||||||
|
margin-top: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion:hover {
|
||||||
|
border-color: #eff1f3;
|
||||||
|
color: #00a8e8;
|
||||||
|
background-color: #eff1f3; /* Changer la couleur au survol */
|
||||||
|
}
|
||||||
|
|
||||||
|
#smart_building {
|
||||||
|
width: 13%;
|
||||||
|
margin-left: -40px;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------- */
|
||||||
|
/* Complexe */
|
||||||
|
/* ----------------- */
|
||||||
|
|
||||||
|
body {
|
||||||
|
background-color: #1e1e1e;
|
||||||
|
color: #eff1f3;
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
main.admin-container {
|
||||||
|
padding: 40px;
|
||||||
|
max-width: 1000px;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
font-size: 36px;
|
||||||
|
color: #00a8e8;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
background-color: #2c2c2c;
|
||||||
|
border-radius: 12px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
th,
|
||||||
|
td {
|
||||||
|
padding: 12px 16px;
|
||||||
|
text-align: center;
|
||||||
|
border-bottom: 1px solid #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
background-color: #0077b6;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr:nth-child(even) {
|
||||||
|
background-color: #353535;
|
||||||
|
}
|
||||||
|
|
||||||
|
select,
|
||||||
|
button {
|
||||||
|
padding: 6px 10px;
|
||||||
|
border-radius: 6px;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
background-color: #00a8e8;
|
||||||
|
color: white;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:hover {
|
||||||
|
background-color: #0077b6;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------- */
|
||||||
|
/* Footer */
|
||||||
|
/* --------------- */
|
||||||
|
|
||||||
|
footer {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-size: 14px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
padding: 20px;
|
||||||
|
margin-top: auto; /* Cela force le footer à se pousser vers le bas */
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
padding: 10px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #eff1f3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_link {
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1;
|
||||||
|
gap: 10%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_link a {
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
padding: 10px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------- */
|
||||||
|
/* Responsive Design */
|
||||||
|
/* ------------------------- */
|
||||||
|
|
||||||
|
/* GRAND ÉCRAN (> 1440px) */
|
||||||
|
@media (min-width: 1440px) {
|
||||||
|
main.admin-container {
|
||||||
|
padding: 60px;
|
||||||
|
max-width: 1200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table th, table td {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion {
|
||||||
|
padding: 12px 24px;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TABLETTE - Moyenne (1025px à 1440px) */
|
||||||
|
@media (max-width: 1440px) and (min-width: 1025px) {
|
||||||
|
|
||||||
|
table th, table td {
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TABLETTE - Petite (769px à 1024px) */
|
||||||
|
@media (max-width: 1024px) and (min-width: 769px) {
|
||||||
|
header {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 20px;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#smart_building {
|
||||||
|
width: 100px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text {
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion {
|
||||||
|
padding: 8px 16px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
main.admin-container {
|
||||||
|
padding: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 36px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table th, table td {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* MOBILE (≤ 768px) */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
header {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#smart_building {
|
||||||
|
width: 90px;
|
||||||
|
height: auto;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion {
|
||||||
|
padding: 10px 20px;
|
||||||
|
width: auto;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
main.admin-container {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 28px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table th, table td {
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
flex-direction: column;
|
||||||
|
text-align: center;
|
||||||
|
gap: 10px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_link {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TÉLÉPHONE TRÈS PETIT (≤ 480px) */
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
main.admin-container {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 24px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion {
|
||||||
|
padding: 8px 16px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#smart_building {
|
||||||
|
width: 70px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table th, table td {
|
||||||
|
padding: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------- */
|
||||||
|
/* Transitions douces */
|
||||||
|
/* ------------------------- */
|
||||||
|
|
||||||
|
* {
|
||||||
|
transition: all 0.3s ease-in-out;
|
||||||
|
}
|
||||||
453
z1/webapp/public/styleConnexion.css
Normal file
@ -0,0 +1,453 @@
|
|||||||
|
/* ------------- */
|
||||||
|
/* HTML */
|
||||||
|
/* ------------- */
|
||||||
|
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
background-color: #1e1e1e;
|
||||||
|
color: #eff1f3;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
overflow: auto;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------- */
|
||||||
|
/* Header */
|
||||||
|
/* --------------- */
|
||||||
|
|
||||||
|
header {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 10px 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
header a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #eff1f3;
|
||||||
|
}
|
||||||
|
|
||||||
|
header ul {
|
||||||
|
list-style: none;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
header li {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text {
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1; /* Le conteneur des liens prend toute la place disponible */
|
||||||
|
justify-content: center; /* Centre les liens horizontalement */
|
||||||
|
gap: 15%; /* Espace entre les liens */
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text a {
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text li a:hover {
|
||||||
|
color: #00a8e8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion {
|
||||||
|
padding: 10px 20px;
|
||||||
|
border-radius: 900px;
|
||||||
|
font-size: 16px; /* Taille de la police */
|
||||||
|
border-color: #00a8e8;
|
||||||
|
color: #eff1f3;
|
||||||
|
background-color: #00a8e8;
|
||||||
|
margin-top: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion:hover {
|
||||||
|
border-color: #eff1f3;
|
||||||
|
color: #00a8e8;
|
||||||
|
background-color: #eff1f3; /* Changer la couleur au survol */
|
||||||
|
}
|
||||||
|
|
||||||
|
#smart_building {
|
||||||
|
width: 13%;
|
||||||
|
margin-left: -40px;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------- */
|
||||||
|
/* Connexion */
|
||||||
|
/* ------------------- */
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 45px; /* Taille de la police */
|
||||||
|
color: #eff1f3;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
#connexion {
|
||||||
|
display: flex; /* Ajouté pour aligner les enfants */
|
||||||
|
justify-content: center; /* Centrer les éléments verticalement */
|
||||||
|
align-items: center; /* Centrer les éléments horizontalement */
|
||||||
|
flex: 1;; /* Prend toute la hauteur de l'écran */
|
||||||
|
}
|
||||||
|
|
||||||
|
.building {
|
||||||
|
width: 23%;
|
||||||
|
height: 640px;
|
||||||
|
border-radius: 33px;
|
||||||
|
padding-left: 8%;
|
||||||
|
background-image: url("/images/building.jpg");
|
||||||
|
background-size: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-connexion {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 24px;
|
||||||
|
background-color: #2c2c2c;
|
||||||
|
padding: 40px 60px; /* Augmente l'espace intérieur */
|
||||||
|
width: 100%; /* Prend toute la largeur disponible */
|
||||||
|
max-width: 400px; /* Définit une largeur max pour éviter qu'elle ne devienne trop étroite */
|
||||||
|
box-shadow: 0 4px 8px 0 rgba(21, 21, 21, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
width: 100%;
|
||||||
|
position: relative; /* Position relative */
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group .icon {
|
||||||
|
position: absolute;
|
||||||
|
left: 15px; /* Ajuste la position des icônes */
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group .icon svg {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
fill: #191717;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control-connexion {
|
||||||
|
width: 100%;
|
||||||
|
padding-left: 50px; /* Remplissage à gauche de 55px */
|
||||||
|
padding-right: 80px;
|
||||||
|
height: 48px; /* Hauteur de 40px */
|
||||||
|
border-radius: 34px; /* Bordure arrondie */
|
||||||
|
font-size: 16px; /* Taille de la police */
|
||||||
|
letter-spacing: 0.5px; /* Espacement des lettres */
|
||||||
|
background-color: #eff1f3; /* Couleur de fond */
|
||||||
|
border: none; /* Supprimer la bordure */
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton-connexion {
|
||||||
|
padding: 10px 20px;
|
||||||
|
border-radius: 900px;
|
||||||
|
font-size: 16px; /* Taille de la police */
|
||||||
|
border-color: #00a8e8;
|
||||||
|
color: #eff1f3;
|
||||||
|
background-color: #00a8e8;
|
||||||
|
margin-top: 10px; /* Centrage vertical */
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton-connexion:hover {
|
||||||
|
border-color: #eff1f3;
|
||||||
|
color: #00a8e8;
|
||||||
|
background-color: #eff1f3; /* Changer la couleur au survol */
|
||||||
|
}
|
||||||
|
|
||||||
|
.lien {
|
||||||
|
display: inline-block; /* Permet de mieux gérer la taille du soulignement */
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
font-size: 20px; /* Taille de la police */
|
||||||
|
color: #eff1f3;
|
||||||
|
text-decoration: none; /* Supprime le soulignement par défaut */
|
||||||
|
text-underline-offset: 10px; /* Augmente l'espace entre le texte et le soulignement */
|
||||||
|
cursor: pointer;
|
||||||
|
padding-bottom: 10px; /* Ajoute un petit espace sous le texte */
|
||||||
|
position: relative; /* Positionner l'élément par rapport à son parent */
|
||||||
|
}
|
||||||
|
|
||||||
|
.lien::after {
|
||||||
|
content: "";
|
||||||
|
display: block;
|
||||||
|
width: 150%; /* La ligne est maintenant 1.5 fois plus grande que le texte */
|
||||||
|
height: 2px; /* Épaisseur du soulignement */
|
||||||
|
background-color: #eff1f3; /* Couleur du soulignement */
|
||||||
|
position: absolute;
|
||||||
|
left: 50%; /* Centre la ligne horizontalement */
|
||||||
|
transform: translateX(
|
||||||
|
-50%
|
||||||
|
); /* Déplace la ligne pour qu'elle soit exactement centrée */
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lien:hover {
|
||||||
|
color: #0077b6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cellule {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
margin-left: 9%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------- */
|
||||||
|
/* Footer */
|
||||||
|
/* --------------- */
|
||||||
|
|
||||||
|
footer {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-size: 14px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
padding: 20px;
|
||||||
|
margin-top: auto; /* Cela force le footer à se pousser vers le bas */
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
padding: 10px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #eff1f3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_link {
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1;
|
||||||
|
gap: 10%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_link a {
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
padding: 10px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------- */
|
||||||
|
/* Responsive Design */
|
||||||
|
/* ------------------------- */
|
||||||
|
|
||||||
|
/* GRAND ÉCRAN (> 1440px) */
|
||||||
|
@media (min-width: 1440px) {
|
||||||
|
h1 {
|
||||||
|
font-size: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.building {
|
||||||
|
height: 700px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control-connexion {
|
||||||
|
font-size: 18px;
|
||||||
|
height: 52px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* TABLETTE - Moyenne (1025px à 1440px) */
|
||||||
|
@media (max-width: 1440px) and (min-width: 1025px) {
|
||||||
|
h1 {
|
||||||
|
font-size: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.building {
|
||||||
|
height: 600px;
|
||||||
|
width: 28%;
|
||||||
|
padding-left: 5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-connexion {
|
||||||
|
padding: 40px 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control-connexion {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* TABLETTE - Petite (769px à 1024px) */
|
||||||
|
@media (max-width: 1024px) and (min-width: 769px) {
|
||||||
|
header {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 20px;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#smart_building {
|
||||||
|
width: 100px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text {
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion {
|
||||||
|
padding: 8px 16px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 40px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#connexion {
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 40px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.building {
|
||||||
|
width: 100%;
|
||||||
|
height: 300px;
|
||||||
|
border-radius: 20px;
|
||||||
|
padding: 0;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-connexion {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control-connexion {
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* MOBILE (≤ 768px) */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
header {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 15px;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion {
|
||||||
|
width: auto;
|
||||||
|
padding: 10px 16px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#smart_building {
|
||||||
|
width: 80px;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 32px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#connexion {
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.building {
|
||||||
|
width: 100%;
|
||||||
|
height: 250px;
|
||||||
|
padding: 0;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-connexion {
|
||||||
|
padding: 30px 20px;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control-connexion {
|
||||||
|
font-size: 14px;
|
||||||
|
height: 44px;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
text-align: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_link {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* TÉLÉPHONE TRÈS PETIT (≤ 480px) */
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
h1 {
|
||||||
|
font-size: 26px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control-connexion {
|
||||||
|
font-size: 13px;
|
||||||
|
padding-left: 40px;
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group .icon svg {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-connexion {
|
||||||
|
padding: 20px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton-connexion {
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 8px 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lien {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#smart_building {
|
||||||
|
width: 60px;
|
||||||
|
}
|
||||||
|
}
|
||||||
240
z1/webapp/public/styleContact.css
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
|
||||||
|
/* --------------- */
|
||||||
|
/* Header */
|
||||||
|
/* --------------- */
|
||||||
|
|
||||||
|
header {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 10px 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
header a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #eff1f3;
|
||||||
|
}
|
||||||
|
|
||||||
|
header ul {
|
||||||
|
list-style: none;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
header li {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text {
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1; /* Le conteneur des liens prend toute la place disponible */
|
||||||
|
justify-content: center; /* Centre les liens horizontalement */
|
||||||
|
gap: 15%; /* Espace entre les liens */
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text a {
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion {
|
||||||
|
padding: 10px 20px;
|
||||||
|
border-radius: 900px;
|
||||||
|
font-size: 16px; /* Taille de la police */
|
||||||
|
border-color: #00a8e8;
|
||||||
|
color: #eff1f3;
|
||||||
|
background-color: #00a8e8;
|
||||||
|
margin-top: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion:hover {
|
||||||
|
border-color: #eff1f3;
|
||||||
|
color: #00a8e8;
|
||||||
|
background-color: #eff1f3; /* Changer la couleur au survol */
|
||||||
|
}
|
||||||
|
|
||||||
|
#smart_building {
|
||||||
|
width: 13%;
|
||||||
|
margin-left: -40px;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
font-family: 'Segoe UI', sans-serif;
|
||||||
|
background-color: #121212;
|
||||||
|
color: #f1f1f1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-container {
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 60px auto;
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #1e1e1e;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 0 20px rgba(0,0,0,0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-container h1 {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
font-size: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-container p {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
color: #cccccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-form {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-form label {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-form input,
|
||||||
|
.contact-form textarea {
|
||||||
|
padding: 10px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
background-color: #2a2a2a;
|
||||||
|
color: #f1f1f1;
|
||||||
|
border: 1px solid #444;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-form input:focus,
|
||||||
|
.contact-form textarea:focus {
|
||||||
|
outline: none;
|
||||||
|
border: 1px solid #00bcd4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-form button {
|
||||||
|
background-color: #00bcd4;
|
||||||
|
color: #121212;
|
||||||
|
padding: 12px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
font-weight: bold;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-form button:hover {
|
||||||
|
background-color: #0097a7;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------------- */
|
||||||
|
/* FOOTER */
|
||||||
|
/* ---------------- */
|
||||||
|
|
||||||
|
footer {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-size: 14px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
padding: 20px;
|
||||||
|
margin-top: auto; /* Cela force le footer à se pousser vers le bas */
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
padding: 10px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #eff1f3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_link {
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1;
|
||||||
|
gap: 10%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_link a {
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
padding: 10px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
/* HEADER */
|
||||||
|
header {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
padding: 15px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion {
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#smart_building {
|
||||||
|
width: 40%;
|
||||||
|
margin-left: 0;
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CONTACT */
|
||||||
|
.contact-container {
|
||||||
|
width: 90%;
|
||||||
|
margin: 40px auto;
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-container h1 {
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-form input,
|
||||||
|
.contact-form textarea {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-form button {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FOOTER */
|
||||||
|
footer {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_link {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_link a {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
484
z1/webapp/public/styleInscription.css
Normal file
@ -0,0 +1,484 @@
|
|||||||
|
/* ------------- */
|
||||||
|
/* HTML */
|
||||||
|
/* ------------- */
|
||||||
|
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
background-color: #1e1e1e;
|
||||||
|
color: #eff1f3;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
overflow: auto;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------- */
|
||||||
|
/* Header */
|
||||||
|
/* --------------- */
|
||||||
|
|
||||||
|
header {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 10px 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
header a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #eff1f3;
|
||||||
|
}
|
||||||
|
|
||||||
|
header ul {
|
||||||
|
list-style: none;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
header li {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text {
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1; /* Le conteneur des liens prend toute la place disponible */
|
||||||
|
justify-content: center; /* Centre les liens horizontalement */
|
||||||
|
gap: 15%; /* Espace entre les liens */
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text a {
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text li a:hover {
|
||||||
|
color: #00a8e8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion {
|
||||||
|
padding: 10px 20px;
|
||||||
|
border-radius: 900px;
|
||||||
|
font-size: 16px; /* Taille de la police */
|
||||||
|
border-color: #00a8e8;
|
||||||
|
color: #eff1f3;
|
||||||
|
background-color: #00a8e8;
|
||||||
|
margin-top: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion:hover {
|
||||||
|
border-color: #eff1f3;
|
||||||
|
color: #00a8e8;
|
||||||
|
background-color: #eff1f3; /* Changer la couleur au survol */
|
||||||
|
}
|
||||||
|
|
||||||
|
#smart_building {
|
||||||
|
width: 13%;
|
||||||
|
margin-left: -40px;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------- */
|
||||||
|
/* Inscription */
|
||||||
|
/* --------------------- */
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 45px; /* Taille de la police */
|
||||||
|
color: #eff1f3;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 20px;
|
||||||
|
color: #eff1f3;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
appearance: none; /* Supprime le style natif */
|
||||||
|
background: white;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#inscription {
|
||||||
|
display: flex; /* Ajouté pour aligner les enfants */
|
||||||
|
justify-content: center; /* Centrer les éléments verticalement */
|
||||||
|
align-items: center; /* Centrer les éléments horizontalement */
|
||||||
|
flex: 1; /* Prend toute la hauteur de l'écran */
|
||||||
|
margin-bottom: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tour {
|
||||||
|
width: 23%;
|
||||||
|
height: 640px;
|
||||||
|
border-radius: 33px;
|
||||||
|
padding-left: 8%;
|
||||||
|
background-image: url("/images/tour.jpg");
|
||||||
|
background-size: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-inscription {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 24px;
|
||||||
|
background-color: #2c2c2c;
|
||||||
|
padding: 40px 100px; /* Augmente l'espace intérieur */
|
||||||
|
width: 100%; /* Prend toute la largeur disponible */
|
||||||
|
max-width: 400px; /* Définit une largeur max pour éviter qu'elle ne devienne trop étroite */
|
||||||
|
box-shadow: 0 4px 8px 0 rgba(21, 21, 21, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
width: 100%;
|
||||||
|
position: relative; /* Position relative */
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group .icon {
|
||||||
|
position: absolute;
|
||||||
|
left: 15px; /* Ajuste la position des icônes */
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group .icon svg {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
fill: #191717;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control-inscription {
|
||||||
|
width: 100%;
|
||||||
|
padding-left: 50px; /* Remplissage à gauche de 50px */
|
||||||
|
padding-right: 40px;
|
||||||
|
height: 48px; /* Hauteur de 48px */
|
||||||
|
border-radius: 34px; /* Bordure arrondie */
|
||||||
|
font-size: 16px; /* Taille de la police */
|
||||||
|
letter-spacing: 0.5px; /* Espacement des lettres */
|
||||||
|
background-color: #eff1f3; /* Couleur de fond */
|
||||||
|
border: none; /* Supprimer la bordure */
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px; /* espace entre label et champ */
|
||||||
|
flex-wrap: nowrap; /* évite le retour à la ligne */
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton-inscription {
|
||||||
|
padding: 10px 20px;
|
||||||
|
border-radius: 900px;
|
||||||
|
font-size: 16px; /* Taille de la police */
|
||||||
|
border-color: #00a8e8;
|
||||||
|
color: #eff1f3;
|
||||||
|
background-color: #00a8e8;
|
||||||
|
margin-top: 0; /* Centrage vertical */
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton-inscription:hover {
|
||||||
|
border-color: #eff1f3;
|
||||||
|
color: #00a8e8;
|
||||||
|
background-color: #eff1f3; /* Changer la couleur au survol */
|
||||||
|
}
|
||||||
|
|
||||||
|
.boutons {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20px;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Alignement parfait du bouton "Photo" */
|
||||||
|
.custom-file-upload {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 8px;
|
||||||
|
background-color: #004fa9;
|
||||||
|
color: #eff1f3;
|
||||||
|
padding: 10px 20px;
|
||||||
|
border-radius: 900px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-file-upload:hover {
|
||||||
|
background-color: #eff1f3;
|
||||||
|
color: #004fa9;
|
||||||
|
border: 1px solid #004fa9;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Alignement du SVG */
|
||||||
|
.custom-file-upload svg {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
vertical-align: middle;
|
||||||
|
padding-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.case {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
margin-right: 9%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lien {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
font-family: inherit; /* pour garder la cohérence du texte */
|
||||||
|
display: inline-block; /* Permet de mieux gérer la taille du soulignement */
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
font-size: 23px; /* Taille de la police */
|
||||||
|
color: #eff1f3;
|
||||||
|
text-decoration: none; /* Supprime le soulignement par défaut */
|
||||||
|
text-underline-offset: 10px; /* Augmente l'espace entre le texte et le soulignement */
|
||||||
|
cursor: pointer;
|
||||||
|
padding-bottom: 10px; /* Ajoute un petit espace sous le texte */
|
||||||
|
position: relative; /* Positionner l'élément par rapport à son parent */
|
||||||
|
}
|
||||||
|
|
||||||
|
.lien::after {
|
||||||
|
content: "";
|
||||||
|
display: block;
|
||||||
|
width: 120%; /* La ligne est maintenant 1.5 fois plus grande que le texte */
|
||||||
|
height: 2px; /* Épaisseur du soulignement */
|
||||||
|
background-color: #eff1f3; /* Couleur du soulignement */
|
||||||
|
position: absolute;
|
||||||
|
left: 50%; /* Centre la ligne horizontalement */
|
||||||
|
transform: translateX(
|
||||||
|
-50%
|
||||||
|
); /* Déplace la ligne pour qu'elle soit exactement centrée */
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lien:hover {
|
||||||
|
color: #0077b6;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------- */
|
||||||
|
/* Footer */
|
||||||
|
/* --------------- */
|
||||||
|
|
||||||
|
footer {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-size: 14px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
padding: 20px;
|
||||||
|
margin-top: auto; /* Cela force le footer à se pousser vers le bas */
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
padding: 10px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #eff1f3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_link {
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1;
|
||||||
|
gap: 10%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_link a {
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
padding: 10px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------- */
|
||||||
|
/* Media Queries */
|
||||||
|
/* ---------------------- */
|
||||||
|
|
||||||
|
/* GRAND ÉCRAN (> 1440px) */
|
||||||
|
@media (min-width: 1440px) {
|
||||||
|
h1 {
|
||||||
|
font-size: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tour {
|
||||||
|
height: 700px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control-inscription {
|
||||||
|
font-size: 18px;
|
||||||
|
height: 52px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TABLETTE - Moyenne (1025px à 1440px) */
|
||||||
|
@media (max-width: 1440px) and (min-width: 1025px) {
|
||||||
|
h1 {
|
||||||
|
font-size: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tour {
|
||||||
|
height: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-inscription {
|
||||||
|
padding: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control-inscription {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TABLETTE - Petite (769px à 1024px) */
|
||||||
|
@media (max-width: 1024px) and (min-width: 769px) {
|
||||||
|
header {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 20px;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#smart_building {
|
||||||
|
width: 100px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text {
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion {
|
||||||
|
padding: 8px 16px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 40px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tour {
|
||||||
|
width: 100%;
|
||||||
|
height: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control-inscription {
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* MOBILE (≤ 768px) */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
header {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 15px;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion {
|
||||||
|
width: auto;
|
||||||
|
padding: 10px 16px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#smart_building {
|
||||||
|
width: 80px;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 32px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tour {
|
||||||
|
height: 250px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control-inscription {
|
||||||
|
font-size: 14px;
|
||||||
|
height: 44px;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
text-align: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_link {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TÉLÉPHONE TRÈS PETIT (≤ 480px) */
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
h1 {
|
||||||
|
font-size: 26px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control-inscription {
|
||||||
|
font-size: 13px;
|
||||||
|
padding-left: 40px;
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group .icon svg {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-inscription {
|
||||||
|
padding: 20px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton-inscription {
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 8px 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lien {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tour {
|
||||||
|
width: 60px;
|
||||||
|
}
|
||||||
|
}
|
||||||
576
z1/webapp/public/styleMembres.css
Normal file
@ -0,0 +1,576 @@
|
|||||||
|
/* ------------- */
|
||||||
|
/* HTML */
|
||||||
|
/* ------------- */
|
||||||
|
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
font-family: "Inter", sans-serif;
|
||||||
|
background-color: #1e1e1e;
|
||||||
|
color: #eff1f3;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
overflow: auto;
|
||||||
|
height: 100%; /* Définit la hauteur de la page à 100% */
|
||||||
|
display: flex; /* Flexbox sur le body */
|
||||||
|
flex-direction: column; /* Aligne le contenu du body en colonne */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------- */
|
||||||
|
/* Header */
|
||||||
|
/* --------------- */
|
||||||
|
|
||||||
|
header {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 10px 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
header a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #eff1f3;
|
||||||
|
}
|
||||||
|
|
||||||
|
header ul {
|
||||||
|
list-style: none;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
header li {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text {
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1; /* Le conteneur des liens prend toute la place disponible */
|
||||||
|
justify-content: center; /* Centre les liens horizontalement */
|
||||||
|
gap: 15%; /* Espace entre les liens */
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text a {
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text li a:hover {
|
||||||
|
color: #00a8e8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion {
|
||||||
|
padding: 10px 20px;
|
||||||
|
border-radius: 900px;
|
||||||
|
font-size: 16px; /* Taille de la police */
|
||||||
|
border-color: #00a8e8;
|
||||||
|
color: #eff1f3;
|
||||||
|
background-color: #00a8e8;
|
||||||
|
margin-top: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion:hover {
|
||||||
|
border-color: #eff1f3;
|
||||||
|
color: #00a8e8;
|
||||||
|
background-color: #eff1f3; /* Changer la couleur au survol */
|
||||||
|
}
|
||||||
|
|
||||||
|
#smart_building {
|
||||||
|
width: 13%;
|
||||||
|
margin-left: -40px;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------- */
|
||||||
|
/* Membres */
|
||||||
|
/* ---------------- */
|
||||||
|
|
||||||
|
main {
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1; /* Permet à la section principale d'occuper l'espace restant */
|
||||||
|
justify-content: center; /* Centre verticalement le contenu */
|
||||||
|
align-items: center; /* Centre horizontalement le contenu */
|
||||||
|
padding-bottom: 50px;
|
||||||
|
gap: 30px; /* Espace entre les 2 sections */
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-panel {
|
||||||
|
flex: 3; /* 30% de la largeur totale */
|
||||||
|
display: flex;
|
||||||
|
justify-content: center; /* Centrer l'image horizontalement */
|
||||||
|
align-items: center; /* Centrer l'image verticalement */
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-panel img {
|
||||||
|
width: 100%; /* L'image prend toute la largeur de son conteneur */
|
||||||
|
max-width: 450px; /* Maximum de 300px de largeur */
|
||||||
|
height: auto; /* La hauteur de l'image s'ajuste automatiquement */
|
||||||
|
border-radius: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-panel {
|
||||||
|
flex: 7; /* 70% de la largeur totale */
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-panel h1 {
|
||||||
|
font-size: 60px;
|
||||||
|
margin-bottom: 60px;
|
||||||
|
padding-left: 50px; /* Ajoute un espacement à gauche du titre */
|
||||||
|
}
|
||||||
|
|
||||||
|
#membres-container {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr); /* 2 cartes par ligne */
|
||||||
|
gap: 30px;
|
||||||
|
justify-items: center;
|
||||||
|
padding: 20px 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.membre {
|
||||||
|
width: 100%; /* occupe toute la colonne */
|
||||||
|
max-width: 400px; /* limite visuelle de largeur */
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #2c2c2c;
|
||||||
|
color: #eff1f3;
|
||||||
|
border-radius: 20px;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
||||||
|
transition: transform 0.2s ease, background-color 0.3s ease;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.membre:hover {
|
||||||
|
background-color: #dfe3e6;
|
||||||
|
transform: translateY(-5px);
|
||||||
|
color: #2c2c2c;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.membre h3 {
|
||||||
|
font-size: 22px;
|
||||||
|
margin: 10px 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.membre h4 {
|
||||||
|
font-size: 18px;
|
||||||
|
margin: 5px 0;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.membre p {
|
||||||
|
margin: 6px 0;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------- */
|
||||||
|
/* Footer */
|
||||||
|
/* --------------- */
|
||||||
|
|
||||||
|
footer {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-size: 14px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
padding: 20px;
|
||||||
|
margin-top: auto; /* Cela force le footer à se pousser vers le bas */
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
padding: 10px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #eff1f3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_link {
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1;
|
||||||
|
gap: 10%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_link a {
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
padding: 10px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------- */
|
||||||
|
/* Barre Recherche */
|
||||||
|
/* -------------------- */
|
||||||
|
|
||||||
|
.form {
|
||||||
|
width: 300px;
|
||||||
|
margin: 0 50px;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
display: flex;
|
||||||
|
gap: 0.5rem;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
isolation: isolate;
|
||||||
|
--input-text-color: #363636;
|
||||||
|
--input-bg-color: #eff1f3;
|
||||||
|
--focus-input-bg-color: transparent;
|
||||||
|
--text-color: #2a2a2a;
|
||||||
|
--active-color: #eff1f3;
|
||||||
|
--width-of-input: 250px;
|
||||||
|
--inline-padding-of-input: 1.2em;
|
||||||
|
--gap: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fancy-bg {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
inset: 0;
|
||||||
|
background: var(--input-bg-color);
|
||||||
|
border-radius: 30px;
|
||||||
|
height: 100%;
|
||||||
|
z-index: -1;
|
||||||
|
pointer-events: none;
|
||||||
|
box-shadow: rgba(0, 0, 0, 0.16) 0px 1px 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
padding: 0.2em;
|
||||||
|
height: 40px;
|
||||||
|
padding-inline: var(--inline-padding-of-input);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search,
|
||||||
|
.close-btn {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search {
|
||||||
|
fill: var(--text-color);
|
||||||
|
left: var(--inline-padding-of-input);
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
width: 17px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input {
|
||||||
|
color: var(--input-text-color);
|
||||||
|
width: 100%;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
font-size: 1rem;
|
||||||
|
margin-inline: min(2em, calc(var(--inline-padding-of-input) + var(--gap)));
|
||||||
|
}
|
||||||
|
|
||||||
|
.input:focus {
|
||||||
|
outline: none;
|
||||||
|
color: #eff1f3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input:focus ~ .fancy-bg {
|
||||||
|
border: 1px solid var(--active-color);
|
||||||
|
background: var(--focus-input-bg-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.input:focus ~ .search {
|
||||||
|
fill: var(--active-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.input:valid ~ .close-btn {
|
||||||
|
visibility: visible;
|
||||||
|
color: #eff1f3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-btn {
|
||||||
|
right: var(--inline-padding-of-input);
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
box-shadow: none;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
padding: 0;
|
||||||
|
opacity: 1;
|
||||||
|
color: #eff1f3;
|
||||||
|
visibility: hidden;
|
||||||
|
font-size: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-btn:hover,
|
||||||
|
.close-btn:focus {
|
||||||
|
background: none;
|
||||||
|
font-weight: bold;
|
||||||
|
transform: scale(1.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.input:not(:focus):not(:placeholder-shown) {
|
||||||
|
color: #2a2a2a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input:not(:focus):not(:placeholder-shown) ~ .search {
|
||||||
|
fill: #2a2a2a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input:not(:focus):not(:placeholder-shown) ~ .close-btn {
|
||||||
|
color: #2a2a2a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-membres {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 70px;
|
||||||
|
margin-bottom: 60px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-membres h1 {
|
||||||
|
font-size: 60px;
|
||||||
|
margin: 0;
|
||||||
|
color: #eff1f3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------- */
|
||||||
|
/* Responsive Design */
|
||||||
|
/* ----------------------------- */
|
||||||
|
|
||||||
|
/* GRAND ÉCRAN (> 1440px) */
|
||||||
|
@media (min-width: 1440px) {
|
||||||
|
.right-panel h1,
|
||||||
|
.header-membres h1 {
|
||||||
|
font-size: 72px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-panel img {
|
||||||
|
max-width: 500px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* TABLETTE LARGE (1025px à 1440px) */
|
||||||
|
@media (max-width: 1440px) and (min-width: 1025px) {
|
||||||
|
.right-panel h1,
|
||||||
|
.header-membres h1 {
|
||||||
|
font-size: 56px;
|
||||||
|
padding-left: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-membres {
|
||||||
|
padding: 0 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#membres-container {
|
||||||
|
padding: 20px 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-panel img {
|
||||||
|
max-width: 400px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* TABLETTE MOYENNE (769px à 1024px) */
|
||||||
|
@media (max-width: 1024px) and (min-width: 769px) {
|
||||||
|
header {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 20px;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#smart_building {
|
||||||
|
width: 100px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text {
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion {
|
||||||
|
padding: 8px 16px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-panel,
|
||||||
|
.left-panel {
|
||||||
|
width: 100%;
|
||||||
|
flex: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.features {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-panel h1,
|
||||||
|
.header-membres h1 {
|
||||||
|
font-size: 42px;
|
||||||
|
padding-left: 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-membres {
|
||||||
|
padding: 0 30px;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form {
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#membres-container {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* MOBILE (≤ 768px) */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
header {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#smart_building {
|
||||||
|
width: 90px;
|
||||||
|
height: auto;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion {
|
||||||
|
padding: 10px 20px;
|
||||||
|
width: auto;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-panel,
|
||||||
|
.right-panel {
|
||||||
|
width: 100%;
|
||||||
|
flex: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-panel h1,
|
||||||
|
.header-membres h1 {
|
||||||
|
font-size: 36px;
|
||||||
|
padding-left: 0;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-membres {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20px;
|
||||||
|
padding: 0 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#membres-container {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.membre {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
flex-direction: column;
|
||||||
|
text-align: center;
|
||||||
|
gap: 10px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_link {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* MOBILE TRÈS PETIT (≤ 480px) */
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
.right-panel h1,
|
||||||
|
.header-membres h1 {
|
||||||
|
font-size: 28px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form {
|
||||||
|
width: 90%;
|
||||||
|
max-width: 280px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-btn {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#membres-container {
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.membre {
|
||||||
|
padding: 16px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.membre h3 {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.membre h4 {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.membre p {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------------------ */
|
||||||
|
/* Transitions Générales */
|
||||||
|
/* ------------------------ */
|
||||||
|
|
||||||
|
* {
|
||||||
|
transition: all 0.3s ease-in-out;
|
||||||
|
}
|
||||||
472
z1/webapp/public/styleObjets.css
Normal file
@ -0,0 +1,472 @@
|
|||||||
|
/* ------------- */
|
||||||
|
/* HTML */
|
||||||
|
/* ------------- */
|
||||||
|
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
font-family: "Inter", sans-serif;
|
||||||
|
background-color: #1e1e1e;
|
||||||
|
color: #eff1f3;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
overflow: auto;
|
||||||
|
height: 100%; /* Définit la hauteur de la page à 100% */
|
||||||
|
display: flex; /* Flexbox sur le body */
|
||||||
|
flex-direction: column; /* Aligne le contenu du body en colonne */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------- */
|
||||||
|
/* Header */
|
||||||
|
/* --------------- */
|
||||||
|
|
||||||
|
header {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 10px 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
header a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #eff1f3;
|
||||||
|
}
|
||||||
|
|
||||||
|
header ul {
|
||||||
|
list-style: none;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
header li {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text {
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1; /* Le conteneur des liens prend toute la place disponible */
|
||||||
|
justify-content: center; /* Centre les liens horizontalement */
|
||||||
|
gap: 15%; /* Espace entre les liens */
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text a {
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion {
|
||||||
|
padding: 10px 20px;
|
||||||
|
border-radius: 900px;
|
||||||
|
font-size: 16px; /* Taille de la police */
|
||||||
|
border-color: #00a8e8;
|
||||||
|
color: #eff1f3;
|
||||||
|
background-color: #00a8e8;
|
||||||
|
margin-top: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion:hover {
|
||||||
|
border-color: #eff1f3;
|
||||||
|
color: #00a8e8;
|
||||||
|
background-color: #eff1f3; /* Changer la couleur au survol */
|
||||||
|
}
|
||||||
|
|
||||||
|
#smart_building {
|
||||||
|
width: 13%;
|
||||||
|
margin-left: -40px;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------- */
|
||||||
|
/* Objets */
|
||||||
|
/* --------------- */
|
||||||
|
|
||||||
|
main {
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1; /* Permet à la section principale d'occuper l'espace restant */
|
||||||
|
justify-content: center; /* Centre verticalement le contenu */
|
||||||
|
align-items: center; /* Centre horizontalement le contenu */
|
||||||
|
padding-bottom: 50px;
|
||||||
|
gap: 30px; /* Espace entre les 2 sections */
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-panel {
|
||||||
|
flex: 3; /* 30% de la largeur totale */
|
||||||
|
display: flex;
|
||||||
|
justify-content: center; /* Centrer l'image horizontalement */
|
||||||
|
align-items: center; /* Centrer l'image verticalement */
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-panel img {
|
||||||
|
width: 100%; /* L'image prend toute la largeur de son conteneur */
|
||||||
|
max-width: 450px; /* Maximum de 300px de largeur */
|
||||||
|
height: auto; /* La hauteur de l'image s'ajuste automatiquement */
|
||||||
|
border-radius: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-panel {
|
||||||
|
flex: 7; /* 70% de la largeur totale */
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-panel h1 {
|
||||||
|
font-size: 60px;
|
||||||
|
margin-bottom: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-objets {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 70px;
|
||||||
|
margin-bottom: 60px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-objets h1 {
|
||||||
|
font-size: 60px;
|
||||||
|
margin: 0;
|
||||||
|
color: #eff1f3;
|
||||||
|
}
|
||||||
|
|
||||||
|
#objets-container {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr); /* 3 cartes par ligne */
|
||||||
|
gap: 20px;
|
||||||
|
justify-items: center;
|
||||||
|
padding: 20px 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.objet {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 300px; /* Limite la largeur des cartes pour que ça soit plus joli */
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #2c2c2c;
|
||||||
|
color: #eff1f3;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
||||||
|
transition: transform 0.2s ease, background-color 0.3s ease;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.objet:hover {
|
||||||
|
transform: translateY(-5px);
|
||||||
|
background-color: #dfe3e6;
|
||||||
|
color: #2c2c2c;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.objet h3 {
|
||||||
|
font-size: 22px;
|
||||||
|
margin: 10px 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.etat-point {
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
border-radius: 50%;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 5px;
|
||||||
|
right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.etat-point.actif {
|
||||||
|
background-color: rgb(100, 236, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
.etat-point.inactif {
|
||||||
|
background-color: rgb(240, 84, 84);
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-btn {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-btn i {
|
||||||
|
font-size: 20px;
|
||||||
|
color: #a8a3a3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-btn:hover i {
|
||||||
|
transform: scale(1.4);
|
||||||
|
transition: transform 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.objet:hover i {
|
||||||
|
color: #2c2c2c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.info_objet{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info_objet h2{
|
||||||
|
margin-bottom: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info_objet h4{
|
||||||
|
margin:0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.edit-button {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.edit-button i {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #eff1f3;
|
||||||
|
transition: transform 0.2s ease;
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.edit-button:hover i {
|
||||||
|
transform: scale(1.3) translateY(-2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-edit {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inline-edit h2,
|
||||||
|
.inline-edit p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[contenteditable="true"] {
|
||||||
|
border: 1px solid #eff1f3; /* Bordure fine autour de l'élément modifiable */
|
||||||
|
border-radius: 4px; /* Bords arrondis pour un style plus doux */
|
||||||
|
padding: 3px 5px; /* Un peu de padding pour l'esthétique */
|
||||||
|
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1); /* Ombre légère autour de l'élément */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Style modal */
|
||||||
|
.modal {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
background: rgba(60, 60, 60, 0.98); /* Plus clair que le fond de base */
|
||||||
|
backdrop-filter: blur(12px); /* Plus de flou = plus de séparation */
|
||||||
|
padding: 30px;
|
||||||
|
border-radius: 20px;
|
||||||
|
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.8); /* Ombre plus forte */
|
||||||
|
color: #eff1f3;
|
||||||
|
max-width: 450px;
|
||||||
|
width: 90%;
|
||||||
|
z-index: 1000;
|
||||||
|
animation: fadeIn 0.3s ease;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.1); /* Léger contour clair */
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal h2 {
|
||||||
|
font-size: 24px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
color: #eff1f3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal p {
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal .close {
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
right: 15px;
|
||||||
|
font-size: 22px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #eff1f3;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: transform 0.2s ease, color 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal .close:hover {
|
||||||
|
color: #ff4d4d;
|
||||||
|
transform: scale(1.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------- */
|
||||||
|
/* Barre Recherche */
|
||||||
|
/* -------------------- */
|
||||||
|
|
||||||
|
.form {
|
||||||
|
width: 300px;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
display: flex;
|
||||||
|
gap: 0.5rem;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
isolation: isolate;
|
||||||
|
--input-text-color: #363636;
|
||||||
|
--input-bg-color: #eff1f3;
|
||||||
|
--focus-input-bg-color: transparent;
|
||||||
|
--text-color: #2a2a2a;
|
||||||
|
--active-color: #eff1f3;
|
||||||
|
--width-of-input: 250px;
|
||||||
|
--inline-padding-of-input: 1.2em;
|
||||||
|
--gap: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fancy-bg {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
inset: 0;
|
||||||
|
background: var(--input-bg-color);
|
||||||
|
border-radius: 30px;
|
||||||
|
height: 100%;
|
||||||
|
z-index: -1;
|
||||||
|
pointer-events: none;
|
||||||
|
box-shadow: rgba(0, 0, 0, 0.16) 0px 1px 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
padding: 0.2em;
|
||||||
|
height: 40px;
|
||||||
|
padding-inline: var(--inline-padding-of-input);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search,
|
||||||
|
.close-btn {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search {
|
||||||
|
fill: var(--text-color);
|
||||||
|
left: var(--inline-padding-of-input);
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
width: 17px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input {
|
||||||
|
color: var(--input-text-color); /* La couleur du texte par défaut */
|
||||||
|
width: 100%;
|
||||||
|
margin-inline: min(2em, calc(var(--inline-padding-of-input) + var(--gap)));
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input:focus {
|
||||||
|
outline: none;
|
||||||
|
color: #eff1f3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* input background change in focus */
|
||||||
|
.input:focus ~ .fancy-bg {
|
||||||
|
border: 1px solid var(--active-color);
|
||||||
|
background: var(--focus-input-bg-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* search icon color change in focus */
|
||||||
|
.input:focus ~ .search {
|
||||||
|
fill: var(--active-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* showing close button when typing */
|
||||||
|
.input:valid ~ .close-btn {
|
||||||
|
visibility: visible; /* Si l'input est valide, rendre le bouton visible */
|
||||||
|
color: #eff1f3; /* Garde l'icône en blanc */
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-btn {
|
||||||
|
right: var(--inline-padding-of-input);
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
box-shadow: none;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
padding: 0;
|
||||||
|
opacity: 1;
|
||||||
|
color: #eff1f3;
|
||||||
|
visibility: hidden;
|
||||||
|
font-size: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-btn:hover,
|
||||||
|
.close-btn:focus {
|
||||||
|
background: none;
|
||||||
|
font-weight: bold;
|
||||||
|
transform: scale(1.2); /* Légèrement agrandit l'icône pour la rendre plus évidente */
|
||||||
|
}
|
||||||
|
|
||||||
|
.input:not(:focus):not(:placeholder-shown) {
|
||||||
|
color: #2a2a2a; /* Couleur texte sombre si champ rempli mais pas focus */
|
||||||
|
}
|
||||||
|
|
||||||
|
.input:not(:focus):not(:placeholder-shown) ~ .search {
|
||||||
|
fill: #2a2a2a; /* Loupe sombre quand input rempli mais pas focus */
|
||||||
|
}
|
||||||
|
|
||||||
|
.input:not(:focus):not(:placeholder-shown) ~ .close-btn {
|
||||||
|
color: #2a2a2a; /* Croix sombre également */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------- */
|
||||||
|
/* Footer */
|
||||||
|
/* --------------- */
|
||||||
|
|
||||||
|
footer {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-size: 14px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
padding: 20px;
|
||||||
|
margin-top: auto; /* Cela force le footer à se pousser vers le bas */
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
padding: 10px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #eff1f3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_link {
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1;
|
||||||
|
gap: 10%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_link a {
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
padding: 10px 20px;
|
||||||
|
}
|
||||||
378
z1/webapp/public/styleProfil.css
Normal file
@ -0,0 +1,378 @@
|
|||||||
|
/* ------------- */
|
||||||
|
/* HTML */
|
||||||
|
/* ------------- */
|
||||||
|
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
font-family: "Inter", sans-serif;
|
||||||
|
background-color: #1e1e1e;
|
||||||
|
color: #eff1f3;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
overflow: auto;
|
||||||
|
height: 100%; /* Définit la hauteur de la page à 100% */
|
||||||
|
display: flex; /* Flexbox sur le body */
|
||||||
|
flex-direction: column; /* Aligne le contenu du body en colonne */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------- */
|
||||||
|
/* Header */
|
||||||
|
/* --------------- */
|
||||||
|
|
||||||
|
header {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 10px 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
header a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #eff1f3;
|
||||||
|
}
|
||||||
|
|
||||||
|
header ul {
|
||||||
|
list-style: none;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
header li {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text {
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1; /* Le conteneur des liens prend toute la place disponible */
|
||||||
|
justify-content: center; /* Centre les liens horizontalement */
|
||||||
|
gap: 15%; /* Espace entre les liens */
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text a {
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text li a:hover {
|
||||||
|
color: #00a8e8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion {
|
||||||
|
padding: 10px 20px;
|
||||||
|
border-radius: 900px;
|
||||||
|
font-size: 16px; /* Taille de la police */
|
||||||
|
border-color: #00a8e8;
|
||||||
|
color: #eff1f3;
|
||||||
|
background-color: #00a8e8;
|
||||||
|
margin-top: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion:hover {
|
||||||
|
border-color: #eff1f3;
|
||||||
|
color: #00a8e8;
|
||||||
|
background-color: #eff1f3; /* Changer la couleur au survol */
|
||||||
|
}
|
||||||
|
|
||||||
|
#smart_building {
|
||||||
|
width: 13%;
|
||||||
|
margin-left: -40px;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------- */
|
||||||
|
/* Profil */
|
||||||
|
/* --------------- */
|
||||||
|
|
||||||
|
/* Conteneur Profil */
|
||||||
|
.container {
|
||||||
|
width: 80%; /* Adaptation à la nouvelle structure, largeur plus grande */
|
||||||
|
max-width: 800px; /* Limite la taille maximale à 800px */
|
||||||
|
margin: 50px auto; /* Centre le conteneur et ajoute un espacement */
|
||||||
|
background-color: #2c2c2c;
|
||||||
|
padding: 30px 40px;
|
||||||
|
border-radius: 15px;
|
||||||
|
box-shadow: 0 0 20px rgba(0, 0, 0, 0.6);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column; /* Assure un alignement vertical des éléments */
|
||||||
|
gap: 20px; /* Espacement entre les éléments internes */
|
||||||
|
z-index: 1; /* Pour s'assurer que ce contenu reste bien en-dessous de l'en-tête */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Titre */
|
||||||
|
h1 {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Formulaire Profil */
|
||||||
|
form div {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Champs de saisie */
|
||||||
|
input[type="text"],
|
||||||
|
input[type="password"],
|
||||||
|
input[type="file"],
|
||||||
|
select {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px 12px;
|
||||||
|
font-size: 14px;
|
||||||
|
background-color: #3a3a3a;
|
||||||
|
color: #ffffff;
|
||||||
|
border: 1px solid #555;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
transition: border-color 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Champs désactivés */
|
||||||
|
input:disabled,
|
||||||
|
select:disabled {
|
||||||
|
background-color: #2c2c2c;
|
||||||
|
color: #888;
|
||||||
|
border: 1px solid #444;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Image de profil */
|
||||||
|
.container img {
|
||||||
|
margin-top: 10px;
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 2px solid #444;
|
||||||
|
max-width: 100px;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Boutons (Editer, Sauvegarder) */
|
||||||
|
button {
|
||||||
|
padding: 10px 16px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: 15px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s ease;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bouton Modifier */
|
||||||
|
#editBtn {
|
||||||
|
background-color: #27ae60;
|
||||||
|
}
|
||||||
|
|
||||||
|
#editBtn:hover {
|
||||||
|
background-color: #219150;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bouton Sauvegarder */
|
||||||
|
#saveBtn {
|
||||||
|
background-color: #e67e22;
|
||||||
|
}
|
||||||
|
|
||||||
|
#saveBtn:hover {
|
||||||
|
background-color: #d35400;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------- */
|
||||||
|
/* Footer */
|
||||||
|
/* --------------- */
|
||||||
|
|
||||||
|
footer {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
font-size: 14px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
padding: 20px;
|
||||||
|
margin-top: auto; /* Cela force le footer à se pousser vers le bas */
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
padding: 10px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #eff1f3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_link {
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1;
|
||||||
|
gap: 10%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_link a {
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
padding: 10px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------- */
|
||||||
|
/* Responsive Design */
|
||||||
|
/* ------------------------- */
|
||||||
|
|
||||||
|
/* GRAND ÉCRAN (> 1440px) */
|
||||||
|
@media (min-width: 1440px) {
|
||||||
|
main {
|
||||||
|
padding: 60px;
|
||||||
|
max-width: 1200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
width: 70%;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion {
|
||||||
|
padding: 12px 24px;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TABLETTE - Moyenne (1025px à 1440px) */
|
||||||
|
@media (max-width: 1440px) and (min-width: 1025px) {
|
||||||
|
.container {
|
||||||
|
width: 75%;
|
||||||
|
max-width: 1000px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion {
|
||||||
|
padding: 10px 20px;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TABLETTE - Petite (769px à 1024px) */
|
||||||
|
@media (max-width: 1024px) and (min-width: 769px) {
|
||||||
|
header {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 20px;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#smart_building {
|
||||||
|
width: 100px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text {
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion {
|
||||||
|
padding: 8px 16px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
width: 90%;
|
||||||
|
max-width: 1000px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 36px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* MOBILE (≤ 768px) */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
header {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#smart_building {
|
||||||
|
width: 90px;
|
||||||
|
height: auto;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_text {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion {
|
||||||
|
padding: 10px 20px;
|
||||||
|
width: auto;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 28px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
flex-direction: column;
|
||||||
|
text-align: center;
|
||||||
|
gap: 10px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_link {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TÉLÉPHONE TRÈS PETIT (≤ 480px) */
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
.container {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 24px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bouton_connexion {
|
||||||
|
padding: 8px 16px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#smart_building {
|
||||||
|
width: 70px;
|
||||||
|
}
|
||||||
|
}
|
||||||
1
z1/webapp/query
Normal file
@ -0,0 +1 @@
|
|||||||
|
mysql
|
||||||
115
z1/webapp/routes/admin.js
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const router = express.Router();
|
||||||
|
const db = require('../config/db');
|
||||||
|
|
||||||
|
// Middleware de protection admin (défini ici si non global)
|
||||||
|
const requireAdmin = (req, res, next) => {
|
||||||
|
if (!req.session.utilisateur || req.session.utilisateur.statut !== 'administrateur') {
|
||||||
|
return res.send(`
|
||||||
|
<script>
|
||||||
|
alert("Tu n'es pas connecté en tant qu'admin !");
|
||||||
|
window.location.href = '/connexion';
|
||||||
|
</script>
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Applique le middleware à toutes les routes de ce fichier
|
||||||
|
router.use(requireAdmin);
|
||||||
|
|
||||||
|
// Route principale - admin dashboard
|
||||||
|
router.get('/', (req, res) => {
|
||||||
|
const usersQuery = 'SELECT * FROM utilisateur';
|
||||||
|
const objetsQuery = 'SELECT * FROM objet';
|
||||||
|
const contactsQuery = 'SELECT * FROM contact'; // Récupérer les messages de contact
|
||||||
|
|
||||||
|
db.query(usersQuery, (err, utilisateurs) => {
|
||||||
|
if (err) return res.status(500).send('Erreur récupération utilisateurs');
|
||||||
|
|
||||||
|
db.query(objetsQuery, (err2, objets) => {
|
||||||
|
if (err2) return res.status(500).send('Erreur récupération objets');
|
||||||
|
|
||||||
|
db.query(contactsQuery, (err3, contacts) => {
|
||||||
|
if (err3) return res.status(500).send('Erreur récupération messages');
|
||||||
|
res.render('admin', { utilisateurs, objets, contacts });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Mise à jour utilisateur
|
||||||
|
router.post('/update-user', (req, res) => {
|
||||||
|
const { id, etat, statut } = req.body;
|
||||||
|
const sql = 'UPDATE utilisateur SET etat = ?, statut = ? WHERE id = ?';
|
||||||
|
|
||||||
|
db.query(sql, [etat, statut, id], (err) => {
|
||||||
|
if (err) {
|
||||||
|
console.error('Erreur update utilisateur :', err);
|
||||||
|
return res.status(500).send('Erreur update utilisateur');
|
||||||
|
}
|
||||||
|
res.redirect('/admin');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Suppression utilisateur
|
||||||
|
router.post('/supprimer-user', (req, res) => {
|
||||||
|
const { id } = req.body;
|
||||||
|
const sql = 'DELETE FROM utilisateur WHERE id = ?';
|
||||||
|
|
||||||
|
db.query(sql, [id], (err) => {
|
||||||
|
if (err) {
|
||||||
|
console.error('Erreur suppression utilisateur :', err);
|
||||||
|
return res.status(500).send("Erreur lors de la suppression de l'utilisateur");
|
||||||
|
}
|
||||||
|
res.redirect('/admin');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Mise à jour objet
|
||||||
|
router.post('/update-objet', (req, res) => {
|
||||||
|
const { adresse_ip, niveau, etat, type } = req.body;
|
||||||
|
const sql = 'UPDATE objet SET niveau = ?, etat = ?, type = ? WHERE adresse_ip = ?';
|
||||||
|
|
||||||
|
db.query(sql, [niveau, etat, type, adresse_ip], (err) => {
|
||||||
|
if (err) {
|
||||||
|
console.error('Erreur update objet :', err);
|
||||||
|
return res.status(500).send('Erreur update objet');
|
||||||
|
}
|
||||||
|
res.redirect('/admin');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Suppression objet + dépendances
|
||||||
|
router.post('/supprimer-objet', (req, res) => {
|
||||||
|
const { adresse_ip } = req.body;
|
||||||
|
const deleteChildTables = ['climatisation_chauffage', 'thermostat', 'appareil_menager', 'securite'];
|
||||||
|
|
||||||
|
const deleteFromTable = (table) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const sql = `DELETE FROM ${table} WHERE adresse_ip = ?`;
|
||||||
|
db.query(sql, [adresse_ip], (err) => {
|
||||||
|
if (err) return reject(err);
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Promise.all(deleteChildTables.map(deleteFromTable))
|
||||||
|
.then(() => {
|
||||||
|
const sql = 'DELETE FROM objet WHERE adresse_ip = ?';
|
||||||
|
db.query(sql, [adresse_ip], (err) => {
|
||||||
|
if (err) {
|
||||||
|
console.error('Erreur suppression objet :', err);
|
||||||
|
return res.status(500).send("Erreur lors de la suppression de l'objet");
|
||||||
|
}
|
||||||
|
res.redirect('/admin');
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error("Erreur suppression dépendances : ", err);
|
||||||
|
res.status(500).send("Erreur lors de la suppression des dépendances liées à l'objet");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
56
z1/webapp/routes/api/objet.js
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const router = express.Router();
|
||||||
|
const db = require('../../config/db');
|
||||||
|
|
||||||
|
router.get('/', (req, res) => {
|
||||||
|
const sql = `
|
||||||
|
SELECT
|
||||||
|
objet.adresse_ip,
|
||||||
|
objet.niveau,
|
||||||
|
objet.denomination,
|
||||||
|
objet.etat,
|
||||||
|
objet.derniere_interaction,
|
||||||
|
objet.type,
|
||||||
|
thermostat.temperature_actuelle,
|
||||||
|
thermostat.temperature_cible,
|
||||||
|
thermostat.mode,
|
||||||
|
appareil_menager.depart_differe,
|
||||||
|
appareil_menager.etat_de_la_tache,
|
||||||
|
securite.situation AS situation_securite
|
||||||
|
FROM objet
|
||||||
|
LEFT JOIN thermostat ON objet.adresse_ip = thermostat.adresse_ip
|
||||||
|
LEFT JOIN appareil_menager ON objet.adresse_ip = appareil_menager.adresse_ip
|
||||||
|
LEFT JOIN securite ON objet.adresse_ip = securite.adresse_ip
|
||||||
|
`;
|
||||||
|
|
||||||
|
db.query(sql, (err, result) => {
|
||||||
|
if (err) {
|
||||||
|
console.error('Erreur lors de la récupération des objets :', err);
|
||||||
|
return res.status(500).send('Erreur serveur');
|
||||||
|
}
|
||||||
|
res.json(result);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
router.put('/:adresse_ip', (req, res) => {
|
||||||
|
const adresse_ip = req.params.adresse_ip;
|
||||||
|
const champs = req.body;
|
||||||
|
|
||||||
|
const setValues = Object.keys(champs)
|
||||||
|
.map(key => `${key} = ?`)
|
||||||
|
.join(', ');
|
||||||
|
|
||||||
|
const sql = `UPDATE objet SET ${setValues} WHERE adresse_ip = ?`;
|
||||||
|
const values = [...Object.values(champs), adresse_ip];
|
||||||
|
|
||||||
|
db.query(sql, values, (err) => {
|
||||||
|
if (err) {
|
||||||
|
console.error('Erreur lors de la mise à jour de l\'objet :', err);
|
||||||
|
return res.status(500).send('Erreur serveur');
|
||||||
|
}
|
||||||
|
res.sendStatus(200);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
34
z1/webapp/routes/api/ressource.js
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const router = express.Router();
|
||||||
|
const db = require('../../config/db'); // Connexion à la base de données
|
||||||
|
|
||||||
|
// Route pour récupérer les ressources
|
||||||
|
router.get('/', (req, res) => {
|
||||||
|
const search = req.query.search || '';
|
||||||
|
|
||||||
|
if (search) {
|
||||||
|
const sql = 'SELECT * FROM ressources WHERE nom LIKE ?';
|
||||||
|
const values = [`%${search}%`];
|
||||||
|
|
||||||
|
db.query(sql, values, (err, results) => {
|
||||||
|
if (err) {
|
||||||
|
console.error('Erreur lors de la recherche des ressources :', err);
|
||||||
|
res.status(500).send('Erreur serveur');
|
||||||
|
} else {
|
||||||
|
res.json(results);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const sql = 'SELECT * FROM ressources';
|
||||||
|
db.query(sql, (err, results) => {
|
||||||
|
if (err) {
|
||||||
|
console.error('Erreur lors de la récupération des ressources :', err);
|
||||||
|
res.status(500).send('Erreur serveur');
|
||||||
|
} else {
|
||||||
|
res.json(results);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
18
z1/webapp/routes/api/utilisateur.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const router = express.Router();
|
||||||
|
const db = require('../../config/db'); // Connexion à la base de données
|
||||||
|
|
||||||
|
// Route pour récupérer les objets
|
||||||
|
router.get('/', (req, res) => {
|
||||||
|
const sql = 'SELECT * FROM utilisateur';
|
||||||
|
db.query(sql, (err, results) => {
|
||||||
|
if (err) {
|
||||||
|
console.error('Erreur lors de la récupération des objets :', err);
|
||||||
|
res.status(500).send('Erreur serveur');
|
||||||
|
} else {
|
||||||
|
res.json(results); // Retourne les objets sous forme de JSON
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
77
z1/webapp/routes/complexe.js
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const router = express.Router();
|
||||||
|
const db = require('../config/db');
|
||||||
|
|
||||||
|
// Modifier un objet
|
||||||
|
router.post('/update-objet', (req, res) => {
|
||||||
|
const { adresse_ip, niveau, etat } = req.body;
|
||||||
|
const sql = 'UPDATE objet SET niveau = ?, etat = ? WHERE adresse_ip = ?';
|
||||||
|
|
||||||
|
db.query(sql, [niveau, etat, adresse_ip], (err) => {
|
||||||
|
if (err) {
|
||||||
|
console.error("Erreur lors de la modification de l'objet :", err);
|
||||||
|
return res.status(500).send("Erreur lors de la modification de l'objet");
|
||||||
|
}
|
||||||
|
res.redirect('/dashboard-complexe');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Supprimer un objet (et ses dépendances)
|
||||||
|
router.post('/supprimer-objet', (req, res) => {
|
||||||
|
const { adresse_ip } = req.body;
|
||||||
|
console.log('Adresse IP reçue pour suppression :', adresse_ip);
|
||||||
|
|
||||||
|
const deleteChildTables = [
|
||||||
|
'climatisation_chauffage',
|
||||||
|
'thermostat',
|
||||||
|
'appareil_menager',
|
||||||
|
'securite'
|
||||||
|
];
|
||||||
|
|
||||||
|
const deleteFromTable = (table) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const sql = `DELETE FROM ${table} WHERE adresse_ip = ?`;
|
||||||
|
db.query(sql, [adresse_ip], (err) => {
|
||||||
|
if (err) {
|
||||||
|
console.error(`Erreur suppression dans ${table} :`, err);
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Promise.all(deleteChildTables.map(deleteFromTable))
|
||||||
|
.then(() => {
|
||||||
|
db.query('DELETE FROM objet WHERE adresse_ip = ?', [adresse_ip], (err) => {
|
||||||
|
if (err) {
|
||||||
|
console.error('Erreur suppression objet :', err);
|
||||||
|
return res.status(500).send("Erreur lors de la suppression de l'objet");
|
||||||
|
}
|
||||||
|
res.redirect('/dashboard-complexe');
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
res.status(500).send("Erreur lors de la suppression d'une dépendance liée à l'objet");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Ajouter un objet
|
||||||
|
router.post('/ajouter-objet', (req, res) => {
|
||||||
|
const { denomination, adresse_ip, type, niveau, etat } = req.body;
|
||||||
|
|
||||||
|
const sql = `
|
||||||
|
INSERT INTO objet (denomination, adresse_ip, type, niveau, etat)
|
||||||
|
VALUES (?, ?, ?, ?, ?)`;
|
||||||
|
|
||||||
|
db.query(sql, [denomination, adresse_ip, type, niveau, etat], (err) => {
|
||||||
|
if (err) {
|
||||||
|
console.error('Erreur ajout objet :', err);
|
||||||
|
return res.status(500).send("Erreur lors de l'ajout de l'objet");
|
||||||
|
}
|
||||||
|
|
||||||
|
res.redirect('/dashboard-complexe');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
52
z1/webapp/routes/connexion.js
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const router = express.Router();
|
||||||
|
const bcrypt = require('bcrypt');
|
||||||
|
const db = require('../config/db');
|
||||||
|
|
||||||
|
// Connexion - Formulaire
|
||||||
|
router.get('/', (req, res) => {
|
||||||
|
res.render('connexion');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Connexion - Traitement
|
||||||
|
router.post('/', (req, res) => {
|
||||||
|
const { identifiant, mot_de_passe } = req.body;
|
||||||
|
|
||||||
|
const sql = 'SELECT * FROM utilisateur WHERE identifiant = ?';
|
||||||
|
db.query(sql, [identifiant], async (err, results) => {
|
||||||
|
if (err) {
|
||||||
|
console.error('Erreur lors de la requête :', err);
|
||||||
|
return res.send('Erreur serveur');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (results.length === 0) {
|
||||||
|
return res.send('Identifiant incorrect');
|
||||||
|
}
|
||||||
|
|
||||||
|
const utilisateur = results[0];
|
||||||
|
const match = await bcrypt.compare(mot_de_passe, utilisateur.mot_de_passe);
|
||||||
|
|
||||||
|
if (!match) {
|
||||||
|
return res.send('Mot de passe incorrect');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enregistrement en session
|
||||||
|
req.session.utilisateur = utilisateur;
|
||||||
|
console.log("Utilisateur connecté :", req.session.utilisateur);
|
||||||
|
|
||||||
|
// Redirection selon le statut
|
||||||
|
switch (utilisateur.statut) {
|
||||||
|
case 'administrateur':
|
||||||
|
return res.redirect('/admin');
|
||||||
|
case 'complexe':
|
||||||
|
return res.redirect('/dashboard-complexe');
|
||||||
|
case 'simple':
|
||||||
|
return res.redirect('/objets'); // 🔄 Redirection mise à jour ici
|
||||||
|
case 'visiteur':
|
||||||
|
default:
|
||||||
|
return res.redirect('/');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
44
z1/webapp/routes/inscription.js
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const router = express.Router();
|
||||||
|
const bcrypt = require('bcrypt');
|
||||||
|
const db = require('../config/db');
|
||||||
|
const multer = require('multer');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
|
||||||
|
const storage = multer.diskStorage({
|
||||||
|
destination: (req, file, cb) => {
|
||||||
|
const uploadDir = path.join(__dirname, '../img');
|
||||||
|
cb(null, uploadDir);
|
||||||
|
},
|
||||||
|
filename: (req, file, cb) => {
|
||||||
|
const uniqueName = `${Date.now()}_${file.originalname}`;
|
||||||
|
cb(null, uniqueName);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const upload = multer({ storage });
|
||||||
|
|
||||||
|
|
||||||
|
router.get('/', (req, res) => {
|
||||||
|
res.render('inscription');
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post('/', upload.single('photo_profil'), async (req, res) => {
|
||||||
|
const { nom, prenom, sexe, age, date_naissance, identifiant, mot_de_passe, situation, email } = req.body;
|
||||||
|
const photo = req.file ? req.file.filename : null;
|
||||||
|
const hashedPassword = await bcrypt.hash(mot_de_passe, 10);
|
||||||
|
|
||||||
|
const sql = `INSERT INTO utilisateur (nom, prenom, sexe, age, date_naissance, identifiant, mot_de_passe, photo, situation, email)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`;
|
||||||
|
|
||||||
|
db.query(sql, [nom, prenom, sexe, age, date_naissance, identifiant, hashedPassword, photo, situation, email], (err, result) => {
|
||||||
|
if (err) {
|
||||||
|
console.error(err);
|
||||||
|
return res.send('Erreur lors de l’inscription');
|
||||||
|
}
|
||||||
|
res.redirect('/connexion');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
56
z1/webapp/routes/profil.js
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const router = express.Router();
|
||||||
|
const ensureAuthenticated = require('../middleware/auth');
|
||||||
|
const db = require('../config/db');
|
||||||
|
const multer = require('multer');
|
||||||
|
const bcrypt = require('bcrypt');
|
||||||
|
const storage = multer.diskStorage({
|
||||||
|
destination: (req, file, cb) => {
|
||||||
|
cb(null, 'photos');
|
||||||
|
},
|
||||||
|
filename: (req, file, cb) => {
|
||||||
|
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
|
||||||
|
cb(null, uniqueSuffix + '-' + file.originalname); // Nom unique pour éviter les conflits
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const upload = multer({
|
||||||
|
storage: storage,
|
||||||
|
limits: { fileSize: 5 * 1024 * 1024 }, // Limite de taille (5 Mo)
|
||||||
|
}).fields([
|
||||||
|
{ name: 'photo', maxCount: 1 }, // Champ pour le fichier
|
||||||
|
]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
router.get('/', ensureAuthenticated, (req, res) => {
|
||||||
|
const utilisateur = req.session.utilisateur;
|
||||||
|
res.render('profil', { utilisateur });
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post('/update', ensureAuthenticated, upload, (req, res) => {
|
||||||
|
const mot_de_passe = req.body.mot_de_passe ? bcrypt.hashSync(req.body.mot_de_passe, 10) : req.session.utilisateur.mot_de_passe;
|
||||||
|
const { identifiant, nom, prenom, sexe, situation } = req.body;
|
||||||
|
const photo = req.files && req.files.photo ? req.files.photo[0].filename : req.session.utilisateur.photo;
|
||||||
|
const id = req.session.utilisateur.id;
|
||||||
|
|
||||||
|
const sql = 'UPDATE utilisateur SET identifiant = ?, nom = ?, prenom = ?, sexe = ?, situation = ?, photo = ?, mot_de_passe = ? WHERE id = ?';
|
||||||
|
db.query(sql, [identifiant, nom, prenom, sexe, situation, photo, mot_de_passe, id], (err, result) => {
|
||||||
|
if (err) {
|
||||||
|
console.error(err);
|
||||||
|
return res.status(500).send("Erreur lors de la mise à jour");
|
||||||
|
}
|
||||||
|
|
||||||
|
req.session.utilisateur.identifiant = identifiant;
|
||||||
|
req.session.utilisateur.nom = nom;
|
||||||
|
req.session.utilisateur.prenom = prenom;
|
||||||
|
req.session.utilisateur.sexe = sexe;
|
||||||
|
req.session.utilisateur.situation = situation;
|
||||||
|
req.session.utilisateur.photo = photo;
|
||||||
|
req.session.utilisateur.mot_de_passe = mot_de_passe;
|
||||||
|
|
||||||
|
res.redirect('/profil');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
156
z1/webapp/user.sql
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
-- Création de la base de données et sélection
|
||||||
|
CREATE DATABASE IF NOT EXISTS user;
|
||||||
|
USE user;
|
||||||
|
|
||||||
|
SET NAMES utf8mb4;
|
||||||
|
|
||||||
|
-- Table `utilisateur`
|
||||||
|
CREATE TABLE IF NOT EXISTS `utilisateur` (
|
||||||
|
`id` INT NOT NULL AUTO_INCREMENT,
|
||||||
|
`nom` VARCHAR(100) NOT NULL,
|
||||||
|
`prenom` VARCHAR(100) NOT NULL,
|
||||||
|
`sexe` ENUM('Homme', 'Femme', 'Autre') NOT NULL,
|
||||||
|
`age` INT DEFAULT NULL,
|
||||||
|
`date_naissance` DATE NOT NULL,
|
||||||
|
`identifiant` VARCHAR(50) NOT NULL UNIQUE,
|
||||||
|
`email` VARCHAR(255) NOT NULL UNIQUE,
|
||||||
|
`mot_de_passe` VARCHAR(255) NOT NULL,
|
||||||
|
`photo` VARCHAR(255) DEFAULT NULL,
|
||||||
|
`situation` VARCHAR(255) DEFAULT NULL,
|
||||||
|
`etat` ENUM('en attente', 'validé') DEFAULT 'en attente',
|
||||||
|
`statut` ENUM('visiteur','simple','complexe','administrateur') DEFAULT 'visiteur',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO `utilisateur` VALUES
|
||||||
|
(1, 'Dupont', 'Jean', 'Homme', 30, '1994-05-12', 'jdupont', 'jean.dupont@mail.com', '$2b$10$sOFuc/cZzpK1P8fINfmsAOQ33K0xyCeEXD.OCilFH0SPyuMC.3LNC', './photos/jean.jpg', 'Ingénieur', 'validé', 'complexe'), -- mots de passe dupont
|
||||||
|
(2, 'Martin', 'Sophie', 'Femme', 25, '1999-08-21', 'smartin', 'sophie.martin@mail.com', '$2b$10$ydWLQyCvL8PVAN18KCWBWe.oMdtm7Y.R4oCVVJenP9fJqfyBLR26C', './photos/sophie.jpg', 'Étudiante', 'en attente', 'visiteur'), -- mots de passe martin
|
||||||
|
(3, 'Durand', 'Paul', 'Homme', 45, '1979-11-30', 'pdurand', 'paul.durand@mail.com', '$2b$10$HnhXjkKOPNLE.2erAwzg.e5zVVRK/wNeegd8GrNxWv2f3U660xQbW', './photos/paul.jpg', 'Directeur', 'validé', 'administrateur'), -- mots de passe durand
|
||||||
|
(4, 'Bernard', 'Alice', 'Femme', 28, '1996-02-15', 'aliceb', 'alice.bernard@mail.com', '$2b$10$6BslSk7oJc6fGzQx3YQRHu6Op8xtVQIGFznA0vsmZX40Ix4ywBTfy', './photos/alice.jpg', 'Développeuse', 'validé', 'simple'), -- mots de passe bernard
|
||||||
|
(5, 'Lemoine', 'Alex', 'Autre', 32, '1992-07-19', 'alemoine', 'alex.lemoine@mail.com', '$2b$10$lZebS.LIRJi9Z5yDaLSNxujY0piysZAb9BRjGOLVW3Hr2wDPoYTgO', './photos/alex.jpg', 'Freelance', 'en attente', 'simple'), -- mots de passe lemoine
|
||||||
|
(6, 'Arricastres', 'Guillaume', 'Homme', 26, '1998-01-15', 'garricastres', 'guillaume.arricastres@mail.com', '$2b$10$StE4wQ2Mox/CUpuR.o/1nObQMT/rAAndmKXOgAJ7r.V/YGvEs7isy', './photos/guillaume.jpg', 'Étudiant', 'validé', 'simple'), -- mots de passe 1234
|
||||||
|
(7, 'Chosson', 'Clément', 'Homme', 25, '1999-06-15', 'clement_cx', 'clement.chosson@mail.com', '$2b$10$StE4wQ2Mox/CUpuR.o/1nObQMT/rAAndmKXOgAJ7r.V/YGvEs7isy', NULL, 'Technicien', 'validé', 'complexe'), -- mots de passe 1234
|
||||||
|
(8, 'Admin', 'Root', 'Homme', 30, '1993-12-31', 'admin', 'admin@smartbuilding.com', '$2b$10$StE4wQ2Mox/CUpuR.o/1nObQMT/rAAndmKXOgAJ7r.V/YGvEs7isy', NULL, 'Administrateur', 'validé', 'administrateur'); -- mots de passe 1234
|
||||||
|
|
||||||
|
|
||||||
|
-- Table `objet`
|
||||||
|
CREATE TABLE IF NOT EXISTS `objet` (
|
||||||
|
`adresse_ip` VARCHAR(45) NOT NULL,
|
||||||
|
`niveau` ENUM('débutant','intermédiaire','avancé','expert') NOT NULL,
|
||||||
|
`denomination` VARCHAR(255) NOT NULL,
|
||||||
|
`etat` ENUM('Actif','Inactif') NOT NULL,
|
||||||
|
`derniere_interaction` DATETIME DEFAULT NULL,
|
||||||
|
`type` ENUM('Climatisation','Lumière','thermostat','securite','Enceinte connectée','Capteur','appareil_menager','Prise') NOT NULL,
|
||||||
|
PRIMARY KEY (`adresse_ip`)
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO `objet` VALUES
|
||||||
|
('192.168.1.10', 'débutant', 'Ampoule connectée', 'Inactif', '2025-04-08 10:40:50', 'Lumière'),
|
||||||
|
('192.168.1.11', 'débutant', 'Cuisinière', 'Inactif', '2025-04-08 10:40:50', 'appareil_menager'),
|
||||||
|
('192.168.1.12', 'débutant', 'Machine à café', 'Inactif', '2025-04-08 10:40:50', 'appareil_menager'),
|
||||||
|
('192.168.1.20', 'intermédiaire', 'Thermostat intelligent', 'Actif', '2025-04-08 10:40:50', 'thermostat'),
|
||||||
|
('192.168.1.30', 'avancé', 'Caméra de surveillance', 'Actif', '2025-04-08 10:40:50', 'Capteur'),
|
||||||
|
('192.168.1.40', 'débutant', 'Machine à laver', 'Inactif', '2025-04-08 10:40:50', 'appareil_menager'),
|
||||||
|
('192.168.1.50', 'débutant', 'Enceinte intelligente', 'Inactif', '2025-04-08 10:40:50', 'Enceinte connectée'),
|
||||||
|
('192.168.1.60', 'intermédiaire', 'Prise connectée', 'Actif', '2025-04-08 10:40:50', 'Prise'),
|
||||||
|
('192.168.1.70', 'avancé', 'Serrure connectée', 'Actif', '2025-04-08 10:40:50', 'securite'),
|
||||||
|
('192.168.1.80', 'expert', 'Porte connectée salle de contrôle', 'Actif', '2025-04-08 10:40:50', 'securite'),
|
||||||
|
('192.168.1.90', 'avancé', 'Climatisation', 'Actif', '2025-04-08 10:40:50', 'Climatisation');
|
||||||
|
|
||||||
|
-- Table `thermostat`
|
||||||
|
CREATE TABLE `thermostat` (
|
||||||
|
`adresse_ip` VARCHAR(45) NOT NULL,
|
||||||
|
`temperature_actuelle` FLOAT DEFAULT NULL,
|
||||||
|
`temperature_cible` FLOAT DEFAULT NULL,
|
||||||
|
`mode` ENUM('Automatique','Manuel') NOT NULL,
|
||||||
|
PRIMARY KEY (`adresse_ip`),
|
||||||
|
FOREIGN KEY (`adresse_ip`) REFERENCES `objet` (`adresse_ip`)
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO `thermostat` VALUES
|
||||||
|
('192.168.1.20', 17, 20, 'Automatique');
|
||||||
|
|
||||||
|
-- Table `climatisation_chauffage`
|
||||||
|
CREATE TABLE `climatisation_chauffage` (
|
||||||
|
`adresse_ip` VARCHAR(45) NOT NULL,
|
||||||
|
`thermostat` VARCHAR(45) NOT NULL,
|
||||||
|
PRIMARY KEY (`adresse_ip`),
|
||||||
|
FOREIGN KEY (`adresse_ip`) REFERENCES `objet` (`adresse_ip`),
|
||||||
|
FOREIGN KEY (`thermostat`) REFERENCES `thermostat` (`adresse_ip`)
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO `climatisation_chauffage` VALUES
|
||||||
|
('192.168.1.90', '192.168.1.20');
|
||||||
|
|
||||||
|
-- Table `appareil_menager`
|
||||||
|
CREATE TABLE `appareil_menager` (
|
||||||
|
`adresse_ip` VARCHAR(45) NOT NULL,
|
||||||
|
`depart_differe` TIME DEFAULT NULL,
|
||||||
|
`etat_de_la_tache` ENUM('Complété','En cours','En attente','Aucune') NOT NULL,
|
||||||
|
PRIMARY KEY (`adresse_ip`),
|
||||||
|
FOREIGN KEY (`adresse_ip`) REFERENCES `objet` (`adresse_ip`) ON DELETE RESTRICT ON UPDATE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO `appareil_menager` VALUES
|
||||||
|
('192.168.1.11', NULL, 'Aucune'),
|
||||||
|
('192.168.1.12', NULL, 'Aucune'),
|
||||||
|
('192.168.1.40', NULL, 'Aucune');
|
||||||
|
|
||||||
|
-- Table `securite`
|
||||||
|
CREATE TABLE `securite` (
|
||||||
|
`adresse_ip` VARCHAR(45) NOT NULL,
|
||||||
|
`situation` ENUM('Verouillé','Ouvert') NOT NULL,
|
||||||
|
PRIMARY KEY (`adresse_ip`),
|
||||||
|
FOREIGN KEY (`adresse_ip`) REFERENCES `objet` (`adresse_ip`) ON DELETE RESTRICT ON UPDATE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO `securite` VALUES
|
||||||
|
('192.168.1.70', 'Ouvert'),
|
||||||
|
('192.168.1.80', 'Verouillé');
|
||||||
|
|
||||||
|
-- Table `gestion`
|
||||||
|
CREATE TABLE `gestion` (
|
||||||
|
`id` INT NOT NULL AUTO_INCREMENT,
|
||||||
|
`id_utilisateur` INT NOT NULL,
|
||||||
|
`competence` VARCHAR(255) NOT NULL,
|
||||||
|
`niveau` ENUM('débutant','intermédiaire','avancé','expert') NOT NULL,
|
||||||
|
`categorie_experience` FLOAT DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
FOREIGN KEY (`id_utilisateur`) REFERENCES `utilisateur` (`id`) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO `gestion` (`id`, `id_utilisateur`, `competence`, `niveau`, `categorie_experience`) VALUES
|
||||||
|
(1, 1, 'Informatique', 'expert', 5),
|
||||||
|
(2, 1, 'Electronique', 'avancé', 3.5),
|
||||||
|
(3, 2, 'Internet', 'intermédiaire', 2),
|
||||||
|
(4, 2, 'Assistance numerique', 'débutant', 1),
|
||||||
|
(5, 3, 'Cuisine', 'expert', 10),
|
||||||
|
(6, 3, 'Aménagement', 'avancé', 7),
|
||||||
|
(7, 4, 'Securite', 'avancé', 4),
|
||||||
|
(8, 4, 'Acceuil', 'intermédiaire', 2.5),
|
||||||
|
(9, 5, 'Entretien', 'intermédiaire', 3),
|
||||||
|
(10, 5, 'Securite', 'débutant', 1.5);
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE `ressources` (
|
||||||
|
`id` int NOT NULL,
|
||||||
|
`nom` varchar(50) NOT NULL,
|
||||||
|
`consommation` varchar(50) NOT NULL,
|
||||||
|
`consommation_max` varchar(50) NOT NULL,
|
||||||
|
`fournisseur` varchar(100) NOT NULL,
|
||||||
|
`abonnement` varchar(100) NOT NULL,
|
||||||
|
`echeance` varchar(50) NOT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
||||||
|
|
||||||
|
INSERT INTO `ressources` (`id`, `nom`, `consommation`, `consommation_max`, `fournisseur`, `abonnement`, `echeance`) VALUES
|
||||||
|
(0, 'Électricité', '250 kWh', '500 kWh', 'EDF', '50 € / mois', '2025-12-30'),
|
||||||
|
(1, 'Gaz', '90 m³', '200 m³', 'Engie', '40 € / mois', '2025-06-30'),
|
||||||
|
(2, 'Eau', '1200 L', '3000 L', 'Veolia', '20 € / mois', '2025-08-15');
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS contact (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
nom VARCHAR(100) NOT NULL,
|
||||||
|
email VARCHAR(255) NOT NULL,
|
||||||
|
message TEXT NOT NULL,
|
||||||
|
date_envoi TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
67
z1/webapp/views/accueil.ejs
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>Page d'accueil - Smart Building</title>
|
||||||
|
<link rel="stylesheet" href="/style.css" />
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
|
<link
|
||||||
|
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css"
|
||||||
|
rel="stylesheet"
|
||||||
|
/>
|
||||||
|
<script
|
||||||
|
src="https://kit.fontawesome.com/a076d05399.js"
|
||||||
|
crossorigin="anonymous"
|
||||||
|
></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<%- include('partials/header') %>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<section class="left-panel">
|
||||||
|
<img src="/images/batiment.png" alt="Bâtiment" />
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="right-panel">
|
||||||
|
<h1>Accueil</h1>
|
||||||
|
<div class="features">
|
||||||
|
<a href="/objets" style="text-decoration: none">
|
||||||
|
<div class="feature">
|
||||||
|
<div class="circle">
|
||||||
|
<i class="fas fa-cogs"></i>
|
||||||
|
</div>
|
||||||
|
<p>Objets connectés</p>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<a href="/membres" style="text-decoration: none">
|
||||||
|
<div class="feature">
|
||||||
|
<div class="circle">
|
||||||
|
<i class="fas fa-users"></i>
|
||||||
|
</div>
|
||||||
|
<p>Membres</p>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="/ressources" class="text-decoration: none">
|
||||||
|
<div class="feature">
|
||||||
|
<div class="circle">
|
||||||
|
<i class="fas fa-map-marker-alt"></i>
|
||||||
|
</div>
|
||||||
|
<p>Ressources</p>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="/description" class="feature">
|
||||||
|
<div class="circle">
|
||||||
|
<i class="fas fa-building"></i>
|
||||||
|
</div>
|
||||||
|
<p>Description bâtiment</p>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<%- include('partials/footer') %>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
401
z1/webapp/views/admin.ejs
Normal file
@ -0,0 +1,401 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>Admin - Smart Building</title>
|
||||||
|
<link rel="stylesheet" href="/styleAdmin.css" />
|
||||||
|
<script>
|
||||||
|
function toggleForm(id) {
|
||||||
|
const form = document.getElementById(id);
|
||||||
|
form.style.display = form.style.display === 'none' ? 'block' : 'none';
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<%- include('partials/header') %>
|
||||||
|
|
||||||
|
<main class="admin-container">
|
||||||
|
<h1>Gestion des utilisateurs</h1>
|
||||||
|
|
||||||
|
<div class="ajout-section">
|
||||||
|
<h2>Ajouter un utilisateur <span class="toggle-btn" onclick="toggleForm('form-ajout-user')">➕</span></h2>
|
||||||
|
<form id="form-ajout-user" action="/admin/ajouter-utilisateur" method="POST" style="display: none;">
|
||||||
|
<div class="form-group">
|
||||||
|
<span class="icon">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke-width="1.5"
|
||||||
|
stroke="currentColor"
|
||||||
|
class="size-6"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
d="M15 9h3.75M15 12h3.75M15 15h3.75M4.5 19.5h15a2.25 2.25 0 0 0 2.25-2.25V6.75A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25v10.5A2.25 2.25 0 0 0 4.5 19.5Zm6-10.125a1.875 1.875 0 1 1-3.75 0 1.875 1.875 0 0 1 3.75 0Zm1.294 6.336a6.721 6.721 0 0 1-3.17.789 6.721 6.721 0 0 1-3.168-.789 3.376 3.376 0 0 1 6.338 0Z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<input type="text" name="nom" class="form-control-admin" placeholder="Nom" required />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<span class="icon">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke-width="1.5"
|
||||||
|
stroke="currentColor"
|
||||||
|
class="size-6"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
d="M15 9h3.75M15 12h3.75M15 15h3.75M4.5 19.5h15a2.25 2.25 0 0 0 2.25-2.25V6.75A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25v10.5A2.25 2.25 0 0 0 4.5 19.5Zm6-10.125a1.875 1.875 0 1 1-3.75 0 1.875 1.875 0 0 1 3.75 0Zm1.294 6.336a6.721 6.721 0 0 1-3.17.789 6.721 6.721 0 0 1-3.168-.789 3.376 3.376 0 0 1 6.338 0Z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<input type="text" name="prenom" class="form-control-admin" placeholder="Prénom" required />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<label>Sexe / Genre :</label>
|
||||||
|
<div class="form-group">
|
||||||
|
<span class="icon">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512">
|
||||||
|
<path
|
||||||
|
d="M176 288a112 112 0 1 0 0-224 112 112 0 1 0 0 224zM352 176c0 86.3-62.1 158.1-144 173.1l0 34.9 32 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-32 0 0 32c0 17.7-14.3 32-32 32s-32-14.3-32-32l0-32-32 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l32 0 0-34.9C62.1 334.1 0 262.3 0 176C0 78.8 78.8 0 176 0s176 78.8 176 176zM271.9 360.6c19.3-10.1 36.9-23.1 52.1-38.4c20 18.5 46.7 29.8 76.1 29.8c61.9 0 112-50.1 112-112s-50.1-112-112-112c-7.2 0-14.3 .7-21.1 2c-4.9-21.5-13-41.7-24-60.2C369.3 66 384.4 64 400 64c37 0 71.4 11.4 99.8 31l20.6-20.6L487 41c-6.9-6.9-8.9-17.2-5.2-26.2S494.3 0 504 0L616 0c13.3 0 24 10.7 24 24l0 112c0 9.7-5.8 18.5-14.8 22.2s-19.3 1.7-26.2-5.2l-33.4-33.4L545 140.2c19.5 28.4 31 62.7 31 99.8c0 97.2-78.8 176-176 176c-50.5 0-96-21.3-128.1-55.4z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<select name="sexe" class="form-control-admin">
|
||||||
|
<option value="Homme">Homme</option>
|
||||||
|
<option value="Femme">Femme</option>
|
||||||
|
<option value="Autre">Autre</option></select
|
||||||
|
><br />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<span class="icon">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="24"
|
||||||
|
>
|
||||||
|
<path d="M0 0h24v24H0z" fill="none" />
|
||||||
|
<path
|
||||||
|
d="M12 6c1.11 0 2-.9 2-2 0-.38-.1-.73-.29-1.03L12 0l-1.71 2.97c-.19.3-.29.65-.29 1.03 0 1.1.9 2 2 2zm4.6 9.99l-1.07-1.07-1.08 1.07c-1.3 1.3-3.58 1.31-4.89 0l-1.07-1.07-1.09 1.07C6.75 16.64 5.88 17 4.96 17c-.73 0-1.4-.23-1.96-.61V21c0 .55.45 1 1 1h16c.55 0 1-.45 1-1v-4.61c-.56.38-1.23.61-1.96.61-.92 0-1.79-.36-2.44-1.01zM18 9h-5V7h-2v2H6c-1.66 0-3 1.34-3 3v1.54c0 1.08.88 1.96 1.96 1.96.52 0 1.02-.2 1.38-.57l2.14-2.13 2.13 2.13c.74.74 2.03.74 2.77 0l2.14-2.13 2.13 2.13c.37.37.86.57 1.38.57 1.08 0 1.96-.88 1.96-1.96V12C21 10.34 19.66 9 18 9z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<input type="number" name="age" class="form-control-admin" placeholder="Âge" required />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<label>Date de naissance :</label>
|
||||||
|
<div class="form-group">
|
||||||
|
<span class="icon">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
height="24px"
|
||||||
|
viewBox="0 -960 960 960"
|
||||||
|
width="24px"
|
||||||
|
fill="#e3e3e3"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M200-80q-33 0-56.5-23.5T120-160v-560q0-33 23.5-56.5T200-800h40v-80h80v80h320v-80h80v80h40q33 0 56.5 23.5T840-720v560q0 33-23.5 56.5T760-80H200Zm0-80h560v-400H200v400Zm0-480h560v-80H200v80Zm0 0v-80 80Zm280 240q-17 0-28.5-11.5T440-440q0-17 11.5-28.5T480-480q17 0 28.5 11.5T520-440q0 17-11.5 28.5T480-400Zm-160 0q-17 0-28.5-11.5T280-440q0-17 11.5-28.5T320-480q17 0 28.5 11.5T360-440q0 17-11.5 28.5T320-400Zm320 0q-17 0-28.5-11.5T600-440q0-17 11.5-28.5T640-480q17 0 28.5 11.5T680-440q0 17-11.5 28.5T640-400ZM480-240q-17 0-28.5-11.5T440-280q0-17 11.5-28.5T480-320q17 0 28.5 11.5T520-280q0 17-11.5 28.5T480-240Zm-160 0q-17 0-28.5-11.5T280-280q0-17 11.5-28.5T320-320q17 0 28.5 11.5T360-280q0 17-11.5 28.5T320-240Zm320 0q-17 0-28.5-11.5T600-280q0-17 11.5-28.5T640-320q17 0 28.5 11.5T680-280q0 17-11.5 28.5T640-240Z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<input type="date" name="date_naissance" class="form-control-admin" required />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<span class="icon">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M12 12c2.21 0 4-1.79 4-4S14.21 4 12 4 8 5.79 8 8s1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<input type="text" name="identifiant" class="form-control-admin" placeholder="Identifiant" required />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<span class="icon">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M20 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<input type="email" name="email" class="form-control-admin" placeholder="Email" required />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<span class="icon">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M12 2C8.691 2 6 4.691 6 8v4c-1.104 0-2 .896-2 2v8c0 1.104.896 2 2 2h12c1.104 0 2-.896 2-2v-8c0-1.104-.896-2-2-2V8c0-3.309-2.691-6-6-6zm0 2c2.205 0 4 1.795 4 4v4H8V8c0-2.205 1.795-4 4-4zm-4 10h8v8H8v-8z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<input type="password" name="mot_de_passe" class="form-control-admin" placeholder="Mot de passe" required />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<span class="icon">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
color="#000000"
|
||||||
|
stroke-width="1.5"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
d="M20.75 16.7143C20.75 16.7631 20.7453 16.8109 20.7364 16.8571C20.7453 16.9034 20.75 16.9511 20.75 17C20.75 17.4142 20.4142 17.75 20 17.75H6C5.30964 17.75 4.75 18.3096 4.75 19C4.75 19.6904 5.30964 20.25 6 20.25H20C20.4142 20.25 20.75 20.5858 20.75 21C20.75 21.4142 20.4142 21.75 20 21.75H6C4.48122 21.75 3.25 20.5188 3.25 19V5C3.25 3.48122 4.48122 2.25 6 2.25H19.4C20.1456 2.25 20.75 2.85442 20.75 3.6V16.7143ZM9 6.25C8.58579 6.25 8.25 6.58579 8.25 7C8.25 7.41421 8.58579 7.75 9 7.75H15C15.4142 7.75 15.75 7.41421 15.75 7C15.75 6.58579 15.4142 6.25 15 6.25H9Z"
|
||||||
|
fill="#000000"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<input type="text" name="situation" class="form-control-admin" placeholder="Situation professionnelle" required />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<label>Statut :</label>
|
||||||
|
<div class="form-group">
|
||||||
|
<span class="icon">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path d="M12 2a10 10 0 1 0 7.07 2.93A9.95 9.95 0 0 0 12 2zm0 18a8 8 0 1 1 5.66-2.34A7.96 7.96 0 0 1 12 20z"/>
|
||||||
|
<circle cx="12" cy="12" r="4"/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<select name="statut" class="form-control-admin">
|
||||||
|
<option value="visiteur">Visiteur</option>
|
||||||
|
<option value="simple">Simple</option>
|
||||||
|
<option value="complexe">Complexe</option>
|
||||||
|
<option value="administrateur">Administrateur</option></select
|
||||||
|
><br />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button class="bouton-admin" type="submit">Ajouter</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Nom</th>
|
||||||
|
<th>Prénom</th>
|
||||||
|
<th>Statut</th>
|
||||||
|
<th>État</th>
|
||||||
|
<th>Modifier</th>
|
||||||
|
<th>Supprimer</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<% utilisateurs.forEach(user => { %>
|
||||||
|
<tr>
|
||||||
|
<form action="/admin/update-user" method="POST">
|
||||||
|
<input type="hidden" name="id" value="<%= user.id %>" />
|
||||||
|
<td><%= user.nom %></td>
|
||||||
|
<td><%= user.prenom %></td>
|
||||||
|
<td>
|
||||||
|
<select name="statut">
|
||||||
|
<option value="visiteur" <%= user.statut === 'visiteur' ? 'selected' : '' %>>Visiteur</option>
|
||||||
|
<option value="simple" <%= user.statut === 'simple' ? 'selected' : '' %>>Simple</option>
|
||||||
|
<option value="complexe" <%= user.statut === 'complexe' ? 'selected' : '' %>>Complexe</option>
|
||||||
|
<option value="administrateur" <%= user.statut === 'administrateur' ? 'selected' : '' %>>Administrateur</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<select name="etat">
|
||||||
|
<option value="en attente" <%= user.etat === 'en attente' ? 'selected' : '' %>>En attente</option>
|
||||||
|
<option value="validé" <%= user.etat === 'validé' ? 'selected' : '' %>>Validé</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td><button type="submit">Modifier</button></td>
|
||||||
|
</form>
|
||||||
|
<td>
|
||||||
|
<form action="/admin/supprimer-user" method="POST" onsubmit="return confirm('Supprimer cet utilisateur ?')">
|
||||||
|
<input type="hidden" name="id" value="<%= user.id %>">
|
||||||
|
<button type="submit" style="background-color: #e74c3c; color: white;">Supprimer</button>
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<% }) %>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h1>Gestion des objets</h1>
|
||||||
|
|
||||||
|
<div class="ajout-section">
|
||||||
|
<h2>Ajouter un objet <span class="toggle-btn" onclick="toggleForm('form-ajout-objet')">➕</span></h2>
|
||||||
|
<form id="form-ajout-objet" action="/admin/ajouter-objet" method="POST" style="display: none;">
|
||||||
|
|
||||||
|
<div class="ajout-section">
|
||||||
|
<div class="form-group">
|
||||||
|
<span class="icon">
|
||||||
|
<svg id="Layer_1" height="512" viewBox="0 0 24 24" width="512" xmlns="http://www.w3.org/2000/svg" data-name="Layer 1"><path d="m19 4h-4v-1a3 3 0 0 0 -6 0v1h-4a5.006 5.006 0 0 0 -5 5v10a5.006 5.006 0 0 0 5 5h14a5.006 5.006 0 0 0 5-5v-10a5.006 5.006 0 0 0 -5-5zm-8-1a1 1 0 0 1 2 0v2a1 1 0 0 1 -2 0zm11 16a3 3 0 0 1 -3 3h-14a3 3 0 0 1 -3-3v-10a3 3 0 0 1 3-3h4.184a2.982 2.982 0 0 0 5.632 0h4.184a3 3 0 0 1 3 3zm-12-9h-5a1 1 0 0 0 -1 1v8a1 1 0 0 0 1 1h5a1 1 0 0 0 1-1v-8a1 1 0 0 0 -1-1zm-1 8h-3v-6h3zm11-3a1 1 0 0 1 -1 1h-5a1 1 0 0 1 0-2h5a1 1 0 0 1 1 1zm0-4a1 1 0 0 1 -1 1h-5a1 1 0 0 1 0-2h5a1 1 0 0 1 1 1zm-2 8a1 1 0 0 1 -1 1h-3a1 1 0 0 1 0-2h3a1 1 0 0 1 1 1z"/></svg>
|
||||||
|
</span>
|
||||||
|
<input type="text" name="denomination" class="form-control-admin" placeholder="Nom" required />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<span class="icon">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 24 24">
|
||||||
|
<path d="m19.07,2.929c-1.889-1.889-4.399-2.929-7.07-2.929s-5.183,1.04-7.071,2.929c-3.899,3.899-3.899,10.243.008,14.149l7.063,6.909,7.07-6.917c1.89-1.889,2.93-4.4,2.93-7.071s-1.04-5.182-2.93-7.071Zm-1.406,12.72l-5.664,5.541-5.657-5.533c-1.511-1.511-2.343-3.52-2.343-5.657s.832-4.146,2.343-5.657,3.521-2.343,5.657-2.343,4.146.832,5.656,2.343c1.512,1.511,2.344,3.52,2.344,5.657s-.832,4.146-2.336,5.649ZM8.9,6h1.6v8h-1.6V6Zm5.6,0h-2.5v8h1.6v-3h.9c1.381,0,2.5-1.119,2.5-2.5s-1.119-2.5-2.5-2.5Zm0,3.4h-.9v-1.801h.9c.497,0,.9.403.9.9s-.403.9-.9.9Z"/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<input type="text" name="adresse_ip" class="form-control-admin" placeholder="Adresse IP" required />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<label>Type :</label>
|
||||||
|
<div class="form-group">
|
||||||
|
<span class="icon">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="512" height="512"><g id="_01_align_center" data-name="01 align center"><path d="M15,24H9V20.487a9,9,0,0,1-2.849-1.646L3.107,20.6l-3-5.2L3.15,13.645a9.1,9.1,0,0,1,0-3.29L.107,8.6l3-5.2L6.151,5.159A9,9,0,0,1,9,3.513V0h6V3.513a9,9,0,0,1,2.849,1.646L20.893,3.4l3,5.2L20.85,10.355a9.1,9.1,0,0,1,0,3.29L23.893,15.4l-3,5.2-3.044-1.758A9,9,0,0,1,15,20.487Zm-4-2h2V18.973l.751-.194A6.984,6.984,0,0,0,16.994,16.9l.543-.553,2.623,1.515,1-1.732-2.62-1.513.206-.746a7.048,7.048,0,0,0,0-3.75l-.206-.746,2.62-1.513-1-1.732L17.537,7.649,16.994,7.1a6.984,6.984,0,0,0-3.243-1.875L13,5.027V2H11V5.027l-.751.194A6.984,6.984,0,0,0,7.006,7.1l-.543.553L3.84,6.134l-1,1.732L5.46,9.379l-.206.746a7.048,7.048,0,0,0,0,3.75l.206.746L2.84,16.134l1,1.732,2.623-1.515.543.553a6.984,6.984,0,0,0,3.243,1.875l.751.194Zm1-6a4,4,0,1,1,4-4A4,4,0,0,1,12,16Zm0-6a2,2,0,1,0,2,2A2,2,0,0,0,12,10Z"/></g></svg> </span>
|
||||||
|
<select name="type" class="form-control-admin" required>
|
||||||
|
<option value="Climatisation">Climatisation</option>
|
||||||
|
<option value="Lumière">Lumière</option>
|
||||||
|
<option value="thermostat">Thermostat</option>
|
||||||
|
<option value="securite">Sécurité</option>
|
||||||
|
<option value="Enceinte connectée">Enceinte connectée</option>
|
||||||
|
<option value="Capteur">Capteur</option>
|
||||||
|
<option value="appareil_menager">Appareil ménager</option>
|
||||||
|
<option value="Prise">Prise</option></select
|
||||||
|
><br />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<label>Niveau :</label>
|
||||||
|
<div class="form-group">
|
||||||
|
<span class="icon">
|
||||||
|
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" id="Outline" viewBox="0 0 24 24" width="512" height="512"><path d="M1,4.75H3.736a3.728,3.728,0,0,0,7.195,0H23a1,1,0,0,0,0-2H10.931a3.728,3.728,0,0,0-7.195,0H1a1,1,0,0,0,0,2ZM7.333,2a1.75,1.75,0,1,1-1.75,1.75A1.752,1.752,0,0,1,7.333,2Z"/><path d="M23,11H20.264a3.727,3.727,0,0,0-7.194,0H1a1,1,0,0,0,0,2H13.07a3.727,3.727,0,0,0,7.194,0H23a1,1,0,0,0,0-2Zm-6.333,2.75A1.75,1.75,0,1,1,18.417,12,1.752,1.752,0,0,1,16.667,13.75Z"/><path d="M23,19.25H10.931a3.728,3.728,0,0,0-7.195,0H1a1,1,0,0,0,0,2H3.736a3.728,3.728,0,0,0,7.195,0H23a1,1,0,0,0,0-2ZM7.333,22a1.75,1.75,0,1,1,1.75-1.75A1.753,1.753,0,0,1,7.333,22Z"/></svg> </span>
|
||||||
|
<select name="niveau" class="form-control-admin" required>
|
||||||
|
<option value="débutant">Débutant</option>
|
||||||
|
<option value="intermédiaire">Intermédiaire</option>
|
||||||
|
<option value="avancé">Avancé</option>
|
||||||
|
<option value="expert">Expert</option></select
|
||||||
|
><br />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<label>État :</label>
|
||||||
|
<div class="form-group">
|
||||||
|
<span class="icon">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path d="M12 2a10 10 0 1 0 7.07 2.93A9.95 9.95 0 0 0 12 2zm0 18a8 8 0 1 1 5.66-2.34A7.96 7.96 0 0 1 12 20z"/>
|
||||||
|
<circle cx="12" cy="12" r="4"/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<select name="etat" class="form-control-admin">
|
||||||
|
<option value="Actif">Actif</option>
|
||||||
|
<option value="Inactif">Inactif</option></select
|
||||||
|
><br />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button class="bouton-admin" type="submit">Ajouter</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Nom</th>
|
||||||
|
<th>Adresse IP</th>
|
||||||
|
<th>Type</th>
|
||||||
|
<th>Niveau</th>
|
||||||
|
<th>État</th>
|
||||||
|
<th>Modifier</th>
|
||||||
|
<th>Supprimer</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<% objets.forEach(objet => { %>
|
||||||
|
<tr>
|
||||||
|
<form action="/admin/update-objet" method="POST">
|
||||||
|
<input type="hidden" name="adresse_ip" value="<%= objet.adresse_ip %>" />
|
||||||
|
<td><%= objet.denomination %></td>
|
||||||
|
<td><%= objet.adresse_ip %></td>
|
||||||
|
<td><%= objet.type %></td>
|
||||||
|
<td>
|
||||||
|
<select name="niveau">
|
||||||
|
<option value="débutant" <%= objet.niveau === 'débutant' ? 'selected' : '' %>>Débutant</option>
|
||||||
|
<option value="intermédiaire" <%= objet.niveau === 'intermédiaire' ? 'selected' : '' %>>Intermédiaire</option>
|
||||||
|
<option value="avancé" <%= objet.niveau === 'avancé' ? 'selected' : '' %>>Avancé</option>
|
||||||
|
<option value="expert" <%= objet.niveau === 'expert' ? 'selected' : '' %>>Expert</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<select name="etat">
|
||||||
|
<option value="Actif" <%= objet.etat === 'Actif' ? 'selected' : '' %>>Actif</option>
|
||||||
|
<option value="Inactif" <%= objet.etat === 'Inactif' ? 'selected' : '' %>>Inactif</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td><button type="submit">Modifier</button></td>
|
||||||
|
</form>
|
||||||
|
<td>
|
||||||
|
<form action="/admin/supprimer-objet" method="POST" onsubmit="return confirm('Supprimer cet objet ?')">
|
||||||
|
<input type="hidden" name="adresse_ip" value="<%= objet.adresse_ip %>">
|
||||||
|
<button type="submit" style="background-color: #e74c3c; color: white;">Supprimer</button>
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<% }) %>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h1>Messages de contact</h1>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Nom</th>
|
||||||
|
<th>Email</th>
|
||||||
|
<th>Message</th>
|
||||||
|
<th>Date</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<% contacts.forEach(c => { %>
|
||||||
|
<tr>
|
||||||
|
<td><%= c.nom %></td>
|
||||||
|
<td><%= c.email %></td>
|
||||||
|
<td><%= c.message %></td>
|
||||||
|
<td><%= new Date(c.date_envoi).toLocaleString('fr-FR') %></td>
|
||||||
|
</tr>
|
||||||
|
<% }) %>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<%- include('partials/footer') %>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
71
z1/webapp/views/connexion.ejs
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>Page d'accueil - Smart Building</title>
|
||||||
|
<link rel="stylesheet" href="/styleConnexion.css" />
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<%- include('partials/header') %>
|
||||||
|
<div id="connexion">
|
||||||
|
<div class="building"></div>
|
||||||
|
<div class="cellule">
|
||||||
|
<div class="page-connexion">
|
||||||
|
<h1>Connexion</h1>
|
||||||
|
<form action="/connexion" method="POST">
|
||||||
|
<div class="form-group">
|
||||||
|
<span class="icon">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M12 12c2.21 0 4-1.79 4-4S14.21 4 12 4 8 5.79 8 8s1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<input
|
||||||
|
class="form-control-connexion"
|
||||||
|
type="text"
|
||||||
|
id="identifiant"
|
||||||
|
name="identifiant"
|
||||||
|
placeholder="Identifiant"
|
||||||
|
required
|
||||||
|
/><br /><br />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<span class="icon">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M12 2C8.691 2 6 4.691 6 8v4c-1.104 0-2 .896-2 2v8c0 1.104.896 2 2 2h12c1.104 0 2-.896 2-2v-8c0-1.104-.896-2-2-2V8c0-3.309-2.691-6-6-6zm0 2c2.205 0 4 1.795 4 4v4H8V8c0-2.205 1.795-4 4-4zm-4 10h8v8H8v-8z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<input
|
||||||
|
class="form-control-connexion"
|
||||||
|
type="password"
|
||||||
|
id="mot_de_passe"
|
||||||
|
name="mot_de_passe"
|
||||||
|
placeholder="Mot de passe"
|
||||||
|
required
|
||||||
|
/><br /><br />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<input class="bouton-connexion" type="submit" value="Connexion" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<%- include('partials/footer') %>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
31
z1/webapp/views/contact.ejs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>Contact - Smart Building</title>
|
||||||
|
<link rel="stylesheet" href="/styleContact.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<%- include('partials/header') %>
|
||||||
|
|
||||||
|
<main class="contact-container">
|
||||||
|
<h1>Nous contacter</h1>
|
||||||
|
<p>Une question ? Une suggestion ? N'hésitez pas à nous écrire !</p>
|
||||||
|
|
||||||
|
<form action="/contact" method="POST" class="contact-form">
|
||||||
|
<label for="nom">Nom</label>
|
||||||
|
<input type="text" id="nom" name="nom" required />
|
||||||
|
|
||||||
|
<label for="email">Adresse e-mail</label>
|
||||||
|
<input type="email" id="email" name="email" required />
|
||||||
|
|
||||||
|
<label for="message">Message</label>
|
||||||
|
<textarea id="message" name="message" rows="5" required></textarea>
|
||||||
|
|
||||||
|
<button type="submit">Envoyer</button>
|
||||||
|
</form>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<%- include('partials/footer') %>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
105
z1/webapp/views/dashboard-complexe.ejs
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>Dashboard Complexe - Smart Building</title>
|
||||||
|
<link rel="stylesheet" href="/styleComplexe.css" />
|
||||||
|
<script>
|
||||||
|
function toggleForm(id) {
|
||||||
|
const form = document.getElementById(id);
|
||||||
|
form.style.display = form.style.display === 'none' ? 'block' : 'none';
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<%- include('partials/header') %>
|
||||||
|
|
||||||
|
<main class="admin-container">
|
||||||
|
<h1>Gestion des objets</h1>
|
||||||
|
|
||||||
|
<div class="ajout-section">
|
||||||
|
<h2>Ajouter un objet <span class="toggle-btn" onclick="toggleForm('form-ajout-objet')">➕</span></h2>
|
||||||
|
<form id="form-ajout-objet" action="/complexe/ajouter-objet" method="POST" style="display: none;">
|
||||||
|
<input type="text" name="denomination" placeholder="Nom" required />
|
||||||
|
<input type="text" name="adresse_ip" placeholder="Adresse IP" required />
|
||||||
|
|
||||||
|
<select name="type" required>
|
||||||
|
<option value="Climatisation">Climatisation</option>
|
||||||
|
<option value="Lumière">Lumière</option>
|
||||||
|
<option value="thermostat">Thermostat</option>
|
||||||
|
<option value="securite">Sécurité</option>
|
||||||
|
<option value="Enceinte connectée">Enceinte connectée</option>
|
||||||
|
<option value="Capteur">Capteur</option>
|
||||||
|
<option value="appareil_menager">Appareil ménager</option>
|
||||||
|
<option value="Prise">Prise</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select name="niveau">
|
||||||
|
<option value="débutant">Débutant</option>
|
||||||
|
<option value="intermédiaire">Intermédiaire</option>
|
||||||
|
<option value="avancé">Avancé</option>
|
||||||
|
<option value="expert">Expert</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select name="etat">
|
||||||
|
<option value="Actif">Actif</option>
|
||||||
|
<option value="Inactif">Inactif</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<button type="submit">Ajouter</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Nom</th>
|
||||||
|
<th>Adresse IP</th>
|
||||||
|
<th>Type</th>
|
||||||
|
<th>Niveau</th>
|
||||||
|
<th>État</th>
|
||||||
|
<th>Modifier</th>
|
||||||
|
<th>Supprimer</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<% objets.forEach(objet => { %>
|
||||||
|
<tr>
|
||||||
|
<form action="/complexe/update-objet" method="POST">
|
||||||
|
<input type="hidden" name="adresse_ip" value="<%= objet.adresse_ip %>" />
|
||||||
|
<td><%= objet.denomination %></td>
|
||||||
|
<td><%= objet.adresse_ip %></td>
|
||||||
|
<td><%= objet.type %></td>
|
||||||
|
<td>
|
||||||
|
<select name="niveau">
|
||||||
|
<option value="débutant" <%= objet.niveau === 'débutant' ? 'selected' : '' %>>Débutant</option>
|
||||||
|
<option value="intermédiaire" <%= objet.niveau === 'intermédiaire' ? 'selected' : '' %>>Intermédiaire</option>
|
||||||
|
<option value="avancé" <%= objet.niveau === 'avancé' ? 'selected' : '' %>>Avancé</option>
|
||||||
|
<option value="expert" <%= objet.niveau === 'expert' ? 'selected' : '' %>>Expert</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<select name="etat">
|
||||||
|
<option value="Actif" <%= objet.etat === 'Actif' ? 'selected' : '' %>>Actif</option>
|
||||||
|
<option value="Inactif" <%= objet.etat === 'Inactif' ? 'selected' : '' %>>Inactif</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<button type="submit">Modifier</button>
|
||||||
|
</td>
|
||||||
|
</form>
|
||||||
|
<td>
|
||||||
|
<form action="/complexe/supprimer-objet" method="POST" onsubmit="return confirm('Supprimer cet objet ?')">
|
||||||
|
<input type="hidden" name="adresse_ip" value="<%= objet.adresse_ip %>">
|
||||||
|
<button type="submit" style="background-color: #e74c3c; color: white;">Supprimer</button>
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<% }) %>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<%- include('partials/footer') %>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
42
z1/webapp/views/description.ejs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>Présentation de la maison - Smart Building</title>
|
||||||
|
<link rel="stylesheet" href="/styleObjets.css" />
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css" rel="stylesheet" />
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<%- include('partials/header') %>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<section class="left-panel">
|
||||||
|
<img src="/images/batiment.png" alt="Image de la maison connectée" />
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="right-panel">
|
||||||
|
<div class="header-objets">
|
||||||
|
<h1>Présentation de la maison connectée</h1>
|
||||||
|
</div>
|
||||||
|
<div style="padding: 0 70px; font-size: 18px; line-height: 1.8;">
|
||||||
|
<p>
|
||||||
|
Notre maison connectée est conçue pour offrir confort, sécurité et efficacité énergétique. Équipée de capteurs intelligents, d’un système de gestion centralisée et d’une connectivité en temps réel, elle permet une surveillance continue des équipements et une optimisation automatique des ressources.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Avec une surface habitable estimée à environ 300 m² répartie sur 4 à 5 niveaux, la maison connectée propose de vastes espaces ouverts et lumineux. Chaque étage est conçu pour maximiser l’apport en lumière naturelle grâce aux nombreuses baies vitrées. Les terrasses végétalisées apportent un lien direct avec la nature, tout en favorisant l’isolation thermique.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Le bâtiment comprend de nombreux équipements connectés tels que l’éclairage intelligent, le chauffage programmable, des outils ménager et une surveillance vidéo connectée. Toutes les données sont centralisées via une interface web qui permet un contrôle à distance via son smartphone ou son ordinateur. De plus en fonction des droits que possèdes votre compte vous avez accés à différentes fonctionnalités.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<%- include('partials/footer') %>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
273
z1/webapp/views/inscription.ejs
Normal file
@ -0,0 +1,273 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>Page d'accueil - Smart Building</title>
|
||||||
|
<link rel="stylesheet" href="/styleInscription.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<%- include('partials/header') %>
|
||||||
|
|
||||||
|
<div id="inscription">
|
||||||
|
<div class="case">
|
||||||
|
<form action="/connexion" method="GET">
|
||||||
|
<button class="lien" type="submit">
|
||||||
|
Déjà inscrit ? Se connecter
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="page-inscription">
|
||||||
|
<h1>Inscription</h1>
|
||||||
|
<form
|
||||||
|
action="/inscription"
|
||||||
|
method="POST"
|
||||||
|
enctype="multipart/form-data"
|
||||||
|
>
|
||||||
|
<div class="form-group">
|
||||||
|
<span class="icon">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke-width="1.5"
|
||||||
|
stroke="currentColor"
|
||||||
|
class="size-6"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
d="M15 9h3.75M15 12h3.75M15 15h3.75M4.5 19.5h15a2.25 2.25 0 0 0 2.25-2.25V6.75A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25v10.5A2.25 2.25 0 0 0 4.5 19.5Zm6-10.125a1.875 1.875 0 1 1-3.75 0 1.875 1.875 0 0 1 3.75 0Zm1.294 6.336a6.721 6.721 0 0 1-3.17.789 6.721 6.721 0 0 1-3.168-.789 3.376 3.376 0 0 1 6.338 0Z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="form-control-inscription"
|
||||||
|
name="nom"
|
||||||
|
placeholder="Nom"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<span class="icon">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke-width="1.5"
|
||||||
|
stroke="currentColor"
|
||||||
|
class="size-6"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
d="M15 9h3.75M15 12h3.75M15 15h3.75M4.5 19.5h15a2.25 2.25 0 0 0 2.25-2.25V6.75A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25v10.5A2.25 2.25 0 0 0 4.5 19.5Zm6-10.125a1.875 1.875 0 1 1-3.75 0 1.875 1.875 0 0 1 3.75 0Zm1.294 6.336a6.721 6.721 0 0 1-3.17.789 6.721 6.721 0 0 1-3.168-.789 3.376 3.376 0 0 1 6.338 0Z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="form-control-inscription"
|
||||||
|
name="prenom"
|
||||||
|
placeholder="Prénom"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<label>Sexe / Genre :</label>
|
||||||
|
<div class="form-group">
|
||||||
|
<span class="icon">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512">
|
||||||
|
<path
|
||||||
|
d="M176 288a112 112 0 1 0 0-224 112 112 0 1 0 0 224zM352 176c0 86.3-62.1 158.1-144 173.1l0 34.9 32 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-32 0 0 32c0 17.7-14.3 32-32 32s-32-14.3-32-32l0-32-32 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l32 0 0-34.9C62.1 334.1 0 262.3 0 176C0 78.8 78.8 0 176 0s176 78.8 176 176zM271.9 360.6c19.3-10.1 36.9-23.1 52.1-38.4c20 18.5 46.7 29.8 76.1 29.8c61.9 0 112-50.1 112-112s-50.1-112-112-112c-7.2 0-14.3 .7-21.1 2c-4.9-21.5-13-41.7-24-60.2C369.3 66 384.4 64 400 64c37 0 71.4 11.4 99.8 31l20.6-20.6L487 41c-6.9-6.9-8.9-17.2-5.2-26.2S494.3 0 504 0L616 0c13.3 0 24 10.7 24 24l0 112c0 9.7-5.8 18.5-14.8 22.2s-19.3 1.7-26.2-5.2l-33.4-33.4L545 140.2c19.5 28.4 31 62.7 31 99.8c0 97.2-78.8 176-176 176c-50.5 0-96-21.3-128.1-55.4z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<select name="sexe" class="form-control-inscription">
|
||||||
|
<option value="Homme">Homme</option>
|
||||||
|
<option value="Femme">Femme</option>
|
||||||
|
<option value="Autre">Autre</option></select
|
||||||
|
><br />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<span class="icon">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="24"
|
||||||
|
>
|
||||||
|
<path d="M0 0h24v24H0z" fill="none" />
|
||||||
|
<path
|
||||||
|
d="M12 6c1.11 0 2-.9 2-2 0-.38-.1-.73-.29-1.03L12 0l-1.71 2.97c-.19.3-.29.65-.29 1.03 0 1.1.9 2 2 2zm4.6 9.99l-1.07-1.07-1.08 1.07c-1.3 1.3-3.58 1.31-4.89 0l-1.07-1.07-1.09 1.07C6.75 16.64 5.88 17 4.96 17c-.73 0-1.4-.23-1.96-.61V21c0 .55.45 1 1 1h16c.55 0 1-.45 1-1v-4.61c-.56.38-1.23.61-1.96.61-.92 0-1.79-.36-2.44-1.01zM18 9h-5V7h-2v2H6c-1.66 0-3 1.34-3 3v1.54c0 1.08.88 1.96 1.96 1.96.52 0 1.02-.2 1.38-.57l2.14-2.13 2.13 2.13c.74.74 2.03.74 2.77 0l2.14-2.13 2.13 2.13c.37.37.86.57 1.38.57 1.08 0 1.96-.88 1.96-1.96V12C21 10.34 19.66 9 18 9z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
class="form-control-inscription"
|
||||||
|
name="age"
|
||||||
|
min="0"
|
||||||
|
max="120"
|
||||||
|
placeholder="Âge"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<label>Date de naissance :</label>
|
||||||
|
<div class="form-group">
|
||||||
|
<span class="icon">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
height="24px"
|
||||||
|
viewBox="0 -960 960 960"
|
||||||
|
width="24px"
|
||||||
|
fill="#e3e3e3"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M200-80q-33 0-56.5-23.5T120-160v-560q0-33 23.5-56.5T200-800h40v-80h80v80h320v-80h80v80h40q33 0 56.5 23.5T840-720v560q0 33-23.5 56.5T760-80H200Zm0-80h560v-400H200v400Zm0-480h560v-80H200v80Zm0 0v-80 80Zm280 240q-17 0-28.5-11.5T440-440q0-17 11.5-28.5T480-480q17 0 28.5 11.5T520-440q0 17-11.5 28.5T480-400Zm-160 0q-17 0-28.5-11.5T280-440q0-17 11.5-28.5T320-480q17 0 28.5 11.5T360-440q0 17-11.5 28.5T320-400Zm320 0q-17 0-28.5-11.5T600-440q0-17 11.5-28.5T640-480q17 0 28.5 11.5T680-440q0 17-11.5 28.5T640-400ZM480-240q-17 0-28.5-11.5T440-280q0-17 11.5-28.5T480-320q17 0 28.5 11.5T520-280q0 17-11.5 28.5T480-240Zm-160 0q-17 0-28.5-11.5T280-280q0-17 11.5-28.5T320-320q17 0 28.5 11.5T360-280q0 17-11.5 28.5T320-240Zm320 0q-17 0-28.5-11.5T600-280q0-17 11.5-28.5T640-320q17 0 28.5 11.5T680-280q0 17-11.5 28.5T640-240Z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<input
|
||||||
|
type="date"
|
||||||
|
class="form-control-inscription"
|
||||||
|
name="date_naissance"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<span class="icon">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M12 12c2.21 0 4-1.79 4-4S14.21 4 12 4 8 5.79 8 8s1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="form-control-inscription"
|
||||||
|
name="identifiant"
|
||||||
|
placeholder="Identifiant"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<span class="icon">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M20 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<input
|
||||||
|
type="email"
|
||||||
|
class="form-control-inscription"
|
||||||
|
name="email"
|
||||||
|
placeholder="Adresse mail"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<span class="icon">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M12 2C8.691 2 6 4.691 6 8v4c-1.104 0-2 .896-2 2v8c0 1.104.896 2 2 2h12c1.104 0 2-.896 2-2v-8c0-1.104-.896-2-2-2V8c0-3.309-2.691-6-6-6zm0 2c2.205 0 4 1.795 4 4v4H8V8c0-2.205 1.795-4 4-4zm-4 10h8v8H8v-8z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
class="form-control-inscription"
|
||||||
|
name="mot_de_passe"
|
||||||
|
placeholder="Mot de Passe"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<span class="icon">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
color="#000000"
|
||||||
|
stroke-width="1.5"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
d="M20.75 16.7143C20.75 16.7631 20.7453 16.8109 20.7364 16.8571C20.7453 16.9034 20.75 16.9511 20.75 17C20.75 17.4142 20.4142 17.75 20 17.75H6C5.30964 17.75 4.75 18.3096 4.75 19C4.75 19.6904 5.30964 20.25 6 20.25H20C20.4142 20.25 20.75 20.5858 20.75 21C20.75 21.4142 20.4142 21.75 20 21.75H6C4.48122 21.75 3.25 20.5188 3.25 19V5C3.25 3.48122 4.48122 2.25 6 2.25H19.4C20.1456 2.25 20.75 2.85442 20.75 3.6V16.7143ZM9 6.25C8.58579 6.25 8.25 6.58579 8.25 7C8.25 7.41421 8.58579 7.75 9 7.75H15C15.4142 7.75 15.75 7.41421 15.75 7C15.75 6.58579 15.4142 6.25 15 6.25H9Z"
|
||||||
|
fill="#000000"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="form-control-inscription"
|
||||||
|
name="situation"
|
||||||
|
placeholder="Situation professionnelle"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="boutons">
|
||||||
|
<label for="photo_profil" class="custom-file-upload">
|
||||||
|
<span class="icon">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="currentColor"
|
||||||
|
class="upload-icon"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M19 15v4H5v-4H3v4a2 2 0 002 2h14a2 2 0 002-2v-4h-2zm-7-1l5-5h-3V4h-4v5H7l5 5z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
Photo de profil (facultatif)
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<input
|
||||||
|
id="photo_profil"
|
||||||
|
type="file"
|
||||||
|
name="photo_profil"
|
||||||
|
accept="image/*"
|
||||||
|
hidden
|
||||||
|
/>
|
||||||
|
|
||||||
|
<button class="bouton-inscription" type="submit">
|
||||||
|
S'inscrire
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tour"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<%- include('partials/footer') %>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
31
z1/webapp/views/membre.ejs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>Page d'accueil - Smart Building</title>
|
||||||
|
<link rel="stylesheet" href="/styleMembres.css" />
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
|
<link
|
||||||
|
href="https://fonts.googleapis.com/css2?family=Inter&display=swap"
|
||||||
|
rel="stylesheet"
|
||||||
|
/>
|
||||||
|
<script
|
||||||
|
src="https://kit.fontawesome.com/a076d05399.js"
|
||||||
|
crossorigin="anonymous"
|
||||||
|
></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<%- include('partials/header') %>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<h1>Member Details</h1>
|
||||||
|
<p>Member ID: <%= id %></p>
|
||||||
|
<!-- Display the ID passed from the route -->
|
||||||
|
|
||||||
|
<!-- More member details would go here, once you fetch them -->
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<%- include('partials/footer') %>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
119
z1/webapp/views/membres.ejs
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>Page d'accueil - Smart Building</title>
|
||||||
|
<link rel="stylesheet" href="/styleMembres.css" />
|
||||||
|
<link
|
||||||
|
href="https://fonts.googleapis.com/css2?family=Inter&display=swap"
|
||||||
|
rel="stylesheet"
|
||||||
|
/>
|
||||||
|
<script
|
||||||
|
src="https://kit.fontawesome.com/a076d05399.js"
|
||||||
|
crossorigin="anonymous"
|
||||||
|
></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<%- include('partials/header') %>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<section class="left-panel">
|
||||||
|
<img src="/images/batiment.png" alt="Bâtiment" />
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="right-panel">
|
||||||
|
<div class="header-membres">
|
||||||
|
<h1>Membres</h1>
|
||||||
|
<form class="form">
|
||||||
|
<label for="search">
|
||||||
|
<input
|
||||||
|
class="input"
|
||||||
|
type="text"
|
||||||
|
placeholder="Rechercher"
|
||||||
|
id="search"
|
||||||
|
/>
|
||||||
|
<div class="fancy-bg"></div>
|
||||||
|
<div class="search">
|
||||||
|
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||||
|
<path
|
||||||
|
d="M21.53 20.47l-3.66-3.66C19.19 15.24 20 13.21 20 11c0-4.97-4.03-9-9-9s-9 4.03-9 9 4.03 9 9 9c2.21 0 4.24-.8 5.81-2.13l3.66 3.66c.29.29.76.29 1.06 0s.29-.76 0-1.06zM3.5 11c0-4.14 3.36-7.5 7.5-7.5s7.5 3.36 7.5 7.5-3.36 7.5-7.5 7.5S3.5 15.14 3.5 11z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<button class="close-btn" type="reset" onClick="clearInput()">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
fill="currentColor"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</label>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="membres-container"></div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<%- include('partials/footer') %>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const membresContainer = document.getElementById("membres-container");
|
||||||
|
|
||||||
|
async function fetchMembres() {
|
||||||
|
try {
|
||||||
|
const response = await fetch("/api/utilisateurs");
|
||||||
|
const membres = await response.json();
|
||||||
|
|
||||||
|
const statutColor = {
|
||||||
|
visiteur: "#ffbe0b",
|
||||||
|
simple: "#4ecdc4",
|
||||||
|
complexe: "#f72585",
|
||||||
|
administrateur: "#e63946",
|
||||||
|
};
|
||||||
|
|
||||||
|
membresContainer.innerHTML = "";
|
||||||
|
|
||||||
|
membres.forEach((membre) => {
|
||||||
|
const div = document.createElement("div");
|
||||||
|
div.classList.add("membre");
|
||||||
|
div.innerHTML = `
|
||||||
|
<h3>${membre.nom}</h3>
|
||||||
|
<h4>${membre.prenom}</h4>
|
||||||
|
<p>${membre.age} ans</p>
|
||||||
|
<p style="color: ${
|
||||||
|
statutColor[membre.statut] || "#888"
|
||||||
|
}; font-weight: bold;">${membre.statut}</p>
|
||||||
|
`;
|
||||||
|
membresContainer.appendChild(div);
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Erreur lors du chargement des membres :", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fonction pour réinitialiser l'input et les objets affichés
|
||||||
|
function clearInput() {
|
||||||
|
const inputField = document.getElementById("search"); // Sélectionne l'input par son id
|
||||||
|
inputField.value = ""; // Vide l'input
|
||||||
|
inputField.dispatchEvent(new Event("input")); // Déclenche l'événement 'input' pour actualiser l'affichage des objets
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById("search").addEventListener("input", function (e) {
|
||||||
|
const val = e.target.value.toLowerCase();
|
||||||
|
document.querySelectorAll(".membre").forEach((div) => {
|
||||||
|
const content = div.innerText.toLowerCase();
|
||||||
|
div.style.display = content.includes(val) ? "block" : "none";
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
window.onload = fetchMembres;
|
||||||
|
</script>
|
||||||
|
</html>
|
||||||
200
z1/webapp/views/objets.ejs
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>Page d'accueil - Smart Building</title>
|
||||||
|
<link rel="stylesheet" href="/styleObjets.css" />
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css" rel="stylesheet" />
|
||||||
|
<script src="https://kit.fontawesome.com/a076d05399.js" crossorigin="anonymous"></script>
|
||||||
|
<style>
|
||||||
|
.setting-btn.disabled {
|
||||||
|
opacity: 0.4;
|
||||||
|
pointer-events: none;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<%- include('partials/header') %>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<section class="left-panel">
|
||||||
|
<img src="/images/batiment.png" alt="Bâtiment" />
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="right-panel">
|
||||||
|
<div class="header-objets">
|
||||||
|
<h1>Objets Connectés</h1>
|
||||||
|
<form class="form">
|
||||||
|
<label for="search">
|
||||||
|
<input class="input" type="text" required placeholder="Rechercher" id="search" />
|
||||||
|
<div class="fancy-bg"></div>
|
||||||
|
<div class="search">
|
||||||
|
<svg viewBox="0 0 24 24" aria-hidden="true" class="r-yyyyoo">
|
||||||
|
<g>
|
||||||
|
<path d="M21.53 20.47l-3.66-3.66C19.195 15.24 20 13.214 20 11c0-4.97-4.03-9-9-9s-9 4.03-9 9 4.03 9 9 9c2.215 0 4.24-.804 5.808-2.13l3.66 3.66c.147.146.34.22.53.22s.385-.073.53-.22c.295-.293.295-.767.002-1.06zM3.5 11c0-4.135 3.365-7.5 7.5-7.5s7.5 3.365 7.5 7.5-3.365 7.5-7.5 7.5-7.5-3.365-7.5-7.5z"></path>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<span class="close-btn" aria-label="Reset" onClick="clearInput()">×</span>
|
||||||
|
</label>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div id="objets-container" data-statut="<%= session.utilisateur ? session.utilisateur.statut : '' %>"></div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<div id="myModal" class="modal">
|
||||||
|
<div class="modal-content">
|
||||||
|
<span class="close">×</span>
|
||||||
|
<div id="modal-info"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<%- include('partials/footer') %>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const span = document.getElementsByClassName("close")[0];
|
||||||
|
span.onclick = () => document.getElementById('myModal').style.display = "none";
|
||||||
|
|
||||||
|
function openModal(objet) {
|
||||||
|
const modal = document.getElementById('myModal');
|
||||||
|
const modalInfo = document.getElementById('modal-info');
|
||||||
|
|
||||||
|
modalInfo.innerHTML = `
|
||||||
|
<div class='info_objet'>
|
||||||
|
<h2 id='denomination-edit'>${objet.denomination}</h2>
|
||||||
|
<button type="submit" onClick="toggleEdit('${objet.adresse_ip}','edit-icon_denomination', 'denomination')">
|
||||||
|
<i id="edit-icon_denomination" class="fas fa-pen"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class='info_objet'>
|
||||||
|
<p id='adresse_ip-edit'>${objet.adresse_ip}</p>
|
||||||
|
<button type="submit" onClick="toggleEdit('${objet.adresse_ip}','edit-icon_adresse_ip', 'adresse_ip')">
|
||||||
|
<i id="edit-icon_adresse_ip" class="fas fa-pen"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class='info_objet'>
|
||||||
|
<p id='niveau-edit'>${objet.niveau}</p>
|
||||||
|
<button type="submit" onClick="toggleEdit('${objet.adresse_ip}','edit-icon_niveau', 'niveau')">
|
||||||
|
<i id="edit-icon_niveau" class="fas fa-pen"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class='info_objet'>
|
||||||
|
<p id='type-edit'>${objet.type}</p>
|
||||||
|
<button type="submit" onClick="toggleEdit('${objet.adresse_ip}','edit-icon_type', 'type')">
|
||||||
|
<i id="edit-icon_type" class="fas fa-pen"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class='info_objet'>
|
||||||
|
<p><strong>Dernière interaction:</strong> ${objet.derniere_interaction}</p>
|
||||||
|
</div>
|
||||||
|
<div class='info_objet'>
|
||||||
|
<p><strong>État:</strong> ${objet.etat}</p>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
modal.style.display = 'block';
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleEdit(adresse_ip, edit_icon, field) {
|
||||||
|
const editIcon = document.getElementById(edit_icon);
|
||||||
|
const paragraph = document.getElementById(field + "-edit");
|
||||||
|
if (editIcon.className === "fas fa-pen") {
|
||||||
|
editIcon.className = "fas fa-check";
|
||||||
|
paragraph.contentEditable = true;
|
||||||
|
paragraph.style.backgroundColor = "transparent";
|
||||||
|
} else {
|
||||||
|
editIcon.className = "fas fa-pen";
|
||||||
|
paragraph.contentEditable = false;
|
||||||
|
paragraph.style.backgroundColor = "rgba(60, 60, 60, 0.98)";
|
||||||
|
saveChanges(adresse_ip, field, paragraph.innerText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function saveChanges(adresse_ip, field, newValue) {
|
||||||
|
document.getElementById('h3_' + adresse_ip).innerText = newValue;
|
||||||
|
try {
|
||||||
|
const response = await fetch('/api/objets/' + encodeURIComponent(adresse_ip), {
|
||||||
|
method: 'PUT',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ [field]: newValue })
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
console.log('Objet mis à jour avec succès !');
|
||||||
|
} else {
|
||||||
|
console.error('Erreur serveur :', response.statusText);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur réseau :', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearInput() {
|
||||||
|
const input = document.getElementById("search");
|
||||||
|
input.value = "";
|
||||||
|
input.dispatchEvent(new Event("input"));
|
||||||
|
fetchObjets();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchObjets() {
|
||||||
|
try {
|
||||||
|
const response = await fetch('/api/objets');
|
||||||
|
const objets = await response.json();
|
||||||
|
const container = document.getElementById('objets-container');
|
||||||
|
const userStatut = container.getAttribute("data-statut");
|
||||||
|
|
||||||
|
container.innerHTML = "";
|
||||||
|
|
||||||
|
const niveauColor = {
|
||||||
|
débutant: "#2ecc71",
|
||||||
|
intermédiaire: "#3498db",
|
||||||
|
avancé: "#f39c12",
|
||||||
|
expert: "#e74c3c",
|
||||||
|
};
|
||||||
|
|
||||||
|
const peutModifier = ['administrateur', 'complexe', 'simple'].includes(userStatut);
|
||||||
|
|
||||||
|
|
||||||
|
objets.forEach(objet => {
|
||||||
|
console.log(objet);
|
||||||
|
const div = document.createElement('div');
|
||||||
|
div.className = 'objet';
|
||||||
|
div.innerHTML = `
|
||||||
|
<button class="setting-btn ${peutModifier ? '' : 'disabled'}"
|
||||||
|
${peutModifier ? `onclick='openModal(${JSON.stringify(objet)})'` : ''}>
|
||||||
|
<i class="fas fa-cog"></i>
|
||||||
|
</button>
|
||||||
|
<h3 id='h3_${objet.adresse_ip}'>${objet.denomination}</h3>
|
||||||
|
<p>${objet.adresse_ip}</p>
|
||||||
|
<p><strong>Type</strong> : ${objet.type}</p>
|
||||||
|
${objet.temperature_actuelle !== null ? `<p><strong>Temperature Actuelle</strong> : ${objet.temperature_actuelle}°</p>` : ''}
|
||||||
|
${objet.temperature_cible !== null ? `<p><strong>Temperature Cible</strong> : ${objet.temperature_cible}°</p>` : ''}
|
||||||
|
${objet.mode !== null ? `<p><strong>Mode</strong> : ${objet.mode}</p>` : ''}
|
||||||
|
<p><strong>Niveau:</strong> <span style="color: ${niveauColor[objet.niveau]}">${objet.niveau}</span></p>
|
||||||
|
<div class="etat-point ${objet.etat === 'Actif' ? 'actif' : 'inactif'}"></div>
|
||||||
|
`;
|
||||||
|
container.appendChild(div);
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erreur fetchObjets :', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('search').addEventListener('input', function (e) {
|
||||||
|
const searchTerm = e.target.value.toLowerCase();
|
||||||
|
document.querySelectorAll('.objet').forEach(objet => {
|
||||||
|
const text = objet.innerText.toLowerCase();
|
||||||
|
objet.style.display = text.includes(searchTerm) ? 'block' : 'none';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
window.onload = fetchObjets;
|
||||||
|
</script>
|
||||||
9
z1/webapp/views/partials/footer.ejs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<footer>
|
||||||
|
<div class="footer_link">
|
||||||
|
<a href="/description">À PROPOS</a>
|
||||||
|
<a href="/contact">CONTACT</a>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="copyright">© 404 NOT FOUND | CY-TECH</div>
|
||||||
|
</footer>
|
||||||
39
z1/webapp/views/partials/header.ejs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<header>
|
||||||
|
<a href="/">
|
||||||
|
<img id="smart_building" alt="smart_building" src="/images/smart_building.png" />
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<ul class="header_text">
|
||||||
|
<% if (!session.utilisateur) { %>
|
||||||
|
<li><a href="/">Accueil</a></li>
|
||||||
|
<li><a href="/inscription">Inscription</a></li>
|
||||||
|
<% } else if (session.utilisateur.statut === 'administrateur') { %>
|
||||||
|
<% if (currentRoute === '/admin') { %>
|
||||||
|
<li><a href="/">Accueil</a></li>
|
||||||
|
<li><a href="/profil">Profil</a></li>
|
||||||
|
<% } else { %>
|
||||||
|
<li><a href="/admin">Dashboard</a></li>
|
||||||
|
<li><a href="/">Accueil</a></li>
|
||||||
|
<li><a href="/profil">Profil</a></li>
|
||||||
|
<% } %>
|
||||||
|
<% } else if (session.utilisateur.statut === 'complexe') { %>
|
||||||
|
<% if (currentRoute === '/dashboard-complexe') { %>
|
||||||
|
<li><a href="/">Accueil</a></li>
|
||||||
|
<li><a href="/profil">Profil</a></li>
|
||||||
|
<% } else { %>
|
||||||
|
<li><a href="/dashboard-complexe">Dashboard</a></li>
|
||||||
|
<li><a href="/">Accueil</a></li>
|
||||||
|
<li><a href="/profil">Profil</a></li>
|
||||||
|
<% } %>
|
||||||
|
<% } else { %>
|
||||||
|
<li><a href="/">Accueil</a></li>
|
||||||
|
<li><a href="/profil">Profil</a></li>
|
||||||
|
<% } %>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<% if (!session.utilisateur) { %>
|
||||||
|
<a class="bouton_connexion" href="/connexion">Connexion</a>
|
||||||
|
<% } else { %>
|
||||||
|
<a class="bouton_connexion" href="/deconnexion">Déconnexion</a>
|
||||||
|
<% } %>
|
||||||
|
</header>
|
||||||
70
z1/webapp/views/profil.ejs
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
<!-- views/profil.ejs -->
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Mon Profil</title>
|
||||||
|
<link rel="stylesheet" href="/styleProfil.css">
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<%- include("partials/header") %>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<h1>Mon Profil</h1>
|
||||||
|
<form id="profilForm" action="/profil/update" method="POST" enctype="multipart/form-data">
|
||||||
|
<div>
|
||||||
|
<label>Login :</label>
|
||||||
|
<input type="text" name="identifiant" value="<%= session.utilisateur.identifiant %>" disabled>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label>Nom :</label>
|
||||||
|
<input type="text" name="nom" value="<%= session.utilisateur.nom %>" disabled>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label>Prénom :</label>
|
||||||
|
<input type="text" name="prenom" value="<%= session.utilisateur.prenom %>" disabled>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label>Sexe :</label>
|
||||||
|
<select name="sexe" disabled>
|
||||||
|
<option value="Homme" <%= session.utilisateur.sexe === 'Homme' ? 'selected' : '' %>>Homme</option>
|
||||||
|
<option value="Femme" <%= session.utilisateur.sexe === 'Femme' ? 'selected' : '' %>>Femme</option>
|
||||||
|
<option value="Autre" <%= session.utilisateur.sexe === 'Autre' ? 'selected' : '' %>>Autre</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label>Situation professionnelle :</label>
|
||||||
|
<input type="text" name="situation" value="<%= session.utilisateur.situation %>" disabled>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label>Photo de profil :</label><br>
|
||||||
|
<img src="../photos/<%= session.utilisateur.photo %>" width="100" alt=""><br>
|
||||||
|
<input type="file" name="photo" disabled>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label>Mot de passe :</label>
|
||||||
|
<input type="password" name="mot_de_passe" placeholder="nouveau mot de passe si désiré" disabled>
|
||||||
|
</div>
|
||||||
|
<button type="button" id="editBtn">Modifier mon profil</button>
|
||||||
|
<button type="submit" id="saveBtn" style="display: none;">Enregistrer</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const editBtn = document.getElementById('editBtn');
|
||||||
|
const saveBtn = document.getElementById('saveBtn');
|
||||||
|
const inputs = document.querySelectorAll('#profilForm input, #profilForm select');
|
||||||
|
|
||||||
|
editBtn.addEventListener('click', () => {
|
||||||
|
inputs.forEach(input => {
|
||||||
|
input.disabled = false;
|
||||||
|
});
|
||||||
|
editBtn.style.display = 'none';
|
||||||
|
saveBtn.style.display = 'inline-block';
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<%- include("partials/footer") %>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
162
z1/webapp/views/ressources.ejs
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<title>Page d'accueil - Smart Building</title>
|
||||||
|
<link rel="stylesheet" href="/styleObjets.css" />
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css" rel="stylesheet" />
|
||||||
|
<script src="https://kit.fontawesome.com/a076d05399.js" crossorigin="anonymous"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<%- include('partials/header') %>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<section class="left-panel">
|
||||||
|
<img src="/images/batiment.png" alt="Bâtiment" />
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="right-panel">
|
||||||
|
<div class="header-objets">
|
||||||
|
<h1>Gestion des ressources</h1>
|
||||||
|
</div>
|
||||||
|
<div id="objets-container"></div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<div id="myModal" class="modal">
|
||||||
|
<!-- Modal content -->
|
||||||
|
<div class="modal-content">
|
||||||
|
<span class="close">×</span>
|
||||||
|
<div id="modal-info"></div>
|
||||||
|
<!-- Conteneur pour les informations -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
<%- include('partials/footer') %>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
let objetsContainer = document.getElementById('objets-container');
|
||||||
|
|
||||||
|
function openModal(objet) {
|
||||||
|
const modal = document.getElementById('myModal');
|
||||||
|
const modalInfo = document.getElementById('modal-info');
|
||||||
|
|
||||||
|
modalInfo.innerHTML = `
|
||||||
|
<div class='info_objet'>
|
||||||
|
<h2 id='denomination-edit'>${objet.denomination}</h2>
|
||||||
|
<button type="submit" id="edit-button" onClick="toggleEdit('edit-icon_denomination', 'denomination-edit')">
|
||||||
|
<i id="edit-icon_denomination" class="fas fa-pen"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class='info_objet'>
|
||||||
|
<p id='address_ip-edit'>${objet.adresse_ip}</p>
|
||||||
|
<button type="submit" id="edit-button" onClick="toggleEdit('edit-icon_adresse_ip', 'address_ip-edit')">
|
||||||
|
<i id="edit-icon_adresse_ip" class="fas fa-pen"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class='info_objet'>
|
||||||
|
<p id='etat-edit'>${objet.etat}</p>
|
||||||
|
<button type="submit" id="edit-button" onClick="toggleEdit('edit-icon_etat', 'etat-edit')">
|
||||||
|
<i id="edit-icon_etat" class="fas fa-pen"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class='info_objet'>
|
||||||
|
<p id='type-edit'>${objet.type}</p>
|
||||||
|
<button type="submit" id="edit-button" onClick="toggleEdit('edit-icon_type', 'type-edit')">
|
||||||
|
<i id="edit-icon_type" class="fas fa-pen"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class='info_objet'>
|
||||||
|
<p><strong>Consommation actuelle :</strong> ${objet.consommation}</p>
|
||||||
|
</div>
|
||||||
|
<div class='info_objet'>
|
||||||
|
<p><strong>Consommation maximale :</strong> ${objet.consommation_max}</p>
|
||||||
|
</div>
|
||||||
|
<div class='info_objet'>
|
||||||
|
<p><strong>Fournisseur :</strong> ${objet.fournisseur}</p>
|
||||||
|
</div>
|
||||||
|
<div class='info_objet'>
|
||||||
|
<p><strong>Abonnement :</strong> ${objet.abonnement}</p>
|
||||||
|
</div>
|
||||||
|
<div class='info_objet'>
|
||||||
|
<p><strong>Échéance :</strong> ${objet.echeance}</p>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
modal.style.display = 'block';
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleEdit(edit_icon, field) {
|
||||||
|
const editIcon = document.getElementById(edit_icon);
|
||||||
|
const paragraph = document.getElementById(field);
|
||||||
|
if (editIcon.className == "fas fa-pen") {
|
||||||
|
editIcon.className = "fas fa-check";
|
||||||
|
editIcon.alt = "Check";
|
||||||
|
paragraph.contentEditable = true;
|
||||||
|
paragraph.style.backgroundColor = "#cfcfcf";
|
||||||
|
} else {
|
||||||
|
if (editIcon.className == "fas fa-check") {
|
||||||
|
editIcon.className = "fas fa-pen";
|
||||||
|
editIcon.alt = "Stylo";
|
||||||
|
paragraph.contentEditable = false;
|
||||||
|
paragraph.style.backgroundColor = "#666666";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var span = document.getElementsByClassName("close")[0];
|
||||||
|
|
||||||
|
span.onclick = function () {
|
||||||
|
const modal = document.getElementById('myModal');
|
||||||
|
modal.style.display = "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fonction pour réinitialiser l'input et les objets affichés
|
||||||
|
function clearInput() {
|
||||||
|
const inputField = document.getElementById("search"); // Sélectionne l'input par son id
|
||||||
|
inputField.value = ""; // Vide l'input
|
||||||
|
inputField.dispatchEvent(new Event("input")); // Déclenche l'événement 'input' pour actualiser l'affichage des objets
|
||||||
|
fetchObjets(); // Recharge les objets
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchObjets() {
|
||||||
|
const objetsContainer = document.getElementById('objets-container');
|
||||||
|
objetsContainer.innerHTML = "";
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch('/api/ressources');
|
||||||
|
const ressources = await response.json();
|
||||||
|
|
||||||
|
ressources.forEach(r => {
|
||||||
|
const div = document.createElement('div');
|
||||||
|
div.classList.add('objet');
|
||||||
|
|
||||||
|
div.innerHTML = `
|
||||||
|
<h3>${r.nom}</h3>
|
||||||
|
<p><strong>Consommation actuelle :</strong> ${r.consommation}</p>
|
||||||
|
<p><strong>Max atteignable :</strong> ${r.consommation_max}</p>
|
||||||
|
<p><strong>Fournisseur :</strong> ${r.fournisseur}</p>
|
||||||
|
<p><strong>Abonnement :</strong> ${r.abonnement}</p>
|
||||||
|
<p><strong>Date paiement :</strong> ${r.echeance}</p>
|
||||||
|
`;
|
||||||
|
|
||||||
|
objetsContainer.appendChild(div);
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Erreur lors du chargement des ressources :", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Charger les objets au premier chargement de la page
|
||||||
|
window.onload = function () {
|
||||||
|
fetchObjets(); // Charge les objets au premier chargement
|
||||||
|
};
|
||||||
|
|
||||||
|
</script>
|
||||||