-
+
Legend
@@ -135,24 +102,11 @@ export const Peers = () => {
Connections
-
-
+
+
- {good ? (
- <>
-
- Peer connections in good standing.
- >
- ) : (
- <>
-
- No peer connection active.
- >
- )}
+
diff --git a/src/components/Peers/PeersCard.css b/src/components/Peers/PeersCard.css
new file mode 100644
index 0000000..c5007ed
--- /dev/null
+++ b/src/components/Peers/PeersCard.css
@@ -0,0 +1,23 @@
+.peers-card {
+ position: relative;
+
+ .peers-map {
+ border-top: 1px solid #96969633;
+ border-bottom: 1px solid #96969633;
+ width: 100%;
+
+ svg {
+ width: 100%;
+ }
+ }
+
+ .peers-chart {
+ position: absolute;
+ left: 0;
+ right: 0;
+ }
+
+ footer {
+ padding-top: 16px;
+ }
+}
diff --git a/src/components/Peers/PeersCard.tsx b/src/components/Peers/PeersCard.tsx
new file mode 100644
index 0000000..a705426
--- /dev/null
+++ b/src/components/Peers/PeersCard.tsx
@@ -0,0 +1,38 @@
+import { PeersIcon } from "../Menu/PeersIcon";
+import { PeersMap } from "./PeersMap";
+import "./PeersCard.css";
+import { useDebug } from "../../hooks/useDebug";
+import { PeerUtils } from "./peers.util";
+import { PeersChart } from "./PeersChart";
+import { PeersQuality } from "./PeersQuality";
+import { Button } from "@codex-storage/marketplace-ui-components";
+
+const throwOnError = true;
+
+export function PeersCard() {
+ const { data } = useDebug(throwOnError);
+
+ const nodes = data?.table.nodes ?? [];
+ const actives = PeerUtils.countActives(nodes);
+ const degrees = PeerUtils.calculareDegrees(nodes);
+ const good = PeerUtils.isGoodQuality(actives);
+
+ return (
+
+ );
+}
diff --git a/src/components/Peers/PeersChart.css b/src/components/Peers/PeersChart.css
new file mode 100644
index 0000000..a500a3f
--- /dev/null
+++ b/src/components/Peers/PeersChart.css
@@ -0,0 +1,65 @@
+.peers-chart {
+ position: relative;
+ width: 350px;
+ height: 175px;
+ overflow: hidden;
+ transform: scale(0.5);
+ margin: auto;
+ left: -32px;
+
+ @media (min-width: 1000px) {
+ & {
+ transform: scale(0.73);
+ }
+ }
+
+ *,
+ &::before {
+ box-sizing: border-box;
+ }
+
+ &::before,
+ &::after {
+ position: absolute;
+ }
+
+ &::before {
+ content: "";
+ width: inherit;
+ height: inherit;
+ border: 45px solid #323232;
+ border-bottom: none;
+ border-top-left-radius: 175px;
+ border-top-right-radius: 175px;
+ }
+
+ div {
+ position: absolute;
+ top: 100%;
+ width: inherit;
+ height: inherit;
+ border: 45px solid #323232;
+ border-top: none;
+ border-bottom-left-radius: 175px;
+ border-bottom-right-radius: 175px;
+ transform-origin: 50% 0;
+ }
+
+ div:nth-child(1) {
+ border-color: var(--codex-color-primary);
+ transform: rotate(calc(var(--codex-peers-degrees) * 1deg));
+ background-color: transparent;
+ }
+
+ span {
+ font-family: Inter;
+ font-size: 38.67px;
+ font-weight: 500;
+ line-height: 48.34px;
+ letter-spacing: -0.005em;
+ text-align: center;
+ position: absolute;
+ bottom: 0;
+ left: calc(50% - 24px);
+ }
+}
diff --git a/src/components/Peers/PeersChart.tsx b/src/components/Peers/PeersChart.tsx
new file mode 100644
index 0000000..3406f87
--- /dev/null
+++ b/src/components/Peers/PeersChart.tsx
@@ -0,0 +1,23 @@
+import "./PeersChart.css";
+
+type Props = {
+ actives: number;
+ degrees: number;
+};
+
+type CustomCSSProperties = React.CSSProperties & {
+ "--codex-peers-degrees": number;
+};
+
+export function PeersChart({ actives, degrees }: Props) {
+ const style: CustomCSSProperties = {
+ "--codex-peers-degrees": degrees,
+ };
+
+ return (
+
+ );
+}
diff --git a/src/components/Peers/PeersMap.css b/src/components/Peers/PeersMap.css
new file mode 100644
index 0000000..d88c745
--- /dev/null
+++ b/src/components/Peers/PeersMap.css
@@ -0,0 +1,21 @@
+.peers-map {
+ circle[fill="#d6ff79"] {
+ stroke: var(--codex-color-primary);
+ stroke-width: 0.6px;
+ fill: #141414;
+ animation: circle-pulse 3s infinite;
+ }
+}
+
+@keyframes circle-pulse {
+ 0% {
+ opacity: 1; /* Fully opaque */
+ }
+ 50% {
+ r: 2; /* Increased radius */
+ opacity: 1; /* Slightly transparent */
+ }
+ 100% {
+ opacity: 1; /* Fully opaque */
+ }
+}
diff --git a/src/components/Peers/PeersMap.tsx b/src/components/Peers/PeersMap.tsx
new file mode 100644
index 0000000..7391302
--- /dev/null
+++ b/src/components/Peers/PeersMap.tsx
@@ -0,0 +1,56 @@
+import { getMapJSON } from "dotted-map";
+import DottedMap from "dotted-map/without-countries";
+import { PeerGeo, PeerNode, PeerUtils } from "./peers.util";
+import { useCallback, useState } from "react";
+import { PeersPin } from "./PeersPin";
+import "./PeersMap.css";
+
+// This function accepts the same arguments as DottedMap in the example above.
+const mapJsonString = getMapJSON({ height: 60, grid: "diagonal" });
+
+type Props = {
+ nodes: PeerNode[];
+ onPinAdd?: (node: PeerNode, geo: PeerGeo) => void;
+};
+
+export function PeersMap({ nodes, onPinAdd }: Props) {
+ // It’s safe to re-create the map at each render, because of the
+ // pre-computation it’s super fast ⚡️
+ const map = new DottedMap({ map: JSON.parse(mapJsonString) });
+
+ const [pins, setPins] = useState<[PeerNode & PeerGeo, number][]>([]);
+
+ const onInternalPinAdd = useCallback(
+ (node: PeerNode, geo: PeerGeo) => {
+ setPins((val) => PeerUtils.incPin(val, { ...node, ...geo }));
+ onPinAdd?.(node, geo);
+ },
+ [setPins]
+ );
+
+ pins.map(([pin, quantity]) =>
+ map.addPin({
+ lat: pin.latitude,
+ lng: pin.longitude,
+ svgOptions: { color: "#d6ff79", radius: 0.4 * quantity },
+ })
+ );
+
+ const svgMap = map.getSVG({
+ radius: 0.32,
+ color: "#969696",
+ shape: "circle",
+ backgroundColor: "#141414",
+ });
+
+ return (
+ <>
+ {nodes.map((node, index) => (
+
+ ))}
+
+ >
+ );
+}
diff --git a/src/components/Peers/PeersPin.ts b/src/components/Peers/PeersPin.ts
new file mode 100644
index 0000000..d74c596
--- /dev/null
+++ b/src/components/Peers/PeersPin.ts
@@ -0,0 +1,44 @@
+import { useQuery } from "@tanstack/react-query";
+import { PeerGeo, PeerNode } from "./peers.util";
+import { useEffect } from "react";
+
+type Props = {
+ node: PeerNode
+ onLoad: (node: PeerNode, geo: PeerGeo) => void
+}
+
+export function PeersPin({ node, onLoad }: Props) {
+ const { data } = useQuery({
+ queryFn: () => {
+ const [ip] = node.address.split(":");
+
+ return fetch(import.meta.env.VITE_GEO_IP_URL + "/json?ip=" + ip).then(
+ (res) => res.json()
+ );
+ },
+ queryKey: ["peers", node.address],
+
+ // No need to retry because if the connection to the node
+ // is back again, all the queries will be invalidated.
+ retry: false,
+
+ // We can cache the data at Infinity because the relation between
+ // country and ip is fixed
+ staleTime: Infinity,
+
+ // Don't expect something new when coming back to the UI
+ refetchOnWindowFocus: false,
+
+ refetchOnMount: false,
+ });
+
+ useEffect(() => {
+ if (data) {
+ onLoad(node, data)
+ console.info(node.address)
+ }
+ }, [data, onLoad, node])
+
+
+ return ""
+}
\ No newline at end of file
diff --git a/src/components/Peers/PeersQuality.css b/src/components/Peers/PeersQuality.css
new file mode 100644
index 0000000..712f541
--- /dev/null
+++ b/src/components/Peers/PeersQuality.css
@@ -0,0 +1,10 @@
+.peers-quality {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ font-family: Inter;
+ font-size: 14px;
+ font-weight: 400;
+ line-height: 20px;
+ letter-spacing: -0.006em;
+}
diff --git a/src/components/Peers/PeersQuality.tsx b/src/components/Peers/PeersQuality.tsx
new file mode 100644
index 0000000..9521fa2
--- /dev/null
+++ b/src/components/Peers/PeersQuality.tsx
@@ -0,0 +1,25 @@
+import { ErrorCircleIcon } from "../ErrorCircleIcon/ErrorCircleIcon";
+import { SuccessCheckIcon } from "../SuccessCheckIcon/SuccessCheckIcon";
+import "./PeersQuality.css";
+
+type Props = {
+ good: boolean;
+};
+
+export function PeersQuality({ good }: Props) {
+ if (good) {
+ return (
+
+
+ Peer connections in good standing.
+
+ );
+ }
+
+ return (
+
+
+ No peer connection active.
+
+ );
+}
diff --git a/src/components/Peers/peers.util.test.ts b/src/components/Peers/peers.util.test.ts
index 95d4dbf..326a728 100644
--- a/src/components/Peers/peers.util.test.ts
+++ b/src/components/Peers/peers.util.test.ts
@@ -1,5 +1,5 @@
import { assert, describe, it } from "vitest";
-import { PeerUtils } from "./peers.util";
+import { PeerGeo, PeerUtils } from "./peers.util";
describe("peers", () => {
it("sorts by boolean", async () => {
@@ -19,10 +19,16 @@ describe("peers", () => {
it("sorts by country", async () => {
const a = { nodeId: "a", peerId: "", record: "", address: "127.0.0.1", seen: false }
const b = { nodeId: "a", peerId: "", record: "", address: "127.0.0.2", seen: true }
+
const table = {
- "127.0.0.1": "US",
- "127.0.0.2": "France",
+ "127.0.0.1": {
+ country: "United States"
+ } as PeerGeo,
+ "127.0.0.2": {
+ country: "France"
+ } as PeerGeo,
}
+
const items = [a, b,]
const descSorted = items.slice().sort(PeerUtils.sortByCountry("desc", table))
@@ -35,14 +41,14 @@ describe("peers", () => {
});
it("adds a new pin", async () => {
- const latLng = { lat: 0, lng: 0 }
+ const latLng = { latitude: 0, longitude: 0 } as any
const values = PeerUtils.incPin([], latLng)
assert.deepEqual(values, [[latLng, 1]]);
});
it("increments an existing pin", async () => {
- const latLng = { lat: 0, lng: 0 }
+ const latLng = { lat: 0, lng: 0 } as any
const values = PeerUtils.incPin([[latLng, 1]], latLng)
assert.deepEqual(values, [[latLng, 2]]);
diff --git a/src/components/Peers/peers.util.ts b/src/components/Peers/peers.util.ts
index 7d40ed5..bfd6c05 100644
--- a/src/components/Peers/peers.util.ts
+++ b/src/components/Peers/peers.util.ts
@@ -8,10 +8,12 @@ export type PeerNode = {
seen: boolean;
};
-export type PeerPin = {
- lat: number;
- lng: number;
-};
+export type PeerGeo = {
+ latitude: number
+ longitude: number
+ country: string
+ country_iso: string
+}
export type PeerSortFn = (a: PeerNode, b: PeerNode) => number;
@@ -21,12 +23,12 @@ export const PeerUtils = {
return a?.seen === b?.seen ? 0 : b?.seen ? order : -order;
},
- sortByCountry: (state: TabSortState, ipTable: Record
) =>
+ sortByCountry: (state: TabSortState, ipTable: Record) =>
(a: PeerNode, b: PeerNode) => {
const [ipA = ""] = a.address.split(":")
const [ipB = ""] = b.address.split(":")
- const countryA = ipTable[ipA] || "";
- const countryB = ipTable[ipB] || "";
+ const countryA = ipTable[ipA].country || "";
+ const countryB = ipTable[ipB].country || "";
return state === "desc"
? countryA.localeCompare(countryB)
@@ -36,10 +38,10 @@ export const PeerUtils = {
/**
* Increments the number of pin for a location
*/
- incPin(val: [PeerPin, number][], pin: PeerPin): [PeerPin, number][] {
+ incPin(val: [PeerNode & PeerGeo, number][], pin: PeerNode & PeerGeo): [PeerNode & PeerGeo, number][] {
const [, quantity = 0] =
- val.find(([p]) => p.lat === pin.lat && p.lng == pin.lng) || [];
- const rest = val.filter(([p]) => p.lat !== pin.lat || p.lng !== pin.lng)
+ val.find(([p]) => p.latitude === pin.latitude && p.longitude == pin.longitude) || [];
+ const rest = val.filter(([p]) => p.latitude !== pin.latitude || p.longitude !== pin.longitude)
return [...rest, [pin, quantity + 1]];
},
@@ -53,6 +55,10 @@ export const PeerUtils = {
return (actives / total) * 180
},
+ isGoodQuality(actives: number) {
+ return actives > 0
+ },
+
geCountryEmoji: (countryCode: string) => {
const codePoints = countryCode
.toUpperCase()
diff --git a/src/components/PlusIcon/PlusIcon.tsx b/src/components/PlusIcon/PlusIcon.tsx
new file mode 100644
index 0000000..c4f4795
--- /dev/null
+++ b/src/components/PlusIcon/PlusIcon.tsx
@@ -0,0 +1,15 @@
+export function PlusIcon() {
+ return (
+
+
+
+ );
+}
diff --git a/src/components/UploadCard/UploadCard.tsx b/src/components/UploadCard/UploadCard.tsx
new file mode 100644
index 0000000..5e9c1e5
--- /dev/null
+++ b/src/components/UploadCard/UploadCard.tsx
@@ -0,0 +1,25 @@
+import { Upload, UploadIcon } from "@codex-storage/marketplace-ui-components";
+import { CodexSdk } from "../../sdk/codex";
+import { useQueryClient } from "@tanstack/react-query";
+
+export function UploadCard() {
+ const queryClient = useQueryClient();
+
+ const onSuccess = () => {
+ queryClient.invalidateQueries({ queryKey: ["cids"] });
+ };
+
+ return (
+
+ );
+}
diff --git a/src/components/Welcome/DiscordIcon.tsx b/src/components/Welcome/DiscordIcon.tsx
new file mode 100644
index 0000000..7bb9690
--- /dev/null
+++ b/src/components/Welcome/DiscordIcon.tsx
@@ -0,0 +1,15 @@
+export function DiscordIcon() {
+ return (
+
+
+
+ );
+}
diff --git a/src/components/Welcome/Welcome.css b/src/components/Welcome/Welcome.css
deleted file mode 100644
index 3530439..0000000
--- a/src/components/Welcome/Welcome.css
+++ /dev/null
@@ -1,35 +0,0 @@
-.welcome {
- border-radius: var(--codex-border-radius);
- border: 1px solid var(--codex-border-color);
- background-color: var(--codex-background-secondary);
- padding: 1rem 1.5rem;
- display: flex;
- align-items: flex-start;
- flex-direction: column;
- flex: 1;
-}
-
-.welcome-disclaimer {
- margin: 1rem 0;
-}
-
-.welcome-title {
- font-weight: bold;
- font-size: 1.125rem;
- line-height: 1.75rem;
- margin-bottom: 0.75rem;
-}
-
-.welcome-body {
- flex: 1;
-}
-
-.welcome-link {
- display: flex;
- align-items: center;
- color: var(--codex-color-primary);
-}
-
-.welcome-link:hover {
- text-decoration: underline;
-}
diff --git a/src/components/Welcome/Welcome.tsx b/src/components/Welcome/Welcome.tsx
deleted file mode 100644
index 65a6090..0000000
--- a/src/components/Welcome/Welcome.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-import "./Welcome.css";
-import { Link } from "@tanstack/react-router";
-import { ChevronRight } from "lucide-react";
-
-export function Welcome() {
- return (
-
-
Welcome to Codex Marketplace
-
-
- Begin your journey with Codex by uploading new files for testing.
- Experience the power of our decentralized data storage platform and
- explore its features. Your feedback is invaluable as we continue to
- improve!
-
-
-
-
- Explore more content
-
-
- );
-}
diff --git a/src/components/Welcome/WelcomeCard.css b/src/components/Welcome/WelcomeCard.css
new file mode 100644
index 0000000..4c3c987
--- /dev/null
+++ b/src/components/Welcome/WelcomeCard.css
@@ -0,0 +1,102 @@
+.welcome-card {
+ display: flex;
+ flex-direction: column;
+
+ > div {
+ padding: 16px;
+ background-color: #141414;
+ background-image: url(img/welcome.png);
+ background-repeat: no-repeat;
+ background-position: right;
+ flex: 1;
+ }
+
+ main {
+ max-width: 400px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ flex: 1;
+
+ h6 {
+ font-family: Inter;
+ font-size: 20px;
+ font-weight: 400;
+ line-height: 24.2px;
+ color: var(--codex-color-primary);
+ }
+
+ p {
+ margin-top: 16px;
+ margin-bottom: 32px;
+ font-family: Azeret Mono;
+ font-size: 12px;
+ font-weight: 400;
+ line-height: 14px;
+ text-align: left;
+ color: #7f948d;
+ }
+
+ div {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ }
+
+ a {
+ font-family: Inter;
+ font-size: 16px;
+ font-weight: 600;
+ line-height: 19.36px;
+ letter-spacing: 0.01em;
+ text-align: left;
+ color: #7bfbaf;
+ display: flex;
+ align-items: center;
+
+ &:nth-child(2) {
+ gap: 12px;
+ }
+ }
+ }
+
+ footer {
+ margin-top: 32px;
+ }
+}
+
+.welcome {
+ border-radius: var(--codex-border-radius);
+ border: 1px solid var(--codex-border-color);
+ background-color: var(--codex-background-secondary);
+ padding: 1rem 1.5rem;
+ display: flex;
+ align-items: flex-start;
+ flex-direction: column;
+ flex: 1;
+}
+
+.welcome-disclaimer {
+ margin: 1rem 0;
+}
+
+.welcome-title {
+ font-weight: bold;
+ font-size: 1.125rem;
+ line-height: 1.75rem;
+ margin-bottom: 0.75rem;
+}
+
+.welcome-body {
+ flex: 1;
+}
+
+.welcome-link {
+ display: flex;
+ align-items: center;
+ color: var(--codex-color-primary);
+}
+
+.welcome-link:hover {
+ text-decoration: underline;
+}
diff --git a/src/components/Welcome/WelcomeCard.tsx b/src/components/Welcome/WelcomeCard.tsx
new file mode 100644
index 0000000..f36b3bb
--- /dev/null
+++ b/src/components/Welcome/WelcomeCard.tsx
@@ -0,0 +1,47 @@
+import "./WelcomeCard.css";
+import { Link } from "@tanstack/react-router";
+import { ArrowRight } from "lucide-react";
+import { Logo } from "../Logo/Logo";
+import { Logotype } from "../Logotype/Logotype";
+import { DiscordIcon } from "./DiscordIcon";
+import { Alert } from "@codex-storage/marketplace-ui-components";
+
+export function WelcomeCard() {
+ return (
+
+
+
+
+
+ Begin your journey with Codex by uploading new files for testing.
+
+
+ Experience the power of our decentralized data storage platform and
+ explore its features. Your feedback is invaluable as we continue to
+ improve!
+
+
+
+
+
+ The website and the content herein is not intended for public use
+ and is for informational and demonstration purposes only.
+
+
+
+
+ );
+}
diff --git a/src/index.css b/src/index.css
index 0271dd1..791f9c6 100644
--- a/src/index.css
+++ b/src/index.css
@@ -30,7 +30,7 @@
--codex-color-on-primary: #333;
--codex-color-disabled: #717171;
--codex-color-light: rgb(150 150 150);
- --codex-border-color: #2b303b;
+ --codex-border-color: #96969633;
--codex-input-border-color: #494949;
--codex-background-secondary: rgb(38 38 38);
--codex-highlight-color: #2f2f2f;
@@ -130,7 +130,7 @@ ul {
padding: 0;
}
-main {
+body > main {
flex: 1;
display: flex;
flex-direction: column;
@@ -181,3 +181,36 @@ input:-webkit-autofill:active {
.gap {
gap: var(--codex-row-gap);
}
+
+.card {
+ border: 1px solid #96969633;
+ border-radius: 16px;
+ padding: 16px;
+ background-color: #232323;
+
+ > header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 16px;
+ margin-bottom: 16px;
+
+ svg {
+ color: #969696;
+ }
+
+ > div {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ }
+
+ h5 {
+ font-family: Inter;
+ font-size: 16px;
+ font-weight: 500;
+ line-height: 24px;
+ letter-spacing: -0.011em;
+ }
+ }
+}
diff --git a/src/routes/dashboard/favorites.tsx b/src/routes/dashboard/favorites.tsx
index 7b9dd9c..c96d39f 100644
--- a/src/routes/dashboard/favorites.tsx
+++ b/src/routes/dashboard/favorites.tsx
@@ -2,19 +2,16 @@ import { createFileRoute } from "@tanstack/react-router";
import { Files } from "../../components/Files/Files";
import { ErrorBoundary } from "@sentry/react";
import { ErrorPlaceholder } from "../../components/ErrorPlaceholder/ErrorPlaceholder";
-import { Card } from "@codex-storage/marketplace-ui-components";
export const Route = createFileRoute("/dashboard/favorites")({
component: () => (
<>
(
-
-
-
+
)}>
diff --git a/src/routes/dashboard/index.css b/src/routes/dashboard/index.css
index 68f050e..a1c58e6 100644
--- a/src/routes/dashboard/index.css
+++ b/src/routes/dashboard/index.css
@@ -1,6 +1,7 @@
.dashboard {
display: flex;
justify-content: space-between;
+ margin-bottom: 16px;
h3 {
font-family: Inter;
@@ -32,3 +33,31 @@
font-size: 26px;
}
}
+
+.dashboard-body {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 16px;
+}
+
+.welcome-card,
+.connected-account {
+ min-width: 550px;
+ display: flex;
+ flex-direction: column;
+ flex: 1;
+}
+
+.column {
+ min-width: 400px;
+}
+
+.files {
+ flex: 1;
+ min-width: 100%;
+}
+
+@media (min-width: 1800px) {
+ .dashboard-body {
+ }
+}
diff --git a/src/routes/dashboard/index.tsx b/src/routes/dashboard/index.tsx
index 944b966..01dc9c6 100644
--- a/src/routes/dashboard/index.tsx
+++ b/src/routes/dashboard/index.tsx
@@ -1,28 +1,23 @@
import { createFileRoute } from "@tanstack/react-router";
import { Files } from "../../components/Files/Files.tsx";
-import { Alert, Card, Upload } from "@codex-storage/marketplace-ui-components";
-import { CodexSdk } from "../../sdk/codex";
-import { Welcome } from "../../components/Welcome/Welcome.tsx";
+import { WelcomeCard } from "../../components/Welcome/WelcomeCard.tsx";
import { ErrorPlaceholder } from "../../components/ErrorPlaceholder/ErrorPlaceholder.tsx";
import { ErrorBoundary } from "@sentry/react";
-import { useQueryClient } from "@tanstack/react-query";
import { Download } from "../../components/Download/Download.tsx";
-import { ManifestFetch } from "../../components/ManifestFetch/ManifestFetch.tsx";
import "./index.css";
import { Versions } from "../../components/Versions/Versions.tsx";
import { WebStorage } from "../../utils/web-storage.ts";
+import { ConnectedAccount } from "../../components/ConnectedAccount/ConnectedAccount.tsx";
+import { NodeSpace } from "../../components/NodeSpace/NodeSpace.tsx";
+import { UploadCard } from "../../components/UploadCard/UploadCard.tsx";
+import { ManifestFetchCard } from "../../components/ManifestFetch/ManifestFetchCard.tsx";
+import { PeersCard } from "../../components/Peers/PeersCard.tsx";
export const Route = createFileRoute("/dashboard/")({
component: Dashboard,
});
function Dashboard() {
- const queryClient = useQueryClient();
-
- const onSuccess = () => {
- queryClient.invalidateQueries({ queryKey: ["cids"] });
- };
-
const username = WebStorage.onBoarding.getDisplayName();
const emoji = WebStorage.onBoarding.getEmoji();
@@ -40,22 +35,20 @@ function Dashboard() {
-
-
(
-
- )}>
-
-
-
-
+
+
+
(
@@ -64,11 +57,23 @@ function Dashboard() {
subtitle="Cannot retrieve the data."
/>
)}>
-
-
-
+
+
+ (
+
+ )}>
+
+
+
+
+
+
(
)}>
-
-
-
+
-
-
(
-
- )}>
-
-
-
-
- The website and the content herein is not intended for public use
- and is for informational and demonstration purposes only.
-
-
-
-
-
-
- (
-
-
-
- )}>
-
-
>
);