diff --git a/web/src/components/Item.tsx b/web/src/components/Item.tsx
index 4cbddbb..2c5e1ef 100644
--- a/web/src/components/Item.tsx
+++ b/web/src/components/Item.tsx
@@ -5,20 +5,15 @@ import {
ArrowsClockwiseIcon,
CaretDownIcon,
CaretUpIcon,
- CheckCircleIcon,
- DownloadSimpleIcon,
TrashIcon,
} from "@phosphor-icons/react";
-import { useDownloadTorrentMutation } from "../api/useDownloadTorrentMutation";
import { useDeleteItemMutation } from "../api/useDeleteItemMutation";
import { useQueryClient } from "@tanstack/react-query";
import dayjs from "dayjs";
import relativeTime from "dayjs/plugin/relativeTime";
-import { humanFileSize } from "../utils/humanFileSize";
-import { useDeleteTorrentMutation } from "../api/useDeleteTorrentMutation";
import { useRefreshItemMutation } from "../api/useRefreshItemMutation";
import { Loader } from "./Loader";
-import { categories } from "../lib/categories";
+import { Torrent } from "./Torrent";
dayjs.extend(relativeTime);
@@ -34,9 +29,7 @@ export const Item = ({ item }: ItemProps) => {
const { data: torrents } = useItemTorrentsQuery(item.id, open);
const deleteMutation = useDeleteItemMutation();
- const downloadMutation = useDownloadTorrentMutation();
const refreshMutation = useRefreshItemMutation();
- const deleteTorrentMutation = useDeleteTorrentMutation();
const Icon = open ? CaretUpIcon : CaretDownIcon;
@@ -61,10 +54,6 @@ export const Item = ({ item }: ItemProps) => {
}
}, [item]);
- const handleDownloadTorrent = (torrentId: number) => {
- downloadMutation.mutate({ torrentId });
- };
-
const handleDelete = () => {
if (!confirm("Do you want to delete this item?")) return;
@@ -95,22 +84,6 @@ export const Item = ({ item }: ItemProps) => {
);
};
- const handleDeleteTorrent = (torrentId: number) => {
- deleteTorrentMutation.mutate(
- {
- id: torrentId,
- },
- {
- onSuccess() {
- queryClient.invalidateQueries({ queryKey: ["items"] });
- queryClient.invalidateQueries({
- queryKey: ["items", item.id, "torrents"],
- });
- },
- },
- );
- };
-
return (
{
{filteredTorrents && filteredTorrents.length > 0 ? (
filteredTorrents.map((torrent) => (
-
-
-
-
- {torrent.title}
- {" "}
- [{formatCategory(torrent.category)}] [{torrent.indexer}]
-
- {torrent.downloaded && (
-
-
-
- )}
-
-
-
- Seeds: {torrent.seeders}
- Peers: {torrent.peers}
-
- PubDate: {dayjs(torrent.pubdate).format("DD.MM.YYYY")} at{" "}
- {dayjs(torrent.pubdate).format("HH:mm")}
-
-
- {humanFileSize(torrent.size)}
-
-
+
))
) : (
No torrents yet
@@ -215,7 +146,3 @@ export const Item = ({ item }: ItemProps) => {
);
};
-
-const formatCategory = (category: number): string => {
- return categories[category as keyof typeof categories] || "";
-};
diff --git a/web/src/components/Torrent.tsx b/web/src/components/Torrent.tsx
new file mode 100644
index 0000000..b1db293
--- /dev/null
+++ b/web/src/components/Torrent.tsx
@@ -0,0 +1,116 @@
+import { useState } from "react";
+import type { ItemTorrent } from "../api/useItemTorrentsQuery";
+import { categories } from "../lib/categories";
+import {
+ ArrowSquareOutIcon,
+ CaretDownIcon,
+ CaretUpIcon,
+ CheckCircleIcon,
+ DownloadSimpleIcon,
+ TrashIcon,
+} from "@phosphor-icons/react";
+import dayjs from "dayjs";
+import { humanFileSize } from "../utils/humanFileSize";
+import { useDeleteTorrentMutation } from "../api/useDeleteTorrentMutation";
+import { useDownloadTorrentMutation } from "../api/useDownloadTorrentMutation";
+import { useQueryClient } from "@tanstack/react-query";
+
+export type TorrentProps = {
+ itemId: number;
+ torrent: ItemTorrent;
+};
+
+export const Torrent = ({ itemId, torrent }: TorrentProps) => {
+ const queryClient = useQueryClient();
+ const downloadMutation = useDownloadTorrentMutation();
+ const deleteMutation = useDeleteTorrentMutation();
+
+ const [open, setOpen] = useState(false);
+
+ const ChevronIcon = open ? CaretUpIcon : CaretDownIcon;
+
+ const handleDownload = () => {
+ downloadMutation.mutate({ torrentId: torrent.id });
+ };
+
+ const handleDelete = () => {
+ deleteMutation.mutate(
+ {
+ id: torrent.id,
+ },
+ {
+ onSuccess() {
+ queryClient.invalidateQueries({ queryKey: ["items"] });
+ queryClient.invalidateQueries({
+ queryKey: ["items", itemId, "torrents"],
+ });
+ },
+ },
+ );
+ };
+
+ return (
+
+
setOpen((prev) => !prev)}
+ >
+
{torrent.title}
+ {torrent.downloaded && (
+
+
+
+ )}
+
+ [{formatCategory(torrent.category)}]
+ {humanFileSize(torrent.size)}
+
+
+
+
+
+
+ {open && (
+
+
Indexer: {torrent.indexer}
+
Seeders: {torrent.seeders}
+
Peers: {torrent.peers}
+
+ Published: {dayjs(torrent.pubdate).format("DD.MM.YYYY")} at{" "}
+ {dayjs(torrent.pubdate).format("HH:mm")}
+
+
+
+ Open
+
+
+
+
+
+ )}
+
+ );
+};
+
+const formatCategory = (category: number): string => {
+ return categories[category as keyof typeof categories] || "";
+};