179 lines
6.2 KiB
TypeScript
179 lines
6.2 KiB
TypeScript
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) {}
|
||
};
|
||
|
||
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;
|