Skip to content

Commit e6ea815

Browse files
committed
Use pitch to display skyboxes in the grid
1 parent d26e2b4 commit e6ea815

File tree

2 files changed

+88
-46
lines changed

2 files changed

+88
-46
lines changed

app/ui/skyboxgrid.tsx

Lines changed: 87 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,78 +1,120 @@
11

2-
import { useMemo } from 'react';
2+
import { useMemo, ReactElement } from 'react';
33
import SkyboxCard from './skyboxcard';
44

55
// Define the SortOption type matching the one in header.tsx / page.tsx
66
import { SortOption } from './sort-types';
77

8+
// Import Sun type from SunParams component
9+
import type { Sun } from './sunparameters';
10+
811
const TIME_OF_DAY_ORDER = ['Morning', 'Afternoon', 'Evening', 'Night', 'Other'];
912
const WEATHER_CONDITIONS_ORDER = ['Clear', 'Cloudy', 'Hazy', 'Overcast', 'Other'];
1013

14+
// Helper types
15+
interface SkyboxMeta {
16+
timeOfDay?: string;
17+
weatherCondition?: string;
18+
sunParameters?: Sun;
19+
title?: string;
20+
}
21+
22+
// Helper functions
23+
function getSkyboxCategory(slug: string, meta: Record<string, SkyboxMeta>, category: 'timeOfDay' | 'weatherCondition'): string {
24+
return meta[slug]?.[category] || 'Other';
25+
}
26+
27+
function filterByQuery(slugs: string[], meta: Record<string, SkyboxMeta>, query: string): string[] {
28+
if (!query) return slugs;
29+
const q = query.toLowerCase();
30+
return slugs.filter(slug =>
31+
slug.includes(q) ||
32+
meta[slug]?.title?.toLowerCase().includes(q)
33+
);
34+
}
35+
36+
function sortSkyboxesByPitch(slugs: string[], meta: Record<string, SkyboxMeta>): string[] {
37+
const sortedSlugs = [...slugs];
38+
return sortedSlugs.sort((slugA, slugB) => {
39+
const pitchA = meta[slugA]?.sunParameters?.pitch;
40+
const pitchValueA = pitchA !== undefined
41+
? (typeof pitchA === 'string' ? parseFloat(pitchA) : pitchA)
42+
: 0;
43+
const pitchB = meta[slugB]?.sunParameters?.pitch;
44+
const pitchValueB = pitchB !== undefined
45+
? (typeof pitchB === 'string' ? parseFloat(pitchB) : pitchB)
46+
: 0;
47+
const absPitchA = Math.abs(pitchValueA);
48+
const absPitchB = Math.abs(pitchValueB);
49+
return absPitchB - absPitchA;
50+
});
51+
}
52+
53+
// Helper function to group skyboxes by category
54+
function groupSkyboxes(
55+
slugs: string[],
56+
meta: Record<string, SkyboxMeta>,
57+
category: 'timeOfDay' | 'weatherCondition'
58+
): Record<string, string[]> {
59+
const groups: Record<string, string[]> = {};
60+
61+
slugs.forEach(slug => {
62+
const categoryValue = getSkyboxCategory(slug, meta, category);
63+
if (!groups[categoryValue]) {
64+
groups[categoryValue] = [];
65+
}
66+
groups[categoryValue].push(slug);
67+
});
68+
69+
return groups;
70+
}
71+
72+
function groupAndSortSkyboxes(
73+
slugs: string[],
74+
meta: Record<string, SkyboxMeta>,
75+
category: 'timeOfDay' | 'weatherCondition'
76+
): { title: string; slugs: string[] }[] {
77+
const groups = groupSkyboxes(slugs, meta, category);
78+
const order = category === 'timeOfDay' ? TIME_OF_DAY_ORDER : WEATHER_CONDITIONS_ORDER;
79+
return order
80+
.filter(cat => groups[cat])
81+
.map(cat => ({
82+
title: cat,
83+
slugs: sortSkyboxesByPitch(groups[cat], meta)
84+
}));
85+
}
86+
1187
export default function SkyboxGrid({
1288
slugs,
1389
meta,
1490
sort = 'time-of-day',
1591
query,
1692
}: {
1793
slugs: string[];
18-
meta: Record<string, any>;
94+
meta: Record<string, SkyboxMeta>;
1995
sort?: SortOption;
2096
query: string;
21-
}) {
22-
const visible = useMemo(() => {
23-
let list = [...slugs];
24-
// Filter based on query prop
25-
if (query) {
26-
const q = query.toLowerCase();
27-
list = list.filter((s) => s.includes(q) || meta[s]?.title?.toLowerCase().includes(q));
28-
}
29-
return list;
30-
}, [slugs, meta, query]);
97+
}): ReactElement {
98+
const visible = useMemo(() => filterByQuery(slugs, meta, query), [slugs, meta, query]);
3199

32100
// Group skyboxes by time of day or weather conditions
33101
const groupedSkyboxes = useMemo(() => {
34-
if (sort === 'time-of-day') {
35-
const groups: Record<string, string[]> = {};
36-
37-
visible.forEach((slug) => {
38-
const timeOfDay = meta[slug]?.timeOfDay || 'Other';
39-
if (!groups[timeOfDay]) {
40-
groups[timeOfDay] = [];
41-
}
42-
groups[timeOfDay].push(slug);
43-
});
44-
45-
// Sort groups by predefined time of day order
46-
return TIME_OF_DAY_ORDER
47-
.filter(time => groups[time])
48-
.map(time => ({ title: time, slugs: groups[time] }));
49-
} else {
50-
const groups: Record<string, string[]> = {};
51-
52-
visible.forEach((slug) => {
53-
const weatherCondition = meta[slug]?.weatherCondition || 'Other';
54-
if (!groups[weatherCondition]) {
55-
groups[weatherCondition] = [];
56-
}
57-
groups[weatherCondition].push(slug);
58-
});
59-
60-
// Sort groups by predefined weather conditions order
61-
return WEATHER_CONDITIONS_ORDER
62-
.filter(weather => groups[weather])
63-
.map(weather => ({ title: weather, slugs: groups[weather] }));
64-
}
102+
return groupAndSortSkyboxes(
103+
visible,
104+
meta,
105+
sort === 'time-of-day' ? 'timeOfDay' : 'weatherCondition'
106+
);
65107
}, [visible, meta, sort]);
66108

67109
return (
68110
<div className="space-y-8 mx-auto px-4 py-8">
69-
{groupedSkyboxes.map(({ title, slugs }) => (
111+
{groupedSkyboxes.map(({ title, slugs }: { title: string; slugs: string[] }) => (
70112
<div key={title}>
71113
<div className="flex items-center justify-between mb-4">
72114
<h2 className="text-2xl font-bold text-neutral-200">{title} Skies</h2>
73115
</div>
74116
<div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-4">
75-
{slugs.map((slug) => (
117+
{slugs.map((slug: string) => (
76118
<SkyboxCard key={slug} slug={slug} meta={meta[slug]} />
77119
))}
78120
</div>

app/ui/sunparameters.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Swatch } from "./swatch";
22
import { ParamSection, ParamRow } from './parametersections';
33

4-
type Sun = {
4+
export type Sun = {
55
sunAngle?: string;
66
pitch?: string | number;
77
brightness?: number[];

0 commit comments

Comments
 (0)