feat: UI improvements and responsive design enhancements
- Fix dark mode overscroll areas with proper background colors - Add mobile responsiveness for project logos in header - Improve viewport handling with interactive-widget support - Update app title to proper case 'AdsPreview' - Add mobile-friendly padding adjustments for tabs and headers - Update .gitignore to exclude .code-workspace files - Enhance CSS with anticon color overrides and mobile breakpoints
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -39,3 +39,4 @@ area/
|
|||||||
|
|
||||||
# Deployment
|
# Deployment
|
||||||
.env.upload
|
.env.upload
|
||||||
|
.code-workspace
|
||||||
7
adspreview_react.code-workspace
Normal file
7
adspreview_react.code-workspace
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"folders": [
|
||||||
|
{
|
||||||
|
"path": "."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -2,8 +2,8 @@
|
|||||||
<html lang="de">
|
<html lang="de">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1, interactive-widget=resizes-content" />
|
||||||
<title>adspreview</title>
|
<title>AdsPreview</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|||||||
@@ -19,6 +19,41 @@ function App() {
|
|||||||
return stored === 'true';
|
return stored === 'true';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Set initial background colors immediately on component mount
|
||||||
|
useEffect(() => {
|
||||||
|
const htmlElement = document.documentElement;
|
||||||
|
const bodyElement = document.body;
|
||||||
|
|
||||||
|
// Set initial colors based on current darkMode state
|
||||||
|
const bgColor = darkMode ? '#181818' : '#f5f5f5';
|
||||||
|
htmlElement.style.backgroundColor = bgColor;
|
||||||
|
bodyElement.style.backgroundColor = bgColor;
|
||||||
|
|
||||||
|
if (darkMode) {
|
||||||
|
htmlElement.classList.add('dark-mode');
|
||||||
|
} else {
|
||||||
|
htmlElement.classList.remove('dark-mode');
|
||||||
|
}
|
||||||
|
}, []); // Run only once on mount
|
||||||
|
|
||||||
|
// Update HTML class and background color when darkMode changes
|
||||||
|
useEffect(() => {
|
||||||
|
const htmlElement = document.documentElement;
|
||||||
|
const bodyElement = document.body;
|
||||||
|
|
||||||
|
if (darkMode) {
|
||||||
|
htmlElement.classList.add('dark-mode');
|
||||||
|
// Set dark mode background colors to prevent white overscroll areas
|
||||||
|
htmlElement.style.backgroundColor = '#181818';
|
||||||
|
bodyElement.style.backgroundColor = '#181818';
|
||||||
|
} else {
|
||||||
|
htmlElement.classList.remove('dark-mode');
|
||||||
|
// Set light mode background colors
|
||||||
|
htmlElement.style.backgroundColor = '#ebebeb';
|
||||||
|
bodyElement.style.backgroundColor = '#f5f5f5';
|
||||||
|
}
|
||||||
|
}, [darkMode]);
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const token = localStorage.getItem('jwt');
|
const token = localStorage.getItem('jwt');
|
||||||
@@ -99,8 +134,7 @@ function App() {
|
|||||||
>
|
>
|
||||||
<AntApp>
|
<AntApp>
|
||||||
<Router>
|
<Router>
|
||||||
<Layout style={{ minHeight: '100vh' }}>
|
<Layout style={{ minHeight: '100dvh' }}>
|
||||||
{/* Kein globaler Header mehr, Header wird ggf. in einzelnen Seiten eingebunden */}
|
|
||||||
<Layout.Content style={{ padding: 0 }}>
|
<Layout.Content style={{ padding: 0 }}>
|
||||||
<Routes>
|
<Routes>
|
||||||
{user.role === 'admin' ? (
|
{user.role === 'admin' ? (
|
||||||
|
|||||||
@@ -11,7 +11,29 @@
|
|||||||
margin-bottom: 0px;
|
margin-bottom: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ant-layout-header.overview-header {
|
||||||
|
padding: 0 32px;
|
||||||
|
}
|
||||||
|
|
||||||
.ant-tabs-content {
|
.ant-tabs-content {
|
||||||
padding: 0px 32px;
|
padding: 0px 32px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Adjust tab navigation padding on mobile */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.ant-tabs > .ant-tabs-nav {
|
||||||
|
padding: 9px 16px; /* Reduced padding on mobile */
|
||||||
|
}
|
||||||
|
.ant-layout-header.overview-header {
|
||||||
|
padding: 0 16px;
|
||||||
|
}
|
||||||
|
.ant-tabs-content {
|
||||||
|
padding: 0px 16px; /* Reduced padding on mobile */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Global anticon color override */
|
||||||
|
.anticon {
|
||||||
|
color: rgb(0, 31, 30) !important;
|
||||||
}
|
}
|
||||||
@@ -198,7 +198,7 @@ export default function ClientProjects({ user, darkMode, onLogout, onToggleDarkM
|
|||||||
cursor: ${sortMode ? 'grabbing' : 'default'};
|
cursor: ${sortMode ? 'grabbing' : 'default'};
|
||||||
}
|
}
|
||||||
`}</style>
|
`}</style>
|
||||||
<Layout.Header style={{
|
<Layout.Header className='overview-header' style={{
|
||||||
position: 'sticky',
|
position: 'sticky',
|
||||||
top: 0,
|
top: 0,
|
||||||
zIndex: 100,
|
zIndex: 100,
|
||||||
@@ -206,8 +206,7 @@ export default function ClientProjects({ user, darkMode, onLogout, onToggleDarkM
|
|||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
background: darkMode ? '#001f1e' : '#001f1e',
|
background: darkMode ? '#001f1e' : '#001f1e',
|
||||||
color: darkMode ? '#fff' : '#fff',
|
color: darkMode ? '#fff' : '#fff'
|
||||||
padding: '0 32px'
|
|
||||||
}}>
|
}}>
|
||||||
<div style={{ fontWeight: 700, fontSize: 20, color: darkMode ? '#fff' : undefined }}>Übersicht</div>
|
<div style={{ fontWeight: 700, fontSize: 20, color: darkMode ? '#fff' : undefined }}>Übersicht</div>
|
||||||
<div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
|
<div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ export default function LoginPage({ onLogin }) {
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
minHeight: '100vh',
|
minHeight: '100dvh',
|
||||||
width: '100vw',
|
width: '100vw',
|
||||||
background: darkMode ? '#181818' : '#f5f5f5',
|
background: darkMode ? '#181818' : '#f5f5f5',
|
||||||
transition: 'background 0.2s',
|
transition: 'background 0.2s',
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { useParams, useNavigate } from 'react-router-dom';
|
import { useParams, useNavigate } from 'react-router-dom';
|
||||||
import { Tabs, Button, Spin, Skeleton, Result } from 'antd';
|
import { Tabs, Button, Spin, Skeleton, Result, Grid } from 'antd';
|
||||||
import { ArrowLeftOutlined, LoadingOutlined, LockOutlined } from '@ant-design/icons';
|
import { ArrowLeftOutlined, LoadingOutlined, LockOutlined } from '@ant-design/icons';
|
||||||
import UserMenu from '../components/UserMenu';
|
import UserMenu from '../components/UserMenu';
|
||||||
import FilePreview, { formatFileSize, formatDuration } from '../components/FilePreview';
|
import FilePreview, { formatFileSize, formatDuration } from '../components/FilePreview';
|
||||||
import debugLogger from '../utils/debugLogger';
|
import debugLogger from '../utils/debugLogger';
|
||||||
|
|
||||||
const backendUrl = process.env.REACT_APP_BACKEND || '';
|
const backendUrl = process.env.REACT_APP_BACKEND || '';
|
||||||
|
const { useBreakpoint } = Grid;
|
||||||
|
|
||||||
function ProjectDetail({ user, darkMode, onLogout, onToggleDarkMode, overrideParams, ...props }) {
|
function ProjectDetail({ user, darkMode, onLogout, onToggleDarkMode, overrideParams, ...props }) {
|
||||||
// URL-Parameter holen, mit Override-Support für Smart Resolution
|
// URL-Parameter holen, mit Override-Support für Smart Resolution
|
||||||
@@ -16,6 +17,10 @@ function ProjectDetail({ user, darkMode, onLogout, onToggleDarkMode, overridePar
|
|||||||
const client = user.role === 'admin' ? routeClient : user.client;
|
const client = user.role === 'admin' ? routeClient : user.client;
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
// Responsive breakpoints
|
||||||
|
const screens = useBreakpoint();
|
||||||
|
const isMobile = !screens.md; // md breakpoint ist 768px
|
||||||
|
|
||||||
debugLogger.routing('ProjectDetail - Received params:', {
|
debugLogger.routing('ProjectDetail - Received params:', {
|
||||||
routeParams,
|
routeParams,
|
||||||
overrideParams,
|
overrideParams,
|
||||||
@@ -264,7 +269,7 @@ function ProjectDetail({ user, darkMode, onLogout, onToggleDarkMode, overridePar
|
|||||||
onClick={() => navigate('/')}
|
onClick={() => navigate('/')}
|
||||||
style={{ marginRight: projectLogo ? 12 : 0 }}
|
style={{ marginRight: projectLogo ? 12 : 0 }}
|
||||||
/>
|
/>
|
||||||
{projectLogo && (
|
{projectLogo && !isMobile && (
|
||||||
<img
|
<img
|
||||||
src={projectLogo}
|
src={projectLogo}
|
||||||
alt="Logo"
|
alt="Logo"
|
||||||
|
|||||||
Reference in New Issue
Block a user