PortainerManager/app/envs/[env].tsx

117 lines
3.3 KiB
TypeScript

import { Text, View, ActivityIndicator } from 'react-native';
import { useEffect, useState } from 'react';
import { useLocalSearchParams, useGlobalSearchParams, Link } from 'expo-router';
import { useAuth } from '../context/AuthContext';
import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';
import { ScrollView } from 'react-native';
interface Container {
Id: string;
Names: string[];
Image: string;
ImageID: string;
Command: string;
Created: number;
State: string;
Status: string;
// Add other fields as needed
}
export default function Route() {
const glob = useGlobalSearchParams();
const local = useLocalSearchParams();
const { domain, username, authData } = useAuth();
const [containers, setContainers] = useState<Container[]>([]);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
fetchData();
}, []); // Empty dependency array means this runs once on mount
const fetchData = async () => {
setIsLoading(true);
try {
const response = await fetch(`${domain}/api/endpoints/${local.env}/docker/containers/json?all=true`, {
headers: {
'Authorization': `Bearer ${authData.jwt}`
}
});
const data = await response.json();
setContainers(data);
} catch (error) {
console.error('Error fetching data:', error);
setError('Failed to fetch containers');
} finally {
setIsLoading(false);
}
};
if (isLoading) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<ActivityIndicator size="large" color="#0000ff" />
</View>
);
}
if (error) {
return (
<View>
<Text>Error: {error}</Text>
</View>
);
}
return (
<SafeAreaProvider>
<SafeAreaView style={{ flex: 1, padding: 16, width: '100%' }}>
<ScrollView showsVerticalScrollIndicator={false}>
{containers.map((container) => (
<View key={container.Id} style={{
padding: 20,
marginVertical: 10,
backgroundColor: 'rgba(13, 71, 161, 0.1)',
borderRadius: 8,
borderLeftWidth: 6,
borderLeftColor: '#0D47A1',
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.25,
shadowRadius: 3.84,
elevation: 5,
minHeight: 120,
borderWidth: 1,
borderColor: 'rgba(13, 71, 161, 0.2)',
}}>
<Text style={{
fontSize: 18,
fontWeight: 'bold',
color: '#0D47A1',
marginBottom: 8
}}>{container.Names[0].replace('/', '')}</Text>
<Text style={{
fontSize: 14,
color: '#1976D2',
marginBottom: 4
}}>Status: {container.Status}</Text>
<Text style={{
fontSize: 14,
color: container.State === 'running' ? '#2E7D32' : '#C62828',
marginBottom: 4
}}>State: {container.State}</Text>
<Text style={{
fontSize: 14,
color: '#1976D2',
marginBottom: 4
}}>Image: {container.Image}</Text>
</View>
))}
</ScrollView>
</SafeAreaView>
</SafeAreaProvider>
);
}