InviteCodeDialog.tsx raw

   1  import { Button } from '@/components/ui/button'
   2  import {
   3    Dialog,
   4    DialogContent,
   5    DialogDescription,
   6    DialogHeader,
   7    DialogTitle
   8  } from '@/components/ui/dialog'
   9  import {
  10    Drawer,
  11    DrawerContent,
  12    DrawerDescription,
  13    DrawerHeader,
  14    DrawerTitle
  15  } from '@/components/ui/drawer'
  16  import { Input } from '@/components/ui/input'
  17  import { Label } from '@/components/ui/label'
  18  import { useScreenSize } from '@/providers/ScreenSizeProvider'
  19  import relayMembershipService from '@/services/relay-membership.service'
  20  import { TRelayInfo } from '@/types'
  21  import { Check, Copy } from 'lucide-react'
  22  import { useEffect, useState } from 'react'
  23  import { useTranslation } from 'react-i18next'
  24  import { toast } from 'sonner'
  25  
  26  export default function InviteCodeDialog({
  27    relayInfo,
  28    showInviteCodeDialog,
  29    setShowInviteCodeDialog
  30  }: {
  31    relayInfo: TRelayInfo
  32    showInviteCodeDialog: boolean
  33    setShowInviteCodeDialog: (open: boolean) => void
  34  }) {
  35    const { t } = useTranslation()
  36    const { isSmallScreen } = useScreenSize()
  37    const [isFetching, setIsFetching] = useState(false)
  38    const [inviteCode, setInviteCode] = useState('')
  39    const [copied, setCopied] = useState(false)
  40  
  41    useEffect(() => {
  42      if (!showInviteCodeDialog) {
  43        setInviteCode('')
  44        return
  45      }
  46  
  47      const getInviteCode = async () => {
  48        setIsFetching(true)
  49        try {
  50          if (relayInfo.pubkey) {
  51            const code = await relayMembershipService.requestInviteCode(
  52              relayInfo.url,
  53              relayInfo.pubkey
  54            )
  55            if (code) {
  56              setInviteCode(code)
  57            } else {
  58              toast.error(t('Failed to get invite code from relay'))
  59            }
  60          }
  61        } catch (error: any) {
  62          toast.error(error.message || t('Failed to get invite code'))
  63        } finally {
  64          setIsFetching(false)
  65        }
  66      }
  67      getInviteCode()
  68    }, [showInviteCodeDialog])
  69  
  70    const handleCopyInviteCode = () => {
  71      if (!inviteCode) return
  72  
  73      navigator.clipboard.writeText(inviteCode)
  74      toast.success(t('Invite code copied to clipboard'))
  75      setCopied(true)
  76  
  77      setTimeout(() => {
  78        setCopied(false)
  79      }, 2000)
  80    }
  81  
  82    const content = isFetching ? (
  83      <div className="flex items-center justify-center py-8">
  84        <div className="text-muted-foreground">{t('Loading...')}</div>
  85      </div>
  86    ) : inviteCode ? (
  87      <div className="space-y-2">
  88        <Label htmlFor="fetched-invite-code">{t('Invite Code')}</Label>
  89        <div className="flex gap-2">
  90          <Input id="fetched-invite-code" value={inviteCode} readOnly className="font-mono" />
  91          <Button onClick={handleCopyInviteCode} variant="outline">
  92            {copied ? <Check /> : <Copy />}
  93          </Button>
  94        </div>
  95        <p className="text-sm text-muted-foreground">
  96          {t('This invite code can be used by others to join the relay.')}
  97        </p>
  98      </div>
  99    ) : (
 100      <div className="text-center py-8 text-muted-foreground">
 101        {t('No invite code available from this relay.')}
 102      </div>
 103    )
 104  
 105    if (isSmallScreen) {
 106      return (
 107        <Drawer open={showInviteCodeDialog} onOpenChange={setShowInviteCodeDialog}>
 108          <DrawerContent>
 109            <DrawerHeader>
 110              <DrawerTitle>{t('Get Invite Code')}</DrawerTitle>
 111              <DrawerDescription>
 112                {t('Share this invite code with others to invite them to join this relay.')}
 113              </DrawerDescription>
 114            </DrawerHeader>
 115            <div className="p-4">{content}</div>
 116          </DrawerContent>
 117        </Drawer>
 118      )
 119    }
 120  
 121    return (
 122      <Dialog open={showInviteCodeDialog} onOpenChange={setShowInviteCodeDialog}>
 123        <DialogContent>
 124          <DialogHeader>
 125            <DialogTitle>{t('Get Invite Code')}</DialogTitle>
 126            <DialogDescription>
 127              {t('Share this invite code with others to invite them to join this relay.')}
 128            </DialogDescription>
 129          </DialogHeader>
 130          {content}
 131        </DialogContent>
 132      </Dialog>
 133    )
 134  }
 135