'use client' import React, { useState } from 'react' interface ImportDataModalProps { isOpen: boolean onClose: () => void onImportComplete?: () => void } interface ImportPreview { export_info?: { username: string export_date: string } user_data?: { username: string email: string full_name: string bio?: string } groups_count: number links_count: number has_design_settings: boolean media_files: { avatars: number customization: number link_groups: number links: number } groups_preview: Array<{ id: number title: string description?: string }> links_preview: Array<{ id: number title: string url: string group_id: number }> } interface ImportSelection { groups: boolean links: boolean styles: boolean media: boolean overwrite_existing: boolean } export function ImportDataModal({ isOpen, onClose, onImportComplete }: ImportDataModalProps) { const [selectedFile, setSelectedFile] = useState(null) const [preview, setPreview] = useState(null) const [selection, setSelection] = useState({ groups: true, links: true, styles: true, media: true, overwrite_existing: false }) const [loading, setLoading] = useState(false) const [previewLoading, setPreviewLoading] = useState(false) const handleFileSelect = async (file: File) => { setSelectedFile(file) setPreview(null) if (!file.name.endsWith('.zip')) { alert('Пожалуйста, выберите ZIP архив') return } setPreviewLoading(true) try { const formData = new FormData() formData.append('import_file', file) const token = localStorage.getItem('access_token') || localStorage.getItem('token') const API = process.env.NEXT_PUBLIC_API_URL || 'https://links.shareon.kr' const response = await fetch(`${API}/api/import/preview/`, { method: 'POST', headers: { 'Authorization': `Bearer ${token}` }, body: formData }) if (response.ok) { const previewData = await response.json() setPreview(previewData) } else { const errorData = await response.json() throw new Error(errorData.error || 'Ошибка при анализе архива') } } catch (error) { console.error('Ошибка при анализе файла:', error) alert('Ошибка при анализе архива: ' + (error instanceof Error ? error.message : 'Неизвестная ошибка')) setSelectedFile(null) } finally { setPreviewLoading(false) } } const handleImport = async () => { if (!selectedFile) { alert('Пожалуйста, выберите файл для импорта') return } setLoading(true) try { const formData = new FormData() formData.append('import_file', selectedFile) formData.append('import_groups', selection.groups.toString()) formData.append('import_links', selection.links.toString()) formData.append('import_styles', selection.styles.toString()) formData.append('import_media', selection.media.toString()) formData.append('overwrite_existing', selection.overwrite_existing.toString()) const token = localStorage.getItem('access_token') || localStorage.getItem('token') const API = process.env.NEXT_PUBLIC_API_URL || 'https://links.shareon.kr' const response = await fetch(`${API}/api/import/`, { method: 'POST', headers: { 'Authorization': `Bearer ${token}` }, body: formData }) if (response.ok) { const result = await response.json() alert(`Импорт завершен успешно!\nИмпортировано групп: ${result.imported_groups_count}\nИмпортировано ссылок: ${result.imported_links_count}\nИмпортировано медиафайлов: ${result.imported_media_count}`) // Очищаем состояние setSelectedFile(null) setPreview(null) // Вызываем коллбэк для обновления данных if (onImportComplete) { onImportComplete() } onClose() } else { const errorData = await response.json() throw new Error(errorData.error || 'Ошибка при импорте') } } catch (error) { console.error('Ошибка импорта:', error) alert('Ошибка при импорте: ' + (error instanceof Error ? error.message : 'Неизвестная ошибка')) } finally { setLoading(false) } } const formatFileSize = (bytes: number) => { if (bytes < 1024) return bytes + ' B' if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB' return (bytes / (1024 * 1024)).toFixed(1) + ' MB' } if (!isOpen) return null return (
Импорт данных профиля
{/* Выбор файла */}
{ const file = e.target.files?.[0] if (file) { handleFileSelect(file) } }} disabled={previewLoading || loading} /> {selectedFile && (
{selectedFile.name} ({formatFileSize(selectedFile.size)})
)}
{/* Индикатор загрузки превью */} {previewLoading && (
Анализ архива...

Анализ архива...

)} {/* Превью содержимого */} {preview && (
Содержимое архива
Информация об экспорте
{preview.export_info && (
  • Источник: {preview.export_info.username}
  • Дата экспорта: {new Date(preview.export_info.export_date).toLocaleString()}
)}
Статистика данных
  • Групп: {preview.groups_count}
  • Ссылок: {preview.links_count}
  • Настройки дизайна: {preview.has_design_settings ? 'Есть' : 'Нет'}
  • Медиафайлов: {Object.values(preview.media_files).reduce((a, b) => a + b, 0)}
{/* Превью групп */} {preview.groups_preview.length > 0 && (
Группы (первые 5)
{preview.groups_preview.map((group, index) => (
{group.title} {group.description && (
{group.description}
)}
))}
)} {/* Превью ссылок */} {preview.links_preview.length > 0 && (
Ссылки (первые 10)
{preview.links_preview.map((link, index) => (
{link.title}
{link.url}
))}
)}
)} {/* Настройки импорта */} {preview && (
Настройки импорта
setSelection(prev => ({ ...prev, groups: e.target.checked }))} />
setSelection(prev => ({ ...prev, links: e.target.checked }))} />
setSelection(prev => ({ ...prev, styles: e.target.checked }))} disabled={!preview.has_design_settings} />
setSelection(prev => ({ ...prev, media: e.target.checked }))} />
setSelection(prev => ({ ...prev, overwrite_existing: e.target.checked }))} />
Если отключено, существующие группы и ссылки с такими же названиями будут пропущены
)}
) }