diff --git a/src/admin/AdminAddAllUploads.tsx b/src/admin/AdminAddAllUploads.tsx index 8360411f..f790ae5d 100644 --- a/src/admin/AdminAddAllUploads.tsx +++ b/src/admin/AdminAddAllUploads.tsx @@ -20,6 +20,7 @@ import ProgressButton from '@/components/primitives/ProgressButton'; import { UrlAddStatus } from './AdminUploadsClient'; import PhotoTagFieldset from './PhotoTagFieldset'; import DeleteUploadButton from './DeleteUploadButton'; +import { useAppState } from '@/state/AppState'; const UPLOAD_BATCH_SIZE = 4; @@ -36,6 +37,8 @@ export default function AdminAddAllUploads({ setIsAdding: (isAdding: boolean) => void setUrlAddStatuses: Dispatch> }) { + const { updateAdminData } = useAppState(); + const [buttonText, setButtonText] = useState('Add All Uploads'); const [showTags, setShowTags] = useState(false); const [tags, setTags] = useState(''); @@ -184,7 +187,10 @@ export default function AdminAddAllUploads({ router.push(PATH_ADMIN_PHOTOS)} + onDelete={() => { + updateAdminData?.({ uploadsCount: 0 }); + router.push(PATH_ADMIN_PHOTOS); + }} className="w-full flex justify-center" shouldRedirectToAdminPhotos hideTextOnMobile={false} diff --git a/src/admin/AdminAppMenu.tsx b/src/admin/AdminAppMenu.tsx index 43b22056..a487398e 100644 --- a/src/admin/AdminAppMenu.tsx +++ b/src/admin/AdminAppMenu.tsx @@ -131,7 +131,8 @@ export default function AdminAppMenu({ }, { label: 'Sign Out', icon: , - action: () => signOutAction().then(clearAuthStateAndRedirect), + action: () => signOutAction() + .then(() => clearAuthStateAndRedirect?.(false)), }); return ( diff --git a/src/admin/actions.ts b/src/admin/actions.ts index a3be182d..59ad75d0 100644 --- a/src/admin/actions.ts +++ b/src/admin/actions.ts @@ -10,13 +10,15 @@ import { getStorageUploadUrlsNoStore } from '@/platforms/storage/cache'; import { getPhotosMetaCached, getUniqueTagsCached } from '@/photo/cache'; import { getInsightsIndicatorStatus } from '@/admin/insights/server'; +export type AdminData = Awaited>; + export const getAdminDataAction = async () => runAuthenticatedAdminServerAction(async () => { const [ - countPhotos, - countHiddenPhotos, - countTags, - countUploads, + photosCount, + photosCountHidden, + tagsCount, + uploadsCount, insightsIndicatorStatus, ] = await Promise.all([ getPhotosMetaCached() @@ -37,11 +39,19 @@ export const getAdminDataAction = async () => getInsightsIndicatorStatus(), ]); + const photosCountTotal = ( + photosCount !== undefined && + photosCountHidden !== undefined + ) + ? photosCount + photosCountHidden + : undefined; + return { - countPhotos, - countHiddenPhotos, - countTags, - countUploads, + photosCount, + photosCountHidden, + photosCountTotal, + tagsCount, + uploadsCount, insightsIndicatorStatus, }; }); diff --git a/src/state/AppState.ts b/src/state/AppState.ts index 1da924ec..64648fa5 100644 --- a/src/state/AppState.ts +++ b/src/state/AppState.ts @@ -9,8 +9,9 @@ import { AnimationConfig } from '@/components/AnimateItems'; import { ShareModalProps } from '@/share'; import { InsightsIndicatorStatus } from '@/admin/insights'; import { INITIAL_UPLOAD_STATE, UploadState } from '@/admin/upload'; +import { AdminData } from '@/admin/actions'; -export interface AppStateContext { +export type AppStateContext = { // CORE previousPathname?: string hasLoaded?: boolean @@ -38,22 +39,17 @@ export interface AppStateContext { setUserEmail?: Dispatch> isUserSignedIn?: boolean isUserSignedInEager?: boolean - clearAuthStateAndRedirect?: () => void + clearAuthStateAndRedirect?: (shouldRedirect?: boolean) => void // ADMIN adminUpdateTimes?: Date[] registerAdminUpdate?: () => void refreshAdminData?: () => void - photosCount?: number - photosCountHidden?: number - photosCountTotal?: number - uploadsCount?: number - tagsCount?: number + updateAdminData?: (updatedData: Partial) => void selectedPhotoIds?: string[] setSelectedPhotoIds?: Dispatch> isPerformingSelectEdit?: boolean setIsPerformingSelectEdit?: Dispatch> insightsIndicatorStatus?: InsightsIndicatorStatus - setInsightsIndicatorStatus?: Dispatch> // DEBUG isGridHighDensity?: boolean setIsGridHighDensity?: Dispatch> @@ -69,7 +65,7 @@ export interface AppStateContext { setShouldDebugInsights?: Dispatch> shouldDebugRecipeOverlays?: boolean setShouldDebugRecipeOverlays?: Dispatch> -} +} & Partial export const AppStateContext = createContext({ uploadState: INITIAL_UPLOAD_STATE, diff --git a/src/state/AppStateProvider.tsx b/src/state/AppStateProvider.tsx index 36eaa49d..2039f0e6 100644 --- a/src/state/AppStateProvider.tsx +++ b/src/state/AppStateProvider.tsx @@ -14,8 +14,7 @@ import { } from '@/app/config'; import { ShareModalProps } from '@/share'; import { storeTimezoneCookie } from '@/utility/timezone'; -import { InsightsIndicatorStatus } from '@/admin/insights'; -import { getAdminDataAction } from '@/admin/actions'; +import { AdminData, getAdminDataAction } from '@/admin/actions'; import { storeAuthEmailCookie, clearAuthEmailCookie, @@ -60,20 +59,10 @@ export default function AppStateProvider({ // ADMIN const [adminUpdateTimes, setAdminUpdateTimes] = useState([]); - const [photosCount, setPhotosCount] = - useState(); - const [photosCountHidden, setPhotosCountHidden] = - useState(); - const [uploadsCount, setUploadsCount] = - useState(); - const [tagsCount, setTagsCount] = - useState(); const [selectedPhotoIds, setSelectedPhotoIds] = useState(); const [isPerformingSelectEdit, setIsPerformingSelectEdit] = useState(false); - const [insightsIndicatorStatus, setInsightsIndicatorStatus] = - useState(); // DEBUG const [isGridHighDensity, setIsGridHighDensity] = useState(HIGH_DENSITY_GRID); @@ -90,26 +79,9 @@ export default function AppStateProvider({ const [shouldDebugRecipeOverlays, setShouldDebugRecipeOverlays] = useState(false); - const photosCountTotal = ( - photosCount !== undefined && - photosCountHidden !== undefined - ) - ? photosCount + photosCountHidden - : undefined; - - const startUpload = useCallback((onStart?: () => void) => { - if (uploadInputRef.current) { - uploadInputRef.current.value = ''; - uploadInputRef.current.click(); - uploadInputRef.current.oninput = onStart ?? null; - uploadInputRef.current.oncancel = onStart ?? null; - } - }, []); - const setUploadState = useCallback((uploadState: Partial) => { - _setUploadState(prev => ({ ...prev, ...uploadState })); - }, []); - const resetUploadState = useCallback(() => { - _setUploadState(INITIAL_UPLOAD_STATE); + useEffect(() => { + setHasLoaded?.(true); + storeTimezoneCookie(); }, []); const invalidateSwr = useCallback(() => setSwrTimestamp(Date.now()), []); @@ -129,31 +101,28 @@ export default function AppStateProvider({ refreshInterval: 1000 * 60, }, ); + const updateAdminData = useCallback( + (updatedData: Partial) => { + if (adminData) { + refreshAdminData({ + ...adminData, + ...updatedData, + }); + } + }, [adminData, refreshAdminData]); useEffect(() => { if (userEmail) { storeAuthEmailCookie(userEmail); - if (adminData) { - setPhotosCount(adminData.countPhotos); - setPhotosCountHidden(adminData.countHiddenPhotos); - setUploadsCount(adminData.countUploads); - setTagsCount(adminData.countTags); - setInsightsIndicatorStatus(adminData.insightsIndicatorStatus); - } - } else { - setPhotosCountHidden(0); } - }, [adminData, userEmail]); + }, [userEmail, refreshAdminData, adminData]); + + console.log({ userEmail, isUserSignedIn, isUserSignedInEager }); const registerAdminUpdate = useCallback(() => setAdminUpdateTimes(updates => [...updates, new Date()]) , []); - useEffect(() => { - setHasLoaded?.(true); - storeTimezoneCookie(); - }, []); - const clearAuthStateAndRedirect = useCallback((shouldRedirect = true) => { setUserEmail(undefined); setIsUserSignedInEager(false); @@ -161,6 +130,21 @@ export default function AppStateProvider({ if (shouldRedirect) { router.push(PATH_SIGN_IN); } }, [router]); + const startUpload = useCallback((onStart?: () => void) => { + if (uploadInputRef.current) { + uploadInputRef.current.value = ''; + uploadInputRef.current.click(); + uploadInputRef.current.oninput = onStart ?? null; + uploadInputRef.current.oncancel = onStart ?? null; + } + }, []); + const setUploadState = useCallback((uploadState: Partial) => { + _setUploadState(prev => ({ ...prev, ...uploadState })); + }, []); + const resetUploadState = useCallback(() => { + _setUploadState(INITIAL_UPLOAD_STATE); + }, []); + return (