@@ -7,7 +7,8 @@ import { rfidService } from "@/services/rfid.service";
77import type { Team } from "@/types/team" ;
88import type { Participant } from "@/types/user" ;
99import { useAtomValue } from "jotai" ;
10- import { useEffect , useRef , useState } from "react" ;
10+ import { Check , Clipboard } from "lucide-react" ;
11+ import { useCallback , useEffect , useRef , useState } from "react" ;
1112import { useNavigate } from "react-router-dom" ;
1213
1314export default function RFIDReader ( ) {
@@ -32,6 +33,13 @@ export default function RFIDReader() {
3233 const [ showActivityAssignedToast , setShowActivityAssignedToast ] = useState <
3334 "hidden" | "success" | "alreadyAttended"
3435 > ( "hidden" ) ;
36+ const [ copied , setCopied ] = useState ( false ) ;
37+
38+ const copyToClipboard = useCallback ( ( text : string ) => {
39+ navigator . clipboard . writeText ( text ) ;
40+ setCopied ( true ) ;
41+ setTimeout ( ( ) => setCopied ( false ) , 1500 ) ;
42+ } , [ ] ) ;
3543
3644 useEffect ( ( ) => {
3745 if ( ! rfidService . isSupported ( ) ) {
@@ -66,6 +74,8 @@ export default function RFIDReader() {
6674 setShowActivityAssignedToast ( "hidden" ) ;
6775 setRfidData ( uuid ) ;
6876
77+ copyToClipboard ( uuid ) ;
78+
6979 setRfidParticipant ( undefined ) ;
7080 setTeam ( null ) ;
7181
@@ -162,8 +172,8 @@ export default function RFIDReader() {
162172
163173 < p className = "mt-4" >
164174 Choose whether the user should receive attendance for an
165- activity when they tap their card. No need to use this for
166- check-in.
175+ activity when they tap their card.
176+ < strong > No need to use this for check-in.</ strong >
167177 < br /> * means this activity is not eligible for the raffle.
168178 </ p >
169179
@@ -208,9 +218,25 @@ export default function RFIDReader() {
208218 { rfidData && (
209219 < >
210220 < p className = "mt-4" > The card has the following ID:</ p >
211- < p className = "font-mono text-lg text-muted-foreground" >
212- { rfidData }
213- </ p >
221+ < button
222+ type = "button"
223+ className = "mt-1 inline-flex items-center gap-2 font-mono text-lg text-muted-foreground cursor-pointer hover:text-foreground transition-colors"
224+ onClick = { ( ) => copyToClipboard ( rfidData ) }
225+ >
226+ < span className = "underline decoration-dashed underline-offset-4" >
227+ { rfidData }
228+ </ span >
229+ { copied ? (
230+ < >
231+ < Check className = "size-4 text-green-500" />
232+ < span className = "text-sm text-green-500 font-sans" >
233+ Copied to clipboard!
234+ </ span >
235+ </ >
236+ ) : (
237+ < Clipboard className = "size-4" />
238+ ) }
239+ </ button >
214240 </ >
215241 ) }
216242 { rfidParticipant ? (
0 commit comments