
h1 {
text-align: center;
}
.header {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100px;
background-color: #fff;
z-index: 1000; /* 다른 요소들 위에 표시되도록 z-index 설정 */
padding: 0;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* 약간의 그림자 추가 */
text-align: center;
}
import React from "react";
import "./Header.css";
function Header() {
return (
<div className="header">
<h1>IrishNoah Bit-Coin Information</h1>
</div>
);
}
export default Header;
.nav {
position: fixed;
top: 100px; /* Header 아래에 위치하도록 설정 */
left: 0;
width: 100%;
background-color: #000;
z-index: 999; /* Header 아래에 표시되도록 z-index 설정 */
padding: 0;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* 약간의 그림자 추가 */
text-align: center;
align-items: center; /* 수직 중앙 정렬 */
justify-content: center; /* 수평 중앙 정렬 */
}
.navbar {
width: 1500px; /* 너비를 960px로 고정 */
max-width: 100%; /* 최대 너비를 100%로 설정하여 작은 화면에서도 잘 보이도록 함 */
margin: 0 auto; /* 상하 마진 0, 좌우 마진 자동 조정으로 중앙 정렬 */
background-color: black;
padding: 15px 0px;
text-align: center;
font-size: x-large;
}
@media (max-width: 768px) {
.navbar {
width: 100%; /* 작은 화면에서는 너비를 100%로 설정 */
padding: 10px 0px; /* 패딩을 줄여서 공간을 절약 */
}
}
.navbarMenu {
color: white;
margin: 30px;
text-decoration: none;
}
.navbarMenu:hover {
color: orange; /* 마우스 오버 시 글자 색상을 파란색으로 변경 */
}
import { Link } from "react-router-dom";
import React from "react";
import "./Nav.css";
function Nav() {
return (
<div className="nav">
<div className="navbar">
<Link className="navbarMenu" to={"/"}>
Main
</Link>
<Link className="navbarMenu" to={"/posting"}>
Posting
</Link>
<Link className="navbarMenu" to={"/contact"}>
Contact
</Link>
</div>
</div>
);
}
export default Nav;
import React from "react";
function Posting() {
return (
<div>
<h3>This is Posting Page!</h3>
</div>
);
}
export default Posting;
import React from "react";
function Contact() {
return (
<div>
<h3>This is Contact Page!</h3>
</div>
);
}
export default Contact;
import PropTypes from "prop-types";
import { Link } from "react-router-dom";
function HomeCoinInfo({ rank, id, name, symbol, first_data_at }) {
return (
<div>
<h2>
<Link to={`/DetailCoin/${id}`}>{id}</Link>
</h2>
<ul>
<li>rank : {rank}</li>
<li>name : {name}</li>
<li>symbol : {symbol}</li>
<li>first_data_at : {first_data_at}</li>
</ul>
</div>
);
}
HomeCoinInfo.propTypes = {
rank: PropTypes.string.isRequired,
id: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
symbol: PropTypes.string.isRequired,
first_data_at: PropTypes.string.isRequired,
};
export default HomeCoinInfo;
.container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100vh; /* 화면 전체 높이를 차지하도록 설정 */
padding: 150px 20px 50px; /* 고정된 Header와 Nav의 높이를 고려하여 padding-top을 설정 */
box-sizing: border-box;
}
import React from "react";
import styles from "./Layout.module.css";
const Layout = ({ children }) => {
return <div className={styles.container}>{children}</div>;
};
export default Layout;
import React, { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
function DetailCoin() {
const { id } = useParams(); // URL에서 id 파라미터를 추출합니다.
const [coin, setCoin] = useState(null);
useEffect(() => {
fetch(`https://api.coinpaprika.com/v1/tickers/${id}`) // 코인 정보를 가져오는 API (예시 URL)
.then((response) => response.json())
.then((data) => {
setCoin(data);
console.log(data);
})
.catch((error) => console.error("Error fetching coin data:", error));
}, [id]); // id가 변경될 때마다 이 effect를 다시 실행합니다.
if (!coin) {
return <p>Loading...</p>;
}
const quotes = coin.quotes.USD;
return (
<div>
<h1>
{coin.name} ({coin.id})
</h1>
<ul>
<li>Rank: {coin.rank}</li>
<li>symbol: {coin.symbol}</li>
<li>total_supply: {coin.total_supply}</li>
<li>first_data_at: {coin.first_data_at}</li>
<li>last_updated: {coin.last_updated}</li>
{Object.keys(quotes).map((key) => (
<li key={key}>
{key}: {quotes[key]}
</li>
))}
</ul>
</div>
);
}
export default DetailCoin;
.container {
width: 1500px; /* 너비를 960px로 고정 */
max-width: 100%; /* 최대 너비를 100%로 설정하여 작은 화면에서도 잘 보이도록 함 */
margin: 0 auto; /* 상하 마진 0, 좌우 마진 자동 조정으로 중앙 정렬 */
padding: 20px; /* 내부 여백 추가 */
}
.coinsMainText {
text-align: center; /* 텍스트 중앙 정렬 */
}
.coins {
display: grid;
grid-template-columns: repeat(3, 1fr); /* 한 행당 3개의 열 */
gap: 100px; /* 그리드 항목 간의 간격 */
justify-content: center; /* 중앙 정렬 */
padding: 150px;
width: 100%; /* 부모 컨테이너의 너비에 맞춤 */
padding-top: 20px;
}
.coins > div {
width: 400px; /* 각 코인 항목의 너비를 고정 */
height: 250px; /* 각 코인 항목의 높이를 고정 */
border: 1px solid #ccc; /* 각 코인 항목에 경계선 추가 */
padding: 10px; /* 경계선과 내용 사이에 여백 추가 */
border-radius: 8px; /* 경계선의 모서리를 둥글게 만듦 */
background-color: #fff; /* 배경색을 흰색으로 설정 */
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* 약간의 그림자 추가 */
}
@media screen and (max-width: 1090px) {
.coins {
grid-template-columns: 1fr;
width: 100%;
}
}
.eachCoin:hover {
background-color: green;
transform: scale(1.1); /* 5%만큼 크기를 증가시킴 */
}
import React, { useState, useEffect } from "react";
import styles from "./HomeCoin.module.css";
import HomeCoinInfo from "../components/HomeCoinInfo";
function HomeCoin() {
const [coin, setCoin] = useState(null);
const [error, setError] = useState(null);
useEffect(() => {
async function fetchCoinData() {
try {
const response = await fetch("https://api.coinpaprika.com/v1/tickers");
const coins = await response.json();
setCoin(coins); // >>> 모두 다 불러옴
} catch (error) {
setError(error);
console.error("Error fetching coin data:", error);
}
}
fetchCoinData();
}, []);
if (error) {
return <div>Error fetching coin data: {error.message}</div>;
}
if (!coin) {
return <div>Loading...</div>;
}
return (
<div className={styles.container}>
<div className={styles.coins}>
{coin.map((data) => (
<div className={styles.eachCoin}>
<div>
<HomeCoinInfo
rank={data.rank}
id={data.id}
name={data.name}
symbol={data.symbol}
first_data_at={data.first_data_at}
/>
</div>
</div>
))}
</div>
</div>
);
}
export default HomeCoin;
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import Header from "./components/Header";
import Nav from "./components/Nav";
import DetailCoin from "./routes/DetailCoin";
import HomeCoin from "./routes/HomeCoin";
import Main from "./routes/HomeCoin";
import Posting from "./components/Posting.js";
import Contact from "./components/Contact.js";
import Layout from "./components/Layout";
function App() {
return (
<Router>
<Header />
<Nav />
<Layout>
<Switch>
<Route path="/hello">
<h1>Hello</h1>
</Route>
<Route path="/DetailCoin/:id">
<DetailCoin />
</Route>
<Route exact path="/">
<HomeCoin />
</Route>
<Route exact path="/">
<Main />
</Route>
<Route path="/posting">
<Posting />
</Route>
<Route path="/contact">
<Contact />
</Route>
</Switch>
</Layout>
</Router>
);
}
export default App;
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
background-color: #eff3f7;
height: 100%;
}
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import "./styles.css";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
⇒ 화면 비율 100%

⇒ 화면 비율 25%

⇒ Posting / Contact
