WeightDisplay.tsx 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. import { useTranslation } from 'react-i18next';
  2. import { spoolbuddyApi } from '../../api/client';
  3. interface WeightDisplayProps {
  4. weight: number | null;
  5. weightStable: boolean;
  6. deviceOnline: boolean;
  7. deviceId: string | null;
  8. }
  9. export function WeightDisplay({ weight, weightStable, deviceOnline, deviceId }: WeightDisplayProps) {
  10. const { t } = useTranslation();
  11. const handleTare = async () => {
  12. if (!deviceId) return;
  13. try {
  14. await spoolbuddyApi.tare(deviceId);
  15. } catch (e) {
  16. console.error('Failed to tare:', e);
  17. }
  18. };
  19. const formatWeight = (w: number | null) => {
  20. if (w === null) return '--.-';
  21. return w.toFixed(1);
  22. };
  23. return (
  24. <div className="flex flex-col items-center gap-3">
  25. {/* Weight readout */}
  26. <div className="flex items-baseline gap-2">
  27. <span className="text-5xl font-light tabular-nums text-zinc-100">
  28. {formatWeight(weight)}
  29. </span>
  30. <span className="text-xl text-zinc-400">g</span>
  31. </div>
  32. {/* Stability indicator */}
  33. <div className="flex items-center gap-2">
  34. <div className={`w-2 h-2 rounded-full ${
  35. !deviceOnline
  36. ? 'bg-zinc-600'
  37. : weightStable
  38. ? 'bg-green-500 shadow-[0_0_6px_rgba(34,197,94,0.5)]'
  39. : 'bg-amber-500 animate-pulse'
  40. }`} />
  41. <span className="text-xs text-zinc-400">
  42. {!deviceOnline
  43. ? t('spoolbuddy.weight.noReading', 'No reading')
  44. : weightStable
  45. ? t('spoolbuddy.weight.stable', 'Stable')
  46. : t('spoolbuddy.weight.measuring', 'Measuring...')}
  47. </span>
  48. </div>
  49. {/* Tare button */}
  50. <button
  51. onClick={handleTare}
  52. disabled={!deviceOnline || !deviceId}
  53. className="px-4 py-2 text-sm font-medium rounded-lg bg-zinc-800 text-zinc-300 hover:bg-zinc-700 disabled:opacity-40 disabled:cursor-not-allowed transition-colors min-h-[40px]"
  54. >
  55. {t('spoolbuddy.weight.tare', 'Tare')}
  56. </button>
  57. </div>
  58. );
  59. }