Skip to content

Commit

Permalink
Add error boundaries
Browse files Browse the repository at this point in the history
  • Loading branch information
patelnets committed Feb 22, 2024
1 parent 2ef63ba commit d8f4183
Show file tree
Hide file tree
Showing 13 changed files with 184 additions and 17 deletions.
18 changes: 18 additions & 0 deletions app/error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
'use client';

export default function GlobalError({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
return (
<html>
<body>
<h2>{error.message}</h2>
<button onClick={() => reset()}>Try again</button>
</body>
</html>
);
}
6 changes: 6 additions & 0 deletions app/getQueryClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// app/getQueryClient.jsx
import { QueryClient } from '@tanstack/react-query';
import { cache } from 'react';

const getQueryClient = cache(() => new QueryClient());
export default getQueryClient;
5 changes: 5 additions & 0 deletions app/product/[slug]/edit/error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
'use client';

import { GenericErrorBoundary } from '@/components/error-boundaries/GenericErrorBoundary';

export default GenericErrorBoundary;
5 changes: 5 additions & 0 deletions app/product/[slug]/error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
'use client';

import { GenericErrorBoundary } from '@/components/error-boundaries/GenericErrorBoundary';

export default GenericErrorBoundary;
15 changes: 10 additions & 5 deletions app/product/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@ import { getProduct, STORES } from '@/fetch-queries/products/get-product';
import { Button } from '@nextui-org/button';
import Link from 'next/link';
import { Image } from '@nextui-org/image';
import React from 'react';
import { Divider } from '@nextui-org/divider';
import { getServerSession } from 'next-auth';
import { authOptions } from '@/libs/next-auth';
import { DeleteProduct } from '@/components/products/Delete';

export default async function Page({ params }: { params: { slug: string } }) {
const session = await getServerSession(authOptions);
const product = await getProduct({ id: params.slug });

console.log('product', product);

return (
<div className={'flex gap-2 flex-col justify-center items-center'}>
<h1 className={'text-2xl'}> {product.name} </h1>
Expand All @@ -35,9 +37,12 @@ export default async function Page({ params }: { params: { slug: string } }) {
))}
</ul>
{session && (
<Link className={'self-start'} href={`/product/${params.slug}/edit`}>
<Button color='primary'>Edit</Button>
</Link>
<div className={'flex gap-2'}>
<Link className={'self-start'} href={`/product/${params.slug}/edit`}>
<Button color='primary'>Edit</Button>
</Link>
<DeleteProduct id={product.id} />
</div>
)}
</div>
);
Expand Down
5 changes: 5 additions & 0 deletions app/products/add/error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
'use client';

import { GenericErrorBoundary } from '@/components/error-boundaries/GenericErrorBoundary';

export default GenericErrorBoundary;
5 changes: 5 additions & 0 deletions app/products/error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
'use client';

import { GenericErrorBoundary } from '@/components/error-boundaries/GenericErrorBoundary';

export default GenericErrorBoundary;
22 changes: 22 additions & 0 deletions components/error-boundaries/GenericErrorBoundary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
'use client';

import { Button } from '@nextui-org/react';

export const GenericErrorBoundary = ({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) => {
return (
<div
className={
'flex flex-col w-full justify-center items-center h-full gap-4'
}
>
<h2>{error.message}</h2>
<Button onClick={() => reset()}>Try again</Button>
</div>
);
};
37 changes: 37 additions & 0 deletions components/products/Delete.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
'use client';

import { Button } from '@nextui-org/react';
import { useMutation } from '@tanstack/react-query';
import { deleteProduct } from '@/fetch-queries/products/delete-product';
import { useSession } from 'next-auth/react';
import { useRouter } from 'next/navigation';

interface Props {
id: string;
}
export const DeleteProduct = ({ id }: Props) => {
const { data: session } = useSession();
const { mutate: mutateDelete, isPending } = useMutation({
mutationFn: deleteProduct,
throwOnError: true,
});

const router = useRouter();

const onHandleDelete = () => {
mutateDelete(
// @ts-ignore
{ id, token: session?.token.id_token },
{
onSuccess: () => router.push('/products'),
}
);
};

if (!session) return null;
return (
<Button isLoading={isPending} onClick={onHandleDelete}>
Delete Product
</Button>
);
};
39 changes: 32 additions & 7 deletions components/products/ImageUploads.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { postImages } from '@/fetch-queries/products/post-image';
import { useSession } from 'next-auth/react';
import { Button } from '@nextui-org/react';
import ArrowUpOnSquareIcon from '@heroicons/react/20/solid/ArrowUpOnSquareStackIcon';
import { useRouter } from 'next/navigation';

interface Props {
productId: string;
Expand All @@ -16,6 +17,7 @@ export const ImageUploads = ({ productId }: Props) => {
throwOnError: true,
});
const { data: session } = useSession();
const router = useRouter();

const [files, setFiles] = useState<File[]>([]);
const onDrop = useCallback((acceptedFiles: File[]) => {
Expand All @@ -34,12 +36,20 @@ export const ImageUploads = ({ productId }: Props) => {
formdata.append('files', file);
}

mutateUpload({
id: productId,
files: formdata,
// @ts-ignore
token: session?.token.id_token,
});
mutateUpload(
{
id: productId,
files: formdata,
// @ts-ignore
token: session?.token.id_token,
},
{
onSuccess: () => {
router.refresh();
setFiles([]);
},
}
);
};

return (
Expand All @@ -53,11 +63,26 @@ export const ImageUploads = ({ productId }: Props) => {
<input {...getInputProps()} />
{isDragActive ? (
<p>Drop the files here</p>
) : files.length > 0 ? (
<div>
<p>{files.length} file(s)</p>
<ul>
{files.map((file) => (
<li key={file.name}>{file.name}</li>
))}
</ul>
</div>
) : (
<ArrowUpOnSquareIcon width={25} />
)}
</div>
<Button onClick={onHandleUpload}>Upload images</Button>
<Button
isLoading={isPending}
isDisabled={files.length === 0}
onClick={onHandleUpload}
>
Upload images
</Button>
</div>
);
};
15 changes: 12 additions & 3 deletions components/products/ProductForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,12 @@ export const ProductForm = ({ initialValues }: { initialValues?: Inputs }) => {
token: session?.token.id_token,
data: { name: data.name, stores: data.stores, id: initialValues.id },
},
{ onSuccess: () => router.push('/products') }
{
onSuccess: () => {
router.refresh();
router.push('/products');
},
}
);
} else {
mutateAdd(
Expand All @@ -81,12 +86,16 @@ export const ProductForm = ({ initialValues }: { initialValues?: Inputs }) => {
token: session?.token.id_token,
data: { name: data.name, stores: data.stores },
},
{ onSuccess: () => router.push('/products') }
{
onSuccess: () => {
router.refresh();
router.push('/products');
},
}
);
}
};

console.log(initialValues);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<ControlledInput
Expand Down
25 changes: 25 additions & 0 deletions fetch-queries/products/delete-product.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
export async function deleteProduct({
id,
token,
}: {
id: string;
token: string;
}) {
const response = await fetch(
`${process.env.NEXT_PUBLIC_BACKEND_URL}/products/${id}`,
{
method: 'DELETE',
headers: {
Authorization: token,
},
}
);

if (!response.ok) {
const data: { message: string } = await response.json();
console.error(data);
throw new Error(data.message || 'An error occurred');
}
const data = await response.json();
return data;
}
4 changes: 2 additions & 2 deletions fetch-queries/products/get-product.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,9 @@ export async function getProduct({ id }: { id: string }) {
);

if (!response.ok) {
const data: { message: string } = await response.json();
const data: { detail: string } = await response.json();
console.error(data);
throw new Error(data.message || 'An error occurred');
throw new Error(data.detail || 'An error occurred');
}
const data: Response = await response.json();
return data;
Expand Down

0 comments on commit d8f4183

Please sign in to comment.