mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-21 10:15:04 +02:00
implemented pr (worth fixing) feedback
update commit
This commit is contained in:
@@ -36,6 +36,7 @@ export function AddNotificationModal({ provider, onClose }: AddNotificationModal
|
||||
const [onPrintFailed, setOnPrintFailed] = useState(provider?.on_print_failed ?? true);
|
||||
const [onPrintStopped, setOnPrintStopped] = useState(provider?.on_print_stopped ?? true);
|
||||
const [onPrintProgress, setOnPrintProgress] = useState(provider?.on_print_progress ?? false);
|
||||
const [onBillingChargeFailed, setOnBillingChargeFailed] = useState(provider?.on_billing_charge_failed ?? true);
|
||||
const [onPrinterOffline, setOnPrinterOffline] = useState(provider?.on_printer_offline ?? false);
|
||||
const [onPrinterError, setOnPrinterError] = useState(provider?.on_printer_error ?? false);
|
||||
const [onAiFailureDetection, setOnAiFailureDetection] = useState(provider?.on_ai_failure_detection ?? false);
|
||||
@@ -192,6 +193,7 @@ export function AddNotificationModal({ provider, onClose }: AddNotificationModal
|
||||
on_print_failed: onPrintFailed,
|
||||
on_print_stopped: onPrintStopped,
|
||||
on_print_progress: onPrintProgress,
|
||||
on_billing_charge_failed: onBillingChargeFailed,
|
||||
on_printer_offline: onPrinterOffline,
|
||||
on_printer_error: onPrinterError,
|
||||
on_ai_failure_detection: onAiFailureDetection,
|
||||
@@ -605,6 +607,13 @@ export function AddNotificationModal({ provider, onClose }: AddNotificationModal
|
||||
</div>
|
||||
<Toggle checked={onPrintProgress} onChange={setOnPrintProgress} />
|
||||
</div>
|
||||
<div className="flex items-center justify-between col-span-2">
|
||||
<div>
|
||||
<span className="text-sm text-white">{t('notifications.billingChargeFailedLabel')}</span>
|
||||
<span className="text-xs text-bambu-gray ml-1">{t('notifications.billingChargeFailedDescription')}</span>
|
||||
</div>
|
||||
<Toggle checked={onBillingChargeFailed} onChange={setOnBillingChargeFailed} />
|
||||
</div>
|
||||
<div className="flex items-center justify-between col-span-2">
|
||||
<div>
|
||||
<span className="text-sm text-white">{t('notifications.plateClearRequired')}</span>
|
||||
@@ -692,6 +701,7 @@ export function AddNotificationModal({ provider, onClose }: AddNotificationModal
|
||||
if (onPrintFailed) enabledEvents.push({ key: 'on_print_failed', label: t('notifications.failed') });
|
||||
if (onPrintStopped) enabledEvents.push({ key: 'on_print_stopped', label: t('notifications.stopped') });
|
||||
if (onPrintProgress) enabledEvents.push({ key: 'on_print_progress', label: t('notifications.progress') });
|
||||
if (onBillingChargeFailed) enabledEvents.push({ key: 'on_billing_charge_failed', label: t('notifications.billingChargeFailedLabel') });
|
||||
if (onPlateClearRequired) enabledEvents.push({ key: 'on_plate_clear_required', label: t('notifications.plateClearRequired') });
|
||||
if (onBedCooled) enabledEvents.push({ key: 'on_bed_cooled', label: t('notifications.bedCooled') });
|
||||
if (onFirstLayerComplete) enabledEvents.push({ key: 'on_first_layer_complete', label: t('notifications.firstLayerCompleteLabel') });
|
||||
|
||||
@@ -132,6 +132,9 @@ export function NotificationProviderCard({ provider, onEdit }: NotificationProvi
|
||||
{provider.on_print_stopped && (
|
||||
<span className="px-2 py-0.5 bg-orange-100 dark:bg-orange-500/20 text-orange-700 dark:text-orange-400 text-xs rounded">{t('notifications.stopped')}</span>
|
||||
)}
|
||||
{provider.on_billing_charge_failed && (
|
||||
<span className="px-2 py-0.5 bg-red-100 dark:bg-red-600/20 text-red-700 dark:text-red-300 text-xs rounded">{t('notifications.billingChargeFailedLabel')}</span>
|
||||
)}
|
||||
{provider.on_print_progress && (
|
||||
<span className="px-2 py-0.5 bg-yellow-100 dark:bg-yellow-500/20 text-yellow-700 dark:text-yellow-400 text-xs rounded">{t('notifications.progress')}</span>
|
||||
)}
|
||||
@@ -354,6 +357,17 @@ export function NotificationProviderCard({ provider, onEdit }: NotificationProvi
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm text-white">{t('notifications.billingChargeFailedLabel')}</p>
|
||||
<p className="text-xs text-bambu-gray">{t('notifications.billingChargeFailedDescription')}</p>
|
||||
</div>
|
||||
<Toggle
|
||||
checked={provider.on_billing_charge_failed ?? true}
|
||||
onChange={(checked) => updateMutation.mutate({ on_billing_charge_failed: checked })}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<p className="text-sm text-white">{t('notifications.progressMilestones')}</p>
|
||||
|
||||
@@ -15,6 +15,7 @@ export function CostCenterSelect({
|
||||
const { t } = useTranslation();
|
||||
|
||||
if (costCenters.length === 0) return null;
|
||||
const selectedCostCenter = costCenters.find((center) => center.id === selectedCostCenterId);
|
||||
|
||||
return (
|
||||
<div className="space-y-1">
|
||||
@@ -33,6 +34,11 @@ export function CostCenterSelect({
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
{selectedCostCenter?.budget_mode === 'none' && (
|
||||
<p className="text-xs text-bambu-gray">
|
||||
{t('printModal.unlimitedNoBudget', 'Unlimited – no budget limit is set.')}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -315,7 +315,7 @@ export function PrintModal({
|
||||
queryFn: api.getPrinters,
|
||||
});
|
||||
|
||||
const { data: myCostCenters } = useQuery({
|
||||
const { data: myCostCenters, isLoading: loadingCostCenters } = useQuery({
|
||||
queryKey: ['finance', 'cost-centers', 'mine'],
|
||||
queryFn: api.getMyCostCenters,
|
||||
enabled: !!user && billingEnabled,
|
||||
@@ -824,6 +824,11 @@ export function PrintModal({
|
||||
const handleSubmit = async (e?: React.FormEvent, options?: { skipFilamentCheck?: boolean }) => {
|
||||
e?.preventDefault();
|
||||
|
||||
if (billingEnabled && selectedCostCenter == null) {
|
||||
showToast(t('printModal.noPrintableCostCenters'), 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
!options?.skipFilamentCheck &&
|
||||
!settings?.disable_filament_warnings &&
|
||||
@@ -1277,6 +1282,11 @@ export function PrintModal({
|
||||
const canSubmit = useMemo(() => {
|
||||
if (isPending) return false;
|
||||
|
||||
// Billing requires a server-authorized cost center. Wait for the query and
|
||||
// keep submission disabled when the user has no printable center, rather
|
||||
// than letting the API fail with an unexplained 400.
|
||||
if (billingEnabled && (loadingCostCenters || selectedCostCenter == null)) return false;
|
||||
|
||||
// Need valid printer/model selection
|
||||
if (assignmentMode === 'printer' && selectedPrinters.length === 0) return false;
|
||||
// Both are about the single-model case. A cross-model job has no one target
|
||||
@@ -1313,6 +1323,9 @@ export function PrintModal({
|
||||
perPlateReqsFailed,
|
||||
printerStatusLoading,
|
||||
isCrossModel,
|
||||
billingEnabled,
|
||||
loadingCostCenters,
|
||||
selectedCostCenter,
|
||||
]);
|
||||
|
||||
// Quantity only applies for single-printer or model-based assignment (not multi-printer)
|
||||
@@ -1714,6 +1727,15 @@ export function PrintModal({
|
||||
onChange={setSelectedCostCenterId}
|
||||
/>
|
||||
)}
|
||||
{billingEnabled && !loadingCostCenters && printableCostCenters.length === 0 && (
|
||||
<div
|
||||
role="alert"
|
||||
className="p-3 bg-yellow-100 dark:bg-yellow-500/20 border border-yellow-500/50 rounded-lg text-sm text-yellow-800 dark:text-yellow-300 flex items-start gap-2"
|
||||
>
|
||||
<AlertTriangle className="w-4 h-4 mt-0.5 shrink-0" />
|
||||
{t('printModal.noPrintableCostCenters')}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Quantity — create multiple copies (batch). Hidden for multi-printer
|
||||
selection, and for multi-plate files where the per-plate steppers
|
||||
|
||||
Reference in New Issue
Block a user