Skip to content

Commit b29c4c3

Browse files
Adding a list of comics; Ability to choose a certain comic;
1 parent 0977f6f commit b29c4c3

File tree

15 files changed

+295
-134
lines changed

15 files changed

+295
-134
lines changed

package-lock.json

Lines changed: 0 additions & 86 deletions
This file was deleted.

package.json

Lines changed: 0 additions & 5 deletions
This file was deleted.
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import { useState, useEffect } from 'react';
2+
import { Link } from 'react-router-dom';
3+
import noImage from '../../resources/img/no-image.jpg';
4+
5+
import useMarvelService from '../../services/MarvelService';
6+
import Spinner from '../spinner/Spinner';
7+
import ErrorMessage from '../errorMessage/ErrorMessage';
8+
9+
import './ComicsList.scss';
10+
11+
const ComicsList = () => {
12+
const [comicsList, setComicsList] = useState([]);
13+
const [newItemLoading, setnewItemLoading] = useState(false);
14+
const [offset, setOffset] = useState(0);
15+
const [comicsEnded, setComicsEnded] = useState(false);
16+
17+
const { loading, error, getAllComics } = useMarvelService();
18+
19+
useEffect(() => {
20+
onRequest(offset, true);
21+
}, []);
22+
23+
const onRequest = (offset, initial) => {
24+
initial ? setnewItemLoading(false) : setnewItemLoading(true);
25+
getAllComics(offset).then(onComicsListLoaded);
26+
};
27+
28+
const onComicsListLoaded = (newComicsList) => {
29+
let ended = false;
30+
if (newComicsList.length < 8) {
31+
ended = true;
32+
}
33+
setComicsList([...comicsList, ...newComicsList]);
34+
setnewItemLoading(false);
35+
setOffset(offset + 8);
36+
setComicsEnded(ended);
37+
};
38+
39+
function renderItems(arr) {
40+
const items = arr.map((item, i) => {
41+
return (
42+
<li className='comics__item' key={i}>
43+
<Link to={`/comics/${item.id}`}>
44+
<img
45+
src={
46+
item.thumbnail !==
47+
'http://i.annihil.us/u/prod/marvel/i/mg/b/40/image_not_available.jpg'
48+
? item.thumbnail
49+
: noImage
50+
}
51+
alt={item.title}
52+
className='comics__item-img'
53+
/>
54+
<div className='comics__item-name'>{item.title}</div>
55+
<div className='comics__item-price'>{item.price}</div>
56+
</Link>
57+
</li>
58+
);
59+
});
60+
61+
return <ul className='comics__flex'>{items}</ul>;
62+
}
63+
64+
const items = renderItems(comicsList);
65+
console.log(comicsList)
66+
67+
const errorMessage = error ? <ErrorMessage /> : null;
68+
const spinner = loading && !newItemLoading ? <Spinner /> : null;
69+
70+
return (
71+
<div className='comics__list'>
72+
{errorMessage}
73+
{spinner}
74+
{items}
75+
<button
76+
disabled={newItemLoading}
77+
style={{ display: comicsEnded ? 'none' : 'block' }}
78+
className='button button__main'
79+
onClick={() => onRequest(offset)}
80+
>
81+
<div className='inner'>load more</div>
82+
</button>
83+
</div>
84+
);
85+
};
86+
87+
export default ComicsList;
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
.comics {
2+
&__list {
3+
margin-top: 45px;
4+
padding-bottom: 50px;
5+
}
6+
7+
&__flex {
8+
display: flex;
9+
flex-wrap: wrap;
10+
max-width: 100%;
11+
justify-content:space-between;
12+
}
13+
14+
&__item {
15+
transition: 0.3s transform;
16+
width: 20%;
17+
margin: 20px;
18+
19+
&-img {
20+
box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.25);
21+
width: 300px;
22+
height: 345px;
23+
object-fit: cover;
24+
}
25+
26+
&-name {
27+
margin-top: 10px;
28+
font-weight: bold;
29+
font-size: 14px;
30+
line-height: 18px;
31+
}
32+
33+
&-price {
34+
margin-top: 5px;
35+
font-weight: bold;
36+
font-size: 14px;
37+
line-height: 18px;
38+
color: rgba(0, 0, 0, 0.6);
39+
text-transform: uppercase;
40+
}
41+
42+
&:hover {
43+
transform: translateY(-5px);
44+
}
45+
}
46+
}

project/src/components/SingleComic/SingleComic.js

Lines changed: 0 additions & 20 deletions
This file was deleted.

project/src/components/app/App.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ import { useState, React } from 'react';
22
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
33
import AppHeader from '../appHeader/AppHeader';
44
import MainPage from '../pages/MainPage';
5-
import ComicPage from '../pages/ComicPage';
5+
import NoMatch from '../pages/404';
6+
import ComicsList from '../ComicsList/ComicsList';
7+
import SinglePageComic from '../pages/SinglePageComic';
68
const App = () => {
79
return (
810
<Router>
@@ -14,8 +16,10 @@ const App = () => {
1416
</div>
1517
<main>
1618
<Routes>
17-
<Route path='/' element={<MainPage/>}></Route>
18-
<Route path='/comics' element={<ComicPage/>}></Route>
19+
<Route path='/' element={<MainPage />}></Route>
20+
<Route path='/comics' element={<ComicsList />}></Route>
21+
<Route path='/comics/:comicId' element={<SinglePageComic />}></Route>
22+
<Route path='*' element={<NoMatch/>}></Route>
1923
</Routes>
2024
</main>
2125
</div>

project/src/components/appHeader/AppHeader.scss

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
@import '../../style/variables.scss';
22

33
.app {
4-
height: 2000px;
54

65
&-wrapper {
76
background-color: $dark;

project/src/components/charInfo/CharInfo.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,22 @@ import ErrorMessage from '../errorMessage/ErrorMessage';
55
import Skelet from '../skelet/Skelet';
66
import noImage from '../../resources/img/no-image.jpg';
77
import PropTypes from 'prop-types';
8+
import { Link } from 'react-router-dom';
89
const CharInfo = (props) => {
910
const [loading, setLoading] = useState(false);
10-
const [error, setError] = useState(false);
1111

12-
const onCharInfoLoaded = () => setLoading(true);
1312
const onComicsloaded = (comics) => {
1413
const items = [];
1514
for (let item in comics) {
15+
16+
let link = `/comics/${comics[item].resourceURI.replace(
17+
'http://gateway.marvel.com/v1/public/comics/',
18+
''
19+
)}`;
20+
console.log(link)
1621
items.push(
1722
<li className='char__comics-item' key={comics[item].name}>
18-
<a href={comics[item].resourceURL}>{comics[item].name}</a>
23+
<Link to={link}>{comics[item].name}</Link>
1924
</li>
2025
);
2126
}
@@ -26,6 +31,7 @@ const CharInfo = (props) => {
2631
}, []);
2732

2833
const { name, description, thumbnail, wiki, homepage, comics } = props.char;
34+
console.log(comics);
2935
const skelet = loading ? <Skelet /> : null;
3036
return (
3137
<>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import React from 'react';
2+
import NoPage from '../../resources/img/404.png';
3+
const NoMatch = () => {
4+
return <div style={{display:'flex',justifyContent:'center',alignItems:'center'}}>
5+
<h1 style={{fontSize:'300px',fontWeight:'300'}}>404</h1>
6+
<h3 style={{fontSize:'50px',fontWeight:'300'}}>Not Found</h3>
7+
</div>;
8+
};
9+
export default NoMatch;

project/src/components/pages/ComicPage.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
import { React } from 'react';
2-
import SingleComic from '../SingleComic/SingleComic';
2+
import SingleCSinglePageComicomicPage from './SinglePageComic';
33
import AppBanner from '../AppBanner/AppBanner';
4+
import ErrorBoundary from '../ErrorBoundary/ErrorBoundary';
45

56
const ComicPage = () => {
67
return (
78
<>
8-
<AppBanner />
9-
<SingleComic />
9+
<ErrorBoundary>
10+
<AppBanner />
11+
<SinglePageComic />
12+
</ErrorBoundary>
1013
</>
1114
);
1215
};

0 commit comments

Comments
 (0)