Skip to content

Commit ad69824

Browse files
committed
add sort
1 parent e6a95dd commit ad69824

File tree

3 files changed

+85
-6
lines changed

3 files changed

+85
-6
lines changed

app/tools/paper-graph/PaperList.tsx

Lines changed: 78 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
'use client';
2-
import React from 'react';
2+
import { Dropdown } from '@components/molecules';
3+
import { ArrowDownIcon, ArrowDownUpIcon, ArrowUpIcon } from '@public/icons';
4+
import { useState } from 'react';
35

46
interface Props {
57
nodes: GraphNode[];
@@ -8,10 +10,78 @@ interface Props {
810
onClick: (node: GraphNode) => void;
911
}
1012

13+
const FIELDS: { [key in 'title' | 'year' | 'citationCount']: string } = {
14+
title: 'Title',
15+
year: 'Year',
16+
citationCount: 'Citations',
17+
}
18+
1119
export default function PaperList({ nodes, hoveredNodeId, onHover, onClick }: Props) {
20+
const [sort, setSort] = useState<{
21+
open: boolean,
22+
field: keyof typeof FIELDS,
23+
direction: 'asc' | 'desc'
24+
}
25+
>({ open: false, field: 'title', direction: 'asc' })
26+
27+
const sortedNodes = [...nodes].sort((a, b) => {
28+
const field = sort.field;
29+
const dir = sort.direction === 'asc' ? 1 : -1;
30+
31+
const aValue = a[field] ?? '';
32+
const bValue = b[field] ?? '';
33+
34+
if (typeof aValue === 'string' && typeof bValue === 'string') {
35+
return aValue.localeCompare(bValue) * dir;
36+
}
37+
if (typeof aValue === 'number' && typeof bValue === 'number') {
38+
return (aValue - bValue) * dir;
39+
}
40+
41+
return 0; // fallback
42+
});
43+
1244
return (
13-
<div className='h-[650px] overflow-auto shadow-gray-500 shadow-sm'>
14-
{nodes.map((node) => (
45+
<div className='paper-list overflow-auto max-h-[80vh] shadow-gray-500 shadow-sm'>
46+
<div className={`paper-list-options flex items-center justify-between`}>
47+
<span className='font-semibold'>
48+
{nodes.length} documents
49+
</span>
50+
<span className='sort-filter flex items-center gap-2 mx-2'>
51+
<Dropdown>
52+
<Dropdown.Toggler>
53+
<ArrowDownUpIcon
54+
size={18}
55+
onClick={() => setSort(prev => ({ ...prev, open: !prev.open }))}
56+
className='cursor-pointer'
57+
/>
58+
</Dropdown.Toggler>
59+
<Dropdown.Content>
60+
<div className='flex items-center border-2 bg-white rounded-md'>
61+
<span className={`sort-fields mr-10px`}>
62+
{Object.entries(FIELDS).map(([key, value]) => (
63+
<span className={`mr-2 py-[2px] px-[4px] ${sort.field === key ? 'bg-blue-200' : ''} cursor-pointer`} key={key} onClick={() => setSort(prev => ({
64+
...prev,
65+
field: key as 'title' | 'year' | 'citationCount'
66+
}))}>
67+
{value}
68+
</span>
69+
))}
70+
</span>
71+
<span className='sort-order flex items-center gap-[2px] cursor-pointer'>
72+
{sort.direction === 'asc'
73+
? <ArrowUpIcon size={20} onClick={() => setSort(prev => ({ ...prev, direction: 'desc' }))} />
74+
: <ArrowDownIcon size={20} onClick={() => setSort(prev => ({ ...prev, direction: 'asc' }))} />
75+
}
76+
77+
</span>
78+
79+
</div>
80+
</Dropdown.Content>
81+
</Dropdown>
82+
</span>
83+
</div>
84+
{sortedNodes.map((node) => (
1585
<div
1686
key={node.id}
1787
className={`p-3
@@ -21,10 +91,13 @@ export default function PaperList({ nodes, hoveredNodeId, onHover, onClick }: Pr
2191
onMouseLeave={() => onHover(null)}
2292
onClick={() => onClick(node)}
2393
>
24-
<div className="text-sm">{node.title}</div>
94+
<div className="text-sm">
95+
{node.title}
96+
</div>
2597
<div>
2698
{(node.tags ?? []).map((tag) =>
27-
<span key={tag.name} style={{ backgroundColor: tag.color }} className='mt-2 mr-1 p-1 text-[10px] rounded-sm text-white opacity-60'>
99+
<span key={tag.name} style={{ backgroundColor: tag.color }}
100+
className='mt-2 mr-1 p-1 text-[10px] rounded-sm text-white opacity-60'>
28101
{tag.name}
29102
</span>)}
30103
</div>

components/molecules/Dropdown.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ Dropdown.Content = function Content({ children }: ContentProps) {
9393

9494
return (
9595
<div
96-
className={`absolute z-[10] mt-1 w-fit bg-white border border-gray-200 shadow-lg rounded-lg
96+
className={`absolute z-[10] mt-1 w-fit
9797
transition-all duration-300 ease-out ${isOpen ? 'translate-y-0 opacity-100' : 'translate-y-[-10px] opacity-0 pointer-events-none'}`}
9898
>
9999
{children}

public/icons/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,19 @@ import {
3333
FaLightbulb as LightbulbIcon
3434
} from "react-icons/fa";
3535

36+
import {
37+
LuArrowDownUp as ArrowDownUpIcon
38+
39+
} from "react-icons/lu";
40+
3641
import {
3742
HiMiniViewColumns as ViewColumnsIcon,
3843
HiAdjustmentsHorizontal as AdjustmentsIcon
3944
} from "react-icons/hi2";
4045

4146
export {
4247
AddIcon,
48+
ArrowDownUpIcon,
4349
ListIcon,
4450
AddCircleIcon,
4551
NavigateNextIcon,

0 commit comments

Comments
 (0)