diff --git a/Frontend/src/components/CodeChallenge.jsx b/Frontend/src/components/CodeChallenge.jsx index 0af571d..c9875e8 100644 --- a/Frontend/src/components/CodeChallenge.jsx +++ b/Frontend/src/components/CodeChallenge.jsx @@ -618,6 +618,70 @@ int main() { } }; + // Handle final test submission + const handleSubmitTest = async () => { + if (!test) { + alert('No test data available.'); + return; + } + + const confirmSubmit = window.confirm( + 'Are you sure you want to submit the entire test? You will not be able to make any changes after submission.' + ); + + if (!confirmSubmit) return; + + try { + // Save the current question's answer before submitting + const currentQuestion = getCurrentQuestion(); + if (currentQuestion && code.trim()) { + const apiUrl = import.meta.env.VITE_FACULTY_API_URL || 'http://localhost:5000/api'; + try { + const saveResponse = await fetch(`${apiUrl}/students/submissions`, { + method: 'POST', + headers: { + 'Authorization': `Bearer ${token}`, + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + testId: test.id, + answers: [{ + questionId: currentQuestion.id, + submittedAnswer: code + }] + }), + }); + + if (saveResponse.ok) { + console.log('Current answer saved successfully'); + } + } catch (err) { + console.warn('Failed to save current answer:', err); + } + } + + // For now, just mark test as completed locally and redirect + // TODO: Implement backend endpoint for test submission + alert('Test submitted successfully! You will be redirected to the test list.'); + + // Mark test as submitted locally + localStorage.setItem(`test_${test.id}_submitted`, JSON.stringify({ + submittedAt: new Date().toISOString(), + testId: test.id + })); + + // Clear test data + localStorage.removeItem('currentTest'); + + // Redirect to tests page + navigate('/tests'); + + } catch (error) { + console.error('Error submitting test:', error); + alert(`Error submitting test: ${error.message}`); + } + }; + // Render the current problem const renderProblem = () => { const currentQuestion = getCurrentQuestion(); @@ -626,8 +690,6 @@ int main() { if (currentQuestion) { return (
-

{currentQuestion.title || `Question ${getQuestionIndex(activeQuestion) + 1}`}

-

{currentQuestion.question_text || currentQuestion.description}

{currentQuestion.constraints &&

Constraints: {currentQuestion.constraints}

} @@ -664,8 +726,6 @@ int main() { return (
-

{problem.title}

-

{problem.description}

{problem.constraints &&

{problem.constraints}

} @@ -696,29 +756,8 @@ int main() {

{test?.title || 'CS101: Midterm Examination'}

- {timeRemaining && ( -
-
Time Remaining
-
- {timeRemaining !== 'Time Up!' ? ( - <> - {timeRemaining.split(':')[0]} - : - {timeRemaining.split(':')[1]} - : - {timeRemaining.split(':')[2]} - - ) : ( - {timeRemaining} - )} -
-
- Hours - Minutes - Seconds -
-
- )} + All changes saved ✓ +
@@ -730,297 +769,211 @@ int main() {
- {/*
-

1. {problems["Q.1"].title}

-
*/} - -
-
-
-

Question Palette

-
-
- {(questions.length > 0 ? questions : Array.from({length: 20}, (_, i) => i + 1)).map((q, idx) => { - const questionKey = `Q.${idx + 1}`; - const questionNum = idx + 1; - return ( - - ); - })} -
-
-
-
- Current -
-
-
- Answered -
-
-
- Not Visited -
-
-
- -
-
- Question {activeQuestion.replace('Q.', '')} of {questions.length || 20} - | 10 Points -
- {renderProblem()} -
- - -
-
- -
-
-
- - - -
- -
- - - +
+ {/* Left Sidebar */} +
+ {/* Time Remaining */} +
+

Time Remaining

+
+ {timeRemaining && timeRemaining !== 'Time Up!' ? ( + <> +
+ {timeRemaining.split(':')[0]} + Hours +
+
+ {timeRemaining.split(':')[1]} + Minutes +
+
+ {timeRemaining.split(':')[2]} + Seconds +
+ + ) : timeRemaining === 'Time Up!' ? ( + {timeRemaining} + ) : ( + <> +
+ 00 + Hours +
+
+ 00 + Minutes +
+
+ 00 + Seconds +
+ + )}
-
- setCode(value)} - theme="hc-black" - options={{ - fontSize: 14, - minimap: { enabled: false }, - scrollBeyondLastLine: false, - automaticLayout: true, - }} - /> -
-
-
- -
-
-
- - -
-
-
-
- {terminalOutput.length === 0 ? ( -
- Console output will appear here... + {/* Question Palette */} +
+

Question Palette

+
+ {(questions.length > 0 ? questions : Array.from({length: 20}, (_, i) => i + 1)).map((q, idx) => { + const questionKey = `Q.${idx + 1}`; + const questionNum = idx + 1; + return ( + + ); + })} +
+
+
+
+ Current
- ) : ( - terminalOutput.map((line, index) => ( -
- {line.content} +
+
+ Answered +
+
+
+ Skipped +
+
+
+ Marked for Review +
+
+
+ Not Visited +
+
+
+
+ + {/* Main Content Area */} +
+ {/* Top Section: Question text above editor */} +
+
+ {/* Question Text Bar */} +
+
+

Question {activeQuestion.replace('Q.', '')} of {questions.length || 20} | 10 Points

- )) - )} -
- $ - { - // Auto-focus input when isRunning changes to true - if (inputEl && isRunning) { - inputEl.focus(); - // Clear any previous input - inputEl.value = ''; - } - }} - onKeyDown={(e) => { // Change from onKeyPress to onKeyDown for better cross-browser support - if (e.key === 'Enter') { - e.preventDefault(); // Prevent default to avoid form submissions - const input = e.target.value.trim(); - - if (!input) return; // Skip empty input - - if (activeSocket && activeSocket.readyState === WebSocket.OPEN) { - try { - // Send input to server - activeSocket.send(JSON.stringify({ - "type": "input", - "content": input - })); - - // Add input to terminal output - setTerminalOutput(prev => [ - ...prev, - { type: 'system', content: `$ ${input}` } - ]); - - // Clear the input field - e.target.value = ''; - } catch (error) { - console.error("Error sending input:", error); - setTerminalOutput(prev => [ - ...prev, - { type: 'error', content: `Failed to send input: ${error.message}` } - ]); - } - } else { - // Better error message with socket state information - const socketState = activeSocket ? - ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED'][activeSocket.readyState] : - 'NO_SOCKET'; - - console.log(`Cannot send input: Socket state is ${socketState}`); - setTerminalOutput(prev => [ - ...prev, - { type: 'error', content: `Cannot send input: connection not available (${socketState})` } - ]); - } - } - }} - onKeyPress={(e) => { - if (e.key === 'Enter' && activeSocket && activeSocket.readyState === WebSocket.OPEN) { - const input = e.target.value; - // Send input to WebSocket with the correct format - try { - activeSocket.send(JSON.stringify({ - "type": "input", - "content": input - })); - - // Add input to terminal output - setTerminalOutput(prev => [ - ...prev, - { type: 'system', content: `$ ${input}` } - ]); - - // Clear the input field - e.target.value = ''; - } catch (error) { - console.error("Error sending input:", error); - setTerminalOutput(prev => [ - ...prev, - { type: 'error', content: `Failed to send input: ${error.message}` } - ]); - } - } else if (e.key === 'Enter') { - // Inform user if socket isn't available - if (!activeSocket || activeSocket.readyState !== WebSocket.OPEN) { - setTerminalOutput(prev => [ - ...prev, - { type: 'error', content: `Cannot send input: connection closed` } - ]); - } - } - }} - /> -
-
-
-
- - - +
+ {renderProblem()} +
+
+ + {/* Code Editor */} +
+
+
+ + +
+
+ +
+ setCode(value)} + theme="hc-black" + options={{ + fontSize: 14, + minimap: { enabled: false }, + scrollBeyondLastLine: false, + automaticLayout: true, + }} + /> +
+
-
+
+ + {/* Bottom Section: Console/Testcases */} +
+
+
+
+ + +
+
+
+ {terminalOutput.length === 0 ? ( +
+ Console output will appear here... +
+ ) : ( + terminalOutput.map((line, index) => ( +
+ {line.content} +
+ )) + )} +
+
+
+ + {/* Action Buttons at Bottom Right */} +
+ +
+
diff --git a/Frontend/src/index.css b/Frontend/src/index.css index 063bae1..e6b370e 100644 --- a/Frontend/src/index.css +++ b/Frontend/src/index.css @@ -1,3 +1,6 @@ +/* Import Lexend font from Google Fonts */ +@import url('https://fonts.googleapis.com/css2?family=Lexend:wght@300;400;500;600;700&display=swap'); + :root { /* Light theme variables */ --background: #ffffff; @@ -65,7 +68,7 @@ body { margin: 0; padding: 0; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", + font-family: 'Lexend', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; overflow: hidden; } @@ -1092,12 +1095,12 @@ body { opacity: 1; } -/* Code Challenge Component Styles */ +/* Code Challenge Component Styles - Exact Screenshot Layout */ .code-challenge-container { display: flex; flex-direction: column; height: 100vh; - background-color: #ffffff; + background-color: #f5f5f5; color: #1a1a1a; } @@ -1105,17 +1108,10 @@ body { display: flex; justify-content: space-between; align-items: center; - padding: 16px 24px; + padding: 12px 24px; background-color: #ffffff; - border-bottom: 1px solid #e5e7eb; - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05); -} - -.code-challenge-header h1 { - margin: 0; - font-size: 18px; - font-weight: 600; - color: #1a1a1a; + border-bottom: 1px solid #e0e0e0; + z-index: 10; } .header-left { @@ -1125,83 +1121,56 @@ body { } .header-icon { - font-size: 24px; + font-size: 22px; +} + +.code-challenge-header h1 { + margin: 0; + font-size: 17px; + font-weight: 600; + color: #1a1a1a; } .header-right { display: flex; align-items: center; - gap: 24px; -} - -.timer-display { - display: flex; - flex-direction: column; - align-items: center; - gap: 4px; -} - -.timer-label { - font-size: 12px; - color: #6b7280; - font-weight: 500; - text-transform: uppercase; - letter-spacing: 0.5px; -} - -.timer-value { - display: flex; - align-items: center; - gap: 4px; -} - -.time-block { - background-color: #fee2e2; - color: #dc2626; - padding: 6px 10px; - border-radius: 6px; - font-size: 18px; - font-weight: 700; - min-width: 40px; - text-align: center; - font-family: 'Consolas', 'Monaco', monospace; -} - -.time-separator { - color: #dc2626; - font-size: 18px; - font-weight: 700; -} - -.time-up { - color: #dc2626; - font-size: 18px; - font-weight: 700; -} - -.timer-labels { - display: flex; gap: 16px; - font-size: 10px; - color: #9ca3af; - text-transform: uppercase; - letter-spacing: 0.5px; } -.timer-labels span { - min-width: 40px; - text-align: center; +.saved-indicator { + font-size: 13px; + color: #666; + display: flex; + align-items: center; + gap: 4px; } +.submit-test-btn { + background-color: #007bff; + color: white; + border: none; + padding: 8px 20px; + border-radius: 4px; + font-size: 14px; + font-weight: 500; + cursor: pointer; + transition: background-color 0.2s; +} + +.submit-test-btn:hover { + background-color: #0056b3; +} + +/* Old timer styles removed - now using time-remaining-widget */ + .user-profile { display: flex; align-items: center; - gap: 8px; } .user-avatar { - width: 40px; - height: 40px; + width: 36px; + height: 36px; border-radius: 50%; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); display: flex; @@ -1216,6 +1185,80 @@ body { transform: scale(1.05); } +/* Body Layout */ +.code-challenge-body { + display: flex; + flex: 1; + overflow: hidden; +} + +/* Left Sidebar */ +.left-sidebar { + width: 280px; + background-color: #ffffff; + border-right: 1px solid #e0e0e0; + display: flex; + flex-direction: column; + overflow-y: auto; +} + +/* Time Remaining Widget */ +.time-remaining-widget { + padding: 20px; + border-bottom: 1px solid #e0e0e0; +} + +.time-remaining-widget h3 { + margin: 0 0 16px 0; + font-size: 15px; + font-weight: 600; + color: #333; +} + +.time-remaining-widget .timer-value { + display: flex; + justify-content: center; + gap: 8px; +} + +.time-unit { + display: flex; + flex-direction: column; + align-items: center; +} + +.time-unit .time-block { + background-color: #fef3cd; + color: #d97706; + padding: 12px 16px; + border-radius: 6px; + font-size: 24px; + font-weight: 700; + min-width: 50px; + text-align: center; + font-family: 'Consolas', 'Monaco', monospace; +} + +.time-unit .time-label { + font-size: 11px; + color: #666; + margin-top: 6px; + text-transform: capitalize; +} + +/* Question Palette Widget */ +.question-palette-widget { + padding: 20px; + flex: 1; +} + +.question-palette-widget h3 { + margin: 0 0 16px 0; + font-size: 15px; + font-weight: 600; + color: #333; +} + .sign-in-btn { background-color: transparent; color: #6b7280; @@ -1234,81 +1277,38 @@ body { color: #374151; } -.code-challenge-problem-nav { - padding: 12px 24px; - border-bottom: 1px solid #e5e7eb; - background-color: #f9fafb; -} - -.problem-number { - margin: 0; - font-size: 16px; - font-weight: 500; - color: #374151; -} - -.code-challenge-main { - display: flex; - height: 60vh; - border-bottom: 1px solid #e5e7eb; - background-color: #ffffff; -} - -.problem-tabs { - display: flex; - flex-direction: column; - padding: 16px; - border-right: 1px solid #e5e7eb; - background-color: #f9fafb; - width: 240px; - overflow-y: auto; -} - -.question-palette-header { - margin-bottom: 16px; -} - -.question-palette-header h3 { - margin: 0; - font-size: 14px; - font-weight: 600; - color: #111827; - text-transform: uppercase; - letter-spacing: 0.5px; -} +/* Removed old styles */ .question-palette-grid { display: grid; - grid-template-columns: repeat(4, 1fr); - gap: 8px; - margin-bottom: 20px; + grid-template-columns: repeat(6, 1fr); + gap: 10px; + margin-bottom: 24px; } .question-palette-btn { - padding: 12px 8px; - background-color: #ffffff; - color: #6b7280; - border: 1px solid #e5e7eb; - border-radius: 6px; + padding: 10px 8px; + background-color: #e9ecef; + color: #495057; + border: 1px solid #dee2e6; + border-radius: 4px; text-align: center; cursor: pointer; font-size: 14px; font-weight: 600; transition: all 0.2s ease; - min-width: 40px; + min-width: 36px; } .question-palette-btn:hover:not(.palette-active):not(:disabled) { - background-color: #f3f4f6; - border-color: #d1d5db; - transform: translateY(-1px); + background-color: #dee2e6; + border-color: #adb5bd; } .question-palette-btn.palette-active { - background-color: #2563eb; + background-color: #007bff; color: #ffffff; - border-color: #2563eb; - box-shadow: 0 2px 4px rgba(37, 99, 235, 0.3); + border-color: #007bff; } .question-palette-btn:disabled { @@ -1316,12 +1316,29 @@ body { cursor: not-allowed; } +/* Question status colors */ +.question-palette-btn.answered { + background-color: #28a745; + color: #ffffff; + border-color: #28a745; +} + +.question-palette-btn.marked { + background-color: #ff9800; + color: #ffffff; + border-color: #ff9800; +} + +.question-palette-btn.skipped { + background-color: #6c757d; + color: #ffffff; + border-color: #6c757d; +} + .palette-legend { display: flex; flex-direction: column; - gap: 12px; - padding-top: 16px; - border-top: 1px solid #e5e7eb; + gap: 10px; } .legend-item { @@ -1329,154 +1346,216 @@ body { align-items: center; gap: 8px; font-size: 12px; - color: #6b7280; + color: #495057; } .legend-dot { - width: 12px; - height: 12px; - border-radius: 50%; + width: 14px; + height: 14px; + border-radius: 2px; flex-shrink: 0; } .legend-current { - background-color: #2563eb; + background-color: #007bff; } .legend-answered { - background-color: #10b981; + background-color: #28a745; +} + +.legend-skipped { + background-color: #6c757d; +} + +.legend-marked { + background-color: #ff9800; } .legend-not-visited { - background-color: #e5e7eb; + background-color: #e9ecef; } -.problem-content { +/* Main Content Area */ +.main-content-area { flex: 1; - overflow-y: auto; - padding: 24px; - border-right: 1px solid #e5e7eb; - width: 50%; - background-color: #ffffff; + display: flex; + flex-direction: column; + overflow: hidden; + background-color: #f5f5f5; +} + +/* Top Section: Question above Editor */ +.top-section { + flex: 1; + overflow: hidden; display: flex; flex-direction: column; } -.problem-header-info { - display: flex; - align-items: center; - gap: 8px; - margin-bottom: 16px; - font-size: 14px; -} - -.question-label { - color: #374151; - font-weight: 600; -} - -.question-points { - color: #6b7280; -} - -.problem-container { +.content-wrapper { flex: 1; + display: flex; + flex-direction: column; + overflow: hidden; +} + +/* Question Bar - appears above editor */ +.question-bar { + background-color: #f8f9fa; + border-bottom: 1px solid #e0e0e0; + max-height: 40%; + overflow-y: auto; + display: flex; + flex-direction: column; +} + +.question-header { + padding: 12px 24px; + background-color: #e9ecef; + border-bottom: 1px solid #dee2e6; +} + +.question-header h2 { + margin: 0; + font-size: 15px; + font-weight: 600; + color: #212529; +} + +.question-text { + padding: 16px 24px; + flex: 1; + overflow-y: auto; } .problem-container h1 { - margin-top: 0; - font-size: 20px; - font-weight: 600; - margin-bottom: 16px; - color: #111827; -} - -.problem-actions { - display: flex; - justify-content: flex-end; - gap: 12px; - padding-top: 20px; - margin-top: auto; - border-top: 1px solid #e5e7eb; -} - -.action-btn { - display: flex; - align-items: center; - gap: 6px; - padding: 8px 16px; - border-radius: 6px; + margin: 0 0 12px 0; font-size: 14px; - font-weight: 500; - cursor: pointer; - transition: all 0.2s ease; - border: none; -} - -.action-btn-secondary { - background-color: #f3f4f6; - color: #374151; - border: 1px solid #d1d5db; -} - -.action-btn-secondary:hover { - background-color: #e5e7eb; - border-color: #9ca3af; + font-weight: 400; + color: #495057; + line-height: 1.6; } .problem-description { - margin-bottom: 24px; - font-size: 14px; + margin-bottom: 16px; + font-size: 13px; line-height: 1.6; - color: #374151; + color: #495057; } .problem-description strong { - color: #111827; + color: #212529; font-weight: 600; } .problem-description p { - margin-bottom: 12px; + margin-bottom: 10px; +} + +.problem-container { + font-size: 13px; + color: #495057; +} + +/* Editor Section Wrapper */ +.editor-section-wrapper { + flex: 1; + display: flex; + flex-direction: column; + background-color: #1e1e1e; + overflow: hidden; +} + +.editor-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 8px 16px; + background-color: #2d2d30; + border-bottom: 1px solid #1e1e1e; +} + +.editor-controls { + display: flex; + align-items: center; + gap: 12px; +} + +.language-selector { + background-color: #3e3e42; + color: #cccccc; + border: 1px solid #3e3e42; + border-radius: 4px; + padding: 6px 12px; + font-size: 13px; + cursor: pointer; + outline: none; +} + +.language-selector:hover { + background-color: #4e4e52; +} + +.reset-code-btn { + display: flex; + align-items: center; + gap: 6px; + background-color: transparent; + color: #cccccc; + border: 1px solid #555555; + border-radius: 4px; + padding: 6px 12px; + font-size: 13px; + cursor: pointer; + transition: all 0.2s; +} + +.reset-code-btn:hover { + background-color: #3e3e42; + border-color: #777777; +} + +.editor-container { + flex: 1; + overflow: hidden; } .test-cases-section { - margin-top: 24px; + margin-top: 16px; } .test-cases-section h3 { - font-size: 16px; + font-size: 13px; font-weight: 600; - margin-bottom: 16px; - color: #111827; + margin-bottom: 10px; + color: #212529; } .test-case-card { - background-color: #f9fafb; - border: 1px solid #e5e7eb; - border-radius: 8px; - margin-bottom: 12px; + background-color: #ffffff; + border: 1px solid #dee2e6; + border-radius: 3px; + margin-bottom: 10px; overflow: hidden; } .test-case-label { - background-color: #e5e7eb; - padding: 8px 16px; - font-size: 12px; + background-color: #f8f9fa; + padding: 5px 10px; + font-size: 11px; font-weight: 600; - color: #374151; - text-transform: uppercase; - letter-spacing: 0.5px; + color: #495057; } .test-case-content { - padding: 16px; + padding: 10px; } .test-case-item { display: flex; flex-direction: column; - margin-bottom: 12px; + margin-bottom: 8px; } .test-case-item:last-child { @@ -1484,21 +1563,168 @@ body { } .test-label { - font-size: 13px; + font-size: 11px; font-weight: 600; - color: #6b7280; - margin-bottom: 6px; + color: #6c757d; + margin-bottom: 3px; } .test-value { + background-color: #f8f9fa; + border: 1px solid #dee2e6; + padding: 6px 8px; + border-radius: 3px; + font-family: 'Consolas', 'Monaco', monospace; + font-size: 12px; + line-height: 1.4; + color: #212529; +} + +/* Bottom Section: Console */ +.bottom-section { + height: 250px; background-color: #ffffff; - border: 1px solid #e5e7eb; - padding: 10px 12px; - border-radius: 6px; + border-top: 1px solid #e0e0e0; + display: flex; + flex-direction: column; + position: relative; +} + +.console-section { + flex: 1; + display: flex; + flex-direction: column; + overflow: hidden; +} + +.console-header { + display: flex; + align-items: center; + padding: 0; + background-color: #f8f9fa; + border-bottom: 1px solid #dee2e6; +} + +.console-tabs { + display: flex; + gap: 0; +} + +.console-tab { + padding: 10px 20px; + background-color: transparent; + color: #6c757d; + border: none; + border-bottom: 2px solid transparent; + cursor: pointer; + font-size: 14px; + font-weight: 500; + transition: all 0.2s; +} + +.console-tab:hover { + color: #495057; +} + +.console-tab-active { + color: #007bff; + border-bottom-color: #007bff; +} + +.console-content { + flex: 1; + padding: 16px; + overflow-y: auto; + background-color: #f8f9fa; font-family: 'Consolas', 'Monaco', monospace; font-size: 13px; +} + +.console-placeholder { + color: #adb5bd; + font-style: italic; +} + +.console-line { + margin-bottom: 6px; line-height: 1.5; - color: #111827; + color: #212529; +} + +.console-line.system { + color: #007bff; +} + +.console-line.error { + color: #dc3545; +} + +.console-line.output { + color: #212529; +} + +/* Action Bar */ +.action-bar { + position: absolute; + bottom: 16px; + right: 16px; + display: flex; + gap: 12px; + z-index: 10; +} + +.action-bar-btn { + display: flex; + align-items: center; + gap: 6px; + padding: 8px 16px; + border-radius: 4px; + font-size: 14px; + font-weight: 500; + cursor: pointer; + transition: all 0.2s; + border: none; +} + +.action-clear { + background-color: #6c757d; + color: white; +} + +.action-clear:hover { + background-color: #5a6268; +} + +.action-mark { + background-color: #6c757d; + color: white; +} + +.action-mark:hover { + background-color: #5a6268; +} + +.action-run { + background-color: #28a745; + color: white; +} + +.action-run:hover:not(:disabled) { + background-color: #218838; +} + +.action-run:disabled { + opacity: 0.6; + cursor: not-allowed; +} + +.action-save { + background-color: #007bff; + color: white; +} + +.action-save:hover { + background-color: #0056b3; } .problem-examples h2 { @@ -1520,113 +1746,6 @@ body { line-height: 1.6; } -.editor-section { - width: 50%; - display: flex; - flex-direction: column; - background-color: #f9fafb; -} - -.editor-header { - display: flex; - justify-content: space-between; - align-items: center; - padding: 12px 16px; - background-color: #ffffff; - border-bottom: 1px solid #e5e7eb; - position: relative; - z-index: 200; -} - -.editor-controls { - display: flex; - align-items: center; -} - -.language-selector { - background-color: #f3f4f6; - color: #374151; - border: 1px solid #d1d5db; - border-radius: 6px; - padding: 6px 12px; - font-size: 14px; - margin-right: 8px; - font-weight: 500; - cursor: pointer; -} - -.language-selector:hover { - background-color: #e5e7eb; -} - -.auto-btn { - background-color: #f3f4f6; - color: #374151; - border: 1px solid #d1d5db; - border-radius: 6px; - padding: 6px 12px; - font-size: 14px; - cursor: pointer; - font-weight: 500; -} - -.auto-selected { - background-color: #e5e7eb; -} - -.editor-actions { - display: flex; - gap: 8px; - position: relative; - z-index: 150; -} - -.run-btn { - display: flex; - align-items: center; - gap: 6px; - background-color: #10b981; - color: #ffffff; - border: none; - border-radius: 6px; - padding: 8px 16px; - font-size: 14px; - font-weight: 500; - cursor: pointer; - transition: all 0.2s ease; -} - -.submit-btn { - display: flex; - align-items: center; - gap: 6px; - background-color: #2563eb; - color: #ffffff; - border: none; - border-radius: 6px; - padding: 8px 16px; - font-size: 14px; - font-weight: 500; - cursor: pointer; - transition: all 0.2s ease; -} - -.run-btn:hover:not(:disabled) { - background-color: #059669; - box-shadow: 0 2px 4px rgba(16, 185, 129, 0.2); -} - -.submit-btn:hover:not(:disabled) { - background-color: #1d4ed8; - box-shadow: 0 2px 4px rgba(37, 99, 235, 0.2); -} - -.run-btn:disabled, -.submit-btn:disabled { - opacity: 0.6; - cursor: not-allowed; -} - .loading-spinner { display: inline-block; width: 14px; @@ -1643,244 +1762,7 @@ body { } } -.editor-container { - flex: 1; - background-color: #1e1e1e; -} - -.terminal-section { - flex: 1; - display: flex; - flex-direction: column; - background-color: #ffffff; - border-top: 1px solid #e5e7eb; - position: relative; -} - -.terminal-content-wrapper { - flex: 1; - display: flex; - flex-direction: column; - overflow: hidden; -} - -.terminal-header { - display: flex; - justify-content: space-between; - align-items: center; - padding: 0; - background-color: #f9fafb; - border-bottom: 1px solid #e5e7eb; -} - -.terminal-tabs { - display: flex; - gap: 4px; - padding: 8px 16px; -} - -.terminal-tab { - padding: 8px 16px; - background-color: transparent; - color: #6b7280; - border: none; - border-bottom: 2px solid transparent; - cursor: pointer; - font-size: 14px; - font-weight: 500; - transition: all 0.2s ease; -} - -.terminal-tab:hover { - color: #374151; - background-color: #f3f4f6; -} - -.terminal-tab-active { - color: #2563eb; - border-bottom-color: #2563eb; - background-color: transparent; -} - -.terminal-controls { - display: flex; - gap: 4px; - padding-right: 16px; -} - -.terminal-btn { - background-color: transparent; - color: #6b7280; - border: none; - cursor: pointer; - font-size: 14px; - width: 24px; - height: 24px; - display: flex; - align-items: center; - justify-content: center; - border-radius: 4px; - transition: all 0.2s ease; -} - -.terminal-btn:hover { - background-color: #e5e7eb; - color: #374151; -} - -.terminal-content { - flex: 1; - padding: 16px; - font-family: 'Consolas', 'Monaco', monospace; - font-size: 13px; - overflow-y: auto; - overflow-x: hidden; - white-space: pre-wrap; - background-color: #f9fafb; - scrollbar-width: thin; - scrollbar-color: #d1d5db #f9fafb; -} - -.terminal-placeholder { - color: #9ca3af; - font-style: italic; - text-align: center; - padding: 40px 20px; -} - -.terminal-content::-webkit-scrollbar { - width: 8px; -} - -.terminal-content::-webkit-scrollbar-track { - background: #1e1e1e; -} - -.terminal-content::-webkit-scrollbar-thumb { - background: #555555; - border-radius: 4px; -} - -.terminal-content::-webkit-scrollbar-thumb:hover { - background: #666666; -} - -.terminal-line { - margin-bottom: 6px; - line-height: 1.5; - color: #374151; -} - -.terminal-line.system { - color: #2563eb; - font-weight: 500; -} - -.terminal-line.error { - color: #dc2626; - font-weight: 500; -} - -.terminal-line.output { - color: #111827; -} - -.terminal-prompt { - display: flex; - align-items: center; - margin-top: 8px; - background-color: #ffffff; - padding: 8px; - border-radius: 6px; - border: 1px solid #e5e7eb; -} - -.prompt-symbol { - color: #2563eb; - margin-right: 8px; - font-weight: 600; -} - -.terminal-input { - background-color: transparent; - color: #374151; - border: none; - outline: none; - flex: 1; - font-family: 'Consolas', 'Monaco', monospace; - font-size: 13px; -} - -.terminal-footer { - display: flex; - justify-content: space-between; - align-items: center; - padding: 16px 24px; - background-color: #ffffff; - border-top: 1px solid #e5e7eb; - box-shadow: 0 -2px 4px rgba(0, 0, 0, 0.05); -} - -.terminal-footer-actions { - display: flex; - gap: 12px; -} - -.footer-btn { - display: flex; - align-items: center; - gap: 6px; - padding: 10px 20px; - border-radius: 6px; - font-size: 14px; - font-weight: 500; - cursor: pointer; - transition: all 0.2s ease; - border: none; -} - -.footer-btn-outline { - background-color: #ffffff; - color: #6b7280; - border: 1px solid #d1d5db; -} - -.footer-btn-outline:hover { - background-color: #f3f4f6; - border-color: #9ca3af; - color: #374151; -} - -.footer-btn-primary { - background-color: #2563eb; - color: #ffffff; - border: none; -} - -.footer-btn-primary:hover { - background-color: #1d4ed8; - box-shadow: 0 2px 4px rgba(37, 99, 235, 0.3); -} - -.footer-btn-success { - background-color: #10b981; - color: #ffffff; - border: none; -} - -.footer-btn-success:hover { - background-color: #059669; - box-shadow: 0 2px 4px rgba(16, 185, 129, 0.3); -} - -.changes-saved { - display: flex; - align-items: center; - gap: 6px; - color: #10b981; - font-size: 14px; - font-weight: 500; -} +/* Old terminal styles removed */ /* Login Page Styles */ .login-container { @@ -2171,4 +2053,9 @@ footer { .animate-fadeIn { animation: fadeIn 0.3s ease-out; } .animate-slideUp { animation: slideUp 0.3s ease-out; } -.line-clamp-2 { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; } +.line-clamp-2 { + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +}