361 lines
13 KiB
TypeScript
361 lines
13 KiB
TypeScript
|
|
'use client';
|
||
|
|
|
||
|
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||
|
|
import { Badge } from '@/components/ui/badge';
|
||
|
|
import { Label } from '@/components/ui/label';
|
||
|
|
import {
|
||
|
|
Smartphone,
|
||
|
|
Info,
|
||
|
|
HardDrive,
|
||
|
|
Shield,
|
||
|
|
Wifi,
|
||
|
|
XCircle,
|
||
|
|
Battery,
|
||
|
|
CheckCircle,
|
||
|
|
AlertCircle
|
||
|
|
} from 'lucide-react';
|
||
|
|
import { AddigyDevice } from '@/lib/types/addigy';
|
||
|
|
|
||
|
|
interface AddigyTabProps {
|
||
|
|
device?: AddigyDevice;
|
||
|
|
}
|
||
|
|
|
||
|
|
export function AddigyTab({ device }: AddigyTabProps) {
|
||
|
|
if (!device) {
|
||
|
|
return (
|
||
|
|
<Card className="border-0 shadow-lg">
|
||
|
|
<CardContent className="pt-6">
|
||
|
|
<div className="text-center py-12 text-muted-foreground">
|
||
|
|
<Smartphone className="w-12 h-12 mx-auto mb-4 opacity-50" />
|
||
|
|
<p>No Addigy data available for this device</p>
|
||
|
|
</div>
|
||
|
|
</CardContent>
|
||
|
|
</Card>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
const isOnline = device.online;
|
||
|
|
const batteryPercentage = device['Battery Percentage'];
|
||
|
|
const isCharging = device['Battery Charging'];
|
||
|
|
const freeSpacePercentage = device['Free Disk Percentage'];
|
||
|
|
|
||
|
|
return (
|
||
|
|
<Card className="border-0 shadow-lg">
|
||
|
|
<CardHeader className="bg-gradient-to-r from-orange-50 to-orange-100 dark:from-orange-950 dark:to-orange-900 rounded-t-lg">
|
||
|
|
<CardTitle className="text-lg flex items-center gap-2">
|
||
|
|
<Smartphone className="w-5 h-5" />
|
||
|
|
Addigy Device Information (Apple RMM)
|
||
|
|
</CardTitle>
|
||
|
|
</CardHeader>
|
||
|
|
<CardContent className="pt-6">
|
||
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||
|
|
{/* Basic Information */}
|
||
|
|
<div className="space-y-4">
|
||
|
|
<h3 className="font-semibold flex items-center gap-2">
|
||
|
|
<Info className="w-4 h-4" />
|
||
|
|
Basic Information
|
||
|
|
</h3>
|
||
|
|
|
||
|
|
<div className="space-y-3">
|
||
|
|
<div>
|
||
|
|
<Label>Device Name</Label>
|
||
|
|
<p className="text-sm text-muted-foreground mt-1">{device['Device Name']}</p>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<Label>Model</Label>
|
||
|
|
<p className="text-sm text-muted-foreground mt-1">
|
||
|
|
{device['Device Model Name'] || '-'}
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<Label>Serial Number</Label>
|
||
|
|
<p className="text-sm text-muted-foreground font-mono mt-1">
|
||
|
|
{device['Serial Number'] || '-'}
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<Label>Current User</Label>
|
||
|
|
<p className="text-sm text-muted-foreground mt-1">
|
||
|
|
{device['Current User'] || '-'}
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<Label>Status</Label>
|
||
|
|
<div className="flex items-center gap-2 mt-1">
|
||
|
|
{isOnline ? (
|
||
|
|
<Badge variant="default" className="bg-green-600">
|
||
|
|
<Wifi className="w-3 h-3 mr-1" />
|
||
|
|
Online
|
||
|
|
</Badge>
|
||
|
|
) : (
|
||
|
|
<Badge variant="secondary">
|
||
|
|
<XCircle className="w-3 h-3 mr-1" />
|
||
|
|
Offline
|
||
|
|
</Badge>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{device['Last Check In'] && (
|
||
|
|
<div>
|
||
|
|
<Label>Last Check In</Label>
|
||
|
|
<p className="text-sm text-muted-foreground mt-1">
|
||
|
|
{new Date(device['Last Check In']).toLocaleString()}
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* System Information */}
|
||
|
|
<div className="space-y-4">
|
||
|
|
<h3 className="font-semibold flex items-center gap-2">
|
||
|
|
<HardDrive className="w-4 h-4" />
|
||
|
|
System Information
|
||
|
|
</h3>
|
||
|
|
|
||
|
|
<div className="space-y-3">
|
||
|
|
<div>
|
||
|
|
<Label>Operating System</Label>
|
||
|
|
<p className="text-sm text-muted-foreground mt-1">
|
||
|
|
{device['MAC OS X Version'] || device['iOS Version'] || '-'}
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{device['Processor Type'] && (
|
||
|
|
<div>
|
||
|
|
<Label>Processor</Label>
|
||
|
|
<p className="text-sm text-muted-foreground mt-1">
|
||
|
|
{device['Processor Type']}
|
||
|
|
{device['Processor Speed (GHz)'] && ` @ ${device['Processor Speed (GHz)']} GHz`}
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
|
||
|
|
{device['Total Disk Space (GB)'] && (
|
||
|
|
<div>
|
||
|
|
<Label>Disk Space</Label>
|
||
|
|
<div className="mt-1">
|
||
|
|
<p className="text-sm text-muted-foreground">
|
||
|
|
{device['Free Disk Space (GB)']} GB free of {device['Total Disk Space (GB)']} GB
|
||
|
|
</p>
|
||
|
|
{freeSpacePercentage !== undefined && (
|
||
|
|
<div className="flex items-center gap-2 mt-1">
|
||
|
|
<div className="flex-1 h-2 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
|
||
|
|
<div
|
||
|
|
className={`h-full ${
|
||
|
|
freeSpacePercentage < 10 ? 'bg-red-500' :
|
||
|
|
freeSpacePercentage < 20 ? 'bg-orange-500' :
|
||
|
|
'bg-green-500'
|
||
|
|
}`}
|
||
|
|
style={{ width: `${freeSpacePercentage}%` }}
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
<span className="text-xs text-muted-foreground">{freeSpacePercentage.toFixed(1)}%</span>
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
|
||
|
|
{batteryPercentage !== undefined && (
|
||
|
|
<div>
|
||
|
|
<Label>Battery</Label>
|
||
|
|
<div className="flex items-center gap-2 mt-1">
|
||
|
|
<Battery className={`w-4 h-4 ${isCharging ? 'text-green-600' : ''}`} />
|
||
|
|
<span className="text-sm text-muted-foreground">
|
||
|
|
{batteryPercentage}%
|
||
|
|
{isCharging && ' (Charging)'}
|
||
|
|
</span>
|
||
|
|
{device['Battery Capacity Loss Percentage'] !== undefined && (
|
||
|
|
<span className="text-xs text-muted-foreground">
|
||
|
|
({device['Battery Capacity Loss Percentage']}% capacity loss)
|
||
|
|
</span>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<Label>Agent Version</Label>
|
||
|
|
<p className="text-sm text-muted-foreground mt-1">
|
||
|
|
{device['Agent Version'] || '-'}
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{device.Timezone && (
|
||
|
|
<div>
|
||
|
|
<Label>Timezone</Label>
|
||
|
|
<p className="text-sm text-muted-foreground mt-1">
|
||
|
|
{device.Timezone}
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* Security & Features */}
|
||
|
|
<div className="space-y-4">
|
||
|
|
<h3 className="font-semibold flex items-center gap-2">
|
||
|
|
<Shield className="w-4 h-4" />
|
||
|
|
Security & Features
|
||
|
|
</h3>
|
||
|
|
|
||
|
|
<div className="space-y-3">
|
||
|
|
<div>
|
||
|
|
<Label>Firewall</Label>
|
||
|
|
<div className="flex items-center gap-2 mt-1">
|
||
|
|
{device['Firewall Enabled'] ? (
|
||
|
|
<Badge variant="default" className="bg-green-600">
|
||
|
|
<CheckCircle className="w-3 h-3 mr-1" />
|
||
|
|
Enabled
|
||
|
|
</Badge>
|
||
|
|
) : (
|
||
|
|
<Badge variant="destructive">
|
||
|
|
<XCircle className="w-3 h-3 mr-1" />
|
||
|
|
Disabled
|
||
|
|
</Badge>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<Label>FileVault</Label>
|
||
|
|
<div className="flex items-center gap-2 mt-1">
|
||
|
|
{device['FileVault Enabled'] ? (
|
||
|
|
<Badge variant="default" className="bg-green-600">
|
||
|
|
<CheckCircle className="w-3 h-3 mr-1" />
|
||
|
|
Enabled
|
||
|
|
</Badge>
|
||
|
|
) : (
|
||
|
|
<Badge variant="destructive">
|
||
|
|
<XCircle className="w-3 h-3 mr-1" />
|
||
|
|
Disabled
|
||
|
|
</Badge>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{device['Remote Login Enabled'] !== undefined && (
|
||
|
|
<div>
|
||
|
|
<Label>Remote Login</Label>
|
||
|
|
<div className="flex items-center gap-2 mt-1">
|
||
|
|
{device['Remote Login Enabled'] ? (
|
||
|
|
<Badge variant="outline">
|
||
|
|
<CheckCircle className="w-3 h-3 mr-1" />
|
||
|
|
Enabled
|
||
|
|
</Badge>
|
||
|
|
) : (
|
||
|
|
<Badge variant="secondary">
|
||
|
|
<XCircle className="w-3 h-3 mr-1" />
|
||
|
|
Disabled
|
||
|
|
</Badge>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
|
||
|
|
{device['SMART Failing'] !== undefined && (
|
||
|
|
<div>
|
||
|
|
<Label>SMART Status</Label>
|
||
|
|
<div className="flex items-center gap-2 mt-1">
|
||
|
|
{device['SMART Failing'] ? (
|
||
|
|
<Badge variant="destructive">
|
||
|
|
<AlertCircle className="w-3 h-3 mr-1" />
|
||
|
|
Failing
|
||
|
|
</Badge>
|
||
|
|
) : (
|
||
|
|
<Badge variant="default" className="bg-green-600">
|
||
|
|
<CheckCircle className="w-3 h-3 mr-1" />
|
||
|
|
Healthy
|
||
|
|
</Badge>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
|
||
|
|
{device['Has Wireless'] !== undefined && (
|
||
|
|
<div>
|
||
|
|
<Label>Wireless Capability</Label>
|
||
|
|
<p className="text-sm text-muted-foreground mt-1">
|
||
|
|
{device['Has Wireless'] ? 'Yes' : 'No'}
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
|
||
|
|
{device['XCode Installed'] !== undefined && (
|
||
|
|
<div>
|
||
|
|
<Label>XCode</Label>
|
||
|
|
<p className="text-sm text-muted-foreground mt-1">
|
||
|
|
{device['XCode Installed'] ? 'Installed' : 'Not Installed'}
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{/* Additional Information */}
|
||
|
|
<div className="space-y-4">
|
||
|
|
<h3 className="font-semibold flex items-center gap-2">
|
||
|
|
<Info className="w-4 h-4" />
|
||
|
|
Additional Information
|
||
|
|
</h3>
|
||
|
|
|
||
|
|
<div className="space-y-3">
|
||
|
|
<div>
|
||
|
|
<Label>Agent ID</Label>
|
||
|
|
<p className="text-sm text-muted-foreground font-mono mt-1">
|
||
|
|
{device.agentid}
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<Label>Policy ID</Label>
|
||
|
|
<p className="text-sm text-muted-foreground font-mono mt-1">
|
||
|
|
{device.policy_id}
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
{device['Warranty Expiration Date'] && (
|
||
|
|
<div>
|
||
|
|
<Label>Warranty</Label>
|
||
|
|
<p className="text-sm text-muted-foreground mt-1">
|
||
|
|
Expires: {new Date(device['Warranty Expiration Date']).toLocaleDateString()}
|
||
|
|
{device['Warranty Days Left'] !== undefined && (
|
||
|
|
<span className="ml-2">({device['Warranty Days Left']} days left)</span>
|
||
|
|
)}
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
|
||
|
|
{device['TeamViewer Client Id'] && (
|
||
|
|
<div>
|
||
|
|
<Label>TeamViewer ID</Label>
|
||
|
|
<p className="text-sm text-muted-foreground font-mono mt-1">
|
||
|
|
{device['TeamViewer Client Id']}
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
|
||
|
|
{device['Displays Serial Number'] && device['Displays Serial Number'].length > 0 && (
|
||
|
|
<div>
|
||
|
|
<Label>Display Serial Numbers</Label>
|
||
|
|
<div className="text-sm text-muted-foreground font-mono mt-1 space-y-1">
|
||
|
|
{device['Displays Serial Number'].map((serial, idx) => (
|
||
|
|
<div key={idx}>{serial}</div>
|
||
|
|
))}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</CardContent>
|
||
|
|
</Card>
|
||
|
|
);
|
||
|
|
}
|