diff --git a/frontend/src/pages/dashboard.tsx b/frontend/src/pages/dashboard.tsx index 88c7328..2816dae 100644 --- a/frontend/src/pages/dashboard.tsx +++ b/frontend/src/pages/dashboard.tsx @@ -7,146 +7,189 @@ import LayoutAuthenticated from '../layouts/Authenticated' import SectionMain from '../components/SectionMain' import SectionTitleLineWithButton from '../components/SectionTitleLineWithButton' import BaseIcon from "../components/BaseIcon"; +import BaseButton from "../components/BaseButton"; import { getPageTitle } from '../config' import Link from "next/link"; - import { hasPermission } from "../helpers/userPermissions"; import { fetchWidgets } from '../stores/roles/rolesSlice'; import { WidgetCreator } from '../components/WidgetCreator/WidgetCreator'; import { SmartWidget } from '../components/SmartWidget/SmartWidget'; - import { useAppDispatch, useAppSelector } from '../stores/hooks'; + +const EntityCard = ({ entity, label, count, iconPath, iconsColor, corners, cardsStyle }: any) => ( + +
+
+
+
+ {label} +
+
+ {count} +
+
+
+ +
+
+
+ +) + const Dashboard = () => { const dispatch = useAppDispatch(); const iconsColor = useAppSelector((state) => state.style.iconsColor); const corners = useAppSelector((state) => state.style.corners); const cardsStyle = useAppSelector((state) => state.style.cardsStyle); - const loadingMessage = 'Loading...'; - + const loadingMessage = '...'; - const [users, setUsers] = React.useState(loadingMessage); - const [roles, setRoles] = React.useState(loadingMessage); - const [permissions, setPermissions] = React.useState(loadingMessage); - const [tenants, setTenants] = React.useState(loadingMessage); - const [user_roles, setUser_roles] = React.useState(loadingMessage); - const [modules, setModules] = React.useState(loadingMessage); - const [tenant_modules, setTenant_modules] = React.useState(loadingMessage); - const [plans, setPlans] = React.useState(loadingMessage); - const [subscriptions, setSubscriptions] = React.useState(loadingMessage); - const [activation_codes, setActivation_codes] = React.useState(loadingMessage); - const [licenses, setLicenses] = React.useState(loadingMessage); - const [audit_logs, setAudit_logs] = React.useState(loadingMessage); - const [products, setProducts] = React.useState(loadingMessage); - const [stock_movements, setStock_movements] = React.useState(loadingMessage); - const [warehouses, setWarehouses] = React.useState(loadingMessage); - const [warehouse_locations, setWarehouse_locations] = React.useState(loadingMessage); - const [customers, setCustomers] = React.useState(loadingMessage); - const [suppliers, setSuppliers] = React.useState(loadingMessage); - const [invoices, setInvoices] = React.useState(loadingMessage); - const [invoice_items, setInvoice_items] = React.useState(loadingMessage); - const [payments, setPayments] = React.useState(loadingMessage); - const [expenses, setExpenses] = React.useState(loadingMessage); - const [equipment_assets, setEquipment_assets] = React.useState(loadingMessage); - const [orders, setOrders] = React.useState(loadingMessage); - const [order_items, setOrder_items] = React.useState(loadingMessage); - - - const [widgetsRole, setWidgetsRole] = React.useState({ - role: { value: '', label: '' }, - }); + const [counts, setCounts] = React.useState>({}); const { currentUser } = useAppSelector((state) => state.auth); const { isFetchingQuery } = useAppSelector((state) => state.openAi); - const { rolesWidgets, loading } = useAppSelector((state) => state.roles); - - - const organizationId = currentUser?.tenants?.id; - + const [widgetsRole, setWidgetsRole] = React.useState({ role: { value: '', label: '' } }); + + const entities = [ + { key: 'products', label: 'Products', icon: icon.mdiPackageVariant, module: 'Inventory & Storage' }, + { key: 'stock_movements', label: 'Stock Movements', icon: icon.mdiSwapHorizontal, module: 'Inventory & Storage' }, + { key: 'warehouses', label: 'Warehouses', icon: icon.mdiWarehouse, module: 'Inventory & Storage' }, + { key: 'warehouse_locations', label: 'Warehouse Locations', icon: icon.mdiMapMarkerRadius, module: 'Inventory & Storage' }, + { key: 'suppliers', label: 'Suppliers', icon: icon.mdiTruckDelivery, module: 'Inventory & Storage' }, + + { key: 'invoices', label: 'Invoices', icon: icon.mdiInvoice, module: 'Accounting' }, + { key: 'payments', label: 'Payments', icon: icon.mdiCreditCard, module: 'Accounting' }, + { key: 'expenses', label: 'Expenses', icon: icon.mdiClipboardList, module: 'Accounting' }, + { key: 'customers', label: 'Customers', icon: icon.mdiAccountCircle, module: 'Accounting' }, + + { key: 'equipment_assets', label: 'Equipment Assets', icon: icon.mdiWrench, module: 'Assets & Orders' }, + { key: 'orders', label: 'Orders', icon: icon.mdiTruck, module: 'Assets & Orders' }, + + { key: 'users', label: 'Users', icon: icon.mdiAccountGroup, module: 'Administration' }, + { key: 'subscriptions', label: 'Subscriptions', icon: icon.mdiCalendarClock, module: 'Administration' }, + { key: 'activation_codes', label: 'Activation Codes', icon: icon.mdiKey, module: 'Administration' }, + ]; + async function loadData() { - const entities = ['users','roles','permissions','tenants','user_roles','modules','tenant_modules','plans','subscriptions','activation_codes','licenses','audit_logs','products','stock_movements','warehouses','warehouse_locations','customers','suppliers','invoices','invoice_items','payments','expenses','equipment_assets','orders','order_items',]; - const fns = [setUsers,setRoles,setPermissions,setTenants,setUser_roles,setModules,setTenant_modules,setPlans,setSubscriptions,setActivation_codes,setLicenses,setAudit_logs,setProducts,setStock_movements,setWarehouses,setWarehouse_locations,setCustomers,setSuppliers,setInvoices,setInvoice_items,setPayments,setExpenses,setEquipment_assets,setOrders,setOrder_items,]; - - const requests = entities.map((entity, index) => { - - if(hasPermission(currentUser, `READ_${entity.toUpperCase()}`)) { - return axios.get(`/${entity.toLowerCase()}/count`); - } else { - fns[index](null); - return Promise.resolve({data: {count: null}}); + const requests = entities.map((entity) => { + if(hasPermission(currentUser, `READ_${entity.key.toUpperCase()}`)) { + return axios.get(`/${entity.key.toLowerCase()}/count`); } - + return Promise.resolve({ data: { count: null } }); }); - Promise.allSettled(requests).then((results) => { - results.forEach((result, i) => { - if (result.status === 'fulfilled') { - fns[i](result.value.data.count); - } else { - fns[i](result.reason.message); - } - }); + const results = await Promise.allSettled(requests); + const newCounts: Record = {}; + results.forEach((result, i) => { + if (result.status === 'fulfilled') { + newCounts[entities[i].key] = (result.value as any).data.count; + } else { + newCounts[entities[i].key] = 'Error'; + } }); + setCounts(newCounts); } - - async function getWidgets(roleId) { - await dispatch(fetchWidgets(roleId)); - } + React.useEffect(() => { if (!currentUser) return; - loadData().then(); + loadData(); setWidgetsRole({ role: { value: currentUser?.app_role?.id, label: currentUser?.app_role?.name } }); }, [currentUser]); React.useEffect(() => { if (!currentUser || !widgetsRole?.role?.value) return; - getWidgets(widgetsRole?.role?.value || '').then(); + dispatch(fetchWidgets(widgetsRole?.role?.value)); }, [widgetsRole?.role?.value]); - + + const renderModuleGroup = (moduleName: string) => { + const moduleEntities = entities.filter(e => e.module === moduleName && hasPermission(currentUser, `READ_${e.key.toUpperCase()}`)); + if (moduleEntities.length === 0) return null; + + return ( +
+

+ + {moduleName} +

+
+ {moduleEntities.map(e => ( + + ))} +
+
+ ) + } + return ( <> - - {getPageTitle('Overview')} - + {getPageTitle('Overview')} + title='Enterprise Dashboard' + main + > {''} - {hasPermission(currentUser, 'CREATE_ROLES') && +
+
+ +
+
+

DIGIHELP-IMS Premium Active

+

Your enterprise subscription is valid until 2026-12-31

+
+
+
+ + +
+ + + {hasPermission(currentUser, 'CREATE_ROLES') && ( + } - {!!rolesWidgets.length && - hasPermission(currentUser, 'CREATE_ROLES') && ( -

- {`${widgetsRole?.role?.label || 'Users'}'s widgets`} -

- )} + /> + )} -
- {(isFetchingQuery || loading) && ( -
- {' '} - Loading widgets... -
- )} - - { rolesWidgets && - rolesWidgets.map((widget) => ( + {/* Dynamic AI Widgets */} + {(rolesWidgets.length > 0 || isFetchingQuery || loading) && ( +
+

+ + AI Insights & Reports +

+
+ {(isFetchingQuery || loading) && ( +
+ + Generating Insights... +
+ )} + {rolesWidgets.map((widget) => ( { roleId={widgetsRole?.role?.value || ''} admin={hasPermission(currentUser, 'CREATE_ROLES')} /> - ))} -
+ ))} +
+
+ )} + + {/* Grouped Entity Cards */} + {['Inventory & Storage', 'Accounting', 'Assets & Orders', 'Administration'].map(renderModuleGroup)} - {!!rolesWidgets.length &&
} - -
- - - {hasPermission(currentUser, 'READ_USERS') && -
-
-
-
- Users -
-
- {users} -
-
-
- -
-
-
- } - - {hasPermission(currentUser, 'READ_ROLES') && -
-
-
-
- Roles -
-
- {roles} -
-
-
- -
-
-
- } - - {hasPermission(currentUser, 'READ_PERMISSIONS') && -
-
-
-
- Permissions -
-
- {permissions} -
-
-
- -
-
-
- } - - {hasPermission(currentUser, 'READ_TENANTS') && -
-
-
-
- Tenants -
-
- {tenants} -
-
-
- -
-
-
- } - - {hasPermission(currentUser, 'READ_USER_ROLES') && -
-
-
-
- User roles -
-
- {user_roles} -
-
-
- -
-
-
- } - - {hasPermission(currentUser, 'READ_MODULES') && -
-
-
-
- Modules -
-
- {modules} -
-
-
- -
-
-
- } - - {hasPermission(currentUser, 'READ_TENANT_MODULES') && -
-
-
-
- Tenant modules -
-
- {tenant_modules} -
-
-
- -
-
-
- } - - {hasPermission(currentUser, 'READ_PLANS') && -
-
-
-
- Plans -
-
- {plans} -
-
-
- -
-
-
- } - - {hasPermission(currentUser, 'READ_SUBSCRIPTIONS') && -
-
-
-
- Subscriptions -
-
- {subscriptions} -
-
-
- -
-
-
- } - - {hasPermission(currentUser, 'READ_ACTIVATION_CODES') && -
-
-
-
- Activation codes -
-
- {activation_codes} -
-
-
- -
-
-
- } - - {hasPermission(currentUser, 'READ_LICENSES') && -
-
-
-
- Licenses -
-
- {licenses} -
-
-
- -
-
-
- } - - {hasPermission(currentUser, 'READ_AUDIT_LOGS') && -
-
-
-
- Audit logs -
-
- {audit_logs} -
-
-
- -
-
-
- } - - {hasPermission(currentUser, 'READ_PRODUCTS') && -
-
-
-
- Products -
-
- {products} -
-
-
- -
-
-
- } - - {hasPermission(currentUser, 'READ_STOCK_MOVEMENTS') && -
-
-
-
- Stock movements -
-
- {stock_movements} -
-
-
- -
-
-
- } - - {hasPermission(currentUser, 'READ_WAREHOUSES') && -
-
-
-
- Warehouses -
-
- {warehouses} -
-
-
- -
-
-
- } - - {hasPermission(currentUser, 'READ_WAREHOUSE_LOCATIONS') && -
-
-
-
- Warehouse locations -
-
- {warehouse_locations} -
-
-
- -
-
-
- } - - {hasPermission(currentUser, 'READ_CUSTOMERS') && -
-
-
-
- Customers -
-
- {customers} -
-
-
- -
-
-
- } - - {hasPermission(currentUser, 'READ_SUPPLIERS') && -
-
-
-
- Suppliers -
-
- {suppliers} -
-
-
- -
-
-
- } - - {hasPermission(currentUser, 'READ_INVOICES') && -
-
-
-
- Invoices -
-
- {invoices} -
-
-
- -
-
-
- } - - {hasPermission(currentUser, 'READ_INVOICE_ITEMS') && -
-
-
-
- Invoice items -
-
- {invoice_items} -
-
-
- -
-
-
- } - - {hasPermission(currentUser, 'READ_PAYMENTS') && -
-
-
-
- Payments -
-
- {payments} -
-
-
- -
-
-
- } - - {hasPermission(currentUser, 'READ_EXPENSES') && -
-
-
-
- Expenses -
-
- {expenses} -
-
-
- -
-
-
- } - - {hasPermission(currentUser, 'READ_EQUIPMENT_ASSETS') && -
-
-
-
- Equipment assets -
-
- {equipment_assets} -
-
-
- -
-
-
- } - - {hasPermission(currentUser, 'READ_ORDERS') && -
-
-
-
- Orders -
-
- {orders} -
-
-
- -
-
-
- } - - {hasPermission(currentUser, 'READ_ORDER_ITEMS') && -
-
-
-
- Order items -
-
- {order_items} -
-
-
- -
-
-
- } - - -
) diff --git a/frontend/src/pages/index.tsx b/frontend/src/pages/index.tsx index 07380d6..b8c1bc4 100644 --- a/frontend/src/pages/index.tsx +++ b/frontend/src/pages/index.tsx @@ -1,166 +1,192 @@ - -import React, { useEffect, useState } from 'react'; +import React from 'react'; import type { ReactElement } from 'react'; import Head from 'next/head'; import Link from 'next/link'; import BaseButton from '../components/BaseButton'; -import CardBox from '../components/CardBox'; -import SectionFullScreen from '../components/SectionFullScreen'; import LayoutGuest from '../layouts/Guest'; -import BaseDivider from '../components/BaseDivider'; -import BaseButtons from '../components/BaseButtons'; import { getPageTitle } from '../config'; -import { useAppSelector } from '../stores/hooks'; -import CardBoxComponentTitle from "../components/CardBoxComponentTitle"; -import { getPexelsImage, getPexelsVideo } from '../helpers/pexels'; +import { mdiPackageVariant, mdiWarehouse, mdiInvoice, mdiTruck, mdiWrench } from '@mdi/js'; +import BaseIcon from '../components/BaseIcon'; +const features = [ + { + title: 'Inventory Management', + description: 'Track stock levels, products, and movements in real-time.', + icon: mdiPackageVariant, + }, + { + title: 'Storage & Warehouses', + description: 'Manage multiple warehouses and locations with ease.', + icon: mdiWarehouse, + }, + { + title: 'Accounting & Invoices', + description: 'Complete billing system with payments and expense tracking.', + icon: mdiInvoice, + }, + { + title: 'Shipping & Orders', + description: 'Handle customer orders and shipping workflows efficiently.', + icon: mdiTruck, + }, + { + title: 'Asset Management', + description: 'Track equipment and assets across your organization.', + icon: mdiWrench, + }, +]; -export default function Starter() { - const [illustrationImage, setIllustrationImage] = useState({ - src: undefined, - photographer: undefined, - photographer_url: undefined, - }) - const [illustrationVideo, setIllustrationVideo] = useState({video_files: []}) - const [contentType, setContentType] = useState('image'); - const [contentPosition, setContentPosition] = useState('right'); - const textColor = useAppSelector((state) => state.style.linkColor); - - const title = 'DIGIHELP-IMS' - - // Fetch Pexels image/video - useEffect(() => { - async function fetchData() { - const image = await getPexelsImage(); - const video = await getPexelsVideo(); - setIllustrationImage(image); - setIllustrationVideo(video); - } - fetchData(); - }, []); - - const imageBlock = (image) => ( -
-
- - Photo by {image?.photographer} on Pexels - -
-
- ); - - const videoBlock = (video) => { - if (video?.video_files?.length > 0) { - return ( -
- -
- - Video by {video.user.name} on Pexels - -
-
) - } - }; - +export default function LandingPage() { return ( -
+
- {getPageTitle('Starter Page')} + {getPageTitle('DIGIHELP-IMS - Integrated Management Suite')} + - -
- {contentType === 'image' && contentPosition !== 'background' - ? imageBlock(illustrationImage) - : null} - {contentType === 'video' && contentPosition !== 'background' - ? videoBlock(illustrationVideo) - : null} -
- - - -
-

This is a React.js/Node.js app generated by the Flatlogic Web App Generator

-

For guides and documentation please check - your local README.md and the Flatlogic documentation

-
- - - - - -
+ {/* Hero Section */} +
+
+
+
-
- -
-

© 2026 {title}. All rights reserved

- - Privacy Policy - -
+ +
+

+ DIGIHELP-IMS +

+

+ The Integrated Management Suite for Modern Enterprise. + Streamline Inventory, Accounting, and Logistics in one unified platform. +

+
+ + +
+
+ + {/* Features Section */} +
+
+
+

Comprehensive Enterprise Modules

+
+

+ Everything you need to run your business operations smoothly and efficiently. +

+
+ +
+ {features.map((feature, index) => ( +
+
+ +
+

{feature.title}

+

{feature.description}

+
+ ))} +
+
+
+ + {/* How It Works Section */} +
+
+
+

How It Works

+

Scale your business in three simple steps.

+
+
+ {[ + { step: '01', title: 'Register Tenant', desc: 'Create your organization account and subdomain.' }, + { step: '02', title: 'Activate Modules', desc: 'Choose the modules your business needs to grow.' }, + { step: '03', title: 'Start Scaling', desc: 'Onboard your team and automate your workflows.' }, + ].map((item, idx) => ( +
+
{item.step}
+

{item.title}

+

{item.desc}

+
+ ))} +
+
+
+ + {/* Pricing Section */} +
+
+
+

Flexible Subscription Plans

+

Choose a plan that fits your business scale.

+
+
+ {['Weekly', 'Monthly', 'Yearly', 'Lifetime'].map((plan) => ( +
+

{plan}

+
+ {plan === 'Lifetime' ? 'Contact' : '$XX'} +
+
    +
  • ✓ All Modules Included
  • +
  • ✓ Unlimited Users
  • +
  • ✓ Priority Support
  • +
  • ✓ 99.9% Uptime SLA
  • +
+ +
+ ))} +
+
+
+ + {/* Footer */} +
+
+
+
+

DIGIHELP-IMS

+

+ Next-generation enterprise resource planning and management suite. +

+
+
+

Product

+
    +
  • Dashboard
  • +
  • Pricing
  • +
  • Modules
  • +
+
+
+

Legal

+
    +
  • Privacy Policy
  • +
  • Terms of Service
  • +
+
+
+
+

© 2026 DIGIHELP-IMS. All rights reserved.

+
+
+
); } -Starter.getLayout = function getLayout(page: ReactElement) { +LandingPage.getLayout = function getLayout(page: ReactElement) { return {page}; }; -