refactor: list -> stack
This commit is contained in:
@ -53,7 +53,7 @@ func (h *StackHandler) getStackItems(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
stackID, err := middleware.GetPathParamID(h.logger, "listID", w, r)
|
stackID, err := middleware.GetPathParamID(h.logger, "stackID", w, r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -86,7 +86,7 @@ func (h *StackHandler) deleteStack(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
stackID, err := middleware.GetPathParamID(h.logger, "listID", w, r)
|
stackID, err := middleware.GetPathParamID(h.logger, "stackID", w, r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ import {
|
|||||||
Settings,
|
Settings,
|
||||||
SearchPage,
|
SearchPage,
|
||||||
AllImages,
|
AllImages,
|
||||||
List,
|
Stack,
|
||||||
} from "./pages";
|
} from "./pages";
|
||||||
import { SearchImageContextProvider } from "@contexts/SearchImageContext";
|
import { SearchImageContextProvider } from "@contexts/SearchImageContext";
|
||||||
import { WithNotifications } from "@contexts/Notifications";
|
import { WithNotifications } from "@contexts/Notifications";
|
||||||
@ -41,7 +41,7 @@ export const App = () => {
|
|||||||
path="/image/:imageId"
|
path="/image/:imageId"
|
||||||
component={ImagePage}
|
component={ImagePage}
|
||||||
/>
|
/>
|
||||||
<Route path="/list/:listId" component={List} />
|
<Route path="/stack/:stackID" component={Stack} />
|
||||||
<Route path="/settings" component={Settings} />
|
<Route path="/settings" component={Settings} />
|
||||||
</Route>
|
</Route>
|
||||||
</Route>
|
</Route>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { List } from "@network/index";
|
import { Stack } from "@network/index";
|
||||||
import { Component } from "solid-js";
|
import { Component } from "solid-js";
|
||||||
import fastHashCode from "../../utils/hash";
|
import fastHashCode from "../../utils/hash";
|
||||||
import { A } from "@solidjs/router";
|
import { A } from "@solidjs/router";
|
||||||
@ -17,19 +17,19 @@ const colors = [
|
|||||||
"bg-pink-50",
|
"bg-pink-50",
|
||||||
];
|
];
|
||||||
|
|
||||||
export const StackCard: Component<{ list: List }> = (props) => {
|
export const StackCard: Component<{ stack: Stack }> = (props) => {
|
||||||
return (
|
return (
|
||||||
<A
|
<A
|
||||||
href={`/list/${props.list.ID}`}
|
href={`/stack/${props.stack.ID}`}
|
||||||
class={
|
class={
|
||||||
"flex flex-col p-4 border border-neutral-200 rounded-lg " +
|
"flex flex-col p-4 border border-neutral-200 rounded-lg " +
|
||||||
colors[
|
colors[
|
||||||
fastHashCode(props.list.Name, { forcePositive: true }) % colors.length
|
fastHashCode(props.stack.Name, { forcePositive: true }) % colors.length
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<p class="text-xl font-bold">{props.list.Name}</p>
|
<p class="text-xl font-bold">{props.stack.Name}</p>
|
||||||
<p class="text-lg">{props.list.Images.length}</p>
|
<p class="text-lg">{props.stack.Images.length}</p>
|
||||||
</A>
|
</A>
|
||||||
);
|
);
|
||||||
};
|
};
|
@ -133,7 +133,7 @@ export const deleteStackItem = async (
|
|||||||
await fetch(request);
|
await fetch(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const deleteList = async (listID: string): Promise<void> => {
|
export const deleteStack = async (listID: string): Promise<void> => {
|
||||||
const request = await getBaseAuthorizedRequest({
|
const request = await getBaseAuthorizedRequest({
|
||||||
path: `stacks/${listID}`,
|
path: `stacks/${listID}`,
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
@ -238,7 +238,7 @@ const stackValidator = strictObject({
|
|||||||
SchemaItems: array(stackSchemaItem),
|
SchemaItems: array(stackSchemaItem),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type List = InferOutput<typeof stackValidator>;
|
export type Stack = InferOutput<typeof stackValidator>;
|
||||||
|
|
||||||
const imageRequestValidator = strictObject({
|
const imageRequestValidator = strictObject({
|
||||||
UserImages: array(userImageValidator),
|
UserImages: array(userImageValidator),
|
||||||
@ -303,13 +303,13 @@ export const postCode = async (
|
|||||||
return parsedRes.output;
|
return parsedRes.output;
|
||||||
};
|
};
|
||||||
|
|
||||||
export class ReachedListLimit extends Error {
|
export class ReachedStackLimit extends Error {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const createList = async (
|
export const createStack = async (
|
||||||
title: string,
|
title: string,
|
||||||
description: string,
|
description: string,
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
@ -323,6 +323,6 @@ export const createList = async (
|
|||||||
|
|
||||||
const res = await fetch(request);
|
const res = await fetch(request);
|
||||||
if (!res.ok && res.status == 429) {
|
if (!res.ok && res.status == 429) {
|
||||||
throw new ReachedListLimit();
|
throw new ReachedStackLimit();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { Component, For, createSignal } from "solid-js";
|
import { Component, For, createSignal } from "solid-js";
|
||||||
import { useSearchImageContext } from "@contexts/SearchImageContext";
|
import { useSearchImageContext } from "@contexts/SearchImageContext";
|
||||||
import { StackCard } from "@components/list-card";
|
|
||||||
import { Button } from "@kobalte/core/button";
|
import { Button } from "@kobalte/core/button";
|
||||||
import { Dialog } from "@kobalte/core/dialog";
|
import { Dialog } from "@kobalte/core/dialog";
|
||||||
import { createList, ReachedListLimit } from "../../network";
|
import { createStack, ReachedStackLimit } from "../../network";
|
||||||
import { createToast } from "../../utils/show-toast";
|
import { createToast } from "../../utils/show-toast";
|
||||||
|
import { StackCard } from "@components/stack-card";
|
||||||
|
|
||||||
export const Categories: Component = () => {
|
export const Categories: Component = () => {
|
||||||
const { stacks, onRefetchImages } = useSearchImageContext();
|
const { stacks, onRefetchImages } = useSearchImageContext();
|
||||||
@ -15,20 +15,20 @@ export const Categories: Component = () => {
|
|||||||
const [isCreating, setIsCreating] = createSignal(false);
|
const [isCreating, setIsCreating] = createSignal(false);
|
||||||
const [showForm, setShowForm] = createSignal(false);
|
const [showForm, setShowForm] = createSignal(false);
|
||||||
|
|
||||||
const handleCreateList = async () => {
|
const handleCreatestack = async () => {
|
||||||
if (description().trim().length === 0 || title().trim().length === 0)
|
if (description().trim().length === 0 || title().trim().length === 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
setIsCreating(true);
|
setIsCreating(true);
|
||||||
try {
|
try {
|
||||||
await createList(title().trim(), description().trim());
|
await createStack(title().trim(), description().trim());
|
||||||
setTitle("");
|
setTitle("");
|
||||||
setDescription("");
|
setDescription("");
|
||||||
setShowForm(false);
|
setShowForm(false);
|
||||||
onRefetchImages(); // Refresh the stacks
|
onRefetchImages(); // Refresh the stacks
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to create list:", error);
|
console.error("Failed to create stack:", error);
|
||||||
if (error instanceof ReachedListLimit) {
|
if (error instanceof ReachedStackLimit) {
|
||||||
createToast("Reached limit!", "You've reached your limit for new stacks");
|
createToast("Reached limit!", "You've reached your limit for new stacks");
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
@ -40,7 +40,7 @@ export const Categories: Component = () => {
|
|||||||
<div class="rounded-xl bg-white p-4 flex flex-col gap-2">
|
<div class="rounded-xl bg-white p-4 flex flex-col gap-2">
|
||||||
<h2 class="text-xl font-bold">Generated stacks</h2>
|
<h2 class="text-xl font-bold">Generated stacks</h2>
|
||||||
<div class="w-full grid grid-cols-3 auto-rows-[minmax(100px,1fr)] gap-4">
|
<div class="w-full grid grid-cols-3 auto-rows-[minmax(100px,1fr)] gap-4">
|
||||||
<For each={stacks()}>{(list) => <StackCard list={list} />}</For>
|
<For each={stacks()}>{(stack) => <StackCard stack={stack} />}</For>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
@ -48,7 +48,7 @@ export const Categories: Component = () => {
|
|||||||
class="px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 transition-colors font-medium shadow-sm hover:shadow-md"
|
class="px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 transition-colors font-medium shadow-sm hover:shadow-md"
|
||||||
onClick={() => setShowForm(true)}
|
onClick={() => setShowForm(true)}
|
||||||
>
|
>
|
||||||
+ Create List
|
+ Create stack
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -59,25 +59,25 @@ export const Categories: Component = () => {
|
|||||||
<Dialog.Content class="bg-white rounded-lg shadow-xl max-w-md w-full max-h-[90vh] overflow-y-auto">
|
<Dialog.Content class="bg-white rounded-lg shadow-xl max-w-md w-full max-h-[90vh] overflow-y-auto">
|
||||||
<div class="p-6">
|
<div class="p-6">
|
||||||
<Dialog.Title class="text-xl font-bold text-neutral-900 mb-4">
|
<Dialog.Title class="text-xl font-bold text-neutral-900 mb-4">
|
||||||
Create New List
|
Create New stack
|
||||||
</Dialog.Title>
|
</Dialog.Title>
|
||||||
|
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
<div>
|
<div>
|
||||||
<label
|
<label
|
||||||
for="list-title"
|
for="stack-title"
|
||||||
class="block text-sm font-medium text-neutral-700 mb-2"
|
class="block text-sm font-medium text-neutral-700 mb-2"
|
||||||
>
|
>
|
||||||
List Title
|
stack Title
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
id="list-title"
|
id="stack-title"
|
||||||
type="text"
|
type="text"
|
||||||
value={title()}
|
value={title()}
|
||||||
onInput={(e) =>
|
onInput={(e) =>
|
||||||
setTitle(e.target.value)
|
setTitle(e.target.value)
|
||||||
}
|
}
|
||||||
placeholder="Enter a title for your list"
|
placeholder="Enter a title for your stack"
|
||||||
class="w-full p-3 border border-neutral-300 rounded-lg focus:ring-2 focus:ring-indigo-600 focus:border-transparent transition-colors"
|
class="w-full p-3 border border-neutral-300 rounded-lg focus:ring-2 focus:ring-indigo-600 focus:border-transparent transition-colors"
|
||||||
disabled={isCreating()}
|
disabled={isCreating()}
|
||||||
/>
|
/>
|
||||||
@ -85,18 +85,18 @@ export const Categories: Component = () => {
|
|||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label
|
<label
|
||||||
for="list-description"
|
for="stack-description"
|
||||||
class="block text-sm font-medium text-neutral-700 mb-2"
|
class="block text-sm font-medium text-neutral-700 mb-2"
|
||||||
>
|
>
|
||||||
List Description
|
stack Description
|
||||||
</label>
|
</label>
|
||||||
<textarea
|
<textarea
|
||||||
id="list-description"
|
id="stack-description"
|
||||||
value={description()}
|
value={description()}
|
||||||
onInput={(e) =>
|
onInput={(e) =>
|
||||||
setDescription(e.target.value)
|
setDescription(e.target.value)
|
||||||
}
|
}
|
||||||
placeholder="Describe what kind of list you want to create (e.g., 'A list of my favorite recipes' or 'Photos from my vacation')"
|
placeholder="Describe what kind of stack you want to create (e.g., 'A list of my favorite recipes' or 'Photos from my vacation')"
|
||||||
class="w-full p-3 border border-neutral-300 rounded-lg resize-none focus:ring-2 focus:ring-indigo-600 focus:border-transparent transition-colors"
|
class="w-full p-3 border border-neutral-300 rounded-lg resize-none focus:ring-2 focus:ring-indigo-600 focus:border-transparent transition-colors"
|
||||||
rows="4"
|
rows="4"
|
||||||
disabled={isCreating()}
|
disabled={isCreating()}
|
||||||
@ -107,7 +107,7 @@ export const Categories: Component = () => {
|
|||||||
<div class="flex gap-3 mt-6">
|
<div class="flex gap-3 mt-6">
|
||||||
<Button
|
<Button
|
||||||
class="flex-1 px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 transition-colors disabled:opacity-50 font-medium shadow-sm hover:shadow-md"
|
class="flex-1 px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 transition-colors disabled:opacity-50 font-medium shadow-sm hover:shadow-md"
|
||||||
onClick={handleCreateList}
|
onClick={handleCreatestack}
|
||||||
disabled={
|
disabled={
|
||||||
isCreating() ||
|
isCreating() ||
|
||||||
!title().trim() ||
|
!title().trim() ||
|
||||||
@ -116,7 +116,7 @@ export const Categories: Component = () => {
|
|||||||
>
|
>
|
||||||
{isCreating()
|
{isCreating()
|
||||||
? "Creating..."
|
? "Creating..."
|
||||||
: "Create List"}
|
: "Create stack"}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
class="px-4 py-2 bg-neutral-300 text-neutral-700 rounded-lg hover:bg-neutral-400 transition-colors font-medium"
|
class="px-4 py-2 bg-neutral-300 text-neutral-700 rounded-lg hover:bg-neutral-400 transition-colors font-medium"
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { ImageComponentFullHeight } from "@components/image";
|
import { ImageComponentFullHeight } from "@components/image";
|
||||||
|
import { StackCard } from "@components/stack-card";
|
||||||
import { useSearchImageContext } from "@contexts/SearchImageContext";
|
import { useSearchImageContext } from "@contexts/SearchImageContext";
|
||||||
import { useNavigate, useParams } from "@solidjs/router";
|
import { useNavigate, useParams } from "@solidjs/router";
|
||||||
import { For, type Component } from "solid-js";
|
import { For, type Component } from "solid-js";
|
||||||
import SolidjsMarkdown from "solidjs-markdown";
|
import SolidjsMarkdown from "solidjs-markdown";
|
||||||
import { StackCard } from "@components/list-card";
|
|
||||||
|
|
||||||
export const ImagePage: Component = () => {
|
export const ImagePage: Component = () => {
|
||||||
const { imageId } = useParams<{ imageId: string }>();
|
const { imageId } = useParams<{ imageId: string }>();
|
||||||
@ -27,7 +27,7 @@ export const ImagePage: Component = () => {
|
|||||||
<For each={image()?.ImageStacks}>
|
<For each={image()?.ImageStacks}>
|
||||||
{(imageList) => (
|
{(imageList) => (
|
||||||
<StackCard
|
<StackCard
|
||||||
list={stacks().find((l) => l.ID === imageList.ListID)!}
|
stack={stacks().find((l) => l.ID === imageList.ListID)!}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</For>
|
</For>
|
||||||
|
@ -4,4 +4,4 @@ export * from "./settings";
|
|||||||
export * from "./login";
|
export * from "./login";
|
||||||
export * from "./search";
|
export * from "./search";
|
||||||
export * from "./all-images";
|
export * from "./all-images";
|
||||||
export * from "./list";
|
export * from "./stack";
|
||||||
|
@ -8,7 +8,7 @@ import {
|
|||||||
createResource,
|
createResource,
|
||||||
createSignal,
|
createSignal,
|
||||||
} from "solid-js";
|
} from "solid-js";
|
||||||
import { base, deleteList, getAccessToken } from "../../network";
|
import { base, deleteStack, getAccessToken } from "../../network";
|
||||||
import { Dialog } from "@kobalte/core";
|
import { Dialog } from "@kobalte/core";
|
||||||
|
|
||||||
const DeleteButton: Component<{ onDelete: () => void }> = (props) => {
|
const DeleteButton: Component<{ onDelete: () => void }> = (props) => {
|
||||||
@ -57,7 +57,7 @@ const DeleteButton: Component<{ onDelete: () => void }> = (props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const DeleteListButton: Component<{ onDelete: () => void }> = (props) => {
|
const DeleteStackButton: Component<{ onDelete: () => void }> = (props) => {
|
||||||
const [isOpen, setIsOpen] = createSignal(false);
|
const [isOpen, setIsOpen] = createSignal(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -67,7 +67,7 @@ const DeleteListButton: Component<{ onDelete: () => void }> = (props) => {
|
|||||||
class="text-white bg-red-600 hover:bg-red-700 rounded px-3 py-2 text-sm font-medium"
|
class="text-white bg-red-600 hover:bg-red-700 rounded px-3 py-2 text-sm font-medium"
|
||||||
onClick={() => setIsOpen(true)}
|
onClick={() => setIsOpen(true)}
|
||||||
>
|
>
|
||||||
Delete List
|
Delete Stack
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<Dialog.Root open={isOpen()} onOpenChange={setIsOpen}>
|
<Dialog.Root open={isOpen()} onOpenChange={setIsOpen}>
|
||||||
@ -76,7 +76,7 @@ const DeleteListButton: Component<{ onDelete: () => void }> = (props) => {
|
|||||||
<div class="fixed inset-0 z-50 flex items-center justify-center p-4">
|
<div class="fixed inset-0 z-50 flex items-center justify-center p-4">
|
||||||
<Dialog.Content class="bg-white rounded-lg shadow-xl max-w-md w-full p-6">
|
<Dialog.Content class="bg-white rounded-lg shadow-xl max-w-md w-full p-6">
|
||||||
<Dialog.Title class="text-lg font-bold mb-2">
|
<Dialog.Title class="text-lg font-bold mb-2">
|
||||||
Confirm Delete List
|
Confirm Delete Stack
|
||||||
</Dialog.Title>
|
</Dialog.Title>
|
||||||
<Dialog.Description class="mb-4">
|
<Dialog.Description class="mb-4">
|
||||||
Are you sure you want to delete this entire
|
Are you sure you want to delete this entire
|
||||||
@ -92,7 +92,7 @@ const DeleteListButton: Component<{ onDelete: () => void }> = (props) => {
|
|||||||
class="px-4 py-2 bg-red-600 text-white rounded hover:bg-red-700"
|
class="px-4 py-2 bg-red-600 text-white rounded hover:bg-red-700"
|
||||||
onClick={props.onDelete}
|
onClick={props.onDelete}
|
||||||
>
|
>
|
||||||
Delete List
|
Delete Stack
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</Dialog.Content>
|
</Dialog.Content>
|
||||||
@ -103,39 +103,39 @@ const DeleteListButton: Component<{ onDelete: () => void }> = (props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const List: Component = () => {
|
export const Stack: Component = () => {
|
||||||
const { listId } = useParams();
|
const { stackID } = useParams();
|
||||||
const nav = useNavigate();
|
const nav = useNavigate();
|
||||||
|
|
||||||
const { stacks, onDeleteImageFromStack } = useSearchImageContext();
|
const { stacks, onDeleteImageFromStack } = useSearchImageContext();
|
||||||
|
|
||||||
const [accessToken] = createResource(getAccessToken);
|
const [accessToken] = createResource(getAccessToken);
|
||||||
|
|
||||||
const list = () => stacks().find((l) => l.ID === listId);
|
const stack = () => stacks().find((l) => l.ID === stackID);
|
||||||
|
|
||||||
const handleDeleteList = async () => {
|
const handleDeleteStack = async () => {
|
||||||
await deleteList(listId)
|
await deleteStack(stackID)
|
||||||
nav("/");
|
nav("/");
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Suspense>
|
<Suspense>
|
||||||
<Show when={list()} fallback="List could not be found">
|
<Show when={stack()} fallback="Stack could not be found">
|
||||||
{(l) => (
|
{(s) => (
|
||||||
<div class="w-full h-full bg-white rounded-lg shadow-sm border border-neutral-200 overflow-hidden">
|
<div class="w-full h-full bg-white rounded-lg shadow-sm border border-neutral-200 overflow-hidden">
|
||||||
<div class="px-6 py-4 border-b border-neutral-200 bg-neutral-50">
|
<div class="px-6 py-4 border-b border-neutral-200 bg-neutral-50">
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
<h1 class="text-xl font-semibold text-neutral-900">
|
<h1 class="text-xl font-semibold text-neutral-900">
|
||||||
{l().Name}
|
{s().Name}
|
||||||
</h1>
|
</h1>
|
||||||
<Show when={l().Description}>
|
<Show when={s().Description}>
|
||||||
<p class="text-sm text-neutral-600 mt-1">
|
<p class="text-sm text-neutral-600 mt-1">
|
||||||
{l().Description}
|
{s().Description}
|
||||||
</p>
|
</p>
|
||||||
</Show>
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
<DeleteListButton onDelete={handleDeleteList} />
|
<DeleteStackButton onDelete={handleDeleteStack} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
@ -148,11 +148,11 @@ export const List: Component = () => {
|
|||||||
<th class="px-6 py-4 text-left text-sm font-semibold text-neutral-900 border-r border-neutral-200 min-w-40">
|
<th class="px-6 py-4 text-left text-sm font-semibold text-neutral-900 border-r border-neutral-200 min-w-40">
|
||||||
Image
|
Image
|
||||||
</th>
|
</th>
|
||||||
<For each={l().SchemaItems}>
|
<For each={s().SchemaItems}>
|
||||||
{(item, index) => (
|
{(item, index) => (
|
||||||
<th
|
<th
|
||||||
class={`px-6 py-4 text-left text-sm font-semibold text-neutral-900 min-w-32 ${index() <
|
class={`px-6 py-4 text-left text-sm font-semibold text-neutral-900 min-w-32 ${index() <
|
||||||
l().SchemaItems
|
s().SchemaItems
|
||||||
.length -
|
.length -
|
||||||
1
|
1
|
||||||
? "border-r border-neutral-200"
|
? "border-r border-neutral-200"
|
||||||
@ -166,7 +166,7 @@ export const List: Component = () => {
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class="divide-y divide-neutral-200">
|
<tbody class="divide-y divide-neutral-200">
|
||||||
<For each={l().Images}>
|
<For each={s().Images}>
|
||||||
{(image, rowIndex) => (
|
{(image, rowIndex) => (
|
||||||
<tr
|
<tr
|
||||||
class={`hover:bg-neutral-50 transition-colors ${rowIndex() % 2 === 0
|
class={`hover:bg-neutral-50 transition-colors ${rowIndex() % 2 === 0
|
||||||
@ -183,13 +183,13 @@ export const List: Component = () => {
|
|||||||
<img
|
<img
|
||||||
class="w-full h-full object-cover rounded-lg"
|
class="w-full h-full object-cover rounded-lg"
|
||||||
src={`${base}/images/${image.ImageID}?token=${accessToken()}`}
|
src={`${base}/images/${image.ImageID}?token=${accessToken()}`}
|
||||||
alt="List item"
|
alt="Stack item"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
<DeleteButton
|
<DeleteButton
|
||||||
onDelete={() =>
|
onDelete={() =>
|
||||||
onDeleteImageFromStack(
|
onDeleteImageFromStack(
|
||||||
l().ID,
|
s().ID,
|
||||||
image.ImageID,
|
image.ImageID,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -223,7 +223,7 @@ export const List: Component = () => {
|
|||||||
</For>
|
</For>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<Show when={l().Images.length === 0}>
|
<Show when={s().Images.length === 0}>
|
||||||
<div class="px-6 py-12 text-center text-neutral-500">
|
<div class="px-6 py-12 text-center text-neutral-500">
|
||||||
<p class="text-lg">
|
<p class="text-lg">
|
||||||
No images in this list yet
|
No images in this list yet
|
Reference in New Issue
Block a user