Compare commits

..

No commits in common. "master" and "feature/FEATURE0004_Connexion" have entirely different histories.

12 changed files with 23 additions and 745 deletions

10
app.js
View file

@ -1,10 +1,11 @@
const SESSION_SECRET = "your_session_secret";
// ...existing code...
const express = require('express');
const session = require('express-session');
const initDb = require('./db_init');
const path = require('path');
const expressLayouts = require('express-ejs-layouts');
const routes = require('./routes');
@ -33,13 +34,6 @@ app.use(session({
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
// Express EJS Layouts
app.use(expressLayouts);
app.set('layout', 'layout'); // nom du fichier layout sans .ejs
// Static files
app.use(express.static(path.join(__dirname, 'public')));
// Routes
app.use('/', routes);

Binary file not shown.

View file

@ -1,14 +1,13 @@
const axios = require("axios");
const { getUserByGId } = require('../users/getUsers');
const { getUserByDId } = require('../users/getUsers');
const { postUser } = require('../users/postUsers');
const CLIEN_ID = "71229835507-9413gbpdamv2qbcb2ov8oda2oqgcsk8q.apps.googleusercontent.com";
const GOOGLE_SECRET = "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";
const GOOGLE_REDIRECT_URI = "http://localhost:3000/auth/google/callback";
const REDIRECT_URI = "http://localhost:3000/auth/google/callback";
exports.handleGoogleAuth = async (req, res) => {
const code = req.query.code;
exports.handleGoogleAuth = async (code, res) => {
if (!code) return res.status(400).json({ error: "Code de validation manquant" });
try {
const params = new URLSearchParams();
@ -42,6 +41,8 @@ exports.handleGoogleAuth = async (req, res) => {
const newUser = {
username: userData.name || userData.email,
google_id: userData.id,
email: userData.email,
avatar: userData.picture || null,
};
savedUser = await postUser(newUser);
}

6
package-lock.json generated
View file

@ -12,7 +12,6 @@
"axios": "^1.11.0",
"ejs": "^3.1.10",
"express": "^5.1.0",
"express-ejs-layouts": "^2.5.1",
"express-session": "^1.18.2",
"sqlite3": "^5.1.7"
}
@ -709,11 +708,6 @@
"url": "https://opencollective.com/express"
}
},
"node_modules/express-ejs-layouts": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/express-ejs-layouts/-/express-ejs-layouts-2.5.1.tgz",
"integrity": "sha512-IXROv9n3xKga7FowT06n1Qn927JR8ZWDn5Dc9CJQoiiaaDqbhW5PDmWShzbpAa2wjWT1vJqaIM1S6vJwwX11gA=="
},
"node_modules/express-session": {
"version": "1.18.2",
"resolved": "https://registry.npmjs.org/express-session/-/express-session-1.18.2.tgz",

View file

@ -18,7 +18,6 @@
"axios": "^1.11.0",
"ejs": "^3.1.10",
"express": "^5.1.0",
"express-ejs-layouts": "^2.5.1",
"express-session": "^1.18.2",
"sqlite3": "^5.1.7"
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 238 KiB

View file

@ -1,111 +0,0 @@
main {
text-align: left !important;
}
.restaurant-page {
width: 90%;
max-width: 1200px;
margin: auto;
}
.header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-top: 20px;
}
.restaurant-info h1 {
margin: 0;
font-size: 24px;
}
.heart {
display: inline-flex;
align-items: center;
justify-content: center;
background: #ececec;
border-radius: 50%;
width: 32px;
height: 32px;
font-size: 20px;
margin-left: 8px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
}
.rating {
display: flex;
align-items: center;
margin: 10px 0;
gap: 10px;
}
.btn {
background: #999;
border: none;
color: white;
padding: 5px 10px;
cursor: pointer;
}
.chart-placeholder {
width: 200px;
height: 200px;
background: #eee;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
}
.main-image {
width: 100%;
height: 200px;
background: #ccc;
margin: 20px 0;
}
.description {
background: #f9f9f9;
padding: 15px;
margin-bottom: 20px;
}
.gallery {
display: flex;
justify-content: space-between;
margin-bottom: 30px;
}
.gallery-item {
width: 32%;
height: 150px;
background: #ddd;
}
.reviews-title {
background: #eee;
padding: 10px;
margin: 0;
}
.reviews {
display: flex;
flex-direction: column;
gap: 20px;
margin: 20px 0;
}
.review {
background: #f5f5f5;
padding: 15px;
border: 1px solid #ddd;
}
.review h3 {
margin-top: 0;
}
.review-rating div {
margin-top: 5px;
}

View file

@ -1,294 +0,0 @@
body {
margin: 0;
font-family: Arial, sans-serif;
background: linear-gradient(135deg, #f8f6fc 0%, #fffbe7 100%);
color: #7a5c1e;
}
header {
background: linear-gradient(90deg, #8e68aa 60%, #cb8d37 100%);
color: white;
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 20px;
box-shadow: 0 2px 8px rgba(140, 104, 170, 0.08);
}
header h1 {
font-size: 1.2rem;
}
.search-bar {
flex-grow: 1;
margin: 0 20px;
}
.search-bar input {
width: 100%;
padding: 5px;
border: none;
border-radius: 4px;
}
.account {
background: linear-gradient(90deg, #cb8d37 60%, #8e68aa 100%);
padding: 6px 12px;
border-radius: 4px;
color: white;
cursor: pointer;
font-weight: bold;
transition: background 0.2s;
}
.account:hover {
background: #a97b2c;
}
main {
padding: 20px;
text-align: center;
}
main h2 {
font-size: 2rem;
margin: 10px 0;
}
.sections {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 30px;
margin-top: 20px;
}
.section h3 {
margin-bottom: 15px;
text-align: left;
}
.cards {
display: flex;
flex-direction: column;
gap: 15px;
}
.card {
background: #ddd;
border-radius: 8px;
padding: 15px;
display: flex;
justify-content: space-between;
align-items: center;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}
.card-info {
text-align: left;
}
.card-info h4 {
margin: 0 0 5px;
font-weight: bold;
}
.card-photo {
background: #8e68aa;
width: 120px;
height: 80px;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.9rem;
color: #555;
}
footer {
background: #8e68aa;
text-align: center;
padding: 10px;
margin-top: 30px;
}
footer a {
margin: 0 10px;
text-decoration: none;
color: #333;
}
/* Header layout amélioré */
.main-header {
background: linear-gradient(90deg, #8e68aa 60%, #cb8d37 100%);
color: white;
box-shadow: 0 2px 8px rgba(140, 104, 170, 0.08);
padding: 0;
}
.header-content {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 20px;
max-width: 1200px;
margin: 0 auto;
width: 100%;
gap: 0;
}
.header-left {
display: flex;
align-items: center;
min-width: 220px;
}
.header-left h1 {
font-size: 1.4rem;
margin: 0 0 0 10px;
white-space: nowrap;
}
.header-center {
flex: 1 1 0;
display: flex;
justify-content: center;
}
.header-right {
display: flex;
align-items: center;
min-width: 260px;
justify-content: flex-end;
}
.search-bar {
flex: 1 1 300px;
max-width: 700px;
margin: 0 18px;
}
.search-bar input {
width: 100%;
padding: 7px 12px;
border: none;
border-radius: 4px;
font-size: 1rem;
}
.account {
display: flex;
align-items: center;
background: linear-gradient(90deg, #cb8d37 60%, #8e68aa 100%);
padding: 6px 12px;
border-radius: 4px;
color: white;
font-weight: bold;
transition: background 0.2s;
}
.account a {
color: white;
text-decoration: none;
margin-left: 8px;
font-weight: bold;
}
.account a:first-child {
margin-left: 0;
}
.account:hover {
background: #a97b2c;
}
.social-buttons {
display: flex;
gap: 12px;
margin: 0;
}
.btn-social {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 18px;
border: none;
border-radius: 30px;
font-size: 1rem;
font-weight: 600;
cursor: pointer;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.07);
transition: transform 0.1s, box-shadow 0.2s;
outline: none;
text-decoration: none;
}
.btn-social:active {
transform: scale(0.97);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.btn-google {
background: #fff;
color: #444;
border: 1px solid #e0e0e0;
}
.btn-google:hover {
background: #f5f5f5;
}
.btn-discord {
background: #5865f2;
color: #fff;
border: none;
}
.btn-discord:hover {
background: #4752c4;
}
.icon-social {
width: 22px;
height: 22px;
display: inline-block;
vertical-align: middle;
}
.logo {
height: 40px;
width: 40px;
border-radius: 8px;
margin-right: 10px;
object-fit: contain;
}
/* Responsive */
@media (max-width: 900px) {
.header-content {
flex-direction: column;
align-items: stretch;
gap: 10px;
}
.header-center {
justify-content: stretch;
margin: 10px 0;
}
.header-right {
justify-content: center;
min-width: 0;
margin-top: 10px;
}
.search-bar {
min-width: 180px;
max-width: 100%;
margin: 10px 0;
}
.account {
margin-top: 10px;
}
.sections {
grid-template-columns: 1fr;
}
.social-buttons {
flex-direction: column;
gap: 12px;
}
}

View file

@ -6,11 +6,6 @@ router.get('/', (req, res) => {
res.render('index', { user: req.session.user });
});
// Page resto
router.get('/resto/:id', (req, res) => {
res.render('resto', { user: req.session.user });
});
// Auth Discord
router.get('/auth/discord', (req, res) => {
const clientId = '1410258710407811082';
@ -22,17 +17,6 @@ router.get('/auth/discord', (req, res) => {
router.get('/auth/discord/callback', require('./modules/auth/discord').handleDiscordAuth);
// Auth Google
router.get('/auth/google', (req, res) => {
const clientId = '71229835507-9413gbpdamv2qbcb2ov8oda2oqgcsk8q.apps.googleusercontent.com';
const redirectUri = 'http://localhost:3000/auth/google/callback';
const scope = 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile';
const googleAuthUrl = `https://accounts.google.com/o/oauth2/auth?client_id=${clientId}&redirect_uri=${encodeURIComponent(redirectUri)}&response_type=code&scope=${encodeURIComponent(scope)}`;
res.redirect(googleAuthUrl);
});
router.get('/auth/google/callback', require('./modules/auth/google').handleGoogleAuth);
// Déconnexion
router.get('/logout', (req, res) => {
req.session.destroy((err) => {

View file

@ -1,78 +1,15 @@
<div style="display:flex; justify-content: center; align-items: center;">
<h2 style="margin-right: 20px;">LEPICURIEN</h2>
<img style="height: 70px; width: 70px; object-fit: contain;" alt="Logo de l'entreprise" src="logo.png" onerror="this.onerror=null;this.src='https://via.placeholder.com/70?text=Logo';" />
</div>
<div class="sections">
<!-- Restaurants proches -->
<div class="section">
<h3>Restaurants les plus proches</h3>
<div class="cards">
<a href="/resto/1" style="text-decoration:none; color:inherit;">
<div class="card">
<div class="card-info">
<h4>Le Canard Toulousain</h4>
<p>12 Rue du Capitole, 31000 Toulouse</p>
<p>Avis général</p>
</div>
<img alt="Photo du restaurant" src="https://source.unsplash.com/100x100/?restaurant=1" />
</div>
</a>
<a href="/resto/2" style="text-decoration:none; color:inherit;">
<div class="card">
<div class="card-info">
<h4>Chez Pépé Louis</h4>
<p>8 Avenue de la Garonne, 31000 Toulouse</p>
<p>Avis général</p>
</div>
<img alt="Photo du restaurant" src="https://source.unsplash.com/100x100/?restaurant=2" />
</div>
</a>
<a href="/resto/3" style="text-decoration:none; color:inherit;">
<div class="card">
<div class="card-info">
<h4>La Table Rose</h4>
<p>25 Rue Saint-Rome, 31000 Toulouse</p>
<p>Avis général</p>
</div>
<img alt="Photo du restaurant" src="https://source.unsplash.com/100x100/?restaurant=3" />
</div>
</a>
</div>
</div>
<!-- Restaurants populaires -->
<div class="section">
<h3>Restaurants les plus populaires</h3>
<div class="cards">
<a href="/resto/4" style="text-decoration:none; color:inherit;">
<div class="card">
<div class="card-info">
<h4>Bistro Occitan</h4>
<p>5 Place Wilson, 31000 Toulouse</p>
<p>Avis général</p>
</div>
<img alt="Photo du restaurant" src="https://source.unsplash.com/100x100/?restaurant=4" />
</div>
</a>
<a href="/resto/5" style="text-decoration:none; color:inherit;">
<div class="card">
<div class="card-info">
<h4>LAssiette du Sud</h4>
<p>17 Allée Jean Jaurès, 31000 Toulouse</p>
<p>Avis général</p>
</div>
<img alt="Photo du restaurant" src="https://source.unsplash.com/100x100/?restaurant=5" />
</div>
</a>
<a href="/resto/6" style="text-decoration:none; color:inherit;">
<div class="card">
<div class="card-info">
<h4>Le Petit Cassoulet</h4>
<p>3 Rue des Filatiers, 31000 Toulouse</p>
<p>Avis général</p>
</div>
<img alt="Photo du restaurant" src="https://source.unsplash.com/100x100/?restaurant=6" />
</div>
</a>
</div>
</div>
<!DOCTYPE html>
<html>
<head>
<title>Accueil</title>
</head>
<body>
<% if (user) { %>
<h1>Bienvenue, <%= user.username %>!</h1>
<a href="/logout">Déconnexion</a>
<% } else { %>
<h1>Bienvenue sur Resto-EPI</h1>
<a href="/auth/discord">Connexion/Inscription via Discord</a>
<% } %>
</body>
</html>

View file

@ -1,60 +0,0 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="L'EPICURIEN - Découvrez et partagez les meilleurs restaurants autour de vous." />
<meta name="author" content="L'EPICURIEN Team" />
<title>L'EPICURIEN</title>
<link rel="stylesheet" href="/style.css" />
<link rel="icon" href="/logo.png" type="image/png" />
</head>
<body>
<header class="main-header">
<div class="header-content">
<div class="header-left">
<a href="/" class="logo-link">
<img src="/logo.png" alt="Logo L'EPICURIEN" class="logo" />
</a>
<a href="/" class="">
<h1 style="text-decoration: none; color: white;">L'EPICURIEN</h1>
</a>
</div>
<div class="header-center">
<div class="search-bar">
<input type="text" placeholder="Rechercher un restaurant" />
</div>
</div>
<div class="header-right">
<div class="account">
<% if (user) { %>
<a href="/logout" style="margin-left:12px;">Déconnexion</a>
<% } else { %>
<div class="social-buttons">
<a href="/auth/google" class="btn-social btn-google">
<img src="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/google/google-original.svg" alt="Google" class="icon-social"/>
</a>
<a href="/auth/discord" class="btn-social btn-discord">
<img src="https://cdn.jsdelivr.net/gh/edent/SuperTinyIcons/images/svg/discord.svg" alt="Discord" class="icon-social"/>
</a>
</div>
<% } %>
</div>
</div>
</div>
</header>
<main>
<%- body %>
</main>
<footer class="main-footer">
<a href="#">Mentions légales</a> |
<a href="#">Politique de confidentialité</a> |
<a href="#">CGU</a>
</footer>
</body>
</html>

View file

@ -1,166 +0,0 @@
<link rel="stylesheet" href="/resto.css" />
<div class="restaurant-page">
<!-- En-tête restaurant -->
<div class="header">
<div class="restaurant-info">
<h1>
Nom restaurant
<span class="heart">
<% if (user) { %>
❤️
<% } else { %>
🤍
<% } %>
</span>
</h1>
<p class="address">Adresse</p>
<div class="rating">
<span>⭐️⭐️⭐️⭐️⭐️</span>
<a href="#avis" class="btn">Voir tous les avis</a>
</div>
</div>
<div class="chart">
<div class="chart-placeholder">
<canvas id="radarChart"></canvas>
</div>
</div>
</div>
<!-- Image principale -->
<div class="main-image"></div>
<!-- Description -->
<div class="description">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat cupidatat
</p>
</div>
<!-- Galerie -->
<div class="gallery">
<div class="gallery-item"></div>
<div class="gallery-item"></div>
<div class="gallery-item"></div>
</div>
<!-- Avis -->
<h2 class="reviews-title" id="avis">Avis</h2>
<div class="reviews">
<div class="review">
<h3>Titre avis</h3>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.
</p>
<div class="review-rating">
<div>Qualité des plats ⭐⭐⭐⭐⭐</div>
<div>Service ⭐⭐⭐⭐⭐</div>
<div>Ambiance ⭐⭐⭐⭐⭐</div>
<div>Accessibilité ⭐⭐⭐⭐⭐</div>
<div>Tarif ⭐⭐⭐⭐⭐</div>
</div>
</div>
<div class="review">
<h3>Titre avis</h3>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.
</p>
<div class="review-rating">
<div>Qualité des plats ⭐⭐⭐⭐⭐</div>
<div>Service ⭐⭐⭐⭐⭐</div>
<div>Ambiance ⭐⭐⭐⭐⭐</div>
<div>Accessibilité ⭐⭐⭐⭐⭐</div>
<div>Tarif ⭐⭐⭐⭐⭐</div>
</div>
</div>
<div class="review">
<h3>Titre avis</h3>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.
</p>
<div class="review-rating">
<div>Qualité des plats ⭐⭐⭐⭐⭐</div>
<div>Service ⭐⭐⭐⭐⭐</div>
<div>Ambiance ⭐⭐⭐⭐⭐</div>
<div>Accessibilité ⭐⭐⭐⭐⭐</div>
<div>Tarif ⭐⭐⭐⭐⭐</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
const ctx = document.getElementById('radarChart').getContext('2d');
const radarChart = new Chart(ctx, {
type: 'radar',
data: {
labels: ['Qualité des plats', 'Ambiance', 'Accessibilité', 'Service', 'Tradition'],
datasets: [
{
label: 'Moyenne des notes',
data: [4.7, 4.6, 4.4, 4.3, 4.8],
fill: true,
backgroundColor: 'rgba(255,215, 0, 0.2)',
borderColor: 'rgb(255,215, 0, 1)',
pointBackgroundColor: 'rgb(255,215, 0)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgb(255,215, 0)',
pointStyle: 'circle',
pointRadius: 5,
pointRotation: 0,
},
]
},
options: {
plugins: {
legend: {
display: false
},
tooltip: {
callbacks: {
label: function(context) {
let label = context.dataset.label || '';
if (label) {
label += ': ';
}
label += context.formattedValue;
return label;
}
}
}
},
scales: {
r: {
max: 5,
min: 0,
ticks: {
stepSize: 1,
display: false,
callback: function(value, index, values) {
return value.toFixed(1);
}
}
}
},
elements: {
line: {
borderWidth: 3
}
}
}
});
});
</script>