0% found this document useful (0 votes)
13 views16 pages

Children Table

The document outlines a React application structure for a Children Management system, including components for authentication (Register and Login) and children management. It features routing with protected routes, user authentication via JWT, and CRUD operations for managing children's information. The application also includes a server-side implementation using Express and MySQL for user registration and login functionalities.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
13 views16 pages

Children Table

The document outlines a React application structure for a Children Management system, including components for authentication (Register and Login) and children management. It features routing with protected routes, user authentication via JWT, and CRUD operations for managing children's information. The application also includes a server-side implementation using Express and MySQL for user registration and login functionalities.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 16

src/

├── components/

│ ├── Auth/

│ │ ├── Register.jsx

│ │ ├── Login.jsx

│ │ └── index.jsx

│ └── ChildrenManagement.jsx

├── App.jsx

└── main.jsx

APP.JSX

// src/App.js

import React from 'react';


import { BrowserRouter as Router, Routes, Route, Navigate, Link } from
'react-router-dom';
import Register from './components/Auth/Register.jsx';
import Login from './components/Auth/Login.jsx';
import ChildrenManagement from './components/ChildrenManagement';

// Protected Route Component


const ProtectedRoute = ({ children }) => {
const token = localStorage.getItem('token');
if (!token) {
return <Navigate to="/login" />;
}
return children;
};

// Navigation Component
const Navigation = () => {
const token = localStorage.getItem('token');

const handleLogout = () => {


localStorage.removeItem('token');
localStorage.removeItem('userId');
window.location.href = '/login';
};

return (
<nav className="bg-gray-800 text-white p-4">
<div className="max-w-6xl mx-auto flex justify-between items-
center">
<Link to="/" className="text-xl font-bold">
Children Manager
</Link>
<div className="space-x-4">
{!token ? (
<>
<Link to="/login" className="hover:text-gray-300">
Login
</Link>
<Link to="/register" className="hover:text-gray-300">
Register
</Link>
</>
) : (
<>
<Link to="/children" className="hover:text-gray-300">
Children
</Link>
<button
onClick={handleLogout}
className="hover:text-gray-300"
>
Logout
</button>
</>
)}
</div>
</div>
</nav>
);
};

// Home Component
const Home = () => {
return (
<div className="max-w-4xl mx-auto mt-10 p-6 text-center">
<h1 className="text-4xl font-bold mb-4">Welcome to Children
Manager</h1>
<p className="text-xl text-gray-600 mb-8">
Manage your children's information easily and securely.
</p>
{!localStorage.getItem('token') && (
<div className="space-x-4">
<Link
to="/register"
className="bg-blue-500 text-white px-6 py-2 rounded hover:bg-
blue-600"
>
Get Started
</Link>
<Link
to="/login"
className="bg-gray-500 text-white px-6 py-2 rounded hover:bg-
gray-600"
>
Login
</Link>
</div>
)}
</div>
);
};

// Main App Component


const App = () => {
return (
<Router>
<div className="min-h-screen bg-gray-100">
<Navigation />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/register" element={<Register />} />
<Route path="/login" element={<Login />} />
<Route
path="/children"
element={
<ProtectedRoute>
<ChildrenManagement />
</ProtectedRoute>
}
/>
</Routes>
</div>
</Router>
);
};

export default App;

MAIN.JSX

// src/main.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';

// Include Tailwind CSS


import 'tailwindcss/tailwind.css';

const root = ReactDOM.createRoot(document.getElementById('root'));


root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);

ChildrenManagement.jsx

// src/components/ChildrenManagement.js

import React, { useState, useEffect } from 'react';


import axios from 'axios';

const ChildrenManagement = () => {


const [children, setChildren] = useState([]);
const [newChild, setNewChild] = useState('');
const [editingChild, setEditingChild] = useState(null);
const [error, setError] = useState('');
const [loading, setLoading] = useState(true);
const [successMessage, setSuccessMessage] = useState('');

const token = localStorage.getItem('token');


const axiosConfig = {
headers: { Authorization: `Bearer ${token}` }
};

useEffect(() => {
fetchChildren();
}, []);

const fetchChildren = async () => {


try {
setLoading(true);
const response = await
axios.get('http://localhost:5000/api/children', axiosConfig);
setChildren(response.data);
setError('');
} catch (err) {
setError('Failed to fetch children');
} finally {
setLoading(false);
}
};

const addChild = async (e) => {


e.preventDefault();
if (!newChild.trim()) {
setError("Child's name cannot be empty");
return;
}
try {
await axios.post('http://localhost:5000/api/children',
{ children_name: newChild },
axiosConfig
);
setNewChild('');
setSuccessMessage('Child added successfully!');
setTimeout(() => setSuccessMessage(''), 3000);
fetchChildren();
} catch (err) {
setError('Failed to add child');
}
};
const updateChild = async (id, newName) => {
if (!newName.trim()) {
setError("Child's name cannot be empty");
return;
}
try {
await axios.put(`http://localhost:5000/api/children/${id}`,
{ children_name: newName },
axiosConfig
);
setEditingChild(null);
setSuccessMessage('Child updated successfully!');
setTimeout(() => setSuccessMessage(''), 3000);
fetchChildren();
} catch (err) {
setError('Failed to update child');
}
};

const deleteChild = async (id) => {


if (window.confirm('Are you sure you want to delete this child?')) {
try {
await axios.delete(`http://localhost:5000/api/children/${id}`,
axiosConfig);
setSuccessMessage('Child deleted successfully!');
setTimeout(() => setSuccessMessage(''), 3000);
fetchChildren();
} catch (err) {
setError('Failed to delete child');
}
}
};

const handleKeyPress = (e, id, name) => {


if (e.key === 'Enter') {
updateChild(id, name);
} else if (e.key === 'Escape') {
setEditingChild(null);
}
};

if (loading) {
return (
<div className="max-w-2xl mx-auto mt-10 p-6 bg-white rounded-lg
shadow-lg">
<div className="text-center text-gray-600">Loading...</div>
</div>
);
}

return (
<div className="max-w-2xl mx-auto mt-10 p-6 bg-white rounded-lg
shadow-lg">
<h2 className="text-2xl font-bold mb-6">Children Management</h2>
{error && <div className="text-red-500 mb-4 p-2 bg-red-50
rounded">{error}</div>}
{successMessage && (
<div className="text-green-500 mb-4 p-2 bg-green-50
rounded">{successMessage}</div>
)}

{/* Add Child Form */}


<form onSubmit={addChild} className="mb-6">
<div className="flex gap-2">
<input
type="text"
placeholder="Child's Name"
className="flex-1 p-2 border rounded"
value={newChild}
onChange={(e) => setNewChild(e.target.value)}
/>
<button
type="submit"
className="bg-green-500 text-white px-4 py-2 rounded
hover:bg-green-600 transition duration-200"
>
Add Child
</button>
</div>
</form>

{/* Children List */}


<div className="space-y-4">
{children.length === 0 ? (
<div className="text-center text-gray-500 py-4">
No children added yet. Add your first child above!
</div>
) : (
children.map((child) => (
<div key={child.id} className="flex items-center justify-
between p-4 border rounded hover:bg-gray-50">
{editingChild === child.id ? (
<input
type="text"
className="flex-1 p-2 border rounded mr-2"
value={child.children_name}
onChange={(e) => {
const updatedChildren = children.map(c =>
c.id === child.id ? { ...c, children_name:
e.target.value } : c
);
setChildren(updatedChildren);
}}
onBlur={() => updateChild(child.id,
child.children_name)}
onKeyDown={(e) => handleKeyPress(e, child.id,
child.children_name)}
autoFocus
/>
) : (
<div>
<span className="font-
medium">#{child.children_number}</span>
<span className="ml-4">{child.children_name}</span>
</div>
)}

<div className="flex gap-2">


<button
onClick={() => setEditingChild(child.id)}
className="bg-blue-500 text-white px-3 py-1 rounded
hover:bg-blue-600 transition duration-200"
>
Edit
</button>
<button
onClick={() => deleteChild(child.id)}
className="bg-red-500 text-white px-3 py-1 rounded
hover:bg-red-600 transition duration-200"
>
Delete
</button>
</div>
</div>
))
)}
</div>
</div>
);
};

export default ChildrenManagement;

index.jsx

// src/components/Auth/index.js
export { default as Register } from './Register';
export { default as Login } from './Login';

Login.jsx
// src/components/Auth/Login.js
import React, { useState } from 'react';
import axios from 'axios';
import { useNavigate } from 'react-router-dom';

const Login = () => {


const [formData, setFormData] = useState({
email: '',
password: ''
});
const [error, setError] = useState('');
const navigate = useNavigate();

const handleSubmit = async (e) => {


e.preventDefault();
try {
const response = await
axios.post('http://localhost:5000/api/login', formData);
localStorage.setItem('token', response.data.token);
localStorage.setItem('userId', response.data.userId);
navigate('/children');
} catch (err) {
setError(err.response?.data?.error || 'Login failed');
}
};

return (
<div className="max-w-md mx-auto mt-10 p-6 bg-white rounded-lg
shadow-lg">
<h2 className="text-2xl font-bold mb-6">Login</h2>
{error && <div className="text-red-500 mb-4">{error}</div>}
<form onSubmit={handleSubmit}>
<div className="mb-4">
<input
type="email"
placeholder="Email"
className="w-full p-2 border rounded"
value={formData.email}
onChange={(e) => setFormData({...formData, email:
e.target.value})}
/>
</div>
<div className="mb-4">
<input
type="password"
placeholder="Password"
className="w-full p-2 border rounded"
value={formData.password}
onChange={(e) => setFormData({...formData, password:
e.target.value})}
/>
</div>
<button
type="submit"
className="w-full bg-blue-500 text-white p-2 rounded hover:bg-
blue-600"
>
Login
</button>
</form>
</div>
);
};
export default Login;

Register.jsx
// src/components/Auth/Register.js
import React, { useState } from 'react';
import axios from 'axios';
import { useNavigate } from 'react-router-dom';

const Register = () => {


const [formData, setFormData] = useState({
username: '',
email: '',
password: ''
});
const [error, setError] = useState('');
const navigate = useNavigate();

const handleSubmit = async (e) => {


e.preventDefault();
try {
await axios.post('http://localhost:5000/api/register', formData);
navigate('/login');
} catch (err) {
setError(err.response?.data?.error || 'Registration failed');
}
};

return (
<div className="max-w-md mx-auto mt-10 p-6 bg-white rounded-lg
shadow-lg">
<h2 className="text-2xl font-bold mb-6">Register</h2>
{error && <div className="text-red-500 mb-4">{error}</div>}
<form onSubmit={handleSubmit}>
<div className="mb-4">
<input
type="text"
placeholder="Username"
className="w-full p-2 border rounded"
value={formData.username}
onChange={(e) => setFormData({...formData, username:
e.target.value})}
/>
</div>
<div className="mb-4">
<input
type="email"
placeholder="Email"
className="w-full p-2 border rounded"
value={formData.email}
onChange={(e) => setFormData({...formData, email:
e.target.value})}
/>
</div>
<div className="mb-4">
<input
type="password"
placeholder="Password"
className="w-full p-2 border rounded"
value={formData.password}
onChange={(e) => setFormData({...formData, password:
e.target.value})}
/>
</div>
<button
type="submit"
className="w-full bg-blue-500 text-white p-2 rounded hover:bg-
blue-600"
>
Register
</button>
</form>
</div>
);
};

export default Register;


server.js
const express = require('express');
const mysql = require('mysql2');
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const cors = require('cors');

const app = express();


app.use(express.json());
app.use(cors());

const db = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'testdb'
});

// User Registration
app.post('/api/register', async (req, res) => {
try {
const { username, email, password } = req.body;
const hashedPassword = await bcrypt.hash(password, 10);

const query = 'INSERT INTO users (username, email, password)


VALUES (?, ?, ?)';
db.query(query, [username, email, hashedPassword], (err, result)
=> {
if (err) {
return res.status(400).json({ error: 'Username or email
already exists' });
}
res.status(201).json({ message: 'User registered
successfully' });
});
} catch (error) {
res.status(500).json({ error: 'Server error' });
}
});

// User Login
app.post('/api/login', async (req, res) => {
try {
const { email, password } = req.body;
const query = 'SELECT * FROM users WHERE email = ?';

db.query(query, [email], async (err, results) => {


if (err || results.length === 0) {
return res.status(401).json({ error: 'Invalid
credentials' });
}

const user = results[0];


const validPassword = await bcrypt.compare(password,
user.password);

if (!validPassword) {
return res.status(401).json({ error: 'Invalid
credentials' });
}

const token = jwt.sign({ userId: user.id },


'your_jwt_secret', { expiresIn: '24h' });
res.json({ token, userId: user.id });
});
} catch (error) {
res.status(500).json({ error: 'Server error' });
}
});

// Middleware to verify JWT token


const authenticateToken = (req, res, next) => {
const token = req.headers.authorization?.split(' ')[1];
if (!token) return res.status(401).json({ error: 'Access denied' });

jwt.verify(token, 'your_jwt_secret', (err, user) => {


if (err) return res.status(403).json({ error: 'Invalid token' });
req.user = user;
next();
});
};

// Get all children for a user


app.get('/api/children', authenticateToken, (req, res) => {
const query = 'SELECT * FROM children WHERE user_id = ? ORDER BY
children_number';
db.query(query, [req.user.userId], (err, results) => {
if (err) return res.status(500).json({ error: 'Server error' });
res.json(results);
});
});

// Add a new child


app.post('/api/children', authenticateToken, (req, res) => {
const { children_name } = req.body;

// Get the next children_number


db.query(
'SELECT MAX(children_number) as max_num FROM children WHERE
user_id = ?',
[req.user.userId],
(err, results) => {
if (err) return res.status(500).json({ error: 'Server
error' });

const nextNumber = (results[0].max_num || 0) + 1;

const query = 'INSERT INTO children (user_id, children_name,


children_number) VALUES (?, ?, ?)';
db.query(query, [req.user.userId, children_name, nextNumber],
(err, result) => {
if (err) return res.status(500).json({ error: 'Server
error' });
res.status(201).json({ id: result.insertId,
children_number: nextNumber });
});
}
);
});

// Update a child
app.put('/api/children/:id', authenticateToken, (req, res) => {
const { children_name } = req.body;
const query = 'UPDATE children SET children_name = ? WHERE id = ? AND
user_id = ?';
db.query(query, [children_name, req.params.id, req.user.userId],
(err, result) => {
if (err) return res.status(500).json({ error: 'Server error' });
if (result.affectedRows === 0) return res.status(404).json({
error: 'Child not found' });
res.json({ message: 'Child updated successfully' });
});
});
// Delete a child
app.delete('/api/children/:id', authenticateToken, (req, res) => {
const query = 'DELETE FROM children WHERE id = ? AND user_id = ?';
db.query(query, [req.params.id, req.user.userId], (err, result) => {
if (err) return res.status(500).json({ error: 'Server error' });
if (result.affectedRows === 0) return res.status(404).json({
error: 'Child not found' });
res.json({ message: 'Child deleted successfully' });
});
});

const PORT = process.env.PORT || 5000;


app.listen(PORT, () => console.log(`Server running on port ${PORT}`));

You might also like