diff --git a/package-lock.json b/package-lock.json index e762154..af21257 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "0.0.7", "license": "MIT", "dependencies": { - "@codex-storage/marketplace-ui-components": "^0.0.33", + "@codex-storage/marketplace-ui-components": "^0.0.34", "@codex-storage/sdk-js": "^0.0.15", "@sentry/browser": "^8.32.0", "@sentry/react": "^8.31.0", @@ -379,9 +379,9 @@ "peer": true }, "node_modules/@codex-storage/marketplace-ui-components": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/@codex-storage/marketplace-ui-components/-/marketplace-ui-components-0.0.33.tgz", - "integrity": "sha512-Au/k1FNygejrcHNLdgghgxm8VuERb2bQsI0JjGaIdk4LGgTS0EuMCd0Y6fo6VuZeyuVPN/kFSWMVPBO5xdFEEw==", + "version": "0.0.34", + "resolved": "https://registry.npmjs.org/@codex-storage/marketplace-ui-components/-/marketplace-ui-components-0.0.34.tgz", + "integrity": "sha512-WRSgQU/OiERKBqpUIq95tgz1jKizM8fd28hottD4Ra8Z0gHkFZThxoVGad2pq96ha7U/Q/U+VEW+f+t4Z251rg==", "dependencies": { "lucide-react": "^0.453.0" }, diff --git a/package.json b/package.json index acae8f0..58b3f5f 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "React" ], "dependencies": { - "@codex-storage/marketplace-ui-components": "^0.0.33", + "@codex-storage/marketplace-ui-components": "^0.0.34", "@codex-storage/sdk-js": "^0.0.15", "@sentry/browser": "^8.32.0", "@sentry/react": "^8.31.0", diff --git a/src/components/CloseIcon/CloseIcon.tsx b/src/components/CloseIcon/CloseIcon.tsx new file mode 100644 index 0000000..932c469 --- /dev/null +++ b/src/components/CloseIcon/CloseIcon.tsx @@ -0,0 +1,15 @@ +export function CloseIcon() { + return ( + + + + ); +} diff --git a/src/components/ConnectedAccount/WalletLines.tsx b/src/components/ConnectedAccount/WalletLines.tsx index bd097f4..79be98a 100644 --- a/src/components/ConnectedAccount/WalletLines.tsx +++ b/src/components/ConnectedAccount/WalletLines.tsx @@ -9,13 +9,13 @@ export function WalletLines() { opacity="0.5" d="M16.8017 44.5368H0.231579C0.103681 44.5368 0 44.6405 0 44.7684C0 44.8963 0.103681 45 0.231579 45H679C681.209 45 683 43.2091 683 41V5C683 2.79086 681.209 1 679 1H644.034C643.689 1 643.345 1.04472 643.011 1.13303L560.776 22.8885C560.443 22.9768 560.099 23.0215 559.753 23.0215H532.049C531.504 23.0215 530.964 22.91 530.463 22.6937L480.993 1.32786C480.493 1.11157 479.953 1 479.408 1H428.397C427.753 1 427.117 1.15593 426.546 1.45451L386.125 22.567C385.553 22.8656 384.945 23.0215 384.3 23.0215H317.645C317.177 23.0215 316.73 23.1039 316.289 23.2648L274.515 38.5387C274.075 38.6996 273.61 38.782 273.141 38.782H244.777C244.302 38.782 243.831 38.6975 243.386 38.5324L202.234 23.2711C201.789 23.1061 201.318 23.0215 200.843 23.0215H164.28C163.623 23.0215 162.977 22.8599 162.397 22.5508L122.879 1.47072C122.299 1.16166 121.653 1 120.996 1H73.6247C72.7112 1 71.8252 1.31267 71.1141 1.88603L19.3123 43.6508C18.6011 44.2242 17.7152 44.5368 16.8017 44.5368Z" fill="url(#paint0_linear_401_31774)" - fill-opacity="0.06" + fillOpacity="0.06" /> - - + + diff --git a/src/components/Files/AllFilesIcon.tsx b/src/components/Files/AllFilesIcon.tsx new file mode 100644 index 0000000..1e50876 --- /dev/null +++ b/src/components/Files/AllFilesIcon.tsx @@ -0,0 +1,15 @@ +export function AllFilesIcon() { + return ( + + + + ); +} diff --git a/src/components/Files/ArchiveIcon.tsx b/src/components/Files/ArchiveIcon.tsx new file mode 100644 index 0000000..a64e83d --- /dev/null +++ b/src/components/Files/ArchiveIcon.tsx @@ -0,0 +1,15 @@ +export function ArchiveIcon() { + return ( + + + + ); +} diff --git a/src/components/Files/CidCopyButton.tsx b/src/components/Files/CidCopyButton.tsx index 12d61ab..54982a7 100644 --- a/src/components/Files/CidCopyButton.tsx +++ b/src/components/Files/CidCopyButton.tsx @@ -1,7 +1,7 @@ import { useRef, useState } from "react"; -import { COPY_DURATION, ICON_SIZE } from "../../utils/constants"; -import { Copy } from "lucide-react"; +import { COPY_DURATION } from "../../utils/constants"; import { Button } from "@codex-storage/marketplace-ui-components"; +import { CoypIcon } from "./CopyIcon"; type CopyButtonProps = { cid: string; @@ -27,13 +27,11 @@ export function CidCopyButton({ cid }: CopyButtonProps) { const label = copied ? "Copied !" : "Copy CID"; - const Icon = () => ; - return ( + Icon={CoypIcon}> ); } diff --git a/src/components/Files/CopyIcon.tsx b/src/components/Files/CopyIcon.tsx new file mode 100644 index 0000000..3e4a794 --- /dev/null +++ b/src/components/Files/CopyIcon.tsx @@ -0,0 +1,15 @@ +export function CoypIcon() { + return ( + + + + ); +} diff --git a/src/components/Files/DocumentIcon.tsx b/src/components/Files/DocumentIcon.tsx new file mode 100644 index 0000000..11d7078 --- /dev/null +++ b/src/components/Files/DocumentIcon.tsx @@ -0,0 +1,15 @@ +export function DocumentIcon() { + return ( + + + + ); +} diff --git a/src/components/Files/DownloadIcon.tsx b/src/components/Files/DownloadIcon.tsx new file mode 100644 index 0000000..8b73bf1 --- /dev/null +++ b/src/components/Files/DownloadIcon.tsx @@ -0,0 +1,15 @@ +export function DownloadIcon() { + return ( + + + + ); +} diff --git a/src/components/Files/FavoriteIcon.tsx b/src/components/Files/FavoriteIcon.tsx new file mode 100644 index 0000000..acc2447 --- /dev/null +++ b/src/components/Files/FavoriteIcon.tsx @@ -0,0 +1,15 @@ +export function FavoriteIcon() { + return ( + + + + ); +} diff --git a/src/components/Files/FileActions.css b/src/components/Files/FileActions.css new file mode 100644 index 0000000..242ffac --- /dev/null +++ b/src/components/Files/FileActions.css @@ -0,0 +1,19 @@ +.file-actions { + > div { + display: inline-flex; + align-items: center; + border: 1px solid var(--codex-border-color); + border-radius: var(--codex-border-radius); + padding: 0.5rem; + background-color: #14141499; + gap: 8px; + padding: 10px; + + .button-icon { + width: 40px; + height: 40px; + background-color: #2f2f2f; + border: 1px solid #96969633; + } + } +} diff --git a/src/components/Files/FileActions.tsx b/src/components/Files/FileActions.tsx index c520797..73eb14a 100644 --- a/src/components/Files/FileActions.tsx +++ b/src/components/Files/FileActions.tsx @@ -1,9 +1,10 @@ import { ButtonIcon, Cell } from "@codex-storage/marketplace-ui-components"; -import { Download, ReceiptText } from "lucide-react"; -import { ICON_SIZE } from "../../utils/constants"; import { FolderButton } from "./FolderButton"; import { CodexDataContent } from "@codex-storage/sdk-js"; import { CodexSdk } from "../../sdk/codex"; +import "./FileActions.css"; +import { DownloadIcon } from "./DownloadIcon"; +import { InfoFileIcon } from "./InfoFileIcon"; type Props = { content: CodexDataContent; @@ -21,15 +22,12 @@ export function FileActions({ const url = CodexSdk.url() + "/api/codex/v1/data/"; return ( - -
+ +
window.open(url + content.cid, "_blank")} - Icon={(props) => ( - - )}> + Icon={DownloadIcon}> [ @@ -42,7 +40,7 @@ export function FileActions({ onDetails(content.cid)} - Icon={() => }> + Icon={InfoFileIcon}>
); diff --git a/src/components/Files/FileCell.css b/src/components/Files/FileCell.css new file mode 100644 index 0000000..b0a4d65 --- /dev/null +++ b/src/components/Files/FileCell.css @@ -0,0 +1,22 @@ +.file-cell { + small { + word-break: break-all; + } + + > div { + display: flex; + gap: 12px; + align-items: center; + + > div { + flex: 1; + } + + .button-icon { + width: 40px; + height: 40px; + background-color: #14141499; + border: 1px solid #96969633; + } + } +} diff --git a/src/components/Files/FileCell.tsx b/src/components/Files/FileCell.tsx index 31c5a9e..f712189 100644 --- a/src/components/Files/FileCell.tsx +++ b/src/components/Files/FileCell.tsx @@ -7,6 +7,7 @@ import { import { CodexDataContent } from "@codex-storage/sdk-js"; import { Copy } from "lucide-react"; import { useState } from "react"; +import "./FileCell.css"; type Props = { content: CodexDataContent; @@ -22,23 +23,23 @@ export function FileCell({ content }: Props) { return ( <> - -
+ +
- {content.manifest.filename} -
- {content.cid} - onCopy(content.cid)} - animation="buzz" - Icon={(props) => ( - - )}> -
+

+ {content.manifest.filename} +

+

+ {content.cid} +

+ onCopy(content.cid)} + animation="buzz" + Icon={(props) => }>
diff --git a/src/components/Files/FileDetails.css b/src/components/Files/FileDetails.css index a38bb60..4672ece 100644 --- a/src/components/Files/FileDetails.css +++ b/src/components/Files/FileDetails.css @@ -1,16 +1,118 @@ -.fileDetails-header { - padding: 0.75rem 1.5rem; - border-bottom: 1px solid var(--codex-border-color); - display: flex; - align-items: center; -} +.file-details { + background-color: #232323; + border-left: 1px solid #96969633; + border-top-left-radius: 16px; + border-bottom-left-radius: 16px; + padding: 16px; + height: 100%; -.fileDetails-headerTitle { - flex-grow: 1; -} + header { + display: flex; + align-items: center; + font-family: Inter; + font-size: 16px; + font-weight: 500; + line-height: 24px; + letter-spacing: -0.011em; + text-align: left; -.fileDetails-body { - padding: 0; + span { + flex-grow: 1; + } + + .button-icon { + background-color: #2f2f2f; + border: 1px solid #96969633; + } + } + + .preview { + background-color: #14141499; + border: 1px solid #69696933; + height: 200px; + margin: auto; + border-radius: 10px; + margin-bottom: 16px; + + img { + max-width: 100%; + max-height: 100%; + margin: auto; + display: flex; + } + + figure { + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + height: 100%; + margin: 0; + + font-family: Inter; + font-size: 16px; + font-weight: 400; + line-height: 24px; + letter-spacing: -0.011em; + text-align: left; + color: #ffffff33; + + p { + margin-top: 8px; + } + } + } + + ul { + li { + grid-template-columns: repeat(4, minmax(0, 1fr)); + display: grid; + padding: 8px 0; + align-items: center; + + p:first-child { + font-family: Inter; + font-size: 14px; + font-weight: 700; + line-height: 20px; + letter-spacing: -0.006em; + text-align: left; + } + + p:nth-child(2) { + grid-column: span 2 / span 2; + font-family: Inter; + font-size: 14px; + font-weight: 400; + line-height: 20px; + letter-spacing: -0.006em; + text-align: left; + color: #ffffffcc; + } + + &:last-child p:nth-child(2) { + font-family: Inter; + font-size: 14px; + font-weight: 400; + line-height: 20px; + letter-spacing: -0.006em; + text-align: left; + + color: #6beca1; + } + } + } + + .buttons { + padding: 16px 0; + border-bottom: 1px solid #96969633; + display: flex; + gap: 16px; + + button { + flex: 1; + } + } } .fileDetails-grid { diff --git a/src/components/Files/FileDetails.tsx b/src/components/Files/FileDetails.tsx index 48464bb..745325c 100644 --- a/src/components/Files/FileDetails.tsx +++ b/src/components/Files/FileDetails.tsx @@ -2,18 +2,20 @@ import { ButtonIcon, Button, Sheets, + WebFileIcon, } from "@codex-storage/marketplace-ui-components"; import { CodexDataContent } from "@codex-storage/sdk-js"; import { PrettyBytes } from "../../utils/bytes"; -import { ICON_SIZE } from "../../utils/constants"; import { Dates } from "../../utils/dates"; import { CidCopyButton } from "./CidCopyButton"; import "./FileDetails.css"; -import { DownloadIcon, X } from "lucide-react"; import { CodexSdk } from "../../sdk/codex"; import { Files } from "../../utils/files"; import { useEffect, useState } from "react"; import { WebStorage } from "../../utils/web-storage"; +import { FileDetailsIcon } from "./FileDetailsIcon"; +import { CloseIcon } from "../CloseIcon/CloseIcon"; +import { DownloadIcon } from "./DownloadIcon"; type Props = { details: CodexDataContent | null; @@ -37,84 +39,85 @@ export function FileDetails({ onClose, details }: Props) { const url = CodexSdk.url() + "/api/codex/v1/data/"; - const Icon = () => ; - const onDownload = () => window.open(url + details?.cid, "_target"); return ( <> {details && ( - <> -
- File details - +
+
+ + File details + +
+ +
+ {Files.isImage(details.manifest.mimetype) ? ( + + ) : ( +
+ +

File Preview not available.

+
+ )}
- {Files.isImage(details.manifest.mimetype) && ( -
- -
- )} +
    +
  • +

    CID:

    +

    {details.cid}

    +
  • -
    -
    -

    CID:

    -

    {details.cid}

    -
    +
  • +

    File name:

    +

    {details.manifest.filename}

    +
  • -
    -

    File name:

    -

    - {details.manifest.filename} +

  • +

    Date:

    +

    {Dates.format(details.manifest.uploadedAt).toString()}

    +
  • + +
  • +

    Mimetype:

    +

    {details.manifest.mimetype}

    +
  • + +
  • +

    Size:

    +

    {PrettyBytes(details.manifest.datasetSize)}

    +
  • + +
  • +

    Protected:

    +

    {details.manifest.protected ? "Yes" : "No"}

    +
  • + +
  • +

    Used:

    +

    + {purchases} purchase(s)

    -
  • + +
-
-

Date:

-

- {Dates.format(details.manifest.uploadedAt).toString()} -

-
+
+ -
-

Mimetype:

-

- {details.manifest.mimetype} -

-
- -
-

Size:

-

- {PrettyBytes(details.manifest.datasetSize)} -

-
- -
-

Protected:

-

- {details.manifest.protected ? "Yes" : "No"} -

-
- -
-

Used:

-

- {purchases + " purchase(s)"} -

-
- -
- - - -
+
- +
)} diff --git a/src/components/Files/FileDetailsIcon.tsx b/src/components/Files/FileDetailsIcon.tsx new file mode 100644 index 0000000..794f1ab --- /dev/null +++ b/src/components/Files/FileDetailsIcon.tsx @@ -0,0 +1,15 @@ +export function FileDetailsIcon() { + return ( + + + + ); +} diff --git a/src/components/Files/FileFilters.css b/src/components/Files/FileFilters.css new file mode 100644 index 0000000..7606270 --- /dev/null +++ b/src/components/Files/FileFilters.css @@ -0,0 +1,35 @@ +.filter { + padding: 4px 8px; + gap: 8px; + border-radius: 6px; + border: 1px solid #96969633; + background-color: #2f2f2f; + font-family: Inter; + font-size: 12px; + font-weight: 500; + line-height: 16px; + text-align: left; + color: #969696; + text-transform: capitalize; + display: inline-flex; + align-items: center; + cursor: pointer; + transition: box-shadow 0.35s; + + &:hover { + box-shadow: 0 0 0 3px var(--codex-border-color); + } + + svg { + color: #969696; + } + + &.filter--active { + border-color: var(--codex-color-primary); + color: var(--codex-color-primary); + + svg { + color: var(--codex-color-primary); + } + } +} diff --git a/src/components/Files/FileFilters.tsx b/src/components/Files/FileFilters.tsx index 412fb94..fd98c44 100644 --- a/src/components/Files/FileFilters.tsx +++ b/src/components/Files/FileFilters.tsx @@ -1,7 +1,11 @@ import { CodexDataContent } from "@codex-storage/sdk-js"; import { Files } from "../../utils/files"; import { classnames } from "../../utils/classnames"; -import { Check } from "lucide-react"; +import "./FileFilters.css"; +import { ArchiveIcon } from "./ArchiveIcon"; +import { ImageIcon } from "./ImageIcon"; +import { VideoIcon } from "./VideoIcon"; +import { DocumentIcon } from "./DocumentIcon"; type Props = { files: CodexDataContent[]; @@ -9,28 +13,73 @@ type Props = { selected: string[]; }; +function getIcon(type: string) { + switch (type) { + case "image": { + return ; + } + + case "archive": { + return ; + } + + case "video": { + return ; + } + + default: { + return ; + } + } +} + +function getType(mimetype: string) { + if (Files.isArchive(mimetype)) { + return "archive"; + } + + if (Files.isImage(mimetype)) { + return "image"; + } + + if (Files.isVideo(mimetype)) { + return "video"; + } + + return "document"; +} + export function FilterFilters({ selected, files, onFilterToggle }: Props) { const filters = Array.from( new Set( files .filter((f) => f.manifest.mimetype !== "") - .map((file) => - Files.isArchive(file.manifest.mimetype) - ? "archive" - : Files.type(file.manifest.mimetype) - ) + .map((file) => getType(file.manifest.mimetype || "")) ) ); - return filters.map((type) => ( - selected.includes(f))] - )} - onClick={() => onFilterToggle(type)}> - {type} - - )); + const html = filters.map((type) => { + const count = files.reduce( + (acc, file) => + getType(file.manifest.mimetype || "") === type ? acc + 1 : acc, + 0 + ); + + return ( + onFilterToggle(type)}> + {getIcon(type)} + + {type + "s"} ({count}) + + + ); + }); + + return
{html}
; } diff --git a/src/components/Files/Files.css b/src/components/Files/Files.css index 9125700..b12183f 100644 --- a/src/components/Files/Files.css +++ b/src/components/Files/Files.css @@ -1,8 +1,29 @@ .files { - border-radius: var(--codex-border-radius); - border: 1px solid var(--codex-border-color); - background-color: var(--codex-background-secondary); - padding: 1rem 1.5rem; + main > section { + display: inline-flex; + justify-content: space-between; + align-items: center; + width: 100%; + gap: 16px; + + .tabs { + flex-basis: 75%; + } + } + + .filters { + margin-top: 16px; + gap: 16px; + display: flex; + } + + .button { + width: 105px; + } + + table thead tr th { + background-color: #14141499; + } } .files-cell-file { @@ -90,10 +111,6 @@ gap: 0.5rem; } -.files-fileBody { - margin-top: 1.25rem; -} - .files-folders { width: 200px; min-width: 0px; diff --git a/src/components/Files/Files.tsx b/src/components/Files/Files.tsx index 5e2b57e..1ea646c 100644 --- a/src/components/Files/Files.tsx +++ b/src/components/Files/Files.tsx @@ -1,4 +1,4 @@ -import { FilesIcon, Folder, Plus, X } from "lucide-react"; +import { Plus } from "lucide-react"; import { ChangeEvent, useEffect, useState } from "react"; import { PrettyBytes } from "../../utils/bytes"; import { Dates } from "../../utils/dates"; @@ -22,6 +22,9 @@ import { Files as F } from "../../utils/files.ts"; import { FilterFilters } from "./FileFilters.tsx"; import { FileCell } from "./FileCell.tsx"; import { FileActions } from "./FileActions.tsx"; +import { FilesIconOutline } from "../FilesIcon/FilesIcon.tsx"; +import { AllFilesIcon } from "./AllFilesIcon.tsx"; +import { FavoriteIcon } from "./FavoriteIcon.tsx"; type SortFn = (a: CodexDataContent, b: CodexDataContent) => number; @@ -82,17 +85,17 @@ export function Files() { setFolders([...folders, [folder, []]]); }; - const onFolderDelete = (val: string) => { - WebStorage.folders.delete(val); + // const onFolderDelete = (val: string) => { + // WebStorage.folders.delete(val); - const currentIndex = folders.findIndex(([name]) => name === val); + // const currentIndex = folders.findIndex(([name]) => name === val); - if (currentIndex + 1 == index) { - setIndex(index - 1); - } + // if (currentIndex + 1 == index) { + // setIndex(index - 1); + // } - setFolders(folders.filter(([name]) => name !== val)); - }; + // setFolders(folders.filter(([name]) => name !== val)); + // }; const onFolderToggle = (cid: string, folder: string) => { const current = folders.find(([name]) => name === folder); @@ -124,22 +127,22 @@ export function Files() { } }; - const tabs: TabProps[] = folders.map(([folder]) => ({ + const tabs: TabProps[] = folders.map(([folder], index) => ({ label: folder, - Icon: () => , - IconAfter: - folder === "Favorites" - ? undefined - : () => ( - { - e.preventDefault(); - e.stopPropagation(); + Icon: () => (index === 0 ? : null), + // IconAfter: + // folder === "Favorites" + // ? undefined + // : () => ( + // { + // e.preventDefault(); + // e.stopPropagation(); - onFolderDelete(folder); - }}> - ), + // onFolderDelete(folder); + // }}> + // ), })); const onSortByFilename = (state: TabSortState) => { @@ -200,8 +203,8 @@ export function Files() { : setSelectedFilters([...selectedFilters, filter]); tabs.unshift({ - label: "All files", - Icon: () => , + label: "All", + Icon: () => , }); const items = @@ -241,13 +244,17 @@ export function Files() { )) || []; return ( -
-
-
-
Files
+
+
+
+ +
Files
-
-
+
+
+
+ +
+ +
+
- -
-
- - - -
-
-
- - +
+
+ - + + ); } diff --git a/src/components/Files/FolderAdd.tsx b/src/components/Files/FolderAdd.tsx new file mode 100644 index 0000000..8c1585d --- /dev/null +++ b/src/components/Files/FolderAdd.tsx @@ -0,0 +1,15 @@ +export function FolderAdd() { + return ( + + + + ); +} diff --git a/src/components/Files/FolderButton.css b/src/components/Files/FolderButton.css index 237bc41..e26bf49 100644 --- a/src/components/Files/FolderButton.css +++ b/src/components/Files/FolderButton.css @@ -1,38 +1,41 @@ -.folderButton { - position: relative; -} +.folder-button { + > div { + position: absolute; + transform: translate(-110px, -75px); + opacity: 0; + transition: + transform 0.25s, + opacity 0.15s; + background-color: var(--codex-background); + padding: 0.5rem; + border-radius: var(--codex-border-radius); + width: 150px; + right: -40px; + border: 1px solid var(--codex-border-color); + z-index: -1; -.folderButton-options { - position: absolute; - transform: translateY(200px); - opacity: 0; - transition: - transform 0.25s, - opacity 0.15s; - background-color: var(--codex-background); - padding: 0.5rem; - border-radius: var(--codex-border-radius); - width: 150px; - right: -40px; - border: 1px solid var(--codex-border-color); -} + &[aria-expanded] { + z-index: 12; + transform: translate(-110px, -200px); + opacity: 1; + } -.folderButton-options[aria-expanded] { - z-index: 12; - transform: translateY(0px); - opacity: 1; -} + > div { + padding: 0.75rem; + transition: background-color 0.35s; + cursor: pointer; + border-radius: var(--codex-border-radius); + display: flex; + align-items: center; + justify-content: space-between; -.folderButton-option { - padding: 0.75rem; - transition: background-color 0.35s; - cursor: pointer; - border-radius: var(--codex-border-radius); - display: flex; - align-items: center; - justify-content: space-between; -} + &:hover { + background-color: var(--codex-background-light); + } + } -.folderButton-option:hover { - background-color: var(--codex-background-light); + svg { + color: var(--codex-color-primary); + } + } } diff --git a/src/components/Files/FolderButton.tsx b/src/components/Files/FolderButton.tsx index 45015a2..ad29489 100644 --- a/src/components/Files/FolderButton.tsx +++ b/src/components/Files/FolderButton.tsx @@ -1,8 +1,10 @@ import { Backdrop, ButtonIcon } from "@codex-storage/marketplace-ui-components"; -import { CheckCircle, Folder } from "lucide-react"; +import { CheckCircle } from "lucide-react"; import "./FolderButton.css"; import { useState } from "react"; import { attributes } from "../../utils/attributes"; +import { FolderAdd } from "./FolderAdd"; +import { classnames } from "../../utils/classnames"; type Props = { folders: [string, boolean][]; @@ -24,35 +26,28 @@ export function FolderButton({ folders, onFolderToggle }: Props) { ); return ( -
- + <> +
+ - ( - - )}> - -
- {folders.map(([folder, isActive]) => ( -
onFolderToggle(folder)}> -
{folder}
-
- {isActive && ( - - - - )} +
+ {folders.map(([folder, isActive]) => ( +
onFolderToggle(folder)}> + {folder} + {isActive && }
-
- ))} + ))} +
-
+ + ); } diff --git a/src/components/Files/ImageIcon.tsx b/src/components/Files/ImageIcon.tsx new file mode 100644 index 0000000..b83f769 --- /dev/null +++ b/src/components/Files/ImageIcon.tsx @@ -0,0 +1,15 @@ +export function ImageIcon() { + return ( + + + + ); +} diff --git a/src/components/Files/InfoFileIcon.tsx b/src/components/Files/InfoFileIcon.tsx new file mode 100644 index 0000000..9c22055 --- /dev/null +++ b/src/components/Files/InfoFileIcon.tsx @@ -0,0 +1,15 @@ +export function InfoFileIcon() { + return ( + + + + ); +} diff --git a/src/components/Files/VideoIcon.tsx b/src/components/Files/VideoIcon.tsx new file mode 100644 index 0000000..4ad16d2 --- /dev/null +++ b/src/components/Files/VideoIcon.tsx @@ -0,0 +1,15 @@ +export function VideoIcon() { + return ( + + + + ); +} diff --git a/src/components/FilesIcon/FilesIcon.tsx b/src/components/FilesIcon/FilesIcon.tsx new file mode 100644 index 0000000..34315cd --- /dev/null +++ b/src/components/FilesIcon/FilesIcon.tsx @@ -0,0 +1,34 @@ +type Props = { + width?: number; +}; + +export function FilesIcon({ width = 16 }: Props) { + return ( + + + + ); +} + +export function FilesIconOutline() { + return ( + + + + ); +} diff --git a/src/components/Menu/FilesIcon.tsx b/src/components/Menu/FilesIcon.tsx deleted file mode 100644 index cf011f8..0000000 --- a/src/components/Menu/FilesIcon.tsx +++ /dev/null @@ -1,15 +0,0 @@ -export function FilesIcon() { - return ( - - - - ); -} diff --git a/src/components/Menu/Menu.tsx b/src/components/Menu/Menu.tsx index 72c4d9d..bba89c5 100644 --- a/src/components/Menu/Menu.tsx +++ b/src/components/Menu/Menu.tsx @@ -8,7 +8,7 @@ import { classnames } from "../../utils/classnames"; import { Link } from "@tanstack/react-router"; import { HomeIcon } from "./HomeIcon"; import { WalletIcon } from "./WalletIcon"; -import { FilesIcon } from "./FilesIcon"; +import { FilesIcon } from "../FilesIcon/FilesIcon"; import { NodesIcon } from "./NodesIcon"; import { AnalyticsIcon } from "./AnalyticsIcon"; import { DeviceIcon } from "./DeviceIcon"; diff --git a/src/routes/dashboard/files.css b/src/routes/dashboard/files.css new file mode 100644 index 0000000..2bbaf15 --- /dev/null +++ b/src/routes/dashboard/files.css @@ -0,0 +1,17 @@ +.files-page { + display: flex; + flex-wrap: wrap; + gap: 16px; + + .files { + margin-bottom: 16px; + flex: 1 1 67%; + } + + .column { + display: flex; + flex-direction: column; + gap: 16px; + flex: 1 1 auto; + } +} diff --git a/src/routes/dashboard/files.tsx b/src/routes/dashboard/files.tsx index 08c54f4..abe7b44 100644 --- a/src/routes/dashboard/files.tsx +++ b/src/routes/dashboard/files.tsx @@ -1,5 +1,30 @@ import { createFileRoute } from "@tanstack/react-router"; +import { Files } from "../../components/Files/Files"; +import "./files.css"; +import { ErrorBoundary } from "@sentry/react"; +import { ErrorPlaceholder } from "../../components/ErrorPlaceholder/ErrorPlaceholder"; +import { ManifestFetchCard } from "../../components/ManifestFetch/ManifestFetchCard"; +import { UploadCard } from "../../components/UploadCard/UploadCard"; +import { Download } from "../../components/Download/Download"; export const Route = createFileRoute("/dashboard/files")({ - component: () =>
Hello /dashboard/files!
, + component: () => ( +
+ + +
+ ( + + )}> + + + + +
+
+ ), }); diff --git a/src/utils/files.ts b/src/utils/files.ts index fdd43a4..22c0b07 100644 --- a/src/utils/files.ts +++ b/src/utils/files.ts @@ -13,6 +13,9 @@ export const Files = { isImage(type: string | null) { return type && type.startsWith("image"); }, + isVideo(type: string | null) { + return type && type.startsWith("video"); + }, type(mimetype: string | null) { const [type] = mimetype?.split("/") || [] return type