From b9c795278d1aa27e012b380631b417daeae3f594 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Thu, 8 Jan 2026 12:36:10 +0000 Subject: [PATCH] Revert to version 9bb4dbe --- .../src/components/Comments/ListComments.tsx | 12 +- frontend/src/menuAside.ts | 15 +- frontend/src/pages/dashboard.tsx | 465 +++++++++++++----- frontend/src/pages/leads/kanban.tsx | 64 --- .../pages/leads/{list.tsx => leads-list.tsx} | 2 +- frontend/tailwind.config.js | 2 +- 6 files changed, 346 insertions(+), 214 deletions(-) delete mode 100644 frontend/src/pages/leads/kanban.tsx rename frontend/src/pages/leads/{list.tsx => leads-list.tsx} (98%) diff --git a/frontend/src/components/Comments/ListComments.tsx b/frontend/src/components/Comments/ListComments.tsx index b7ad782..03ee695 100644 --- a/frontend/src/components/Comments/ListComments.tsx +++ b/frontend/src/components/Comments/ListComments.tsx @@ -45,17 +45,7 @@ const ListComments = ({ comments, loading, onDelete, currentPage, numPages, onPa 'flex-1 px-4 py-6 h-24 flex divide-x-2 divide-stone-300 items-center overflow-hidden`}> dark:divide-dark-700 overflow-x-auto' } > -
-
- {item.author?.fullName || 'Anonymous'} -
-
- {dataFormatter.dateFormatter(item.created)} -
-
- {item.content} -
-
+ { - const iconsColor = useAppSelector((state) => state.style.iconsColor) - const corners = useAppSelector((state) => state.style.corners) - const cardsStyle = useAppSelector((state) => state.style.cardsStyle) - const { currentUser } = useAppSelector((state) => state.auth) + 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 = 'Loading...'; - const [leads, setLeads] = React.useState(loadingMessage) - const [projects, setProjects] = React.useState(loadingMessage) - const [tasks, setTasks] = React.useState(loadingMessage) + + const [users, setUsers] = React.useState(loadingMessage); + const [roles, setRoles] = React.useState(loadingMessage); + const [permissions, setPermissions] = React.useState(loadingMessage); + const [leads, setLeads] = React.useState(loadingMessage); + const [projects, setProjects] = React.useState(loadingMessage); + const [tasks, setTasks] = React.useState(loadingMessage); + const [comments, setComments] = React.useState(loadingMessage); + const [attachments, setAttachments] = React.useState(loadingMessage); - async function loadData() { - const entities = ['leads', 'projects', 'tasks'] - const fns = [setLeads, setProjects, setTasks] + + const [widgetsRole, setWidgetsRole] = React.useState({ + role: { value: '', label: '' }, + }); + const { currentUser } = useAppSelector((state) => state.auth); + const { isFetchingQuery } = useAppSelector((state) => state.openAi); + + const { rolesWidgets, loading } = useAppSelector((state) => state.roles); + + + async function loadData() { + const entities = ['users','roles','permissions','leads','projects','tasks','comments','attachments',]; + const fns = [setUsers,setRoles,setPermissions,setLeads,setProjects,setTasks,setComments,setAttachments,]; - 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, index) => { + + if(hasPermission(currentUser, `READ_${entity.toUpperCase()}`)) { + return axios.get(`/${entity.toLowerCase()}/count`); + } else { + fns[index](null); + 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) - } - }) - }) - } - - React.useEffect(() => { - if (!currentUser) return - loadData().then() - }, [currentUser]) + 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); + } + }); + }); + } + + async function getWidgets(roleId) { + await dispatch(fetchWidgets(roleId)); + } + React.useEffect(() => { + if (!currentUser) return; + loadData().then(); + 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(); + }, [widgetsRole?.role?.value]); + return ( <> - {getPageTitle('Dashboard')} + + {getPageTitle('Overview')} + + icon={icon.mdiChartTimelineVariant} + title='Overview' + main> {''} + + {hasPermission(currentUser, 'CREATE_ROLES') && } + {!!rolesWidgets.length && + hasPermission(currentUser, 'CREATE_ROLES') && ( +

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

+ )} -
- {hasPermission(currentUser, 'READ_LEADS') && ( - -
-
-
-
- Potential Leads -
-
{leads}
-
-
+
+ {(isFetchingQuery || loading) && ( +
-
+ className={`${iconsColor} animate-spin mr-5`} + w='w-16' + h='h-16' + size={48} + path={icon.mdiLoading} + />{' '} + Loading widgets...
-
- - )} + )} - {hasPermission(currentUser, 'READ_PROJECTS') && ( - -
-
-
-
- Active Projects -
-
{projects}
-
-
- ( + -
-
-
- - )} + ))} +
- {hasPermission(currentUser, 'READ_TASKS') && ( - -
-
-
-
- Open Tasks + {!!rolesWidgets.length &&
} + +
+ + + {hasPermission(currentUser, 'READ_USERS') && +
+
+
+
+ Users +
+
+ {users} +
+
+
+ +
-
{tasks}
-
-
- -
-
- - )} + } + + {hasPermission(currentUser, 'READ_ROLES') && +
+
+
+
+ Roles +
+
+ {roles} +
+
+
+ +
+
+
+ } + + {hasPermission(currentUser, 'READ_PERMISSIONS') && +
+
+
+
+ Permissions +
+
+ {permissions} +
+
+
+ +
+
+
+ } + + {hasPermission(currentUser, 'READ_LEADS') && +
+
+
+
+ Leads +
+
+ {leads} +
+
+
+ +
+
+
+ } + + {hasPermission(currentUser, 'READ_PROJECTS') && +
+
+
+
+ Projects +
+
+ {projects} +
+
+
+ +
+
+
+ } + + {hasPermission(currentUser, 'READ_TASKS') && +
+
+
+
+ Tasks +
+
+ {tasks} +
+
+
+ +
+
+
+ } + + {hasPermission(currentUser, 'READ_COMMENTS') && +
+
+
+
+ Comments +
+
+ {comments} +
+
+
+ +
+
+
+ } + + {hasPermission(currentUser, 'READ_ATTACHMENTS') && +
+
+
+
+ Attachments +
+
+ {attachments} +
+
+
+ +
+
+
+ } + +
@@ -161,4 +379,3 @@ Dashboard.getLayout = function getLayout(page: ReactElement) { } export default Dashboard - diff --git a/frontend/src/pages/leads/kanban.tsx b/frontend/src/pages/leads/kanban.tsx deleted file mode 100644 index 82e0010..0000000 --- a/frontend/src/pages/leads/kanban.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import { mdiChartTimelineVariant } from '@mdi/js' -import Head from 'next/head' -import React, { ReactElement } from 'react' -import CardBox from '../../components/CardBox' -import LayoutAuthenticated from '../../layouts/Authenticated' -import SectionMain from '../../components/SectionMain' -import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton' -import { getPageTitle } from '../../config' -import BaseButton from '../../components/BaseButton' -import { useAppSelector } from '../../stores/hooks' -import { hasPermission } from '../../helpers/userPermissions' -import KanbanBoard from '../../components/KanbanBoard/KanbanBoard' -import Link from 'next/link' -import { deleteItem, update } from '../../stores/leads/leadsSlice' - -const LeadsKanbanPage = () => { - const { currentUser } = useAppSelector((state) => state.auth) - const hasCreatePermission = currentUser && hasPermission(currentUser, 'CREATE_LEADS') - - const columns = [ - { id: 'New', label: 'New' }, - { id: 'Contacted', label: 'Contacted' }, - { id: 'Qualified', label: 'Qualified' }, - { id: 'Proposal', label: 'Proposal' }, - { id: 'Converted', label: 'Converted' }, - { id: 'Lost', label: 'Lost' }, - ] - - return ( - <> - - {getPageTitle('Leads Kanban')} - - - - {''} - - - - {hasCreatePermission && } -
- Switch to List -
-
- - -
- - ) -} - -LeadsKanbanPage.getLayout = function getLayout(page: ReactElement) { - return {page} -} - -export default LeadsKanbanPage diff --git a/frontend/src/pages/leads/list.tsx b/frontend/src/pages/leads/leads-list.tsx similarity index 98% rename from frontend/src/pages/leads/list.tsx rename to frontend/src/pages/leads/leads-list.tsx index 53df185..1f0e07e 100644 --- a/frontend/src/pages/leads/list.tsx +++ b/frontend/src/pages/leads/leads-list.tsx @@ -117,7 +117,7 @@ const LeadsTablesPage = () => {
- Switch to Kanban + Switch to Table
diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js index 1695dab..c75b32b 100644 --- a/frontend/tailwind.config.js +++ b/frontend/tailwind.config.js @@ -68,7 +68,7 @@ module.exports = { pastelEmeraldTheme: { - text: '#030A0D', + text: '#515564', iconsColor: '#030A0D', mainBG: '#DFECF2', buttonColor: '#030A0D',