mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-21 23:30:32 +00:00
feat: add project billable entries cell.
This commit is contained in:
27
src/components/DataTableCells/ProjectBillableEntriesCell.tsx
Normal file
27
src/components/DataTableCells/ProjectBillableEntriesCell.tsx
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import React from 'react';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
import { Popover2 } from '@blueprintjs/popover2';
|
||||||
|
import { Button } from '@blueprintjs/core';
|
||||||
|
import { CellType } from '@/constants';
|
||||||
|
import { Icon, FormattedMessage as T } from '@/components';
|
||||||
|
import ProjectBillableEntries from '@/containers/Projects/containers/ProjectBillableEntries';
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
export function ProjectBillableEntriesCell() {
|
||||||
|
const content = <ProjectBillableEntries />;
|
||||||
|
return (
|
||||||
|
<Popover2 content={content}>
|
||||||
|
<Button
|
||||||
|
icon={<Icon icon={'info'} iconSize={14} />}
|
||||||
|
className="m12"
|
||||||
|
minimal={true}
|
||||||
|
/>
|
||||||
|
</Popover2>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectBillableEntriesCell.cellType = CellType.Button;
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
// @ts-nocheck
|
|
||||||
import React from 'react';
|
|
||||||
import styled from 'styled-components';
|
|
||||||
import { Popover2 } from '@blueprintjs/popover2';
|
|
||||||
import { Button } from '@blueprintjs/core';
|
|
||||||
import { CellType } from '@/constants';
|
|
||||||
import {
|
|
||||||
Icon,
|
|
||||||
FormattedMessage as T,
|
|
||||||
ButtonLink,
|
|
||||||
DetailsMenu,
|
|
||||||
DetailItem,
|
|
||||||
FormatDate,
|
|
||||||
} from '@/components';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
export function ProjectInvoicingCell({}) {
|
|
||||||
const content = (
|
|
||||||
<ProjectInvoicingContent>
|
|
||||||
<DetailsMenu direction={'vertical'}>
|
|
||||||
<DetailItem label={'Type'}>
|
|
||||||
<ButtonLink>Expense</ButtonLink>
|
|
||||||
</DetailItem>
|
|
||||||
<DetailItem label={'Transaction No.'}>EXP-1000</DetailItem>
|
|
||||||
<DetailItem label={'Date'}>2022-02-02</DetailItem>
|
|
||||||
<DetailItem label={'Amount'}>$1000.00</DetailItem>
|
|
||||||
</DetailsMenu>
|
|
||||||
</ProjectInvoicingContent>
|
|
||||||
);
|
|
||||||
return (
|
|
||||||
<Popover2 content={content}>
|
|
||||||
<Button
|
|
||||||
icon={<Icon icon={'info'} iconSize={14} />}
|
|
||||||
className="m12"
|
|
||||||
minimal={true}
|
|
||||||
/>
|
|
||||||
</Popover2>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
ProjectInvoicingCell.cellType = CellType.Button;
|
|
||||||
|
|
||||||
const ProjectInvoicingContent = styled.div`
|
|
||||||
width: 450px;
|
|
||||||
padding: 7px 12px;
|
|
||||||
`;
|
|
||||||
@@ -12,7 +12,7 @@ import SwitchFieldCell from './SwitchFieldCell';
|
|||||||
import TextAreaCell from './TextAreaCell';
|
import TextAreaCell from './TextAreaCell';
|
||||||
import BranchesListFieldCell from './BranchesListFieldCell';
|
import BranchesListFieldCell from './BranchesListFieldCell';
|
||||||
import { ProjectsListFieldCell } from './ProjectsListFieldCell';
|
import { ProjectsListFieldCell } from './ProjectsListFieldCell';
|
||||||
import { ProjectInvoicingCell } from './ProjectInvoicingCell';
|
import { ProjectBillableEntriesCell } from './ProjectBillableEntriesCell';
|
||||||
import { TextOverviewTooltipCell } from './TextOverviewTooltipCell';
|
import { TextOverviewTooltipCell } from './TextOverviewTooltipCell';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@@ -30,6 +30,6 @@ export {
|
|||||||
TextAreaCell,
|
TextAreaCell,
|
||||||
BranchesListFieldCell,
|
BranchesListFieldCell,
|
||||||
ProjectsListFieldCell,
|
ProjectsListFieldCell,
|
||||||
ProjectInvoicingCell,
|
ProjectBillableEntriesCell,
|
||||||
TextOverviewTooltipCell,
|
TextOverviewTooltipCell,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import {
|
|||||||
PercentFieldCell,
|
PercentFieldCell,
|
||||||
NumericInputCell,
|
NumericInputCell,
|
||||||
CheckBoxFieldCell,
|
CheckBoxFieldCell,
|
||||||
ProjectInvoicingCell,
|
ProjectBillableEntriesCell,
|
||||||
} from '@/components/DataTableCells';
|
} from '@/components/DataTableCells';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -157,7 +157,7 @@ export function useEditableItemsEntriesColumns({ landedCost }) {
|
|||||||
{
|
{
|
||||||
Header: '',
|
Header: '',
|
||||||
accessor: 'invoicing',
|
accessor: 'invoicing',
|
||||||
Cell: ProjectInvoicingCell,
|
Cell: ProjectBillableEntriesCell,
|
||||||
disableSortBy: true,
|
disableSortBy: true,
|
||||||
disableResizing: true,
|
disableResizing: true,
|
||||||
width: 45,
|
width: 45,
|
||||||
|
|||||||
@@ -61,10 +61,10 @@ const billableTypeInputValueRenderer = (inputValue) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Project billable suggest field.
|
* Project billable type suggest field.
|
||||||
* @param
|
* @param
|
||||||
*/
|
*/
|
||||||
export function ProjectBillableSuggestField({
|
export function ProjectBillableTypeSuggestField({
|
||||||
billableType,
|
billableType,
|
||||||
initialBillableTypeId,
|
initialBillableTypeId,
|
||||||
selectedBillableTypeId,
|
selectedBillableTypeId,
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import React from 'react';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
import { BillableEntriesItems } from './components';
|
||||||
|
import { useProjectBillableEntriesContext } from './ProjectBillableEntriesProvider';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Project billable entries content.
|
||||||
|
*/
|
||||||
|
export default function ProjectBillableEntriesContent() {
|
||||||
|
const { billableEntries } = useProjectBillableEntriesContext();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<BillableEntriesContentRoot>
|
||||||
|
<BillableEntriesItems billableEntries={billableEntries} />
|
||||||
|
</BillableEntriesContentRoot>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const BillableEntriesContentRoot = styled.div`
|
||||||
|
width: 400px;
|
||||||
|
padding: 6px 12px;
|
||||||
|
`;
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import { useProjectBillableEntries } from '../../hooks';
|
||||||
|
import { DialogContent } from '@/components';
|
||||||
|
|
||||||
|
const ProjectBillableEntriesContext = React.createContext();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Project billable entries provider.
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
function ProjectBillableEntriesProvider({ projectId, ...props }) {
|
||||||
|
// Handle fetch project billable entries.
|
||||||
|
const { data: billableEntries, isLoading: isProjectBillableEntriesLoading } =
|
||||||
|
useProjectBillableEntries(projectId, {
|
||||||
|
enabled: !!projectId,
|
||||||
|
});
|
||||||
|
|
||||||
|
//state provider.
|
||||||
|
const provider = {
|
||||||
|
projectId,
|
||||||
|
billableEntries,
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DialogContent isLoading={isProjectBillableEntriesLoading}>
|
||||||
|
<ProjectBillableEntriesContext.Provider value={provider} {...props} />
|
||||||
|
</DialogContent>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const useProjectBillableEntriesContext = () =>
|
||||||
|
React.useContext(ProjectBillableEntriesContext);
|
||||||
|
|
||||||
|
export { ProjectBillableEntriesProvider, useProjectBillableEntriesContext };
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import React from 'react';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
import { FormattedMessage as T, ButtonLink, FormatDate } from '@/components';
|
||||||
|
|
||||||
|
function BillableEntry({ label, children }) {
|
||||||
|
return (
|
||||||
|
<BillableEntryItem>
|
||||||
|
<BillableEntryItemLabel>{label}</BillableEntryItemLabel>
|
||||||
|
<BillableEntryItemContent>{children}</BillableEntryItemContent>
|
||||||
|
</BillableEntryItem>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function BillableEntriesList({ billableEntries }) {
|
||||||
|
return (
|
||||||
|
<BillableEntriesContent>
|
||||||
|
<BillableEntry label={'Type'}>
|
||||||
|
<ButtonLink>{billableEntries.billable_type} </ButtonLink>
|
||||||
|
</BillableEntry>
|
||||||
|
|
||||||
|
<BillableEntry label={'Transaction No.'}>
|
||||||
|
{billableEntries.billable_transaction_no}
|
||||||
|
</BillableEntry>
|
||||||
|
<BillableEntry label={'Date'}>2022-02-02</BillableEntry>
|
||||||
|
<BillableEntry label={'Amount'}>
|
||||||
|
{billableEntries.billable_amount_formatted}
|
||||||
|
</BillableEntry>
|
||||||
|
</BillableEntriesContent>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function BillableEntriesItems({ billableEntries }) {
|
||||||
|
return billableEntries.map((entries) => (
|
||||||
|
<BillableEntriesList billableEntries={entries} />
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
const BillableEntriesContent = styled.div`
|
||||||
|
display: flex;
|
||||||
|
padding: 6px 0px;
|
||||||
|
&:not(:last-child) {
|
||||||
|
border-bottom: 1px solid #d2dce2;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const BillableEntryItem = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const BillableEntryItemLabel = styled.div`
|
||||||
|
color: #727983;
|
||||||
|
font-weight: 500;
|
||||||
|
`;
|
||||||
|
const BillableEntryItemContent = styled.div`
|
||||||
|
text-transform: capitalize;
|
||||||
|
margin: 4px 0px;
|
||||||
|
`;
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import React from 'react';
|
||||||
|
import ProjectBillableEntriesContent from './ProjectBillableEntriesContent';
|
||||||
|
import { ProjectBillableEntriesProvider } from './ProjectBillableEntriesProvider';
|
||||||
|
|
||||||
|
export default function ProjectBillableEntries() {
|
||||||
|
return (
|
||||||
|
<ProjectBillableEntriesProvider projectId={1}>
|
||||||
|
<ProjectBillableEntriesContent />
|
||||||
|
</ProjectBillableEntriesProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
FieldRequiredHint,
|
FieldRequiredHint,
|
||||||
FormattedMessage as T,
|
FormattedMessage as T,
|
||||||
} from '@/components';
|
} from '@/components';
|
||||||
import { ProjectBillableSuggestField } from '../../components';
|
import { ProjectBillableTypeSuggestField } from '../../components';
|
||||||
import { billableTypeOption } from '../common';
|
import { billableTypeOption } from '../common';
|
||||||
import { ProjectRowDivider, ProjectEntiresBox } from './components';
|
import { ProjectRowDivider, ProjectEntiresBox } from './components';
|
||||||
import { useProjectBillableEntriesFormContext } from './ProjectBillableEntriesFormProvider';
|
import { useProjectBillableEntriesFormContext } from './ProjectBillableEntriesFormProvider';
|
||||||
@@ -41,7 +41,10 @@ export default function ProjectBillableEntriesFormFields() {
|
|||||||
label={<T id={'project_billable_entries.dialog.filter_by_type'} />}
|
label={<T id={'project_billable_entries.dialog.filter_by_type'} />}
|
||||||
labelInfo={<FieldRequiredHint />}
|
labelInfo={<FieldRequiredHint />}
|
||||||
>
|
>
|
||||||
<ProjectBillableSuggestField billableType={billableTypeOption} />
|
<ProjectBillableTypeSuggestField
|
||||||
|
billableType={billableTypeOption}
|
||||||
|
// onBillableTypeSelected={()=>}
|
||||||
|
/>
|
||||||
</FFormGroup>
|
</FFormGroup>
|
||||||
|
|
||||||
<ProjectEntiresBox billableEntries={[]} />
|
<ProjectEntiresBox billableEntries={[]} />
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
|
export const getDefaultQuery = () => {
|
||||||
|
return {
|
||||||
|
billableType: '',
|
||||||
|
to_date: moment(new Date()).format('YYYY-MM-DD'),
|
||||||
|
};
|
||||||
|
};
|
||||||
1
src/containers/Projects/containers/common/index.ts
Normal file
1
src/containers/Projects/containers/common/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export * from './modalChargeOptions'
|
||||||
@@ -21,9 +21,18 @@ export const expenseChargeOption = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export const billableTypeOption = [
|
export const billableTypeOption = [
|
||||||
{ name: intl.get('project_billable_entries.dialog.task'), value: 'Task' },
|
|
||||||
{ name: intl.get('project_billable_entries.dialog.bill'), value: 'Bill' },
|
|
||||||
{
|
{
|
||||||
|
id: 1,
|
||||||
|
name: intl.get('project_billable_entries.dialog.task'),
|
||||||
|
value: 'Task',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: intl.get('project_billable_entries.dialog.bill'),
|
||||||
|
value: 'Bill',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
name: intl.get('project_billable_entries.dialog.expense'),
|
name: intl.get('project_billable_entries.dialog.expense'),
|
||||||
value: 'Expense',
|
value: 'Expense',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ const getSchema = () =>
|
|||||||
exchange_rate: Yup.number(),
|
exchange_rate: Yup.number(),
|
||||||
branch_id: Yup.string(),
|
branch_id: Yup.string(),
|
||||||
warehouse_id: Yup.string(),
|
warehouse_id: Yup.string(),
|
||||||
|
project_id: Yup.string(),
|
||||||
entries: Yup.array().of(
|
entries: Yup.array().of(
|
||||||
Yup.object().shape({
|
Yup.object().shape({
|
||||||
quantity: Yup.number()
|
quantity: Yup.number()
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ export const defaultInvoice = {
|
|||||||
currency_code: '',
|
currency_code: '',
|
||||||
branch_id: '',
|
branch_id: '',
|
||||||
warehouse_id: '',
|
warehouse_id: '',
|
||||||
|
project_id: '',
|
||||||
entries: [...repeatValue(defaultInvoiceEntry, MIN_LINES_NUMBER)],
|
entries: [...repeatValue(defaultInvoiceEntry, MIN_LINES_NUMBER)],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user