diff --git a/app/components/climb-card/climb-card.tsx b/app/components/climb-card/climb-card.tsx index b3f495f..4eac980 100644 --- a/app/components/climb-card/climb-card.tsx +++ b/app/components/climb-card/climb-card.tsx @@ -2,11 +2,12 @@ import React from 'react'; import Card from 'antd/es/card'; -import { CopyrightOutlined } from '@ant-design/icons'; +import { CopyrightOutlined, StopOutlined } from '@ant-design/icons'; import ClimbCardCover from './climb-card-cover'; import { Climb, BoardDetails } from '@/app/lib/types'; import ClimbCardActions from './climb-card-actions'; +import { hasNoMatchingPattern } from '@/app/lib/climb-utils'; type ClimbCardProps = { climb?: Climb; @@ -26,6 +27,9 @@ const ClimbCard = ({ climb, boardDetails, onCoverClick, selected, actions }: Cli
{climb.name} @ {climb.angle}° {climb.benchmark_difficulty !== null && } + {boardDetails.board_name === 'tension' && hasNoMatchingPattern(climb.description) && ( + + )}
{/* RIGHT: Difficulty, Quality */} diff --git a/app/lib/__tests__/climb-utils.test.ts b/app/lib/__tests__/climb-utils.test.ts new file mode 100644 index 0000000..60a5f24 --- /dev/null +++ b/app/lib/__tests__/climb-utils.test.ts @@ -0,0 +1,33 @@ +import { hasNoMatchingPattern } from '../climb-utils'; + +describe('climb-utils', () => { + describe('hasNoMatchingPattern', () => { + it('should return true for "no matching" patterns', () => { + expect(hasNoMatchingPattern('No matching allowed')).toBe(true); + expect(hasNoMatchingPattern('Don\'t match this route')).toBe(true); + expect(hasNoMatchingPattern('Dont match on this problem')).toBe(true); + expect(hasNoMatchingPattern('no match')).toBe(true); + expect(hasNoMatchingPattern('don\'t matching')).toBe(true); + }); + + it('should return false for descriptions without no-matching patterns', () => { + expect(hasNoMatchingPattern('Great route with good holds')).toBe(false); + expect(hasNoMatchingPattern('Matching holds on this climb')).toBe(false); + expect(hasNoMatchingPattern('Really fun project')).toBe(false); + expect(hasNoMatchingPattern('')).toBe(false); + }); + + it('should be case insensitive', () => { + expect(hasNoMatchingPattern('NO MATCHING')).toBe(true); + expect(hasNoMatchingPattern('Don\'T Match')).toBe(true); + expect(hasNoMatchingPattern('No Match')).toBe(true); + }); + + it('should handle whitespace variations', () => { + expect(hasNoMatchingPattern('no match')).toBe(true); + expect(hasNoMatchingPattern('no match')).toBe(true); + expect(hasNoMatchingPattern('don\'tmatch')).toBe(true); + expect(hasNoMatchingPattern('don\'t match')).toBe(true); + }); + }); +}); \ No newline at end of file diff --git a/app/lib/climb-utils.ts b/app/lib/climb-utils.ts new file mode 100644 index 0000000..ae4499a --- /dev/null +++ b/app/lib/climb-utils.ts @@ -0,0 +1,16 @@ +/** + * Utility functions for climb-related operations + */ + +/** + * Check if a climb description contains "no matching" text + * Uses regex pattern: \b(?:no|don'?t)\s?match(?:ing)?\b + * @param description - The climb description to check + * @returns true if the description contains "no matching" pattern + */ +export function hasNoMatchingPattern(description: string): boolean { + if (!description) return false; + + const noMatchingRegex = /\b(?:no|don'?t)\s*match(?:ing)?\b/i; + return noMatchingRegex.test(description); +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index a682e9d..f5d90c5 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -25,5 +25,5 @@ "target": "ES2017" }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], - "exclude": ["node_modules"] + "exclude": ["node_modules", "**/*.test.ts", "**/*.test.tsx", "**/__tests__/**"] }