Streamline admin data state

This commit is contained in:
Sam Becker 2025-03-01 13:34:57 -06:00
parent 74e91be001
commit 69d584e51c
5 changed files with 65 additions and 73 deletions

View File

@ -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<SetStateAction<UrlAddStatus[]>>
}) {
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({
</ProgressButton>
<DeleteUploadButton
urls={storageUrls}
onDelete={() => router.push(PATH_ADMIN_PHOTOS)}
onDelete={() => {
updateAdminData?.({ uploadsCount: 0 });
router.push(PATH_ADMIN_PHOTOS);
}}
className="w-full flex justify-center"
shouldRedirectToAdminPhotos
hideTextOnMobile={false}

View File

@ -131,7 +131,8 @@ export default function AdminAppMenu({
}, {
label: 'Sign Out',
icon: <PiSignOutBold size={15} />,
action: () => signOutAction().then(clearAuthStateAndRedirect),
action: () => signOutAction()
.then(() => clearAuthStateAndRedirect?.(false)),
});
return (

View File

@ -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<ReturnType<typeof getAdminDataAction>>;
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,
};
});

View File

@ -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<SetStateAction<string | undefined>>
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<AdminData>) => void
selectedPhotoIds?: string[]
setSelectedPhotoIds?: Dispatch<SetStateAction<string[] | undefined>>
isPerformingSelectEdit?: boolean
setIsPerformingSelectEdit?: Dispatch<SetStateAction<boolean>>
insightsIndicatorStatus?: InsightsIndicatorStatus
setInsightsIndicatorStatus?: Dispatch<SetStateAction<InsightsIndicatorStatus>>
// DEBUG
isGridHighDensity?: boolean
setIsGridHighDensity?: Dispatch<SetStateAction<boolean>>
@ -69,7 +65,7 @@ export interface AppStateContext {
setShouldDebugInsights?: Dispatch<SetStateAction<boolean>>
shouldDebugRecipeOverlays?: boolean
setShouldDebugRecipeOverlays?: Dispatch<SetStateAction<boolean>>
}
} & Partial<AdminData>
export const AppStateContext = createContext<AppStateContext>({
uploadState: INITIAL_UPLOAD_STATE,

View File

@ -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<Date[]>([]);
const [photosCount, setPhotosCount] =
useState<number>();
const [photosCountHidden, setPhotosCountHidden] =
useState<number>();
const [uploadsCount, setUploadsCount] =
useState<number>();
const [tagsCount, setTagsCount] =
useState<number>();
const [selectedPhotoIds, setSelectedPhotoIds] =
useState<string[] | undefined>();
const [isPerformingSelectEdit, setIsPerformingSelectEdit] =
useState(false);
const [insightsIndicatorStatus, setInsightsIndicatorStatus] =
useState<InsightsIndicatorStatus>();
// 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<UploadState>) => {
_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<AdminData>) => {
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<UploadState>) => {
_setUploadState(prev => ({ ...prev, ...uploadState }));
}, []);
const resetUploadState = useCallback(() => {
_setUploadState(INITIAL_UPLOAD_STATE);
}, []);
return (
<AppStateContext.Provider
value={{
@ -196,17 +180,12 @@ export default function AppStateProvider({
adminUpdateTimes,
registerAdminUpdate,
refreshAdminData,
photosCount,
photosCountHidden,
photosCountTotal,
uploadsCount,
tagsCount,
updateAdminData,
...adminData,
selectedPhotoIds,
setSelectedPhotoIds,
isPerformingSelectEdit,
setIsPerformingSelectEdit,
insightsIndicatorStatus,
setInsightsIndicatorStatus,
// DEBUG
isGridHighDensity,
setIsGridHighDensity,