6.11.4: Товары перенесены из таба в профиль
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m7s

This commit is contained in:
poignatov
2026-03-11 09:34:36 +03:00
parent 20778d6d39
commit a35797a1f9
7 changed files with 68 additions and 39 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "play-life-web",
"version": "6.11.3",
"version": "6.11.4",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -35,8 +35,8 @@ const CURRENT_WEEK_API_URL = '/playlife-feed'
const FULL_STATISTICS_API_URL = '/d2dc349a-0d13-49b2-a8f0-1ab094bfba9b'
// Определяем основные табы (без крестика) и глубокие табы (с крестиком)
const mainTabs = ['current', 'tasks', 'wishlist', 'shopping', 'profile']
const deepTabs = ['add-words', 'test', 'purchase', 'task-form', 'wishlist-form', 'wishlist-detail', 'board-form', 'board-join', 'words', 'dictionaries', 'todoist-integration', 'telegram-integration', 'fitbit-integration', 'full', 'priorities', 'tracking', 'tracking-access', 'tracking-invite', 'shopping-item-form', 'shopping-board-form', 'shopping-board-join', 'shopping-item-history']
const mainTabs = ['current', 'tasks', 'wishlist', 'profile']
const deepTabs = ['add-words', 'test', 'purchase', 'task-form', 'wishlist-form', 'wishlist-detail', 'board-form', 'board-join', 'words', 'dictionaries', 'todoist-integration', 'telegram-integration', 'fitbit-integration', 'full', 'priorities', 'tracking', 'tracking-access', 'tracking-invite', 'shopping', 'shopping-item-form', 'shopping-board-form', 'shopping-board-join', 'shopping-item-history']
/**
* Гарантирует базовую запись истории для главного экрана перед глубоким табом.
@@ -1109,7 +1109,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-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'
// Функция для получения классов скролл-контейнера для каждого таба
// Каждый таб имеет свой изолированный скролл-контейнер для автоматического сохранения позиции скролла
@@ -1121,9 +1121,9 @@ function AppContent() {
// Определяем padding для каждого таба
let paddingClasses = ''
if (tabName === 'current' || tabName === 'tasks' || tabName === 'wishlist' || tabName === 'shopping' || tabName === 'profile') {
if (tabName === 'current' || tabName === 'tasks' || tabName === 'wishlist' || tabName === 'profile') {
paddingClasses = 'pb-20'
} else if (tabName === 'words' || tabName === 'dictionaries') {
} else if (tabName === 'words' || tabName === 'dictionaries' || tabName === 'shopping') {
paddingClasses = 'pb-16'
}
@@ -1132,13 +1132,13 @@ function AppContent() {
// Функция для определения отступов внутреннего контейнера
const getInnerContainerClasses = (tabName) => {
if (tabName === 'tasks' || tabName === 'wishlist' || tabName === 'shopping' || tabName === 'profile') {
if (tabName === 'tasks' || tabName === 'wishlist' || tabName === 'profile') {
return 'max-w-7xl mx-auto p-4 md:p-8'
}
if (tabName === 'current') {
return 'max-w-7xl mx-auto p-4 md:p-6'
}
if (tabName === 'full' || tabName === 'priorities' || tabName === 'dictionaries' || tabName === 'words' || tabName === 'shopping-item-history' || tabName === 'purchase') {
if (tabName === 'full' || tabName === 'priorities' || tabName === 'dictionaries' || tabName === 'words' || tabName === 'shopping' || tabName === 'shopping-item-history' || tabName === 'purchase') {
return 'max-w-7xl mx-auto px-4 md:px-8 py-0'
}
// Fullscreen табы без отступов
@@ -1547,7 +1547,7 @@ function AppContent() {
)}
{/* Кнопка добавления товара (только для таба shopping) */}
{!isFullscreenTab && activeTab === 'shopping' && (
{activeTab === 'shopping' && (
<button
onClick={() => {
let boardId = tabParams.boardId
@@ -1564,7 +1564,7 @@ function AppContent() {
}
handleNavigate('shopping-item-form', { itemId: undefined, boardId: boardId })
}}
className="fixed bottom-16 right-4 z-20 bg-gradient-to-r from-indigo-600 to-purple-600 hover:from-indigo-700 hover:to-purple-700 text-white w-[61px] h-[61px] rounded-2xl shadow-lg transition-all duration-200 hover:scale-105 flex items-center justify-center"
className="fixed bottom-4 right-4 z-20 bg-gradient-to-r from-indigo-600 to-purple-600 hover:from-indigo-700 hover:to-purple-700 text-white w-[61px] h-[61px] rounded-2xl shadow-lg transition-all duration-200 hover:scale-105 flex items-center justify-center"
title="Добавить товар"
>
<svg
@@ -1697,26 +1697,6 @@ function AppContent() {
<div className="absolute top-0 left-0 right-0 h-1 bg-gradient-to-r from-indigo-500 to-purple-500"></div>
)}
</button>
<button
onClick={() => handleTabChange('shopping')}
className={`min-w-max whitespace-nowrap px-4 py-4 transition-all duration-300 relative ${
activeTab === 'shopping' || activeTab === 'shopping-item-form'
? 'text-indigo-700 bg-white/50'
: 'text-gray-600 hover:text-indigo-600 hover:bg-white/30'
}`}
title="Товары"
>
<span className="relative z-10 flex items-center justify-center">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<circle cx="9" cy="21" r="1"></circle>
<circle cx="20" cy="21" r="1"></circle>
<path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"></path>
</svg>
</span>
{(activeTab === 'shopping' || activeTab === 'shopping-item-form') && (
<div className="absolute top-0 left-0 right-0 h-1 bg-gradient-to-r from-indigo-500 to-purple-500"></div>
)}
</button>
<button
onClick={() => handleTabChange('wishlist')}
className={`min-w-max whitespace-nowrap px-4 py-4 transition-all duration-300 relative ${

View File

@@ -24,12 +24,12 @@
display: flex;
align-items: center;
gap: 10px;
height: 52px;
padding: 0 20px;
height: 40px;
padding: 0 10px 0 16px;
background: white;
border: 1px solid #e5e7eb;
border-radius: 26px;
font-size: 17px;
border-radius: 20px;
font-size: 15px;
font-weight: 500;
color: #1f2937;
cursor: pointer;
@@ -74,11 +74,11 @@
display: flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
margin-left: 4px;
width: 18px;
height: 18px;
margin-left: 6px;
border-left: 1px solid #e5e7eb;
padding-left: 10px;
padding-left: 6px;
color: #9ca3af;
flex-shrink: 0;
cursor: pointer;

View File

@@ -120,6 +120,29 @@ function Profile({ onNavigate }) {
</svg>
</div>
</button>
<button
onClick={() => onNavigate?.('shopping')}
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">
<span className="text-gray-800 font-medium group-hover:text-indigo-600 transition-colors">
Товары
</span>
<svg
className="w-5 h-5 text-gray-400 group-hover:text-indigo-500 transition-colors"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M9 5l7 7-7 7"
/>
</svg>
</div>
</button>
</div>
</div>

View File

@@ -4,6 +4,31 @@
padding-bottom: 2.5rem;
}
.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);
}
.close-x-button:hover {
background-color: #ffffff;
color: #2c3e50;
}
.shopping-empty {
text-align: center;
padding: 3rem 1rem;

View File

@@ -531,6 +531,7 @@ function ShoppingList({ onNavigate, refreshTrigger = 0, isActive = false, initia
return (
<div className="shopping-list">
<button className="close-x-button" onClick={() => window.history.back()}></button>
<BoardSelector
boards={boards}
selectedBoardId={selectedBoardId}