mango-v4-ui/components/profile/EditNftProfilePic.tsx

182 lines
5.9 KiB
TypeScript
Raw Normal View History

2022-09-20 22:31:54 -07:00
import { useState, useEffect } from 'react'
import mangoStore from '@store/mangoStore'
import { useWallet } from '@solana/wallet-adapter-react'
import { ArrowLeftIcon } from '@heroicons/react/20/solid'
2022-09-20 22:31:54 -07:00
import { useTranslation } from 'next-i18next'
2022-09-24 05:07:10 -07:00
import Button, { LinkButton } from '../shared/Button'
2022-09-20 22:31:54 -07:00
import { bs58 } from '@project-serum/anchor/dist/cjs/utils/bytes'
import { notify } from 'utils/notifications'
import { MANGO_DATA_API_URL } from 'utils/constants'
import { ImgWithLoader } from '@components/ImgWithLoader'
2023-11-08 20:24:44 -08:00
import useProfileDetails from 'hooks/useProfileDetails'
2022-09-20 22:31:54 -07:00
const EditNftProfilePic = ({ onClose }: { onClose: () => void }) => {
const { t } = useTranslation(['common', 'profile'])
const { publicKey, signMessage } = useWallet()
const nfts = mangoStore((s) => s.wallet.nfts.data)
const nftsLoading = mangoStore((s) => s.wallet.nfts.loading)
const [selectedProfile, setSelectedProfile] = useState<string>('')
2023-11-08 20:24:44 -08:00
const { refetch: refetchProfileDetails } = useProfileDetails()
const { data: profile } = useProfileDetails()
2022-09-20 22:31:54 -07:00
useEffect(() => {
if (profile?.profile_image_url) {
2022-09-20 22:31:54 -07:00
setSelectedProfile(profile.profile_image_url)
}
}, [profile])
const saveProfileImage = async () => {
const name = profile?.profile_name.toLowerCase()
const traderCategory = profile?.trader_category
2022-09-20 22:31:54 -07:00
try {
if (!publicKey) throw new Error('Wallet not connected!')
if (!signMessage)
throw new Error('Wallet does not support message signing!')
const messageString = JSON.stringify({
profile_name: name,
trader_category: traderCategory,
profile_image_url: selectedProfile,
})
const message = new TextEncoder().encode(messageString)
const signature = await signMessage(message)
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
wallet_pk: publicKey.toString(),
message: messageString,
signature: bs58.encode(signature),
}),
}
const response = await fetch(
`${MANGO_DATA_API_URL}/user-data/profile-details`,
2023-07-21 11:47:53 -07:00
requestOptions,
2022-09-20 22:31:54 -07:00
)
if (response.status === 200) {
2023-11-08 20:24:44 -08:00
await refetchProfileDetails()
2022-09-20 22:31:54 -07:00
notify({
type: 'success',
title: t('profile:profile-pic-success'),
})
}
} catch {
notify({
type: 'success',
title: t('profile:profile:profile-pic-failure'),
})
} finally {
onClose()
}
}
const removeProfileImage = async () => {
const name = profile?.profile_name.toLowerCase()
const traderCategory = profile?.trader_category
2022-09-20 22:31:54 -07:00
try {
if (!publicKey) throw new Error('Wallet not connected!')
if (!signMessage)
throw new Error('Wallet does not support message signing!')
const messageString = JSON.stringify({
profile_name: name,
trader_category: traderCategory,
profile_image_url: '',
})
const message = new TextEncoder().encode(messageString)
const signature = await signMessage(message)
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
wallet_pk: publicKey.toString(),
message: messageString,
signature: bs58.encode(signature),
}),
}
const response = await fetch(
`${MANGO_DATA_API_URL}/user-data/profile-details`,
2023-07-21 11:47:53 -07:00
requestOptions,
2022-09-20 22:31:54 -07:00
)
if (response.status === 200) {
2023-11-08 20:24:44 -08:00
await refetchProfileDetails()
2022-09-20 22:31:54 -07:00
notify({
type: 'success',
title: t('profile:profile-pic-remove-success'),
})
}
} catch {
notify({
type: 'success',
title: t('profile:profile-pic-remove-failure'),
})
} finally {
onClose()
}
}
return (
<>
<div className="mb-3 flex w-full flex-col items-center sm:mt-3 sm:flex-row sm:justify-between">
<button
onClick={onClose}
2022-12-15 19:16:05 -08:00
className={`absolute left-2 top-3 z-40 text-th-fgd-4 focus:outline-none md:hover:text-th-active`}
2022-09-20 22:31:54 -07:00
>
<ArrowLeftIcon className={`h-5 w-5`} />
</button>
<h2>{t('profile:choose-profile')}</h2>
<div className="mt-3 flex items-center space-x-4 sm:mt-0">
<Button disabled={!selectedProfile} onClick={saveProfileImage}>
{t('save')}
</Button>
{profile?.profile_image_url ? (
2023-04-20 19:32:20 -07:00
<LinkButton onClick={removeProfileImage}>
2022-09-20 22:31:54 -07:00
{t('profile:remove')}
</LinkButton>
) : null}
</div>
</div>
{nfts.length > 0 ? (
<div className="flex flex-col items-center">
2022-11-02 09:16:25 -07:00
<div className="mb-4 grid w-full grid-flow-row grid-cols-3 gap-3">
2023-04-14 04:48:09 -07:00
{nfts.map((n, i) => (
2022-09-20 22:31:54 -07:00
<button
2023-04-19 18:12:45 -07:00
className={`col-span-1 flex items-center justify-center rounded-md border bg-th-bkg-2 py-3 sm:py-4 md:hover:bg-th-bkg-3 ${
2022-09-20 22:31:54 -07:00
selectedProfile === n.image
2022-11-30 19:32:32 -08:00
? 'border-th-active'
2022-09-20 22:31:54 -07:00
: 'border-th-bkg-3'
}`}
2023-04-14 04:48:09 -07:00
key={n.image + i}
2022-09-20 22:31:54 -07:00
onClick={() => setSelectedProfile(n.image)}
>
<ImgWithLoader
2023-04-14 04:48:09 -07:00
alt={n.name}
2022-09-20 22:31:54 -07:00
className="h-16 w-16 flex-shrink-0 rounded-full sm:h-20 sm:w-20"
src={n.image}
/>
</button>
))}
</div>
</div>
) : nftsLoading ? (
<div className="mb-4 grid w-full grid-flow-row grid-cols-3 gap-4">
2023-04-14 04:48:09 -07:00
{[...Array(9)].map((x, i) => (
2022-09-20 22:31:54 -07:00
<div
className="col-span-1 h-[90px] animate-pulse rounded-md bg-th-bkg-3 sm:h-28"
key={i}
/>
))}
</div>
) : (
<div className="flex h-60 items-center justify-center">
<p>{t('profile:no-nfts')}</p>
</div>
)}
</>
)
}
export default EditNftProfilePic