From 06dc063125f4412c15b4e4afdc5d22f9d62f0d53 Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 18 Feb 2026 13:34:44 +0200 Subject: [PATCH] feat: add business identity settings for invoice branding --- src/views/Settings.vue | 129 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) diff --git a/src/views/Settings.vue b/src/views/Settings.vue index 0c41038..c720d88 100644 --- a/src/views/Settings.vue +++ b/src/views/Settings.vue @@ -26,6 +26,8 @@
+ +

General

@@ -380,6 +382,85 @@
+ + +
+ + +

Business Identity

+

This information appears on your invoices.

+ +
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+
+ +
+
+ +
+
+ + +
+
+

PNG or JPG, max 200x80px. Appears on invoice header.

+
+
@@ -468,6 +549,8 @@ + + @@ -554,6 +637,13 @@ const roundingEnabled = ref(false) const roundingIncrement = ref(15) const roundingMethod = ref('nearest') +// Business identity settings +const businessName = ref('') +const businessAddress = ref('') +const businessEmail = ref('') +const businessPhone = ref('') +const businessLogo = ref('') + const roundingIncrements = [ { value: 1, label: '1 minute' }, { value: 5, label: '5 minutes' }, @@ -701,6 +791,40 @@ async function saveRoundingSettings() { await settingsStore.updateSetting('rounding_method', roundingMethod.value) } +// Save business identity settings +async function saveBusinessSettings() { + await settingsStore.updateSetting('business_name', businessName.value) + await settingsStore.updateSetting('business_address', businessAddress.value) + await settingsStore.updateSetting('business_email', businessEmail.value) + await settingsStore.updateSetting('business_phone', businessPhone.value) +} + +async function uploadLogo() { + try { + const { open } = await import('@tauri-apps/plugin-dialog') + const selected = await open({ + filters: [{ name: 'Images', extensions: ['png', 'jpg', 'jpeg'] }] + }) + if (!selected) return + + const { readFile } = await import('@tauri-apps/plugin-fs') + const bytes = await readFile(selected as string) + const ext = (selected as string).toLowerCase().endsWith('.png') ? 'png' : 'jpeg' + const base64 = btoa(String.fromCharCode(...new Uint8Array(bytes))) + const dataUrl = `data:image/${ext};base64,${base64}` + businessLogo.value = dataUrl + await settingsStore.updateSetting('business_logo', dataUrl) + } catch (e) { + console.error('Failed to upload logo:', e) + toastStore.error('Failed to upload logo') + } +} + +async function removeLogo() { + businessLogo.value = '' + await settingsStore.updateSetting('business_logo', '') +} + // Import file handling async function handleImportFile() { try { @@ -816,5 +940,10 @@ onMounted(async () => { roundingEnabled.value = settingsStore.settings.rounding_enabled === 'true' roundingIncrement.value = parseInt(settingsStore.settings.rounding_increment) || 15 roundingMethod.value = settingsStore.settings.rounding_method || 'nearest' + businessName.value = settingsStore.settings.business_name || '' + businessAddress.value = settingsStore.settings.business_address || '' + businessEmail.value = settingsStore.settings.business_email || '' + businessPhone.value = settingsStore.settings.business_phone || '' + businessLogo.value = settingsStore.settings.business_logo || '' })