@@ -4,20 +4,24 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
44import { createClient } from "../lib/supabase/client" ;
55import Link from "next/link" ;
66import { useState } from "react" ;
7- import { faKey , faTrash } from "@fortawesome/free-solid-svg-icons" ;
7+ import { faKey , faRefresh , faTrash } from "@fortawesome/free-solid-svg-icons" ;
88import { toast } from "react-toastify" ;
9+ import { Leaderboard } from "./dashboard/LeaderbordList" ;
10+ import { User } from "@supabase/supabase-js" ;
911
1012export default function BoardList ( {
13+ user,
1114 board,
1215} : {
13- board : { id : string ; name : string ; slug : string ; join_code : string } ;
16+ user : User ;
17+ board : Leaderboard ;
1418} ) {
19+ const supabase = createClient ( ) ;
1520 const [ showCodeModal , setShowCodeModal ] = useState ( false ) ;
1621 const [ selectedCode , setSelectedCode ] = useState < string | null > ( null ) ;
1722 const [ showDeleteModal , setShowDeleteModal ] = useState ( false ) ;
1823
1924 const handleDelete = async ( ) => {
20- const supabase = await createClient ( ) ;
2125 const { error } = await supabase
2226 . from ( "leaderboards" )
2327 . delete ( )
@@ -27,6 +31,74 @@ export default function BoardList({
2731 window . location . reload ( ) ;
2832 } ;
2933
34+ const regenerateJoinCode = ( boardId : string ) => {
35+ const generateJoinCode = new Promise ( async ( resolve , reject ) => {
36+ try {
37+ const joinCode = crypto . randomUUID ( ) . slice ( 0 , 8 ) ;
38+ const { data, error } = await supabase
39+ . from ( "leaderboards" )
40+ . update ( { join_code : joinCode } )
41+ . eq ( "id" , boardId )
42+ . select ( )
43+ . single ( ) ;
44+
45+ if ( error ) return reject ( error ) ;
46+
47+ resolve ( data ) ;
48+ } catch ( error ) {
49+ reject ( error ) ;
50+ }
51+ } ) ;
52+
53+ toast . promise ( generateJoinCode , {
54+ pending : "Generating new join code..." ,
55+ success : "Successfully generated new join code." ,
56+ error : {
57+ render ( { data } ) {
58+ const err = data as Error ;
59+ return (
60+ err ?. message ||
61+ "Failed to generate new join code. Please try again."
62+ ) ;
63+ } ,
64+ } ,
65+ } ) ;
66+ } ;
67+
68+ const getJoinCode = ( boardId : string ) => {
69+ const joinCode : Promise < { join_code : string } [ ] > = new Promise (
70+ async ( resolve , reject ) => {
71+ try {
72+ const { data, error } = await supabase
73+ . from ( "leaderboards" )
74+ . select ( "join_code" )
75+ . eq ( "id" , boardId )
76+
77+ if ( error ) return reject ( error ) ;
78+
79+ resolve ( data ) ;
80+ } catch ( error ) {
81+ reject ( error ) ;
82+ }
83+ } ,
84+ ) ;
85+
86+ toast . promise ( joinCode , {
87+ pending : "Getting join code..." ,
88+ error : {
89+ render ( { data } ) {
90+ const err = data as Error ;
91+ return err ?. message || "Failed to get join code. Please try again." ;
92+ } ,
93+ } ,
94+ } ) ;
95+
96+ joinCode . then ( ( data ) => {
97+ setSelectedCode ( data [ 0 ] . join_code ) ;
98+ setShowCodeModal ( true ) ;
99+ } ) ;
100+ } ;
101+
30102 return (
31103 < >
32104 < div
@@ -39,23 +111,31 @@ export default function BoardList({
39111 </ p >
40112 </ Link >
41113
42- < div className = "flex items-center gap-2" >
43- < button
44- onClick = { ( ) => setShowDeleteModal ( true ) }
45- className = "p-2 rounded-lg text-gray-600 hover:text-red-400 hover:bg-red-500/10 transition"
46- >
47- < FontAwesomeIcon icon = { faTrash } className = "text-xs" />
48- </ button >
49- < button
50- onClick = { ( ) => {
51- setSelectedCode ( board . join_code ) ;
52- setShowCodeModal ( true ) ;
53- } }
54- className = "p-2 rounded-lg text-gray-600 hover:text-indigo-400 hover:bg-indigo-500/10 transition"
55- >
56- < FontAwesomeIcon icon = { faKey } className = "text-xs" />
57- </ button >
58- </ div >
114+ { user . id === board . owner_id && (
115+ < div className = "flex items-center gap-2" >
116+ < button
117+ onClick = { ( ) => setShowDeleteModal ( true ) }
118+ className = "p-2 rounded-lg text-gray-600 hover:text-red-400 hover:bg-red-500/10 transition"
119+ title = "Delete Leaderboard"
120+ >
121+ < FontAwesomeIcon icon = { faTrash } className = "text-xs" />
122+ </ button >
123+ < button
124+ onClick = { ( ) => regenerateJoinCode ( board . id ) }
125+ className = "p-2 rounded-lg text-gray-600 hover:text-indigo-400 hover:bg-indigo-500/10 transition"
126+ title = "Regenerate Join Code"
127+ >
128+ < FontAwesomeIcon icon = { faRefresh } className = "text-xs" />
129+ </ button >
130+ < button
131+ onClick = { ( ) => getJoinCode ( board . id ) }
132+ className = "p-2 rounded-lg text-gray-600 hover:text-indigo-400 hover:bg-indigo-500/10 transition"
133+ title = "View Join Code"
134+ >
135+ < FontAwesomeIcon icon = { faKey } className = "text-xs" />
136+ </ button >
137+ </ div >
138+ ) }
59139 </ div >
60140
61141 { showCodeModal && (
0 commit comments