Files
skybridge/kms/web/src/components/Applications.tsx
2025-09-01 17:17:27 -04:00

156 lines
3.7 KiB
TypeScript

import React, { useState, useEffect } from 'react';
import {
DataTable,
TableColumn,
Badge,
Group,
Text,
SidebarLayout,
Sidebar
} from '@skybridge/web-components';
import { IconEye, IconCopy } from '@tabler/icons-react';
import { notifications } from '@mantine/notifications';
import { apiService, Application } from '../services/apiService';
import ApplicationSidebar from './ApplicationSidebar';
import dayjs from 'dayjs';
const Applications: React.FC = () => {
const [applications, setApplications] = useState<Application[]>([]);
const [loading, setLoading] = useState(false);
const [sidebarOpen, setSidebarOpen] = useState(false);
const [editingApp, setEditingApp] = useState<Application | null>(null);
useEffect(() => {
loadApplications();
}, []);
const loadApplications = async () => {
try {
setLoading(true);
const response = await apiService.getApplications(100, 0);
setApplications(response.data);
} catch (error) {
console.error('Failed to load applications:', error);
} finally {
setLoading(false);
}
};
const handleAdd = () => {
setEditingApp(null);
setSidebarOpen(true);
};
const handleEdit = (app: Application) => {
setEditingApp(app);
setSidebarOpen(true);
};
const handleDelete = async (app: Application) => {
await apiService.deleteApplication(app.app_id);
loadApplications();
};
const handleSuccess = () => {
setSidebarOpen(false);
setEditingApp(null);
loadApplications();
};
const copyToClipboard = (text: string) => {
navigator.clipboard.writeText(text);
notifications.show({
title: 'Copied',
message: 'Copied to clipboard',
color: 'blue',
});
};
const columns: TableColumn[] = [
{
key: 'app_id',
label: 'Application ID',
render: (value) => <Text fw={500}>{value}</Text>
},
{
key: 'type',
label: 'Type',
render: (value: string[]) => (
<Group gap="xs">
{value.map((type) => (
<Badge key={type} variant="light" size="sm">
{type}
</Badge>
))}
</Group>
)
},
{
key: 'owner',
label: 'Owner',
render: (value: any) => (
<Text size="sm" c="dimmed">
{value.name} ({value.owner})
</Text>
)
},
{
key: 'created_at',
label: 'Created',
render: (value) => (
<Text size="sm">
{dayjs(value).format('MMM DD, YYYY')}
</Text>
)
},
];
const customActions = [
{
key: 'view',
label: 'View Details',
icon: <IconEye size={14} />,
onClick: (app: Application) => {
// Could open a modal or navigate to details page
console.log('View details for:', app.app_id);
},
},
{
key: 'copy',
label: 'Copy App ID',
icon: <IconCopy size={14} />,
onClick: (app: Application) => copyToClipboard(app.app_id),
},
];
return (
<SidebarLayout
sidebarOpened={sidebarOpen}
sidebarWidth={450}
sidebar={
<ApplicationSidebar
opened={sidebarOpen}
onClose={() => setSidebarOpen(false)}
onSuccess={handleSuccess}
editingApp={editingApp}
/>
}
>
<DataTable
data={applications}
columns={columns}
loading={loading}
title="Applications"
searchable
onAdd={handleAdd}
onEdit={handleEdit}
onDelete={handleDelete}
onRefresh={loadApplications}
customActions={customActions}
emptyMessage="No applications found"
/>
</SidebarLayout>
);
};
export default Applications;