import React, { useCallback, useState, useRef, type JSX, } from 'react'; import { useAtomValue, useSetAtom } from 'jotai'; import { useTranslation } from 'react-i18next'; import ImageCropModal from '~/client/components/Common/ImageCropModal'; import { apiv3Delete, apiv3PostForm, apiv3Put, } from '~/client/util/apiv3-client'; import { toastError, toastSuccess } from '~/client/util/toastr'; import { useIsDefaultLogo } from '~/states/global'; import { isCustomizedLogoUploadedAtom } from '~/states/server-configurations'; import AdminUpdateButtonRow from '../Common/AdminUpdateButtonRow'; const DEFAULT_LOGO = '/images/logo.svg'; const CUSTOMIZED_LOGO = '/attachment/brand-logo'; const CustomizeLogoSetting = (): JSX.Element => { const { t } = useTranslation(); const isDefaultLogo = useIsDefaultLogo(); const isCustomizedLogoUploaded = useAtomValue(isCustomizedLogoUploadedAtom); const setIsCustomizedLogoUploaded = useSetAtom(isCustomizedLogoUploadedAtom); const [uploadLogoSrc, setUploadLogoSrc] = useState(null); const [isImageCropModalShow, setIsImageCropModalShow] = useState(false); const [isDefaultLogoSelected, setIsDefaultLogoSelected] = useState(isDefaultLogo ?? true); const [retrieveError, setRetrieveError] = useState(); const fileInputRef = useRef(null); const isUpdateButtonDisabled = retrieveError != null || (!isDefaultLogoSelected && uploadLogoSrc == null && !isCustomizedLogoUploaded); const onSelectFile = useCallback((e: React.ChangeEvent) => { const files = e.target.files; const hasFile = files != null && files.length > 0; if (hasFile) { const reader = new FileReader(); reader.addEventListener('load', () => setUploadLogoSrc(reader.result)); reader.readAsDataURL(files[0]); setIsImageCropModalShow(true); } }, [setUploadLogoSrc, setIsImageCropModalShow]); const onClickSubmit = useCallback(async () => { try { await apiv3Put('/customize-setting/customize-logo', { isDefaultLogo: isDefaultLogoSelected }); toastSuccess(t('toaster.update_successed', { target: t('admin:customize_settings.custom_logo'), ns: 'commons' })); } catch (err) { toastError(err); } }, [t, isDefaultLogoSelected]); const clearFileInput = useCallback(() => { if (fileInputRef.current) { fileInputRef.current.value = ''; } }, []); const onClickDeleteBtn = useCallback(async () => { try { await apiv3Delete('/customize-setting/delete-brand-logo'); setIsCustomizedLogoUploaded(false); toastSuccess(t('toaster.update_successed', { target: t('admin:customize_settings.current_logo'), ns: 'commons' })); setUploadLogoSrc(null); setIsImageCropModalShow(false); clearFileInput(); } catch (err) { toastError(err); setRetrieveError(err); throw new Error('Failed to delete logo'); } }, [setIsCustomizedLogoUploaded, t, setUploadLogoSrc, setIsImageCropModalShow, clearFileInput, setRetrieveError]); const processImageCompletedHandler = useCallback(async (croppedImage) => { try { const formData = new FormData(); formData.append('file', croppedImage); const response = await apiv3PostForm('/customize-setting/upload-brand-logo', formData); const newLogoUrl = response.data.attachment.filePathProxied; setUploadLogoSrc(newLogoUrl); setIsImageCropModalShow(false); setIsCustomizedLogoUploaded(true); toastSuccess(t('toaster.update_successed', { target: t('admin:customize_settings.current_logo'), ns: 'commons' })); } catch (err) { toastError(err); setRetrieveError(err); throw new Error('Failed to upload brand logo'); } }, [setUploadLogoSrc, setIsCustomizedLogoUploaded, t, setIsImageCropModalShow, setRetrieveError]); const closeImageCropModalHandler = useCallback(() => { if (uploadLogoSrc !== null && typeof uploadLogoSrc !== 'string') { clearFileInput(); setUploadLogoSrc(null); } setIsImageCropModalShow(false); }, [clearFileInput, setUploadLogoSrc, setIsImageCropModalShow, uploadLogoSrc]); return (

{t('admin:customize_settings.custom_logo')}

{ setIsDefaultLogoSelected(true) }} />

{ setIsDefaultLogoSelected(false) }} />

{isCustomizedLogoUploaded && ( <>

)}
); }; export default CustomizeLogoSetting;