Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { TableSet, type BoardName } from '../util/table-select';
import type { SizeEdges } from '../util/product-sizes-data';
import { boardseshTicks, boardProductSizes } from '@boardsesh/db/schema';
import type { HoldState } from '@boardsesh/shared-schema';

export interface ClimbSearchParams {
// Pagination
Expand All @@ -19,8 +20,8 @@
settername?: string[];
onlyClassics?: boolean;
onlyTallClimbs?: boolean;
// Hold filters
holdsFilter?: Record<string, 'ANY' | 'NOT'>;
// Hold filters - accepts all HoldState values (currently only 'ANY' and 'NOT' are processed)
holdsFilter?: Record<string, HoldState>;
// Personal progress filters
hideAttempted?: boolean;
hideCompleted?: boolean;
Expand Down Expand Up @@ -72,7 +73,7 @@
// Size-specific conditions using pre-fetched static edge values
// This eliminates the need for a JOIN on product_sizes in the main query
const sizeConditions: SQL[] = [
sql`${tables.climbs.edgeLeft} > ${sizeEdges.edgeLeft}`,

Check failure on line 76 in packages/backend/src/db/queries/climbs/create-climb-filters.ts

View workflow job for this annotation

GitHub Actions / test

src/__tests__/climb-queries.test.ts > Climb Query Functions > countClimbs > should respect filters in count

TypeError: Cannot read properties of null (reading 'edgeLeft') ❯ createClimbFilters src/db/queries/climbs/create-climb-filters.ts:76:49 ❯ countClimbs src/db/queries/climbs/count-climbs.ts:27:19 ❯ src/__tests__/climb-queries.test.ts:221:35

Check failure on line 76 in packages/backend/src/db/queries/climbs/create-climb-filters.ts

View workflow job for this annotation

GitHub Actions / test

src/__tests__/climb-queries.test.ts > Climb Query Functions > countClimbs > should return accurate total count

TypeError: Cannot read properties of null (reading 'edgeLeft') ❯ createClimbFilters src/db/queries/climbs/create-climb-filters.ts:76:49 ❯ countClimbs src/db/queries/climbs/count-climbs.ts:27:19 ❯ src/__tests__/climb-queries.test.ts:202:27
sql`${tables.climbs.edgeRight} < ${sizeEdges.edgeRight}`,
sql`${tables.climbs.edgeBottom} > ${sizeEdges.edgeBottom}`,
sql`${tables.climbs.edgeTop} < ${sizeEdges.edgeTop}`,
Expand Down
3 changes: 2 additions & 1 deletion packages/backend/src/validation/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,8 @@ export const ClimbSearchInputSchema = z.object({
setterId: z.number().int().optional(),
onlyBenchmarks: z.boolean().optional(),
onlyTallClimbs: z.boolean().optional(),
holdsFilter: z.record(z.enum(['ANY', 'NOT'])).optional(),
// Accept all HoldState values for future UI implementations (currently only 'ANY' and 'NOT' are used)
holdsFilter: z.record(z.enum(['OFF', 'STARTING', 'FINISH', 'HAND', 'FOOT', 'ANY', 'NOT'])).optional(),
// Personal progress filters
hideAttempted: z.boolean().optional(),
hideCompleted: z.boolean().optional(),
Expand Down
4 changes: 2 additions & 2 deletions packages/shared-schema/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,8 @@ export type ClimbSearchInput = {
setterId?: number;
onlyBenchmarks?: boolean;
onlyTallClimbs?: boolean;
// Hold filters
holdsFilter?: Record<string, 'ANY' | 'NOT'>;
// Hold filters - accepts any HoldState for filtering climbs by hold usage
holdsFilter?: Record<string, HoldState>;
// Personal progress filters
hideAttempted?: boolean;
hideCompleted?: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,16 @@ export default async function DynamicResultsPage(props: {
sortOrder: searchParamsObject.sortOrder || 'desc',
name: searchParamsObject.name || undefined,
setter: searchParamsObject.settername && searchParamsObject.settername.length > 0 ? searchParamsObject.settername : undefined,
onlyTallClimbs: searchParamsObject.onlyTallClimbs || undefined,
// Convert holdsFilter from LitUpHoldsMap to Record<string, HoldState> format expected by GraphQL
holdsFilter: searchParamsObject.holdsFilter && Object.keys(searchParamsObject.holdsFilter).length > 0
? Object.fromEntries(
Object.entries(searchParamsObject.holdsFilter).map(([key, value]) => [
key.replace('hold_', ''),
value.state
])
)
: undefined,
};

// Check if this is a default search (no custom filters applied)
Expand All @@ -218,7 +228,9 @@ export default async function DynamicResultsPage(props: {
!searchParamsObject.name &&
(!searchParamsObject.settername || searchParamsObject.settername.length === 0) &&
(searchParamsObject.sortBy || 'ascents') === 'ascents' &&
(searchParamsObject.sortOrder || 'desc') === 'desc';
(searchParamsObject.sortOrder || 'desc') === 'desc' &&
!searchParamsObject.onlyTallClimbs &&
(!searchParamsObject.holdsFilter || Object.keys(searchParamsObject.holdsFilter).length === 0);

let searchResponse: ClimbSearchResponse;
let boardDetails: BoardDetails;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export const useQueueDataFetching = ({
name: searchParams.name || undefined,
setter: searchParams.settername && searchParams.settername.length > 0 ? searchParams.settername : undefined,
onlyTallClimbs: searchParams.onlyTallClimbs || undefined,
// Convert holdsFilter from LitUpHoldsMap to Record<string, 'ANY' | 'NOT'>
// Convert holdsFilter from LitUpHoldsMap to Record<string, HoldState> format expected by GraphQL
holdsFilter: searchParams.holdsFilter && Object.keys(searchParams.holdsFilter).length > 0
? Object.fromEntries(
Object.entries(searchParams.holdsFilter).map(([key, value]) => [
Expand Down
4 changes: 2 additions & 2 deletions packages/web/app/lib/graphql/operations/climb-search.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { gql } from 'graphql-request';
import type { Climb } from '@/app/lib/types';
import type { Climb, HoldState } from '@/app/lib/types';

// Fragment for climb fields
const CLIMB_FIELDS = `
Expand Down Expand Up @@ -74,7 +74,7 @@ export interface ClimbSearchInputVariables {
name?: string;
setter?: string[];
onlyTallClimbs?: boolean;
holdsFilter?: Record<string, 'ANY' | 'NOT'>;
holdsFilter?: Record<string, HoldState>;
hideAttempted?: boolean;
hideCompleted?: boolean;
showOnlyAttempted?: boolean;
Expand Down
Loading