import 'dart:ui'; import 'package:flutter/material.dart'; import '../models/filament_model.dart'; class FilamentCard extends StatelessWidget { final FilamentModel filament; final VoidCallback? onEdit; final VoidCallback? onDelete; final VoidCallback? onTap; const FilamentCard({ super.key, required this.filament, this.onEdit, this.onDelete, this.onTap, }); double get _remaining => (filament.weight - filament.weightUsed).clamp(0, filament.weight); double get _progress => filament.weight > 0 ? _remaining / filament.weight : 0; Color get _progressColor { if (_progress > 0.5) return const Color(0xFF4FFFB0); if (_progress > 0.2) return const Color(0xFFFFD166); return const Color(0xFFFF6B6B); } @override Widget build(BuildContext context) { return GestureDetector( onTap: onTap, child: ClipRRect( borderRadius: BorderRadius.circular(20), child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 16, sigmaY: 16), child: Container( decoration: BoxDecoration( color: Colors.white.withValues(alpha: 0.07), borderRadius: BorderRadius.circular(20), border: Border.all( color: Colors.white.withValues(alpha: 0.15), width: 1, ), ), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // ── Header ───────────────────────────────────────── _CardHeader( filament: filament, onEdit: onEdit, onDelete: onDelete, ), // ── Weight Progress ───────────────────────────────── Padding( padding: const EdgeInsets.fromLTRB(16, 0, 16, 4), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( '${_remaining.toStringAsFixed(0)} g verbleibend', style: TextStyle( color: _progressColor, fontSize: 13, fontWeight: FontWeight.w600, ), ), Text( 'von ${filament.weight.toStringAsFixed(0)} g', style: TextStyle( color: Colors.white.withValues(alpha: 0.45), fontSize: 12, ), ), ], ), const SizedBox(height: 6), ClipRRect( borderRadius: BorderRadius.circular(4), child: LinearProgressIndicator( value: _progress, minHeight: 6, backgroundColor: Colors.white.withValues(alpha: 0.12), valueColor: AlwaysStoppedAnimation(_progressColor), ), ), ], ), ), // ── Details ────────────────────────────────────────── Padding( padding: const EdgeInsets.fromLTRB(16, 12, 16, 16), child: Wrap( spacing: 8, runSpacing: 8, children: [ _InfoChip( icon: Icons.thermostat_outlined, label: '${filament.printingTemp}°C Druck', ), _InfoChip( icon: Icons.bed_outlined, label: '${filament.bedTemp}°C Bett', ), _InfoChip( icon: Icons.euro_outlined, label: filament.price.toStringAsFixed(2), ), if (filament.purchaseDate.isNotEmpty) _InfoChip( icon: Icons.calendar_today_outlined, label: filament.purchaseDate, ), ], ), ), // ── Notizen ────────────────────────────────────────── if (filament.notes != null && filament.notes!.isNotEmpty) Padding( padding: const EdgeInsets.fromLTRB(16, 0, 16, 16), child: Text( filament.notes!, style: TextStyle( color: Colors.white.withValues(alpha: 0.5), fontSize: 12, fontStyle: FontStyle.italic, ), maxLines: 2, overflow: TextOverflow.ellipsis, ), ), ], ), ), ), ), ); } } // ── Header ─────────────────────────────────────────────────────────────────── class _CardHeader extends StatelessWidget { final FilamentModel filament; final VoidCallback? onEdit; final VoidCallback? onDelete; const _CardHeader({required this.filament, this.onEdit, this.onDelete}); @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.fromLTRB(16, 16, 8, 12), decoration: BoxDecoration( border: Border( bottom: BorderSide(color: Colors.white.withValues(alpha: 0.08)), ), ), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Farb-Kreis Container( width: 36, height: 36, decoration: BoxDecoration( shape: BoxShape.circle, color: _parseColor(filament.color), border: Border.all( color: Colors.white.withValues(alpha: 0.3), width: 1.5, ), ), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( filament.name, style: const TextStyle( color: Colors.white, fontSize: 17, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 2), Row( children: [ _TypeBadge(label: filament.type), const SizedBox(width: 6), Text( filament.manufacturer, style: TextStyle( color: Colors.white.withValues(alpha: 0.5), fontSize: 12, ), ), ], ), ], ), ), // Edit / Delete Row( mainAxisSize: MainAxisSize.min, children: [ if (onEdit != null) IconButton( icon: const Icon( Icons.edit_outlined, size: 18, color: Colors.white60, ), onPressed: onEdit, tooltip: 'Bearbeiten', ), if (onDelete != null) IconButton( icon: const Icon( Icons.delete_outline, size: 18, color: Color(0xFFFF6B6B), ), onPressed: onDelete, tooltip: 'Löschen', ), ], ), ], ), ); } Color _parseColor(String colorStr) { final knownColors = { 'rot': Colors.red, 'blau': Colors.blue, 'grün': Colors.green, 'grau': Colors.grey, 'schwarz': Colors.black, 'weiß': Colors.white, 'gelb': Colors.yellow, 'orange': Colors.orange, 'lila': Colors.purple, 'pink': Colors.pink, 'braun': Colors.brown, }; final lower = colorStr.toLowerCase(); final known = knownColors[lower]; if (known != null) return known; // Hex-Format #RRGGBB oder RRGGBB final hex = colorStr.replaceAll('#', ''); if (hex.length == 6) { final v = int.tryParse('FF$hex', radix: 16); if (v != null) return Color(v); } return const Color(0xFF7B9FFF); } } class _TypeBadge extends StatelessWidget { final String label; const _TypeBadge({required this.label}); @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.symmetric(horizontal: 7, vertical: 2), decoration: BoxDecoration( color: const Color(0xFF7B9FFF).withValues(alpha: 0.25), borderRadius: BorderRadius.circular(6), border: Border.all( color: const Color(0xFF7B9FFF).withValues(alpha: 0.4), ), ), child: Text( label, style: const TextStyle( color: Color(0xFF7B9FFF), fontSize: 11, fontWeight: FontWeight.w600, ), ), ); } } class _InfoChip extends StatelessWidget { final IconData icon; final String label; const _InfoChip({required this.icon, required this.label}); @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: Colors.white.withValues(alpha: 0.07), borderRadius: BorderRadius.circular(8), border: Border.all(color: Colors.white.withValues(alpha: 0.12)), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon(icon, size: 13, color: Colors.white54), const SizedBox(width: 4), Text( label, style: const TextStyle(color: Colors.white70, fontSize: 12), ), ], ), ); } }