Skip to content
Open
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
1 change: 0 additions & 1 deletion .eslintignore

This file was deleted.

63 changes: 0 additions & 63 deletions .eslintrc.js

This file was deleted.

19 changes: 0 additions & 19 deletions .prettierrc

This file was deleted.

54 changes: 54 additions & 0 deletions Rick-and-morty.postman_collection
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
{
"info": {
"_postman_id": "d874b8b8-3eaa-4a7c-9f74-fc3aaaae1e2b",
"name": "New Collection",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"item": [
{
"name": "New Request",
"request": {
"method": "GET",
"header": [],
"url": null
},
"response": []
},
{
"name": "New Request",
"request": {
"method": "GET",
"header": [],
"url": null
},
"response": []
},
{
"name": "New Request",
"request": {
"method": "GET",
"header": [],
"url": null
},
"response": []
},
{
"name": "New Request",
"request": {
"method": "GET",
"header": [],
"url": null
},
"response": []
},
{
"name": "New Request",
"request": {
"method": "GET",
"header": [],
"url": null
},
"response": []
}
]
}
30 changes: 0 additions & 30 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,28 +29,8 @@
"@babel/plugin-syntax-jsx": "^7.12.13",
"@babel/preset-env": "^7.13.10",
"@babel/preset-react": "^7.12.13",
"@html-eslint/eslint-plugin": "^0.8.0",
"@html-eslint/parser": "^0.8.0",
"@typescript-eslint/eslint-plugin": "^4.17.0",
"@typescript-eslint/parser": "^4.17.0",
"cross-env": "^7.0.3",
"eslint": "^7.21.0",
"eslint-config-airbnb": "^18.2.1",
"eslint-config-airbnb-babel": "^0.2.1",
"eslint-config-prettier": "^8.1.0",
"eslint-plugin-babel": "^5.3.1",
"eslint-plugin-compat": "^3.9.0",
"eslint-plugin-html": "^6.1.2",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-jest": "^24.2.1",
"eslint-plugin-jsx-a11y": "^6.4.1",
"eslint-plugin-markdown": "^2.0.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-react": "^7.22.0",
"eslint-plugin-react-hooks": "^4.2.0",
"eslint-plugin-testing-library": "^3.10.1",
"jest": "^26.6.0",
"prettier": "^2.2.1",
"typescript": "^4.2.3"
},
"scripts": {
Expand All @@ -61,18 +41,8 @@
"test:watch": "react-scripts test --watchAll",
"test:ci:all": "cross-env CI=true react-scripts test --all --env=jsdom",
"test:related": "cross-env CI=true react-scripts test --bail --findRelatedTests --env=jsdom",
"lint:js": "eslint . --ext .js",
"lint:js:fix": "npm run lint:js -- --fix",
"lint:format": "prettier --write .",
"lint:format:check": "prettier --check .",
"pre:push": "npm run lint:js && npm run lint:format:check && npm run test:ci:all"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
Expand Down
27 changes: 27 additions & 0 deletions src/Api/Api.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import axios from "axios";

export function makeApi() {
return axios.create({
baseURL: "https://rickandmortyapi.com/api",
});
}

export function getEpisodes(page = 1, api = makeApi()) {
return api.get(`/episode?page=${page}`);
}

export function getEpisode(episodeId, api = makeApi()) {
return api.get(`/episode/${episodeId}`);
}

export function getUrl(url, api = makeApi()) {
return api.get(url);
}

export function getLocation(locationId, api = makeApi()) {
return api.get(`/location/${locationId}`);
}

export function getCharacter(characterId, api = makeApi()) {
return api.get(`/character/${characterId}`);
}
1 change: 1 addition & 0 deletions src/Api/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./Api"
25 changes: 23 additions & 2 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,30 @@
import React from "react";
import { Switch, Route } from "react-router-dom";

import { EPISODE, HOME, LOCATION, CHARACTER } from "./constants/routes";
import Home from "./pages/Home";
import Episode from "./pages/Episode";
import Location from "./pages/Location";
import Character from "./pages/Character";

function App() {
return <Home />;
return (
<Switch>
<Route
path={`${EPISODE}/:episodeId`}
render={(routeProps) => <Episode {...routeProps} />}
/>
<Route
path={`${CHARACTER}/:characterId`}
render={(routeProps) => <Character {...routeProps} />}
/>
<Route
path={`${LOCATION}/:locationId`}
render={(routeProps) => <Location {...routeProps} />}
/>
<Route path={HOME} render={(routeProps) => <Home {...routeProps} />} />
</Switch>
);
}

export default App;
export default App;
7 changes: 4 additions & 3 deletions src/components/CharacterCard/CharacterCard.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import "./CharacterCard.scss";

import * as routes from "../../constants/routes";

function CharacterCard({ id, name, image, species, status, origin, location }) {
function CharacterCard({ id, name, image, status, location }) {
const locationId = location.url.split("/").pop();
return (
<div className="col col-12 col-sm-6 col-xl-3 CharacterCard">
<img className="CharacterCard__img" src={image} alt="" />
Expand All @@ -15,9 +16,9 @@ function CharacterCard({ id, name, image, species, status, origin, location }) {
<div className="CharacterCard__meta">
<Link
className="CharacterCard__meta-item"
to={`${routes.LOCATION}/${id}`}
to={`${routes.LOCATION}/${locationId}`}
>
{origin.name}
{location.name}
</Link>
<p className="CharacterCard__meta-item">|</p>
<p className="CharacterCard__meta-item">{status}</p>
Expand Down
122 changes: 122 additions & 0 deletions src/pages/Character/Character.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import React, { Component } from "react";
import axios from "axios";

import Layout from "../../components/Layout";

import { getCharacter } from "../../Api";
import EpisodeCard from "../../components/EpisodeCard";

class Character extends Component {
constructor(props) {
super(props);

this.state = {
character: null,
episodes: [],
hasLoaded: false,
hasError: false,
errorMessage: null,
};
this.loadCharacter = this.loadCharacter.bind(this);
}

componentDidMount() {
const { match } = this.props;
const { characterId } = match.params;

this.loadCharacter(characterId);
}

async loadCharacter(characterId) {
try {
const { data } = await getCharacter(characterId);

const promises = data.episode.map((eachEpisode) =>
axios.get(eachEpisode),
);

const episodesResponse = await Promise.all(promises);

const episodes = episodesResponse.map((episode) => episode.data);

this.setState({
hasLoaded: true,
character: data,
episodes: episodes,
});
} catch (e) {
this.setState({
hasLoaded: true,
hasError: true,
errorMessage: e.message,
});
}
}

render() {
const {
character,
episodes,
hasLoaded,
hasError,
errorMessage,
} = this.state;
return (
<Layout>
<section className="row">
{!hasLoaded && (
<div className="col col-12">
<p>Character not loaded...</p>
</div>
)}
{hasLoaded && (
<div className="container">
<div className="row">
<img className="col col-3" src={character.image} alt="" />
<div className="col col-6 my-auto">
<h3>{character.name}</h3>
<hr />
<h6 className="font-weight-bold">CHARACTER</h6>
<p>{`${character.species} | ${character.status}`}</p>
<div className="row">
<div className="col col-3">
<h6 className="font-weight-bold">ORIGIN</h6>
<p>{`${character.origin.name}`}</p>
</div>
<div className="col col-6">
<h6 className="font-weight-bold">LOCATION</h6>
<p>{`${character.location.name}`}</p>
</div>
</div>
</div>
</div>
<hr />
<h4>Episodes</h4>
<hr />
</div>
)}

{hasError && (
<div className="col col-12">
<p>Character error...</p>
<p>{errorMessage}</p>
</div>
)}
{episodes.length > 0 &&
episodes.map((episode) => (
<EpisodeCard
key={episode.id}
id={episode.id}
name={episode.name}
airDate={episode.air_date}
episode={episode.episode}
/>
))}

</section>
</Layout>
);
}
}

export default Character;
Loading