1
1
import React from 'react' ;
2
- import type { Column , ColumnDef , Row , TableMeta } from '@tanstack/react-table' ;
3
- import clsx from 'clsx' ;
4
2
import { isNil , omit } from 'lodash' ;
5
- import { ArrowDown10 , ArrowDownZA , ArrowUp10 , ArrowUpZA , ChevronRight } from 'lucide-react' ;
6
- import { FormattedMessage } from 'react-intl ' ;
3
+ import { ArrowUp10 , ChevronRight } from 'lucide-react' ;
4
+ import { useRouter } from 'next/router ' ;
7
5
8
- import type {
9
- AccountMetricsFragment ,
10
- Currency ,
11
- OverviewMetricsQueryVariables ,
12
- } from '../../lib/graphql/types/v2/graphql' ;
13
- import type { useQueryFilterReturnType } from '../../lib/hooks/useQueryFilter' ;
14
- import { getCollectivePageRoute } from '../../lib/url-helpers' ;
6
+ import type { AccountMetricsFragment } from '../../lib/graphql/types/v2/graphql' ;
15
7
16
- import { AccountHoverCard } from '../AccountHoverCard' ;
17
- import Avatar from '../Avatar' ;
18
- import type { schema } from '../dashboard/sections/overview/CollectiveOverview' ;
19
- import type { MetricProps } from '../dashboard/sections/overview/Metric' ;
20
- import { ChangeBadge , getPercentageDifference } from '../dashboard/sections/overview/Metric' ;
8
+ import { getPercentageDifference } from '../dashboard/sections/overview/Metric' ;
21
9
import FormattedMoneyAmount from '../FormattedMoneyAmount' ;
22
10
import Link from '../Link' ;
23
- import { DataTable } from '../table/DataTable' ;
24
- import { Badge } from '../ui/Badge' ;
25
11
import { Button } from '../ui/Button' ;
26
- import { Checkbox } from '../ui/Checkbox' ;
27
- import { useRouter } from 'next/router' ;
12
+
13
+ import { triggerPrototypeToast } from './helpers' ;
14
+
28
15
type AccountMetricsRow = AccountMetricsFragment & {
29
16
current : number ;
30
17
comparison ?: number ;
31
18
percentageDifference ?: number ;
32
19
} ;
33
20
34
- interface AccountMetricsMeta extends TableMeta < AccountMetricsRow > {
35
- currency : Currency ;
36
- isAmount : boolean ;
37
- queryFilter : useQueryFilterReturnType < typeof schema , OverviewMetricsQueryVariables > ;
38
- metric : MetricProps ;
39
- }
40
-
41
- const SortableHeader = ( {
42
- column,
43
- label,
44
- type,
45
- align,
46
- } : {
47
- column : Column < AccountMetricsRow , unknown > ;
48
- label : React . ReactNode ;
49
- type ?: 'alphabetic' | 'numerical' ;
50
- align ?: 'left' | 'right' ;
51
- } ) => {
52
- const isSorted = column . getIsSorted ( ) ;
53
- const isSortedDesc = isSorted === 'desc' ;
54
- const UpIcon = type === 'alphabetic' ? ArrowUpZA : ArrowUp10 ;
55
- const DownIcon = type === 'alphabetic' ? ArrowDownZA : ArrowDown10 ;
56
- const SortIcon = isSortedDesc || ! isSorted ? UpIcon : DownIcon ;
57
- return (
58
- < div className = { clsx ( 'flex items-center' , align === 'right' && 'justify-end' ) } >
59
- < Button
60
- variant = "ghost"
61
- size = "xs"
62
- className = { clsx ( 'group/btn -m-2 gap-2' , isSorted && 'text-foreground' ) }
63
- onClick = { ( ) => column . toggleSorting ( ! isSortedDesc ) }
64
- >
65
- < SortIcon
66
- className = { clsx (
67
- 'h-4 w-4 transition-colors' ,
68
- isSorted ? 'text-muted-foreground' : 'text-transparent group-hover/btn:text-muted-foreground' ,
69
- ) }
70
- />
71
- < span className = { clsx ( align === 'left' && '-order-1' ) } > { label } </ span >
72
- </ Button >
73
- </ div >
74
- ) ;
75
- } ;
76
- const columns : ColumnDef < AccountMetricsRow > [ ] = [
77
- {
78
- id : 'name' ,
79
- accessorKey : 'name' ,
80
- header : ( { column } ) => (
81
- < SortableHeader
82
- column = { column }
83
- type = "alphabetic"
84
- label = { < FormattedMessage defaultMessage = "Name" id = "HAlOn1" /> }
85
- align = "left"
86
- />
87
- ) ,
88
- meta : { className : 'min-w-0 max-w-[300px]' } ,
89
-
90
- cell : ( { row, table } ) => {
91
- const account = row . original ;
92
- // const { queryFilter } = table.options.meta as AccountMetricsMeta;
93
- // const selectedAccountSlug = queryFilter.values.account;
94
- return (
95
- < div className = "flex items-center gap-3 text-base" >
96
- < div className = "flex items-center gap-1.5 overflow-hidden" >
97
- < AccountHoverCard
98
- account = { account }
99
- trigger = {
100
- < div className = "max-w-[400px] truncate" >
101
- < Link
102
- href = { getCollectivePageRoute ( account ) }
103
- className = { clsx ( 'truncate hover:underline group-hover/row:text-foreground' ) }
104
- >
105
- { account . name }
106
- </ Link >
107
- </ div >
108
- }
109
- />
110
-
111
- { account . isArchived && (
112
- < Badge size = "xs" className = "capitalize" >
113
- Archived { account . type . toLowerCase ( ) }
114
- </ Badge >
115
- ) }
116
- </ div >
117
- </ div >
118
- ) ;
119
- } ,
120
- } ,
121
- {
122
- id : 'current' ,
123
- accessorKey : 'current' ,
124
- meta : { className : 'text-right' } ,
125
- header : ( { column, table } ) => {
126
- const meta = table . options . meta as AccountMetricsMeta ;
127
- return < SortableHeader align = "right" column = { column } label = { meta . metric . label } /> ;
128
- } ,
129
- sortingFn : ( rowA : Row < AccountMetricsRow > , rowB : Row < AccountMetricsRow > ) : number => {
130
- const a = rowA . original . current ;
131
- const b = rowB . original . current ;
132
-
133
- const diff = a - b ;
134
-
135
- // sort by comparison value if current is the same
136
- if ( diff === 0 ) {
137
- const rowAPrevious = rowA . original . comparison ;
138
- const rowBPrevious = rowB . original . comparison ;
139
- return rowAPrevious - rowBPrevious ;
140
- }
141
- return a - b ;
142
- } ,
143
- cell : ( { cell, table } ) => {
144
- const current = cell . getValue ( ) as number ;
145
- const meta = table . options . meta as AccountMetricsMeta ;
146
-
147
- return (
148
- < div className = "flex items-center justify-end gap-2" >
149
- < span className = "text-base font-medium" >
150
- { meta . isAmount ? (
151
- < FormattedMoneyAmount amount = { current } currency = { meta . currency } precision = { 2 } showCurrencyCode = { false } />
152
- ) : (
153
- current . toLocaleString ( )
154
- ) }
155
- </ span >
156
- < ChevronRight size = { 20 } className = "text-muted-foreground" />
157
- </ div >
158
- ) ;
159
- } ,
160
- } ,
161
- ] ;
162
-
163
21
export function AccountsSublist ( { label, type, data, metric, meta } ) {
164
22
const router = useRouter ( ) ;
165
23
const columnData : AccountMetricsRow [ ] = React . useMemo ( ( ) => {
@@ -178,10 +36,23 @@ export function AccountsSublist({ label, type, data, metric, meta }) {
178
36
percentageDifference : getPercentageDifference ( current , comparison ) ,
179
37
} ;
180
38
} ) ;
181
- } , [ metric . id , data ] ) ;
39
+ } , [ metric . id , data , type ] ) ;
40
+
182
41
return (
183
42
< div className = "" >
184
- < h2 className = "mb-3 px-2 text-lg font-semibold text-slate-800" > { label } </ h2 >
43
+ < div className = "mb-2 flex items-center justify-between gap-4 px-2" >
44
+ < h2 className = "text-lg font-semibold text-slate-800" > { label } </ h2 >
45
+ < Button
46
+ variant = "ghost"
47
+ size = "sm"
48
+ className = { 'group/btn -m-2 gap-2 text-foreground' }
49
+ onClick = { triggerPrototypeToast }
50
+ disabled = { columnData . length === 1 }
51
+ >
52
+ < span > { metric . id === 'balance' ? 'Balance' : metric . label } </ span >
53
+ < ArrowUp10 className = "h-4 w-4 text-muted-foreground transition-colors" />
54
+ </ Button >
55
+ </ div >
185
56
< div className = "flex flex-col divide-y overflow-hidden rounded-xl border bg-background" >
186
57
{ columnData
187
58
. sort ( ( a , b ) => b . current - a . current )
@@ -206,17 +77,6 @@ export function AccountsSublist({ label, type, data, metric, meta }) {
206
77
</ Link >
207
78
) ) }
208
79
</ div >
209
-
210
- { /* <DataTable
211
- hideHeader
212
- className="bg-background"
213
- columns={columns}
214
- data={columnData}
215
- initialSort={[{ id: 'current', desc: true }]}
216
- nbPlaceholders={nbPlaceholders}
217
- loading={loading}
218
- meta={meta}
219
- /> */ }
220
80
</ div >
221
81
) ;
222
82
}
0 commit comments