mirror of
https://github.com/aaronpo97/the-biergarten-app.git
synced 2026-02-16 10:42:08 +00:00
refactor brewery post requests
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import sendUploadBreweryImagesRequest from '@/requests/images/brewery-image/sendUploadBreweryImageRequest';
|
||||
import sendCreateBreweryPostRequest from '@/requests/posts/brewery-post/sendCreateBreweryPostRequest';
|
||||
|
||||
import CreateBreweryPostSchema from '@/services/posts/brewery-post/schema/CreateBreweryPostSchema';
|
||||
import UploadImageValidationSchema from '@/services/schema/ImageSchema/UploadImageValidationSchema';
|
||||
import createErrorToast from '@/util/createErrorToast';
|
||||
@@ -27,6 +27,7 @@ import FormSegment from '../ui/forms/FormSegment';
|
||||
import FormTextArea from '../ui/forms/FormTextArea';
|
||||
import FormTextInput from '../ui/forms/FormTextInput';
|
||||
import Button from '../ui/forms/Button';
|
||||
import { sendCreateBreweryPostRequest } from '@/requests/posts/brewery-post';
|
||||
|
||||
const AddressAutofill = dynamic(
|
||||
// @ts-expect-error
|
||||
@@ -225,7 +226,7 @@ const CreateBreweryPostForm: FC<{
|
||||
if (!(data.images instanceof FileList)) {
|
||||
return;
|
||||
}
|
||||
const breweryPost = await sendCreateBreweryPostRequest(data);
|
||||
const breweryPost = await sendCreateBreweryPostRequest({ body: data });
|
||||
await sendUploadBreweryImagesRequest({ breweryPost, images: data.images });
|
||||
await router.push(`/breweries/${breweryPost.id}`);
|
||||
toast.remove(loadingToast);
|
||||
|
||||
106
src/components/EditBreweryPostForm.tsx
Normal file
106
src/components/EditBreweryPostForm.tsx
Normal file
@@ -0,0 +1,106 @@
|
||||
import EditBreweryPostValidationSchema from '@/services/posts/brewery-post/schema/EditBreweryPostValidationSchema';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { z } from 'zod';
|
||||
import { FC, useState } from 'react';
|
||||
import BreweryPostQueryResult from '@/services/posts/brewery-post/schema/BreweryPostQueryResult';
|
||||
import {
|
||||
sendDeleteBreweryPostRequest,
|
||||
sendEditBreweryPostRequest,
|
||||
} from '@/requests/posts/brewery-post';
|
||||
import FormError from './ui/forms/FormError';
|
||||
import FormInfo from './ui/forms/FormInfo';
|
||||
import FormLabel from './ui/forms/FormLabel';
|
||||
import FormSegment from './ui/forms/FormSegment';
|
||||
import FormTextArea from './ui/forms/FormTextArea';
|
||||
import FormTextInput from './ui/forms/FormTextInput';
|
||||
|
||||
interface EditBreweryPostFormProps {
|
||||
breweryPost: z.infer<typeof BreweryPostQueryResult>;
|
||||
}
|
||||
const EditBreweryPostForm: FC<EditBreweryPostFormProps> = ({ breweryPost }) => {
|
||||
const router = useRouter();
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
formState: { errors, isSubmitting },
|
||||
} = useForm<z.infer<typeof EditBreweryPostValidationSchema>>({
|
||||
resolver: zodResolver(EditBreweryPostValidationSchema),
|
||||
defaultValues: {
|
||||
name: breweryPost.name,
|
||||
description: breweryPost.description,
|
||||
id: breweryPost.id,
|
||||
dateEstablished: breweryPost.dateEstablished,
|
||||
},
|
||||
});
|
||||
|
||||
const [isDeleting, setIsDeleting] = useState(false);
|
||||
|
||||
const onSubmit = async (data: z.infer<typeof EditBreweryPostValidationSchema>) => {
|
||||
await sendEditBreweryPostRequest({ breweryPostId: breweryPost.id, body: data });
|
||||
await router.push(`/breweries/${breweryPost.id}`);
|
||||
};
|
||||
|
||||
const handleDelete = async () => {
|
||||
setIsDeleting(true);
|
||||
await sendDeleteBreweryPostRequest({ breweryPostId: breweryPost.id });
|
||||
await router.push('/breweries');
|
||||
};
|
||||
|
||||
return (
|
||||
<form className="form-control space-y-4" onSubmit={handleSubmit(onSubmit)}>
|
||||
<div className="w-full">
|
||||
<FormInfo>
|
||||
<FormLabel htmlFor="name">Name</FormLabel>
|
||||
<FormError>{errors.name?.message}</FormError>
|
||||
</FormInfo>
|
||||
<FormSegment>
|
||||
<FormTextInput
|
||||
id="name"
|
||||
type="text"
|
||||
placeholder="Name"
|
||||
formValidationSchema={register('name')}
|
||||
error={!!errors.name}
|
||||
disabled={isSubmitting || isDeleting}
|
||||
/>
|
||||
</FormSegment>
|
||||
|
||||
<FormInfo>
|
||||
<FormLabel htmlFor="description">Description</FormLabel>
|
||||
<FormError>{errors.description?.message}</FormError>
|
||||
</FormInfo>
|
||||
<FormSegment>
|
||||
<FormTextArea
|
||||
disabled={isSubmitting || isDeleting}
|
||||
placeholder="Ratione cumque quas quia aut impedit ea culpa facere. Ut in sit et quas reiciendis itaque."
|
||||
error={!!errors.description}
|
||||
formValidationSchema={register('description')}
|
||||
id="description"
|
||||
rows={8}
|
||||
/>
|
||||
</FormSegment>
|
||||
</div>
|
||||
|
||||
<div className="w-full space-y-3">
|
||||
<button
|
||||
disabled={isSubmitting || isDeleting}
|
||||
className="btn btn-primary w-full"
|
||||
type="submit"
|
||||
>
|
||||
{isSubmitting ? 'Saving...' : 'Save'}
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-primary w-full"
|
||||
type="button"
|
||||
disabled={isSubmitting || isDeleting}
|
||||
onClick={handleDelete}
|
||||
>
|
||||
Delete Brewery
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
export default EditBreweryPostForm;
|
||||
@@ -1,20 +1,11 @@
|
||||
import FormError from '@/components/ui/forms/FormError';
|
||||
import FormInfo from '@/components/ui/forms/FormInfo';
|
||||
import FormLabel from '@/components/ui/forms/FormLabel';
|
||||
import EditBreweryPostForm from '@/components/EditBreweryPostForm';
|
||||
import FormPageLayout from '@/components/ui/forms/FormPageLayout';
|
||||
import FormSegment from '@/components/ui/forms/FormSegment';
|
||||
import FormTextArea from '@/components/ui/forms/FormTextArea';
|
||||
import FormTextInput from '@/components/ui/forms/FormTextInput';
|
||||
import { getBreweryPostByIdService } from '@/services/posts/brewery-post';
|
||||
|
||||
import BreweryPostQueryResult from '@/services/posts/brewery-post/schema/BreweryPostQueryResult';
|
||||
import EditBreweryPostValidationSchema from '@/services/posts/brewery-post/schema/EditBreweryPostValidationSchema';
|
||||
import withPageAuthRequired from '@/util/withPageAuthRequired';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { NextPage } from 'next';
|
||||
import Head from 'next/head';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { BiBeer } from 'react-icons/bi';
|
||||
import { z } from 'zod';
|
||||
|
||||
@@ -25,49 +16,6 @@ interface EditPageProps {
|
||||
const EditBreweryPostPage: NextPage<EditPageProps> = ({ breweryPost }) => {
|
||||
const pageTitle = `Edit \u201c${breweryPost.name}\u201d`;
|
||||
|
||||
const router = useRouter();
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
formState: { errors, isSubmitting },
|
||||
} = useForm<z.infer<typeof EditBreweryPostValidationSchema>>({
|
||||
resolver: zodResolver(EditBreweryPostValidationSchema),
|
||||
defaultValues: {
|
||||
name: breweryPost.name,
|
||||
description: breweryPost.description,
|
||||
id: breweryPost.id,
|
||||
dateEstablished: breweryPost.dateEstablished,
|
||||
},
|
||||
});
|
||||
|
||||
const onSubmit = async (data: z.infer<typeof EditBreweryPostValidationSchema>) => {
|
||||
const response = await fetch(`/api/breweries/${breweryPost.id}`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Something went wrong');
|
||||
}
|
||||
|
||||
router.push(`/breweries/${breweryPost.id}`);
|
||||
};
|
||||
|
||||
const handleDelete = async () => {
|
||||
const response = await fetch(`/api/breweries/${breweryPost.id}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Something went wrong');
|
||||
}
|
||||
|
||||
router.push('/breweries');
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
@@ -81,59 +29,7 @@ const EditBreweryPostPage: NextPage<EditPageProps> = ({ breweryPost }) => {
|
||||
backLink={`/breweries/${breweryPost.id}`}
|
||||
backLinkText={`Back to "${breweryPost.name}"`}
|
||||
>
|
||||
<>
|
||||
<form className="form-control space-y-4" onSubmit={handleSubmit(onSubmit)}>
|
||||
<div className="w-full">
|
||||
<FormInfo>
|
||||
<FormLabel htmlFor="name">Name</FormLabel>
|
||||
<FormError>{errors.name?.message}</FormError>
|
||||
</FormInfo>
|
||||
<FormSegment>
|
||||
<FormTextInput
|
||||
id="name"
|
||||
type="text"
|
||||
placeholder="Name"
|
||||
formValidationSchema={register('name')}
|
||||
error={!!errors.name}
|
||||
disabled={isSubmitting}
|
||||
/>
|
||||
</FormSegment>
|
||||
|
||||
<FormInfo>
|
||||
<FormLabel htmlFor="description">Description</FormLabel>
|
||||
<FormError>{errors.description?.message}</FormError>
|
||||
</FormInfo>
|
||||
<FormSegment>
|
||||
<FormTextArea
|
||||
disabled={isSubmitting}
|
||||
placeholder="Ratione cumque quas quia aut impedit ea culpa facere. Ut in sit et quas reiciendis itaque."
|
||||
error={!!errors.description}
|
||||
formValidationSchema={register('description')}
|
||||
id="description"
|
||||
rows={8}
|
||||
/>
|
||||
</FormSegment>
|
||||
</div>
|
||||
|
||||
<div className="w-full space-y-3">
|
||||
<button
|
||||
disabled={isSubmitting}
|
||||
className="btn btn-primary w-full"
|
||||
type="submit"
|
||||
>
|
||||
{isSubmitting ? 'Saving...' : 'Save'}
|
||||
</button>
|
||||
|
||||
<button
|
||||
className="btn btn-primary w-full"
|
||||
type="button"
|
||||
onClick={handleDelete}
|
||||
>
|
||||
Delete Brewery
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</>
|
||||
<EditBreweryPostForm breweryPost={breweryPost} />
|
||||
</FormPageLayout>
|
||||
</>
|
||||
);
|
||||
|
||||
105
src/requests/posts/brewery-post/index.ts
Normal file
105
src/requests/posts/brewery-post/index.ts
Normal file
@@ -0,0 +1,105 @@
|
||||
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
|
||||
import BreweryPostQueryResult from '@/services/posts/brewery-post/schema/BreweryPostQueryResult';
|
||||
import {
|
||||
SendEditBreweryPostRequest,
|
||||
SendDeleteBreweryPostRequest,
|
||||
SendCreateBreweryPostRequest,
|
||||
} from './types';
|
||||
|
||||
/**
|
||||
* Sends an api request to edit a brewery post.
|
||||
*
|
||||
* @param args - The arguments for the request.
|
||||
* @param args.body - The body of the request.
|
||||
* @param args.body.name - The name of the brewery.
|
||||
* @param args.body.description - The description of the brewery.
|
||||
* @param args.body.dateEstablished - The date the brewery was established.
|
||||
* @param args.breweryPostId - The id of the brewery post to edit.
|
||||
*/
|
||||
export const sendEditBreweryPostRequest: SendEditBreweryPostRequest = async ({
|
||||
body,
|
||||
breweryPostId,
|
||||
}) => {
|
||||
const response = await fetch(`/api/breweries/${breweryPostId}`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Something went wrong');
|
||||
}
|
||||
|
||||
const json = await response.json();
|
||||
const parsed = APIResponseValidationSchema.safeParse(json);
|
||||
|
||||
if (!parsed.success) {
|
||||
throw new Error('Something went wrong');
|
||||
}
|
||||
|
||||
return parsed.data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sends an api request to delete a brewery post.
|
||||
*
|
||||
* @param args - The arguments for the request.
|
||||
* @param args.breweryPostId - The id of the brewery post to delete.
|
||||
*/
|
||||
export const sendDeleteBreweryPostRequest: SendDeleteBreweryPostRequest = async ({
|
||||
breweryPostId,
|
||||
}) => {
|
||||
const response = await fetch(`/api/breweries/${breweryPostId}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(response.statusText);
|
||||
}
|
||||
|
||||
const json = await response.json();
|
||||
const parsed = APIResponseValidationSchema.safeParse(json);
|
||||
|
||||
if (!parsed.success) {
|
||||
throw new Error(parsed.error.message);
|
||||
}
|
||||
|
||||
return parsed.data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sends an api request to create a brewery post.
|
||||
*
|
||||
* @param args - The arguments for the request.
|
||||
* @param args.body - The body of the request.
|
||||
* @param args.body.name - The name of the brewery.
|
||||
* @param args.body.description - The description of the brewery.
|
||||
* @param args.body.dateEstablished - The date the brewery was established.
|
||||
*/
|
||||
export const sendCreateBreweryPostRequest: SendCreateBreweryPostRequest = async ({
|
||||
body,
|
||||
}) => {
|
||||
const response = await fetch('/api/breweries/create', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(response.statusText);
|
||||
}
|
||||
|
||||
const json = await response.json();
|
||||
|
||||
const parsed = APIResponseValidationSchema.safeParse(json);
|
||||
if (!parsed.success) {
|
||||
throw new Error('API response parsing failed');
|
||||
}
|
||||
|
||||
const parsedPayload = BreweryPostQueryResult.safeParse(parsed.data.payload);
|
||||
if (!parsedPayload.success) {
|
||||
throw new Error('API response payload parsing failed');
|
||||
}
|
||||
|
||||
return parsedPayload.data;
|
||||
};
|
||||
@@ -1,34 +0,0 @@
|
||||
import BreweryPostQueryResult from '@/services/posts/brewery-post/schema/BreweryPostQueryResult';
|
||||
import CreateBreweryPostSchema from '@/services/posts/brewery-post/schema/CreateBreweryPostSchema';
|
||||
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
|
||||
import { z } from 'zod';
|
||||
|
||||
const sendCreateBreweryPostRequest = async (
|
||||
data: z.infer<typeof CreateBreweryPostSchema>,
|
||||
) => {
|
||||
const response = await fetch('/api/breweries/create', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(response.statusText);
|
||||
}
|
||||
|
||||
const json = await response.json();
|
||||
|
||||
const parsed = APIResponseValidationSchema.safeParse(json);
|
||||
if (!parsed.success) {
|
||||
throw new Error('API response parsing failed');
|
||||
}
|
||||
|
||||
const parsedPayload = BreweryPostQueryResult.safeParse(parsed.data.payload);
|
||||
if (!parsedPayload.success) {
|
||||
throw new Error('API response payload parsing failed');
|
||||
}
|
||||
|
||||
return parsedPayload.data;
|
||||
};
|
||||
|
||||
export default sendCreateBreweryPostRequest;
|
||||
23
src/requests/posts/brewery-post/types/index.ts
Normal file
23
src/requests/posts/brewery-post/types/index.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import BreweryPostQueryResult from '@/services/posts/brewery-post/schema/BreweryPostQueryResult';
|
||||
import CreateBreweryPostSchema from '@/services/posts/brewery-post/schema/CreateBreweryPostSchema';
|
||||
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
|
||||
import { z } from 'zod';
|
||||
|
||||
type APIResponse = z.infer<typeof APIResponseValidationSchema>;
|
||||
|
||||
export type SendDeleteBreweryPostRequest = (args: {
|
||||
breweryPostId: string;
|
||||
}) => Promise<APIResponse>;
|
||||
|
||||
export type SendEditBreweryPostRequest = (args: {
|
||||
body: {
|
||||
name: string;
|
||||
description: string;
|
||||
dateEstablished: Date;
|
||||
};
|
||||
breweryPostId: string;
|
||||
}) => Promise<APIResponse>;
|
||||
|
||||
export type SendCreateBreweryPostRequest = (args: {
|
||||
body: z.infer<typeof CreateBreweryPostSchema>;
|
||||
}) => Promise<z.infer<typeof BreweryPostQueryResult>>;
|
||||
Reference in New Issue
Block a user