본문 바로가기
TIL

12. 13. 36일차 TIL Next.js 과제_02

by 눈 새 2024. 12. 14.

오늘은 어제 작성한 fetch 로직을 이용하여 브라우저에 정보를 렌더링하는 것과 다크모드/화이트모드를 구현하였다. 하지만 로테이션과 챔피언은 제대로 작동하지 않고 있다. 이는 오후에 일어나서 확인하고 수정할 예정이다.


1. 아이템 정보 렌더링

// app/items/page.tsx

import { fetchItemData } from "@/utils/serverApi";
import Image from "next/image";
import { ItemDetails } from "@/types/items";

export const revalidate = 86400;

export default async function Items() {
  const itemRes = await fetchItemData();
  const items: Record<string, ItemDetails> = itemRes.data;
  const version: string = itemRes.version;

  return (
    <div>
      <ul className="grid grid-cols-5 gap-4">
        {Object.entries(items).map(([id, item]) => (
          <li
            key={id}
            className="flex-col justify-center items-center gap-4 border p-4 rounded-md shadow-md bg-white"
          >
            <Image
              src={`https://ddragon.leagueoflegends.com/cdn/${version}/img/item/${
                item.image?.full || "default.png"
              }`}
              alt={item.name || "아이템"}
              width={50}
              height={50}
              style={{
                marginRight: "10px",
              }}
            />
            <p className="text-lg font-semibold mb-2">
              {item.name || "알 수 없는 아이템"}
            </p>
            <p className="text-sm text-gray-500 mb-2">
              {item.plaintext || "설명이 없습니다."}
            </p>
            <p className="text-sm">
              구매가격: {item.gold?.total || 0} / 판매가격:{" "}
              {item.gold?.sell || 0}
            </p>
          </li>
        ))}
      </ul>
    </div>
  );
}


2. 다크모드 / 화이트모드

// utils/useDarkMode.ts

import { useState, useEffect } from "react";

export default function useDarkMode() {
  const [theme, setTheme] = useState<string>("light");

  useEffect(() => {
    const savedTheme = localStorage.getItem("theme");
    if (savedTheme) {
      setTheme(savedTheme);
    } else {
      setTheme("light");
    }
  }, []);

  const toggleTheme = () => {
    const newTheme = theme === "dark" ? "light" : "dark";
    setTheme(newTheme);
    localStorage.setItem("theme", newTheme);
  };

  return { theme, toggleTheme };
}

 

이렇게 작성한 로직을 헤더에 적용시켰고, 아래에서 잘 적용되고 있는 모습을 볼 수 있다.

// conponents/layout/Header.tsx

import Link from "next/link";

function Header({
  theme,
  toggleTheme,
}: {
  theme: string;
  toggleTheme: () => void;
}) {
  return (
    <header className="bg-gray-800 text-white p-4">
      <nav className="container mx-auto flex justify-between items-center">
        {/* 로고 */}
        <div>
          <Link href="/" className="text-lg font-bold">
            로고
          </Link>
        </div>

        {/* 네비게이션 메뉴 */}
        <div className="flex space-x-4">
          <Link href="/rotation" className="hover:text-gray-300">
            로테이션
          </Link>
          <Link href="/champions" className="hover:text-gray-300">
            챔피언
          </Link>
          <Link href="/items" className="hover:text-gray-300">
            아이템
          </Link>
        </div>

        {/* 다크모드 토글 버튼 */}
        <button
          className="bg-gray-700 text-white px-4 py-2 rounded"
          onClick={toggleTheme}
        >
          {theme === "dark" ? "Light Mode" : "Dark Mode"}
        </button>
      </nav>
    </header>
  );
}

export default Header;

화이트 모드 모습
다크 모드 모습