feat(invoices): expose the automatic reminder kill switch in settings (#1476)
* feat(invoices): expose the automatic reminder kill switch in settings The send_invoice_reminders column, API schema, and cron processor check already existed, but no UI ever exposed the toggle. Add a switch in Settings -> Fakturering (day thresholds fold away when off, values preserved), and make the invoice detail Paminnelser card say reminders are off instead of promising emails that will never be sent. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(invoices): do not assume reminders enabled before settings load CodeRabbit finding on PR 1476: with no company_settings row loaded, the Paminnelser card defaulted to promising the reminder schedule. Track the toggle as boolean | null and render no schedule text until the settings row has actually resolved. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
741cdcc60e
commit
d4b0bd3df1
@@ -169,6 +169,8 @@ export default function InvoiceDetailPage({ params }: { params: Promise<{ id: st
|
||||
const [showBookConfirm, setShowBookConfirm] = useState(false)
|
||||
const [bookVoucherPreview, setBookVoucherPreview] = useState<string | null>(null)
|
||||
const [reminderDays, setReminderDays] = useState<[number, number, number]>([15, 30, 45])
|
||||
// null = settings row not loaded; don't promise a reminder schedule then.
|
||||
const [autoRemindersEnabled, setAutoRemindersEnabled] = useState<boolean | null>(null)
|
||||
|
||||
const statusLabel = (status: InvoiceStatus): string => t(`status_${status}`)
|
||||
const reminderLevelLabel = (level: 1 | 2 | 3): string => t(`reminder_level_${level}`)
|
||||
@@ -213,7 +215,7 @@ export default function InvoiceDetailPage({ params }: { params: Promise<{ id: st
|
||||
const settingsPromise = company?.id
|
||||
? supabase
|
||||
.from('company_settings')
|
||||
.select('ore_rounding, vat_registered, accounting_method, defer_invoice_booking, reminder_days_level_1, reminder_days_level_2, reminder_days_level_3')
|
||||
.select('ore_rounding, vat_registered, accounting_method, defer_invoice_booking, reminder_days_level_1, reminder_days_level_2, reminder_days_level_3, send_invoice_reminders')
|
||||
.eq('company_id', company.id)
|
||||
.maybeSingle()
|
||||
: Promise.resolve(null)
|
||||
@@ -311,6 +313,9 @@ export default function InvoiceDetailPage({ params }: { params: Promise<{ id: st
|
||||
settings?.reminder_days_level_2 ?? 30,
|
||||
settings?.reminder_days_level_3 ?? 45,
|
||||
])
|
||||
if (settings) {
|
||||
setAutoRemindersEnabled(settings.send_invoice_reminders ?? true)
|
||||
}
|
||||
}
|
||||
|
||||
// Related documents need the invoice row but do not gate the main detail
|
||||
@@ -1480,13 +1485,15 @@ export default function InvoiceDetailPage({ params }: { params: Promise<{ id: st
|
||||
<Bell className="h-5 w-5" />
|
||||
{t('reminders_card_title')}
|
||||
</CardTitle>
|
||||
{reminders.length === 0 && (
|
||||
{reminders.length === 0 && autoRemindersEnabled !== null && (
|
||||
<CardDescription>
|
||||
{t('reminders_description', {
|
||||
day1: reminderDays[0],
|
||||
day2: reminderDays[1],
|
||||
day3: reminderDays[2],
|
||||
})}
|
||||
{autoRemindersEnabled
|
||||
? t('reminders_description', {
|
||||
day1: reminderDays[0],
|
||||
day2: reminderDays[1],
|
||||
day3: reminderDays[2],
|
||||
})
|
||||
: t('reminders_disabled')}
|
||||
</CardDescription>
|
||||
)}
|
||||
</CardHeader>
|
||||
|
||||
Reference in New Issue
Block a user