diff --git a/packages/webapp/src/constants/preferencesMenu.tsx b/packages/webapp/src/constants/preferencesMenu.tsx index f90c7ed04..562cce1b1 100644 --- a/packages/webapp/src/constants/preferencesMenu.tsx +++ b/packages/webapp/src/constants/preferencesMenu.tsx @@ -12,6 +12,10 @@ export default [ text: , href: '/preferences/users', }, + { + text: 'Invoices', + href: '/preferences/invoices', + }, { text: , href: '/preferences/currencies', diff --git a/packages/webapp/src/containers/Preferences/CreditNotes/PreferencesCreditNotes.tsx b/packages/webapp/src/containers/Preferences/CreditNotes/PreferencesCreditNotes.tsx new file mode 100644 index 000000000..ee1753398 --- /dev/null +++ b/packages/webapp/src/containers/Preferences/CreditNotes/PreferencesCreditNotes.tsx @@ -0,0 +1,14 @@ +// @ts-nocheck +import { PreferencesCreditNotesBoot } from './PreferencesCreditNotesFormBoot'; +import PreferencesInvoiceFormPage from './PreferencesCreditNotesFormPage'; + +/** + * items preferences. + */ +export default function PreferencesCreditNotes() { + return ( + + + + ); +} diff --git a/packages/webapp/src/containers/Preferences/CreditNotes/PreferencesCreditNotesForm.schema.ts b/packages/webapp/src/containers/Preferences/CreditNotes/PreferencesCreditNotesForm.schema.ts new file mode 100644 index 000000000..b6cf3eab6 --- /dev/null +++ b/packages/webapp/src/containers/Preferences/CreditNotes/PreferencesCreditNotesForm.schema.ts @@ -0,0 +1,9 @@ +// @ts-nocheck +import * as Yup from 'yup'; + +const Schema = Yup.object().shape({ + termsConditions: Yup.string().optional(), + customerNotes: Yup.string().optional(), +}); + +export const PreferencesEstimatesFormSchema = Schema; diff --git a/packages/webapp/src/containers/Preferences/CreditNotes/PreferencesCreditNotesForm.tsx b/packages/webapp/src/containers/Preferences/CreditNotes/PreferencesCreditNotesForm.tsx new file mode 100644 index 000000000..17fc18c0d --- /dev/null +++ b/packages/webapp/src/containers/Preferences/CreditNotes/PreferencesCreditNotesForm.tsx @@ -0,0 +1,80 @@ +// @ts-nocheck +import styled from 'styled-components'; +import { Form } from 'formik'; +import { Button, Intent } from '@blueprintjs/core'; +import { useHistory } from 'react-router-dom'; + +import { + FieldRequiredHint, + FormattedMessage as T, + FFormGroup, + FTextArea, +} from '@/components'; + +/** + * Preferences estimates form. + */ +export function PreferencesCreditNotesForm({ isSubmitting }) { + const history = useHistory(); + + // Handle close click. + const handleCloseClick = () => { + history.go(-1); + }; + + return ( +
+ {/* ---------- Terms & Conditions ---------- */} + } + labelInfo={} + fastField={true} + > + + + + {/* ---------- Customer Notes ---------- */} + } + fastField={true} + > + + + + + + + +
+ ); +} + +const CardFooterActions = styled.div` + padding-top: 16px; + border-top: 1px solid #e0e7ea; + margin-top: 30px; + + .bp4-button { + min-width: 70px; + + + .bp4-button { + margin-left: 10px; + } + } +`; diff --git a/packages/webapp/src/containers/Preferences/CreditNotes/PreferencesCreditNotesFormBoot.tsx b/packages/webapp/src/containers/Preferences/CreditNotes/PreferencesCreditNotesFormBoot.tsx new file mode 100644 index 000000000..c416f69c4 --- /dev/null +++ b/packages/webapp/src/containers/Preferences/CreditNotes/PreferencesCreditNotesFormBoot.tsx @@ -0,0 +1,41 @@ +// @ts-nocheck +import React from 'react'; +import classNames from 'classnames'; +import { CLASSES } from '@/constants/classes'; +import { useSettings } from '@/hooks/query'; +import PreferencesPageLoader from '../PreferencesPageLoader'; + +const PreferencesCreditNotesFormContext = React.createContext(); + +function PreferencesCreditNotesBoot({ ...props }) { + // Fetches organization settings. + const { isLoading: isSettingsLoading } = useSettings(); + + // Provider state. + const provider = { + organization: {}, + }; + + // Detarmines whether if any query is loading. + const isLoading = isSettingsLoading; + + return ( +
+ {isLoading ? ( + + ) : ( + + )} +
+ ); +} + +const usePreferencesCreditNotesFormContext = () => + React.useContext(PreferencesCreditNotesFormContext); + +export { PreferencesCreditNotesBoot, usePreferencesCreditNotesFormContext }; diff --git a/packages/webapp/src/containers/Preferences/CreditNotes/PreferencesCreditNotesFormPage.tsx b/packages/webapp/src/containers/Preferences/CreditNotes/PreferencesCreditNotesFormPage.tsx new file mode 100644 index 000000000..045ffbbc5 --- /dev/null +++ b/packages/webapp/src/containers/Preferences/CreditNotes/PreferencesCreditNotesFormPage.tsx @@ -0,0 +1,69 @@ +// @ts-nocheck +import React, { useEffect } from 'react'; +import intl from 'react-intl-universal'; +import { Formik } from 'formik'; +import { Intent } from '@blueprintjs/core'; + +import { AppToaster } from '@/components'; +import { PreferencesCreditNotesFormSchema } from './PreferencesCreditNotesForm.schema'; +import { usePreferencesInvoiceFormContext } from './PreferencesCreditNotesFormBoot'; +import { PreferencesCreditNotesForm } from './PreferencesCreditNotesForm'; +import withDashboardActions from '@/containers/Dashboard/withDashboardActions'; + +import { compose, transformToForm } from '@/utils'; + +const defaultValues = { + termsConditions: '', + customerNotes: '', +}; + +/** + * Preferences - . + */ +function PreferencesCreditNotesFormPageRoot({ + // #withDashboardActions + changePreferencesPageTitle, +}) { + const { organization } = usePreferencesInvoiceFormContext(); + + useEffect(() => { + changePreferencesPageTitle(intl.get('preferences.estimates')); + }, [changePreferencesPageTitle]); + + // Initial values. + const initialValues = { + ...defaultValues, + ...transformToForm(organization.metadata, defaultValues), + }; + // Handle the form submit. + const handleFormSubmit = (values, { setSubmitting }) => { + // Handle request success. + const onSuccess = (response) => { + AppToaster.show({ + message: intl.get('preferences.estimates.success_message'), + intent: Intent.SUCCESS, + }); + setSubmitting(false); + }; + // Handle request error. + const onError = () => { + setSubmitting(false); + }; + // updateOrganization({ ...values }) + // .then(onSuccess) + // .catch(onError); + }; + + return ( + + ); +} + +export const PreferencesCreditNotesFormPage = compose(withDashboardActions)( + PreferencesCreditNotesFormPageRoot, +); diff --git a/packages/webapp/src/containers/Preferences/Estimates/PreferencesEstimates.tsx b/packages/webapp/src/containers/Preferences/Estimates/PreferencesEstimates.tsx new file mode 100644 index 000000000..2b5af6bdf --- /dev/null +++ b/packages/webapp/src/containers/Preferences/Estimates/PreferencesEstimates.tsx @@ -0,0 +1,14 @@ +// @ts-nocheck +import { PreferencesEstimatesBoot } from './PreferencesEstimatesFormBoot'; +import PreferencesInvoiceFormPage from './PreferencesEstimatesFormPage'; + +/** + * items preferences. + */ +export default function PreferencesEstimates() { + return ( + + + + ); +} diff --git a/packages/webapp/src/containers/Preferences/Estimates/PreferencesEstimatesForm.schema.ts b/packages/webapp/src/containers/Preferences/Estimates/PreferencesEstimatesForm.schema.ts new file mode 100644 index 000000000..b6cf3eab6 --- /dev/null +++ b/packages/webapp/src/containers/Preferences/Estimates/PreferencesEstimatesForm.schema.ts @@ -0,0 +1,9 @@ +// @ts-nocheck +import * as Yup from 'yup'; + +const Schema = Yup.object().shape({ + termsConditions: Yup.string().optional(), + customerNotes: Yup.string().optional(), +}); + +export const PreferencesEstimatesFormSchema = Schema; diff --git a/packages/webapp/src/containers/Preferences/Estimates/PreferencesEstimatesForm.tsx b/packages/webapp/src/containers/Preferences/Estimates/PreferencesEstimatesForm.tsx new file mode 100644 index 000000000..426797f4d --- /dev/null +++ b/packages/webapp/src/containers/Preferences/Estimates/PreferencesEstimatesForm.tsx @@ -0,0 +1,80 @@ +// @ts-nocheck +import styled from 'styled-components'; +import { Form } from 'formik'; +import { Button, Intent } from '@blueprintjs/core'; +import { useHistory } from 'react-router-dom'; + +import { + FieldRequiredHint, + FormattedMessage as T, + FFormGroup, + FTextArea, +} from '@/components'; + +/** + * Preferences estimates form. + */ +export function PreferencesEstimatesForm({ isSubmitting }) { + const history = useHistory(); + + // Handle close click. + const handleCloseClick = () => { + history.go(-1); + }; + + return ( +
+ {/* ---------- Terms & Conditions ---------- */} + } + labelInfo={} + fastField={true} + > + + + + {/* ---------- Customer Notes ---------- */} + } + fastField={true} + > + + + + + + + +
+ ); +} + +const CardFooterActions = styled.div` + padding-top: 16px; + border-top: 1px solid #e0e7ea; + margin-top: 30px; + + .bp4-button { + min-width: 70px; + + + .bp4-button { + margin-left: 10px; + } + } +`; diff --git a/packages/webapp/src/containers/Preferences/Estimates/PreferencesEstimatesFormBoot.tsx b/packages/webapp/src/containers/Preferences/Estimates/PreferencesEstimatesFormBoot.tsx new file mode 100644 index 000000000..e444c5998 --- /dev/null +++ b/packages/webapp/src/containers/Preferences/Estimates/PreferencesEstimatesFormBoot.tsx @@ -0,0 +1,41 @@ +// @ts-nocheck +import React from 'react'; +import classNames from 'classnames'; +import { CLASSES } from '@/constants/classes'; +import { useSettings } from '@/hooks/query'; +import PreferencesPageLoader from '../PreferencesPageLoader'; + +const PreferencesEstimatesFormContext = React.createContext(); + +function PreferencesEstimatesBoot({ ...props }) { + // Fetches organization settings. + const { isLoading: isSettingsLoading } = useSettings(); + + // Provider state. + const provider = { + organization: {}, + }; + + // Detarmines whether if any query is loading. + const isLoading = isSettingsLoading; + + return ( +
+ {isLoading ? ( + + ) : ( + + )} +
+ ); +} + +const usePreferencesEstimatesFormContext = () => + React.useContext(PreferencesEstimatesFormContext); + +export { PreferencesEstimatesBoot, usePreferencesEstimatesFormContext }; diff --git a/packages/webapp/src/containers/Preferences/Estimates/PreferencesEstimatesFormPage.tsx b/packages/webapp/src/containers/Preferences/Estimates/PreferencesEstimatesFormPage.tsx new file mode 100644 index 000000000..b74279741 --- /dev/null +++ b/packages/webapp/src/containers/Preferences/Estimates/PreferencesEstimatesFormPage.tsx @@ -0,0 +1,69 @@ +// @ts-nocheck +import React, { useEffect } from 'react'; +import intl from 'react-intl-universal'; +import { Formik } from 'formik'; +import { Intent } from '@blueprintjs/core'; + +import { AppToaster } from '@/components'; +import { PreferencesEstimatesFormSchema } from './PreferencesEstimatesForm.schema'; +import { usePreferencesInvoiceFormContext } from './PreferencesEstimatesFormBoot'; +import { PreferencesEstimatesForm } from './PreferencesEstimatesForm'; +import withDashboardActions from '@/containers/Dashboard/withDashboardActions'; + +import { compose, transformToForm } from '@/utils'; + +const defaultValues = { + termsConditions: '', + customerNotes: '', +}; + +/** + * Preferences - . + */ +function PreferencesEstimatesFormPageRoot({ + // #withDashboardActions + changePreferencesPageTitle, +}) { + const { organization } = usePreferencesInvoiceFormContext(); + + useEffect(() => { + changePreferencesPageTitle(intl.get('preferences.estimates')); + }, [changePreferencesPageTitle]); + + // Initial values. + const initialValues = { + ...defaultValues, + ...transformToForm(organization.metadata, defaultValues), + }; + // Handle the form submit. + const handleFormSubmit = (values, { setSubmitting }) => { + // Handle request success. + const onSuccess = (response) => { + AppToaster.show({ + message: intl.get('preferences.estimates.success_message'), + intent: Intent.SUCCESS, + }); + setSubmitting(false); + }; + // Handle request error. + const onError = () => { + setSubmitting(false); + }; + // updateOrganization({ ...values }) + // .then(onSuccess) + // .catch(onError); + }; + + return ( + + ); +} + +export const PreferencesEstimatesFormPage = compose(withDashboardActions)( + PreferencesEstimatesFormPageRoot, +); diff --git a/packages/webapp/src/containers/Preferences/Invoices/PreferencesInvoiceForm.schema.ts b/packages/webapp/src/containers/Preferences/Invoices/PreferencesInvoiceForm.schema.ts new file mode 100644 index 000000000..be7bead85 --- /dev/null +++ b/packages/webapp/src/containers/Preferences/Invoices/PreferencesInvoiceForm.schema.ts @@ -0,0 +1,9 @@ +// @ts-nocheck +import * as Yup from 'yup'; + +const Schema = Yup.object().shape({ + termsConditions: Yup.string().optional(), + customerNotes: Yup.string().optional(), +}); + +export const PreferencesInvoiceFormSchema = Schema; diff --git a/packages/webapp/src/containers/Preferences/Invoices/PreferencesInvoiceFormBoot.tsx b/packages/webapp/src/containers/Preferences/Invoices/PreferencesInvoiceFormBoot.tsx new file mode 100644 index 000000000..b4983531a --- /dev/null +++ b/packages/webapp/src/containers/Preferences/Invoices/PreferencesInvoiceFormBoot.tsx @@ -0,0 +1,41 @@ +// @ts-nocheck +import React from 'react'; +import classNames from 'classnames'; +import { CLASSES } from '@/constants/classes'; +import { useSettings } from '@/hooks/query'; +import PreferencesPageLoader from '../PreferencesPageLoader'; + +const PreferencesInvoiceFormContext = React.createContext(); + +function PreferencesInvoicesBoot({ ...props }) { + // Fetches organization settings. + const { isLoading: isSettingsLoading } = useSettings(); + + // Provider state. + const provider = { + organization: {}, + }; + + // Detarmines whether if any query is loading. + const isLoading = isSettingsLoading; + + return ( +
+ {isLoading ? ( + + ) : ( + + )} +
+ ); +} + +const usePreferencesInvoiceFormContext = () => + React.useContext(PreferencesInvoiceFormContext); + +export { PreferencesInvoicesBoot, usePreferencesInvoiceFormContext }; diff --git a/packages/webapp/src/containers/Preferences/Invoices/PreferencesInvoiceFormPage.tsx b/packages/webapp/src/containers/Preferences/Invoices/PreferencesInvoiceFormPage.tsx new file mode 100644 index 000000000..ddf74b02f --- /dev/null +++ b/packages/webapp/src/containers/Preferences/Invoices/PreferencesInvoiceFormPage.tsx @@ -0,0 +1,67 @@ +// @ts-nocheck +import React, { useEffect } from 'react'; +import intl from 'react-intl-universal'; +import { Formik } from 'formik'; +import { Intent } from '@blueprintjs/core'; + +import { AppToaster } from '@/components'; +import { PreferencesInvoiceFormSchema } from './PreferencesInvoiceForm.schema'; +import { usePreferencesInvoiceFormContext } from './PreferencesInvoiceFormBoot'; +import { PreferencesGeneralForm } from './PreferencesInvoicesForm'; +import withDashboardActions from '@/containers/Dashboard/withDashboardActions'; + +import { compose, transformToForm } from '@/utils'; + +const defaultValues = { + termsConditions: '', + customerNotes: '', +}; + +/** + * Preferences - Invoices. + */ +function PreferencesInvoiceFormPage({ + // #withDashboardActions + changePreferencesPageTitle, +}) { + const { organization } = usePreferencesInvoiceFormContext(); + + useEffect(() => { + changePreferencesPageTitle(intl.get('preferences.invoices')); + }, [changePreferencesPageTitle]); + + // Initial values. + const initialValues = { + ...defaultValues, + ...transformToForm(organization.metadata, defaultValues), + }; + // Handle the form submit. + const handleFormSubmit = (values, { setSubmitting }) => { + // Handle request success. + const onSuccess = (response) => { + AppToaster.show({ + message: intl.get('preferences.invoices.success_message'), + intent: Intent.SUCCESS, + }); + setSubmitting(false); + }; + // Handle request error. + const onError = () => { + setSubmitting(false); + }; + // updateOrganization({ ...values }) + // .then(onSuccess) + // .catch(onError); + }; + + return ( + + ); +} + +export default compose(withDashboardActions)(PreferencesInvoiceFormPage); diff --git a/packages/webapp/src/containers/Preferences/Invoices/PreferencesInvoices.tsx b/packages/webapp/src/containers/Preferences/Invoices/PreferencesInvoices.tsx new file mode 100644 index 000000000..da349ea9a --- /dev/null +++ b/packages/webapp/src/containers/Preferences/Invoices/PreferencesInvoices.tsx @@ -0,0 +1,14 @@ +// @ts-nocheck +import { PreferencesInvoicesBoot } from './PreferencesInvoiceFormBoot'; +import PreferencesInvoiceFormPage from './PreferencesInvoiceFormPage'; + +/** + * items preferences. + */ +export default function PreferencesInvoices() { + return ( + + + + ); +} diff --git a/packages/webapp/src/containers/Preferences/Invoices/PreferencesInvoicesForm.tsx b/packages/webapp/src/containers/Preferences/Invoices/PreferencesInvoicesForm.tsx new file mode 100644 index 000000000..0e2b44f51 --- /dev/null +++ b/packages/webapp/src/containers/Preferences/Invoices/PreferencesInvoicesForm.tsx @@ -0,0 +1,81 @@ +// @ts-nocheck +import styled from 'styled-components'; +import { Form } from 'formik'; +import { Button, Intent } from '@blueprintjs/core'; +import { useHistory } from 'react-router-dom'; + +import { + FieldRequiredHint, + FormattedMessage as T, + FFormGroup, + FInputGroup, + FTextArea, +} from '@/components'; + +/** + * Preferences general form. + */ +export function PreferencesGeneralForm({ isSubmitting }) { + const history = useHistory(); + + // Handle close click. + const handleCloseClick = () => { + history.go(-1); + }; + + return ( +
+ {/* ---------- Terms & Conditions ---------- */} + } + labelInfo={} + fastField={true} + > + + + + {/* ---------- Customer Notes ---------- */} + } + fastField={true} + > + + + + + + + +
+ ); +} + +const CardFooterActions = styled.div` + padding-top: 16px; + border-top: 1px solid #e0e7ea; + margin-top: 30px; + + .bp4-button { + min-width: 70px; + + + .bp4-button { + margin-left: 10px; + } + } +`; diff --git a/packages/webapp/src/lang/en/index.json b/packages/webapp/src/lang/en/index.json index 4a78b4e76..f67a6f478 100644 --- a/packages/webapp/src/lang/en/index.json +++ b/packages/webapp/src/lang/en/index.json @@ -2290,5 +2290,8 @@ "sidebar.new_project": "New Project", "sidebar.new_time_entry": "New Time Entry", "sidebar.project_profitability_summary": "Project Profitability Summary", - "global_error.too_many_requests": "Too many requests" + "global_error.too_many_requests": "Too many requests", + + "pref.invoices.termsConditions.field": "Terms & Conditions", + "pref.invoices.customerNotes.field": "Customer Notes" } diff --git a/packages/webapp/src/routes/preferences.tsx b/packages/webapp/src/routes/preferences.tsx index 775efcf82..5fdcb13e6 100644 --- a/packages/webapp/src/routes/preferences.tsx +++ b/packages/webapp/src/routes/preferences.tsx @@ -9,6 +9,8 @@ import SMSIntegration from '../containers/Preferences/SMSIntegration'; import DefaultRoute from '../containers/Preferences/DefaultRoute'; import Warehouses from '../containers/Preferences/Warehouses'; import Branches from '../containers/Preferences/Branches'; +import Invoices from '../containers/Preferences/Invoices/PreferencesInvoices'; + const BASE_URL = '/preferences'; @@ -23,6 +25,16 @@ export default [ component: Users, exact: true, }, + { + path: `${BASE_URL}/invoices`, + component: Invoices, + exact: true, + }, + { + path: `${BASE_URL}/credit-notes`, + component: CreditNotes, + exact: true, + }, { path: `${BASE_URL}/roles`, component: Roles,