podcast-generator/client/src/components/upload-image.tsx
2025-07-24 17:54:24 +01:00

67 lines
2.2 KiB
TypeScript

import { createDropzone } from "@soorria/solid-dropzone";
import { Info, UploadIcon } from "lucide-solid";
import { createSignal, Show } from "solid-js";
import { createMutation, useQueryClient } from "@tanstack/solid-query";
import { readPodcastQueryKey, readPodcastsQueryKey, updatePodcastImageMutation } from "../client/@tanstack/solid-query.gen";
import { PodcastPublic } from "../client";
export default function UploadImage(props: { podcastId: string }) {
const queryClient = useQueryClient();
const [uploading, setUploading] = createSignal(false);
const [statusText, setStatusText] = createSignal<string | null>(null);
const updatePodcastImage = createMutation(() => ({
...updatePodcastImageMutation(),
onSuccess(data, vars) {
queryClient.setQueryData(readPodcastQueryKey({ path: vars.path }), data);
queryClient.setQueryData(readPodcastsQueryKey(), (oldData: PodcastPublic[]) => oldData ? [...oldData.filter((x) => x.id !== data.id), data] : oldData);
},
}))
const dropzone = createDropzone({
onDrop(files: File[]) {
if (!files[0]) {
throw new Error("No file was uploaded");
}
setStatusText("Uploading...");
setUploading(true);
updatePodcastImage.mutate({
body: {
image: files[0],
},
path: {
podcast_id: props.podcastId,
}
}, {
onSuccess() {
setStatusText("Podcast image uploaded!");
setUploading(false);
},
onError(error, _variables, _context) {
setStatusText(`Error uploading: ${error.detail}`);
setUploading(false);
},
});
}
});
return <>
<Show when={statusText()}>
<div role="alert" class="alert">
<Info class="stroke-primary h-6 w-6 shrink-0" />
<p>{statusText()}</p>
</div>
</Show>
<Show when={!uploading()}>
<div {...dropzone.getRootProps()} class="bg-base-200 rounded-lg shadow-sm flex flex-col items-center p-6 mb-6">
<input {...dropzone.getInputProps()} />
<UploadIcon size="42" />
<p class="mt-4 text-center">
{dropzone.isDragActive ? "Drop podcast image here..." : "Drag podcast image here to upload, or click to open"}
</p>
</div>
</Show>
</>;
}