Files
opvault.js/packages/web/src/components/Item.tsx
2021-11-05 03:17:18 -04:00

143 lines
3.5 KiB
TypeScript

import styled from "@emotion/styled"
import type { Attachment, AttachmentMetadata, Item } from "opvault.js"
import { useEffect, useState } from "react"
import { CategoryIcon } from "./CategoryIcon"
import { ItemDates } from "./ItemDates"
import {
ItemFieldView,
FieldContainer,
FieldTitle,
ItemDetailsFieldView,
} from "./ItemField"
import { ItemWarning } from "./ItemWarning"
interface ItemViewProps {
item: Item
}
const Header = styled.div`
display: flex;
align-items: center;
`
const Icon = styled(CategoryIcon)`
font-size: 2em;
margin-right: 5px;
`
const SectionTitle = styled.div`
font-size: 85%;
font-weight: 600;
text-transform: uppercase;
margin: 20px 0 10px;
`
const Tag = styled.div`
display: inline-block;
margin-top: 2px;
margin-right: 5px;
border-radius: 4px;
padding: 3px 7px;
background-color: var(--label-background);
`
const ExtraField = styled(FieldContainer)`
margin-bottom: 20px;
`
const ItemTitle = styled.h2``
const Container = styled.div`
height: 100%;
overflow: auto;
padding: 0 10px;
`
const Inner = styled.div`
padding: 10px 0;
`
const AttachmentContainer = styled.div`
display: flex;
margin: 5px 0;
`
export const ItemView: React.FC<ItemViewProps> = ({ item }) => (
<Container>
<Inner>
<ItemWarning item={item} />
<Header>
{item.details.fields == null}
<Icon category={item.category} />
<ItemTitle>{item.overview.title}</ItemTitle>
</Header>
<details>
<summary>JSON</summary>
<pre>
{JSON.stringify({ overview: item.overview, details: item.details }, null, 2)}
</pre>
</details>
<div style={{ marginBottom: 20 }}>
{item.details.sections
?.filter(s => s.fields?.some(x => x.v != null))
.map((section, i) => (
<div key={i}>
{section.title != null && <SectionTitle>{section.title}</SectionTitle>}
{section.fields?.map((field, j) => (
<ItemFieldView key={j} field={field} />
))}
</div>
))}
</div>
{!!item.details.fields?.length && (
<div style={{ marginBottom: 20 }}>
{item.details.fields!.map((field, i) => (
<ItemDetailsFieldView key={i} field={field} />
))}
</div>
)}
{item.details.notesPlain != null && (
<ExtraField>
<FieldTitle>notes</FieldTitle>
<div>
<p>{item.details.notesPlain}</p>
</div>
</ExtraField>
)}
{!!item.overview.tags?.length && (
<ExtraField>
<FieldTitle>tags</FieldTitle>
<div>
{item.overview.tags!.map((tag, i) => (
<Tag key={i}>{tag}</Tag>
))}
</div>
</ExtraField>
)}
{item.attachments.length > 0 && (
<ExtraField>
<FieldTitle>attachments</FieldTitle>
<div>
{item.attachments.map((file, i) => (
<AttachmentView key={i} file={file} />
))}
</div>
</ExtraField>
)}
<ExtraField>
<ItemDates item={item} />
</ExtraField>
</Inner>
</Container>
)
function AttachmentView({ file }: { file: Attachment }) {
const [metadata, setMetadata] = useState<AttachmentMetadata>()
useEffect(() => {
file.unlock().then(() => setMetadata(file.metadata))
}, [file])
if (!metadata) return null
return <AttachmentContainer>{metadata.overview.filename}</AttachmentContainer>
}