From 051681e6f38826645e8266af641622d5f88d5a4c Mon Sep 17 00:00:00 2001
From: elforjani13 <39470382+elforjani13@users.noreply.github.com>
Date: Mon, 13 Jun 2022 17:33:54 +0200
Subject: [PATCH] feat: add timesheet & project details.
---
.../ProjectDetailActionsBar.tsx | 99 +++++++++++++++
.../ProjectDetails/ProjectDetailProvider.tsx | 25 ++++
.../ProjectDetails/ProjectDetailTabs.tsx | 65 ++++++++++
.../TimeSheet/TimeSheetDataTable.tsx | 117 ++++++++++++++++++
.../ProjectDetails/TimeSheet/components.tsx | 67 ++++++++++
.../containers/ProjectDetails/index.tsx | 37 ++++++
.../ProjectsLanding/ProjectsDataTable.tsx | 17 ++-
src/containers/Settings/withSettings.js | 3 +-
src/lang/en/index.json | 15 ++-
src/routes/dashboard.js | 10 ++
src/store/settings/settings.reducer.js | 3 +
11 files changed, 455 insertions(+), 3 deletions(-)
create mode 100644 src/containers/Projects/containers/ProjectDetails/ProjectDetailActionsBar.tsx
create mode 100644 src/containers/Projects/containers/ProjectDetails/ProjectDetailProvider.tsx
create mode 100644 src/containers/Projects/containers/ProjectDetails/ProjectDetailTabs.tsx
create mode 100644 src/containers/Projects/containers/ProjectDetails/TimeSheet/TimeSheetDataTable.tsx
create mode 100644 src/containers/Projects/containers/ProjectDetails/TimeSheet/components.tsx
create mode 100644 src/containers/Projects/containers/ProjectDetails/index.tsx
diff --git a/src/containers/Projects/containers/ProjectDetails/ProjectDetailActionsBar.tsx b/src/containers/Projects/containers/ProjectDetails/ProjectDetailActionsBar.tsx
new file mode 100644
index 000000000..8c60ab583
--- /dev/null
+++ b/src/containers/Projects/containers/ProjectDetails/ProjectDetailActionsBar.tsx
@@ -0,0 +1,99 @@
+import React from 'react';
+import {
+ Button,
+ Classes,
+ NavbarDivider,
+ NavbarGroup,
+ Alignment,
+} from '@blueprintjs/core';
+import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
+import {
+ Icon,
+ FormattedMessage as T,
+ DashboardRowsHeightButton,
+} from 'components';
+import withSettings from '../../../Settings/withSettings';
+import withSettingsActions from '../../../Settings/withSettingsActions';
+
+import { compose } from 'utils';
+
+/**
+ * Project detail actions bar.
+ * @returns
+ */
+function ProjectDetailActionsBar({
+ // #withSettings
+ timeSheetsTableSize,
+
+ // #withSettingsActions
+ addSetting,
+}) {
+ // Handle new transaction button click.
+ const handleNewTransactionBtnClick = () => {};
+
+ // Handle table row size change.
+ const handleTableRowSizeChange = (size) => {
+ addSetting('timeSheets', 'tableSize', size);
+ };
+
+ // Handle the refresh button click.
+ const handleRefreshBtnClick = () => {};
+
+ return (
+
+
+ }
+ onClick={handleNewTransactionBtnClick}
+ />
+ }
+ // onClick={}
+ />
+ }
+ // onClick={}
+ />
+
+ }
+ text={}
+ />
+ }
+ text={}
+ />
+ }
+ text={}
+ />
+
+
+
+ } minimal={true} />
+
+
+ }
+ onClick={handleRefreshBtnClick}
+ />
+
+
+ );
+}
+export default compose(
+ withSettingsActions,
+ withSettings(({ timeSheetsSettings }) => ({
+ timeSheetsTableSize: timeSheetsSettings?.tableSize,
+ })),
+)(ProjectDetailActionsBar);
diff --git a/src/containers/Projects/containers/ProjectDetails/ProjectDetailProvider.tsx b/src/containers/Projects/containers/ProjectDetails/ProjectDetailProvider.tsx
new file mode 100644
index 000000000..926419813
--- /dev/null
+++ b/src/containers/Projects/containers/ProjectDetails/ProjectDetailProvider.tsx
@@ -0,0 +1,25 @@
+// @ts-nocheck
+import React from 'react';
+
+const ProjectDetailContext = React.createContext();
+
+/**
+ * Project detail provider.
+ * @returns
+ */
+function ProjectDetailProvider({
+ // #ownProps
+ ...props
+}) {
+ // State provider.
+ const provider = {};
+ return (
+
+
+
+ );
+}
+
+const useProjectDetailContext = () => React.useContext(ProjectDetailContext);
+
+export { ProjectDetailProvider, useProjectDetailContext };
diff --git a/src/containers/Projects/containers/ProjectDetails/ProjectDetailTabs.tsx b/src/containers/Projects/containers/ProjectDetails/ProjectDetailTabs.tsx
new file mode 100644
index 000000000..df1766fb8
--- /dev/null
+++ b/src/containers/Projects/containers/ProjectDetails/ProjectDetailTabs.tsx
@@ -0,0 +1,65 @@
+import React from 'react';
+import styled from 'styled-components';
+import intl from 'react-intl-universal';
+import { Tabs, Tab } from '@blueprintjs/core';
+import TimeSheetDataTable from './TimeSheet/TimeSheetDataTable';
+
+/**
+ * Project detail tabs.
+ * @returns
+ */
+export default function ProjectDetailTabs() {
+ return (
+
+
+
+ }
+ />
+
+
+
+
+
+ );
+}
+
+const ProjectTabsContent = styled.div`
+ .bp3-tabs {
+ .bp3-tab-list {
+ position: relative;
+ background-color: #fff;
+ padding: 0 20px;
+ border-bottom: 1px solid #d2dce2;
+
+ &.bp3-large > .bp3-tab {
+ font-size: 14px;
+ font-weight: 400;
+ color: #646a7d;
+ margin: 0 1rem;
+
+ &[aria-selected='true'],
+ &:not([aria-disabled='true']):hover {
+ color: #0052cc;
+ }
+ }
+ .bp3-tab-indicator-wrapper .bp3-tab-indicator {
+ height: 2px;
+ bottom: -2px;
+ }
+ }
+ .bp3-tab-panel {
+ margin-top: 0;
+ }
+ }
+`;
diff --git a/src/containers/Projects/containers/ProjectDetails/TimeSheet/TimeSheetDataTable.tsx b/src/containers/Projects/containers/ProjectDetails/TimeSheet/TimeSheetDataTable.tsx
new file mode 100644
index 000000000..d88f25d77
--- /dev/null
+++ b/src/containers/Projects/containers/ProjectDetails/TimeSheet/TimeSheetDataTable.tsx
@@ -0,0 +1,117 @@
+// @ts-nocheck
+import React from 'react';
+import styled from 'styled-components';
+import { DataTable, TableFastCell, DashboardContentTable } from 'components';
+import TableVirtualizedListRows from 'components/Datatable/TableVirtualizedRows';
+import TableSkeletonRows from 'components/Datatable/TableSkeletonRows';
+import TableSkeletonHeader from 'components/Datatable/TableHeaderSkeleton';
+import { useTimeSheetColumns, ActionMenu } from './components';
+import { TableStyle } from '../../../../../common';
+import withSettings from '../../../../Settings/withSettings';
+
+import { compose } from 'utils';
+
+const TimeSheet = [
+ {
+ id: 1,
+ data: '2020-01-01',
+ task: 'Task 1',
+ user: 'User 1',
+ time: '12:00Am',
+ billingStatus: '',
+ },
+ {
+ id: 2,
+ data: '2021-01-01',
+ task: 'Task 2',
+ user: 'User 2',
+ time: '12:00Am',
+ billingStatus: '',
+ },
+ {
+ id: 3,
+ data: '2022-01-01',
+ task: 'Task 3',
+ user: 'User 3',
+ time: '12:00Am',
+ billingStatus: '',
+ },
+];
+
+/**
+ * TimeSheet DataTable.
+ * @returns
+ */
+function TimeSheetDataTable({
+ // #withSettings
+ timeSheetsTableSize,
+}) {
+ // Retrieve timesheet table columns.
+ const columns = useTimeSheetColumns();
+
+ return (
+
+
+
+ );
+}
+
+export default compose(
+ withSettings(({ timeSheetsSettings }) => ({
+ timeSheetsTableSize: timeSheetsSettings?.tableSize,
+ })),
+)(TimeSheetDataTable);
+
+const DashboardConstrantTable = styled(DataTable)`
+ .table {
+ .thead {
+ .th {
+ background: #fff;
+ }
+ }
+
+ .tbody {
+ .tr:last-child .td {
+ border-bottom: 0;
+ }
+ }
+ }
+`;
+
+const TimeSheetsTable = styled(DashboardConstrantTable)`
+ .table .tbody {
+ .tbody-inner .tr.no-results {
+ .td {
+ padding: 2rem 0;
+ font-size: 14px;
+ color: #888;
+ font-weight: 400;
+ border-bottom: 0;
+ }
+ }
+
+ .tbody-inner {
+ .tr .td:not(:first-child) {
+ border-left: 1px solid #e6e6e6;
+ }
+ }
+ }
+`;
diff --git a/src/containers/Projects/containers/ProjectDetails/TimeSheet/components.tsx b/src/containers/Projects/containers/ProjectDetails/TimeSheet/components.tsx
new file mode 100644
index 000000000..06f6a8a77
--- /dev/null
+++ b/src/containers/Projects/containers/ProjectDetails/TimeSheet/components.tsx
@@ -0,0 +1,67 @@
+import React from 'react';
+import intl from 'react-intl-universal';
+import { FormatDateCell } from 'components';
+import { Menu, MenuDivider, MenuItem, Intent } from '@blueprintjs/core';
+
+/**
+ * Table actions cell.
+ */
+export const ActionMenu = ({ row: { original }, payload: {} }) =>
;
+
+/**
+ * Retrieve timesheet list columns columns.
+ */
+export const useTimeSheetColumns = () => {
+ return React.useMemo(
+ () => [
+ {
+ id: 'date',
+ Header: intl.get('timesheets.column.date'),
+ accessor: 'date',
+ Cell: FormatDateCell,
+ width: 115,
+ className: 'date',
+ clickable: true,
+ textOverview: true,
+ },
+ {
+ id: 'task',
+ Header: intl.get('timesheets.column.task'),
+ accessor: 'task',
+ width: 115,
+ className: 'task',
+ clickable: true,
+ textOverview: true,
+ },
+ {
+ id: 'user',
+ Header: intl.get('timesheets.column.user'),
+ accessor: 'user',
+ width: 115,
+ className: 'user',
+ clickable: true,
+ textOverview: true,
+ },
+ {
+ id: 'time',
+ Header: intl.get('timesheets.column.time'),
+ accessor: 'time',
+ width: 115,
+ className: 'user',
+ align: 'right',
+ clickable: true,
+ textOverview: true,
+ },
+ {
+ id: 'billingStatus',
+ Header: intl.get('timesheets.column.billing_status'),
+ accessor: 'billing_status',
+ width: 160,
+ className: 'billingStatus',
+ clickable: true,
+ textOverview: true,
+ },
+ ],
+ [],
+ );
+};
diff --git a/src/containers/Projects/containers/ProjectDetails/index.tsx b/src/containers/Projects/containers/ProjectDetails/index.tsx
new file mode 100644
index 000000000..ee9efac23
--- /dev/null
+++ b/src/containers/Projects/containers/ProjectDetails/index.tsx
@@ -0,0 +1,37 @@
+//@ts-nocheck
+import React from 'react';
+import { useLocation } from 'react-router-dom';
+import ProjectDetailActionsBar from './ProjectDetailActionsBar';
+import ProjectDetailTabs from './ProjectDetailTabs';
+import { DashboardPageContent } from 'components';
+import { ProjectDetailProvider } from './ProjectDetailProvider';
+import withDashboardActions from 'containers/Dashboard/withDashboardActions';
+import { compose } from 'utils';
+
+/**
+ * Project tabs.
+ * @returns
+ */
+function ProjectTabs({
+ // #withDashboardActions
+ changePageTitle,
+}) {
+ const {
+ state: { original },
+ } = useLocation();
+
+ React.useEffect(() => {
+ changePageTitle(original.name);
+ }, [changePageTitle, original]);
+
+ return (
+
+
+
+
+
+
+ );
+}
+
+export default compose(withDashboardActions)(ProjectTabs);
diff --git a/src/containers/Projects/containers/ProjectsLanding/ProjectsDataTable.tsx b/src/containers/Projects/containers/ProjectsLanding/ProjectsDataTable.tsx
index ea14c783e..dcd9c5ed5 100644
--- a/src/containers/Projects/containers/ProjectsLanding/ProjectsDataTable.tsx
+++ b/src/containers/Projects/containers/ProjectsLanding/ProjectsDataTable.tsx
@@ -1,4 +1,5 @@
import React from 'react';
+import { useHistory } from 'react-router-dom';
import { DataTable } from 'components';
import { TABLES } from 'common/tables';
import TableSkeletonRows from 'components/Datatable/TableSkeletonRows';
@@ -44,11 +45,17 @@ function ProjectsDataTable({
// #withSettings
projectsTableSize,
}) {
+ const history = useHistory();
+
// Retrieve projects table columns.
const columns = useProjectsListColumns();
// Handle cell click.
- const handleCellClick = (cell, event) => {};
+ const handleCellClick = ({ row: { original } }) => {
+ return history.push(`/projects/${original?.id}/details`, {
+ original,
+ });
+ };
// Handle edit project.
const handleEditProject = (project) => {
@@ -66,6 +73,13 @@ function ProjectsDataTable({
const [initialColumnsWidths, , handleColumnResizing] =
useMemorizedColumnsWidths(TABLES.PROJECTS);
+ // Handle view detail project.
+ const handleViewDetailProject = (project) => {
+ return history.push(`/projects/${project.id}/details`, {
+ original: project.name,
+ });
+ };
+
return (
{
creditNoteSettings: state.settings.data.creditNote,
vendorsCreditNoteSetting: state.settings.data.vendorCredit,
warehouseTransferSettings: state.settings.data.warehouseTransfers,
- projectSettings:state.settings.data.projects
+ projectSettings:state.settings.data.projects,
+ timeSheetsSettings:state.settings.data.timeSheets
};
return mapState ? mapState(mapped, state, props) : mapped;
};
diff --git a/src/lang/en/index.json b/src/lang/en/index.json
index fea33284a..e540d5999 100644
--- a/src/lang/en/index.json
+++ b/src/lang/en/index.json
@@ -2069,5 +2069,18 @@
"task.schema.label.task_name": "Task name",
"task.schema.label.task_house": "Task house",
"task.schema.label.charge": "Charge",
- "task.schema.label.amount": "Amount"
+ "task.schema.label.amount": "Amount",
+ "projcet_details.action.new_transaction": "New Transaction",
+ "projcet_details.action.log_time": "Log Time",
+ "projcet_details.action.edit_project": "Edit Project",
+ "project_details.label.overview": "Overview",
+ "project_details.label.timesheet": "Timesheet",
+ "project_details.label.purchases": "Purchases",
+ "project_details.label.sales": "Sales",
+ "project_details.label.journals": "Journals",
+ "timesheets.column.date": "Date",
+ "timesheets.column.task": "Task",
+ "timesheets.column.user": "User",
+ "timesheets.column.time": "Time",
+ "timesheets.column.billing_status": "Billing Status"
}
\ No newline at end of file
diff --git a/src/routes/dashboard.js b/src/routes/dashboard.js
index f5b5c2c12..e8a8ecd86 100644
--- a/src/routes/dashboard.js
+++ b/src/routes/dashboard.js
@@ -969,6 +969,15 @@ export const getDashboardRoutes = () => [
),
pageTitle: intl.get('sidebar.transactions_locaking'),
},
+
+ {
+ path: '/projects/:id/details',
+ component: lazy(() =>
+ import('../containers/Projects/containers/ProjectDetails'),
+ ),
+ sidebarExpand: false,
+ backLink: true,
+ },
{
path: '/projects',
component: lazy(() =>
@@ -976,6 +985,7 @@ export const getDashboardRoutes = () => [
),
pageTitle: intl.get('sidebar.projects'),
},
+
// Homepage
{
path: `/`,
diff --git a/src/store/settings/settings.reducer.js b/src/store/settings/settings.reducer.js
index fb28d894f..b57bceebf 100644
--- a/src/store/settings/settings.reducer.js
+++ b/src/store/settings/settings.reducer.js
@@ -64,6 +64,9 @@ const initialState = {
projects: {
tableSize: 'medium',
},
+ timeSheets: {
+ tableSize: 'medium',
+ },
},
};