-
-
Save julioaze/74319e0265a038ab5ca357625307b778 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { | |
useEffect, | |
useState, | |
useRef, | |
useMemo, | |
useCallback, | |
} from 'react'; | |
import { PropTypes } from 'prop-types'; | |
import { useWindowSize } from '@react-hook/window-size'; | |
import { toast } from 'react-toastify'; | |
import base64 from 'base-64'; | |
import { | |
FaDollarSign, | |
FaSave, | |
FaBroom, | |
FaTimes, | |
FaPlus, | |
FaMinus, | |
} from 'react-icons/fa'; | |
import { format, parseISO } from 'date-fns'; | |
import { Scope } from '@unform/core'; | |
import * as Yup from 'yup'; | |
import { confirmAlert } from 'react-confirm-alert'; | |
import api from '~/services/api'; | |
import history from '~/services/history'; | |
import { useAuth } from '~/hooks/auth'; | |
import { | |
FormContainer, | |
FormLoading, | |
Select, | |
Input, | |
InputMask, | |
} from '~/components/Form'; | |
import { | |
Container, | |
Header, | |
Controls, | |
Content, | |
Company, | |
Periods, | |
FormScroll, | |
} from './styles'; | |
const { v4: uuid } = require('uuid'); | |
const Form = ({ match }) => { | |
const { id } = match.params; | |
const { company, companyUsers } = useAuth(); | |
const formRef = useRef(null); | |
const [, height] = useWindowSize(); | |
const [loading, setLoading] = useState(false); | |
const [clients, setClients] = useState([]); | |
const [periods, setPeriods] = useState([]); | |
const [selectedClient, setSelectedClient] = useState({ | |
value: '', | |
label: 'Selecione uma empresa', | |
}); | |
const [selectedContractType, setSelectedContractType] = useState({ | |
value: '', | |
label: 'Selecione um tipo', | |
}); | |
const [checkStatus, setCheckStatus] = useState(true); | |
useEffect(() => { | |
async function loadProfile() { | |
if (id) { | |
try { | |
setLoading(true); | |
const response = await api.get( | |
`/register/tributaryProfile/${company.id}/${base64.decode(id)}` | |
); | |
const { data } = response; | |
formRef.current.setFieldValue('client', { | |
value: data.client.id, | |
label: data.client.name, | |
}); | |
formRef.current.setFieldValue('contract_type', { | |
value: data.contract_type, | |
label: data.contract_type_label, | |
}); | |
const formattedPeriods = data.periods.map(period => ({ | |
...period, | |
start_period: | |
period.start_period && | |
format(parseISO(period.start_period), 'dd/MM/yyyy'), | |
end_period: | |
period.end_period && | |
format(parseISO(period.end_period), 'dd/MM/yyyy'), | |
})); | |
setPeriods(formattedPeriods); | |
setCheckStatus(data.status); | |
} catch (err) { | |
toast.error(err.response.data.error, { | |
position: toast.POSITION.BOTTOM_RIGHT, | |
}); | |
} finally { | |
setLoading(false); | |
} | |
} | |
const response = await api.get(`/register/client/${company.id}`); | |
const clientsOptions = response.data.docs.map(client => ({ | |
value: client.id, | |
label: client.name, | |
})); | |
setClients(clientsOptions); | |
} | |
loadProfile(); | |
}, [company.id, id]); | |
const handleSubmit = useCallback( | |
async data => { | |
try { | |
const schema = Yup.object().shape({ | |
client: Yup.string().required('A empresa é obrigatória'), | |
contract_type: Yup.string().required( | |
'O tipo de contrato é obrigatório' | |
), | |
periods: Yup.array() | |
.min(1) | |
.of( | |
Yup.object().shape({ | |
taxation_type: Yup.number() | |
.required('A tributação é obrigatória') | |
.nullable(), | |
start_period: Yup.string().required( | |
'A data de início é obrigatória' | |
), | |
end_period: Yup.string().required( | |
'A data de término é obrigatória' | |
), | |
labour: Yup.number(), | |
tax: Yup.number(), | |
accounting: Yup.number(), | |
}) | |
) | |
.required(), | |
}); | |
await schema.validate(data, { | |
abortEarly: false, | |
}); | |
const tributaryProfileData = { | |
client_id: data.client, | |
contract_type: data.contract_type, | |
status: checkStatus, | |
}; | |
if (id) { | |
const decodedId = base64.decode(id); | |
const periodsData = data.periods.map(period => { | |
const startPeriodTimes = period.start_period.split('/'); | |
const endPeriodTimes = period.end_period.split('/'); | |
return { | |
id: Number(period.id), | |
tributary_id: Number(decodedId), | |
taxation_type: period.taxation_type, | |
start_period: new Date( | |
startPeriodTimes[2], | |
startPeriodTimes[1] - 1, | |
startPeriodTimes[0] | |
), | |
end_period: new Date( | |
endPeriodTimes[2], | |
endPeriodTimes[1] - 1, | |
endPeriodTimes[0] | |
), | |
responsible_labour: period.labour, | |
responsible_tax: period.tax, | |
responsible_accounting: period.accounting, | |
}; | |
}); | |
await Promise.all([ | |
api.put( | |
`register/tributaryProfile/${base64.decode(id)}`, | |
tributaryProfileData | |
), | |
api.post('register/tributaryProfilePeriods', periodsData), | |
]); | |
} else { | |
tributaryProfileData.company_id = company.id; | |
const response = await api.post( | |
'register/tributaryProfile', | |
tributaryProfileData | |
); | |
const { id: tributary_id } = response.data; | |
const periodsData = data.periods.map(period => { | |
const startPeriodTimes = period.start_period.split('/'); | |
const endPeriodTimes = period.end_period.split('/'); | |
return { | |
id: Number(period.id), | |
tributary_id, | |
taxation_type: period.taxation_type, | |
start_period: new Date( | |
startPeriodTimes[2], | |
startPeriodTimes[1] - 1, | |
startPeriodTimes[0] | |
), | |
end_period: new Date( | |
endPeriodTimes[2], | |
endPeriodTimes[1] - 1, | |
endPeriodTimes[0] | |
), | |
responsible_labour: period.labour, | |
responsible_tax: period.tax, | |
responsible_accounting: period.accounting, | |
}; | |
}); | |
await api.post('register/tributaryProfilePeriods', periodsData); | |
} | |
formRef.current.setErrors({}); | |
toast.success('Compromisso salvo com sucesso', { | |
position: toast.POSITION.BOTTOM_RIGHT, | |
}); | |
history.push('/tributaryProfile'); | |
} catch (err) { | |
if (err instanceof Yup.ValidationError) { | |
const errorMessages = {}; | |
err.inner.forEach(error => { | |
errorMessages[error.path] = error.message; | |
}); | |
formRef.current.setErrors(errorMessages); | |
} else { | |
toast.error('Falha ao salvar compromisso', { | |
position: toast.POSITION.BOTTOM_RIGHT, | |
}); | |
} | |
} | |
}, | |
[id, checkStatus, company.id] | |
); | |
const contractTypeOptions = useMemo(() => { | |
return [ | |
{ value: 1, label: 'Terceirizado' }, | |
{ value: 2, label: 'Próprio' }, | |
]; | |
}, []); | |
const taxationTypeOptions = useMemo(() => { | |
return [ | |
{ value: 1, label: 'MEI' }, | |
{ value: 2, label: 'Simples Nacional' }, | |
{ value: 3, label: 'Lucro Presumido' }, | |
{ value: 4, label: 'Lucro Real' }, | |
{ value: 5, label: 'Empregador Doméstico' }, | |
{ value: 6, label: 'Empregador PF' }, | |
]; | |
}, []); | |
const usersOptions = useMemo(() => { | |
return companyUsers.map(userItem => { | |
return { value: userItem.id, label: userItem.short_name }; | |
}); | |
}, [companyUsers]); | |
const resetForm = useCallback(() => { | |
formRef.current.reset(); | |
setSelectedClient({ | |
value: '', | |
label: 'Selecione uma empresa', | |
}); | |
setSelectedContractType({ | |
value: '', | |
label: 'Selecione um tipo', | |
}); | |
}, [formRef]); | |
const confirmResetForm = useCallback(() => { | |
confirmAlert({ | |
title: 'Alerta', | |
message: 'Tem certeza? Todos os dados digitados serão perdidos', | |
closeOnEscape: false, | |
closeOnClickOutside: false, | |
buttons: [ | |
{ | |
label: 'Sim', | |
onClick: () => resetForm(), | |
}, | |
{ | |
label: 'Não', | |
}, | |
], | |
}); | |
}, [resetForm]); | |
const handleClose = useCallback(() => { | |
confirmAlert({ | |
title: 'Alerta', | |
message: 'Tem certeza? Todos os dados não salvos serão perdidos', | |
closeOnEscape: false, | |
closeOnClickOutside: false, | |
buttons: [ | |
{ | |
label: 'Sair', | |
onClick: () => history.push('/tributaryProfile'), | |
}, | |
{ | |
label: 'Não', | |
}, | |
], | |
}); | |
}, []); | |
const handleAddNewPeriod = useCallback(() => { | |
const blankPeriod = { | |
id: uuid(), | |
taxation_type: null, | |
start_period: '', | |
end_period: '', | |
labour: '', | |
tax: '', | |
accounting: '', | |
}; | |
setPeriods(oldPeriods => [...oldPeriods, { ...blankPeriod }]); | |
}, []); | |
const handleRemovePeriod = useCallback(periodId => { | |
setPeriods(oldPeriods => oldPeriods.filter(item => item.id !== periodId)); | |
}, []); | |
return ( | |
<Container> | |
<Header> | |
<div> | |
<FaDollarSign size={20} color="#44546a" /> | |
<h1>Perfil Tributário</h1> | |
</div> | |
</Header> | |
<Controls> | |
<button type="submit" form="form"> | |
<FaSave size={15} color="#44546a" /> | |
<span>Salvar</span> | |
</button> | |
<button type="button" onClick={confirmResetForm}> | |
<FaBroom size={15} color="#44546a" /> | |
<span>Limpar</span> | |
</button> | |
<button type="button" onClick={handleClose}> | |
<FaTimes size={15} color="#44546a" /> | |
<span>Fechar</span> | |
</button> | |
</Controls> | |
{loading && <FormLoading className="loading" />} | |
<Content> | |
<FormContainer | |
id="form" | |
ref={formRef} | |
loading={loading} | |
onSubmit={handleSubmit} | |
> | |
<FormScroll height={height}> | |
<Company> | |
<h4>EMPRESA</h4> | |
<section> | |
<Select | |
name="client" | |
className="client" | |
label="Empresa" | |
placeholder="Selecione uma empresa" | |
options={clients} | |
defaultValue={selectedClient} | |
/> | |
<Select | |
name="contract_type" | |
className="contract_type" | |
label="Tipo de Contrato" | |
placeholder="Selecione um tipo" | |
options={contractTypeOptions} | |
defaultValue={selectedContractType} | |
/> | |
<Input | |
type="checkbox" | |
name="status" | |
className="status" | |
label="Ativo" | |
defaultChecked={checkStatus} | |
checkbox | |
onChange={e => setCheckStatus(e.target.checked)} | |
/> | |
</section> | |
</Company> | |
<Periods> | |
<header> | |
<h4>PERÍODOS</h4> | |
<button type="button" onClick={handleAddNewPeriod}> | |
<FaPlus size={10} /> | |
</button> | |
</header> | |
{periods && | |
periods.length > 0 && | |
periods.map((period, index) => ( | |
<Scope path={`periods[${index}]`} key={String(period.id)}> | |
<section> | |
<button | |
type="button" | |
onClick={() => handleRemovePeriod(period.id)} | |
> | |
<FaMinus size={10} /> | |
</button> | |
<Input | |
name="id" | |
value={period.id} | |
type="text" | |
className="hide" | |
readOnly | |
/> | |
<Select | |
name="taxation_type" | |
className="taxation_type" | |
label="Tributação" | |
placeholder="Selecione um tipo" | |
options={taxationTypeOptions} | |
defaultValue={{ | |
value: period.taxation_type, | |
label: period.taxation_type_label, | |
}} | |
/> | |
<InputMask | |
name="start_period" | |
className="start_period" | |
label="Início" | |
mask="99/99/9999" | |
defaultValue={period.start_period} | |
/> | |
<InputMask | |
name="end_period" | |
className="end_period" | |
label="Fim" | |
mask="99/99/9999" | |
defaultValue={period.end_period} | |
/> | |
</section> | |
<section className="responsibles"> | |
<Select | |
name="labour" | |
className="labour" | |
label="Responsável Trabalhista" | |
placeholder="Selecione um tipo" | |
options={usersOptions} | |
defaultValue={{ | |
value: period.labour?.id, | |
label: period.labour?.short_name, | |
}} | |
/> | |
<Select | |
name="tax" | |
className="tax" | |
label="Responsável Tributário" | |
placeholder="Selecione um tipo" | |
options={usersOptions} | |
defaultValue={{ | |
value: period.tax?.id, | |
label: period.tax?.short_name, | |
}} | |
/> | |
<Select | |
name="accounting" | |
className="accounting" | |
label="Responsável Contábil" | |
placeholder="Selecione um tipo" | |
options={usersOptions} | |
defaultValue={{ | |
value: period.accounting?.id, | |
label: period.accounting?.short_name, | |
}} | |
/> | |
</section> | |
</Scope> | |
))} | |
</Periods> | |
</FormScroll> | |
</FormContainer> | |
</Content> | |
</Container> | |
); | |
}; | |
export default Form; | |
Form.propTypes = { | |
match: PropTypes.shape({ | |
params: PropTypes.shape({ | |
id: PropTypes.node, | |
}).isRequired, | |
}).isRequired, | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment