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
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 47s
This commit is contained in:
@@ -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} />
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 ? (
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user