Makes some document previews
This commit is contained in:
35
src/components/EditToggle.tsx
Normal file
35
src/components/EditToggle.tsx
Normal file
@@ -0,0 +1,35 @@
|
||||
import * as Icons from "./Icons";
|
||||
import { useState, Children } from "react";
|
||||
|
||||
export function EditToggle({ children }: React.PropsWithChildren) {
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
const editChildren = (
|
||||
Children.toArray(children) as React.ReactElement[]
|
||||
).filter((c) => c.type === Editing);
|
||||
const nonEditChildren = (
|
||||
Children.toArray(children) as React.ReactElement[]
|
||||
).filter((c) => c.type !== Editing);
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
<div className="absolute right-0 top-0 z-50">
|
||||
<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={() => setIsEditing(!isEditing)}
|
||||
>
|
||||
<Icons.Edit />
|
||||
</button>
|
||||
</div>
|
||||
{isEditing ? editChildren : nonEditChildren}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export const Editing = ({ children }: React.PropsWithChildren) => (
|
||||
<>{children}</>
|
||||
);
|
||||
export const NotEditing = ({ children }: React.PropsWithChildren) => (
|
||||
<>{children}</>
|
||||
);
|
||||
15
src/components/documents/BasicPreview.tsx
Normal file
15
src/components/documents/BasicPreview.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import { FormattedText } from "../FormattedText";
|
||||
|
||||
export type Props = {
|
||||
title?: string;
|
||||
description?: string;
|
||||
};
|
||||
|
||||
export const BasicPreview = ({ title, description }: Props) => {
|
||||
return (
|
||||
<div>
|
||||
{title && <h4 className="font-bold">{title}</h4>}
|
||||
{description && <FormattedText>{description}</FormattedText>}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
68
src/components/documents/DocumentPreview.tsx
Normal file
68
src/components/documents/DocumentPreview.tsx
Normal file
@@ -0,0 +1,68 @@
|
||||
// Shows a preview of a document with it's relationships.
|
||||
import { makeDocumentPath } from "@/lib/documentPath";
|
||||
import { relationshipsForDocument } from "@/lib/relationships";
|
||||
import { type AnyDocument } from "@/lib/types";
|
||||
import { Link } from "@tanstack/react-router";
|
||||
import { Editing, EditToggle, NotEditing } from "../EditToggle";
|
||||
import { BasicPreview } from "./BasicPreview";
|
||||
import { DocumentEditForm } from "./DocumentEditForm";
|
||||
|
||||
export const DocumentPreview = ({ doc }: { doc: AnyDocument }) => {
|
||||
const relationships = relationshipsForDocument(doc);
|
||||
return (
|
||||
<div>
|
||||
<EditToggle>
|
||||
<Editing>
|
||||
<DocumentEditForm document={doc} />
|
||||
</Editing>
|
||||
<NotEditing>
|
||||
<ShowDocument doc={doc} />
|
||||
</NotEditing>
|
||||
</EditToggle>
|
||||
<ul>
|
||||
{relationships.map((relType) => (
|
||||
<li>
|
||||
<Link to={makeDocumentPath(doc.id, relType)}>{relType}</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const ShowDocument = ({ doc }: { doc: AnyDocument }) => {
|
||||
switch (doc.type) {
|
||||
case "location":
|
||||
return (
|
||||
<BasicPreview
|
||||
title={doc.data.name}
|
||||
description={doc.data.description}
|
||||
/>
|
||||
);
|
||||
|
||||
case "monster":
|
||||
return <BasicPreview title={doc.data.name} />;
|
||||
|
||||
case "npc":
|
||||
return (
|
||||
<BasicPreview
|
||||
title={doc.data.name}
|
||||
description={doc.data.description}
|
||||
/>
|
||||
);
|
||||
|
||||
case "session":
|
||||
return (
|
||||
<BasicPreview title={doc.created} description={doc.data.strongStart} />
|
||||
);
|
||||
|
||||
case "secret":
|
||||
return <BasicPreview title={doc.data.text} />;
|
||||
|
||||
case "scene":
|
||||
return <BasicPreview description={doc.data.text} />;
|
||||
|
||||
case "treasure":
|
||||
return <BasicPreview title={doc.data.text} />;
|
||||
}
|
||||
};
|
||||
@@ -9,6 +9,7 @@ import { DocumentTitle } from "./DocumentTitle";
|
||||
import { Tab, TabbedLayout } from "../layout/TabbedLayout";
|
||||
import { DocumentEditForm } from "./DocumentEditForm";
|
||||
import { RelatedDocumentList } from "./RelatedDocumentList";
|
||||
import { DocumentPreview } from "./DocumentPreview";
|
||||
|
||||
export function DocumentView({
|
||||
documentId,
|
||||
@@ -59,6 +60,7 @@ export function DocumentView({
|
||||
tabs={[
|
||||
<Tab
|
||||
to="/document/$documentId"
|
||||
key="attributes"
|
||||
params={{
|
||||
documentId,
|
||||
}}
|
||||
@@ -68,6 +70,7 @@ export function DocumentView({
|
||||
...relationshipList.map((relationshipEntry) => (
|
||||
<Tab
|
||||
to="/document/$documentId/$relationshipType"
|
||||
key={relationshipEntry}
|
||||
params={{
|
||||
documentId,
|
||||
relationshipType: relationshipEntry,
|
||||
@@ -101,5 +104,5 @@ function Flyout({ docId }: { docId: DocumentId }) {
|
||||
|
||||
const doc = docResult.value.doc;
|
||||
|
||||
return <DocumentEditForm document={doc} />;
|
||||
return <DocumentPreview doc={doc} />;
|
||||
}
|
||||
|
||||
@@ -6,8 +6,9 @@ export const SessionRow = ({ session }: { session: Session }) => {
|
||||
return (
|
||||
<div>
|
||||
<Link
|
||||
to="/document/$documentId"
|
||||
params={{ documentId: session.id }}
|
||||
to="/campaigns/$campaignId"
|
||||
params={{ campaignId: session.campaign }}
|
||||
search={{ tab: "sessions", docId: session.id }}
|
||||
className="block font-semibold text-lg text-slate-300"
|
||||
>
|
||||
<FormattedDate date={session.created} />
|
||||
|
||||
@@ -38,8 +38,8 @@ export function TabbedLayout({
|
||||
export type TabProps = {
|
||||
label: string;
|
||||
to: string;
|
||||
params: Record<string, any>;
|
||||
search: Record<string, any>;
|
||||
params?: Record<string, any>;
|
||||
search?: Record<string, any>;
|
||||
active?: boolean;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user