66 lines
2.7 KiB
TypeScript
66 lines
2.7 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useState } from "react";
|
|
import Link from "next/link";
|
|
import ReactMarkdown from "react-markdown";
|
|
import remarkGfm from "remark-gfm";
|
|
import { api, DocumentItem } from "@/lib/api";
|
|
import { Shell } from "@/components/Shell";
|
|
import { Button, Card } from "@/components/ui";
|
|
|
|
export default function DocumentPage({ params }: { params: { documentId: string } }) {
|
|
const documentId = Number(params.documentId);
|
|
const [document, setDocument] = useState<DocumentItem | null>(null);
|
|
const [content, setContent] = useState("");
|
|
const [savedContent, setSavedContent] = useState("");
|
|
const [status, setStatus] = useState("");
|
|
const dirty = content !== savedContent;
|
|
|
|
useEffect(() => {
|
|
Promise.all([api.document(documentId), api.markdown(documentId)]).then(([doc, markdown]) => {
|
|
setDocument(doc); setContent(markdown); setSavedContent(markdown);
|
|
}).catch((err) => setStatus(err.message));
|
|
}, [documentId]);
|
|
|
|
async function save() {
|
|
setStatus("Guardando...");
|
|
await api.saveMarkdown(documentId, content);
|
|
setSavedContent(content);
|
|
setStatus("Guardado");
|
|
}
|
|
|
|
async function copy() {
|
|
await navigator.clipboard.writeText(content);
|
|
setStatus("Copiado al portapapeles");
|
|
}
|
|
|
|
return (
|
|
<Shell>
|
|
<Link href="/" className="text-sm text-blue-300">Volver al dashboard</Link>
|
|
<div className="mt-4 flex flex-wrap items-center justify-between gap-4">
|
|
<div>
|
|
<h1 className="text-3xl font-bold">{document?.title || "Documento"}</h1>
|
|
<p className="mt-1 text-sm text-slate-400">{dirty ? "Cambios sin guardar" : "Sin cambios pendientes"} {status && `- ${status}`}</p>
|
|
</div>
|
|
<div className="flex flex-wrap gap-2">
|
|
<Button onClick={save} disabled={!dirty}>Guardar</Button>
|
|
<Button className="bg-slate-700 hover:bg-slate-600" onClick={copy}>Copiar</Button>
|
|
<a className="rounded-xl border border-white/10 px-4 py-2 hover:bg-white/10" href={api.downloadDocumentUrl(documentId)}>Descargar .md</a>
|
|
</div>
|
|
</div>
|
|
<div className="mt-6 grid gap-6 xl:grid-cols-2">
|
|
<Card className="p-0">
|
|
<div className="border-b border-white/10 px-4 py-3 font-medium">Editor Markdown</div>
|
|
<textarea value={content} onChange={(event) => setContent(event.target.value)} className="h-[72vh] w-full resize-none rounded-b-2xl bg-slate-950 p-4 font-mono text-sm leading-6 outline-none" />
|
|
</Card>
|
|
<Card className="overflow-auto">
|
|
<div className="mb-4 font-medium">Vista previa</div>
|
|
<article className="prose prose-invert prose-slate">
|
|
<ReactMarkdown remarkPlugins={[remarkGfm]}>{content}</ReactMarkdown>
|
|
</article>
|
|
</Card>
|
|
</div>
|
|
</Shell>
|
|
);
|
|
}
|