96 lines
4.3 KiB
TypeScript
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>
|
|
);
|
|
}
|