6.18.5: Фиксированные кнопки в формах задачи и желания
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 1m19s
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 1m19s
This commit is contained in:
@@ -1360,6 +1360,7 @@ function AppContent() {
|
||||
wishlistId={tabParams.wishlistId}
|
||||
returnTo={tabParams.returnTo}
|
||||
returnWishlistId={tabParams.returnWishlistId}
|
||||
isActive={activeTab === 'task-form'}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1389,6 +1390,7 @@ function AppContent() {
|
||||
editConditionIndex={tabParams.editConditionIndex}
|
||||
newTaskId={tabParams.newTaskId}
|
||||
boardId={tabParams.boardId}
|
||||
isActive={activeTab === 'wishlist-form'}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, { useState, useEffect, useRef } from 'react'
|
||||
import { createPortal } from 'react-dom'
|
||||
import { useAuth } from './auth/AuthContext'
|
||||
import Toast from './Toast'
|
||||
import SubmitButton from './SubmitButton'
|
||||
@@ -8,7 +9,7 @@ import './TaskForm.css'
|
||||
const API_URL = '/api/tasks'
|
||||
const PROJECTS_API_URL = '/projects'
|
||||
|
||||
function TaskForm({ onNavigate, taskId, wishlistId, returnTo, returnWishlistId }) {
|
||||
function TaskForm({ onNavigate, taskId, wishlistId, returnTo, returnWishlistId, isActive }) {
|
||||
const { authFetch } = useAuth()
|
||||
const [name, setName] = useState('')
|
||||
const [progressionBase, setProgressionBase] = useState('')
|
||||
@@ -885,6 +886,7 @@ function TaskForm({ onNavigate, taskId, wishlistId, returnTo, returnWishlistId }
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="task-form">
|
||||
<button className="close-x-button" onClick={handleCancel}>
|
||||
✕
|
||||
@@ -900,7 +902,7 @@ function TaskForm({ onNavigate, taskId, wishlistId, returnTo, returnWishlistId }
|
||||
<>
|
||||
<h2>{taskId ? 'Редактировать задачу' : 'Новая задача'}</h2>
|
||||
|
||||
<form onSubmit={handleSubmit}>
|
||||
<form id="task-form-element" onSubmit={handleSubmit}>
|
||||
<div className="form-group">
|
||||
<label htmlFor="name">Название задачи *</label>
|
||||
<input
|
||||
@@ -1393,23 +1395,6 @@ function TaskForm({ onNavigate, taskId, wishlistId, returnTo, returnWishlistId }
|
||||
<div className="error-message">{error}</div>
|
||||
)}
|
||||
|
||||
<div className="form-actions">
|
||||
<SubmitButton
|
||||
type="submit"
|
||||
loading={loading}
|
||||
disabled={isDeleting}
|
||||
>
|
||||
Сохранить
|
||||
</SubmitButton>
|
||||
{taskId && (
|
||||
<DeleteButton
|
||||
onClick={handleDelete}
|
||||
loading={isDeleting}
|
||||
disabled={loading}
|
||||
title="Удалить задачу"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</form>
|
||||
{toastMessage && (
|
||||
<Toast
|
||||
@@ -1421,6 +1406,41 @@ function TaskForm({ onNavigate, taskId, wishlistId, returnTo, returnWishlistId }
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
{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',
|
||||
}}>
|
||||
<SubmitButton
|
||||
type="submit"
|
||||
form="task-form-element"
|
||||
loading={loading}
|
||||
disabled={isDeleting}
|
||||
style={{ flex: 1, maxWidth: '42rem' }}
|
||||
>
|
||||
Сохранить
|
||||
</SubmitButton>
|
||||
{taskId && (
|
||||
<DeleteButton
|
||||
onClick={handleDelete}
|
||||
loading={isDeleting}
|
||||
disabled={loading}
|
||||
title="Удалить задачу"
|
||||
/>
|
||||
)}
|
||||
</div>,
|
||||
document.body
|
||||
) : null}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, { useState, useEffect, useCallback, useRef } from 'react'
|
||||
import { createPortal } from 'react-dom'
|
||||
import Cropper from 'react-easy-crop'
|
||||
import { useAuth } from './auth/AuthContext'
|
||||
import Toast from './Toast'
|
||||
@@ -16,7 +17,7 @@ const TASKS_API_URL = '/api/tasks'
|
||||
const PROJECTS_API_URL = '/projects'
|
||||
const WISHLIST_FORM_STATE_KEY = 'wishlistFormPendingState'
|
||||
|
||||
function WishlistForm({ onNavigate, wishlistId, editConditionIndex, newTaskId: newTaskIdProp, boardId }) {
|
||||
function WishlistForm({ onNavigate, wishlistId, editConditionIndex, newTaskId: newTaskIdProp, boardId, isActive }) {
|
||||
const { authFetch, user } = useAuth()
|
||||
|
||||
// newTaskId может прийти из props (через onNavigate) или из sessionStorage (через history.back)
|
||||
@@ -791,6 +792,7 @@ function WishlistForm({ onNavigate, wishlistId, editConditionIndex, newTaskId: n
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="wishlist-form">
|
||||
<button className="close-x-button" onClick={handleCancel}>
|
||||
✕
|
||||
@@ -806,7 +808,7 @@ function WishlistForm({ onNavigate, wishlistId, editConditionIndex, newTaskId: n
|
||||
<>
|
||||
<h2>{wishlistId ? 'Редактировать желание' : 'Новое желание'}</h2>
|
||||
|
||||
<form onSubmit={handleSubmit}>
|
||||
<form id="wishlist-form-element" onSubmit={handleSubmit}>
|
||||
<div className="form-group">
|
||||
<label htmlFor="link">Ссылка</label>
|
||||
<div className="link-input-wrapper">
|
||||
@@ -1038,11 +1040,6 @@ function WishlistForm({ onNavigate, wishlistId, editConditionIndex, newTaskId: n
|
||||
|
||||
{error && <div className="error-message">{error}</div>}
|
||||
|
||||
<div className="form-actions">
|
||||
<button type="submit" disabled={loading} className="submit-button">
|
||||
{loading ? 'Сохранение...' : 'Сохранить'}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{showConditionForm && (
|
||||
@@ -1068,6 +1065,45 @@ function WishlistForm({ onNavigate, wishlistId, editConditionIndex, newTaskId: n
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
{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',
|
||||
}}>
|
||||
<button
|
||||
type="submit"
|
||||
form="wishlist-form-element"
|
||||
disabled={loading}
|
||||
style={{
|
||||
width: '100%',
|
||||
maxWidth: '42rem',
|
||||
padding: '0.875rem',
|
||||
background: loading ? undefined : 'linear-gradient(to right, #10b981, #059669)',
|
||||
backgroundColor: loading ? '#9ca3af' : undefined,
|
||||
color: 'white',
|
||||
border: 'none',
|
||||
borderRadius: '0.5rem',
|
||||
fontSize: '1rem',
|
||||
fontWeight: 600,
|
||||
cursor: loading ? 'not-allowed' : 'pointer',
|
||||
opacity: loading ? 0.6 : 1,
|
||||
transition: 'all 0.2s',
|
||||
}}
|
||||
>
|
||||
{loading ? 'Сохранение...' : 'Сохранить'}
|
||||
</button>
|
||||
</div>,
|
||||
document.body
|
||||
) : null}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user