import { useState } from 'react'; import { Alert, StyleSheet, Text, View } from 'react-native'; import * as DocumentPicker from 'expo-document-picker'; import * as FileSystem from 'expo-file-system/legacy'; import * as Sharing from 'expo-sharing'; import { useMutation } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import { downloadImportTemplate, importRecipesFromExcel } from '@/src/api/recipe-management.api'; import { Button } from '@/src/components/Button'; import { useAppearance } from '@/src/context/AppearanceContext'; import { extractApiError } from '@/src/utils/apiError'; interface ExcelImportPanelProps { onImported?: () => void; } export function ExcelImportPanel({ onImported }: ExcelImportPanelProps) { const { t } = useTranslation(); const { colors } = useAppearance(); const [selectedFile, setSelectedFile] = useState<{ uri: string; name: string } | null>(null); const [downloading, setDownloading] = useState(false); const importMutation = useMutation({ mutationFn: () => { if (!selectedFile) throw new Error('No file'); return importRecipesFromExcel(selectedFile.uri, selectedFile.name); }, onSuccess: (result) => { setSelectedFile(null); onImported?.(); Alert.alert( t('manage.importComplete'), `${t('manage.createdCount', { count: result.createdCount })} · ${t('manage.skippedCount', { count: result.skippedCount })}`, ); }, }); async function handleDownloadTemplate() { setDownloading(true); try { const blob = await downloadImportTemplate(); const reader = new FileReader(); const base64 = await new Promise((resolve, reject) => { reader.onloadend = () => { const dataUrl = reader.result as string; resolve(dataUrl.split(',')[1] ?? ''); }; reader.onerror = reject; reader.readAsDataURL(blob); }); const path = `${FileSystem.cacheDirectory}DailyMeals-recipe-import-template.xlsx`; await FileSystem.writeAsStringAsync(path, base64, { encoding: FileSystem.EncodingType.Base64 }); if (await Sharing.isAvailableAsync()) { await Sharing.shareAsync(path); } } catch (err) { Alert.alert(t('errors.generic'), extractApiError(err, t('errors.saveRecipeFailed'))); } finally { setDownloading(false); } } async function handlePickFile() { const result = await DocumentPicker.getDocumentAsync({ type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', copyToCacheDirectory: true, }); if (!result.canceled && result.assets[0]) { setSelectedFile({ uri: result.assets[0].uri, name: result.assets[0].name }); } } return ( {t('manage.importTitle')} {t('manage.importDescription')}