MAJOR REFACTOR (#494)
* move index to home folder, create state and context files and barrell folder * Sanity Check Commit: reducer added to home.tsx manual QA all working * WIP: promptBar * fix missing json parse on folders and prompts * split context and add promptbar context * add context to nested prompt componets and componetize Folder componet * remove log * Create buttons folder and componetize sidebar action button * tidy up prompt handlers * componetized sidebar * added back chatbar componet to left side sidebar * monster commit: Componetized the common code between chatbar and promptbar into new componet Sidebar and added context to both bars * add useFetch service * added prettier import sort to keep imports ordered and easier to indentify * added react query and useFetch to work with RQ * added apiService, errorService and reactQuery * add callback and tidy up error service * refactor chat and child componets to useContext * fix extra calls and bad calls to mel endpoint * minor import cleanup --------- Co-authored-by: jc.durbin <jc.durbin@ardanis.com>
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
import { useMemo, useReducer } from 'react';
|
||||
|
||||
// Extracts property names from initial state of reducer to allow typesafe dispatch objects
|
||||
export type FieldNames<T> = {
|
||||
[K in keyof T]: T[K] extends string ? K : K;
|
||||
}[keyof T];
|
||||
|
||||
// Returns the Action Type for the dispatch object to be used for typing in things like context
|
||||
export type ActionType<T> =
|
||||
| { type: 'reset' }
|
||||
| { type?: 'change'; field: FieldNames<T>; value: any };
|
||||
|
||||
// Returns a typed dispatch and state
|
||||
export const useCreateReducer = <T>({ initialState }: { initialState: T }) => {
|
||||
type Action =
|
||||
| { type: 'reset' }
|
||||
| { type?: 'change'; field: FieldNames<T>; value: any };
|
||||
|
||||
const reducer = (state: T, action: Action) => {
|
||||
if (!action.type) return { ...state, [action.field]: action.value };
|
||||
|
||||
if (action.type === 'reset') return initialState;
|
||||
|
||||
throw new Error();
|
||||
};
|
||||
|
||||
const [state, dispatch] = useReducer(reducer, initialState);
|
||||
|
||||
return useMemo(() => ({ state, dispatch }), [state, dispatch]);
|
||||
};
|
||||
@@ -0,0 +1,88 @@
|
||||
export type RequestModel = {
|
||||
params?: object;
|
||||
headers?: object;
|
||||
signal?: AbortSignal;
|
||||
};
|
||||
|
||||
export type RequestWithBodyModel = RequestModel & {
|
||||
body?: object | FormData;
|
||||
};
|
||||
|
||||
export const useFetch = () => {
|
||||
const handleFetch = async (
|
||||
url: string,
|
||||
request: any,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
const requestUrl = request?.params ? `${url}${request.params}` : url;
|
||||
|
||||
const requestBody = request?.body
|
||||
? request.body instanceof FormData
|
||||
? { ...request, body: request.body }
|
||||
: { ...request, body: JSON.stringify(request.body) }
|
||||
: request;
|
||||
|
||||
const headers = {
|
||||
...(request?.headers
|
||||
? request.headers
|
||||
: request?.body && request.body instanceof FormData
|
||||
? {}
|
||||
: { 'Content-type': 'application/json' }),
|
||||
};
|
||||
|
||||
return fetch(requestUrl, { ...requestBody, headers, signal })
|
||||
.then((response) => {
|
||||
if (!response.ok) throw response;
|
||||
|
||||
const contentType = response.headers.get('content-type');
|
||||
const contentDisposition = response.headers.get('content-disposition');
|
||||
|
||||
const headers = response.headers;
|
||||
|
||||
const result =
|
||||
contentType &&
|
||||
(contentType?.indexOf('application/json') !== -1 ||
|
||||
contentType?.indexOf('text/plain') !== -1)
|
||||
? response.json()
|
||||
: contentDisposition?.indexOf('attachment') !== -1
|
||||
? response.blob()
|
||||
: response;
|
||||
|
||||
return result;
|
||||
})
|
||||
.catch(async (err) => {
|
||||
const contentType = err.headers.get('content-type');
|
||||
|
||||
const errResult =
|
||||
contentType && contentType?.indexOf('application/problem+json') !== -1
|
||||
? await err.json()
|
||||
: err;
|
||||
|
||||
throw errResult;
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
get: async <T>(url: string, request?: RequestModel): Promise<T> => {
|
||||
return handleFetch(url, { ...request, method: 'get' });
|
||||
},
|
||||
post: async <T>(
|
||||
url: string,
|
||||
request?: RequestWithBodyModel,
|
||||
): Promise<T> => {
|
||||
return handleFetch(url, { ...request, method: 'post' });
|
||||
},
|
||||
put: async <T>(url: string, request?: RequestWithBodyModel): Promise<T> => {
|
||||
return handleFetch(url, { ...request, method: 'put' });
|
||||
},
|
||||
patch: async <T>(
|
||||
url: string,
|
||||
request?: RequestWithBodyModel,
|
||||
): Promise<T> => {
|
||||
return handleFetch(url, { ...request, method: 'patch' });
|
||||
},
|
||||
delete: async <T>(url: string, request?: RequestModel): Promise<T> => {
|
||||
return handleFetch(url, { ...request, method: 'delete' });
|
||||
},
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user