Presidentlin commited on
Commit
35a1853
1 Parent(s): 4060e49
Files changed (2) hide show
  1. src/App.tsx +73 -16
  2. src/lib/data.ts +1 -1
src/App.tsx CHANGED
@@ -29,10 +29,11 @@ const App: React.FC = () => {
29
  const [selectedProviders, setSelectedProviders] = useState<string[]>([])
30
  const [selectedModels, setSelectedModels] = useState<string[]>([])
31
  const [expandedProviders, setExpandedProviders] = useState<string[]>([])
 
32
 
33
  useEffect(() => {
34
  setData(mockData)
35
- setComparisonModels(['OpenAI:GPT-4o', 'Anthropic:Claude 3.5 (Sonnet)', 'Google:Gemini 1.5 Pro'])
36
  }, [])
37
 
38
  const calculatePrice = (price: number, tokens: number): number => {
@@ -50,6 +51,45 @@ const App: React.FC = () => {
50
  }))
51
  .filter((provider) => provider.models.length > 0)
52
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  console.log(filteredData)
54
 
55
  const toggleProviderExpansion = (provider: string) => {
@@ -145,10 +185,26 @@ const App: React.FC = () => {
145
  <Table>
146
  <TableHeader>
147
  <TableRow>
148
- <TableHead>Provider</TableHead>
149
- <TableHead>Model</TableHead>
150
- <TableHead>Input Price (per 1M tokens)</TableHead>
151
- <TableHead>Output Price (per 1M tokens)</TableHead>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152
  <TableHead>Total Price</TableHead>
153
  {comparisonModels.map((model) => (
154
  <TableHead key={model} colSpan={2}>
@@ -191,7 +247,7 @@ const App: React.FC = () => {
191
  </TableRow>
192
  </TableHeader>
193
  <TableBody>
194
- {filteredData.flatMap((provider) =>
195
  provider.models.map((model) => (
196
  <TableRow key={`${provider.provider}-${model.name}`}>
197
  <TableCell>
@@ -217,13 +273,12 @@ const App: React.FC = () => {
217
  return [
218
  <TableCell
219
  key={`${comparisonModel}-input`}
220
- className={`${
221
- parseFloat(calculateComparison(model.inputPrice, comparisonModelData.inputPrice)) < 0
222
- ? 'bg-green-100'
223
- : parseFloat(calculateComparison(model.inputPrice, comparisonModelData.inputPrice)) > 0
224
  ? 'bg-red-100'
225
  : ''
226
- }`}
227
  >
228
  {`${provider.provider}:${model.name}` === comparisonModel
229
  ? '0.00%'
@@ -231,13 +286,12 @@ const App: React.FC = () => {
231
  </TableCell>,
232
  <TableCell
233
  key={`${comparisonModel}-output`}
234
- className={`${
235
- parseFloat(calculateComparison(model.outputPrice, comparisonModelData.outputPrice)) < 0
236
- ? 'bg-green-100'
237
- : parseFloat(calculateComparison(model.outputPrice, comparisonModelData.outputPrice)) > 0
238
  ? 'bg-red-100'
239
  : ''
240
- }`}
241
  >
242
  {`${provider.provider}:${model.name}` === comparisonModel
243
  ? '0.00%'
@@ -250,6 +304,9 @@ const App: React.FC = () => {
250
  )}
251
  </TableBody>
252
  </Table>
 
 
 
253
  </CardContent>
254
  </Card>
255
  )
 
29
  const [selectedProviders, setSelectedProviders] = useState<string[]>([])
30
  const [selectedModels, setSelectedModels] = useState<string[]>([])
31
  const [expandedProviders, setExpandedProviders] = useState<string[]>([])
32
+ const [sortConfig, setSortConfig] = useState<{ key: string, direction: string } | null>(null)
33
 
34
  useEffect(() => {
35
  setData(mockData)
36
+ setComparisonModels(['OpenAI:GPT-4o-mini', 'Anthropic:Claude 3.5 (Sonnet)', 'Google:Gemini 1.5 Pro'])
37
  }, [])
38
 
39
  const calculatePrice = (price: number, tokens: number): number => {
 
51
  }))
52
  .filter((provider) => provider.models.length > 0)
53
 
54
+ const sortedData = React.useMemo(() => {
55
+ let sortableData = [...filteredData];
56
+ if (sortConfig !== null) {
57
+ if (sortConfig.key === 'provider') {
58
+ sortableData.sort((a, b) => {
59
+ if (a.provider < b.provider) {
60
+ return sortConfig.direction === 'ascending' ? -1 : 1;
61
+ }
62
+ if (a.provider > b.provider) {
63
+ return sortConfig.direction === 'ascending' ? 1 : -1;
64
+ }
65
+ return 0;
66
+ });
67
+ } else if (sortConfig.key === 'model' || sortConfig.key === 'inputPrice' || sortConfig.key === 'outputPrice') {
68
+ sortableData.forEach(provider => {
69
+ provider.models.sort((a, b) => {
70
+ if (a[sortConfig.key] < b[sortConfig.key]) {
71
+ return sortConfig.direction === 'ascending' ? -1 : 1;
72
+ }
73
+ if (a[sortConfig.key] > b[sortConfig.key]) {
74
+ return sortConfig.direction === 'ascending' ? 1 : -1;
75
+ }
76
+ return 0;
77
+ });
78
+ });
79
+ }
80
+ }
81
+ return sortableData;
82
+ }, [filteredData, sortConfig]);
83
+
84
+ const requestSort = (key: string) => {
85
+ let direction = 'ascending';
86
+ if (sortConfig && sortConfig.key === key && sortConfig.direction === 'ascending') {
87
+ direction = 'descending';
88
+ }
89
+ setSortConfig({ key, direction });
90
+ };
91
+
92
+
93
  console.log(filteredData)
94
 
95
  const toggleProviderExpansion = (provider: string) => {
 
185
  <Table>
186
  <TableHeader>
187
  <TableRow>
188
+ <TableHead>
189
+ <button type="button" onClick={() => requestSort('provider')}>
190
+ Provider {sortConfig?.key === 'provider' ? (sortConfig.direction === 'ascending' ? '▲' : '▼') : null}
191
+ </button>
192
+ </TableHead>
193
+ <TableHead>
194
+ <button type="button" onClick={() => requestSort('model')}>
195
+ Model {sortConfig?.key === 'model' ? (sortConfig.direction === 'ascending' ? '▲' : '▼') : null}
196
+ </button>
197
+ </TableHead>
198
+ <TableHead>
199
+ <button type="button" onClick={() => requestSort('inputPrice')}>
200
+ Input Price (per 1M tokens) {sortConfig?.key === 'inputPrice' ? (sortConfig.direction === 'ascending' ? '▲' : '▼') : null}
201
+ </button>
202
+ </TableHead>
203
+ <TableHead>
204
+ <button type="button" onClick={() => requestSort('outputPrice')}>
205
+ Output Price (per 1M tokens) {sortConfig?.key === 'outputPrice' ? (sortConfig.direction === 'ascending' ? '▲' : '▼') : null}
206
+ </button>
207
+ </TableHead>
208
  <TableHead>Total Price</TableHead>
209
  {comparisonModels.map((model) => (
210
  <TableHead key={model} colSpan={2}>
 
247
  </TableRow>
248
  </TableHeader>
249
  <TableBody>
250
+ {sortedData.flatMap((provider) =>
251
  provider.models.map((model) => (
252
  <TableRow key={`${provider.provider}-${model.name}`}>
253
  <TableCell>
 
273
  return [
274
  <TableCell
275
  key={`${comparisonModel}-input`}
276
+ className={`${parseFloat(calculateComparison(model.inputPrice, comparisonModelData.inputPrice)) < 0
277
+ ? 'bg-green-100'
278
+ : parseFloat(calculateComparison(model.inputPrice, comparisonModelData.inputPrice)) > 0
 
279
  ? 'bg-red-100'
280
  : ''
281
+ }`}
282
  >
283
  {`${provider.provider}:${model.name}` === comparisonModel
284
  ? '0.00%'
 
286
  </TableCell>,
287
  <TableCell
288
  key={`${comparisonModel}-output`}
289
+ className={`${parseFloat(calculateComparison(model.outputPrice, comparisonModelData.outputPrice)) < 0
290
+ ? 'bg-green-100'
291
+ : parseFloat(calculateComparison(model.outputPrice, comparisonModelData.outputPrice)) > 0
 
292
  ? 'bg-red-100'
293
  : ''
294
+ }`}
295
  >
296
  {`${provider.provider}:${model.name}` === comparisonModel
297
  ? '0.00%'
 
304
  )}
305
  </TableBody>
306
  </Table>
307
+
308
+
309
+
310
  </CardContent>
311
  </Card>
312
  )
src/lib/data.ts CHANGED
@@ -6,7 +6,7 @@ export const mockData: Provider[] = [
6
  uri: 'https://openai.com/api/pricing/',
7
  models: [
8
  { name: 'GPT-4o', inputPrice: 5.0, outputPrice: 15.0 },
9
- { name: 'GPT-4o-mini', inputPrice: 0.15, outputPrice: 0.6 },
10
  { name: 'GPT-4 (8K)', inputPrice: 30.0, outputPrice: 60.0 },
11
  { name: 'GPT-4 Turbo', inputPrice: 10.0, outputPrice: 30.0 },
12
  { name: 'GPT-3.5-turbo', inputPrice: 0.5, outputPrice: 1.5 },
 
6
  uri: 'https://openai.com/api/pricing/',
7
  models: [
8
  { name: 'GPT-4o', inputPrice: 5.0, outputPrice: 15.0 },
9
+ { name: 'GPT-4o-mini', inputPrice: 0.15, outputPrice: 0.60 },
10
  { name: 'GPT-4 (8K)', inputPrice: 30.0, outputPrice: 60.0 },
11
  { name: 'GPT-4 Turbo', inputPrice: 10.0, outputPrice: 30.0 },
12
  { name: 'GPT-3.5-turbo', inputPrice: 0.5, outputPrice: 1.5 },