'use client'; import ErrorNote from '@/components/ErrorNote'; import FieldSetWithStatus from '@/components/FieldSetWithStatus'; import Container from '@/components/Container'; import { addAllUploadsAction } from '@/photo/actions'; import { PATH_ADMIN_PHOTOS } from '@/site/paths'; import { Tags, convertTagsForForm, getValidationMessageForTags, } from '@/tag'; import { generateLocalNaivePostgresString, generateLocalPostgresString, } from '@/utility/date'; import sleep from '@/utility/sleep'; import { readStreamableValue } from 'ai/rsc'; import { clsx } from 'clsx/lite'; import { useRouter } from 'next/navigation'; import { Dispatch, SetStateAction, useRef, useState } from 'react'; import { BiCheckCircle, BiImageAdd } from 'react-icons/bi'; import ProgressButton from '@/components/primitives/ProgressButton'; const UPLOAD_BATCH_SIZE = 4; export default function AdminAddAllUploads({ storageUrls, uniqueTags, isAdding, setIsAdding, setAddedUploadUrls, }: { storageUrls: string[] uniqueTags?: Tags isAdding: boolean setIsAdding: (isAdding: boolean) => void setAddedUploadUrls?: Dispatch> }) { const divRef = useRef(null); const [buttonText, setButtonText] = useState('Add All Uploads'); const [buttonSubheadText, setButtonSubheadText] = useState(''); const [showTags, setShowTags] = useState(false); const [tags, setTags] = useState(''); const [actionErrorMessage, setActionErrorMessage] = useState(''); const [tagErrorMessage, setTagErrorMessage] = useState(''); const [addingProgress, setAddingProgress] = useState(); const [isAddingComplete, setIsAddingComplete] = useState(false); const router = useRouter(); const addedUploadUrls = useRef([]); const addUploadUrls = async (uploadUrls: string[]) => { try { const stream = await addAllUploadsAction({ uploadUrls, tags: showTags ? tags : undefined, takenAtLocal: generateLocalPostgresString(), takenAtNaiveLocal: generateLocalNaivePostgresString(), }); for await (const data of readStreamableValue(stream)) { setButtonText(addedUploadUrls.current.length === 0 ? `Adding ${storageUrls.length} uploads` : `Adding ${addedUploadUrls.current.length} of ${storageUrls.length}` ); setButtonSubheadText(data?.subhead ?? ''); setAddingProgress(( addedUploadUrls.current.length / storageUrls.length ) * 0.95); setAddedUploadUrls?.(current => { const urls = data?.addedUploadUrls.split(',') ?? []; const updatedUrls = current .filter(url => !urls.includes(url)) .concat(urls); addedUploadUrls.current = updatedUrls; return updatedUrls; }); } } catch (e: any) { setIsAdding(false); setButtonText('Try Again'); setAddingProgress(undefined); setActionErrorMessage(e); } }; return ( <> {actionErrorMessage && {actionErrorMessage}}
{showTags ? tagErrorMessage || 'Add tags to all uploads' : `Found ${storageUrls.length} uploads`}
{ setShowTags(value === 'true'); if (value === 'true') { setTimeout(() => divRef.current?.querySelectorAll('input')[0]?.focus() , 100); } }} readOnly={isAdding} />
{ setTags(tags); setTagErrorMessage(getValidationMessageForTags(tags) ?? ''); }} readOnly={isAdding} error={tagErrorMessage} required={false} hideLabel />
: } onClick={async () => { // eslint-disable-next-line max-len if (confirm(`Are you sure you want to add all ${storageUrls.length} uploads?`)) { setIsAdding(true); let uploadsToAdd = storageUrls.slice(); try { while (uploadsToAdd.length > 0) { await addUploadUrls( uploadsToAdd.splice(0, UPLOAD_BATCH_SIZE), ); } setButtonText('Complete'); setButtonSubheadText('All uploads added'); setAddingProgress(1); setIsAdding(false); setIsAddingComplete(true); await sleep(1000).then(() => router.push(PATH_ADMIN_PHOTOS)); } catch (e: any) { setAddingProgress(undefined); setIsAdding(false); setButtonText('Try Again'); setActionErrorMessage(e); } } }} hideTextOnMobile={false} > {buttonText} {buttonSubheadText &&
{buttonSubheadText}
}
); }