From fb1fe3e16ce881c2cae3ddc6226d4ba314ed46ac Mon Sep 17 00:00:00 2001 From: isfaw1 <164429179+isfaw1@users.noreply.github.com> Date: Sun, 1 Jun 2025 22:04:43 +0100 Subject: [PATCH] Add files via upload --- AdminDashboard.js | 35 ++++++++ App.css | 184 ++++++++++++++++++++++++++++++++++++++++++ App.js | 97 ++++++++++++++++++++++ BatForm.js | 158 ++++++++++++++++++++++++++++++++++++ Dashboard.js | 52 ++++++++++++ OperateurDashboard.js | 39 +++++++++ QualiteDashboard.js | 15 ++++ firebase-config.js | 19 +++++ index.css | 20 +++++ index.js | 14 ++++ login.js | 70 ++++++++++++++++ logo.svg | 1 + 12 files changed, 704 insertions(+) create mode 100644 AdminDashboard.js create mode 100644 App.css create mode 100644 App.js create mode 100644 BatForm.js create mode 100644 Dashboard.js create mode 100644 OperateurDashboard.js create mode 100644 QualiteDashboard.js create mode 100644 firebase-config.js create mode 100644 index.css create mode 100644 index.js create mode 100644 login.js create mode 100644 logo.svg diff --git a/AdminDashboard.js b/AdminDashboard.js new file mode 100644 index 0000000..c5410ec --- /dev/null +++ b/AdminDashboard.js @@ -0,0 +1,35 @@ +import React from 'react'; +import logo from './assets/logo-tecpap.png'; + +function AdminDashboard({ onLogout }) { + return ( +
+
+
+ Logo de TECPAP + +
+ +

🎛️ Tableau de bord Administrateur

+

Bienvenue dans l’espace admin. Vous avez un accès complet à la gestion des utilisateurs, des documents BAT, et à la traçabilité.

+ + {/* Vous pouvez ajouter plus de fonctionnalités ou liens vers différentes sections du tableau de bord */} +
+
    +
  • +
  • +
  • +
+
+
+
+ ); +} + +export default AdminDashboard; diff --git a/App.css b/App.css new file mode 100644 index 0000000..09f42fd --- /dev/null +++ b/App.css @@ -0,0 +1,184 @@ +:root { + --primary-color: #218838; + --primary-dark-color: #1a6e2b; + --secondary-color: #007BFF; + --secondary-dark-color: #0056b3; + --danger-color: #dc3545; +} + +body { + margin: 0; + font-family: Arial, sans-serif; + background: + linear-gradient(rgba(0,0,0,0.3), rgba(0,0,0,0.3)), + url('./assets/slider-1.jpg'); /* Fixed path */ + background-size: cover; + background-position: center; + background-attachment: fixed; +} + +.auth-container { + display: flex; + justify-content: center; + align-items: flex-start; + min-height: 100vh; + padding: 40px 20px; + overflow-y: auto; + box-sizing: border-box; +} + +.auth-box { + background: + linear-gradient(rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0.3)), + url('./assets/slider-1.jpg'); /* Already correct */ + background-size: cover; + background-position: center; + background-attachment: fixed; + font-family: 'Segoe UI', Tahoma, sans-serif; +} + +.auth-box form { + display: flex; + flex-direction: column; + gap: 15px; + text-align: left; +} + +input, +select, +button { + padding: 12px; + border-radius: 6px; + border: 1px solid #ccc; + transition: background-color 0.3s ease-in-out, transform 0.2s ease-in-out; +} + +button { + background: var(--primary-color); + color: white; + cursor: pointer; +} + +button:hover { + background: var(--primary-dark-color); + transform: scale(1.05); +} + +.error-message { + color: #dc3545; + font-size: 0.9em; + font-weight: bold; + margin-top: 10px; + padding: 8px; + background: #f8d7da; + border: 1px solid #f5c6cb; + border-radius: 5px; +} + +/* Responsive Design */ +@media (max-width: 768px) { + .auth-box { + padding: 30px 20px; + max-width: 100%; + } + + .form-grid { + grid-template-columns: 1fr; + } + + .form-grid label, + .form-grid input, + .form-grid select { + grid-column: 1; + } +} + +@media (max-width: 480px) { + .auth-box { + padding: 20px; + } + + .form-grid { + grid-template-columns: 1fr; + } + + .form-grid label, + .form-grid input, + .form-grid select { + grid-column: 1; + } +} + +.error-message { + color: #dc3545; + background-color: #f8d7da; + padding: 10px; + border-radius: 5px; + margin-bottom: 20px; +} + +.success-message { + color: green; + font-weight: bold; + margin-top: 10px; +} + +.admin-box { + padding: 20px; + background-color: #f4f7fb; + border-radius: 8px; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); +} + +.dashboard-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 20px; +} + +.dashboard-header .logo { + width: 120px; +} + +.dashboard-subtitle { + font-size: 1.2em; + color: #333; + margin-top: 15px; +} + +.admin-functions ul { + list-style-type: none; + padding: 0; +} + +.admin-functions li { + margin: 10px 0; +} + +.admin-functions button { + padding: 10px 20px; + background-color: #218838; + color: white; + border: none; + border-radius: 5px; + cursor: pointer; + transition: background 0.3s; +} + +.admin-functions button:hover { + background-color: #1a6e2b; +} + +.logout-btn { + padding: 8px 15px; + background-color: #dc3545; + color: white; + border: none; + border-radius: 5px; + cursor: pointer; +} + +.logout-btn:hover { + background-color: #c82333; +} \ No newline at end of file diff --git a/App.js b/App.js new file mode 100644 index 0000000..c4ad111 --- /dev/null +++ b/App.js @@ -0,0 +1,97 @@ +import React, { useState } from 'react'; +import './App.css'; +import logo from './assets/logo-tecpap.png'; +import sliderImage from './assets/slider-1.jpg'; // Ajout de l'import +import { auth, db } from './firebase-config'; +import { signInWithEmailAndPassword, signOut } from 'firebase/auth'; +import { doc, getDoc } from 'firebase/firestore'; +import Login from './login'; +import AdminDashboard from './AdminDashboard'; +import QualiteDashboard from './QualiteDashboard'; +import OperateurDashboard from './OperateurDashboard'; + +function App() { + const [email, setEmail] = useState(''); + const [password, setPassword] = useState(''); + const [isLoggedIn, setIsLoggedIn] = useState(false); + const [role, setRole] = useState(''); + + const handleLogin = async (e) => { + e.preventDefault(); + try { + const userCredential = await signInWithEmailAndPassword(auth, email, password); + const uid = userCredential.user.uid; + + const userDoc = await getDoc(doc(db, 'users', uid)); + if (userDoc.exists()) { + const userData = userDoc.data(); + setRole(userData.role); + setIsLoggedIn(true); + } else { + alert("Aucun rôle trouvé pour cet utilisateur."); + } + } catch (error) { + alert(error.code === 'auth/user-not-found' ? "Utilisateur non trouvé" : "Erreur de connexion : " + error.message); + } + }; + + const handleLogout = async () => { + try { + await signOut(auth); + setEmail(''); + setPassword(''); + setIsLoggedIn(false); + setRole(''); + } catch (error) { + alert("Erreur lors de la déconnexion : " + error.message); + } + }; + + if (isLoggedIn) { + return ( +
+ {role === 'admin' && } + {role === 'qualite' && } + {role === 'operateur' && } + {!['admin', 'qualite', 'operateur'].includes(role) && ( +
+ TECPAP Logo +

Rôle inconnu

+

Ce rôle n’est pas reconnu.

+ +
+ )} +
+ ); + } + + return ( +
+
+ TECPAP Logo +

Connexion sécurisée

+
+ + setEmail(e.target.value)} + required + /> + + setPassword(e.target.value)} + required + /> + +
+
+
+ ); +} + +export default App; \ No newline at end of file diff --git a/BatForm.js b/BatForm.js new file mode 100644 index 0000000..9a73617 --- /dev/null +++ b/BatForm.js @@ -0,0 +1,158 @@ +import React, { useState } from 'react'; +import { db } from './firebase-config'; +import { collection, addDoc } from 'firebase/firestore'; +import './App.css'; + +function BatForm() { + const [formData, setFormData] = useState({ + commercial: '', + date: '', + client: '', + motif: '', + typeCommande: '', + format: '', + papier: '', + poignee: '', + couleurs: '', + pantone: '', + poses: '', + manchons: '', + machine: '', + fichier: null + }); + + const handleChange = (e) => { + const { name, value, files } = e.target; + if (name === "fichier") { + setFormData(prev => ({ ...prev, fichier: files[0] })); + } else { + setFormData(prev => ({ ...prev, [name]: value })); + } + }; + + const handleSubmit = async (e) => { + e.preventDefault(); + + try { + const { fichier, ...dataToSend } = formData; + await addDoc(collection(db, "bat"), dataToSend); + alert("✅ B.A.T enregistré avec succès !"); + setFormData({ + commercial: '', + date: '', + client: '', + motif: '', + typeCommande: '', + format: '', + papier: '', + poignee: '', + couleurs: '', + pantone: '', + poses: '', + manchons: '', + machine: '', + fichier: null + }); + } catch (error) { + alert("❌ Erreur : " + error.message); + } + }; + + return ( +
+

📄 Formulaire B.A.T

+
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ + +
+
+ ); +} + +export default BatForm; diff --git a/Dashboard.js b/Dashboard.js new file mode 100644 index 0000000..00dcfa6 --- /dev/null +++ b/Dashboard.js @@ -0,0 +1,52 @@ +import React from 'react'; +import BatList from './BatList'; + +function Dashboard({ user, onLogout }) { + if (!user) { + return

Utilisateur non trouvé, veuillez vous connecter.

; + } + + const { email, role } = user; + + // Fonction pour rendre le contenu en fonction du rôle + const renderContent = () => { + switch (role) { + case 'admin': + return ( +
+

Vous pouvez gérer les utilisateurs, consulter les statistiques globales et exporter les BAT.

+ {/* Ajouter plus de composants ou actions pour l'admin ici */} +
+ ); + case 'qualite': + return ( +
+

Vous pouvez valider les fiches BAT, effectuer des contrôles et suivre les non-conformités.

+ {/* Ajouter des actions spécifiques à la qualité ici */} +
+ ); + case 'operateur': + return ( +
+

Vous pouvez consulter les ordres de fabrication et suivre les étapes de production.

+ {/* Ajouter des actions spécifiques à l'opérateur ici */} +
+ ); + default: + return

Rôle non défini.

; + } + }; + + return ( +
+
+

Bienvenue, {email.split('@')[0]}

+

Rôle : {role}

+ {renderContent()} + +
+
+ ); +} + +export default Dashboard; diff --git a/OperateurDashboard.js b/OperateurDashboard.js new file mode 100644 index 0000000..c1967f7 --- /dev/null +++ b/OperateurDashboard.js @@ -0,0 +1,39 @@ +import React, { useState } from 'react'; +import logo from './assets/logo-tecpap.png'; +import BatForm from './BatForm'; +import './App.css'; + +function OperateurDashboard({ onLogout }) { + const [message, setMessage] = useState(''); // Gère les messages dynamiques + + const handleLogout = () => { + setMessage('Vous avez été déconnecté avec succès.'); + onLogout(); // Appel à la fonction de déconnexion + }; + + return ( +
+
+
+ Logo de TECPAP + +
+ +

🛠️ Espace Opérateur

+

Bienvenue, merci de compléter le formulaire BAT.

+ + {message &&

{message}

} {/* Affiche un message si nécessaire */} + + {/* Formulaire pour l'opérateur */} +
+
+ ); +} + +export default OperateurDashboard; diff --git a/QualiteDashboard.js b/QualiteDashboard.js new file mode 100644 index 0000000..59787a0 --- /dev/null +++ b/QualiteDashboard.js @@ -0,0 +1,15 @@ +import React from 'react'; +import logo from './assets/logo-tecpap.png'; + +function QualiteDashboard({ onLogout }) { + return ( +
+ TECPAP Logo +

📋 Espace Qualité

+

Bienvenue dans l’espace qualité. Accédez au contrôle BAT, check-lists de conformité, suivi des défauts, et validation finale.

+ +
+ ); +} + +export default QualiteDashboard; diff --git a/firebase-config.js b/firebase-config.js new file mode 100644 index 0000000..a69f27f --- /dev/null +++ b/firebase-config.js @@ -0,0 +1,19 @@ +// src/firebase-config.js +import { initializeApp } from "firebase/app"; +import { getAuth } from "firebase/auth"; +import { getFirestore } from "firebase/firestore"; + +const firebaseConfig = { + apiKey: "AIzaSyDkpEKKs9GR8SNxZxTy3wgOsdu7Ywlouu4", + authDomain: "tecpap-digital.firebaseapp.com", + projectId: "tecpap-digital", + storageBucket: "tecpap-digital.firebasestorage.app", + messagingSenderId: "1085503988391", + appId: "1:1085503988391:web:819f7cdfe0dffcc128b182" +}; +// Initialiser Firebase +const app = initializeApp(firebaseConfig); + +// Exporter les services +export const auth = getAuth(app); +export const db = getFirestore(app); diff --git a/index.css b/index.css new file mode 100644 index 0000000..224d436 --- /dev/null +++ b/index.css @@ -0,0 +1,20 @@ +/* Reset and global styles */ +*, +*::before, +*::after { + box-sizing: border-box; /* Simplifie le calcul des tailles */ + margin: 0; /* Supprime la marge par défaut */ +} + +body { + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; + -webkit-font-smoothing: antialiased; /* Améliore la lisibilité des polices sur MacOS */ + -moz-osx-font-smoothing: grayscale; /* Idem pour Firefox sur MacOS */ +} + +code { + font-family: 'Source Code Pro', Menlo, Monaco, Consolas, 'Courier New', monospace; + white-space: pre; /* Assurez-vous que l'espace blanc est respecté */ +} diff --git a/index.js b/index.js new file mode 100644 index 0000000..aaa9e53 --- /dev/null +++ b/index.js @@ -0,0 +1,14 @@ +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import './index.css'; // Votre CSS global +import App from './App'; // Composant principal de l'application + +// Récupération de l'élément root dans le fichier HTML +const root = ReactDOM.createRoot(document.getElementById('root')); + +// Rendu de l'application dans l'élément root +root.render( + + + +); diff --git a/login.js b/login.js new file mode 100644 index 0000000..e0f3c56 --- /dev/null +++ b/login.js @@ -0,0 +1,70 @@ +import React, { useState } from 'react'; +import './App.css'; +import logo from './assets/logo-tecpap.png'; // Ajoutez cet import +import { signInWithEmailAndPassword } from 'firebase/auth'; +import { doc, getDoc } from 'firebase/firestore'; +import { auth, db } from './firebase-config'; + +function Login({ onLogin }) { + const [email, setEmail] = useState(''); + const [password, setPassword] = useState(''); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + + const handleLogin = async (e) => { + e.preventDefault(); + setLoading(true); + setError(null); + + try { + const userCredential = await signInWithEmailAndPassword(auth, email, password); + const user = userCredential.user; + const userDoc = await getDoc(doc(db, 'users', user.uid)); + const role = userDoc.exists() ? userDoc.data().role : null; + + if (!role) { + setError("Aucun rôle défini pour cet utilisateur."); + setLoading(false); + return; + } + + onLogin(user, role); + } catch (error) { + setError("Erreur de connexion : " + error.message); + setLoading(false); + } + }; + + return ( +
+
+ TECPAP Logo +

Connexion sécurisée

+ {error &&
{error}
} +
+ + setEmail(e.target.value)} + required + /> + + setPassword(e.target.value)} + required + /> + +
+
+
+ ); +} + +export default Login; \ No newline at end of file diff --git a/logo.svg b/logo.svg new file mode 100644 index 0000000..9dfc1c0 --- /dev/null +++ b/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file