跳到主要内容

编写铸造宠物蛋页面

在本小节中,我们将完成宠物蛋铸造页面的编写。

编写页头和页脚

DAPP 中的所有页面都应包含着一个页头和一个页脚。因此在编写页面主体之前,我们会先编写页头和页脚的 component 。

页头(HeaderApp

页头从左至右应包含网站 Logo、跳转其他页面的链接、搜索框(完善其他页面之后再添加)、签到按钮/积分展示框以及前面 RainbowKit 设置全局展示的钱包组件。代码如下所示:

HeaderApp.jsx
import React from 'react';
import Image from 'next/image';
import Link from 'next/link';
import { Checkin } from './Checkin';
import { useSelector } from 'react-redux';

const HeaderApp = () => {

const address = useSelector((state) => state.address.address);

return (
<nav className='flex items-center justify-start space-x-8 bg-slate-50 container drop-shadow-xl'>
<Link href={"/"} className="flex items-center font-medium text-white text-lg">
<Image
src={`/images/logo.png`}
width={64}
height={64}
alt=""
priority
className="relative w-16 h-16 mr-auto md:mr-0 flex-shrink-0 !important"
/>
</Link>
<ul className='flex sm:items-center space-x-5'>
<li>
<Link href={"/profile"} className='hover:text-black text-gray-400'>
主页
</Link>
</li>
<li>
<Link href="/mint" className='hover:text-black text-gray-400'>
铸造
</Link>
</li>
</ul>
{!!address && <div className='overflow-hidden'>
<Checkin />
</div>}
</nav>
);
};
export default HeaderApp;

页脚(FooterApp

页脚从左至右从上至下应包括项目简介、相关链接、版权、以及联系方式。代码如下:

FooterApp.jsx
import { GithubFilled } from "@ant-design/icons";
import Link from "next/link";

const FooterApp = () => {
return (
<div className="bg-footer bg-black">
<div className="text-white">
<div className="max-w-7xl mx-auto px-4 py-10">
<div className="flex flex-row justify-between gap-10">
<div className="flex flex-col gap-6">
<div className="text-xl font-bold">
<Link href="/" passHref className="hover:text-white">
iCat
</Link>
</div>
<div className="text-sm">
基于AIGC的区块链游戏,玩家可以通过游戏体验到区块链
<br /> 和AIGC的乐趣,开发者可以学习在Web3.0开发
</div>
</div>
<div className="flex flex-col gap-6 text-xs">
<div className="text-xl font-semibold">相关链接</div>
<div className="flex gap-4">
<a
href="https://github.com/iCat/frontend"
target="_blank"
rel="noopener noreferrer"
>
<GithubFilled />
</a>
</div>
</div>
</div>
<div className="border-t border-gray-700 mt-10"></div>
<div className="flex justify-between items-center gap-10 mt-10 text-xs">
<div>© {new Date().getFullYear()} iCat. All rights reserved.</div>
<div className="flex gap-4 text-xs">
<a
href="https://game-tutorial-beta.vercel.app/"
target="_blank"
rel="noopener noreferrer"
className="hover:text-white"
>
开发文档
</a>
<a
href="https://github.com/iCat/frontend"
target="_blank"
rel="noopener noreferrer"
className="hover:text-white"
>
源代码
</a>
</div>
</div>
</div>
</div>
</div>
)
}

export default FooterApp;

之后 DAPP 中的每个页面都需要引用这两个 components 而无需额外编写页头和页脚。

编写页面主体

页面主体我们同样编写一个单独的 component,方便日后 debug。

components文件夹下创建文件Mint.jsx,放入以下代码:

Mint.jsx
import { useContractWrite, usePrepareContractWrite } from "wagmi";
import { ConnectButton, useAddRecentTransaction } from "@rainbow-me/rainbowkit";
import abi from "@/lib/abi/eggAbi";
import { useEffect } from "react";
import Image from "next/image";
import Link from "next/link";
import { toast, Toaster } from "react-hot-toast";

const Mint = () => {
const { config } = usePrepareContractWrite({
address: process.env.NEXT_PUBLIC_EGG_CONTRACT_ADDRESS,
abi: abi,
functionName: 'mint',
args: []
});
const { data, isLoading, isSuccess, write } = useContractWrite(config);

const addRecentTransaction = useAddRecentTransaction();

useEffect(() => {
if (isSuccess) {
addRecentTransaction({
hash: data?.hash || "",
description: "铸造Egg"
})
}
}, [data, isSuccess])

return (
<div>
<Toaster
position="bottom-right"
reverseOrder={true}
/>
<div className="bg-white">
<div className="max-w-7xl mx-auto py-20 px-4 sm:px-6 lg:px-8">
<div className="flex flex-col items-center gap-4 max-w-2xl mx-auto border rounded-lg p-4 bg-white drop-shadow-2xl">
<h1 className="text-2xl font-semibold text-center pt-8">铸造iCat Egg</h1>
<div className="relative overflow-hidden flex flex-col items-center justify-center gap-18 p-4 w-full">
<img src="/images/qr.png" alt="" className="w-[80%] h-[80%] object-contain md:w-[300px] lg:w-[300px]" />
</div>
<div className="w-full space-x-5 flex items-center justify-center">
<button disabled={!write} onClick={() => write?.()} className={`rounded-xl px-8 py-3 text-neutral-100 font-[500] transition tracking-wide w-[200px] outline-none ${isLoading ? "bg-emerald-500" : isSuccess ? 'bg-amber-400' : 'bg-blue-600 hover:bg-blue-700'}`}>
{isLoading ? "铸造中..." : isSuccess ? "铸造成功!" : "铸造"}
</button>
{isSuccess &&
<Link href="/profile">
<button className="rounded-xl px-8 py-3 text-neutral-100 font-[500] transition tracking-wide w-[200px] outline-none bg-blue-600 hover:bg-blue-700">
个人主页
</button>
</Link>
}
</div>
</div>
</div>
</div>
</div>
)
}

export default Mint;

然后打开app/mint/page.jsx,将代码更改为以下内容并保存:

"use client";

import { Loader } from '@/components/Loader';
import React from 'react';
import Mint from '@/components/Mint';
import FooterApp from '@/components/FooterApp';
import HeaderApp from '@/components/HeaderApp';

const MintPage = () => {
return (
<>
<HeaderApp />
<Mint/>
<FooterApp />
</>
);
};

export default MintPage;

然后打开http://localhost:3000/mint,就可以看到渲染好的页面啦!