mirror of
https://gitlab.com/megazordpobeda/DataRush.git
synced 2026-05-22 23:17:09 +00:00
refactoring: taskstatus
This commit is contained in:
@@ -1,21 +1,99 @@
|
||||
import React, { useState } from 'react';
|
||||
import { DataRush } from "@/components/ui/icons/datarush";
|
||||
import { ChevronDown } from "lucide-react";
|
||||
import { ChevronDown, User, Settings, BarChart2, LogOut } from "lucide-react";
|
||||
import { Link } from "react-router";
|
||||
import {
|
||||
Sheet,
|
||||
SheetContent,
|
||||
SheetHeader,
|
||||
SheetTitle,
|
||||
SheetClose
|
||||
} from "@/components/ui/sheet";
|
||||
|
||||
const Header = () => {
|
||||
const [isProfileOpen, setIsProfileOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<header className="bg-card sticky top-0 z-30 flex h-[72px] w-full items-center justify-center">
|
||||
<div className="flex w-full max-w-5xl items-center justify-between">
|
||||
<Link to="/">
|
||||
<DataRush />
|
||||
</Link>
|
||||
<div className="flex items-center gap-1">
|
||||
<span className="text-lg font-semibold">itqdev</span>
|
||||
<div
|
||||
className="flex items-center gap-1 cursor-pointer hover:opacity-80 transition-opacity px-2 py-1 rounded-md"
|
||||
onClick={() => setIsProfileOpen(true)}
|
||||
>
|
||||
<span className="text-lg font-semibold font-hse-sans">itqdev</span>
|
||||
<ChevronDown size={20} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Sheet open={isProfileOpen} onOpenChange={setIsProfileOpen}>
|
||||
<SheetContent className="w-[300px] sm:w-[350px] p-0">
|
||||
<SheetHeader className="border-b py-4 px-5">
|
||||
<SheetTitle className="font-hse-sans text-lg font-medium">Профиль</SheetTitle>
|
||||
</SheetHeader>
|
||||
|
||||
<div className="py-4 px-2">
|
||||
<ProfileOption
|
||||
icon={<User size={18} />}
|
||||
label="Ваш профиль"
|
||||
onClick={() => {
|
||||
setIsProfileOpen(false);
|
||||
}}
|
||||
/>
|
||||
|
||||
<ProfileOption
|
||||
icon={<Settings size={18} />}
|
||||
label="Настройки"
|
||||
onClick={() => {
|
||||
setIsProfileOpen(false);
|
||||
}}
|
||||
/>
|
||||
|
||||
<ProfileOption
|
||||
icon={<BarChart2 size={18} />}
|
||||
label="Статистика"
|
||||
onClick={() => {
|
||||
setIsProfileOpen(false);
|
||||
}}
|
||||
/>
|
||||
|
||||
<div className="border-t mt-2 pt-2">
|
||||
<ProfileOption
|
||||
icon={<LogOut size={18} />}
|
||||
label="Выйти"
|
||||
onClick={() => {
|
||||
setIsProfileOpen(false);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
</header>
|
||||
);
|
||||
};
|
||||
|
||||
export { Header };
|
||||
interface ProfileOptionProps {
|
||||
icon: React.ReactNode;
|
||||
label: string;
|
||||
onClick: () => void;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const ProfileOption: React.FC<ProfileOptionProps> = ({ icon, label, onClick, className }) => {
|
||||
return (
|
||||
<SheetClose asChild>
|
||||
<button
|
||||
className={`flex items-center gap-3 w-full px-3 py-2.5 rounded-md text-left transition-colors hover:bg-gray-100 ${className || ''}`}
|
||||
onClick={onClick}
|
||||
>
|
||||
<span className="text-gray-600">{icon}</span>
|
||||
<span className="font-hse-sans">{label}</span>
|
||||
</button>
|
||||
</SheetClose>
|
||||
);
|
||||
};
|
||||
|
||||
export { Header };
|
||||
+5
-5
@@ -9,15 +9,15 @@ interface SolutionStatusProps {
|
||||
const SolutionStatus: React.FC<SolutionStatusProps> = ({ solution }) => {
|
||||
const getStatusText = (status: TaskStatus, score?: number, maxScore?: number) => {
|
||||
switch (status) {
|
||||
case 'checking':
|
||||
case TaskStatus.Checking:
|
||||
return 'На проверке';
|
||||
case 'wrong':
|
||||
case TaskStatus.Wrong:
|
||||
return 'Неверный ответ';
|
||||
case 'correct':
|
||||
case TaskStatus.Correct:
|
||||
return `Зачтено ${maxScore}/${maxScore} баллов`;
|
||||
case 'partial':
|
||||
case TaskStatus.Partial:
|
||||
return `Зачтено ${score}/${maxScore} баллов`;
|
||||
case 'uncleared':
|
||||
case TaskStatus.Uncleared:
|
||||
return 'Не решено';
|
||||
default:
|
||||
return '';
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
import { TaskStatus } from "@/shared/types";
|
||||
const getTaskBgColor = (status: TaskStatus): string => {
|
||||
switch (status) {
|
||||
case "uncleared": return "bg-[var(--color-task-uncleared)]";
|
||||
case "checking": return "bg-[var(--color-task-checking)]";
|
||||
case "correct": return "bg-[var(--color-task-correct)]";
|
||||
case "partial": return "bg-[var(--color-task-partial)]";
|
||||
case "wrong": return "bg-[var(--color-task-wrong)]";
|
||||
case TaskStatus.Uncleared: return "bg-[var(--color-task-uncleared)]";
|
||||
case TaskStatus.Checking: return "bg-[var(--color-task-checking)]";
|
||||
case TaskStatus.Correct: return "bg-[var(--color-task-correct)]";
|
||||
case TaskStatus.Partial: return "bg-[var(--color-task-partial)]";
|
||||
case TaskStatus.Wrong: return "bg-[var(--color-task-wrong)]";
|
||||
}
|
||||
};
|
||||
|
||||
const getTaskTextColor = (status: TaskStatus): string => {
|
||||
switch (status) {
|
||||
case "uncleared": return "text-[var(--color-task-text-uncleared)]";
|
||||
case "checking": return "text-[var(--color-task-text-checking)]";
|
||||
case "correct": return "text-[var(--color-task-text-correct)]";
|
||||
case "partial": return "text-[var(--color-task-text-partial)]";
|
||||
case "wrong": return "text-[var(--color-task-text-wrong)]";
|
||||
case TaskStatus.Uncleared: return "text-[var(--color-task-text-uncleared)]";
|
||||
case TaskStatus.Checking: return "text-[var(--color-task-text-checking)]";
|
||||
case TaskStatus.Correct: return "text-[var(--color-task-text-correct)]";
|
||||
case TaskStatus.Partial: return "text-[var(--color-task-text-partial)]";
|
||||
case TaskStatus.Wrong: return "text-[var(--color-task-text-wrong)]";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Competition, CompetitionStatus, Solution, Task } from "../types";
|
||||
import { Competition, CompetitionStatus, Solution, Task, TaskStatus } from "../types";
|
||||
|
||||
const mockCompetitions: Competition[] = [
|
||||
{
|
||||
@@ -56,49 +56,49 @@ const mockTasks: Task[] = [
|
||||
{
|
||||
id: "1",
|
||||
number: "1.1",
|
||||
status: "uncleared",
|
||||
status: TaskStatus.Uncleared,
|
||||
solutionType: "input"
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
number: "1.2",
|
||||
status: "checking",
|
||||
status: TaskStatus.Checking,
|
||||
solutionType: "file"
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
number: "1.3",
|
||||
status: "correct",
|
||||
status: TaskStatus.Correct,
|
||||
solutionType: "code"
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
number: "2.1",
|
||||
status: "partial",
|
||||
status: TaskStatus.Partial,
|
||||
solutionType: "input"
|
||||
},
|
||||
{
|
||||
id: "5",
|
||||
number: "2.2",
|
||||
status: "wrong",
|
||||
status: TaskStatus.Wrong,
|
||||
solutionType: "file"
|
||||
},
|
||||
{
|
||||
id: "6",
|
||||
number: "2.3",
|
||||
status: "uncleared",
|
||||
status: TaskStatus.Uncleared,
|
||||
solutionType: "code"
|
||||
},
|
||||
{
|
||||
id: "7",
|
||||
number: "3.1",
|
||||
status: "checking",
|
||||
status: TaskStatus.Checking,
|
||||
solutionType: "file"
|
||||
},
|
||||
{
|
||||
id: "8",
|
||||
number: "3.2",
|
||||
status: "correct",
|
||||
status: TaskStatus.Correct,
|
||||
solutionType: "input"
|
||||
},
|
||||
];
|
||||
@@ -107,26 +107,26 @@ const mockTasks: Task[] = [
|
||||
const mockSolutions: Solution[] = [
|
||||
{
|
||||
id: '1',
|
||||
status: 'wrong',
|
||||
status: TaskStatus.Wrong,
|
||||
date: '1 марта, 08:41',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
status: 'partial',
|
||||
status: TaskStatus.Partial,
|
||||
score: 5,
|
||||
maxScore: 10,
|
||||
date: '28 февраля, 15:22',
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
status: 'correct',
|
||||
status: TaskStatus.Correct,
|
||||
score: 0,
|
||||
maxScore: 10,
|
||||
date: '27 февраля, 12:10',
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
status: 'checking',
|
||||
status: TaskStatus.Checking,
|
||||
date: '1 марта, 08:41',
|
||||
},
|
||||
|
||||
|
||||
@@ -4,6 +4,14 @@ enum CompetitionStatus {
|
||||
Completed = "Завершено",
|
||||
}
|
||||
|
||||
enum TaskStatus {
|
||||
Uncleared = "uncleared",
|
||||
Checking = "checking",
|
||||
Correct = "correct",
|
||||
Partial = "partial",
|
||||
Wrong = "wrong"
|
||||
}
|
||||
|
||||
interface Competition {
|
||||
id: string;
|
||||
name: string;
|
||||
@@ -13,7 +21,6 @@ interface Competition {
|
||||
description?: string;
|
||||
}
|
||||
|
||||
type TaskStatus = "uncleared" | "checking" | "correct" | "partial" | "wrong";
|
||||
type SolutionType = "input" | "file" | "code";
|
||||
|
||||
interface Solution {
|
||||
@@ -30,5 +37,5 @@ interface Task {
|
||||
solutionType: SolutionType;
|
||||
}
|
||||
|
||||
export { CompetitionStatus };
|
||||
export type { Solution, Competition, TaskStatus, Task };
|
||||
export { CompetitionStatus, TaskStatus };
|
||||
export type { Solution, Competition, Task };
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
import { ChevronDown } from "lucide-react";
|
||||
|
||||
const Navbar = () => {
|
||||
return (
|
||||
<nav className="bg-white border-b border-gray-200 py-3 px-4 fixed top-0 left-0 right-0 z-10">
|
||||
<div className="container mx-auto flex justify-between items-center">
|
||||
<div className="flex items-center">
|
||||
<div className="bg-black px-3 py-2 rounded font-hse-sans">
|
||||
<span className="font-bold text-yellow-400">DATA</span>
|
||||
<span className="font-bold text-white">RUSH</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center cursor-pointer">
|
||||
<span className="mr-2 font-semibold font-hse-sans">itqdev</span>
|
||||
<ChevronDown size={16} />
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
export default Navbar
|
||||
Reference in New Issue
Block a user