Skip to content

Commit

Permalink
Merge pull request #93 from marcodejongh/one_climbstat_per_uuid_angle
Browse files Browse the repository at this point in the history
One climbstat per UUID angle
  • Loading branch information
marcodejongh authored Dec 28, 2024
2 parents b3f8c18 + ee5b6fc commit cc0f89f
Show file tree
Hide file tree
Showing 35 changed files with 6,864 additions and 2,586 deletions.
7 changes: 6 additions & 1 deletion .env.development.local
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,9 @@
# docker container
VERCEL_ENV=development
POSTGRES_URL=postgresql://postgres:password@localhost:54320/verceldb
BASE_URL=http://localhost:3000
BASE_URL=http://localhost:3000
POSTGRES_HOST=localhost
POSTGRES_PORT=54320
POSTGRES_USER=postgres
POSTGRES_PASSWORD=password
POSTGRES_DATABASE=verceldb
5 changes: 1 addition & 4 deletions app/api/internal/shared-sync/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,7 @@ export async function GET(request: Request) {
}

// Sync both board types
const results = await Promise.all([
syncSharedData('tension'),
syncSharedData('kilter')
]);
const results = await Promise.all([syncSharedData('tension'), syncSharedData('kilter')]);

return NextResponse.json({
success: true,
Expand Down
2 changes: 1 addition & 1 deletion app/components/climb-card/climb-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type ClimbCardProps = {

const ClimbCard = ({ climb, boardDetails, onCoverClick, selected, actions }: ClimbCardProps) => {
const cover = <ClimbCardCover climb={climb} boardDetails={boardDetails} onClick={onCoverClick} />;

const cardTitle = climb ? (
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
{/* LEFT: Name, Angle, Benchmark */}
Expand Down
2 changes: 1 addition & 1 deletion app/components/logbook/logascent-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -164,4 +164,4 @@ export const LogAscentForm: React.FC<LogAscentFormProps> = ({ currentClimb, boar
</Form.Item>
</Form>
);
};
};
132 changes: 77 additions & 55 deletions app/components/logbook/logbook-stats.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
import React, { useEffect, useState } from 'react';
import { Bar, Pie } from 'react-chartjs-2';
import { Chart as ChartJS, CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend, ArcElement, TooltipItem } from 'chart.js';
import {
Chart as ChartJS,
CategoryScale,
LinearScale,
BarElement,
Title,
Tooltip,
Legend,
ArcElement,
TooltipItem,
} from 'chart.js';
import dayjs from 'dayjs';
import isoWeek from 'dayjs/plugin/isoWeek';
dayjs.extend(isoWeek);
Expand Down Expand Up @@ -110,30 +120,30 @@ const difficultyMapping: Record<number, string> = {
};

const gradeColors: Record<string, string> = {
'4a': 'rgba(153,255,153,0.7)', // Light Green
'4b': 'rgba(179,255,128,0.7)', // Soft Green-Yellow
'4c': 'rgba(204,255,102,0.7)', // Yellow-Green
'5a': 'rgba(230,255,77,0.7)', // Yellowish
'5b': 'rgba(255,255,51,0.7)', // Yellow
'5c': 'rgba(255,230,25,0.7)', // Dark Yellow
'6a': 'rgba(255,204,51,0.7)', // Golden Yellow
'6a+': 'rgba(255,179,77,0.7)', // Light Orange
'6b': 'rgba(255,153,102,0.7)', // Orange
'4a': 'rgba(153,255,153,0.7)', // Light Green
'4b': 'rgba(179,255,128,0.7)', // Soft Green-Yellow
'4c': 'rgba(204,255,102,0.7)', // Yellow-Green
'5a': 'rgba(230,255,77,0.7)', // Yellowish
'5b': 'rgba(255,255,51,0.7)', // Yellow
'5c': 'rgba(255,230,25,0.7)', // Dark Yellow
'6a': 'rgba(255,204,51,0.7)', // Golden Yellow
'6a+': 'rgba(255,179,77,0.7)', // Light Orange
'6b': 'rgba(255,153,102,0.7)', // Orange
'6b+': 'rgba(255,128,128,0.7)', // Peachy Red
'6c': 'rgba(204,102,204,0.7)', // Light Violet
'6c': 'rgba(204,102,204,0.7)', // Light Violet
'6c+': 'rgba(153,102,255,0.7)', // Indigo
'7a': 'rgba(102,102,255,0.7)', // Blue
'7a+': 'rgba(77,128,255,0.7)', // Light Blue
'7b': 'rgba(51,153,255,0.7)', // Sky Blue
'7b+': 'rgba(25,179,255,0.7)', // Cyan
'7c': 'rgba(25,204,230,0.7)', // Light Cyan
'7c+': 'rgba(51,204,204,0.7)', // Blue-Green
'8a': 'rgba(255,77,77,0.7)', // Red
'8a+': 'rgba(204,51,153,0.7)', // Deep Magenta
'8b': 'rgba(153,51,204,0.9)', // Purple
'8b+': 'rgba(102,51,153,1)', // Dark Purple
'8c': 'rgba(77,25,128,1)', // Very Dark Purple
'8c+': 'rgba(51,0,102,1)', // Deep Violet
'7a': 'rgba(102,102,255,0.7)', // Blue
'7a+': 'rgba(77,128,255,0.7)', // Light Blue
'7b': 'rgba(51,153,255,0.7)', // Sky Blue
'7b+': 'rgba(25,179,255,0.7)', // Cyan
'7c': 'rgba(25,204,230,0.7)', // Light Cyan
'7c+': 'rgba(51,204,204,0.7)', // Blue-Green
'8a': 'rgba(255,77,77,0.7)', // Red
'8a+': 'rgba(204,51,153,0.7)', // Deep Magenta
'8b': 'rgba(153,51,204,0.9)', // Purple
'8b+': 'rgba(102,51,153,1)', // Dark Purple
'8c': 'rgba(77,25,128,1)', // Very Dark Purple
'8c+': 'rgba(51,0,102,1)', // Deep Violet
};

// Define types for logbook entries
Expand Down Expand Up @@ -170,7 +180,7 @@ export const LogBookStats: React.FC<{ boardName: string; userId: string }> = ({
const response = await fetch(`/api/v1/${boardName}/proxy/getLogbook`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ userId, climbUuids: "", }),
body: JSON.stringify({ userId, climbUuids: '' }),
});
const data = await response.json();
setLogbook(data);
Expand All @@ -185,13 +195,13 @@ export const LogBookStats: React.FC<{ boardName: string; userId: string }> = ({
const now = dayjs();
switch (timeframe) {
case 'lastWeek':
return logbook.filter(entry => dayjs(entry.climbed_at).isAfter(now.subtract(1, 'week')));
return logbook.filter((entry) => dayjs(entry.climbed_at).isAfter(now.subtract(1, 'week')));
case 'lastMonth':
return logbook.filter(entry => dayjs(entry.climbed_at).isAfter(now.subtract(1, 'month')));
return logbook.filter((entry) => dayjs(entry.climbed_at).isAfter(now.subtract(1, 'month')));
case 'lastYear':
return logbook.filter(entry => dayjs(entry.climbed_at).isAfter(now.subtract(1, 'year')));
return logbook.filter((entry) => dayjs(entry.climbed_at).isAfter(now.subtract(1, 'year')));
case 'custom':
return logbook.filter(entry => {
return logbook.filter((entry) => {
const climbedAt = dayjs(entry.climbed_at);
return climbedAt.isAfter(dayjs(fromDate)) && climbedAt.isBefore(dayjs(toDate));
});
Expand Down Expand Up @@ -250,19 +260,19 @@ export const LogBookStats: React.FC<{ boardName: string; userId: string }> = ({
data: Object.values(angles),
backgroundColor: Object.keys(angles).map((_, index) => {
const angleColors = [
'rgba(255,77,77,0.7)', // Red
'rgba(51,0,102,1)', // Deep Violet
'rgba(77,128,255,0.7)', // Light Blue
'rgba(255,204,51,0.7)', // Golden Yellow
'rgba(204,51,153,0.7)', // Deep Magenta
'rgba(51,204,204,0.7)', // Blue-Green
'rgba(255,230,25,0.7)', // Dark Yellow
'rgba(102,102,255,0.7)', // Blue
'rgba(51,153,255,0.7)', // Sky Blue
'rgba(25,179,255,0.7)', // Cyan
'rgba(255,255,51,0.7)', // Yellow
'rgba(102,51,153,1)', // Dark Purple
'rgba(179,255,128,0.7)', // Soft Green-Yellow
'rgba(255,77,77,0.7)', // Red
'rgba(51,0,102,1)', // Deep Violet
'rgba(77,128,255,0.7)', // Light Blue
'rgba(255,204,51,0.7)', // Golden Yellow
'rgba(204,51,153,0.7)', // Deep Magenta
'rgba(51,204,204,0.7)', // Blue-Green
'rgba(255,230,25,0.7)', // Dark Yellow
'rgba(102,102,255,0.7)', // Blue
'rgba(51,153,255,0.7)', // Sky Blue
'rgba(25,179,255,0.7)', // Cyan
'rgba(255,255,51,0.7)', // Yellow
'rgba(102,51,153,1)', // Dark Purple
'rgba(179,255,128,0.7)', // Soft Green-Yellow
];
return angleColors[index] || 'rgba(200,200,200,0.7)';
}),
Expand Down Expand Up @@ -291,22 +301,24 @@ export const LogBookStats: React.FC<{ boardName: string; userId: string }> = ({
[difficulty]: (weeklyData[week]?.[difficulty] || 0) + 1,
};
});
const datasets = Object.values(difficultyMapping).map((difficulty) => {
const data = weeks.map((week) => weeklyData[week]?.[difficulty] || 0);
return {
label: difficulty,
data,
backgroundColor: gradeColors[difficulty],
};
}).filter(dataset => dataset.data.some(value => value > 0)); // Ensure datasets with all zero values are filtered out
const datasets = Object.values(difficultyMapping)
.map((difficulty) => {
const data = weeks.map((week) => weeklyData[week]?.[difficulty] || 0);
return {
label: difficulty,
data,
backgroundColor: gradeColors[difficulty],
};
})
.filter((dataset) => dataset.data.some((value) => value > 0)); // Ensure datasets with all zero values are filtered out

setChartDataWeeklyBar({
labels: weeks,
datasets,
});
}
}, [filteredLogbook]);

const buttonStyle = (btnTimeframe: string) => ({
marginRight: '10px',
backgroundColor: timeframe === btnTimeframe ? '#007bff' : '#f8f9fa',
Expand All @@ -320,11 +332,21 @@ export const LogBookStats: React.FC<{ boardName: string; userId: string }> = ({
<div style={{ width: '80%', margin: '0 auto', padding: '20px' }}>
<h3>LogBook Stats</h3>
<div style={{ marginBottom: '20px' }}>
<button onClick={() => setTimeframe('all')} style={buttonStyle('all')}>All</button>
<button onClick={() => setTimeframe('lastYear')} style={buttonStyle('lastYear')}>Last Year</button>
<button onClick={() => setTimeframe('lastMonth')} style={buttonStyle('lastMonth')}>Last Month</button>
<button onClick={() => setTimeframe('lastWeek')} style={buttonStyle('lastWeek')}>Last Week</button>
<button onClick={() => setTimeframe('custom')} style={buttonStyle('custom')}>Select Timeframe</button>
<button onClick={() => setTimeframe('all')} style={buttonStyle('all')}>
All
</button>
<button onClick={() => setTimeframe('lastYear')} style={buttonStyle('lastYear')}>
Last Year
</button>
<button onClick={() => setTimeframe('lastMonth')} style={buttonStyle('lastMonth')}>
Last Month
</button>
<button onClick={() => setTimeframe('lastWeek')} style={buttonStyle('lastWeek')}>
Last Week
</button>
<button onClick={() => setTimeframe('custom')} style={buttonStyle('custom')}>
Select Timeframe
</button>
{timeframe === 'custom' && (
<div style={{ marginTop: '10px' }}>
<label>
Expand Down
2 changes: 1 addition & 1 deletion app/components/rest-api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export const fetchClimbs = async (

// Build the URL using the new route structure
const response = await fetch(
`${API_BASE_URL}/v1/${routeParameters.board_name}/${routeParameters.layout_id}/${routeParameters.size_id}/${routeParameters.set_ids}/${routeParameters.angle}/search?${urlParams}&bustCache=38`,
`${API_BASE_URL}/v1/${routeParameters.board_name}/${routeParameters.layout_id}/${routeParameters.size_id}/${routeParameters.set_ids}/${routeParameters.angle}/search?${urlParams}&bustCache=40`,
);

const rawResults = await response.json();
Expand Down
5 changes: 1 addition & 4 deletions app/components/setup-wizard/sets-selection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@ const SetsSelection = ({ sets = [] }: { sets: SetRow[] }) => {
<div style={{ padding: '24px', background: '#f7f7f7', borderRadius: '8px' }}>
<Title level={4}>Select Hold Sets</Title>
<Form layout="vertical">
<Form.Item
label="Sets"
required
tooltip="Select hold types">
<Form.Item label="Sets" required tooltip="Select hold types">
<Select mode="multiple" value={selectedSize} onChange={(value) => setSelectedSize(value)}>
{sets.map(({ id, name }) => (
<Option key={id} value={id}>
Expand Down
14 changes: 3 additions & 11 deletions app/components/setup-wizard/size-selection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,8 @@ const SizeSelection = ({ sizes = [] }: { sizes: SizeRow[] }) => {
<div style={{ padding: '24px', background: '#f7f7f7', borderRadius: '8px' }}>
<Title level={4}>Select a size</Title>
<Form layout="vertical">
<Form.Item
label="Size"
required
tooltip="Choose your current board size"
>
<Select
placeholder="Choose a size"
value={selectedSize}
onChange={(value) => setSelectedSize(value)}
>
<Form.Item label="Size" required tooltip="Choose your current board size">
<Select placeholder="Choose a size" value={selectedSize} onChange={(value) => setSelectedSize(value)}>
{sizes.map(({ id, name, description }) => (
<Option key={id} value={id}>
{`${name} ${description}`}
Expand All @@ -52,4 +44,4 @@ const SizeSelection = ({ sizes = [] }: { sizes: SizeRow[] }) => {
);
};

export default SizeSelection;
export default SizeSelection;
1 change: 0 additions & 1 deletion app/lib/api-wrappers/aurora/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,4 +199,3 @@ export const SHARED_SYNC_TABLES = [
'climb_stats',
'beta_links',
];

2 changes: 1 addition & 1 deletion app/lib/api-wrappers/aurora/user/follows-save.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@
// accept-encoding: gzip, deflate, br
// cookie: token=XXXX

// followee_id=44710&follower_id=118684&state=pending
// followee_id=44710&follower_id=118684&state=pending
2 changes: 0 additions & 2 deletions app/lib/api-wrappers/aurora/user/getLogbook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
// accept-encoding: gzip, deflate, br
// cookie: token=XXXX



// Common fields for all logbook entries
interface BaseLogbookEntry {
_type: 'bid' | 'ascent'; // Discriminator type, e.g., "bid" or "ascent"
Expand Down
6 changes: 3 additions & 3 deletions app/lib/api-wrappers/aurora/user/getUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ export interface Circuit {
uuid: string;
name: string;
description: string;
color: string;
user_id: number;
color: string;
user_id: number;
is_public: boolean;
is_listed: boolean;
created_at: string;
updated_at: string;
user: CircuitUser;
count: number;
count: number;
}

export interface User {
Expand Down
5 changes: 1 addition & 4 deletions app/lib/api-wrappers/aurora/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@ export function generateUuid(): string {
return uuidv4().replace(/-/g, '').toUpperCase();
}

export async function auroraGetApi<T>(
url: string,
token: string,
): Promise<T> {
export async function auroraGetApi<T>(url: string, token: string): Promise<T> {
// Default headers
const headers: Record<string, string> = {
Accept: '*/*', // Accept any content type
Expand Down
2 changes: 1 addition & 1 deletion app/lib/data-sync/aurora/getTableName.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BoardName } from "../../types";
import { BoardName } from '../../types';

export const getTableName = (boardName: BoardName, tableName: string) => {
if (!boardName) {
Expand Down
Loading

1 comment on commit cc0f89f

@vercel
Copy link

@vercel vercel bot commented on cc0f89f Dec 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.