11"use client" ;
22import { useState , useEffect } from "react" ;
33import { createPortal } from "react-dom" ;
4- import { Info , X , GitPullRequest , Users } from "lucide-react" ;
4+ import { Info , X , GitPullRequest , Users , Copy , Check } from "lucide-react" ;
55import { ds , fontMono } from "@/lib/ds" ;
66import { getLabelChipColors } from "@/lib/labelColors" ;
77
8+ /* ── Copy text ─────────────────────────────────────────────────── */
9+ const COPY_CONTRIBUTOR = `🌟 GSSoC '26 Contributor Points System 🌟
10+
11+ Base (every approved PR):
12+ gssoc:approved = +50 pts
13+
14+ Difficulty:
15+ level:beginner = 20 pts
16+ level:intermediate = 35 pts
17+ level:advanced = 55 pts
18+ level:critical = 80 pts
19+
20+ Quality Multiplier:
21+ quality:clean = ×1.2
22+ quality:exceptional = ×1.5
23+
24+ Type Bonus:
25+ type:docs = +5 pts
26+ type:testing = +10 pts
27+ type:design = +10 pts
28+ type:refactor = +10 pts
29+ type:bug = +10 pts
30+ type:feature = +10 pts
31+ type:accessibility = +15 pts
32+ type:performance = +15 pts
33+ type:devops = +15 pts
34+ type:security = +20 pts
35+
36+ Blocking Labels:
37+ gssoc:invalid = 0 pts
38+ gssoc:spam = 0 pts
39+ gssoc:ai-slop = 0 pts
40+
41+ Example: gssoc:approved + level:advanced + quality:exceptional + type:devops = 50 + (55 × 1.5) + 15 = 147 pts
42+ Full label guide: https://gssoc.girlscript.org/guidelines/labeling` ;
43+
44+ const COPY_MENTOR = `🌟 GSSoC '26 Mentor Points System 🌟
45+
46+ Level Base (per reviewed PR):
47+ level:beginner = 10 pts
48+ level:intermediate = 20 pts
49+ level:advanced = 30 pts
50+ level:critical = 50 pts
51+
52+ Quality Bonus:
53+ quality:clean = +5 pts
54+ quality:exceptional = +10 pts
55+
56+ Example: level:advanced + quality:exceptional = 30 + 10 = 40 pts
57+ Only PRs labeled mentor:username + gssoc:approved are counted.` ;
58+
859/* ── Contributor data ────────────────────────────────────────── */
960const C_DIFF = [
1061 { label : "level:beginner" , value : "20 pts" } ,
@@ -161,12 +212,19 @@ function MentorTab() {
161212/* ── Modal ───────────────────────────────────────────────────── */
162213function Modal ( { onClose } : { onClose : ( ) => void } ) {
163214 const [ tab , setTab ] = useState < "contributor" | "mentor" > ( "contributor" ) ;
215+ const [ copied , setCopied ] = useState ( false ) ;
164216
165217 const tabs = [
166218 { id : "contributor" as const , label : "Contributor" , icon : < GitPullRequest size = { 12 } /> , accent : ds . primaryDeep , activeBg : "rgba(62,207,142,0.08)" , activeBorder : ds . primaryDeep } ,
167219 { id : "mentor" as const , label : "Mentor" , icon : < Users size = { 12 } /> , accent : "#ca8a04" , activeBg : "rgba(251,191,36,0.08)" , activeBorder : "#ca8a04" } ,
168220 ] ;
169221
222+ const handleCopy = ( ) => {
223+ navigator . clipboard . writeText ( tab === "contributor" ? COPY_CONTRIBUTOR : COPY_MENTOR ) ;
224+ setCopied ( true ) ;
225+ setTimeout ( ( ) => setCopied ( false ) , 2000 ) ;
226+ } ;
227+
170228 return createPortal (
171229 < div
172230 className = "light"
@@ -180,9 +238,17 @@ function Modal({ onClose }: { onClose: () => void }) {
180238 { /* Header */ }
181239 < div style = { { padding : "16px 20px 14px" , borderBottom : `1px solid ${ ds . hairlineCool } ` , display : "flex" , alignItems : "center" , justifyContent : "space-between" , flexShrink : 0 } } >
182240 < p style = { { margin : 0 , fontSize : 15 , fontWeight : 700 , color : ds . ink } } > Points System</ p >
183- < button onClick = { onClose } style = { { width : 28 , height : 28 , border : `1px solid ${ ds . hairlineCool } ` , borderRadius : ds . rSm , background : "transparent" , color : ds . inkMute2 , cursor : "pointer" , display : "flex" , alignItems : "center" , justifyContent : "center" } } >
184- < X size = { 14 } />
185- </ button >
241+ < div style = { { display : "flex" , gap : 8 , alignItems : "center" } } >
242+ < button
243+ onClick = { handleCopy }
244+ style = { { display : "inline-flex" , alignItems : "center" , gap : 5 , padding : "5px 10px" , borderRadius : ds . rSm , border : `1px solid ${ copied ? "rgba(62,207,142,0.4)" : ds . hairlineCool } ` , background : copied ? "rgba(62,207,142,0.08)" : "transparent" , color : copied ? ds . primaryDeep : ds . inkMute2 , fontSize : 11 , fontWeight : 600 , cursor : "pointer" , transition : "all 0.15s" } }
245+ >
246+ { copied ? < Check size = { 12 } /> : < Copy size = { 12 } /> } { copied ? "Copied" : "Copy" }
247+ </ button >
248+ < button onClick = { onClose } style = { { width : 28 , height : 28 , border : `1px solid ${ ds . hairlineCool } ` , borderRadius : ds . rSm , background : "transparent" , color : ds . inkMute2 , cursor : "pointer" , display : "flex" , alignItems : "center" , justifyContent : "center" } } >
249+ < X size = { 14 } />
250+ </ button >
251+ </ div >
186252 </ div >
187253
188254 { /* Tabs */ }
0 commit comments