Skip to content

14.3 Tanstackin lisääminen pääsivulle | Antti/add-tanstack-library-index-page #62

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

Merged
merged 38 commits into from
Jan 22, 2025
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
32387c6
Add a new SVG image. Create a TSX file of it. Add the URL where the S…
anttiasmala Nov 6, 2024
00b7d9f
Add a logout query
anttiasmala Nov 6, 2024
64f64b6
Change spinner's color to be currentColor so its color can be changed…
anttiasmala Nov 6, 2024
a955433
Add useQuery. Add a handler for logouting inside index.tsx. Add condi…
anttiasmala Nov 6, 2024
63607c7
Remove a random Test toast
anttiasmala Nov 7, 2024
3a7c033
Change giftQuery -> fetchGiftsQuery. Add addGiftQuery. Add some condi…
anttiasmala Nov 7, 2024
21213f4
Remove a couple comments that were explaining about the sleep. Not ne…
anttiasmala Nov 7, 2024
03c2625
Add deleteGiftQuery for queries. Change closeModal's position in code…
anttiasmala Nov 7, 2024
b04dc77
Revert edits in DeleteModal.tsx. They are made into wrong branch atm
anttiasmala Nov 8, 2024
84bf6a7
Merge branch antti/add-tanstack-library-register-page into antti/add-…
anttiasmala Jan 16, 2025
27a3a42
Change the way how Gift creation request is sent
anttiasmala Jan 16, 2025
8ea3cb7
Add a QueryKey type for gift creation
anttiasmala Jan 16, 2025
3ddd6ef
Fix logout query. Disable User Modal closing if logout is in progress
anttiasmala Jan 16, 2025
d3d4884
Add a QueryKey type for logout
anttiasmala Jan 16, 2025
35f30b4
Change the URL where logging out redirects
anttiasmala Jan 17, 2025
29a742e
ESLint and fixes
anttiasmala Jan 17, 2025
a59ed04
Change onClick to not be async, should not be needed. Add handleError…
anttiasmala Jan 17, 2025
8f33262
Add Z-index 100 if account is logging out so no modal can be closed b…
anttiasmala Jan 17, 2025
f01b283
Add createGiftQuery.isPending to disabled attribute
anttiasmala Jan 17, 2025
becd2c3
Remove useShowErrorToast and error variable
anttiasmala Jan 18, 2025
93dc9af
Remove whole useGetGifts function. Remove unnecessary attributes from…
anttiasmala Jan 18, 2025
dee75a4
Merge branch antti/add-tanstack-library-register-page into antti/add-…
anttiasmala Jan 18, 2025
cf575be
Revert "Remove useShowErrorToast and error variable". Started to do i…
anttiasmala Jan 18, 2025
83b347c
Merge branch 'antti/add-tanstack-library-register-page' into antti/ad…
anttiasmala Jan 18, 2025
396693f
Change '...' loading indicator to spinning spinner
anttiasmala Jan 19, 2025
14db5bd
Refactor TODO.md and add TODO task
anttiasmala Jan 19, 2025
fd55e59
Add function errorWrapper into Button.tsx component
anttiasmala Jan 19, 2025
697af06
Add just created errorWrapper to the Button component. It will let us…
anttiasmala Jan 19, 2025
3e8cbd4
Create a new file utils/errorWrapper.ts. Move the errorWrapper from B…
anttiasmala Jan 20, 2025
92abaf9
Import errorWrapper and include it in code
anttiasmala Jan 20, 2025
2f3ed2d
Remove errorWrapper due to no usage right now
anttiasmala Jan 20, 2025
6693c10
Remove xml tag in Spinner.svg file
anttiasmala Jan 20, 2025
db8d061
Add Tanstack query cache clear functions when logging in and when log…
anttiasmala Jan 20, 2025
d8f9cac
Disable button when the gift is being added
anttiasmala Jan 20, 2025
481bc79
Update TODO.md
anttiasmala Jan 20, 2025
43cbaae
Move errorWrapper function from its own file to utilFunctions.ts
anttiasmala Jan 20, 2025
815a0f3
Delete errorWrapper file for now
anttiasmala Jan 20, 2025
7960798
Add catch for router.push
anttiasmala Jan 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,19 @@

# Enter-näppäimellä EditModalin ja DeleteModalin hyväksyminen

### </IDEOITA>
# Jos tulee virhe vaikka lahjoja hakiessa, ehkä jokin nappula olisi hyvä tehdä, jolla voisi mahdollisesti kokeilla hakea uudestaan lahjoja

TODO:
# Kun lisää uuden lahjan / kun lahjoja haetaan, järjestetään ne uusin -> vanhin. Myöhemmin voidaan lisätä käyttäjälle mahdollisuus valita miten lahjat haluaa järjestää (vaikka vanhin -> uusin, aakkosjärjestys, ymsyms)

Lisää /pages/login.tsx:n Kirjaudu sisään -nappulaan "select-none" jottei teksti tule maalatuksi jos silmää painaa muutaman kerran liian nopeasti
# Tässä toteutustapa:const sortedArrayNewestToOldest = gifts.sort((a, b) =>new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(),);

Jos tulee virhe vaikka lahjoja hakiessa, ehkä jokin nappula olisi hyvä tehdä, jolla voisi mahdollisesti kokeilla hakea uudestaan lahjoja
# Tanstackin requesteihin joku maksimiaika mitä odotetaan

Kun lisää uuden lahjan / kun lahjoja haetaan, järjestetään ne uusin -> vanhin. Myöhemmin voidaan lisätä käyttäjälle mahdollisuus valita miten lahjat haluaa järjestää (vaikka vanhin -> uusin, aakkosjärjestys, ymsyms)
### </IDEOITA>

TODO:

Tässä toteutustapa:
1. Tee https://github.com/samuliasmala/lahjalista/pull/62#discussion_r1921024704 omaan branchiin

const sortedArrayNewestToOldest = gifts.sort(
(a, b) =>
new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(),
);
2.1 Vaihda "Kirjaudu sisään"- ja "Luo käyttäjätunnus" -nappuloihin pyörivä spinner-indikaattori "..." sijaan
2.2 Lisää /pages/login.tsx:n Kirjaudu sisään -nappulaan "select-none" jottei teksti tule maalatuksi jos silmää painaa muutaman kerran liian nopeasti
16 changes: 10 additions & 6 deletions components/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import { ButtonHTMLAttributes } from 'react';
import { ComponentPropsWithoutRef } from 'react';
import { twMerge } from 'tailwind-merge';
import { errorWrapper } from '~/utils/utilFunctions';

export function Button({
children,
className,
...rest
}: ButtonHTMLAttributes<HTMLButtonElement>) {
type ButtonProps = ComponentPropsWithoutRef<'button'> & {
onClick?: (
event: React.MouseEvent<HTMLButtonElement, globalThis.MouseEvent>,
) => void | Promise<void>;
};

export function Button({ children, onClick, className, ...rest }: ButtonProps) {
return (
<button
onClick={onClick === undefined ? undefined : errorWrapper(onClick)}
className={twMerge(
`mt-6 w-full rounded-md border border-lines bg-primary p-2 text-lg font-medium text-white disabled:bg-gray-300 disabled:text-gray-500`,
className,
Expand Down
28 changes: 19 additions & 9 deletions pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,6 @@ export default function Home({
}),
});

const { isFetching, error } = useGetGifts();

useShowErrorToast(error);

const queryClient = useQueryClient();

async function handleSubmit(e: FormEvent<HTMLElement>) {
Expand Down Expand Up @@ -140,7 +136,11 @@ export default function Home({
<div className="text-red-500">Lahjansaaja on pakollinen</div>
)}
</div>
<Button type="submit" className="mt-8" disabled={isFetching}>
<Button
type="submit"
className="mt-8"
disabled={createGiftQuery.isPending}
>
Lisää
{createGiftQuery.isPending ? (
<span className="absolute p-1">
Expand Down Expand Up @@ -172,7 +172,12 @@ function GiftList() {

if (isFetching)
return (
<p className="loading-dots mt-4 text-lg font-bold">Noudetaan lahjoja</p>
<p className="mt-4 text-lg font-bold">
Noudetaan lahjoja{' '}
<span className="absolute ml-2 mt-1.5">
<SvgSpinner width={18} height={18} className="animate-spin" />
</span>
</p>
);

if (error) return <p className="mt-5 bg-red-500 text-lg">{error.message}</p>;
Expand Down Expand Up @@ -246,10 +251,15 @@ function UserDetailModal({
}) {
const router = useRouter();

const queryClient = useQueryClient();

const { isPending, error, mutateAsync } = useMutation({
mutationKey: QueryKeys.LOGOUT,
mutationFn: async () => await axios.post('/api/auth/logout'),
onSuccess: () => router.push('/logout'),
onSuccess: () => {
queryClient.clear();
router.push('/logout').catch((e) => console.error(e));
},
});

useShowErrorToast(error);
Expand All @@ -274,9 +284,9 @@ function UserDetailModal({
<div className="flex w-full justify-center">
<Button
className="mb-4 ml-3 mr-3 mt-4 flex h-8 w-full max-w-56 items-center justify-center rounded-md bg-primary text-sm font-medium"
onClick={() => {
onClick={async () => {
try {
void mutateAsync();
await mutateAsync();
} catch (e) {
handleErrorToast(handleError(e));
}
Expand Down
9 changes: 7 additions & 2 deletions pages/login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { Label } from '~/components/Label';
import { GetServerSidePropsContext } from 'next';
import { handleErrorToast } from '~/utils/handleToasts';
import { ErrorParagraph } from '~/components/ErrorParagraph';
import { useMutation } from '@tanstack/react-query';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { useShowErrorToast } from '~/hooks/useShowErrorToast';

export async function getServerSideProps(context: GetServerSidePropsContext) {
Expand Down Expand Up @@ -48,11 +48,16 @@ export default function Login() {

const router = useRouter();

const queryClient = useQueryClient();

const { mutateAsync, isPending, error } = useMutation({
mutationKey: QueryKeys.LOGIN,
mutationFn: async (loginCredentials: UserLoginDetails) =>
await axios.post('/api/auth/login', loginCredentials),
onSuccess: () => router.push('/'),
onSuccess: () => {
queryClient.clear();
Copy link
Collaborator Author

@anttiasmala anttiasmala Jan 20, 2025

Choose a reason for hiding this comment

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

Lisäsin tyhjennysfunktion sekä kirjautumiseen että uloskirjautumiseen. Onko ok, että on molemmissa? Eipä tuo pitäisi paljoa "tehoa" viedä :P

Kirjautuessa tuo tarkistus pitää ainakin olla, koska jos käyttäjä uloskirjautuu sessionin vanhentumisen takia, ei cachea tyhjennetä

Copy link
Owner

Choose a reason for hiding this comment

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

Kannattaa olla molemmissa.

router.push('/').catch((e) => console.error(e));
Copy link
Collaborator Author

@anttiasmala anttiasmala Jan 20, 2025

Choose a reason for hiding this comment

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

Puhun router.push('/').catch((e) => console.error(e)); rivistä

Tuli vain tämmöinen skenaario mieleen, että mitä jos tämä käyttäjän siirtäminen paikkaan X jostain syystä ei onnistu. En tiedä onko tämä mahdollista, en keksinyt tapaa kokeilla tätä 😅 Olisiko parempi laittaa käyttäjälle jokin Toasti, esim "Uudelleenohjaus epäonnistui" kuin tuo console.error 🤔

Mietin kanssa, että pitäisikö toisessa branchissa tehdä jokin nappula joka ilmestyy jos siirto toiselle sivulle jostain syystä epäonnistuu. Nappia painamalla redirectausta voitaisiin kokeilla uudelleen 😄

Copy link
Owner

Choose a reason for hiding this comment

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

En tiedä onko mahdollista, että siirto epäonnistuu. Jättäisin tämän näin, me ei olla D-alustassakaan potentiaalista virhetilannetta käsitelty. Aina voi F5 refreshata sivun jos meinaa jäädä jumiin :)

},
});

useShowErrorToast(error);
Expand Down
1 change: 0 additions & 1 deletion public/images/icons/spinner.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
35 changes: 35 additions & 0 deletions utils/utilFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,38 @@ export async function sleep(timeoutTimeInMs: number) {
export function randomBoolean() {
return !Math.round(Math.random());
}

/**
* A higher-order function that wraps a given function to handle both
* synchronous and asynchronous errors. Used to ensure that errors are
* caught in event handlers and other places where they would otherwise be
* uncaugh.
*
* @template A - The type of the arguments that the wrapped function accepts.
* @param {(...args: A) => Promise<void> | void} fn - The function to be
* wrapped. It can be either synchronous or asynchronous.
* @returns {(...args: A) => void} - A new function that wraps the original
* function and handles errors and returns a synchronous result.
*
* @example
* // Usage with an asynchronous function in click handler
* const handleClick = async () => { throw new Error('Asynchronous error'); };
*
* <Button onClick={errorWrapper(handleClick)}>Click me</Button>
*/
export function errorWrapper<A extends unknown[]>(
fn: (...args: A) => Promise<void> | void,
): (...args: A) => void {
return (...args: A) => {
try {
const p = fn(...args);
// Check if the function returns a promise to catch async errors
if (p instanceof Promise)
p.catch((error: unknown) => {
console.error('Error thrown asynchronously', error);
});
} catch (error) {
console.error('Error thrown synchronously', error);
}
};
}
Loading