Skip to content

Commit

Permalink
Merge pull request #104 from poap-xyz/feat/search-drops
Browse files Browse the repository at this point in the history
Search drops
  • Loading branch information
jm42 authored Apr 8, 2024
2 parents 9aa1f94 + 31d718b commit 4b0c168
Show file tree
Hide file tree
Showing 16 changed files with 272 additions and 85 deletions.
1 change: 1 addition & 0 deletions docs/pages/packages/drops.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
- Update a Drop attributes
- Fetch a single Drop
- Fetch multiple Drops
- Search Drops

## Installation

Expand Down
31 changes: 31 additions & 0 deletions docs/pages/packages/drops/SearchDrops.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Search Drops

There are two ways that drops can be searched, by exact word in name or fuzzy
search in name and description.

## Exact word search

When searching for a whole word, use `fetch` method:

```typescript
const data: PaginatedResult<Drop> = await dropsClient.fetch({
sortField: DropsSortFields.Name,
sortDir: Order.ASC,
limit: 3,
offset: 0,
name: 'POAP',
});
```

## Fuzzy search

When given a generic search input, and to match any part of the words used in
the name of the description, use `search` method:

```typescript
const data: PaginatedResult<Drop> = await dropsClient.search({
limit: 3,
offset: 0,
search: 'POAP',
});
```
3 changes: 3 additions & 0 deletions docs/pages/packages/drops/_meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"SearchDrops": "Search Drops"
}
1 change: 1 addition & 0 deletions packages/drops/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
- Update a Drop attributes
- Fetch a single Drop
- Fetch multiple Drops
- Search Drops

## Installation

Expand Down
131 changes: 90 additions & 41 deletions packages/drops/src/DropsClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import {
DropResponse as ProviderDropResponse,
} from '@poap-xyz/providers';
import { Drop } from './domain/Drop';
import { PaginatedDropsResponse, PAGINATED_DROPS_QUERY } from './queries';
import {
PaginatedDropsResponse,
PAGINATED_DROPS_QUERY,
CreateDropsInput,
DropImageResponse,
DropResponse,
} from './queries';
import { CreateDropsInput, FetchDropsInput, UpdateDropsInput } from './types';
FetchDropsInput,
SearchDropsInput,
UpdateDropsInput,
} from './types';
import {
PaginatedResult,
nextCursor,
Expand All @@ -19,8 +21,12 @@ import {
createBetweenFilter,
createFilter,
createInFilter,
Order,
isNumeric,
removeSpecialCharacters,
} from '@poap-xyz/utils';
import { DropImage } from './types/dropImage';
import { SEARCH_DROPS_QUERY, SearchDropsResponse } from './queries/SearchDrops';

/**
* Represents a client for working with POAP drops.
Expand All @@ -32,8 +38,8 @@ export class DropsClient {
* Creates a new DropsClient object.
*
* @constructor
* @param {CompassProvider} CompassProvider - The provider for the POAP compass API.
* @param {DropApiProvider} DropApiProvider - The provider for the POAP drop API.
* @param {CompassProvider} compassProvider - The provider for the POAP compass API.
* @param {DropApiProvider} dropApiProvider - The provider for the POAP drop API.
*/
constructor(
private compassProvider: CompassProvider,
Expand Down Expand Up @@ -78,41 +84,48 @@ export class DropsClient {
variables,
);

const drops = data.drops.map((drop) => {
const { imageUrl, originalImageUrl } = this.computeDropImages(drop);

return new Drop({
id: Number(drop.id),
fancyId: drop.fancy_id,
name: drop.name,
description: drop.description,
city: drop.city,
country: drop.country,
channel: drop.channel,
platform: drop.platform,
locationType: drop.location_type,
dropUrl: drop.drop_url,
imageUrl,
originalImageUrl,
animationUrl: drop.animation_url,
year: Number(drop.year),
startDate: new Date(drop.start_date),
timezone: drop.timezone,
private: drop.private,
createdDate: new Date(drop.created_date),
poapCount: drop.stats_by_chain_aggregate.aggregate.sum
? Number(drop.stats_by_chain_aggregate.aggregate.sum.poap_count)
: 0,
transferCount: drop.stats_by_chain_aggregate.aggregate.sum
? Number(drop.stats_by_chain_aggregate.aggregate.sum.transfer_count)
: 0,
emailReservationCount: drop.email_claims_stats
? Number(drop.email_claims_stats.total)
: 0,
expiryDate: new Date(drop.expiry_date),
endDate: new Date(drop.end_date),
});
});
const drops = data.drops.map(
(drop: DropResponse): Drop => this.mapDrop(drop),
);

return new PaginatedResult<Drop>(
drops,
nextCursor(drops.length, limit, offset),
);
}

/**
* Searches drops based on the specified input.
*
* @async
* @method
* @param {SearchDropsInput} input - The input for searching drops.
* @returns {Promise<PaginatedResult<Drop>>} A paginated result of drops.
*/
async search(input: SearchDropsInput): Promise<PaginatedResult<Drop>> {
const { search, offset, limit } = input;

if (!search) {
return new PaginatedResult<Drop>([], null);
}

const variables = {
limit,
offset,
...(isNumeric(search) && { orderBy: { id: Order.ASC } }),
args: {
search: removeSpecialCharacters(search),
},
};

const { data } = await this.compassProvider.request<SearchDropsResponse>(
SEARCH_DROPS_QUERY,
variables,
);

const drops = data.search_drops.map(
(drop: DropResponse): Drop => this.mapDrop(drop),
);

return new PaginatedResult<Drop>(
drops,
Expand Down Expand Up @@ -226,4 +239,40 @@ export class DropsClient {

return { ...images };
}

private mapDrop(drop: DropResponse): Drop {
const { imageUrl, originalImageUrl } = this.computeDropImages(drop);

return new Drop({
id: Number(drop.id),
fancyId: drop.fancy_id,
name: drop.name,
description: drop.description,
city: drop.city,
country: drop.country,
channel: drop.channel,
platform: drop.platform,
locationType: drop.location_type,
dropUrl: drop.drop_url,
imageUrl,
originalImageUrl,
animationUrl: drop.animation_url,
year: Number(drop.year),
startDate: new Date(drop.start_date),
timezone: drop.timezone,
private: drop.private,
createdDate: new Date(drop.created_date),
poapCount: drop.stats_by_chain_aggregate.aggregate.sum
? Number(drop.stats_by_chain_aggregate.aggregate.sum.poap_count)
: 0,
transferCount: drop.stats_by_chain_aggregate.aggregate.sum
? Number(drop.stats_by_chain_aggregate.aggregate.sum.transfer_count)
: 0,
emailReservationCount: drop.email_claims_stats
? Number(drop.email_claims_stats.total)
: 0,
expiryDate: new Date(drop.expiry_date),
endDate: new Date(drop.end_date),
});
}
}
45 changes: 1 addition & 44 deletions packages/drops/src/queries/PaginatedDrop.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DropImageGatewayType } from '../types/dropImage';
import { DropResponse } from '../types/DropResponse';

export const PAGINATED_DROPS_QUERY = `
query PaginatedDrops(
Expand Down Expand Up @@ -48,49 +48,6 @@ export const PAGINATED_DROPS_QUERY = `
}
`;

export interface DropImageGatewayResponse {
type: DropImageGatewayType;
url: string;
}

export interface DropImageResponse {
gateways: Array<DropImageGatewayResponse>;
}

export interface DropResponse {
id: number;
fancy_id: string;
name: string;
description: string;
city: string;
country: string;
channel: string;
platform: string;
location_type: string;
drop_url: string;
image_url: string;
animation_url: string;
year: number;
start_date: string;
timezone: string;
private: boolean;
created_date: string;
expiry_date: string;
end_date: string;
stats_by_chain_aggregate: {
aggregate: {
sum: {
transfer_count: number;
poap_count: number;
};
};
};
email_claims_stats: {
total: number;
};
drop_image?: DropImageResponse;
}

export interface PaginatedDropsResponse {
data: {
drops: DropResponse[];
Expand Down
60 changes: 60 additions & 0 deletions packages/drops/src/queries/SearchDrops.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { DropResponse } from '../types/DropResponse';

export const SEARCH_DROPS_QUERY = `
query SearchDrops(
$limit: Int!
$offset: Int!
$args: search_drops_args!
$orderBy: [drops_order_by!]
) {
search_drops(
limit: $limit
offset: $offset
args: $args
order_by: $orderBy
) {
id
fancy_id
name
description
city
country
channel
platform
location_type
drop_url
image_url
animation_url
year
start_date
timezone
private
created_date
expiry_date
end_date
stats_by_chain_aggregate {
aggregate {
sum {
transfer_count
poap_count
}
}
}
email_claims_stats {
total
}
drop_image {
gateways {
type
url
}
}
}
}
`;

export interface SearchDropsResponse {
data: {
search_drops: DropResponse[];
};
}
10 changes: 10 additions & 0 deletions packages/drops/src/types/DropImageResponse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { DropImageGatewayType } from './dropImage';

interface DropImageGatewayResponse {
type: DropImageGatewayType;
url: string;
}

export interface DropImageResponse {
gateways: Array<DropImageGatewayResponse>;
}
35 changes: 35 additions & 0 deletions packages/drops/src/types/DropResponse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { DropImageResponse } from './DropImageResponse';

export interface DropResponse {
id: number;
fancy_id: string;
name: string;
description: string;
city: string;
country: string;
channel: string;
platform: string;
location_type: string;
drop_url: string;
image_url: string;
animation_url: string;
year: number;
start_date: string;
timezone: string;
private: boolean;
created_date: string;
expiry_date: string;
end_date: string;
stats_by_chain_aggregate: {
aggregate: {
sum: {
transfer_count: number;
poap_count: number;
};
};
};
email_claims_stats: {
total: number;
};
drop_image?: DropImageResponse;
}
5 changes: 5 additions & 0 deletions packages/drops/src/types/SearchDropsInput.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { PaginationInput } from '@poap-xyz/utils';

export interface SearchDropsInput extends PaginationInput {
search: string;
}
3 changes: 3 additions & 0 deletions packages/drops/src/types/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
export * from './input';
export * from './DropImageResponse';
export * from './DropResponse';
export * from './SearchDropsInput';
1 change: 1 addition & 0 deletions packages/utils/src/format/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './removeSpecialCharacters';
Loading

0 comments on commit 4b0c168

Please sign in to comment.