mirror of
https://github.com/Lifeforge-app/lifeforge.git
synced 2026-06-28 06:46:24 +00:00
25w21
Former-commit-id: 44b553bd067cd5ad00ca0b97a7173decb3356263 [formerly d2ab1d1336bd562b454d7d1f33554e4ad4339e22] [formerly 8e464743040679a782f8bbd644f3943068a5d6da [formerly d9d751bcc11a4b98db62d2669a876734d286d5de]] Former-commit-id: 266f7b659a1b944ba5cd66caef3053ea9208d4fa [formerly f8f75b017f7332a2da7f9ae2f915413319415480] Former-commit-id: 2e3ce847f7d7fbbfcf2ff55f196cbe3cec0c74f6
This commit is contained in:
@@ -1,5 +1,11 @@
|
||||
# Change Log
|
||||
|
||||
### 📌 **dev 25w21 (5/19/2025 - 5/26/2025)**
|
||||
- **Account Settings**: Renamed the folder from `Account` to `Account Settings` for better clarity.
|
||||
- **Code**: Module route configs are now stored in a separate file in each module directory and loaded dynamically in the routing mechanism.
|
||||
- **Code**: Massive mechanism refactor to load module routes dynamically.
|
||||
- **Code**: Renamed `layout` folder to `routes` for better clarity.
|
||||
|
||||
### 📌 **dev 25w20 (5/12/2025 - 5/19/2025)**
|
||||
- **Wallet**: Fixed a bug where the order of the transactions doesn't update when the user update the date of a transaction.
|
||||
- **Wallet**: Fixed a critical bug where the page will crash when user tries to load the dashboard.
|
||||
|
||||
13
src/apps/Achievements/config.tsx
Normal file
13
src/apps/Achievements/config.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
import { IconAward } from '@tabler/icons-react'
|
||||
import { lazy } from 'react'
|
||||
|
||||
import { ModuleConfig } from '../../core/routes/interfaces/routes_interfaces'
|
||||
|
||||
export default {
|
||||
name: 'Achievements',
|
||||
icon: <IconAward />,
|
||||
routes: {
|
||||
achievements: lazy(() => import('.'))
|
||||
},
|
||||
togglable: true
|
||||
} satisfies ModuleConfig
|
||||
12
src/apps/BooksLibrary/config.tsx
Normal file
12
src/apps/BooksLibrary/config.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import { ModuleConfig } from '@core/routes/interfaces/routes_interfaces'
|
||||
import { lazy } from 'react'
|
||||
|
||||
export default {
|
||||
name: 'Books Library',
|
||||
icon: 'tabler:books',
|
||||
provider: lazy(() => import('./providers/BooksLibraryProvider')),
|
||||
routes: {
|
||||
'': lazy(() => import('.'))
|
||||
},
|
||||
togglable: true
|
||||
} satisfies ModuleConfig
|
||||
13
src/apps/Calendar/config.tsx
Normal file
13
src/apps/Calendar/config.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
import { IconCalendar } from '@tabler/icons-react'
|
||||
import { lazy } from 'react'
|
||||
|
||||
import { ModuleConfig } from '../../core/routes/interfaces/routes_interfaces'
|
||||
|
||||
export default {
|
||||
name: 'Calendar',
|
||||
icon: <IconCalendar />,
|
||||
routes: {
|
||||
calendar: lazy(() => import('.'))
|
||||
},
|
||||
togglable: true
|
||||
} satisfies ModuleConfig
|
||||
11
src/apps/CodeTime/config.tsx
Normal file
11
src/apps/CodeTime/config.tsx
Normal file
@@ -0,0 +1,11 @@
|
||||
import { IconCode } from '@tabler/icons-react'
|
||||
import { lazy } from 'react'
|
||||
|
||||
export default {
|
||||
name: 'Code Time',
|
||||
icon: <IconCode />,
|
||||
routes: {
|
||||
'code-time': lazy(() => import('.'))
|
||||
},
|
||||
togglable: true
|
||||
}
|
||||
12
src/apps/CurrencyConverter/config.tsx
Normal file
12
src/apps/CurrencyConverter/config.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import { lazy } from 'react'
|
||||
|
||||
import { ModuleConfig } from '../../core/routes/interfaces/routes_interfaces'
|
||||
|
||||
export default {
|
||||
name: 'Currency Converter',
|
||||
icon: 'tabler:currency-dollar',
|
||||
routes: {
|
||||
'currency-converter': lazy(() => import('.'))
|
||||
},
|
||||
togglable: true
|
||||
} satisfies ModuleConfig
|
||||
12
src/apps/GuitarTabs/config.tsx
Normal file
12
src/apps/GuitarTabs/config.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import { lazy } from 'react'
|
||||
|
||||
import { ModuleConfig } from '../../core/routes/interfaces/routes_interfaces'
|
||||
|
||||
export default {
|
||||
name: 'Guitar Tabs',
|
||||
icon: 'mingcute:guitar-line',
|
||||
routes: {
|
||||
'guitar-tabs': lazy(() => import('.'))
|
||||
},
|
||||
togglable: true
|
||||
} satisfies ModuleConfig
|
||||
15
src/apps/IdeaBox/config.tsx
Normal file
15
src/apps/IdeaBox/config.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import { IconBulb } from '@tabler/icons-react'
|
||||
import { lazy } from 'react'
|
||||
|
||||
import { ModuleConfig } from '../../core/routes/interfaces/routes_interfaces'
|
||||
|
||||
export default {
|
||||
name: 'Idea Box',
|
||||
provider: lazy(() => import('./providers/IdeaBoxProvider')),
|
||||
icon: <IconBulb />,
|
||||
routes: {
|
||||
'': lazy(() => import('./pages/Containers')),
|
||||
':id/*': lazy(() => import('./pages/Ideas'))
|
||||
},
|
||||
togglable: true
|
||||
} satisfies ModuleConfig
|
||||
14
src/apps/MomentVault/config.tsx
Normal file
14
src/apps/MomentVault/config.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import { lazy } from 'react'
|
||||
|
||||
import { ModuleConfig } from '../../core/routes/interfaces/routes_interfaces'
|
||||
|
||||
export default {
|
||||
name: 'Moment Vault',
|
||||
icon: 'tabler:history',
|
||||
hasAI: true,
|
||||
routes: {
|
||||
'moment-vault': lazy(() => import('.'))
|
||||
},
|
||||
togglable: true,
|
||||
requiredAPIKeys: ['openai']
|
||||
} satisfies ModuleConfig
|
||||
13
src/apps/Movies/config.tsx
Normal file
13
src/apps/Movies/config.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
import { lazy } from 'react'
|
||||
|
||||
import { ModuleConfig } from '../../core/routes/interfaces/routes_interfaces'
|
||||
|
||||
export default {
|
||||
name: 'Movies',
|
||||
icon: 'tabler:movie',
|
||||
routes: {
|
||||
movies: lazy(() => import('.'))
|
||||
},
|
||||
togglable: true,
|
||||
requiredAPIKeys: ['tmdb']
|
||||
} satisfies ModuleConfig
|
||||
12
src/apps/Music/config.tsx
Normal file
12
src/apps/Music/config.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import { lazy } from 'react'
|
||||
|
||||
import { ModuleConfig } from '../../core/routes/interfaces/routes_interfaces'
|
||||
|
||||
export default {
|
||||
name: 'Music',
|
||||
icon: 'tabler:music',
|
||||
routes: {
|
||||
music: lazy(() => import('.'))
|
||||
},
|
||||
togglable: true
|
||||
} satisfies ModuleConfig
|
||||
13
src/apps/Passwords/config.tsx
Normal file
13
src/apps/Passwords/config.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
import { lazy } from 'react'
|
||||
|
||||
import { ModuleConfig } from '../../core/routes/interfaces/routes_interfaces'
|
||||
|
||||
export default {
|
||||
name: 'Passwords',
|
||||
icon: 'tabler:key',
|
||||
provider: lazy(() => import('./providers/PasswordsProvider')),
|
||||
routes: {
|
||||
'': lazy(() => import('.'))
|
||||
},
|
||||
togglable: true
|
||||
} satisfies ModuleConfig
|
||||
13
src/apps/RailwayMap/config.tsx
Normal file
13
src/apps/RailwayMap/config.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
import { lazy } from 'react'
|
||||
|
||||
import { ModuleConfig } from '../../core/routes/interfaces/routes_interfaces'
|
||||
|
||||
export default {
|
||||
name: 'Railway Map',
|
||||
icon: 'uil:subway',
|
||||
provider: lazy(() => import('./providers/RailwayMapProvider')),
|
||||
routes: {
|
||||
'': lazy(() => import('.'))
|
||||
},
|
||||
togglable: true
|
||||
} satisfies ModuleConfig
|
||||
12
src/apps/Sudoku/config.tsx
Normal file
12
src/apps/Sudoku/config.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import { lazy } from 'react'
|
||||
|
||||
import { ModuleConfig } from '../../core/routes/interfaces/routes_interfaces'
|
||||
|
||||
export default {
|
||||
name: 'Sudoku',
|
||||
icon: 'uil:table',
|
||||
routes: {
|
||||
sudoku: lazy(() => import('.'))
|
||||
},
|
||||
togglable: true
|
||||
} satisfies ModuleConfig
|
||||
15
src/apps/TodoList/config.tsx
Normal file
15
src/apps/TodoList/config.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import { IconListCheck } from '@tabler/icons-react'
|
||||
import { lazy } from 'react'
|
||||
|
||||
import { ModuleConfig } from '../../core/routes/interfaces/routes_interfaces'
|
||||
|
||||
export default {
|
||||
name: 'Todo List',
|
||||
icon: <IconListCheck />,
|
||||
routes: {
|
||||
'todo-list': lazy(() => import('@apps/TodoList'))
|
||||
},
|
||||
togglable: true,
|
||||
hasAI: true,
|
||||
requiredAPIKeys: ['groq']
|
||||
} satisfies ModuleConfig
|
||||
27
src/apps/VirtualWardrobe/config.tsx
Normal file
27
src/apps/VirtualWardrobe/config.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
import { lazy } from 'react'
|
||||
import { Navigate } from 'react-router'
|
||||
|
||||
import { ModuleConfig } from '../../core/routes/interfaces/routes_interfaces'
|
||||
|
||||
export default {
|
||||
name: 'Virtual Wardrobe',
|
||||
icon: 'tabler:shirt',
|
||||
subsection: [
|
||||
{
|
||||
name: 'Virtual Wardrobe Clothes',
|
||||
icon: 'tabler:shirt',
|
||||
path: 'clothes'
|
||||
},
|
||||
{
|
||||
name: 'Virtual Wardrobe Outfits',
|
||||
icon: 'tabler:layout',
|
||||
path: 'outfits'
|
||||
}
|
||||
],
|
||||
routes: {
|
||||
'virtual-wardrobe': () => <Navigate to="/virtual-wardrobe/clothes" />,
|
||||
'virtual-wardrobe/clothes': lazy(() => import('./pages/Clothes')),
|
||||
'virtual-wardrobe/outfits': lazy(() => import('./pages/Outfits'))
|
||||
},
|
||||
togglable: true
|
||||
} satisfies ModuleConfig
|
||||
40
src/apps/Wallet/config.tsx
Normal file
40
src/apps/Wallet/config.tsx
Normal file
@@ -0,0 +1,40 @@
|
||||
import {
|
||||
IconArrowsExchange,
|
||||
IconBook,
|
||||
IconCurrencyDollar,
|
||||
IconDashboard,
|
||||
IconFileText,
|
||||
IconWallet
|
||||
} from '@tabler/icons-react'
|
||||
import { lazy } from 'react'
|
||||
|
||||
import { ModuleConfig } from '../../core/routes/interfaces/routes_interfaces'
|
||||
|
||||
export default {
|
||||
name: 'Wallet',
|
||||
icon: <IconCurrencyDollar />,
|
||||
hasAI: true,
|
||||
subsection: [
|
||||
{ name: 'Dashboard', icon: <IconDashboard />, path: '' },
|
||||
{
|
||||
name: 'Transactions',
|
||||
icon: <IconArrowsExchange />,
|
||||
path: 'transactions'
|
||||
},
|
||||
{ name: 'Assets', icon: <IconWallet />, path: 'assets' },
|
||||
{ name: 'Ledgers', icon: <IconBook />, path: 'ledgers' },
|
||||
{
|
||||
name: 'Financial Statements',
|
||||
icon: <IconFileText />,
|
||||
path: 'statements'
|
||||
}
|
||||
],
|
||||
routes: {
|
||||
wallet: lazy(() => import('./pages/Dashboard')),
|
||||
'wallet/transactions': lazy(() => import('./pages/Transactions')),
|
||||
'wallet/assets': lazy(() => import('./pages/Assets')),
|
||||
'wallet/ledgers': lazy(() => import('./pages/Ledgers')),
|
||||
'wallet/statements': lazy(() => import('./pages/Statements'))
|
||||
},
|
||||
togglable: true
|
||||
} satisfies ModuleConfig
|
||||
14
src/apps/Wishlist/config.tsx
Normal file
14
src/apps/Wishlist/config.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import { lazy } from 'react'
|
||||
|
||||
import { ModuleConfig } from '../../core/routes/interfaces/routes_interfaces'
|
||||
|
||||
export default {
|
||||
name: 'Wishlist',
|
||||
icon: 'tabler:heart',
|
||||
routes: {
|
||||
wishlist: lazy(() => import('./pages/WishlistList')),
|
||||
'wishlist/:id': lazy(() => import('./pages/WishlistEntries'))
|
||||
},
|
||||
togglable: true,
|
||||
hasAI: true
|
||||
} satisfies ModuleConfig
|
||||
14
src/apps/YoutubeSummarizer/config.tsx
Normal file
14
src/apps/YoutubeSummarizer/config.tsx
Normal file
@@ -0,0 +1,14 @@
|
||||
import { lazy } from 'react'
|
||||
|
||||
import { ModuleConfig } from '../../core/routes/interfaces/routes_interfaces'
|
||||
|
||||
export default {
|
||||
name: 'Youtube Summarizer',
|
||||
icon: 'tabler:brand-youtube',
|
||||
routes: {
|
||||
'youtube-summarizer': lazy(() => import('.'))
|
||||
},
|
||||
togglable: true,
|
||||
requiredAPIKeys: ['groq'],
|
||||
hasAI: true
|
||||
} satisfies ModuleConfig
|
||||
12
src/apps/YoutubeVideos/config.tsx
Normal file
12
src/apps/YoutubeVideos/config.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import { lazy } from 'react'
|
||||
|
||||
import { ModuleConfig } from '../../core/routes/interfaces/routes_interfaces'
|
||||
|
||||
export default {
|
||||
name: 'Youtube Videos',
|
||||
icon: 'tabler:brand-youtube',
|
||||
routes: {
|
||||
'youtube-videos': lazy(() => import('.'))
|
||||
},
|
||||
togglable: true
|
||||
} satisfies ModuleConfig
|
||||
@@ -22,7 +22,7 @@ import '@lifeforge/ui/dist/index.css'
|
||||
|
||||
import './i18n'
|
||||
import './index.css'
|
||||
import AppRouter from './layout/index.tsx'
|
||||
import AppRouter from './routes/index.tsx'
|
||||
|
||||
dayjs.extend(duration)
|
||||
dayjs.extend(isBetween)
|
||||
|
||||
@@ -1,382 +0,0 @@
|
||||
import {
|
||||
IconArrowsExchange,
|
||||
IconAward,
|
||||
IconBook,
|
||||
IconBooks,
|
||||
IconBulb,
|
||||
IconCalendar,
|
||||
IconCode,
|
||||
IconCurrencyDollar,
|
||||
IconDashboard,
|
||||
IconFileText,
|
||||
IconHeart,
|
||||
IconHistory,
|
||||
IconInfoCircle,
|
||||
IconKey,
|
||||
IconLayout,
|
||||
IconListCheck,
|
||||
IconMovie,
|
||||
IconMusic,
|
||||
IconPalette,
|
||||
IconPassword,
|
||||
IconPlug,
|
||||
IconServer,
|
||||
IconShirt,
|
||||
IconUserCog,
|
||||
IconWallet
|
||||
} from '@tabler/icons-react'
|
||||
import { lazy } from 'react'
|
||||
import { Navigate } from 'react-router'
|
||||
|
||||
import { RouteCategory } from './layout/interfaces/routes_interfaces'
|
||||
|
||||
export const ROUTES: RouteCategory[] = [
|
||||
{
|
||||
title: '',
|
||||
items: [
|
||||
{
|
||||
name: 'Dashboard',
|
||||
icon: <IconDashboard />,
|
||||
routes: {
|
||||
dashboard: lazy(() => import('./pages/Dashboard'))
|
||||
},
|
||||
togglable: false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Productivity',
|
||||
items: [
|
||||
{
|
||||
name: 'Idea Box',
|
||||
provider: lazy(() => import('@apps/IdeaBox/providers/IdeaBoxProvider')),
|
||||
icon: <IconBulb />,
|
||||
routes: {
|
||||
'': lazy(() => import('@apps/IdeaBox/pages/Containers')),
|
||||
':id/*': lazy(() => import('@apps/IdeaBox/pages/Ideas'))
|
||||
},
|
||||
togglable: true
|
||||
},
|
||||
{
|
||||
name: 'Todo List',
|
||||
icon: <IconListCheck />,
|
||||
routes: {
|
||||
'todo-list': lazy(() => import('@apps/TodoList'))
|
||||
},
|
||||
togglable: true,
|
||||
hasAI: true,
|
||||
requiredAPIKeys: ['groq']
|
||||
},
|
||||
{
|
||||
name: 'Calendar',
|
||||
icon: <IconCalendar />,
|
||||
routes: {
|
||||
calendar: lazy(() => import('@apps/Calendar'))
|
||||
},
|
||||
togglable: true
|
||||
},
|
||||
{
|
||||
name: 'Code Time',
|
||||
icon: <IconCode />,
|
||||
routes: {
|
||||
'code-time': lazy(() => import('@apps/CodeTime'))
|
||||
},
|
||||
togglable: true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Study',
|
||||
items: []
|
||||
},
|
||||
{
|
||||
title: 'Lifestyle',
|
||||
items: [
|
||||
{
|
||||
name: 'Moment Vault',
|
||||
icon: <IconHistory />,
|
||||
hasAI: true,
|
||||
routes: {
|
||||
'moment-vault': lazy(() => import('@apps/MomentVault'))
|
||||
},
|
||||
togglable: true,
|
||||
requiredAPIKeys: ['openai']
|
||||
},
|
||||
{
|
||||
name: 'Achievements',
|
||||
icon: <IconAward />,
|
||||
routes: {
|
||||
achievements: lazy(() => import('@apps/Achievements'))
|
||||
},
|
||||
togglable: true
|
||||
},
|
||||
{
|
||||
name: 'Virtual Wardrobe',
|
||||
icon: <IconShirt />,
|
||||
subsection: [
|
||||
{
|
||||
name: 'Virtual Wardrobe Clothes',
|
||||
icon: <IconShirt />,
|
||||
path: 'clothes'
|
||||
},
|
||||
{
|
||||
name: 'Virtual Wardrobe Outfits',
|
||||
icon: <IconLayout />,
|
||||
path: 'outfits'
|
||||
}
|
||||
],
|
||||
routes: {
|
||||
'virtual-wardrobe': () => <Navigate to="/virtual-wardrobe/clothes" />,
|
||||
'virtual-wardrobe/clothes': lazy(
|
||||
() => import('@apps/VirtualWardrobe/pages/Clothes')
|
||||
),
|
||||
'virtual-wardrobe/outfits': lazy(
|
||||
() => import('@apps/VirtualWardrobe/pages/Outfits')
|
||||
)
|
||||
},
|
||||
togglable: true
|
||||
},
|
||||
{
|
||||
name: 'Movies',
|
||||
icon: <IconMovie />,
|
||||
routes: {
|
||||
movies: lazy(() => import('@apps/Movies'))
|
||||
},
|
||||
togglable: true,
|
||||
requiredAPIKeys: ['tmdb']
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Finance',
|
||||
items: [
|
||||
{
|
||||
name: 'Wallet',
|
||||
icon: <IconCurrencyDollar />,
|
||||
hasAI: true,
|
||||
subsection: [
|
||||
{ name: 'Dashboard', icon: <IconDashboard />, path: '' },
|
||||
{
|
||||
name: 'Transactions',
|
||||
icon: <IconArrowsExchange />,
|
||||
path: 'transactions'
|
||||
},
|
||||
{ name: 'Assets', icon: <IconWallet />, path: 'assets' },
|
||||
{ name: 'Ledgers', icon: <IconBook />, path: 'ledgers' },
|
||||
{
|
||||
name: 'Financial Statements',
|
||||
icon: <IconFileText />,
|
||||
path: 'statements'
|
||||
}
|
||||
],
|
||||
routes: {
|
||||
wallet: lazy(() => import('@apps/Wallet/pages/Dashboard')),
|
||||
'wallet/transactions': lazy(
|
||||
() => import('@apps/Wallet/pages/Transactions')
|
||||
),
|
||||
'wallet/assets': lazy(() => import('@apps/Wallet/pages/Assets')),
|
||||
'wallet/ledgers': lazy(() => import('@apps/Wallet/pages/Ledgers')),
|
||||
'wallet/statements': lazy(
|
||||
() => import('@apps/Wallet/pages/Statements')
|
||||
)
|
||||
},
|
||||
togglable: true
|
||||
},
|
||||
{
|
||||
name: 'Wishlist',
|
||||
icon: <IconHeart />,
|
||||
routes: {
|
||||
wishlist: lazy(() => import('@apps/Wishlist/pages/WishlistList')),
|
||||
'wishlist/:id': lazy(
|
||||
() => import('@apps/Wishlist/pages/WishlistEntries')
|
||||
)
|
||||
},
|
||||
togglable: true,
|
||||
hasAI: true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Storage',
|
||||
items: [
|
||||
{
|
||||
name: 'Books Library',
|
||||
icon: <IconBooks />,
|
||||
provider: lazy(
|
||||
() => import('@apps/BooksLibrary/providers/BooksLibraryProvider')
|
||||
),
|
||||
routes: {
|
||||
'': lazy(() => import('@apps/BooksLibrary'))
|
||||
},
|
||||
togglable: true
|
||||
},
|
||||
{
|
||||
name: 'Music',
|
||||
icon: <IconMusic />,
|
||||
routes: {
|
||||
music: lazy(() => import('@apps/Music'))
|
||||
},
|
||||
togglable: true
|
||||
},
|
||||
{
|
||||
name: 'Guitar Tabs',
|
||||
icon: 'mingcute:guitar-line',
|
||||
routes: {
|
||||
'guitar-tabs': lazy(() => import('@apps/GuitarTabs'))
|
||||
},
|
||||
togglable: true
|
||||
},
|
||||
{
|
||||
name: 'Youtube Videos',
|
||||
icon: 'tabler:brand-youtube',
|
||||
routes: {
|
||||
'youtube-videos': lazy(() => import('@apps/YoutubeVideos'))
|
||||
},
|
||||
togglable: true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Confidential',
|
||||
items: [
|
||||
{
|
||||
name: 'Passwords',
|
||||
icon: <IconKey />,
|
||||
provider: lazy(
|
||||
() => import('@apps/Passwords/providers/PasswordsProvider')
|
||||
),
|
||||
routes: {
|
||||
'': lazy(() => import('@apps/Passwords'))
|
||||
},
|
||||
togglable: true
|
||||
},
|
||||
{
|
||||
name: 'API Keys',
|
||||
icon: <IconPassword />,
|
||||
routes: {
|
||||
'api-keys': lazy(() => import('./pages/APIKeys'))
|
||||
},
|
||||
togglable: false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Information',
|
||||
items: [
|
||||
{
|
||||
name: 'Railway Map',
|
||||
icon: 'uil:subway',
|
||||
provider: lazy(
|
||||
() => import('@apps/RailwayMap/providers/RailwayMapProvider')
|
||||
),
|
||||
routes: {
|
||||
'': lazy(() => import('@apps/RailwayMap'))
|
||||
},
|
||||
togglable: true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Utilities',
|
||||
items: [
|
||||
{
|
||||
name: 'Sudoku',
|
||||
icon: 'uil:table',
|
||||
routes: {
|
||||
sudoku: lazy(() => import('@apps/Sudoku'))
|
||||
},
|
||||
togglable: true
|
||||
},
|
||||
{
|
||||
name: 'Currency Converter',
|
||||
icon: <IconCurrencyDollar />,
|
||||
routes: {
|
||||
'currency-converter': lazy(() => import('@apps/CurrencyConverter'))
|
||||
},
|
||||
togglable: true
|
||||
},
|
||||
{
|
||||
name: 'Youtube Summarizer',
|
||||
icon: 'tabler:brand-youtube',
|
||||
routes: {
|
||||
'youtube-summarizer': lazy(() => import('@apps/YoutubeSummarizer'))
|
||||
},
|
||||
togglable: true,
|
||||
requiredAPIKeys: ['groq'],
|
||||
hasAI: true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Settings',
|
||||
items: [
|
||||
{
|
||||
name: 'Personalization',
|
||||
icon: <IconPalette />,
|
||||
routes: {
|
||||
personalization: lazy(() => import('./pages/Personalization'))
|
||||
},
|
||||
togglable: false
|
||||
},
|
||||
{
|
||||
name: 'Modules',
|
||||
icon: <IconPlug />,
|
||||
routes: {
|
||||
modules: lazy(() => import('@apps/Modules'))
|
||||
},
|
||||
togglable: false
|
||||
},
|
||||
{
|
||||
name: 'Server Status',
|
||||
icon: <IconServer />,
|
||||
routes: {
|
||||
'server-status': lazy(() => import('./pages/ServerStatus'))
|
||||
},
|
||||
togglable: false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'sso',
|
||||
items: [
|
||||
{
|
||||
name: 'Localization Manager',
|
||||
icon: 'mingcute:translate-line',
|
||||
routes: {
|
||||
'localization-manager': lazy(
|
||||
() => import('./pages/LocalizationManager')
|
||||
)
|
||||
},
|
||||
togglable: false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
items: [
|
||||
{
|
||||
name: 'Documentation',
|
||||
icon: <IconInfoCircle />,
|
||||
routes: {
|
||||
documentation: () => {
|
||||
window.location.href =
|
||||
'https://docs.lifeforge.melvinchia.dev/getting-started/introduction'
|
||||
return <Navigate to="/" />
|
||||
}
|
||||
},
|
||||
togglable: false
|
||||
},
|
||||
{
|
||||
name: 'Account Settings',
|
||||
icon: <IconUserCog />,
|
||||
routes: {
|
||||
account: lazy(() => import('./pages/Account'))
|
||||
},
|
||||
togglable: false,
|
||||
hidden: true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
export default ROUTES
|
||||
13
src/core/pages/AccountSettings/config.tsx
Normal file
13
src/core/pages/AccountSettings/config.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
import { ModuleConfig } from '@core/routes/interfaces/routes_interfaces'
|
||||
import { IconUserCog } from '@tabler/icons-react'
|
||||
import { lazy } from 'react'
|
||||
|
||||
export default {
|
||||
name: 'Account Settings',
|
||||
icon: <IconUserCog />,
|
||||
routes: {
|
||||
account: lazy(() => import('.'))
|
||||
},
|
||||
togglable: false,
|
||||
hidden: true
|
||||
} satisfies ModuleConfig
|
||||
@@ -7,7 +7,7 @@ import PasswordColumn from './components/PasswordColumn'
|
||||
import TwoFAColumn from './components/TwoFAColumn'
|
||||
import { AccountSettingsModals } from './modals'
|
||||
|
||||
function Account() {
|
||||
function AccountSettings() {
|
||||
useModalsEffect(AccountSettingsModals)
|
||||
|
||||
return (
|
||||
@@ -35,4 +35,4 @@ function Account() {
|
||||
)
|
||||
}
|
||||
|
||||
export default Account
|
||||
export default AccountSettings
|
||||
12
src/core/pages/Dashboard/config.tsx
Normal file
12
src/core/pages/Dashboard/config.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import { ModuleConfig } from '@core/routes/interfaces/routes_interfaces'
|
||||
import { IconDashboard } from '@tabler/icons-react'
|
||||
import { lazy } from 'react'
|
||||
|
||||
export default {
|
||||
name: 'Dashboard',
|
||||
icon: <IconDashboard />,
|
||||
routes: {
|
||||
dashboard: lazy(() => import('.'))
|
||||
},
|
||||
togglable: false
|
||||
} satisfies ModuleConfig
|
||||
16
src/core/pages/Documentation/config.tsx
Normal file
16
src/core/pages/Documentation/config.tsx
Normal file
@@ -0,0 +1,16 @@
|
||||
import { ModuleConfig } from '@core/routes/interfaces/routes_interfaces'
|
||||
import { IconInfoCircle } from '@tabler/icons-react'
|
||||
import { Navigate } from 'react-router'
|
||||
|
||||
export default {
|
||||
name: 'Documentation',
|
||||
icon: <IconInfoCircle />,
|
||||
routes: {
|
||||
documentation: () => {
|
||||
window.location.href =
|
||||
'https://docs.lifeforge.melvinchia.dev/getting-started/introduction'
|
||||
return <Navigate to="/" />
|
||||
}
|
||||
},
|
||||
togglable: false
|
||||
} as ModuleConfig
|
||||
12
src/core/pages/LocalizationManager/config.tsx
Normal file
12
src/core/pages/LocalizationManager/config.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import { lazy } from 'react'
|
||||
|
||||
import { ModuleConfig } from '../../routes/interfaces/routes_interfaces'
|
||||
|
||||
export default {
|
||||
name: 'Localization Manager',
|
||||
icon: 'mingcute:translate-line',
|
||||
routes: {
|
||||
'localization-manager': lazy(() => import('.'))
|
||||
},
|
||||
togglable: false
|
||||
} satisfies ModuleConfig
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ModuleConfig } from '@core/routes/interfaces/routes_interfaces'
|
||||
import { Icon } from '@iconify/react'
|
||||
import clsx from 'clsx'
|
||||
import _ from 'lodash'
|
||||
@@ -8,14 +9,12 @@ import { Switch } from '@lifeforge/ui'
|
||||
|
||||
import useComponentBg from '@hooks/useComponentBg'
|
||||
|
||||
import { RouteItem } from '../../core/layout/interfaces/routes_interfaces'
|
||||
|
||||
function ModuleItem({
|
||||
module,
|
||||
enabled,
|
||||
toggleModule
|
||||
}: {
|
||||
module: RouteItem
|
||||
module: ModuleConfig
|
||||
enabled: boolean
|
||||
toggleModule: (moduleName: string) => void
|
||||
}) {
|
||||
11
src/core/pages/Modules/config.tsx
Normal file
11
src/core/pages/Modules/config.tsx
Normal file
@@ -0,0 +1,11 @@
|
||||
import { ModuleConfig } from '@core/routes/interfaces/routes_interfaces'
|
||||
import { lazy } from 'react'
|
||||
|
||||
export default {
|
||||
name: 'Modules',
|
||||
icon: 'tabler:plug',
|
||||
routes: {
|
||||
modules: lazy(() => import('.'))
|
||||
},
|
||||
togglable: false
|
||||
} satisfies ModuleConfig
|
||||
@@ -1,3 +1,4 @@
|
||||
import ROUTES from '@core/routes/Routes'
|
||||
import _ from 'lodash'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { toast } from 'react-toastify'
|
||||
@@ -6,9 +7,8 @@ import { LoadingScreen, ModuleHeader, ModuleWrapper } from '@lifeforge/ui'
|
||||
|
||||
import fetchAPI from '@utils/fetchAPI'
|
||||
|
||||
import ROUTES from '../../core/Routes'
|
||||
import { useAuth } from '../../core/pages/Auth/providers/AuthProvider'
|
||||
import ModuleItem from './ModuleItem'
|
||||
import { useAuth } from '../Auth/providers/AuthProvider'
|
||||
import ModuleItem from './components/ModuleItem'
|
||||
|
||||
function Modules() {
|
||||
const { t } = useTranslation('common.sidebar')
|
||||
12
src/core/pages/Personalization/config.tsx
Normal file
12
src/core/pages/Personalization/config.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import { ModuleConfig } from '@core/routes/interfaces/routes_interfaces'
|
||||
import { IconPalette } from '@tabler/icons-react'
|
||||
import { lazy } from 'react'
|
||||
|
||||
export default {
|
||||
name: 'Personalization',
|
||||
icon: <IconPalette />,
|
||||
routes: {
|
||||
personalization: lazy(() => import('.'))
|
||||
},
|
||||
togglable: false
|
||||
} satisfies ModuleConfig
|
||||
12
src/core/pages/ServerStatus/config.tsx
Normal file
12
src/core/pages/ServerStatus/config.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import { ModuleConfig } from '@core/routes/interfaces/routes_interfaces'
|
||||
import { IconServer } from '@tabler/icons-react'
|
||||
import { lazy } from 'react'
|
||||
|
||||
export default {
|
||||
name: 'Server Status',
|
||||
icon: <IconServer />,
|
||||
routes: {
|
||||
'server-status': lazy(() => import('.'))
|
||||
},
|
||||
togglable: false
|
||||
} satisfies ModuleConfig
|
||||
43
src/core/routes/Routes.tsx
Normal file
43
src/core/routes/Routes.tsx
Normal file
@@ -0,0 +1,43 @@
|
||||
import { ModuleCategory } from './interfaces/routes_interfaces'
|
||||
import RouteItems from './routes.json'
|
||||
|
||||
export const ROUTES: ModuleCategory[] = []
|
||||
|
||||
const modules = import.meta.glob([
|
||||
'../../apps/**/config.tsx',
|
||||
'../pages/**/config.tsx'
|
||||
])
|
||||
|
||||
function resolveAlias(path: string): string {
|
||||
if (path.startsWith('@apps')) {
|
||||
return path.replace('@apps', '../../apps')
|
||||
}
|
||||
if (path.startsWith('@core')) {
|
||||
return path.replace('@core', '../pages')
|
||||
}
|
||||
|
||||
return path
|
||||
}
|
||||
|
||||
for (const route of RouteItems) {
|
||||
const { title, items } = route
|
||||
|
||||
const importPromises = items.map(async item => {
|
||||
const resolved = `${resolveAlias(item)}/config.tsx`
|
||||
const importer = modules[resolved]
|
||||
|
||||
if (!importer) throw new Error(`Module not found: ${resolved}`)
|
||||
|
||||
const mod = (await importer()) as { default: any }
|
||||
return mod.default
|
||||
})
|
||||
|
||||
const awaitedRoutes = await Promise.all(importPromises)
|
||||
|
||||
ROUTES.push({
|
||||
title,
|
||||
items: awaitedRoutes
|
||||
})
|
||||
}
|
||||
|
||||
export default ROUTES
|
||||
@@ -3,7 +3,7 @@ import { Route } from 'react-router'
|
||||
|
||||
import { LoadingScreen, ModalManager } from '@lifeforge/ui'
|
||||
|
||||
import { RouteItem } from '../interfaces/routes_interfaces'
|
||||
import { ModuleConfig } from '../../routes/interfaces/routes_interfaces'
|
||||
import APIKeyStatusProvider from '../providers/APIKeyStatusProvider'
|
||||
|
||||
function ChildRoutesRenderer({
|
||||
@@ -12,7 +12,7 @@ function ChildRoutesRenderer({
|
||||
APIKeys = [],
|
||||
t
|
||||
}: {
|
||||
routes: RouteItem['routes']
|
||||
routes: ModuleConfig['routes']
|
||||
t: any
|
||||
isNested?: boolean
|
||||
APIKeys?: string[]
|
||||
@@ -1,14 +1,14 @@
|
||||
import MainApplication from '@core/routes/components/Layout'
|
||||
import _ from 'lodash'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Route, Routes } from 'react-router'
|
||||
|
||||
import { NotFoundScreen } from '@lifeforge/ui'
|
||||
|
||||
import ROUTES from '../../Routes'
|
||||
import Auth from '../../pages/Auth'
|
||||
import { useAuth } from '../../pages/Auth/providers/AuthProvider'
|
||||
import ROUTES from '../Routes'
|
||||
import ChildRoutesRenderer from './ChildRoutesRenderer'
|
||||
import MainApplication from './Layout'
|
||||
|
||||
function MainRoutesRenderer() {
|
||||
const { t } = useTranslation('common.misc')
|
||||
@@ -29,6 +29,8 @@ function MainRoutesRenderer() {
|
||||
? (() => {
|
||||
const Provider: React.FC = item.provider
|
||||
|
||||
console.log('Provider', Provider)
|
||||
|
||||
return (
|
||||
<Route
|
||||
key={item.name}
|
||||
@@ -10,8 +10,8 @@ import {
|
||||
SidebarTitle
|
||||
} from '@lifeforge/ui'
|
||||
|
||||
import ROUTES from '../../../Routes'
|
||||
import { useAuth } from '../../../pages/Auth/providers/AuthProvider'
|
||||
import ROUTES from '../../Routes'
|
||||
|
||||
function SidebarItems({ query }: { query: string }) {
|
||||
const { userData } = useAuth()
|
||||
@@ -1,7 +1,7 @@
|
||||
import _ from 'lodash'
|
||||
import { useEffect } from 'react'
|
||||
|
||||
import ROUTES from '../../Routes'
|
||||
import ROUTES from '../Routes'
|
||||
|
||||
function useTitleEffect() {
|
||||
useEffect(() => {
|
||||
@@ -1,3 +1,4 @@
|
||||
import MainRoutesRenderer from '@core/routes/components/MainRoutesRenderer'
|
||||
import { useEffect } from 'react'
|
||||
import { useLocation, useNavigate } from 'react-router'
|
||||
|
||||
@@ -12,7 +13,6 @@ import { useModalsEffect } from '@lifeforge/ui'
|
||||
|
||||
import Auth from '../pages/Auth'
|
||||
import { useAuth } from '../pages/Auth/providers/AuthProvider'
|
||||
import MainRoutesRenderer from './components/MainRoutesRenderer'
|
||||
import useAuthEffect from './hooks/useAuthEffect'
|
||||
import useTitleEffect from './hooks/useTitleEffect'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export interface RouteItem {
|
||||
export interface ModuleConfig {
|
||||
name: string
|
||||
icon: React.ReactElement | string
|
||||
provider?:
|
||||
@@ -20,7 +20,7 @@ export interface RouteItem {
|
||||
hidden?: boolean
|
||||
}
|
||||
|
||||
export interface RouteCategory {
|
||||
export interface ModuleCategory {
|
||||
title: string
|
||||
items: RouteItem[]
|
||||
items: ModuleConfig[]
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
import MissingAPIKeyScreen from '@core/routes/components/MissingAPIKeyScreen'
|
||||
|
||||
import { ModuleWrapper, QueryWrapper } from '@lifeforge/ui'
|
||||
|
||||
import useAPIQuery from '@hooks/useAPIQuery'
|
||||
|
||||
import MissingAPIKeyScreen from '../components/MissingAPIKeyScreen'
|
||||
|
||||
function APIKeyStatusProvider({
|
||||
APIKeys,
|
||||
children
|
||||
83
src/core/routes/routes.json
Normal file
83
src/core/routes/routes.json
Normal file
@@ -0,0 +1,83 @@
|
||||
[
|
||||
{
|
||||
"title": "",
|
||||
"items": [
|
||||
"@core/Dashboard"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Productivity",
|
||||
"items": [
|
||||
"@apps/IdeaBox",
|
||||
"@apps/TodoList",
|
||||
"@apps/Calendar",
|
||||
"@apps/CodeTime"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Lifestyle",
|
||||
"items": [
|
||||
"@apps/MomentVault",
|
||||
"@apps/VirtualWardrobe",
|
||||
"@apps/Movies",
|
||||
"@apps/Achievements"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Finance",
|
||||
"items": [
|
||||
"@apps/Wallet",
|
||||
"@apps/Wishlist"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Storage",
|
||||
"items": [
|
||||
"@apps/BooksLibrary",
|
||||
"@apps/Music",
|
||||
"@apps/GuitarTabs",
|
||||
"@apps/YoutubeVideos"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Confidential",
|
||||
"items": [
|
||||
"@apps/Passwords"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Information",
|
||||
"items": [
|
||||
"@apps/RailwayMap"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Utilities",
|
||||
"items": [
|
||||
"@apps/Sudoku",
|
||||
"@apps/CurrencyConverter",
|
||||
"@apps/YoutubeSummarizer"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Settings",
|
||||
"items": [
|
||||
"@core/Personalization",
|
||||
"@core/Modules",
|
||||
"@core/ServerStatus"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "sso",
|
||||
"items": [
|
||||
"@core/LocalizationManager"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "",
|
||||
"items": [
|
||||
"@core/Documentation",
|
||||
"@core/AccountSettings"
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -2,10 +2,16 @@
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"lib": [
|
||||
"ES2020",
|
||||
"DOM",
|
||||
"DOM.Iterable"
|
||||
],
|
||||
"module": "ESNext",
|
||||
"skipLibCheck": true,
|
||||
"types": ["node"],
|
||||
"types": [
|
||||
"node"
|
||||
],
|
||||
/* Bundler mode */
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
@@ -19,19 +25,38 @@
|
||||
"noUnusedParameters": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"paths": {
|
||||
"@components/*": ["./src/components/*"],
|
||||
"@providers/*": ["./src/core/providers/*"],
|
||||
"@hooks/*": ["./src/core/hooks/*"],
|
||||
"@interfaces/*": ["./src/core/interfaces/*"],
|
||||
"@utils/*": ["./src/core/utils/*"],
|
||||
"@apps/*": ["./src/apps/*"],
|
||||
"@security/*": ["./src/core/security/*"]
|
||||
"@components/*": [
|
||||
"./src/components/*"
|
||||
],
|
||||
"@providers/*": [
|
||||
"./src/core/providers/*"
|
||||
],
|
||||
"@hooks/*": [
|
||||
"./src/core/hooks/*"
|
||||
],
|
||||
"@interfaces/*": [
|
||||
"./src/core/interfaces/*"
|
||||
],
|
||||
"@utils/*": [
|
||||
"./src/core/utils/*"
|
||||
],
|
||||
"@apps/*": [
|
||||
"./src/apps/*"
|
||||
],
|
||||
"@security/*": [
|
||||
"./src/core/security/*"
|
||||
],
|
||||
"@core/*": [
|
||||
"./src/core/*"
|
||||
],
|
||||
}
|
||||
},
|
||||
"include": ["./src/**/*"],
|
||||
"include": [
|
||||
"./src/**/*"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.node.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,17 @@ const ReactCompilerConfig = {
|
||||
}
|
||||
}
|
||||
|
||||
export const alias = {
|
||||
'@components': path.resolve(__dirname, './src/components'),
|
||||
'@providers': path.resolve(__dirname, './src/core/providers'),
|
||||
'@hooks': path.resolve(__dirname, './src/core/hooks'),
|
||||
'@interfaces': path.resolve(__dirname, './src/core/interfaces'),
|
||||
'@utils': path.resolve(__dirname, './src/core/utils'),
|
||||
'@apps': path.resolve(__dirname, './src/apps'),
|
||||
'@security': path.resolve(__dirname, './src/core/security'),
|
||||
'@core': path.resolve(__dirname, './src/core')
|
||||
}
|
||||
|
||||
export default defineConfig({
|
||||
envDir: path.resolve(__dirname, './env'),
|
||||
plugins: [
|
||||
@@ -30,15 +41,7 @@ export default defineConfig({
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'@components': path.resolve(__dirname, './src/components'),
|
||||
'@providers': path.resolve(__dirname, './src/core/providers'),
|
||||
'@hooks': path.resolve(__dirname, './src/core/hooks'),
|
||||
'@interfaces': path.resolve(__dirname, './src/core/interfaces'),
|
||||
'@utils': path.resolve(__dirname, './src/core/utils'),
|
||||
'@apps': path.resolve(__dirname, './src/apps'),
|
||||
'@security': path.resolve(__dirname, './src/core/security')
|
||||
}
|
||||
alias
|
||||
},
|
||||
build: {
|
||||
target: 'esnext',
|
||||
|
||||
Reference in New Issue
Block a user