'use client' import {X} from 'lucide-react'; import IconButton from "@/components/ui/IconButton"; import React, {ChangeEvent, forwardRef, useContext, useImperativeHandle, useState} from "react"; import {apiDelete, apiPost} from "@/lib/api/client"; import {fetch} from "@tauri-apps/plugin-http"; import {AlertContext, AlertContextProps} from "@/context/AlertContext"; import {BookContext, BookContextProps} from "@/context/BookContext"; import {SessionContext, SessionContextProps} from "@/context/SessionContext"; import TextInput from "@/components/form/TextInput"; import TextAreaInput from "@/components/form/TextAreaInput"; import InputField from "@/components/form/InputField"; import NumberInput from "@/components/form/NumberInput"; import DatePicker from "@/components/form/DatePicker"; import {configs, isDesktop} from "@/lib/configs"; import * as tauri from '@/lib/tauri'; import OfflineContext, {OfflineContextType} from '@/context/OfflineContext'; import {useTranslations} from '@/lib/i18n'; import {LangContext, LangContextProps} from "@/context/LangContext"; import {BookProps} from "@/lib/types/book"; import {SettingRef} from "@/lib/types/settings"; import ImageDropZone from "@/components/form/ImageDropZone"; import {BooksSyncContext, BooksSyncContextProps} from "@/context/BooksSyncContext"; import {SyncedBook} from "@/lib/types/synced-book"; import {LocalSyncQueueContext, LocalSyncQueueContextProps} from "@/context/SyncQueueContext"; function BasicInformationSetting(_props: object, ref: React.ForwardedRef): React.JSX.Element { const t = useTranslations(); const {lang}: LangContextProps = useContext(LangContext); const {session}: SessionContextProps = useContext(SessionContext); const {book, setBook}: BookContextProps = useContext(BookContext); const userToken: string = session?.accessToken ? session?.accessToken : ''; const {errorMessage, successMessage}: AlertContextProps = useContext(AlertContext); const {isCurrentlyOffline}: OfflineContextType = useContext(OfflineContext); const {addToQueue}: LocalSyncQueueContextProps = useContext(LocalSyncQueueContext); const {localSyncedBooks}: BooksSyncContextProps = useContext(BooksSyncContext); const bookId: string = book?.bookId ? book?.bookId.toString() : ''; const [currentImage, setCurrentImage] = useState(book?.coverImage ?? ''); const [title, setTitle] = useState(book?.title ? book?.title : ''); const [subTitle, setSubTitle] = useState(book?.subTitle ? book?.subTitle : ''); const [summary, setSummary] = useState(book?.summary ? book?.summary : ''); const [publicationDate, setPublicationDate] = useState(book?.publicationDate ? book?.publicationDate : ''); const [wordCount, setWordCount] = useState(book?.desiredWordCount ? book?.desiredWordCount : 0); useImperativeHandle(ref, function (): SettingRef { return { handleSave: handleSave }; }); async function handleCoverImageChange(file: File): Promise { const formData: FormData = new FormData(); formData.append('bookId', bookId); formData.append('picture', file); try { const query: Response = await fetch( configs.apiUrl + `book/cover?bookid=${bookId}&lang=${lang}&plateforme=desktop`, { method: "POST", headers: {'Authorization': `Bearer ${userToken}`}, body: formData, } ); const contentType: string = query.headers.get('content-type') || 'image/jpeg'; const blob: Blob = new Blob([await query.arrayBuffer()], {type: contentType}); const reader: FileReader = new FileReader(); reader.onloadend = function (): void { if (typeof reader.result === 'string') { setCurrentImage(reader.result); } }; reader.readAsDataURL(blob); } catch (e: unknown) { if (e instanceof Error) { errorMessage(e.message); } else { errorMessage(t('basicInformationSetting.error.unknown')); } } } async function handleRemoveCurrentImage(): Promise { try { const response: boolean = await apiDelete(`book/cover/delete`, { bookId: bookId }, userToken, lang); if (!response) { errorMessage(t('basicInformationSetting.error.removeCover')); } setCurrentImage(''); } catch (e: unknown) { if (e instanceof Error) { errorMessage(e.message); } else { errorMessage(t('basicInformationSetting.error.unknown')); } } } async function handleSave(): Promise { if (!title) { errorMessage(t('basicInformationSetting.error.titleRequired')); return; } try { let response: boolean; if (isDesktop && (isCurrentlyOffline() || book?.localBook)) { response = await tauri.updateBookBasicInfo({ bookId: bookId, title: title, subTitle: subTitle, summary: summary, publicationDate: publicationDate, wordCount: wordCount, }); } else { const basicInfoData = { title, subTitle, summary, publicationDate, wordCount, bookId }; response = await apiPost('book/basic-information', basicInfoData, userToken, lang); if (isDesktop && localSyncedBooks.find((syncedBook: SyncedBook): boolean => syncedBook.id === bookId)) { addToQueue('update_book_basic_info', basicInfoData); } } if (!response) { errorMessage(t('basicInformationSetting.error.update')); return; } if (!book) { errorMessage(t('basicInformationSetting.error.unknown')); return; } const updatedBook: BookProps = { ...book, title: title, subTitle: subTitle, summary: summary, publicationDate: publicationDate, desiredWordCount: wordCount, }; setBook(updatedBook); successMessage(t('basicInformationSetting.success.update')); } catch (e: unknown) { if (e instanceof Error) { errorMessage(e.message); } else { errorMessage(t('basicInformationSetting.error.unknown')); } } } return (
): void => setTitle(e.target.value)} placeholder={t('basicInformationSetting.fields.titlePlaceholder')} />}/> ): void => setSubTitle(e.target.value)} placeholder={t('basicInformationSetting.fields.subtitlePlaceholder')} />}/>
): void => setSummary(e.target.value)} placeholder={t('basicInformationSetting.fields.summaryPlaceholder')} />}/>
): void => setPublicationDate(e.target.value)} /> }/> }/>
{currentImage ? (
{t('basicInformationSetting.fields.coverImageAlt')}
) : ( )}
); } export default forwardRef(BasicInformationSetting);