diff --git a/frontend/src/components/image/index.tsx b/frontend/src/components/image/index.tsx index b426cfe..50b6458 100644 --- a/frontend/src/components/image/index.tsx +++ b/frontend/src/components/image/index.tsx @@ -1,25 +1,105 @@ -import { Component } from "solid-js"; +import { Component, createSignal } from "solid-js"; import { base } from "../../network"; import { A } from "@solidjs/router"; +import { Dialog } from "@kobalte/core"; -export const ImageComponent: Component<{ ID: string }> = (props) => { - return ( - - - - ); +type ImageComponentProps = { + ID: string; + onDelete: (id: string) => void; +} + +export const ImageComponent: Component = (props) => { + const [isOpen, setIsOpen] = createSignal(false); + + return ( + <> +
+ + + + +
+ + + + + + + Confirm Delete + + + Are you sure you want to delete this image? + +
+ + + + +
+
+
+
+ + ); }; -export const ImageComponentFullHeight: Component<{ ID: string }> = (props) => { - return ( - - - - ); +export const ImageComponentFullHeight: Component = (props) => { + const [isOpen, setIsOpen] = createSignal(false); + + return ( + <> +
+ + + + +
+ + + + + + + Confirm Delete + + + Are you sure you want to delete this image? + +
+ + + + +
+
+
+
+ + ); }; diff --git a/frontend/src/contexts/SearchImageContext.tsx b/frontend/src/contexts/SearchImageContext.tsx index 83f5d7f..ac7171c 100644 --- a/frontend/src/contexts/SearchImageContext.tsx +++ b/frontend/src/contexts/SearchImageContext.tsx @@ -1,92 +1,91 @@ import { - type Accessor, - type Component, - type ParentProps, - createContext, - createEffect, - createMemo, - createResource, - useContext, + type Accessor, + type Component, + type ParentProps, + createContext, + createMemo, + createResource, + useContext, } from "solid-js"; -import { getUserImages, JustTheImageWhatAreTheseNames } from "../network"; +import { deleteImage, getUserImages, JustTheImageWhatAreTheseNames } from "../network"; export type SearchImageStore = { - imagesByDate: Accessor< - Array<{ date: Date; images: JustTheImageWhatAreTheseNames }> - >; + imagesByDate: Accessor< + Array<{ date: Date; images: JustTheImageWhatAreTheseNames }> + >; - lists: Accessor>["lists"]>; + lists: Accessor>["lists"]>; - userImages: Accessor; + userImages: Accessor; - processingImages: Accessor< - Awaited>["processingImages"] | undefined - >; + processingImages: Accessor< + Awaited>["processingImages"] | undefined + >; - onRefetchImages: () => void; + onRefetchImages: () => void; + onDeleteImage: (imageID: string) => void; }; const SearchImageContext = createContext(); export const SearchImageContextProvider: Component = (props) => { - const [data, { refetch }] = createResource(getUserImages); + const [data, { refetch }] = createResource(getUserImages); - createEffect(() => { - console.log(data()); - }); + const sortedImages = createMemo>( + () => { + const d = data(); + if (d == null) { + return []; + } - const sortedImages = createMemo>( - () => { - const d = data(); - if (d == null) { - return []; - } + // Sorted by day. But we could potentially add more in the future. + const buckets: Record = {}; - // Sorted by day. But we could potentially add more in the future. - const buckets: Record = {}; + for (const image of d.userImages) { + if (image.CreatedAt == null) { + continue; + } - for (const image of d.userImages) { - if (image.CreatedAt == null) { - continue; - } + const date = new Date(image.CreatedAt).toDateString(); + if (!(date in buckets)) { + buckets[date] = []; + } - const date = new Date(image.CreatedAt).toDateString(); - if (!(date in buckets)) { - buckets[date] = []; - } + buckets[date].push(image); + } - buckets[date].push(image); - } + return Object.entries(buckets) + .map(([date, images]) => ({ date: new Date(date), images })) + .sort((a, b) => b.date.getTime() - a.date.getTime()); + }, + ); - return Object.entries(buckets) - .map(([date, images]) => ({ date: new Date(date), images })) - .sort((a, b) => b.date.getTime() - a.date.getTime()); - }, - ); + const processingImages = () => data()?.processingImages ?? []; - const processingImages = () => data()?.processingImages ?? []; - - return ( - data()?.lists ?? [], - userImages: () => data()?.userImages ?? [], - processingImages, - onRefetchImages: refetch, - }} - > - {props.children} - - ); + return ( + data()?.lists ?? [], + userImages: () => data()?.userImages ?? [], + processingImages, + onRefetchImages: refetch, + onDeleteImage: (imageID: string) => { + deleteImage(imageID).then(refetch); + } + }} + > + {props.children} + + ); }; export const useSearchImageContext = () => { - const context = useContext(SearchImageContext); - if (context == null) { - throw new Error( - "Unreachable: We should always have a mounted context and no undefined values", - ); - } + const context = useContext(SearchImageContext); + if (context == null) { + throw new Error( + "Unreachable: We should always have a mounted context and no undefined values", + ); + } - return context; + return context; }; diff --git a/frontend/src/pages/all-images/index.tsx b/frontend/src/pages/all-images/index.tsx index 5e6a838..c588907 100644 --- a/frontend/src/pages/all-images/index.tsx +++ b/frontend/src/pages/all-images/index.tsx @@ -3,62 +3,63 @@ import { Component, For } from "solid-js"; import { createVirtualizer } from "@tanstack/solid-virtual"; import { ImageComponent } from "@components/image"; import { chunkRows } from "./chunk"; +import { deleteImage } from "@network/index"; type ImageOrDate = - | { type: "image"; ID: string[] } - | { type: "date"; date: Date }; + | { type: "image"; ID: string[] } + | { type: "date"; date: Date }; export const AllImages: Component = () => { - let scrollRef: HTMLDivElement | undefined; + let scrollRef: HTMLDivElement | undefined; - const { imagesByDate } = useSearchImageContext(); + const { imagesByDate, onDeleteImage } = useSearchImageContext(); - const items = () => { - const items: Array = []; + const items = () => { + const items: Array = []; - for (const { date, images } of imagesByDate()) { - items.push({ type: "date", date }); - const chunkedRows = chunkRows(3, images); - for (const chunk of chunkedRows) { - items.push({ type: "image", ID: chunk.map((c) => c.ImageID) }); - } - } + for (const { date, images } of imagesByDate()) { + items.push({ type: "date", date }); + const chunkedRows = chunkRows(3, images); + for (const chunk of chunkedRows) { + items.push({ type: "image", ID: chunk.map((c) => c.ImageID) }); + } + } - return items; - }; + return items; + }; - const rowVirtualizer = createVirtualizer({ - count: items().length, - estimateSize: () => 400, - getScrollElement: () => scrollRef!, - overscan: 3, - }); + const rowVirtualizer = createVirtualizer({ + count: items().length, + estimateSize: () => 400, + getScrollElement: () => scrollRef!, + overscan: 3, + }); - return ( -
-
- - {(i) => { - const item = items()[i.index]; - if (item.type === "image") { - return ( - {(id) => } - ); - } else { - return ( -

- {item.date.toDateString()} -

- ); - } - }} -
-
-
- ); + return ( +
+
+ + {(i) => { + const item = items()[i.index]; + if (item.type === "image") { + return ( + {(id) => } + ); + } else { + return ( +

+ {item.date.toDateString()} +

+ ); + } + }} +
+
+
+ ); }; diff --git a/frontend/src/pages/front/recent.tsx b/frontend/src/pages/front/recent.tsx index b22954c..4925179 100644 --- a/frontend/src/pages/front/recent.tsx +++ b/frontend/src/pages/front/recent.tsx @@ -1,28 +1,29 @@ import { Component, For } from "solid-js"; import { ImageComponent } from "@components/image"; import { useSearchImageContext } from "@contexts/SearchImageContext"; +import { deleteImage } from "@network/index"; const NUMBER_OF_MAX_RECENT_IMAGES = 10; export const Recent: Component = () => { - const { userImages } = useSearchImageContext(); + const { userImages, onDeleteImage } = useSearchImageContext(); - const latestImages = () => - userImages() - .sort( - (a, b) => - new Date(b.CreatedAt!).getTime() - new Date(a.CreatedAt!).getTime(), - ) - .slice(0, NUMBER_OF_MAX_RECENT_IMAGES); + const latestImages = () => + userImages() + .sort( + (a, b) => + new Date(b.CreatedAt!).getTime() - new Date(a.CreatedAt!).getTime(), + ) + .slice(0, NUMBER_OF_MAX_RECENT_IMAGES); - return ( -
-

Recent Screenshots

-
- - {(image) => } - -
-
- ); + return ( +
+

Recent Screenshots

+
+ + {(image) => } + +
+
+ ); }; diff --git a/frontend/src/pages/image/index.tsx b/frontend/src/pages/image/index.tsx index af435e5..2d80b50 100644 --- a/frontend/src/pages/image/index.tsx +++ b/frontend/src/pages/image/index.tsx @@ -4,35 +4,36 @@ import { useParams } from "@solidjs/router"; import { For, type Component } from "solid-js"; import SolidjsMarkdown from "solidjs-markdown"; import { ListCard } from "@components/list-card"; +import { deleteImage } from "@network/index"; export const ImagePage: Component = () => { - const { imageId } = useParams<{ imageId: string }>(); + const { imageId } = useParams<{ imageId: string }>(); - const { userImages, lists } = useSearchImageContext(); + const { userImages, lists, onDeleteImage } = useSearchImageContext(); - const image = () => userImages().find((i) => i.ImageID === imageId); + const image = () => userImages().find((i) => i.ImageID === imageId); - return ( -
-
- -
-
-

Description

-
- - {(imageList) => ( - l.ID === imageList.ListID)!} - /> - )} - -
-
-
-

Description

- {image()?.Image.Description} -
-
- ); + return ( +
+
+ +
+
+

Description

+
+ + {(imageList) => ( + l.ID === imageList.ListID)!} + /> + )} + +
+
+
+

Description

+ {image()?.Image.Description} +
+
+ ); }; diff --git a/frontend/src/pages/search/index.tsx b/frontend/src/pages/search/index.tsx index eb3b909..3c04d60 100644 --- a/frontend/src/pages/search/index.tsx +++ b/frontend/src/pages/search/index.tsx @@ -2,47 +2,50 @@ import { Component, createSignal, For } from "solid-js"; import { Search } from "@kobalte/core/search"; import { IconSearch } from "@tabler/icons-solidjs"; import { useSearch } from "./search"; -import { JustTheImageWhatAreTheseNames } from "@network/index"; +import { deleteImage, JustTheImageWhatAreTheseNames } from "@network/index"; import { ImageComponent } from "@components/image"; +import { useSearchImageContext } from "@contexts/SearchImageContext"; export const SearchPage: Component = () => { - const fuse = useSearch(); + const fuse = useSearch(); - const [searchItems, setSearchItems] = - createSignal([]); + const { onDeleteImage } = useSearchImageContext(); - return ( - { - setSearchItems( - fuse() - .search(e) - .map((i) => i.item), - ); - }} - > - - - - - - - - - - - - - - {(item) => } - - No result found - - - - ); + const [searchItems, setSearchItems] = + createSignal([]); + + return ( + { + setSearchItems( + fuse() + .search(e) + .map((i) => i.item), + ); + }} + > + + + + + + + + + + + + + + {(item) => } + + No result found + + + + ); };