diff --git a/src/app/nfts/share/[id]/layout.tsx b/src/app/nfts/share/[id]/layout.tsx new file mode 100644 index 0000000..d231c94 --- /dev/null +++ b/src/app/nfts/share/[id]/layout.tsx @@ -0,0 +1,13 @@ +'use client' + +import MainLayout from 'src/layouts/main' + +// ---------------------------------------------------------------------- + +type Props = { + children: React.ReactNode +} + +export default function Layout({ children }: Props) { + return {children} +} diff --git a/src/app/nfts/share/[id]/page.tsx b/src/app/nfts/share/[id]/page.tsx new file mode 100644 index 0000000..94253fa --- /dev/null +++ b/src/app/nfts/share/[id]/page.tsx @@ -0,0 +1,11 @@ +import NftShareView from 'src/sections/nfts/view/nft-share-view' + +// ---------------------------------------------------------------------- + +export const metadata = { + title: 'NFT Share' +} + +export default function NftMintPage({ params }: { params: { id: string } }) { + return +} diff --git a/src/app/nfts/share/page.tsx b/src/app/nfts/share/page.tsx new file mode 100644 index 0000000..e0c8ab5 --- /dev/null +++ b/src/app/nfts/share/page.tsx @@ -0,0 +1,7 @@ +import { redirect } from 'next/navigation' + +// ---------------------------------------------------------------------- + +export default function Share() { + return redirect('/') +} diff --git a/src/locales/langs/br.json b/src/locales/langs/br.json index 527eb7a..2181f0d 100644 --- a/src/locales/langs/br.json +++ b/src/locales/langs/br.json @@ -11,7 +11,7 @@ "required": "obrigatório", "must-be-numeric": "Deve ser numérico", "must-be-max": "Deve ter no máximo {MAX_DIGITS} dígitos", - "must-be-valid-email": "O email deve ser um endereço de email válido", + "must-be-valid-email": "O email deve ser um endereço de email válido", "must-be-min": "Deve ter no mínimo {MIN_CHARS} caracteres", "nodata": "Sem Dados", "save": "Salvar Alterações", @@ -250,7 +250,7 @@ "answer": "Digite seu número de telefone registrado. Um código de 6 dígitos será enviado para o seu telefone por segurança; depois de inseri-lo, você poderá acessar o site." } } - }, + }, "get-started": { "title": "Comece com", "description": "Todo o poder do Web3 sem complicações.", @@ -310,8 +310,8 @@ "transfer-all": { "info": "Indica um endereço de carteira para onde serão enviados todos os fundos que você possui no Chatterpay.", "msgs": { - "ok": "Os fundos foram transferidos. Você os verá na carteira indicada em breve.", - "error": "Houve um erro ao tentar transferir os fundos." + "ok": "Os fundos foram transferidos. Você os verá na carteira indicada em breve.", + "error": "Houve um erro ao tentar transferir os fundos." }, "actions": { "transfer": "Transferir Tudo" @@ -335,6 +335,10 @@ "cta-msg": "Reivindique seu certificado na blockchain gratuitamente!", "opensea-alt": "logo open sea", "wapp-msg": "Gostaria de mintar o NFT" + }, + "share": { + "cta": "Compartilhar certificado", + "clipboard": "Link copiado!" } }, "account": { @@ -352,4 +356,4 @@ "code-bot": "Insira este código {2FA_CODE} para validar a alteração do seu e-mail no Chatterpay. É muito importante que você não compartilhe esta informação com ninguém. Se você não solicitou o código, desconsidere esta mensagem e entre em contato conosco para que possamos ajudá-lo!" } } -} +} \ No newline at end of file diff --git a/src/locales/langs/en.json b/src/locales/langs/en.json index 92815ce..0cf153e 100644 --- a/src/locales/langs/en.json +++ b/src/locales/langs/en.json @@ -38,8 +38,8 @@ }, "home": { "header": { - "sign-up": "Create your account", - "sign-in": "Sign in" + "sign-up": "Create your account", + "sign-in": "Sign in" }, "help": { "need-help": "Need help?" @@ -293,12 +293,12 @@ "send": "Send", "transfer-all": "Transfer All", "wapp-msg": "Hi!" - }, + }, "transactions": { "title": "Recent Transactions", "table-transaction": "Transaction", "table-amount": "Amount", - "table-date": "Date", + "table-date": "Date", "table-status": "Status", "table-view-all": "View All", "table-download": "Download", @@ -310,8 +310,8 @@ "transfer-all": { "info": "Indicates a wallet address where all funds in Chatterpay will be sent.", "msgs": { - "ok": "The funds were transferred. You will see them in the indicated wallet shortly.", - "error": "There was an error attempting to transfer the funds." + "ok": "The funds were transferred. You will see them in the indicated wallet shortly.", + "error": "There was an error attempting to transfer the funds." }, "actions": { "transfer": "Transfer All" @@ -335,6 +335,10 @@ "cta-msg": "Claim your certificate on the blockchain for free!", "opensea-alt": "open sea logo", "wapp-msg": "I would like to mint the NFT" + }, + "share": { + "cta": "Share", + "clipboard": "Link copied!" } }, "account": { diff --git a/src/locales/langs/es.json b/src/locales/langs/es.json index 3f6377e..c714799 100644 --- a/src/locales/langs/es.json +++ b/src/locales/langs/es.json @@ -102,7 +102,7 @@ "home": { "header": { "sign-up": "Creá tu cuenta", - "sign-in": "Ingresá" + "sign-in": "Ingresá" }, "help": { "need-help": "¿Necesita ayuda?" @@ -250,7 +250,7 @@ "answer": "Ingresa tu número de teléfono registrado. Se enviará un código de 6 dígitos a tu teléfono por seguridad; una vez que lo ingreses, podrás acceder al sitio." } } - }, + }, "get-started": { "title": "Comienza con", "description": "Todo el poder de Web3 sin complicaciones.", @@ -329,13 +329,16 @@ "meta-geo": "Geolocalización", "original": "Original", "copy-of": "Copia #{X} de #{Z}" - }, "claim": { "cta": "Reclamar", "cta-msg": "¡Reclamá tu certificado en blockchain gratis!", "opensea-alt": "logo open sea", "wapp-msg": "Me gustaría mintear el NFT" + }, + "share": { + "cta": "Compartir", + "clipboard": "Link copiado!" } }, "account": { @@ -353,4 +356,4 @@ "code-bot": "Ingresá este código *{2FA_CODE}* para validar tu cambio de correo electrónico en Chatterpay. Es muy importante que no compartas esta información con nadie. Si no solicitaste el código, desestimá este mensaje y contactate con nosotros para que podamos ayudarte!" } } -} +} \ No newline at end of file diff --git a/src/sections/nfts/nft-item-share.tsx b/src/sections/nfts/nft-item-share.tsx new file mode 100644 index 0000000..3c4ac32 --- /dev/null +++ b/src/sections/nfts/nft-item-share.tsx @@ -0,0 +1,218 @@ +import Image from 'next/image' +import { useState } from 'react' +import { m } from 'framer-motion' +import { Icon } from '@iconify/react' +import { useSnackbar } from 'notistack' + +import { Box, Stack } from '@mui/system' +import { + Card, + Button, + Dialog, + IconButton, + Typography, + DialogTitle, + DialogActions, + DialogContent +} from '@mui/material' + +import { useResponsive } from 'src/hooks/use-responsive' + +import { useTranslate } from 'src/locales' +import { NFT_MARKETPLACE_URL, NFT_IMAGE_REPOSITORY } from 'src/config-global' + +import { varFade } from 'src/components/animate' + +import { INFT, ImageURLRepository } from 'src/types/wallet' + +// ---------------------------------------------------------------------- + +type NftItemClaimProps = { + nftId: string + nftData: INFT +} + +export default function NftItemShare({ nftId, nftData }: NftItemClaimProps) { + const mdUp = useResponsive('up', 'md') + const { t } = useTranslate() + const [openShare, setOpenShare] = useState(false) + const { enqueueSnackbar } = useSnackbar() + + const handleOpenOpenSea = () => { + const url = `${NFT_MARKETPLACE_URL}/${nftId}` + window.open(url, '_blank') + } + + const handleShare = (platform: string) => { + const nftUrl = `${NFT_MARKETPLACE_URL}/${nftId}` + const text = nftData.metadata.description + + const shareUrls = { + twitter: `https://twitter.com/intent/tweet?text=${encodeURIComponent(text)}&url=${encodeURIComponent(nftUrl)}`, + facebook: `https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(nftUrl)}`, + whatsapp: `https://wa.me/?text=${encodeURIComponent(`${text} ${nftUrl}`)}`, + linkedin: `https://www.linkedin.com/sharing/share-offsite/?url=${encodeURIComponent(nftUrl)}` + } as const + + window.open(shareUrls[platform as keyof typeof shareUrls], '_blank') + } + + const handleCopyLink = async () => { + try { + await navigator.clipboard.writeText(`${NFT_MARKETPLACE_URL}/${nftId}`) + enqueueSnackbar(t('nfts.share.clipboard'), { variant: 'info' }) + } catch (err) { + console.error('Error al copiar:', err) + } + } + + let imageUrl = nftData.metadata.image_url[NFT_IMAGE_REPOSITORY as ImageURLRepository] + ? nftData.metadata.image_url[NFT_IMAGE_REPOSITORY as ImageURLRepository] + : nftData.metadata.image_url.gcp + imageUrl = imageUrl || '/assets/images/nfts/default_nft.png' + + const handleTriggerShare = async () => { + if (!openShare && !navigator.share) { + try { + await navigator.share({ + title: nftData.metadata.description, + url: `${NFT_MARKETPLACE_URL}/${nftId}` + }) + } catch (err) { + console.error('Error al compartir:', err) + } + } else { + setOpenShare(!openShare) + } + } + + const socialButtons = [ + { icon: 'ri:twitter-x-fill', name: 'Twitter', action: () => handleShare('twitter') }, + { icon: 'ri:whatsapp-fill', name: 'WhatsApp', action: () => handleShare('whatsapp') }, + { icon: 'ri:linkedin-box-fill', name: 'LinkedIn', action: () => handleShare('linkedin') }, + { icon: 'ri:facebook-circle-fill', name: 'Facebook', action: () => handleShare('facebook') }, + { icon: 'ri:links-fill', name: 'Copiar Link', action: handleCopyLink } + ] + + return ( + + + + {nftData.metadata.description} + + + + + + {nftData.metadata.description} + + + {/* Botones flotantes */} + + + setOpenShare(true)} + sx={{ + backgroundColor: 'white', + '&:hover': { backgroundColor: 'rgba(255,255,255,0.9)' } + }} + > + + + + + + {t('nfts.claim.opensea-alt')} + + + + + + + + + + {/* Diálogo de compartir */} + + {t('nfts.share.cta')} + + + {socialButtons.map((button) => ( + + ))} + + + + + + + + ) +} diff --git a/src/sections/nfts/view/nft-share-view.tsx b/src/sections/nfts/view/nft-share-view.tsx new file mode 100644 index 0000000..3f327f8 --- /dev/null +++ b/src/sections/nfts/view/nft-share-view.tsx @@ -0,0 +1,50 @@ +'use client' + +import Container from '@mui/material/Container' + +import { useTranslate } from 'src/locales' +import { useGetNftById } from 'src/app/api/_hooks' + +import EmptyContent from 'src/components/empty-content' +import { useSettingsContext } from 'src/components/settings' +import { LoadingScreen } from 'src/components/loading-screen' + +import { INFT } from 'src/types/wallet' + +import NftItemShare from '../nft-item-share' + +// ---------------------------------------------------------------------- + +type NftItemProps = { + nftId: string +} +export default function NftShareView({ nftId }: NftItemProps) { + const { t } = useTranslate() + const settings = useSettingsContext() + + const { + data: nftData, + isLoading + }: { + data: INFT + isLoading: boolean + } = useGetNftById(nftId) + + const notFound = !nftData + + const renderContent = ( + <> + {notFound ? ( + + ) : ( + + )} + + ) + + return ( + + {isLoading ? : renderContent} + + ) +}