feat(form): add loading state and replace custom switch component
This commit introduces a loading state for form submissions and replaces the custom switch component with a third-party library for improved user experience and maintainability. - Adds `react-switch` as a dependency to replace the custom-built switch component, providing a more robust and feature-rich solution. - Implements a loading indicator on form submission buttons and in the confirmation modal by utilizing the `useIsMutating` hook from TanStack Query. This provides clear visual feedback to the user during asynchronous operations. - Creates a reusable `FormFooter` component to encapsulate the submit and cancel buttons, centralizing the form submission logic and loading state. - Refactors the company create/edit forms to use the new `FormFooter` and `react-switch` components. - Moves the `BreadcrumbItem` type to a shared types file for better code organization.
This commit is contained in:
@@ -19,6 +19,14 @@ export const API_ENDPOINTS = {
|
||||
UPDATE: (id: string) => `companies/${id}`,
|
||||
DELETE: (id: string) => `companies/${id}`,
|
||||
DETAILS: (id: string) => `companies/${id}`,
|
||||
CATEGORIES: {
|
||||
READ_ALL: "company-categories",
|
||||
CREATE: "company-categories",
|
||||
UPDATE: (id: string) => `company-categories/${id}`,
|
||||
DELETE: (id: string) => `company-categories/${id}`,
|
||||
DETAILS: (id: string) => `company-categories/${id}`,
|
||||
TOGGLE_PUBLISHED:(id:string) => `company-categories/${id}/publish`,
|
||||
},
|
||||
},
|
||||
TENDERS: {
|
||||
READ_ALL: "tenders",
|
||||
|
||||
@@ -4,6 +4,8 @@ import {
|
||||
ApiResponse,
|
||||
CompaniesListResponseSchema,
|
||||
TCompaniesResponse,
|
||||
TCompanyCategoryApiResponse,
|
||||
TCreateCompanyCategoryCredentials,
|
||||
} from "../types";
|
||||
|
||||
import { ICreateCompanyCredentials } from "../types";
|
||||
@@ -58,3 +60,85 @@ export const companiesService = {
|
||||
}
|
||||
},
|
||||
};
|
||||
export const companyCategoriesService = {
|
||||
getCategories: async (
|
||||
params?: Record<string, any>,
|
||||
): Promise<TCompanyCategoryApiResponse> => {
|
||||
try {
|
||||
const response = await api.get(
|
||||
API_ENDPOINTS.COMPANIES.CATEGORIES.READ_ALL,
|
||||
{
|
||||
params,
|
||||
},
|
||||
);
|
||||
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.error("ERROR Caught in company categories service: ", error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
getSingleCategory: async (id: string) => {
|
||||
try {
|
||||
return (await api.get(API_ENDPOINTS.COMPANIES.CATEGORIES.DETAILS(id)))
|
||||
.data;
|
||||
} catch (error) {
|
||||
console.error(
|
||||
"ERROR caught in Company categories service, Get single category",
|
||||
error,
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
createCategory: async (credentials: TCreateCompanyCategoryCredentials) => {
|
||||
try {
|
||||
const response = await api.post(
|
||||
API_ENDPOINTS.COMPANIES.CATEGORIES.CREATE,
|
||||
credentials,
|
||||
);
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.error("ERROR Caught in company categories service: ", error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
deleteCategory: async (id: string) => {
|
||||
try {
|
||||
return (await api.delete(API_ENDPOINTS.COMPANIES.CATEGORIES.DELETE(id)))
|
||||
.data;
|
||||
} catch (error) {
|
||||
console.error(
|
||||
"ERROR caught in Company Categories Services Delete:",
|
||||
error,
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
togglePublished: async (id: string) => {
|
||||
try {
|
||||
return (
|
||||
await api.patch(API_ENDPOINTS.COMPANIES.CATEGORIES.TOGGLE_PUBLISHED(id))
|
||||
).data;
|
||||
} catch (error) {
|
||||
console.error(
|
||||
"ERROR caught in Company Categories Services Toggle Published:",
|
||||
error,
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
updateCategories: async ({
|
||||
id,
|
||||
credentials,
|
||||
}: {
|
||||
id: string;
|
||||
credentials: TCreateCompanyCategoryCredentials;
|
||||
}) => {
|
||||
const response = await api.put(
|
||||
API_ENDPOINTS.COMPANIES.CATEGORIES.UPDATE(id),
|
||||
credentials,
|
||||
);
|
||||
return response.data;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import { z } from "zod";
|
||||
import { createApiResponseSchema } from "./Factory";
|
||||
export const companyCategorySchema = z.object({
|
||||
created_at: z.number(),
|
||||
description: z.string(),
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
published: z.boolean(),
|
||||
published_at: z.number(),
|
||||
thumbnail: z.string(),
|
||||
updated_at: z.number(),
|
||||
});
|
||||
export const createCompanyCategoryCredentials = z.object({
|
||||
name: z.string(),
|
||||
description: z.string(),
|
||||
thumbnail: z.string().optional(),
|
||||
});
|
||||
export const companyCategoriesResponseSchema = createApiResponseSchema(
|
||||
z.object({
|
||||
categories: z.array(companyCategorySchema),
|
||||
}),
|
||||
);
|
||||
export type TCompanyCategory = z.infer<typeof companyCategorySchema>;
|
||||
export type TCompanyCategoryApiResponse = z.infer<
|
||||
typeof companyCategoriesResponseSchema
|
||||
>;
|
||||
export type TCreateCompanyCategoryCredentials = z.infer<
|
||||
typeof createCompanyCategoryCredentials
|
||||
>;
|
||||
@@ -1,7 +1,8 @@
|
||||
export * from "./shared";
|
||||
export * from "./User";
|
||||
export * from "./Posts";
|
||||
export * from "./Factory";
|
||||
export * from "./TCompany";
|
||||
export * from "./CompanyCategories";
|
||||
export * from "./Customers";
|
||||
export * from "./Factory";
|
||||
export * from "./Posts";
|
||||
export * from "./Profile";
|
||||
export * from "./shared";
|
||||
export * from "./TCompany";
|
||||
export * from "./User";
|
||||
|
||||
Reference in New Issue
Block a user