erp-platform/ui/src/views/menu/MenuManager.tsx
2025-08-16 22:47:24 +03:00

174 lines
5.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useState } from 'react'
import { SortableMenuTree } from './SortableMenuTree'
import { MenuItem } from '@/@types/menu'
import { useMenuData } from '@/utils/hooks/useMenuData'
import {
FaRegBell,
FaSpinner,
FaBars,
FaRegSave
} from 'react-icons/fa';
import { Container } from '@/components/shared'
import { Helmet } from 'react-helmet'
import { useLocalization } from '@/utils/hooks/useLocalization'
export const MenuManager = () => {
const { menuItems, setMenuItems, loading, error, refetch, saveMenuData } = useMenuData()
const [isDesignMode, setIsDesignMode] = useState(true)
const [isSaving, setIsSaving] = useState(false)
const { translate } = useLocalization()
const [saveMessage, setSaveMessage] = useState<{
type: 'success' | 'error'
text: string
} | null>(null)
const handleMenuChange = (updatedItems: MenuItem[]) => {
setMenuItems(updatedItems)
}
const handleSave = async () => {
if (!isDesignMode) return
try {
setIsSaving(true)
setSaveMessage(null)
await saveMenuData(menuItems)
setSaveMessage({ type: 'success', text: 'Menu configuration saved successfully!' })
setTimeout(() => setSaveMessage(null), 3000)
setIsDesignMode(false)
} catch (err) {
setSaveMessage({
type: 'error',
text: err instanceof Error ? err.message : 'Failed to save menu configuration',
})
setTimeout(() => setSaveMessage(null), 5000)
} finally {
setIsSaving(false)
}
}
const handleToggleDesignMode = () => {
setIsDesignMode(!isDesignMode)
setSaveMessage(null)
}
if (loading) {
return (
<div className="min-h-screen bg-gray-50 flex items-center justify-center">
<div className="flex items-center gap-3 text-gray-600">
<FaSpinner className="animate-spin" />
<span className="text-lg">Loading menu configuration...</span>
</div>
</div>
)
}
if (error) {
return (
<div className="min-h-screen bg-gray-50 flex items-center justify-center">
<div className="bg-white p-8 rounded-lg shadow-md max-w-md w-full mx-4">
<div className="flex items-center gap-3 text-red-600 mb-4">
<FaRegBell size={24} />
<h2 className="text-lg font-semibold">Error Loading Menu</h2>
</div>
<p className="text-gray-600 mb-6">{error}</p>
<button
onClick={refetch}
className="w-full bg-blue-600 text-white py-2 px-4 rounded-lg hover:bg-blue-700 transition-colors"
>
Retry
</button>
</div>
</div>
)
}
return (
<Container>
<Helmet
titleTemplate="%s | Kurs Platform"
title={translate('::' + 'App.Menus.Manager')}
defaultTitle="Kurs Platform"
></Helmet>
<div className="bg-white rounded px-4 sm:px-4 lg:px-6 py-6">
<div className="flex items-center justify-between mb-6 flex-wrap gap-4">
{/* Sol kısım: Başlık */}
<div className="flex items-center gap-2">
<FaBars size={20} className="text-gray-600" />
<h2 className="text-lg font-semibold text-gray-900">Menu Manager</h2>
<span className="text-sm text-gray-500">({menuItems.length} root items)</span>
</div>
{/* Sağ kısım: Design Mode + Save butonu */}
<div className="flex items-center gap-4">
<div className="flex items-center gap-3">
<span
className={`text-sm font-medium ${isDesignMode ? 'text-blue-600' : 'text-gray-500'}`}
>
Design Mode
</span>
<button
onClick={handleToggleDesignMode}
className={`
relative inline-flex h-6 w-11 items-center rounded-full transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2
${isDesignMode ? 'bg-blue-600' : 'bg-gray-200'}
`}
>
<span
className={`
inline-block h-4 w-4 transform rounded-full bg-white transition-transform duration-200 ease-in-out
${isDesignMode ? 'translate-x-6' : 'translate-x-1'}
`}
/>
</button>
</div>
{
<button
onClick={handleSave}
disabled={!isDesignMode || isSaving}
className={`
flex items-center gap-2 px-4 py-2 rounded-lg transition-colors
${isDesignMode ? 'bg-green-600 hover:bg-green-700 text-white' : 'bg-gray-300 text-gray-500 cursor-not-allowed'}
${isSaving ? 'opacity-50' : ''}
`}
>
{isSaving ? (
<>
<FaSpinner size={16} className="animate-spin" />
Saving...
</>
) : (
<>
<FaRegSave size={16} />
Save Changes
</>
)}
</button>
}
</div>
</div>
{menuItems.length > 0 ? (
<SortableMenuTree
items={menuItems}
onItemsChange={handleMenuChange}
isDesignMode={isDesignMode}
refetch={refetch}
/>
) : (
<div className="text-center py-12 text-gray-500">
<FaBars size={24} className="mx-auto mb-4 text-gray-300" />
<p className="text-lg">No menu items found</p>
<p className="text-sm">Try refreshing the page or contact your administrator</p>
</div>
)}
</div>
</Container>
)
}
export default MenuManager