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