6.19.8: Кнопки сохранения досок внизу экрана
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 1m16s
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 1m16s
This commit is contained in:
@@ -1166,7 +1166,7 @@ function AppContent() {
|
||||
}
|
||||
|
||||
// Определяем, нужно ли скрывать нижнюю панель (для fullscreen экранов)
|
||||
const isFullscreenTab = activeTab === 'test' || activeTab === 'purchase' || activeTab === 'add-words' || activeTab === 'task-form' || activeTab === 'wishlist-form' || activeTab === 'wishlist-detail' || activeTab === 'todoist-integration' || activeTab === 'telegram-integration' || activeTab === 'fitbit-integration' || activeTab === 'full' || activeTab === 'priorities' || activeTab === 'words' || activeTab === 'dictionaries' || activeTab === 'tracking' || activeTab === 'tracking-access' || activeTab === 'tracking-invite' || activeTab === 'shopping' || activeTab === 'shopping-item-form' || activeTab === 'shopping-board-form' || activeTab === 'shopping-board-join' || activeTab === 'shopping-item-history'
|
||||
const isFullscreenTab = activeTab === 'test' || activeTab === 'purchase' || activeTab === 'add-words' || activeTab === 'task-form' || activeTab === 'wishlist-form' || activeTab === 'wishlist-detail' || activeTab === 'todoist-integration' || activeTab === 'telegram-integration' || activeTab === 'fitbit-integration' || activeTab === 'full' || activeTab === 'priorities' || activeTab === 'words' || activeTab === 'dictionaries' || activeTab === 'tracking' || activeTab === 'tracking-access' || activeTab === 'tracking-invite' || activeTab === 'shopping' || activeTab === 'shopping-item-form' || activeTab === 'shopping-board-form' || activeTab === 'shopping-board-join' || activeTab === 'shopping-item-history' || activeTab === 'board-form'
|
||||
|
||||
// Функция для получения классов скролл-контейнера для каждого таба
|
||||
// Каждый таб имеет свой изолированный скролл-контейнер для автоматического сохранения позиции скролла
|
||||
@@ -1418,6 +1418,7 @@ function AppContent() {
|
||||
onNavigate={handleNavigate}
|
||||
boardId={tabParams.boardId}
|
||||
onSaved={() => setWishlistRefreshTrigger(prev => prev + 1)}
|
||||
isActive={activeTab === 'board-form'}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1473,6 +1474,7 @@ function AppContent() {
|
||||
onNavigate={handleNavigate}
|
||||
boardId={tabParams.boardId}
|
||||
onSaved={() => setShoppingRefreshTrigger(prev => prev + 1)}
|
||||
isActive={activeTab === 'shopping-board-form'}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { createPortal } from 'react-dom'
|
||||
import { useAuth } from './auth/AuthContext'
|
||||
import BoardMembers from './BoardMembers'
|
||||
import Toast from './Toast'
|
||||
import SubmitButton from './SubmitButton'
|
||||
import DeleteButton from './DeleteButton'
|
||||
import './Buttons.css'
|
||||
import './BoardForm.css'
|
||||
|
||||
function BoardForm({ boardId, onNavigate, onSaved }) {
|
||||
function BoardForm({ boardId, onNavigate, onSaved, isActive }) {
|
||||
const { authFetch } = useAuth()
|
||||
const [name, setName] = useState('')
|
||||
const [inviteEnabled, setInviteEnabled] = useState(false)
|
||||
@@ -252,14 +252,51 @@ function BoardForm({ boardId, onNavigate, onSaved }) {
|
||||
</>
|
||||
)}
|
||||
|
||||
<div className="form-actions">
|
||||
<SubmitButton
|
||||
</div>
|
||||
|
||||
{toastMessage && (
|
||||
<Toast
|
||||
message={toastMessage.text}
|
||||
type={toastMessage.type}
|
||||
onClose={() => setToastMessage(null)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{isActive ? createPortal(
|
||||
<div style={{
|
||||
position: 'fixed',
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
padding: '0.75rem 1rem',
|
||||
paddingBottom: 'max(0.75rem, env(safe-area-inset-bottom))',
|
||||
background: 'linear-gradient(to top, white 60%, rgba(255,255,255,0))',
|
||||
zIndex: 1500,
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
gap: '0.75rem',
|
||||
}}>
|
||||
<button
|
||||
onClick={handleSave}
|
||||
loading={loading}
|
||||
disabled={!name.trim()}
|
||||
disabled={loading || isDeleting || !name.trim()}
|
||||
style={{
|
||||
flex: 1,
|
||||
maxWidth: '42rem',
|
||||
padding: '0.875rem',
|
||||
background: (loading || !name.trim()) ? undefined : 'linear-gradient(to right, #10b981, #059669)',
|
||||
backgroundColor: (loading || !name.trim()) ? '#9ca3af' : undefined,
|
||||
color: 'white',
|
||||
border: 'none',
|
||||
borderRadius: '0.5rem',
|
||||
fontSize: '1rem',
|
||||
fontWeight: 600,
|
||||
cursor: (loading || isDeleting || !name.trim()) ? 'not-allowed' : 'pointer',
|
||||
opacity: loading ? 0.6 : 1,
|
||||
transition: 'all 0.2s',
|
||||
}}
|
||||
>
|
||||
Сохранить
|
||||
</SubmitButton>
|
||||
{loading ? 'Сохранение...' : 'Сохранить'}
|
||||
</button>
|
||||
{isEdit && (
|
||||
<DeleteButton
|
||||
onClick={handleDelete}
|
||||
@@ -268,16 +305,9 @@ function BoardForm({ boardId, onNavigate, onSaved }) {
|
||||
title="Удалить доску"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{toastMessage && (
|
||||
<Toast
|
||||
message={toastMessage.text}
|
||||
type={toastMessage.type}
|
||||
onClose={() => setToastMessage(null)}
|
||||
/>
|
||||
)}
|
||||
</div>,
|
||||
document.body
|
||||
) : null}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { createPortal } from 'react-dom'
|
||||
import { useAuth } from './auth/AuthContext'
|
||||
import BoardMembers from './BoardMembers'
|
||||
import Toast from './Toast'
|
||||
import SubmitButton from './SubmitButton'
|
||||
import DeleteButton from './DeleteButton'
|
||||
import './Buttons.css'
|
||||
import './BoardForm.css'
|
||||
|
||||
function ShoppingBoardForm({ boardId, onNavigate, onSaved }) {
|
||||
function ShoppingBoardForm({ boardId, onNavigate, onSaved, isActive }) {
|
||||
const { authFetch } = useAuth()
|
||||
const [name, setName] = useState('')
|
||||
const [inviteEnabled, setInviteEnabled] = useState(false)
|
||||
@@ -245,23 +245,6 @@ function ShoppingBoardForm({ boardId, onNavigate, onSaved }) {
|
||||
</>
|
||||
)}
|
||||
|
||||
<div className="form-actions">
|
||||
<SubmitButton
|
||||
onClick={handleSave}
|
||||
loading={loading}
|
||||
disabled={!name.trim()}
|
||||
>
|
||||
Сохранить
|
||||
</SubmitButton>
|
||||
{isEdit && (
|
||||
<DeleteButton
|
||||
onClick={handleDelete}
|
||||
loading={isDeleting}
|
||||
disabled={loading}
|
||||
title="Удалить доску"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{toastMessage && (
|
||||
@@ -271,6 +254,53 @@ function ShoppingBoardForm({ boardId, onNavigate, onSaved }) {
|
||||
onClose={() => setToastMessage(null)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{isActive ? createPortal(
|
||||
<div style={{
|
||||
position: 'fixed',
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
padding: '0.75rem 1rem',
|
||||
paddingBottom: 'max(0.75rem, env(safe-area-inset-bottom))',
|
||||
background: 'linear-gradient(to top, white 60%, rgba(255,255,255,0))',
|
||||
zIndex: 1500,
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
gap: '0.75rem',
|
||||
}}>
|
||||
<button
|
||||
onClick={handleSave}
|
||||
disabled={loading || isDeleting || !name.trim()}
|
||||
style={{
|
||||
flex: 1,
|
||||
maxWidth: '42rem',
|
||||
padding: '0.875rem',
|
||||
background: (loading || !name.trim()) ? undefined : 'linear-gradient(to right, #10b981, #059669)',
|
||||
backgroundColor: (loading || !name.trim()) ? '#9ca3af' : undefined,
|
||||
color: 'white',
|
||||
border: 'none',
|
||||
borderRadius: '0.5rem',
|
||||
fontSize: '1rem',
|
||||
fontWeight: 600,
|
||||
cursor: (loading || isDeleting || !name.trim()) ? 'not-allowed' : 'pointer',
|
||||
opacity: loading ? 0.6 : 1,
|
||||
transition: 'all 0.2s',
|
||||
}}
|
||||
>
|
||||
{loading ? 'Сохранение...' : 'Сохранить'}
|
||||
</button>
|
||||
{isEdit && (
|
||||
<DeleteButton
|
||||
onClick={handleDelete}
|
||||
loading={isDeleting}
|
||||
disabled={loading}
|
||||
title="Удалить доску"
|
||||
/>
|
||||
)}
|
||||
</div>,
|
||||
document.body
|
||||
) : null}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user