Skip to content

Commit a9d2577

Browse files
linting fixes
1 parent 4cc1b0a commit a9d2577

File tree

10 files changed

+121
-110
lines changed

10 files changed

+121
-110
lines changed

src/app/list/page.tsx

+24-33
Original file line numberDiff line numberDiff line change
@@ -6,48 +6,39 @@ import { DataTable } from '../../components/list/data-table';
66
import { useShallowStore } from '~/store';
77

88
import React from 'react';
9-
import { type Photo } from '~/server/db/schema';
9+
10+
const groupBy = <T, K extends PropertyKey>(arr: T[], key: (i: T) => K) =>
11+
arr.reduce(
12+
(groups, item) => {
13+
(groups[key(item)] ||= []).push(item);
14+
return groups;
15+
},
16+
{} as Record<K, T[]>,
17+
);
1018

1119
export default function ListPage() {
12-
const {
13-
selected,
14-
setSelected,
15-
activityDict,
16-
filterIDs,
17-
tableState,
18-
photos,
19-
loaded,
20-
} = useShallowStore((state) => ({
21-
selected: state.selected,
22-
setSelected: state.setSelected,
23-
activityDict: state.activityDict,
24-
filterIDs: state.filterIDs,
25-
tableState: state.fullList,
26-
photos: state.photos,
27-
loaded: state.loaded,
28-
}));
20+
const { selected, setSelected, activityDict, filterIDs, tableState, photos } =
21+
useShallowStore((state) => ({
22+
selected: state.selected,
23+
setSelected: state.setSelected,
24+
activityDict: state.activityDict,
25+
filterIDs: state.filterIDs,
26+
tableState: state.fullList,
27+
photos: state.photos,
28+
}));
2929

3030
const columnFilters = [{ id: 'id', value: filterIDs }];
31-
const photoDict = photos.reduce(
32-
(acc, photo) => {
33-
const id = photo.activity_id;
34-
if (id in acc) {
35-
acc[id].push(photo);
36-
} else {
37-
acc[id] = [photo];
38-
}
39-
return acc;
40-
},
41-
{} as Record<number, Photo[]>,
42-
);
31+
const photoDict = groupBy(photos, (photo) => photo.activity_id);
32+
4333
const rows = React.useMemo(() => {
44-
return Object.values(activityDict).map((act) => {
45-
const photos = photoDict[(act as { id: number }).id] ?? [];
34+
const result = Object.entries(activityDict).map(([idStr, act]) => {
35+
const id = parseInt(idStr);
4636
return {
4737
...act,
48-
photos,
38+
...(id in photoDict && { photos: photoDict[id] }),
4939
};
5040
});
41+
return result;
5142
}, [activityDict, photoDict]);
5243

5344
return (

src/app/map/page.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ function Map() {
214214
if (map) {
215215
setTimeout(() => map.resize(), 200);
216216
}
217-
}, [open]);
217+
}, [open, mapRefLoc]);
218218

219219
const [viewport, setViewport] = useState(mapPosition);
220220

@@ -372,7 +372,7 @@ function Map() {
372372
data={rows}
373373
selected={selected}
374374
setSelected={setSelected}
375-
map={mapRefLoc}
375+
map={mapRefLoc.current ?? undefined}
376376
columnFilters={columnFilters}
377377
{...compactList}
378378
/>

src/components/Share.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export function ShareButton() {
3838
useEffect(() => {
3939
const url = new URL(window.location.origin);
4040
if (shareMode === 'selected' && selected.length > 0) {
41-
// Get public_ids directly from activityDict
41+
// Get public_ids from activityDict for sharing
4242
const publicIds = selected
4343
.map((id) => activityDict[id]?.public_id)
4444
.filter(Boolean);

src/components/app-header.tsx

+2-6
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,10 @@ import { ShareButton } from './Share';
1313

1414
export function ModeToggle() {
1515
const { setTheme, theme } = useTheme();
16-
const themeMap = { undefined: 'light', dark: 'light', light: 'dark' };
16+
const toggleTheme = () => setTheme(theme === 'dark' ? 'light' : 'dark');
1717

1818
return (
19-
<Button
20-
variant="ghost"
21-
size="icon"
22-
onClick={() => setTheme(themeMap[theme])}
23-
>
19+
<Button variant="ghost" size="icon" onClick={toggleTheme}>
2420
<Sun className="rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
2521
<Moon className="absolute rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
2622
</Button>

src/components/list/columns.tsx

+24-27
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,24 @@
33
import { type ColumnDef, type Table } from '@tanstack/react-table';
44
import { Pin } from 'lucide-react';
55
import { Checkbox } from '~/components/ui/checkbox';
6-
import { type ComponentType } from 'react';
76

87
import { type Activity, type Photo } from '~/server/db/schema';
98
import { Button } from '~/components/ui/button';
109

1110
import { DataTableColumnHeader } from './data-table';
12-
import { activityFields } from '~/settings/activity';
11+
import {
12+
activityFields,
13+
type ActivityField,
14+
type ActivityValueType,
15+
} from '~/settings/activity';
1316

1417
import { ActivityCard, DescriptionCard } from './card';
1518
import { EditActivity } from './edit';
1619
import { PhotoLightbox } from './photo';
1720

18-
type ActivityField = {
19-
formatter: (value: any) => string | null;
20-
Icon?: ComponentType<any>;
21-
title: string;
22-
reducer?: (values: any[]) => number;
23-
reducerSymbol?: string;
24-
summaryFormatter?: (value: any) => string;
25-
accessorFn?: (row: Activity) => any;
26-
};
27-
28-
function columnFromField(
21+
function columnFromField<K extends ActivityValueType>(
2922
id: keyof typeof activityFields,
30-
spec: ActivityField,
23+
spec: ActivityField<K>,
3124
): ColumnDef<Activity> {
3225
const footer = ({ table }: { table: Table<Activity> }) => {
3326
const rows =
@@ -38,21 +31,20 @@ function columnFromField(
3831
: table.getState().summaryRow == 'all'
3932
? table.getFilteredRowModel().rows
4033
: table.getSelectedRowModel().rows;
41-
const values = rows.map((row) => row.getValue(id));
34+
const values: K[] = rows.map((row) => row.getValue(id));
4235
const reducedValue = spec.reducer ? spec.reducer(values) : null;
43-
const summary =
44-
spec.summaryFormatter && reducedValue != null
45-
? spec.summaryFormatter(reducedValue)
46-
: reducedValue != null
47-
? `${spec.reducerSymbol ?? ''}${spec.formatter(reducedValue)}`
48-
: '';
36+
const summary = spec.summary
37+
? spec.summary(values)
38+
: reducedValue != null
39+
? `${spec.reducerSymbol ?? ''}${spec.formatter(reducedValue)}`
40+
: '';
4941
return <div className="text-right w-full">{summary}</div>;
5042
};
5143

5244
return {
5345
id,
5446
cell: ({ getValue }) => (
55-
<div className="text-right w-full">{spec.formatter(getValue())}</div>
47+
<div className="text-right w-full">{spec.formatter(getValue() as K)}</div>
5648
),
5749
meta: {
5850
title: spec.title,
@@ -68,7 +60,7 @@ function columnFromField(
6860
enableResizing: true,
6961
...(spec.accessorFn && { accessorFn: spec.accessorFn }),
7062
...(!spec.accessorFn && { accessorKey: id }),
71-
...(spec.reducer && { footer }),
63+
...((spec.reducer ?? spec.summary) && { footer }),
7264
};
7365
}
7466

@@ -80,9 +72,11 @@ export const columns: ColumnDef<Activity>[] = [
8072
<DataTableColumnHeader table={table} column={column} title="ID" />
8173
),
8274
enableHiding: false,
83-
filterFn: (row, columnId, filterValue) => {
84-
return filterValue.includes(row.original.public_id);
85-
},
75+
filterFn: (
76+
row: { original: Activity },
77+
_columnId: string,
78+
filterValue: number[],
79+
) => filterValue.includes(row.original.id),
8680
},
8781
{
8882
id: 'name',
@@ -128,7 +122,10 @@ export const columns: ColumnDef<Activity>[] = [
128122
enableHiding: false,
129123
},
130124
...Object.entries(activityFields).map(([id, spec]) =>
131-
columnFromField(id as keyof typeof activityFields, spec as ActivityField),
125+
columnFromField(
126+
id as keyof typeof activityFields,
127+
spec as ActivityField<ActivityValueType>,
128+
),
132129
),
133130
{
134131
id: 'description',

src/components/list/edit.tsx

+1-2
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ import {
3838
} from '~/components/ui/select';
3939
import { aliasMap, colorMap, iconMap } from '~/settings/category';
4040
import { useShallowStore } from '~/store';
41-
import { LucideIcon } from 'lucide-react';
4241

4342
const formSchema = z.object({
4443
name: z.string().min(2, {
@@ -73,7 +72,7 @@ export function ProfileForm({
7372
resolver: zodResolver(formSchema),
7473
defaultValues: {
7574
name: row.original.name,
76-
description: row.original.description || '',
75+
description: row.original.description ?? '',
7776
sportType: row.original.sport_type,
7877
},
7978
});

src/components/list/photo.tsx

+27-13
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,21 @@ export function PhotoLightbox({
2626
}: PhotoLightboxProps) {
2727
const [open, setOpen] = useState(false);
2828
const [api, setApi] = useState<CarouselApi>();
29-
const [currentIndex, setCurrentIndex] = useState(0);
29+
30+
const smallPhotos = photos.map((photo) => ({
31+
url: photo.urls ? (Object.values(photo.urls)[0] ?? '') : '',
32+
unique_id: photo.unique_id,
33+
caption: photo.caption ?? '',
34+
width: photo.sizes ? Object.values(photo.sizes)[0]?.[0] : 0,
35+
height: photo.sizes ? Object.values(photo.sizes)[0]?.[1] : 0,
36+
}));
37+
const largePhotos = photos.map((photo) => ({
38+
url: photo.urls ? (Object.values(photo.urls).at(-1) ?? '') : '',
39+
unique_id: photo.unique_id,
40+
caption: photo.caption ?? '',
41+
width: photo.sizes ? Object.values(photo.sizes).at(-1)?.[0] : 0,
42+
height: photo.sizes ? Object.values(photo.sizes).at(-1)?.[1] : 0,
43+
}));
3044

3145
return (
3246
<>
@@ -36,18 +50,18 @@ export function PhotoLightbox({
3650
className,
3751
)}
3852
>
39-
{photos?.map((photo, index) => (
53+
{smallPhotos.map((photo, index) => (
4054
<Button
4155
key={photo.unique_id}
4256
variant="ghost"
4357
size="icon"
4458
className="p-0 h-full rounded-sm aspect-square object-cover w-auto"
4559
>
46-
<Image
47-
src={photo.urls ? Object.values(photo.urls)[0] : ''}
48-
width={Object.values(photo.sizes)[0][0]}
49-
height={Object.values(photo.sizes)[0][1]}
50-
alt={photo.caption ?? ''}
60+
<img
61+
src={photo.url}
62+
//width={photo.width}
63+
//height={photo.height}
64+
alt={photo.caption}
5165
className="h-full rounded-sm aspect-square object-cover"
5266
onClick={() => {
5367
api?.scrollTo(index);
@@ -65,16 +79,16 @@ export function PhotoLightbox({
6579
<DialogTitle className="hidden">{title}</DialogTitle>
6680
<Carousel className="relative" setApi={(api) => setApi(api)}>
6781
<CarouselContent className="h-full absolute inset-0 ml-0">
68-
{photos.map((photo, index) => (
82+
{largePhotos.map((photo) => (
6983
<CarouselItem
7084
key={photo.unique_id}
7185
className="flex items-center justify-center pl-0"
7286
>
73-
<Image
74-
src={photo.urls ? Object.values(photo.urls).at(-1) : ''}
75-
width={Object.values(photo.sizes).at(-1)?.[0] ?? 0}
76-
height={Object.values(photo.sizes).at(-1)?.[1] ?? 0}
77-
alt={photo.caption ?? ''}
87+
<img
88+
src={photo.url}
89+
//width={photo.width}
90+
//height={photo.height}
91+
alt={photo.caption}
7892
className="max-w-[calc(100vw-4rem)] max-h-[calc(100vh-4rem)] object-contain rounded-lg border-2 border-background"
7993
onClick={(e) => e.stopPropagation()}
8094
/>

0 commit comments

Comments
 (0)