diff --git a/package-lock.json b/package-lock.json index 13e2a490..727a451d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -58,8 +58,8 @@ "parse5": "^7.1.2", "pocketbase": "^0.21.5", "postcss": "^8.4.38", - "prettier": "^3.2.5", - "prettier-plugin-svelte": "^3.2.3", + "prettier": "^3.3.3", + "prettier-plugin-svelte": "^3.2.7", "quill": "^2.0.2", "quill-delta-to-html": "^0.12.1", "rollup-plugin-visualizer": "^5.12.0", @@ -7339,6 +7339,7 @@ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", "dev": true, + "license": "MIT", "bin": { "prettier": "bin/prettier.cjs" }, @@ -7350,10 +7351,11 @@ } }, "node_modules/prettier-plugin-svelte": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-3.2.5.tgz", - "integrity": "sha512-vP/M/Goc8z4iVIvrwXwbrYVjJgA0Hf8PO1G4LBh/ocSt6vUP6sLvyu9F3ABEGr+dbKyxZjEKLkeFsWy/yYl0HQ==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-3.2.7.tgz", + "integrity": "sha512-/Dswx/ea0lV34If1eDcG3nulQ63YNr5KPDfMsjbdtpSWOxKKJ7nAc2qlVuYwEvCr4raIuredNoR7K4JCkmTGaQ==", "dev": true, + "license": "MIT", "peerDependencies": { "prettier": "^3.0.0", "svelte": "^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0" diff --git a/package.json b/package.json index 84106b83..3acd11be 100644 --- a/package.json +++ b/package.json @@ -57,8 +57,8 @@ "parse5": "^7.1.2", "pocketbase": "^0.21.5", "postcss": "^8.4.38", - "prettier": "^3.2.5", - "prettier-plugin-svelte": "^3.2.3", + "prettier": "^3.3.3", + "prettier-plugin-svelte": "^3.2.7", "quill": "^2.0.2", "quill-delta-to-html": "^0.12.1", "rollup-plugin-visualizer": "^5.12.0", diff --git a/src/lib/components/Table/TableHeader.svelte b/src/lib/components/Table/TableHeader.svelte new file mode 100644 index 00000000..df61a0a6 --- /dev/null +++ b/src/lib/components/Table/TableHeader.svelte @@ -0,0 +1,25 @@ + + + + {#each columns as column} + sortData(column.key)} + class="cursor-pointer select-none text-white font-semibold text-[1rem] whitespace-nowrap {column.align === 'right' ? 'text-end' : ''}" + > + {column.label} + {@html SortIcon({ sortOrder: sortOrders[column.key].order })} + + {/each} + \ No newline at end of file diff --git a/src/lib/utils.ts b/src/lib/utils.ts index cce414f9..122d0fda 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -73,6 +73,62 @@ export const flyAndScale = ( }; }; +export const sortTableData = (key, displayList, rawData, sortOrders) => { + // Reset all other keys to 'none' except the current key + for (const k in sortOrders) { + if (k !== key) { + sortOrders[k].order = "none"; + } + } + + // Cycle through 'none', 'asc', 'desc' for the clicked key + const orderCycle = ["none", "asc", "desc"]; + const originalData = rawData?.slice(0, 40); + const currentOrderIndex = orderCycle.indexOf(sortOrders[key].order); + sortOrders[key].order = + orderCycle[(currentOrderIndex + 1) % orderCycle.length]; + const sortOrder = sortOrders[key].order; + + // Reset to original data when 'none' and stop further sorting + if (sortOrder === "none") { + analytRatingList = [...originalData]; // Reset to original data (spread to avoid mutation) + return; + } + + // Define a generic comparison function + const compareValues = (a, b) => { + const { type } = sortOrders[key]; + let valueA, valueB; + + switch (type) { + case "date": + valueA = new Date(a[key]); + valueB = new Date(b[key]); + break; + case "string": + valueA = a[key].toUpperCase(); + valueB = b[key].toUpperCase(); + return sortOrder === "asc" + ? valueA.localeCompare(valueB) + : valueB.localeCompare(valueA); + case "number": + default: + valueA = parseFloat(a[key]); + valueB = parseFloat(b[key]); + break; + } + + if (sortOrder === "asc") { + return valueA < valueB ? -1 : valueA > valueB ? 1 : 0; + } else { + return valueA > valueB ? -1 : valueA < valueB ? 1 : 0; + } + }; + + // Sort using the generic comparison function + analytRatingList = [...originalData].sort(compareValues); +}; + export const formatDateRange = (lastDateStr) => { // Convert lastDateStr to Date object const lastDate = new Date(lastDateStr); diff --git a/src/routes/analysts/+page.svelte b/src/routes/analysts/+page.svelte index 1e0a055b..0ceb2460 100644 --- a/src/routes/analysts/+page.svelte +++ b/src/routes/analysts/+page.svelte @@ -1,8 +1,11 @@ - - - - - {$numberOfUnreadNotification > 0 ? `(${$numberOfUnreadNotification})` : ''} Top Wall Street Stock Analysts · stocknear - - + + + + {$numberOfUnreadNotification > 0 ? `(${$numberOfUnreadNotification})` : ''} Top + Wall Street Stock Analysts · stocknear + + - - - - - - - - - - - + + + + + + + + + + - - - -
- +
- +
- -
-
- - -
- -
-
- - -
-
-

- Top Wall Street Analysts -

-
- - - A performance-based ranking of Wall Street Analysts. - - - - -
- - - - - +
+
+
+
+
+ +
+
+

+ Top Wall Street Analysts +

- - - - + + + A performance-based ranking of Wall Street Analysts. +
- + - -
- {#if isLoaded} + + - -
-
+ +
goto('/analysts/top-stocks')} + class="w-full bg-[#141417] duration-100 ease-out sm:hover:text-white text-gray-400 sm:hover:border-gray-700 border border-gray-800 rounded-lg h-fit pb-4 mt-4 cursor-pointer" + > +
+
+

+ Top Stocks Picks ⭐ +

+ +
+ + Get the latest top Wall Street analyst ratings. + +
+
+
goto('/most-shorted-stocks')} + class="w-full bg-[#141417] duration-100 ease-out sm:hover:text-white text-gray-400 sm:hover:border-gray-700 border border-gray-800 rounded-lg h-fit pb-4 mt-4 cursor-pointer" + > +
+
+

+ Top Shorted Stocks 🍋 +

+ +
+ + Never miss out another short squeeze + +
+
+
- -
- - - -
\ No newline at end of file +