big refactor
This commit is contained in:
@@ -1,13 +1,163 @@
|
||||
<script setup lang="ts">
|
||||
import type { AlertRecipient, CustomAlertRule } from '~/composables/useAlertConfig'
|
||||
|
||||
definePageMeta({ ssr: false })
|
||||
usePageTitle('Alerts & Notifications · Settings')
|
||||
|
||||
const { config, addThreshold, removeThreshold, addPaymentTier, removePaymentTier, addCustomRule, updateCustomRule, removeCustomRule } = useAlertConfig()
|
||||
const toast = useToast()
|
||||
|
||||
// ── Recipient helpers ──────────────────────────────────────────────────────
|
||||
type AlertRecipient = 'handler' | 'manager' | 'customer' | 'custom'
|
||||
|
||||
interface Threshold {
|
||||
id: string
|
||||
daysBefore: number
|
||||
enabled: boolean
|
||||
}
|
||||
|
||||
interface PaymentTier {
|
||||
id: string
|
||||
daysOverdue: number
|
||||
action: string
|
||||
recipients: AlertRecipient[]
|
||||
}
|
||||
|
||||
interface CustomAlertRule {
|
||||
id: string
|
||||
alertName: string
|
||||
field: string
|
||||
operator: string
|
||||
value: number
|
||||
recipients: AlertRecipient[]
|
||||
enabled: boolean
|
||||
}
|
||||
|
||||
interface AlertConfig {
|
||||
emailSender: {
|
||||
senderEmail: string
|
||||
senderDisplayName: string
|
||||
replyToEmail: string
|
||||
}
|
||||
renewals: {
|
||||
enabled: boolean
|
||||
thresholds: Threshold[]
|
||||
}
|
||||
cancellations: {
|
||||
enabled: boolean
|
||||
recipients: AlertRecipient[]
|
||||
}
|
||||
latePayments: {
|
||||
enabled: boolean
|
||||
tiers: PaymentTier[]
|
||||
}
|
||||
creditCardExpiry: {
|
||||
enabled: boolean
|
||||
autoDebitOnly: boolean
|
||||
thresholds: Threshold[]
|
||||
}
|
||||
customRules: CustomAlertRule[]
|
||||
}
|
||||
|
||||
const STORAGE_KEY = 'policy-ui.alerts'
|
||||
|
||||
function loadConfig(): AlertConfig {
|
||||
if (import.meta.client) {
|
||||
const stored = localStorage.getItem(STORAGE_KEY)
|
||||
if (stored) {
|
||||
try {
|
||||
return JSON.parse(stored)
|
||||
} catch {
|
||||
return defaultConfig()
|
||||
}
|
||||
}
|
||||
}
|
||||
return defaultConfig()
|
||||
}
|
||||
|
||||
function defaultConfig(): AlertConfig {
|
||||
return {
|
||||
emailSender: {
|
||||
senderEmail: '',
|
||||
senderDisplayName: '',
|
||||
replyToEmail: ''
|
||||
},
|
||||
renewals: {
|
||||
enabled: true,
|
||||
thresholds: [
|
||||
{ id: '1', daysBefore: 30, enabled: true },
|
||||
{ id: '2', daysBefore: 7, enabled: true }
|
||||
]
|
||||
},
|
||||
cancellations: {
|
||||
enabled: true,
|
||||
recipients: ['handler', 'manager']
|
||||
},
|
||||
latePayments: {
|
||||
enabled: true,
|
||||
tiers: [
|
||||
{ id: '1', daysOverdue: 15, action: 'First reminder', recipients: ['handler'] },
|
||||
{ id: '2', daysOverdue: 30, action: 'Second reminder', recipients: ['handler', 'manager'] },
|
||||
{ id: '3', daysOverdue: 45, action: 'Escalate to collections', recipients: ['handler', 'manager', 'customer'] }
|
||||
]
|
||||
},
|
||||
creditCardExpiry: {
|
||||
enabled: true,
|
||||
autoDebitOnly: true,
|
||||
thresholds: [
|
||||
{ id: '1', daysBefore: 30, enabled: true },
|
||||
{ id: '2', daysBefore: 7, enabled: true }
|
||||
]
|
||||
},
|
||||
customRules: []
|
||||
}
|
||||
}
|
||||
|
||||
const config = ref<AlertConfig>(loadConfig())
|
||||
|
||||
function saveConfig() {
|
||||
if (import.meta.client) {
|
||||
localStorage.setItem(STORAGE_KEY, JSON.stringify(config.value))
|
||||
}
|
||||
}
|
||||
|
||||
function addThreshold(type: 'renewals' | 'creditCardExpiry', days: number) {
|
||||
const id = String(Date.now())
|
||||
config.value[type].thresholds.push({ id, daysBefore: days, enabled: true })
|
||||
saveConfig()
|
||||
}
|
||||
|
||||
function removeThreshold(type: 'renewals' | 'creditCardExpiry', id: string) {
|
||||
config.value[type].thresholds = config.value[type].thresholds.filter(t => t.id !== id)
|
||||
saveConfig()
|
||||
}
|
||||
|
||||
function addPaymentTier(days: number, action: string, recipients: AlertRecipient[]) {
|
||||
const id = String(Date.now())
|
||||
config.value.latePayments.tiers.push({ id, daysOverdue: days, action, recipients: [...recipients] })
|
||||
saveConfig()
|
||||
}
|
||||
|
||||
function removePaymentTier(id: string) {
|
||||
config.value.latePayments.tiers = config.value.latePayments.tiers.filter(t => t.id !== id)
|
||||
saveConfig()
|
||||
}
|
||||
|
||||
function addCustomRule(rule: Omit<CustomAlertRule, 'id'>) {
|
||||
const id = String(Date.now())
|
||||
config.value.customRules.push({ ...rule, id })
|
||||
saveConfig()
|
||||
}
|
||||
|
||||
function updateCustomRule(id: string, updates: Partial<CustomAlertRule>) {
|
||||
const idx = config.value.customRules.findIndex(r => r.id === id)
|
||||
if (idx !== -1) {
|
||||
config.value.customRules[idx] = { ...config.value.customRules[idx], ...updates }
|
||||
saveConfig()
|
||||
}
|
||||
}
|
||||
|
||||
function removeCustomRule(id: string) {
|
||||
config.value.customRules = config.value.customRules.filter(r => r.id !== id)
|
||||
saveConfig()
|
||||
}
|
||||
|
||||
const RECIPIENT_OPTIONS: { id: AlertRecipient; label: string }[] = [
|
||||
{ id: 'handler', label: 'Handler' },
|
||||
{ id: 'manager', label: 'Manager' },
|
||||
@@ -19,9 +169,9 @@ function toggleRecipient(list: AlertRecipient[], r: AlertRecipient) {
|
||||
const idx = list.indexOf(r)
|
||||
if (idx === -1) list.push(r)
|
||||
else list.splice(idx, 1)
|
||||
saveConfig()
|
||||
}
|
||||
|
||||
// ── Threshold add ──────────────────────────────────────────────────────────
|
||||
const newRenewalDays = ref(7)
|
||||
const newCcDays = ref(7)
|
||||
|
||||
@@ -29,19 +179,18 @@ function addRenewalThreshold() {
|
||||
addThreshold('renewals', newRenewalDays.value)
|
||||
newRenewalDays.value = 7
|
||||
}
|
||||
|
||||
function addCcThreshold() {
|
||||
addThreshold('creditCardExpiry', newCcDays.value)
|
||||
newCcDays.value = 7
|
||||
}
|
||||
|
||||
// ── Late payment tier add ──────────────────────────────────────────────────
|
||||
const newLpDays = ref(45)
|
||||
function addNewPaymentTier() {
|
||||
addPaymentTier(newLpDays.value, 'Notify assigned handler', ['handler'])
|
||||
newLpDays.value = 45
|
||||
}
|
||||
|
||||
// ── Custom rule add ────────────────────────────────────────────────────────
|
||||
const FIELD_OPTIONS = [
|
||||
{ value: 'premium', label: 'Annual premium' },
|
||||
{ value: 'policy_count', label: 'Policy count' },
|
||||
@@ -75,7 +224,6 @@ function submitNewRule() {
|
||||
showNewRule.value = false
|
||||
}
|
||||
|
||||
// ── Escalation dot color ───────────────────────────────────────────────────
|
||||
function tierDotClass(idx: number, total: number) {
|
||||
if (total <= 1) return 'al-dot-green'
|
||||
if (idx === total - 1) return 'al-dot-red'
|
||||
@@ -84,6 +232,7 @@ function tierDotClass(idx: number, total: number) {
|
||||
}
|
||||
|
||||
function handleSave() {
|
||||
saveConfig()
|
||||
toast.add({ title: 'Alert configuration saved', color: 'green' })
|
||||
}
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user