'use client' import React, {ReactNode, useContext, useState} from 'react'; import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'; import {faArrowDown, faArrowUp, faSpinner} from '@fortawesome/free-solid-svg-icons'; import {useTranslations} from 'next-intl'; import {SessionContext} from '@/context/SessionContext'; import {AlertContext} from '@/context/AlertContext'; import {LangContext, LangContextProps} from '@/context/LangContext'; import OfflineContext, {OfflineContextType} from '@/context/OfflineContext'; import {LocalSyncQueueContext, LocalSyncQueueContextProps} from '@/context/SyncQueueContext'; import {BooksSyncContext, BooksSyncContextProps} from '@/context/BooksSyncContext'; import {BookContext} from '@/context/BookContext'; import {SyncedBook} from '@/lib/models/SyncedBook'; import System from '@/lib/models/System'; export type SyncElementType = 'character' | 'world' | 'location' | 'spell'; interface SyncFieldWrapperProps { children: ReactNode; seriesElementId: string | null | undefined; seriesValue: string; currentValue: string; bookElementId: string; field: string; elementType: SyncElementType; onDownload: () => void; onSyncComplete?: () => void; } interface SeriesSyncUploadResponse { success: boolean; updatedCount: number; } export default function SyncFieldWrapper({ children, seriesElementId, seriesValue, currentValue, bookElementId, field, elementType, onDownload, onSyncComplete }: SyncFieldWrapperProps) { const t = useTranslations(); const {session} = useContext(SessionContext); const {errorMessage, successMessage} = useContext(AlertContext); const {lang} = useContext(LangContext); const {isCurrentlyOffline} = useContext(OfflineContext); const {addToQueue} = useContext(LocalSyncQueueContext); const {localSyncedBooks} = useContext(BooksSyncContext); const {book} = useContext(BookContext); const [isUploading, setIsUploading] = useState(false); const isLinkedToSeries: boolean = !!seriesElementId; const hasSeriesDiff: boolean = isLinkedToSeries && seriesValue !== currentValue; async function handleUpload(): Promise { if (!seriesElementId || isUploading) return; setIsUploading(true); try { const requestData = { type: elementType, bookElementId: bookElementId, field: field, value: currentValue }; let response: SeriesSyncUploadResponse; if (isCurrentlyOffline() || book?.localBook) { // Offline OU livre local → IPC response = await window.electron.invoke('db:series:sync:upload', requestData); } else { // Online + livre serveur → Server response = await System.authPostToServer( 'series/propagate', requestData, session.accessToken, lang ); // Si le livre a une copie locale → addToQueue pour sync if (book?.bookId && localSyncedBooks.find((sb: SyncedBook): boolean => sb.id === book.bookId)) { addToQueue('db:series:sync:upload', requestData); } } if (response.success) { successMessage(t('syncField.uploadSuccess', {count: response.updatedCount})); if (onSyncComplete) { onSyncComplete(); } } } catch (e: unknown) { if (e instanceof Error) { errorMessage(e.message); } } finally { setIsUploading(false); } } function handleDownload(): void { onDownload(); } if (!isLinkedToSeries) { return <>{children}; } return (
{children}
); }