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; updateEntity: (id: string, entity: CreateUpdateSqlTableDto) => Promise; deleteEntity: (id: string) => Promise; getEntity: (id: string) => SqlTable | undefined; refreshEntities: () => Promise; toggleEntityActiveStatus: (id: string) => Promise; // Generated endpoint operations generateCrudEndpoints: (entityId: string) => Promise; toggleEndpoint: (endpointId: string) => Promise; getEntityEndpoints: (entityId: string) => CrudEndpoint[]; deleteGeneratedEndpoint: (id: string) => Promise; } const EntityContext = createContext(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([]); const [generatedEndpoints, setGeneratedEndpoints] = useState([]); const [loading, setLoading] = useState(false); const [error, setError] = useState(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 ( {children} ); };