added submissions count

This commit is contained in:
rngsurrounded
2025-03-03 21:09:57 +09:00
parent 515b051587
commit 39143116c4
4 changed files with 212 additions and 159 deletions
@@ -1,14 +1,19 @@
import React from 'react'; import React from 'react';
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Loader2 } from "lucide-react";
interface ActionButtonsProps { interface ActionButtonsProps {
onSubmit: () => void; onSubmit: () => void;
onHistoryClick: () => void; onHistoryClick: () => void;
isSubmitting?: boolean;
hasSubmissionsLeft?: boolean;
} }
const ActionButtons: React.FC<ActionButtonsProps> = ({ const ActionButtons: React.FC<ActionButtonsProps> = ({
onSubmit, onSubmit,
onHistoryClick onHistoryClick,
isSubmitting = false,
hasSubmissionsLeft = true
}) => { }) => {
return ( return (
<div className="flex gap-8"> <div className="flex gap-8">
@@ -16,15 +21,31 @@ const ActionButtons: React.FC<ActionButtonsProps> = ({
variant="ghost" variant="ghost"
className="font-hse-sans bg-white hover:bg-gray-100" className="font-hse-sans bg-white hover:bg-gray-100"
onClick={onHistoryClick} onClick={onHistoryClick}
disabled={isSubmitting}
> >
История История
</Button> </Button>
{hasSubmissionsLeft ? (
<Button <Button
onClick={onSubmit} onClick={onSubmit}
className="font-hse-sans flex-grow" className="font-hse-sans flex-grow"
disabled={isSubmitting}
> >
Отправить решение {isSubmitting ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
Отправка...
</>
) : (
"Отправить решение"
)}
</Button> </Button>
) : (
<div className="flex-grow text-right text-gray-500 flex items-center justify-end font-hse-sans">
Лимит посылок исчерпан
</div>
)}
</div> </div>
); );
}; };
@@ -68,6 +68,7 @@ const FileSolution: React.FC<FileSolutionProps> = ({
? existingFileUrl.split('/').pop() || 'file' ? existingFileUrl.split('/').pop() || 'file'
: ''; : '';
console.log(firstSolution, "IS FIRST SOLUTION")
const hasFile = !!selectedFile || (!!existingFileUrl && !firstSolution); const hasFile = !!selectedFile || (!!existingFileUrl && !firstSolution);
return ( return (
@@ -17,6 +17,7 @@
selectedFile: File | null; selectedFile: File | null;
setSelectedFile: (file: File | null) => void; setSelectedFile: (file: File | null) => void;
onSubmit: () => void; onSubmit: () => void;
isSubmitting?: boolean;
} }
const TaskSolution: React.FC<TaskSolutionProps> = ({ const TaskSolution: React.FC<TaskSolutionProps> = ({
@@ -26,6 +27,7 @@
selectedFile, selectedFile,
setSelectedFile, setSelectedFile,
onSubmit, onSubmit,
isSubmitting = false
}) => { }) => {
const fileInputRef = useRef<HTMLInputElement>(null); const fileInputRef = useRef<HTMLInputElement>(null);
const [isHistoryOpen, setIsHistoryOpen] = useState(false); const [isHistoryOpen, setIsHistoryOpen] = useState(false);
@@ -42,6 +44,11 @@
const solutionHistory = solutionsQuery.data || []; const solutionHistory = solutionsQuery.data || [];
const maxAttempts = task.max_attempts || -1;
const submissionsUsed = solutionHistory.length;
const submissionsLeft = Math.max(0, maxAttempts - submissionsUsed);
const hasSubmissionsLeft = submissionsLeft > 0;
useEffect(() => { useEffect(() => {
if (solutionHistory.length > 0 && !displayedSolution) { if (solutionHistory.length > 0 && !displayedSolution) {
const latestSolution = solutionHistory[solutionHistory.length - 1]; const latestSolution = solutionHistory[solutionHistory.length - 1];
@@ -73,7 +80,6 @@
} }
}, [solutionHistory, displayedSolution]); }, [solutionHistory, displayedSolution]);
// Load solution content when the displayed solution changes
useEffect(() => { useEffect(() => {
const loadSolutionContent = async () => { const loadSolutionContent = async () => {
if (!displayedSolution || !displayedSolution.content) return; if (!displayedSolution || !displayedSolution.content) return;
@@ -115,11 +121,10 @@
{displayedSolution ? ( {displayedSolution ? (
<> <>
<div className="bg-gray-100 rounded-lg p-4 text-gray-600 font-hse-sans"> <div className="bg-gray-100 rounded-lg p-4 text-gray-600 font-hse-sans">
Последнее решение Результат последней посылки:
</div> </div>
<SolutionStatus solution={displayedSolution} maxPoints={task.points}/> <SolutionStatus key={displayedSolution.id} solution={displayedSolution} maxPoints={task.points}/>
</> </>
) : ( ) : (
<div className="bg-gray-100 rounded-lg p-4 text-gray-600 font-hse-sans"> <div className="bg-gray-100 rounded-lg p-4 text-gray-600 font-hse-sans">
Решение еще не отправлено Решение еще не отправлено
@@ -151,9 +156,34 @@
/> />
)} )}
<div className={`rounded-lg p-3 font-hse-sans text-sm flex items-center
${hasSubmissionsLeft
? 'bg-blue-50 text-blue-700'
: 'bg-red-50 text-red-700'}`}
>
{hasSubmissionsLeft ? (
<>
<span className="font-medium">
Осталось посылок: {submissionsLeft === Infinity ? '∞' : submissionsLeft}
</span>
{maxAttempts !== -1 && (
<span className="text-blue-500 ml-1">
(из {maxAttempts})
</span>
)}
</>
) : (
<span className="font-medium">
Вы использовали все посылки
</span>
)}
</div>
<ActionButtons <ActionButtons
onSubmit={onSubmit} onSubmit={onSubmit}
onHistoryClick={handleOpenHistory} onHistoryClick={handleOpenHistory}
isSubmitting={isSubmitting}
hasSubmissionsLeft={hasSubmissionsLeft}
/> />
<SolutionHistorySheet <SolutionHistorySheet
@@ -5,6 +5,7 @@ interface Task {
type: TaskType; type: TaskType;
in_competition_position: number; in_competition_position: number;
points: number; points: number;
max_attempts: number;
} }
export interface TaskAttachment { export interface TaskAttachment {