# GraphQL TypeScript Usage Guide

## Import Types

```typescript
import type { GlobalParticipant, GlobalProduct, GlobalSoundRecording } from './graphql/graphql';
```

## Example 1: Typing Apollo Hooks

```typescript
import { useLazyQuery } from '@apollo/client';
import { globalParticipantSearchQuery } from '../queries/search';
import type { GlobalParticipant } from '../graphql/graphql';

interface ParticipantSearchData {
    globalParticipantSearchES: {
        items: Array<{
            item: GlobalParticipant;
        }>;
    };
}

interface ParticipantSearchVariables {
    term: string;
    limit?: number;
    offset?: number;
    catalogOnly?: boolean;
}

const [globalParticipantSearch, globalParticipantResult] = useLazyQuery<
    ParticipantSearchData,
    ParticipantSearchVariables
>(globalParticipantSearchQuery);

const participants = globalParticipantResult.data?.globalParticipantSearchES.items.map(
    ({ item }) => item.name
);
```

## Example 2: Typing Data Formatters

```typescript
import type { GlobalProduct, GlobalParticipant, GlobalSoundRecording } from '../graphql/graphql';

interface RawSearchData {
    allProductsSearch?: {
        products: Array<Partial<GlobalProduct>>;
    };
    globalParticipantSearchES?: {
        items: Array<{ item: GlobalParticipant }>;
    };
    globalSoundRecordingSearchES?: {
        items: Array<{ item: GlobalSoundRecording }>;
    };
}

interface FormattedSearchResults {
    products: {
        results: Array<{
            productId: string;
            productName: string | null;
            artistName: string;
        }>;
    };
    participants: {
        results: Array<{
            id: string;
            name: string | null;
            imageUrl: string | null;
        }>;
    };
    soundRecordings: {
        results: Array<{
            isrc: string;
            trackName: string | null;
        }>;
    };
}

export const formatSearch = (data: RawSearchData): FormattedSearchResults => {
    const products = data.allProductsSearch?.products?.map(product => ({
        productId: product.productId!,
        productName: product.productName,
    })) || [];
};
```

## Example 3: Typing Component Props

```typescript
import type { GlobalParticipant } from '../graphql/graphql';

interface SearchResult {
    type: 'product' | 'participant' | 'soundRecording';
    data: GlobalParticipant | GlobalProduct | GlobalSoundRecording;
}

interface SearchScreenProps {
    query: string;
    searchResults: SearchResult[];
    loading: boolean;
    online: boolean;
    hasAccess: boolean;
    setQuery: (query: string) => void;
    onSearchClear: () => void;
}

const SearchScreenComponent: React.FC<SearchScreenProps> = ({
    query,
    searchResults,
    loading,
}) => {
};
```

## Example 4: Typing useQuery Hook

```typescript
import { useQuery } from '@apollo/client';
import { globalProductSearchQuery } from '../queries/search';
import type { GlobalProduct } from '../graphql/graphql';

interface ProductSearchData {
    allProductsSearch: {
        totalCount: number;
        products: Array<GlobalProduct>;
    };
}

interface ProductSearchVariables {
    term: string;
}

function MyComponent() {
    const { data, loading, error } = useQuery<
        ProductSearchData,
        ProductSearchVariables
    >(globalProductSearchQuery, {
        variables: { term: 'test' },
    });

    if (loading) return <Spinner />;
    if (error) return <Error />;

    const products = data?.allProductsSearch.products || [];
    const count = data?.allProductsSearch.totalCount || 0;

    return <ProductList products={products} />;
}
```

## Example 5: Typing Utility Functions

```typescript
import type { GlobalParticipant, Maybe } from '../graphql/graphql';

export function getParticipantName(participant: GlobalParticipant): string {
    return participant.name || 'Unknown Artist';
}

export function getParticipantImageUrl(
    participant: GlobalParticipant
): Maybe<string> {
    return participant.imageUrl;
}

export function extractParticipantIds(
    participants: GlobalParticipant[]
): string[] {
    return participants.map(p => p.id);
}
```

## Common Patterns

### Partial Types for Queries

```typescript
import type { GlobalParticipant } from '../graphql/graphql';

type ParticipantBasic = Pick<GlobalParticipant, 'id' | 'name' | 'imageUrl'>;

function formatParticipant(data: Partial<GlobalParticipant>) {
    return {
        id: data.id || '',
        name: data.name || 'Unknown',
    };
}
```

### Nested Types

```typescript
import type { GlobalProduct } from '../graphql/graphql';

type LabelParticipation = NonNullable<
    GlobalProduct['labelParticipations']
>[number];

type GlobalParticipantFromProduct = NonNullable<
    LabelParticipation['labelParticipant']
>['globalParticipant'];
```

### Arrays and Maybe

```typescript
import type { GlobalParticipant, Maybe, Scalars } from '../graphql/graphql';

function processParticipants(items: GlobalParticipant[]): string[] {
    return items.map(item => item.name || 'Unknown');
}

function getMonthlyListeners(
    socialStats: Maybe<{ monthlyListeners: Maybe<Scalars['Long']['output']> }>
): number {
    return socialStats?.monthlyListeners || 0;
}
```
