import {
IconBolt,
IconHelp,
IconMapRoute,
IconPlus,
IconSettings,
IconWifiOff,
} from '@tabler/icons-react'
import { Head, Link, router, usePage } from '@inertiajs/react'
import AppLayout from '~/layouts/AppLayout'
import { getServiceLink } from '~/lib/navigation'
import { ServiceSlim } from '../../types/services'
import DynamicIcon, { DynamicIconName } from '~/components/DynamicIcon'
import { useUpdateAvailable } from '~/hooks/useUpdateAvailable'
import { useSystemSetting } from '~/hooks/useSystemSetting'
import Alert from '~/components/Alert'
import { SERVICE_NAMES } from '../../constants/service_names'
import { useTranslation } from 'react-i18next'
// Maps is a Core Capability (display_order: 4)
const getMapsItem = (t: (key: string) => string) => ({
label: t('menu.maps'),
to: '/maps',
target: '',
description: t('maps.viewOffline'),
icon: ,
installed: true,
displayOrder: 4,
poweredBy: null,
})
// System items shown after all apps
const getSystemItems = (t: (key: string) => string) => [
{
label: t('menu.easySetup'),
to: '/easy-setup',
target: '',
description: t('home.easySetupDesc'),
icon: ,
installed: true,
displayOrder: 50,
poweredBy: null,
},
{
label: t('menu.installApps'),
to: '/settings/apps',
target: '',
description: t('home.installAppsDesc'),
icon: ,
installed: true,
displayOrder: 51,
poweredBy: null,
},
{
label: t('menu.docs'),
to: '/docs/home',
target: '',
description: t('home.docsDesc'),
icon: ,
installed: true,
displayOrder: 52,
poweredBy: null,
},
{
label: t('menu.settings'),
to: '/settings/system',
target: '',
description: t('home.settingsDesc'),
icon: ,
installed: true,
displayOrder: 53,
poweredBy: null,
},
]
interface DashboardItem {
label: string
to: string
target: string
description: string
icon: React.ReactNode
installed: boolean
displayOrder: number
poweredBy: string | null
}
export default function Home(props: {
system: {
services: ServiceSlim[]
}
}) {
const { t } = useTranslation()
const items: DashboardItem[] = []
const updateInfo = useUpdateAvailable()
const { aiAssistantName } = usePage<{ aiAssistantName: string }>().props
// Check if user has visited Easy Setup
const { data: easySetupVisited } = useSystemSetting({
key: 'ui.hasVisitedEasySetup',
})
const shouldHighlightEasySetup = easySetupVisited?.value
? String(easySetupVisited.value) !== 'true'
: false
// Add installed services (non-dependency services only)
props.system.services
.filter((service) => service.installed && service.ui_location)
.forEach((service) => {
items.push({
// Inject custom AI Assistant name if this is the chat service
label:
service.service_name === SERVICE_NAMES.OLLAMA && aiAssistantName
? aiAssistantName
: service.friendly_name || service.service_name,
to: service.ui_location ? getServiceLink(service.ui_location) : '#',
target: '_blank',
description:
service.description ||
`Access the ${service.friendly_name || service.service_name} application`,
icon: service.icon ? (
) : (
),
installed: service.installed,
displayOrder: service.display_order ?? 100,
poweredBy: service.powered_by ?? null,
})
})
// Add Maps as a Core Capability
items.push(getMapsItem(t))
// Add system items
items.push(...getSystemItems(t))
// Sort all items by display order
items.sort((a, b) => a.displayOrder - b.displayOrder)
return (
{updateInfo?.updateAvailable && (
router.visit('/settings/update'),
}}
/>
)}
{items.map((item) => {
const isEasySetup = item.label === t('menu.easySetup')
const shouldHighlight = isEasySetup && shouldHighlightEasySetup
const tileContent = (
{shouldHighlight && (
{t('home.startHere')}
)}
{item.icon}
{item.label}
{item.poweredBy && (
{t('home.poweredBy')} {item.poweredBy}
)}
{item.description}
)
return item.target === '_blank' ? (
{tileContent}
) : (
{tileContent}
)
})}
)
}