feat: improved navigation and unified close buttons - version 3.5.0
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 47s

This commit is contained in:
Play Life Bot
2026-01-08 00:02:06 +03:00
parent b1cfea22e6
commit 60a6f4deb4
11 changed files with 326 additions and 93 deletions

View File

@@ -13,6 +13,7 @@ import {
import { Line } from 'react-chartjs-2'
import WeekProgressChart from './WeekProgressChart'
import { getAllProjectsSorted, getProjectColor, sortProjectsLikeCurrentWeek } from '../utils/projectUtils'
import './Integrations.css'
// Экспортируем для обратной совместимости (если используется в других местах)
export { getProjectColorByIndex } from '../utils/projectUtils'
@@ -216,18 +217,13 @@ function FullStatistics({ selectedProject, onClearSelection, data, loading, erro
return (
<div>
{onNavigate && (
<div className="flex justify-end mb-4">
<button
onClick={() => onNavigate('current')}
className="flex items-center justify-center w-10 h-10 rounded-full bg-white hover:bg-gray-100 text-gray-600 hover:text-gray-800 border border-gray-200 hover:border-gray-300 transition-all duration-200 shadow-sm hover:shadow-md"
title="Закрыть"
>
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
</div>
<button
onClick={() => onNavigate('current')}
className="close-x-button"
title="Закрыть"
>
</button>
)}
<div style={{ height: '550px' }}>
<Line data={chartData} options={chartOptions} />

View File

@@ -1,15 +1,12 @@
import React, { useState } from 'react'
import React from 'react'
import { useAuth } from './auth/AuthContext'
import TodoistIntegration from './TodoistIntegration'
import TelegramIntegration from './TelegramIntegration'
function Profile({ onNavigate }) {
const { user, logout } = useAuth()
const [selectedIntegration, setSelectedIntegration] = useState(null)
const integrations = [
{ id: 'todoist', name: 'TODOist' },
{ id: 'telegram', name: 'Telegram' },
{ id: 'todoist-integration', name: 'TODOist' },
{ id: 'telegram-integration', name: 'Telegram' },
]
const handleLogout = async () => {
@@ -18,14 +15,6 @@ function Profile({ onNavigate }) {
}
}
if (selectedIntegration) {
if (selectedIntegration === 'todoist') {
return <TodoistIntegration onBack={() => setSelectedIntegration(null)} />
} else if (selectedIntegration === 'telegram') {
return <TelegramIntegration onBack={() => setSelectedIntegration(null)} />
}
}
return (
<div className="p-4 md:p-6 max-w-2xl mx-auto">
{/* Profile Header */}
@@ -52,7 +41,7 @@ function Profile({ onNavigate }) {
{integrations.map((integration) => (
<button
key={integration.id}
onClick={() => setSelectedIntegration(integration.id)}
onClick={() => onNavigate?.(integration.id)}
className="w-full p-4 bg-white rounded-xl shadow-sm hover:shadow-md transition-all text-left border border-gray-100 hover:border-indigo-200 group"
>
<div className="flex items-center justify-between">

View File

@@ -20,6 +20,7 @@ import {
import { CSS } from '@dnd-kit/utilities'
import { getAllProjectsSorted, getProjectColor } from '../utils/projectUtils'
import { useAuth } from './auth/AuthContext'
import './Integrations.css'
// API endpoints (используем относительные пути, проксирование настроено в nginx/vite)
const PROJECTS_API_URL = '/projects'
@@ -866,18 +867,13 @@ function ProjectPriorityManager({ allProjectsData, currentWeekData, shouldLoad,
return (
<div className="max-w-4xl mx-auto flex flex-col max-h-[calc(100vh-11rem)]">
{onNavigate && (
<div className="flex justify-end mb-4 flex-shrink-0">
<button
onClick={() => onNavigate('current')}
className="flex items-center justify-center w-10 h-10 rounded-full bg-white hover:bg-gray-100 text-gray-600 hover:text-gray-800 border border-gray-200 hover:border-gray-300 transition-all duration-200 shadow-sm hover:shadow-md"
title="Закрыть"
>
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
</div>
<button
onClick={() => onNavigate('current')}
className="close-x-button"
title="Закрыть"
>
</button>
)}
{projectsError && (!maxPriority.length && !mediumPriority.length && !lowPriority.length) && (
<div className="mb-4 rounded-lg border border-red-200 bg-red-50 p-4 text-sm text-red-700 shadow-sm flex-shrink-0">

View File

@@ -6,26 +6,28 @@
}
.close-x-button {
position: absolute;
position: fixed;
top: 1rem;
right: 1rem;
background: #f3f4f6;
border: 1px solid #e5e7eb;
border-radius: 50%;
width: 2rem;
height: 2rem;
background: rgba(255, 255, 255, 0.9);
border: none;
font-size: 1.5rem;
color: #7f8c8d;
cursor: pointer;
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
font-size: 1.25rem;
color: #6b7280;
transition: all 0.2s;
border-radius: 50%;
transition: background-color 0.2s, color 0.2s;
z-index: 1600;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}
.close-x-button:hover {
background: #e5e7eb;
color: #1f2937;
background-color: #ffffff;
color: #2c3e50;
}
.task-form h2 {

View File

@@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react'
import { useAuth } from './auth/AuthContext'
import './Integrations.css'
function TelegramIntegration({ onBack }) {
function TelegramIntegration({ onNavigate }) {
const { authFetch } = useAuth()
const [integration, setIntegration] = useState(null)
const [loading, setLoading] = useState(true)
@@ -49,7 +49,7 @@ function TelegramIntegration({ onBack }) {
return (
<div className="p-4 md:p-6">
<button className="close-x-button" onClick={onBack} title="Закрыть">
<button className="close-x-button" onClick={() => onNavigate?.('profile')} title="Закрыть">
</button>

View File

@@ -16,30 +16,6 @@
flex-direction: column;
}
.test-close-x-button {
position: fixed;
top: 1rem;
right: 1rem;
background: rgba(255, 255, 255, 0.9);
border: none;
font-size: 1.5rem;
color: #7f8c8d;
cursor: pointer;
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
transition: background-color 0.2s, color 0.2s;
z-index: 1600;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}
.test-close-x-button:hover {
background-color: #ffffff;
color: #2c3e50;
}
.test-duration-selection {
text-align: center;

View File

@@ -1,6 +1,7 @@
import React, { useState, useEffect, useRef } from 'react'
import { useAuth } from './auth/AuthContext'
import './TestWords.css'
import './Integrations.css'
const API_URL = '/api'
@@ -436,7 +437,7 @@ function TestWords({ onNavigate, wordCount: initialWordCount, configId: initialC
return (
<div className="test-container test-container-fullscreen">
<button className="test-close-x-button" onClick={handleClose}>
<button className="close-x-button" onClick={handleClose}>
</button>
{showPreview ? (

View File

@@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react'
import { useAuth } from './auth/AuthContext'
import './Integrations.css'
function TodoistIntegration({ onBack }) {
function TodoistIntegration({ onNavigate }) {
const { authFetch } = useAuth()
const [connected, setConnected] = useState(false)
const [todoistEmail, setTodoistEmail] = useState('')
@@ -102,7 +102,7 @@ function TodoistIntegration({ onBack }) {
return (
<div className="p-4 md:p-6">
<button className="close-x-button" onClick={onBack} title="Закрыть">
<button className="close-x-button" onClick={() => onNavigate?.('profile')} title="Закрыть">
</button>