Skip to content

Instantly share code, notes, and snippets.

@OkoliEvans
Last active June 25, 2024 17:25
Show Gist options
  • Save OkoliEvans/4b2aa3d2139751f7e6982c5721495de6 to your computer and use it in GitHub Desktop.
Save OkoliEvans/4b2aa3d2139751f7e6982c5721495de6 to your computer and use it in GitHub Desktop.
import { useCallback, useEffect, useState } from "react";
import { Text } from "../atom/Text";
import userImg from "../../assets/img/team01.png";
import { ImageWrap } from "../atom/ImageWrap";
import { Button } from "../atom/Button";
import { toast } from "sonner";
import signMessages from "../../utils/relayTransaction.js"
import readGameState from "../../utils/readState.js";
import axios from "axios";
import { useActiveAccount } from "thirdweb/react";
const UserProfile = () => {
const [createdProfile, setCreatedProfile] = useState(false);
const [avatar, setAvatar] = useState(null);
const [name, setName] = useState("");
const [imgUrl, setImgUrl] = useState<string | null>(null);
const [characters, setCharacters] = useState(0);
const [gamePoints, setGamePoints] = useState(0);
const [nebulaBalance, setNebulaBalance] = useState(0);
const [userAddress, setUserAddress] = useState('');
const userAccount = useActiveAccount();
useEffect(() => {
let address = userAccount?.address;
if (userAccount && address) {
setUserAddress(address);
}
}, [userAccount]);
async function createProfile() {
const togglePlayer = { "func": "create_player", "monika": name, "avatar_url": imgUrl };
await signMessages(togglePlayer);
}
async function readProfile(address: string) {
if (userAddress) {
try {
const { Status, request_payload } = await readGameState(`profile`);
if (Status === true) {
setCharacters(request_payload.characters);
setGamePoints(request_payload.points);
setNebulaBalance(request_payload.nebula);
}
console.log(Status, request_payload)
} catch (err) {
console.log('Error fetching user profile', err);
}
}
}
const handleNameChange = (event: any) => {
setName(event.target.value);
}
const handleSetCreatedProfile = async () => {
if (imgUrl) {
setCreatedProfile(true);
createProfile();
toast.success('Profile updated successfully');
}
}
const handleAvatarChange = async (event: any) => {
if (event.target.files && event.target.files[0]) {
setAvatar(event.target.files[0]);
}
};
const getAvatar = useCallback(async () => {
if(avatar) {
try {
const formData = new FormData();
formData.append("file", avatar!);
const response = await axios.post(
"https://api.pinata.cloud/pinning/pinFileToIPFS",
formData,
{
headers: {
"Content-Type": "multipart/form-data",
pinata_api_key: import.meta.env.VITE_PINATA_API_KEY,
pinata_secret_api_key: import.meta.env.VITE_PINATA_SECRET_API_KEY,
},
}
);
const avatarUrl = response.data.IpfsHash;
setImgUrl(`https://orange-personal-vulture-360.mypinata.cloud/ipfs/${avatarUrl}`);
console.log(imgUrl);
} catch(err) {
console.log('Pinata API error', err);
}
}
}, [avatar]);
getAvatar();
return (
<section className="w-full h-auto bg-bodyBg">
<main className="w-full lg:py-32 md:py-24 py-20 px-6 flex flex-col items-center gap-4">
<Text
as="h2"
className="font-bold text-center uppercase lg:text-5xl md:text-4xl text-2xl font-barlow"
>
Create your profile
</Text>
<Text
as="p"
className="font-bold text-center text-lg text-gray-400 font-barlow"
>
Are you ready to be a Gamer? Create your profile and let's get started
</Text>
<div className="w-20 h-1.5 bg-myGreen"></div>
<section className="lg:w-[70%] w-full md:mt-20 mt-12 grid md:grid-cols-2 gap-4">
<div className="w-full h-auto relative lg:px-12 px-3">
<div className="text-center border shadow-[0px_3px_13px_0px_rgba(0,0,0,0.17)] relative transition-[0.3s] duration-500 overflow-hidden z-[1] mt-0 mb-[30px] mx-0 pt-[30px] pb-[35px] px-[25px] rounded-xl border-solid border-[#27313f] bg-[#1c242f] before:content-[''] before:absolute before:top-[-60px] before:w-[70px] before:h-80 before:rotate-[-55deg] before:transition-all before:duration-[0.3s] before:ease-[ease-out] before:delay-[0s] before:opacity-[0.55] before:z-[-1] before:left-0 before:bg-[#45f882] after:content-[''] after:absolute after:top-[-60px] after:w-[70px] after:h-80 after:rotate-[55deg] after:transition-all after:duration-[0.3s] after:ease-[ease-out] after:delay-[0s] after:opacity-[0.55] after:z-[-1] after:left-auto after:right-0 after:bg-[#45f882] hover:translate-y-[-7px] hover:before:opacity-[1] hover:after:opacity-[1] group sm:before:!h-[295px] sm:before:!-top-12 sm:after:!h-[295px] sm:after:!-top-12 xsm:before:!h-[295px] xsm:before:!-top-12 xsm:after:!h-[295px] xsm:after:!-top-12 xsm:m-[0_auto_30px] xsm:max-w-[320px]">
<div className="mt-0 mb-[33px] mx-0 after:right-[75px] group-hover:before:opacity-40 group-hover:after:opacity-40 before:content-[''] before:absolute before:top-[-50px] before:w-px before:h-[260px] before:rotate-[-55deg] before:transition-all before:duration-[0.3s] before:ease-[ease-out] before:delay-[0s] before:z-[-1] before:opacity-20 before:left-[75px] before:bg-[#45f882] after:content-[''] after:absolute after:top-[-50px] after:w-px after:h-[260px] after:rotate-[55deg] after:transition-all after:duration-[0.3s] after:ease-[ease-out] after:delay-[0s] after:z-[-1] after:opacity-20 after:left-auto after:bg-[#45f882]">
{imgUrl ? (
<img
src={imgUrl}
onError={(e) => console.log('Image load error:', e)}
className="inline-block sm:max-w-full xsm:max-w-full border-[#fff] max-w-[224px] rounded-[50%] border-[3px] border-solid shadow-[0px_3px_7px_0px_rgba(0,0,0,0.21),inset_0px_3px_9px_0px_rgba(0,0,0,0.92)]"
alt="Avatar"
/>
) : (
<ImageWrap
className="inline-block"
image={avatar ? URL.createObjectURL(avatar) : userImg}
alt=""
objectStatus="sm:max-w-full xsm:max-w-full border-[#fff] max-w-[224px] rounded-[50%] border-[3px] border-solid shadow-[0px_3px_7px_0px_rgba(0,0,0,0.21),inset_0px_3px_9px_0px_rgba(0,0,0,0.92)]"
/>
)}
</div>
<div className="team__content">
<h4 className="text-[20px] font-extrabold tracking-[1px] mt-0 mb-px mx-0 text-gray-200">
{
name ? name : "KILLER MASTER"
}
</h4>
<span className="block font-semibold text-[16px] text-[#45f882] transition-all duration-[0.3s] ease-[ease-out] delay-[0s] font-Barlow">
Player
</span>
</div>
<div className="mt-4 flex flex-col gap-1">
<Text
as="p"
className="text-gray-400 text-base font-belanosima"
>
No of Characters:{" "}
<Text
as="span"
className="text-myGreen/70 font-poppins"
>
3
</Text>
</Text>
<Text
as="p"
className="text-gray-400 text-base font-belanosima"
>
Game Points:{" "}
<Text
as="span"
className="text-myGreen/70 font-poppins"
>
250 pts
</Text>
</Text>
<Text
as="p"
className="text-gray-400 text-base font-belanosima"
>
Nebula Balance:{" "}
<Text
as="span"
className="text-myGreen/70 font-poppins"
>
0 $Neb
</Text>
</Text>
</div>
</div>
</div>
<aside>
{!createdProfile ? (
<form className="w-full">
<div className="relative mt-0 mb-[30px] mx-0 clip-path-polygon-[100%_0,_100%_calc(100%_-_20px),_calc(100%_-_20px)_100%,_0_100%,_0_0] after:content-[''] after:absolute after:bg-[#262f39] after:w-[60px] after:h-px after:right-[-21px] after:-rotate-45 after:bottom-3">
<label
htmlFor="name"
className="text-gray-400 font-belanosima"
>
Name
</label>
<input
type="text"
name="name"
placeholder="Enter your name *"
className=" block w-full text-[#fff] transition-all duration-[0.3s] ease-[ease-out] delay-[0s] px-[25px] py-3.5 border-2 border-solid border-[#19222b] bg-transparent placeholder:opacity-80 focus:!border-[#19222b] focus:!ring-0 focus:!ring-[none] focus:border-solid focus:!outline-offset-0 focus:outline-0"
required
value={name}
onChange={handleNameChange}
/>
</div>
<div className="relative mt-0 mb-[30px] mx-0 clip-path-polygon-[100%_0,_100%_calc(100%_-_20px),_calc(100%_-_20px)_100%,_0_100%,_0_0] after:content-[''] after:absolute after:bg-[#262f39] after:w-[60px] after:h-px after:right-[-21px] after:-rotate-45 after:bottom-3">
<label
htmlFor="profile"
className="text-gray-400 font-belanosima"
>
Upload Avatar
</label>
<input
type="file"
name="profile"
placeholder="Upload avatar *"
accept="image/*"
className=" block w-full text-[#fff] transition-all duration-[0.3s] ease-[ease-out] delay-[0s] px-[25px] py-3.5 border-2 border-solid border-[#19222b] bg-transparent placeholder:opacity-80 focus:!border-[#19222b] focus:!ring-0 focus:!ring-[none] focus:border-solid focus:!outline-offset-0 focus:outline-0"
required
onChange={handleAvatarChange}
/>
</div>
<Button
type="button"
className={`text-[#0f161b] uppercase font-bold tracking-[1px] px-[30px] py-3.5 border-[none] ${imgUrl ? 'bg-[#45f882] hover:bg-[#ffbe18]' : 'bg-[#45f882] opacity-50 cursor-not-allowed'} font-Barlow clip-path-polygon-[100%_0,100%_65%,89%_100%,0_100%,0_0]`} disabled={!imgUrl}
onClick={handleSetCreatedProfile}
>
Submit Now
</Button>
</form>
) : (
<form className="w-full">
<div className="relative mt-0 mb-[30px] mx-0 clip-path-polygon-[100%_0,_100%_calc(100%_-_20px),_calc(100%_-_20px)_100%,_0_100%,_0_0] after:content-[''] after:absolute after:bg-[#262f39] after:w-[60px] after:h-px after:right-[-21px] after:-rotate-45 after:bottom-3">
<label
htmlFor="name"
className="text-gray-400 font-belanosima"
>
Name
</label>
<input
type="text"
name="name"
placeholder="Enter your name *"
className=" block w-full text-[#fff] transition-all duration-[0.3s] ease-[ease-out] delay-[0s] px-[25px] py-3.5 border-2 border-solid border-[#19222b] bg-transparent placeholder:opacity-80 focus:!border-[#19222b] focus:!ring-0 focus:!ring-[none] focus:border-solid focus:!outline-offset-0 focus:outline-0"
required
value={name}
onChange={handleNameChange}
/>
</div>
<div className="relative mt-0 mb-[30px] mx-0 clip-path-polygon-[100%_0,_100%_calc(100%_-_20px),_calc(100%_-_20px)_100%,_0_100%,_0_0] after:content-[''] after:absolute after:bg-[#262f39] after:w-[60px] after:h-px after:right-[-21px] after:-rotate-45 after:bottom-3">
<label
htmlFor="profile"
className="text-gray-400 font-belanosima"
>
Upload Avatar
</label>
<input
type="file"
name="profile"
placeholder="Upload avatar *"
accept="image/*"
className=" block w-full text-[#fff] transition-all duration-[0.3s] ease-[ease-out] delay-[0s] px-[25px] py-3.5 border-2 border-solid border-[#19222b] bg-transparent placeholder:opacity-80 focus:!border-[#19222b] focus:!ring-0 focus:!ring-[none] focus:border-solid focus:!outline-offset-0 focus:outline-0"
required
onChange={handleAvatarChange}
/>
</div>
<Button
type="button"
className={`text-[#0f161b] uppercase font-bold tracking-[1px] px-[30px] py-3.5 border-[none] ${imgUrl ? 'bg-[#45f882] hover:bg-[#ffbe18]' : 'bg-[#45f882] opacity-50 cursor-not-allowed'} font-Barlow clip-path-polygon-[100%_0,100%_65%,89%_100%,0_100%,0_0]`}
disabled={!imgUrl}
onClick={handleSetCreatedProfile}
>
Update profile
</Button>
</form>
)}
</aside>
</section>
</main>
</section>
);
};
export default UserProfile;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment