Skip to content

h #8

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open

h #8

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link
href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
rel="stylesheet"
/>
<link rel="icon" type="icon" href="/4geeks.ico" />
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css" integrity="sha512-SnH5WK+bZxgPHs44uWIX+LLJAJ9/2PkPKZ5QiAj6Ta86w+fsb2TkcmfRyVX3pBnMFcV7oQPJkl9QevSCWr3W6A==" crossorigin="anonymous" referrerpolicy="no-referrer" />
Expand Down
324 changes: 302 additions & 22 deletions package-lock.json

Large diffs are not rendered by default.

9 changes: 6 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@
"preview": "vite preview"
},
"dependencies": {
"bootstrap": "^5.3.7",
"prop-types": "^15.8.1",
"react": "^18.2.0",
"react-bootstrap": "^2.10.10",
"react-dom": "^18.2.0",
"react-router-dom": "^6.18.0"
"react-router-bootstrap": "^0.26.3",
"react-router-dom": "^6.30.1"
},
"devDependencies": {
"@types/react": "^18.2.18",
Expand All @@ -27,6 +30,6 @@
"vite": "^4.4.8"
},
"engines": {
"node": ">=20.0.0"
}
"node": ">=20.0.0"
}
}
46 changes: 46 additions & 0 deletions src/components/CardItem.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React, { useContext } from "react";
import { Link } from "react-router-dom";
import { Context } from "../store.jsx";

const CardItem = ({ item, type }) => {
const { actions, store } = useContext(Context);

const isFavorite = store.favorites.some(fav => fav.uid === item.uid && fav.type === type);

// URL imagen basada en starwars-visualguide.com
const imageURL = `https://starwars-visualguide.com/assets/img/${type === "people" ? "characters" : type}/${item.uid}.jpg`;

return (
<div className="card h-100 shadow-sm">
<img
src={imageURL}
className="card-img-top"
alt={item.name}
onError={(e) => e.target.src = "https://starwars-visualguide.com/assets/img/big-placeholder.jpg"}
/>
<div className="card-body d-flex flex-column">
<h5 className="card-title">{item.name}</h5>
<div className="mt-auto d-flex justify-content-between align-items-center">
<Link to={`/single/${type}/${item.uid}`} className="btn btn-primary btn-sm">
Learn More
</Link>
<button
className={`btn btn-sm ${isFavorite ? "btn-danger" : "btn-outline-warning"}`}
onClick={() => {
if (isFavorite) {
actions.removeFavorite(item.uid, type);
} else {
actions.addFavorite({ ...item, type });
}
}}
>
{isFavorite ? "Remove Favorite" : "Add Favorite"}
</button>
</div>
</div>
</div>
);
};

export default CardItem;

20 changes: 9 additions & 11 deletions src/components/Footer.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
export const Footer = () => (
<footer className="footer mt-auto py-3 text-center">
<p>
Check the <a target="_blank" href="https://4geeks.com/docs/start/start-react-advanced-project">template documentation</a> <i className="fa-solid fa-file"></i> for help.
</p>
<p>
Made with <i className="fa fa-heart text-danger" /> by{" "}
<a href="http://www.4geeksacademy.com">4Geeks Academy</a>
</p>
</footer>
);
import React from "react";

const Footer = () => (
<footer className="bg-dark text-white text-center py-3 mt-auto">
<p className="mb-0">Made with ❤️ by 4Geeks Academy</p>
</footer>
);

export default Footer;
66 changes: 50 additions & 16 deletions src/components/Navbar.jsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,53 @@
import React, { useContext, useState } from "react";
import { Context } from "../store.jsx";
import { Link } from "react-router-dom";

export const Navbar = () => {
const Navbar = () => {
const { store, actions } = useContext(Context);
const [showDropdown, setShowDropdown] = useState(false);

return (
<nav className="navbar navbar-light bg-light">
<div className="container">
<Link to="/">
<span className="navbar-brand mb-0 h1">React Boilerplate</span>
</Link>
<div className="ml-auto">
<Link to="/demo">
<button className="btn btn-primary">Check the Context in action</button>
</Link>
</div>
</div>
</nav>
);
};
return (
<nav className="navbar navbar-dark bg-dark px-4">
<Link to="/" className="navbar-brand">
StarWars Blog
</Link>
<div className="dropdown">
<button
className="btn btn-warning dropdown-toggle"
onClick={() => setShowDropdown(!showDropdown)}
>
Favorites ({store.favorites.length})
</button>
{showDropdown && (
<div className="dropdown-menu dropdown-menu-end show">
{store.favorites.length === 0 ? (
<span className="dropdown-item">No favorites</span>
) : (
store.favorites.map((fav, index) => (
<div
key={index}
className="dropdown-item d-flex justify-content-between align-items-center"
>
<Link
to={`/details/${fav.type}/${fav.uid}`}
className="text-decoration-none"
>
{fav.name}
</Link>
<button
className="btn btn-sm btn-outline-danger ms-2"
onClick={() => actions.removeFavorite(fav.uid, fav.type)}
>
</button>
</div>
))
)}
</div>
)}
</div>
</nav>
);
};

export default Navbar;
Empty file removed src/index.css
Empty file.
33 changes: 13 additions & 20 deletions src/main.jsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,15 @@
import React from 'react'
import ReactDOM from 'react-dom/client'
import './index.css' // Global styles for your application
import { RouterProvider } from "react-router-dom"; // Import RouterProvider to use the router
import { router } from "./routes"; // Import the router configuration
import { StoreProvider } from './hooks/useGlobalReducer'; // Import the StoreProvider for global state management
import React from "react";
import ReactDOM from "react-dom/client";
import { BrowserRouter } from "react-router-dom";
import { StoreProvider } from "./store.jsx";
import { router } from "./routes.jsx"; // Importa el router configurado

const Main = () => {
return (
<React.StrictMode>
{/* Provide global state to all components */}
<StoreProvider>
{/* Set up routing for the application */}
<RouterProvider router={router}>
</RouterProvider>
</StoreProvider>
</React.StrictMode>
);
}
import { RouterProvider } from "react-router-dom";

// Render the Main component into the root DOM element.
ReactDOM.createRoot(document.getElementById('root')).render(<Main />)
ReactDOM.createRoot(document.getElementById("root")).render(
<React.StrictMode>
<StoreProvider>
<RouterProvider router={router} />
</StoreProvider>
</React.StrictMode>
);
43 changes: 0 additions & 43 deletions src/pages/Demo.jsx

This file was deleted.

50 changes: 37 additions & 13 deletions src/pages/Home.jsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,40 @@
import rigoImageUrl from "../assets/img/rigo-baby.jpg";
import useGlobalReducer from "../hooks/useGlobalReducer.jsx";
import React, { useContext } from "react";
import { Context } from "../store.jsx";
import CardItem from "../components/CardItem.jsx";

export const Home = () => {
const Home = () => {
const { store } = useContext(Context);

const {store, dispatch} =useGlobalReducer()
return (
<div className="container mt-4">
<h2 className="text-warning">Characters</h2>
<div className="row">
{store.people.map(person => (
<div key={person.uid} className="col-12 col-sm-6 col-md-4 col-lg-3 mb-3">
<CardItem item={person} type="people" />
</div>
))}
</div>

return (
<div className="text-center mt-5">
<h1>Hello Rigo!!</h1>
<p>
<img src={rigoImageUrl} />
</p>
</div>
);
};
<h2 className="mt-5 text-success">Planets</h2>
<div className="row">
{store.planets.map(planet => (
<div key={planet.uid} className="col-12 col-sm-6 col-md-4 col-lg-3 mb-3">
<CardItem item={planet} type="planets" />
</div>
))}
</div>

<h2 className="mt-5 text-info">Vehicles</h2>
<div className="row">
{store.vehicles.map(vehicle => (
<div key={vehicle.uid} className="col-12 col-sm-6 col-md-4 col-lg-3 mb-3">
<CardItem item={vehicle} type="vehicles" />
</div>
))}
</div>
</div>
);
};

export default Home;
31 changes: 17 additions & 14 deletions src/pages/Layout.jsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import { Outlet } from "react-router-dom/dist"
import ScrollToTop from "../components/ScrollToTop"
import { Navbar } from "../components/Navbar"
import { Footer } from "../components/Footer"
import React from "react";
import { Outlet } from "react-router-dom";
import Navbar from "../components/Navbar.jsx";
import Footer from "../components/Footer.jsx";

// Base component that maintains the navbar and footer throughout the page and the scroll to top functionality.
export const Layout = () => {
return (
<ScrollToTop>
<Navbar />
<Outlet />
<Footer />
</ScrollToTop>
)
}
const Layout = () => {
return (
<>
<Navbar />
<div style={{ minHeight: "80vh" }}>
<Outlet />
</div>
<Footer />
</>
);
};

export default Layout;
Loading