feat: animate event list while reordering (#4611)

* fix: prevent waiting while invalidating

* feat: add auto animate

* static postion is added to animation container because auto animate adding
a inline style of position relative, which breaks arrow buttons
position.

* fix: wait until query get cancelled

* fix: set querydata correctly

Co-authored-by: Alex van Andel <me@alexvanandel.com>
pull/4633/head
Nafees Nazik 2022-09-20 21:25:37 +05:30 committed by GitHub
parent 48ee7a956c
commit 0a2de203a6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 17 additions and 20 deletions

View File

@ -1,3 +1,4 @@
import { useAutoAnimate } from "@formkit/auto-animate/react";
import { UserPlan } from "@prisma/client"; import { UserPlan } from "@prisma/client";
import Head from "next/head"; import Head from "next/head";
import Link from "next/link"; import Link from "next/link";
@ -82,6 +83,7 @@ const MemoizedItem = React.memo(Item);
export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeListProps): JSX.Element => { export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeListProps): JSX.Element => {
const { t } = useLocale(); const { t } = useLocale();
const router = useRouter(); const router = useRouter();
const [parent] = useAutoAnimate<HTMLUListElement>();
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
const [deleteDialogTypeId, setDeleteDialogTypeId] = useState(0); const [deleteDialogTypeId, setDeleteDialogTypeId] = useState(0);
const utils = trpc.useContext(); const utils = trpc.useContext();
@ -91,8 +93,8 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
await utils.cancelQuery(["viewer.eventTypes"]); await utils.cancelQuery(["viewer.eventTypes"]);
await utils.invalidateQueries(["viewer.eventTypes"]); await utils.invalidateQueries(["viewer.eventTypes"]);
}, },
onSettled: async () => { onSettled: () => {
await utils.invalidateQueries(["viewer.eventTypes"]); utils.invalidateQueries(["viewer.eventTypes"]);
}, },
}); });
@ -107,7 +109,7 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
}, },
}); });
function moveEventType(index: number, increment: 1 | -1) { async function moveEventType(index: number, increment: 1 | -1) {
const newList = [...types]; const newList = [...types];
const type = types[index]; const type = types[index];
@ -117,24 +119,19 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
newList[index + increment] = type; newList[index + increment] = type;
} }
utils.cancelQuery(["viewer.eventTypes"]); await utils.cancelQuery(["viewer.eventTypes"]);
utils.setQueryData(["viewer.eventTypes"], (data) => {
// tRPC is very strict with the return signature... const previousValue = utils.getQueryData(["viewer.eventTypes"]);
if (!data) if (previousValue) {
return { utils.setQueryData(["viewer.eventTypes"], {
eventTypeGroups: [], ...previousValue,
profiles: [], eventTypeGroups: [
viewer: { canAddEvents: true, plan: UserPlan.PRO }, ...previousValue.eventTypeGroups.slice(0, groupIndex),
};
return {
...data,
eventTypesGroups: [
...data.eventTypeGroups.slice(0, groupIndex),
{ ...group, eventTypes: newList }, { ...group, eventTypes: newList },
...data.eventTypeGroups.slice(groupIndex + 1), ...previousValue.eventTypeGroups.slice(groupIndex + 1),
], ],
}; });
}); }
mutation.mutate({ mutation.mutate({
ids: newList.map((type) => type.id), ids: newList.map((type) => type.id),
@ -201,7 +198,7 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
const lastItem = types[types.length - 1]; const lastItem = types[types.length - 1];
return ( return (
<div className="mb-16 flex overflow-hidden rounded-md border border-gray-200 bg-white"> <div className="mb-16 flex overflow-hidden rounded-md border border-gray-200 bg-white">
<ul className="w-full divide-y divide-neutral-200" data-testid="event-types"> <ul ref={parent} className="!static w-full divide-y divide-neutral-200" data-testid="event-types">
{types.map((type, index) => { {types.map((type, index) => {
const embedLink = `${group.profile.slug}/${type.slug}`; const embedLink = `${group.profile.slug}/${type.slug}`;
const calLink = `${CAL_URL}/${embedLink}`; const calLink = `${CAL_URL}/${embedLink}`;