Skip to content

Commit a81e655

Browse files
Add auto-copy to clipboard on scan
1 parent bee98dd commit a81e655

1 file changed

Lines changed: 32 additions & 6 deletions

File tree

src/pages/RFIDReader.tsx

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import { rfidService } from "@/services/rfid.service";
77
import type { Team } from "@/types/team";
88
import type { Participant } from "@/types/user";
99
import { 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";
1112
import { useNavigate } from "react-router-dom";
1213

1314
export 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

Comments
 (0)