Move next js project to archive (#207)

This commit is contained in:
Aaron Po
2026-04-20 02:30:25 -04:00
committed by GitHub
parent 92ec16ce93
commit d47e3ed7f0
347 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,118 @@
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import CommentQueryResult from '@/services/schema/CommentSchema/CommentQueryResult';
import {
SendCreateBeerCommentRequest,
SendDeleteBeerPostCommentRequest,
SendEditBeerPostCommentRequest,
} from './types';
/**
* Sends an api request to edit a beer post comment.
*
* @param params - The parameters for the request.
* @param params.body - The body of the request.
* @param params.body.content - The content of the comment.
* @param params.body.rating - The rating of the beer.
* @param params.commentId - The id of the comment to edit.
* @param params.beerPostId - The id of the beer post the comment belongs to.
* @returns The JSON response from the server.
* @throws An error if the request fails or the response is invalid.
*/
export const editBeerPostCommentRequest: SendEditBeerPostCommentRequest = async ({
body,
commentId,
beerPostId,
}) => {
const response = await fetch(`/api/beers/${beerPostId}/comments/${commentId}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});
if (!response.ok) {
throw new Error('Failed to edit comment');
}
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 delete a beer post comment.
*
* @param params - The parameters for the request.
* @param params.commentId - The id of the comment to delete.
* @param params.beerPostId - The id of the beer post the comment belongs to.
* @returns The JSON response from the server.
* @throws An error if the request fails or the response is invalid.
*/
export const deleteBeerPostCommentRequest: SendDeleteBeerPostCommentRequest = async ({
commentId,
beerPostId,
}) => {
const response = await fetch(`/api/beers/${beerPostId}/comments/${commentId}`, {
method: 'DELETE',
});
if (!response.ok) {
throw new Error('Failed to delete comment');
}
const json = await response.json();
const parsed = APIResponseValidationSchema.safeParse(json);
if (!parsed.success) {
throw new Error(parsed.error.message);
}
return parsed.data;
};
/**
* Send an api request to create a comment on a beer post.
*
* @param params - The parameters for the request.
* @param params.beerPostId - The id of the beer post to create the comment on.
* @param params.body - The body of the request.
* @param params.body.content - The content of the comment.
* @param params.body.rating - The rating of the beer.
* @returns The created comment.
* @throws An error if the request fails or the response is invalid.
*/
export const sendCreateBeerCommentRequest: SendCreateBeerCommentRequest = async ({
beerPostId,
body: { content, rating },
}) => {
const response = await fetch(`/api/beers/${beerPostId}/comments`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ beerPostId, content, rating }),
});
if (!response.ok) {
throw new Error(response.statusText);
}
const data = await response.json();
const parsedResponse = APIResponseValidationSchema.safeParse(data);
if (!parsedResponse.success) {
throw new Error('Invalid API response');
}
const parsedPayload = CommentQueryResult.safeParse(parsedResponse.data.payload);
if (!parsedPayload.success) {
throw new Error('Invalid API response payload');
}
return parsedPayload.data;
};
export default sendCreateBeerCommentRequest;

View File

@@ -0,0 +1,19 @@
import CommentQueryResult from '@/services/schema/CommentSchema/CommentQueryResult';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import { z } from 'zod';
export type SendEditBeerPostCommentRequest = (args: {
body: { content: string; rating: number };
commentId: string;
beerPostId: string;
}) => Promise<z.infer<typeof APIResponseValidationSchema>>;
export type SendDeleteBeerPostCommentRequest = (args: {
commentId: string;
beerPostId: string;
}) => Promise<z.infer<typeof APIResponseValidationSchema>>;
export type SendCreateBeerCommentRequest = (args: {
beerPostId: string;
body: { content: string; rating: number };
}) => Promise<z.infer<typeof CommentQueryResult>>;

View File

@@ -0,0 +1,117 @@
import CommentQueryResult from '@/services/schema/CommentSchema/CommentQueryResult';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import {
SendCreateBeerStyleCommentRequest,
SendDeleteBeerStyleCommentRequest,
SendEditBeerStyleCommentRequest,
} from './types';
/**
* Sends an api request to edit a beer style comment.
*
* @param params - The parameters for the request.
* @param params.body - The body of the request.
* @param params.body.content - The content of the comment.
* @param params.body.rating - The rating of the beer.
* @param params.beerStyleId - The id of the beer style the comment belongs to.
* @param params.commentId - The id of the comment to edit.
* @returns The JSON response from the server.
* @throws An error if the request fails or the response is invalid.
*/
export const sendEditBeerStyleCommentRequest: SendEditBeerStyleCommentRequest = async ({
commentId,
body: { content, rating },
beerStyleId,
}) => {
const response = await fetch(`/api/beers/styles/${beerStyleId}/comments/${commentId}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ content, rating }),
});
if (!response.ok) {
throw new Error(response.statusText);
}
const json = await response.json();
const parsed = APIResponseValidationSchema.safeParse(json);
if (!parsed.success) {
throw new Error('Invalid API response');
}
return parsed.data;
};
/**
* Sends an api request to delete a beer style comment.
*
* @param params - The parameters for the request.
* @param params.beerStyleId - The id of the beer style the comment belongs to.
* @param params.commentId - The id of the comment to delete.
* @returns The json response from the server.
* @throws An error if the request fails or the response is invalid.
*/
export const sendDeleteBeerStyleCommentRequest: SendDeleteBeerStyleCommentRequest =
async ({ beerStyleId, commentId }) => {
const response = await fetch(
`/api/beers/styles/${beerStyleId}/comments/${commentId}`,
{
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('Invalid API response');
}
return parsed.data;
};
/**
* Sends an api request to create a beer style comment.
*
* @param params - The parameters for the request.
* @param params.body - The body of the request.
* @param params.body.content - The content of the comment.
* @param params.body.rating - The rating of the beer.
* @param params.beerStyleId - The id of the beer style the comment belongs to.
* @returns The created comment.
* @throws An error if the request fails or the response is invalid.
*/
export const sendCreateBeerStyleCommentRequest: SendCreateBeerStyleCommentRequest =
async ({ beerStyleId, body: { content, rating } }) => {
const response = await fetch(`/api/beers/styles/${beerStyleId}/comments`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ beerStyleId, content, rating }),
});
if (!response.ok) {
throw new Error(response.statusText);
}
const data = await response.json();
const parsedResponse = APIResponseValidationSchema.safeParse(data);
if (!parsedResponse.success) {
throw new Error('Invalid API response');
}
const parsedPayload = CommentQueryResult.safeParse(parsedResponse.data.payload);
if (!parsedPayload.success) {
throw new Error('Invalid API response payload');
}
return parsedPayload.data;
};

View File

@@ -0,0 +1,19 @@
import CommentQueryResult from '@/services/schema/CommentSchema/CommentQueryResult';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import { z } from 'zod';
export type SendEditBeerStyleCommentRequest = (args: {
body: { content: string; rating: number };
commentId: string;
beerStyleId: string;
}) => Promise<z.infer<typeof APIResponseValidationSchema>>;
export type SendDeleteBeerStyleCommentRequest = (args: {
commentId: string;
beerStyleId: string;
}) => Promise<z.infer<typeof APIResponseValidationSchema>>;
export type SendCreateBeerStyleCommentRequest = (args: {
beerStyleId: string;
body: { content: string; rating: number };
}) => Promise<z.infer<typeof CommentQueryResult>>;

View File

@@ -0,0 +1,109 @@
import CommentQueryResult from '@/services/schema/CommentSchema/CommentQueryResult';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import {
SendCreateBreweryPostCommentRequest,
SendDeleteBreweryPostCommentRequest,
SendEditBreweryPostCommentRequest,
} from './types';
/**
* Sends an api request to edit a brewery comment.
*
* @param params - The parameters for the request.
* @param params.breweryId - The id of the brewery the comment belongs to.
* @param params.commentId - The id of the comment to edit.
* @param params.body - The body of the request.
* @param params.body.content - The content of the comment.
* @param params.body.rating - The rating of the beer.
*/
export const sendEditBreweryPostCommentRequest: SendEditBreweryPostCommentRequest =
async ({ body: { content, rating }, breweryPostId, commentId }) => {
const response = await fetch(
`/api/breweries/${breweryPostId}/comments/${commentId}`,
{
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ content, rating }),
},
);
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 delete a brewery comment.
*
* @param params - The parameters for the request.
* @param params.breweryId - The id of the brewery the comment belongs to.
* @param params.commentId - The id of the comment to delete.
* @returns The JSON response from the server.
* @throws An error if the request fails or the response is invalid.
*/
export const sendDeleteBreweryPostCommentRequest: SendDeleteBreweryPostCommentRequest =
async ({ breweryPostId, commentId }) => {
const response = await fetch(
`/api/breweries/${breweryPostId}/comments/${commentId}`,
{
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 comment.
*
* @param params - The parameters for the request.
* @param params.body - The body of the request.
* @param params.body.content - The content of the comment.
* @param params.body.rating - The rating of the beer.
* @param params.breweryId - The id of the brewery the comment belongs to.
* @returns The created comment.
* @throws An error if the request fails or the response is invalid.
*/
export const sendCreateBreweryCommentRequest: SendCreateBreweryPostCommentRequest =
async ({ body: { content, rating }, breweryPostId }) => {
const response = await fetch(`/api/breweries/${breweryPostId}/comments`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ content, rating }),
});
if (!response.ok) {
throw new Error(response.statusText);
}
const data = await response.json();
const parsedResponse = APIResponseValidationSchema.safeParse(data);
if (!parsedResponse.success) {
throw new Error('Invalid API response');
}
const parsedPayload = CommentQueryResult.safeParse(parsedResponse.data.payload);
if (!parsedPayload.success) {
throw new Error('Invalid API response payload');
}
return parsedPayload.data;
};

View File

@@ -0,0 +1,39 @@
import CommentQueryResult from '@/services/schema/CommentSchema/CommentQueryResult';
import CreateCommentValidationSchema from '@/services/schema/CommentSchema/CreateCommentValidationSchema';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import { z } from 'zod';
const BreweryCommentValidationSchemaWithId = CreateCommentValidationSchema.extend({
breweryPostId: z.string(),
});
const sendCreateBreweryCommentRequest = async ({
content,
rating,
breweryPostId,
}: z.infer<typeof BreweryCommentValidationSchemaWithId>) => {
const response = await fetch(`/api/breweries/${breweryPostId}/comments`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ content, rating }),
});
if (!response.ok) {
throw new Error(response.statusText);
}
const data = await response.json();
const parsedResponse = APIResponseValidationSchema.safeParse(data);
if (!parsedResponse.success) {
throw new Error('Invalid API response');
}
const parsedPayload = CommentQueryResult.safeParse(parsedResponse.data.payload);
if (!parsedPayload.success) {
throw new Error('Invalid API response payload');
}
return parsedPayload.data;
};
export default sendCreateBreweryCommentRequest;

View File

@@ -0,0 +1,19 @@
import CommentQueryResult from '@/services/schema/CommentSchema/CommentQueryResult';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import { z } from 'zod';
export type SendEditBreweryPostCommentRequest = (args: {
body: { content: string; rating: number };
commentId: string;
breweryPostId: string;
}) => Promise<z.infer<typeof APIResponseValidationSchema>>;
export type SendDeleteBreweryPostCommentRequest = (args: {
commentId: string;
breweryPostId: string;
}) => Promise<z.infer<typeof APIResponseValidationSchema>>;
export type SendCreateBreweryPostCommentRequest = (args: {
breweryPostId: string;
body: { content: string; rating: number };
}) => Promise<z.infer<typeof CommentQueryResult>>;

View File

@@ -0,0 +1,51 @@
import BeerPostQueryResult from '@/services/posts/beer-post/schema/BeerPostQueryResult';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import { z } from 'zod';
interface SendUploadBeerImagesRequestArgs {
beerPost: z.infer<typeof BeerPostQueryResult>;
images: FileList;
}
/**
* Sends a POST request to the server to upload images for a beer post.
*
* @param beerPost The beer post object.
* @param images The list of images to upload.
* @returns A promise that resolves to the response from the server.
* @throws An error if the upload fails or the API response is invalid.
*/
const sendUploadBeerImagesRequest = async ({
beerPost,
images,
}: SendUploadBeerImagesRequestArgs) => {
const formData = new FormData();
[...images].forEach((file) => {
formData.append('images', file);
});
formData.append('caption', `Image of ${beerPost.name}`);
formData.append('alt', beerPost.name);
const uploadResponse = await fetch(`/api/beers/${beerPost.id}/images`, {
method: 'POST',
body: formData,
});
if (!uploadResponse.ok) {
throw new Error('Failed to upload images');
}
const json = await uploadResponse.json();
const parsed = APIResponseValidationSchema.safeParse(json);
if (!parsed.success) {
throw new Error('Invalid API response');
}
return parsed.data;
};
export default sendUploadBeerImagesRequest;

View File

@@ -0,0 +1,34 @@
import BreweryPostQueryResult from '@/services/posts/brewery-post/schema/BreweryPostQueryResult';
import { z } from 'zod';
interface SendUploadBeerImagesRequestArgs {
breweryPost: z.infer<typeof BreweryPostQueryResult>;
images: FileList;
}
const sendUploadBreweryImagesRequest = async ({
breweryPost,
images,
}: SendUploadBeerImagesRequestArgs) => {
const formData = new FormData();
[...images].forEach((file) => {
formData.append('images', file);
});
formData.append('caption', `Image of ${breweryPost.name}`);
formData.append('alt', breweryPost.name);
const uploadResponse = await fetch(`/api/breweries/${breweryPost.id}/images`, {
method: 'POST',
body: formData,
});
if (!uploadResponse.ok) {
throw new Error('Failed to upload images');
}
return uploadResponse.json();
};
export default sendUploadBreweryImagesRequest;

View File

@@ -0,0 +1,31 @@
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
/**
* Sends a POST request to the server to like or unlike a beer post.
*
* @param beerPostId The ID of the beer post to like or unlike.
* @returns An object containing a success boolean and a message string.
* @throws An error if the response is not ok or if the API response is invalid.
*/
const sendBeerPostLikeRequest = async (beerPostId: string) => {
const response = await fetch(`/api/beers/${beerPostId}/like`, {
method: 'POST',
});
if (!response.ok) {
throw new Error('Something went wrong.');
}
const data = await response.json();
const parsed = APIResponseValidationSchema.safeParse(data);
if (!parsed.success) {
throw new Error('Invalid API response.');
}
const { success, message } = parsed.data;
return { success, message };
};
export default sendBeerPostLikeRequest;

View File

@@ -0,0 +1,31 @@
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
/**
* Sends a POST request to the server to like or unlike a beer post.
*
* @param beerStyleId The ID of the beer post to like or unlike.
* @returns An object containing a success boolean and a message string.
* @throws An error if the response is not ok or if the API response is invalid.
*/
const sendBeerStyleLikeRequest = async (beerStyleId: string) => {
const response = await fetch(`/api/beers/styles/${beerStyleId}/like`, {
method: 'POST',
});
if (!response.ok) {
throw new Error('Something went wrong.');
}
const data = await response.json();
const parsed = APIResponseValidationSchema.safeParse(data);
if (!parsed.success) {
throw new Error('Invalid API response.');
}
const { success, message } = parsed.data;
return { success, message };
};
export default sendBeerStyleLikeRequest;

View File

@@ -0,0 +1,18 @@
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
const sendBreweryPostLikeRequest = async (breweryPostId: string) => {
const response = await fetch(`/api/breweries/${breweryPostId}/like`, {
method: 'POST',
});
const json = await response.json();
const parsed = APIResponseValidationSchema.safeParse(json);
if (!parsed.success) {
throw new Error('Invalid API response.');
}
return parsed.data;
};
export default sendBreweryPostLikeRequest;

View File

@@ -0,0 +1,134 @@
import BeerPostQueryResult from '@/services/posts/beer-post/schema/BeerPostQueryResult';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import {
SendCreateBeerPostRequest,
SendDeleteBeerPostRequest,
SendEditBeerPostRequest,
} from './types';
/**
* Sends a POST request to create a new beer post.
*
* @example
* const beerPost = await sendCreateBeerPostRequest({
* body: {
* abv: 5.5,
* description: 'A golden delight with a touch of citrus.',
* ibu: 30,
* name: 'Yerb Sunshine Ale',
* },
* styleId: 'clqmteqxc000008jphoy31wqw',
* breweryId: 'clqmtexfb000108jp3nsg26c6',
* });
*
* @param data - The data to send in the request.
* @param data.body - The body of the request.
* @param data.body.abv - The ABV of the beer.
* @param data.body.description - The description of the beer.
* @param data.body.ibu - The IBU of the beer.
* @param data.body.name - The name of the beer.
* @param data.styleId - The ID of the style of the beer.
* @param data.breweryId - The ID of the brewery of the beer.
* @returns The created beer post.
* @throws An error if the request fails or the response is invalid.
*/
export const sendCreateBeerPostRequest: SendCreateBeerPostRequest = async ({
body: { abv, description, ibu, name },
styleId,
breweryId,
}) => {
const response = await fetch('/api/beers/create', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ abv, description, ibu, name, styleId, breweryId }),
});
if (!response.ok) {
throw new Error(response.statusText);
}
const json = await response.json();
const parsed = APIResponseValidationSchema.safeParse(json);
if (!parsed.success) {
throw new Error('Invalid API response');
}
const { payload, success, message } = parsed.data;
if (!success) {
throw new Error(message);
}
const parsedPayload = BeerPostQueryResult.safeParse(payload);
if (!parsedPayload.success) {
throw new Error('Invalid API response payload');
}
return parsedPayload.data;
};
/**
* Sends a DELETE request to delete a beer post.
*
* @example
* const response = await sendDeleteBeerPostRequest({
* beerPostId: 'clqmtexfb000108jp3nsg26c6',
* });
*
* @param args - The arguments to send in the request.
* @param args.beerPostId - The ID of the beer post to delete.
* @returns The response from the server.
* @throws An error if the request fails or the response is invalid.
*/
export const sendDeleteBeerPostRequest: SendDeleteBeerPostRequest = async ({
beerPostId,
}) => {
const response = await fetch(`/api/beers/${beerPostId}`, { 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('Could not successfully parse the response.');
}
return parsed.data;
};
/**
* Sends a PUT request to edit a beer post.
*
* @example
* const response = await sendEditBeerPostRequest({
* beerPostId: 'clqmtexfb000108jp3nsg26c6',
* body: {
* abv: 5.5,
* description: 'A golden delight with a touch of citrus.',
* ibu: 30,
* name: 'Yerb Sunshine Ale',
* },
* });
*
* @param args - The arguments to send in the request.
* @param args.beerPostId - The ID of the beer post to edit.
* @param args.body - The body of the request.
* @param args.body.abv - The ABV of the beer.
* @param args.body.description - The description of the beer.
* @param args.body.ibu - The IBU of the beer.
* @param args.body.name - The name of the beer.
* @returns The response from the server.
* @throws An error if the request fails or the response is invalid.
*/
export const sendEditBeerPostRequest: SendEditBeerPostRequest = async ({
beerPostId,
body: { abv, description, ibu, name },
}) => {
const response = await fetch(`/api/beers/${beerPostId}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ abv, description, ibu, name }),
});
if (!response.ok) {
throw new Error(response.statusText);
}
const json = await response.json();
const parsed = APIResponseValidationSchema.safeParse(json);
if (!parsed.success) {
throw new Error('Invalid API response');
}
return parsed.data;
};

View File

@@ -0,0 +1,31 @@
import BeerPostQueryResult from '@/services/posts/beer-post/schema/BeerPostQueryResult';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import { z } from 'zod';
type BeerPostQueryResultT = z.infer<typeof BeerPostQueryResult>;
type APIResponse = z.infer<typeof APIResponseValidationSchema>;
export type SendCreateBeerPostRequest = (data: {
body: {
abv: number;
description: string;
ibu: number;
name: string;
};
styleId: string;
breweryId: string;
}) => Promise<BeerPostQueryResultT>;
export type SendDeleteBeerPostRequest = (args: {
beerPostId: string;
}) => Promise<APIResponse>;
export type SendEditBeerPostRequest = (args: {
beerPostId: string;
body: {
abv: number;
description: string;
ibu: number;
name: string;
};
}) => Promise<APIResponse>;

View 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;
};

View 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>>;

View File

@@ -0,0 +1,169 @@
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import { BasicUserInfoSchema } from '@/config/auth/types';
import GetUserSchema from '@/services/users/auth/schema/GetUserSchema';
import type {
SendEditUserRequest,
SendForgotPasswordRequest,
SendLoginUserRequest,
SendRegisterUserRequest,
SendUpdatePasswordRequest,
SendUserFollowRequest,
ValidateEmailRequest,
} from './types';
import { z } from 'zod';
export const sendEditUserRequest: SendEditUserRequest = async ({ user, data }) => {
const response = await fetch(`/api/users/${user!.id}`, {
body: JSON.stringify(data),
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
});
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 validation failed.');
}
return parsed.data;
};
export const sendForgotPasswordRequest: SendForgotPasswordRequest = async ({ email }) => {
const response = await fetch('/api/users/forgot-password', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email }),
});
if (!response.ok) {
throw new Error("Something went wrong and we couldn't send the reset link.");
}
const json = await response.json();
const parsed = APIResponseValidationSchema.safeParse(json);
if (!parsed.success) {
throw new Error(parsed.error.message);
}
return parsed.data;
};
export const sendLoginUserRequest: SendLoginUserRequest = async ({
username,
password,
}) => {
const response = await fetch('/api/users/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
username,
password,
}),
});
const json: unknown = await response.json();
const parsed = APIResponseValidationSchema.safeParse(json);
if (!parsed.success) {
throw new Error('API response validation failed');
}
if (!parsed.data.success) {
throw new Error(parsed.data.message);
}
const parsedPayload = BasicUserInfoSchema.safeParse(parsed.data.payload);
if (!parsedPayload.success) {
throw new Error('API response payload validation failed');
}
return parsedPayload.data;
};
export const sendRegisterUserRequest: SendRegisterUserRequest = async (data) => {
const response = await fetch('/api/users/register', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
const json = await response.json();
const parsed = APIResponseValidationSchema.safeParse(json);
if (!parsed.success) {
throw new Error('API response validation failed.');
}
if (!parsed.data.success) {
throw new Error(parsed.data.message);
}
const parsedPayload = GetUserSchema.safeParse(parsed.data.payload);
if (!parsedPayload.success) {
throw new Error('API response payload validation failed.');
}
return parsedPayload.data;
};
export const sendUpdatePasswordRequest: SendUpdatePasswordRequest = async (data) => {
const response = await fetch('/api/users/edit-password', {
body: JSON.stringify(data),
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
});
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 validation failed.');
}
return parsed.data;
};
export const sendUserFollowRequest: SendUserFollowRequest = async ({ userId }) => {
const response = await fetch(`/api/users/${userId}/follow-user`, { method: 'POST' });
const json = await response.json();
const parsed = APIResponseValidationSchema.safeParse(json);
if (!parsed.success) {
throw new Error('Invalid API response.');
}
return parsed.data;
};
export const validateEmailRequest: ValidateEmailRequest = async ({ email }) => {
const response = await fetch(`/api/users/check-email?email=${email}`);
const json = await response.json();
const parsed = APIResponseValidationSchema.safeParse(json);
if (!parsed.success) {
return false;
}
const parsedPayload = z
.object({ emailIsTaken: z.boolean() })
.safeParse(parsed.data.payload);
if (!parsedPayload.success) {
return false;
}
return !parsedPayload.data.emailIsTaken;
};

View File

@@ -0,0 +1,41 @@
import { BasicUserInfoSchema } from '@/config/auth/types';
import {
CreateUserValidationSchema,
UpdatePasswordSchema,
} from '@/services/users/auth/schema/CreateUserValidationSchemas';
import GetUserSchema from '@/services/users/auth/schema/GetUserSchema';
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import { z } from 'zod';
export type SendEditUserRequest = (args: {
user: z.infer<typeof GetUserSchema>;
data: {
username: string;
email: string;
firstName: string;
lastName: string;
};
}) => Promise<z.infer<typeof APIResponseValidationSchema>>;
export type SendForgotPasswordRequest = (args: {
email: string;
}) => Promise<z.infer<typeof APIResponseValidationSchema>>;
export type SendLoginUserRequest = (args: {
username: string;
password: string;
}) => Promise<z.infer<typeof BasicUserInfoSchema>>;
export type SendRegisterUserRequest = (
args: z.infer<typeof CreateUserValidationSchema>,
) => Promise<z.infer<typeof GetUserSchema>>;
export type SendUpdatePasswordRequest = (
args: z.infer<typeof UpdatePasswordSchema>,
) => Promise<z.infer<typeof APIResponseValidationSchema>>;
export type SendUserFollowRequest = (args: {
userId: string;
}) => Promise<z.infer<typeof APIResponseValidationSchema>>;
export type ValidateEmailRequest = (args: { email: string }) => Promise<boolean>;

View File

@@ -0,0 +1,27 @@
interface UpdateProfileRequestParams {
file: File;
userId: string;
}
const sendUpdateUserAvatarRequest = async ({
file,
userId,
}: UpdateProfileRequestParams) => {
const formData = new FormData();
formData.append('image', file);
const response = await fetch(`/api/users/${userId}/profile/update-avatar`, {
method: 'PUT',
body: formData,
});
if (!response.ok) {
throw new Error('Failed to update profile.');
}
const json = await response.json();
return json;
};
export default sendUpdateUserAvatarRequest;

View File

@@ -0,0 +1,28 @@
import UpdateProfileSchema from '@/services/users/auth/schema/UpdateProfileSchema';
import { z } from 'zod';
interface UpdateProfileRequestParams {
userId: string;
bio: z.infer<typeof UpdateProfileSchema>['bio'];
}
const sendUpdateUserProfileRequest = async ({
bio,
userId,
}: UpdateProfileRequestParams) => {
const response = await fetch(`/api/users/${userId}/profile/update-profile`, {
method: 'PUT',
body: JSON.stringify({ bio }),
headers: { 'Content-Type': 'application/json' },
});
if (!response.ok) {
throw new Error('Failed to update profile.');
}
const json = await response.json();
return json;
};
export default sendUpdateUserProfileRequest;

View File

@@ -0,0 +1,25 @@
import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema';
import { z } from 'zod';
const validateUsernameRequest = async (username: string) => {
const response = await fetch(`/api/users/check-username?username=${username}`);
const json = await response.json();
const parsed = APIResponseValidationSchema.safeParse(json);
if (!parsed.success) {
return false;
}
const parsedPayload = z
.object({ usernameIsTaken: z.boolean() })
.safeParse(parsed.data.payload);
if (!parsedPayload.success) {
return false;
}
return !parsedPayload.data.usernameIsTaken;
};
export default validateUsernameRequest;