@@ -74,9 +74,73 @@ export interface IGapVerified {
74
74
} ;
75
75
}
76
76
77
+ export interface IGapProjectUpdate {
78
+ id : string ;
79
+ uid : Hex ;
80
+ schemaUID : Hex ;
81
+ refUID : Hex ;
82
+ attester : Hex ;
83
+ recipient : Hex ;
84
+ revoked : boolean ;
85
+ revocationTime : number ;
86
+ createdAt : string ;
87
+ updatedAt : string ;
88
+ chainID : number ;
89
+ type : string ;
90
+ data : {
91
+ title : string ;
92
+ text : string ;
93
+ startDate ?: Date ;
94
+ endDate ?: Date ;
95
+ grants ?: string [ ] ;
96
+ indicators ?: {
97
+ name : string ;
98
+ indicatorId : string ;
99
+ } [ ] ;
100
+ deliverables ?: {
101
+ name : string ;
102
+ proof : string ;
103
+ description : string ;
104
+ } [ ] ;
105
+ type : "project-update" ;
106
+ } ;
107
+ }
108
+
109
+ export interface IGapProjectIndicatorData {
110
+ id : string ;
111
+ name : string ;
112
+ description : string ;
113
+ unitOfMeasure : string ;
114
+ createdAt ?: string ;
115
+ updatedAt ?: string ;
116
+ programs : {
117
+ programId : string ;
118
+ chainID : number ;
119
+ } [ ] ;
120
+ datapoints : {
121
+ value : number | string ;
122
+ proof : string ;
123
+ startDate : string ;
124
+ endDate : string ;
125
+ outputTimestamp ?: string ;
126
+ } [ ] ;
127
+ hasData : boolean ;
128
+ isAssociatedWithPrograms : boolean ;
129
+ }
130
+
131
+ export interface IGapGrantData {
132
+ uid : string ;
133
+ details : {
134
+ data : {
135
+ title : string ;
136
+ } ;
137
+ } ;
138
+ }
139
+
77
140
export function useGap ( projectId ?: string ) {
78
141
const [ grants , setGrants ] = useState < IGapGrant [ ] > ( [ ] ) ;
79
142
const [ impacts , setImpacts ] = useState < IGapImpact [ ] > ( [ ] ) ;
143
+ const [ updates , setUpdates ] = useState < IGapProjectUpdate [ ] > ( [ ] ) ;
80
144
81
145
const getGrantsFor = async ( projectRegistryId : string ) => {
82
146
if ( ! indexerUrl ) throw new Error ( "GAP Indexer url not set." ) ;
@@ -141,6 +205,25 @@ export function useGap(projectId?: string) {
141
205
setImpacts ( [ ] ) ;
142
206
}
143
207
} ;
208
+ const getProjectUpdatesFor = async ( projectRegistryId : string ) => {
209
+ if ( ! indexerUrl ) throw new Error ( "GAP Indexer url not set." ) ;
210
+ try {
211
+ const items : IGapProjectUpdate [ ] = await fetch (
212
+ `${ indexerUrl } /grants/external-id/${ projectRegistryId } /updates`
213
+ ) . then ( ( res ) => res . json ( ) ) ;
214
+
215
+ if ( ! Array . isArray ( items ) ) {
216
+ setUpdates ( [ ] ) ;
217
+ return ;
218
+ }
219
+
220
+ setUpdates ( items ) ;
221
+ } catch ( e ) {
222
+ console . error ( `No updates found for project: ${ projectRegistryId } ` ) ;
223
+ console . error ( e ) ;
224
+ setUpdates ( [ ] ) ;
225
+ }
226
+ } ;
144
227
145
228
const { isLoading : isGrantsLoading } = useSWR (
146
229
`${ indexerUrl } /grants/external-id/${ projectId } ` ,
@@ -156,6 +239,13 @@ export function useGap(projectId?: string) {
156
239
}
157
240
) ;
158
241
242
+ const { isLoading : isUpdatesLoading } = useSWR (
243
+ projectId ? `${ indexerUrl } /grants/external-id/${ projectId } /updates` : null ,
244
+ {
245
+ fetcher : async ( ) => projectId && getProjectUpdatesFor ( projectId ) ,
246
+ }
247
+ ) ;
248
+
159
249
return {
160
250
/**
161
251
* Fetch GAP Indexer for grants for a project
@@ -178,7 +268,108 @@ export function useGap(projectId?: string) {
178
268
/**
179
269
* Loading state for grants and impacts
180
270
*/
181
- isGapLoading : isGrantsLoading || isImpactsLoading ,
271
+ isGapLoading : isGrantsLoading || isImpactsLoading || isUpdatesLoading ,
272
+ /**
273
+ * Updates for a project (loaded from GAP)
274
+ */
275
+ updates,
276
+ /**
277
+ * Loading state for updates
278
+ */
279
+ isUpdatesLoading,
280
+ } ;
281
+ }
282
+
283
+ export function useGapGrants ( projectUID ?: string ) {
284
+ const [ grants , setGrants ] = useState < IGapGrantData [ ] > ( [ ] ) ;
285
+
286
+ const {
287
+ data : grantsData ,
288
+ error : grantsError ,
289
+ isLoading : grantsLoading ,
290
+ } = useSWR (
291
+ projectUID ? `${ indexerUrl } /projects/${ projectUID } /grants` : null ,
292
+ async ( ) => {
293
+ if ( ! indexerUrl || ! projectUID ) return [ ] ;
294
+
295
+ try {
296
+ const response = await fetch (
297
+ `${ indexerUrl } /projects/${ projectUID } /grants`
298
+ ) ;
299
+
300
+ if ( ! response . ok ) {
301
+ throw new Error ( `Failed to fetch grants: ${ response . statusText } ` ) ;
302
+ }
303
+
304
+ const data : IGapGrantData [ ] = await response . json ( ) ;
305
+
306
+ if ( ! Array . isArray ( data ) ) {
307
+ console . error ( "Unexpected grants data format" , data ) ;
308
+ return [ ] ;
309
+ }
310
+
311
+ setGrants ( data ) ;
312
+ return data ;
313
+ } catch ( e ) {
314
+ console . error (
315
+ `Error fetching indicators for project: ${ projectUID } ` ,
316
+ e
317
+ ) ;
318
+ setGrants ( [ ] ) ;
319
+ return [ ] ;
320
+ }
321
+ }
322
+ ) ;
323
+
324
+ return {
325
+ grants,
326
+ grantsLoading,
327
+ grantsError,
328
+ } ;
329
+ }
330
+
331
+ export function useGapIndicators ( projectUID ?: string ) {
332
+ const [ indicators , setIndicators ] = useState < IGapProjectIndicatorData [ ] > ( [ ] ) ;
333
+
334
+ const { data, error, isLoading } = useSWR (
335
+ projectUID
336
+ ? `${ indexerUrl } /projects/${ projectUID } /indicators/data/all`
337
+ : null ,
338
+ async ( ) => {
339
+ if ( ! indexerUrl || ! projectUID ) return [ ] ;
340
+
341
+ try {
342
+ const response = await fetch (
343
+ `${ indexerUrl } /projects/${ projectUID } /indicators/data/all`
344
+ ) ;
345
+
346
+ if ( ! response . ok ) {
347
+ throw new Error ( `Failed to fetch indicators: ${ response . statusText } ` ) ;
348
+ }
349
+
350
+ const data : IGapProjectIndicatorData [ ] = await response . json ( ) ;
351
+
352
+ if ( ! Array . isArray ( data ) ) {
353
+ console . error ( "Unexpected indicators data format" , data ) ;
354
+ return [ ] ;
355
+ }
356
+
357
+ setIndicators ( data ) ;
358
+ return data ;
359
+ } catch ( e ) {
360
+ console . error (
361
+ `Error fetching indicators for project: ${ projectUID } ` ,
362
+ e
363
+ ) ;
364
+ return [ ] ;
365
+ }
366
+ }
367
+ ) ;
368
+
369
+ return {
370
+ indicators,
371
+ isLoading,
372
+ error,
182
373
} ;
183
374
}
184
375
@@ -191,3 +382,6 @@ export const getGapProjectGrantUrl = (projectUID: string, grantUID?: string) =>
191
382
192
383
export const getGapProjectImpactUrl = ( projectUID : string ) =>
193
384
`${ gapAppUrl } /project/${ projectUID } /impact` ;
385
+
386
+ export const getGapProjectUrl = ( projectUID : string ) =>
387
+ `${ gapAppUrl } /project/${ projectUID } ` ;
0 commit comments