sozsoft-platform/ui/src/contexts/EntityContext.tsx
2026-03-01 23:43:25 +03:00

212 lines
6.5 KiB
TypeScript

import React, { createContext, useContext, useState, useEffect } from "react";
import { developerKitService } from "@/services/developerKit.service";
import {
CrudEndpoint,
CreateUpdateSqlTableDto,
SqlTable,
} from "@/proxy/developerKit/models";
export const FIELD_TYPE_OPTIONS = [
{ label: "String", value: "string" },
{ label: "Number", value: "number" },
{ label: "Boolean", value: "boolean" },
{ label: "Date", value: "date" },
{ label: "Guid", value: "guid" },
{ label: "Decimal", value: "decimal" },
] as const;
export type EntityFieldType = (typeof FIELD_TYPE_OPTIONS)[number]["value"];
interface EntityContextType {
entities: SqlTable[];
generatedEndpoints: CrudEndpoint[];
loading: boolean;
error: string | null;
// Entity operations
addEntity: (entity: CreateUpdateSqlTableDto) => Promise<void>;
updateEntity: (id: string, entity: CreateUpdateSqlTableDto) => Promise<void>;
deleteEntity: (id: string) => Promise<void>;
getEntity: (id: string) => SqlTable | undefined;
refreshEntities: () => Promise<void>;
toggleEntityActiveStatus: (id: string) => Promise<void>;
// Generated endpoint operations
generateCrudEndpoints: (entityId: string) => Promise<void>;
toggleEndpoint: (endpointId: string) => Promise<void>;
getEntityEndpoints: (entityId: string) => CrudEndpoint[];
deleteGeneratedEndpoint: (id: string) => Promise<void>;
}
const EntityContext = createContext<EntityContextType | undefined>(undefined);
// eslint-disable-next-line react-refresh/only-export-components
export const useEntities = () => {
const context = useContext(EntityContext);
if (context === undefined) {
throw new Error("useEntities must be used within an EntityProvider");
}
return context;
};
export const EntityProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const [entities, setEntities] = useState<SqlTable[]>([]);
const [generatedEndpoints, setGeneratedEndpoints] = useState<CrudEndpoint[]>([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const refreshEntities = async () => {
try {
setLoading(true);
setError(null);
const [entitiesData, generatedEndpointsData] = await Promise.all([
developerKitService.getSqlTables(),
developerKitService.getGeneratedEndpoints(),
]);
setEntities(entitiesData.items || []);
setGeneratedEndpoints(generatedEndpointsData.items || []);
} catch (err) {
setError(err instanceof Error ? err.message : "Failed to fetch data");
console.error("Failed to fetch data:", err);
} finally {
setLoading(false);
}
};
useEffect(() => {
refreshEntities();
}, []);
const addEntity = async (entityData: CreateUpdateSqlTableDto) => {
try {
setLoading(true);
setError(null);
const newEntity = await developerKitService.createSqlTable(entityData);
setEntities((prev) => [...prev, newEntity]);
} catch (err) {
setError(err instanceof Error ? err.message : "Failed to create entity");
throw err;
} finally {
setLoading(false);
}
};
const updateEntity = async (id: string, entityData: CreateUpdateSqlTableDto) => {
try {
setLoading(true);
setError(null);
const updatedEntity = await developerKitService.updateSqlTable(id, entityData);
setEntities((prev) => prev.map((e) => (e.id === id ? updatedEntity : e)));
await refreshEntities();
} catch (err) {
setError(err instanceof Error ? err.message : "Failed to update entity");
throw err;
} finally {
setLoading(false);
}
};
const deleteEntity = async (id: string) => {
try {
setLoading(true);
setError(null);
await developerKitService.deleteSqlTable(id);
setEntities((prev) => prev.filter((e) => e.id !== id));
setGeneratedEndpoints((prev) => prev.filter((ep) => ep.entityId !== id));
} catch (err) {
setError(err instanceof Error ? err.message : "Failed to delete entity");
throw err;
} finally {
setLoading(false);
}
};
const toggleEntityActiveStatus = async (id: string) => {
try {
setLoading(true);
setError(null);
await developerKitService.toggleSqlTableActiveStatus(id);
await refreshEntities();
} catch (err) {
setError(err instanceof Error ? err.message : "Failed to toggle entity status");
throw err;
} finally {
setLoading(false);
}
};
const getEntity = (id: string): SqlTable | undefined =>
entities.find((e) => e.id === id);
const generateCrudEndpoints = async (entityId: string) => {
try {
setLoading(true);
setError(null);
const endpointsData = await developerKitService.generateCrudEndpoints(entityId);
setGeneratedEndpoints((prev) => [
...prev.filter((e) => e.entityId !== entityId),
...(endpointsData.items || []),
]);
await refreshEntities();
} catch (err) {
setError(err instanceof Error ? err.message : "Failed to generate CRUD endpoints");
throw err;
} finally {
setLoading(false);
}
};
const toggleEndpoint = async (endpointId: string) => {
try {
setLoading(true);
setError(null);
const updatedEndpoint = await developerKitService.toggleGeneratedEndpoint(endpointId);
setGeneratedEndpoints((prev) =>
prev.map((e) => (e.id === endpointId ? updatedEndpoint : e)),
);
} catch (err) {
setError(err instanceof Error ? err.message : "Failed to toggle endpoint");
throw err;
} finally {
setLoading(false);
}
};
const getEntityEndpoints = (entityId: string): CrudEndpoint[] =>
generatedEndpoints.filter((e) => e.entityId === entityId);
const deleteGeneratedEndpoint = async (id: string) => {
try {
setLoading(true);
setError(null);
await developerKitService.deleteGeneratedEndpoint(id);
setGeneratedEndpoints((prev) => prev.filter((e) => e.id !== id));
} catch (err) {
setError(err instanceof Error ? err.message : "Failed to delete generated endpoint");
throw err;
} finally {
setLoading(false);
}
};
return (
<EntityContext.Provider
value={{
entities,
generatedEndpoints,
loading,
error,
addEntity,
updateEntity,
deleteEntity,
getEntity,
refreshEntities,
toggleEntityActiveStatus,
generateCrudEndpoints,
toggleEndpoint,
getEntityEndpoints,
deleteGeneratedEndpoint,
}}
>
{children}
</EntityContext.Provider>
);
};