mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-10 18:01:59 +00:00
Merge pull request #705 from bigcapitalhq/fix-invoice-form-layout
fix: Invoice form layout
This commit is contained in:
@@ -17,6 +17,8 @@
|
||||
"@casl/ability": "^5.4.3",
|
||||
"@casl/react": "^2.3.0",
|
||||
"@craco/craco": "^5.9.0",
|
||||
"@emotion/css": "^11.13.4",
|
||||
"@emotion/react": "^11.13.3",
|
||||
"@reduxjs/toolkit": "^1.2.5",
|
||||
"@stripe/connect-js": "^3.3.12",
|
||||
"@stripe/react-connect-js": "^3.3.13",
|
||||
@@ -48,6 +50,7 @@
|
||||
"@typescript-eslint/eslint-plugin": "^2.10.0",
|
||||
"@typescript-eslint/parser": "^2.10.0",
|
||||
"@welldone-software/why-did-you-render": "^6.0.0-rc.1",
|
||||
"@xstyled/emotion": "^3.8.1",
|
||||
"accounting": "^0.4.1",
|
||||
"axios": "^1.6.0",
|
||||
"basscss": "^8.0.2",
|
||||
@@ -124,6 +127,7 @@
|
||||
"style-loader": "0.23.1",
|
||||
"styled-components": "^5.3.1",
|
||||
"stylis-rtlcss": "^2.1.1",
|
||||
"theme-ui": "^0.16.2",
|
||||
"typescript": "^4.8.3",
|
||||
"yup": "^0.28.1"
|
||||
},
|
||||
|
||||
@@ -35,6 +35,7 @@ const OneClickDemoPage = lazy(
|
||||
const PaymentPortalPage = lazy(
|
||||
() => import('@/containers/PaymentPortal/PaymentPortalPage'),
|
||||
);
|
||||
|
||||
/**
|
||||
* App inner.
|
||||
*/
|
||||
@@ -59,7 +60,10 @@ function AppInsider({ history }) {
|
||||
children={<EmailConfirmation />}
|
||||
/>
|
||||
<Route path={'/auth'} children={<AuthenticationPage />} />
|
||||
<Route path={'/payment/:linkId'} children={<PaymentPortalPage />} />
|
||||
<Route
|
||||
path={'/payment/:linkId'}
|
||||
children={<PaymentPortalPage />}
|
||||
/>
|
||||
<Route path={'/'} children={<DashboardPrivatePages />} />
|
||||
</Switch>
|
||||
</Router>
|
||||
|
||||
@@ -1,12 +1,31 @@
|
||||
// @ts-nocheck
|
||||
import React, { createContext } from 'react';
|
||||
|
||||
const AppIntlContext = createContext();
|
||||
interface AppIntlContextValue {
|
||||
currentLocale: string;
|
||||
direction: 'rtl' | 'ltr';
|
||||
isRTL: boolean;
|
||||
isLTR: boolean;
|
||||
}
|
||||
|
||||
const AppIntlContext = createContext<AppIntlContextValue>(
|
||||
{} as AppIntlContextValue,
|
||||
);
|
||||
|
||||
interface AppIntlProviderProps {
|
||||
currentLocale: string;
|
||||
isRTL: boolean;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Application intl provider.
|
||||
*/
|
||||
function AppIntlProvider({ currentLocale, isRTL, children }) {
|
||||
function AppIntlProvider({
|
||||
currentLocale,
|
||||
isRTL,
|
||||
children,
|
||||
}: AppIntlProviderProps) {
|
||||
const provider = {
|
||||
currentLocale,
|
||||
isRTL,
|
||||
@@ -21,6 +40,7 @@ function AppIntlProvider({ currentLocale, isRTL, children }) {
|
||||
);
|
||||
}
|
||||
|
||||
const useAppIntlContext = () => React.useContext(AppIntlContext);
|
||||
const useAppIntlContext = () =>
|
||||
React.useContext<AppIntlContextValue>(AppIntlContext);
|
||||
|
||||
export { AppIntlProvider, useAppIntlContext };
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import React from 'react';
|
||||
import classnames from 'classnames';
|
||||
import { LoadingIndicator } from '../Indicator';
|
||||
import { css } from '@emotion/css';
|
||||
|
||||
export function DashboardInsider({
|
||||
loading,
|
||||
@@ -9,6 +10,7 @@ export function DashboardInsider({
|
||||
name,
|
||||
mount = false,
|
||||
className,
|
||||
style
|
||||
}) {
|
||||
return (
|
||||
<div
|
||||
@@ -17,9 +19,11 @@ export function DashboardInsider({
|
||||
dashboard__insider: true,
|
||||
'dashboard__insider--loading': loading,
|
||||
[`dashboard__insider--${name}`]: !!name,
|
||||
|
||||
},
|
||||
className,
|
||||
)}
|
||||
style={style}
|
||||
>
|
||||
<LoadingIndicator loading={loading} mount={mount}>
|
||||
{children}
|
||||
|
||||
@@ -1,9 +1,20 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import { ThemeProvider, StyleSheetManager } from 'styled-components';
|
||||
import {
|
||||
ThemeProvider as StyleComponentsThemeProvider,
|
||||
StyleSheetManager,
|
||||
} from 'styled-components';
|
||||
import rtlcss from 'stylis-rtlcss';
|
||||
import {
|
||||
defaultTheme,
|
||||
ThemeProvider as XStyledEmotionThemeProvider,
|
||||
} from '@xstyled/emotion';
|
||||
import { useAppIntlContext } from '../AppIntlProvider';
|
||||
|
||||
const theme = {
|
||||
...defaultTheme,
|
||||
bpPrefix: 'bp4',
|
||||
};
|
||||
|
||||
interface DashboardThemeProviderProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
@@ -17,7 +28,11 @@ export function DashboardThemeProvider({
|
||||
<StyleSheetManager
|
||||
{...(direction === 'rtl' ? { stylisPlugins: [rtlcss] } : {})}
|
||||
>
|
||||
<ThemeProvider theme={{ dir: direction }}>{children}</ThemeProvider>
|
||||
<StyleComponentsThemeProvider theme={{ dir: direction }}>
|
||||
<XStyledEmotionThemeProvider theme={theme}>
|
||||
{children}
|
||||
</XStyledEmotionThemeProvider>
|
||||
</StyleComponentsThemeProvider>
|
||||
</StyleSheetManager>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
import React, { forwardRef, Ref } from 'react';
|
||||
import { HTMLDivProps, Props } from '@blueprintjs/core';
|
||||
import { SystemProps, x } from '@xstyled/emotion';
|
||||
|
||||
export interface BoxProps extends Props, HTMLDivProps {
|
||||
className?: string;
|
||||
}
|
||||
export interface BoxProps
|
||||
extends SystemProps,
|
||||
Props,
|
||||
Omit<HTMLDivProps, 'color'> {}
|
||||
|
||||
export const Box = forwardRef(
|
||||
({ className, ...rest }: BoxProps, ref: Ref<HTMLDivElement>) => {
|
||||
const Element = 'div';
|
||||
const Element = x.div;
|
||||
|
||||
return <Element className={className} ref={ref} {...rest} />;
|
||||
},
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { SystemProps } from '@xstyled/emotion';
|
||||
import { Box } from '../Box';
|
||||
import { filterFalsyChildren } from './_utils';
|
||||
|
||||
@@ -12,7 +12,9 @@ export const GROUP_POSITIONS = {
|
||||
apart: 'space-between',
|
||||
};
|
||||
|
||||
export interface GroupProps extends React.ComponentPropsWithoutRef<'div'> {
|
||||
export interface GroupProps
|
||||
extends SystemProps,
|
||||
Omit<React.ComponentPropsWithoutRef<'div'>, 'color'> {
|
||||
/** Defines justify-content property */
|
||||
position?: GroupPosition;
|
||||
|
||||
@@ -27,34 +29,30 @@ export interface GroupProps extends React.ComponentPropsWithoutRef<'div'> {
|
||||
|
||||
/** Defines align-items css property */
|
||||
align?: React.CSSProperties['alignItems'];
|
||||
|
||||
flex?: React.CSSProperties['flex'];
|
||||
}
|
||||
|
||||
const defaultProps: Partial<GroupProps> = {
|
||||
position: 'left',
|
||||
spacing: 20,
|
||||
flex: 'none'
|
||||
};
|
||||
|
||||
export function Group({ children, ...props }: GroupProps) {
|
||||
const groupProps = {
|
||||
...defaultProps,
|
||||
...props,
|
||||
};
|
||||
export function Group({
|
||||
position = 'left',
|
||||
spacing = 20,
|
||||
align = 'center',
|
||||
noWrap,
|
||||
children,
|
||||
...props
|
||||
}: GroupProps) {
|
||||
const filteredChildren = filterFalsyChildren(children);
|
||||
|
||||
return <GroupStyled {...groupProps}>{filteredChildren}</GroupStyled>;
|
||||
return (
|
||||
<Box
|
||||
boxSizing={'border-box'}
|
||||
display={'flex'}
|
||||
flexDirection={'row'}
|
||||
alignItems={align}
|
||||
flexWrap={noWrap ? 'nowrap' : 'wrap'}
|
||||
justifyContent={GROUP_POSITIONS[position]}
|
||||
gap={`${spacing}px`}
|
||||
{...props}
|
||||
>
|
||||
{filteredChildren}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
const GroupStyled = styled(Box)`
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex: ${(props: GroupProps) => (props.flex)};
|
||||
align-items: ${(props: GroupProps) => (props.align || 'center')};
|
||||
flex-wrap: ${(props: GroupProps) => (props.noWrap ? 'nowrap' : 'wrap')};
|
||||
justify-content: ${(props: GroupProps) =>
|
||||
GROUP_POSITIONS[props.position || 'left']};
|
||||
gap: ${(props: GroupProps) => props.spacing}px;
|
||||
`;
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { Box } from '../Box';
|
||||
import { x, SystemProps } from '@xstyled/emotion';
|
||||
|
||||
export interface StackProps extends React.ComponentPropsWithoutRef<'div'> {
|
||||
export interface StackProps
|
||||
extends SystemProps,
|
||||
Omit<React.ComponentPropsWithoutRef<'div'>, 'color'> {
|
||||
/** Key of theme.spacing or number to set gap in px */
|
||||
spacing?: number;
|
||||
|
||||
@@ -11,30 +12,22 @@ export interface StackProps extends React.ComponentPropsWithoutRef<'div'> {
|
||||
|
||||
/** justify-content CSS property */
|
||||
justify?: React.CSSProperties['justifyContent'];
|
||||
|
||||
flex?: React.CSSProperties['flex'];
|
||||
}
|
||||
|
||||
const defaultProps: Partial<StackProps> = {
|
||||
spacing: 20,
|
||||
align: 'stretch',
|
||||
justify: 'top',
|
||||
flex: 'none',
|
||||
};
|
||||
|
||||
export function Stack(props: StackProps) {
|
||||
const stackProps = {
|
||||
...defaultProps,
|
||||
...props,
|
||||
};
|
||||
return <StackStyled {...stackProps} />;
|
||||
export function Stack({
|
||||
spacing = 20,
|
||||
align = 'stretch',
|
||||
justify = 'top',
|
||||
...restProps
|
||||
}: StackProps) {
|
||||
return (
|
||||
<x.div
|
||||
display={'flex'}
|
||||
flexDirection="column"
|
||||
justifyContent="justify"
|
||||
gap={`${spacing}px`}
|
||||
alignItems={align}
|
||||
{...restProps}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const StackStyled = styled(Box)`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: ${(props: StackProps) => props.align};
|
||||
justify-content: justify;
|
||||
gap: ${(props: StackProps) => props.spacing}px;
|
||||
flex: ${(props: StackProps) => props.flex};
|
||||
`;
|
||||
|
||||
91
packages/webapp/src/components/PageForm/PageForm.tsx
Normal file
91
packages/webapp/src/components/PageForm/PageForm.tsx
Normal file
@@ -0,0 +1,91 @@
|
||||
import React, { FC } from 'react';
|
||||
import clsx from 'classnames';
|
||||
import { x, SystemProps } from '@xstyled/emotion';
|
||||
import { css } from '@emotion/css';
|
||||
import { Group, GroupProps } from '@/components';
|
||||
|
||||
interface PageFormProps extends SystemProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Page form layout.
|
||||
* @returns {React.ReactNode}
|
||||
*/
|
||||
export const PageForm = ({ children, ...props }: PageFormProps) => {
|
||||
return (
|
||||
<x.div display="flex" flexDirection={'column'} overflow="hidden" {...props}>
|
||||
{children}
|
||||
</x.div>
|
||||
);
|
||||
};
|
||||
PageForm.displayName = 'PageFormBody';
|
||||
|
||||
/**
|
||||
* Page form body layout, by default the content body is scrollable.
|
||||
* @returns {React.ReactNode}
|
||||
*/
|
||||
const PageFormBody: FC<{ children: React.ReactNode } & SystemProps> = ({
|
||||
children,
|
||||
...props
|
||||
}) => {
|
||||
return (
|
||||
<x.div flex="1" overflow="auto" {...props}>
|
||||
{children}
|
||||
</x.div>
|
||||
);
|
||||
};
|
||||
PageFormBody.displayName = 'PageFormBody';
|
||||
|
||||
/**
|
||||
* Page form footer.
|
||||
* @returns {React.ReactNode}
|
||||
*/
|
||||
const PageFormFooter: FC<{ children: React.ReactNode } & SystemProps> = ({ children }) => {
|
||||
return <x.div>{children} </x.div>;
|
||||
};
|
||||
|
||||
PageFormFooter.displayName = 'PageFormFooter';
|
||||
|
||||
const footerActionsStyle = `
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
padding: 14px 18px;
|
||||
border-top: 1px solid rgb(210, 221, 226);
|
||||
box-shadow: 0px -1px 4px 0px rgba(0, 0, 0, 0.05);
|
||||
|
||||
.bp4-button-group{
|
||||
.bp4-button{
|
||||
&:not(:last-child),
|
||||
&.bp4-popover-wrapper:not(:last-child) {
|
||||
border-right: 1px solid rgba(92, 112, 127, 0.3);
|
||||
margin-right: 0;
|
||||
|
||||
&.bp4-intent-primary{
|
||||
border-right: 1px solid rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const PageFormFooterActions: FC<GroupProps> = ({
|
||||
children,
|
||||
className,
|
||||
...restProps
|
||||
}) => {
|
||||
return (
|
||||
<Group
|
||||
spacing={20}
|
||||
{...restProps}
|
||||
className={clsx(css(footerActionsStyle), className)}
|
||||
>
|
||||
{children}
|
||||
</Group>
|
||||
);
|
||||
};
|
||||
PageFormFooterActions.displayName = 'PageFormFooterActions';
|
||||
|
||||
PageForm.Body = PageFormBody;
|
||||
PageForm.Footer = PageFormFooter;
|
||||
PageForm.FooterActions = PageFormFooterActions;
|
||||
@@ -2,3 +2,4 @@
|
||||
export * from './FormTopbar';
|
||||
export * from './FormTopbarSelectInputs';
|
||||
export * from './PageFormBigNumber';
|
||||
export * from './PageForm';
|
||||
@@ -1,13 +1,20 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { x, SystemProps } from '@xstyled/emotion';
|
||||
|
||||
export function Paper({ children, className }) {
|
||||
return <PaperRoot className={className}>{children}</PaperRoot>;
|
||||
interface PaperProps extends SystemProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
const PaperRoot = styled.div`
|
||||
border: 1px solid #d2dce2;
|
||||
background: #fff;
|
||||
padding: 10px;
|
||||
`;
|
||||
export const Paper = ({ children, ...props }: PaperProps) => {
|
||||
return (
|
||||
<x.div
|
||||
background={'white'}
|
||||
p={'10px'}
|
||||
border={'1px solid #d2dce2'}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</x.div>
|
||||
);
|
||||
};
|
||||
Paper.displayName = 'Paper';
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import { Row, Col, Paper } from '@/components';
|
||||
@@ -12,7 +11,7 @@ import { UploadAttachmentButton } from '@/containers/Attachments/UploadAttachmen
|
||||
export default function MakeJournalFormFooter() {
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_FOOTER)}>
|
||||
<MakeJournalFooterPaper>
|
||||
<Paper p={'20px'}>
|
||||
<Row>
|
||||
<Col md={8}>
|
||||
<MakeJournalFormFooterLeft />
|
||||
@@ -23,10 +22,7 @@ export default function MakeJournalFormFooter() {
|
||||
<MakeJournalFormFooterRight />
|
||||
</Col>
|
||||
</Row>
|
||||
</MakeJournalFooterPaper>
|
||||
</Paper>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
const MakeJournalFooterPaper = styled(Paper)`
|
||||
padding: 20px;
|
||||
`;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import { Row, Col, Paper } from '@/components';
|
||||
@@ -12,7 +11,7 @@ import { UploadAttachmentButton } from '@/containers/Attachments/UploadAttachmen
|
||||
export default function ExpenseFormFooter() {
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_FOOTER)}>
|
||||
<ExpensesFooterPaper>
|
||||
<Paper p={'20px'}>
|
||||
<Row>
|
||||
<Col md={8}>
|
||||
<ExpenseFormFooterLeft />
|
||||
@@ -23,11 +22,7 @@ export default function ExpenseFormFooter() {
|
||||
<ExpenseFormFooterRight />
|
||||
</Col>
|
||||
</Row>
|
||||
</ExpensesFooterPaper>
|
||||
</Paper>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const ExpensesFooterPaper = styled(Paper)`
|
||||
padding: 20px;
|
||||
`;
|
||||
|
||||
@@ -13,7 +13,7 @@ import { UploadAttachmentButton } from '@/containers/Attachments/UploadAttachmen
|
||||
export default function BillFormFooter() {
|
||||
return (
|
||||
<div class={classNames(CLASSES.PAGE_FORM_FOOTER)}>
|
||||
<BillFooterPaper>
|
||||
<Paper p={'20px'}>
|
||||
<Row>
|
||||
<Col md={8}>
|
||||
<BillFormFooterLeft />
|
||||
@@ -24,11 +24,7 @@ export default function BillFormFooter() {
|
||||
<BillFormFooterRight />
|
||||
</Col>
|
||||
</Row>
|
||||
</BillFooterPaper>
|
||||
</Paper>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const BillFooterPaper = styled(Paper)`
|
||||
padding: 20px;
|
||||
`;
|
||||
|
||||
@@ -15,7 +15,7 @@ import { UploadAttachmentButton } from '@/containers/Attachments/UploadAttachmen
|
||||
export default function VendorCreditNoteFormFooter() {
|
||||
return (
|
||||
<div class={classNames(CLASSES.PAGE_FORM_FOOTER)}>
|
||||
<VendorCreditNoteFooterPaper>
|
||||
<Paper p={'20px'}>
|
||||
<Row>
|
||||
<Col md={8}>
|
||||
<VendorCreditNoteFormFooterLeft />
|
||||
@@ -26,11 +26,7 @@ export default function VendorCreditNoteFormFooter() {
|
||||
<VendorCreditNoteFormFooterRight />
|
||||
</Col>
|
||||
</Row>
|
||||
</VendorCreditNoteFooterPaper>
|
||||
</Paper>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const VendorCreditNoteFooterPaper = styled(Paper)`
|
||||
padding: 20px;
|
||||
`;
|
||||
|
||||
@@ -15,7 +15,7 @@ import { UploadAttachmentButton } from '@/containers/Attachments/UploadAttachmen
|
||||
export default function PaymentMadeFooter() {
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_FOOTER)}>
|
||||
<PaymentReceiveFooterPaper>
|
||||
<Paper p={'20px'}>
|
||||
<Row>
|
||||
<Col md={8}>
|
||||
<PaymentMadeFormFooterLeft />
|
||||
@@ -26,11 +26,7 @@ export default function PaymentMadeFooter() {
|
||||
<PaymentMadeFormFooterRight />
|
||||
</Col>
|
||||
</Row>
|
||||
</PaymentReceiveFooterPaper>
|
||||
</Paper>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const PaymentReceiveFooterPaper = styled(Paper)`
|
||||
padding: 20px;
|
||||
`;
|
||||
|
||||
@@ -12,9 +12,14 @@ import {
|
||||
Menu,
|
||||
MenuItem,
|
||||
} from '@blueprintjs/core';
|
||||
import { If, Icon, FormattedMessage as T, Group, FSelect } from '@/components';
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import classNames from 'classnames';
|
||||
import {
|
||||
If,
|
||||
Icon,
|
||||
FormattedMessage as T,
|
||||
Group,
|
||||
FSelect,
|
||||
PageForm,
|
||||
} from '@/components';
|
||||
import { useCreditNoteFormContext } from './CreditNoteFormProvider';
|
||||
import {
|
||||
BrandingThemeFormGroup,
|
||||
@@ -82,140 +87,141 @@ export default function CreditNoteFloatingActions() {
|
||||
const brandingTemplatesOptions = useCreditNoteFormBrandingTemplatesOptions();
|
||||
|
||||
return (
|
||||
<Group
|
||||
spacing={10}
|
||||
className={classNames(CLASSES.PAGE_FORM_FLOATING_ACTIONS)}
|
||||
>
|
||||
{/* ----------- Save And Open ----------- */}
|
||||
<If condition={!creditNote || !creditNote?.is_open}>
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
loading={isSubmitting}
|
||||
intent={Intent.PRIMARY}
|
||||
onClick={handleSubmitOpenBtnClick}
|
||||
text={<T id={'save_open'} />}
|
||||
/>
|
||||
<Popover
|
||||
content={
|
||||
<Menu>
|
||||
<MenuItem
|
||||
text={<T id={'open_and_new'} />}
|
||||
onClick={handleSubmitOpenAndNewBtnClick}
|
||||
/>
|
||||
<MenuItem
|
||||
text={<T id={'open_continue_editing'} />}
|
||||
onClick={handleSubmitOpenContinueEditingBtnClick}
|
||||
/>
|
||||
</Menu>
|
||||
}
|
||||
minimal={true}
|
||||
interactionKind={PopoverInteractionKind.CLICK}
|
||||
position={Position.BOTTOM_LEFT}
|
||||
>
|
||||
<PageForm.FooterActions position={'apart'} spacing={20}>
|
||||
<Group spacing={10}>
|
||||
{/* ----------- Save And Open ----------- */}
|
||||
<If condition={!creditNote || !creditNote?.is_open}>
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
loading={isSubmitting}
|
||||
intent={Intent.PRIMARY}
|
||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||
onClick={handleSubmitOpenBtnClick}
|
||||
text={<T id={'save_open'} />}
|
||||
/>
|
||||
</Popover>
|
||||
</ButtonGroup>
|
||||
{/* ----------- Save As Draft ----------- */}
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
className={'ml1'}
|
||||
onClick={handleSubmitDraftBtnClick}
|
||||
text={<T id={'save_as_draft'} />}
|
||||
/>
|
||||
<Popover
|
||||
content={
|
||||
<Menu>
|
||||
<MenuItem
|
||||
text={<T id={'save_and_new'} />}
|
||||
onClick={handleSubmitDraftAndNewBtnClick}
|
||||
/>
|
||||
<MenuItem
|
||||
text={<T id={'save_continue_editing'} />}
|
||||
onClick={handleSubmitDraftContinueEditingBtnClick}
|
||||
/>
|
||||
</Menu>
|
||||
}
|
||||
minimal={true}
|
||||
interactionKind={PopoverInteractionKind.CLICK}
|
||||
position={Position.BOTTOM_LEFT}
|
||||
>
|
||||
<Popover
|
||||
content={
|
||||
<Menu>
|
||||
<MenuItem
|
||||
text={<T id={'open_and_new'} />}
|
||||
onClick={handleSubmitOpenAndNewBtnClick}
|
||||
/>
|
||||
<MenuItem
|
||||
text={<T id={'open_continue_editing'} />}
|
||||
onClick={handleSubmitOpenContinueEditingBtnClick}
|
||||
/>
|
||||
</Menu>
|
||||
}
|
||||
minimal={true}
|
||||
interactionKind={PopoverInteractionKind.CLICK}
|
||||
position={Position.BOTTOM_LEFT}
|
||||
>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
intent={Intent.PRIMARY}
|
||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||
/>
|
||||
</Popover>
|
||||
</ButtonGroup>
|
||||
{/* ----------- Save As Draft ----------- */}
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||
className={'ml1'}
|
||||
onClick={handleSubmitDraftBtnClick}
|
||||
text={<T id={'save_as_draft'} />}
|
||||
/>
|
||||
</Popover>
|
||||
</ButtonGroup>
|
||||
</If>
|
||||
{/* ----------- Save and New ----------- */}
|
||||
<If condition={creditNote && creditNote?.is_open}>
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
loading={isSubmitting}
|
||||
intent={Intent.PRIMARY}
|
||||
onClick={handleSubmitOpenBtnClick}
|
||||
style={{ minWidth: '85px' }}
|
||||
text={<T id={'save'} />}
|
||||
/>
|
||||
<Popover
|
||||
content={
|
||||
<Menu>
|
||||
<MenuItem
|
||||
text={<T id={'save_and_new'} />}
|
||||
onClick={handleSubmitOpenAndNewBtnClick}
|
||||
/>
|
||||
</Menu>
|
||||
}
|
||||
minimal={true}
|
||||
interactionKind={PopoverInteractionKind.CLICK}
|
||||
position={Position.BOTTOM_LEFT}
|
||||
>
|
||||
<Popover
|
||||
content={
|
||||
<Menu>
|
||||
<MenuItem
|
||||
text={<T id={'save_and_new'} />}
|
||||
onClick={handleSubmitDraftAndNewBtnClick}
|
||||
/>
|
||||
<MenuItem
|
||||
text={<T id={'save_continue_editing'} />}
|
||||
onClick={handleSubmitDraftContinueEditingBtnClick}
|
||||
/>
|
||||
</Menu>
|
||||
}
|
||||
minimal={true}
|
||||
interactionKind={PopoverInteractionKind.CLICK}
|
||||
position={Position.BOTTOM_LEFT}
|
||||
>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||
/>
|
||||
</Popover>
|
||||
</ButtonGroup>
|
||||
</If>
|
||||
{/* ----------- Save and New ----------- */}
|
||||
<If condition={creditNote && creditNote?.is_open}>
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
loading={isSubmitting}
|
||||
intent={Intent.PRIMARY}
|
||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||
onClick={handleSubmitOpenBtnClick}
|
||||
style={{ minWidth: '85px' }}
|
||||
text={<T id={'save'} />}
|
||||
/>
|
||||
</Popover>
|
||||
</ButtonGroup>
|
||||
</If>
|
||||
{/* ----------- Clear & Reset----------- */}
|
||||
<Button
|
||||
className={'ml1'}
|
||||
disabled={isSubmitting}
|
||||
onClick={handleClearBtnClick}
|
||||
text={creditNote ? <T id={'reset'} /> : <T id={'clear'} />}
|
||||
/>
|
||||
{/* ----------- Cancel ----------- */}
|
||||
<Button
|
||||
className={'ml1'}
|
||||
disabled={isSubmitting}
|
||||
onClick={handleCancelBtnClick}
|
||||
text={<T id={'cancel'} />}
|
||||
/>
|
||||
|
||||
{/* ----------- Branding Template Select ----------- */}
|
||||
<BrandingThemeFormGroup
|
||||
name={'pdf_template_id'}
|
||||
label={'Branding'}
|
||||
inline
|
||||
fastField
|
||||
style={{ marginLeft: 20 }}
|
||||
>
|
||||
<FSelect
|
||||
name={'pdf_template_id'}
|
||||
items={brandingTemplatesOptions}
|
||||
input={({ activeItem, text, label, value }) => (
|
||||
<BrandingThemeSelectButton text={text || 'Brand Theme'} minimal />
|
||||
)}
|
||||
filterable={false}
|
||||
popoverProps={{ minimal: true }}
|
||||
<Popover
|
||||
content={
|
||||
<Menu>
|
||||
<MenuItem
|
||||
text={<T id={'save_and_new'} />}
|
||||
onClick={handleSubmitOpenAndNewBtnClick}
|
||||
/>
|
||||
</Menu>
|
||||
}
|
||||
minimal={true}
|
||||
interactionKind={PopoverInteractionKind.CLICK}
|
||||
position={Position.BOTTOM_LEFT}
|
||||
>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
intent={Intent.PRIMARY}
|
||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||
/>
|
||||
</Popover>
|
||||
</ButtonGroup>
|
||||
</If>
|
||||
{/* ----------- Clear & Reset----------- */}
|
||||
<Button
|
||||
className={'ml1'}
|
||||
disabled={isSubmitting}
|
||||
onClick={handleClearBtnClick}
|
||||
text={creditNote ? <T id={'reset'} /> : <T id={'clear'} />}
|
||||
/>
|
||||
</BrandingThemeFormGroup>
|
||||
</Group>
|
||||
{/* ----------- Cancel ----------- */}
|
||||
<Button
|
||||
className={'ml1'}
|
||||
disabled={isSubmitting}
|
||||
onClick={handleCancelBtnClick}
|
||||
text={<T id={'cancel'} />}
|
||||
/>
|
||||
</Group>
|
||||
|
||||
<Group>
|
||||
{/* ----------- Branding Template Select ----------- */}
|
||||
<BrandingThemeFormGroup
|
||||
name={'pdf_template_id'}
|
||||
label={'Branding'}
|
||||
inline
|
||||
fastField
|
||||
style={{ marginLeft: 20 }}
|
||||
>
|
||||
<FSelect
|
||||
name={'pdf_template_id'}
|
||||
items={brandingTemplatesOptions}
|
||||
input={({ activeItem, text, label, value }) => (
|
||||
<BrandingThemeSelectButton text={text || 'Brand Theme'} minimal />
|
||||
)}
|
||||
filterable={false}
|
||||
popoverProps={{ minimal: true }}
|
||||
/>
|
||||
</BrandingThemeFormGroup>
|
||||
</Group>
|
||||
</PageForm.FooterActions>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import intl from 'react-intl-universal';
|
||||
import classNames from 'classnames';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { Formik, Form } from 'formik';
|
||||
import { Intent } from '@blueprintjs/core';
|
||||
import { defaultTo, isEmpty } from 'lodash';
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import { css } from '@emotion/css';
|
||||
|
||||
import {
|
||||
CreateCreditNoteFormSchema,
|
||||
EditCreditNoteFormSchema,
|
||||
@@ -42,6 +42,7 @@ import {
|
||||
CreditNoteExchangeRateSync,
|
||||
CreditNoteSyncIncrementSettingsToForm,
|
||||
} from './components';
|
||||
import { PageForm } from '@/components/PageForm';
|
||||
|
||||
/**
|
||||
* Credit note form.
|
||||
@@ -148,36 +149,42 @@ function CreditNoteForm({
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
CLASSES.PAGE_FORM,
|
||||
CLASSES.PAGE_FORM_STRIP_STYLE,
|
||||
CLASSES.PAGE_FORM_CREDIT_NOTE,
|
||||
)}
|
||||
<Formik
|
||||
validationSchema={
|
||||
isNewMode ? CreateCreditNoteFormSchema : EditCreditNoteFormSchema
|
||||
}
|
||||
initialValues={initialValues}
|
||||
onSubmit={handleFormSubmit}
|
||||
>
|
||||
<Formik
|
||||
validationSchema={
|
||||
isNewMode ? CreateCreditNoteFormSchema : EditCreditNoteFormSchema
|
||||
}
|
||||
initialValues={initialValues}
|
||||
onSubmit={handleFormSubmit}
|
||||
<Form
|
||||
className={css({
|
||||
overflow: 'hidden',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
flex: 1,
|
||||
})}
|
||||
>
|
||||
<Form>
|
||||
<CreditNoteFormTopBar />
|
||||
<CreditNoteFormHeader />
|
||||
<CreditNoteItemsEntriesEditorField />
|
||||
<CreditNoteFormFooter />
|
||||
<CreditNoteFloatingActions />
|
||||
<PageForm flex="1">
|
||||
<PageForm.Body>
|
||||
<CreditNoteFormTopBar />
|
||||
<CreditNoteFormHeader />
|
||||
<CreditNoteItemsEntriesEditorField />
|
||||
<CreditNoteFormFooter />
|
||||
</PageForm.Body>
|
||||
|
||||
{/*-------- Dialogs --------*/}
|
||||
<CreditNoteFormDialogs />
|
||||
<PageForm.Footer>
|
||||
<CreditNoteFloatingActions />
|
||||
</PageForm.Footer>
|
||||
</PageForm>
|
||||
|
||||
{/*-------- Effects --------*/}
|
||||
<CreditNoteSyncIncrementSettingsToForm />
|
||||
<CreditNoteExchangeRateSync />
|
||||
</Form>
|
||||
</Formik>
|
||||
</div>
|
||||
{/*-------- Dialogs --------*/}
|
||||
<CreditNoteFormDialogs />
|
||||
|
||||
{/*-------- Effects --------*/}
|
||||
<CreditNoteSyncIncrementSettingsToForm />
|
||||
<CreditNoteExchangeRateSync />
|
||||
</Form>
|
||||
</Formik>
|
||||
);
|
||||
}
|
||||
export default compose(
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import { Row, Col, Paper } from '@/components';
|
||||
import { Row, Col, Paper, Stack } from '@/components';
|
||||
import { CreditNoteFormFooterLeft } from './CreditNoteFormFooterLeft';
|
||||
import { CreditNoteFormFooterRight } from './CreditNoteFormFooterRight';
|
||||
import { UploadAttachmentButton } from '@/containers/Attachments/UploadAttachmentButton';
|
||||
@@ -14,8 +11,8 @@ import { UploadAttachmentButton } from '@/containers/Attachments/UploadAttachmen
|
||||
*/
|
||||
export default function CreditNoteFormFooter() {
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_FOOTER)}>
|
||||
<CreditNoteFooterPaper>
|
||||
<Stack mt={'20px'} px={'32px'} pb={'20px'} flex={1}>
|
||||
<Paper p={'20px'}>
|
||||
<Row>
|
||||
<Col md={8}>
|
||||
<CreditNoteFormFooterLeft />
|
||||
@@ -26,10 +23,7 @@ export default function CreditNoteFormFooter() {
|
||||
<CreditNoteFormFooterRight />
|
||||
</Col>
|
||||
</Row>
|
||||
</CreditNoteFooterPaper>
|
||||
</div>
|
||||
</Paper>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
const CreditNoteFooterPaper = styled(Paper)`
|
||||
padding: 20px;
|
||||
`;
|
||||
|
||||
@@ -1,23 +1,28 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import intl from 'react-intl-universal';
|
||||
import classNames from 'classnames';
|
||||
import { useFormikContext } from 'formik';
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import CreditNoteFormHeaderFields from './CreditNoteFormHeaderFields';
|
||||
|
||||
import { getEntriesTotal } from '@/containers/Entries/utils';
|
||||
import { PageFormBigNumber } from '@/components';
|
||||
import { Group, PageFormBigNumber } from '@/components';
|
||||
|
||||
/**
|
||||
* Credit note header.
|
||||
*/
|
||||
function CreditNoteFormHeader() {
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_HEADER)}>
|
||||
<Group
|
||||
position="apart"
|
||||
align={'flex-start'}
|
||||
display="flex"
|
||||
bg="white"
|
||||
p="25px 32px"
|
||||
borderBottom="1px solid #d2dce2"
|
||||
>
|
||||
<CreditNoteFormHeaderFields />
|
||||
<CreditNoteFormBigNumber />
|
||||
</div>
|
||||
</Group>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@ import styled from 'styled-components';
|
||||
import { FormGroup, InputGroup, Position } from '@blueprintjs/core';
|
||||
import { DateInput } from '@blueprintjs/datetime';
|
||||
import { FastField, ErrorMessage, useFormikContext } from 'formik';
|
||||
import { css } from '@emotion/css';
|
||||
import { useTheme } from '@emotion/react';
|
||||
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import {
|
||||
@@ -14,6 +16,7 @@ import {
|
||||
CustomerDrawerLink,
|
||||
FFormGroup,
|
||||
CustomersSelect,
|
||||
Stack,
|
||||
} from '@/components';
|
||||
import { customerNameFieldShouldUpdate } from './utils';
|
||||
|
||||
@@ -28,12 +31,31 @@ import {
|
||||
} from '@/utils';
|
||||
import { useCustomerUpdateExRate } from '@/containers/Entries/withExRateItemEntriesPriceRecalc';
|
||||
|
||||
const getCreditNoteFieldsStyle = (theme: Theme) => css`
|
||||
.${theme.bpPrefix}-form-group {
|
||||
margin-bottom: 0;
|
||||
|
||||
&.${theme.bpPrefix}-inline {
|
||||
max-width: 450px;
|
||||
}
|
||||
.${theme.bpPrefix}-label {
|
||||
min-width: 150px;
|
||||
}
|
||||
.${theme.bpPrefix}-form-content {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* Credit note form header fields.
|
||||
*/
|
||||
export default function CreditNoteFormHeaderFields({}) {
|
||||
export default function CreditNoteFormHeaderFields() {
|
||||
const theme = useTheme();
|
||||
const styleClassName = getCreditNoteFieldsStyle(theme);
|
||||
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_HEADER_FIELDS)}>
|
||||
<Stack spacing={18} flex={1} className={styleClassName}>
|
||||
{/* ----------- Customer name ----------- */}
|
||||
<CreditNoteCustomersSelect />
|
||||
|
||||
@@ -65,24 +87,15 @@ export default function CreditNoteFormHeaderFields({}) {
|
||||
</FormGroup>
|
||||
)}
|
||||
</FastField>
|
||||
|
||||
{/* ----------- Credit note # ----------- */}
|
||||
<CreditNoteTransactionNoField />
|
||||
|
||||
{/* ----------- Reference ----------- */}
|
||||
<FastField name={'reference_no'}>
|
||||
{({ field, meta: { error, touched } }) => (
|
||||
<FormGroup
|
||||
label={<T id={'reference_no'} />}
|
||||
inline={true}
|
||||
className={classNames('form-group--reference', CLASSES.FILL)}
|
||||
intent={inputIntent({ error, touched })}
|
||||
helperText={<ErrorMessage name="reference_no" />}
|
||||
>
|
||||
<InputGroup minimal={true} {...field} />
|
||||
</FormGroup>
|
||||
)}
|
||||
</FastField>
|
||||
</div>
|
||||
<FormGroup label={<T id={'reference_no'} />} name={'reference_no'} inline>
|
||||
<InputGroup name={'reference_no'} minimal />
|
||||
</FormGroup>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
import '@/style/pages/CreditNote/PageForm.scss';
|
||||
|
||||
import { css } from '@emotion/css';
|
||||
import CreditNoteForm from './CreditNoteForm';
|
||||
import { CreditNoteFormProvider } from './CreditNoteFormProvider';
|
||||
import {
|
||||
CreditNoteFormProvider,
|
||||
useCreditNoteFormContext,
|
||||
} from './CreditNoteFormProvider';
|
||||
import { AutoExchangeRateProvider } from '@/containers/Entries/AutoExchangeProvider';
|
||||
import { DashboardInsider } from '@/components';
|
||||
|
||||
/**
|
||||
* Credit note form page.
|
||||
@@ -18,8 +20,24 @@ export default function CreditNoteFormPage() {
|
||||
return (
|
||||
<CreditNoteFormProvider creditNoteId={idAsInteger}>
|
||||
<AutoExchangeRateProvider>
|
||||
<CreditNoteForm />
|
||||
<CreditNoteFormPageContent />
|
||||
</AutoExchangeRateProvider>
|
||||
</CreditNoteFormProvider>
|
||||
);
|
||||
}
|
||||
|
||||
function CreditNoteFormPageContent() {
|
||||
const { isBootLoading } = useCreditNoteFormContext();
|
||||
|
||||
return (
|
||||
<DashboardInsider
|
||||
loading={isBootLoading}
|
||||
className={css`
|
||||
min-height: calc(100vh - var(--top-offset));
|
||||
max-height: calc(100vh - var(--top-offset));
|
||||
`}
|
||||
>
|
||||
<CreditNoteForm />
|
||||
</DashboardInsider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -113,6 +113,13 @@ function CreditNoteFormProvider({ creditNoteId, ...props }) {
|
||||
})
|
||||
: [];
|
||||
|
||||
const isBootLoading =
|
||||
isItemsLoading ||
|
||||
isCustomersLoading ||
|
||||
isCreditNoteLoading ||
|
||||
isInvoiceLoading ||
|
||||
isBrandingTemplatesLoading;
|
||||
|
||||
// Provider payload.
|
||||
const provider = {
|
||||
items,
|
||||
@@ -141,20 +148,11 @@ function CreditNoteFormProvider({ creditNoteId, ...props }) {
|
||||
// Credit note state
|
||||
creditNoteState,
|
||||
isCreditNoteStateLoading,
|
||||
|
||||
isBootLoading,
|
||||
};
|
||||
|
||||
const isLoading =
|
||||
isItemsLoading ||
|
||||
isCustomersLoading ||
|
||||
isCreditNoteLoading ||
|
||||
isInvoiceLoading ||
|
||||
isBrandingTemplatesLoading;
|
||||
|
||||
return (
|
||||
<DashboardInsider loading={isLoading} name={'credit-note-form'}>
|
||||
<CreditNoteFormContext.Provider value={provider} {...props} />
|
||||
</DashboardInsider>
|
||||
);
|
||||
return <CreditNoteFormContext.Provider value={provider} {...props} />;
|
||||
}
|
||||
|
||||
const useCreditNoteFormContext = () =>
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { FastField } from 'formik';
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import ItemsEntriesTable from '@/containers/Entries/ItemsEntriesTable';
|
||||
import { useCreditNoteFormContext } from './CreditNoteFormProvider';
|
||||
import { entriesFieldShouldUpdate } from './utils';
|
||||
import { Box } from '@/components';
|
||||
|
||||
/**
|
||||
* Credit note items entries editor field.
|
||||
@@ -14,7 +13,7 @@ export default function CreditNoteItemsEntriesEditorField() {
|
||||
const { items } = useCreditNoteFormContext();
|
||||
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_BODY)}>
|
||||
<Box p="18px 32px 0">
|
||||
<FastField
|
||||
name={'entries'}
|
||||
items={items}
|
||||
@@ -38,6 +37,6 @@ export default function CreditNoteItemsEntriesEditorField() {
|
||||
/>
|
||||
)}
|
||||
</FastField>
|
||||
</div>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import {
|
||||
Intent,
|
||||
Button,
|
||||
@@ -12,7 +11,6 @@ import {
|
||||
MenuItem,
|
||||
} from '@blueprintjs/core';
|
||||
import { If, Icon, FormattedMessage as T, Group, FSelect } from '@/components';
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { useFormikContext } from 'formik';
|
||||
import { useEstimateFormContext } from './EstimateFormProvider';
|
||||
@@ -21,6 +19,7 @@ import {
|
||||
BrandingThemeFormGroup,
|
||||
BrandingThemeSelectButton,
|
||||
} from '@/containers/BrandingTemplates/BrandingTemplatesSelectFields';
|
||||
import { PageForm } from '@/components/PageForm';
|
||||
|
||||
/**
|
||||
* Estimate floating actions bar.
|
||||
@@ -81,144 +80,145 @@ export default function EstimateFloatingActions() {
|
||||
const brandingTemplatesOptions = useEstimateFormBrandingTemplatesOptions();
|
||||
|
||||
return (
|
||||
<Group
|
||||
spacing={10}
|
||||
className={classNames(CLASSES.PAGE_FORM_FLOATING_ACTIONS)}
|
||||
>
|
||||
{/* ----------- Save And Deliver ----------- */}
|
||||
<If condition={!estimate || !estimate?.is_delivered}>
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
loading={isSubmitting}
|
||||
intent={Intent.PRIMARY}
|
||||
onClick={handleSubmitDeliverBtnClick}
|
||||
text={<T id={'save_and_deliver'} />}
|
||||
/>
|
||||
<Popover
|
||||
content={
|
||||
<Menu>
|
||||
<MenuItem
|
||||
text={<T id={'deliver_and_new'} />}
|
||||
onClick={handleSubmitDeliverAndNewBtnClick}
|
||||
/>
|
||||
<MenuItem
|
||||
text={<T id={'deliver_continue_editing'} />}
|
||||
onClick={handleSubmitDeliverContinueEditingBtnClick}
|
||||
/>
|
||||
</Menu>
|
||||
}
|
||||
minimal={true}
|
||||
interactionKind={PopoverInteractionKind.CLICK}
|
||||
position={Position.BOTTOM_LEFT}
|
||||
>
|
||||
<PageForm.FooterActions position={'apart'} spacing={10}>
|
||||
<Group spacing={10}>
|
||||
{/* ----------- Save And Deliver ----------- */}
|
||||
<If condition={!estimate || !estimate?.is_delivered}>
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
loading={isSubmitting}
|
||||
intent={Intent.PRIMARY}
|
||||
onClick={handleSubmitDeliverBtnClick}
|
||||
text={<T id={'save_and_deliver'} />}
|
||||
/>
|
||||
<Popover
|
||||
content={
|
||||
<Menu>
|
||||
<MenuItem
|
||||
text={<T id={'deliver_and_new'} />}
|
||||
onClick={handleSubmitDeliverAndNewBtnClick}
|
||||
/>
|
||||
<MenuItem
|
||||
text={<T id={'deliver_continue_editing'} />}
|
||||
onClick={handleSubmitDeliverContinueEditingBtnClick}
|
||||
/>
|
||||
</Menu>
|
||||
}
|
||||
minimal={true}
|
||||
interactionKind={PopoverInteractionKind.CLICK}
|
||||
position={Position.BOTTOM_LEFT}
|
||||
>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
intent={Intent.PRIMARY}
|
||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||
/>
|
||||
</Popover>
|
||||
</ButtonGroup>
|
||||
|
||||
{/* ----------- Save As Draft ----------- */}
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
className={'ml1'}
|
||||
onClick={handleSubmitDraftBtnClick}
|
||||
text={<T id={'save_as_draft'} />}
|
||||
/>
|
||||
<Popover
|
||||
content={
|
||||
<Menu>
|
||||
<MenuItem
|
||||
text={<T id={'save_and_new'} />}
|
||||
onClick={handleSubmitDraftAndNewBtnClick}
|
||||
/>
|
||||
<MenuItem
|
||||
text={<T id={'save_continue_editing'} />}
|
||||
onClick={handleSubmitDraftContinueEditingBtnClick}
|
||||
/>
|
||||
</Menu>
|
||||
}
|
||||
minimal={true}
|
||||
interactionKind={PopoverInteractionKind.CLICK}
|
||||
position={Position.BOTTOM_LEFT}
|
||||
>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||
/>
|
||||
</Popover>
|
||||
</ButtonGroup>
|
||||
</If>
|
||||
|
||||
{/* ----------- Save and New ----------- */}
|
||||
<If condition={estimate && estimate?.is_delivered}>
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
intent={Intent.PRIMARY}
|
||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||
onClick={handleSubmitDeliverBtnClick}
|
||||
style={{ minWidth: '85px' }}
|
||||
text={<T id={'save'} />}
|
||||
/>
|
||||
</Popover>
|
||||
</ButtonGroup>
|
||||
<Popover
|
||||
content={
|
||||
<Menu>
|
||||
<MenuItem
|
||||
text={<T id={'save_and_new'} />}
|
||||
onClick={handleSubmitDeliverAndNewBtnClick}
|
||||
/>
|
||||
</Menu>
|
||||
}
|
||||
minimal={true}
|
||||
interactionKind={PopoverInteractionKind.CLICK}
|
||||
position={Position.BOTTOM_LEFT}
|
||||
>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
intent={Intent.PRIMARY}
|
||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||
/>
|
||||
</Popover>
|
||||
</ButtonGroup>
|
||||
</If>
|
||||
|
||||
{/* ----------- Save As Draft ----------- */}
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
className={'ml1'}
|
||||
onClick={handleSubmitDraftBtnClick}
|
||||
text={<T id={'save_as_draft'} />}
|
||||
/>
|
||||
<Popover
|
||||
content={
|
||||
<Menu>
|
||||
<MenuItem
|
||||
text={<T id={'save_and_new'} />}
|
||||
onClick={handleSubmitDraftAndNewBtnClick}
|
||||
/>
|
||||
<MenuItem
|
||||
text={<T id={'save_continue_editing'} />}
|
||||
onClick={handleSubmitDraftContinueEditingBtnClick}
|
||||
/>
|
||||
</Menu>
|
||||
}
|
||||
minimal={true}
|
||||
interactionKind={PopoverInteractionKind.CLICK}
|
||||
position={Position.BOTTOM_LEFT}
|
||||
>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||
/>
|
||||
</Popover>
|
||||
</ButtonGroup>
|
||||
</If>
|
||||
|
||||
{/* ----------- Save and New ----------- */}
|
||||
<If condition={estimate && estimate?.is_delivered}>
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
intent={Intent.PRIMARY}
|
||||
onClick={handleSubmitDeliverBtnClick}
|
||||
style={{ minWidth: '85px' }}
|
||||
text={<T id={'save'} />}
|
||||
/>
|
||||
<Popover
|
||||
content={
|
||||
<Menu>
|
||||
<MenuItem
|
||||
text={<T id={'save_and_new'} />}
|
||||
onClick={handleSubmitDeliverAndNewBtnClick}
|
||||
/>
|
||||
</Menu>
|
||||
}
|
||||
minimal={true}
|
||||
interactionKind={PopoverInteractionKind.CLICK}
|
||||
position={Position.BOTTOM_LEFT}
|
||||
>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
intent={Intent.PRIMARY}
|
||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||
/>
|
||||
</Popover>
|
||||
</ButtonGroup>
|
||||
</If>
|
||||
|
||||
{/* ----------- Clear & Reset----------- */}
|
||||
<Button
|
||||
className={'ml1'}
|
||||
disabled={isSubmitting}
|
||||
onClick={handleClearBtnClick}
|
||||
text={estimate ? <T id={'reset'} /> : <T id={'clear'} />}
|
||||
/>
|
||||
|
||||
{/* ----------- Cancel ----------- */}
|
||||
<Button
|
||||
className={'ml1'}
|
||||
disabled={isSubmitting}
|
||||
onClick={handleCancelBtnClick}
|
||||
text={<T id={'cancel'} />}
|
||||
/>
|
||||
|
||||
{/* ----------- Branding Template Select ----------- */}
|
||||
<BrandingThemeFormGroup
|
||||
name={'pdf_template_id'}
|
||||
label={'Branding'}
|
||||
inline
|
||||
fastField
|
||||
style={{ marginLeft: 20 }}
|
||||
>
|
||||
<FSelect
|
||||
name={'pdf_template_id'}
|
||||
items={brandingTemplatesOptions}
|
||||
input={({ activeItem, text, label, value }) => (
|
||||
<BrandingThemeSelectButton text={text || 'Brand Theme'} minimal />
|
||||
)}
|
||||
filterable={false}
|
||||
popoverProps={{ minimal: true }}
|
||||
{/* ----------- Clear & Reset----------- */}
|
||||
<Button
|
||||
className={'ml1'}
|
||||
disabled={isSubmitting}
|
||||
onClick={handleClearBtnClick}
|
||||
text={estimate ? <T id={'reset'} /> : <T id={'clear'} />}
|
||||
/>
|
||||
</BrandingThemeFormGroup>
|
||||
</Group>
|
||||
|
||||
{/* ----------- Cancel ----------- */}
|
||||
<Button
|
||||
className={'ml1'}
|
||||
disabled={isSubmitting}
|
||||
onClick={handleCancelBtnClick}
|
||||
text={<T id={'cancel'} />}
|
||||
/>
|
||||
</Group>
|
||||
|
||||
<Group>
|
||||
{/* ----------- Branding Template Select ----------- */}
|
||||
<BrandingThemeFormGroup
|
||||
name={'pdf_template_id'}
|
||||
label={'Branding'}
|
||||
inline
|
||||
fastField
|
||||
style={{ marginLeft: 20 }}
|
||||
>
|
||||
<FSelect
|
||||
name={'pdf_template_id'}
|
||||
items={brandingTemplatesOptions}
|
||||
input={({ activeItem, text, label, value }) => (
|
||||
<BrandingThemeSelectButton text={text || 'Brand Theme'} minimal />
|
||||
)}
|
||||
filterable={false}
|
||||
popoverProps={{ minimal: true }}
|
||||
/>
|
||||
</BrandingThemeFormGroup>
|
||||
</Group>
|
||||
</PageForm.FooterActions>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
// @ts-nocheck
|
||||
import intl from 'react-intl-universal';
|
||||
import classNames from 'classnames';
|
||||
import { css } from '@emotion/css';
|
||||
import { Formik, Form } from 'formik';
|
||||
import { Intent } from '@blueprintjs/core';
|
||||
import { sumBy, isEmpty, defaultTo } from 'lodash';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
|
||||
import {
|
||||
CreateEstimateFormSchema,
|
||||
@@ -36,8 +35,9 @@ import {
|
||||
handleErrors,
|
||||
resetFormState,
|
||||
} from './utils';
|
||||
import { PageForm } from '@/components/PageForm';
|
||||
|
||||
/**
|
||||
/**6
|
||||
* Estimate form.
|
||||
*/
|
||||
function EstimateForm({
|
||||
@@ -148,36 +148,42 @@ function EstimateForm({
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
CLASSES.PAGE_FORM,
|
||||
CLASSES.PAGE_FORM_STRIP_STYLE,
|
||||
CLASSES.PAGE_FORM_ESTIMATE,
|
||||
)}
|
||||
<Formik
|
||||
validationSchema={
|
||||
isNewMode ? CreateEstimateFormSchema : EditEstimateFormSchema
|
||||
}
|
||||
initialValues={initialValues}
|
||||
onSubmit={handleFormSubmit}
|
||||
>
|
||||
<Formik
|
||||
validationSchema={
|
||||
isNewMode ? CreateEstimateFormSchema : EditEstimateFormSchema
|
||||
}
|
||||
initialValues={initialValues}
|
||||
onSubmit={handleFormSubmit}
|
||||
<Form
|
||||
className={css({
|
||||
overflow: 'hidden',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
flex: 1
|
||||
})}
|
||||
>
|
||||
<Form>
|
||||
<EstimtaeFormTopBar />
|
||||
<EstimateFormHeader />
|
||||
<EstimateItemsEntriesField />
|
||||
<EstimateFormFooter />
|
||||
<EstimateFloatingActions />
|
||||
<PageForm flex={1}>
|
||||
<PageForm.Body>
|
||||
<EstimtaeFormTopBar />
|
||||
<EstimateFormHeader />
|
||||
<EstimateItemsEntriesField />
|
||||
<EstimateFormFooter />
|
||||
</PageForm.Body>
|
||||
|
||||
{/*------- Dialogs -------*/}
|
||||
<EstimateFormDialogs />
|
||||
<PageForm.Footer>
|
||||
<EstimateFloatingActions />
|
||||
</PageForm.Footer>
|
||||
</PageForm>
|
||||
|
||||
{/*------- Effects -------*/}
|
||||
<EstimateIncrementSyncSettingsToForm />
|
||||
<EstimateSyncAutoExRateToForm />
|
||||
</Form>
|
||||
</Formik>
|
||||
</div>
|
||||
{/*------- Dialogs -------*/}
|
||||
<EstimateFormDialogs />
|
||||
|
||||
{/*------- Effects -------*/}
|
||||
<EstimateIncrementSyncSettingsToForm />
|
||||
<EstimateSyncAutoExRateToForm />
|
||||
</Form>
|
||||
</Formik>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import styled from 'styled-components';
|
||||
import { x } from '@xstyled/emotion';
|
||||
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import { Row, Col, Paper } from '@/components';
|
||||
import { EstimateFormFooterLeft } from './EstimateFormFooterLeft';
|
||||
import { EstimateFormFooterRight } from './EstimateFormFooterRight';
|
||||
@@ -14,8 +12,8 @@ import { UploadAttachmentButton } from '@/containers/Attachments/UploadAttachmen
|
||||
*/
|
||||
export default function EstiamteFormFooter() {
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_FOOTER)}>
|
||||
<EstimateFooterPaper>
|
||||
<x.div mt={'20px'} px={'32px'} pb={'20px'} flex={1}>
|
||||
<Paper p={'20px'}>
|
||||
<Row>
|
||||
<Col md={8}>
|
||||
<EstimateFormFooterLeft />
|
||||
@@ -26,11 +24,7 @@ export default function EstiamteFormFooter() {
|
||||
<EstimateFormFooterRight />
|
||||
</Col>
|
||||
</Row>
|
||||
</EstimateFooterPaper>
|
||||
</div>
|
||||
</Paper>
|
||||
</x.div>
|
||||
);
|
||||
}
|
||||
|
||||
const EstimateFooterPaper = styled(Paper)`
|
||||
padding: 20px;
|
||||
`;
|
||||
|
||||
@@ -1,22 +1,26 @@
|
||||
// @ts-nocheck
|
||||
import React, { useMemo } from 'react';
|
||||
import intl from 'react-intl-universal';
|
||||
import classNames from 'classnames';
|
||||
import { useFormikContext } from 'formik';
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import { x } from '@xstyled/emotion';
|
||||
|
||||
import EstimateFormHeaderFields from './EstimateFormHeaderFields';
|
||||
|
||||
import { getEntriesTotal } from '@/containers/Entries/utils';
|
||||
import { PageFormBigNumber } from '@/components';
|
||||
import { Group, PageFormBigNumber } from '@/components';
|
||||
|
||||
// Estimate form top header.
|
||||
function EstimateFormHeader() {
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_HEADER)}>
|
||||
<Group
|
||||
position="apart"
|
||||
align={'flex-start'}
|
||||
bg="white"
|
||||
p="25px 32px"
|
||||
borderBottom="1px solid #d2dce2"
|
||||
>
|
||||
<EstimateFormHeaderFields />
|
||||
<EstimateFormBigTotal />
|
||||
</div>
|
||||
</Group>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
// @ts-nocheck
|
||||
import styled from 'styled-components';
|
||||
import classNames from 'classnames';
|
||||
import { FormGroup, InputGroup, Position, Classes } from '@blueprintjs/core';
|
||||
import { FormGroup, Position, Classes } from '@blueprintjs/core';
|
||||
import { DateInput } from '@blueprintjs/datetime';
|
||||
import { FastField, ErrorMessage, useFormikContext } from 'formik';
|
||||
|
||||
import { css } from '@emotion/css';
|
||||
import {
|
||||
FeatureCan,
|
||||
FFormGroup,
|
||||
@@ -13,6 +13,8 @@ import {
|
||||
Icon,
|
||||
CustomerDrawerLink,
|
||||
CustomersSelect,
|
||||
FInputGroup,
|
||||
Stack,
|
||||
} from '@/components';
|
||||
import {
|
||||
momentFormatter,
|
||||
@@ -31,15 +33,36 @@ import {
|
||||
import { EstimateFormEstimateNumberField } from './EstimateFormEstimateNumberField';
|
||||
import { useEstimateFormContext } from './EstimateFormProvider';
|
||||
import { useCustomerUpdateExRate } from '@/containers/Entries/withExRateItemEntriesPriceRecalc';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import { Theme } from '@xstyled/emotion';
|
||||
|
||||
const getEstimateFieldsStyle = (theme: Theme) => css`
|
||||
.${theme.bpPrefix}-form-group {
|
||||
margin-bottom: 0;
|
||||
|
||||
&.${theme.bpPrefix}-inline {
|
||||
max-width: 470px;
|
||||
}
|
||||
.${theme.bpPrefix}-label {
|
||||
min-width: 160px;
|
||||
font-weight: 500;
|
||||
}
|
||||
.${theme.bpPrefix}-form-content {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* Estimate form header.
|
||||
*/
|
||||
export default function EstimateFormHeader() {
|
||||
const theme = useTheme();
|
||||
const { projects } = useEstimateFormContext();
|
||||
const styleClassName = getEstimateFieldsStyle(theme);
|
||||
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_HEADER_FIELDS)}>
|
||||
<Stack spacing={18} flex={1} className={styleClassName}>
|
||||
{/* ----------- Customer name ----------- */}
|
||||
<EstimateFormCustomerSelect />
|
||||
|
||||
@@ -106,19 +129,9 @@ export default function EstimateFormHeader() {
|
||||
<EstimateFormEstimateNumberField />
|
||||
|
||||
{/* ----------- Reference ----------- */}
|
||||
<FastField name={'reference'}>
|
||||
{({ form, field, meta: { error, touched } }) => (
|
||||
<FormGroup
|
||||
label={<T id={'reference'} />}
|
||||
inline={true}
|
||||
className={classNames('form-group--reference', CLASSES.FILL)}
|
||||
intent={inputIntent({ error, touched })}
|
||||
helperText={<ErrorMessage name="reference" />}
|
||||
>
|
||||
<InputGroup minimal={true} {...field} />
|
||||
</FormGroup>
|
||||
)}
|
||||
</FastField>
|
||||
<FFormGroup name={'reference'} label={<T id={'reference'} />} inline fill>
|
||||
<FInputGroup name={'reference'} minimal={true} />
|
||||
</FFormGroup>
|
||||
|
||||
{/*------------ Project name -----------*/}
|
||||
<FeatureCan feature={Features.Projects}>
|
||||
@@ -136,7 +149,7 @@ export default function EstimateFormHeader() {
|
||||
/>
|
||||
</FFormGroup>
|
||||
</FeatureCan>
|
||||
</div>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
import '@/style/pages/SaleEstimate/PageForm.scss';
|
||||
import { css } from '@emotion/css';
|
||||
|
||||
import EstimateForm from './EstimateForm';
|
||||
import { EstimateFormProvider } from './EstimateFormProvider';
|
||||
import {
|
||||
EstimateFormProvider,
|
||||
useEstimateFormContext,
|
||||
} from './EstimateFormProvider';
|
||||
import { AutoExchangeRateProvider } from '@/containers/Entries/AutoExchangeProvider';
|
||||
import { DashboardInsider } from '@/components';
|
||||
|
||||
/**
|
||||
* Estimate form page.
|
||||
@@ -18,8 +21,24 @@ export default function EstimateFormPage() {
|
||||
return (
|
||||
<EstimateFormProvider estimateId={idInteger}>
|
||||
<AutoExchangeRateProvider>
|
||||
<EstimateForm />
|
||||
<EstimateFormPageContent />
|
||||
</AutoExchangeRateProvider>
|
||||
</EstimateFormProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export function EstimateFormPageContent() {
|
||||
const { isBootLoading } = useEstimateFormContext();
|
||||
|
||||
return (
|
||||
<DashboardInsider
|
||||
loading={isBootLoading}
|
||||
className={css`
|
||||
min-height: calc(100vh - var(--top-offset));
|
||||
max-height: calc(100vh - var(--top-offset));
|
||||
`}
|
||||
>
|
||||
<EstimateForm />
|
||||
</DashboardInsider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -103,6 +103,13 @@ function EstimateFormProvider({ query, estimateId, ...props }) {
|
||||
const isFeatureLoading =
|
||||
isWarehouesLoading || isBranchesLoading || isProjectsLoading;
|
||||
|
||||
const isBootLoading =
|
||||
isCustomersLoading ||
|
||||
isItemsLoading ||
|
||||
isEstimateLoading ||
|
||||
isBrandingTemplatesLoading ||
|
||||
isSaleEstimateStateLoading;
|
||||
|
||||
// Provider payload.
|
||||
const provider = {
|
||||
estimateId,
|
||||
@@ -136,20 +143,11 @@ function EstimateFormProvider({ query, estimateId, ...props }) {
|
||||
// Estimate state
|
||||
saleEstimateState,
|
||||
isSaleEstimateStateLoading,
|
||||
|
||||
isBootLoading,
|
||||
};
|
||||
|
||||
const isLoading =
|
||||
isCustomersLoading ||
|
||||
isItemsLoading ||
|
||||
isEstimateLoading ||
|
||||
isBrandingTemplatesLoading ||
|
||||
isSaleEstimateStateLoading;
|
||||
|
||||
return (
|
||||
<DashboardInsider loading={isLoading} name={'estimate-form'}>
|
||||
<EstimateFormContext.Provider value={provider} {...props} />
|
||||
</DashboardInsider>
|
||||
);
|
||||
return <EstimateFormContext.Provider value={provider} {...props} />;
|
||||
}
|
||||
|
||||
const useEstimateFormContext = () =>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { x } from '@xstyled/emotion';
|
||||
import { FastField } from 'formik';
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import ItemsEntriesTable from '@/containers/Entries/ItemsEntriesTable';
|
||||
import { useEstimateFormContext } from './EstimateFormProvider';
|
||||
import { entriesFieldShouldUpdate } from './utils';
|
||||
@@ -14,7 +13,7 @@ export default function EstimateFormItemsEntriesField() {
|
||||
const { items } = useEstimateFormContext();
|
||||
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_BODY)}>
|
||||
<x.div p="18px 32px 0">
|
||||
<FastField
|
||||
name={'entries'}
|
||||
items={items}
|
||||
@@ -38,6 +37,6 @@ export default function EstimateFormItemsEntriesField() {
|
||||
/>
|
||||
)}
|
||||
</FastField>
|
||||
</div>
|
||||
</x.div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// @ts-nocheck
|
||||
import React, { useMemo } from 'react';
|
||||
import React from 'react';
|
||||
import {
|
||||
Intent,
|
||||
Button,
|
||||
@@ -11,9 +11,7 @@ import {
|
||||
MenuItem,
|
||||
} from '@blueprintjs/core';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import classNames from 'classnames';
|
||||
import { useFormikContext } from 'formik';
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import { If, Icon, FormattedMessage as T, Group, FSelect } from '@/components';
|
||||
import { useInvoiceFormContext } from './InvoiceFormProvider';
|
||||
import { useInvoiceFormBrandingTemplatesOptions } from './utils';
|
||||
@@ -21,6 +19,7 @@ import {
|
||||
BrandingThemeFormGroup,
|
||||
BrandingThemeSelectButton,
|
||||
} from '@/containers/BrandingTemplates/BrandingTemplatesSelectFields';
|
||||
import { PageForm } from '@/components/PageForm';
|
||||
|
||||
/**
|
||||
* Invoice floating actions bar.
|
||||
@@ -83,142 +82,144 @@ export default function InvoiceFloatingActions() {
|
||||
const brandingTemplatesOptions = useInvoiceFormBrandingTemplatesOptions();
|
||||
|
||||
return (
|
||||
<Group
|
||||
spacing={10}
|
||||
className={classNames(CLASSES.PAGE_FORM_FLOATING_ACTIONS)}
|
||||
>
|
||||
{/* ----------- Save And Deliver ----------- */}
|
||||
<If condition={!invoice || !invoice?.is_delivered}>
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
loading={isSubmitting}
|
||||
intent={Intent.PRIMARY}
|
||||
onClick={handleSubmitDeliverBtnClick}
|
||||
text={<T id={'save_and_deliver'} />}
|
||||
/>
|
||||
<Popover
|
||||
content={
|
||||
<Menu>
|
||||
<MenuItem
|
||||
text={<T id={'deliver_and_new'} />}
|
||||
onClick={handleSubmitDeliverAndNewBtnClick}
|
||||
/>
|
||||
<MenuItem
|
||||
text={<T id={'deliver_continue_editing'} />}
|
||||
onClick={handleSubmitDeliverContinueEditingBtnClick}
|
||||
/>
|
||||
</Menu>
|
||||
}
|
||||
minimal={true}
|
||||
interactionKind={PopoverInteractionKind.CLICK}
|
||||
position={Position.BOTTOM_LEFT}
|
||||
>
|
||||
<PageForm.FooterActions spacing={10} position={'apart'}>
|
||||
<Group spacing={10}>
|
||||
{/* ----------- Save And Deliver ----------- */}
|
||||
<If condition={!invoice || !invoice?.is_delivered}>
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
loading={isSubmitting}
|
||||
intent={Intent.PRIMARY}
|
||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||
onClick={handleSubmitDeliverBtnClick}
|
||||
text={<T id={'save_and_deliver'} />}
|
||||
/>
|
||||
</Popover>
|
||||
</ButtonGroup>
|
||||
{/* ----------- Save As Draft ----------- */}
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
className={'ml1'}
|
||||
onClick={handleSubmitDraftBtnClick}
|
||||
text={<T id={'save_as_draft'} />}
|
||||
/>
|
||||
<Popover
|
||||
content={
|
||||
<Menu>
|
||||
<MenuItem
|
||||
text={<T id={'save_and_new'} />}
|
||||
onClick={handleSubmitDraftAndNewBtnClick}
|
||||
/>
|
||||
<MenuItem
|
||||
text={<T id={'save_continue_editing'} />}
|
||||
onClick={handleSubmitDraftContinueEditingBtnClick}
|
||||
/>
|
||||
</Menu>
|
||||
}
|
||||
minimal={true}
|
||||
interactionKind={PopoverInteractionKind.CLICK}
|
||||
position={Position.BOTTOM_LEFT}
|
||||
>
|
||||
<Popover
|
||||
content={
|
||||
<Menu>
|
||||
<MenuItem
|
||||
text={<T id={'deliver_and_new'} />}
|
||||
onClick={handleSubmitDeliverAndNewBtnClick}
|
||||
/>
|
||||
<MenuItem
|
||||
text={<T id={'deliver_continue_editing'} />}
|
||||
onClick={handleSubmitDeliverContinueEditingBtnClick}
|
||||
/>
|
||||
</Menu>
|
||||
}
|
||||
minimal={true}
|
||||
interactionKind={PopoverInteractionKind.CLICK}
|
||||
position={Position.BOTTOM_LEFT}
|
||||
>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
intent={Intent.PRIMARY}
|
||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||
/>
|
||||
</Popover>
|
||||
</ButtonGroup>
|
||||
|
||||
{/* ----------- Save As Draft ----------- */}
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||
className={'ml1'}
|
||||
onClick={handleSubmitDraftBtnClick}
|
||||
text={<T id={'save_as_draft'} />}
|
||||
/>
|
||||
</Popover>
|
||||
</ButtonGroup>
|
||||
</If>
|
||||
{/* ----------- Save and New ----------- */}
|
||||
<If condition={invoice && invoice?.is_delivered}>
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
loading={isSubmitting}
|
||||
intent={Intent.PRIMARY}
|
||||
onClick={handleSubmitDeliverBtnClick}
|
||||
style={{ minWidth: '85px' }}
|
||||
text={<T id={'save'} />}
|
||||
/>
|
||||
<Popover
|
||||
content={
|
||||
<Menu>
|
||||
<MenuItem
|
||||
text={<T id={'save_and_new'} />}
|
||||
onClick={handleSubmitDeliverAndNewBtnClick}
|
||||
/>
|
||||
</Menu>
|
||||
}
|
||||
minimal={true}
|
||||
interactionKind={PopoverInteractionKind.CLICK}
|
||||
position={Position.BOTTOM_LEFT}
|
||||
>
|
||||
<Popover
|
||||
content={
|
||||
<Menu>
|
||||
<MenuItem
|
||||
text={<T id={'save_and_new'} />}
|
||||
onClick={handleSubmitDraftAndNewBtnClick}
|
||||
/>
|
||||
<MenuItem
|
||||
text={<T id={'save_continue_editing'} />}
|
||||
onClick={handleSubmitDraftContinueEditingBtnClick}
|
||||
/>
|
||||
</Menu>
|
||||
}
|
||||
minimal={true}
|
||||
interactionKind={PopoverInteractionKind.CLICK}
|
||||
position={Position.BOTTOM_LEFT}
|
||||
>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||
/>
|
||||
</Popover>
|
||||
</ButtonGroup>
|
||||
</If>
|
||||
|
||||
{/* ----------- Save and New ----------- */}
|
||||
<If condition={invoice && invoice?.is_delivered}>
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
loading={isSubmitting}
|
||||
intent={Intent.PRIMARY}
|
||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||
onClick={handleSubmitDeliverBtnClick}
|
||||
style={{ minWidth: '85px' }}
|
||||
text={<T id={'save'} />}
|
||||
/>
|
||||
</Popover>
|
||||
</ButtonGroup>
|
||||
</If>
|
||||
<Popover
|
||||
content={
|
||||
<Menu>
|
||||
<MenuItem
|
||||
text={<T id={'save_and_new'} />}
|
||||
onClick={handleSubmitDeliverAndNewBtnClick}
|
||||
/>
|
||||
</Menu>
|
||||
}
|
||||
minimal={true}
|
||||
interactionKind={PopoverInteractionKind.CLICK}
|
||||
position={Position.BOTTOM_LEFT}
|
||||
>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
intent={Intent.PRIMARY}
|
||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||
/>
|
||||
</Popover>
|
||||
</ButtonGroup>
|
||||
</If>
|
||||
|
||||
{/* ----------- Clear & Reset----------- */}
|
||||
<Button
|
||||
className={'ml1'}
|
||||
disabled={isSubmitting}
|
||||
onClick={handleClearBtnClick}
|
||||
text={invoice ? <T id={'reset'} /> : <T id={'clear'} />}
|
||||
/>
|
||||
{/* ----------- Cancel ----------- */}
|
||||
<Button
|
||||
className={'ml1'}
|
||||
onClick={handleCancelBtnClick}
|
||||
text={<T id={'cancel'} />}
|
||||
/>
|
||||
|
||||
{/* ----------- Branding Template Select ----------- */}
|
||||
<BrandingThemeFormGroup
|
||||
name={'pdf_template_id'}
|
||||
label={'Branding'}
|
||||
inline
|
||||
fastField
|
||||
style={{ marginLeft: 20 }}
|
||||
>
|
||||
<FSelect
|
||||
name={'pdf_template_id'}
|
||||
items={brandingTemplatesOptions}
|
||||
input={({ activeItem, text, label, value }) => (
|
||||
<BrandingThemeSelectButton text={text || 'Brand Theme'} minimal />
|
||||
)}
|
||||
filterable={false}
|
||||
popoverProps={{ minimal: true }}
|
||||
{/* ----------- Clear & Reset----------- */}
|
||||
<Button
|
||||
className={'ml1'}
|
||||
disabled={isSubmitting}
|
||||
onClick={handleClearBtnClick}
|
||||
text={invoice ? <T id={'reset'} /> : <T id={'clear'} />}
|
||||
/>
|
||||
</BrandingThemeFormGroup>
|
||||
</Group>
|
||||
{/* ----------- Cancel ----------- */}
|
||||
<Button
|
||||
className={'ml1'}
|
||||
onClick={handleCancelBtnClick}
|
||||
text={<T id={'cancel'} />}
|
||||
/>
|
||||
</Group>
|
||||
|
||||
<Group spacing={10}>
|
||||
{/* ----------- Branding Template Select ----------- */}
|
||||
<BrandingThemeFormGroup
|
||||
name={'pdf_template_id'}
|
||||
label={'Branding'}
|
||||
inline
|
||||
fastField
|
||||
style={{ marginLeft: 20 }}
|
||||
>
|
||||
<FSelect
|
||||
name={'pdf_template_id'}
|
||||
items={brandingTemplatesOptions}
|
||||
input={({ activeItem, text, label, value }) => (
|
||||
<BrandingThemeSelectButton text={text || 'Brand Theme'} minimal />
|
||||
)}
|
||||
filterable={false}
|
||||
popoverProps={{ minimal: true }}
|
||||
/>
|
||||
</BrandingThemeFormGroup>
|
||||
</Group>
|
||||
</PageForm.FooterActions>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import intl from 'react-intl-universal';
|
||||
import classNames from 'classnames';
|
||||
import { Formik, Form } from 'formik';
|
||||
import { Intent } from '@blueprintjs/core';
|
||||
import { sumBy, isEmpty, defaultTo } from 'lodash';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import { css } from '@emotion/css';
|
||||
import {
|
||||
getCreateInvoiceFormSchema,
|
||||
getEditInvoiceFormSchema,
|
||||
@@ -23,7 +22,7 @@ import withDashboardActions from '@/containers/Dashboard/withDashboardActions';
|
||||
import withSettings from '@/containers/Settings/withSettings';
|
||||
import withCurrentOrganization from '@/containers/Organization/withCurrentOrganization';
|
||||
|
||||
import { AppToaster } from '@/components';
|
||||
import { AppToaster, Box } from '@/components';
|
||||
import { compose, orderingLinesIndexes, transactionNumber } from '@/utils';
|
||||
import { useInvoiceFormContext } from './InvoiceFormProvider';
|
||||
import { InvoiceFormActions } from './InvoiceFormActions';
|
||||
@@ -34,12 +33,16 @@ import {
|
||||
transformValueToRequest,
|
||||
resetFormState,
|
||||
} from './utils';
|
||||
import { InvoiceExchangeRateSync, InvoiceNoSyncSettingsToForm } from './components';
|
||||
import {
|
||||
InvoiceExchangeRateSync,
|
||||
InvoiceNoSyncSettingsToForm,
|
||||
} from './components';
|
||||
import { PageForm } from '@/components/PageForm';
|
||||
|
||||
/**
|
||||
* Invoice form.
|
||||
*/
|
||||
function InvoiceForm({
|
||||
function InvoiceFormRoot({
|
||||
// #withSettings
|
||||
invoiceNextNumber,
|
||||
invoiceNumberPrefix,
|
||||
@@ -61,7 +64,7 @@ function InvoiceForm({
|
||||
createInvoiceMutate,
|
||||
editInvoiceMutate,
|
||||
submitPayload,
|
||||
saleInvoiceState
|
||||
saleInvoiceState,
|
||||
} = useInvoiceFormContext();
|
||||
|
||||
// Invoice number.
|
||||
@@ -156,30 +159,36 @@ function InvoiceForm({
|
||||
const EditInvoiceFormSchema = getEditInvoiceFormSchema();
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
CLASSES.PAGE_FORM,
|
||||
CLASSES.PAGE_FORM_STRIP_STYLE,
|
||||
CLASSES.PAGE_FORM_INVOICE,
|
||||
)}
|
||||
<Formik
|
||||
validationSchema={
|
||||
isNewMode ? CreateInvoiceFormSchema : EditInvoiceFormSchema
|
||||
}
|
||||
initialValues={initialValues}
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
<Formik
|
||||
validationSchema={
|
||||
isNewMode ? CreateInvoiceFormSchema : EditInvoiceFormSchema
|
||||
}
|
||||
initialValues={initialValues}
|
||||
onSubmit={handleSubmit}
|
||||
<Form
|
||||
className={css({
|
||||
overflow: 'hidden',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
flex: 1,
|
||||
})}
|
||||
>
|
||||
<Form>
|
||||
<InvoiceFormTopBar />
|
||||
<InvoiceFormHeader />
|
||||
<PageForm flex={1}>
|
||||
<PageForm.Body>
|
||||
<InvoiceFormTopBar />
|
||||
<InvoiceFormHeader />
|
||||
|
||||
<div className={classNames(CLASSES.PAGE_FORM_BODY)}>
|
||||
<InvoiceFormActions />
|
||||
<InvoiceItemsEntriesEditorField />
|
||||
</div>
|
||||
<InvoiceFormFooter />
|
||||
<InvoiceFloatingActions />
|
||||
<Box p="18px 32px 0">
|
||||
<InvoiceFormActions />
|
||||
<InvoiceItemsEntriesEditorField />
|
||||
</Box>
|
||||
<InvoiceFormFooter />
|
||||
</PageForm.Body>
|
||||
|
||||
<PageForm.Footer>
|
||||
<InvoiceFloatingActions />
|
||||
</PageForm.Footer>
|
||||
|
||||
{/*---------- Dialogs ----------*/}
|
||||
<InvoiceFormDialogs />
|
||||
@@ -187,13 +196,13 @@ function InvoiceForm({
|
||||
{/*---------- Effects ----------*/}
|
||||
<InvoiceNoSyncSettingsToForm />
|
||||
<InvoiceExchangeRateSync />
|
||||
</Form>
|
||||
</Formik>
|
||||
</div>
|
||||
</PageForm>
|
||||
</Form>
|
||||
</Formik>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(
|
||||
export const InvoiceForm = compose(
|
||||
withDashboardActions,
|
||||
withSettings(({ invoiceSettings }) => ({
|
||||
invoiceNextNumber: invoiceSettings?.nextNumber,
|
||||
@@ -203,4 +212,4 @@ export default compose(
|
||||
invoiceTermsConditions: invoiceSettings?.termsConditions,
|
||||
})),
|
||||
withCurrentOrganization(),
|
||||
)(InvoiceForm);
|
||||
)(InvoiceFormRoot);
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import styled from 'styled-components';
|
||||
import { x } from '@xstyled/emotion';
|
||||
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import { Paper, Row, Col } from '@/components';
|
||||
import { Row, Col, Paper } from '@/components';
|
||||
import { InvoiceFormFooterLeft } from './InvoiceFormFooterLeft';
|
||||
import { InvoiceFormFooterRight } from './InvoiceFormFooterRight';
|
||||
import { UploadAttachmentButton } from '../../../Attachments/UploadAttachmentButton';
|
||||
|
||||
export default function InvoiceFormFooter() {
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_FOOTER)}>
|
||||
<InvoiceFooterPaper>
|
||||
<x.div mt={'20px'} px={'32px'} pb={'20px'} flex={1}>
|
||||
<Paper p={'20px'}>
|
||||
<Row>
|
||||
<Col md={8}>
|
||||
<InvoiceFormFooterLeft />
|
||||
@@ -23,11 +21,7 @@ export default function InvoiceFormFooter() {
|
||||
<InvoiceFormFooterRight />
|
||||
</Col>
|
||||
</Row>
|
||||
</InvoiceFooterPaper>
|
||||
</div>
|
||||
</Paper>
|
||||
</x.div>
|
||||
);
|
||||
}
|
||||
|
||||
const InvoiceFooterPaper = styled(Paper)`
|
||||
padding: 20px;
|
||||
`;
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import intl from 'react-intl-universal';
|
||||
import classNames from 'classnames';
|
||||
import { useFormikContext } from 'formik';
|
||||
|
||||
import { Group, PageFormBigNumber } from '@/components';
|
||||
import InvoiceFormHeaderFields from './InvoiceFormHeaderFields';
|
||||
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import { PageFormBigNumber } from '@/components';
|
||||
import { useInvoiceDueAmount } from './utils';
|
||||
|
||||
/**
|
||||
@@ -15,10 +11,16 @@ import { useInvoiceDueAmount } from './utils';
|
||||
*/
|
||||
function InvoiceFormHeader() {
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_HEADER)}>
|
||||
<Group
|
||||
position="apart"
|
||||
align={'flex-start'}
|
||||
bg="white"
|
||||
p="25px 32px"
|
||||
borderBottom="1px solid #d2dce2"
|
||||
>
|
||||
<InvoiceFormHeaderFields />
|
||||
<InvoiceFormBigTotal />
|
||||
</div>
|
||||
</Group>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,19 +2,23 @@
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import classNames from 'classnames';
|
||||
import { FormGroup, InputGroup, Position, Classes } from '@blueprintjs/core';
|
||||
import { FormGroup, Position, Classes } from '@blueprintjs/core';
|
||||
import { DateInput } from '@blueprintjs/datetime';
|
||||
import { FastField, ErrorMessage, useFormikContext } from 'formik';
|
||||
import { css } from '@emotion/css';
|
||||
import { Theme, useTheme } from '@emotion/react';
|
||||
|
||||
import {
|
||||
FFormGroup,
|
||||
FormattedMessage as T,
|
||||
Col,
|
||||
Row,
|
||||
CustomerDrawerLink,
|
||||
FieldRequiredHint,
|
||||
FeatureCan,
|
||||
CustomersSelect,
|
||||
Stack,
|
||||
Group,
|
||||
FInputGroup,
|
||||
Icon,
|
||||
} from '@/components';
|
||||
import {
|
||||
momentFormatter,
|
||||
@@ -38,97 +42,105 @@ import {
|
||||
import { Features } from '@/constants';
|
||||
import { useCustomerUpdateExRate } from '@/containers/Entries/withExRateItemEntriesPriceRecalc';
|
||||
|
||||
const getInvoiceFieldsStyle = (theme: Theme) => css`
|
||||
.${theme.bpPrefix}-form-group {
|
||||
margin-bottom: 0;
|
||||
|
||||
&.${theme.bpPrefix}-inline {
|
||||
max-width: 450px;
|
||||
}
|
||||
.${theme.bpPrefix}-label {
|
||||
min-width: 150px;
|
||||
font-weight: 500;
|
||||
}
|
||||
.${theme.bpPrefix}-form-content {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* Invoice form header fields.
|
||||
*/
|
||||
export default function InvoiceFormHeaderFields() {
|
||||
// Invoice form context.
|
||||
const theme = useTheme();
|
||||
const { projects } = useInvoiceFormContext();
|
||||
const { values } = useFormikContext();
|
||||
const invoiceFieldsClassName = getInvoiceFieldsStyle(theme);
|
||||
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_HEADER_FIELDS)}>
|
||||
<Stack spacing={18} flex={1} className={invoiceFieldsClassName}>
|
||||
{/* ----------- Customer name ----------- */}
|
||||
<InvoiceFormCustomerSelect />
|
||||
|
||||
{/* ----------- Exchange rate ----------- */}
|
||||
<InvoiceExchangeRateInputField />
|
||||
|
||||
<Row>
|
||||
<Col xs={6}>
|
||||
{/* ----------- Invoice date ----------- */}
|
||||
<FastField name={'invoice_date'}>
|
||||
{({ form, field: { value }, meta: { error, touched } }) => (
|
||||
<FormGroup
|
||||
label={<T id={'invoice_date'} />}
|
||||
inline={true}
|
||||
labelInfo={<FieldRequiredHint />}
|
||||
className={classNames('form-group--invoice-date', CLASSES.FILL)}
|
||||
intent={inputIntent({ error, touched })}
|
||||
helperText={<ErrorMessage name="invoice_date" />}
|
||||
>
|
||||
<DateInput
|
||||
{...momentFormatter('YYYY/MM/DD')}
|
||||
value={tansformDateValue(value)}
|
||||
onChange={handleDateChange((formattedDate) => {
|
||||
form.setFieldValue('invoice_date', formattedDate);
|
||||
})}
|
||||
popoverProps={{
|
||||
position: Position.BOTTOM_LEFT,
|
||||
minimal: true,
|
||||
}}
|
||||
/>
|
||||
</FormGroup>
|
||||
)}
|
||||
</FastField>
|
||||
</Col>
|
||||
{/* ----------- Invoice date ----------- */}
|
||||
<FastField name={'invoice_date'}>
|
||||
{({ form, field: { value }, meta: { error, touched } }) => (
|
||||
<FormGroup
|
||||
label={<T id={'invoice_date'} />}
|
||||
inline={true}
|
||||
labelInfo={<FieldRequiredHint />}
|
||||
className={classNames(CLASSES.FILL)}
|
||||
intent={inputIntent({ error, touched })}
|
||||
helperText={<ErrorMessage name="invoice_date" />}
|
||||
>
|
||||
<DateInput
|
||||
{...momentFormatter('YYYY/MM/DD')}
|
||||
value={tansformDateValue(value)}
|
||||
onChange={handleDateChange((formattedDate) => {
|
||||
form.setFieldValue('invoice_date', formattedDate);
|
||||
})}
|
||||
popoverProps={{
|
||||
position: Position.BOTTOM_LEFT,
|
||||
minimal: true,
|
||||
}}
|
||||
inputProps={{
|
||||
leftIcon: <Icon icon={'date-range'} />,
|
||||
}}
|
||||
/>
|
||||
</FormGroup>
|
||||
)}
|
||||
</FastField>
|
||||
|
||||
<Col xs={6}>
|
||||
{/* ----------- Due date ----------- */}
|
||||
<FastField name={'due_date'}>
|
||||
{({ form, field: { value }, meta: { error, touched } }) => (
|
||||
<FormGroup
|
||||
label={<T id={'due_date'} />}
|
||||
labelInfo={<FieldRequiredHint />}
|
||||
inline={true}
|
||||
className={classNames('form-group--due-date', CLASSES.FILL)}
|
||||
intent={inputIntent({ error, touched })}
|
||||
helperText={<ErrorMessage name="due_date" />}
|
||||
>
|
||||
<DateInput
|
||||
{...momentFormatter('YYYY/MM/DD')}
|
||||
value={tansformDateValue(value)}
|
||||
onChange={handleDateChange((formattedDate) => {
|
||||
form.setFieldValue('due_date', formattedDate);
|
||||
})}
|
||||
popoverProps={{
|
||||
position: Position.BOTTOM_LEFT,
|
||||
minimal: true,
|
||||
}}
|
||||
/>
|
||||
</FormGroup>
|
||||
)}
|
||||
</FastField>
|
||||
</Col>
|
||||
</Row>
|
||||
{/* ----------- Due date ----------- */}
|
||||
<FastField name={'due_date'}>
|
||||
{({ form, field: { value }, meta: { error, touched } }) => (
|
||||
<FormGroup
|
||||
label={<T id={'due_date'} />}
|
||||
labelInfo={<FieldRequiredHint />}
|
||||
inline={true}
|
||||
className={classNames(CLASSES.FILL)}
|
||||
intent={inputIntent({ error, touched })}
|
||||
helperText={<ErrorMessage name="due_date" />}
|
||||
>
|
||||
<DateInput
|
||||
{...momentFormatter('YYYY/MM/DD')}
|
||||
value={tansformDateValue(value)}
|
||||
onChange={handleDateChange((formattedDate) => {
|
||||
form.setFieldValue('due_date', formattedDate);
|
||||
})}
|
||||
popoverProps={{
|
||||
position: Position.BOTTOM_LEFT,
|
||||
minimal: true,
|
||||
}}
|
||||
inputProps={{
|
||||
leftIcon: <Icon icon={'date-range'} />,
|
||||
}}
|
||||
/>
|
||||
</FormGroup>
|
||||
)}
|
||||
</FastField>
|
||||
|
||||
{/* ----------- Invoice number ----------- */}
|
||||
<InvoiceFormInvoiceNumberField />
|
||||
|
||||
{/* ----------- Reference ----------- */}
|
||||
<FastField name={'reference_no'}>
|
||||
{({ field, meta: { error, touched } }) => (
|
||||
<FormGroup
|
||||
label={<T id={'reference'} />}
|
||||
inline={true}
|
||||
className={classNames('form-group--reference', CLASSES.FILL)}
|
||||
intent={inputIntent({ error, touched })}
|
||||
helperText={<ErrorMessage name="reference_no" />}
|
||||
>
|
||||
<InputGroup minimal={true} {...field} />
|
||||
</FormGroup>
|
||||
)}
|
||||
</FastField>
|
||||
<FFormGroup name={'reference_no'} label={<T id={'reference'} />} inline>
|
||||
<FInputGroup name={'reference_no'} minimal={true} />
|
||||
</FFormGroup>
|
||||
|
||||
{/*------------ Project name -----------*/}
|
||||
<FeatureCan feature={Features.Projects}>
|
||||
@@ -151,7 +163,7 @@ export default function InvoiceFormHeaderFields() {
|
||||
)}
|
||||
</FFormGroup>
|
||||
</FeatureCan>
|
||||
</div>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,25 +1,43 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
import '@/style/pages/SaleInvoice/PageForm.scss';
|
||||
|
||||
import InvoiceForm from './InvoiceForm';
|
||||
import { InvoiceFormProvider } from './InvoiceFormProvider';
|
||||
import { css } from '@emotion/css';
|
||||
import { InvoiceForm } from './InvoiceForm';
|
||||
import {
|
||||
InvoiceFormProvider,
|
||||
useInvoiceFormContext,
|
||||
} from './InvoiceFormProvider';
|
||||
import { AutoExchangeRateProvider } from '@/containers/Entries/AutoExchangeProvider';
|
||||
import { DashboardInsider } from '@/components';
|
||||
|
||||
/**
|
||||
* Invoice form page.
|
||||
*/
|
||||
export default function InvoiceFormPage() {
|
||||
const { id } = useParams();
|
||||
const idAsInteger = parseInt(id, 10);
|
||||
const invoiceId = parseInt(id, 10);
|
||||
|
||||
return (
|
||||
<InvoiceFormProvider invoiceId={idAsInteger}>
|
||||
<InvoiceFormProvider invoiceId={invoiceId}>
|
||||
<AutoExchangeRateProvider>
|
||||
<InvoiceForm />
|
||||
<InvoiceFormPageContent />
|
||||
</AutoExchangeRateProvider>
|
||||
</InvoiceFormProvider>
|
||||
);
|
||||
}
|
||||
|
||||
function InvoiceFormPageContent() {
|
||||
const { isBootLoading } = useInvoiceFormContext();
|
||||
|
||||
return (
|
||||
<DashboardInsider
|
||||
loading={isBootLoading}
|
||||
className={css`
|
||||
min-height: calc(100vh - var(--top-offset));
|
||||
max-height: calc(100vh - var(--top-offset));
|
||||
`}
|
||||
>
|
||||
<InvoiceForm />
|
||||
</DashboardInsider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -132,6 +132,14 @@ function InvoiceFormProvider({ invoiceId, baseCurrency, ...props }) {
|
||||
isProjectsLoading ||
|
||||
isBrandingTemplatesLoading;
|
||||
|
||||
const isBootLoading =
|
||||
isInvoiceLoading ||
|
||||
isItemsLoading ||
|
||||
isCustomersLoading ||
|
||||
isEstimateLoading ||
|
||||
isSettingsLoading ||
|
||||
isInvoiceStateLoading;
|
||||
|
||||
const provider = {
|
||||
invoice,
|
||||
items,
|
||||
@@ -170,21 +178,11 @@ function InvoiceFormProvider({ invoiceId, baseCurrency, ...props }) {
|
||||
// Invoice state
|
||||
saleInvoiceState,
|
||||
isInvoiceStateLoading,
|
||||
|
||||
isBootLoading,
|
||||
};
|
||||
|
||||
const isLoading =
|
||||
isInvoiceLoading ||
|
||||
isItemsLoading ||
|
||||
isCustomersLoading ||
|
||||
isEstimateLoading ||
|
||||
isSettingsLoading ||
|
||||
isInvoiceStateLoading;
|
||||
|
||||
return (
|
||||
<DashboardInsider loading={isLoading} name={'invoice-form'}>
|
||||
<InvoiceFormContext.Provider value={provider} {...props} />
|
||||
</DashboardInsider>
|
||||
);
|
||||
return <InvoiceFormContext.Provider value={provider} {...props} />;
|
||||
}
|
||||
|
||||
const useInvoiceFormContext = () =>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import { FastField } from 'formik';
|
||||
import { x } from '@xstyled/emotion';
|
||||
import ItemsEntriesTable from '@/containers/Entries/ItemsEntriesTable';
|
||||
import { useInvoiceFormContext } from './InvoiceFormProvider';
|
||||
import { entriesFieldShouldUpdate } from './utils';
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import {
|
||||
Intent,
|
||||
Button,
|
||||
@@ -15,12 +14,12 @@ import { useHistory } from 'react-router-dom';
|
||||
import { FSelect, Group, Icon, FormattedMessage as T } from '@/components';
|
||||
import { useFormikContext } from 'formik';
|
||||
import { usePaymentReceiveFormContext } from './PaymentReceiveFormProvider';
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import {
|
||||
BrandingThemeFormGroup,
|
||||
BrandingThemeSelectButton,
|
||||
} from '@/containers/BrandingTemplates/BrandingTemplatesSelectFields';
|
||||
import { usePaymentReceivedFormBrandingTemplatesOptions } from './utils';
|
||||
import { PageForm } from '@/components/PageForm';
|
||||
|
||||
/**
|
||||
* Payment receive floating actions bar.
|
||||
@@ -62,80 +61,80 @@ export default function PaymentReceiveFormFloatingActions() {
|
||||
usePaymentReceivedFormBrandingTemplatesOptions();
|
||||
|
||||
return (
|
||||
<Group
|
||||
spacing={10}
|
||||
className={classNames(CLASSES.PAGE_FORM_FLOATING_ACTIONS)}
|
||||
>
|
||||
{/* ----------- Save and New ----------- */}
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
loading={isSubmitting}
|
||||
intent={Intent.PRIMARY}
|
||||
type="submit"
|
||||
onClick={handleSubmitBtnClick}
|
||||
style={{ minWidth: '85px' }}
|
||||
text={!isNewMode ? <T id={'edit'} /> : <T id={'save'} />}
|
||||
/>
|
||||
<Popover
|
||||
content={
|
||||
<Menu>
|
||||
<MenuItem
|
||||
text={<T id={'save_and_new'} />}
|
||||
onClick={handleSubmitAndNewClick}
|
||||
/>
|
||||
<MenuItem
|
||||
text={<T id={'save_continue_editing'} />}
|
||||
onClick={handleSubmitContinueEditingBtnClick}
|
||||
/>
|
||||
</Menu>
|
||||
}
|
||||
minimal={true}
|
||||
interactionKind={PopoverInteractionKind.CLICK}
|
||||
position={Position.BOTTOM_LEFT}
|
||||
>
|
||||
<PageForm.FooterActions position={'apart'} spacing={20}>
|
||||
<Group spacing={10}>
|
||||
{/* ----------- Save and New ----------- */}
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
loading={isSubmitting}
|
||||
intent={Intent.PRIMARY}
|
||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||
type="submit"
|
||||
onClick={handleSubmitBtnClick}
|
||||
style={{ minWidth: '85px' }}
|
||||
text={!isNewMode ? <T id={'edit'} /> : <T id={'save'} />}
|
||||
/>
|
||||
</Popover>
|
||||
</ButtonGroup>
|
||||
<Popover
|
||||
content={
|
||||
<Menu>
|
||||
<MenuItem
|
||||
text={<T id={'save_and_new'} />}
|
||||
onClick={handleSubmitAndNewClick}
|
||||
/>
|
||||
<MenuItem
|
||||
text={<T id={'save_continue_editing'} />}
|
||||
onClick={handleSubmitContinueEditingBtnClick}
|
||||
/>
|
||||
</Menu>
|
||||
}
|
||||
minimal={true}
|
||||
interactionKind={PopoverInteractionKind.CLICK}
|
||||
position={Position.BOTTOM_LEFT}
|
||||
>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
intent={Intent.PRIMARY}
|
||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||
/>
|
||||
</Popover>
|
||||
</ButtonGroup>
|
||||
|
||||
{/* ----------- Clear & Reset----------- */}
|
||||
<Button
|
||||
className={'ml1'}
|
||||
disabled={isSubmitting}
|
||||
onClick={handleClearBtnClick}
|
||||
text={!isNewMode ? <T id={'reset'} /> : <T id={'clear'} />}
|
||||
/>
|
||||
|
||||
{/* ----------- Cancel ----------- */}
|
||||
<Button
|
||||
className={'ml1'}
|
||||
disabled={isSubmitting}
|
||||
onClick={handleCancelBtnClick}
|
||||
text={<T id={'cancel'} />}
|
||||
/>
|
||||
|
||||
{/* ----------- Branding Template Select ----------- */}
|
||||
<BrandingThemeFormGroup
|
||||
name={'pdf_template_id'}
|
||||
label={'Branding'}
|
||||
inline
|
||||
fastField
|
||||
style={{ marginLeft: 20 }}
|
||||
>
|
||||
<FSelect
|
||||
name={'pdf_template_id'}
|
||||
items={brandingTemplatesOpts}
|
||||
input={({ activeItem, text, label, value }) => (
|
||||
<BrandingThemeSelectButton text={text || 'Brand Theme'} minimal />
|
||||
)}
|
||||
filterable={false}
|
||||
popoverProps={{ minimal: true }}
|
||||
{/* ----------- Clear & Reset----------- */}
|
||||
<Button
|
||||
className={'ml1'}
|
||||
disabled={isSubmitting}
|
||||
onClick={handleClearBtnClick}
|
||||
text={!isNewMode ? <T id={'reset'} /> : <T id={'clear'} />}
|
||||
/>
|
||||
</BrandingThemeFormGroup>
|
||||
</Group>
|
||||
{/* ----------- Cancel ----------- */}
|
||||
<Button
|
||||
className={'ml1'}
|
||||
disabled={isSubmitting}
|
||||
onClick={handleCancelBtnClick}
|
||||
text={<T id={'cancel'} />}
|
||||
/>
|
||||
</Group>
|
||||
|
||||
<Group>
|
||||
{/* ----------- Branding Template Select ----------- */}
|
||||
<BrandingThemeFormGroup
|
||||
name={'pdf_template_id'}
|
||||
label={'Branding'}
|
||||
inline
|
||||
fastField
|
||||
style={{ marginLeft: 20 }}
|
||||
>
|
||||
<FSelect
|
||||
name={'pdf_template_id'}
|
||||
items={brandingTemplatesOpts}
|
||||
input={({ activeItem, text, label, value }) => (
|
||||
<BrandingThemeSelectButton text={text || 'Brand Theme'} minimal />
|
||||
)}
|
||||
filterable={false}
|
||||
popoverProps={{ minimal: true }}
|
||||
/>
|
||||
</BrandingThemeFormGroup>
|
||||
</Group>
|
||||
</PageForm.FooterActions>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
// @ts-nocheck
|
||||
import React, { useMemo } from 'react';
|
||||
import React from 'react';
|
||||
import { isEmpty, defaultTo } from 'lodash';
|
||||
import intl from 'react-intl-universal';
|
||||
import classNames from 'classnames';
|
||||
import { Formik, Form } from 'formik';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { Intent } from '@blueprintjs/core';
|
||||
import { css } from '@emotion/css';
|
||||
|
||||
import '@/style/pages/PaymentReceive/PageForm.scss';
|
||||
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import PaymentReceiveHeader from './PaymentReceiveFormHeader';
|
||||
import PaymentReceiveFormBody from './PaymentReceiveFormBody';
|
||||
import PaymentReceiveFloatingActions from './PaymentReceiveFloatingActions';
|
||||
@@ -40,11 +37,12 @@ import {
|
||||
getExceededAmountFromValues,
|
||||
} from './utils';
|
||||
import { PaymentReceiveSyncIncrementSettingsToForm } from './components';
|
||||
import { PageForm } from '@/components/PageForm';
|
||||
|
||||
/**
|
||||
* Payment Receive form.
|
||||
*/
|
||||
function PaymentReceiveForm({
|
||||
function PaymentReceiveFormRoot({
|
||||
// #withSettings
|
||||
preferredDepositAccount,
|
||||
paymentReceiveNextNumber,
|
||||
@@ -159,30 +157,37 @@ function PaymentReceiveForm({
|
||||
return createPaymentReceiveMutate(form).then(onSaved).catch(onError);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
CLASSES.PAGE_FORM,
|
||||
CLASSES.PAGE_FORM_STRIP_STYLE,
|
||||
CLASSES.PAGE_FORM_PAYMENT_RECEIVE,
|
||||
)}
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
onSubmit={handleSubmitForm}
|
||||
validationSchema={
|
||||
isNewMode
|
||||
? CreatePaymentReceiveFormSchema
|
||||
: EditPaymentReceiveFormSchema
|
||||
}
|
||||
>
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
onSubmit={handleSubmitForm}
|
||||
validationSchema={
|
||||
isNewMode
|
||||
? CreatePaymentReceiveFormSchema
|
||||
: EditPaymentReceiveFormSchema
|
||||
}
|
||||
<Form
|
||||
className={css({
|
||||
overflow: 'hidden',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
flex: 1,
|
||||
})}
|
||||
>
|
||||
<Form>
|
||||
<PageForm flex={1}>
|
||||
<PaymentReceiveInnerProvider>
|
||||
<PaymentReceiveFormTopBar />
|
||||
<PaymentReceiveHeader />
|
||||
<PaymentReceiveFormBody />
|
||||
<PaymentReceiveFormFooter />
|
||||
<PaymentReceiveFloatingActions />
|
||||
<PageForm.Body>
|
||||
<PaymentReceiveFormTopBar />
|
||||
<PaymentReceiveHeader />
|
||||
<PaymentReceiveFormBody />
|
||||
<PaymentReceiveFormFooter />
|
||||
</PageForm.Body>
|
||||
|
||||
<PageForm.Footer>
|
||||
<PaymentReceiveFloatingActions />
|
||||
</PageForm.Footer>
|
||||
|
||||
{/* ------- Effects ------- */}
|
||||
<PaymentReceiveSyncIncrementSettingsToForm />
|
||||
@@ -191,13 +196,13 @@ function PaymentReceiveForm({
|
||||
<PaymentReceiveFormAlerts />
|
||||
<PaymentReceiveFormDialogs />
|
||||
</PaymentReceiveInnerProvider>
|
||||
</Form>
|
||||
</Formik>
|
||||
</div>
|
||||
</PageForm>
|
||||
</Form>
|
||||
</Formik>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(
|
||||
export const PaymentReceivedForm = compose(
|
||||
withSettings(({ paymentReceiveSettings }) => ({
|
||||
paymentReceiveSettings,
|
||||
paymentReceiveNextNumber: paymentReceiveSettings?.nextNumber,
|
||||
@@ -207,4 +212,4 @@ export default compose(
|
||||
})),
|
||||
withCurrentOrganization(),
|
||||
withDialogActions,
|
||||
)(PaymentReceiveForm);
|
||||
)(PaymentReceiveFormRoot);
|
||||
|
||||
@@ -2,15 +2,14 @@
|
||||
import React from 'react';
|
||||
import { FastField } from 'formik';
|
||||
import PaymentReceiveItemsTable from './PaymentReceiveItemsTable';
|
||||
import classNames from 'classnames';
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import { Box } from '@/components';
|
||||
|
||||
/**
|
||||
* Payment Receive form body.
|
||||
*/
|
||||
export default function PaymentReceiveFormBody() {
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_BODY)}>
|
||||
<Box p="18px 32px 0">
|
||||
<FastField name={'entries'}>
|
||||
{({ form: { values, setFieldValue }, field: { value } }) => (
|
||||
<PaymentReceiveItemsTable
|
||||
@@ -22,6 +21,6 @@ export default function PaymentReceiveFormBody() {
|
||||
/>
|
||||
)}
|
||||
</FastField>
|
||||
</div>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,21 +1,19 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import styled from 'styled-components';
|
||||
import { x } from '@xstyled/emotion';
|
||||
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import { Row, Col, Paper } from '@/components';
|
||||
import { Row, Col, Paper, Box } from '@/components';
|
||||
import { PaymentReceiveFormFootetLeft } from './PaymentReceiveFormFootetLeft';
|
||||
import { PaymentReceiveFormFootetRight } from './PaymentReceiveFormFootetRight';
|
||||
import { UploadAttachmentButton } from '@/containers/Attachments/UploadAttachmentButton';
|
||||
|
||||
/**
|
||||
* Payment receive form footer.
|
||||
* Payment received form footer.
|
||||
*/
|
||||
export default function PaymentReceiveFormFooter() {
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_FOOTER)}>
|
||||
<PaymentReceiveFooterPaper>
|
||||
<Box mt={'20px'} px={'32px'} pb={'20px'} flex={1}>
|
||||
<Paper p={'20px'}>
|
||||
<Row>
|
||||
<Col md={8}>
|
||||
<PaymentReceiveFormFootetLeft />
|
||||
@@ -26,11 +24,7 @@ export default function PaymentReceiveFormFooter() {
|
||||
<PaymentReceiveFormFootetRight />
|
||||
</Col>
|
||||
</Row>
|
||||
</PaymentReceiveFooterPaper>
|
||||
</div>
|
||||
</Paper>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
const PaymentReceiveFooterPaper = styled(Paper)`
|
||||
padding: 20px;
|
||||
`;
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
// @ts-nocheck
|
||||
import React, { useMemo } from 'react';
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { sumBy } from 'lodash';
|
||||
import { useFormikContext } from 'formik';
|
||||
import { Money } from '@/components';
|
||||
import { Group, Money } from '@/components';
|
||||
import { FormattedMessage as T } from '@/components';
|
||||
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
@@ -14,12 +13,16 @@ import PaymentReceiveHeaderFields from './PaymentReceiveHeaderFields';
|
||||
*/
|
||||
function PaymentReceiveFormHeader() {
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_HEADER)}>
|
||||
<div className={classNames(CLASSES.PAGE_FORM_HEADER_PRIMARY)}>
|
||||
<PaymentReceiveHeaderFields />
|
||||
<PaymentReceiveFormBigTotal />
|
||||
</div>
|
||||
</div>
|
||||
<Group
|
||||
position="apart"
|
||||
align={'flex-start'}
|
||||
bg="white"
|
||||
p="25px 32px"
|
||||
borderBottom="1px solid #d2dce2"
|
||||
>
|
||||
<PaymentReceiveHeaderFields />
|
||||
<PaymentReceiveFormBigTotal />
|
||||
</Group>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,20 +1,40 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
import { PaymentReceiveFormProvider } from './PaymentReceiveFormProvider';
|
||||
import PaymentReceiveForm from './PaymentReceiveForm';
|
||||
import { css } from '@emotion/css';
|
||||
import {
|
||||
PaymentReceiveFormProvider,
|
||||
usePaymentReceiveFormContext,
|
||||
} from './PaymentReceiveFormProvider';
|
||||
import { PaymentReceivedForm } from './PaymentReceiveForm';
|
||||
import { DashboardInsider } from '@/components';
|
||||
|
||||
/**
|
||||
* Payment receive form page.
|
||||
* Payment received form page.
|
||||
*/
|
||||
export default function PaymentReceiveFormPage() {
|
||||
const { id: paymentReceiveId } = useParams();
|
||||
const paymentReceiveIdInt = parseInt(paymentReceiveId, 10);
|
||||
const { id } = useParams();
|
||||
const paymentReceivedId = parseInt(id, 10);
|
||||
|
||||
return (
|
||||
<PaymentReceiveFormProvider paymentReceiveId={paymentReceiveIdInt}>
|
||||
<PaymentReceiveForm paymentReceiveId={paymentReceiveIdInt} />
|
||||
<PaymentReceiveFormProvider paymentReceiveId={paymentReceivedId}>
|
||||
<PaymentReceivedFormPageContent />
|
||||
</PaymentReceiveFormProvider>
|
||||
);
|
||||
}
|
||||
|
||||
function PaymentReceivedFormPageContent() {
|
||||
const { isBootLoading } = usePaymentReceiveFormContext();
|
||||
|
||||
return (
|
||||
<DashboardInsider
|
||||
loading={isBootLoading}
|
||||
className={css`
|
||||
min-height: calc(100vh - var(--top-offset));
|
||||
max-height: calc(100vh - var(--top-offset));
|
||||
`}
|
||||
>
|
||||
<PaymentReceivedForm />
|
||||
</DashboardInsider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -97,6 +97,13 @@ function PaymentReceiveFormProvider({ query, paymentReceiveId, ...props }) {
|
||||
|
||||
const [isExcessConfirmed, setIsExcessConfirmed] = useState<boolean>(false);
|
||||
|
||||
const isBootLoading =
|
||||
isPaymentLoading ||
|
||||
isAccountsLoading ||
|
||||
isCustomersLoading ||
|
||||
isBrandingTemplatesLoading ||
|
||||
isPaymentReceivedStateLoading;
|
||||
|
||||
// Provider payload.
|
||||
const provider = {
|
||||
paymentReceiveId,
|
||||
@@ -131,20 +138,11 @@ function PaymentReceiveFormProvider({ query, paymentReceiveId, ...props }) {
|
||||
// Payment received state
|
||||
isPaymentReceivedStateLoading,
|
||||
paymentReceivedState,
|
||||
|
||||
isBootLoading,
|
||||
};
|
||||
|
||||
const isLoading =
|
||||
isPaymentLoading ||
|
||||
isAccountsLoading ||
|
||||
isCustomersLoading ||
|
||||
isBrandingTemplatesLoading ||
|
||||
isPaymentReceivedStateLoading;
|
||||
|
||||
return (
|
||||
<DashboardInsider loading={isLoading} name={'payment-receive-form'}>
|
||||
<PaymentReceiveFormContext.Provider value={provider} {...props} />
|
||||
</DashboardInsider>
|
||||
);
|
||||
return <PaymentReceiveFormContext.Provider value={provider} {...props} />;
|
||||
}
|
||||
|
||||
const usePaymentReceiveFormContext = () =>
|
||||
|
||||
@@ -13,12 +13,15 @@ import {
|
||||
import { DateInput } from '@blueprintjs/datetime';
|
||||
import { isEmpty, toSafeInteger } from 'lodash';
|
||||
import { FastField, useFormikContext, ErrorMessage } from 'formik';
|
||||
import { css } from '@emotion/css';
|
||||
import { Theme, useTheme } from '@emotion/react';
|
||||
|
||||
import {
|
||||
FeatureCan,
|
||||
CustomersSelect,
|
||||
FormattedMessage as T,
|
||||
FMoneyInputGroup,
|
||||
Stack,
|
||||
} from '@/components';
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import {
|
||||
@@ -55,10 +58,30 @@ import {
|
||||
import { Features } from '@/constants';
|
||||
import { PaymentReceivePaymentNoField } from './PaymentReceivePaymentNoField';
|
||||
|
||||
|
||||
const getHeaderFieldsStyle = (theme: Theme) => css`
|
||||
.${theme.bpPrefix}-form-group {
|
||||
margin-bottom: 0;
|
||||
|
||||
&.${theme.bpPrefix}-inline {
|
||||
max-width: 470px;
|
||||
}
|
||||
.${theme.bpPrefix}-label {
|
||||
min-width: 160px;
|
||||
}
|
||||
.${theme.bpPrefix}-form-content {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* Payment receive header fields.
|
||||
*/
|
||||
export default function PaymentReceiveHeaderFields() {
|
||||
const theme = useTheme();
|
||||
const styleClassName = getHeaderFieldsStyle(theme);
|
||||
|
||||
// Payment receive form context.
|
||||
const { accounts, projects } = usePaymentReceiveFormContext();
|
||||
|
||||
@@ -88,7 +111,7 @@ export default function PaymentReceiveHeaderFields() {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_HEADER_FIELDS)}>
|
||||
<Stack spacing={18} flex={1} className={styleClassName}>
|
||||
{/* ------------- Customer name ------------- */}
|
||||
<PaymentReceiveCustomerSelect />
|
||||
|
||||
@@ -143,9 +166,25 @@ export default function PaymentReceiveHeaderFields() {
|
||||
{!isEmpty(entries) && (
|
||||
<Button
|
||||
onClick={handleReceiveFullAmountClick}
|
||||
className={'receive-full-amount'}
|
||||
small={true}
|
||||
minimal={true}
|
||||
className={css`
|
||||
&:not([class*='${theme.bpPrefix}-intent-']) {
|
||||
&.${theme.bpPrefix}-minimal {
|
||||
width: auto;
|
||||
padding: 0;
|
||||
min-height: auto;
|
||||
font-size: 12px;
|
||||
margin-top: 4px;
|
||||
background-color: transparent;
|
||||
color: #0052cc;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
`}
|
||||
small
|
||||
minimal
|
||||
>
|
||||
<T id={'receive_full_amount'} /> (
|
||||
<Money amount={totalDueAmount} currency={currency_code} />)
|
||||
@@ -186,10 +225,10 @@ export default function PaymentReceiveHeaderFields() {
|
||||
<FFormGroup
|
||||
name={'reference_no'}
|
||||
label={<T id={'reference'} />}
|
||||
inline={true}
|
||||
inline
|
||||
fastField
|
||||
>
|
||||
<InputGroup name={'reference_no'} minimal={true} fastField />
|
||||
<InputGroup name={'reference_no'} minimal fastField />
|
||||
</FFormGroup>
|
||||
|
||||
{/*------------ Project name -----------*/}
|
||||
@@ -208,7 +247,7 @@ export default function PaymentReceiveHeaderFields() {
|
||||
/>
|
||||
</FFormGroup>
|
||||
</FeatureCan>
|
||||
</div>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
// @ts-nocheck
|
||||
import intl from 'react-intl-universal';
|
||||
import classNames from 'classnames';
|
||||
import { Formik, Form } from 'formik';
|
||||
import { Intent } from '@blueprintjs/core';
|
||||
import { sumBy, isEmpty } from 'lodash';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { css } from '@emotion/css';
|
||||
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import {
|
||||
EditReceiptFormSchema,
|
||||
CreateReceiptFormSchema,
|
||||
@@ -17,7 +16,7 @@ import { useReceiptFormContext } from './ReceiptFormProvider';
|
||||
import ReceiptFromHeader from './ReceiptFormHeader';
|
||||
import ReceiptItemsEntriesEditor from './ReceiptItemsEntriesEditor';
|
||||
import ReceiptFormFloatingActions from './ReceiptFormFloatingActions';
|
||||
import ReceiptFormFooter from './ReceiptFormFooter';
|
||||
import { ReceiptFormFooter } from './ReceiptFormFooter';
|
||||
import ReceiptFormDialogs from './ReceiptFormDialogs';
|
||||
import ReceiptFormTopBar from './ReceiptFormTopbar';
|
||||
|
||||
@@ -38,11 +37,12 @@ import {
|
||||
ReceiptSyncAutoExRateToForm,
|
||||
ReceiptSyncIncrementSettingsToForm,
|
||||
} from './components';
|
||||
import { PageForm } from '@/components/PageForm';
|
||||
|
||||
/**
|
||||
* Receipt form.
|
||||
*/
|
||||
function ReceiptForm({
|
||||
function ReceiptFormRoot({
|
||||
// #withSettings
|
||||
receiptNextNumber,
|
||||
receiptNumberPrefix,
|
||||
@@ -150,40 +150,46 @@ function ReceiptForm({
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
CLASSES.PAGE_FORM,
|
||||
CLASSES.PAGE_FORM_STRIP_STYLE,
|
||||
CLASSES.PAGE_FORM_RECEIPT,
|
||||
)}
|
||||
<Formik
|
||||
validationSchema={
|
||||
isNewMode ? CreateReceiptFormSchema : EditReceiptFormSchema
|
||||
}
|
||||
initialValues={initialValues}
|
||||
onSubmit={handleFormSubmit}
|
||||
>
|
||||
<Formik
|
||||
validationSchema={
|
||||
isNewMode ? CreateReceiptFormSchema : EditReceiptFormSchema
|
||||
}
|
||||
initialValues={initialValues}
|
||||
onSubmit={handleFormSubmit}
|
||||
<Form
|
||||
className={css({
|
||||
overflow: 'hidden',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
flex: 1,
|
||||
})}
|
||||
>
|
||||
<Form>
|
||||
<ReceiptFormTopBar />
|
||||
<ReceiptFromHeader />
|
||||
<ReceiptItemsEntriesEditor />
|
||||
<ReceiptFormFooter />
|
||||
<ReceiptFormFloatingActions />
|
||||
<PageForm flex={1}>
|
||||
<PageForm.Body>
|
||||
<ReceiptFormTopBar />
|
||||
<ReceiptFromHeader />
|
||||
<ReceiptItemsEntriesEditor />
|
||||
<ReceiptFormFooter />
|
||||
</PageForm.Body>
|
||||
|
||||
{/*---------- Dialogs ---------*/}
|
||||
<ReceiptFormDialogs />
|
||||
css
|
||||
{/*---------- Effects ---------*/}
|
||||
<ReceiptSyncIncrementSettingsToForm />
|
||||
<ReceiptSyncAutoExRateToForm />
|
||||
</Form>
|
||||
</Formik>
|
||||
</div>
|
||||
<PageForm.Footer>
|
||||
<ReceiptFormFloatingActions />
|
||||
</PageForm.Footer>
|
||||
</PageForm>
|
||||
|
||||
{/*---------- Dialogs ---------*/}
|
||||
<ReceiptFormDialogs />
|
||||
|
||||
{/*---------- Effects ---------*/}
|
||||
<ReceiptSyncIncrementSettingsToForm />
|
||||
<ReceiptSyncAutoExRateToForm />
|
||||
</Form>
|
||||
</Formik>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(
|
||||
export const ReceiptForm = compose(
|
||||
withDashboardActions,
|
||||
withSettings(({ receiptSettings }) => ({
|
||||
receiptNextNumber: receiptSettings?.nextNumber,
|
||||
@@ -194,4 +200,4 @@ export default compose(
|
||||
preferredDepositAccount: receiptSettings?.preferredDepositAccount,
|
||||
})),
|
||||
withCurrentOrganization(),
|
||||
)(ReceiptForm);
|
||||
)(ReceiptFormRoot);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import {
|
||||
Intent,
|
||||
Button,
|
||||
@@ -14,7 +13,6 @@ import {
|
||||
import { FSelect, Group, FormattedMessage as T } from '@/components';
|
||||
import { useFormikContext } from 'formik';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import { If, Icon } from '@/components';
|
||||
import { useReceiptFormContext } from './ReceiptFormProvider';
|
||||
import { useReceiptFormBrandingTemplatesOptions } from './utils';
|
||||
@@ -22,6 +20,7 @@ import {
|
||||
BrandingThemeFormGroup,
|
||||
BrandingThemeSelectButton,
|
||||
} from '@/containers/BrandingTemplates/BrandingTemplatesSelectFields';
|
||||
import { PageForm } from '@/components/PageForm';
|
||||
|
||||
/**
|
||||
* Receipt floating actions bar.
|
||||
@@ -84,139 +83,142 @@ export default function ReceiptFormFloatingActions() {
|
||||
const brandingTemplatesOptions = useReceiptFormBrandingTemplatesOptions();
|
||||
|
||||
return (
|
||||
<Group
|
||||
spacing={10}
|
||||
className={classNames(CLASSES.PAGE_FORM_FLOATING_ACTIONS)}
|
||||
>
|
||||
{/* ----------- Save And Close ----------- */}
|
||||
<If condition={!receipt || !receipt?.is_closed}>
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
loading={isSubmitting}
|
||||
intent={Intent.PRIMARY}
|
||||
onClick={handleSubmitCloseBtnClick}
|
||||
text={<T id={'save_close'} />}
|
||||
/>
|
||||
<Popover
|
||||
content={
|
||||
<Menu>
|
||||
<MenuItem
|
||||
text={<T id={'close_and_new'} />}
|
||||
onClick={handleSubmitCloseAndNewBtnClick}
|
||||
/>
|
||||
<MenuItem
|
||||
text={<T id={'close_continue_editing'} />}
|
||||
onClick={handleSubmitCloseContinueEditingBtnClick}
|
||||
/>
|
||||
</Menu>
|
||||
}
|
||||
minimal={true}
|
||||
interactionKind={PopoverInteractionKind.CLICK}
|
||||
position={Position.BOTTOM_LEFT}
|
||||
>
|
||||
<PageForm.FooterActions spacing={10} position="apart">
|
||||
<Group spacing={10}>
|
||||
{/* ----------- Save And Close ----------- */}
|
||||
<If condition={!receipt || !receipt?.is_closed}>
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
loading={isSubmitting}
|
||||
intent={Intent.PRIMARY}
|
||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||
onClick={handleSubmitCloseBtnClick}
|
||||
text={<T id={'save_close'} />}
|
||||
/>
|
||||
</Popover>
|
||||
</ButtonGroup>
|
||||
{/* ----------- Save As Draft ----------- */}
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
className={'ml1'}
|
||||
onClick={handleSubmitDraftBtnClick}
|
||||
text={<T id={'save_as_draft'} />}
|
||||
/>
|
||||
<Popover
|
||||
content={
|
||||
<Menu>
|
||||
<MenuItem
|
||||
text={<T id={'save_and_new'} />}
|
||||
onClick={handleSubmitDraftAndNewBtnClick}
|
||||
/>
|
||||
<MenuItem
|
||||
text={<T id={'save_continue_editing'} />}
|
||||
onClick={handleSubmitDraftContinueEditingBtnClick}
|
||||
/>
|
||||
</Menu>
|
||||
}
|
||||
minimal={true}
|
||||
interactionKind={PopoverInteractionKind.CLICK}
|
||||
position={Position.BOTTOM_LEFT}
|
||||
>
|
||||
<Popover
|
||||
content={
|
||||
<Menu>
|
||||
<MenuItem
|
||||
text={<T id={'close_and_new'} />}
|
||||
onClick={handleSubmitCloseAndNewBtnClick}
|
||||
/>
|
||||
<MenuItem
|
||||
text={<T id={'close_continue_editing'} />}
|
||||
onClick={handleSubmitCloseContinueEditingBtnClick}
|
||||
/>
|
||||
</Menu>
|
||||
}
|
||||
minimal={true}
|
||||
interactionKind={PopoverInteractionKind.CLICK}
|
||||
position={Position.BOTTOM_LEFT}
|
||||
>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
intent={Intent.PRIMARY}
|
||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||
/>
|
||||
</Popover>
|
||||
</ButtonGroup>
|
||||
{/* ----------- Save As Draft ----------- */}
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||
className={'ml1'}
|
||||
onClick={handleSubmitDraftBtnClick}
|
||||
text={<T id={'save_as_draft'} />}
|
||||
/>
|
||||
</Popover>
|
||||
</ButtonGroup>
|
||||
</If>
|
||||
{/* ----------- Save and New ----------- */}
|
||||
<If condition={receipt && receipt?.is_closed}>
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
intent={Intent.PRIMARY}
|
||||
onClick={handleSubmitCloseBtnClick}
|
||||
style={{ minWidth: '85px' }}
|
||||
text={<T id={'save'} />}
|
||||
/>
|
||||
<Popover
|
||||
content={
|
||||
<Menu>
|
||||
<MenuItem
|
||||
text={<T id={'save_and_new'} />}
|
||||
onClick={handleSubmitCloseAndNewBtnClick}
|
||||
/>
|
||||
</Menu>
|
||||
}
|
||||
minimal={true}
|
||||
interactionKind={PopoverInteractionKind.CLICK}
|
||||
position={Position.BOTTOM_LEFT}
|
||||
>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
intent={Intent.PRIMARY}
|
||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||
/>
|
||||
</Popover>
|
||||
</ButtonGroup>
|
||||
</If>
|
||||
{/* ----------- Clear & Reset----------- */}
|
||||
<Button
|
||||
className={'ml1'}
|
||||
disabled={isSubmitting}
|
||||
onClick={handleClearBtnClick}
|
||||
text={receipt ? <T id={'reset'} /> : <T id={'clear'} />}
|
||||
/>
|
||||
{/* ----------- Cancel ----------- */}
|
||||
<Button
|
||||
className={'ml1'}
|
||||
onClick={handleCancelBtnClick}
|
||||
text={<T id={'cancel'} />}
|
||||
/>
|
||||
<Popover
|
||||
content={
|
||||
<Menu>
|
||||
<MenuItem
|
||||
text={<T id={'save_and_new'} />}
|
||||
onClick={handleSubmitDraftAndNewBtnClick}
|
||||
/>
|
||||
<MenuItem
|
||||
text={<T id={'save_continue_editing'} />}
|
||||
onClick={handleSubmitDraftContinueEditingBtnClick}
|
||||
/>
|
||||
</Menu>
|
||||
}
|
||||
minimal={true}
|
||||
interactionKind={PopoverInteractionKind.CLICK}
|
||||
position={Position.BOTTOM_LEFT}
|
||||
>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||
/>
|
||||
</Popover>
|
||||
</ButtonGroup>
|
||||
</If>
|
||||
|
||||
{/* ----------- Branding Template Select ----------- */}
|
||||
<BrandingThemeFormGroup
|
||||
name={'pdf_template_id'}
|
||||
label={'Branding'}
|
||||
inline
|
||||
fastField
|
||||
style={{ marginLeft: 20 }}
|
||||
>
|
||||
<FSelect
|
||||
name={'pdf_template_id'}
|
||||
items={brandingTemplatesOptions}
|
||||
input={({ activeItem, text, label, value }) => (
|
||||
<BrandingThemeSelectButton text={text || 'Brand Theme'} minimal />
|
||||
)}
|
||||
filterable={false}
|
||||
popoverProps={{ minimal: true }}
|
||||
{/* ----------- Save and New ----------- */}
|
||||
<If condition={receipt && receipt?.is_closed}>
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
intent={Intent.PRIMARY}
|
||||
onClick={handleSubmitCloseBtnClick}
|
||||
style={{ minWidth: '85px' }}
|
||||
text={<T id={'save'} />}
|
||||
/>
|
||||
<Popover
|
||||
content={
|
||||
<Menu>
|
||||
<MenuItem
|
||||
text={<T id={'save_and_new'} />}
|
||||
onClick={handleSubmitCloseAndNewBtnClick}
|
||||
/>
|
||||
</Menu>
|
||||
}
|
||||
minimal={true}
|
||||
interactionKind={PopoverInteractionKind.CLICK}
|
||||
position={Position.BOTTOM_LEFT}
|
||||
>
|
||||
<Button
|
||||
disabled={isSubmitting}
|
||||
intent={Intent.PRIMARY}
|
||||
rightIcon={<Icon icon="arrow-drop-up-16" iconSize={20} />}
|
||||
/>
|
||||
</Popover>
|
||||
</ButtonGroup>
|
||||
</If>
|
||||
|
||||
{/* ----------- Clear & Reset----------- */}
|
||||
<Button
|
||||
className={'ml1'}
|
||||
disabled={isSubmitting}
|
||||
onClick={handleClearBtnClick}
|
||||
text={receipt ? <T id={'reset'} /> : <T id={'clear'} />}
|
||||
/>
|
||||
</BrandingThemeFormGroup>
|
||||
</Group>
|
||||
{/* ----------- Cancel ----------- */}
|
||||
<Button
|
||||
className={'ml1'}
|
||||
onClick={handleCancelBtnClick}
|
||||
text={<T id={'cancel'} />}
|
||||
/>
|
||||
</Group>
|
||||
|
||||
<Group spacing={20}>
|
||||
{/* ----------- Branding Template Select ----------- */}
|
||||
<BrandingThemeFormGroup
|
||||
name={'pdf_template_id'}
|
||||
label={'Branding'}
|
||||
inline
|
||||
fastField
|
||||
style={{ marginLeft: 20 }}
|
||||
>
|
||||
<FSelect
|
||||
name={'pdf_template_id'}
|
||||
items={brandingTemplatesOptions}
|
||||
input={({ activeItem, text, label, value }) => (
|
||||
<BrandingThemeSelectButton text={text || 'Brand Theme'} minimal />
|
||||
)}
|
||||
filterable={false}
|
||||
popoverProps={{ minimal: true }}
|
||||
/>
|
||||
</BrandingThemeFormGroup>
|
||||
</Group>
|
||||
</PageForm.FooterActions>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import { x } from '@xstyled/emotion';
|
||||
import { Paper, Row, Col } from '@/components';
|
||||
import { ReceiptFormFooterLeft } from './ReceiptFormFooterLeft';
|
||||
import { ReceiptFormFooterRight } from './ReceiptFormFooterRight';
|
||||
import { UploadAttachmentButton } from '@/containers/Attachments/UploadAttachmentButton';
|
||||
|
||||
export default function ReceiptFormFooter({}) {
|
||||
export function ReceiptFormFooter({}) {
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_FOOTER)}>
|
||||
<ReceiptFooterPaper>
|
||||
<x.div mt={'20px'} px={'32px'} pb={'20px'} flex={1}>
|
||||
<Paper p={'20px'}>
|
||||
<Row>
|
||||
<Col md={8}>
|
||||
<ReceiptFormFooterLeft />
|
||||
@@ -23,11 +20,7 @@ export default function ReceiptFormFooter({}) {
|
||||
<ReceiptFormFooterRight />
|
||||
</Col>
|
||||
</Row>
|
||||
</ReceiptFooterPaper>
|
||||
</div>
|
||||
</Paper>
|
||||
</x.div>
|
||||
);
|
||||
}
|
||||
|
||||
const ReceiptFooterPaper = styled(Paper)`
|
||||
padding: 20px;
|
||||
`;
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
// @ts-nocheck
|
||||
import React, { useMemo } from 'react';
|
||||
import intl from 'react-intl-universal';
|
||||
import classNames from 'classnames';
|
||||
import { useFormikContext } from 'formik';
|
||||
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import { PageFormBigNumber } from '@/components';
|
||||
import { Group, PageFormBigNumber } from '@/components';
|
||||
import ReceiptFormHeaderFields from './ReceiptFormHeaderFields';
|
||||
|
||||
import { getEntriesTotal } from '@/containers/Entries/utils';
|
||||
|
||||
/**
|
||||
@@ -18,12 +14,19 @@ function ReceiptFormHeader({
|
||||
onReceiptNumberChanged,
|
||||
}) {
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_HEADER)}>
|
||||
<Group
|
||||
position="apart"
|
||||
align={'flex-start'}
|
||||
display="flex"
|
||||
bg="white"
|
||||
p="25px 32px"
|
||||
borderBottom="1px solid #d2dce2"
|
||||
>
|
||||
<ReceiptFormHeaderFields
|
||||
onReceiptNumberChanged={onReceiptNumberChanged}
|
||||
/>
|
||||
<ReceiptFormHeaderBigTotal />
|
||||
</div>
|
||||
</Group>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
// @ts-nocheck
|
||||
import React, { useCallback } from 'react';
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import classNames from 'classnames';
|
||||
import { FormGroup, InputGroup, Position, Classes } from '@blueprintjs/core';
|
||||
import { DateInput } from '@blueprintjs/datetime';
|
||||
import { FastField, ErrorMessage, useFormikContext } from 'formik';
|
||||
import { FormGroup, Position, Classes } from '@blueprintjs/core';
|
||||
import { DateInput } from '@blueprintjs/datetime';
|
||||
import { css } from '@emotion/css';
|
||||
import { Theme, useTheme } from '@emotion/react';
|
||||
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import { ACCOUNT_TYPE } from '@/constants/accountTypes';
|
||||
@@ -18,6 +20,8 @@ import {
|
||||
CustomerDrawerLink,
|
||||
FormattedMessage as T,
|
||||
FeatureCan,
|
||||
FInputGroup,
|
||||
Stack,
|
||||
} from '@/components';
|
||||
import { ProjectsSelect } from '@/containers/Projects/components';
|
||||
import {
|
||||
@@ -35,14 +39,33 @@ import {
|
||||
import { ReceiptFormReceiptNumberField } from './ReceiptFormReceiptNumberField';
|
||||
import { useCustomerUpdateExRate } from '@/containers/Entries/withExRateItemEntriesPriceRecalc';
|
||||
|
||||
const getEstimateFieldsStyle = (theme: Theme) => css`
|
||||
.${theme.bpPrefix}-form-group {
|
||||
margin-bottom: 0;
|
||||
|
||||
&.${theme.bpPrefix}-inline {
|
||||
max-width: 450px;
|
||||
}
|
||||
.${theme.bpPrefix}-label {
|
||||
min-width: 150px;
|
||||
font-weight: 500;
|
||||
}
|
||||
.${theme.bpPrefix}-form-content {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* Receipt form header fields.
|
||||
*/
|
||||
export default function ReceiptFormHeader() {
|
||||
const theme = useTheme();
|
||||
const receiptFieldsClassName = getEstimateFieldsStyle(theme);
|
||||
const { accounts, projects } = useReceiptFormContext();
|
||||
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_HEADER_FIELDS)}>
|
||||
<Stack spacing={18} flex={1} className={receiptFieldsClassName}>
|
||||
{/* ----------- Customer name ----------- */}
|
||||
<ReceiptFormCustomerSelect />
|
||||
|
||||
@@ -104,19 +127,13 @@ export default function ReceiptFormHeader() {
|
||||
<ReceiptFormReceiptNumberField />
|
||||
|
||||
{/* ----------- Reference ----------- */}
|
||||
<FastField name={'reference_no'}>
|
||||
{({ field, meta: { error, touched } }) => (
|
||||
<FormGroup
|
||||
label={<T id={'reference'} />}
|
||||
inline={true}
|
||||
className={classNames('form-group--reference', CLASSES.FILL)}
|
||||
intent={inputIntent({ error, touched })}
|
||||
helperText={<ErrorMessage name="reference_no" />}
|
||||
>
|
||||
<InputGroup minimal={true} {...field} />
|
||||
</FormGroup>
|
||||
)}
|
||||
</FastField>
|
||||
<FFormGroup
|
||||
label={<T id={'reference'} />}
|
||||
inline={true}
|
||||
name={'reference_no'}
|
||||
>
|
||||
<FInputGroup minimal={true} name={'reference_no'} />
|
||||
</FFormGroup>
|
||||
|
||||
{/*------------ Project name -----------*/}
|
||||
<FeatureCan feature={Features.Projects}>
|
||||
@@ -134,7 +151,7 @@ export default function ReceiptFormHeader() {
|
||||
/>
|
||||
</FFormGroup>
|
||||
</FeatureCan>
|
||||
</div>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,25 +1,44 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { css } from '@emotion/css';
|
||||
|
||||
import '@/style/pages/SaleReceipt/PageForm.scss';
|
||||
|
||||
import ReceiptFrom from './ReceiptForm';
|
||||
import { ReceiptFormProvider } from './ReceiptFormProvider';
|
||||
import {
|
||||
ReceiptFormProvider,
|
||||
useReceiptFormContext,
|
||||
} from './ReceiptFormProvider';
|
||||
import { AutoExchangeRateProvider } from '@/containers/Entries/AutoExchangeProvider';
|
||||
import { DashboardInsider } from '@/components';
|
||||
import { ReceiptForm } from './ReceiptForm';
|
||||
|
||||
/**
|
||||
* Receipt form page.
|
||||
*/
|
||||
export default function ReceiptFormPage() {
|
||||
const { id } = useParams();
|
||||
const idInt = parseInt(id, 10);
|
||||
const receiptId = parseInt(id, 10);
|
||||
|
||||
return (
|
||||
<ReceiptFormProvider receiptId={idInt}>
|
||||
<ReceiptFormProvider receiptId={receiptId}>
|
||||
<AutoExchangeRateProvider>
|
||||
<ReceiptFrom />
|
||||
<ReceiptFormPageContent />
|
||||
</AutoExchangeRateProvider>
|
||||
</ReceiptFormProvider>
|
||||
);
|
||||
}
|
||||
|
||||
function ReceiptFormPageContent() {
|
||||
const { isBootLoading } = useReceiptFormContext();
|
||||
|
||||
return (
|
||||
<DashboardInsider
|
||||
loading={isBootLoading}
|
||||
className={css`
|
||||
min-height: calc(100vh - var(--top-offset));
|
||||
max-height: calc(100vh - var(--top-offset));
|
||||
`}
|
||||
>
|
||||
<ReceiptForm />
|
||||
</DashboardInsider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -120,6 +120,15 @@ function ReceiptFormProvider({ receiptId, ...props }) {
|
||||
const isNewMode = !receiptId;
|
||||
const isFeatureLoading = isWarehouesLoading || isBranchesLoading;
|
||||
|
||||
const isBootLoading =
|
||||
isReceiptLoading ||
|
||||
isAccountsLoading ||
|
||||
isCustomersLoading ||
|
||||
isItemsLoading ||
|
||||
isSettingLoading ||
|
||||
isBrandingTemplatesLoading ||
|
||||
isSaleReceiptStateLoading;
|
||||
|
||||
const provider = {
|
||||
receiptId,
|
||||
receipt,
|
||||
@@ -154,21 +163,10 @@ function ReceiptFormProvider({ receiptId, ...props }) {
|
||||
// State
|
||||
isSaleReceiptStateLoading,
|
||||
saleReceiptState,
|
||||
};
|
||||
const isLoading =
|
||||
isReceiptLoading ||
|
||||
isAccountsLoading ||
|
||||
isCustomersLoading ||
|
||||
isItemsLoading ||
|
||||
isSettingLoading ||
|
||||
isBrandingTemplatesLoading ||
|
||||
isSaleReceiptStateLoading;
|
||||
|
||||
return (
|
||||
<DashboardInsider loading={isLoading} name={'receipt-form'}>
|
||||
<ReceiptFormContext.Provider value={provider} {...props} />
|
||||
</DashboardInsider>
|
||||
);
|
||||
isBootLoading,
|
||||
};
|
||||
return <ReceiptFormContext.Provider value={provider} {...props} />;
|
||||
}
|
||||
|
||||
const useReceiptFormContext = () =>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { x } from '@xstyled/emotion';
|
||||
import { FastField } from 'formik';
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import ItemsEntriesTable from '@/containers/Entries/ItemsEntriesTable';
|
||||
import { useReceiptFormContext } from './ReceiptFormProvider';
|
||||
import { entriesFieldShouldUpdate } from './utils';
|
||||
@@ -11,8 +10,12 @@ export default function ReceiptItemsEntriesEditor({ defaultReceipt }) {
|
||||
const { items } = useReceiptFormContext();
|
||||
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_BODY)}>
|
||||
<FastField name={'entries'} items={items} shouldUpdate={entriesFieldShouldUpdate}>
|
||||
<x.div p="18px 32px 0">
|
||||
<FastField
|
||||
name={'entries'}
|
||||
items={items}
|
||||
shouldUpdate={entriesFieldShouldUpdate}
|
||||
>
|
||||
{({
|
||||
form: { values, setFieldValue },
|
||||
field: { value },
|
||||
@@ -31,6 +34,6 @@ export default function ReceiptItemsEntriesEditor({ defaultReceipt }) {
|
||||
/>
|
||||
)}
|
||||
</FastField>
|
||||
</div>
|
||||
</x.div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -10,17 +10,13 @@ import { WarehouseTransferFormFooterLeft } from './WarehouseTransferFormFooterLe
|
||||
export default function WarehouseTransferFormFooter() {
|
||||
return (
|
||||
<div className={classNames(CLASSES.PAGE_FORM_FOOTER)}>
|
||||
<WarehousesTransferFooterPaper>
|
||||
<Paper p={'20px'}>
|
||||
<Row>
|
||||
<Col md={8}>
|
||||
<WarehouseTransferFormFooterLeft />
|
||||
</Col>
|
||||
</Row>
|
||||
</WarehousesTransferFooterPaper>
|
||||
</Paper>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const WarehousesTransferFooterPaper = styled(Paper)`
|
||||
padding: 20px;
|
||||
`;
|
||||
|
||||
@@ -292,4 +292,8 @@ span.table-tooltip-overview-target {
|
||||
font-size: 14px;
|
||||
margin-bottom: 5px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
:root {
|
||||
--top-offset: 60px;
|
||||
}
|
||||
@@ -60,6 +60,7 @@
|
||||
margin: 20px 0 0 0;
|
||||
padding-left: 32px;
|
||||
padding-right: 32px;
|
||||
padding-bottom: 20px;
|
||||
|
||||
label.bp4-label{
|
||||
font-weight: 500;
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
body.page-credit-note-new,
|
||||
body.page-credit-note-edit {
|
||||
.dashboard__footer {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.dashboard__insider--credit-note-form {
|
||||
padding-bottom: 64px;
|
||||
}
|
||||
|
||||
.page-form--credit-note {
|
||||
$self: '.page-form';
|
||||
|
||||
#{$self}__header {
|
||||
display: flex;
|
||||
|
||||
&-fields {
|
||||
flex: 1 0 0;
|
||||
}
|
||||
|
||||
.bp4-label {
|
||||
min-width: 150px;
|
||||
}
|
||||
.bp4-form-content {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.bp4-form-group {
|
||||
&.bp4-inline {
|
||||
max-width: 450px;
|
||||
}
|
||||
}
|
||||
.col--credit-note-date {
|
||||
max-width: 435px;
|
||||
}
|
||||
}
|
||||
#{$self}__footer {
|
||||
.form-group--note,
|
||||
.form-group--terms_conditions {
|
||||
max-width: 450px;
|
||||
width: 100%;
|
||||
|
||||
textarea {
|
||||
width: 100%;
|
||||
min-height: 60px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
|
||||
body.page-estimate-new,
|
||||
body.page-estimate-edit{
|
||||
|
||||
.dashboard__footer{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.dashboard__insider--estimate-form{
|
||||
padding-bottom: 64px;
|
||||
}
|
||||
|
||||
.page-form--estimate {
|
||||
$self: '.page-form';
|
||||
|
||||
#{$self}__header {
|
||||
display: flex;
|
||||
|
||||
&-fields {
|
||||
flex: 1 0 0;
|
||||
}
|
||||
|
||||
.bp4-label {
|
||||
min-width: 140px;
|
||||
}
|
||||
.bp4-form-content {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.bp4-form-group {
|
||||
margin-bottom: 18px;
|
||||
|
||||
&.bp4-inline {
|
||||
max-width: 440px;
|
||||
}
|
||||
}
|
||||
.col--invoice-date {
|
||||
max-width: 435px;
|
||||
}
|
||||
}
|
||||
|
||||
#{$self}__footer {
|
||||
.form-group--customer_note,
|
||||
.form-group--terms_conditions {
|
||||
max-width: 450px;
|
||||
width: 100%;
|
||||
|
||||
textarea {
|
||||
width: 100%;
|
||||
min-height: 60px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
body.page-invoice-new,
|
||||
body.page-invoice-edit {
|
||||
.dashboard__footer {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.dashboard__insider--invoice-form {
|
||||
padding-bottom: 64px;
|
||||
}
|
||||
|
||||
.page-form--invoice {
|
||||
$self: '.page-form';
|
||||
|
||||
#{$self}__header {
|
||||
display: flex;
|
||||
|
||||
&-fields {
|
||||
flex: 1 0 0;
|
||||
}
|
||||
|
||||
.bp4-label {
|
||||
min-width: 150px;
|
||||
}
|
||||
|
||||
.bp4-form-content {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.bp4-form-group {
|
||||
&.bp4-inline {
|
||||
max-width: 450px;
|
||||
}
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
|
||||
.col {
|
||||
max-width: 470px;
|
||||
|
||||
&--due-date {
|
||||
.bp4-form-group {
|
||||
margin: 0px 15px 15px;
|
||||
|
||||
.bp4-label {
|
||||
min-width: 100px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.col--invoice-date {
|
||||
max-width: 435px;
|
||||
}
|
||||
}
|
||||
|
||||
#{$self}__footer {
|
||||
|
||||
.form-group--invoice_message,
|
||||
.form-group--terms_conditions {
|
||||
max-width: 450px;
|
||||
width: 100%;
|
||||
|
||||
textarea {
|
||||
width: 100%;
|
||||
min-height: 60px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.status-accessor {
|
||||
span {
|
||||
font-size: 13px;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.fully-paid-status {
|
||||
height: 19px;
|
||||
width: 19px;
|
||||
display: inline-block;
|
||||
background: #2ba01d;
|
||||
border-radius: 50%;
|
||||
margin-right: 6px;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.bp4-progress-bar {
|
||||
background: rgba(92, 112, 128, 0.2);
|
||||
border-radius: 40px;
|
||||
display: block;
|
||||
height: 5px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
margin-top: 5px;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
&.overdue-status {}
|
||||
|
||||
&.remaining-status {}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
|
||||
|
||||
body.page-receipt-new,
|
||||
body.page-receipt-edit{
|
||||
|
||||
.dashboard__footer{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.dashboard__insider--receipt-form{
|
||||
padding-bottom: 64px;
|
||||
}
|
||||
|
||||
.page-form--receipt{
|
||||
$self: '.page-form';
|
||||
|
||||
#{$self}__header{
|
||||
display: flex;
|
||||
|
||||
&-fields{
|
||||
flex: 1 0 0;
|
||||
}
|
||||
.bp4-label{
|
||||
min-width: 150px;
|
||||
}
|
||||
.bp4-form-content{
|
||||
width: 100%;
|
||||
}
|
||||
.bp4-form-group{
|
||||
margin-bottom: 18px;
|
||||
|
||||
&.bp4-inline{
|
||||
max-width: 450px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#{$self}__footer{
|
||||
.form-group--receipt_message,
|
||||
.form-group--statement{
|
||||
max-width: 450px;
|
||||
width: 100%;
|
||||
|
||||
textarea{
|
||||
width: 100%;
|
||||
min-height: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
381
pnpm-lock.yaml
generated
381
pnpm-lock.yaml
generated
@@ -520,6 +520,12 @@ importers:
|
||||
'@craco/craco':
|
||||
specifier: ^5.9.0
|
||||
version: 5.9.0(react-scripts@5.0.1)
|
||||
'@emotion/css':
|
||||
specifier: ^11.13.4
|
||||
version: 11.13.4
|
||||
'@emotion/react':
|
||||
specifier: ^11.13.3
|
||||
version: 11.13.3(@types/react@16.14.60)(react@18.3.1)
|
||||
'@reduxjs/toolkit':
|
||||
specifier: ^1.2.5
|
||||
version: 1.9.7(react-redux@7.2.9)(react@18.3.1)
|
||||
@@ -613,6 +619,9 @@ importers:
|
||||
'@welldone-software/why-did-you-render':
|
||||
specifier: ^6.0.0-rc.1
|
||||
version: 6.2.3(react@18.3.1)
|
||||
'@xstyled/emotion':
|
||||
specifier: ^3.8.1
|
||||
version: 3.8.1(@emotion/react@11.13.3)(@emotion/styled@11.13.0)
|
||||
accounting:
|
||||
specifier: ^0.4.1
|
||||
version: 0.4.1
|
||||
@@ -841,6 +850,9 @@ importers:
|
||||
stylis-rtlcss:
|
||||
specifier: ^2.1.1
|
||||
version: 2.1.1
|
||||
theme-ui:
|
||||
specifier: ^0.16.2
|
||||
version: 0.16.2(@emotion/react@11.13.3)(react@18.3.1)
|
||||
typescript:
|
||||
specifier: ^4.8.3
|
||||
version: 4.9.5
|
||||
@@ -3731,6 +3743,22 @@ packages:
|
||||
resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
|
||||
/@emotion/babel-plugin@11.12.0:
|
||||
resolution: {integrity: sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw==}
|
||||
dependencies:
|
||||
'@babel/helper-module-imports': 7.24.3
|
||||
'@babel/runtime': 7.24.5
|
||||
'@emotion/hash': 0.9.2
|
||||
'@emotion/memoize': 0.9.0
|
||||
'@emotion/serialize': 1.3.2
|
||||
babel-plugin-macros: 3.1.0
|
||||
convert-source-map: 1.9.0
|
||||
escape-string-regexp: 4.0.0
|
||||
find-root: 1.1.0
|
||||
source-map: 0.5.7
|
||||
stylis: 4.2.0
|
||||
dev: false
|
||||
|
||||
/@emotion/cache@10.0.29:
|
||||
resolution: {integrity: sha512-fU2VtSVlHiF27empSbxi1O2JFdNWZO+2NFHfwO0pxgTep6Xa3uGb+3pVKfLww2l/IBGLNEZl5Xf/++A4wAYDYQ==}
|
||||
dependencies:
|
||||
@@ -3740,6 +3768,16 @@ packages:
|
||||
'@emotion/weak-memoize': 0.2.5
|
||||
dev: false
|
||||
|
||||
/@emotion/cache@11.13.1:
|
||||
resolution: {integrity: sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw==}
|
||||
dependencies:
|
||||
'@emotion/memoize': 0.9.0
|
||||
'@emotion/sheet': 1.4.0
|
||||
'@emotion/utils': 1.4.1
|
||||
'@emotion/weak-memoize': 0.4.0
|
||||
stylis: 4.2.0
|
||||
dev: false
|
||||
|
||||
/@emotion/core@10.3.1(react@18.3.1):
|
||||
resolution: {integrity: sha512-447aUEjPIm0MnE6QYIaFz9VQOHSXf4Iu6EWOIqq11EAPqinkSZmfymPTmlOE3QjLv846lH4JVZBUOtwGbuQoww==}
|
||||
peerDependencies:
|
||||
@@ -3762,16 +3800,42 @@ packages:
|
||||
babel-plugin-emotion: 10.2.2
|
||||
dev: false
|
||||
|
||||
/@emotion/css@11.13.4:
|
||||
resolution: {integrity: sha512-CthbOD5EBw+iN0rfM96Tuv5kaZN4nxPyYDvGUs0bc7wZBBiU/0mse+l+0O9RshW2d+v5HH1cme+BAbLJ/3Folw==}
|
||||
dependencies:
|
||||
'@emotion/babel-plugin': 11.12.0
|
||||
'@emotion/cache': 11.13.1
|
||||
'@emotion/serialize': 1.3.2
|
||||
'@emotion/sheet': 1.4.0
|
||||
'@emotion/utils': 1.4.1
|
||||
dev: false
|
||||
|
||||
/@emotion/hash@0.8.0:
|
||||
resolution: {integrity: sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==}
|
||||
dev: false
|
||||
|
||||
/@emotion/hash@0.9.2:
|
||||
resolution: {integrity: sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==}
|
||||
dev: false
|
||||
|
||||
/@emotion/is-prop-valid@0.8.8:
|
||||
resolution: {integrity: sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==}
|
||||
dependencies:
|
||||
'@emotion/memoize': 0.7.4
|
||||
dev: false
|
||||
|
||||
/@emotion/is-prop-valid@1.2.2:
|
||||
resolution: {integrity: sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==}
|
||||
dependencies:
|
||||
'@emotion/memoize': 0.8.1
|
||||
dev: false
|
||||
|
||||
/@emotion/is-prop-valid@1.3.1:
|
||||
resolution: {integrity: sha512-/ACwoqx7XQi9knQs/G0qKvv5teDMhD7bXYns9N/wM8ah8iNb8jZ2uNO0YOgiq2o2poIvVtJS2YALasQuMSQ7Kw==}
|
||||
dependencies:
|
||||
'@emotion/memoize': 0.9.0
|
||||
dev: false
|
||||
|
||||
/@emotion/memoize@0.7.4:
|
||||
resolution: {integrity: sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==}
|
||||
dev: false
|
||||
@@ -3780,6 +3844,31 @@ packages:
|
||||
resolution: {integrity: sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==}
|
||||
dev: false
|
||||
|
||||
/@emotion/memoize@0.9.0:
|
||||
resolution: {integrity: sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==}
|
||||
dev: false
|
||||
|
||||
/@emotion/react@11.13.3(@types/react@16.14.60)(react@18.3.1):
|
||||
resolution: {integrity: sha512-lIsdU6JNrmYfJ5EbUCf4xW1ovy5wKQ2CkPRM4xogziOxH1nXxBSjpC9YqbFAP7circxMfYp+6x676BqWcEiixg==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: '>=16.8.0'
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.24.5
|
||||
'@emotion/babel-plugin': 11.12.0
|
||||
'@emotion/cache': 11.13.1
|
||||
'@emotion/serialize': 1.3.2
|
||||
'@emotion/use-insertion-effect-with-fallbacks': 1.1.0(react@18.3.1)
|
||||
'@emotion/utils': 1.4.1
|
||||
'@emotion/weak-memoize': 0.4.0
|
||||
'@types/react': 16.14.60
|
||||
hoist-non-react-statics: 3.3.2
|
||||
react: 18.3.1
|
||||
dev: false
|
||||
|
||||
/@emotion/serialize@0.11.16:
|
||||
resolution: {integrity: sha512-G3J4o8by0VRrO+PFeSc3js2myYNOXVJ3Ya+RGVxnshRYgsvErfAOglKAiy1Eo1vhzxqtUvjCyS5gtewzkmvSSg==}
|
||||
dependencies:
|
||||
@@ -3790,26 +3879,81 @@ packages:
|
||||
csstype: 2.6.21
|
||||
dev: false
|
||||
|
||||
/@emotion/serialize@1.3.2:
|
||||
resolution: {integrity: sha512-grVnMvVPK9yUVE6rkKfAJlYZgo0cu3l9iMC77V7DW6E1DUIrU68pSEXRmFZFOFB1QFo57TncmOcvcbMDWsL4yA==}
|
||||
dependencies:
|
||||
'@emotion/hash': 0.9.2
|
||||
'@emotion/memoize': 0.9.0
|
||||
'@emotion/unitless': 0.10.0
|
||||
'@emotion/utils': 1.4.1
|
||||
csstype: 3.1.3
|
||||
dev: false
|
||||
|
||||
/@emotion/sheet@0.9.4:
|
||||
resolution: {integrity: sha512-zM9PFmgVSqBw4zL101Q0HrBVTGmpAxFZH/pYx/cjJT5advXguvcgjHFTCaIO3enL/xr89vK2bh0Mfyj9aa0ANA==}
|
||||
dev: false
|
||||
|
||||
/@emotion/sheet@1.4.0:
|
||||
resolution: {integrity: sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==}
|
||||
dev: false
|
||||
|
||||
/@emotion/styled@11.13.0(@emotion/react@11.13.3)(@types/react@16.14.60)(react@18.3.1):
|
||||
resolution: {integrity: sha512-tkzkY7nQhW/zC4hztlwucpT8QEZ6eUzpXDRhww/Eej4tFfO0FxQYWRyg/c5CCXa4d/f174kqeXYjuQRnhzf6dA==}
|
||||
peerDependencies:
|
||||
'@emotion/react': ^11.0.0-rc.0
|
||||
'@types/react': '*'
|
||||
react: '>=16.8.0'
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.24.5
|
||||
'@emotion/babel-plugin': 11.12.0
|
||||
'@emotion/is-prop-valid': 1.3.1
|
||||
'@emotion/react': 11.13.3(@types/react@16.14.60)(react@18.3.1)
|
||||
'@emotion/serialize': 1.3.2
|
||||
'@emotion/use-insertion-effect-with-fallbacks': 1.1.0(react@18.3.1)
|
||||
'@emotion/utils': 1.4.1
|
||||
'@types/react': 16.14.60
|
||||
react: 18.3.1
|
||||
dev: false
|
||||
|
||||
/@emotion/stylis@0.8.5:
|
||||
resolution: {integrity: sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==}
|
||||
dev: false
|
||||
|
||||
/@emotion/unitless@0.10.0:
|
||||
resolution: {integrity: sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==}
|
||||
dev: false
|
||||
|
||||
/@emotion/unitless@0.7.5:
|
||||
resolution: {integrity: sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==}
|
||||
dev: false
|
||||
|
||||
/@emotion/use-insertion-effect-with-fallbacks@1.1.0(react@18.3.1):
|
||||
resolution: {integrity: sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw==}
|
||||
peerDependencies:
|
||||
react: '>=16.8.0'
|
||||
dependencies:
|
||||
react: 18.3.1
|
||||
dev: false
|
||||
|
||||
/@emotion/utils@0.11.3:
|
||||
resolution: {integrity: sha512-0o4l6pZC+hI88+bzuaX/6BgOvQVhbt2PfmxauVaYOGgbsAw14wdKyvMCZXnsnsHys94iadcF+RG/wZyx6+ZZBw==}
|
||||
dev: false
|
||||
|
||||
/@emotion/utils@1.4.1:
|
||||
resolution: {integrity: sha512-BymCXzCG3r72VKJxaYVwOXATqXIZ85cuvg0YOUDxMGNrKc1DJRZk8MgV5wyXRyEayIMd4FuXJIUgTBXvDNW5cA==}
|
||||
dev: false
|
||||
|
||||
/@emotion/weak-memoize@0.2.5:
|
||||
resolution: {integrity: sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==}
|
||||
dev: false
|
||||
|
||||
/@emotion/weak-memoize@0.4.0:
|
||||
resolution: {integrity: sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==}
|
||||
dev: false
|
||||
|
||||
/@esbuild/aix-ppc64@0.23.1:
|
||||
resolution: {integrity: sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -6082,6 +6226,91 @@ packages:
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
dev: false
|
||||
|
||||
/@styled-system/background@5.1.2:
|
||||
resolution: {integrity: sha512-jtwH2C/U6ssuGSvwTN3ri/IyjdHb8W9X/g8Y0JLcrH02G+BW3OS8kZdHphF1/YyRklnrKrBT2ngwGUK6aqqV3A==}
|
||||
dependencies:
|
||||
'@styled-system/core': 5.1.2
|
||||
dev: false
|
||||
|
||||
/@styled-system/border@5.1.5:
|
||||
resolution: {integrity: sha512-JvddhNrnhGigtzWRCVuAHepniyVi6hBlimxWDVAdcTuk7aRn9BYJUwfHslURtwYFsF5FoEs8Zmr1oZq2M1AP0A==}
|
||||
dependencies:
|
||||
'@styled-system/core': 5.1.2
|
||||
dev: false
|
||||
|
||||
/@styled-system/color@5.1.2:
|
||||
resolution: {integrity: sha512-1kCkeKDZkt4GYkuFNKc7vJQMcOmTl3bJY3YBUs7fCNM6mMYJeT1pViQ2LwBSBJytj3AB0o4IdLBoepgSgGl5MA==}
|
||||
dependencies:
|
||||
'@styled-system/core': 5.1.2
|
||||
dev: false
|
||||
|
||||
/@styled-system/core@5.1.2:
|
||||
resolution: {integrity: sha512-XclBDdNIy7OPOsN4HBsawG2eiWfCcuFt6gxKn1x4QfMIgeO6TOlA2pZZ5GWZtIhCUqEPTgIBta6JXsGyCkLBYw==}
|
||||
dependencies:
|
||||
object-assign: 4.1.1
|
||||
dev: false
|
||||
|
||||
/@styled-system/css@5.1.5:
|
||||
resolution: {integrity: sha512-XkORZdS5kypzcBotAMPBoeckDs9aSZVkvrAlq5K3xP8IMAUek+x2O4NtwoSgkYkWWzVBu6DGdFZLR790QWGG+A==}
|
||||
dev: false
|
||||
|
||||
/@styled-system/flexbox@5.1.2:
|
||||
resolution: {integrity: sha512-6hHV52+eUk654Y1J2v77B8iLeBNtc+SA3R4necsu2VVinSD7+XY5PCCEzBFaWs42dtOEDIa2lMrgL0YBC01mDQ==}
|
||||
dependencies:
|
||||
'@styled-system/core': 5.1.2
|
||||
dev: false
|
||||
|
||||
/@styled-system/grid@5.1.2:
|
||||
resolution: {integrity: sha512-K3YiV1KyHHzgdNuNlaw8oW2ktMuGga99o1e/NAfTEi5Zsa7JXxzwEnVSDSBdJC+z6R8WYTCYRQC6bkVFcvdTeg==}
|
||||
dependencies:
|
||||
'@styled-system/core': 5.1.2
|
||||
dev: false
|
||||
|
||||
/@styled-system/layout@5.1.2:
|
||||
resolution: {integrity: sha512-wUhkMBqSeacPFhoE9S6UF3fsMEKFv91gF4AdDWp0Aym1yeMPpqz9l9qS/6vjSsDPF7zOb5cOKC3tcKKOMuDCPw==}
|
||||
dependencies:
|
||||
'@styled-system/core': 5.1.2
|
||||
dev: false
|
||||
|
||||
/@styled-system/position@5.1.2:
|
||||
resolution: {integrity: sha512-60IZfMXEOOZe3l1mCu6sj/2NAyUmES2kR9Kzp7s2D3P4qKsZWxD1Se1+wJvevb+1TP+ZMkGPEYYXRyU8M1aF5A==}
|
||||
dependencies:
|
||||
'@styled-system/core': 5.1.2
|
||||
dev: false
|
||||
|
||||
/@styled-system/shadow@5.1.2:
|
||||
resolution: {integrity: sha512-wqniqYb7XuZM7K7C0d1Euxc4eGtqEe/lvM0WjuAFsQVImiq6KGT7s7is+0bNI8O4Dwg27jyu4Lfqo/oIQXNzAg==}
|
||||
dependencies:
|
||||
'@styled-system/core': 5.1.2
|
||||
dev: false
|
||||
|
||||
/@styled-system/should-forward-prop@5.1.5:
|
||||
resolution: {integrity: sha512-+rPRomgCGYnUIaFabDoOgpSDc4UUJ1KsmlnzcEp0tu5lFrBQKgZclSo18Z1URhaZm7a6agGtS5Xif7tuC2s52Q==}
|
||||
dependencies:
|
||||
'@emotion/is-prop-valid': 0.8.8
|
||||
'@emotion/memoize': 0.7.4
|
||||
styled-system: 5.1.5
|
||||
dev: false
|
||||
|
||||
/@styled-system/space@5.1.2:
|
||||
resolution: {integrity: sha512-+zzYpR8uvfhcAbaPXhH8QgDAV//flxqxSjHiS9cDFQQUSznXMQmxJegbhcdEF7/eNnJgHeIXv1jmny78kipgBA==}
|
||||
dependencies:
|
||||
'@styled-system/core': 5.1.2
|
||||
dev: false
|
||||
|
||||
/@styled-system/typography@5.1.2:
|
||||
resolution: {integrity: sha512-BxbVUnN8N7hJ4aaPOd7wEsudeT7CxarR+2hns8XCX1zp0DFfbWw4xYa/olA0oQaqx7F1hzDg+eRaGzAJbF+jOg==}
|
||||
dependencies:
|
||||
'@styled-system/core': 5.1.2
|
||||
dev: false
|
||||
|
||||
/@styled-system/variant@5.1.5:
|
||||
resolution: {integrity: sha512-Yn8hXAFoWIro8+Q5J8YJd/mP85Teiut3fsGVR9CAxwgNfIAiqlYxsk5iHU7VHJks/0KjL4ATSjmbtCDC/4l1qw==}
|
||||
dependencies:
|
||||
'@styled-system/core': 5.1.2
|
||||
'@styled-system/css': 5.1.5
|
||||
dev: false
|
||||
|
||||
/@supercharge/promise-pool@3.2.0:
|
||||
resolution: {integrity: sha512-pj0cAALblTZBPtMltWOlZTQSLT07jIaFNeM8TWoJD1cQMgDB9mcMlVMoetiB35OzNJpqQ2b+QEtwiR9f20mADg==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -6269,6 +6498,83 @@ packages:
|
||||
'@testing-library/dom': 10.1.0
|
||||
dev: false
|
||||
|
||||
/@theme-ui/color-modes@0.16.2(@emotion/react@11.13.3)(react@18.3.1):
|
||||
resolution: {integrity: sha512-jWEWx53lxNgWCT38i/kwLV2rsvJz8lVZgi5oImnVwYba9VejXD23q1ckbNFJHosQ8KKXY87ht0KPC6BQFIiHtQ==}
|
||||
peerDependencies:
|
||||
'@emotion/react': ^11.11.1
|
||||
react: '>=18'
|
||||
dependencies:
|
||||
'@emotion/react': 11.13.3(@types/react@16.14.60)(react@18.3.1)
|
||||
'@theme-ui/core': 0.16.2(@emotion/react@11.13.3)(react@18.3.1)
|
||||
'@theme-ui/css': 0.16.2(@emotion/react@11.13.3)
|
||||
deepmerge: 4.3.1
|
||||
react: 18.3.1
|
||||
dev: false
|
||||
|
||||
/@theme-ui/components@0.16.2(@emotion/react@11.13.3)(@theme-ui/theme-provider@0.16.2)(react@18.3.1):
|
||||
resolution: {integrity: sha512-d9HDxLTZzVHSiNNQUJrs4k0FU9kTFZhM3KjR+lVuztoWSGhkZEjf1KrWK8OWWXPH2LxEC5okcvggx177tnfejg==}
|
||||
peerDependencies:
|
||||
'@emotion/react': ^11.11.1
|
||||
'@theme-ui/theme-provider': ^0.16.2
|
||||
react: '>=18'
|
||||
dependencies:
|
||||
'@emotion/react': 11.13.3(@types/react@16.14.60)(react@18.3.1)
|
||||
'@styled-system/color': 5.1.2
|
||||
'@styled-system/should-forward-prop': 5.1.5
|
||||
'@styled-system/space': 5.1.2
|
||||
'@theme-ui/core': 0.16.2(@emotion/react@11.13.3)(react@18.3.1)
|
||||
'@theme-ui/css': 0.16.2(@emotion/react@11.13.3)
|
||||
'@theme-ui/theme-provider': 0.16.2(@emotion/react@11.13.3)(react@18.3.1)
|
||||
'@types/styled-system': 5.1.22
|
||||
react: 18.3.1
|
||||
dev: false
|
||||
|
||||
/@theme-ui/core@0.16.2(@emotion/react@11.13.3)(react@18.3.1):
|
||||
resolution: {integrity: sha512-bBd/ltbwO9vIUjF1jtlOX6XN0IIOdf1vzBp2JCKsSOqdfn84m+XL8OogIe/zOhQ+aM94Nrq4+32tFJc8sFav4Q==}
|
||||
peerDependencies:
|
||||
'@emotion/react': ^11.11.1
|
||||
react: '>=18'
|
||||
dependencies:
|
||||
'@emotion/react': 11.13.3(@types/react@16.14.60)(react@18.3.1)
|
||||
'@theme-ui/css': 0.16.2(@emotion/react@11.13.3)
|
||||
deepmerge: 4.3.1
|
||||
react: 18.3.1
|
||||
dev: false
|
||||
|
||||
/@theme-ui/css@0.16.2(@emotion/react@11.13.3):
|
||||
resolution: {integrity: sha512-fNe+FhwKC5+7jQfxCRnm3oqYNhMFuiWiLA9OoLBEkt3b4egot29UK1+fqemwiNVjl206e2fPT5Z7uXRdb6LC2A==}
|
||||
peerDependencies:
|
||||
'@emotion/react': ^11.11.1
|
||||
dependencies:
|
||||
'@emotion/react': 11.13.3(@types/react@16.14.60)(react@18.3.1)
|
||||
csstype: 3.1.3
|
||||
dev: false
|
||||
|
||||
/@theme-ui/global@0.16.2(@emotion/react@11.13.3)(react@18.3.1):
|
||||
resolution: {integrity: sha512-Y2CtNblERWJDxZpckR1TA0+UTH762VA82v/xTMMbufcEmJjzPasEOSZxJYH3qUOuCaJpbX5eFT49MEAujvLCzg==}
|
||||
peerDependencies:
|
||||
'@emotion/react': ^11.11.1
|
||||
react: '>=18'
|
||||
dependencies:
|
||||
'@emotion/react': 11.13.3(@types/react@16.14.60)(react@18.3.1)
|
||||
'@theme-ui/core': 0.16.2(@emotion/react@11.13.3)(react@18.3.1)
|
||||
'@theme-ui/css': 0.16.2(@emotion/react@11.13.3)
|
||||
react: 18.3.1
|
||||
dev: false
|
||||
|
||||
/@theme-ui/theme-provider@0.16.2(@emotion/react@11.13.3)(react@18.3.1):
|
||||
resolution: {integrity: sha512-LRnVevODcGqO0JyLJ3wht+PV3ZoZcJ7XXLJAJWDoGeII4vZcPQKwVy4Lpz/juHsZppQxKcB3U+sQDGBnP25irQ==}
|
||||
peerDependencies:
|
||||
'@emotion/react': ^11.11.1
|
||||
react: '>=18'
|
||||
dependencies:
|
||||
'@emotion/react': 11.13.3(@types/react@16.14.60)(react@18.3.1)
|
||||
'@theme-ui/color-modes': 0.16.2(@emotion/react@11.13.3)(react@18.3.1)
|
||||
'@theme-ui/core': 0.16.2(@emotion/react@11.13.3)(react@18.3.1)
|
||||
'@theme-ui/css': 0.16.2(@emotion/react@11.13.3)
|
||||
react: 18.3.1
|
||||
dev: false
|
||||
|
||||
/@tiptap/core@2.1.13(@tiptap/pm@2.1.13):
|
||||
resolution: {integrity: sha512-cMC8bgTN63dj1Mv82iDeeLl6sa9kY0Pug8LSalxVEptRmyFVsVxGgu2/6Y3T+9aCYScxfS06EkA8SdzFMAwYTQ==}
|
||||
peerDependencies:
|
||||
@@ -7062,6 +7368,12 @@ packages:
|
||||
csstype: 3.1.3
|
||||
dev: false
|
||||
|
||||
/@types/styled-system@5.1.22:
|
||||
resolution: {integrity: sha512-NbRp37zWcrf/+Qf2NumdyZfhSx1dzJ50zgfKvnezYJx1HTRUMVYY8jtWvK1eoIAa6F5sXwHLhE8oXNu15ThBAA==}
|
||||
dependencies:
|
||||
csstype: 3.1.3
|
||||
dev: false
|
||||
|
||||
/@types/superagent@4.1.13:
|
||||
resolution: {integrity: sha512-YIGelp3ZyMiH0/A09PMAORO0EBGlF5xIKfDpK74wdYvWUs2o96b5CItJcWPdH409b7SAXIIG6p8NdU/4U2Maww==}
|
||||
dependencies:
|
||||
@@ -7652,6 +7964,37 @@ packages:
|
||||
resolution: {integrity: sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ==}
|
||||
dev: false
|
||||
|
||||
/@xstyled/core@3.8.1:
|
||||
resolution: {integrity: sha512-5mqKUZQLuB26NqF36jxvfhl6xqTW9TT2LfBbZJmoJISqS+cgAVoO9H82edisQsH/vxtoO9vjevcxtFXwOJPArA==}
|
||||
dependencies:
|
||||
'@xstyled/system': 3.8.1
|
||||
'@xstyled/util': 3.7.0
|
||||
dev: false
|
||||
|
||||
/@xstyled/emotion@3.8.1(@emotion/react@11.13.3)(@emotion/styled@11.13.0):
|
||||
resolution: {integrity: sha512-HRPkKiCFUTCYL5QDLH27Lz3tBBCHvF2zUEybxIHcIOIRnH4VgCtTmGuY7wa/tkiIaauHYtHoJBWYaogsPY3mHw==}
|
||||
peerDependencies:
|
||||
'@emotion/react': ^11.0.0
|
||||
'@emotion/styled': ^11.0.0
|
||||
dependencies:
|
||||
'@emotion/react': 11.13.3(@types/react@16.14.60)(react@18.3.1)
|
||||
'@emotion/styled': 11.13.0(@emotion/react@11.13.3)(@types/react@16.14.60)(react@18.3.1)
|
||||
'@xstyled/core': 3.8.1
|
||||
'@xstyled/system': 3.8.1
|
||||
'@xstyled/util': 3.7.0
|
||||
dev: false
|
||||
|
||||
/@xstyled/system@3.8.1:
|
||||
resolution: {integrity: sha512-mmWeAHrnTjV5ZDhUv5kPf4NF0BKLUbN9bHBmx1U+6kNwPAqHq+kOA+7ef9DZEeedTY4g29uYg8hvLqBweHXKqQ==}
|
||||
dependencies:
|
||||
'@xstyled/util': 3.7.0
|
||||
csstype: 3.1.3
|
||||
dev: false
|
||||
|
||||
/@xstyled/util@3.7.0:
|
||||
resolution: {integrity: sha512-rYtXRcNh+pgRxGnciP0Mas21mpyOzcCTVy7w9uIByQk3EytwBQjDiN6wCasXibkw49Urfti5efsklRbCl5QZww==}
|
||||
dev: false
|
||||
|
||||
/@xtuc/ieee754@1.2.0:
|
||||
resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==}
|
||||
|
||||
@@ -24615,6 +24958,24 @@ packages:
|
||||
- '@babel/core'
|
||||
dev: false
|
||||
|
||||
/styled-system@5.1.5:
|
||||
resolution: {integrity: sha512-7VoD0o2R3RKzOzPK0jYrVnS8iJdfkKsQJNiLRDjikOpQVqQHns/DXWaPZOH4tIKkhAT7I6wIsy9FWTWh2X3q+A==}
|
||||
dependencies:
|
||||
'@styled-system/background': 5.1.2
|
||||
'@styled-system/border': 5.1.5
|
||||
'@styled-system/color': 5.1.2
|
||||
'@styled-system/core': 5.1.2
|
||||
'@styled-system/flexbox': 5.1.2
|
||||
'@styled-system/grid': 5.1.2
|
||||
'@styled-system/layout': 5.1.2
|
||||
'@styled-system/position': 5.1.2
|
||||
'@styled-system/shadow': 5.1.2
|
||||
'@styled-system/space': 5.1.2
|
||||
'@styled-system/typography': 5.1.2
|
||||
'@styled-system/variant': 5.1.5
|
||||
object-assign: 4.1.1
|
||||
dev: false
|
||||
|
||||
/stylehacks@5.1.1(postcss@8.4.38):
|
||||
resolution: {integrity: sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==}
|
||||
engines: {node: ^10 || ^12 || >=14.0}
|
||||
@@ -24632,6 +24993,10 @@ packages:
|
||||
rtlcss: 2.6.2
|
||||
dev: false
|
||||
|
||||
/stylis@4.2.0:
|
||||
resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==}
|
||||
dev: false
|
||||
|
||||
/stylis@4.3.2:
|
||||
resolution: {integrity: sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==}
|
||||
dev: false
|
||||
@@ -24975,6 +25340,22 @@ packages:
|
||||
/text-table@0.2.0:
|
||||
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
|
||||
|
||||
/theme-ui@0.16.2(@emotion/react@11.13.3)(react@18.3.1):
|
||||
resolution: {integrity: sha512-6+/D9ZMKlwWWLQ3idoESxcDUNPkNuGPiixKWGrTD1Fo1yAS3wSb9Je4Xt9Zu3a8f1kbrAyy4vnTVcomFZ1Meig==}
|
||||
peerDependencies:
|
||||
'@emotion/react': '>=11.1.1'
|
||||
react: '>=18'
|
||||
dependencies:
|
||||
'@emotion/react': 11.13.3(@types/react@16.14.60)(react@18.3.1)
|
||||
'@theme-ui/color-modes': 0.16.2(@emotion/react@11.13.3)(react@18.3.1)
|
||||
'@theme-ui/components': 0.16.2(@emotion/react@11.13.3)(@theme-ui/theme-provider@0.16.2)(react@18.3.1)
|
||||
'@theme-ui/core': 0.16.2(@emotion/react@11.13.3)(react@18.3.1)
|
||||
'@theme-ui/css': 0.16.2(@emotion/react@11.13.3)
|
||||
'@theme-ui/global': 0.16.2(@emotion/react@11.13.3)(react@18.3.1)
|
||||
'@theme-ui/theme-provider': 0.16.2(@emotion/react@11.13.3)(react@18.3.1)
|
||||
react: 18.3.1
|
||||
dev: false
|
||||
|
||||
/then-request@6.0.2:
|
||||
resolution: {integrity: sha512-3ZBiG7JvP3wbDzA9iNY5zJQcHL4jn/0BWtXIkagfz7QgOL/LqjCEOBQuJNZfu0XYnv5JhKh+cDxCPM4ILrqruA==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
|
||||
Reference in New Issue
Block a user