Files
LiquidCode_Frontend/src/views/mission/statement/Statement.tsx
Виталий Лавшонок 8429bd4082 copy button
2025-11-03 16:08:50 +03:00

139 lines
5.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { FC } from "react";
import { cn } from "../../../lib/cn";
import LaTextContainer from "./LaTextContainer";
import { CopyIcon } from "../../../assets/icons/missions";
// import FullLatexRenderer from "./FullLatexRenderer";
import { useState } from "react";
interface CopyableDivPropd{
content: string;
}
const CopyableDiv: FC<CopyableDivPropd> = ({ content }) => {
const [hovered, setHovered] = useState(false);
const handleCopy = async () => {
try {
await navigator.clipboard.writeText(content);
alert("Скопировано!");
} catch (err) {
console.error("Ошибка копирования:", err);
}
};
return (
<div
className="relative p-[10px] bg-liquid-lighter rounded-[10px] whitespace-pre-line"
onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)}
>
{content}
<img
src={CopyIcon}
alt="copy"
className={cn("absolute top-2 right-2 w-6 h-6 cursor-pointer opacity-0 transition-all duration-300 hover:h-7 hover:w-7 hover:top-[6px] hover:right-[6px]",
hovered && " opacity-100"
)}
onClick={handleCopy}
/>
</div>
);
}
export interface StatementData {
id?: number;
name?: string;
tags?: string[];
timeLimit?: number;
memoryLimit?: number;
legend?: string;
input?: string;
output?: string;
sampleTests?: { input: string; output: string }[];
notes?: string;
html?: string;
mediaFiles?: { id: number; fileName: string; mediaUrl: string }[];
}
function extractDivByClass(html: string, className: string): string {
const parser = new DOMParser();
const doc = parser.parseFromString(html, "text/html");
const div = doc.querySelector(`div.${className}`);
return div ? div.outerHTML : "";
}
const Statement: React.FC<StatementData> = ({
id,
name,
tags,
timeLimit = 1000,
memoryLimit = 256 * 1024 * 1024,
legend = "",
input = "",
output = "",
sampleTests = [],
notes = "",
html = "",
mediaFiles,
}) => {
return (
<div className="flex flex-col w-full h-full medium-scrollbar pl-[20px] pr-[12px] gap-[20px] text-liquid-white overflow-y-scroll thin-dark-scrollbar [scrollbar-gutter:stable]">
<div>
<p className="h-[50px] text-[40px] font-bold text-liquid-white">{name}</p>
<p className="h-[23px] text-[18px] font-bold text-liquid-light">Задача #{id}</p>
</div>
<div className="flex gap-[10px] w-full flex-wrap">
{tags && tags.map((v, i) => <div key={i} className="px-[16px] py-[8px] rounded-full bg-liquid-lighter ">{v}</div>)}
</div>
<div className="flex flex-col">
<p className="text-liquid-white h-[20px] text-[18px] font-bold"><span className="text-liquid-light">ограничение по времени на тест:</span> {timeLimit / 1000} секунда</p>
<p className="text-liquid-white h-[20px] text-[18px] font-bold"><span className="text-liquid-light">ограничение по памяти на тест:</span> {memoryLimit / 1024 / 1024} мегабайт</p>
<p className="text-liquid-white h-[20px] text-[18px] font-bold"><span className="text-liquid-light">ввод:</span> стандартный ввод</p>
<p className="text-liquid-white h-[20px] text-[18px] font-bold"><span className="text-liquid-light">вывод:</span> стандартный вывод</p>
</div>
<div className="flex flex-col gap-[10px] mt-[20px]">
<LaTextContainer html={extractDivByClass(html, "legend")} latex={legend} mediaFiles={mediaFiles}/>
</div>
<div className="flex flex-col gap-[10px]">
<LaTextContainer html={extractDivByClass(html, "input-specification")} latex={input} mediaFiles={mediaFiles}/>
</div>
<div className="flex flex-col gap-[10px]">
<LaTextContainer html={extractDivByClass(html, "output-specification")} latex={output} mediaFiles={mediaFiles}/>
</div>
<div className="flex flex-col gap-[10px]">
<div className="text-[18px] font-bold">{sampleTests.length == 1 ? "Пример" : "Примеры"}</div>
{sampleTests.map((v, i) =>
<div key={i} className="flex flex-col gap-[10px]">
<div className="text-[14px] font-bold">Входные данные</div>
<CopyableDiv content={v.input}/>
<div className="text-[14px] font-bold">Выходные данные</div>
<CopyableDiv content={v.output}/>
</div>
)}
</div>
<div className="flex flex-col gap-[10px]">
<LaTextContainer html={extractDivByClass(html, "note")} latex={notes} mediaFiles={mediaFiles}/>
<div>Автор: Jacks</div>
</div>
</div>
);
};
export default Statement;