diff --git a/src/app/admin/dashboard/page-old.tsx b/src/app/admin/dashboard/page-old.tsx deleted file mode 100644 index f246dd6..0000000 --- a/src/app/admin/dashboard/page-old.tsx +++ /dev/null @@ -1,1161 +0,0 @@ -'use client'; - -import AddIcon from '@mui/icons-material/Add'; -import CodeIcon from '@mui/icons-material/Code'; -import DeleteIcon from '@mui/icons-material/Delete'; -import EditIcon from '@mui/icons-material/Edit'; -import LogoutIcon from '@mui/icons-material/Logout'; -import RuleIcon from '@mui/icons-material/Rule'; -import StorageIcon from '@mui/icons-material/Storage'; -import TableChartIcon from '@mui/icons-material/TableChart'; -import ViewColumnIcon from '@mui/icons-material/ViewColumn'; -import { - Alert, - AppBar, - Box, - Button, - Checkbox, - CircularProgress, - Dialog, - DialogActions, - DialogContent, - DialogTitle, - Drawer, - FormControlLabel, - IconButton, - List, - ListItem, - ListItemButton, - ListItemIcon, - ListItemText, - MenuItem, - Paper, - Select, - Table, - TableBody, - TableCell, - TableContainer, - TableHead, - TableRow, - TextField, - Toolbar, - Typography, -} from '@mui/material'; -import { ThemeProvider } from '@mui/material/styles'; -import { useRouter } from 'next/navigation'; -import { useCallback, useEffect, useState } from 'react'; -import ConstraintManagerTab from '@/components/admin/ConstraintManagerTab'; -import { theme } from '@/utils/theme'; - -const DRAWER_WIDTH = 240; - -type TabPanelProps = { - children?: React.ReactNode; - index: number; - value: number; -}; - -function TabPanel(props: TabPanelProps) { - const { children, value, index, ...other } = props; - - return ( - - ); -} - -export default function AdminDashboard() { - const router = useRouter(); - const [tabValue, setTabValue] = useState(0); - const [tables, setTables] = useState([]); - const [selectedTable, setSelectedTable] = useState(''); - const [queryText, setQueryText] = useState(''); - const [queryResult, setQueryResult] = useState(null); - const [tableSchema, setTableSchema] = useState(null); - const [loading, setLoading] = useState(false); - const [error, setError] = useState(''); - const [successMessage, setSuccessMessage] = useState(''); - - // Table Manager states - const [openCreateTableDialog, setOpenCreateTableDialog] = useState(false); - const [openDropTableDialog, setOpenDropTableDialog] = useState(false); - const [newTableName, setNewTableName] = useState(''); - const [tableColumns, setTableColumns] = useState([{ name: '', type: 'VARCHAR', length: 255, nullable: true, primaryKey: false }]); - const [tableToDelete, setTableToDelete] = useState(''); - - // Column Manager states - const [openAddColumnDialog, setOpenAddColumnDialog] = useState(false); - const [openModifyColumnDialog, setOpenModifyColumnDialog] = useState(false); - const [openDropColumnDialog, setOpenDropColumnDialog] = useState(false); - const [selectedTableForColumn, setSelectedTableForColumn] = useState(''); - const [newColumnName, setNewColumnName] = useState(''); - const [newColumnType, setNewColumnType] = useState('VARCHAR'); - const [newColumnNullable, setNewColumnNullable] = useState(true); - const [newColumnDefault, setNewColumnDefault] = useState(''); - const [columnToModify, setColumnToModify] = useState(''); - const [columnToDelete, setColumnToDelete] = useState(''); - - const fetchTables = useCallback(async () => { - try { - const response = await fetch('/api/admin/tables'); - if (!response.ok) { - if (response.status === 401) { - router.push('/admin/login'); - return; - } - throw new Error('Failed to fetch tables'); - } - const data = await response.json(); - setTables(data.tables); - } catch (err: any) { - setError(err.message); - } - }, [router]); - - useEffect(() => { - fetchTables(); - }, [fetchTables]); - - useEffect(() => { - if (selectedTableForColumn && tabValue === 3) { - // Fetch schema when a table is selected in Column Manager - const fetchSchema = async () => { - try { - const schemaResponse = await fetch('/api/admin/table-schema', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ tableName: selectedTableForColumn }), - }); - - if (schemaResponse.ok) { - const schemaData = await schemaResponse.json(); - setTableSchema(schemaData); - } - } catch (err) { - console.error('Failed to fetch schema:', err); - } - }; - fetchSchema(); - } - }, [selectedTableForColumn, tabValue]); - - const handleTableClick = async (tableName: string) => { - setSelectedTable(tableName); - setLoading(true); - setError(''); - setSuccessMessage(''); - setQueryResult(null); - - try { - // Fetch table data - const dataResponse = await fetch('/api/admin/table-data', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ tableName }), - }); - - if (!dataResponse.ok) { - const data = await dataResponse.json(); - throw new Error(data.error || 'Query failed'); - } - - const data = await dataResponse.json(); - setQueryResult(data); - - // Fetch table schema - const schemaResponse = await fetch('/api/admin/table-schema', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ tableName }), - }); - - if (schemaResponse.ok) { - const schemaData = await schemaResponse.json(); - setTableSchema(schemaData); - } - } catch (err: any) { - setError(err.message); - } finally { - setLoading(false); - } - }; - - const handleQuerySubmit = async () => { - if (!queryText.trim()) { - setError('Please enter a query'); - return; - } - - setLoading(true); - setError(''); - setQueryResult(null); - - try { - const response = await fetch('/api/admin/query', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ query: queryText }), - }); - - const data = await response.json(); - - if (!response.ok) { - throw new Error(data.error || 'Query failed'); - } - - setQueryResult(data); - } catch (err: any) { - setError(err.message); - } finally { - setLoading(false); - } - }; - - const handleLogout = async () => { - try { - await fetch('/api/admin/logout', { - method: 'POST', - }); - router.push('/admin/login'); - router.refresh(); - } catch (err) { - console.error('Logout error:', err); - } - }; - - // Table Management Handlers - const handleCreateTable = async () => { - if (!newTableName.trim()) { - setError('Table name is required'); - return; - } - - if (tableColumns.length === 0 || !tableColumns[0].name) { - setError('At least one column is required'); - return; - } - - setLoading(true); - setError(''); - setSuccessMessage(''); - - try { - const response = await fetch('/api/admin/table-manage', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - tableName: newTableName, - columns: tableColumns.filter(col => col.name.trim()), - }), - }); - - const data = await response.json(); - - if (!response.ok) { - throw new Error(data.error || 'Failed to create table'); - } - - setSuccessMessage(data.message); - setOpenCreateTableDialog(false); - setNewTableName(''); - setTableColumns([{ name: '', type: 'VARCHAR', length: 255, nullable: true, primaryKey: false }]); - await fetchTables(); - } catch (err: any) { - setError(err.message); - } finally { - setLoading(false); - } - }; - - const handleDropTable = async () => { - if (!tableToDelete) { - setError('Please select a table to drop'); - return; - } - - setLoading(true); - setError(''); - setSuccessMessage(''); - - try { - const response = await fetch('/api/admin/table-manage', { - method: 'DELETE', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ tableName: tableToDelete }), - }); - - const data = await response.json(); - - if (!response.ok) { - throw new Error(data.error || 'Failed to drop table'); - } - - setSuccessMessage(data.message); - setOpenDropTableDialog(false); - setTableToDelete(''); - if (selectedTable === tableToDelete) { - setSelectedTable(''); - setQueryResult(null); - } - await fetchTables(); - } catch (err: any) { - setError(err.message); - } finally { - setLoading(false); - } - }; - - const addColumnToTable = () => { - setTableColumns([...tableColumns, { name: '', type: 'VARCHAR', length: 255, nullable: true, primaryKey: false }]); - }; - - const updateColumnField = (index: number, field: string, value: any) => { - const updated = [...tableColumns]; - updated[index] = { ...updated[index], [field]: value }; - setTableColumns(updated); - }; - - const removeColumn = (index: number) => { - if (tableColumns.length > 1) { - setTableColumns(tableColumns.filter((_, i) => i !== index)); - } - }; - - // Column Management Handlers - const handleAddColumn = async () => { - if (!selectedTableForColumn || !newColumnName.trim() || !newColumnType) { - setError('Table name, column name, and data type are required'); - return; - } - - setLoading(true); - setError(''); - setSuccessMessage(''); - - try { - const payload: any = { - tableName: selectedTableForColumn, - columnName: newColumnName, - dataType: newColumnType, - nullable: newColumnNullable, - }; - - if (newColumnDefault) { - payload.defaultValue = newColumnDefault; - } - - const response = await fetch('/api/admin/column-manage', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(payload), - }); - - const data = await response.json(); - - if (!response.ok) { - throw new Error(data.error || 'Failed to add column'); - } - - setSuccessMessage(data.message); - setOpenAddColumnDialog(false); - setNewColumnName(''); - setNewColumnType('VARCHAR'); - setNewColumnNullable(true); - setNewColumnDefault(''); - - // Refresh table schema if viewing the modified table - if (selectedTable === selectedTableForColumn) { - await handleTableClick(selectedTableForColumn); - } - } catch (err: any) { - setError(err.message); - } finally { - setLoading(false); - } - }; - - const handleModifyColumn = async () => { - if (!selectedTableForColumn || !columnToModify) { - setError('Table name and column name are required'); - return; - } - - setLoading(true); - setError(''); - setSuccessMessage(''); - - try { - const response = await fetch('/api/admin/column-manage', { - method: 'PUT', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - tableName: selectedTableForColumn, - columnName: columnToModify, - newType: newColumnType, - nullable: newColumnNullable, - }), - }); - - const data = await response.json(); - - if (!response.ok) { - throw new Error(data.error || 'Failed to modify column'); - } - - setSuccessMessage(data.message); - setOpenModifyColumnDialog(false); - setColumnToModify(''); - setNewColumnType('VARCHAR'); - setNewColumnNullable(true); - - // Refresh table schema if viewing the modified table - if (selectedTable === selectedTableForColumn) { - await handleTableClick(selectedTableForColumn); - } - } catch (err: any) { - setError(err.message); - } finally { - setLoading(false); - } - }; - - const handleDropColumn = async () => { - if (!selectedTableForColumn || !columnToDelete) { - setError('Table name and column name are required'); - return; - } - - setLoading(true); - setError(''); - setSuccessMessage(''); - - try { - const response = await fetch('/api/admin/column-manage', { - method: 'DELETE', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - tableName: selectedTableForColumn, - columnName: columnToDelete, - }), - }); - - const data = await response.json(); - - if (!response.ok) { - throw new Error(data.error || 'Failed to drop column'); - } - - setSuccessMessage(data.message); - setOpenDropColumnDialog(false); - setColumnToDelete(''); - - // Refresh table schema if viewing the modified table - if (selectedTable === selectedTableForColumn) { - await handleTableClick(selectedTableForColumn); - } - } catch (err: any) { - setError(err.message); - } finally { - setLoading(false); - } - }; - - // Constraint Management Handlers - const handleAddConstraint = async (tableName: string, data: any) => { - setLoading(true); - setError(''); - setSuccessMessage(''); - - try { - const response = await fetch('/api/admin/constraints', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - tableName, - ...data, - }), - }); - - const result = await response.json(); - - if (!response.ok) { - throw new Error(result.error || 'Failed to add constraint'); - } - - setSuccessMessage(result.message || 'Constraint added successfully'); - } catch (err: any) { - setError(err.message); - throw err; - } finally { - setLoading(false); - } - }; - - const handleDropConstraint = async (tableName: string, constraintName: string) => { - setLoading(true); - setError(''); - setSuccessMessage(''); - - try { - const response = await fetch('/api/admin/constraints', { - method: 'DELETE', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - tableName, - constraintName, - }), - }); - - const result = await response.json(); - - if (!response.ok) { - throw new Error(result.error || 'Failed to drop constraint'); - } - - setSuccessMessage(result.message || 'Constraint dropped successfully'); - } catch (err: any) { - setError(err.message); - throw err; - } finally { - setLoading(false); - } - }; - - return ( - - - theme.zIndex.drawer + 1 }} - > - - - - Postgres Admin Panel - - - - - - - - - - - setTabValue(0)}> - - - - - - - - setTabValue(1)}> - - - - - - - - setTabValue(2)}> - - - - - - - - setTabValue(3)}> - - - - - - - - setTabValue(4)}> - - - - - - - - - - - - - - - - Database Tables - - - - - {tables.map(table => ( - - handleTableClick(table.table_name)}> - - - - - - - ))} - - - - {selectedTable && ( - - Table: - {' '} - {selectedTable} - - )} - - - - - SQL Query Interface - - - - setQueryText(e.target.value)} - placeholder="SELECT * FROM your_table LIMIT 10;" - sx={{ mb: 2 }} - /> - - - - - - - Table Manager - - - - - - - - - - - Existing Tables - - - {tables.map(table => ( - - - - - - - ))} - {tables.length === 0 && ( - - - - )} - - - - - - - - Column Manager - - - - - Select a table to manage its columns: - - - - - {selectedTableForColumn && ( - <> - - - - - - - {tableSchema && ( - - - - Current Columns for {selectedTableForColumn} - - - - - - Column Name - Data Type - Nullable - Default - - - - {tableSchema.columns?.map((col: any) => ( - - {col.column_name} - {col.data_type} - {col.is_nullable} - {col.column_default || 'NULL'} - - ))} - -
-
-
-
- )} - - )} -
- - - - - - {successMessage && ( - setSuccessMessage('')}> - {successMessage} - - )} - - {error && ( - - {error} - - )} - - {loading && ( - - - - )} - - {queryResult && !loading && ( - - - - Rows returned: - {' '} - {queryResult.rowCount} - - - - - - - {queryResult.fields?.map((field: any) => ( - - {field.name} - - ))} - - - - {queryResult.rows?.map((row: any, idx: number) => ( - - {queryResult.fields?.map((field: any) => ( - - {row[field.name] !== null - ? String(row[field.name]) - : 'NULL'} - - ))} - - ))} - -
-
-
- )} -
- - {/* Create Table Dialog */} - setOpenCreateTableDialog(false)} maxWidth="md" fullWidth> - Create New Table - - setNewTableName(e.target.value)} - sx={{ mt: 2, mb: 2 }} - /> - - Columns: - - {tableColumns.map((col, index) => ( - - updateColumnField(index, 'name', e.target.value)} - sx={{ mr: 1, mb: 1 }} - /> - - {(col.type === 'VARCHAR') && ( - updateColumnField(index, 'length', e.target.value)} - sx={{ mr: 1, mb: 1, width: 100 }} - /> - )} - updateColumnField(index, 'nullable', e.target.checked)} - /> - } - label="Nullable" - sx={{ mr: 1 }} - /> - updateColumnField(index, 'primaryKey', e.target.checked)} - /> - } - label="Primary Key" - sx={{ mr: 1 }} - /> - {tableColumns.length > 1 && ( - removeColumn(index)} color="error" size="small"> - - - )} - - ))} - - - - - - - - - {/* Drop Table Dialog */} - setOpenDropTableDialog(false)}> - Drop Table - - - Warning: This will permanently delete the table and all its data! - - - - - - - - - - {/* Add Column Dialog */} - setOpenAddColumnDialog(false)}> - Add Column to {selectedTableForColumn} - - setNewColumnName(e.target.value)} - sx={{ mt: 2, mb: 2 }} - /> - - setNewColumnNullable(e.target.checked)} - /> - } - label="Nullable" - sx={{ mb: 2 }} - /> - setNewColumnDefault(e.target.value)} - /> - - - - - - - - {/* Modify Column Dialog */} - setOpenModifyColumnDialog(false)}> - Modify Column in {selectedTableForColumn} - - - {columnToModify && ( - <> - - setNewColumnNullable(e.target.checked)} - /> - } - label="Nullable" - /> - - )} - - - - - - - - {/* Drop Column Dialog */} - setOpenDropColumnDialog(false)}> - Drop Column from {selectedTableForColumn} - - - Warning: This will permanently delete the column and all its data! - - - - - - - - -
-
- ); -} diff --git a/src/app/admin/dashboard/page.tsx b/src/app/admin/dashboard/page.tsx index 3b733d4..1f019fc 100644 --- a/src/app/admin/dashboard/page.tsx +++ b/src/app/admin/dashboard/page.tsx @@ -32,14 +32,14 @@ import { import { ThemeProvider } from '@mui/material/styles'; import { useRouter } from 'next/navigation'; import { useCallback, useEffect, useState } from 'react'; -import TablesTab from '@/components/admin/TablesTab'; -import SQLQueryTab from '@/components/admin/SQLQueryTab'; -import TableManagerTab from '@/components/admin/TableManagerTab'; import ColumnManagerTab from '@/components/admin/ColumnManagerTab'; import ConstraintManagerTab from '@/components/admin/ConstraintManagerTab'; -import QueryBuilderTab from '@/components/admin/QueryBuilderTab'; import IndexManagerTab from '@/components/admin/IndexManagerTab'; -import { getNavItems, getFeatureById } from '@/utils/featureConfig'; +import QueryBuilderTab from '@/components/admin/QueryBuilderTab'; +import SQLQueryTab from '@/components/admin/SQLQueryTab'; +import TableManagerTab from '@/components/admin/TableManagerTab'; +import TablesTab from '@/components/admin/TablesTab'; +import { getFeatureById, getNavItems } from '@/utils/featureConfig'; import { theme } from '@/utils/theme'; import Button from '@mui/material/Button'; diff --git a/src/app/admin/dashboard/page.tsx.backup b/src/app/admin/dashboard/page.tsx.backup deleted file mode 100644 index 275d9ea..0000000 --- a/src/app/admin/dashboard/page.tsx.backup +++ /dev/null @@ -1,369 +0,0 @@ -'use client'; - -import AddIcon from '@mui/icons-material/Add'; -import CodeIcon from '@mui/icons-material/Code'; -import DeleteIcon from '@mui/icons-material/Delete'; -import EditIcon from '@mui/icons-material/Edit'; -import LogoutIcon from '@mui/icons-material/Logout'; -import StorageIcon from '@mui/icons-material/Storage'; -import TableChartIcon from '@mui/icons-material/TableChart'; -import { - Alert, - AppBar, - Box, - Button, - CircularProgress, - Dialog, - DialogActions, - DialogContent, - DialogTitle, - Drawer, - IconButton, - List, - ListItem, - ListItemButton, - ListItemIcon, - ListItemText, - Paper, - Table, - TableBody, - TableCell, - TableContainer, - TableHead, - TableRow, - TextField, - Toolbar, - Typography, -} from '@mui/material'; -import { ThemeProvider } from '@mui/material/styles'; -import { useRouter } from 'next/navigation'; -import { useCallback, useEffect, useState } from 'react'; -import { theme } from '@/utils/theme'; - -const DRAWER_WIDTH = 240; - -type TabPanelProps = { - children?: React.ReactNode; - index: number; - value: number; -}; - -function TabPanel(props: TabPanelProps) { - const { children, value, index, ...other } = props; - - return ( - - ); -} - -export default function AdminDashboard() { - const router = useRouter(); - const [tabValue, setTabValue] = useState(0); - const [tables, setTables] = useState([]); - const [selectedTable, setSelectedTable] = useState(''); - const [queryText, setQueryText] = useState(''); - const [queryResult, setQueryResult] = useState(null); - const [tableSchema, setTableSchema] = useState(null); - const [loading, setLoading] = useState(false); - const [error, setError] = useState(''); - const [successMessage, setSuccessMessage] = useState(''); - - // Dialog states - const [openCreateDialog, setOpenCreateDialog] = useState(false); - const [openEditDialog, setOpenEditDialog] = useState(false); - const [openDeleteDialog, setOpenDeleteDialog] = useState(false); - const [editingRecord, setEditingRecord] = useState(null); - const [deletingRecord, setDeletingRecord] = useState(null); - const [formData, setFormData] = useState({}); - - const fetchTables = useCallback(async () => { - try { - const response = await fetch('/api/admin/tables'); - if (!response.ok) { - if (response.status === 401) { - router.push('/admin/login'); - return; - } - throw new Error('Failed to fetch tables'); - } - const data = await response.json(); - setTables(data.tables); - } catch (err: any) { - setError(err.message); - } - }, [router]); - - useEffect(() => { - fetchTables(); - }, [fetchTables]); - - const handleTableClick = async (tableName: string) => { - setSelectedTable(tableName); - setLoading(true); - setError(''); - setSuccessMessage(''); - setQueryResult(null); - - try { - // Fetch table data - const dataResponse = await fetch('/api/admin/table-data', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ tableName }), - }); - - if (!response.ok) { - const data = await dataResponse.json(); - throw new Error(data.error || 'Query failed'); - } - - const data = await dataResponse.json(); - setQueryResult(data); - - // Fetch table schema - const schemaResponse = await fetch('/api/admin/table-schema', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ tableName }), - }); - - if (schemaResponse.ok) { - const schemaData = await schemaResponse.json(); - setTableSchema(schemaData); - } - } catch (err: any) { - setError(err.message); - } finally { - setLoading(false); - } - }; - - const handleQuerySubmit = async () => { - if (!queryText.trim()) { - setError('Please enter a query'); - return; - } - - setLoading(true); - setError(''); - setQueryResult(null); - - try { - const response = await fetch('/api/admin/query', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ query: queryText }), - }); - - const data = await response.json(); - - if (!response.ok) { - throw new Error(data.error || 'Query failed'); - } - - setQueryResult(data); - } catch (err: any) { - setError(err.message); - } finally { - setLoading(false); - } - }; - - const handleLogout = async () => { - try { - await fetch('/api/admin/logout', { - method: 'POST', - }); - router.push('/admin/login'); - router.refresh(); - } catch (err) { - console.error('Logout error:', err); - } - }; - - return ( - - - theme.zIndex.drawer + 1 }} - > - - - - Postgres Admin Panel - - - - - - - - - - - setTabValue(0)}> - - - - - - - - setTabValue(1)}> - - - - - - - - - - - - - - - - Database Tables - - - - - {tables.map(table => ( - - handleTableClick(table.table_name)}> - - - - - - - ))} - - - - {selectedTable && ( - - Table: - {' '} - {selectedTable} - - )} - - - - - SQL Query Interface - - - - setQueryText(e.target.value)} - placeholder="SELECT * FROM your_table LIMIT 10;" - sx={{ mb: 2 }} - /> - - - - - {error && ( - - {error} - - )} - - {loading && ( - - - - )} - - {queryResult && !loading && ( - - - - Rows returned: - {' '} - {queryResult.rowCount} - - - - - - - {queryResult.fields?.map((field: any) => ( - - {field.name} - - ))} - - - - {queryResult.rows?.map((row: any, idx: number) => ( - - {queryResult.fields?.map((field: any) => ( - - {row[field.name] !== null - ? String(row[field.name]) - : 'NULL'} - - ))} - - ))} - -
-
-
- )} -
-
-
- ); -}