1
0
Fork 0

feat: render notes as markdown

user-stream
Lea 2023-08-11 20:19:53 +02:00 committed by insert
parent 03fffc9849
commit edd1f9d297
4 changed files with 741 additions and 112 deletions

View File

@ -8,6 +8,9 @@ import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle }
import { useSession } from "next-auth/react"; import { useSession } from "next-auth/react";
import dayjs from "dayjs"; import dayjs from "dayjs";
import relativeTime from "dayjs/plugin/relativeTime"; import relativeTime from "dayjs/plugin/relativeTime";
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
dayjs.extend(relativeTime); dayjs.extend(relativeTime);
export default function SafetyNotesCard({ objectId, type, title }: { export default function SafetyNotesCard({ objectId, type, title }: {
@ -20,6 +23,7 @@ export default function SafetyNotesCard({ objectId, type, title }: {
const [value, setValue] = useState<SafetyNotes | null>(null); const [value, setValue] = useState<SafetyNotes | null>(null);
const [ready, setReady] = useState(false); const [ready, setReady] = useState(false);
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null);
const [editing, setEditing] = useState(false);
useEffect(() => { useEffect(() => {
fetchSafetyNote(objectId, type) fetchSafetyNote(objectId, type)
@ -39,41 +43,63 @@ export default function SafetyNotesCard({ objectId, type, title }: {
<CardTitle>{title ?? type.charAt(0).toUpperCase() + type.slice(1) + " notes"}</CardTitle> <CardTitle>{title ?? type.charAt(0).toUpperCase() + type.slice(1) + " notes"}</CardTitle>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<Textarea {
placeholder={ editing
error ? <Textarea
? error placeholder={
: ready error
? "Enter notes here... (save on unfocus)" ? error
: "Fetching notes..." : ready
} ? "Enter notes here... (save on unfocus)"
className="!min-h-[80px] max-h-[50vh]" : "Fetching notes..."
disabled={!ready || error != null}
value={ready ? draft : undefined} // not defaulting to undefined causes next to complain
onChange={(e) => setDraft(e.currentTarget.value)}
onBlur={async () => {
if (draft === value?.text ?? "") return;
try {
await updateSafetyNote(objectId, type, draft);
setValue({
_id: { id: objectId, type: type },
edited_at: new Date(Date.now()),
edited_by: session.data?.user?.email || "",
text: draft,
});
toast({
title: "Updated notes",
});
} catch (err) {
toast({
title: "Failed to update notes",
description: String(err),
variant: "destructive",
});
} }
}} className="!min-h-[80px] max-h-[50vh]"
/> disabled={!ready || error != null}
value={ready ? draft : undefined} // not defaulting to undefined causes next to complain
autoFocus
onChange={(e) => setDraft(e.currentTarget.value)}
onBlur={async () => {
if (draft === value?.text ?? "") return setEditing(false);
try {
await updateSafetyNote(objectId, type, draft);
setValue({
_id: { id: objectId, type: type },
edited_at: new Date(Date.now()),
edited_by: session.data?.user?.email || "",
text: draft,
});
setEditing(false);
toast({
title: "Updated notes",
});
} catch (err) {
setEditing(false);
toast({
title: "Failed to update notes",
description: String(err),
variant: "destructive",
});
}
}}
/>
: <div onClick={() => setEditing(true)}>
{
error
? <>{error}</>
: value?.text
? <ReactMarkdown
className="prose prose-a:text-[#fd6671] prose-img:max-h-96"
remarkPlugins={[remarkGfm]}
>
{value.text}
</ReactMarkdown>
: ready
? <i>Click to add a note</i>
: <i>Fetching notes...</i>
}
</div>
}
</CardContent> </CardContent>
<CardFooter className="-my-2"> <CardFooter className="-my-2">
<CardDescription> <CardDescription>

View File

@ -39,7 +39,9 @@
"postcss": "8.4.27", "postcss": "8.4.27",
"react": "18.2.0", "react": "18.2.0",
"react-dom": "18.2.0", "react-dom": "18.2.0",
"react-markdown": "^8.0.7",
"redis": "^4.6.7", "redis": "^4.6.7",
"remark-gfm": "^3.0.1",
"revolt-api": "^0.6.5", "revolt-api": "^0.6.5",
"sass": "^1.64.1", "sass": "^1.64.1",
"tailwind-merge": "^1.14.0", "tailwind-merge": "^1.14.0",
@ -49,6 +51,7 @@
"ulid": "^2.3.0" "ulid": "^2.3.0"
}, },
"devDependencies": { "devDependencies": {
"@tailwindcss/typography": "^0.5.9",
"@types/lodash.debounce": "^4.0.7", "@types/lodash.debounce": "^4.0.7",
"revolt.js": "7.0.0-beta.9" "revolt.js": "7.0.0-beta.9"
} }

File diff suppressed because it is too large Load Diff

View File

@ -72,5 +72,5 @@ module.exports = {
}, },
}, },
}, },
plugins: [require("tailwindcss-animate")], plugins: [require("tailwindcss-animate"), require("@tailwindcss/typography")],
} }