initial project setup

This commit is contained in:
glenn schrooyen
2025-09-11 22:08:12 +02:00
parent 8cc588dc92
commit 21e4972ab1
46 changed files with 2755 additions and 1 deletions

View File

@@ -0,0 +1,147 @@
import React from 'react';
import { Row, Col, Card, Statistic, Progress, List, Typography } from 'antd';
import {
DashboardOutlined,
ServerOutlined,
DatabaseOutlined,
WifiOutlined,
CheckCircleOutlined,
ExclamationCircleOutlined
} from '@ant-design/icons';
import SystemMetrics from './SystemMetrics';
const { Title, Text } = Typography;
const Dashboard = () => {
// Mock data - in real app, this would come from API
const systemStats = {
cpu: 45.2,
memory: 68.5,
disk: 32.1,
network: 12.3
};
const services = [
{ name: 'Home Assistant', status: 'online', uptime: '7d 12h' },
{ name: 'Frigate', status: 'online', uptime: '7d 12h' },
{ name: 'Immich', status: 'online', uptime: '7d 12h' },
{ name: 'n8n', status: 'offline', uptime: '0d 0h' },
{ name: 'PostgreSQL', status: 'online', uptime: '7d 12h' },
{ name: 'Redis', status: 'online', uptime: '7d 12h' }
];
const recentEvents = [
{ time: '2 minutes ago', event: 'Person detected at front door', service: 'Frigate' },
{ time: '5 minutes ago', event: 'CPU usage above 80%', service: 'System' },
{ time: '12 minutes ago', event: 'Alice arrived home', service: 'Home Assistant' },
{ time: '1 hour ago', event: 'New photo uploaded', service: 'Immich' }
];
const getStatusIcon = (status) => {
return status === 'online' ?
<CheckCircleOutlined style={{ color: '#52c41a' }} /> :
<ExclamationCircleOutlined style={{ color: '#ff4d4f' }} />;
};
return (
<div className="dashboard-container">
<Title level={2}>System Overview</Title>
{/* System Metrics */}
<Row gutter={16} style={{ marginBottom: 24 }}>
<Col span={6}>
<Card>
<Statistic
title="CPU Usage"
value={systemStats.cpu}
suffix="%"
prefix={<ServerOutlined />}
/>
<Progress percent={systemStats.cpu} showInfo={false} />
</Card>
</Col>
<Col span={6}>
<Card>
<Statistic
title="Memory Usage"
value={systemStats.memory}
suffix="%"
prefix={<DatabaseOutlined />}
/>
<Progress percent={systemStats.memory} showInfo={false} />
</Card>
</Col>
<Col span={6}>
<Card>
<Statistic
title="Disk Usage"
value={systemStats.disk}
suffix="%"
prefix={<DatabaseOutlined />}
/>
<Progress percent={systemStats.disk} showInfo={false} />
</Card>
</Col>
<Col span={6}>
<Card>
<Statistic
title="Network"
value={systemStats.network}
suffix="Mbps"
prefix={<WifiOutlined />}
/>
</Card>
</Col>
</Row>
<Row gutter={16}>
{/* Service Status */}
<Col span={12}>
<Card title="Service Status" style={{ height: 400 }}>
<List
dataSource={services}
renderItem={(service) => (
<List.Item>
<List.Item.Meta
avatar={getStatusIcon(service.status)}
title={service.name}
description={`Uptime: ${service.uptime}`}
/>
<Text type={service.status === 'online' ? 'success' : 'danger'}>
{service.status.toUpperCase()}
</Text>
</List.Item>
)}
/>
</Card>
</Col>
{/* Recent Events */}
<Col span={12}>
<Card title="Recent Events" style={{ height: 400 }}>
<List
dataSource={recentEvents}
renderItem={(event) => (
<List.Item>
<List.Item.Meta
title={event.event}
description={`${event.time}${event.service}`}
/>
</List.Item>
)}
/>
</Card>
</Col>
</Row>
{/* System Metrics Chart */}
<Row style={{ marginTop: 24 }}>
<Col span={24}>
<SystemMetrics />
</Col>
</Row>
</div>
);
};
export default Dashboard;

View File

@@ -0,0 +1,124 @@
import React, { useState } from 'react';
import { Card, Form, Input, Button, Switch, Select, Divider, Typography, message } from 'antd';
const { Title, Text } = Typography;
const { Option } = Select;
const Settings = () => {
const [form] = Form.useForm();
const [loading, setLoading] = useState(false);
const onFinish = (values) => {
setLoading(true);
// Simulate API call
setTimeout(() => {
setLoading(false);
message.success('Settings saved successfully!');
}, 1000);
};
return (
<div className="dashboard-container">
<Title level={2}>Settings</Title>
<Card title="Service Integrations" style={{ marginBottom: 24 }}>
<Form
form={form}
layout="vertical"
onFinish={onFinish}
initialValues={{
homeAssistant: {
enabled: true,
url: 'http://homeassistant.local:8123',
token: 'your-token-here'
},
frigate: {
enabled: true,
url: 'http://frigate.local:5000',
token: 'your-token-here'
},
immich: {
enabled: false,
url: 'http://immich.local:2283',
apiKey: 'your-api-key-here'
}
}}
>
{/* Home Assistant */}
<Card size="small" title="Home Assistant" style={{ marginBottom: 16 }}>
<Form.Item name={['homeAssistant', 'enabled']} valuePropName="checked">
<Switch checkedChildren="Enabled" unCheckedChildren="Disabled" />
</Form.Item>
<Form.Item label="URL" name={['homeAssistant', 'url']}>
<Input placeholder="http://homeassistant.local:8123" />
</Form.Item>
<Form.Item label="Token" name={['homeAssistant', 'token']}>
<Input.Password placeholder="Your Home Assistant token" />
</Form.Item>
</Card>
{/* Frigate */}
<Card size="small" title="Frigate" style={{ marginBottom: 16 }}>
<Form.Item name={['frigate', 'enabled']} valuePropName="checked">
<Switch checkedChildren="Enabled" unCheckedChildren="Disabled" />
</Form.Item>
<Form.Item label="URL" name={['frigate', 'url']}>
<Input placeholder="http://frigate.local:5000" />
</Form.Item>
<Form.Item label="Token" name={['frigate', 'token']}>
<Input.Password placeholder="Your Frigate token" />
</Form.Item>
</Card>
{/* Immich */}
<Card size="small" title="Immich" style={{ marginBottom: 16 }}>
<Form.Item name={['immich', 'enabled']} valuePropName="checked">
<Switch checkedChildren="Enabled" unCheckedChildren="Disabled" />
</Form.Item>
<Form.Item label="URL" name={['immich', 'url']}>
<Input placeholder="http://immich.local:2283" />
</Form.Item>
<Form.Item label="API Key" name={['immich', 'apiKey']}>
<Input.Password placeholder="Your Immich API key" />
</Form.Item>
</Card>
<Button type="primary" htmlType="submit" loading={loading}>
Save Settings
</Button>
</Form>
</Card>
<Card title="Dashboard Configuration">
<Form layout="vertical">
<Form.Item label="Default Dashboard Layout">
<Select defaultValue="grid" style={{ width: 200 }}>
<Option value="grid">Grid Layout</Option>
<Option value="list">List Layout</Option>
<Option value="custom">Custom Layout</Option>
</Select>
</Form.Item>
<Form.Item label="Auto-refresh Interval">
<Select defaultValue="30" style={{ width: 200 }}>
<Option value="10">10 seconds</Option>
<Option value="30">30 seconds</Option>
<Option value="60">1 minute</Option>
<Option value="300">5 minutes</Option>
</Select>
</Form.Item>
<Form.Item label="Theme">
<Select defaultValue="light" style={{ width: 200 }}>
<Option value="light">Light</Option>
<Option value="dark">Dark</Option>
<Option value="auto">Auto</Option>
</Select>
</Form.Item>
</Form>
</Card>
</div>
);
};
export default Settings;

View File

@@ -0,0 +1,111 @@
import React from 'react';
import { Card, Row, Col, Statistic, Progress } from 'antd';
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, AreaChart, Area } from 'recharts';
const SystemMetrics = () => {
// Mock data for charts
const cpuData = [
{ time: '00:00', cpu: 25 },
{ time: '04:00', cpu: 30 },
{ time: '08:00', cpu: 45 },
{ time: '12:00', cpu: 60 },
{ time: '16:00', cpu: 55 },
{ time: '20:00', cpu: 40 },
{ time: '24:00', cpu: 35 }
];
const memoryData = [
{ time: '00:00', memory: 2.1 },
{ time: '04:00', memory: 2.3 },
{ time: '08:00', memory: 2.8 },
{ time: '12:00', memory: 3.2 },
{ time: '16:00', memory: 3.0 },
{ time: '20:00', memory: 2.7 },
{ time: '24:00', memory: 2.4 }
];
const networkData = [
{ time: '00:00', in: 5, out: 3 },
{ time: '04:00', in: 8, out: 4 },
{ time: '08:00', in: 15, out: 8 },
{ time: '12:00', in: 20, out: 12 },
{ time: '16:00', in: 18, out: 10 },
{ time: '20:00', in: 12, out: 7 },
{ time: '24:00', in: 6, out: 4 }
];
return (
<div>
<Card title="System Performance Metrics" style={{ marginBottom: 16 }}>
<Row gutter={16}>
<Col span={8}>
<Card size="small">
<Statistic title="CPU Usage (24h)" value={45.2} suffix="%" />
<Progress percent={45.2} showInfo={false} />
</Card>
</Col>
<Col span={8}>
<Card size="small">
<Statistic title="Memory Usage (24h)" value={68.5} suffix="%" />
<Progress percent={68.5} showInfo={false} />
</Card>
</Col>
<Col span={8}>
<Card size="small">
<Statistic title="Disk Usage" value={32.1} suffix="%" />
<Progress percent={32.1} showInfo={false} />
</Card>
</Col>
</Row>
</Card>
<Row gutter={16}>
<Col span={12}>
<Card title="CPU Usage Over Time">
<ResponsiveContainer width="100%" height={300}>
<AreaChart data={cpuData}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="time" />
<YAxis />
<Tooltip />
<Area type="monotone" dataKey="cpu" stroke="#1890ff" fill="#1890ff" fillOpacity={0.3} />
</AreaChart>
</ResponsiveContainer>
</Card>
</Col>
<Col span={12}>
<Card title="Memory Usage Over Time">
<ResponsiveContainer width="100%" height={300}>
<LineChart data={memoryData}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="time" />
<YAxis />
<Tooltip />
<Line type="monotone" dataKey="memory" stroke="#52c41a" strokeWidth={2} />
</LineChart>
</ResponsiveContainer>
</Card>
</Col>
</Row>
<Row gutter={16} style={{ marginTop: 16 }}>
<Col span={24}>
<Card title="Network Traffic">
<ResponsiveContainer width="100%" height={300}>
<AreaChart data={networkData}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="time" />
<YAxis />
<Tooltip />
<Area type="monotone" dataKey="in" stackId="1" stroke="#1890ff" fill="#1890ff" fillOpacity={0.6} />
<Area type="monotone" dataKey="out" stackId="1" stroke="#52c41a" fill="#52c41a" fillOpacity={0.6} />
</AreaChart>
</ResponsiveContainer>
</Card>
</Col>
</Row>
</div>
);
};
export default SystemMetrics;