From 32c38107bb18c2d963d05e6a9410afb1c4e4adba Mon Sep 17 00:00:00 2001 From: Mauricio Medvescig Date: Mon, 12 Feb 2024 22:51:13 -0300 Subject: [PATCH] refactor albums by date to RTK --- src/actions/albumActions.types.ts | 3 ++ src/api_client/albums/date.ts | 62 ++++++++++++++++++++++++++ src/layouts/photos/TimestampPhotos.tsx | 36 ++++++--------- 3 files changed, 79 insertions(+), 22 deletions(-) create mode 100644 src/api_client/albums/date.ts diff --git a/src/actions/albumActions.types.ts b/src/actions/albumActions.types.ts index 0b18ea47..661e72c3 100644 --- a/src/actions/albumActions.types.ts +++ b/src/actions/albumActions.types.ts @@ -139,6 +139,9 @@ export const FetchAutoAlbumsListResponseSchema = z.object({ export const FetchDateAlbumsListResponseSchema = z.object({ results: IncompleteDatePhotosGroupSchema.array(), }); +export const FetchDateAlbumResponseSchema = z.object({ + results: IncompleteDatePhotosGroupSchema, +}); export const FetchUserAlbumsSharedResponseSchema = z.object({ results: UserAlbumInfoSchema.array(), diff --git a/src/api_client/albums/date.ts b/src/api_client/albums/date.ts new file mode 100644 index 00000000..c9cd9be1 --- /dev/null +++ b/src/api_client/albums/date.ts @@ -0,0 +1,62 @@ +import { FetchDateAlbumResponseSchema, FetchDateAlbumsListResponseSchema } from "../../actions/albumActions.types"; +import { IncompleteDatePhotosGroup } from "../../actions/photosActions.types"; +import { addTempElementsToGroups } from "../../util/util"; +import { api } from "../api"; + +enum Endpoints { + fetchDateAlbums = "fetchDateAlbums", + fetchDateAlbum = "fetchDateAlbum", +} + +export const dateAlbumsApi = api + .injectEndpoints({ + endpoints: builder => ({ + [Endpoints.fetchDateAlbums]: builder.query({ + query: () => "albums/date/list/", + transformResponse: response => { + const { results } = FetchDateAlbumsListResponseSchema.parse(response); + addTempElementsToGroups(results); + + return results; + }, + }), + [Endpoints.fetchDateAlbum]: builder.query({ + query: ({ id, page }) => `albums/date/${id}/?page=${page}`, + transformResponse: response => FetchDateAlbumResponseSchema.parse(response).results, + // Add results to fetchDateAlbums cache + async onQueryStarted({ id, page }, { dispatch, queryFulfilled }) { + const { data } = await queryFulfilled; + + dispatch( + dateAlbumsApi.util.updateQueryData(Endpoints.fetchDateAlbums, undefined, draft => { + const indexToReplace = draft.findIndex(group => group.id === id); + const groupToChange = draft[indexToReplace]; + if (!groupToChange) return; + + const { items } = groupToChange; + groupToChange.items = items + .slice(0, (page - 1) * 100) + .concat(data.items) + .concat(items.slice(page * 100)); + + // eslint-disable-next-line no-param-reassign + draft[indexToReplace] = groupToChange; + }) + ); + }, + }), + }), + }) + .enhanceEndpoints<"DateAlbums" | "DateAlbum">({ + addTagTypes: ["DateAlbums", "DateAlbum"], + endpoints: { + [Endpoints.fetchDateAlbums]: { + providesTags: ["DateAlbums"], + }, + [Endpoints.fetchDateAlbum]: { + providesTags: ["DateAlbum"], + }, + }, + }); + +export const { useFetchDateAlbumsQuery, useFetchDateAlbumQuery } = dateAlbumsApi; diff --git a/src/layouts/photos/TimestampPhotos.tsx b/src/layouts/photos/TimestampPhotos.tsx index 6910b5a4..0e5a71a4 100644 --- a/src/layouts/photos/TimestampPhotos.tsx +++ b/src/layouts/photos/TimestampPhotos.tsx @@ -2,33 +2,24 @@ import { IconPhoto as Photo } from "@tabler/icons-react"; import React, { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; -import { fetchAlbumDate, fetchAlbumDateList } from "../../actions/albumsActions"; +import { PigPhoto } from "../../actions/photosActions.types"; +import { useFetchDateAlbumQuery, useFetchDateAlbumsQuery } from "../../api_client/albums/date"; import { PhotoListView } from "../../components/photolist/PhotoListView"; -import type { PhotosState } from "../../reducers/photosReducer"; -import { PhotosetType } from "../../reducers/photosReducer"; -import { useAppDispatch, useAppSelector } from "../../store/store"; +import { getPhotosFlatFromGroupedByDate } from "../../util/util"; import type { PhotoGroup } from "./common"; export function TimestampPhotos() { - const { fetchedPhotosetType, photosFlat, photosGroupedByDate } = useAppSelector(state => state.photos as PhotosState); - const dispatch = useAppDispatch(); const { t } = useTranslation(); - const [group, setGroup] = useState({} as PhotoGroup); - useEffect(() => { - if (group.id && group.page) { - fetchAlbumDate(dispatch, { - album_date_id: group.id, - page: group.page, - photosetType: PhotosetType.TIMESTAMP, - }); - } - }, [dispatch, group.id, group.page]); + const [photosFlat, setPhotosFlat] = useState([]); + + const { data: photosGroupedByDate, isLoading } = useFetchDateAlbumsQuery(); useEffect(() => { - if (fetchedPhotosetType !== PhotosetType.TIMESTAMP) { - fetchAlbumDateList(dispatch, { photosetType: PhotosetType.TIMESTAMP }); - } - }, [dispatch]); + if (photosGroupedByDate) setPhotosFlat(getPhotosFlatFromGroupedByDate(photosGroupedByDate)); + }, [photosGroupedByDate]); + + const [group, setGroup] = useState({} as PhotoGroup); + useFetchDateAlbumQuery(group, { skip: !group.id }); const getAlbums = (visibleGroups: any) => { visibleGroups.reverse().forEach((photoGroup: any) => { @@ -36,6 +27,7 @@ export function TimestampPhotos() { if (visibleImages.filter((i: any) => i.isTemp).length > 0) { const firstTempObject = visibleImages.filter((i: any) => i.isTemp)[0]; const page = Math.ceil((parseInt(firstTempObject.id, 10) + 1) / 100); + setGroup({ id: photoGroup.id, page }); } }); @@ -44,9 +36,9 @@ export function TimestampPhotos() { return ( } - photoset={photosGroupedByDate} + photoset={photosGroupedByDate ?? []} idx2hash={photosFlat} updateGroups={getAlbums} selectable