diff --git a/src/screens/AddStickerToPackScreen.module.css b/src/screens/AddStickerToPackScreen.module.css index ee9ed6c..10b76dd 100644 --- a/src/screens/AddStickerToPackScreen.module.css +++ b/src/screens/AddStickerToPackScreen.module.css @@ -5,6 +5,7 @@ padding: calc(3rem + var(--spacing-small)) var(--spacing-medium) var(--spacing-large); width: 100%; box-sizing: border-box; + position: relative; /* Добавляем для позиционирования фиксированной кнопки */ } .header { @@ -37,12 +38,15 @@ } .content { + position: relative; display: flex; flex-direction: column; gap: var(--spacing-large); background-color: var(--color-surface); border-radius: var(--border-radius); padding: var(--spacing-large); + min-height: 100vh; /* Обеспечиваем, чтобы контент занимал как минимум всю высоту экрана */ + padding-bottom: calc(7rem + 80px + var(--safe-area-inset-bottom)); /* Отступ для кнопки */ } .section { @@ -74,6 +78,7 @@ transition: transform 0.2s, border-color 0.2s; } + .imageItem:hover { transform: translateY(-2px); } @@ -89,46 +94,65 @@ } .emojiSelector { - display: flex; - flex-direction: column; - align-items: center; - gap: var(--spacing-small); - padding: var(--spacing-medium); - background-color: var(--color-background); + position: absolute; + bottom: var(--spacing-small); + right: var(--spacing-small); + background-color: rgba(0, 0, 0, 0.7); border-radius: var(--border-radius); + padding: 2px; } -.emojiInput { - width: 5rem; - height: 3rem; +.emojiButton { + width: 2.5rem; + height: 2.5rem; background: none; - border: 1px solid var(--color-border); - border-radius: var(--border-radius); - color: var(--color-text); - font-size: 2rem; + border: none; + color: white; + font-size: 1.2rem; text-align: center; + cursor: pointer; } -.emojiHelp { - font-size: 0.9rem; - color: var(--color-text); - opacity: 0.7; - text-align: center; +@supports (-webkit-touch-callout: none) { + /* Стили только для iOS устройств */ + .emojiSelector { + display: flex; + justify-content: center; + align-items: center; + } + + .emojiButton { + display: flex; + justify-content: center; + align-items: center; + padding: 0; + line-height: 1; /* Важно для вертикального центрирования текста на iOS */ + -webkit-appearance: none; + -webkit-tap-highlight-color: transparent; + } } -.actions { - display: flex; - justify-content: center; - margin-top: var(--spacing-medium); +/* Стили для контейнера кнопки */ +.addButtonContainer { + position: fixed; + bottom: calc(6rem + var(--safe-area-inset-bottom)); /* Отступ от навигации */ + left: var(--spacing-medium); + right: var(--spacing-medium); + width: auto; + max-width: calc(28rem - 2 * var(--spacing-medium)); + margin: 0 auto; + z-index: 90; } .addButton { - padding: var(--spacing-small) var(--spacing-large); + width: 100%; + padding: calc(var(--spacing-small) * 1.5) var(--spacing-large); /* Увеличенный вертикальный padding для толщины */ background-color: var(--color-primary); color: white; border: none; border-radius: var(--border-radius); font-weight: 500; + font-size: 1.1rem; /* Увеличенный размер шрифта */ cursor: pointer; transition: transform 0.2s; } diff --git a/src/screens/AddStickerToPackScreen.tsx b/src/screens/AddStickerToPackScreen.tsx index c7b9f77..13ecc4e 100644 --- a/src/screens/AddStickerToPackScreen.tsx +++ b/src/screens/AddStickerToPackScreen.tsx @@ -5,17 +5,28 @@ import { stickerService } from '../services/stickerService'; import apiService from '../services/api'; import { GeneratedImage } from '../types/api'; import { getCurrentUserId } from '../constants/user'; +import EmojiPickerModal from '../components/shared/EmojiPickerModal'; +import ValidationModal from '../components/shared/ValidationModal'; const AddStickerToPackScreen: React.FC = () => { const navigate = useNavigate(); const { packName } = useParams<{ packName: string }>(); - const [selectedImage, setSelectedImage] = useState(null); - const [emoji, setEmoji] = useState('😊'); + const [selectedImages, setSelectedImages] = useState([]); + const [emojis, setEmojis] = useState([]); const [availableImages, setAvailableImages] = useState([]); const [loading, setLoading] = useState(true); const [adding, setAdding] = useState(false); const [error, setError] = useState(null); const [packTitle, setPackTitle] = useState(''); + + // Состояния для модального окна эмодзи + const [isEmojiPickerVisible, setIsEmojiPickerVisible] = useState(false); + const [activeEmojiIndex, setActiveEmojiIndex] = useState(null); + + // Состояния для модального окна валидации + const [validationTitle, setValidationTitle] = useState(''); + const [validationMessage, setValidationMessage] = useState(''); + const [isValidationModalVisible, setIsValidationModalVisible] = useState(false); // Загрузка доступных изображений и информации о стикерпаке useEffect(() => { @@ -45,25 +56,74 @@ const AddStickerToPackScreen: React.FC = () => { fetchData(); }, [packName]); - // Обработчик выбора изображения - const handleImageSelect = (image: GeneratedImage) => { - setSelectedImage(image); + // Функция для открытия пикера эмодзи + const openEmojiPicker = (index: number, e: React.MouseEvent) => { + e.stopPropagation(); + setActiveEmojiIndex(index); + setIsEmojiPickerVisible(true); }; - // Обработчик добавления стикера - const handleAddSticker = async () => { - if (!selectedImage) { - setError('Выберите изображение для стикера'); - return; - } + // Функция для закрытия пикера эмодзи без выбора + const handleCancelEmojiPicker = () => { + setIsEmojiPickerVisible(false); + setActiveEmojiIndex(null); + }; - if (!emoji.trim()) { - setError('Введите эмодзи для стикера'); + // Функция для выбора эмодзи + const handleSelectEmoji = (emoji: string) => { + if (activeEmojiIndex !== null) { + handleEmojiChange(activeEmojiIndex, emoji); + } + setIsEmojiPickerVisible(false); + setActiveEmojiIndex(null); + }; + + // Обработчик изменения эмодзи + const handleEmojiChange = (index: number, emoji: string) => { + setEmojis(prev => { + const newEmojis = [...prev]; + newEmojis[index] = emoji; + return newEmojis; + }); + }; + + // Обработчик закрытия модального окна валидации + const handleValidationModalClose = () => { + setIsValidationModalVisible(false); + }; + + // Обработчик выбора изображения + const handleImageSelect = (image: GeneratedImage) => { + // Проверяем, выбрано ли уже изображение + const isSelected = selectedImages.some(img => img.id === image.id); + + if (isSelected) { + // Если изображение уже выбрано, удаляем его из выбранных + setSelectedImages(prev => prev.filter(img => img.id !== image.id)); + setEmojis(prev => { + const index = selectedImages.findIndex(img => img.id === image.id); + return prev.filter((_, i) => i !== index); + }); + } else { + // Если изображение не выбрано, добавляем его в выбранные + setSelectedImages(prev => [...prev, image]); + setEmojis(prev => [...prev, '😊']); // Добавляем эмодзи по умолчанию + } + }; + + // Обработчик добавления стикеров + const handleAddStickers = async () => { + if (selectedImages.length === 0) { + setValidationTitle('Стикеры не выбраны'); + setValidationMessage('Пожалуйста, выберите хотя бы одно изображение для добавления в стикерпак.'); + setIsValidationModalVisible(true); return; } if (!packName) { - setError('Не указано имя стикерпака'); + setValidationTitle('Ошибка'); + setValidationMessage('Не указано имя стикерпака.'); + setIsValidationModalVisible(true); return; } @@ -71,27 +131,34 @@ const AddStickerToPackScreen: React.FC = () => { setAdding(true); setError(null); - // Проверяем, что link существует и является строкой - if (typeof selectedImage.link !== 'string') { - console.error('Некорректный формат link:', selectedImage.link); - setError('Некорректный формат изображения'); - return; - } + // Добавляем каждый стикер по очереди + for (let i = 0; i < selectedImages.length; i++) { + const image = selectedImages[i]; + const emoji = emojis[i] || '😊'; - // Добавляем стикер в стикерпак, используя file_id изображения - await stickerService.addStickerToPack( - packName, - getCurrentUserId().toString(), - selectedImage.link, - emoji, - packTitle // Передаем заголовок стикерпака - ); + // Проверяем, что link существует и является строкой + if (typeof image.link !== 'string') { + console.error('Некорректный формат link:', image.link); + continue; + } + + // Добавляем стикер в стикерпак + await stickerService.addStickerToPack( + packName, + getCurrentUserId().toString(), + image.link, + emoji, + packTitle + ); + } // Возвращаемся на страницу стикерпаков navigate('/packs'); } catch (err) { - console.error('Ошибка при добавлении стикера:', err); - setError('Не удалось добавить стикер'); + console.error('Ошибка при добавлении стикеров:', err); + setValidationTitle('Ошибка'); + setValidationMessage('Не удалось добавить стикеры в стикерпак. Пожалуйста, попробуйте еще раз.'); + setIsValidationModalVisible(true); } finally { setAdding(false); } @@ -107,7 +174,7 @@ const AddStickerToPackScreen: React.FC = () => { ← Назад

- Добавление стикера в "{packTitle || packName}" + Добавление стикеров в "{packTitle || packName}"

@@ -127,7 +194,7 @@ const AddStickerToPackScreen: React.FC = () => { {!loading && ( <>
-

1. Выберите изображение

+

Выберите изображения для стикеров

{availableImages.length === 0 ? (

@@ -136,52 +203,67 @@ const AddStickerToPackScreen: React.FC = () => {

) : (
- {availableImages.map((image, index) => ( -
handleImageSelect(image)} - > - {`Изображение -
- ))} + {availableImages.map((image, index) => { + const isSelected = selectedImages.some(img => img.id === image.id); + const selectedIndex = selectedImages.findIndex(img => img.id === image.id); + + return ( +
handleImageSelect(image)} + > + {`Изображение + + {isSelected && ( +
+ +
+ )} +
+ ); + })}
)}
- -
-

2. Выберите эмодзи

-
- setEmoji(e.target.value)} - className={styles.emojiInput} - maxLength={2} - placeholder="😊" - /> -

- Введите один или два эмодзи, которые будут ассоциироваться со стикером -

-
-
- -
- -
)} + +
+ +
+ + {/* Модальное окно выбора эмодзи */} + + + {/* Модальное окно валидации */} + ); };