Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ui): add prev/next buttons to modals #42

Open
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

gladyshcodes
Copy link
Contributor

@gladyshcodes gladyshcodes commented Feb 21, 2025

Issue: #38

What

This PR adds previous and next buttons to the Moderation and User modals, enabling users to navigate through a filtered list of items without closing the modal

Why

By allowing seamless navigation within the modal, we reduce the need for context switching, thereby enhancing the overall user experience

How

The items come from a TRPC endpoint and are stored in a shared React context that both the Tanstack table and the modals access. The new React context manages the active collection of items. The PrevNextButtons reusable component is added and provides callbacks for moving to the previous or next item. It also fetches additional items when the end of the collection is reached

UI

Before:
Screenshot 2025-02-21 at 03 00 42

After:
Pasted Graphic 2

@CLAassistant
Copy link

CLAassistant commented Feb 21, 2025

CLA assistant check
All committers have signed the CLA.

@@ -187,6 +196,7 @@ export async function RecordDetail({ clerkOrganizationId, id }: { clerkOrganizat
</Section>
</>
)}
{isModal && <RecordsCollectionNavigation currentRecordId={id} />}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Display buttons exclusively in modal view, not on a single page


export function RecordsCollectionNavigation({ currentRecordId }: RecordsCollectionNavigationProps) {
const { query } = useActiveCollection<InfiniteData<RecordsPage>>();
const { data, fetchNextPage, hasNextPage } = query ?? {};
Copy link
Contributor Author

@gladyshcodes gladyshcodes Feb 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Query functions such as fetchNextPage are not stored in react-query cache. The only way to retrieve them is to keep its reference in some kind of state (react context in this case)

router.replace(`/dashboard/records/${recordId}`);
};

const fetchNextItems = async () => {
Copy link
Contributor Author

@gladyshcodes gladyshcodes Feb 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a wrapper function above fetchNextPage

It's there to:

  1. Call react-query fetchNextPage
  2. Aggregate data
  3. Return aggregated data

The reason this function exist and it returns is because without it (when calling fetchNextPage directly) we could end up in race condition. It takes some ms for updated data to be retrieved by component via props (next page is fetched -> context updated -> context consumer rerendered -> new data received)

@@ -16,6 +16,7 @@ export function RouterSheet({ children, title }: { children: React.ReactNode; ti
e.preventDefault();
router.back();
}}
disableAnimation={true}
Copy link
Contributor Author

@gladyshcodes gladyshcodes Feb 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disable Sheet animation as using prev/next buttons will trigger it every time. If it's crucial to keep it, could disable it only for this type of navigation

Another idea here is not to change URL when prev/next is clicked. Since we already have that data into context, we could pull the data from there, without redirecting to a new page every time (and fetching data again). Although that's not how it's done in other parts of app currently

@gladyshcodes
Copy link
Contributor Author

@s3ththompson Could you review, please?

@s3ththompson
Copy link
Contributor

@gladyshcodes The following actions produce a crash:

  1. Click on a moderation from the table at /moderations
  2. In the modal, click on the username of the user who created the record
  3. Rendering the user modal crashes with TypeError: Cannot read properties of undefined (reading 'id')

Perhaps it would solve things to hide the navigation completely, until the query in the context is populated?

Copy link
Contributor

@s3ththompson s3ththompson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See error mentioned above

@s3ththompson
Copy link
Contributor

@gladyshcodes If you hide the navigation completely unless the query is populated, would it solve the race condition allowing you to remove the fetchNextItems wrapper and also allow you to remove the manual isModal prop?

gladyshcodes and others added 5 commits February 21, 2025 21:04
* feat: add client-side date components with timezone support

Co-Authored-By: [email protected] <[email protected]>

* add remaining spots for date components

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: [email protected] <[email protected]>
Co-authored-by: Seth Thompson <[email protected]>
@gladyshcodes gladyshcodes force-pushed the gladish/prevnext-buttons branch from 04dda65 to ea6c694 Compare February 21, 2025 20:05
@gladyshcodes
Copy link
Contributor Author

gladyshcodes commented Feb 21, 2025

The following actions produce a crash

Thank you for noticing that. I ran seed manually and fixed TypeError: Cannot read properties of undefined (reading 'id')

Missed that because I didn't do proper seed. And as a result., I didn't have User section in Moderation modal at all. I have this error when trying to run npm run dev:db:seed. If you have it too and it's not something specific to my env, I could try to fix it in my next pr.

Details Screenshot 2025-02-21 at 21 07 55

@gladyshcodes
Copy link
Contributor Author

gladyshcodes commented Feb 21, 2025

@gladyshcodes If you hide the navigation completely unless the query is populated, would it solve the race condition allowing you to remove the fetchNextItems wrapper and also allow you to remove the manual isModal prop?

The problem was not caused by empty Context when modal is opened but because when you opened User modal from Moderation one, Context contained moderation records and the modal expected Users. Race condition happens when you try to fetch more data within the modal (you reach last fetched item, and click next button that will trigger next page fetch). This new data isn't immediately available from modal component as it needs to travel back from data-table in contrast to using awaited function data

Regarding isModal props, it isn't related to refetching, we need to pass it from @sheet route to differentiate views and show buttons in modal only: #42 (comment)

@gladyshcodes
Copy link
Contributor Author

@s3ththompson Feedback addressed, CLA signed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants