Commit
·
7663767
1
Parent(s):
d90c730
- src/App.tsx +27 -20
src/App.tsx
CHANGED
@@ -9,6 +9,11 @@ import { Button } from '@/components/ui/button'
|
|
9 |
import { ChevronDown, ChevronRight } from 'lucide-react'
|
10 |
import { mockData } from './lib/data'
|
11 |
|
|
|
|
|
|
|
|
|
|
|
12 |
export interface Model {
|
13 |
name: string
|
14 |
inputPrice: number
|
@@ -44,6 +49,16 @@ const App: React.FC = () => {
|
|
44 |
return (((modelPrice - comparisonPrice) / comparisonPrice) * 100).toFixed(2)
|
45 |
}
|
46 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
const filteredData = data
|
48 |
.filter((provider) => selectedProviders.length === 0 || selectedProviders.includes(provider.provider))
|
49 |
.map((provider) => ({
|
@@ -52,24 +67,19 @@ const App: React.FC = () => {
|
|
52 |
}))
|
53 |
.filter((provider) => provider.models.length > 0)
|
54 |
|
55 |
-
const
|
56 |
-
|
57 |
-
provider.models.map(model => ({
|
58 |
-
provider: provider.provider,
|
59 |
-
uri: provider.uri,
|
60 |
-
...model
|
61 |
-
}))
|
62 |
-
);
|
63 |
}
|
64 |
|
65 |
const sortedFlattenedData = React.useMemo(() => {
|
66 |
-
let sortableData = flattenData(filteredData);
|
67 |
if (sortConfig !== null) {
|
68 |
sortableData.sort((a, b) => {
|
69 |
-
|
|
|
70 |
return sortConfig.direction === 'ascending' ? -1 : 1;
|
71 |
}
|
72 |
-
if (a[
|
73 |
return sortConfig.direction === 'ascending' ? 1 : -1;
|
74 |
}
|
75 |
return 0;
|
@@ -78,9 +88,10 @@ const App: React.FC = () => {
|
|
78 |
return sortableData;
|
79 |
}, [filteredData, sortConfig]);
|
80 |
|
81 |
-
|
|
|
82 |
const reassembledData = sortedFlattenedData.reduce((acc, item) => {
|
83 |
-
const providerIndex = acc.findIndex(provider => provider.provider === item.provider);
|
84 |
if (providerIndex === -1) {
|
85 |
acc.push({
|
86 |
provider: item.provider,
|
@@ -91,9 +102,9 @@ const App: React.FC = () => {
|
|
91 |
acc[providerIndex].models.push({ name: item.name, inputPrice: item.inputPrice, outputPrice: item.outputPrice });
|
92 |
}
|
93 |
return acc;
|
94 |
-
}, []);
|
95 |
return reassembledData;
|
96 |
-
}
|
97 |
|
98 |
const sortedData = reassembleData(sortedFlattenedData);
|
99 |
|
@@ -107,10 +118,6 @@ const App: React.FC = () => {
|
|
107 |
|
108 |
|
109 |
|
110 |
-
const toggleProviderExpansion = (provider: string) => {
|
111 |
-
setExpandedProviders((prev) => (prev.includes(provider) ? prev.filter((p) => p !== provider) : [...prev, provider]))
|
112 |
-
}
|
113 |
-
|
114 |
return (
|
115 |
<Card className="w-full max-w-6xl mx-auto">
|
116 |
<CardHeader>
|
@@ -262,7 +269,7 @@ const App: React.FC = () => {
|
|
262 |
</TableRow>
|
263 |
</TableHeader>
|
264 |
<TableBody>
|
265 |
-
{sortedData.flatMap((provider) =>
|
266 |
provider.models.map((model) => (
|
267 |
<TableRow key={`${provider.provider}-${model.name}`}>
|
268 |
<TableCell>
|
|
|
9 |
import { ChevronDown, ChevronRight } from 'lucide-react'
|
10 |
import { mockData } from './lib/data'
|
11 |
|
12 |
+
interface FlattenedModel extends Model {
|
13 |
+
provider: string;
|
14 |
+
uri: string;
|
15 |
+
}
|
16 |
+
|
17 |
export interface Model {
|
18 |
name: string
|
19 |
inputPrice: number
|
|
|
49 |
return (((modelPrice - comparisonPrice) / comparisonPrice) * 100).toFixed(2)
|
50 |
}
|
51 |
|
52 |
+
const flattenData = (data: Provider[]) => {
|
53 |
+
return data.flatMap(provider =>
|
54 |
+
provider.models.map(model => ({
|
55 |
+
provider: provider.provider,
|
56 |
+
uri: provider.uri,
|
57 |
+
...model
|
58 |
+
}))
|
59 |
+
);
|
60 |
+
}
|
61 |
+
|
62 |
const filteredData = data
|
63 |
.filter((provider) => selectedProviders.length === 0 || selectedProviders.includes(provider.provider))
|
64 |
.map((provider) => ({
|
|
|
67 |
}))
|
68 |
.filter((provider) => provider.models.length > 0)
|
69 |
|
70 |
+
const toggleProviderExpansion = (provider: string) => {
|
71 |
+
setExpandedProviders((prev) => (prev.includes(provider) ? prev.filter((p) => p !== provider) : [...prev, provider]))
|
|
|
|
|
|
|
|
|
|
|
|
|
72 |
}
|
73 |
|
74 |
const sortedFlattenedData = React.useMemo(() => {
|
75 |
+
let sortableData: FlattenedModel[] = flattenData(filteredData);
|
76 |
if (sortConfig !== null) {
|
77 |
sortableData.sort((a, b) => {
|
78 |
+
const key = sortConfig.key as keyof FlattenedModel;
|
79 |
+
if (a[key] < b[key]) {
|
80 |
return sortConfig.direction === 'ascending' ? -1 : 1;
|
81 |
}
|
82 |
+
if (a[key] > b[key]) {
|
83 |
return sortConfig.direction === 'ascending' ? 1 : -1;
|
84 |
}
|
85 |
return 0;
|
|
|
88 |
return sortableData;
|
89 |
}, [filteredData, sortConfig]);
|
90 |
|
91 |
+
|
92 |
+
const reassembleData = (sortedFlattenedData: any[]) => {
|
93 |
const reassembledData = sortedFlattenedData.reduce((acc, item) => {
|
94 |
+
const providerIndex = acc.findIndex((provider: { provider: any }) => provider.provider === item.provider);
|
95 |
if (providerIndex === -1) {
|
96 |
acc.push({
|
97 |
provider: item.provider,
|
|
|
102 |
acc[providerIndex].models.push({ name: item.name, inputPrice: item.inputPrice, outputPrice: item.outputPrice });
|
103 |
}
|
104 |
return acc;
|
105 |
+
}, [] as Provider[]);
|
106 |
return reassembledData;
|
107 |
+
};
|
108 |
|
109 |
const sortedData = reassembleData(sortedFlattenedData);
|
110 |
|
|
|
118 |
|
119 |
|
120 |
|
|
|
|
|
|
|
|
|
121 |
return (
|
122 |
<Card className="w-full max-w-6xl mx-auto">
|
123 |
<CardHeader>
|
|
|
269 |
</TableRow>
|
270 |
</TableHeader>
|
271 |
<TableBody>
|
272 |
+
{sortedData.flatMap((provider: { models: any[]; provider: string | number | boolean | React.ReactElement<any, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | React.ReactPortal | null | undefined; uri: string | undefined }) =>
|
273 |
provider.models.map((model) => (
|
274 |
<TableRow key={`${provider.provider}-${model.name}`}>
|
275 |
<TableCell>
|