Add Django backend, Next.js frontend, and deploy templates
This commit is contained in:
1 parent
fc0c991335
commit
e9cd22d36f
93 files changed
+7840
-1
No files matched your search
@@ -0,0 +1,117 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { Download, Eye, FileText } from "lucide-react";
|
||||
|
||||
type DocumentItem = {
|
||||
id: number;
|
||||
title: string;
|
||||
file?: string;
|
||||
mode: "preview" | "download" | "disabled";
|
||||
};
|
||||
|
||||
type Props = {
|
||||
items: DocumentItem[];
|
||||
};
|
||||
|
||||
function getPreviewUrl(origin: string, file: string) {
|
||||
const absoluteUrl = `${origin}/documents/${file}`;
|
||||
const extension = file.split(".").pop()?.toLowerCase();
|
||||
|
||||
if (extension === "pdf") {
|
||||
return `${absoluteUrl}#toolbar=0&navpanes=0&scrollbar=1`;
|
||||
}
|
||||
|
||||
return `https://docs.google.com/gview?embedded=1&url=${encodeURIComponent(absoluteUrl)}`;
|
||||
}
|
||||
|
||||
export function DocumentsViewer({ items }: Props) {
|
||||
const firstPreviewable = items.find((item) => item.mode === "preview" && item.file) ?? null;
|
||||
const [selectedId, setSelectedId] = useState<number>(firstPreviewable?.id ?? 0);
|
||||
const [origin, setOrigin] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
setOrigin(window.location.origin);
|
||||
}, []);
|
||||
|
||||
const selectedItem =
|
||||
items.find((item) => item.id === selectedId && item.mode === "preview" && item.file) ??
|
||||
firstPreviewable;
|
||||
|
||||
return (
|
||||
<div className="documents-layout">
|
||||
<aside className="documents-sidebar">
|
||||
<div className="documents-sidebar__panel">
|
||||
{items.map((item) => {
|
||||
if (item.mode === "download" && item.file) {
|
||||
return (
|
||||
<a
|
||||
key={item.id}
|
||||
href={`/documents/${item.file}`}
|
||||
download
|
||||
className="documents-link documents-link--download"
|
||||
>
|
||||
<Download size={16} />
|
||||
<span>{item.title}</span>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
if (item.mode === "disabled") {
|
||||
return (
|
||||
<div key={item.id} className="documents-link documents-link--disabled">
|
||||
<FileText size={16} />
|
||||
<span>{item.title}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<button
|
||||
key={item.id}
|
||||
type="button"
|
||||
onClick={() => setSelectedId(item.id)}
|
||||
className={`documents-link documents-link--button${
|
||||
selectedItem?.id === item.id ? " documents-link--active" : ""
|
||||
}`}
|
||||
>
|
||||
<Eye size={16} />
|
||||
<span>{item.title}</span>
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<div className="documents-content">
|
||||
<article className="page-panel documents-preview">
|
||||
<div className="documents-preview__header">
|
||||
<div>
|
||||
<span className="eyebrow">Просмотр документа</span>
|
||||
<h2>{selectedItem?.title ?? "Документ не выбран"}</h2>
|
||||
</div>
|
||||
<div className="documents-preview__note">
|
||||
<FileText size={18} />
|
||||
<span>Для просмотра используйте список слева</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{selectedItem?.file && origin ? (
|
||||
<div className="documents-preview__frame">
|
||||
<iframe
|
||||
key={`${origin}-${selectedItem.file}`}
|
||||
src={getPreviewUrl(origin, selectedItem.file)}
|
||||
title={selectedItem.title}
|
||||
className="documents-preview__iframe"
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="documents-preview__empty">
|
||||
Документ загрузится после открытия страницы в браузере.
|
||||
</div>
|
||||
)}
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user