288 lines
9.6 KiB
TypeScript
288 lines
9.6 KiB
TypeScript
import React, { useEffect, useState } from 'react';
|
||
import { useNavigate } from 'react-router-dom';
|
||
import styles from './StickerPacks.module.css';
|
||
import { stickerService } from '../services/stickerService';
|
||
import { getCurrentUserId } from '../constants/user';
|
||
|
||
// Функция для удаления дописанной части из названия стикерпака
|
||
const cleanPackTitle = (title: string): string => {
|
||
// Ищем часть "| by @username" и удаляем её
|
||
const parts = title.split(' | by @');
|
||
return parts[0]; // Возвращаем только первую часть (оригинальное название)
|
||
};
|
||
|
||
interface StickerPack {
|
||
name: string;
|
||
title: string;
|
||
thumbnail_url?: string | null;
|
||
share_url?: string;
|
||
stickers: Array<{
|
||
id?: number;
|
||
file_id: string;
|
||
emoji: string;
|
||
position: number;
|
||
file_url?: string | null;
|
||
}>;
|
||
}
|
||
|
||
const StickerPacks: React.FC = () => {
|
||
const navigate = useNavigate();
|
||
const [stickerPacks, setStickerPacks] = useState<StickerPack[]>([]);
|
||
const [loading, setLoading] = useState(true);
|
||
const [error, setError] = useState<string | null>(null);
|
||
const [selectedPack, setSelectedPack] = useState<StickerPack | null>(null);
|
||
|
||
useEffect(() => {
|
||
const fetchStickerPacks = async () => {
|
||
try {
|
||
setLoading(true);
|
||
const stickerSets = await stickerService.getUserStickerPacks(getCurrentUserId().toString());
|
||
|
||
// Для каждого стикерпака получаем детальную информацию, обрабатывая ошибки отдельно
|
||
const packsDetails: StickerPack[] = [];
|
||
|
||
for (const stickerSet of stickerSets) {
|
||
try {
|
||
const packDetails = await stickerService.getStickerPack(stickerSet.set_name);
|
||
packsDetails.push(packDetails);
|
||
} catch (packError) {
|
||
console.warn(`Не удалось загрузить стикерпак ${stickerSet.set_name}:`, packError);
|
||
// Продолжаем загрузку других стикерпаков
|
||
}
|
||
}
|
||
|
||
setStickerPacks(packsDetails);
|
||
setError(null);
|
||
} catch (err) {
|
||
console.error('Ошибка при загрузке стикерпаков:', err);
|
||
setError('Не удалось загрузить список стикерпаков');
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
};
|
||
|
||
fetchStickerPacks();
|
||
}, []);
|
||
|
||
const handleCreateStickerPack = () => {
|
||
navigate('/create-sticker-pack');
|
||
};
|
||
|
||
const handleSelectPack = (pack: StickerPack) => {
|
||
setSelectedPack(pack);
|
||
};
|
||
|
||
const handleCloseDetails = () => {
|
||
setSelectedPack(null);
|
||
};
|
||
|
||
const handleDeletePack = async (packName: string) => {
|
||
if (!confirm('Вы уверены, что хотите удалить этот стикерпак?')) {
|
||
return;
|
||
}
|
||
|
||
try {
|
||
await stickerService.deleteStickerPack(packName);
|
||
setStickerPacks(prevPacks => prevPacks.filter(pack => pack.name !== packName));
|
||
setSelectedPack(null);
|
||
} catch (err) {
|
||
console.error('Ошибка при удалении стикерпака:', err);
|
||
alert('Не удалось удалить стикерпак');
|
||
}
|
||
};
|
||
|
||
const handleOpenInTelegram = () => {
|
||
if (selectedPack && selectedPack.share_url) {
|
||
window.open(selectedPack.share_url, '_blank');
|
||
}
|
||
};
|
||
|
||
const handleDeleteSticker = async (fileId: string) => {
|
||
if (!fileId) {
|
||
alert('Не удалось определить ID стикера');
|
||
return;
|
||
}
|
||
|
||
if (!confirm('Вы уверены, что хотите удалить этот стикер?')) {
|
||
return;
|
||
}
|
||
|
||
try {
|
||
await stickerService.deleteStickerByFileId(fileId);
|
||
|
||
// Обновляем список стикеров в выбранном стикерпаке
|
||
if (selectedPack) {
|
||
const updatedPack = await stickerService.getStickerPack(selectedPack.name);
|
||
setSelectedPack(updatedPack);
|
||
|
||
// Также обновляем стикерпак в общем списке
|
||
setStickerPacks(prevPacks =>
|
||
prevPacks.map(pack =>
|
||
pack.name === selectedPack.name ? updatedPack : pack
|
||
)
|
||
);
|
||
}
|
||
} catch (err) {
|
||
console.error('Ошибка при удалении стикера:', err);
|
||
alert('Не удалось удалить стикер');
|
||
}
|
||
};
|
||
|
||
return (
|
||
<div className={styles.container}>
|
||
<div className={styles.header}>
|
||
<h1 className={styles.title}>
|
||
Мои стикерпаки
|
||
</h1>
|
||
<p className={styles.subtitle}>
|
||
Создавайте и публикуйте наборы стикеров в Telegram
|
||
</p>
|
||
</div>
|
||
|
||
{loading && (
|
||
<div className={styles.placeholder}>
|
||
<p>Загрузка стикерпаков...</p>
|
||
</div>
|
||
)}
|
||
|
||
{error && (
|
||
<div className={styles.error}>
|
||
<p>{error}</p>
|
||
<button
|
||
className={styles.retryButton}
|
||
onClick={() => window.location.reload()}
|
||
>
|
||
Повторить
|
||
</button>
|
||
</div>
|
||
)}
|
||
|
||
{!loading && !error && stickerPacks.length === 0 && (
|
||
<div className={styles.placeholder}>
|
||
<span className={styles.placeholderIcon}>📦</span>
|
||
<p className={styles.placeholderText}>
|
||
У вас пока нет стикерпаков
|
||
</p>
|
||
<button
|
||
className={styles.createButton}
|
||
onClick={handleCreateStickerPack}
|
||
>
|
||
Создать стикерпак
|
||
</button>
|
||
</div>
|
||
)}
|
||
|
||
{!loading && !error && stickerPacks.length > 0 && !selectedPack && (
|
||
<>
|
||
<div className={styles.packsList}>
|
||
{stickerPacks.map((pack, index) => (
|
||
<div
|
||
key={index}
|
||
className={styles.packItem}
|
||
onClick={() => handleSelectPack(pack)}
|
||
>
|
||
<div className={styles.packHeader}>
|
||
<h3 className={styles.packTitle}>
|
||
Стикерпак: <span className={styles.packTitleName}>{cleanPackTitle(pack.title)}</span>
|
||
</h3>
|
||
<p className={styles.packStats}>
|
||
{pack.stickers ? pack.stickers.length : 0} / 49 стикеров
|
||
</p>
|
||
</div>
|
||
<div className={styles.packStickers}>
|
||
{pack.stickers && pack.stickers.map((sticker, idx) => (
|
||
<div key={idx} className={styles.stickerPreview}>
|
||
{sticker.file_url ? (
|
||
<img
|
||
src={sticker.file_url}
|
||
alt={`Стикер ${idx + 1}`}
|
||
className={styles.stickerImage}
|
||
/>
|
||
) : (
|
||
<div className={styles.stickerPlaceholder}>🖼️</div>
|
||
)}
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
|
||
<button
|
||
className={styles.createButtonFixed}
|
||
onClick={handleCreateStickerPack}
|
||
>
|
||
Создать стикерпак
|
||
</button>
|
||
</>
|
||
)}
|
||
|
||
{selectedPack && (
|
||
<div className={styles.packDetails}>
|
||
<div className={styles.detailsHeader}>
|
||
<button
|
||
className={styles.backButton}
|
||
onClick={handleCloseDetails}
|
||
>
|
||
← Назад
|
||
</button>
|
||
<h2 className={styles.detailsTitle}>{cleanPackTitle(selectedPack.title)}</h2>
|
||
<button
|
||
className={styles.deleteButton}
|
||
onClick={() => handleDeletePack(selectedPack.name)}
|
||
>
|
||
Удалить
|
||
</button>
|
||
</div>
|
||
|
||
<div className={styles.stickersList}>
|
||
{selectedPack.stickers && selectedPack.stickers.map((sticker, index) => (
|
||
<div key={index} className={styles.stickerItem}>
|
||
{sticker.file_url ? (
|
||
<img
|
||
src={sticker.file_url}
|
||
alt={`Стикер ${index + 1}`}
|
||
className={styles.stickerImage}
|
||
/>
|
||
) : (
|
||
<div className={styles.stickerImagePlaceholder}>🖼️</div>
|
||
)}
|
||
<div className={styles.stickerEmoji}>{sticker.emoji}</div>
|
||
|
||
{/* Кнопка удаления стикера */}
|
||
<button
|
||
className={styles.deleteStickerButton}
|
||
onClick={(e) => {
|
||
e.stopPropagation(); // Предотвращаем всплытие события
|
||
handleDeleteSticker(sticker.file_id);
|
||
}}
|
||
>
|
||
✕
|
||
</button>
|
||
</div>
|
||
))}
|
||
</div>
|
||
|
||
<div className={styles.detailsActions}>
|
||
<button
|
||
className={styles.addStickerButton}
|
||
onClick={() => navigate(`/add-sticker/${selectedPack.name}`)}
|
||
>
|
||
Добавить стикер
|
||
</button>
|
||
|
||
<button
|
||
className={styles.openInTelegramButton}
|
||
onClick={handleOpenInTelegram}
|
||
>
|
||
Открыть в Telegram
|
||
</button>
|
||
</div>
|
||
</div>
|
||
)}
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default StickerPacks;
|