diff --git a/.gitea/workflows/rebuild-prod.yaml b/.gitea/workflows/rebuild-prod.yaml index 606ec1e..55eaf5b 100644 --- a/.gitea/workflows/rebuild-prod.yaml +++ b/.gitea/workflows/rebuild-prod.yaml @@ -54,9 +54,12 @@ jobs: # Read stack file content STACK_FILE_CONTENT=$(echo "$( 0)) | map(split("=") | {name: .[0], value: (.[1:] | join("="))}) | map(select(.name != ""))') + + # Prepare JSON payload with environment variables + JSON_PAYLOAD=$(jq -n --arg stackFileContent "$STACK_FILE_CONTENT" --argjson pullImage true --argjson env "$ENV_VARS" \ + '{stackFileContent: $stackFileContent, pullImage: $pullImage, env: $env}') echo "About to push the following JSON payload:" echo $JSON_PAYLOAD diff --git a/docker-compose.yml b/docker-compose.yml index f6181fb..5a81161 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -44,7 +44,7 @@ services: dockerfile: Dockerfile.dev restart: unless-stopped environment: - VITE_API_URL: http://192.168.1.175:4000/api + VITE_API_URL: http://backend:4000/api depends_on: - backend ports: diff --git a/frontend/src/App.css b/frontend/src/App.css index b387289..47f9a00 100644 --- a/frontend/src/App.css +++ b/frontend/src/App.css @@ -134,14 +134,52 @@ body { justify-content: space-between; align-items: center; gap: 1rem; - flex-wrap: wrap; +} + +.nav-brand { + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; +} + +.nav-brand h2 { + margin: 0; +} + +.hamburger { + display: none; + flex-direction: column; + gap: 4px; + background: none; + border: none; + cursor: pointer; + padding: 0.5rem; + z-index: 1001; +} + +.hamburger span { + width: 25px; + height: 3px; + background: var(--text); + border-radius: 3px; + transition: all 0.3s ease; +} + +.nav-menu { + display: flex; + align-items: center; + gap: 2rem; + width: 100%; + justify-content: space-between; } .nav-links { display: flex; gap: 1rem; list-style: none; - flex-wrap: wrap; + margin: 0; + padding: 0; } .nav-links a { @@ -150,12 +188,17 @@ body { padding: 0.5rem 1rem; border-radius: 0.375rem; transition: background 0.2s; + white-space: nowrap; } .nav-links a:hover, .nav-links a.active { background: var(--bg-lighter); } +.logout-btn { + white-space: nowrap; +} + .grid { display: grid; gap: 1rem; @@ -207,19 +250,72 @@ body { } @media (max-width: 768px) { - .nav { + .nav-brand { + width: 100%; + } + + .hamburger { + display: flex; + } + + .hamburger.active span:nth-child(1) { + transform: rotate(45deg) translate(5px, 5px); + } + + .hamburger.active span:nth-child(2) { + opacity: 0; + } + + .hamburger.active span:nth-child(3) { + transform: rotate(-45deg) translate(7px, -7px); + } + + .nav-menu { + position: fixed; + top: 0; + right: -100%; + width: 70%; + height: 100vh; + background: var(--bg-light); + border-left: 1px solid var(--border); flex-direction: column; - align-items: stretch; + justify-content: flex-start; + padding: 5rem 2rem 2rem; + gap: 2rem; + transition: right 0.3s ease; + z-index: 1000; + } + + .nav-menu.active { + right: 0; } .nav-links { - gap: 0.25rem; - justify-content: center; + flex-direction: column; + width: 100%; + gap: 0; + } + + .nav-links li { + width: 100%; } .nav-links a { - padding: 0.5rem; - font-size: 0.875rem; + display: block; + padding: 1rem; + font-size: 1.125rem; + width: 100%; + border-bottom: 1px solid var(--border); + border-radius: 0; + } + + .nav-links a:hover { + background: var(--bg-lighter); + border-radius: 0; + } + + .logout-btn { + width: 100%; } .card { diff --git a/frontend/src/main.jsx b/frontend/src/main.jsx index ef5ae73..6db3499 100644 --- a/frontend/src/main.jsx +++ b/frontend/src/main.jsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState } from 'react'; import ReactDOM from 'react-dom/client'; import { BrowserRouter, Routes, Route, Navigate, Link } from 'react-router-dom'; import { Toaster } from 'react-hot-toast'; @@ -26,25 +26,44 @@ function ProtectedRoute({ children }) { function Header() { const { user, logout } = useAuth(); + const [mobileMenuOpen, setMobileMenuOpen] = useState(false); if (!user) return null; + const handleLogout = () => { + setMobileMenuOpen(false); + logout(); + }; + + const closeMobileMenu = () => setMobileMenuOpen(false); + return (
diff --git a/frontend/src/pages/ChallengeList.jsx b/frontend/src/pages/ChallengeList.jsx index 1e6dbc2..90adfe1 100644 --- a/frontend/src/pages/ChallengeList.jsx +++ b/frontend/src/pages/ChallengeList.jsx @@ -245,7 +245,7 @@ export default function ChallengeList() { /> )}
-

{challenge.title}

+

{challenge.title}

Created by {challenge.creator_username}