Skip to content
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

refactoring detail card component #29

Merged
merged 12 commits into from
Apr 17, 2023
133 changes: 0 additions & 133 deletions src/components/CardDetails/CardDetails.tsx

This file was deleted.

115 changes: 115 additions & 0 deletions src/components/DetailsCard/DetailsCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import React from 'react';
import { AiOutlineColumnHeight } from 'react-icons/ai';
import { FaWeightHanging } from 'react-icons/fa';

import { TypeCard } from '@components/TypeCard/TypeCard';
import { ICardDatails } from '@interfaces/cardDatails';
import { getNumberOrderFormat } from '@utils/getNumberOrderFormat';
import {
getTypesToBackgroundColor,
getTypesToIconsTypes,
} from '@utils/getTheme';

import { AbilitiesCard } from './components/AbilitiesCard/AbilitiesCard';
import { BaseStats } from './components/BaseStats/BaseStats';
import { InfoBox } from './components/InfoBox/InfoBox';
import { Tabs } from './components/Tabs/Tabs';

export const DetailsCard = ({
id,
name,
img,
types,
weight,
height,
abilities,
stats,
}: ICardDatails) => {
const [select, setSelect] = React.useState(true);
const [selectTwo, setSelectTwo] = React.useState(false);

const handleClick = () => {
setSelect(!select);
setSelectTwo(!selectTwo);
};

return (
<div className="bg-white w-[400px] mx-auto rounded-2xl border border-zinc-300 overflow-hidden">
{/* image pokémon */}
<div
style={{
backgroundColor: id!
? getTypesToBackgroundColor(types![0].type.name.toUpperCase())
: '#9d9b9b',
}}
className="bg-zinc-500 flex flex-col items-center text-white px-4 py-4 rounded-b-[50%]"
>
<div className="w-[240px] flex justify-center -mb-14">
<img src={img} alt={name} className="w-full" loading="lazy" />
</div>
</div>

{/* name pokémon */}
<div className="w-full flex flex-col justify-between mt-6 px-4">
<strong className="text-2xl font-medium leading-tight capitalize">
{name}
</strong>
<span className="text-sm font-semibold text-zinc-500">
{getNumberOrderFormat(id!)}
</span>
</div>

{/* types pokémon */}
<div className="flex items-center gap-2 py-2 px-4">
{types?.map((type, index) => {
return (
<div
key={`${type.type.name}-${index}`}
className="font-semibold text-white text-[12px]"
>
<TypeCard
type={type.type.name}
icon={`${
type.type.name &&
getTypesToIconsTypes(type.type.name.toUpperCase())
}`}
/>
</div>
);
})}
</div>

{/* nav tabs */}
<Tabs select={select} selectTwo={selectTwo} onSelect={handleClick} />

{select && (
<div className="mb-4">
{/* info pokémon */}
<div className="flex items-center justify-between px-4 my-2">
<InfoBox
text="Peso"
value={weight}
unity="kg"
icon={<FaWeightHanging size={15} className="text-zinc-500" />}
/>

<InfoBox
text="Altura"
value={height}
unity="m"
icon={
<AiOutlineColumnHeight size={15} className="text-zinc-500" />
}
/>
</div>

{/* abilities */}
<AbilitiesCard abilities={abilities} />
</div>
)}

{/* base stats */}
{selectTwo && <BaseStats stats={stats} />}
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react';
import { CgPokemon } from 'react-icons/cg';

import { IAbilitiesCard } from '@interfaces/abilitiesCard';

export const AbilitiesCard = ({ abilities }: IAbilitiesCard) => {
return (
<div className="flex flex-col justify-center items-center pt-2 px-4">
<h3 className="flex items-center text-sm font-semibold text-zinc-500 gap-2 mb-1 uppercase">
<CgPokemon size={20} className="text-zinc-500" />
Abilities
</h3>

<div className="flex gap-2">
{abilities?.map((ability, index) => {
return (
<div key={`${ability.ability.name}-${index}`}>
<div className="text-center border border-zinc-300 rounded-lg py-2 px-3">
<span className="text-base capitalize">
{ability.ability.name}
</span>
</div>
</div>
);
})}
</div>
</div>
);
};
36 changes: 36 additions & 0 deletions src/components/DetailsCard/components/BaseStats/BaseStats.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React from 'react';
import { ImStatsBars } from 'react-icons/im';

import { IBaseStats } from '@interfaces/baseStats';

import { ProgressBar } from '../ProgressBar/ProgressBar';

export const BaseStats = ({ stats }: IBaseStats) => {
return (
<div className="flex flex-col items-center pt-4 pb-8">
<h3 className="flex items-center text-sm font-semibold text-zinc-500 gap-2 mb-1 uppercase">
<ImStatsBars size={15} className="text-zinc-500" />
Base Stats
</h3>
{stats?.map((stat, index) => {
return (
<div
key={index}
className="w-full justify-between items-center flex gap-2 px-4 text-zinc-700"
>
<div className="w-[200px]">
<span className="text-sm font-semibold">{stat.stat.name}</span>
</div>

{/* progressbar */}
<ProgressBar amount={stat.base_stat} />

<div className="w-11 text-right">
<span className="text-sm font-semibold">{stat.base_stat}</span>
</div>
</div>
);
})}
</div>
);
};
21 changes: 21 additions & 0 deletions src/components/DetailsCard/components/InfoBox/InfoBox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react';

import { IInfoBox } from '@interfaces/infoBox';
import { formatHeightWeight } from '@utils/formatHeightWeight';

export const InfoBox = ({ text, value, icon, unity }: IInfoBox) => {
return (
<div className="w-full px-2">
<h3 className="flex items-center text-sm font-semibold text-zinc-500 gap-2 mb-1 uppercase">
{icon}
{text}:
</h3>
<div className="text-center border border-zinc-300 rounded-lg py-2 px-3">
<span className="text-base font-medium">
{formatHeightWeight(value)}
{unity}
</span>
</div>
</div>
);
};
32 changes: 32 additions & 0 deletions src/components/DetailsCard/components/ProgressBar/ProgressBar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from 'react';

type IProgressBar = {
amount: number;
};

export const ProgressBar = ({ amount }: IProgressBar) => {
const [progress, setProgress] = React.useState(0);
const maxPercentage = 100;

let percentage = (amount / 100) * maxPercentage;

if (percentage > 100) {
percentage = 100;
}

React.useEffect(() => {
const timer = setTimeout(() => setProgress(percentage), 500);
return () => clearTimeout(timer);
}, [percentage]);

return (
<div role="progressbar" className="h-2 w-full bg-zinc-400 rounded">
<div
className="h-2 rounded-xl bg-green-400 transition-all duration-500"
style={{
width: `${progress}%`,
}}
/>
</div>
);
};
Loading