Skip to content

Commit

Permalink
Feature: Borrowers Demographics (#337)
Browse files Browse the repository at this point in the history
Co-authored-by: Hugo Marques <[email protected]>
  • Loading branch information
hugomarquesdev and Hugo Marques authored Aug 4, 2023
1 parent dc4193a commit 0c2df54
Show file tree
Hide file tree
Showing 31 changed files with 967 additions and 1,177 deletions.
120 changes: 95 additions & 25 deletions src/apis/api.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { ApolloClient, HttpLink, InMemoryCache, concat, gql } from '@apollo/client';
import {
ApolloClient,
HttpLink,
InMemoryCache,
concat,
gql
} from '@apollo/client';
import {
CommunityListRequestArguments,
CommunityListRequestResponseType,
Expand All @@ -14,6 +20,7 @@ import {
IGlobalNumbers,
IManager,
IMicrocredit,
IMicrocreditDemographics,
IStories
} from './types';
import { Numbers } from 'humanify-numbers';
Expand All @@ -38,8 +45,20 @@ export default class Api {
static async getCommunities(
requestOptions: CommunityListRequestArguments
): Promise<CommunityListRequestResponseType> {
const params = ['country', 'filter', 'limit', 'name', 'offset', 'orderBy'];
const baseOptions = { limit: 10, orderBy: 'bigger', page: 1, status: 'valid' };
const params = [
'country',
'filter',
'limit',
'name',
'offset',
'orderBy'
];
const baseOptions = {
limit: 10,
orderBy: 'bigger',
page: 1,
status: 'valid'
};
const options = Object.assign({}, baseOptions, requestOptions);
const { page, limit } = options;

Expand All @@ -55,17 +74,21 @@ export default class Api {
return { count, items, page };
}
static async getCommunity(communityId?: number | string): Promise<any> {
const communityResponse = await getRequest<DataResponseType<ICommunity>>(`/community/${communityId}`);
const managersResponse = await getRequest<DataResponseType<IManager[]>>(`/community/${communityId}/managers`);
const dashboardResponse = await getRequest<DataResponseType<ICommunityDashboard[]>>(
`/community/${communityId}/dashboard`
);
const claimLocations = await getRequest<DataResponseType<IClaimLocation[]>>(
`/community/${communityId}/claim-location`
);
const campaignResponse = await getRequest<DataResponseType<ICommunityCampaign>>(
`/community/${communityId}/campaign`
const communityResponse = await getRequest<
DataResponseType<ICommunity>
>(`/community/${communityId}`);
const managersResponse = await getRequest<DataResponseType<IManager[]>>(
`/community/${communityId}/managers`
);
const dashboardResponse = await getRequest<
DataResponseType<ICommunityDashboard[]>
>(`/community/${communityId}/dashboard`);
const claimLocations = await getRequest<
DataResponseType<IClaimLocation[]>
>(`/community/${communityId}/claim-location`);
const campaignResponse = await getRequest<
DataResponseType<ICommunityCampaign>
>(`/community/${communityId}/campaign`);

const data = {
...communityResponse?.data,
Expand All @@ -78,18 +101,23 @@ export default class Api {
return communityResponse?.success ? data : undefined;
}
static async getCommunityCount(groupBy: string = 'country'): Promise<any> {
const response = await getRequest<DataResponseType<any>>(`/community/count?groupBy=${groupBy}`);
const response = await getRequest<DataResponseType<any>>(
`/community/count?groupBy=${groupBy}`
);

return response?.data;
}
static async getGlobalNumbers(): Promise<IGlobalNumbers | {}> {
const response = await getRequest<IGlobalNumbers | undefined>('/global/numbers');
const response = await getRequest<IGlobalNumbers | undefined>(
'/global/numbers'
);

const data = response?.data || ({} as any);

const result = {
backers: data?.backers || null,
beneficiaries: Numbers.stringify(+(data?.beneficiaries || 0)) || null,
beneficiaries:
Numbers.stringify(+(data?.beneficiaries || 0)) || null,
claimed: `$${Numbers.stringify(+(data?.claimed || 0))}` || null,
communities: data?.communities || null,
countries: data?.countries || null
Expand All @@ -99,7 +127,10 @@ export default class Api {
}
static async getGlobalValues(): Promise<IGlobalDashboard | {}> {
// retry with intervals
const retry = new RetryLink({ attempts: { max: 100 }, delay: { max: 30000 } });
const retry = new RetryLink({
attempts: { max: 100 },
delay: { max: 30000 }
});
const http = new HttpLink({ uri: config.subgraphUrl });
const link = concat(retry, http);
const client = new ApolloClient({
Expand All @@ -126,7 +157,12 @@ export default class Api {
const ubiDailyEntityMonth = await client.query({
query: gql`
query GetUbiDailyMonth {
ubidailyEntities(first: 30, skip: 1, orderBy: id, orderDirection: desc) {
ubidailyEntities(
first: 30
skip: 1
orderBy: id
orderDirection: desc
) {
id
claimed
claims
Expand All @@ -142,8 +178,13 @@ export default class Api {
`
});

const result = (await getRequest<IGlobalApiResult | undefined>('/global/status')) || {};
const demographics = await getRequest<IDemographics[] | undefined>('/global/demographics');
const result =
(await getRequest<IGlobalApiResult | undefined>(
'/global/status'
)) || {};
const demographics = await getRequest<IDemographics[] | undefined>(
'/global/demographics'
);

return {
...result,
Expand All @@ -153,14 +194,40 @@ export default class Api {
};
}
static async getMicrocreditData(): Promise<IMicrocredit[]> {
const result = await getRequest<IMicrocredit[]>('/protocol/microcredit');
const result = await getRequest<IMicrocredit[]>(
'/protocol/microcredit'
);

return result ? result : [];
}
static async getMicrocreditDemographics(): Promise<
IMicrocreditDemographics[]
> {
const result = await getRequest<IMicrocreditDemographics[]>(
'/microcredit/demographics'
);

return result ? result : [];
}

static async getPendingCommunities(requestOptions: CommunityListRequestArguments): Promise<any> {
const params = ['country', 'extended', 'filter', 'limit', 'name', 'offset', 'orderBy'];
const baseOptions = { extended: false, limit: 4, orderBy: 'bigger', page: 1 };
static async getPendingCommunities(
requestOptions: CommunityListRequestArguments
): Promise<any> {
const params = [
'country',
'extended',
'filter',
'limit',
'name',
'offset',
'orderBy'
];
const baseOptions = {
extended: false,
limit: 4,
orderBy: 'bigger',
page: 1
};
const options = Object.assign({}, baseOptions, requestOptions);
const { page, limit } = options;

Expand Down Expand Up @@ -204,7 +271,10 @@ export default class Api {

const data = { context, fields, submittedAt };

const result = await axios.post('api/subscribe', { data, recaptchaToken });
const result = await axios.post('api/subscribe', {
data,
recaptchaToken
});

return { success: result?.data?.success };
}
Expand Down
55 changes: 35 additions & 20 deletions src/apis/demographics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ interface IDataItem {
label: string;
value: number;
}
interface IBeneficaryItem {
interface ICountryItem {
country: string;
female: number;
male: number;
Expand All @@ -26,7 +26,9 @@ const countries: {
};
} = countriesJSON;

export const getDemographicsAgeRange = (data: IDemographics[] | undefined): IDataItem[] => {
export const getDemographicsAgeRange = (
data: IDemographics[] | undefined
): IDataItem[] => {
if (!data || !data.length) {
return [];
}
Expand All @@ -45,7 +47,9 @@ export const getDemographicsAgeRange = (data: IDemographics[] | undefined): IDat
total += value;

const label =
index + 1 < ageItems.length ? `${index ? (index + 1) * 10 + 5 : 18}-${(index + 2) * 10 + 4}` : '65+';
index + 1 < ageItems.length
? `${index ? (index + 1) * 10 + 5 : 18}-${(index + 2) * 10 + 4}`
: '65+';

return { label, value };
});
Expand All @@ -57,26 +61,31 @@ export const getDemographicsAgeRange = (data: IDemographics[] | undefined): IDat
}));
};

export const getDemographicsBeneficiariesByCountry = (data: any[] | undefined, chunkSize = 6): IBeneficaryItem[][] => {
export const getDemographicsByCountry = (
data: any[] | undefined,
chunkSize = 6
): ICountryItem[][] => {
if (!data || !data.length) {
return [];
}

const result = data.map(({ country: countryCode, female, male, totalGender, undisclosed }) => {
const country = countries[countryCode]?.name;

const totalMF = male + female;
const nMale = (male / totalMF) * totalGender;
const nFemale = (female / totalMF) * totalGender;

return {
country,
female: totalMF === 0 ? 0 : nFemale,
male: totalMF === 0 ? 0 : nMale,
total: totalGender,
undisclosed
};
});
const result = data.map(
({ country: countryCode, female, male, totalGender, undisclosed }) => {
const country = countries[countryCode]?.name;

const totalMF = male + female;
const nMale = (male / totalMF) * totalGender;
const nFemale = (female / totalMF) * totalGender;

return {
country,
female: totalMF === 0 ? 0 : nFemale,
male: totalMF === 0 ? 0 : nMale,
total: totalGender,
undisclosed
};
}
);

const chunks = chunk(sortBy(result, ['total']).reverse(), chunkSize);

Expand All @@ -94,7 +103,13 @@ export const getDemographicsBeneficiariesByCountry = (data: any[] | undefined, c
return chunks;
};

export const getDemographicsTotalPercentage = (data: any[] | undefined): number => {
export const getDemographicsTotalPercentage = (
data: any[] | undefined
): number => {
if (!data || data.length === 0) {
return 0; // or any other default value that makes sense in your context
}

const { total, totalFromGender } = data?.reduce(
(result, { female, male, totalGender }) => ({
total: result.total + totalGender,
Expand Down
52 changes: 50 additions & 2 deletions src/apis/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,47 @@ export interface IMicrocredit {
success: boolean;
}

export interface IMicrocreditDemographicsData {
gender: {
country: string;
male: string;
female: string;
undisclosed: string;
totalGender: string;
}[];
ageRange: {
paid: {
ageRange1: string;
ageRange2: string;
ageRange3: string;
ageRange4: string;
ageRange5: string;
ageRange6: string;
};
pending: {
ageRange1: string;
ageRange2: string;
ageRange3: string;
ageRange4: string;
ageRange5: string;
ageRange6: string;
};
overdue: {
ageRange1: string;
ageRange2: string;
ageRange3: string;
ageRange4: string;
ageRange5: string;
ageRange6: string;
};
};
}

export interface IMicrocreditDemographics {
data: IMicrocreditDemographicsData[];
success: boolean;
}

export interface IStory {
storyMediaPath: string;
}
Expand Down Expand Up @@ -134,7 +175,11 @@ export interface IGlobalApiResult {
reach: number;
}[];
lastQuarterAvgSSI: { date: Date; avgMedianSSI: number }[];
today: { totalClaimed: string; totalBeneficiaries: number; totalRaised: string };
today: {
totalClaimed: string;
totalBeneficiaries: number;
totalRaised: string;
};
totalBackers: number;
reachedLastMonth: {
reach: number;
Expand Down Expand Up @@ -262,7 +307,10 @@ export interface ICommunity extends CommunityAttributes {
claimLocations?: IClaimLocationGps[];
contract: CommunityContractAttributes;
managers?: IManager[];
metrics?: CommunityDailyMetricsAttributes | CommunityDailyMetricsAttributes[] | any;
metrics?:
| CommunityDailyMetricsAttributes
| CommunityDailyMetricsAttributes[]
| any;
state: CommunityStateAttributes;
dashboard: ICommunityDashboard;
}
Expand Down
Loading

0 comments on commit 0c2df54

Please sign in to comment.