135 lines
3.6 KiB
TypeScript
135 lines
3.6 KiB
TypeScript
import type { MenuItem } from '~/types/menu'
|
|
|
|
export const useMenuManagement = () => {
|
|
const menuItems = ref<MenuItem[]>([])
|
|
const menuOptions = ref<string[]>([])
|
|
const references = ref<string[]>([])
|
|
const selectedReference = ref('Referensi')
|
|
const isLoading = ref(false)
|
|
|
|
// Load menus from JSON file
|
|
const loadMenus = async () => {
|
|
isLoading.value = true
|
|
try {
|
|
const response = await $fetch<{ success: boolean; data: { menus: MenuItem[]; menuOptions: string[]; references: string[] } }>('/api/menus/list')
|
|
const data = response.data
|
|
menuItems.value = data.menus || []
|
|
menuOptions.value = data.menuOptions || []
|
|
references.value = data.references || []
|
|
} catch (error) {
|
|
console.error('Error loading menus:', error)
|
|
throw error
|
|
} finally {
|
|
isLoading.value = false
|
|
}
|
|
}
|
|
|
|
// Save single menu item
|
|
const saveMenu = async (menuItem: MenuItem) => {
|
|
try {
|
|
const response = await $fetch<{ success: boolean; data: MenuItem }>('/api/menus/save', {
|
|
method: 'POST',
|
|
body: { menuItem, reference: selectedReference.value }
|
|
})
|
|
const data = response.data
|
|
|
|
// Update local state
|
|
const index = menuItems.value.findIndex(item => item.id === menuItem.id)
|
|
if (index >= 0) {
|
|
menuItems.value[index] = data
|
|
} else {
|
|
menuItems.value.push(data)
|
|
}
|
|
|
|
return data
|
|
} catch (error) {
|
|
console.error('Error saving menu:', error)
|
|
throw error
|
|
}
|
|
}
|
|
|
|
// Delete menu item
|
|
const deleteMenu = async (menuId: string) => {
|
|
try {
|
|
await $fetch('/api/menus/delete', {
|
|
method: 'DELETE',
|
|
body: { menuId, reference: selectedReference.value }
|
|
})
|
|
|
|
// Remove from local state
|
|
const removeFromItems = (items: MenuItem[]): MenuItem[] => {
|
|
return items.filter(item => {
|
|
if (item.id === menuId) return false
|
|
if (item.children) {
|
|
item.children = removeFromItems(item.children)
|
|
}
|
|
return true
|
|
})
|
|
}
|
|
|
|
menuItems.value = removeFromItems(menuItems.value)
|
|
} catch (error) {
|
|
console.error('Error deleting menu:', error)
|
|
throw error
|
|
}
|
|
}
|
|
|
|
// Update menu order
|
|
const updateMenuOrder = async (newOrder: MenuItem[]) => {
|
|
try {
|
|
await $fetch('/api/menus/reorder', {
|
|
method: 'POST',
|
|
body: { menus: newOrder, reference: selectedReference.value }
|
|
})
|
|
|
|
menuItems.value = newOrder
|
|
} catch (error) {
|
|
console.error('Error updating menu order:', error)
|
|
throw error
|
|
}
|
|
}
|
|
|
|
// Generate Vue page from menu
|
|
const generatePage = async (menuItem: MenuItem) => {
|
|
try {
|
|
const pageData = {
|
|
name: menuItem.title.replace(/\s+/g, ''),
|
|
path: menuItem.url,
|
|
templateType: 'default',
|
|
metadata: {
|
|
title: menuItem.title,
|
|
description: `Page for ${menuItem.title}`,
|
|
keywords: [menuItem.title.toLowerCase()]
|
|
},
|
|
content: {
|
|
title: menuItem.title,
|
|
icon: menuItem.icon
|
|
}
|
|
}
|
|
|
|
await $fetch('/api/pages/generate', {
|
|
method: 'POST',
|
|
body: pageData
|
|
})
|
|
|
|
return pageData
|
|
} catch (error) {
|
|
console.error('Error generating page:', error)
|
|
throw error
|
|
}
|
|
}
|
|
|
|
return {
|
|
menuItems: readonly(menuItems),
|
|
menuOptions: readonly(menuOptions),
|
|
references: readonly(references),
|
|
selectedReference,
|
|
isLoading: readonly(isLoading),
|
|
loadMenus,
|
|
saveMenu,
|
|
deleteMenu,
|
|
updateMenuOrder,
|
|
generatePage
|
|
}
|
|
}
|