v3/frontend/src/components/note/note_header.tsx

96 lines
4.3 KiB
TypeScript

import Icon from "@mdi/react";
import { colors } from "~/lib/color";
import { icons } from "~/lib/icon";
import { NotePropertiesDialog } from "~/components/note/note_properties_dialog";
import { mdiCircle, mdiCog } from "@mdi/js";
import { NoteSettingsDialog } from "~/components/note/note_settings_dialog";
import { useCollection, useNoteMetadata } from "~/hooks/use-metadata";
import type { NoteId, NoteMetadata } from "~/lib/metadata";
export function NoteHeader(props: { id: NoteId }) {
const noteMetadata = useNoteMetadata(props.id);
if (!noteMetadata) {
return null;
}
const primaryColorName = noteMetadata.get("primaryColor");
const secondaryColorName = noteMetadata.get("secondaryColor");
const primaryColor = primaryColorName ? colors[primaryColorName] : colors.white;
const secondaryColor = secondaryColorName ? colors[secondaryColorName] : primaryColor;
return (
<>
<div className="flex-shrink-0 w-full h-[300px] relative shadow mb-[42px]" style={{
background: `linear-gradient(135deg, ${primaryColor.base}, ${secondaryColor.base})`
}}>
<div className="flex flex-row justify-end">
<NoteSettingsDialog noteMetadata={noteMetadata}>
<button
className="m-2 p-2 flex justify-center items-center bg-secondary bg-opacity-50 hover:bg-opacity-90 rounded"
>
<Icon path={mdiCog} size={1} />
</button>
</NoteSettingsDialog>
</div>
<div className="absolute left-8 bottom-[-42px] bg-sidebar rounded-xl flex items-center justify-center h-32 w-32 border-4 border-background">
{noteMetadata.get("icon") && <Icon path={icons[noteMetadata.get("icon")]!.path} color={primaryColor.base} size={4} />}
</div>
</div>
<div className="ml-8 flex flex-col gap-1">
<div className="flex flex-row gap-1">
{<input
className="bg-transparent outline-none font-bold text-3xl flex-grow"
defaultValue={noteMetadata.get("title")}
onChange={(e) => noteMetadata.set("title", e.target.value)}
/>}
</div>
<Properties noteMetadata={noteMetadata} />
</div>
</>
);
}
function Properties(props: { noteMetadata: NoteMetadata }) {
const { noteMetadata } = props;
const collection = useCollection(noteMetadata.get("collectionId"));
if (!collection) {
return <span className="text-muted">No properties</span>;
}
const collectionProps = collection.get("properties")?.toArray();
if (!collectionProps) {
return <span className="text-muted">No properties</span>;
}
const pinnedProperties = collectionProps.filter(property => property.get("pinned"));
return (
<NotePropertiesDialog noteMetadata={noteMetadata}>
<button className="flex flex-row w-fit rounded gap-2 py-1 px-2 hover:bg-accent items-center">
{pinnedProperties.length === 0
? <span className="text-zinc-400">No pinned properties</span>
: pinnedProperties.flatMap(property => {
const propertyId = property.get("id");
const value = noteMetadata.get("properties")
?.toArray()
.find(it => it.get("propertyId") == propertyId)
?.get("value");
const seperator = <Icon key={`${propertyId}-sep`} className="text-muted text-2xl" path={mdiCircle} size={.25} />;
if (!value) {
return [seperator, <span key={propertyId} className="text-muted">
{property.get("name")}
</span>]
} else {
return [seperator, <span key={propertyId} className="text-muted">
{value}
</span>]
}
}).slice(1)}
</button>
</NotePropertiesDialog>
);
}