WIP jordan
This commit is contained in:
205
app/composables/useProfileLayouts.ts
Normal file
205
app/composables/useProfileLayouts.ts
Normal file
@@ -0,0 +1,205 @@
|
||||
import { computed } from 'vue'
|
||||
import { useLocalStorageRef } from '~/utils/useLocalStorageRef'
|
||||
|
||||
/* ── Types ── */
|
||||
|
||||
export type ProfileRole = 'sales' | 'claims' | 'renewals' | 'general_service' | 'management' | 'superadmin'
|
||||
|
||||
export interface ProfileSection {
|
||||
id: string
|
||||
label: string
|
||||
visible: boolean
|
||||
order: number
|
||||
}
|
||||
|
||||
export interface ProfileLayout {
|
||||
id: string
|
||||
role: ProfileRole | string
|
||||
name: string
|
||||
description: string
|
||||
icon: string
|
||||
sections: ProfileSection[]
|
||||
defaultTab: 'policies' | 'claims' | 'payments' | 'activity' | 'history' | 'relationships' | 'notes'
|
||||
isCustom: boolean
|
||||
}
|
||||
|
||||
/* ── Section catalog ── */
|
||||
|
||||
const ALL_SECTION_IDS = [
|
||||
'orientation',
|
||||
'kpi_strip',
|
||||
'quick_policies',
|
||||
'service_actions',
|
||||
'personal_details',
|
||||
'tabbed_content',
|
||||
'documents',
|
||||
] as const
|
||||
|
||||
const SECTION_LABELS: Record<string, string> = {
|
||||
orientation: 'Account Orientation',
|
||||
kpi_strip: 'KPI Strip',
|
||||
quick_policies: 'Quick Policies',
|
||||
service_actions: 'Service Actions',
|
||||
personal_details: 'Personal Details',
|
||||
tabbed_content: 'Tabbed Content',
|
||||
documents: 'Documents',
|
||||
}
|
||||
|
||||
function makeSections(order: string[], hidden: string[] = []): ProfileSection[] {
|
||||
return order.map((id, i) => ({
|
||||
id,
|
||||
label: SECTION_LABELS[id] ?? id,
|
||||
visible: !hidden.includes(id),
|
||||
order: i,
|
||||
}))
|
||||
}
|
||||
|
||||
/* ── Built-in layouts ── */
|
||||
|
||||
function defaultLayouts(): ProfileLayout[] {
|
||||
return [
|
||||
{
|
||||
id: 'sales',
|
||||
role: 'sales',
|
||||
name: 'Sales',
|
||||
description: 'Focus on policies, quotes, and pipeline.',
|
||||
icon: 'i-heroicons-currency-dollar',
|
||||
sections: makeSections([
|
||||
'orientation', 'quick_policies', 'kpi_strip', 'tabbed_content',
|
||||
'service_actions', 'personal_details', 'documents',
|
||||
]),
|
||||
defaultTab: 'policies',
|
||||
isCustom: false,
|
||||
},
|
||||
{
|
||||
id: 'claims',
|
||||
role: 'claims',
|
||||
name: 'Claims',
|
||||
description: 'Focus on claims and service actions.',
|
||||
icon: 'i-heroicons-shield-exclamation',
|
||||
sections: makeSections([
|
||||
'service_actions', 'orientation', 'kpi_strip', 'tabbed_content',
|
||||
'quick_policies', 'personal_details', 'documents',
|
||||
]),
|
||||
defaultTab: 'claims',
|
||||
isCustom: false,
|
||||
},
|
||||
{
|
||||
id: 'renewals',
|
||||
role: 'renewals',
|
||||
name: 'Renewals',
|
||||
description: 'Focus on upcoming events and policies.',
|
||||
icon: 'i-heroicons-arrow-path',
|
||||
sections: makeSections([
|
||||
'orientation', 'quick_policies', 'kpi_strip', 'tabbed_content',
|
||||
'service_actions', 'personal_details', 'documents',
|
||||
]),
|
||||
defaultTab: 'policies',
|
||||
isCustom: false,
|
||||
},
|
||||
{
|
||||
id: 'general_service',
|
||||
role: 'general_service',
|
||||
name: 'General Service',
|
||||
description: 'Balanced default for service representatives.',
|
||||
icon: 'i-heroicons-lifebuoy',
|
||||
sections: makeSections([
|
||||
'orientation', 'kpi_strip', 'quick_policies', 'service_actions',
|
||||
'personal_details', 'tabbed_content', 'documents',
|
||||
]),
|
||||
defaultTab: 'policies',
|
||||
isCustom: false,
|
||||
},
|
||||
{
|
||||
id: 'management',
|
||||
role: 'management',
|
||||
name: 'Management',
|
||||
description: 'KPIs first, everything visible.',
|
||||
icon: 'i-heroicons-chart-bar',
|
||||
sections: makeSections([
|
||||
'kpi_strip', 'orientation', 'service_actions', 'quick_policies',
|
||||
'tabbed_content', 'personal_details', 'documents',
|
||||
]),
|
||||
defaultTab: 'history',
|
||||
isCustom: false,
|
||||
},
|
||||
{
|
||||
id: 'superadmin',
|
||||
role: 'superadmin',
|
||||
name: 'Superadmin',
|
||||
description: 'Everything visible, history focus.',
|
||||
icon: 'i-heroicons-cog-8-tooth',
|
||||
sections: makeSections([
|
||||
'kpi_strip', 'orientation', 'service_actions', 'quick_policies',
|
||||
'tabbed_content', 'personal_details', 'documents',
|
||||
]),
|
||||
defaultTab: 'history',
|
||||
isCustom: false,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
const LAYOUTS_KEY = 'policy-ui-profile-layouts-v1'
|
||||
const ACTIVE_KEY = 'policy-ui-active-profile-layout-v1'
|
||||
|
||||
/* ── Composable ── */
|
||||
|
||||
export function useProfileLayouts() {
|
||||
const layouts = useLocalStorageRef<ProfileLayout[]>(LAYOUTS_KEY, defaultLayouts)
|
||||
|
||||
const activeLayoutId = useLocalStorageRef<{ id: string }>(ACTIVE_KEY, () => ({ id: 'general_service' }))
|
||||
|
||||
const activeLayout = computed<ProfileLayout>(() => {
|
||||
const found = layouts.value.find(l => l.id === activeLayoutId.value.id)
|
||||
return found ?? layouts.value[0] ?? defaultLayouts()[3] // fallback to general_service
|
||||
})
|
||||
|
||||
const sortedSections = computed<ProfileSection[]>(() =>
|
||||
[...activeLayout.value.sections]
|
||||
.filter(s => s.visible)
|
||||
.sort((a, b) => a.order - b.order)
|
||||
)
|
||||
|
||||
function setActiveLayout(id: string) {
|
||||
activeLayoutId.value = { id }
|
||||
}
|
||||
|
||||
function addCustomLayout(layout: Omit<ProfileLayout, 'isCustom'>) {
|
||||
layouts.value = [
|
||||
...layouts.value,
|
||||
{ ...layout, isCustom: true },
|
||||
]
|
||||
}
|
||||
|
||||
function updateLayout(id: string, partial: Partial<ProfileLayout>) {
|
||||
layouts.value = layouts.value.map(l =>
|
||||
l.id === id ? { ...l, ...partial } : l
|
||||
)
|
||||
}
|
||||
|
||||
function removeCustomLayout(id: string) {
|
||||
const target = layouts.value.find(l => l.id === id)
|
||||
if (!target || !target.isCustom) return
|
||||
layouts.value = layouts.value.filter(l => l.id !== id)
|
||||
if (activeLayoutId.value.id === id) {
|
||||
activeLayoutId.value = { id: 'general_service' }
|
||||
}
|
||||
}
|
||||
|
||||
function resetToDefaults() {
|
||||
layouts.value = defaultLayouts()
|
||||
activeLayoutId.value = { id: 'general_service' }
|
||||
}
|
||||
|
||||
return {
|
||||
layouts,
|
||||
activeLayoutId: computed(() => activeLayoutId.value.id),
|
||||
activeLayout,
|
||||
sortedSections,
|
||||
setActiveLayout,
|
||||
addCustomLayout,
|
||||
updateLayout,
|
||||
removeCustomLayout,
|
||||
resetToDefaults,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user