diff options
-rw-r--r-- | package.json | 3 | ||||
-rw-r--r-- | src/components/AdCard.jsx | 13 | ||||
-rw-r--r-- | src/components/AdForm.jsx | 40 | ||||
-rw-r--r-- | src/components/Navbar.jsx | 14 | ||||
-rw-r--r-- | src/main.jsx | 29 | ||||
-rw-r--r-- | src/pages/Dashboard.jsx | 14 | ||||
-rw-r--r-- | src/pages/Login.jsx | 24 | ||||
-rw-r--r-- | src/pages/ManageAds.jsx | 35 | ||||
-rw-r--r-- | src/pages/Register.jsx | 21 | ||||
-rw-r--r-- | src/utils/api.js | 32 | ||||
-rw-r--r-- | yarn.lock | 20 |
11 files changed, 235 insertions, 10 deletions
diff --git a/package.json b/package.json index 056b32f..1c236c5 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ }, "dependencies": { "react": "^18.3.1", - "react-dom": "^18.3.1" + "react-dom": "^18.3.1", + "react-router-dom": "^6.25.1" }, "devDependencies": { "@types/react": "^18.3.3", diff --git a/src/components/AdCard.jsx b/src/components/AdCard.jsx new file mode 100644 index 0000000..6e854ed --- /dev/null +++ b/src/components/AdCard.jsx @@ -0,0 +1,13 @@ +import React from 'react'; + +const AdCard = ({ ad }) => { + return ( + <div> + <h2>{ad.title}</h2> + <p>{ad.description}</p> + <img src={ad.image} alt={ad.title} /> + </div> + ); +}; + +export default AdCard; diff --git a/src/components/AdForm.jsx b/src/components/AdForm.jsx new file mode 100644 index 0000000..3274803 --- /dev/null +++ b/src/components/AdForm.jsx @@ -0,0 +1,40 @@ +import React, { useState } from 'react'; + +const AdForm = ({ onAddAd }) => { + const [title, setTitle] = useState(''); + const [description, setDescription] = useState(''); + const [image, setImage] = useState(''); + + const handleSubmit = (e) => { + e.preventDefault(); + onAddAd({ title, description, image }); + setTitle(''); + setDescription(''); + setImage(''); + }; + + return ( + <form onSubmit={handleSubmit}> + <input + type="text" + placeholder="Title" + value={title} + onChange={(e) => setTitle(e.target.value)} + /> + <textarea + placeholder="Description" + value={description} + onChange={(e) => setDescription(e.target.value)} + /> + <input + type="text" + placeholder="Image URL" + value={image} + onChange={(e) => setImage(e.target.value)} + /> + <button type="submit">Add Ad</button> + </form> + ); +}; + +export default AdForm; diff --git a/src/components/Navbar.jsx b/src/components/Navbar.jsx new file mode 100644 index 0000000..9862d29 --- /dev/null +++ b/src/components/Navbar.jsx @@ -0,0 +1,14 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; + +const Navbar = () => { + return ( + <nav> + <Link to="/dashboard">Dashboard</Link> + <Link to="/manage-ads">Manage Ads</Link> + <Link to="/logout">Logout</Link> + </nav> + ); +}; + +export default Navbar; diff --git a/src/main.jsx b/src/main.jsx index 54b39dd..c4a8c39 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -1,10 +1,21 @@ -import React from 'react' -import ReactDOM from 'react-dom/client' -import App from './App.jsx' -import './index.css' +import React from 'react'; +import ReactDOM from 'react-dom'; +import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; +import './index.css'; +import App from './App'; +import Login from './pages/Login'; +import Register from './pages/Register'; +import Dashboard from './pages/Dashboard'; +import ManageAds from './pages/ManageAds'; -ReactDOM.createRoot(document.getElementById('root')).render( - <React.StrictMode> - <App /> - </React.StrictMode>, -) +ReactDOM.render( + <Router> + <Routes> + <Route path="/" element={<Login />} /> + <Route path="/register" element={<Register />} /> + <Route path="/dashboard" element={<Dashboard />} /> + <Route path="/manage-ads" element={<ManageAds />} /> + </Routes> + </Router>, + document.getElementById('root') +); diff --git a/src/pages/Dashboard.jsx b/src/pages/Dashboard.jsx new file mode 100644 index 0000000..ce3472e --- /dev/null +++ b/src/pages/Dashboard.jsx @@ -0,0 +1,14 @@ +import React from 'react'; +import Navbar from '../components/Navbar'; + +const Dashboard = () => { + return ( + <div> + <Navbar /> + <h1>Dashboard</h1> + {/* Add dashboard content here */} + </div> + ); +}; + +export default Dashboard; diff --git a/src/pages/Login.jsx b/src/pages/Login.jsx new file mode 100644 index 0000000..89e0c8b --- /dev/null +++ b/src/pages/Login.jsx @@ -0,0 +1,24 @@ +import React from 'react'; +import { useNavigate } from 'react-router-dom'; + +const Login = () => { + const navigate = useNavigate(); + + const handleLogin = () => { + // Handle login logic here + navigate('/dashboard'); + }; + + return ( + <div> + <h1>Login</h1> + <form onSubmit={handleLogin}> + <input type="text" placeholder="Username" /> + <input type="password" placeholder="Password" /> + <button type="submit">Login</button> + </form> + </div> + ); +}; + +export default Login; diff --git a/src/pages/ManageAds.jsx b/src/pages/ManageAds.jsx new file mode 100644 index 0000000..834a898 --- /dev/null +++ b/src/pages/ManageAds.jsx @@ -0,0 +1,35 @@ +import React, { useState, useEffect } from 'react'; +import AdCard from '../components/AdCard'; +import AdForm from '../components/AdForm'; +import { fetchAds, addAd } from '../utils/api'; + +const ManageAds = () => { + const [ads, setAds] = useState([]); + + useEffect(() => { + const getAds = async () => { + const adsData = await fetchAds(); + setAds(adsData); + }; + getAds(); + }, []); + + const handleAddAd = async (ad) => { + await addAd(ad); + setAds([...ads, ad]); + }; + + return ( + <div> + <h1>Manage Ads</h1> + <AdForm onAddAd={handleAddAd} /> + <div> + {ads.map((ad) => ( + <AdCard key={ad.id} ad={ad} /> + ))} + </div> + </div> + ); +}; + +export default ManageAds; diff --git a/src/pages/Register.jsx b/src/pages/Register.jsx new file mode 100644 index 0000000..84c0bf2 --- /dev/null +++ b/src/pages/Register.jsx @@ -0,0 +1,21 @@ +import React from 'react'; + +const Register = () => { + const handleRegister = (e) => { + e.preventDefault(); + // Handle registration logic here + }; + + return ( + <div> + <h1>Register</h1> + <form onSubmit={handleRegister}> + <input type="text" placeholder="Username" /> + <input type="password" placeholder="Password" /> + <button type="submit">Register</button> + </form> + </div> + ); +}; + +export default Register; diff --git a/src/utils/api.js b/src/utils/api.js new file mode 100644 index 0000000..1f8e92d --- /dev/null +++ b/src/utils/api.js @@ -0,0 +1,32 @@ +const API_URL = 'http://localhost:5000'; // Replace with your actual API URL + +export const fetchAds = async () => { + try { + const response = await fetch(`${API_URL}/ads`); + if (!response.ok) { + throw new Error('Network response was not ok'); + } + return await response.json(); + } catch (error) { + console.error('Error fetching ads:', error); + return []; + } +}; + +export const addAd = async (ad) => { + try { + const response = await fetch(`${API_URL}/ads`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(ad), + }); + if (!response.ok) { + throw new Error('Network response was not ok'); + } + return await response.json(); + } catch (error) { + console.error('Error adding ad:', error); + } +}; @@ -189,6 +189,11 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@remix-run/router@1.18.0": + version "1.18.0" + resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.18.0.tgz#20b033d1f542a100c1d57cfd18ecf442d1784732" + integrity sha512-L3jkqmqoSVBVKHfpGZmLrex0lxR5SucGA0sUfFzGctehw+S/ggL9L/0NnC5mw6P8HUWpFZ3nQw3cRApjjWx9Sw== + "@rollup/rollup-android-arm-eabi@4.19.0": version "4.19.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.19.0.tgz#3d9fd50164b94964f5de68c3c4ce61933b3a338d" @@ -1604,6 +1609,21 @@ react-is@^16.13.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== +react-router-dom@^6.25.1: + version "6.25.1" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.25.1.tgz#b89f8d63fc8383ea4e89c44bf31c5843e1f7afa0" + integrity sha512-0tUDpbFvk35iv+N89dWNrJp+afLgd+y4VtorJZuOCXK0kkCWjEvb3vTJM++SYvMEpbVwXKf3FjeVveVEb6JpDQ== + dependencies: + "@remix-run/router" "1.18.0" + react-router "6.25.1" + +react-router@6.25.1: + version "6.25.1" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.25.1.tgz#70b4f1af79954cfcfd23f6ddf5c883e8c904203e" + integrity sha512-u8ELFr5Z6g02nUtpPAggP73Jigj1mRePSwhS/2nkTrlPU5yEkH1vYzWNyvSnSzeeE2DNqWdH+P8OhIh9wuXhTw== + dependencies: + "@remix-run/router" "1.18.0" + react@^18.3.1: version "18.3.1" resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891" |