Poniżej jest moje rozwiązanie pierwszego i drugiego punktu zadania. Jest dość przewidywalne. Unikałem skracania kodu, więc powinno być w miarę zrozumiałe. Nowe elementy skomentowałem. Polecam przeanalizowanie kodu i samodzielne dodanie Bootstrapa (punkt 3).
App.jsx
import { WIDOCZKI } from './assets/data';
import { Box } from './components/Box';
import './App.css';
import { useState } from 'react';
import { Ranking } from './components/Ranking';
function App() {
// tworzę poszerzoneWidoczki jako stan i dodaję tam pole likes
//
// operator ...w kopiuje wszystkie pola obiektu w
// tworzy nowy obiekt
// nie przenosi referencji do starego obiektu
const [extWidoczki, setExtWidoczki] = useState(
WIDOCZKI.map(w => ({
...w,
likes: 0
}))
);
// akcja ma za zadanie po prostu powiększyć likes o 1
// likes jest jednak polem jednego z obiektów w tablicy extWidoczki
// więc najpierw wybieram właściwy obiekt item.id === id
// potem tworzę zmodyfikowany obiekt
const akcja = (id) => {
setExtWidoczki(items =>
items.map(item => {
if (item.id !== id) return item;
return { ...item, likes: item.likes + 1 };
})
);
};
return (
<>
<div className="grid">
{ extWidoczki.map(item => (
<Box
key={item.id}
nazwa={item.nazwa}
plik={item.plik}
opis={item.opis}
likes={item.likes}
setLikes={() => akcja(item.id)}
/>
))
}
<div className="box">
<h3>Ranking</h3>
<Ranking data={extWidoczki} />
</div>
</div>
</>
);
}
export default App;
Ranking.jsx
export function Ranking({data}){
return (
<>
{data
.slice()
.sort((a, b) => b.likes - a.likes)
.map(item => (
<div key={item.id}>
{item.nazwa}
</div>
))
}
</>
)
}
// slice() tworzy kopię
// bo sort() mutuje tablicę, a nie wolno mutować stanu Reacta
//
// (a, b) => b.likes - a.likes to funkcja porównującaBox.jsx
import './Box.css';
export function Box({ nazwa, plik, opis, likes, setLikes }) {
return (
<div className="box">
<img src={plik} alt={nazwa} />
<h3>{nazwa}</h3>
<p>
{opis}
<button onClick={setLikes}>Polub</button> {likes}
</p>
</div>
);
}Bootstrapowy szkielet do zadania 3
<!doctype html>
<html lang="pl">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Minimal Bootstrap</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container my-4">
<div class="row g-3">
<div class="col-12 col-md-6">
<div class="card p-3">Kafelek 1</div>
</div>
<div class="col-12 col-md-6">
<div class="card p-3">Kafelek 2</div>
</div>
<div class="col-12 col-md-6">
<div class="card p-3">Kafelek 3</div>
</div>
<div class="col-12 col-md-6">
<div class="card p-3">Kafelek 4</div>
</div>
</div>
</div>
</body>
</html>
tuff quest