All files / hooks usePostRequest.ts

100% Statements 23/23
100% Branches 6/6
100% Functions 3/3
100% Lines 22/22

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98    1x                                                                                     1x       827032x 827032x 827032x               827032x 551354x 551354x   551354x 551354x               551350x 246376x     304974x 304974x   246380x 246378x   2x     551354x       827032x 551355x 551354x       827032x    
'use client';
 
import { useState, useEffect } from 'react';
import { type UsePostParams, type UsePostResult, type User } from '../types/index';
 
/**
 * Custom hook for making POST requests with type safety and state management
 *
 * @param {UsePostParams} params - Configuration object for the request
 * @param {string} params.path - API endpoint path (appended to base URL)
 * @param {object} [params.body] - Optional request body to be JSON stringified
 *
 * @returns {UsePostResult<T>} An object containing:
 *   - data: The response data (type T) or null
 *   - error: Error message string or null
 *   - loading: Boolean indicating request status
 *   - sendPostRequest: Function to manually trigger the request
 *
 * @example
 * // Basic usage with automatic execution
 * const { data, loading } = usePost({
 *   path: 'users',
 *   body: { name: 'John' }
 * });
 *
 * @example
 * // Manual execution with custom type
 * interface ApiResponse { id: string; status: string; }
 * const { sendPostRequest } = usePost<ApiResponse>({
 *   path: 'orders'
 * });
 *
 * @example
 * // Error handling
 * const { error } = usePost({
 *   path: 'login',
 *   body: credentials
 * });
 * useEffect(() => {
 *   if (error) showToast(error);
 * }, [error]);
 *
 * @see UsePostParams for parameter structure
 * @see UsePostResult for return type structure
 */
export const usePost = <T = User>({
	path,
	body,
}: UsePostParams): UsePostResult<T> => {
	const [data, setData] = useState<T | null>(null);
	const [error, setError] = useState<string | null>(null);
	const [loading, setLoading] = useState<boolean>(false);
 
	/**
 * Executes the POST request
 * - Manages loading state
 * - Handles success/error cases
 * - Returns void (results are handled via state updates)
 */
	const sendPostRequest = async () => {
		setLoading(true);
		setError(null);
 
		try {
			const res = await fetch(`${process.env?.["NEXT_PUBLIC_API_URL"]}/${path}`, {
				method: 'POST',
				headers: {
					'Content-Type': 'application/json',
				},
				body: JSON.stringify(body),
			});
 
			if (!res.ok) {
				throw new Error(`Fehler: ${res.status}`);
			}
 
			const responseData = await res.json();
			setData(responseData);
		} catch (error: unknown) {
			if (error instanceof Error) {
				setError(error.message);
			} else {
				setError('Unbekannter Fehler');
			}
		} finally {
			setLoading(false);
		}
	};
	// Automatically execute request when body is provided
	useEffect(() => {
		if (body) {
			sendPostRequest();
		}
	}, [body]);
 
	return { data, error, loading, sendPostRequest };
};