@@ -78,68 +84,136 @@ export default function ContestsPage() {
}
return (
-
-
-
Контесты
-
-
-
- {activeContests.length} активных
-
-
{contests.length} всего
-
-
+
+ {/* Background */}
+
+
-
-
-
-
- Все ({contests.length})
-
-
-
- Активные ({activeContests.length})
-
-
-
- Предстоящие ({upcomingContests.length})
-
-
-
- Прошедшие ({pastContests.length})
-
-
-
-
- {filteredContests().length > 0 ? (
+
+ {/* Header */}
- {filteredContests().map((contest) => (
-
-
-
- ))}
+
+
+
+
+
+
+
+
+
+ $ active_competitions.list()
+
+
+
+
+ {/* Stats */}
+
+ {activeContests.length > 0 && (
+
+
+
+ {activeContests.length} LIVE
+
+
+ )}
+
+ {contests.length} всего
+
+
- ) : (
-
-
-
Контестов в этой категории пока нет
-
- )}
+
+ {/* Tabs */}
+
+
+
+
+ Все
+
+ {contests.length}
+
+
+
+
+ Активные
+ {activeContests.length > 0 && (
+
+ {activeContests.length}
+
+ )}
+
+
+
+ Предстоящие
+
+ {upcomingContests.length}
+
+
+
+
+ Прошедшие
+
+ {pastContests.length}
+
+
+
+
+
+ {/* Contest Grid */}
+ {filteredContests().length > 0 ? (
+
+ {filteredContests().map((contest) => (
+
+
+
+ ))}
+
+ ) : (
+
+
+
+ > Контестов в этой категории пока нет
+
+
+ // check back later
+
+
+ )}
+
);
}
diff --git a/frontend/src/app/globals.css b/frontend/src/app/globals.css
index 3ddfd11..5d53232 100644
--- a/frontend/src/app/globals.css
+++ b/frontend/src/app/globals.css
@@ -1,84 +1,237 @@
@import "tailwindcss";
@theme {
- /* Base colors */
- --color-background: #ffffff;
- --color-foreground: #0a0a0a;
- --color-primary: #2563eb;
- --color-primary-foreground: #ffffff;
- --color-secondary: #f1f5f9;
- --color-secondary-foreground: #0f172a;
- --color-muted: #f1f5f9;
- --color-muted-foreground: #64748b;
- --color-accent: #f1f5f9;
- --color-accent-foreground: #0f172a;
- --color-destructive: #ef4444;
+ /* ========================================
+ CYBERPUNK THEME - ВолГУ.Контесты
+ ======================================== */
+
+ /* Base colors - Dark theme by default */
+ --color-background: #0a0a0f;
+ --color-foreground: #e4e4e7;
+
+ /* Neon accent colors */
+ --color-neon-green: #00ff88;
+ --color-neon-cyan: #00f5ff;
+ --color-neon-purple: #bf00ff;
+ --color-neon-pink: #ff0080;
+ --color-neon-yellow: #f0ff00;
+ --color-neon-orange: #ff6b00;
+
+ /* Semantic color mapping */
+ --color-primary: #00ff88;
+ --color-primary-foreground: #0a0a0f;
+ --color-secondary: #1a1a2e;
+ --color-secondary-foreground: #e4e4e7;
+ --color-muted: #1a1a2e;
+ --color-muted-foreground: #71717a;
+ --color-accent: #1e1e3f;
+ --color-accent-foreground: #00f5ff;
+ --color-destructive: #ff3366;
--color-destructive-foreground: #ffffff;
- --color-popover: #ffffff;
- --color-popover-foreground: #0a0a0a;
- --color-card: #ffffff;
- --color-card-foreground: #0a0a0a;
- --color-border: #e2e8f0;
- --color-input: #e2e8f0;
- --color-ring: #2563eb;
- --radius: 0.5rem;
+ --color-popover: #0f0f1a;
+ --color-popover-foreground: #e4e4e7;
+ --color-card: #0f0f1a;
+ --color-card-foreground: #e4e4e7;
+ --color-border: #2a2a4a;
+ --color-input: #1a1a2e;
+ --color-ring: #00ff88;
+ --radius: 0.25rem;
- /* Additional semantic colors */
- --color-success: #22c55e;
- --color-success-foreground: #ffffff;
- --color-warning: #f59e0b;
- --color-warning-foreground: #000000;
- --color-info: #3b82f6;
- --color-info-foreground: #ffffff;
+ /* Semantic status colors */
+ --color-success: #00ff88;
+ --color-success-foreground: #0a0a0f;
+ --color-warning: #f0ff00;
+ --color-warning-foreground: #0a0a0f;
+ --color-info: #00f5ff;
+ --color-info-foreground: #0a0a0f;
- /* Card shadow */
- --shadow-card: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
- --shadow-card-hover: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
+ /* Glow effects */
+ --glow-green: 0 0 20px rgba(0, 255, 136, 0.5);
+ --glow-green-intense: 0 0 30px rgba(0, 255, 136, 0.7), 0 0 60px rgba(0, 255, 136, 0.3);
+ --glow-cyan: 0 0 20px rgba(0, 245, 255, 0.5);
+ --glow-cyan-intense: 0 0 30px rgba(0, 245, 255, 0.7), 0 0 60px rgba(0, 245, 255, 0.3);
+ --glow-purple: 0 0 20px rgba(191, 0, 255, 0.5);
+ --glow-purple-intense: 0 0 30px rgba(191, 0, 255, 0.7), 0 0 60px rgba(191, 0, 255, 0.3);
+ --glow-pink: 0 0 20px rgba(255, 0, 128, 0.5);
+ --glow-yellow: 0 0 20px rgba(240, 255, 0, 0.5);
+ --glow-orange: 0 0 20px rgba(255, 107, 0, 0.5);
+
+ /* Card shadows */
+ --shadow-card: 0 4px 20px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.03);
+ --shadow-card-hover: 0 8px 30px rgba(0, 0, 0, 0.6), 0 0 20px rgba(0, 255, 136, 0.1);
+
+ /* Typography */
+ --font-display: 'Orbitron', sans-serif;
+ --font-mono: 'JetBrains Mono', monospace;
}
-@media (prefers-color-scheme: dark) {
- @theme {
- --color-background: #0a0a0a;
- --color-foreground: #fafafa;
- --color-primary: #3b82f6;
- --color-primary-foreground: #ffffff;
- --color-secondary: #1e293b;
- --color-secondary-foreground: #f8fafc;
- --color-muted: #1e293b;
- --color-muted-foreground: #94a3b8;
- --color-accent: #1e293b;
- --color-accent-foreground: #f8fafc;
- --color-destructive: #dc2626;
- --color-destructive-foreground: #ffffff;
- --color-popover: #1c1c1c;
- --color-popover-foreground: #fafafa;
- --color-card: #1c1c1c;
- --color-card-foreground: #fafafa;
- --color-border: #334155;
- --color-input: #334155;
- --color-ring: #3b82f6;
-
- /* Dark mode semantic colors */
- --color-success: #4ade80;
- --color-success-foreground: #000000;
- --color-warning: #fbbf24;
- --color-warning-foreground: #000000;
- --color-info: #60a5fa;
- --color-info-foreground: #000000;
-
- /* Dark mode shadows */
- --shadow-card: 0 1px 3px 0 rgb(0 0 0 / 0.3), 0 1px 2px -1px rgb(0 0 0 / 0.3);
- --shadow-card-hover: 0 10px 15px -3px rgb(0 0 0 / 0.3), 0 4px 6px -4px rgb(0 0 0 / 0.3);
- }
-}
+/* ========================================
+ BASE STYLES
+ ======================================== */
body {
background: var(--color-background);
color: var(--color-foreground);
- font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
+ font-family: var(--font-mono), system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
-/* Animations */
+/* ========================================
+ CYBERPUNK ANIMATIONS
+ ======================================== */
+
+/* Glitch effect */
+@keyframes glitch {
+ 0%, 100% {
+ clip-path: inset(0 0 0 0);
+ transform: translate(0);
+ }
+ 20% {
+ clip-path: inset(20% 0 60% 0);
+ transform: translate(-2px, 2px);
+ }
+ 40% {
+ clip-path: inset(40% 0 40% 0);
+ transform: translate(2px, -2px);
+ }
+ 60% {
+ clip-path: inset(60% 0 20% 0);
+ transform: translate(-1px, 1px);
+ }
+ 80% {
+ clip-path: inset(80% 0 5% 0);
+ transform: translate(1px, -1px);
+ }
+}
+
+@keyframes glitch-text {
+ 0%, 100% {
+ text-shadow: 2px 0 var(--color-neon-cyan), -2px 0 var(--color-neon-pink);
+ }
+ 25% {
+ text-shadow: -2px 0 var(--color-neon-cyan), 2px 0 var(--color-neon-pink);
+ }
+ 50% {
+ text-shadow: 2px 0 var(--color-neon-pink), -2px 0 var(--color-neon-cyan);
+ }
+ 75% {
+ text-shadow: -2px 0 var(--color-neon-pink), 2px 0 var(--color-neon-cyan);
+ }
+}
+
+@keyframes glitch-skew {
+ 0%, 100% {
+ transform: skew(0deg);
+ }
+ 20% {
+ transform: skew(-2deg);
+ }
+ 40% {
+ transform: skew(2deg);
+ }
+ 60% {
+ transform: skew(-1deg);
+ }
+ 80% {
+ transform: skew(1deg);
+ }
+}
+
+/* Neon pulse */
+@keyframes neon-pulse {
+ 0%, 100% {
+ filter: drop-shadow(0 0 5px currentColor);
+ opacity: 1;
+ }
+ 50% {
+ filter: drop-shadow(0 0 20px currentColor) drop-shadow(0 0 40px currentColor);
+ opacity: 0.9;
+ }
+}
+
+@keyframes neon-border-pulse {
+ 0%, 100% {
+ box-shadow: 0 0 5px var(--color-neon-green), inset 0 0 5px rgba(0, 255, 136, 0.1);
+ border-color: var(--color-neon-green);
+ }
+ 50% {
+ box-shadow: 0 0 20px var(--color-neon-green), 0 0 40px var(--color-neon-green), inset 0 0 10px rgba(0, 255, 136, 0.2);
+ border-color: var(--color-neon-green);
+ }
+}
+
+/* Scanline effect */
+@keyframes scanline {
+ 0% {
+ transform: translateY(-100%);
+ }
+ 100% {
+ transform: translateY(100vh);
+ }
+}
+
+/* Blink cursor */
+@keyframes blink-cursor {
+ 0%, 100% {
+ opacity: 1;
+ }
+ 50% {
+ opacity: 0;
+ }
+}
+
+/* Flicker */
+@keyframes flicker {
+ 0%, 100% {
+ opacity: 1;
+ }
+ 92% {
+ opacity: 1;
+ }
+ 93% {
+ opacity: 0.3;
+ }
+ 94% {
+ opacity: 1;
+ }
+ 96% {
+ opacity: 0.5;
+ }
+ 97% {
+ opacity: 1;
+ }
+}
+
+/* Data stream */
+@keyframes data-stream {
+ 0% {
+ background-position: 0% 0%;
+ }
+ 100% {
+ background-position: 0% 100%;
+ }
+}
+
+/* Float animation */
+@keyframes float {
+ 0%, 100% {
+ transform: translateY(0px);
+ }
+ 50% {
+ transform: translateY(-20px);
+ }
+}
+
+/* Rotate glow */
+@keyframes rotate-glow {
+ 0% {
+ filter: hue-rotate(0deg);
+ }
+ 100% {
+ filter: hue-rotate(360deg);
+ }
+}
+
+/* Preserved animations from original */
@keyframes shimmer {
0% {
background-position: -200% 0;
@@ -102,13 +255,13 @@ body {
@keyframes pulse-ring {
0% {
- box-shadow: 0 0 0 0 rgba(34, 197, 94, 0.7);
+ box-shadow: 0 0 0 0 rgba(0, 255, 136, 0.7);
}
70% {
- box-shadow: 0 0 0 10px rgba(34, 197, 94, 0);
+ box-shadow: 0 0 0 10px rgba(0, 255, 136, 0);
}
100% {
- box-shadow: 0 0 0 0 rgba(34, 197, 94, 0);
+ box-shadow: 0 0 0 0 rgba(0, 255, 136, 0);
}
}
@@ -121,7 +274,54 @@ body {
}
}
-/* Utility classes */
+/* ========================================
+ ANIMATION UTILITY CLASSES
+ ======================================== */
+
+.animate-glitch {
+ animation: glitch 0.3s infinite;
+}
+
+.animate-glitch-text {
+ animation: glitch-text 2s infinite;
+}
+
+.animate-glitch-skew {
+ animation: glitch-skew 0.5s infinite;
+}
+
+.animate-neon-pulse {
+ animation: neon-pulse 2s ease-in-out infinite;
+}
+
+.animate-neon-border-pulse {
+ animation: neon-border-pulse 2s ease-in-out infinite;
+}
+
+.animate-scanline {
+ animation: scanline 8s linear infinite;
+}
+
+.animate-blink-cursor {
+ animation: blink-cursor 1s step-end infinite;
+}
+
+.animate-flicker {
+ animation: flicker 4s infinite;
+}
+
+.animate-data-stream {
+ animation: data-stream 20s linear infinite;
+}
+
+.animate-float {
+ animation: float 6s ease-in-out infinite;
+}
+
+.animate-rotate-glow {
+ animation: rotate-glow 10s linear infinite;
+}
+
.animate-shimmer {
background: linear-gradient(
90deg,
@@ -145,15 +345,266 @@ body {
animation: spin 1s linear infinite;
}
-/* Focus visible styles for accessibility */
-.focus-visible-ring:focus-visible {
- outline: none;
- ring: 2px;
- ring-color: var(--color-ring);
- ring-offset: 2px;
+/* ========================================
+ GLOW UTILITY CLASSES
+ ======================================== */
+
+.glow-green {
+ box-shadow: var(--glow-green);
}
-/* Scrollbar styling */
+.glow-green-intense {
+ box-shadow: var(--glow-green-intense);
+}
+
+.glow-cyan {
+ box-shadow: var(--glow-cyan);
+}
+
+.glow-cyan-intense {
+ box-shadow: var(--glow-cyan-intense);
+}
+
+.glow-purple {
+ box-shadow: var(--glow-purple);
+}
+
+.glow-purple-intense {
+ box-shadow: var(--glow-purple-intense);
+}
+
+.glow-pink {
+ box-shadow: var(--glow-pink);
+}
+
+.glow-yellow {
+ box-shadow: var(--glow-yellow);
+}
+
+.glow-orange {
+ box-shadow: var(--glow-orange);
+}
+
+.text-glow-green {
+ text-shadow: 0 0 10px var(--color-neon-green), 0 0 20px var(--color-neon-green);
+}
+
+.text-glow-cyan {
+ text-shadow: 0 0 10px var(--color-neon-cyan), 0 0 20px var(--color-neon-cyan);
+}
+
+.text-glow-purple {
+ text-shadow: 0 0 10px var(--color-neon-purple), 0 0 20px var(--color-neon-purple);
+}
+
+.text-glow-pink {
+ text-shadow: 0 0 10px var(--color-neon-pink), 0 0 20px var(--color-neon-pink);
+}
+
+/* ========================================
+ CYBER DECORATIVE CLASSES
+ ======================================== */
+
+/* Cyber grid background */
+.cyber-grid {
+ background-image:
+ linear-gradient(rgba(0, 255, 136, 0.03) 1px, transparent 1px),
+ linear-gradient(90deg, rgba(0, 255, 136, 0.03) 1px, transparent 1px);
+ background-size: 50px 50px;
+}
+
+.cyber-grid-dense {
+ background-image:
+ linear-gradient(rgba(0, 255, 136, 0.05) 1px, transparent 1px),
+ linear-gradient(90deg, rgba(0, 255, 136, 0.05) 1px, transparent 1px);
+ background-size: 20px 20px;
+}
+
+/* Scanline overlay */
+.scanline-overlay {
+ position: relative;
+}
+
+.scanline-overlay::after {
+ content: '';
+ position: absolute;
+ inset: 0;
+ background: repeating-linear-gradient(
+ 0deg,
+ transparent,
+ transparent 2px,
+ rgba(0, 0, 0, 0.1) 2px,
+ rgba(0, 0, 0, 0.1) 4px
+ );
+ pointer-events: none;
+}
+
+/* Corner accent brackets */
+.corner-accent {
+ position: relative;
+}
+
+.corner-accent::before,
+.corner-accent::after {
+ content: '';
+ position: absolute;
+ width: 16px;
+ height: 16px;
+ border-color: var(--color-neon-green);
+ border-style: solid;
+ border-width: 0;
+ opacity: 0.5;
+ transition: opacity 0.3s ease;
+}
+
+.corner-accent::before {
+ top: 8px;
+ left: 8px;
+ border-top-width: 2px;
+ border-left-width: 2px;
+}
+
+.corner-accent::after {
+ bottom: 8px;
+ right: 8px;
+ border-bottom-width: 2px;
+ border-right-width: 2px;
+}
+
+.corner-accent:hover::before,
+.corner-accent:hover::after {
+ opacity: 1;
+}
+
+/* All corners variant */
+.corner-accent-all {
+ position: relative;
+}
+
+.corner-accent-all::before {
+ content: '';
+ position: absolute;
+ top: 4px;
+ left: 4px;
+ right: 4px;
+ bottom: 4px;
+ border: 2px solid transparent;
+ border-image: linear-gradient(
+ 45deg,
+ var(--color-neon-green) 0%,
+ transparent 30%,
+ transparent 70%,
+ var(--color-neon-green) 100%
+ ) 1;
+ pointer-events: none;
+}
+
+/* Cyber border with gradient */
+.cyber-border {
+ border: 1px solid var(--color-border);
+ position: relative;
+}
+
+.cyber-border::before {
+ content: '';
+ position: absolute;
+ inset: -1px;
+ background: linear-gradient(
+ 45deg,
+ var(--color-neon-green),
+ transparent,
+ var(--color-neon-cyan),
+ transparent,
+ var(--color-neon-purple)
+ );
+ z-index: -1;
+ opacity: 0;
+ transition: opacity 0.3s ease;
+ border-radius: inherit;
+}
+
+.cyber-border:hover::before {
+ opacity: 0.5;
+}
+
+/* Neon underline */
+.neon-underline {
+ position: relative;
+}
+
+.neon-underline::after {
+ content: '';
+ position: absolute;
+ bottom: -2px;
+ left: 0;
+ width: 0;
+ height: 2px;
+ background: var(--color-neon-green);
+ box-shadow: var(--glow-green);
+ transition: width 0.3s ease;
+}
+
+.neon-underline:hover::after,
+.neon-underline.active::after {
+ width: 100%;
+}
+
+/* Hexagon clip path */
+.clip-hexagon {
+ clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
+}
+
+/* Diamond clip path */
+.clip-diamond {
+ clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
+}
+
+/* Chamfered corners (cut corners) */
+.clip-chamfer {
+ clip-path: polygon(
+ 12px 0,
+ calc(100% - 12px) 0,
+ 100% 12px,
+ 100% calc(100% - 12px),
+ calc(100% - 12px) 100%,
+ 12px 100%,
+ 0 calc(100% - 12px),
+ 0 12px
+ );
+}
+
+/* ========================================
+ FONT UTILITY CLASSES
+ ======================================== */
+
+.font-display {
+ font-family: var(--font-display);
+ letter-spacing: 0.1em;
+}
+
+.font-mono-cyber {
+ font-family: var(--font-mono);
+ font-variant-numeric: tabular-nums;
+}
+
+/* Tech heading style */
+.cyber-heading {
+ font-family: var(--font-display);
+ text-transform: uppercase;
+ letter-spacing: 0.15em;
+}
+
+/* Terminal text */
+.terminal-text {
+ font-family: var(--font-mono);
+ font-size: 0.875rem;
+ line-height: 1.5;
+}
+
+/* ========================================
+ SCROLLBAR STYLING
+ ======================================== */
+
::-webkit-scrollbar {
width: 8px;
height: 8px;
@@ -165,25 +616,87 @@ body {
}
::-webkit-scrollbar-thumb {
- background: var(--color-muted-foreground);
+ background: var(--color-border);
border-radius: 4px;
+ border: 1px solid var(--color-muted);
}
::-webkit-scrollbar-thumb:hover {
- background: var(--color-foreground);
+ background: var(--color-neon-green);
+ box-shadow: var(--glow-green);
}
-/* Panel resize handle styling */
+/* ========================================
+ PANEL RESIZE HANDLE STYLING
+ ======================================== */
+
[data-panel-resize-handle-enabled] {
- transition: background-color 0.2s ease;
+ transition: all 0.2s ease;
}
[data-panel-resize-handle-enabled]:hover {
- background-color: var(--color-primary) !important;
+ background-color: var(--color-neon-green) !important;
opacity: 0.5;
+ box-shadow: var(--glow-green);
}
[data-panel-resize-handle-enabled][data-resize-handle-active] {
- background-color: var(--color-primary) !important;
+ background-color: var(--color-neon-green) !important;
opacity: 0.8;
+ box-shadow: var(--glow-green-intense);
+}
+
+/* ========================================
+ FOCUS VISIBLE STYLES
+ ======================================== */
+
+.focus-visible-ring:focus-visible {
+ outline: none;
+ box-shadow: 0 0 0 2px var(--color-background), 0 0 0 4px var(--color-neon-green), var(--glow-green);
+}
+
+/* ========================================
+ ACCESSIBILITY - REDUCED MOTION
+ ======================================== */
+
+@media (prefers-reduced-motion: reduce) {
+ .animate-glitch,
+ .animate-glitch-text,
+ .animate-glitch-skew,
+ .animate-neon-pulse,
+ .animate-neon-border-pulse,
+ .animate-scanline,
+ .animate-blink-cursor,
+ .animate-flicker,
+ .animate-data-stream,
+ .animate-float,
+ .animate-rotate-glow,
+ .animate-shimmer,
+ .animate-shake,
+ .animate-pulse-ring,
+ .animate-spin {
+ animation: none !important;
+ }
+
+ *,
+ *::before,
+ *::after {
+ animation-duration: 0.01ms !important;
+ animation-iteration-count: 1 !important;
+ transition-duration: 0.01ms !important;
+ }
+}
+
+/* ========================================
+ SELECTION STYLING
+ ======================================== */
+
+::selection {
+ background: rgba(0, 255, 136, 0.3);
+ color: var(--color-foreground);
+}
+
+::-moz-selection {
+ background: rgba(0, 255, 136, 0.3);
+ color: var(--color-foreground);
}
diff --git a/frontend/src/app/layout.tsx b/frontend/src/app/layout.tsx
index 73ca7d7..9ebe73a 100644
--- a/frontend/src/app/layout.tsx
+++ b/frontend/src/app/layout.tsx
@@ -1,12 +1,27 @@
import type { Metadata } from "next";
+import { JetBrains_Mono, Orbitron } from "next/font/google";
import "./globals.css";
import { Navbar } from "@/components/Navbar";
import { AuthProvider } from "@/lib/auth-context";
import { Toaster } from "sonner";
+// Cyberpunk fonts
+const jetbrainsMono = JetBrains_Mono({
+ subsets: ["latin", "cyrillic"],
+ variable: "--font-mono",
+ display: "swap",
+});
+
+const orbitron = Orbitron({
+ subsets: ["latin"],
+ variable: "--font-display",
+ display: "swap",
+});
+
export const metadata: Metadata = {
title: "ВолГУ.Контесты — Соревнования по программированию",
- description: "Платформа для проведения соревнований по олимпиадному программированию от Волгоградского государственного университета",
+ description:
+ "Платформа для проведения соревнований по олимпиадному программированию от Волгоградского государственного университета",
};
export default function RootLayout({
@@ -15,11 +30,17 @@ export default function RootLayout({
children: React.ReactNode;
}>) {
return (
-
-
+
+
-
- {children}
+ {/* Cyber grid background overlay */}
+
+
+ {/* Main content */}
+
+
+ {children}
+
diff --git a/frontend/src/app/login/page.tsx b/frontend/src/app/login/page.tsx
index bafbe42..37d3ec7 100644
--- a/frontend/src/app/login/page.tsx
+++ b/frontend/src/app/login/page.tsx
@@ -11,7 +11,10 @@ import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { AlertError } from "@/components/ui/alert";
-import { LogIn, Mail, Lock, Eye, EyeOff, Trophy } from "lucide-react";
+import { LogIn, Mail, Lock, Eye, EyeOff, Terminal, ArrowRight } from "lucide-react";
+import { GlowOrbs, GlitchText, CornerBrackets } from "@/components/decorative";
+import { AuthIllustration } from "@/components/illustrations";
+import { CyberBrandText, VolguLogo } from "@/components/VolguLogo";
export default function LoginPage() {
const [email, setEmail] = useState("");
@@ -39,103 +42,185 @@ export default function LoginPage() {
};
return (
-
-
-
-
-
-
-
- Вход
-
- Войдите в свой аккаунт для участия в контестах
+
+ {/* Background effects */}
+
+
+
+ {/* Decorative elements */}
+
+
+ {"// authenticating..."}
+
+
+
+
+ {""}
+
+
+
+
+ {/* Left side - Illustration (hidden on mobile) */}
+
+
+
+
+ $ Безопасный вход в систему
-
-
-
+
-
-
-
-
-
setEmail(e.target.value)}
- required
- className="pl-10"
- placeholder="email@example.com"
+ {/* Right side - Login form */}
+
+
+ {/* Card glow effect */}
+
+
+
+
+
+
+ {/* Animated ring */}
+
-
+
-
-
-
-
- setPassword(e.target.value)}
- required
- className="pl-10 pr-10"
- placeholder="••••••••"
- />
-
-
-
-
-
-
-
-
-
- Нет аккаунта?{" "}
-
- Зарегистрироваться
-
+
+
+
+
+ > Войдите для участия в контестах
-
-
-
-
+
+
+
+
+
+ {/* Divider */}
+
+
+
+
+ Нет аккаунта?{" "}
+
+ Зарегистрироваться
+
+
+
+
+ {/* Bottom decoration */}
+
+
+
+
+
);
}
diff --git a/frontend/src/app/page.tsx b/frontend/src/app/page.tsx
index 5172cd2..0f43544 100644
--- a/frontend/src/app/page.tsx
+++ b/frontend/src/app/page.tsx
@@ -4,65 +4,72 @@ import Link from "next/link";
import { motion } from "framer-motion";
import { Card, CardContent } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
+import { Button } from "@/components/ui/button";
import { useAuth } from "@/lib/auth-context";
import {
Trophy,
Zap,
Code2,
Users,
- CheckCircle2,
ArrowRight,
Terminal,
Timer,
BarChart3,
+ Cpu,
+ Shield,
+ Sparkles,
} from "lucide-react";
-import { VolguLogo } from "@/components/VolguLogo";
+import { CyberBrandText, VolguLogo } from "@/components/VolguLogo";
+import { GlowOrbs, GlitchText, CornerBrackets, TypewriterText } from "@/components/decorative";
+import { HeroIllustration } from "@/components/illustrations";
+import { MatrixRain } from "@/components/effects";
const features = [
{
icon: Trophy,
title: "Соревнования",
description: "Участвуйте в контестах и соревнуйтесь с другими программистами",
- color: "text-yellow-500",
- bgColor: "bg-yellow-500/10",
+ color: "var(--color-neon-green)",
},
{
icon: Zap,
title: "Автопроверка",
description: "Мгновенная проверка решений с детальными результатами по каждому тесту",
- color: "text-blue-500",
- bgColor: "bg-blue-500/10",
+ color: "var(--color-neon-cyan)",
},
{
icon: Code2,
title: "30+ языков",
description: "Python, C++, Java, JavaScript, Go, Rust и многие другие языки",
- color: "text-green-500",
- bgColor: "bg-green-500/10",
+ color: "var(--color-neon-purple)",
},
{
icon: Timer,
title: "Real-time таймеры",
description: "Следите за временем контеста и оставшимся временем в реальном времени",
- color: "text-orange-500",
- bgColor: "bg-orange-500/10",
+ color: "var(--color-neon-orange)",
},
{
icon: BarChart3,
title: "Рейтинг",
description: "Отслеживайте свой прогресс и соревнуйтесь в таблице лидеров",
- color: "text-purple-500",
- bgColor: "bg-purple-500/10",
+ color: "var(--color-neon-pink)",
},
{
icon: Terminal,
title: "Удобный редактор",
description: "Современный редактор кода с подсветкой синтаксиса и автодополнением",
- color: "text-pink-500",
- bgColor: "bg-pink-500/10",
+ color: "var(--color-neon-yellow)",
},
];
+const stats = [
+ { value: "30+", label: "Языков", color: "var(--color-neon-green)" },
+ { value: "∞", label: "Контестов", color: "var(--color-neon-cyan)" },
+ { value: "100%", label: "Автопроверка", color: "var(--color-neon-purple)" },
+ { value: "24/7", label: "Доступность", color: "var(--color-neon-pink)" },
+];
+
const containerVariants = {
hidden: { opacity: 0 },
visible: {
@@ -82,109 +89,164 @@ export default function HomePage() {
const { user } = useAuth();
return (
-
+
{/* Hero Section */}
-
- {/* Background gradient */}
-
-
-
-
-
-
-
- Волгоградский государственный университет
-
-
-
- ВолГУ
- .
- Контесты
-
-
-
- Платформа для проведения соревнований по олимпиадному программированию
- от Волгоградского государственного университета.
-
-
-
-
-
- Перейти к контестам
-
-
- {!user && (
-
-
- Создать аккаунт
-
- )}
-
-
-
- {/* Stats */}
-
- {[
- { value: "30+", label: "Языков программирования" },
- { value: "∞", label: "Контестов" },
- { value: "100%", label: "Автопроверка" },
- { value: "24/7", label: "Доступность" },
- ].map((stat, index) => (
-
-
- {stat.value}
-
-
{stat.label}
-
- ))}
-
+
+ {/* Background Effects */}
+
+
+
+
+ {/* Cyber grid overlay */}
+
+
+ {/* Scanline effect */}
+
+
+
+
+ {/* Left column - Text content */}
+
+ {/* University badge */}
+
+
+
+
+
+
+
+ {/* Main heading */}
+
+
+
+
+ {/* Subtitle with terminal style */}
+
+
+ $ Платформа для проведения соревнований по{" "}
+
+ олимпиадному программированию
+
+
+
+ >
+ _
+
+
+
+ {/* CTA Buttons */}
+
+
+ {!user && (
+
+ )}
+
+
+ {/* Stats */}
+
+ {stats.map((stat, index) => (
+
+
+
+
+ {stat.value}
+
+
+ {stat.label}
+
+
+
+ ))}
+
+
+
+ {/* Right column - Illustration */}
+
+
+
+
+
+
+ {/* Bottom gradient fade */}
+
{/* Features Section */}
-
-
+
+
+
+
-
- Возможности
+
+
+ SYSTEM.FEATURES
-
- Всё, что нужно для соревнований
+
+ <
+ Возможности платформы
+ />
-
- Наша платформа предоставляет все необходимые инструменты для проведения
- и участия в соревнованиях по программированию
+
+ Все необходимые инструменты для проведения и участия в соревнованиях
@@ -199,15 +261,44 @@ export default function HomePage() {
const Icon = feature.icon;
return (
-
-
+
+
+ {/* Icon with glow */}
-
+
- {feature.title}
- {feature.description}
+
+ {/* Title */}
+
+ {feature.title}
+
+
+ {/* Description */}
+
+ {feature.description}
+
+
+ {/* Hover effect line */}
+
@@ -218,32 +309,76 @@ export default function HomePage() {
{/* CTA Section */}
-
+
-
-
-
-
- Готовы начать?
+ {/* Background with cyber styling */}
+
+
+
+ {/* Border glow */}
+
+
+
+ {/* Animated corner accents */}
+
+
+
+
+
+ {/* Content */}
+
+
+
+
+
+
+ Готовы{" "}
+ начать
+ ?
-
- Присоединяйтесь к платформе ВолГУ.Контесты и участвуйте
- в соревнованиях по олимпиадному программированию.
+
+
+ Присоединяйтесь к платформе{" "}
+ >VOLGU.CONTESTS{" "}
+ и участвуйте в соревнованиях
+
-
- {user ? "Перейти к контестам" : "Начать бесплатно"}
-
-
+
@@ -251,9 +386,28 @@ export default function HomePage() {
{/* Footer */}
-