feat: initialize Infra Manager with React, Tailwind CSS, and Inertia.js
- Added main application entry point (app.jsx) and bootstrap file for React setup. - Created Wiki index page (Index.jsx) for documentation and file management. - Implemented utility functions for formatting and status handling in utils.js. - Set up Blade template (app.blade.php) for Inertia.js integration. - Defined API routes for metrics and terminal access in api.php. - Established console commands for scheduled tasks in console.php. - Created web routes for various application features including authentication, hypervisors, containers, cloud accounts, security, backups, and wiki management in web.php. - Developed setup scripts for Windows (setup.ps1) and Linux (setup.sh) environments. - Configured Tailwind CSS for styling with custom themes and animations in tailwind.config.js. - Set up Vite for asset bundling and development server in vite.config.js.
This commit is contained in:
59
resources/js/Components/ui/GlassCard.jsx
Normal file
59
resources/js/Components/ui/GlassCard.jsx
Normal file
@@ -0,0 +1,59 @@
|
||||
import { motion } from 'framer-motion';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
export function GlassCard({ children, className, hover = true, glow, ...props }) {
|
||||
return (
|
||||
<motion.div
|
||||
whileHover={hover ? { y: -2, scale: 1.005 } : undefined}
|
||||
transition={{ type: 'spring', stiffness: 300, damping: 30 }}
|
||||
className={cn(
|
||||
'relative overflow-hidden rounded-xl',
|
||||
'border border-white/10 bg-white/[0.03] backdrop-blur-xl',
|
||||
hover && 'cursor-pointer',
|
||||
glow === 'cyan' && 'hover:border-cyan-500/40 hover:shadow-[0_0_30px_rgba(0,212,255,0.1)]',
|
||||
glow === 'green' && 'hover:border-green-500/40 hover:shadow-[0_0_30px_rgba(0,255,136,0.1)]',
|
||||
glow === 'purple' && 'hover:border-purple-500/40 hover:shadow-[0_0_30px_rgba(157,78,221,0.1)]',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{/* Inner gradient */}
|
||||
<div className="absolute inset-0 bg-gradient-to-br from-white/[0.02] to-transparent pointer-events-none" />
|
||||
<div className="relative z-10">{children}</div>
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
||||
export function StatCard({ title, value, subtitle, icon: Icon, color = 'cyan', trend, className }) {
|
||||
const colors = {
|
||||
cyan: { text: 'text-cyan-400', bg: 'bg-cyan-500/10', border: 'border-cyan-500/20' },
|
||||
green: { text: 'text-green-400', bg: 'bg-green-500/10', border: 'border-green-500/20' },
|
||||
purple: { text: 'text-purple-400', bg: 'bg-purple-500/10', border: 'border-purple-500/20' },
|
||||
orange: { text: 'text-orange-400', bg: 'bg-orange-500/10', border: 'border-orange-500/20' },
|
||||
red: { text: 'text-red-400', bg: 'bg-red-500/10', border: 'border-red-500/20' },
|
||||
blue: { text: 'text-blue-400', bg: 'bg-blue-500/10', border: 'border-blue-500/20' },
|
||||
};
|
||||
const c = colors[color] ?? colors.cyan;
|
||||
|
||||
return (
|
||||
<GlassCard className={cn('p-5', className)} glow={color === 'cyan' ? 'cyan' : undefined}>
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="flex-1">
|
||||
<p className="text-xs font-medium text-white/50 uppercase tracking-wider mb-1">{title}</p>
|
||||
<p className={cn('text-3xl font-bold tracking-tight', c.text)}>{value}</p>
|
||||
{subtitle && <p className="text-xs text-white/40 mt-1">{subtitle}</p>}
|
||||
{trend !== undefined && (
|
||||
<p className={cn('text-xs mt-2', trend >= 0 ? 'text-green-400' : 'text-red-400')}>
|
||||
{trend >= 0 ? '↑' : '↓'} {Math.abs(trend)}% vs last hour
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
{Icon && (
|
||||
<div className={cn('p-2.5 rounded-lg border', c.bg, c.border)}>
|
||||
<Icon className={cn('w-5 h-5', c.text)} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</GlassCard>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user