1- "use client" ;
2-
3- import RichText from "@/components/RichText" ;
4- import { useEffect , useState } from "react" ;
5-
6- interface GitHubIssue {
7- id : number ;
8- title : string ;
9- html_url : string ;
10- repository_url : string ;
11- }
12-
13- export default function GoodFirstIssues ( ) {
14- const [ issues , setIssues ] = useState < GitHubIssue [ ] > ( [ ] ) ;
15-
16- //New
17- const [ loading , setLoading ] = useState ( false ) ;
18- const [ error , setError ] = useState < string | null > ( null ) ;
19-
20- // Filters
21- const [ difficulty , setDifficulty ] = useState ( "good first issue" ) ;
22- const [ sdk , setSdk ] = useState ( "" ) ;
23-
24- // Maps
25- const difficultyMap = {
26- "good first issue" : 'label:"good first issue"' ,
27- beginner : "label:beginner" ,
28- intermediate : "label:intermediate" ,
29- advanced : "label:advanced" ,
30- } as const ;
31-
32- const sdkMap = {
33- python : "repo:hiero-ledger/hiero-sdk-python" ,
34- javascript : "repo:hiero-ledger/hiero-sdk-js" ,
35- cpp : "repo:hiero-ledger/hiero-sdk-cpp" ,
36- java : "repo:hiero-ledger/hiero-sdk-java" ,
37- go : "repo:hiero-ledger/hiero-sdk-go" ,
38- } as const ;
39-
40- const buildQuery = ( ) => {
41- let q = "is:issue state:open" ;
42-
43- const getSdkValue = ( key : string | null ) => {
44- if ( key && key in sdkMap ) {
45- return sdkMap [ key as keyof typeof sdkMap ] ;
46- }
47- return undefined ;
48- } ;
49-
50- const getDifficultyValue = ( key : string | null ) => {
51- if ( key && key in difficultyMap ) {
52- return difficultyMap [ key as keyof typeof difficultyMap ] ;
53- }
54- return undefined ;
55- } ;
56-
57- const sdkValue = getSdkValue ( sdk ) ;
58- const difficultyValue = getDifficultyValue ( difficulty ) ;
59-
60- if ( sdkValue ) {
61- q += ` ${ sdkValue } ` ;
62- } else {
63- q += " org:hiero-ledger" ;
64- }
65-
66- if ( difficultyValue ) {
67- q += ` ${ difficultyValue } ` ;
68- }
69-
70- return q ;
71- } ;
72-
73- useEffect ( ( ) => {
74- console . log ( "Fetching issues with difficulty:" , difficulty , "and sdk:" , sdk ) ;
75- const fetchIssues = async ( ) => {
76- const query = buildQuery ( ) ;
77-
78- console . log ( "Constructed query:" , query ) ;
79- setLoading ( true ) ;
80- setError ( null ) ;
81-
82- try {
83- const res = await fetch (
84- `/api/issues?q= ${ encodeURIComponent ( query ) } `
85- ) ;
86- console . log ( "API response status:" , res . status ) ;
87- const data = await res . json ( ) ;
88- console . log ( "API response data:" , data ) ;
89- console . log ( "RETURNING DATA :" , JSON . stringify ( data ) . slice ( 0 , 300 ) ) ;
90- if ( ! res . ok ) {
91- throw new Error ( data ?. error || "Failed to fetch issues" ) ;
92- }
93-
94- setIssues ( data . items ?? [ ] ) ;
95- } catch ( err ) {
96- console . error ( "Failed to fetch issues:" , err ) ;
97- setError (
98- err instanceof Error ? err . message : "Unknown error occurred"
99- ) ;
100- setIssues ( [ ] ) ;
101- } finally {
102- setLoading ( false ) ;
103- }
104- } ;
105-
106- void fetchIssues ( ) ;
107- } , [ difficulty , sdk ] ) ;
108-
109- return (
110- < div >
111- { /* Filters */ }
112- < div className = "flex gap-4 mb-6" >
113- < select
114- value = { difficulty }
115- onChange = { ( e ) => {
116- setDifficulty ( e . target . value ) ;
117- } }
118- className = "p-2 rounded border"
119- >
120- < option value = "good first issue" > Good First Issue</ option >
121- < option value = "beginner" > Beginner</ option >
122- < option value = "intermediate" > Intermediate</ option >
123- < option value = "advanced" > Advanced</ option >
124- </ select >
125-
126- < select
127- value = { sdk }
128- onChange = { ( e ) => { setSdk ( e . target . value ) } }
129- className = "p-2 rounded border"
130- >
131- < option value = "" > All Repo's </ option >
132- < option value = "python" > Python </ option >
133- < option value = "javascript" > JavaScript </ option >
134- < option value = "cpp" > C++ </ option >
135- < option value = "java" > Java </ option >
136- < option value = "go" > Go </ option >
137- </ select >
138- </ div >
139-
140- { /* Issues Grid */ }
141- < div className = "grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6" >
142- { issues . map ( ( issue ) => (
143- < div
144- key = { issue . id }
145- className = "bg-gradient-to-br from-white-dark via-white to-white p-4 rounded-xl shadow-md"
146- >
147- < a href = { issue . html_url } target = "_blank" rel = "noopener noreferrer" >
148- < RichText markdown = { issue . title } />
149- </ a >
150- < p className = "text-sm opacity-70 mt-2" >
151- { issue . repository_url . split ( "/" ) . pop ( ) }
152- </ p >
153- </ div >
154- ) ) }
155- </ div >
156- </ div >
157- ) ;
158- }
1+ "use client" ;
2+
3+ import RichText from "@/components/RichText" ;
4+ import { useEffect , useState } from "react" ;
5+
6+ interface GitHubIssue {
7+ id : number ;
8+ title : string ;
9+ html_url : string ;
10+ repository_url : string ;
11+ }
12+
13+ export default function GoodFirstIssues ( ) {
14+ const [ issues , setIssues ] = useState < GitHubIssue [ ] > ( [ ] ) ;
15+
16+ //New
17+ const [ loading , setLoading ] = useState ( false ) ;
18+ const [ error , setError ] = useState < string | null > ( null ) ;
19+
20+ // Filters
21+ const [ difficulty , setDifficulty ] = useState ( "good first issue" ) ;
22+ const [ sdk , setSdk ] = useState ( "" ) ;
23+
24+ // Maps
25+ const difficultyMap = {
26+ "good first issue" : 'label:"good first issue"' ,
27+ beginner : "label:beginner" ,
28+ intermediate : "label:intermediate" ,
29+ advanced : "label:advanced" ,
30+ } as const ;
31+
32+ const sdkMap = {
33+ python : "repo:hiero-ledger/hiero-sdk-python" ,
34+ javascript : "repo:hiero-ledger/hiero-sdk-js" ,
35+ cpp : "repo:hiero-ledger/hiero-sdk-cpp" ,
36+ java : "repo:hiero-ledger/hiero-sdk-java" ,
37+ go : "repo:hiero-ledger/hiero-sdk-go" ,
38+ } as const ;
39+
40+ const buildQuery = ( ) => {
41+ let q = "is:issue state:open" ;
42+
43+ const getSdkValue = ( key : string | null ) => {
44+ if ( key && key in sdkMap ) {
45+ return sdkMap [ key as keyof typeof sdkMap ] ;
46+ }
47+ return undefined ;
48+ } ;
49+
50+ const getDifficultyValue = ( key : string | null ) => {
51+ if ( key && key in difficultyMap ) {
52+ return difficultyMap [ key as keyof typeof difficultyMap ] ;
53+ }
54+ return undefined ;
55+ } ;
56+
57+ const sdkValue = getSdkValue ( sdk ) ;
58+ const difficultyValue = getDifficultyValue ( difficulty ) ;
59+
60+ if ( sdkValue ) {
61+ q += ` ${ sdkValue } ` ;
62+ } else {
63+ q += " org:hiero-ledger" ;
64+ }
65+
66+ if ( difficultyValue ) {
67+ q += ` ${ difficultyValue } ` ;
68+ }
69+
70+ return q ;
71+ } ;
72+
73+ useEffect ( ( ) => {
74+ console . log (
75+ "Fetching issues with difficulty:" ,
76+ difficulty ,
77+ "and sdk:" ,
78+ sdk ,
79+ ) ;
80+ const fetchIssues = async ( ) => {
81+ const query = buildQuery ( ) ;
82+
83+ console . log ( "Constructed query:" , query ) ;
84+ setLoading ( true ) ;
85+ setError ( null ) ;
86+
87+ try {
88+ const res = await fetch ( `/api/issues?q= ${ encodeURIComponent ( query ) } ` ) ;
89+ console . log ( "API response status :" , res . status ) ;
90+ const data = await res . json ( ) ;
91+ console . log ( "API response data:" , data ) ;
92+ console . log ( "RETURNING DATA:" , JSON . stringify ( data ) . slice ( 0 , 300 ) ) ;
93+ if ( ! res . ok ) {
94+ throw new Error ( data ?. error || "Failed to fetch issues" ) ;
95+ }
96+
97+ setIssues ( data . items ?? [ ] ) ;
98+ } catch ( err ) {
99+ console . error ( "Failed to fetch issues:" , err ) ;
100+ setError ( err instanceof Error ? err . message : "Unknown error occurred" ) ;
101+ setIssues ( [ ] ) ;
102+ } finally {
103+ setLoading ( false ) ;
104+ }
105+ } ;
106+
107+ void fetchIssues ( ) ;
108+ } , [ difficulty , sdk ] ) ;
109+
110+ return (
111+ < div >
112+ { /* Filters */ }
113+ < div className = "flex gap-4 mb-6" >
114+ < select
115+ value = { difficulty }
116+ onChange = { e => {
117+ setDifficulty ( e . target . value ) ;
118+ } }
119+ className = "p-2 rounded border" >
120+ < option value = "good first issue" > Good First Issue</ option >
121+ < option value = "beginner" > Beginner</ option >
122+ < option value = "intermediate" > Intermediate</ option >
123+ < option value = "advanced" > Advanced</ option >
124+ </ select >
125+
126+ < select
127+ value = { sdk }
128+ onChange = { e => {
129+ setSdk ( e . target . value ) ;
130+ } }
131+ className = "p-2 rounded border" >
132+ < option value = "" > All Repo's </ option >
133+ < option value = "python" > Python </ option >
134+ < option value = "javascript" > JavaScript </ option >
135+ < option value = "cpp" > C++ </ option >
136+ < option value = "java" > Java </ option >
137+ < option value = "go" > Go </ option >
138+ </ select >
139+ </ div >
140+
141+ { /* Issues Grid */ }
142+ < div className = "grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6" >
143+ { issues . map ( issue => (
144+ < div
145+ key = { issue . id }
146+ className = "bg-gradient-to-br from-white-dark via-white to-white p-4 rounded-xl shadow-md" >
147+ < a href = { issue . html_url } target = "_blank" rel = "noopener noreferrer" >
148+ < RichText markdown = { issue . title } />
149+ </ a >
150+ < p className = "text-sm opacity-70 mt-2" >
151+ { issue . repository_url . split ( "/" ) . pop ( ) }
152+ </ p >
153+ </ div >
154+ ) ) }
155+ </ div >
156+ </ div >
157+ ) ;
158+ }
0 commit comments