import React, { useState } from 'react' import { useNavigate } from 'react-router-dom' import { useEntities } from '../../contexts/EntityContext' import { FaBolt, FaSearch, FaFilter, FaCalendarAlt, FaDatabase, FaPlay, FaCheckCircle, FaRegBell, FaRegClock, FaRegFileAlt, FaDownload, FaEye, FaSync, FaTrashAlt, FaPlus, } from 'react-icons/fa' import { ROUTES_ENUM } from '@/routes/route.constant' import { useLocalization } from '@/utils/hooks/useLocalization' const MigrationManager: React.FC = () => { const navigate = useNavigate() const { entities, migrations, generateMigration, applyMigration, deleteMigration, generateCrudEndpoints, loading, error, } = useEntities() const [searchTerm, setSearchTerm] = useState('') const [filterStatus, setFilterStatus] = useState<'all' | 'pending' | 'applied' | 'failed'>('all') const [selectedMigration, setSelectedMigration] = useState(null) const [applyingMigration, setApplyingMigration] = useState(null) const [deletingMigration, setDeletingMigration] = useState(null) const [generatingEndpoints, setGeneratingEndpoints] = useState(null) const { translate } = useLocalization() const filteredMigrations = migrations.filter((migration) => { const matchesSearch = migration.entityName.toLowerCase().includes(searchTerm.toLowerCase()) || (migration.fileName && migration.fileName.toLowerCase().includes(searchTerm.toLowerCase())) const matchesStatusFilter = filterStatus === 'all' || migration.status === filterStatus return matchesSearch && matchesStatusFilter }) const handleGenerateMigration = async (entityId: string) => { try { await generateMigration(entityId) } catch (error) { console.error('Failed to generate migration:', error) } } const handleApplyMigration = async (migrationId: string) => { try { setApplyingMigration(migrationId) await applyMigration(migrationId) } catch (error) { console.error('Failed to apply migration:', error) } finally { setApplyingMigration(null) } } const handleDeleteMigration = async (migrationId: string) => { try { setDeletingMigration(migrationId) await deleteMigration(migrationId) } catch (error) { console.error('Failed to delete migration:', error) } finally { setDeletingMigration(null) } } const handleDownloadMigration = (migration: (typeof migrations)[0]) => { if (!migration.sqlScript) return const blob = new Blob([migration.sqlScript], { type: 'text/sql' }) const url = URL.createObjectURL(blob) const a = document.createElement('a') a.href = url a.download = migration.fileName || `migration_${migration.entityName}_${new Date().toISOString().split('T')[0]}.sql` document.body.appendChild(a) a.click() document.body.removeChild(a) URL.revokeObjectURL(url) } const handleGenerateCrudEndpoints = async (entityId: string) => { try { setGeneratingEndpoints(entityId) await generateCrudEndpoints(entityId) // Navigate to API Endpoints page after successful generation navigate(ROUTES_ENUM.protected.saas.developerKit.migrations) } catch (error) { console.error('Failed to generate CRUD endpoints:', error) } finally { setGeneratingEndpoints(null) } } const getStatusColor = (status: string) => { switch (status) { case 'pending': return 'bg-yellow-100 text-yellow-800 border-yellow-200' case 'applied': return 'bg-green-100 text-green-800 border-green-200' case 'failed': return 'bg-red-100 text-red-800 border-red-200' default: return 'bg-slate-100 text-slate-800 border-slate-200' } } const getStatusIcon = (status: string) => { switch (status) { case 'pending': return FaRegClock case 'applied': return FaCheckCircle case 'failed': return FaRegBell default: return FaRegClock } } const stats = { total: migrations.length, pending: migrations.filter((m) => m.status === 'pending').length, applied: migrations.filter((m) => m.status === 'applied').length, failed: migrations.filter((m) => m.status === 'failed').length, } const entitiesNeedingMigration = entities.filter( (e) => e.migrationStatus === 'pending' || !e.migrationId, ) return (
{/* Error Message */} {error && (
Error

{error}

)}

{translate('::App.DeveloperKit.Migration.Title')}

{translate('::App.DeveloperKit.Migration.Description')}

{translate('::App.DeveloperKit.Migration.SchemaManagement')}
{loading && (
{translate('::App.DeveloperKit.Migration.Loading')}
)}
{/* Stats Cards */}

{translate('::App.DeveloperKit.Migration.Total')}

{stats.total}

{translate('::App.DeveloperKit.Migration.Pending')}

{stats.pending}

{translate('::App.DeveloperKit.Migration.Applied')}

{stats.applied}

{translate('::App.DeveloperKit.Migration.Failed')}

{stats.failed}

{/* Entities Needing Migration */} {entitiesNeedingMigration.length > 0 && (

{translate('::App.DeveloperKit.Migration.EntitiesRequireMigration')}

{translate('::App.DeveloperKit.Migration.EntitiesRequireMigrationDescription')}

{entitiesNeedingMigration.map((entity) => (

{entity.displayName}

{entity.fields.length} {translate('::App.DeveloperKit.Migration.Fields')}

))}
)} {/* Filters */}
setSearchTerm(e.target.value)} className="w-full pl-10 pr-4 py-2 border border-slate-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-colors" />
{/* Migrations List */} {filteredMigrations.length > 0 ? (
{filteredMigrations.map((migration) => { const StatusIcon = getStatusIcon(migration.status) return (

{migration.fileName || `Migration for ${migration.entityName}`}

Entity: {migration.entityName}

{migration.status.charAt(0).toUpperCase() + migration.status.slice(1)}
{translate('::App.DeveloperKit.Migration.Created')}{' '} {new Date(migration.creationTime).toLocaleDateString()}
{migration.appliedAt && (
{translate('::App.DeveloperKit.Migration.AppliedLabel')}{' '} {new Date(migration.appliedAt).toLocaleDateString()}
)}
{/* Actions */}
{migration.status === 'pending' && ( <> )} {migration.status === 'applied' && ( )}
{/* SQL Script Preview */} {selectedMigration === migration.id && (

{translate('::App.DeveloperKit.Migration.SQLScriptLabel')}

{migration.sqlScript ? (
                            {migration.sqlScript}
                          
) : (
{translate('::App.DeveloperKit.Migration.NoSQLScript')}

{translate('::App.DeveloperKit.Migration.NoSQLScriptDesc')}

)}
)} {/* Error Message */} {migration.status === 'failed' && migration.errorMessage && (
{translate('::App.DeveloperKit.Migration.MigrationFailed')}

{migration.errorMessage}

)}
) })}
) : (

{searchTerm || filterStatus !== 'all' ? translate('::App.DeveloperKit.Migration.NoMigrationsFound') : translate('::App.DeveloperKit.Migration.NoMigrationsYet')}

{searchTerm || filterStatus !== 'all' ? translate('::App.DeveloperKit.Migration.NoMigrationsAdjustSearch') : translate('::App.DeveloperKit.Migration.CreateEntitiesForMigration')}

)}
) } export default MigrationManager