ProfileDefaultOption.tsx 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. import { Sparkles } from 'lucide-react';
  2. import { useTranslation } from 'react-i18next';
  3. export type ProfileDefaultScope = 'all' | 'colour';
  4. interface ProfileDefaultOptionProps {
  5. /** "Bambu Lab PLA Basic": the product the default would be for. */
  6. product: string;
  7. colorName: string;
  8. /** Whether the tab was filled in from an existing default. */
  9. prefilled: boolean;
  10. checked: boolean;
  11. onCheckedChange: (checked: boolean) => void;
  12. scope: ProfileDefaultScope;
  13. onScopeChange: (scope: ProfileDefaultScope) => void;
  14. /** No material yet: there is no product to save a default for. */
  15. disabled: boolean;
  16. }
  17. /**
  18. * Below the Printers tab (#1326): says when the tab came from the product's
  19. * profile default, and offers to save what the tab holds as that default.
  20. *
  21. * "All colours" is preselected: it is what saves the work on the first spool
  22. * of every colour, while a colour of its own is for one calibrated apart.
  23. */
  24. export function ProfileDefaultOption({
  25. product,
  26. colorName,
  27. prefilled,
  28. checked,
  29. onCheckedChange,
  30. scope,
  31. onScopeChange,
  32. disabled,
  33. }: ProfileDefaultOptionProps) {
  34. const { t } = useTranslation();
  35. const colour = colorName.trim();
  36. return (
  37. <div className="mt-3 p-3 bg-bambu-dark border border-bambu-dark-tertiary rounded-lg space-y-2">
  38. {prefilled && (
  39. <p className="flex items-center gap-1.5 text-xs text-bambu-green">
  40. <Sparkles className="w-3.5 h-3.5 shrink-0" aria-hidden="true" />
  41. {t('inventory.profileDefaults.prefilled', { product })}
  42. </p>
  43. )}
  44. <label className={`flex items-center gap-2 text-sm ${disabled ? 'text-bambu-gray' : 'text-white cursor-pointer'}`}>
  45. <input
  46. type="checkbox"
  47. checked={checked && !disabled}
  48. disabled={disabled}
  49. onChange={(e) => onCheckedChange(e.target.checked)}
  50. className="w-4 h-4 accent-bambu-green"
  51. />
  52. {disabled
  53. ? t('inventory.profileDefaults.saveNeedsMaterial')
  54. : t('inventory.profileDefaults.saveAsDefault', { product })}
  55. </label>
  56. {checked && !disabled && (
  57. <div role="radiogroup" aria-label={t('inventory.profileDefaults.scope')} className="flex flex-wrap gap-4 pl-6">
  58. <label className="flex items-center gap-2 text-sm text-white cursor-pointer">
  59. <input
  60. type="radio"
  61. name="profile-default-scope"
  62. checked={scope === 'all' || !colour}
  63. onChange={() => onScopeChange('all')}
  64. className="accent-bambu-green"
  65. />
  66. {t('inventory.profileDefaults.allColours')}
  67. </label>
  68. <label className={`flex items-center gap-2 text-sm ${colour ? 'text-white cursor-pointer' : 'text-bambu-gray'}`}>
  69. <input
  70. type="radio"
  71. name="profile-default-scope"
  72. checked={scope === 'colour' && !!colour}
  73. disabled={!colour}
  74. onChange={() => onScopeChange('colour')}
  75. className="accent-bambu-green"
  76. />
  77. {colour
  78. ? t('inventory.profileDefaults.colourOnly', { colour })
  79. : t('inventory.profileDefaults.colourOnlyNeedsColour', { tab: t('inventory.colorAndCostTab') })}
  80. </label>
  81. </div>
  82. )}
  83. </div>
  84. );
  85. }