deleted competition constructor

This commit is contained in:
rngsurrounded
2025-03-02 22:37:57 +09:00
parent db29c0cd70
commit 15d9dc2b9a
10 changed files with 0 additions and 476 deletions
-10
View File
@@ -10,7 +10,6 @@ import LoginPage from "./pages/Login";
import { AuthLayout } from "./widgets/auth-layout"; import { AuthLayout } from "./widgets/auth-layout";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import ReviewPage from "./pages/Review"; import ReviewPage from "./pages/Review";
import CompetitionConstructor from "./pages/CompetitionConstructor";
import UserProfile from "./pages/UserProfile"; import UserProfile from "./pages/UserProfile";
const queryClient = new QueryClient(); const queryClient = new QueryClient();
@@ -32,15 +31,6 @@ const App = () => {
element={<CompetitionSession />} element={<CompetitionSession />}
/> />
<Route path="/constructor/:id" element={<CompetitionConstructor />} />
<Route path="/constructor/new" element={<CompetitionConstructor />} />
<Route
path="/constructor/:id/tasks/:taskId"
element={<CompetitionConstructor />}
/>
<Route path="/profile" element={<UserProfile />} /> <Route path="/profile" element={<UserProfile />} />
<Route path="/review/:token" element={<ReviewPage />} /> <Route path="/review/:token" element={<ReviewPage />} />
@@ -1,63 +0,0 @@
// import React from 'react';
// import { Link } from 'react-router-dom';
// import { Task } from "@/shared/types";
// import { Settings, Plus } from 'lucide-react';
// import { Button } from "@/components/ui/button";
// interface ConstructorHeaderProps {
// title: string;
// tasks: Task[];
// competitionId: string;
// onAddTaskClick: () => void;
// }
// const ConstructorHeader: React.FC<ConstructorHeaderProps> = ({
// title,
// tasks,
// competitionId,
// onAddTaskClick
// }) => {
// return (
// <header className="bg-white shadow-sm sticky top-0 z-30 w-full">
// <div className="mx-auto max-w-6xl px-4">
// <div className="py-4 text-center">
// <h1 className="font-hse-sans text-xl font-semibold">
// {title}
// </h1>
// </div>
// <div className="flex items-center justify-center gap-4 pb-4 overflow-x-auto no-scrollbar">
// <Link
// to={`/constructor/${competitionId}/tasks/settings`}
// className="bg-gray-100 text-gray-700 rounded-lg px-3 py-1.5 font-medium text-sm font-hse-sans cursor-pointer
// transition-all hover:bg-gray-200 flex-shrink-0 flex items-center"
// >
// <Settings size={16} className="mr-1" />
// </Link>
// {tasks.map((task) => (
// <Link
// key={task.id}
// to={`/constructor/${competitionId}/tasks/${task.id}`}
// className="bg-blue-100 text-blue-700 rounded-lg px-3 py-1.5 font-medium text-sm font-hse-sans cursor-pointer
// transition-all hover:bg-blue-200 flex-shrink-0"
// >
// {task.number}
// </Link>
// ))}
// <Button
// variant="ghost"
// size="sm"
// className="rounded-lg flex items-center px-2 h-8"
// onClick={onAddTaskClick}
// >
// <Plus size={18} />
// </Button>
// </div>
// </div>
// </header>
// );
// };
// export default ConstructorHeader;
@@ -1,89 +0,0 @@
// import { useState } from "react";
// import { useParams, Navigate, useNavigate } from "react-router-dom";
// import { Task, TaskStatus } from "@/shared/types";
// import ConstructorHeader from "./components/ConstructorHeader";
// import TaskCreationModal from "./modules/TaskCreationModal";
// const CompetitionConstructor = () => {
// const { id, taskId } = useParams<{ id: string; taskId?: string }>();
// const navigate = useNavigate();
// const [competitionTitle, setCompetitionTitle] = useState("Новая олимпиада");
// const [tasks, setTasks] = useState<Task[]>([]);
// const [isTaskModalOpen, setIsTaskModalOpen] = useState(false);
// const isSettings = taskId === "settings";
// const handleOpenTaskModal = () => {
// setIsTaskModalOpen(true);
// };
// const handleCloseTaskModal = () => {
// setIsTaskModalOpen(false);
// };
// const handleCreateTask = (taskData: Partial<Task>) => {
// const newTask: Task = {
// id: `task-${Date.now()}`,
// number: taskData.number || `${tasks.length + 1}`,
// status: TaskStatus.Uncleared,
// solutionType: taskData.solutionType || "input",
// description: taskData.description || "",
// requirements: taskData.requirements,
// attachments: taskData.attachments || []
// };
// setTasks([...tasks, newTask]);
// setIsTaskModalOpen(false);
// navigate(`/constructor/${id}/tasks/${newTask.id}`);
// };
// if (!taskId) {
// if (tasks.length > 0) {
// return <Navigate to={`/constructor/${id}/tasks/${tasks[0].id}`} replace />;
// } else {
// return <Navigate to={`/constructor/${id}/tasks/settings`} replace />;
// }
// }
// return (
// <div className="flex flex-col min-h-screen">
// <ConstructorHeader
// title={competitionTitle}
// tasks={tasks}
// competitionId={id || ""}
// onAddTaskClick={handleOpenTaskModal}
// />
// <TaskCreationModal
// isOpen={isTaskModalOpen}
// onClose={handleCloseTaskModal}
// onCreateTask={handleCreateTask}
// taskCount={tasks.length}
// />
// <main className="flex-1 bg-[#F8F8F8] pb-8">
// <div className="max-w-6xl mx-auto px-4 py-6">
// {isSettings ? (
// <div className="bg-white rounded-lg p-6 shadow-sm">
// <h2 className="text-2xl font-semibold mb-6 font-hse-sans">Настройки олимпиады</h2>
// <p className="text-gray-500 font-hse-sans">
// Здесь будет форма настроек олимпиады
// </p>
// </div>
// ) : (
// <div className="bg-white rounded-lg p-6 shadow-sm">
// <h2 className="text-2xl font-semibold mb-6 font-hse-sans">
// {`Редактирование задачи ${tasks.find(t => t.id === taskId)?.number || ""}`}
// </h2>
// <p className="text-gray-500 font-hse-sans">
// Здесь будет форма редактирования задачи
// </p>
// </div>
// )}
// </div>
// </main>
// </div>
// );
// };
// export default CompetitionConstructor;
@@ -1,27 +0,0 @@
import React from 'react';
import { Textarea } from "@/components/ui/textarea";
import { Label } from "@/components/ui/label";
interface TaskDescriptionFieldProps {
description: string;
onChange: (value: string) => void;
}
const TaskDescriptionField: React.FC<TaskDescriptionFieldProps> = ({ description, onChange }) => {
return (
<div className="grid grid-cols-4 items-start gap-4">
<Label htmlFor="description" className="text-right pt-2">
Описание
</Label>
<Textarea
id="description"
value={description}
onChange={(e) => onChange(e.target.value)}
className="col-span-3 min-h-[100px]"
placeholder="Введите описание задачи"
/>
</div>
);
};
export default TaskDescriptionField;
@@ -1,92 +0,0 @@
import React from 'react';
import { FileIcon, X, Upload } from 'lucide-react';
import { Button } from "@/components/ui/button";
import { Label } from "@/components/ui/label";
interface TaskFileAttachmentsProps {
files: File[];
onChange: (files: File[]) => void;
}
const TaskFileAttachments: React.FC<TaskFileAttachmentsProps> = ({ files, onChange }) => {
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
if (e.target.files) {
const newFiles = Array.from(e.target.files);
onChange([...files, ...newFiles]);
}
};
const removeFile = (index: number) => {
onChange(files.filter((_, i) => i !== index));
};
return (
<div className="grid grid-cols-4 items-start gap-4">
<Label className="text-right pt-2">
Файлы
</Label>
<div className="col-span-3">
<div className="flex flex-col gap-2">
{files.map((file, index) => (
<FileListItem
key={index}
file={file}
onRemove={() => removeFile(index)}
/>
))}
<FileUploadButton onChange={handleFileChange} />
</div>
</div>
</div>
);
};
interface FileListItemProps {
file: File;
onRemove: () => void;
}
const FileListItem: React.FC<FileListItemProps> = ({ file, onRemove }) => {
return (
<div className="flex items-center justify-between p-2 border rounded-md">
<div className="flex items-center">
<FileIcon size={16} className="mr-2 text-gray-500" />
<span className="text-sm">{file.name}</span>
<span className="text-xs text-gray-500 ml-2">
({Math.round(file.size / 1024)} KB)
</span>
</div>
<Button
variant="ghost"
size="sm"
onClick={onRemove}
>
<X size={16} />
</Button>
</div>
);
};
interface FileUploadButtonProps {
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
}
const FileUploadButton: React.FC<FileUploadButtonProps> = ({ onChange }) => {
return (
<label className="cursor-pointer">
<div className="flex items-center gap-2 p-2 border border-dashed rounded-md hover:bg-gray-50 transition-colors">
<Upload size={16} className="text-gray-500" />
<span className="text-sm text-gray-700">Добавить файлы</span>
</div>
<input
type="file"
className="hidden"
onChange={onChange}
multiple
/>
</label>
);
};
export default TaskFileAttachments;
@@ -1,26 +0,0 @@
import React from 'react';
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
interface TaskNumberFieldProps {
number: string;
onChange: (value: string) => void;
}
const TaskNumberField: React.FC<TaskNumberFieldProps> = ({ number, onChange }) => {
return (
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="task-number" className="text-right">
Номер задачи
</Label>
<Input
id="task-number"
value={number}
onChange={(e) => onChange(e.target.value)}
className="col-span-3"
/>
</div>
);
};
export default TaskNumberField;
@@ -1,27 +0,0 @@
import React from 'react';
import { Textarea } from "@/components/ui/textarea";
import { Label } from "@/components/ui/label";
interface TaskRequirementsFieldProps {
requirements: string;
onChange: (value: string) => void;
}
const TaskRequirementsField: React.FC<TaskRequirementsFieldProps> = ({ requirements, onChange }) => {
return (
<div className="grid grid-cols-4 items-start gap-4">
<Label htmlFor="requirements" className="text-right pt-2">
Требования
</Label>
<Textarea
id="requirements"
value={requirements}
onChange={(e) => onChange(e.target.value)}
className="col-span-3"
placeholder="Введите требования к решению (необязательно)"
/>
</div>
);
};
export default TaskRequirementsField;
@@ -1,41 +0,0 @@
import React from 'react';
import {
RadioGroup,
RadioGroupItem
} from "@/components/ui/radio-group";
import { Label } from "@/components/ui/label";
interface TaskSolutionTypeSelectorProps {
solutionType: 'input' | 'file' | 'code';
onChange: (value: 'input' | 'file' | 'code') => void;
}
const TaskSolutionTypeSelector: React.FC<TaskSolutionTypeSelectorProps> = ({ solutionType, onChange }) => {
return (
<div className="grid grid-cols-4 items-start gap-4">
<Label className="text-right pt-2">
Тип решения
</Label>
<RadioGroup
className="col-span-3"
value={solutionType}
onValueChange={(value) => onChange(value as 'input' | 'file' | 'code')}
>
<div className="flex items-center space-x-2">
<RadioGroupItem value="input" id="input" />
<Label htmlFor="input">Ввод ответа</Label>
</div>
<div className="flex items-center space-x-2">
<RadioGroupItem value="file" id="file" />
<Label htmlFor="file">Загрузка файла</Label>
</div>
<div className="flex items-center space-x-2">
<RadioGroupItem value="code" id="code" />
<Label htmlFor="code">Программный код</Label>
</div>
</RadioGroup>
</div>
);
};
export default TaskSolutionTypeSelector;
@@ -1,101 +0,0 @@
// import React, { useState } from 'react';
// import {
// Dialog,
// DialogContent,
// DialogHeader,
// DialogTitle,
// DialogFooter
// } from "@/components/ui/dialog";
// import { Button } from "@/components/ui/button";
// import { Task } from "@/shared/types";
// import TaskNumberField from './components/TaskNumberField';
// import TaskDescriptionField from './components/TaskDescriptionField';
// import TaskRequirementsField from './components/TaskRequirementsField';
// import TaskSolutionTypeSelector from './components/TaskSolutionTypeSelector';
// import TaskFileAttachments from './components/TaskFileAttachments';
// interface TaskCreationModalProps {
// isOpen: boolean;
// onClose: () => void;
// onCreateTask: (task: Partial<Task>) => void;
// taskCount: number;
// }
// const TaskCreationModal: React.FC<TaskCreationModalProps> = ({
// isOpen,
// onClose,
// onCreateTask,
// taskCount
// }) => {
// const [number, setNumber] = useState(`${taskCount + 1}`);
// const [description, setDescription] = useState('');
// const [requirements, setRequirements] = useState('');
// const [solutionType, setSolutionType] = useState<'input' | 'file' | 'code'>('input');
// const [attachedFiles, setAttachedFiles] = useState<File[]>([]);
// const handleSubmit = () => {
// const newTask: Partial<Task> = {
// number,
// description,
// requirements: requirements || undefined,
// solutionType,
// attachments: attachedFiles.map(file => file.name)
// };
// onCreateTask(newTask);
// setNumber(`${taskCount + 1}`);
// setDescription('');
// setRequirements('');
// setSolutionType('input');
// setAttachedFiles([]);
// };
// return (
// <Dialog open={isOpen} onOpenChange={onClose}>
// <DialogContent className="sm:max-w-[600px] font-hse-sans">
// <DialogHeader>
// <DialogTitle className="text-xl">Создание новой задачи</DialogTitle>
// </DialogHeader>
// <div className="grid gap-4 py-4">
// <TaskNumberField
// number={number}
// onChange={setNumber}
// />
// <TaskDescriptionField
// description={description}
// onChange={setDescription}
// />
// <TaskRequirementsField
// requirements={requirements}
// onChange={setRequirements}
// />
// <TaskSolutionTypeSelector
// solutionType={solutionType}
// onChange={setSolutionType}
// />
// <TaskFileAttachments
// files={attachedFiles}
// onChange={setAttachedFiles}
// />
// </div>
// <DialogFooter>
// <Button type="button" variant="outline" onClick={onClose}>
// Отмена
// </Button>
// <Button type="button" onClick={handleSubmit}>
// Создать задачу
// </Button>
// </DialogFooter>
// </DialogContent>
// </Dialog>
// );
// };
// export default TaskCreationModal;