Skip to content
Open
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 @@ -9,10 +9,10 @@ import BetaVideos from '@/app/components/beta-videos/beta-videos';
import {
constructClimbInfoUrl,
extractUuidFromSlug,
constructClimbViewUrl,
isUuidOnly,
constructClimbViewUrlWithSlugs,
parseBoardRouteParams,
constructClimbViewUrlWithDatabaseSlugs,
} from '@/app/lib/url-utils';
import { parseBoardRouteParamsWithSlugs } from '@/app/lib/url-utils.server';
import { convertLitUpHoldsStringToMap } from '@/app/components/board-renderer/util';
Expand All @@ -34,7 +34,15 @@ export async function generateMetadata(props: { params: Promise<BoardRouteParame
const climbGrade = currentClimb.difficulty || 'Unknown Grade';
const setter = currentClimb.setter_username || 'Unknown Setter';
const description = `${climbName} - ${climbGrade} by ${setter}. Quality: ${currentClimb.quality_average || 0}/5. Ascents: ${currentClimb.ascensionist_count || 0}`;
const climbUrl = constructClimbViewUrl(parsedParams, parsedParams.climb_uuid, climbName);
const climbUrl = constructClimbViewUrlWithDatabaseSlugs(
parsedParams.board_name,
parsedParams.layout_id,
parsedParams.size_id,
parsedParams.set_ids,
parsedParams.angle,
parsedParams.climb_uuid,
climbName,
);

// Generate OG image URL - use parsed numeric IDs for better performance
const ogImageUrl = new URL(
Expand All @@ -44,7 +52,7 @@ export async function generateMetadata(props: { params: Promise<BoardRouteParame
ogImageUrl.searchParams.set('board_name', parsedParams.board_name);
ogImageUrl.searchParams.set('layout_id', parsedParams.layout_id.toString());
ogImageUrl.searchParams.set('size_id', parsedParams.size_id.toString());
ogImageUrl.searchParams.set('set_ids', parsedParams.set_ids.join(','));
ogImageUrl.searchParams.set('set_ids', parsedParams.set_ids);
ogImageUrl.searchParams.set('angle', parsedParams.angle.toString());
ogImageUrl.searchParams.set('climb_uuid', parsedParams.climb_uuid);

Expand Down Expand Up @@ -109,15 +117,15 @@ export default async function DynamicResultsPage(props: { params: Promise<BoardR
// Get the names for slug generation
const layouts = await import('@/app/lib/data/queries').then((m) => m.getLayouts(parsedParams.board_name));
const sizes = await import('@/app/lib/data/queries').then((m) =>
m.getSizes(parsedParams.board_name, parsedParams.layout_id),
m.getSizes(parsedParams.board_name, parseInt(parsedParams.layout_id)),
);
const sets = await import('@/app/lib/data/queries').then((m) =>
m.getSets(parsedParams.board_name, parsedParams.layout_id, parsedParams.size_id),
m.getSets(parsedParams.board_name, parseInt(parsedParams.layout_id), parseInt(parsedParams.size_id)),
);

const layout = layouts.find((l) => l.id === parsedParams.layout_id);
const size = sizes.find((s) => s.id === parsedParams.size_id);
const selectedSets = sets.filter((s) => parsedParams.set_ids.includes(s.id));
const layout = layouts.find((l) => l.id === parseInt(parsedParams.layout_id));
const size = sizes.find((s) => s.id === parseInt(parsedParams.size_id));
const selectedSets = sets.filter((s) => parsedParams.set_ids.includes(s.id.toString()));

if (layout && size && selectedSets.length > 0) {
const newUrl = constructClimbViewUrlWithSlugs(
Expand Down Expand Up @@ -189,7 +197,6 @@ export default async function DynamicResultsPage(props: { params: Promise<BoardR
const auroraAppUrl = constructClimbInfoUrl(
boardDetails,
currentClimb.uuid,
currentClimb.angle || parsedParams.angle,
);

return (
Expand Down
6 changes: 3 additions & 3 deletions app/api/internal/board-details/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ export async function GET(request: NextRequest) {

const details = await getBoardDetails({
board_name: board_name as BoardName,
layout_id,
size_id,
set_ids,
layout_id: layout_id.toString(),
size_id: size_id.toString(),
set_ids: set_ids.map(String).join(','),
angle,
});

Expand Down
8 changes: 2 additions & 6 deletions app/components/board-page/back-to-climb-list-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,10 @@ import { useQueueContext } from '../queue-control/queue-context';
import { searchParamsToUrlParams, constructClimbListWithSlugs } from '@/app/lib/url-utils';

const BackToClimbList = ({
board_name,
layout_id,
size_id,
set_ids,
angle,
climb_uuid,
boardDetails,
}: ParsedBoardRouteParametersWithUuid & { boardDetails?: BoardDetails }) => {
}: Pick<ParsedBoardRouteParametersWithUuid, 'angle' | 'climb_uuid'> & { boardDetails?: BoardDetails }) => {
const { climbSearchParams } = useQueueContext();

const climbListUrl =
Expand All @@ -27,7 +23,7 @@ const BackToClimbList = ({
boardDetails.set_names,
angle,
)
: `/${board_name}/${layout_id}/${size_id}/${set_ids}/${angle}/list`;
: (() => { throw new Error('Board details are missing required slug information'); })();

return (
<Link href={`${climbListUrl}?${searchParamsToUrlParams(climbSearchParams).toString()}#${climb_uuid}`}>
Expand Down
8 changes: 4 additions & 4 deletions app/components/board-page/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,18 @@ export default function BoardSeshHeader({ boardDetails, angle }: BoardSeshHeader
style={{
height: '8dvh',
background: '#fff',
padding: '0 16px',
}}
>
<Row justify="space-between" align="middle" style={{ width: '100%' }}>
<Row>
{/* Column for the "BS" logo (25% width) */}
<Col xs={4} sm={4} md={4} lg={4} xl={4}>
<Col xs={3} sm={3} md={3} lg={3} xl={3} >
<Link href="/">
<Title level={4} style={{ margin: 0, lineHeight: '1.2', cursor: 'pointer' }}>
<Title level={4} align="left" style={{ cursor: 'pointer' }}>
BS
</Title>
</Link>
</Col>
<Col xs={1} sm={1} md={1} lg={1} xl={1} ></Col>

<UISearchParamsProvider>
<Col xs={14} sm={14} md={14} lg={14} xl={14}>
Expand Down
25 changes: 8 additions & 17 deletions app/components/climb-card/climb-card-actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import { useQueueContext } from '../queue-control/queue-context';
import { BoardDetails, Climb } from '@/app/lib/types';
import { PlusCircleOutlined, HeartOutlined, InfoCircleOutlined, CheckCircleOutlined } from '@ant-design/icons';
import Link from 'next/link';
import { constructClimbViewUrl, constructClimbViewUrlWithSlugs } from '@/app/lib/url-utils';
import {
constructClimbViewUrlWithSlugs,
} from '@/app/lib/url-utils';
import { track } from '@vercel/analytics';
import { message } from 'antd';

Expand Down Expand Up @@ -50,27 +52,16 @@ const ClimbCardActions = ({ climb, boardDetails }: ClimbCardActionsProps) => {
<Link
key="infocircle"
href={
boardDetails.layout_name && boardDetails.size_name && boardDetails.set_names
? constructClimbViewUrlWithSlugs(
constructClimbViewUrlWithSlugs(
boardDetails.board_name,
boardDetails.layout_name,
boardDetails.size_name,
boardDetails.set_names,
boardDetails.layout_name || '',
boardDetails.size_name || '',
boardDetails.set_names || [],
climb.angle,
climb.uuid,
climb.name,
)
: constructClimbViewUrl(
{
board_name: boardDetails.board_name,
layout_id: boardDetails.layout_id,
size_id: boardDetails.size_id,
set_ids: boardDetails.set_ids,
angle: climb.angle,
},
climb.uuid,
climb.name,
)

}
onClick={() => {
track('Climb Info Viewed', {
Expand Down
24 changes: 7 additions & 17 deletions app/components/climb-card/climb-thumbnail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Link from 'next/link';
import { BoardDetails, Climb } from '@/app/lib/types';
import BoardRenderer from '../board-renderer/board-renderer';
import ClimbCardModal from './climb-card-modal';
import { constructClimbViewUrl, constructClimbViewUrlWithSlugs, parseBoardRouteParams } from '@/app/lib/url-utils';
import { constructClimbViewUrlWithSlugs } from '@/app/lib/url-utils';

type ClimbThumbnailProps = {
currentClimb: Climb | null;
Expand All @@ -28,26 +28,16 @@ const ClimbThumbnail = ({ boardDetails, currentClimb, enableNavigation = false,

if (enableNavigation && currentClimb) {
// Use slug-based URL construction if slug names are available
const climbViewUrl = boardDetails.layout_name && boardDetails.size_name && boardDetails.set_names
? constructClimbViewUrlWithSlugs(
const climbViewUrl = constructClimbViewUrlWithSlugs(
boardDetails.board_name,
boardDetails.layout_name,
boardDetails.size_name,
boardDetails.set_names,
boardDetails.layout_name || '',
boardDetails.size_name || '',
boardDetails.set_names || [],
currentClimb.angle,
currentClimb.uuid,
currentClimb.name
)
: (() => {
const routeParams = parseBoardRouteParams({
board_name: boardDetails.board_name,
layout_id: boardDetails.layout_id.toString(),
size_id: boardDetails.size_id.toString(),
set_ids: boardDetails.set_ids.join(','),
angle: currentClimb.angle.toString(),
});
return constructClimbViewUrl(routeParams, currentClimb.uuid, currentClimb.name);
})();
);


return (
<Link href={climbViewUrl} onClick={handleLinkClick}>
Expand Down
4 changes: 2 additions & 2 deletions app/components/climb-view/climb-view-actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ const ClimbViewActions = ({ climb, boardDetails, auroraAppUrl, angle }: ClimbVie
return constructClimbListWithSlugs(board_name, layout_name, size_name, set_names, angle);
}

// Fallback to numeric format
return `/${board_name}/${boardDetails.layout_id}/${boardDetails.size_id}/${boardDetails.set_ids.join(',')}/${angle}/list`;
// This should not happen as boardDetails should always have the necessary fields
throw new Error('Board details are missing required slug information');
};

// Define menu items for the meatball menu (overflow actions on mobile)
Expand Down
5 changes: 2 additions & 3 deletions app/components/queue-control/next-climb-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ const NextButton = (props: ButtonProps) => (

export default function NextClimbButton({ navigate = false, boardDetails }: NextClimbButtonProps) {
const { setCurrentClimbQueueItem, getNextClimbQueueItem, viewOnlyMode } = useQueueContext(); // Assuming setSuggestedQueue is available
const { board_name, layout_id, size_id, set_ids, angle } =
parseBoardRouteParams(useParams<BoardRouteParametersWithUuid>());
const { angle } = parseBoardRouteParams(useParams<BoardRouteParametersWithUuid>());

const nextClimb = getNextClimbQueueItem();

Expand All @@ -47,7 +46,7 @@ export default function NextClimbButton({ navigate = false, boardDetails }: Next
nextClimb.climb.uuid,
nextClimb.climb.name,
)
: `/${board_name}/${layout_id}/${size_id}/${set_ids}/${angle}/view/${nextClimb.climb.uuid}`;
: (() => { throw new Error('Board details are missing required slug information'); })();

return (
<Link
Expand Down
5 changes: 2 additions & 3 deletions app/components/queue-control/previous-climb-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ const PreviousButton = (props: ButtonProps) => (

export default function PreviousClimbButton({ navigate = false, boardDetails }: PreviousClimbButtonProps) {
const { getPreviousClimbQueueItem, setCurrentClimbQueueItem, viewOnlyMode } = useQueueContext();
const { board_name, layout_id, size_id, set_ids, angle } =
parseBoardRouteParams(useParams<BoardRouteParametersWithUuid>());
const { angle } = parseBoardRouteParams(useParams<BoardRouteParametersWithUuid>());

const previousClimb = getPreviousClimbQueueItem();

Expand All @@ -48,7 +47,7 @@ export default function PreviousClimbButton({ navigate = false, boardDetails }:
previousClimb.climb.uuid,
previousClimb.climb.name,
)
: `/${board_name}/${layout_id}/${size_id}/${set_ids}/${angle}/view/${previousClimb.climb.uuid}`;
: (() => { throw new Error('Board details are missing required slug information'); })();

return (
<Link
Expand Down
16 changes: 6 additions & 10 deletions app/components/setup-wizard/board-config-preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,24 +88,20 @@ export default function BoardConfigPreview({ config, onDelete, boardConfigs }: B
savedAngle,
);
} else {
// Fallback to old URL format
const setsString = config.setIds.join(',');
url = `/${config.board}/${config.layoutId}/${config.sizeId}/${setsString}/${savedAngle}/list`;
// This should not happen as boardDetails should always have the necessary fields
throw new Error('Board details are missing required slug information');
}
} catch (error) {
console.error('Error generating board URL:', error);
// Fallback to old URL format
const setsString = config.setIds.join(',');
url = `/${config.board}/${config.layoutId}/${config.sizeId}/${setsString}/${savedAngle}/list`;
// Re-throw error instead of falling back to old URL format
throw error;
}

setBoardUrl(url);
} catch (error) {
console.error('Failed to load board details for preview:', error);
// Set fallback URL even if loading fails
const setsString = config.setIds.join(',');
const savedAngle = config.angle || 40;
setBoardUrl(`/${config.board}/${config.layoutId}/${config.sizeId}/${setsString}/${savedAngle}/list`);
// Re-throw error instead of falling back to old URL format
throw error;
} finally {
setIsLoading(false);
}
Expand Down
22 changes: 8 additions & 14 deletions app/components/setup-wizard/consolidated-board-config.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,6 @@ const ConsolidatedBoardConfig = ({ boardConfigs }: ConsolidatedBoardConfigProps)
setUseAsDefault(defaultConfig.useAsDefault);

// Redirect immediately if there's a default
const setsString = defaultConfig.setIds.join(',');
const savedAngle = defaultConfig.angle || 40;

try {
Expand All @@ -196,17 +195,13 @@ const ConsolidatedBoardConfig = ({ boardConfigs }: ConsolidatedBoardConfigProps)
);
router.push(slugUrl);
} else {
// Fallback to old URL format
router.push(
`/${defaultConfig.board}/${defaultConfig.layoutId}/${defaultConfig.sizeId}/${setsString}/${savedAngle}/list`,
);
// This should not happen as boardDetails should always have the necessary fields
throw new Error('Board details are missing required slug information for default config');
}
} catch (error) {
console.error('Error fetching board details for slug URL:', error);
// Fallback to old URL format
router.push(
`/${defaultConfig.board}/${defaultConfig.layoutId}/${defaultConfig.sizeId}/${setsString}/${savedAngle}/list`,
);
// Re-throw error instead of falling back to old URL format
throw error;
}
}
};
Expand Down Expand Up @@ -357,7 +352,6 @@ const ConsolidatedBoardConfig = ({ boardConfigs }: ConsolidatedBoardConfigProps)
const updatedConfigs = await loadAllConfigurations();
setSavedConfigurations(updatedConfigs);

const setsString = selectedSets.join(',');

try {
// Try to get board details for slug-based URL
Expand All @@ -373,13 +367,13 @@ const ConsolidatedBoardConfig = ({ boardConfigs }: ConsolidatedBoardConfigProps)
);
router.push(slugUrl);
} else {
// Fallback to old URL format
router.push(`/${selectedBoard}/${selectedLayout}/${selectedSize}/${setsString}/${selectedAngle}/list`);
// This should not happen as boardDetails should always have the necessary fields
throw new Error('Board details are missing required slug information');
}
} catch (error) {
console.error('Error fetching board details for slug URL:', error);
// Fallback to old URL format
router.push(`/${selectedBoard}/${selectedLayout}/${selectedSize}/${setsString}/${selectedAngle}/list`);
// Re-throw error instead of falling back to old URL format
throw error;
}
} catch (error) {
console.error('Error starting climbing session:', error);
Expand Down
9 changes: 4 additions & 5 deletions app/components/setup-wizard/start-climbing-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,14 +116,13 @@ export default function StartClimbingButton({
selectedAngle,
);
} else {
// Fallback to old URL format
return `/${selectedBoard}/${selectedLayout}/${selectedSize}/${setsString}/${selectedAngle}/list`;
// This should not happen as boardDetails should always have the necessary fields
throw new Error('Board details are missing required slug information');
}
} catch (error) {
console.error('Error generating climbing URL:', error);
// Fallback to old URL format
const setsString = selectedSets.join(',');
return `/${selectedBoard}/${selectedLayout}/${selectedSize}/${setsString}/${selectedAngle}/list`;
// Re-throw error instead of falling back to old URL format
throw error;
} finally {
setIsGeneratingUrl(false);
}
Expand Down
Loading