diff --git a/src/components/ConnectedAccount/ProgressCircle.css b/src/components/ConnectedAccount/ProgressCircle.css
index 6f73ad1..fa55130 100644
--- a/src/components/ConnectedAccount/ProgressCircle.css
+++ b/src/components/ConnectedAccount/ProgressCircle.css
@@ -3,20 +3,21 @@
width: 48px;
height: 48px;
display: flex;
- background: #2f2f2f;
+ background: rgb(47, 47, 47);
background-image:
- -webkit-linear-gradient(90deg, #2f2f2f 50%, transparent 50%),
- -webkit-linear-gradient(270deg, var(--codex-color-primary) 50%, #2f2f2f 50%);
- background-image: linear-gradient(90deg, #2f2f2f 50%, transparent 50%),
- linear-gradient(270deg, var(--codex-color-primary) 50%, #2f2f2f 50%);
+ -webkit-linear-gradient(90deg, rgb(47, 47, 47) 50%, transparent 50%),
+ -webkit-linear-gradient(270deg, var(--codex-color-primary) 50%, rgb
+ (47, 47, 47) 50%);
+ background-image: linear-gradient(90deg, rgb(47, 47, 47) 50%, transparent 50%),
+ linear-gradient(270deg, var(--codex-color-primary) 50%, rgb(47, 47, 47) 50%);
div {
border-radius: 50%;
width: 36px;
height: 36px;
margin: auto;
- background: #232323;
+ background: rgb(35, 35, 35);
text-align: center;
box-sizing: border-box;
}
diff --git a/src/components/ConnectedAccount/ProgressCircle.tsx b/src/components/ConnectedAccount/ProgressCircle.tsx
index 1137d1b..652b39b 100644
--- a/src/components/ConnectedAccount/ProgressCircle.tsx
+++ b/src/components/ConnectedAccount/ProgressCircle.tsx
@@ -4,6 +4,7 @@ type Props = {
value: number;
};
+/* eslint-disable @typescript-eslint/no-unused-vars */
export function ProgressCircle(_: Props) {
return (
diff --git a/src/components/ConnectedAccount/WalletCard.css b/src/components/ConnectedAccount/WalletCard.css
index f0fa1d8..f8f4b57 100644
--- a/src/components/ConnectedAccount/WalletCard.css
+++ b/src/components/ConnectedAccount/WalletCard.css
@@ -10,7 +10,7 @@
background-repeat: no-repeat;
background-size: cover;
- border: 1px solid #96969633;
+ border: 1px solid rgba(150, 150, 150, 0.2);
border-radius: 16px;
padding: 16px;
box-sizing: border-box;
@@ -36,8 +36,8 @@
align-items: center;
button {
- background-color: #161616;
- border: 1px solid #96969633;
+ background-color: rgb(22, 22, 22);
+ border: 1px solid rgba(150, 150, 150, 0.2);
height: 24px;
width: 24px;
cursor: pointer;
@@ -47,7 +47,7 @@
align-items: center;
&:hover {
- box-shadow: 0 0 0 3px var(--codex-border-color);
+ box-shadow: 0 0 0 3px rgba(150, 150, 150, 0.2);
}
&:first-child {
@@ -84,7 +84,7 @@
line-height: 20px;
letter-spacing: -0.006em;
text-align: left;
- color: #ffffffb2;
+ color: rgb(255, 255, 255, 0.7);
}
var {
@@ -92,7 +92,7 @@
font-weight: 500;
line-height: 40px;
letter-spacing: -0.005em;
- color: var(--text-strong-950, #ffffff);
+ color: rgb(255, 255, 255);
display: block;
font-style: normal;
}
@@ -130,30 +130,60 @@
}
select {
- background-color: #161616;
+ background-color: rgb(22, 22, 22);
border-radius: 8px;
- border: 1px solid #96969633;
- padding: 6px 6px 6px 44px;
+ border: 1px solid rgba(150, 150, 150, 0.2);
+ padding: 6px 24px 6px 34px;
outline: none;
-moz-appearance: none; /* Firefox */
-webkit-appearance: none; /* Safari and Chrome */
appearance: none;
position: relative;
transition: box-shadow 0.35s;
+ height: 31px;
+ font-size: 0;
&:hover {
- box-shadow: 0 0 0 3px var(--codex-border-color);
+ box-shadow: 0 0 0 3px rgba(150, 150, 150, 0.2);
}
- &:has(option[value="US"]:checked) {
- background-image: url(/icons/us-flag.svg);
+ &:has(option:checked) {
background-position: 10px;
background-repeat: no-repeat;
background-size: 16px;
}
+ &:has(option[value="USD"]:checked) {
+ background-image: url(/icons/us-flag.svg);
+ }
+
+ &:has(option[value="EUR"]:checked) {
+ background-image: url(/icons/euro-flag.svg);
+ }
+
+ &:has(option[value="AUD"]:checked) {
+ background-image: url(/icons/aud-flag.svg);
+ }
+
+ &:has(option[value="CAD"]:checked) {
+ background-image: url(/icons/cad-flag.svg);
+ }
+
+ &:has(option[value="CNY"]:checked) {
+ background-image: url(/icons/cny-flag.svg);
+ }
+
+ &:has(option[value="BTC"]:checked) {
+ background-image: url(/icons/btc-flag.svg);
+ }
+
+ &:has(option[value="ETH"]:checked) {
+ background-image: url(/icons/eth-flag.svg);
+ }
+
option {
border-radius: 32px;
+ font-size: 16px;
}
}
@@ -166,11 +196,11 @@
}
small {
- color: #3ee089;
+ color: rgb(62, 224, 137);
height: 20px;
width: 42px;
border-radius: 16px;
- background-color: #1fc16b29;
+ background-color: rgb(31, 193, 107, 0.16);
display: flex;
align-items: center;
justify-content: center;
@@ -192,4 +222,8 @@
top: 10px;
}
}
+
+ .lines {
+ height: 200;
+ }
}
diff --git a/src/components/ConnectedAccount/WalletCard.tsx b/src/components/ConnectedAccount/WalletCard.tsx
index 5f6ec8c..0ffdf59 100644
--- a/src/components/ConnectedAccount/WalletCard.tsx
+++ b/src/components/ConnectedAccount/WalletCard.tsx
@@ -1,10 +1,133 @@
import "./WalletCard.css";
import ArrowRightIcon from "../../assets/icons/arrow-right.svg?react";
import ArrowLeftIcon from "../../assets/icons/arrow-left.svg?react";
-import WalletChart from "../../assets/icons/chart.svg?react";
-import WalletLines from "../../assets/icons/lines.svg?react";
+import { useState, ChangeEvent, useRef, useEffect } from "react";
+
+import * as echarts from "echarts/core";
+import { LineChart } from "echarts/charts";
+import { GridComponent } from "echarts/components";
+import { UniversalTransition } from "echarts/features";
+import { CanvasRenderer } from "echarts/renderers";
+
+const defaultTokenValue = 1540;
+
+echarts.use([GridComponent, LineChart, CanvasRenderer, UniversalTransition]);
+
+type Props = {
+ tab: "weekly" | "daily" | "monthly";
+};
+
+export function WalletCard({ tab }: Props) {
+ const [tokenValue, setTokenValue] = useState(defaultTokenValue);
+ const [currency, setCurrency] = useState("USD");
+ const div = useRef
(null);
+ const chart = useRef(null);
+ const [, setRefresher] = useState(Date.now());
+
+ useEffect(() => {
+ if (div.current && !chart.current) {
+ chart.current = echarts.init(div.current, null, {
+ renderer: "svg",
+ });
+ setRefresher(Date.now());
+ }
+ }, [chart, div]);
+
+ useEffect(() => {
+ const refresh = () => chart.current?.resize();
+
+ window.addEventListener("resize", refresh);
+
+ return () => {
+ window.removeEventListener("resize", refresh);
+ };
+ }, []);
+
+ const onCurrencyChange = async (e: ChangeEvent) => {
+ const value = e.currentTarget.value;
+ setCurrency(value);
+
+ if (value === "USD") {
+ setTokenValue(1540);
+ } else if (["BTC", "ETH"].includes(value) === false) {
+ const json = await fetch(
+ "https://cdn.jsdelivr.net/npm/@fawazahmed0/currency-api@latest/v1/currencies/usd.json"
+ ).then((res) => res.json());
+ setTokenValue(defaultTokenValue * json.usd[value.toLocaleLowerCase()]);
+ } else {
+ const json = await fetch(
+ "https://api.coinbase.com/v2/prices/" +
+ value.toLocaleLowerCase() +
+ "-USD/spot.json"
+ ).then((res) => res.json());
+ setTokenValue(defaultTokenValue / json.data.amount);
+ }
+ };
+
+ if (chart.current) {
+ const today = new Date();
+ const startOfWeek = today.getDate() - today.getDay() + 1;
+ const startDates = [];
+
+ today.setDate(startOfWeek);
+
+ for (let i = 0; i < 5; i++) {
+ startDates.push(today.toISOString().split("T")[0]);
+ today.setDate(today.getDate() + 7);
+ }
+
+ const data = {
+ daily: ["MON", "TUE", "WED", "THU", "WED", "SAT", "SUN"],
+ weekly: startDates,
+ monthly: ["JAN", "FEB", "MAR", "APR", "MAY", "JUN"],
+ }[tab];
+
+ const option = {
+ color: ["#3EE089"],
+ xAxis: {
+ type: "category",
+ data: data,
+ show: true,
+ splitLine: {
+ show: true,
+ lineStyle: {
+ width: 0.5,
+ type: "dashed",
+ },
+ },
+ },
+ yAxis: {
+ type: "value",
+ show: false,
+ },
+ grid: [
+ {
+ left: 0,
+ right: 0,
+ top: 50,
+ bottom: 50,
+ },
+ ],
+ series: [
+ {
+ data: [220, 932, 401, 934, 1290, 1330, 1450].slice(0, data.length),
+ type: "line",
+ smooth: true,
+ lineStyle: {
+ normal: {
+ color: "#3EE089",
+ },
+ },
+ },
+ ],
+ tooltip: {
+ type: "item",
+ },
+ };
+
+ chart.current.setOption(option, true);
+ }
-export function WalletCard() {
return (
diff --git a/src/components/CustomStateCellRender/CustomStateCellRender.tsx b/src/components/CustomStateCellRender/CustomStateCellRender.tsx
index 6f4ae77..990552c 100644
--- a/src/components/CustomStateCellRender/CustomStateCellRender.tsx
+++ b/src/components/CustomStateCellRender/CustomStateCellRender.tsx
@@ -13,31 +13,22 @@ export const CustomStateCellRender = ({ state, message }: Props) => {
pending: PurchaseStateIcon,
submitted: PurchaseStateIcon,
started: PurchaseStateIcon,
- finished: SuccessCircleIcon,
+ finished: () => ,
cancelled: ErrorCircleIcon,
errored: ErrorCircleIcon,
};
- const states = {
- cancelled: "error",
- errored: "error",
- pending: "warning",
- started: "loading",
- submitted: "loading",
- finished: "success",
- };
-
const Icon = icons[state as keyof typeof icons] || PurchaseStateIcon;
return (
-
+
{message ? (
-
+
) : (
-
+
)}
|
diff --git a/src/components/Debug/Debug.tsx b/src/components/Debug/Debug.tsx
index 9036a8b..12e65c5 100644
--- a/src/components/Debug/Debug.tsx
+++ b/src/components/Debug/Debug.tsx
@@ -8,7 +8,7 @@ export function Debug() {
if (isPending) {
return (
-
+
);
diff --git a/src/components/Dialog/Dialog.css b/src/components/Dialog/Dialog.css
deleted file mode 100644
index cdb76e9..0000000
--- a/src/components/Dialog/Dialog.css
+++ /dev/null
@@ -1,11 +0,0 @@
-.dialog::backdrop {
- background: rgba(70, 70, 70, 0.75);
- backdrop-filter: blur(2px);
-}
-
-.dialog {
- background-color: var(--codex-background-secondary);
- border: none;
- color: var(--codex-color);
- min-width: 200px;
-}
diff --git a/src/components/Dialog/Dialog.tsx b/src/components/Dialog/Dialog.tsx
deleted file mode 100644
index 1b99e36..0000000
--- a/src/components/Dialog/Dialog.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-import { ReactNode, useEffect, useRef } from "react";
-import "./Dialog.css";
-import { Button } from "@codex-storage/marketplace-ui-components";
-
-type Props = {
- open: boolean;
- children: ReactNode;
- onClose: () => void;
-};
-
-export function Dialog({ open, children, onClose }: Props) {
- const ref = useRef
(null);
-
- useEffect(() => {
- if (open) {
- ref.current?.showModal();
- } else {
- ref.current?.close();
- }
- }, [open]);
-
- return (
-
- );
-}
diff --git a/src/components/Download/Download.tsx b/src/components/Download/Download.tsx
index 26f1675..a7bcc63 100644
--- a/src/components/Download/Download.tsx
+++ b/src/components/Download/Download.tsx
@@ -19,8 +19,9 @@ export function Download() {
id="cid"
placeholder="CID"
inputClassName="download-input"
- size={"medium" as any}
+ variant={"medium"}
autoComplete="off"
+ value={cid}
onChange={onCidChange}>
diff --git a/src/components/ErrorIcon/ErrorIcon.tsx b/src/components/ErrorIcon/ErrorIcon.tsx
deleted file mode 100644
index 1f41214..0000000
--- a/src/components/ErrorIcon/ErrorIcon.tsx
+++ /dev/null
@@ -1,9 +0,0 @@
-import { CircleX } from "lucide-react";
-
-export function ErrorIcon() {
- return (
-
-
-
- );
-}
diff --git a/src/components/ErrorPlaceholder/ErrorPlaceholder.tsx b/src/components/ErrorPlaceholder/ErrorPlaceholder.tsx
index a5c50fb..3e42e6c 100644
--- a/src/components/ErrorPlaceholder/ErrorPlaceholder.tsx
+++ b/src/components/ErrorPlaceholder/ErrorPlaceholder.tsx
@@ -1,5 +1,5 @@
import { Placeholder } from "@codex-storage/marketplace-ui-components";
-import { ErrorIcon } from "../ErrorIcon/ErrorIcon";
+import ErrorCircleIcon from "../../assets/icons/error-circle.svg?react";
type Props = {
subtitle?: string;
@@ -13,7 +13,7 @@ export function ErrorPlaceholder({ subtitle, error }: Props) {
return (
}
+ Icon={}
title="Error"
subtitle={subtitle}
message={message}>
diff --git a/src/components/FileCellRender/FileCell.css b/src/components/FileCellRender/FileCell.css
index 3c0a853..a5e075f 100644
--- a/src/components/FileCellRender/FileCell.css
+++ b/src/components/FileCellRender/FileCell.css
@@ -1,24 +1,18 @@
-.fileCell {
+.file-render {
display: flex;
gap: 0.75rem;
-}
-.fileCell-cid {
- white-space: nowrap;
-}
+ .tooltip:hover::after {
+ left: 0;
+ }
-.fileCell-subtitle {
- display: flex;
- align-items: center;
- gap: 0.5rem;
- position: relative;
-}
-
-.fileCell-tooltip {
- display: flex;
- align-items: center;
-}
-
-.fileCell .tooltip:hover:after {
- left: -33%;
+ small {
+ white-space: nowrap;
+ font-family: Inter;
+ font-size: 12px;
+ font-weight: 500;
+ line-height: 16px;
+ text-align: left;
+ color: rgb(125, 125, 125);
+ }
}
diff --git a/src/components/FileCellRender/FileCell.tsx b/src/components/FileCellRender/FileCell.tsx
index 9095046..07c699a 100644
--- a/src/components/FileCellRender/FileCell.tsx
+++ b/src/components/FileCellRender/FileCell.tsx
@@ -69,17 +69,17 @@ export function FileCell({ requestId, purchaseCid, data, onMetadata }: Props) {
return (
-
+
-
+
{filename}
-
-
+
+
- {cidTruncated}
+ {cidTruncated}
-
+
diff --git a/src/components/Files/FileActions.css b/src/components/Files/FileActions.css
index 242ffac..6ec1267 100644
--- a/src/components/Files/FileActions.css
+++ b/src/components/Files/FileActions.css
@@ -2,18 +2,48 @@
> div {
display: inline-flex;
align-items: center;
- border: 1px solid var(--codex-border-color);
- border-radius: var(--codex-border-radius);
+ border: 1px solid rgba(150, 150, 150, 0.2);
+ border-radius: 10px;
padding: 0.5rem;
- background-color: #14141499;
+ background-color: rgba(20, 20, 20, 0.6);
gap: 8px;
padding: 10px;
+ }
- .button-icon {
- width: 40px;
- height: 40px;
- background-color: #2f2f2f;
- border: 1px solid #96969633;
+ ul {
+ transition: bottom 0.35s;
+ position: fixed;
+ bottom: -500px;
+ left: 0;
+ right: 0;
+ background-color: rgba(47, 47, 47, 1);
+ border-top: 1px solid rgba(150, 150, 150, 0.2);
+ border-top-left-radius: 12px;
+ border-top-right-radius: 12px;
+
+ padding: 16px;
+
+ &[aria-expanded] {
+ bottom: 0;
+ z-index: 11;
+ }
+
+ li {
+ display: flex;
+ align-items: center;
+ gap: 16px;
+ }
+
+ li + li {
+ margin-top: 16px;
+ padding-top: 16px;
+ border-top: 1px solid rgba(150, 150, 150, 0.2);
+ }
+ }
+
+ @media (max-width: 800px) {
+ .folder-button {
+ display: none;
}
}
}
diff --git a/src/components/Files/FileActions.tsx b/src/components/Files/FileActions.tsx
index 18151dd..1e6eae0 100644
--- a/src/components/Files/FileActions.tsx
+++ b/src/components/Files/FileActions.tsx
@@ -1,10 +1,19 @@
-import { ButtonIcon, Cell } from "@codex-storage/marketplace-ui-components";
+import {
+ Backdrop,
+ ButtonIcon,
+ Cell,
+} from "@codex-storage/marketplace-ui-components";
import { FolderButton } from "./FolderButton";
import { CodexDataContent } from "@codex-storage/sdk-js";
import { CodexSdk } from "../../sdk/codex";
import "./FileActions.css";
import DownloadIcon from "../../assets/icons/download-file.svg?react";
import InfoFileIcon from "../../assets/icons/info-file.svg?react";
+import DotsIcon from "../../assets/icons/dots.svg?react";
+import { useIsMobile } from "../../hooks/useMobile";
+import { useState } from "react";
+import { attributes } from "../../utils/attributes";
+import CopyIcon from "../../assets/icons/copy.svg?react";
type Props = {
content: CodexDataContent;
@@ -19,15 +28,62 @@ export function FileActions({
onFolderToggle,
onDetails,
}: Props) {
+ const isMobile = useIsMobile();
const url = CodexSdk.url() + "/api/codex/v1/data/";
+ const [isExpanded, setIsExpanded] = useState(false);
+
+ const onClose = () => setIsExpanded(false);
+
+ const onOpen = () => setIsExpanded(true);
+
+ const onCopy = (cid: string) => {
+ setIsExpanded(false);
+ navigator.clipboard.writeText(cid);
+ };
+
+ if (isMobile) {
+ return (
+
+ <>
+ (
+
+ )}>
+
+ - {
+ window.open(url + content.cid, "_blank");
+ setIsExpanded(false);
+ }}>
+ Download
+
+ - {
+ onDetails(content.cid);
+ setIsExpanded(false);
+ }}>
+ Details
+
+ - onCopy(content.cid)}>
+ Copy
+
+
+
+ >
+ |
+ );
+ }
return (
window.open(url + content.cid, "_blank")}
- Icon={DownloadIcon}>
+ Icon={() => }>
[
diff --git a/src/components/Files/FileCell.css b/src/components/Files/FileCell.css
index b0a4d65..6fbb294 100644
--- a/src/components/Files/FileCell.css
+++ b/src/components/Files/FileCell.css
@@ -15,8 +15,14 @@
.button-icon {
width: 40px;
height: 40px;
- background-color: #14141499;
- border: 1px solid #96969633;
+ background-color: rgba(20, 20, 20, 0.6);
+ border: 1px solid rgba(150, 150, 150, 0.2);
+
+ @media (max-width: 800px) {
+ & {
+ display: none;
+ }
+ }
}
}
}
diff --git a/src/components/Files/FileCell.tsx b/src/components/Files/FileCell.tsx
index 987ec94..b29d3a4 100644
--- a/src/components/Files/FileCell.tsx
+++ b/src/components/Files/FileCell.tsx
@@ -14,11 +14,27 @@ type Props = {
};
export function FileCell({ content }: Props) {
- const [toast, setToast] = useState({ time: 0, message: "" });
+ const [toast, setToast] = useState({
+ time: 0,
+ message: "",
+ variant: "success" as "success" | "error",
+ });
const onCopy = (cid: string) => {
- navigator.clipboard.writeText(cid);
- setToast({ message: "CID copied to the clipboard.", time: Date.now() });
+ if (navigator.clipboard) {
+ navigator.clipboard.writeText(cid);
+ setToast({
+ message: "CID copied to the clipboard.",
+ time: Date.now(),
+ variant: "success" as "success",
+ });
+ } else {
+ setToast({
+ message: "Sorry the CID cannot be copied to the clipboard.",
+ time: Date.now(),
+ variant: "error" as "error",
+ });
+ }
};
return (
@@ -44,7 +60,11 @@ export function FileCell({ content }: Props) {
)}>
-
+
|
>
);
diff --git a/src/components/Files/FileDetails.css b/src/components/Files/FileDetails.css
index 4f78919..6db82d7 100644
--- a/src/components/Files/FileDetails.css
+++ b/src/components/Files/FileDetails.css
@@ -1,6 +1,6 @@
.file-details {
- background-color: #232323;
- border-left: 1px solid #96969633;
+ background-color: rgb(35, 35, 35);
+ border-left: 1px solid rgba(150, 150, 150, 0.2);
border-top-left-radius: 16px;
border-bottom-left-radius: 16px;
padding: 16px;
@@ -21,22 +21,11 @@
span {
flex-grow: 1;
}
-
- .button-icon {
- background-color: #2f2f2f;
- border: 1px solid #96969633;
-
- svg {
- position: relative;
- left: -3px;
- top: -1px;
- }
- }
}
.preview {
- background-color: #14141499;
- border: 1px solid #69696933;
+ background-color: rgba(20, 20, 20, 0.6);
+ border: 1px solid rgba(105, 105, 105, 0.2);
height: 150px;
margin: auto;
border-radius: 10px;
@@ -63,7 +52,7 @@
line-height: 24px;
letter-spacing: -0.011em;
text-align: left;
- color: #ffffff33;
+ color: rgb(255, 255, 255, 0.2);
p {
margin-top: 8px;
@@ -95,7 +84,7 @@
line-height: 20px;
letter-spacing: -0.006em;
text-align: left;
- color: #ffffffcc;
+ color: rgba (255, 255, 255, 0.8);
}
&:last-child p:nth-child(2) {
@@ -106,14 +95,14 @@
letter-spacing: -0.006em;
text-align: left;
- color: #6beca1;
+ color: rgb(107, 236, 161);
}
}
}
.buttons {
padding: 16px 0;
- border-bottom: 1px solid #96969633;
+ border-bottom: 1px solid rgba(150, 150, 150, 0.2);
display: flex;
gap: 16px;
@@ -128,7 +117,7 @@
header {
margin-top: 16px;
display: block;
- border-bottom: 1px solid #96969633;
+ border-bottom: 1px solid rgba(150, 150, 150, 0.2);
padding-bottom: 16px;
> span {
@@ -138,15 +127,15 @@
}
thead tr th {
- border-top: 1px solid #96969633;
- border-bottom: 1px solid #96969633;
+ border-top: 1px solid rgba(150, 150, 150, 0.2);
+ border-bottom: 1px solid rgba(150, 150, 150, 0.2);
&:first-child {
- border-left: 1px solid #96969633;
+ border-left: 1px solid rgba(150, 150, 150, 0.2);
}
&:last-child {
- border-right: 1px solid #96969633;
+ border-right: 1px solid rgba(150, 150, 150, 0.2);
}
}
diff --git a/src/components/Files/FileDetails.tsx b/src/components/Files/FileDetails.tsx
index 4ad1817..8d0b1d0 100644
--- a/src/components/Files/FileDetails.tsx
+++ b/src/components/Files/FileDetails.tsx
@@ -5,8 +5,7 @@ import {
WebFileIcon,
} from "@codex-storage/marketplace-ui-components";
import { CodexDataContent, CodexPurchase } from "@codex-storage/sdk-js";
-import { PrettyBytes } from "../../utils/bytes";
-import { Dates } from "../../utils/dates";
+import { Bytes } from "../../utils/bytes";
import { CidCopyButton } from "./CidCopyButton";
import "./FileDetails.css";
import { CodexSdk } from "../../sdk/codex";
@@ -43,7 +42,8 @@ export function FileDetails({ onClose, details }: Props) {
}
return {
- error: false as any,
+ /* eslint-disable @typescript-eslint/prefer-as-const */
+ error: false as false,
data: all,
};
})
@@ -115,7 +115,11 @@ export function FileDetails({ onClose, details }: Props) {
Date:
- {Dates.format(details.manifest.uploadedAt).toString()}
+
+ {FilesUtils.formatDate(
+ details.manifest.uploadedAt
+ ).toString()}
+
@@ -125,7 +129,7 @@ export function FileDetails({ onClose, details }: Props) {
Size:
- {PrettyBytes(details.manifest.datasetSize)}
+ {Bytes.pretty(details.manifest.datasetSize)}
diff --git a/src/components/Files/FileFilters.css b/src/components/Files/FileFilters.css
index 7606270..ff9a1f9 100644
--- a/src/components/Files/FileFilters.css
+++ b/src/components/Files/FileFilters.css
@@ -2,14 +2,14 @@
padding: 4px 8px;
gap: 8px;
border-radius: 6px;
- border: 1px solid #96969633;
- background-color: #2f2f2f;
+ border: 1px solid rgba(150, 150, 150, 0.2);
+ background-color: rgb(47, 47, 47);
font-family: Inter;
font-size: 12px;
font-weight: 500;
line-height: 16px;
text-align: left;
- color: #969696;
+ color: rgba(150, 150, 150, 1);
text-transform: capitalize;
display: inline-flex;
align-items: center;
@@ -17,11 +17,11 @@
transition: box-shadow 0.35s;
&:hover {
- box-shadow: 0 0 0 3px var(--codex-border-color);
+ box-shadow: 0 0 0 3px rgba(150, 150, 150, 0.2);
}
svg {
- color: #969696;
+ color: rgba(150, 150, 150, 1);
}
&.filter--active {
diff --git a/src/components/Files/Files.css b/src/components/Files/Files.css
index 68a5aa9..09beff0 100644
--- a/src/components/Files/Files.css
+++ b/src/components/Files/Files.css
@@ -24,6 +24,17 @@
}
table thead tr th {
- background-color: #14141499;
+ background-color: rgba(20, 20, 20, 0.6);
+ }
+
+ @media (max-width: 800px) {
+ table th:nth-child(2),
+ table td:nth-child(2),
+ table th:nth-child(3),
+ table td:nth-child(3),
+ section,
+ .filters {
+ display: none;
+ }
}
}
diff --git a/src/components/Files/Files.tsx b/src/components/Files/Files.tsx
index 9f5e275..172e727 100644
--- a/src/components/Files/Files.tsx
+++ b/src/components/Files/Files.tsx
@@ -1,6 +1,5 @@
import { ChangeEvent, useEffect, useState } from "react";
-import { PrettyBytes } from "../../utils/bytes";
-import { Dates } from "../../utils/dates";
+import { Bytes } from "../../utils/bytes";
import "./Files.css";
import {
Tabs,
@@ -165,8 +164,10 @@ export function Files({ limit }: Props) {
,
- | {PrettyBytes(c.manifest.datasetSize)} | ,
- {Dates.format(c.manifest.uploadedAt).toString()} | ,
+ {Bytes.pretty(c.manifest.datasetSize)} | ,
+
+ {FilesUtils.formatDate(c.manifest.uploadedAt).toString()}
+ | ,
diff --git a/src/components/Files/FolderButton.css b/src/components/Files/FolderButton.css
index 3e1a900..37477cd 100644
--- a/src/components/Files/FolderButton.css
+++ b/src/components/Files/FolderButton.css
@@ -4,12 +4,12 @@
transform: translate(310px, -200px);
opacity: 0;
transition: opacity 0.15s;
- background-color: var(--codex-background);
+ background-color: rgba(47, 47, 47, 1);
padding: 0.5rem;
- border-radius: var(--codex-border-radius);
+ border-radius: 8px;
width: 150px;
right: -40px;
- border: 1px solid var(--codex-border-color);
+ border: 1px solid rgba(150, 150, 150, 0.2);
z-index: -1;
&[aria-expanded] {
@@ -22,13 +22,13 @@
padding: 0.75rem;
transition: background-color 0.35s;
cursor: pointer;
- border-radius: var(--codex-border-radius);
+ border-radius: 8px;
display: flex;
align-items: center;
justify-content: space-between;
&:hover {
- background-color: var(--codex-background-light);
+ background-color: rgba(150, 150, 150, 0.1);
}
}
diff --git a/src/components/Files/FolderButton.tsx b/src/components/Files/FolderButton.tsx
index dbbc2aa..8b60849 100644
--- a/src/components/Files/FolderButton.tsx
+++ b/src/components/Files/FolderButton.tsx
@@ -1,10 +1,10 @@
import { Backdrop, ButtonIcon } from "@codex-storage/marketplace-ui-components";
-import { CheckCircle } from "lucide-react";
import "./FolderButton.css";
import { useState } from "react";
import { attributes } from "../../utils/attributes";
import { classnames } from "../../utils/classnames";
import FolderIcon from "../../assets/icons/folder.svg?react";
+import SuccessCircleIcon from "../../assets/icons/success-circle.svg?react";
type Props = {
folders: [string, boolean][];
@@ -42,7 +42,7 @@ export function FolderButton({ folders, onFolderToggle }: Props) {
{folders.map(([folder, isActive]) => (
onFolderToggle(folder)}>
{folder}
- {isActive && }
+ {isActive && }
))}
diff --git a/src/components/Files/files.utils.test.ts b/src/components/Files/files.utils.test.ts
index 355d92e..7e43cc6 100644
--- a/src/components/Files/files.utils.test.ts
+++ b/src/components/Files/files.utils.test.ts
@@ -292,4 +292,10 @@ describe("files", () => {
assert.deepEqual(FilesUtils.applyFilters(files, ["archive"]), [files[1]]);
});
+
+ it("formats date", async () => {
+ const utcDate = new Date(Date.UTC(2024, 10, 20, 11, 36));
+
+ assert.equal(FilesUtils.formatDate(1732102577), "20 Nov 2024, " + utcDate.getHours() + ":" + utcDate.getMinutes());
+ })
})
\ No newline at end of file
diff --git a/src/components/Files/files.utils.ts b/src/components/Files/files.utils.ts
index 3cffb64..4dcffdb 100644
--- a/src/components/Files/files.utils.ts
+++ b/src/components/Files/files.utils.ts
@@ -89,6 +89,16 @@ export const FilesUtils = {
return files.filter(
(file) => filters.length === 0 || filters.includes(this.type(file.manifest.mimetype))
)
+ },
+ formatDate(date: number) {
+ if (!date) {
+ return "-";
+ }
+
+ return new Intl.DateTimeFormat("en-GB", {
+ dateStyle: "medium",
+ timeStyle: "short",
+ }).format(new Date(date * 1000));
}
};
diff --git a/src/components/HealthChecks/HealthChecks.css b/src/components/HealthChecks/HealthChecks.css
index 6ff3ceb..58da689 100644
--- a/src/components/HealthChecks/HealthChecks.css
+++ b/src/components/HealthChecks/HealthChecks.css
@@ -87,7 +87,7 @@
font-size: 12px;
font-weight: 400;
line-height: 14px;
- color: #828282;
+ color: rgb(130, 130, 130);
padding-left: 1.25rem;
margin-top: 1.75rem;
margin-bottom: 3rem;
@@ -101,8 +101,8 @@
align-items: center;
padding: 16px 0;
gap: 16px;
- border-top: 1px solid #96969633;
- border-bottom: 1px solid #96969633;
+ border-top: 1px solid rgba(150, 150, 150, 0.2);
+ border-bottom: 1px solid rgba(150, 150, 150, 0.2);
&:first-child {
font-family: Inter;
diff --git a/src/components/HealthChecks/HealthChecks.tsx b/src/components/HealthChecks/HealthChecks.tsx
index 3a3525b..5f800dc 100644
--- a/src/components/HealthChecks/HealthChecks.tsx
+++ b/src/components/HealthChecks/HealthChecks.tsx
@@ -7,7 +7,7 @@ import { Input, Spinner } from "@codex-storage/marketplace-ui-components";
import { classnames } from "../../utils/classnames";
import "./HealthChecks.css";
import { CodexSdk } from "../../sdk/codex";
-import { HealthCheckUtil } from "./health-check.utils";
+import { HealthCheckUtils } from "./health-check.utils";
import { PortForwardingUtil } from "../../hooks/port-forwarding.util";
import SuccessCircleIcon from "../../assets/icons/success-circle.svg?react";
import ErrorCircleIcon from "../../assets/icons/error-circle.svg?react";
@@ -30,9 +30,9 @@ export function HealthChecks({ online, onStepValid }: Props) {
const [isAddressInvalid, setIsAddressInvalid] = useState(false);
const [isPortInvalid, setIsPortInvalid] = useState(false);
const [address, setAddress] = useState(
- HealthCheckUtil.removePort(CodexSdk.url())
+ HealthCheckUtils.removePort(CodexSdk.url())
);
- const [port, setPort] = useState(HealthCheckUtil.getPort(CodexSdk.url()));
+ const [port, setPort] = useState(HealthCheckUtils.getPort(CodexSdk.url()));
const queryClient = useQueryClient();
useEffect(
@@ -54,12 +54,16 @@ export function HealthChecks({ online, onStepValid }: Props) {
setIsAddressInvalid(!element.checkValidity());
- const address = HealthCheckUtil.removePort(value);
- setAddress(address);
+ setAddress(value);
- if (HealthCheckUtil.containsPort(value)) {
- const p = HealthCheckUtil.getPort(value);
+ if (HealthCheckUtils.containsPort(value)) {
+ const address = HealthCheckUtils.removePort(value);
+ setAddress(address);
+
+ const p = HealthCheckUtils.getPort(value);
setPort(p);
+ } else {
+ setAddress(value);
}
};
@@ -74,7 +78,7 @@ export function HealthChecks({ online, onStepValid }: Props) {
const onSave = () => {
const url = address + ":" + port;
- if (HealthCheckUtil.isUrlInvalid(url)) {
+ if (HealthCheckUtils.isUrlInvalid(url)) {
return;
}
@@ -112,7 +116,7 @@ export function HealthChecks({ online, onStepValid }: Props) {
{isAddressInvalid ? (
) : (
-
+
)}
|
@@ -125,7 +129,7 @@ export function HealthChecks({ online, onStepValid }: Props) {
value={port}
isInvalid={isPortInvalid}
placeholder="8080">
-
+
@@ -152,9 +156,9 @@ export function HealthChecks({ online, onStepValid }: Props) {
{online ? (
-
+
) : (
-
+
)}
Internet connection
@@ -164,9 +168,9 @@ export function HealthChecks({ online, onStepValid }: Props) {
{codex.isFetching ? (
) : codex.isSuccess ? (
-
+
) : (
-
+
)}
Codex connection
@@ -176,9 +180,9 @@ export function HealthChecks({ online, onStepValid }: Props) {
{portForwarding.isFetching ? (
) : portForwarding.enabled ? (
-
+
) : (
-
+
)}
Port forwarding
@@ -188,9 +192,9 @@ export function HealthChecks({ online, onStepValid }: Props) {
{persistence.isFetching ? (
) : persistence.enabled ? (
-
+
) : (
-
+
)}
Marketplace
diff --git a/src/components/HealthChecks/health-check.utils.test.ts b/src/components/HealthChecks/health-check.utils.test.ts
index 4565603..0d6e1e7 100644
--- a/src/components/HealthChecks/health-check.utils.test.ts
+++ b/src/components/HealthChecks/health-check.utils.test.ts
@@ -1,34 +1,34 @@
import { assert, describe, it } from "vitest";
-import { HealthCheckUtil } from "./health-check.utils";
+import { HealthCheckUtils } from "./health-check.utils";
describe("health check", () => {
it("remove the port from an url", async () => {
- assert.deepEqual(HealthCheckUtil.removePort("http://localhost:8080"), "http://localhost");
+ assert.deepEqual(HealthCheckUtils.removePort("http://localhost:8080"), "http://localhost");
});
it("get the port from an url", async () => {
- assert.deepEqual(HealthCheckUtil.getPort("http://localhost:8080"), 8080);
+ assert.deepEqual(HealthCheckUtils.getPort("http://localhost:8080"), 8080);
});
it("get the default port when the url does not contain the port", async () => {
- assert.deepEqual(HealthCheckUtil.getPort("http://localhost"), 80);
+ assert.deepEqual(HealthCheckUtils.getPort("http://localhost"), 80);
});
it("returns true when the url contains a port", async () => {
- assert.deepEqual(HealthCheckUtil.containsPort("http://localhost:8080"), true);
+ assert.deepEqual(HealthCheckUtils.containsPort("http://localhost:8080"), true);
});
it("returns false when the url does not contain a port", async () => {
- assert.deepEqual(HealthCheckUtil.containsPort("http://localhost"), false);
+ assert.deepEqual(HealthCheckUtils.containsPort("http://localhost"), false);
});
it("returns true when the url is invalid", async () => {
- assert.deepEqual(HealthCheckUtil.isUrlInvalid("http://"), true);
+ assert.deepEqual(HealthCheckUtils.isUrlInvalid("http://"), true);
});
it("returns false when the url is valid", async () => {
- assert.deepEqual(HealthCheckUtil.isUrlInvalid("http://localhost:8080"), false);
+ assert.deepEqual(HealthCheckUtils.isUrlInvalid("http://localhost:8080"), false);
});
it("returns the tcp port", async () => {
@@ -57,7 +57,7 @@ describe("health check", () => {
"revision": "2fb7031e"
}
}
- assert.deepEqual(HealthCheckUtil.getTcpPort(debug), { error: false, data: 8070 });
+ assert.deepEqual(HealthCheckUtils.getTcpPort(debug), { error: false, data: 8070 });
});
it("returns an error when the addr is empty", async () => {
@@ -85,7 +85,7 @@ describe("health check", () => {
"revision": "2fb7031e"
}
}
- assert.deepEqual(HealthCheckUtil.getTcpPort(debug).error, true);
+ assert.deepEqual(HealthCheckUtils.getTcpPort(debug).error, true);
});
it("returns an error when the addr is misformated", async () => {
@@ -114,7 +114,7 @@ describe("health check", () => {
"revision": "2fb7031e"
}
}
- assert.deepEqual(HealthCheckUtil.getTcpPort(debug).error, true);
+ assert.deepEqual(HealthCheckUtils.getTcpPort(debug).error, true);
});
it("returns an error when the port is misformated", async () => {
@@ -143,6 +143,14 @@ describe("health check", () => {
"revision": "2fb7031e"
}
}
- assert.deepEqual(HealthCheckUtil.getTcpPort(debug).error, true);
+ assert.deepEqual(HealthCheckUtils.getTcpPort(debug).error, true);
+ });
+
+ it("extracts the announced ip", async () => {
+ assert.deepEqual(HealthCheckUtils.extractAnnounceAddresses([
+ "/ip4/127.0.0.1/tcp/8070"
+ ]).data, "127.0.0.1");
+ assert.deepEqual(HealthCheckUtils.extractAnnounceAddresses([]).error, true);
+ assert.deepEqual(HealthCheckUtils.extractAnnounceAddresses(["hello"]).error, true);
});
})
\ No newline at end of file
diff --git a/src/components/HealthChecks/health-check.utils.ts b/src/components/HealthChecks/health-check.utils.ts
index 65250a4..096eacb 100644
--- a/src/components/HealthChecks/health-check.utils.ts
+++ b/src/components/HealthChecks/health-check.utils.ts
@@ -1,6 +1,6 @@
import { CodexDebugInfo, SafeValue, CodexError } from "@codex-storage/sdk-js"
-export const HealthCheckUtil = {
+export const HealthCheckUtils = {
removePort(url: string) {
const parts = url.split(":")
return parts[0] + ":" + parts[1]
@@ -29,6 +29,21 @@ export const HealthCheckUtil = {
}
},
+ extractAnnounceAddresses(announceAddresses: string[]): SafeValue {
+ if (announceAddresses.length === 0) {
+ return { error: true, data: new CodexError("Not existing announce address") }
+ }
+
+
+ const ip = announceAddresses[0].split("/")
+
+ if (ip.length !== 5) {
+ return { error: true, data: new CodexError("Misformatted ip") }
+ }
+
+ return { error: false, data: ip[2] }
+ },
+
getTcpPort(info: CodexDebugInfo): SafeValue {
if (info.addrs.length === 0) {
return { error: true, data: new CodexError("Not existing address") }
diff --git a/src/components/LogLevel/LogLevel.css b/src/components/LogLevel/LogLevel.css
index 74ac045..42bca48 100644
--- a/src/components/LogLevel/LogLevel.css
+++ b/src/components/LogLevel/LogLevel.css
@@ -7,11 +7,17 @@
> div:first-child {
position: relative;
+ @media (max-width: 800px) {
+ & {
+ flex: 1;
+ }
+ }
+
svg {
position: absolute;
top: 11px;
left: 16px;
- color: #969696;
+ color: rgba(150, 150, 150, 1);
}
}
@@ -20,7 +26,13 @@
}
select {
- border-color: #969696;
+ border-color: rgba(150, 150, 150, 1);
padding-left: 40px;
+
+ @media (max-width: 800px) {
+ & {
+ width: 100%;
+ }
+ }
}
}
diff --git a/src/components/ManifestFetch/ManifestFetch.tsx b/src/components/ManifestFetch/ManifestFetch.tsx
index 1250ff4..082f1a2 100644
--- a/src/components/ManifestFetch/ManifestFetch.tsx
+++ b/src/components/ManifestFetch/ManifestFetch.tsx
@@ -48,7 +48,7 @@ export function ManifestFetch() {
id="cid"
value={cid}
placeholder="CID"
- size={"medium" as any}
+ variant={"medium"}
autoComplete="off"
onChange={onCidChange}>
diff --git a/src/components/Menu/Menu.tsx b/src/components/Menu/Menu.tsx
index 34bb513..e4abd90 100644
--- a/src/components/Menu/Menu.tsx
+++ b/src/components/Menu/Menu.tsx
@@ -1,8 +1,7 @@
import { attributes } from "../../utils/attributes";
import "./menu.css";
-import { ComponentType, useState } from "react";
+import { ComponentType, useEffect } from "react";
import { classnames } from "../../utils/classnames";
-import { Link } from "@tanstack/react-router";
import HomeIcon from "../../assets/icons/home.svg?react";
import ExpandIcon from "../../assets/icons/expand.svg?react";
import WalletIcon from "../../assets/icons/wallet.svg?react";
@@ -17,13 +16,21 @@ import PurchaseIcon from "../../assets/icons/purchase.svg?react";
import HostIcon from "../../assets/icons/host.svg?react";
import LogsIcon from "../../assets/icons/logs.svg?react";
import SettingsIcon from "../../assets/icons/settings.svg?react";
+import CloseIcon from "../../assets/icons/close.svg?react";
import HelpIcon from "../../assets/icons/help.svg?react";
import DisclaimerIcon from "../../assets/icons/disclaimer.svg?react";
+import { NavLink } from "react-router-dom";
+import { useIsMobile } from "../../hooks/useMobile";
export type MenuItemComponentProps = {
onClick: () => void;
};
+export type Props = {
+ isExpanded: boolean;
+ onExpanded: (val: boolean) => void;
+};
+
export type MenuItem =
| {
type: "separator";
@@ -36,16 +43,30 @@ export type MenuItem =
Component: ComponentType;
};
-export function Menu() {
- const [isExpanded, setIsExpanded] = useState(true);
+export function Menu({ isExpanded, onExpanded }: Props) {
+ const isMobile = useIsMobile();
const onLogoClick = () => {
if (isExpanded === false) {
- setIsExpanded(true);
+ onExpanded(true);
}
};
- const onExpandMenu = () => setIsExpanded(!isExpanded);
+ useEffect(() => {
+ if (isMobile) {
+ onExpanded(false);
+ }
+ }, [isMobile, onExpanded]);
+
+ const onExpandMenu = () => onExpanded(!isExpanded);
+
+ const onClose = () => {
+ if (isMobile) {
+ onExpanded(false);
+ }
+ };
+
+ const Icon = isMobile ? CloseIcon : ExpandIcon;
return (
<>
@@ -59,42 +80,43 @@ export function Menu() {
-
+
-
+
Dashboard
-
-
+
+
Wallet
-
-
+
+
Files
-
-
+
+ data-title="Coming soon"
+ end>
Nodes
-
-
+
@@ -102,10 +124,10 @@ export function Menu() {
Analytics
-
-
+
@@ -113,52 +135,52 @@ export function Menu() {
Devices
-
+
-
+
Purchases
-
-
+
+
-
+
Host
-
+
-
+
-
+
Peers
-
-
+
+
-
+
Log
-
+
-
+
Settings
-
-
+
+
Help
-
-
+
+
Disclaimer
-
+
diff --git a/src/components/Menu/menu.css b/src/components/Menu/menu.css
index 459116b..b0edb2d 100644
--- a/src/components/Menu/menu.css
+++ b/src/components/Menu/menu.css
@@ -1,46 +1,38 @@
.menu {
display: flex;
flex-direction: column;
- background-color: #1c1c1c;
- border-radius: var(--codex-border-radius);
+ background-color: rgb(28, 28, 28);
transition: left 0.25s;
position: sticky;
z-index: 10;
- view-transition-name: main-menu;
height: 100%;
top: 0;
transition:
width 0.5s,
font-size 0.5s,
- left 0.05s;
- min-width: 0;
+ left 0.5s;
width: 272px;
min-width: 80px;
- @media (max-width: 1199px) {
+ @media (max-width: 800px) {
& {
- width: 80px;
- .items {
- a {
- width: 26px;
- gap: 0;
- display: flex;
- justify-content: center;
+ left: -300px;
+ position: fixed;
+ z-index: 12;
+ width: 100%;
+ }
- span + span {
- font-size: 0;
- display: none;
- }
- }
- }
+ &[aria-expanded] {
+ left: 0px;
+ font-size: 12px;
}
}
@media (min-width: 1200px) {
&[aria-expanded] a[data-title]:hover::after {
content: attr(data-title);
- background-color: #2f2f2f;
- color: #fff;
+ background-color: rgb(47, 47, 47);
+ color: rgb(255, 255, 255);
padding: 8px;
border-radius: 4px;
font-size: 12px;
@@ -63,9 +55,11 @@
display: flex;
justify-content: center;
- span + span {
- font-size: 0;
- display: none;
+ @media (min-width: 801px) {
+ span + span {
+ font-size: 0;
+ display: none;
+ }
}
}
}
@@ -86,7 +80,7 @@
display: flex;
align-items: center;
gap: 1.5rem;
- background-color: #060606;
+ background-color: rgb(6, 6, 6);
border-radius: 8px;
> svg:first-child {
@@ -127,7 +121,7 @@
height: 100%;
margin-bottom: 2.5rem;
gap: 0.5rem;
- border-top: 1px solid #96969633;
+ border-top: 1px solid rgba(150, 150, 150, 0.2);
&::before {
height: 20px;
@@ -154,17 +148,17 @@
top: 115px;
}
- &:has(.active:nth-child(4))::before {
+ /* &:has(.active:nth-child(4))::before {
top: 158px;
- }
-
+ } */
+ /*
&:has(.active:nth-child(5))::before {
top: 201px;
}
&:has(.active:nth-child(6))::before {
top: 244px;
- }
+ } */
&:has(.active:nth-child(8))::before {
top: 339px;
@@ -201,7 +195,7 @@
hr {
margin-top: 1.5rem;
margin-bottom: 1.5rem;
- border: 0.1px solid #96969633;
+ border: 0.1px solid rgba(150, 150, 150, 0.2);
width: 100%;
}
@@ -220,16 +214,16 @@
font-weight: 500;
line-height: 20px;
letter-spacing: -0.006em;
- color: #969696;
+ color: rgba(150, 150, 150, 1);
border-radius: 8px;
transition: background-color 0.35s;
position: relative;
margin-left: 6px;
&:hover:not([aria-disabled="true"]),
- &.active {
- background-color: var(--codex-highlight-color);
- color: #c7c7c7;
+ &.active:not([aria-disabled="true"]) {
+ background-color: rgb(47, 47, 47);
+ color: rgb(199, 199, 199);
}
span:first-child {
@@ -244,10 +238,15 @@
span + span {
display: inline-block;
overflow: hidden;
- min-width: 0;
}
- &.active span:first-child {
+ @media (min-width: 801px) {
+ span + span {
+ min-width: 0;
+ }
+ }
+
+ &.active:not([aria-disabled="true"]) span:first-child {
color: var(--codex-color-primary);
}
}
diff --git a/src/components/NodeSpace/NodeSpace.css b/src/components/NodeSpace/NodeSpace.css
index 8c7c82d..166422a 100644
--- a/src/components/NodeSpace/NodeSpace.css
+++ b/src/components/NodeSpace/NodeSpace.css
@@ -8,6 +8,6 @@
text-align: left;
padding-top: 16px;
margin-bottom: 16px;
- border-top: 1px solid #96969633;
+ border-top: 1px solid rgba(150, 150, 150, 0.2);
}
}
diff --git a/src/components/NodeSpace/nodeSpace.domain.ts b/src/components/NodeSpace/nodeSpace.domain.ts
deleted file mode 100644
index f8b8a3a..0000000
--- a/src/components/NodeSpace/nodeSpace.domain.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export const nodeSpaceAllocationColors = [
- "var(--codex-color-primary)",
- "#f9fa93",
- "#ccc",
-]
\ No newline at end of file
diff --git a/src/components/OnBoarding/OnBoardingLayout.css b/src/components/OnBoarding/OnBoardingLayout.css
index c58252a..9b129ea 100644
--- a/src/components/OnBoarding/OnBoardingLayout.css
+++ b/src/components/OnBoarding/OnBoardingLayout.css
@@ -36,6 +36,12 @@
section > *:first-child {
flex: 0.5;
+
+ @media (max-width: 800px) {
+ & {
+ flex: 0.2;
+ }
+ }
}
h1 {
@@ -85,7 +91,7 @@
}
&[aria-selected] {
- box-shadow: 0px 0px 12px 0px #fff;
+ box-shadow: 0px 0px 12px 0px rgb(255, 255, 255);
opacity: 1;
}
}
@@ -114,7 +120,7 @@
cursor: pointer;
display: inline-flex;
align-items: center;
- color: var(--codex-color-error-hexa);
+ color: rgb(204, 108, 108);
&:hover {
animation-name: example;
@@ -142,7 +148,7 @@
line-height: 16.34px;
max-width: 532px;
margin-top: 20px;
- color: var(--codex-input-label-color);
+ color: rgba(130, 130, 130, 1);
}
label {
@@ -166,13 +172,14 @@
letter-spacing: 0.01em;
margin-top: 32px;
font-family: Inter;
- color: #7bfbaf;
+ color: rgb(123, 251, 175);
gap: 4px;
text-decoration: none;
- border-bottom: 2px solid #7bfbaf;
+ border-bottom: 2px solid rgb(123, 251, 175);
cursor: pointer;
display: inline-flex;
align-items: center;
+ gap: 8px;
}
}
@@ -192,7 +199,7 @@
.navigation {
cursor: pointer;
- position: absolute;
+ position: fixed;
right: 16px;
bottom: 16px;
border-bottom: none;
@@ -202,6 +209,12 @@
right: 6rem;
bottom: 16px;
+ @media (max-width: 800px) {
+ & {
+ right: 16px;
+ }
+ }
+
&:hover {
animation-name: example;
animation-duration: 2.5s;
@@ -217,6 +230,10 @@
padding: 16px;
max-width: 700px;
}
+
+ .input input {
+ --codex-input-background-color: rgba(35, 35, 35, 1);
+ }
}
@keyframes rotate {
diff --git a/src/components/OnBoarding/OnBoardingLayout.tsx b/src/components/OnBoarding/OnBoardingLayout.tsx
index 9f752a1..0e32889 100644
--- a/src/components/OnBoarding/OnBoardingLayout.tsx
+++ b/src/components/OnBoarding/OnBoardingLayout.tsx
@@ -4,7 +4,7 @@ import Logotype from "../../assets/icons/logotype.svg?react";
import { attributes } from "../../utils/attributes";
import "./OnBoardingLayout.css";
import { BackgroundImage } from "../BackgroundImage/BackgroundImage";
-import { useNavigate } from "@tanstack/react-router";
+import { useNavigate } from "react-router-dom";
type Props = {
children: ReactElement<{ onStepValid: (isValid: boolean) => void }>;
@@ -13,7 +13,7 @@ type Props = {
};
export function OnBoardingLayout({ children, step }: Props) {
- const navigate = useNavigate({ from: window.location.pathname });
+ const navigate = useNavigate();
return (
navigate({ to: "/" })}>
+ onClick={() => navigate("/")}>
navigate({ to: "/onboarding-name" })}>
+ onClick={() => navigate("/onboarding-name")}>
navigate({ to: "/onboarding-checks" })}>
+ onClick={() => navigate("/onboarding-checks")}>
diff --git a/src/components/Peers/PeerCountryCell.css b/src/components/Peers/PeerCountryCell.css
index b2489b3..fa61a27 100644
--- a/src/components/Peers/PeerCountryCell.css
+++ b/src/components/Peers/PeerCountryCell.css
@@ -4,7 +4,7 @@
gap: 1rem;
span:first-child {
- background-color: #141414;
+ background-color: rgb(20, 20, 20);
border-radius: 50%;
padding: 12px;
}
diff --git a/src/components/Peers/Peers.tsx b/src/components/Peers/Peers.tsx
deleted file mode 100644
index 93faf98..0000000
--- a/src/components/Peers/Peers.tsx
+++ /dev/null
@@ -1,106 +0,0 @@
-import {
- TabSortState,
- Row,
- Cell,
- Table,
-} from "@codex-storage/marketplace-ui-components";
-import { useCallback, useState } from "react";
-import { PeerCountryCell } from "./PeerCountryCell";
-import "./Peers.css";
-import { PeerGeo, PeerNode, PeerSortFn, PeerUtils } from "./peers.utils";
-import { PeersMap } from "./PeersMap";
-import { useDebug } from "../../hooks/useDebug";
-import { PeersQuality } from "./PeersQuality";
-import { PeersChart } from "./PeersChart";
-import SuccessCircleIcon from "../../assets/icons/success-circle.svg?react";
-import ErrorCircleIcon from "../../assets/icons/error-circle.svg?react";
-import PeersIcon from "../../assets/icons/peers.svg?react";
-
-const throwOnError = true;
-
-export const Peers = () => {
- const { data } = useDebug(throwOnError);
- const [ips, setIps] = useState
>({});
-
- const onPinAdd = useCallback((node: PeerNode, geo: PeerGeo) => {
- const [ip = ""] = node.address.split(":");
- setIps((ips) => ({ ...ips, [ip]: geo }));
- }, []);
-
- const [sortFn, setSortFn] = useState(() =>
- PeerUtils.sortByBoolean("desc")
- );
-
- const onSortByCountry = (state: TabSortState) =>
- setSortFn(() => PeerUtils.sortByCountry(state, ips));
-
- const onSortActive = (state: TabSortState) =>
- setSortFn(() => PeerUtils.sortByBoolean(state));
-
- const headers = [
- ["Country", onSortByCountry],
- ["PeerId"],
- ["Active", onSortActive],
- ] satisfies [string, ((state: TabSortState) => void)?][];
-
- const nodes = data?.table.nodes || [];
- const sorted = sortFn ? nodes.slice().sort(sortFn) : nodes;
-
- const rows = sorted.map((node) => {
- const [ip = ""] = node.address.split(":");
- const geo = ips[ip];
-
- return (
- ,
- | {node.peerId} | ,
-
- {node.seen ? (
-
- Active
-
- ) : (
-
- Inactive
-
- )}
- | ,
- ]}>
- );
- });
-
- const actives = PeerUtils.countActives(sorted);
- const degrees = PeerUtils.calculareDegrees(sorted);
- const good = PeerUtils.isGoodQuality(actives);
-
- return (
-
-
-
-
-
- - Legend
- - 1-3
- - 3-5
- - 5 +
-
-
-
-
-
-
-
- );
-};
diff --git a/src/components/Peers/PeersCard.css b/src/components/Peers/PeersCard.css
index c5007ed..9d9d75d 100644
--- a/src/components/Peers/PeersCard.css
+++ b/src/components/Peers/PeersCard.css
@@ -2,8 +2,8 @@
position: relative;
.peers-map {
- border-top: 1px solid #96969633;
- border-bottom: 1px solid #96969633;
+ border-top: 1px solid rgba(150, 150, 150, 0.2);
+ border-bottom: 1px solid rgba(150, 150, 150, 0.2);
width: 100%;
svg {
@@ -15,6 +15,15 @@
position: absolute;
left: 0;
right: 0;
+ top: -35px;
+ bottom: 0;
+ margin: auto;
+
+ @media (max-width: 800px) {
+ & {
+ transform: scale(0.8);
+ }
+ }
}
footer {
diff --git a/src/components/Peers/PeersChart.css b/src/components/Peers/PeersChart.css
index e01d60f..108415e 100644
--- a/src/components/Peers/PeersChart.css
+++ b/src/components/Peers/PeersChart.css
@@ -5,6 +5,7 @@
overflow: hidden;
margin: auto;
left: -32px;
+ border-radius: 5px;
@media (min-width: 1000px) {
& {
@@ -26,10 +27,11 @@
content: "";
width: inherit;
height: inherit;
- border: 45px solid #323232;
+ border: 45px solid rgb(50, 50, 50);
border-bottom: none;
border-top-left-radius: 175px;
border-top-right-radius: 175px;
+ border-bottom-right-radius: 5px;
}
div {
@@ -37,11 +39,13 @@
top: 100%;
width: inherit;
height: inherit;
- border: 45px solid #323232;
+ border: 45px solid rgb(50, 50, 50);
border-top: none;
border-bottom-left-radius: 175px;
border-bottom-right-radius: 175px;
transform-origin: 50% 0;
+ border-top-left-radius: 5px;
+ border-top-right-radius: 5px;
}
div:nth-child(1) {
@@ -52,13 +56,13 @@
span {
font-family: Inter;
- font-size: 38.67px;
+ font-size: 50px;
font-weight: 500;
line-height: 48.34px;
letter-spacing: -0.005em;
text-align: center;
position: absolute;
- bottom: 0;
+ bottom: 20px;
left: calc(50% - 24px);
}
}
diff --git a/src/components/Peers/PeersChart.tsx b/src/components/Peers/PeersChart.tsx
index 3406f87..157da63 100644
--- a/src/components/Peers/PeersChart.tsx
+++ b/src/components/Peers/PeersChart.tsx
@@ -15,9 +15,11 @@ export function PeersChart({ actives, degrees }: Props) {
};
return (
-
+ <>
+
+ >
);
}
diff --git a/src/components/Peers/PeersQuality.tsx b/src/components/Peers/PeersQuality.tsx
index 5fb8fa4..e4d0245 100644
--- a/src/components/Peers/PeersQuality.tsx
+++ b/src/components/Peers/PeersQuality.tsx
@@ -10,7 +10,7 @@ export function PeersQuality({ good }: Props) {
if (good) {
return (
-
+
Peer connections in good standing.
);
diff --git a/src/components/Peers/peers.utils.test.ts b/src/components/Peers/peers.utils.test.ts
index 74cc315..9a7b8e7 100644
--- a/src/components/Peers/peers.utils.test.ts
+++ b/src/components/Peers/peers.utils.test.ts
@@ -1,5 +1,5 @@
import { assert, describe, it } from "vitest";
-import { PeerGeo, PeerUtils } from "./peers.utils";
+import { PeerGeo, PeerNode, PeerUtils } from "./peers.utils";
describe("peers", () => {
it("sorts by boolean", async () => {
@@ -41,14 +41,14 @@ describe("peers", () => {
});
it("adds a new pin", async () => {
- const latLng = { latitude: 0, longitude: 0 } as any
- const values = PeerUtils.incPin([], latLng)
+ const latLng = { latitude: 0, longitude: 0 }
+ const values = PeerUtils.incPin([], latLng as PeerNode & PeerGeo)
assert.deepEqual(values, [[latLng, 1]]);
});
it("increments an existing pin", async () => {
- const latLng = { lat: 0, lng: 0 } as any
+ const latLng = { lat: 0, lng: 0 } as unknown as PeerNode & PeerGeo
const values = PeerUtils.incPin([[latLng, 1]], latLng)
assert.deepEqual(values, [[latLng, 2]]);
diff --git a/src/components/Peers/peers.utils.ts b/src/components/Peers/peers.utils.ts
index bfd6c05..799e4d5 100644
--- a/src/components/Peers/peers.utils.ts
+++ b/src/components/Peers/peers.utils.ts
@@ -55,6 +55,14 @@ export const PeerUtils = {
return (actives / total) * 180
},
+ calcularePercent: (peers: PeerNode[]) => {
+ const actives = PeerUtils.countActives(peers);
+ const total = peers.length || 1;
+
+ return (actives / total) * 100
+ },
+
+
isGoodQuality(actives: number) {
return actives > 0
},
diff --git a/src/components/Purchase/PurchasesTable.tsx b/src/components/Purchase/PurchasesTable.tsx
index e8553a1..c776850 100644
--- a/src/components/Purchase/PurchasesTable.tsx
+++ b/src/components/Purchase/PurchasesTable.tsx
@@ -114,7 +114,7 @@ export function PurchasesTable() {
if (isPending) {
return (
-
+
);
diff --git a/src/components/Range/Range.css b/src/components/Range/Range.css
deleted file mode 100644
index d9e9919..0000000
--- a/src/components/Range/Range.css
+++ /dev/null
@@ -1,145 +0,0 @@
-.range {
- /* width: 100%;
- accent-color: var(--codex-color-primary);
- height: 1px;
- outline: none; */
- --val: 50;
- width: 100%;
- margin: 1.5rem 0;
-}
-
-.range-labels {
- display: flex;
- justify-content: space-between;
-}
-
-@property --c {
- syntax: "
";
- inherits: true;
- initial-value: #0000;
-}
-
-.glow {
- --c: rgb(0, 255, 255, calc(0.25 + var(--val) / 125));
- --c: hsl(160deg 80% 50% / calc(0.25 + var(--val) / 125));
- -webkit-appearance: none;
- -moz-appearance: none;
- appearance: none;
- background: transparent;
- cursor: pointer;
- position: relative;
-}
-
-.glow::before {
- content: "";
- position: absolute;
- top: 0;
- left: 0;
- width: calc((var(--val) - 1) * 1%);
- min-width: 0.5em;
- height: 100%;
- background: var(--c);
- box-shadow:
- 0 0 0.2em 0 hsl(0 0% 0%) inset,
- -0.1em 0.1em 0.1em -0.1em hsl(0 0% 100% / 0.5),
- 0 0 calc(1em + 0.001em * var(--val)) calc(0.1em + 0.00025em * var(--val))
- var(--c);
- border-radius: 1em 0 0 1em;
- aopacity: calc(20% + var(--val) * 1%);
-}
-
-/***** Track Styles *****/
-/***** Chrome, Safari, Opera, and Edge Chromium *****/
-.glow::-webkit-slider-runnable-track {
- box-shadow:
- 0 0 0.2em 0 hsl(0 0% 0%) inset,
- -0.1em 0.1em 0.1em -0.1em hsl(0 0% 100% / 0.5);
- background: linear-gradient(to bottom right, #0001, #0000), #343133;
- border-radius: 1em;
- height: 1em;
-}
-
-/******** Firefox ********/
-.glow::-moz-range-track {
- box-shadow:
- 0 0 2px 0 hsl(0 0% 0%) inset,
- -1px 1px 1px -1px hsl(0 0% 100% / 0.5);
- background:
- linear-gradient(var(--c) 0 0) 0 0 / calc(var(--val) * 1%) 100% no-repeat,
- linear-gradient(to bottom right, #0001, #0000),
- #343133;
- border-radius: 1em;
- height: 1em;
-}
-
-/***** Thumb Styles *****/
-/***** Chrome, Safari, Opera, and Edge Chromium *****/
-.glow::-webkit-slider-thumb {
- --d: var(--c);
- --d: rgb(from var(--c) r g b / calc(0.35 * var(--val) * 1%));
- -webkit-appearance: none; /* Override default look */
- appearance: none;
- background-color: #5cd5eb;
- transform: translateY(calc(-50% + 0.5em));
- width: 4em;
- aspect-ratio: 1;
- background: red;
- border-radius: 50%;
- background:
- radial-gradient(
- farthest-side,
- #0000 22.5%,
- var(--d) 0,
- #0000 calc(var(--val) * 0.75%)
- )
- 50% 50% / 100% 100% no-repeat,
- radial-gradient(#0000 15%, #343133 16%, #545153 20%),
- repeating-linear-gradient(#0000 0 10%, #0002 0 20%) 50% 50% / 25% 25%
- no-repeat,
- repeating-linear-gradient(90deg, #0000 0 10%, #0002 0 20%) 50% 50% / 25% 25%
- no-repeat,
- radial-gradient(var(--c) 17%, #0000 0),
- #545153;
- box-shadow:
- inset -0.15em -0.15em 0.2em #0008,
- inset 0.15em 0.15em 0.2em #ffffff22,
- inset calc(var(--val) * 1em / 500) 0em calc(var(--val) * 1em / 500)
- calc(var(--val) * -1em / 700) var(--c),
- 0.25em 0.25em 0.5em #0006,
- calc(0.0125em * var(--val)) calc(0.005em * var(--val))
- calc(0.02em * var(--val)) calc(-0.01em * var(--val)) #000a;
- border-radius: 50%;
-}
-
-/***** Firefox *****/
-.glow::-moz-range-thumb {
- /* --d: var(--c);
- --d: rgb(from var(--c) r g b / calc(0.35 * var(--val) * 1%)); */
- border: none; /*Removes extra border that FF applies*/
- -webkit-appearance: none; /* Override default look */
- appearance: none;
- background-color: #5cd5eb;
- width: 4em;
- height: 4em;
- aspect-ratio: 1;
- background: red;
- border-radius: 50%;
- background:
-/* radial-gradient(farthest-side, #0000 22.5%, var(--d) 0, #0000 calc(var(--val) * 0.75%)) 50% 50% / 100% 100% no-repeat, */
- radial-gradient(#0000 15%, #343133 16%, #545153 20%),
- repeating-linear-gradient(#0000 0 10%, #0002 0 20%) 50% 50% / 25% 25%
- no-repeat,
- repeating-linear-gradient(90deg, #0000 0 10%, #0002 0 20%) 50% 50% / 25% 25%
- no-repeat,
- radial-gradient(var(--c) 17%, #0000 0),
- #545153;
- box-shadow:
- inset -0.15em -0.15em 0.2em #0008,
- inset 0.15em 0.15em 0.2em #ffffff22,
- inset calc(var(--val) * 1em / 500) 0em calc(var(--val) * 1em / 500)
- calc(var(--val) * -1em / 700) var(--c),
- 0.25em 0.25em 0.5em #0006,
- calc(0.015em * var(--val)) calc(0.005em * var(--val))
- calc(0.02em * var(--val)) calc(-0.01em * var(--val)) #0008;
- border-radius: 50%;
-}
diff --git a/src/components/Range/Range.tsx b/src/components/Range/Range.tsx
deleted file mode 100644
index e94415d..0000000
--- a/src/components/Range/Range.tsx
+++ /dev/null
@@ -1,51 +0,0 @@
-import { ChangeEvent, FormEvent, useState } from "react";
-import "./Range.css";
-
-type Props = {
- label?: string;
- max: number;
- labels: string[];
- className?: string;
- onChange: (e: ChangeEvent) => void;
- defaultValue?: number | string;
- value?: number | string;
-};
-
-export function Range({
- label,
- max,
- onChange,
- defaultValue,
- value,
- className = "",
-}: Props) {
- const [val, setVal] = useState(value);
-
- const onInput = (e: FormEvent) => {
- setVal(parseInt(e.currentTarget.value, 10));
- };
-
- return (
-
- {label}
-
- {/*
- {labels.map((l) => (
-
- {l}
-
- ))}
-
*/}
-
- );
-}
diff --git a/src/components/RequireAssitance/RequireAssitance.css b/src/components/RequireAssitance/RequireAssitance.css
index db48d0e..f109613 100644
--- a/src/components/RequireAssitance/RequireAssitance.css
+++ b/src/components/RequireAssitance/RequireAssitance.css
@@ -1,14 +1,14 @@
.require-assistance {
- background-color: #0a1410;
+ background-color: rgb(10, 20, 16);
box-sizing: border-box;
padding: 16px;
border-radius: 16px;
- border-left: 4px solid #6ccc93;
+ border-left: 4px solid rgb(108, 204, 147);
height: 144px;
display: flex;
flex-direction: column;
justify-content: space-around;
- width: 500px;
+ /* width: 500px; */
flex: 1 1 auto;
cursor: pointer;
text-decoration: none;
@@ -21,7 +21,7 @@
font-weight: 400;
line-height: 20px;
text-align: left;
- color: #6ccc93;
+ color: rgb(108, 204, 147);
}
h6 {
@@ -31,7 +31,7 @@
line-height: 19.36px;
letter-spacing: 0.01em;
text-align: left;
- color: #7bfbaf;
+ color: rgb(123, 251, 175);
margin-bottom: 4px;
}
}
diff --git a/src/components/RouteErrorBoundary/RouteErrorBoundary.tsx b/src/components/RouteErrorBoundary/RouteErrorBoundary.tsx
new file mode 100644
index 0000000..7c06203
--- /dev/null
+++ b/src/components/RouteErrorBoundary/RouteErrorBoundary.tsx
@@ -0,0 +1,19 @@
+import { Placeholder } from "@codex-storage/marketplace-ui-components";
+import { useRouteError } from "react-router-dom";
+import ErrorCircleIcon from "../../assets/icons/error-circle.svg?react";
+
+export function RouteErrorBoundary() {
+ const error = useRouteError();
+
+ const message = Object.prototype.hasOwnProperty.call(error, "message")
+ ? (error as { message: string }).message
+ : `${error}`;
+
+ return (
+ }
+ title="Error"
+ subtitle={""}
+ message={message}>
+ );
+}
diff --git a/src/components/StorageRequestSetup/Commitment.css b/src/components/StorageRequestSetup/Commitment.css
new file mode 100644
index 0000000..75837d4
--- /dev/null
+++ b/src/components/StorageRequestSetup/Commitment.css
@@ -0,0 +1,7 @@
+.commitment {
+ --codex-input-group-background-color: transparent;
+
+ span {
+ right: 155px;
+ }
+}
diff --git a/src/components/StorageRequestSetup/Commitment.tsx b/src/components/StorageRequestSetup/Commitment.tsx
new file mode 100644
index 0000000..74c3b50
--- /dev/null
+++ b/src/components/StorageRequestSetup/Commitment.tsx
@@ -0,0 +1,70 @@
+import { InputGroup, Tooltip } from "@codex-storage/marketplace-ui-components";
+import "../CardNumbers/CardNumbers.css";
+import "./Commitment.css";
+
+import { ChangeEvent, useState } from "react";
+import { classnames } from "../../utils/classnames";
+import InfoIcon from "../../assets/icons/info.svg?react";
+import { attributes } from "../../utils/attributes";
+
+type Props = {
+ unit: "months" | "days";
+ value: string;
+ onChange: (value: string, unit: "months" | "days") => void;
+ onValidation?: (value: string) => string;
+};
+
+const TESTNET_MAX_VALUE = 7;
+
+export function Commitment({ unit, value, onValidation, onChange }: Props) {
+ const [error, setError] = useState("");
+
+ const onValueChange = (e: ChangeEvent) => {
+ onValueOrUnitChange(e.currentTarget.value, unit);
+ };
+ const onUnitChange = (e: ChangeEvent) => {
+ onValueOrUnitChange(value, e.currentTarget.value as "months" | "days");
+ };
+
+ const onValueOrUnitChange = (val: string, unit: "months" | "days") => {
+ onChange(val, unit);
+
+ const msg = onValidation?.(val);
+
+ if (msg) {
+ setError(msg);
+ return;
+ }
+
+ setError("");
+ };
+
+ return (
+
+
+
+
+
+
+ {"Contract duration"}
+
+ );
+}
diff --git a/src/components/StorageRequestSetup/StorageRequestAvailability.css b/src/components/StorageRequestSetup/StorageRequestAvailability.css
deleted file mode 100644
index 8768c3d..0000000
--- a/src/components/StorageRequestSetup/StorageRequestAvailability.css
+++ /dev/null
@@ -1,5 +0,0 @@
-.storageRequestAvailability {
- flex: 1;
- display: flex;
- align-items: center;
-}
diff --git a/src/components/StorageRequestSetup/StorageRequestAvailability.tsx b/src/components/StorageRequestSetup/StorageRequestAvailability.tsx
deleted file mode 100644
index c658d3d..0000000
--- a/src/components/StorageRequestSetup/StorageRequestAvailability.tsx
+++ /dev/null
@@ -1,82 +0,0 @@
-import { ChangeEvent, useEffect, useRef, useState } from "react";
-import "./StorageRequestAvailability.css";
-import { WebStorage } from "../../utils/web-storage";
-import { StorageAvailabilityUnit, StorageAvailabilityValue } from "./types";
-import { InputGroup } from "@codex-storage/marketplace-ui-components";
-
-type Props = {
- onToggleNext: (next: boolean) => void;
-};
-
-export function StorageRequestAvailability({ onToggleNext }: Props) {
- const [unit, setUnit] = useState("minutes");
- const [value, setValue] = useState(0);
- const cache = useRef(null);
-
- useEffect(() => {
- if (cache.current) {
- return;
- }
-
- WebStorage.get("storage-request-step-2").then(
- (val) => {
- if (val) {
- cache.current = val;
- setUnit(val.unit);
- setValue(val.value);
- onToggleNext(true);
- }
- }
- );
-
- return () => {
- WebStorage.set("storage-request-step-2", cache.current);
- };
- }, [onToggleNext]);
-
- const onChange = (e: ChangeEvent) => {
- if (!cache.current) {
- cache.current = { unit: "months", value: 0 };
- }
-
- cache.current.value = parseInt(e.currentTarget.value, 10);
-
- setValue(parseInt(e.currentTarget.value, 10));
- onToggleNext(!!e.currentTarget.value);
- };
-
- const onUnitChange = (e: ChangeEvent) => {
- if (!cache.current) {
- cache.current = { unit: "months", value: 0 };
- }
-
- setUnit(e.currentTarget.value as StorageAvailabilityUnit);
- cache.current.unit = e.currentTarget.value as StorageAvailabilityUnit;
- };
-
- return (
- <>
-
- How long do you want to store your file?
-
-
-
- >
- );
-}
diff --git a/src/components/StorageRequestSetup/StorageRequestCreate.css b/src/components/StorageRequestSetup/StorageRequestCreate.css
index 2b746c1..6c6a2ec 100644
--- a/src/components/StorageRequestSetup/StorageRequestCreate.css
+++ b/src/components/StorageRequestSetup/StorageRequestCreate.css
@@ -1,9 +1,4 @@
.storage-request {
- .modal dialog {
- width: 80%;
- max-width: 100% !important;
- }
-
header {
display: flex;
align-items: flex-start;
@@ -16,7 +11,7 @@
font-weight: 400;
line-height: 16px;
text-align: left;
- color: #969696;
+ color: rgba(150, 150, 150, 1);
}
}
diff --git a/src/components/StorageRequestSetup/StorageRequestCreate.tsx b/src/components/StorageRequestSetup/StorageRequestCreate.tsx
index 8d63361..3158d41 100644
--- a/src/components/StorageRequestSetup/StorageRequestCreate.tsx
+++ b/src/components/StorageRequestSetup/StorageRequestCreate.tsx
@@ -13,17 +13,17 @@ import {
import { StorageRequestSuccess } from "./StorageRequestSuccess";
import { Times } from "../../utils/times";
import { useStorageRequestMutation } from "./useStorageRequestMutation";
-import { Plus } from "lucide-react";
import "./StorageRequestCreate.css";
import { StorageRequestError } from "./StorageRequestError";
import PurchaseIcon from "../../assets/icons/purchase.svg?react";
+import PlusIcon from "../../assets/icons/plus.svg?react";
const CONFIRM_STATE = 2;
const defaultStorageRequest: StorageRequest = {
cid: "",
- availabilityUnit: "months",
availability: 1,
+ availabilityUnit: "days",
tolerance: 1,
proofProbability: 1,
nodes: 3,
@@ -43,7 +43,7 @@ export function StorageRequestCreate() {
useEffect(() => {
Promise.all([
WebStorage.get("storage-request-step"),
- WebStorage.get("storage-request"),
+ WebStorage.get("storage-request-3"),
]).then(([s, data]) => {
if (s) {
dispatch({
@@ -83,11 +83,11 @@ export function StorageRequestCreate() {
WebStorage.set("storage-request-step", step);
if (step == CONFIRM_STATE) {
- const { availabilityUnit, availability, expiration, ...rest } =
+ const { availability, availabilityUnit, expiration, ...rest } =
storageRequest;
mutateAsync({
...rest,
- duration: Times.toSeconds(availability, availabilityUnit),
+ duration: Math.trunc(availability * Times.value(availabilityUnit)),
expiry: expiration * 60,
});
} else {
@@ -101,7 +101,7 @@ export function StorageRequestCreate() {
const onStorageRequestChange = (data: Partial) => {
const val = { ...storageRequest, ...data };
- WebStorage.set("storage-request", val);
+ WebStorage.set("storage-request-3", val);
setStorageRequest(val);
};
@@ -121,7 +121,7 @@ export function StorageRequestCreate() {
@@ -283,22 +276,19 @@ export function StorageRequestReview({
-
+ onValidation={isInvalidAvailability}>
+ title="Penality tokens">
+ title="Reward tokens for hosts">
@@ -321,14 +311,9 @@ export function StorageRequestReview({
unit={"Expiration"}
value={storageRequest.expiration.toString()}
onChange={onExpirationChange}
- className="storageRequestReview-expiration"
onValidation={isInvalidNumber}
title="Request expiration in minutes">
-
}
- title="Warning"
- variant="warning"
- className="storageRequestReview-alert">
+
} title="Warning" variant="warning">
If no suitable hosts are found for the CID{" "}
{Strings.shortId(storageRequest.cid)} matching your storage
requirements, you will incur a charge a small amount of tokens.
diff --git a/src/components/StorageRequestSetup/StorageRequestSetup.css b/src/components/StorageRequestSetup/StorageRequestSetup.css
deleted file mode 100644
index a836b75..0000000
--- a/src/components/StorageRequestSetup/StorageRequestSetup.css
+++ /dev/null
@@ -1,78 +0,0 @@
-.storageRequest-title {
- margin-bottom: 0.5rem;
- font-weight: 600;
-}
-
-.storageRequest-intro {
- margin-bottom: 0.5rem;
-}
-
-.storageRequest-steps {
- margin-top: 0.5rem;
- display: flex;
- flex-direction: column;
- gap: 0.75rem;
-}
-
-.storageRequest-step {
- display: flex;
- align-items: center;
- gap: 0.75rem;
-}
-
-.storageRequest-stepText {
- flex: 1;
-}
-
-.storageRequest-stepCompleted {
- text-decoration: line-through;
- mix-blend-mode: difference;
-}
-
-.storageRequest-stepDisabled {
- background-color: var(--codex-border-color);
- color: var(--codex-text-disabled);
- border: none;
- border-radius: var(--codex-border-radius);
- padding: 0.25rem 0.75rem;
- opacity: 0.7;
-}
-
-.storageRequest-step-action {
- background-color: var(--codex-border-color);
- color: var(--codex-text-disabled);
- border: none;
- border-radius: var(--codex-border-radius);
- padding: 0.25rem 0.75rem;
- cursor: pointer;
- transition: opacity 0.35s;
-}
-
-.storageRequest-step-action:hover {
- opacity: 0.8;
-}
-
-.storageRequest-title {
- font-size: 1rem;
- font-weight: 600;
- width: 100%;
- display: inline-block;
- margin-bottom: 0.75rem;
- text-align: center;
-}
-
-@media (max-width: 800px) {
- .storageRequest {
- .stepper-body,
- .stepper {
- /* width: calc(100% - 3rem); */
- }
- }
-}
-
-@media (min-width: 801px) {
- .storageRequest {
- margin: auto;
- width: 85%;
- }
-}
diff --git a/src/components/StorageRequestSetup/StorageRequestSetup.tsx b/src/components/StorageRequestSetup/StorageRequestSetup.tsx
deleted file mode 100644
index b25a475..0000000
--- a/src/components/StorageRequestSetup/StorageRequestSetup.tsx
+++ /dev/null
@@ -1,84 +0,0 @@
-import { CircleCheck, Database, Server } from "lucide-react";
-import { ICON_SIZE } from "../../utils/constants";
-import "./StorageRequestSetup.css";
-
-export function StorageRequestSetup() {
- return (
-
-
Storage setup
-
- You need to follow these steps to start a new request storage.
-
-
- 3 of 5 completed
-
-
-
-
-
- Offers storage for sale
-
-
-
-
-
-
- Updates availability
-
-
-
-
-
-
- Get availability's reservations
-
-
-
-
-
-
- Check list of purchase IDs
-
-
-
-
-
-
- Check storage that is for sale
-
-
-
-
-
- );
-}
diff --git a/src/components/StorageRequestSetup/StorageRequestSuccess.css b/src/components/StorageRequestSetup/StorageRequestSuccess.css
index 3fe9b07..d51d1dd 100644
--- a/src/components/StorageRequestSetup/StorageRequestSuccess.css
+++ b/src/components/StorageRequestSetup/StorageRequestSuccess.css
@@ -1,7 +1,7 @@
-.storageRequestDone {
+.storage-success {
margin: auto;
-}
-.storageRequestDone-icon {
- color: var(--codex-color-primary);
+ svg {
+ color: var(--codex-color-primary);
+ }
}
diff --git a/src/components/StorageRequestSetup/StorageRequestSuccess.tsx b/src/components/StorageRequestSetup/StorageRequestSuccess.tsx
index 685c39c..70aa37e 100644
--- a/src/components/StorageRequestSetup/StorageRequestSuccess.tsx
+++ b/src/components/StorageRequestSetup/StorageRequestSuccess.tsx
@@ -1,8 +1,8 @@
import { Placeholder } from "@codex-storage/marketplace-ui-components";
-import { CircleCheck } from "lucide-react";
import "./StorageRequestSuccess.css";
import { StorageRequestComponentProps } from "./types";
import { useEffect } from "react";
+import SuccessCircleIcon from "../../assets/icons/success-circle.svg?react";
export function StorageRequestSuccess({
dispatch,
@@ -17,10 +17,10 @@ export function StorageRequestSuccess({
return (
}
- className="storageRequestDone"
+ Icon={
}
+ className="storage-success"
title="Your request is being processed."
- message=" Processing your request may take some time. Once completed, it will
+ message="Processing your request may take some time. Once completed, it will
appear in your purchase list. You can safely close this dialog.">
);
}
diff --git a/src/components/StorageRequestSetup/types.ts b/src/components/StorageRequestSetup/types.ts
index 5a64ff3..c459698 100644
--- a/src/components/StorageRequestSetup/types.ts
+++ b/src/components/StorageRequestSetup/types.ts
@@ -16,29 +16,14 @@ export type StoragePriceStepValue = {
expiration: number;
};
-export type StorageAvailabilityUnit =
- | "days"
- | "months"
- | "years"
- | "minutes"
- | "hours";
-
export type StorageAvailabilityValue = {
value: number;
- unit: StorageAvailabilityUnit;
};
-export type AvailabilityUnit =
- | "days"
- | "months"
- | "years"
- | "minutes"
- | "hours";
-
export type StorageRequest = {
cid: string;
availability: number;
- availabilityUnit: AvailabilityUnit;
+ availabilityUnit: "months" | "days";
tolerance: number;
proofProbability: number;
nodes: number;
diff --git a/src/components/StorageRequestSetup/useStorageRequestMutation.ts b/src/components/StorageRequestSetup/useStorageRequestMutation.ts
index 1c349a6..322a865 100644
--- a/src/components/StorageRequestSetup/useStorageRequestMutation.ts
+++ b/src/components/StorageRequestSetup/useStorageRequestMutation.ts
@@ -29,7 +29,7 @@ export function useStorageRequestMutation(
// }
WebStorage.delete("storage-request-step");
- WebStorage.delete("storage-request");
+ WebStorage.delete("storage-request-3");
setError(null);
diff --git a/src/components/SuccessIcon/SuccessIcon.tsx b/src/components/SuccessIcon/SuccessIcon.tsx
deleted file mode 100644
index ea06811..0000000
--- a/src/components/SuccessIcon/SuccessIcon.tsx
+++ /dev/null
@@ -1,9 +0,0 @@
-import { CircleCheck } from "lucide-react";
-
-export function SuccessIcon() {
- return (
-
-
-
- );
-}
diff --git a/src/components/TruncateCell/TruncateCell.css b/src/components/TruncateCell/TruncateCell.css
index 0ea52f5..5412d0e 100644
--- a/src/components/TruncateCell/TruncateCell.css
+++ b/src/components/TruncateCell/TruncateCell.css
@@ -1,26 +1,11 @@
-.truncateCell {
+.truncate-cell {
position: relative;
-}
-.truncateCell .tooltip:hover:after {
- left: -33%;
-}
-
-.truncateCell-point {
- height: 0.5rem;
- width: 3rem;
- border-radius: var(--codex-border-radius);
- display: inline-block;
-}
-
-.truncateCell--ellipsis {
- overflow: hidden;
- white-space: nowrap;
- text-overflow: ellipsis;
- max-width: 150px;
-}
-
-.table-tbodyTr:hover .truncateCell--ellipsis {
- white-space: unset;
- word-break: break-all;
+ small {
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ max-width: 150px;
+ display: inline-block;
+ }
}
diff --git a/src/components/TruncateCell/TruncateCell.tsx b/src/components/TruncateCell/TruncateCell.tsx
index 238a5dd..cecac0c 100644
--- a/src/components/TruncateCell/TruncateCell.tsx
+++ b/src/components/TruncateCell/TruncateCell.tsx
@@ -1,4 +1,4 @@
-import { Cell } from "@codex-storage/marketplace-ui-components";
+import { Cell, Tooltip } from "@codex-storage/marketplace-ui-components";
import "./TruncateCell.css";
type Props = {
@@ -11,11 +11,11 @@ export function TruncateCell({ value }: Props) {
}
return (
-
-
-
- {value}
-
+
+
+
+ {value}
+
|
);
diff --git a/src/components/TruncateCellRender/TruncateCellRender.tsx b/src/components/TruncateCellRender/TruncateCellRender.tsx
deleted file mode 100644
index 10d84a0..0000000
--- a/src/components/TruncateCellRender/TruncateCellRender.tsx
+++ /dev/null
@@ -1,4 +0,0 @@
-export function TruncateCellRender(cid: string) {
- const truncated = cid.slice(0, 5) + ".".repeat(5) + cid.slice(-5);
- return {truncated};
-}
diff --git a/src/components/Versions/Versions.css b/src/components/Versions/Versions.css
index 4e43756..f20e152 100644
--- a/src/components/Versions/Versions.css
+++ b/src/components/Versions/Versions.css
@@ -13,7 +13,7 @@
font-weight: 500;
line-height: 24px;
letter-spacing: -0.011em;
- color: #99a0ae;
+ color: rgb(153, 160, 174);
}
small {
diff --git a/src/components/Versions/Versions.tsx b/src/components/Versions/Versions.tsx
index 23e0357..faa5cba 100644
--- a/src/components/Versions/Versions.tsx
+++ b/src/components/Versions/Versions.tsx
@@ -13,7 +13,7 @@ export function Versions() {
return (
-
+
Client
VER. {version}
@@ -21,7 +21,7 @@ export function Versions() {
Vault
VER. {VersionsUtil.codexVersion()}
-
+
);
diff --git a/src/components/WalletLogin/WalletLogin.css b/src/components/WalletLogin/WalletLogin.css
index 2aeb48f..245e38e 100644
--- a/src/components/WalletLogin/WalletLogin.css
+++ b/src/components/WalletLogin/WalletLogin.css
@@ -3,7 +3,7 @@
display: flex;
align-items: center;
gap: 16px;
- background-color: #252525;
+ background-color: rgb(37, 37, 37);
filter: grayscale(30);
transition: filter 0.5s;
@@ -17,7 +17,7 @@
font-size: 8px;
font-weight: 700;
text-transform: uppercase;
- color: #6e6e6e;
+ color: rgb(110, 110, 110);
display: block;
font-size: 10px;
}
@@ -27,7 +27,7 @@
font-family: Inter;
font-size: 12px;
font-weight: 700;
- color: #ffffff99;
+ color: rgb(255, 255, 255, 0.6);
font-style: normal;
font-size: 16px;
}
@@ -45,7 +45,7 @@
font-weight: 700;
line-height: 10px;
text-align: left;
- color: #3ee089;
+ color: rgb(62, 224, 137);
font-style: normal;
}
@@ -54,7 +54,7 @@
font-size: 10px;
font-weight: 700;
line-height: 10px;
- color: #6e6e6e;
+ color: rgb(110, 110, 110);
cursor: pointer;
}
}
diff --git a/src/components/Welcome/WelcomeCard.css b/src/components/Welcome/WelcomeCard.css
index baa2061..8ba9ed1 100644
--- a/src/components/Welcome/WelcomeCard.css
+++ b/src/components/Welcome/WelcomeCard.css
@@ -2,7 +2,7 @@
display: flex;
flex-direction: column;
flex: 1 1 50%;
- min-width: 420px;
+ /* min-width: 420px; */
.card {
position: relative;
@@ -11,7 +11,7 @@
> div {
padding: 16px;
- background-color: #141414;
+ background-color: rgb(20, 20, 20);
flex: 1;
display: flex;
flex-direction: column;
@@ -40,7 +40,7 @@
font-weight: 400;
line-height: 14px;
text-align: left;
- color: #7f948d;
+ color: rgb(127, 148, 141);
}
div {
@@ -56,12 +56,22 @@
line-height: 19.36px;
letter-spacing: 0.01em;
text-align: left;
- color: #7bfbaf;
+ color: rgb(123, 251, 175);
+ display: flex;
+ align-items: center;
display: flex;
align-items: center;
+ &:first-child {
+ border-bottom: 1px solid rgb(123, 251, 175);
+ text-decoration: none;
+ gap: 8px;
+ }
+
&:nth-child(2) {
gap: 12px;
+ padding-bottom: 2px;
+ text-underline-offset: 5px;
}
}
}
@@ -69,4 +79,10 @@
footer {
margin-top: 32px;
}
+
+ @media (max-width: 600px) {
+ img {
+ display: none;
+ }
+ }
}
diff --git a/src/components/Welcome/WelcomeCard.tsx b/src/components/Welcome/WelcomeCard.tsx
index 77f6357..76dcae2 100644
--- a/src/components/Welcome/WelcomeCard.tsx
+++ b/src/components/Welcome/WelcomeCard.tsx
@@ -1,6 +1,4 @@
import "./WelcomeCard.css";
-import { Link } from "@tanstack/react-router";
-import { ArrowRight } from "lucide-react";
import { Alert } from "@codex-storage/marketplace-ui-components";
import { useEffect, useRef, useState } from "react";
import { classnames } from "../../utils/classnames";
@@ -8,7 +6,9 @@ import Logotype from "../../assets/icons/logotype.svg?react";
import Logo from "../../assets/icons/logo.svg?react";
import DiscordIcon from "../../assets/icons/discord.svg?react";
import WarningIcon from "../../assets/icons/warning.svg?react";
+import ArrowIcon from "../../assets/icons/arrow-onboarding.svg?react";
import { WelcomeImage } from "./WelcomeImage";
+import { Link } from "react-router-dom";
export function WelcomeCard() {
const ref = useRef (null);
@@ -47,11 +47,11 @@ export function WelcomeCard() {
diff --git a/src/hooks/port-forwarding.util.ts b/src/hooks/port-forwarding.util.ts
index 6833ca9..0cce763 100644
--- a/src/hooks/port-forwarding.util.ts
+++ b/src/hooks/port-forwarding.util.ts
@@ -1,8 +1,14 @@
import { CodexDebugInfo, SafeValue, CodexError } from "@codex-storage/sdk-js"
export const PortForwardingUtil = {
- check: (port: number) => fetch(import.meta.env.VITE_GEO_IP_URL + "/port/" + port)
- .then((res) => res.json()),
+ check: (ip: string, port: number) => {
+ const headers = {
+ "X-Real-IP-Custom": ip
+ }
+
+ return fetch(import.meta.env.VITE_GEO_IP_URL + "/port/" + port, { headers })
+ .then((res) => res.json())
+ },
getTcpPort(info: CodexDebugInfo): SafeValue {
if (info.addrs.length === 0) {
diff --git a/src/hooks/useMobile.ts b/src/hooks/useMobile.ts
new file mode 100644
index 0000000..99305e7
--- /dev/null
+++ b/src/hooks/useMobile.ts
@@ -0,0 +1,19 @@
+import { useEffect, useState } from "react";
+
+export const useIsMobile = () => {
+ const [isMobile, setIsMobile] = useState(window.innerWidth <= 800);
+
+ const checkIsMobile = () => {
+ setIsMobile(window.innerWidth <= 800);
+ };
+
+ useEffect(() => {
+ window.addEventListener('resize', checkIsMobile);
+
+ return () => {
+ window.removeEventListener('resize', checkIsMobile);
+ };
+ }, []);
+
+ return isMobile;
+};
\ No newline at end of file
diff --git a/src/hooks/usePersistence.tsx b/src/hooks/usePersistence.tsx
index b66d68d..7546f11 100644
--- a/src/hooks/usePersistence.tsx
+++ b/src/hooks/usePersistence.tsx
@@ -9,7 +9,7 @@ export function usePersistence(isCodexOnline: boolean) {
queryKey: [],
queryFn: async () => {
return CodexSdk.marketplace()
- .purchases()
+ .activeSlots()
.then((data) => Promises.rejectOnError(data, report));
},
diff --git a/src/hooks/usePortForwarding.tsx b/src/hooks/usePortForwarding.tsx
index f77beb1..8782029 100644
--- a/src/hooks/usePortForwarding.tsx
+++ b/src/hooks/usePortForwarding.tsx
@@ -2,6 +2,7 @@ import { useQuery } from "@tanstack/react-query";
import { Errors } from "../utils/errors";
import { CodexDebugInfo } from "@codex-storage/sdk-js";
import { PortForwardingUtil } from "./port-forwarding.util";
+import { HealthCheckUtils } from "../components/HealthChecks/health-check.utils";
type PortForwardingResponse = { reachable: boolean };
@@ -9,12 +10,21 @@ export function usePortForwarding(info: CodexDebugInfo | undefined) {
const { data, isFetching, refetch } = useQuery({
queryFn: (): Promise => {
const port = PortForwardingUtil.getTcpPort(info!);
+
if (port.error) {
Errors.report(port);
return Promise.resolve({ reachable: false });
} else {
- return PortForwardingUtil.check(port.data).catch((e) =>
- Errors.report(e)
+ const ip = HealthCheckUtils.extractAnnounceAddresses(
+ info!.announceAddresses
+ );
+ if (ip.error) {
+ Errors.report(ip);
+ return Promise.resolve({ reachable: false });
+ }
+
+ return PortForwardingUtil.check(ip.data, port.data).catch(
+ Errors.report
);
}
},
diff --git a/src/index.css b/src/index.css
index a144b1c..1ed3ae2 100644
--- a/src/index.css
+++ b/src/index.css
@@ -1,7 +1,3 @@
-@import url(./assets/css/container.css);
-@import url(./assets/css/indicator.css);
-@import url(./assets/css/text.css);
-
@font-face {
font-family: Inter;
font-weight: 300 800;
@@ -15,38 +11,12 @@
}
:root {
- --codex-background: #1c1c1c;
- --codex-color: white;
- --codex-color-contrast: #f8f8f8;
- --codex-color-error: 204, 108, 108;
- --codex-color-error-hexa: #cc6c6c;
- --codex-color-warning: 234, 179, 8;
- --codex-color-success: 20, 184, 166;
- --codex-color-blue: 30, 64, 175;
- --codex-color-grey: 170, 170, 170;
- --codex-color-primary: #6fcb94;
- --codex-color-primary-rgb: 193, 240, 164;
- --codex-color-primary-variant: #c1f0a4cc;
- --codex-color-on-primary: #333;
- --codex-color-disabled: #717171;
- --codex-color-light: rgb(150 150 150);
- --codex-border-color: #96969633;
- --codex-input-border-color: #494949;
- --codex-background-secondary: rgb(38 38 38);
- --codex-highlight-color: #2f2f2f;
- --codex-background-light: rgb(64 64 64);
- --codex-background-backdrop: rgba(70, 70, 70, 0.75);
- --codex-border-radius: 0.5rem;
- --codex-font-size: 14px;
+ --codex-color-primary: rgb(111, 203, 148);
+ --codex-color-error: rgb(251, 55, 72);
--codex-font-family: Inter, ui-sans-serif, system-ui, -apple-system,
BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans,
sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol,
Noto Color Emoji;
- --codex-input-label-color: #7b7b7b;
- --codex-input-border-color: #494949;
- --codex-input-background: #232323;
- --codex-input-color-error: #fb3748;
- --codex-row-gap: 16px;
-webkit-tap-highlight-color: transparent;
-webkit-text-size-adjust: 100%;
@@ -55,47 +25,46 @@
font-feature-settings: normal;
font-variation-settings: normal;
tab-size: 4;
- font-size: 1.15rem;
- font-size: var(--codex-font-size);
+ font-size: 14px;
color-scheme: dark;
- color: var(--codex-color);
- background: #000000; /* Fallback color */
+ color: white;
+ background: rgb(0, 0, 0); /* Fallback color */
background: -webkit-linear-gradient(
246.02deg,
- #000000 30.36%,
- #222222 91.05%
+ rgb(0, 0, 0) 30.36%,
+ rgb(34, 34, 34) 91.05%
); /* For Safari and older Chrome */
background: -moz-linear-gradient(
246.02deg,
- #000000 30.36%,
- #222222 91.05%
+ rgb(0, 0, 0) 30.36%,
+ rgb(34, 34, 34) 91.05%
); /* For older Firefox */
background: linear-gradient(
246.02deg,
- #000000 30.36%,
- #222222 91.05%
+ rgb(0, 0, 0) 30.36%,
+ rgb(34, 34, 34) 91.05%
); /* Standard syntax */
}
::selection {
background: var(--codex-color-primary);
- color: #3a0b5a;
+ color: rgb(58, 11, 90);
}
::-webkit-scrollbar {
height: 12px;
width: 8px;
- background: #aaa;
+ background: rgb(170, 170, 170);
}
::-webkit-scrollbar-thumb {
- background: #444;
+ background: rgb(68, 68, 68);
-webkit-border-radius: 1ex;
-webkit-box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.75);
}
::-webkit-scrollbar-corner {
- background: #000;
+ background: rgb(0, 0, 0);
}
html {
@@ -183,14 +152,14 @@ input:-webkit-autofill:active {
}
.gap {
- gap: var(--codex-row-gap);
+ gap: 16px;
}
.card {
- border: 1px solid #96969633;
+ border: 1px solid rgba(150, 150, 150, 0.2);
border-radius: 16px;
padding: 16px;
- background-color: #232323;
+ background-color: rgb(35, 35, 35);
> header {
display: flex;
@@ -200,7 +169,7 @@ input:-webkit-autofill:active {
margin-bottom: 16px;
svg {
- color: #969696;
+ color: rgba(150, 150, 150, 1);
}
> div {
diff --git a/src/main.tsx b/src/main.tsx
index 9d687a8..0fe4066 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -1,19 +1,26 @@
-import {
- ErrorComponentProps,
- RouterProvider,
- createRouter,
-} from "@tanstack/react-router";
import { StrictMode } from "react";
-import ReactDOM from "react-dom/client";
import "./index.css";
-
+import { render } from "preact";
// Import the generated route tree
-import App from "./App.tsx";
-import { routeTree } from "./routeTree.gen";
-import { Failure } from "@codex-storage/marketplace-ui-components";
import * as Sentry from "@sentry/react";
import { CodexSdk } from "./sdk/codex";
-import { ErrorPlaceholder } from "./components/ErrorPlaceholder/ErrorPlaceholder.tsx";
+import { OnBoardingRoute } from "./routes/onboarding.tsx";
+import { createBrowserRouter, RouterProvider } from "react-router-dom";
+import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
+import { OnBoardingNameRoute } from "./routes/onboarding-name.tsx";
+import { OnBoardingChecksRoute } from "./routes/onboarding-checks.tsx";
+import { Root } from "./routes/root.tsx";
+import { DashboardRoute } from "./routes/dashboard/dashboard.tsx";
+import { WalletRoute } from "./routes/dashboard/wallet.tsx";
+import { FilesRoute } from "./routes/dashboard/files.tsx";
+import { PurchasesRoute } from "./routes/dashboard/purchases.tsx";
+import { AvailabilitiesRoute } from "./routes/dashboard/availabilities.tsx";
+import { PeersRoute } from "./routes/dashboard/peers.tsx";
+import { LogsRoute } from "./routes/dashboard/logs.tsx";
+import { SettingsRoute } from "./routes/dashboard/settings.tsx";
+import { HelpRoute } from "./routes/dashboard/help.tsx";
+import { DisclaimerRoute } from "./routes/dashboard/disclaimer.tsx";
+import { RouteErrorBoundary } from "./components/RouteErrorBoundary/RouteErrorBoundary.tsx";
if (import.meta.env.PROD && !import.meta.env.CI) {
Sentry.init({
@@ -39,48 +46,85 @@ if (import.meta.env.PROD && !import.meta.env.CI) {
});
}
-// Create a new router instance
-const router = createRouter({
- routeTree,
- defaultPreload: "viewport",
- defaultNotFoundComponent: () => {
- return (
- {}}
- />
- );
+const router = createBrowserRouter([
+ {
+ path: "/",
+ element: ,
+ errorElement: ,
},
- defaultErrorComponent:
- () =>
- ({ error }: ErrorComponentProps) => (
-
- ),
-});
+ {
+ path: "/onboarding-name",
+ element: ,
+ errorElement: ,
+ },
+ {
+ path: "/onboarding-checks",
+ element: ,
+ errorElement: ,
+ },
+ {
+ path: "/dashboard",
+ element: ,
+ errorElement: ,
+ children: [
+ {
+ path: "",
+ element: ,
+ },
+ {
+ path: "wallet",
+ element: ,
+ },
+ {
+ path: "files",
+ element: ,
+ },
+ {
+ path: "purchases",
+ element: ,
+ },
+ {
+ path: "availabilities",
+ element: ,
+ },
+ {
+ path: "peers",
+ element: ,
+ },
+ {
+ path: "logs",
+ element: ,
+ },
+ {
+ path: "settings",
+ element: ,
+ },
+ {
+ path: "help",
+ element: ,
+ },
+ {
+ path: "disclaimer",
+ element: ,
+ },
+ ],
+ },
+]);
-// Register the router instance for type safety
-declare module "@tanstack/react-router" {
- interface Register {
- router: typeof router;
- }
-}
+const queryClient = new QueryClient();
// Render the app
const rootElement = document.getElementById("root")!;
if (rootElement) {
- const root = ReactDOM.createRoot(rootElement);
-
CodexSdk.load().then(() => {
- root.render(
+ render(
-
+
-
-
+
+ ,
+ rootElement
);
});
}
diff --git a/src/proxy.ts b/src/proxy.ts
index 84419ed..28be468 100644
--- a/src/proxy.ts
+++ b/src/proxy.ts
@@ -5,7 +5,6 @@ import {
SafeValue,
} from "@codex-storage/sdk-js";
import { CodexSdk as Sdk } from "./sdk/codex";
-import { PortForwardingUtil as PUtil } from "./hooks/port-forwarding.util";
import { WebStorage } from "./utils/web-storage";
class CodexDataMock extends CodexData {
@@ -142,13 +141,3 @@ export const CodexSdk = {
};
-export const PortForwardingUtil = {
- ...PUtil,
- check: (port: number) => {
- if (import.meta.env.CI) {
- return Promise.resolve({ reachable: true })
- }
-
- return PUtil.check(port)
- }
-}
\ No newline at end of file
diff --git a/src/routeTree.gen.ts b/src/routeTree.gen.ts
deleted file mode 100644
index d5991c6..0000000
--- a/src/routeTree.gen.ts
+++ /dev/null
@@ -1,614 +0,0 @@
-/* prettier-ignore-start */
-
-/* eslint-disable */
-
-// @ts-nocheck
-
-// noinspection JSUnusedGlobalSymbols
-
-// This file is auto-generated by TanStack Router
-
-// Import Routes
-
-import { Route as rootRoute } from './routes/__root'
-import { Route as OnboardingNameImport } from './routes/onboarding-name'
-import { Route as OnboardingChecksImport } from './routes/onboarding-checks'
-import { Route as DashboardImport } from './routes/dashboard'
-import { Route as IndexImport } from './routes/index'
-import { Route as DashboardIndexImport } from './routes/dashboard/index'
-import { Route as DashboardWalletImport } from './routes/dashboard/wallet'
-import { Route as DashboardSettingsImport } from './routes/dashboard/settings'
-import { Route as DashboardRequestsImport } from './routes/dashboard/requests'
-import { Route as DashboardPurchasesImport } from './routes/dashboard/purchases'
-import { Route as DashboardPeersImport } from './routes/dashboard/peers'
-import { Route as DashboardNodesImport } from './routes/dashboard/nodes'
-import { Route as DashboardLogsImport } from './routes/dashboard/logs'
-import { Route as DashboardHelpImport } from './routes/dashboard/help'
-import { Route as DashboardFilesImport } from './routes/dashboard/files'
-import { Route as DashboardFavoritesImport } from './routes/dashboard/favorites'
-import { Route as DashboardDisclaimerImport } from './routes/dashboard/disclaimer'
-import { Route as DashboardDeviceImport } from './routes/dashboard/device'
-import { Route as DashboardAvailabilitiesImport } from './routes/dashboard/availabilities'
-import { Route as DashboardAnalyticsImport } from './routes/dashboard/analytics'
-import { Route as DashboardAboutImport } from './routes/dashboard/about'
-
-// Create/Update Routes
-
-const OnboardingNameRoute = OnboardingNameImport.update({
- id: '/onboarding-name',
- path: '/onboarding-name',
- getParentRoute: () => rootRoute,
-} as any)
-
-const OnboardingChecksRoute = OnboardingChecksImport.update({
- id: '/onboarding-checks',
- path: '/onboarding-checks',
- getParentRoute: () => rootRoute,
-} as any)
-
-const DashboardRoute = DashboardImport.update({
- id: '/dashboard',
- path: '/dashboard',
- getParentRoute: () => rootRoute,
-} as any)
-
-const IndexRoute = IndexImport.update({
- id: '/',
- path: '/',
- getParentRoute: () => rootRoute,
-} as any)
-
-const DashboardIndexRoute = DashboardIndexImport.update({
- id: '/',
- path: '/',
- getParentRoute: () => DashboardRoute,
-} as any)
-
-const DashboardWalletRoute = DashboardWalletImport.update({
- id: '/wallet',
- path: '/wallet',
- getParentRoute: () => DashboardRoute,
-} as any)
-
-const DashboardSettingsRoute = DashboardSettingsImport.update({
- id: '/settings',
- path: '/settings',
- getParentRoute: () => DashboardRoute,
-} as any)
-
-const DashboardRequestsRoute = DashboardRequestsImport.update({
- id: '/requests',
- path: '/requests',
- getParentRoute: () => DashboardRoute,
-} as any)
-
-const DashboardPurchasesRoute = DashboardPurchasesImport.update({
- id: '/purchases',
- path: '/purchases',
- getParentRoute: () => DashboardRoute,
-} as any)
-
-const DashboardPeersRoute = DashboardPeersImport.update({
- id: '/peers',
- path: '/peers',
- getParentRoute: () => DashboardRoute,
-} as any)
-
-const DashboardNodesRoute = DashboardNodesImport.update({
- id: '/nodes',
- path: '/nodes',
- getParentRoute: () => DashboardRoute,
-} as any)
-
-const DashboardLogsRoute = DashboardLogsImport.update({
- id: '/logs',
- path: '/logs',
- getParentRoute: () => DashboardRoute,
-} as any)
-
-const DashboardHelpRoute = DashboardHelpImport.update({
- id: '/help',
- path: '/help',
- getParentRoute: () => DashboardRoute,
-} as any)
-
-const DashboardFilesRoute = DashboardFilesImport.update({
- id: '/files',
- path: '/files',
- getParentRoute: () => DashboardRoute,
-} as any)
-
-const DashboardFavoritesRoute = DashboardFavoritesImport.update({
- id: '/favorites',
- path: '/favorites',
- getParentRoute: () => DashboardRoute,
-} as any)
-
-const DashboardDisclaimerRoute = DashboardDisclaimerImport.update({
- id: '/disclaimer',
- path: '/disclaimer',
- getParentRoute: () => DashboardRoute,
-} as any)
-
-const DashboardDeviceRoute = DashboardDeviceImport.update({
- id: '/device',
- path: '/device',
- getParentRoute: () => DashboardRoute,
-} as any)
-
-const DashboardAvailabilitiesRoute = DashboardAvailabilitiesImport.update({
- id: '/availabilities',
- path: '/availabilities',
- getParentRoute: () => DashboardRoute,
-} as any)
-
-const DashboardAnalyticsRoute = DashboardAnalyticsImport.update({
- id: '/analytics',
- path: '/analytics',
- getParentRoute: () => DashboardRoute,
-} as any)
-
-const DashboardAboutRoute = DashboardAboutImport.update({
- id: '/about',
- path: '/about',
- getParentRoute: () => DashboardRoute,
-} as any)
-
-// Populate the FileRoutesByPath interface
-
-declare module '@tanstack/react-router' {
- interface FileRoutesByPath {
- '/': {
- id: '/'
- path: '/'
- fullPath: '/'
- preLoaderRoute: typeof IndexImport
- parentRoute: typeof rootRoute
- }
- '/dashboard': {
- id: '/dashboard'
- path: '/dashboard'
- fullPath: '/dashboard'
- preLoaderRoute: typeof DashboardImport
- parentRoute: typeof rootRoute
- }
- '/onboarding-checks': {
- id: '/onboarding-checks'
- path: '/onboarding-checks'
- fullPath: '/onboarding-checks'
- preLoaderRoute: typeof OnboardingChecksImport
- parentRoute: typeof rootRoute
- }
- '/onboarding-name': {
- id: '/onboarding-name'
- path: '/onboarding-name'
- fullPath: '/onboarding-name'
- preLoaderRoute: typeof OnboardingNameImport
- parentRoute: typeof rootRoute
- }
- '/dashboard/about': {
- id: '/dashboard/about'
- path: '/about'
- fullPath: '/dashboard/about'
- preLoaderRoute: typeof DashboardAboutImport
- parentRoute: typeof DashboardImport
- }
- '/dashboard/analytics': {
- id: '/dashboard/analytics'
- path: '/analytics'
- fullPath: '/dashboard/analytics'
- preLoaderRoute: typeof DashboardAnalyticsImport
- parentRoute: typeof DashboardImport
- }
- '/dashboard/availabilities': {
- id: '/dashboard/availabilities'
- path: '/availabilities'
- fullPath: '/dashboard/availabilities'
- preLoaderRoute: typeof DashboardAvailabilitiesImport
- parentRoute: typeof DashboardImport
- }
- '/dashboard/device': {
- id: '/dashboard/device'
- path: '/device'
- fullPath: '/dashboard/device'
- preLoaderRoute: typeof DashboardDeviceImport
- parentRoute: typeof DashboardImport
- }
- '/dashboard/disclaimer': {
- id: '/dashboard/disclaimer'
- path: '/disclaimer'
- fullPath: '/dashboard/disclaimer'
- preLoaderRoute: typeof DashboardDisclaimerImport
- parentRoute: typeof DashboardImport
- }
- '/dashboard/favorites': {
- id: '/dashboard/favorites'
- path: '/favorites'
- fullPath: '/dashboard/favorites'
- preLoaderRoute: typeof DashboardFavoritesImport
- parentRoute: typeof DashboardImport
- }
- '/dashboard/files': {
- id: '/dashboard/files'
- path: '/files'
- fullPath: '/dashboard/files'
- preLoaderRoute: typeof DashboardFilesImport
- parentRoute: typeof DashboardImport
- }
- '/dashboard/help': {
- id: '/dashboard/help'
- path: '/help'
- fullPath: '/dashboard/help'
- preLoaderRoute: typeof DashboardHelpImport
- parentRoute: typeof DashboardImport
- }
- '/dashboard/logs': {
- id: '/dashboard/logs'
- path: '/logs'
- fullPath: '/dashboard/logs'
- preLoaderRoute: typeof DashboardLogsImport
- parentRoute: typeof DashboardImport
- }
- '/dashboard/nodes': {
- id: '/dashboard/nodes'
- path: '/nodes'
- fullPath: '/dashboard/nodes'
- preLoaderRoute: typeof DashboardNodesImport
- parentRoute: typeof DashboardImport
- }
- '/dashboard/peers': {
- id: '/dashboard/peers'
- path: '/peers'
- fullPath: '/dashboard/peers'
- preLoaderRoute: typeof DashboardPeersImport
- parentRoute: typeof DashboardImport
- }
- '/dashboard/purchases': {
- id: '/dashboard/purchases'
- path: '/purchases'
- fullPath: '/dashboard/purchases'
- preLoaderRoute: typeof DashboardPurchasesImport
- parentRoute: typeof DashboardImport
- }
- '/dashboard/requests': {
- id: '/dashboard/requests'
- path: '/requests'
- fullPath: '/dashboard/requests'
- preLoaderRoute: typeof DashboardRequestsImport
- parentRoute: typeof DashboardImport
- }
- '/dashboard/settings': {
- id: '/dashboard/settings'
- path: '/settings'
- fullPath: '/dashboard/settings'
- preLoaderRoute: typeof DashboardSettingsImport
- parentRoute: typeof DashboardImport
- }
- '/dashboard/wallet': {
- id: '/dashboard/wallet'
- path: '/wallet'
- fullPath: '/dashboard/wallet'
- preLoaderRoute: typeof DashboardWalletImport
- parentRoute: typeof DashboardImport
- }
- '/dashboard/': {
- id: '/dashboard/'
- path: '/'
- fullPath: '/dashboard/'
- preLoaderRoute: typeof DashboardIndexImport
- parentRoute: typeof DashboardImport
- }
- }
-}
-
-// Create and export the route tree
-
-interface DashboardRouteChildren {
- DashboardAboutRoute: typeof DashboardAboutRoute
- DashboardAnalyticsRoute: typeof DashboardAnalyticsRoute
- DashboardAvailabilitiesRoute: typeof DashboardAvailabilitiesRoute
- DashboardDeviceRoute: typeof DashboardDeviceRoute
- DashboardDisclaimerRoute: typeof DashboardDisclaimerRoute
- DashboardFavoritesRoute: typeof DashboardFavoritesRoute
- DashboardFilesRoute: typeof DashboardFilesRoute
- DashboardHelpRoute: typeof DashboardHelpRoute
- DashboardLogsRoute: typeof DashboardLogsRoute
- DashboardNodesRoute: typeof DashboardNodesRoute
- DashboardPeersRoute: typeof DashboardPeersRoute
- DashboardPurchasesRoute: typeof DashboardPurchasesRoute
- DashboardRequestsRoute: typeof DashboardRequestsRoute
- DashboardSettingsRoute: typeof DashboardSettingsRoute
- DashboardWalletRoute: typeof DashboardWalletRoute
- DashboardIndexRoute: typeof DashboardIndexRoute
-}
-
-const DashboardRouteChildren: DashboardRouteChildren = {
- DashboardAboutRoute: DashboardAboutRoute,
- DashboardAnalyticsRoute: DashboardAnalyticsRoute,
- DashboardAvailabilitiesRoute: DashboardAvailabilitiesRoute,
- DashboardDeviceRoute: DashboardDeviceRoute,
- DashboardDisclaimerRoute: DashboardDisclaimerRoute,
- DashboardFavoritesRoute: DashboardFavoritesRoute,
- DashboardFilesRoute: DashboardFilesRoute,
- DashboardHelpRoute: DashboardHelpRoute,
- DashboardLogsRoute: DashboardLogsRoute,
- DashboardNodesRoute: DashboardNodesRoute,
- DashboardPeersRoute: DashboardPeersRoute,
- DashboardPurchasesRoute: DashboardPurchasesRoute,
- DashboardRequestsRoute: DashboardRequestsRoute,
- DashboardSettingsRoute: DashboardSettingsRoute,
- DashboardWalletRoute: DashboardWalletRoute,
- DashboardIndexRoute: DashboardIndexRoute,
-}
-
-const DashboardRouteWithChildren = DashboardRoute._addFileChildren(
- DashboardRouteChildren,
-)
-
-export interface FileRoutesByFullPath {
- '/': typeof IndexRoute
- '/dashboard': typeof DashboardRouteWithChildren
- '/onboarding-checks': typeof OnboardingChecksRoute
- '/onboarding-name': typeof OnboardingNameRoute
- '/dashboard/about': typeof DashboardAboutRoute
- '/dashboard/analytics': typeof DashboardAnalyticsRoute
- '/dashboard/availabilities': typeof DashboardAvailabilitiesRoute
- '/dashboard/device': typeof DashboardDeviceRoute
- '/dashboard/disclaimer': typeof DashboardDisclaimerRoute
- '/dashboard/favorites': typeof DashboardFavoritesRoute
- '/dashboard/files': typeof DashboardFilesRoute
- '/dashboard/help': typeof DashboardHelpRoute
- '/dashboard/logs': typeof DashboardLogsRoute
- '/dashboard/nodes': typeof DashboardNodesRoute
- '/dashboard/peers': typeof DashboardPeersRoute
- '/dashboard/purchases': typeof DashboardPurchasesRoute
- '/dashboard/requests': typeof DashboardRequestsRoute
- '/dashboard/settings': typeof DashboardSettingsRoute
- '/dashboard/wallet': typeof DashboardWalletRoute
- '/dashboard/': typeof DashboardIndexRoute
-}
-
-export interface FileRoutesByTo {
- '/': typeof IndexRoute
- '/onboarding-checks': typeof OnboardingChecksRoute
- '/onboarding-name': typeof OnboardingNameRoute
- '/dashboard/about': typeof DashboardAboutRoute
- '/dashboard/analytics': typeof DashboardAnalyticsRoute
- '/dashboard/availabilities': typeof DashboardAvailabilitiesRoute
- '/dashboard/device': typeof DashboardDeviceRoute
- '/dashboard/disclaimer': typeof DashboardDisclaimerRoute
- '/dashboard/favorites': typeof DashboardFavoritesRoute
- '/dashboard/files': typeof DashboardFilesRoute
- '/dashboard/help': typeof DashboardHelpRoute
- '/dashboard/logs': typeof DashboardLogsRoute
- '/dashboard/nodes': typeof DashboardNodesRoute
- '/dashboard/peers': typeof DashboardPeersRoute
- '/dashboard/purchases': typeof DashboardPurchasesRoute
- '/dashboard/requests': typeof DashboardRequestsRoute
- '/dashboard/settings': typeof DashboardSettingsRoute
- '/dashboard/wallet': typeof DashboardWalletRoute
- '/dashboard': typeof DashboardIndexRoute
-}
-
-export interface FileRoutesById {
- __root__: typeof rootRoute
- '/': typeof IndexRoute
- '/dashboard': typeof DashboardRouteWithChildren
- '/onboarding-checks': typeof OnboardingChecksRoute
- '/onboarding-name': typeof OnboardingNameRoute
- '/dashboard/about': typeof DashboardAboutRoute
- '/dashboard/analytics': typeof DashboardAnalyticsRoute
- '/dashboard/availabilities': typeof DashboardAvailabilitiesRoute
- '/dashboard/device': typeof DashboardDeviceRoute
- '/dashboard/disclaimer': typeof DashboardDisclaimerRoute
- '/dashboard/favorites': typeof DashboardFavoritesRoute
- '/dashboard/files': typeof DashboardFilesRoute
- '/dashboard/help': typeof DashboardHelpRoute
- '/dashboard/logs': typeof DashboardLogsRoute
- '/dashboard/nodes': typeof DashboardNodesRoute
- '/dashboard/peers': typeof DashboardPeersRoute
- '/dashboard/purchases': typeof DashboardPurchasesRoute
- '/dashboard/requests': typeof DashboardRequestsRoute
- '/dashboard/settings': typeof DashboardSettingsRoute
- '/dashboard/wallet': typeof DashboardWalletRoute
- '/dashboard/': typeof DashboardIndexRoute
-}
-
-export interface FileRouteTypes {
- fileRoutesByFullPath: FileRoutesByFullPath
- fullPaths:
- | '/'
- | '/dashboard'
- | '/onboarding-checks'
- | '/onboarding-name'
- | '/dashboard/about'
- | '/dashboard/analytics'
- | '/dashboard/availabilities'
- | '/dashboard/device'
- | '/dashboard/disclaimer'
- | '/dashboard/favorites'
- | '/dashboard/files'
- | '/dashboard/help'
- | '/dashboard/logs'
- | '/dashboard/nodes'
- | '/dashboard/peers'
- | '/dashboard/purchases'
- | '/dashboard/requests'
- | '/dashboard/settings'
- | '/dashboard/wallet'
- | '/dashboard/'
- fileRoutesByTo: FileRoutesByTo
- to:
- | '/'
- | '/onboarding-checks'
- | '/onboarding-name'
- | '/dashboard/about'
- | '/dashboard/analytics'
- | '/dashboard/availabilities'
- | '/dashboard/device'
- | '/dashboard/disclaimer'
- | '/dashboard/favorites'
- | '/dashboard/files'
- | '/dashboard/help'
- | '/dashboard/logs'
- | '/dashboard/nodes'
- | '/dashboard/peers'
- | '/dashboard/purchases'
- | '/dashboard/requests'
- | '/dashboard/settings'
- | '/dashboard/wallet'
- | '/dashboard'
- id:
- | '__root__'
- | '/'
- | '/dashboard'
- | '/onboarding-checks'
- | '/onboarding-name'
- | '/dashboard/about'
- | '/dashboard/analytics'
- | '/dashboard/availabilities'
- | '/dashboard/device'
- | '/dashboard/disclaimer'
- | '/dashboard/favorites'
- | '/dashboard/files'
- | '/dashboard/help'
- | '/dashboard/logs'
- | '/dashboard/nodes'
- | '/dashboard/peers'
- | '/dashboard/purchases'
- | '/dashboard/requests'
- | '/dashboard/settings'
- | '/dashboard/wallet'
- | '/dashboard/'
- fileRoutesById: FileRoutesById
-}
-
-export interface RootRouteChildren {
- IndexRoute: typeof IndexRoute
- DashboardRoute: typeof DashboardRouteWithChildren
- OnboardingChecksRoute: typeof OnboardingChecksRoute
- OnboardingNameRoute: typeof OnboardingNameRoute
-}
-
-const rootRouteChildren: RootRouteChildren = {
- IndexRoute: IndexRoute,
- DashboardRoute: DashboardRouteWithChildren,
- OnboardingChecksRoute: OnboardingChecksRoute,
- OnboardingNameRoute: OnboardingNameRoute,
-}
-
-export const routeTree = rootRoute
- ._addFileChildren(rootRouteChildren)
- ._addFileTypes()
-
-/* prettier-ignore-end */
-
-/* ROUTE_MANIFEST_START
-{
- "routes": {
- "__root__": {
- "filePath": "__root.tsx",
- "children": [
- "/",
- "/dashboard",
- "/onboarding-checks",
- "/onboarding-name"
- ]
- },
- "/": {
- "filePath": "index.tsx"
- },
- "/dashboard": {
- "filePath": "dashboard.tsx",
- "children": [
- "/dashboard/about",
- "/dashboard/analytics",
- "/dashboard/availabilities",
- "/dashboard/device",
- "/dashboard/disclaimer",
- "/dashboard/favorites",
- "/dashboard/files",
- "/dashboard/help",
- "/dashboard/logs",
- "/dashboard/nodes",
- "/dashboard/peers",
- "/dashboard/purchases",
- "/dashboard/requests",
- "/dashboard/settings",
- "/dashboard/wallet",
- "/dashboard/"
- ]
- },
- "/onboarding-checks": {
- "filePath": "onboarding-checks.tsx"
- },
- "/onboarding-name": {
- "filePath": "onboarding-name.tsx"
- },
- "/dashboard/about": {
- "filePath": "dashboard/about.tsx",
- "parent": "/dashboard"
- },
- "/dashboard/analytics": {
- "filePath": "dashboard/analytics.tsx",
- "parent": "/dashboard"
- },
- "/dashboard/availabilities": {
- "filePath": "dashboard/availabilities.tsx",
- "parent": "/dashboard"
- },
- "/dashboard/device": {
- "filePath": "dashboard/device.tsx",
- "parent": "/dashboard"
- },
- "/dashboard/disclaimer": {
- "filePath": "dashboard/disclaimer.tsx",
- "parent": "/dashboard"
- },
- "/dashboard/favorites": {
- "filePath": "dashboard/favorites.tsx",
- "parent": "/dashboard"
- },
- "/dashboard/files": {
- "filePath": "dashboard/files.tsx",
- "parent": "/dashboard"
- },
- "/dashboard/help": {
- "filePath": "dashboard/help.tsx",
- "parent": "/dashboard"
- },
- "/dashboard/logs": {
- "filePath": "dashboard/logs.tsx",
- "parent": "/dashboard"
- },
- "/dashboard/nodes": {
- "filePath": "dashboard/nodes.tsx",
- "parent": "/dashboard"
- },
- "/dashboard/peers": {
- "filePath": "dashboard/peers.tsx",
- "parent": "/dashboard"
- },
- "/dashboard/purchases": {
- "filePath": "dashboard/purchases.tsx",
- "parent": "/dashboard"
- },
- "/dashboard/requests": {
- "filePath": "dashboard/requests.tsx",
- "parent": "/dashboard"
- },
- "/dashboard/settings": {
- "filePath": "dashboard/settings.tsx",
- "parent": "/dashboard"
- },
- "/dashboard/wallet": {
- "filePath": "dashboard/wallet.tsx",
- "parent": "/dashboard"
- },
- "/dashboard/": {
- "filePath": "dashboard/index.tsx",
- "parent": "/dashboard"
- }
- }
-}
-ROUTE_MANIFEST_END */
diff --git a/src/routes/__root.tsx b/src/routes/__root.tsx
deleted file mode 100644
index 9e9864f..0000000
--- a/src/routes/__root.tsx
+++ /dev/null
@@ -1,16 +0,0 @@
-import {
- createRootRoute,
- Outlet,
- ScrollRestoration,
-} from "@tanstack/react-router";
-
-export const Route = createRootRoute({
- component: () => {
- return (
- <>
-
-
- >
- );
- },
-});
diff --git a/src/routes/dashboard.tsx b/src/routes/dashboard.tsx
deleted file mode 100644
index 8c47007..0000000
--- a/src/routes/dashboard.tsx
+++ /dev/null
@@ -1,42 +0,0 @@
-import {
- createFileRoute,
- Outlet,
- ScrollRestoration,
-} from "@tanstack/react-router";
-import "./layout.css";
-import { Menu } from "../components/Menu/Menu";
-import { useState } from "react";
-import { AppBar } from "../components/AppBar/AppBar";
-import { Backdrop } from "@codex-storage/marketplace-ui-components";
-
-const Layout = () => {
- const [hasMobileMenu, setHasMobileMenu] = useState(false);
-
- const onIconClick = () => {
- if (window.innerWidth <= 999) {
- setHasMobileMenu(true);
- }
- };
-
- const onClose = () => setHasMobileMenu(false);
-
- return (
-
- );
-};
-
-export const Route = createFileRoute("/dashboard")({
- component: Layout,
-});
diff --git a/src/routes/dashboard/about.tsx b/src/routes/dashboard/about.tsx
deleted file mode 100644
index b18c86d..0000000
--- a/src/routes/dashboard/about.tsx
+++ /dev/null
@@ -1,104 +0,0 @@
-import { CodexDataContent } from "@codex-storage/sdk-js";
-import { createFileRoute, useRouterState } from "@tanstack/react-router";
-import { PrettyBytes } from "../../utils/bytes";
-import { Button, WebFileIcon } from "@codex-storage/marketplace-ui-components";
-
-function ProtectedIcon({ isProtected }: { isProtected: boolean }) {
- if (isProtected) {
- return (
-
- lock
-
- );
- }
-
- return (
-
- lock_open
-
- );
-}
-
-const About = () => {
- {
- const c = useRouterState({
- select: (s) => s.location.state,
- }) as CodexDataContent;
-
- if (!c.cid) {
- return ;
- }
-
- return (
-
-
-
-
-
-
- {c.manifest.filename}
-
-
- {PrettyBytes(c.manifest.datasetSize)} -{" "}
- {c.manifest.uploadedAt} - ...{c.cid.slice(-5)}
-
-
-
-
-
-
-
- File details
-
-
- Cid:
- {c.cid}
-
-
-
- Name:
- {c.manifest.filename}
-
-
-
- Uploaded:
- {c.manifest.uploadedAt}
-
-
-
- File size:
- {PrettyBytes(c.manifest.datasetSize)}
-
-
-
- Protected:
- {c.manifest.protected ? "Yes" : "No"}
-
-
-
-
-
-
- );
- }
-};
-
-export const Route = createFileRoute("/dashboard/about")({
- component: () => About,
-});
diff --git a/src/routes/dashboard/analytics.tsx b/src/routes/dashboard/analytics.tsx
deleted file mode 100644
index ab7c726..0000000
--- a/src/routes/dashboard/analytics.tsx
+++ /dev/null
@@ -1,5 +0,0 @@
-import { createFileRoute } from "@tanstack/react-router";
-
-export const Route = createFileRoute("/dashboard/analytics")({
- component: () => Hello /dashboard/analytics! ,
-});
diff --git a/src/routes/dashboard/availabilities.css b/src/routes/dashboard/availabilities.css
index 5c5f636..4898d1d 100644
--- a/src/routes/dashboard/availabilities.css
+++ b/src/routes/dashboard/availabilities.css
@@ -4,22 +4,37 @@
flex-wrap: wrap;
gap: 16px;
- dialog {
- width: 80%;
- }
-
> .card {
flex: 1 1 50%;
+
+ @media (max-width: 800px) {
+ & {
+ flex: 1 1 100%;
+ }
+ }
}
.table {
+ @media (max-width: 800px) {
+ th:nth-child(3),
+ td:nth-child(3),
+ th:nth-child(4),
+ td:nth-child(4),
+ th:nth-child(5),
+ td:nth-child(5),
+ th:nth-child(6),
+ td:nth-child(6) {
+ display: none;
+ }
+ }
+
table thead tr th {
- background-color: #14141499;
+ background-color: rgba(20, 20, 20, 0.6);
}
table tbody tr.availabilty-row {
td {
- background-color: #292929;
+ background-color: rgb(41, 41, 41);
padding: 6px 12px;
&:first-child {
@@ -54,14 +69,13 @@
font-weight: 400;
line-height: 16px;
text-align: left;
- color: #ffffffcc;
+ color: rgba (255, 255, 255, 0.8);
}
}
}
aside {
display: flex;
- width: 400px;
flex: 1 1 30%;
.card {
@@ -80,7 +94,7 @@
}
.node-space {
- border-bottom: 1px solid #96969633;
+ border-bottom: 1px solid rgba(150, 150, 150, 0.2);
padding-bottom: 16px;
h6 {
@@ -108,144 +122,18 @@
line-height: 20px;
letter-spacing: -0.006em;
text-align: left;
- color: #969696cc;
+ color: rgba(150, 150, 150, 0.8);
}
}
}
-}
-.availabilities-actions {
- padding: 1rem;
- display: flex;
- align-items: center;
- justify-content: flex-end;
-}
+ .space-allocation {
+ flex-direction: column;
-.availabilities-loader {
- margin: auto;
- display: block;
-}
-
-.availabilities-header {
- position: relative;
-}
-
-.availabilities-content {
- display: flex;
- flex-direction: column;
-}
-
-.nodeSpaceAllocation-bar {
- background-color: var(--codex-background-light);
- padding: 0.25rem;
- border-radius: var(--codex-border-radius);
-}
-
-.availabilities-space-allocation .nodeSpaceAllocation-legendRow,
-.availabilities-space-allocation .nodeSpaceAllocation-barItem {
- transition: opacity 0.35s;
- opacity: 0.3;
-}
-
-.availabilities-space-allocation .nodeSpaceAllocation-barItem:hover {
- opacity: 1;
-}
-
-.availabilities-space-allocation {
- flex: 1;
-}
-/*
-// This isn't the best approach, but it will suffice for now.
-// The issue is that there is no sibling index to create a generic rule.
-// Additionally, rerendering the components with React on hover feels like overkill.
-// We are also uncertain about the number of availabilities that will be in the table,
-// so this workaround is acceptable for the time being.
-// @for $i from 1 through 30 {
-// .availabilities-table:has(.table-tbodyTr:nth-child(#{$i}):hover)
-// + .availabilities-space
-// .nodeSpaceAllocation-barItem:nth-child(#{$i}),
-// .availabilities-table:has(.table-tbodyTr:nth-child(#{$i}):hover)
-// + .availabilities-space
-// .nodeSpaceAllocation-legendRow:nth-child(#{$i}) {
-// opacity: 1;
-// }
-
-// .availabilities-table:has(.table-tbodyTr:nth-child(#{$i}):hover)
-// + .availabilities-space
-// .nodeSpaceAllocation-barItem:nth-child(#{$i})::after {
-// opacity: 1;
-// z-index: 1;
-// }
-
-// .availabilities-table:has(
-// ~ .availabilities-space
-// .nodeSpaceAllocation-barItem:nth-child(#{$i}):hover
-// )
-// .table-tbodyTr:nth-child(#{$i}) {
-// background-color: var(--codex-background-light);
-// }
-// }
-*/
-
-.plus {
- border-radius: 50%;
- width: 5rem;
- height: 5rem;
- display: flex;
- align-items: center;
- justify-content: center;
- position: absolute;
- left: 0;
- right: 0;
- bottom: 0;
- top: 0;
- margin: auto;
- z-index: 1;
-}
-
-.plus .button-label {
- display: none;
-}
-
-.progress {
- border: 1px solid var(--codex-border-color);
- height: 8px;
- width: 200px;
- border-radius: var(--codex-border-radius);
- background-color: var(--codex-background);
- display: flex;
-}
-
-.progress-bar {
- height: 100%;
- background-color: var(--codex-progress-bar);
- display: inline-block;
- border-radius: var(--codex-border-radius);
-}
-
-.progress-container {
- text-align: right;
- display: flex;
- flex-direction: column;
- gap: 0.5rem;
- align-items: center;
-}
-
-.slot {
- background-color: transparent;
- background-image: repeating-linear-gradient(
- -45deg,
- transparent,
- transparent 1rem,
- rgb(var(--codex-color-primary-rgb)) 1rem,
- rgb(var(--codex-color-primary-rgb)) 1.5rem
- );
- background-size: 200% 200%;
- animation: barberpole 10s linear infinite;
-}
-
-@keyframes barberpole {
- 100% {
- background-position: 100% 100%;
+ header {
+ width: 100%;
+ margin-bottom: 0;
+ margin-top: 0;
+ }
}
}
diff --git a/src/routes/dashboard/availabilities.tsx b/src/routes/dashboard/availabilities.tsx
index dc22f94..20d83f1 100644
--- a/src/routes/dashboard/availabilities.tsx
+++ b/src/routes/dashboard/availabilities.tsx
@@ -1,6 +1,3 @@
-import { createFileRoute } from "@tanstack/react-router";
-import { ErrorBoundary } from "@sentry/react";
-import { ErrorPlaceholder } from "../../components/ErrorPlaceholder/ErrorPlaceholder";
import {
Button,
SpaceAllocationItem,
@@ -13,10 +10,9 @@ import "./availabilities.css";
import { AvailabilitiesTable } from "../../components/Availability/AvailabilitiesTable";
import { AvailabilityEdit } from "../../components/Availability/AvailabilityEdit";
import { Strings } from "../../utils/strings";
-import { PrettyBytes } from "../../utils/bytes";
+import { Bytes } from "../../utils/bytes";
import { Sunburst } from "../../components/Availability/Sunburst";
import { Errors } from "../../utils/errors";
-import { availabilityColors } from "../../components/Availability/availability.colors";
import { AvailabilityWithSlots } from "../../components/Availability/types";
import { WebStorage } from "../../utils/web-storage";
import { NodeSpace } from "../../components/NodeSpace/NodeSpace";
@@ -31,7 +27,7 @@ const defaultSpace = {
totalBlocks: 0,
};
-export function Availabilities() {
+export function AvailabilitiesRoute() {
{
// Error will be catched in ErrorBounday
const { data: availabilities = [], isPending } = useQuery<
@@ -115,8 +111,8 @@ export function Availabilities() {
(a, index) => ({
title: Strings.shortId(a.id),
size: a.totalSize,
- tooltip: a.id + "\u000D\u000A" + PrettyBytes(a.totalSize),
- color: availabilityColors[index],
+ tooltip: a.id + "\u000D\u000A" + Bytes.pretty(a.totalSize),
+ color: AvailabilityUtils.availabilityColors[index],
})
);
@@ -128,7 +124,7 @@ export function Availabilities() {
if (isPending) {
return (
-
+
);
@@ -174,7 +170,7 @@ export function Availabilities() {
@@ -183,14 +179,3 @@ export function Availabilities() {
);
}
}
-
-export const Route = createFileRoute("/dashboard/availabilities")({
- component: () => (
- (
-
- )}>
-
-
- ),
-});
diff --git a/src/routes/dashboard/index.css b/src/routes/dashboard/dashboard.css
similarity index 78%
rename from src/routes/dashboard/index.css
rename to src/routes/dashboard/dashboard.css
index ddac5ec..65b8456 100644
--- a/src/routes/dashboard/index.css
+++ b/src/routes/dashboard/dashboard.css
@@ -13,11 +13,11 @@
@media (min-width: 1600px) {
& {
- flex: 1 1 23%;
+ flex: 1 1 35%;
}
&.welcome-card {
- flex: 1 1 30%;
+ flex: 1 1 35%;
}
&.card--main--files {
@@ -37,24 +37,30 @@
font-weight: 700;
line-height: 14.52px;
letter-spacing: 0.01em;
- color: #969696cc;
+ color: rgba(150, 150, 150, 0.8);
text-transform: uppercase;
}
h4 {
font-family: Inter;
- font-size: 32px;
+ font-size: 16px;
font-weight: 400;
- line-height: 38.73px;
letter-spacing: 0.01em;
color: white;
+
+ @media (min-width: 801px) {
+ & {
+ font-size: 32px;
+ line-height: 38.73px;
+ }
+ }
}
.emoji {
border-radius: 50%;
width: 52px;
height: 52px;
- background-color: #4a9a73;
+ background-color: rgb(74, 154, 115);
display: flex;
align-items: center;
justify-content: center;
@@ -89,4 +95,11 @@
flex-basis: 66%;
}
}
+
+ .gauge {
+ position: absolute;
+ left: 0;
+ right: 0;
+ margin: auto;
+ }
}
diff --git a/src/routes/dashboard/index.tsx b/src/routes/dashboard/dashboard.tsx
similarity index 87%
rename from src/routes/dashboard/index.tsx
rename to src/routes/dashboard/dashboard.tsx
index 7d3c8d7..15531d9 100644
--- a/src/routes/dashboard/index.tsx
+++ b/src/routes/dashboard/dashboard.tsx
@@ -1,8 +1,7 @@
-import { createFileRoute, useNavigate } from "@tanstack/react-router";
import { Files } from "../../components/Files/Files.tsx";
import { WelcomeCard } from "../../components/Welcome/WelcomeCard.tsx";
import { Download } from "../../components/Download/Download.tsx";
-import "./index.css";
+import "./dashboard.css";
import { Versions } from "../../components/Versions/Versions.tsx";
import { WebStorage } from "../../utils/web-storage.ts";
import { ConnectedAccount } from "../../components/ConnectedAccount/ConnectedAccount.tsx";
@@ -19,14 +18,11 @@ import DownloadIcon from "../../assets/icons/download.svg?react";
import FetchIcon from "../../assets/icons/fetch.svg?react";
import { ManifestFetch } from "../../components/ManifestFetch/ManifestFetch.tsx";
import FilesIconOutline from "../../assets/icons/files-outline.svg?react";
+import { useNavigate } from "react-router-dom";
-export const Route = createFileRoute("/dashboard/")({
- component: Dashboard,
-});
-
-function Dashboard() {
+export function DashboardRoute() {
const username = WebStorage.onBoarding.getDisplayName();
- const naviguate = useNavigate({ from: window.location.pathname });
+ const naviguate = useNavigate();
const emoji = WebStorage.onBoarding.getEmoji();
return (
@@ -56,14 +52,14 @@ function Dashboard() {
icon={}
title="Storage"
buttonLabel="Details"
- buttonAction={() => naviguate({ to: "/dashboard/availabilities" })}>
+ buttonAction={() => naviguate("/dashboard/availabilities")}>
}
title="Peers"
buttonLabel="Details"
- buttonAction={() => naviguate({ to: "/dashboard/peers" })}>
+ buttonAction={() => naviguate("/dashboard/peers")}>
diff --git a/src/routes/dashboard/device.tsx b/src/routes/dashboard/device.tsx
deleted file mode 100644
index 049ff50..0000000
--- a/src/routes/dashboard/device.tsx
+++ /dev/null
@@ -1,5 +0,0 @@
-import { createFileRoute } from "@tanstack/react-router";
-
-export const Route = createFileRoute("/dashboard/device")({
- component: () => Hello /dashboard/device! ,
-});
diff --git a/src/routes/dashboard/disclaimer.css b/src/routes/dashboard/disclaimer.css
index ad2febf..d8c674d 100644
--- a/src/routes/dashboard/disclaimer.css
+++ b/src/routes/dashboard/disclaimer.css
@@ -2,13 +2,13 @@
max-width: 600px;
margin: auto;
padding: 32px;
-}
-.disclaimer-title {
- margin-bottom: 3rem;
- margin-top: 3rem;
-}
+ h1 {
+ margin-bottom: 3rem;
+ margin-top: 3rem;
+ }
-.disclaimer-text {
- line-height: 1.5rem;
+ p {
+ line-height: 1.5rem;
+ }
}
diff --git a/src/routes/dashboard/disclaimer.tsx b/src/routes/dashboard/disclaimer.tsx
index 2e3d41f..dbe7dfd 100644
--- a/src/routes/dashboard/disclaimer.tsx
+++ b/src/routes/dashboard/disclaimer.tsx
@@ -1,39 +1,33 @@
-import { createFileRoute } from "@tanstack/react-router";
import "./disclaimer.css";
-export const Route = createFileRoute("/dashboard/disclaimer")({
- component: () => (
-
-
- Disclaimer
+export const DisclaimerRoute = () => (
+
+ Disclaimer
-
- The website and the content herein is not intended for public use and
- is for informational and demonstration purposes only.
-
+
+ The website and the content herein is not intended for public use and is
+ for informational and demonstration purposes only.
+
-
+
-
- The website and any associated functionalities are provided on an “as
- is” basis without any guarantees, warranties, or representations of
- any kind, either express or implied. The website and any associated
- functionalities may not reflect the final version of the project and
- is subject to changes, updates, or removal at any time and without
- notice.
-
+
+ The website and any associated functionalities are provided on an “as is”
+ basis without any guarantees, warranties, or representations of any kind,
+ either express or implied. The website and any associated functionalities
+ may not reflect the final version of the project and is subject to
+ changes, updates, or removal at any time and without notice.
+
-
+
-
- By accessing and using this website, you agree that we, Logos
- Collective Association and its affiliates, will not be liable for any
- direct, indirect, incidental, or consequential damages arising from
- the use of, or inability to use, this website. Any data, content, or
- interactions on this site are non-binding and should not be considered
- final or actionable. Your use of this website is at your sole risk.
-
-
-
- ),
-});
+
+ By accessing and using this website, you agree that we, Logos Collective
+ Association and its affiliates, will not be liable for any direct,
+ indirect, incidental, or consequential damages arising from the use of, or
+ inability to use, this website. Any data, content, or interactions on this
+ site are non-binding and should not be considered final or actionable.
+ Your use of this website is at your sole risk.
+
+
+);
diff --git a/src/routes/dashboard/favorites.tsx b/src/routes/dashboard/favorites.tsx
deleted file mode 100644
index c96d39f..0000000
--- a/src/routes/dashboard/favorites.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import { createFileRoute } from "@tanstack/react-router";
-import { Files } from "../../components/Files/Files";
-import { ErrorBoundary } from "@sentry/react";
-import { ErrorPlaceholder } from "../../components/ErrorPlaceholder/ErrorPlaceholder";
-
-export const Route = createFileRoute("/dashboard/favorites")({
- component: () => (
- <>
- (
-
- )}>
-
-
-
-
- >
- ),
-});
diff --git a/src/routes/dashboard/files.tsx b/src/routes/dashboard/files.tsx
index 39092ba..fa9b860 100644
--- a/src/routes/dashboard/files.tsx
+++ b/src/routes/dashboard/files.tsx
@@ -1,4 +1,3 @@
-import { createFileRoute } from "@tanstack/react-router";
import { Files } from "../../components/Files/Files";
import "./files.css";
import { UploadCard } from "../../components/UploadCard/UploadCard";
@@ -10,28 +9,24 @@ import FetchIcon from "../../assets/icons/fetch.svg?react";
import { Card } from "../../components/Card/Card";
import FilesIconOutline from "../../assets/icons/files-outline.svg?react";
-export const Route = createFileRoute("/dashboard/files")({
- component: () => (
-
- }
- title="Files">
-
+export const FilesRoute = () => (
+
+ } title="Files">
+
+
+
+
- ),
-});
+ } title="Fetch manifest">
+
+
+
+
+);
diff --git a/src/routes/dashboard/help.css b/src/routes/dashboard/help.css
index eeeef17..5793bf0 100644
--- a/src/routes/dashboard/help.css
+++ b/src/routes/dashboard/help.css
@@ -1,44 +1,44 @@
.help {
max-width: 600px;
margin: auto;
-}
-.help-title {
- margin-bottom: 3rem;
- margin-top: 3rem;
-}
+ h1 {
+ margin-bottom: 3rem;
+ margin-top: 3rem;
+ }
-.help-text {
- color: var(--codex-color-light);
-}
+ > div {
+ padding-bottom: 2rem;
+ margin-bottom: 2rem;
+ border-bottom: 1px solid rgba(150, 150, 150, 0.2);
+ gap: 1rem;
+ display: flex;
+ align-items: flex-start;
-.help-itemTitle {
- font-size: 1.125rem;
- line-height: 1.75rem;
- font-weight: bold;
- margin-bottom: 0.75rem;
-}
+ div {
+ font-size: 1.125rem;
+ }
+ }
-.help-itemIcon {
- color: var(--codex-color-disabled);
- min-width: 1.5rem;
- height: auto;
-}
+ h2 {
+ font-size: 1.125rem;
+ line-height: 1.75rem;
+ font-weight: bold;
+ margin-bottom: 0.75rem;
+ }
-.help-itemBody {
- font-size: 1.125rem;
-}
+ p {
+ color: rgb(150 150 150);
+ }
-.help-item {
- padding-bottom: 2rem;
- margin-bottom: 2rem;
- border-bottom: 1px solid var(--codex-border-color);
- gap: 1rem;
- display: flex;
- align-items: flex-start;
-}
+ svg {
+ color: rgb(113, 113, 113);
+ min-width: 1.5rem;
+ height: auto;
+ }
-.help-link {
- color: var(--codex-color-primary);
- text-decoration: underline;
+ a {
+ color: var(--codex-color-primary);
+ text-decoration: underline;
+ }
}
diff --git a/src/routes/dashboard/help.tsx b/src/routes/dashboard/help.tsx
index d72e760..78afbfc 100644
--- a/src/routes/dashboard/help.tsx
+++ b/src/routes/dashboard/help.tsx
@@ -1,10 +1,9 @@
-import { createFileRoute } from "@tanstack/react-router";
import "./help.css";
-import { HelpCircle } from "lucide-react";
import { useEffect } from "react";
import * as Sentry from "@sentry/react";
+import HelpIcon from "../../assets/icons/help.svg?react";
-const Help = () => {
+export const HelpRoute = () => {
useEffect(() => {
const feedback = Sentry.feedbackIntegration({
// Additional SDK configuration goes in here, for example:
@@ -18,99 +17,88 @@ const Help = () => {
}, []);
return (
-
-
- You might be wondering...
+
+ You might be wondering...
-
-
-
- What's Codex?
-
- Codex is a decentralised data storage platform that provides
- exceptionally strong censorship resistance and durability
- guarantees. It serves as the storage layer of the Logos tech
- stack.
-
-
+
+
+
+ What's Codex?
+
+ Codex is a decentralised data storage platform that provides
+ exceptionally strong censorship resistance and durability
+ guarantees. It serves as the storage layer of the Logos tech stack.
+
+
-
-
-
-
- What is the purpose of this web application?
-
-
- This application allows you to interact with the Codex Marketplace
- network in a user-friendly manner.
-
-
+
+
+
+ What is the purpose of this web application?
+
+ This application allows you to interact with the Codex Marketplace
+ network in a user-friendly manner.
+
+
-
-
-
- Can Codex handle big files ?
-
- Codex can handle very large files, which is its main purpose.
- However, for this UI, the files used should not be too large.
-
-
+
+
+
+ Can Codex handle big files ?
+
+ Codex can handle very large files, which is its main purpose.
+ However, for this UI, the files used should not be too large.
+
+
-
-
-
- Is it production ready ?
-
- Not at all! This is a very early alpha version. You should expect
- to encounter bugs, but don't worry—feel free to reach out to us if
- you need assistance.
-
-
+
+
+
+ Is it production ready ?
+
+ Not at all! This is a very early alpha version. You should expect to
+ encounter bugs, but don't worry—feel free to reach out to us if you
+ need assistance.
+
+
-
-
-
+
-
);
};
-
-export const Route = createFileRoute("/dashboard/help")({
- component: Help,
-});
diff --git a/src/routes/dashboard/logs.css b/src/routes/dashboard/logs.css
index 75107a5..653c501 100644
--- a/src/routes/dashboard/logs.css
+++ b/src/routes/dashboard/logs.css
@@ -1,10 +1,17 @@
.logs-card {
display: flex;
justify-content: space-between;
- border: 1px solid #96969633;
+ border: 1px solid rgba(150, 150, 150, 0.2);
border-radius: 16px;
margin-bottom: 16px;
+ @media (max-width: 800px) {
+ & {
+ flex-direction: column;
+ gap: 16px;
+ }
+ }
+
> div:first-child {
padding: 16px;
}
@@ -24,12 +31,23 @@
font-weight: 400;
line-height: 16px;
text-align: left;
- color: #969696cc;
+ color: rgba(150, 150, 150, 0.8);
}
.button {
- width: 187px;
gap: 8px;
+
+ @media (min-width: 801px) {
+ & {
+ width: 187px;
+ }
+ }
+
+ @media (max-width: 800px) {
+ span {
+ display: none;
+ }
+ }
}
}
@@ -42,7 +60,7 @@
line-height: 24px;
letter-spacing: -0.011em;
text-align: left;
- color: #757575;
+ color: rgb(117, 117, 117);
}
}
}
diff --git a/src/routes/dashboard/logs.tsx b/src/routes/dashboard/logs.tsx
index 8b5ee93..7ef6feb 100644
--- a/src/routes/dashboard/logs.tsx
+++ b/src/routes/dashboard/logs.tsx
@@ -1,4 +1,3 @@
-import { createFileRoute } from "@tanstack/react-router";
import "./logs.css";
import { RequireAssitance } from "../../components/RequireAssitance/RequireAssitance";
import { LogLevel } from "../../components/LogLevel/LogLevel";
@@ -11,7 +10,7 @@ const throwOnError = false;
// Sentry.showReportDialog({});
-const Logs = () => {
+export const LogsRoute = () => {
const { data } = useDebug(throwOnError);
useEffect(() => {
@@ -26,6 +25,7 @@ const Logs = () => {
};
}, []);
+ /* eslint-disable @typescript-eslint/no-unused-vars */
const { table, ...rest } = data ?? {};
return (
@@ -55,7 +55,3 @@ const Logs = () => {
);
};
-
-export const Route = createFileRoute("/dashboard/logs")({
- component: Logs,
-});
diff --git a/src/routes/dashboard/nodes.tsx b/src/routes/dashboard/nodes.tsx
deleted file mode 100644
index c8d1738..0000000
--- a/src/routes/dashboard/nodes.tsx
+++ /dev/null
@@ -1,5 +0,0 @@
-import { createFileRoute } from '@tanstack/react-router'
-
-export const Route = createFileRoute('/dashboard/nodes')({
- component: () => Hello /nodes! ,
-})
diff --git a/src/components/Peers/Peers.css b/src/routes/dashboard/peers.css
similarity index 70%
rename from src/components/Peers/Peers.css
rename to src/routes/dashboard/peers.css
index 18669ad..851cf1e 100644
--- a/src/components/Peers/Peers.css
+++ b/src/routes/dashboard/peers.css
@@ -9,13 +9,12 @@
}
> div:first-child {
- width: calc(100% - 16px);
- border: 1px solid #96969633;
- padding: 16px;
+ width: 100%;
+ border: 1px solid rgba(150, 150, 150, 0.2);
border-radius: 16px;
position: relative;
- @media (min-width: 1000px) {
+ @media (min-width: 801px) {
& {
width: calc(100% - 128px - 16px);
padding: 16px 16px 16px 128px;
@@ -26,7 +25,7 @@
ul {
display: none;
- @media (min-width: 1000px) {
+ @media (min-width: 801px) {
& {
list-style-type: none;
width: 71px;
@@ -38,7 +37,7 @@
}
li {
- border-bottom: 1px solid #969696cc;
+ border-bottom: 1px solid rgba(150, 150, 150, 0.8);
padding: 16px 0;
text-align: right;
}
@@ -49,7 +48,7 @@
line-height: 20px;
letter-spacing: -0.006em;
text-align: left;
- color: #7b7b7b;
+ color: rgb(123, 123, 123);
}
li:not(:first-child) {
@@ -89,29 +88,23 @@
}
.connections {
- background-color: #232323;
- border: 1px solid #96969633;
+ background-color: rgb(35, 35, 35);
+ border: 1px solid rgba(150, 150, 150, 0.2);
border-radius: 16px;
max-width: 280px;
padding: 16px;
- transform: scale(0.7);
+ /* transform: scale(0.7); */
width: 280px;
- @media (max-width: 999px) {
+ @media (max-width: 800px) {
& {
position: relative;
- bottom: -32px;
- left: -32px;
+ width: calc(100% - 32px);
+ max-width: inherit;
}
}
- @media (min-width: 1000px) {
- & {
- transform: scale(1);
- }
- }
-
- @media (min-width: 1000px) {
+ @media (min-width: 801px) {
& {
position: absolute;
bottom: 16px;
@@ -124,9 +117,9 @@
display: flex;
align-items: center;
gap: 8px;
- color: #969696;
+ color: rgba(150, 150, 150, 1);
padding-bottom: 16px;
- border-bottom: 1px solid #96969633;
+ border-bottom: 1px solid rgba(150, 150, 150, 0.2);
span {
font-family: Inter;
@@ -139,7 +132,7 @@
}
footer {
- border-top: 1px solid #96969633;
+ border-top: 1px solid rgba(150, 150, 150, 0.2);
padding-top: 16px;
}
}
@@ -160,25 +153,34 @@
border-radius: 8px;
&.status--active {
- color: #1daf61;
- background-color: #6fcb9433;
+ color: rgb(29, 175, 97);
+ background-color: rgb(111, 203, 148, 0.2);
}
&.status--inactive {
- color: #fb3748;
- background-color: #fb374833;
+ color: rgb(251, 55, 72);
+ background-color: rgb(251, 55, 72, 0.2);
}
}
}
- }
- .peers-chart {
- transform: scale(0.5);
-
- @media (min-width: 1000px) {
- & {
- transform: scale(0.73);
+ @media (max-width: 800px) {
+ th:nth-child(2),
+ td:nth-child(2) {
+ display: none;
}
}
}
+
+ .gauge {
+ margin: auto;
+ }
+
+ @media (max-width: 800px) {
+ .peers-chart {
+ transform: scale(0.8);
+ margin: auto;
+ left: 0;
+ }
+ }
}
diff --git a/src/routes/dashboard/peers.tsx b/src/routes/dashboard/peers.tsx
index a9c8827..eb884fa 100644
--- a/src/routes/dashboard/peers.tsx
+++ b/src/routes/dashboard/peers.tsx
@@ -1,15 +1,111 @@
-import { ErrorBoundary } from "@sentry/react";
-import { ErrorPlaceholder } from "../../components/ErrorPlaceholder/ErrorPlaceholder";
-import { createFileRoute } from "@tanstack/react-router";
-import { Peers } from "../../components/Peers/Peers";
+import {
+ TabSortState,
+ Row,
+ Cell,
+ Table,
+} from "@codex-storage/marketplace-ui-components";
+import { useCallback, useState } from "react";
+import { PeerCountryCell } from "../../components/Peers/PeerCountryCell";
+import "./peers.css";
+import {
+ PeerGeo,
+ PeerNode,
+ PeerSortFn,
+ PeerUtils,
+} from "../../components/Peers/peers.utils";
+import { PeersMap } from "../../components/Peers/PeersMap";
+import { useDebug } from "../../hooks/useDebug";
+import { PeersQuality } from "../../components/Peers/PeersQuality";
+import { PeersChart } from "../../components/Peers/PeersChart";
+import SuccessCircleIcon from "../../assets/icons/success-circle.svg?react";
+import ErrorCircleIcon from "../../assets/icons/error-circle.svg?react";
+import PeersIcon from "../../assets/icons/peers.svg?react";
-export const Route = createFileRoute("/dashboard/peers")({
- component: () => (
- (
-
- )}>
-
-
- ),
-});
+const throwOnError = true;
+
+export const PeersRoute = () => {
+ const { data } = useDebug(throwOnError);
+ const [ips, setIps] = useState >({});
+
+ const onPinAdd = useCallback((node: PeerNode, geo: PeerGeo) => {
+ const [ip = ""] = node.address.split(":");
+ setIps((ips) => ({ ...ips, [ip]: geo }));
+ }, []);
+
+ const [sortFn, setSortFn] = useState(() =>
+ PeerUtils.sortByBoolean("desc")
+ );
+
+ const onSortByCountry = (state: TabSortState) =>
+ setSortFn(() => PeerUtils.sortByCountry(state, ips));
+
+ const onSortActive = (state: TabSortState) =>
+ setSortFn(() => PeerUtils.sortByBoolean(state));
+
+ const headers = [
+ ["Country", onSortByCountry],
+ ["PeerId"],
+ ["Active", onSortActive],
+ ] satisfies [string, ((state: TabSortState) => void)?][];
+
+ const nodes = data?.table.nodes || [];
+ const sorted = sortFn ? nodes.slice().sort(sortFn) : nodes;
+
+ const rows = sorted.map((node) => {
+ const [ip = ""] = node.address.split(":");
+ const geo = ips[ip];
+
+ return (
+ ,
+ | {node.peerId} | ,
+
+ {node.seen ? (
+
+ Active
+
+ ) : (
+
+ Inactive
+
+ )}
+ | ,
+ ]}>
+ );
+ });
+
+ const actives = PeerUtils.countActives(sorted);
+ const degrees = PeerUtils.calculareDegrees(sorted);
+ const good = PeerUtils.isGoodQuality(actives);
+
+ return (
+
+
+
+
+
+ - Legend
+ - 1-3
+ - 3-5
+ - 5 +
+
+
+
+
+
+
+
+ );
+};
diff --git a/src/routes/dashboard/purchases.css b/src/routes/dashboard/purchases.css
index afb1ae9..c26a437 100644
--- a/src/routes/dashboard/purchases.css
+++ b/src/routes/dashboard/purchases.css
@@ -8,18 +8,20 @@
.table {
table thead tr th {
- background-color: #14141499;
+ background-color: rgba(20, 20, 20, 0.6);
+ }
+
+ @media (max-width: 800px) {
+ th:nth-child(2),
+ td:nth-child(2),
+ th:nth-child(3),
+ td:nth-child(3),
+ th:nth-child(5),
+ td:nth-child(5),
+ th:nth-child(6),
+ td:nth-child(6) {
+ display: none;
+ }
}
}
}
-
-.purchases-loader {
- margin: auto;
- display: block;
-}
-
-@media (max-width: 800px) {
- .purchases-modal {
- width: calc(100% - 2rem);
- }
-}
diff --git a/src/routes/dashboard/purchases.tsx b/src/routes/dashboard/purchases.tsx
index dbf0039..cde4d80 100644
--- a/src/routes/dashboard/purchases.tsx
+++ b/src/routes/dashboard/purchases.tsx
@@ -1,31 +1,24 @@
-import { createFileRoute } from "@tanstack/react-router";
import { StorageRequestCreate } from "../../components/StorageRequestSetup/StorageRequestCreate";
import "./purchases.css";
import { ErrorPlaceholder } from "../../components/ErrorPlaceholder/ErrorPlaceholder";
import { ErrorBoundary } from "@sentry/react";
import { PurchasesTable } from "../../components/Purchase/PurchasesTable";
-const Purchases = () => {
+export const PurchasesRoute = () => {
return (
-
- );
-};
-
-export const Route = createFileRoute("/dashboard/purchases")({
- component: () => (
(
)}>
-
+
- ),
-});
+ );
+};
diff --git a/src/routes/dashboard/requests.css b/src/routes/dashboard/requests.css
deleted file mode 100644
index c004805..0000000
--- a/src/routes/dashboard/requests.css
+++ /dev/null
@@ -1,7 +0,0 @@
-.requests {
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- background-color: var(--codex-background-light);
-}
diff --git a/src/routes/dashboard/requests.tsx b/src/routes/dashboard/requests.tsx
deleted file mode 100644
index f688115..0000000
--- a/src/routes/dashboard/requests.tsx
+++ /dev/null
@@ -1,15 +0,0 @@
-import { createFileRoute } from "@tanstack/react-router";
-import "./requests.css";
-import { StorageRequestSetup } from "../../components/StorageRequestSetup/StorageRequestSetup";
-
-export const Route = createFileRoute("/dashboard/requests")({
- component: () => {
- return (
-
- );
- },
-});
diff --git a/src/routes/dashboard/settings.css b/src/routes/dashboard/settings.css
index c4379c2..adcb085 100644
--- a/src/routes/dashboard/settings.css
+++ b/src/routes/dashboard/settings.css
@@ -24,7 +24,7 @@
.user-info {
padding-bottom: 16px;
margin-bottom: 16px;
- border-bottom: 1px solid #96969633;
+ border-bottom: 1px solid rgba(150, 150, 150, 0.2);
}
}
@@ -41,19 +41,8 @@
.address svg {
top: 55px;
}
-}
-/*
-.settings-title {
- font-weight: bold;
- font-size: 1.125rem;
- line-height: 1.75rem;
- margin-bottom: 0.75rem;
-}
-.settings-input {
- margin-bottom: 0.75rem;
+ .input input {
+ --codex-input-background-color: rgba(35, 35, 35, 1);
+ }
}
-
-.settings-debug-loader {
- margin: auto;
-} */
diff --git a/src/routes/dashboard/settings.tsx b/src/routes/dashboard/settings.tsx
index 182fe10..5478c67 100644
--- a/src/routes/dashboard/settings.tsx
+++ b/src/routes/dashboard/settings.tsx
@@ -1,4 +1,3 @@
-import { createFileRoute } from "@tanstack/react-router";
import "./settings.css";
import { ErrorBoundary } from "@sentry/react";
import { ErrorPlaceholder } from "../../components/ErrorPlaceholder/ErrorPlaceholder";
@@ -9,79 +8,40 @@ import Logo from "../../assets/icons/logo.svg?react";
import { Versions } from "../../components/Versions/Versions";
import { BackgroundImage } from "../../components/BackgroundImage/BackgroundImage";
-export const Route = createFileRoute("/dashboard/settings")({
- component: () => (
-
-
-
- Personalization
- (
-
- )}>
-
-
-
- Connection
-
- (
-
- )}>
- {}} />
-
-
-
-
-
- {/*
- (
-
- )}>
-
-
+export const SettingsRoute = () => (
+
+
+
+ Personalization
+ (
+
+ )}>
+
+
-
- {
- useEffect(() => {
- document.addEventListener("codexinvalidatequeries", resetError);
+ Connection
- return () => {
- document.removeEventListener(
- "codexinvalidatequeries",
- resetError
- );
- };
- }, [resetError]);
+ (
+
+ )}>
+ {}} />
+
+
- return (
-
- );
- }}>
-
-
- */}
-
- ),
-});
+
+
+);
diff --git a/src/routes/dashboard/wallet.css b/src/routes/dashboard/wallet.css
index d6fda3f..4092469 100644
--- a/src/routes/dashboard/wallet.css
+++ b/src/routes/dashboard/wallet.css
@@ -1,25 +1,39 @@
.wallet-page {
display: flex;
gap: 16px;
+ flex-wrap: wrap;
.card {
+ flex: 1;
filter: grayscale(30);
transition: filter 0.5s;
&:hover {
filter: none;
}
+
+ > ul li {
+ border-bottom: 1px solid rgba(150, 150, 150, 0.2);
+ margin-bottom: 16px;
+ padding-bottom: 16px;
+ }
}
.buttons {
- display: flex;
justify-content: space-between;
margin-top: 16px;
margin-bottom: 16px;
- border-top: 1px solid #96969633;
- border-bottom: 1px solid #96969633;
+ border-top: 1px solid rgba(150, 150, 150, 0.2);
+ border-bottom: 1px solid rgba(150, 150, 150, 0.2);
padding-top: 16px;
padding-bottom: 16px;
+ display: none;
+
+ @media (min-width: 801px) {
+ & {
+ display: flex;
+ }
+ }
div {
display: flex;
@@ -34,34 +48,30 @@
font-weight: 500;
line-height: 16px;
text-align: left;
- color: #969696;
+ color: rgba(150, 150, 150, 1);
}
}
span {
height: 36px;
width: 1px;
- background-color: #ffffff33;
+ background-color: rgb(255, 255, 255, 0.2);
margin: auto 0;
}
}
.button-icon {
- background-color: #2f2f2f;
+ background-color: rgb(47, 47, 47);
height: 60px;
width: 60px;
- color: #96969666;
- border: 0.75px solid #96969633;
+ color: rgb(150, 150, 150, 0.4);
+ border: 0.75px solid rgba(150, 150, 150, 0.2);
svg {
mix-blend-mode: unset;
}
}
- .card {
- flex: 1;
- }
-
.require-assistance {
max-height: 145px;
margin-top: 8px;
@@ -80,7 +90,7 @@
align-items: center;
justify-content: center;
gap: 8px;
- color: #969696;
+ color: rgba(150, 150, 150, 1);
font-size: 20px;
}
}
@@ -98,9 +108,6 @@
li {
display: flex;
gap: 48px;
- border-bottom: 1px solid #96969633;
- margin-bottom: 16px;
- padding-bottom: 16px;
div {
display: flex;
@@ -114,7 +121,7 @@
line-height: 20px;
letter-spacing: -0.006em;
text-align: left;
- color: #ffffffb2;
+ color: rgb(255, 255, 255, 0.7);
}
p {
diff --git a/src/routes/dashboard/wallet.tsx b/src/routes/dashboard/wallet.tsx
index 247d9bb..b43a61f 100644
--- a/src/routes/dashboard/wallet.tsx
+++ b/src/routes/dashboard/wallet.tsx
@@ -1,4 +1,3 @@
-import { createFileRoute } from "@tanstack/react-router";
import { ConnectedAccount } from "../../components/ConnectedAccount/ConnectedAccount";
import { Card } from "../../components/Card/Card";
import WalletIcon from "../../assets/icons/wallet.svg?react";
@@ -24,7 +23,7 @@ import {
Tabs,
} from "@codex-storage/marketplace-ui-components";
-const Wallet = () => {
+export const WalletRoute = () => {
const tabs: TabProps[] = [
{
label: "Tokens",
@@ -100,9 +99,7 @@ const Wallet = () => {
>
- }
- title="Activity">
+ } title="">
@@ -114,7 +111,3 @@ const Wallet = () => {
);
};
-
-export const Route = createFileRoute("/dashboard/wallet")({
- component: Wallet,
-});
diff --git a/src/routes/onboarding-checks.tsx b/src/routes/onboarding-checks.tsx
index 3d6a5ec..a6c3407 100644
--- a/src/routes/onboarding-checks.tsx
+++ b/src/routes/onboarding-checks.tsx
@@ -1,4 +1,3 @@
-import { createFileRoute, useNavigate } from "@tanstack/react-router";
import { useState } from "react";
import { attributes } from "../utils/attributes";
import ArrowRightCircle from "../assets/icons/arrow-circle.svg?react";
@@ -7,12 +6,13 @@ import { HealthChecks } from "../components/HealthChecks/HealthChecks";
import { useNetwork } from "../network/useNetwork";
import { WebStorage } from "../utils/web-storage";
import AlphaIcon from "../assets/icons/alpha.svg?react";
+import { useNavigate } from "react-router-dom";
-const OnBoardingChecks = () => {
+export const OnBoardingChecksRoute = () => {
const online = useNetwork();
const displayName = WebStorage.onBoarding.getDisplayName();
const [isStepValid, setIsStepValid] = useState(false);
- const navigate = useNavigate({ from: "/onboarding-checks" });
+ const navigate = useNavigate();
// useEffect(() => {
// const onKeyPress = (event: Event) => {
@@ -31,7 +31,7 @@ const OnBoardingChecks = () => {
const onNextStep = () => {
if (isStepValid) {
- navigate({ to: "/dashboard" });
+ navigate("/dashboard");
}
};
@@ -70,7 +70,3 @@ const OnBoardingChecks = () => {
);
};
-
-export const Route = createFileRoute("/onboarding-checks")({
- component: OnBoardingChecks,
-});
diff --git a/src/routes/onboarding-name.tsx b/src/routes/onboarding-name.tsx
index 834a2c6..dd10761 100644
--- a/src/routes/onboarding-name.tsx
+++ b/src/routes/onboarding-name.tsx
@@ -1,4 +1,3 @@
-import { createFileRoute, useNavigate } from "@tanstack/react-router";
import { useState } from "react";
import { OnBoardingLayout } from "../components/OnBoarding/OnBoardingLayout";
import { attributes } from "../utils/attributes";
@@ -6,36 +5,22 @@ import ArrowRightCircle from "../assets/icons/arrow-circle.svg?react";
import { UserInfo } from "../components/UserInfo/UserInfo";
import { WebStorage } from "../utils/web-storage";
import AlphaIcon from "../assets/icons/alpha.svg?react";
+import { useNavigate } from "react-router-dom";
-const OnBoardingName = () => {
+export const OnBoardingNameRoute = () => {
const [isStepValid, setIsStepValid] = useState(
!!WebStorage.onBoarding.getDisplayName()
);
- const navigate = useNavigate({ from: "/onboarding-name" });
+ const navigate = useNavigate();
const onNameChange = (value: string) => setIsStepValid(!!value);
const onNextStep = () => {
if (isStepValid) {
- navigate({ to: "/onboarding-checks" });
+ navigate("/onboarding-checks");
}
};
- // useEffect(() => {
- // const onKeyPress = (event: Event) => {
- // const e = event as KeyboardEvent;
- // if (e.key === "ArrowRight") {
- // navigate({ to: "/onboarding-checks" });
- // } else if (e.key === "ArrowLeft") {
- // navigate({ to: "/" });
- // }
- // };
-
- // document.addEventListener("keydown", onKeyPress);
-
- // return () => document.removeEventListener("keydown", onKeyPress);
- // }, [navigate]);
-
return (
<>
@@ -64,7 +49,3 @@ const OnBoardingName = () => {
);
};
-
-export const Route = createFileRoute("/onboarding-name")({
- component: OnBoardingName,
-});
diff --git a/src/routes/index.tsx b/src/routes/onboarding.tsx
similarity index 74%
rename from src/routes/index.tsx
rename to src/routes/onboarding.tsx
index a79445e..5abf615 100644
--- a/src/routes/index.tsx
+++ b/src/routes/onboarding.tsx
@@ -1,50 +1,28 @@
-import { createFileRoute, useNavigate } from "@tanstack/react-router";
import { useState } from "react";
import { Modal } from "@codex-storage/marketplace-ui-components";
-import { ArrowRight } from "lucide-react";
import { OnBoardingLayout } from "../components/OnBoarding/OnBoardingLayout";
import AlphaIcon from "../assets/icons/alpha.svg?react";
import AlphaText from "../assets/icons/alphatext.svg?react";
-import ArrowRightCircle from "../assets/icons/arrow-circle.svg?react";
+import ArrowCircleIcon from "../assets/icons/arrow-circle.svg?react";
+import { useNavigate } from "react-router-dom";
+import ArrowIcon from "../assets/icons/arrow-onboarding.svg?react";
-export const Route = createFileRoute("/")({
- component: Index,
- beforeLoad: async () => {
- // throw redirect({
- // to: "/dashboard",
- // });
- },
-});
-
-function Index() {
+export function OnBoardingRoute() {
const [modal, setModal] = useState(false);
- const navigate = useNavigate({ from: "/" });
+ const navigate = useNavigate();
const onLegalDisclaimerOpen = () => setModal(true);
const onLegalDisclaimerClose = () => setModal(false);
- const onNextStep = () => navigate({ to: "/onboarding-name" });
-
- // useEffect(() => {
- // const onKeyPress = (event: Event) => {
- // const e = event as KeyboardEvent;
- // if (e.key === "ArrowRight") {
- // navigate({ to: "/onboarding-name" });
- // }
- // };
-
- // document.addEventListener("keydown", onKeyPress);
-
- // return () => document.removeEventListener("keydown", onKeyPress);
- // }, [navigate]);
+ const onNextStep = () => navigate("/onboarding-name");
return (
<>
<>
-
+
-
+
>
diff --git a/src/routes/layout.css b/src/routes/root.css
similarity index 87%
rename from src/routes/layout.css
rename to src/routes/root.css
index 16ec77c..d2ef3bd 100644
--- a/src/routes/layout.css
+++ b/src/routes/root.css
@@ -5,12 +5,12 @@
> main {
flex: 1;
- background-color: #141414;
+ background-color: rgb(20, 20, 20);
> div {
- padding: 16px;
+ padding: 8px;
- @media (min-width: 1000px) {
+ @media (min-width: 800px) {
padding: 24px 48px;
}
}
@@ -50,7 +50,7 @@
font-weight: 500;
line-height: 24px;
letter-spacing: -0.011em;
- color: #99a0ae;
+ color: rgb(153, 160, 174);
}
.dashboard-welcome-versionValue {
diff --git a/src/routes/root.tsx b/src/routes/root.tsx
new file mode 100644
index 0000000..a446afe
--- /dev/null
+++ b/src/routes/root.tsx
@@ -0,0 +1,38 @@
+import "./root.css";
+import { Menu } from "../components/Menu/Menu";
+import { useCallback, useState } from "react";
+import { AppBar } from "../components/AppBar/AppBar";
+import { Backdrop } from "@codex-storage/marketplace-ui-components";
+import { Outlet, ScrollRestoration } from "react-router-dom";
+import { useIsMobile } from "../hooks/useMobile";
+
+export const Root = () => {
+ const isMobile = useIsMobile();
+ const [isExpanded, setIsExpanded] = useState(!isMobile);
+
+ const onExpanded = useCallback((val: boolean) => setIsExpanded(val), []);
+
+ const onIconClick = () => {
+ if (isMobile) {
+ setIsExpanded(true);
+ }
+ };
+
+ const onClose = () => setIsExpanded(false);
+
+ return (
+
+ );
+};
diff --git a/src/utils/arrays.ts b/src/utils/arrays.ts
deleted file mode 100644
index ab6ee1d..0000000
--- a/src/utils/arrays.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-export const Arrays = {
- toggle: (arr: Array, value: T) =>
- arr.includes(value) ? arr.filter(i => i !== value) : [...arr, value]
-}
\ No newline at end of file
diff --git a/src/utils/bytes.test.ts b/src/utils/bytes.test.ts
new file mode 100644
index 0000000..1c7f3e6
--- /dev/null
+++ b/src/utils/bytes.test.ts
@@ -0,0 +1,12 @@
+import { assert, describe, it } from "vitest";
+import { Bytes } from "./bytes";
+import { GB } from "./constants";
+
+describe("bytes", () => {
+ it("display the bytes", async () => {
+ assert.equal(Bytes.pretty(0), "0 B");
+ assert.equal(Bytes.pretty(512), "512.0 B");
+ assert.equal(Bytes.pretty(1025), "1.0 KB");
+ assert.equal(Bytes.pretty(GB), "1.0 GB");
+ });
+})
\ No newline at end of file
diff --git a/src/utils/bytes.ts b/src/utils/bytes.ts
index 7cf307a..a3171fe 100644
--- a/src/utils/bytes.ts
+++ b/src/utils/bytes.ts
@@ -1,14 +1,17 @@
-export const PrettyBytes = (bytes: number) => {
- const sizes = ["bytes", "KB", "MB", "GB", "TB"];
- if (bytes == 0) {
- return "0 b";
+export const Bytes = {
+ pretty(bytes: number) {
+ const sizes = ["B", "KB", "MB", "GB", "TB"];
+ if (bytes == 0) {
+ return "0 B";
+ }
+
+ const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)).toString());
+
+ if (i == 0) {
+ return bytes.toFixed(1) + " " + sizes[i];
+ }
+
+ return (bytes / Math.pow(1024, i)).toFixed(1) + " " + sizes[i];
}
- const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)).toString());
-
- if (i == 0) {
- return bytes + " " + sizes[i];
- }
-
- return (bytes / Math.pow(1024, i)).toFixed(1) + " " + sizes[i];
-};
+}
\ No newline at end of file
diff --git a/src/utils/dates.ts b/src/utils/dates.ts
deleted file mode 100644
index d34def9..0000000
--- a/src/utils/dates.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-export const Dates = {
- format(date: number) {
- if (!date) {
- return "-";
- }
-
- return new Intl.DateTimeFormat("en-GB", {
- dateStyle: "medium",
- timeStyle: "short",
- }).format(new Date(date * 1000));
- },
-};
diff --git a/src/utils/times.test.ts b/src/utils/times.test.ts
new file mode 100644
index 0000000..e2cb3e2
--- /dev/null
+++ b/src/utils/times.test.ts
@@ -0,0 +1,28 @@
+import { assert, describe, it } from "vitest";
+import { Times } from "./times";
+
+describe("times", () => {
+ it("display the times", async () => {
+ assert.equal(Times.pretty(0), "0 second");
+ assert.equal(Times.pretty(2), "2 seconds");
+ assert.equal(Times.pretty(60), "1 minute");
+ assert.equal(Times.pretty(90), "1.5 minutes");
+ assert.equal(Times.pretty(3600), "1 hour");
+ assert.equal(Times.pretty(3600 * 2), "2 hours");
+ assert.equal(Times.pretty(3600 * 24), "1 day");
+ assert.equal(Times.pretty(3600 * 36), "1.5 days");
+ assert.equal(Times.pretty(3600 * 24 * 30), "1 month");
+ });
+
+ it("guess the time unit", async () => {
+ assert.equal(Times.unit(0), "hours");
+ assert.equal(Times.unit(3600 * 24), "days");
+ assert.equal(Times.unit(3600 * 24 * 30), "months");
+ })
+
+ it("get the seconds for a time unit given", async () => {
+ assert.equal(Times.value("hours"), 3600);
+ assert.equal(Times.value("days"), 3600 * 24);
+ assert.equal(Times.value("months"), 3600 * 24 * 30);
+ })
+})
\ No newline at end of file
diff --git a/src/utils/times.ts b/src/utils/times.ts
index 1ff5c4d..055513b 100644
--- a/src/utils/times.ts
+++ b/src/utils/times.ts
@@ -6,31 +6,33 @@ export type TimesUnit =
| "hours"
| "seconds";
-const plural = (value: number, unit: TimesUnit) =>
- value > 1 ? value + ` ${unit}` : value + ` ${unit.slice(0, -1)}`;
+const plural = (value: number, unit: TimesUnit) => {
+ const val = Number.isInteger(value) ? value : value.toFixed(1)
+ return value > 1 ? val + ` ${unit}` : val + ` ${unit.slice(0, -1)}`;
+}
export const Times = {
toSeconds(value: number, unit: TimesUnit) {
- let seconds = value;
+ let val = value;
/* eslint-disable no-fallthrough */
switch (unit) {
// @ts-expect-error - We don't want to break
case "years":
- seconds *= 365;
+ val *= 365;
// @ts-expect-error - We don't want to break
case "months":
- seconds *= 30;
+ val *= 30;
// @ts-expect-error - We don't want to break
case "days":
- seconds *= 24;
+ val *= 24;
// @ts-expect-error - We don't want to break
case "hours":
- seconds *= 60;
+ val *= 60;
case "minutes":
- seconds *= 60;
+ val *= 60;
}
- return seconds;
+ return val;
},
pretty(value: number) {
@@ -62,7 +64,7 @@ export const Times = {
return plural(value, "seconds");
},
- unit(value: number) {
+ unit(value: number): "months" | "days" | "hours" {
let seconds = 30 * 24 * 60 * 60;
if (value >= seconds) {
@@ -77,7 +79,7 @@ export const Times = {
return "hours"
},
- unitValue(unit: "hours" | "days" | "months") {
+ value(unit: "hours" | "days" | "months") {
switch (unit) {
case "months": {
return 30 * 24 * 60 * 60
@@ -90,4 +92,5 @@ export const Times = {
}
}
}
+
};
diff --git a/vite.config.ts b/vite.config.ts
index b4a2237..b3c28f0 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -1,12 +1,12 @@
-import { TanStackRouterVite } from "@tanstack/router-plugin/vite";
-import react from "@vitejs/plugin-react";
+// import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";
import packageJson from "./package.json";
import svgr from "vite-plugin-svgr";
+import preact from '@preact/preset-vite'
// https://vitejs.dev/config/
export default defineConfig({
- plugins: [TanStackRouterVite(), react(), svgr({
+ plugins: [preact(), svgr({
svgrOptions: {
plugins: ["@svgr/plugin-svgo", "@svgr/plugin-jsx"],
svgoConfig: {
@@ -43,7 +43,8 @@ export default defineConfig({
alias: {
"../sdk/codex": "../proxy",
"../../sdk/codex": "../../proxy",
- "./port-forwarding.util": "../proxy",
+ react: 'preact/compat',
+ 'react-dom': 'preact/compat'
},
},
});
|