diff --git a/frontend/src/assets/locales/ro/translation.json b/frontend/src/assets/locales/ro/translation.json index 3d607419..a1233f18 100644 --- a/frontend/src/assets/locales/ro/translation.json +++ b/frontend/src/assets/locales/ro/translation.json @@ -1019,6 +1019,8 @@ }, "doc_templates": { "title": "Creează template", + "view_title": "Vizualizează template", + "edit_title": "Editează template", "subheading": { "p1": "Acest template a fost realizat respectând normele din domeniu.", "p1_link": "Află mai multe", diff --git a/frontend/src/common/constants/routes.ts b/frontend/src/common/constants/routes.ts index 0c516b8e..4dbec480 100644 --- a/frontend/src/common/constants/routes.ts +++ b/frontend/src/common/constants/routes.ts @@ -71,11 +71,6 @@ export const ROUTES: IRoute[] = [ name: 'Contracte', href: 'documents/templates', }, - { - id: 63, - name: 'Creează template', - href: 'documents/templates/create', - }, { id: 64, name: 'Generează contract', diff --git a/frontend/src/components/DocumentTemplatesTable.tsx b/frontend/src/components/DocumentTemplatesTable.tsx index ba285c20..a644560b 100644 --- a/frontend/src/components/DocumentTemplatesTable.tsx +++ b/frontend/src/components/DocumentTemplatesTable.tsx @@ -12,7 +12,7 @@ import { SortOrder, TableColumn } from 'react-data-table-component'; import { DocumentTemplatesProps } from '../containers/query/DocumentTemplatesTableWithQueryParams'; import { ArrowDownTrayIcon, EyeIcon, PencilIcon, TrashIcon } from '@heroicons/react/24/outline'; import Popover from './Popover'; -import { Link } from 'react-router-dom'; +import { Link, useNavigate } from 'react-router-dom'; const createArchiveRoute = (name: string) => `/actions-archive?author=${name.split(' ').join('+')}`; @@ -62,6 +62,7 @@ const DocumentTemplatesTableHeader = [ export const DocumentTemplatesTable = ({ query, setQuery }: DocumentTemplatesProps) => { const { t } = useTranslation(['doc_templates']); + const navigate = useNavigate(); const { data: templates, isLoading: isLoadingDocumentTemplates } = useDocumentTemplatesQuery({ limit: 10, @@ -108,12 +109,12 @@ export const DocumentTemplatesTable = ({ query, setQuery }: DocumentTemplatesPro { label: t('table.table_actions.view'), icon: , - onClick: () => { }, + onClick: (row: IDocumentTemplateListItem) => { navigate(`${row.id}`) }, }, { label: t('table.table_actions.edit'), icon: , - onClick: () => { }, + onClick: (row: IDocumentTemplateListItem) => { navigate(`${row.id}/edit`) }, }, { label: t('table.table_actions.download_uncompleted'), @@ -132,7 +133,7 @@ export const DocumentTemplatesTable = ({ query, setQuery }: DocumentTemplatesPro { label: t('table.table_actions.view'), icon: , - onClick: () => { }, + onClick: (row: IDocumentTemplateListItem) => { navigate(`${row.id}`) }, }, { label: t('table.table_actions.download_uncompleted'), diff --git a/frontend/src/components/RichText/RichTextEditor.tsx b/frontend/src/components/RichText/RichTextEditor.tsx index 3d2e38a7..4639dd4e 100644 --- a/frontend/src/components/RichText/RichTextEditor.tsx +++ b/frontend/src/components/RichText/RichTextEditor.tsx @@ -9,14 +9,15 @@ const RichTextEditor = ({ onChange, error, className, + readonly, }: { onChange: (value: string) => void; value: string; error?: FieldError | Merge | undefined; className?: string; + readonly?: boolean; }) => { const { t } = useTranslation('doc_templates'); - console.log('error', error); return (
@@ -27,6 +28,7 @@ const RichTextEditor = ({ theme="snow" onChange={onChange} value={value} + readOnly={readonly} // this bottom margin is NECESSARY due to the default styling, which sets the height of 100% to the text editor, but it doesn't take into consideration the toolbar height className={`mb-10 border-2 border-cool-gray-900 rounded min-h-[10rem] max-h-[40rem] ${error && 'border-2 border-red-500'} ${className}`} /> diff --git a/frontend/src/components/contracts/ContractTemplatePreview.tsx b/frontend/src/components/contracts/ContractTemplatePreview.tsx index f41acd6d..5fbd7843 100644 --- a/frontend/src/components/contracts/ContractTemplatePreview.tsx +++ b/frontend/src/components/contracts/ContractTemplatePreview.tsx @@ -13,11 +13,15 @@ export const ContractTemplatePreview = ({ reset, getValues, formErrors, + readonly, + termsValue, }: { control: Control; reset: UseFormReset; getValues: UseFormGetValues; formErrors: FieldErrors; + readonly?: boolean; + termsValue: string; }) => { const { t } = useTranslation('doc_templates'); const [infoParagraphHovered, setInfoParagraphHovered] = useState(false); @@ -157,6 +161,8 @@ export const ContractTemplatePreview = ({ reset={reset} getValues={getValues} formErrors={formErrors} + readonly={readonly} + termsValue={termsValue} /> ; reset: UseFormReset; getValues: UseFormGetValues; formErrors: FieldErrors; + readonly?: boolean; + termsValue?: string; }) => { const { t } = useTranslation(['doc_templates', 'general']); const [editingText, setEditingText] = useState(false); // todo: initial value for contractTerms taken from the template - const [contractTerms, setContractTerms] = useState(''); + const [contractTerms, setContractTerms] = useState(termsValue || '') + + useEffect(() => { + if (termsValue && termsValue !== contractTerms) { + setContractTerms(termsValue || ''); + } + }, [termsValue]); const onSave = () => { const newContractTerms = getValues('contractTerms'); @@ -53,7 +63,7 @@ export const ContractTerms = ({ field: { value: string; onChange: (value: string) => void }; }) => { return ( - + ); }} /> @@ -78,10 +88,10 @@ export const ContractTerms = ({ ); } - if (!contractTerms) { + if (!contractTerms && !readonly) { return ( ); } // normal text - return ; + return ; }; diff --git a/frontend/src/components/contracts/ContractTermsContent.tsx b/frontend/src/components/contracts/ContractTermsContent.tsx index 47ffb566..1317baa1 100644 --- a/frontend/src/components/contracts/ContractTermsContent.tsx +++ b/frontend/src/components/contracts/ContractTermsContent.tsx @@ -7,9 +7,11 @@ import DOMPurify from 'dompurify'; export const ContractTermsContent = ({ innerContent, setEditingText, + readonly, }: { innerContent: string; setEditingText: React.Dispatch>; + readonly?: boolean }) => { const { t } = useTranslation('doc_templates'); @@ -17,12 +19,12 @@ export const ContractTermsContent = ({

{t('contract_terms.title')}

-
diff --git a/frontend/src/components/contracts/OrganizationDetails.tsx b/frontend/src/components/contracts/OrganizationDetails.tsx index 5027603b..308beaa4 100644 --- a/frontend/src/components/contracts/OrganizationDetails.tsx +++ b/frontend/src/components/contracts/OrganizationDetails.tsx @@ -7,7 +7,7 @@ import { useResyncOrganizationWithOngHubMutation } from '../../services/organiza import Button from '../Button'; import { useQueryClient } from 'react-query'; -export const OrganizationDetails = ({ control }: { control: Control }) => { +export const OrganizationDetails = ({ control, readonly }: { control: Control, readonly?: boolean }) => { const { t } = useTranslation(['doc_templates', 'general']); const queryClient = useQueryClient(); @@ -35,6 +35,7 @@ export const OrganizationDetails = ({ control }: { control: Control ? t('required', { ns: 'general' }) : undefined } + readOnly={readonly} /> ); }} diff --git a/frontend/src/pages/CreateContractTemplate.tsx b/frontend/src/pages/CreateContractTemplate.tsx index e1222051..72207676 100644 --- a/frontend/src/pages/CreateContractTemplate.tsx +++ b/frontend/src/pages/CreateContractTemplate.tsx @@ -1,7 +1,7 @@ -import React, { useMemo } from 'react'; +import React, { useEffect, useMemo } from 'react'; import PageLayout from '../layouts/PageLayout'; import PageHeader from '../components/PageHeader'; -import { useNavigate } from 'react-router-dom'; +import { useNavigate, useParams } from 'react-router-dom'; import CardHeader from '../components/CardHeader'; import Card from '../layouts/CardLayout'; import CardBody from '../components/CardBody'; @@ -16,9 +16,18 @@ import { Tooltip } from 'react-tooltip'; import { IAddContractTemplatePayload, useAddContractTemplateMutation, + useDocumentTemplateByIdQuery, } from '../services/documents-templates/documents-templates.service'; +import { IDocumentTemplate } from '../common/interfaces/template.interface'; + +interface CreateContractTemplateProps { + template?: IDocumentTemplate; + readonly?: boolean; +} + +export const CreateContractTemplate = ({ readonly }: CreateContractTemplateProps) => { + const { id } = useParams(); -export const CreateContractTemplate = () => { const navigate = useNavigate(); const { t } = useTranslation(['doc_templates', 'general']); @@ -30,6 +39,19 @@ export const CreateContractTemplate = () => { setError, formState: { errors }, } = useForm(); + + const { data: template } = useDocumentTemplateByIdQuery(id); + const contractTerms = getValues('contractTerms'); + + useEffect(() => { + if (template) { + reset({ + templateName: template.name, + contractTerms: template.documentTerms, + }); + } + }, [template]); + const { data: organization } = useOrganizationQuery(); const isOrganizationDataComplete = useMemo( () => @@ -40,13 +62,10 @@ export const CreateContractTemplate = () => { organization?.legalReprezentativeRole, [organization], ); - console.log('errors', errors); const { mutate: addContractTemplate, isLoading: isLoadingAddContractTemplate } = useAddContractTemplateMutation(); const onSubmit = ({ templateName, contractTerms }: FieldValues) => { - console.log('templateName', templateName); - console.log('contractTerms', contractTerms); if (!contractTerms) { return setError('contractTerms', { type: 'required', @@ -64,6 +83,7 @@ export const CreateContractTemplate = () => { }, documentTerms: contractTerms, } as IAddContractTemplatePayload; + addContractTemplate(contractTemplateData, { onSuccess: () => { //todo @@ -75,15 +95,12 @@ export const CreateContractTemplate = () => { }; const navigateBack = () => { - // todo: this should send us back to the templates tab navigate('/documents/templates', { replace: true }); }; - // TODO: links for - return ( - {t('title')} + {readonly ? t('view_title') : template ? t('edit_title') : t('title')} {/* sub header text */}
@@ -106,7 +123,7 @@ export const CreateContractTemplate = () => {

{t('table_header.title')}

-
+ {!readonly &&
+
}
{/* TABLE BODY */}
- +
diff --git a/frontend/src/routes/Router.tsx b/frontend/src/routes/Router.tsx index 4cc648d9..60f1d752 100644 --- a/frontend/src/routes/Router.tsx +++ b/frontend/src/routes/Router.tsx @@ -97,6 +97,8 @@ const Router = () => { }> } /> + } /> + } /> } /> }> } /> diff --git a/frontend/src/services/documents-templates/documents-templates.api.ts b/frontend/src/services/documents-templates/documents-templates.api.ts index f5d7e350..83093653 100644 --- a/frontend/src/services/documents-templates/documents-templates.api.ts +++ b/frontend/src/services/documents-templates/documents-templates.api.ts @@ -17,7 +17,7 @@ export const getTemplates = async (params: { return API.get('documents/templates', { params }).then((res) => res.data); }; -export const getTemplateById = async (id: string): Promise => { +export const getTemplateById = async (id?: string): Promise => { return API.get(`/documents/templates/${id}`).then((res) => res.data); }; diff --git a/frontend/src/services/documents-templates/documents-templates.service.ts b/frontend/src/services/documents-templates/documents-templates.service.ts index 8250e343..a6a1f02f 100644 --- a/frontend/src/services/documents-templates/documents-templates.service.ts +++ b/frontend/src/services/documents-templates/documents-templates.service.ts @@ -68,7 +68,7 @@ export const useDocumentTemplatesQuery = ({ ); }; -export const useDocumentTemplateByIdQuery = (id: string) => { +export const useDocumentTemplateByIdQuery = (id?: string) => { return useQuery({ queryKey: ['document-template', id], queryFn: () => getTemplateById(id),