@@ -74,9 +74,73 @@ export interface IGapVerified {
7474 } ;
7575}
7676
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+
77140export function useGap ( projectId ?: string ) {
78141 const [ grants , setGrants ] = useState < IGapGrant [ ] > ( [ ] ) ;
79142 const [ impacts , setImpacts ] = useState < IGapImpact [ ] > ( [ ] ) ;
143+ const [ updates , setUpdates ] = useState < IGapProjectUpdate [ ] > ( [ ] ) ;
80144
81145 const getGrantsFor = async ( projectRegistryId : string ) => {
82146 if ( ! indexerUrl ) throw new Error ( "GAP Indexer url not set." ) ;
@@ -141,6 +205,25 @@ export function useGap(projectId?: string) {
141205 setImpacts ( [ ] ) ;
142206 }
143207 } ;
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+ } ;
144227
145228 const { isLoading : isGrantsLoading } = useSWR (
146229 `${ indexerUrl } /grants/external-id/${ projectId } ` ,
@@ -156,6 +239,13 @@ export function useGap(projectId?: string) {
156239 }
157240 ) ;
158241
242+ const { isLoading : isUpdatesLoading } = useSWR (
243+ projectId ? `${ indexerUrl } /grants/external-id/${ projectId } /updates` : null ,
244+ {
245+ fetcher : async ( ) => projectId && getProjectUpdatesFor ( projectId ) ,
246+ }
247+ ) ;
248+
159249 return {
160250 /**
161251 * Fetch GAP Indexer for grants for a project
@@ -178,7 +268,108 @@ export function useGap(projectId?: string) {
178268 /**
179269 * Loading state for grants and impacts
180270 */
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,
182373 } ;
183374}
184375
@@ -191,3 +382,6 @@ export const getGapProjectGrantUrl = (projectUID: string, grantUID?: string) =>
191382
192383export const getGapProjectImpactUrl = ( projectUID : string ) =>
193384 `${ gapAppUrl } /project/${ projectUID } /impact` ;
385+
386+ export const getGapProjectUrl = ( projectUID : string ) =>
387+ `${ gapAppUrl } /project/${ projectUID } ` ;
0 commit comments