WIP: Linking in document list. Working on copying relationships to new sessions
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import type { Document } from "@/lib/types";
|
||||
import type { Document, DocumentId } from "@/lib/types";
|
||||
import {
|
||||
Dialog,
|
||||
DialogPanel,
|
||||
@@ -6,7 +6,8 @@ import {
|
||||
Transition,
|
||||
TransitionChild,
|
||||
} from "@headlessui/react";
|
||||
import { Fragment, useState } from "react";
|
||||
import { Fragment, useCallback, useState } from "react";
|
||||
import * as Icons from "@/components/Icons.tsx";
|
||||
|
||||
type Props<T extends Document> = {
|
||||
title: React.ReactNode;
|
||||
@@ -14,6 +15,7 @@ type Props<T extends Document> = {
|
||||
items: T[];
|
||||
renderRow: (item: T) => React.ReactNode;
|
||||
newItemForm: (onSubmit: () => void) => React.ReactNode;
|
||||
removeItem: (itemId: DocumentId) => void;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -30,8 +32,15 @@ export function DocumentList<T extends Document>({
|
||||
items,
|
||||
renderRow,
|
||||
newItemForm,
|
||||
removeItem,
|
||||
}: Props<T>) {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
|
||||
const toggleEditMode = useCallback(
|
||||
() => setIsEditing((x) => !x),
|
||||
[setIsEditing],
|
||||
);
|
||||
|
||||
// Handles closing the dialog after form submission
|
||||
const handleFormSubmit = (): void => {
|
||||
@@ -42,35 +51,50 @@ export function DocumentList<T extends Document>({
|
||||
<section className="w-full max-w-2xl mx-auto">
|
||||
<div className="flex items-center justify-between my-4">
|
||||
<h2 className="text-xl font-bold text-slate-100">{title}</h2>
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center justify-center rounded-full bg-violet-600 hover:bg-violet-700 text-white w-8 h-8 focus:outline-none focus:ring-2 focus:ring-violet-400"
|
||||
aria-label="Add new item"
|
||||
onClick={() => setOpen(true)}
|
||||
>
|
||||
<svg
|
||||
className="w-5 h-5"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth={2}
|
||||
viewBox="0 0 24 24"
|
||||
aria-hidden="true"
|
||||
<div className="flex gap-2">
|
||||
{isEditing && (
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center justify-center rounded-full bg-violet-600 hover:bg-violet-700 text-white w-8 h-8 focus:outline-none focus:ring-2 focus:ring-violet-400"
|
||||
aria-label="Add new item"
|
||||
onClick={() => setOpen(true)}
|
||||
>
|
||||
<Icons.Cross />
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center justify-center rounded-full bg-violet-600 hover:bg-violet-700 text-white w-8 h-8 focus:outline-none focus:ring-2 focus:ring-violet-400"
|
||||
aria-label={isEditing ? "Exit edit mode" : "Enter edit mode"}
|
||||
onClick={toggleEditMode}
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M12 4v16m8-8H4"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
{isEditing ? <Icons.Done /> : <Icons.Edit />}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{error && (
|
||||
<div className="bg-red-900 rounded p-4 text-slate-100">{error}</div>
|
||||
)}
|
||||
<ul className="space-y-2">
|
||||
{items.map((item) => (
|
||||
<li key={item.id} className="bg-slate-800 rounded p-4 text-slate-100">
|
||||
{renderRow(item)}
|
||||
<li
|
||||
key={item.id}
|
||||
className="bg-slate-800 rounded p-4 text-slate-100 flex flex-row justify-between items-center"
|
||||
>
|
||||
<div>{renderRow(item)}</div>
|
||||
|
||||
{isEditing && (
|
||||
<div>
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex items-center justify-center rounded-full bg-violet-600 hover:bg-violet-700 text-white w-8 h-8 focus:outline-none focus:ring-2 focus:ring-violet-400"
|
||||
aria-label="Remove item"
|
||||
onClick={() => removeItem(item.id)}
|
||||
>
|
||||
<Icons.Remove />
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
Reference in New Issue
Block a user