Set up photo editor and clean up styling
This commit is contained in:
@@ -1,17 +1,18 @@
|
||||
"use client";
|
||||
import type { PhotoData } from "@/server/api/routers/photos/list";
|
||||
import { api } from "@/trpc/react";
|
||||
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import Image from "next/image";
|
||||
import type React from "react";
|
||||
import { useState } from "react";
|
||||
import ImageSvg from "./file-svg";
|
||||
import DirSvg from "./dir-svg";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import z from "zod";
|
||||
import type { PhotoData } from "@/server/api/routers/photos/list";
|
||||
import { api } from "@/trpc/react";
|
||||
import DirSvg from "./dir-svg";
|
||||
import ImageSvg from "./file-svg";
|
||||
import Tiptap from "./photo-editor";
|
||||
|
||||
// - TODO - Pull this from trpc
|
||||
const FormSchema = z.object({
|
||||
title: z
|
||||
.string()
|
||||
@@ -83,24 +84,35 @@ function renderTree(node: DirectoryTree, pathSoFar = ""): Item[] {
|
||||
return items;
|
||||
}
|
||||
|
||||
function RenderLeaf(leaf: Item[], selectImageTab: (path: string) => void) {
|
||||
function RenderLeaf(
|
||||
leaf: Item[],
|
||||
selectImageTab: (path: string) => void,
|
||||
selectedImage: PhotoData | undefined,
|
||||
) {
|
||||
return leaf.map((leaf) => {
|
||||
const selectedLeaf =
|
||||
`https://fly.storage.tigris.dev/joemonk-photos/${leaf.fullPath}` ===
|
||||
selectedImage?.src;
|
||||
if (leaf.children?.length) {
|
||||
return (
|
||||
<li>
|
||||
<li key={leaf.fullPath}>
|
||||
<details open>
|
||||
<summary>
|
||||
<DirSvg />
|
||||
{leaf.name}
|
||||
</summary>
|
||||
<ul>{RenderLeaf(leaf.children, selectImageTab)}</ul>
|
||||
<ul>{RenderLeaf(leaf.children, selectImageTab, selectedImage)}</ul>
|
||||
</details>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<li key={leaf.fullPath}>
|
||||
<button type="button" onClick={() => selectImageTab(leaf.fullPath)}>
|
||||
<button
|
||||
type="button"
|
||||
className={selectedLeaf ? "active" : ""}
|
||||
onClick={() => selectImageTab(leaf.fullPath)}
|
||||
>
|
||||
<ImageSvg />
|
||||
{leaf.name}
|
||||
</button>
|
||||
@@ -111,9 +123,16 @@ function RenderLeaf(leaf: Item[], selectImageTab: (path: string) => void) {
|
||||
|
||||
export function PhotoTab(): React.JSX.Element {
|
||||
const [selectedImage, setSelectedImage] = useState<PhotoData>();
|
||||
const query = api.photos.list.useQuery(undefined, {
|
||||
refetchOnWindowFocus: false,
|
||||
});
|
||||
const listQuery = api.photos.list.useInfiniteQuery(
|
||||
{},
|
||||
{
|
||||
getNextPageParam: (lastPage) => lastPage.next,
|
||||
refetchOnWindowFocus: false,
|
||||
refetchOnMount: false,
|
||||
refetchOnReconnect: false,
|
||||
},
|
||||
);
|
||||
const modifyMutate = api.photos.modify.useMutation();
|
||||
|
||||
const {
|
||||
register,
|
||||
@@ -125,18 +144,21 @@ export function PhotoTab(): React.JSX.Element {
|
||||
mode: "onSubmit",
|
||||
});
|
||||
|
||||
if (query.isLoading) {
|
||||
if (listQuery.isLoading) {
|
||||
return <p>Loading</p>;
|
||||
}
|
||||
if (query.error) {
|
||||
return <p>{query.error.message}</p>;
|
||||
if (listQuery.error) {
|
||||
return <p>{listQuery.error.message}</p>;
|
||||
}
|
||||
const images = query.data?.data;
|
||||
const images = listQuery.data?.pages.flatMap((data) => data.data);
|
||||
if (!images || images?.length === 0) {
|
||||
return <p>No Images</p>;
|
||||
}
|
||||
if (listQuery.hasNextPage) {
|
||||
listQuery.fetchNextPage();
|
||||
}
|
||||
|
||||
const selectImageTab = (path: string) => {
|
||||
const selectImage = (path: string) => {
|
||||
const img = images.find(
|
||||
(img) =>
|
||||
img.src === `https://fly.storage.tigris.dev/joemonk-photos/${path}`,
|
||||
@@ -153,22 +175,26 @@ export function PhotoTab(): React.JSX.Element {
|
||||
);
|
||||
const renderedTree = renderTree(tree);
|
||||
|
||||
const onSubmit = (data: IFormInput) => {
|
||||
console.log(data);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex w-full gap-2">
|
||||
<ul className="menu menu-xs bg-base-200 box w-1/4">
|
||||
{RenderLeaf(renderedTree, selectImageTab)}
|
||||
<div className="flex w-full gap-4 md:gap-2 flex-col md:flex-row">
|
||||
<ul className="menu menu-xs bg-base-200 box w-full md:w-1/4">
|
||||
{RenderLeaf(renderedTree, selectImage, selectedImage)}
|
||||
</ul>
|
||||
<div className="w-3/4 box border border-base-300 p-2">
|
||||
<div className="md:w-3/4 box border border-base-300 p-2 w-full">
|
||||
{selectedImage?.src ? (
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
<form
|
||||
onSubmit={handleSubmit((data) =>
|
||||
modifyMutate.mutate({
|
||||
title: data.title,
|
||||
description: data.description,
|
||||
src: selectedImage.src,
|
||||
}),
|
||||
)}
|
||||
>
|
||||
<label
|
||||
className={`floating-label input text-lg mb-2 w-full ${errors.title ? "input-error" : null}`}
|
||||
>
|
||||
<span>{`Title ${errors.title ? " - " + errors.title.message : ""}`}</span>
|
||||
<span>{`Title ${errors.title ? ` - ${errors.title.message}` : ""}`}</span>
|
||||
<input
|
||||
{...register("title")}
|
||||
type="text"
|
||||
@@ -263,13 +289,30 @@ export function PhotoTab(): React.JSX.Element {
|
||||
control={control}
|
||||
name="description"
|
||||
render={({ field: { onChange } }) => (
|
||||
<Tiptap onChange={onChange} />
|
||||
<Tiptap
|
||||
onChange={onChange}
|
||||
initContent={selectedImage.description}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<button className="button" type="submit">
|
||||
Submit
|
||||
</button>
|
||||
<div className="flex flex-row items-center">
|
||||
<button
|
||||
className="btn btn-primary flex self-center m-4"
|
||||
type="submit"
|
||||
>
|
||||
Save
|
||||
</button>
|
||||
{modifyMutate.isSuccess ? (
|
||||
<p className="badge badge-success">Updated</p>
|
||||
) : modifyMutate.isError ? (
|
||||
<p className="badge badge-error">
|
||||
Error: {modifyMutate.error.message}
|
||||
</p>
|
||||
) : modifyMutate.isPending ? (
|
||||
<p className="badge badge-info">Updating</p>
|
||||
) : null}
|
||||
</div>
|
||||
</form>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user