Skip to content
Merged
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
68 changes: 51 additions & 17 deletions src/components/PokemonCard/PokemonCard.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
div {
.pokemon-card {
display: flex;
flex-direction: column;
align-items: center;
Expand All @@ -9,38 +9,72 @@ div {
background: #fff;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
margin: 0 auto;
max-width: 500px;
}

h1 {
.pokemon-card h1 {
text-align: center;
margin-bottom: 10px;
}

img {
.pokemon-card img {
display: block;
margin: 0 auto 20px auto;
width: 120px;
height: 120px;
}

table {
.general-info {
width: 100%;
background: #f8f9fa;
padding: 16px;
border-radius: 8px;
margin-bottom: 24px;
display: flex;
flex-direction: column;
gap: 8px;
}

.info-row {
display: flex;
align-items: center;
gap: 8px;
font-size: 14px;
}

.type-badges {
display: flex;
gap: 6px;
}

.type-badge {
background: #333;
color: white;
padding: 2px 8px;
border-radius: 12px;
font-size: 12px;
text-transform: capitalize;
}

.stats-table {
display: grid;
grid-template-columns: auto auto 1fr auto auto;
width: 100%;
border-collapse: collapse;
}

tbody,
tfoot,
tr {
.stats-table tbody,
.stats-table tfoot,
.stats-table tr {
display: contents;
}

tr {
.stats-table tr {
border-bottom: 1px solid #eee;
}

th {
.stats-table th {
padding: 8px 4px;
font-weight: normal;
color: #666;
Expand All @@ -52,13 +86,13 @@ th {
white-space: nowrap;
}

th.cell-num:nth-child(1) {
.stats-table th.cell-num:nth-child(1) {
text-align: left;
color: #666;
font-weight: 500;
}

th.cell-num:nth-child(2) {
.stats-table th.cell-num:nth-child(2) {
font-weight: bold;
color: #333;
}
Expand All @@ -79,31 +113,31 @@ th.cell-num:nth-child(2) {
padding: 6px;
}

tfoot tr {
.stats-table tfoot tr {
border-bottom: none;
}

tfoot th {
.stats-table tfoot th {
color: #333;
font-weight: bold !important;
}

tfoot th:nth-child(1) {
.stats-table tfoot th:nth-child(1) {
grid-column: 1;
text-align: left;
}

tfoot th:nth-child(2) {
.stats-table tfoot th:nth-child(2) {
grid-column: 2;
text-align: right;
}

tfoot th:nth-child(3) {
.stats-table tfoot th:nth-child(3) {
grid-column: 4;
text-align: right;
}

tfoot th:nth-child(4) {
.stats-table tfoot th:nth-child(4) {
grid-column: 5;
text-align: right;
}
24 changes: 20 additions & 4 deletions src/components/PokemonCard/PokemonCard.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { render, screen } from "@testing-library/react";
import { expect, test } from "vitest";
import { describe, expect, test } from "vitest";
import { PokemonCard } from "./PokemonCard";

const mockPokemon = {
Expand All @@ -8,6 +8,10 @@ const mockPokemon = {
front_default:
"https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/25.png",
},
height: 4,
weight: 60,
types: [{ type: { name: "electric" } }],
abilities: [{ ability: { name: "static" }, is_hidden: false }],
stats: [
{ base_stat: 35, stat: { name: "hp" } },
{ base_stat: 55, stat: { name: "attack" } },
Expand All @@ -18,7 +22,19 @@ const mockPokemon = {
],
};

test("renders pokemon name", () => {
render(<PokemonCard pokemon={mockPokemon} />);
expect(screen.getByText("Pikachu")).toBeInTheDocument();
describe("PokemonCard Component", () => {
test("renders pokemon name and general information", () => {
render(<PokemonCard pokemon={mockPokemon} />);

expect(screen.getByText("Pikachu")).toBeDefined();
expect(screen.getByText("electric")).toBeDefined();
expect(screen.getByText("static")).toBeDefined();
expect(screen.getByText("0.4 m")).toBeDefined();
expect(screen.getByText("6 kg")).toBeDefined();
});

test("matches snapshot", () => {
const { asFragment } = render(<PokemonCard pokemon={mockPokemon} />);
expect(asFragment()).toMatchSnapshot();
});
});
46 changes: 41 additions & 5 deletions src/components/PokemonCard/PokemonCard.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
import "./PokemonCard.css";

type PokemonData = {
name: string;
sprites: { front_default: string };
stats: Array<{ base_stat: number; stat: { name: string } }>;
height: number;
weight: number;
types: Array<{ type: { name: string } }>;
abilities: Array<{ ability: { name: string }; is_hidden: boolean }>;
};

type PokemonCardProps = {
pokemon: any;
pokemon: PokemonData;
};

export function PokemonCard({ pokemon }: PokemonCardProps) {
Expand All @@ -20,12 +30,38 @@ export function PokemonCard({ pokemon }: PokemonCardProps) {
let total = 0;

return (
<div>
<div className="pokemon-card">
<h1>{displayName}</h1>
<img src={pokemon.sprites.front_default} />
<table>
<img src={pokemon.sprites.front_default} alt={`${displayName} sprite`} />

<div className="general-info">
<div className="info-row">
<strong>Type:</strong>
<div className="type-badges">
{pokemon.types.map((t) => (
<span key={t.type.name} className="type-badge">
{t.type.name}
</span>
))}
</div>
</div>
<div className="info-row">
<strong>Height:</strong> {pokemon.height / 10} m
</div>
<div className="info-row">
<strong>Weight:</strong> {pokemon.weight / 10} kg
</div>
<div className="info-row">
<strong>Abilities:</strong>{" "}
{pokemon.abilities
.map((a) => a.ability.name + (a.is_hidden ? " (Hidden)" : ""))
.join(", ")}
</div>
</div>

<table className="stats-table">
<tbody>
{pokemon.stats.map((stat: any) => {
{pokemon.stats.map((stat) => {
const base = stat.base_stat;
total += base;

Expand Down