Commit 284bf3e6 authored by Rafael's avatar Rafael

Adiciona telas de dados de proposta.

parent ed044d10
......@@ -90,7 +90,7 @@
"@material-ui/icons": "^4.11.2",
"@material-ui/lab": "4.0.0-alpha.58",
"@material-ui/pickers": "^3.3.10",
"@microcredito/client": "^0.7.14",
"@microcredito/client": "^0.7.16",
"@reduxjs/toolkit": "^1.2.5",
"@types/react-swipeable-views": "^0.13.1",
"@types/react-swipeable-views-utils": "^0.13.3",
......
......@@ -42,3 +42,34 @@ export const creditLinesData: Record<string, CreditLineData> = Array.from(Array(
}),
{}
)
export const destinations = [
{
id: '1',
description: 'Ajustar o fluxo de caixa',
},
{
id: '2',
description: 'Compor caixa para possibilitar vendas a prazo',
},
{
id: '3',
description: 'Compor caixa para possibilitar vendas a prazo',
},
{
id: '4',
description: 'Comprar matérias primas',
},
{
id: '5',
description: 'Expandir seu negócio',
},
{
id: '5',
description: 'Fazer reformas necessárias na empresa',
},
{
id: '6',
description: 'Honrar acertos trabalhistas',
},
]
......@@ -23,6 +23,11 @@ export interface IdDescricao {
descricao: string
}
export interface CodigoDescricao {
codigo: string
descricao: string
}
export interface DocumentType extends Entity {
description: string
}
......
import type { VisitAddress } from '../../../domain/schedule'
import { Address } from '../'
export interface BDAddress extends Omit<VisitAddress, 'id'> {
export interface BDAddress extends Address {
proof: string
referencePoint?: string
}
export interface UpdateBDAddressArgs {
interface InputUpdateBDAddress {
projectId: string
address: BDAddress
}
export interface UpdateBDAddress {
Input: InputUpdateBDAddress
Output: BDAddress
}
import type { Document } from '../../../domain/project'
import { Document } from '../..'
export interface BDIdentification {
cnpj: string
document: Document
document?: Document
openingDate: Date | null
companyName: string
stateRegistration: string
......
......@@ -6,3 +6,13 @@ export interface StockSalesCosts {
salesCommission: string
monthRating: string
}
interface InputUpdateBDStockSalesCosts {
projectId: string
stockSalesCosts: StockSalesCosts
}
export interface UpdateBDStockSalesCosts {
Input: InputUpdateBDStockSalesCosts
Output: StockSalesCosts
}
......@@ -28,6 +28,26 @@ export interface HomeType extends Entity {
description: string
}
export interface ActivitySector extends Entity {
description: string
}
export interface SettledOP extends Entity {
description: string
}
export interface Local extends Entity {
description: string
}
export interface MonthRating extends Entity {
description: string
}
export interface DocumentType extends Entity {
description: string
}
export interface ProposalDataContext {
frameworks: Framework[]
genders: Gender[]
......@@ -36,6 +56,11 @@ export interface ProposalDataContext {
referenceTypes: ReferenceType[]
homeTypes: HomeType[]
deedRecords: DeedRecord[]
activitySectors: ActivitySector[]
settledOPs: SettledOP[]
locals: Local[]
documentTypes: DocumentType[]
monthRatings: MonthRating[]
}
export interface FetchContext {
......
import {
AddBDProductService,
BDAddress,
BDProductService,
BusinessData,
CreateProposal,
Document,
StockSalesCosts,
UpdateBDAddress,
UpdateBDIdentification,
UpdateBDProductService
UpdateBDProductService,
UpdateBDStockSalesCosts
} from '@agiliza/api/domain'
import { extractNumbers } from '@agiliza/utils/extractors'
import {
DadosNegocioEnderecoApiModel,
DadosNegocioEstoqueVendasCustosApiModel,
DadosNegocioIdentificacaoApiModel,
DadosNegocioProdutoServicoApiModel,
DocumentoApiModel
} from '@microcredito/client'
import {
AtualizaProdutoServicoDadosNegocioRequest,
AtualizarEnderecoDadosNegocioRequest,
AtualizarEstoqueVendasCustosDadosNegocioRequest,
AtualizarIdentificacaoDadosNegocioRequest,
CriarProdutoServicoDadosNegocioRequest
} from '@microcredito/client/dist/apis/AgenteApi'
import { CriarPropostaRequest } from '@microcredito/client/dist/apis/ClienteApi'
import { ApiAdapter } from '../shared'
import { AddressApiMapper } from './customerData'
export class DocumentApiMapper implements ApiAdapter<Document, DocumentoApiModel> {
private mapDocumentTypeToApi = (docType: Document['type']): DocumentoApiModel['tipoDocumento'] => ({
......@@ -31,7 +40,7 @@ export class DocumentApiMapper implements ApiAdapter<Document, DocumentoApiModel
public mapDomainToApiModel = (doc: Document): DocumentoApiModel => ({
id: doc.id,
imagem: doc.url,
tipoDocumento: this.mapDocumentTypeToApi(doc.type),
tipoDocumento: doc.type ? this.mapDocumentTypeToApi(doc.type) : { codigo: '', descricao: '' },
informacoesComplementares: doc.extraInformations,
})
}
......@@ -45,7 +54,7 @@ export class BDIdentificationApiMapper implements ApiAdapter<BusinessData['ident
cnpj: extractNumbers(ident?.cnpj),
codigoCNAE: ident?.codeCNAE,
dataAbertura: ident?.openingDate !== null ? ident?.openingDate : undefined,
documento: ident?.document ? this.documentAdapter.mapDomainToApiModel(ident?.document) : undefined,
documento: ident?.document ? this.documentAdapter.mapDomainToApiModel(ident.document) : undefined,
inscricaoComercial: ident?.commercialRegistration,
inscricaoEstadual: ident?.stateRegistration,
inscricaoMunicipal: ident?.cityRegistration,
......@@ -117,3 +126,50 @@ export class BDUpdateProductServiceApiMapper implements ApiAdapter<UpdateBDProdu
dadosNegocioProdutoServicoApiModel: this.bdProductServiceApiMapper.mapDomainToApiModel(input.productService),
})
}
export class BDAddressApiMapper implements ApiAdapter<BDAddress, DadosNegocioEnderecoApiModel> {
private addressApiMapper: AddressApiMapper
constructor() {
this.addressApiMapper = new AddressApiMapper()
}
public mapDomainToApiModel = ({ proof, referencePoint, ...adr }: BDAddress): DadosNegocioEnderecoApiModel => ({
comprovante: proof,
pontoReferencia: referencePoint,
endereco: this.addressApiMapper.mapDomainToApiModel(adr),
})
}
export class BDUpdateAddressApiMapper implements ApiAdapter<UpdateBDAddress['Input'], AtualizarEnderecoDadosNegocioRequest> {
private bdAddressApiMapper: BDAddressApiMapper
constructor() {
this.bdAddressApiMapper = new BDAddressApiMapper()
}
public mapDomainToApiModel = (input: UpdateBDAddress['Input']): AtualizarEnderecoDadosNegocioRequest => ({
projetoId: input.projectId,
dadosNegocioEnderecoApiModel: this.bdAddressApiMapper.mapDomainToApiModel(input.address),
})
}
export class BDStockSalesCostsApiAdapter implements ApiAdapter<StockSalesCosts, DadosNegocioEstoqueVendasCustosApiModel> {
private documentApiAdapter: DocumentApiMapper
constructor() {
this.documentApiAdapter = new DocumentApiMapper()
}
public mapDomainToApiModel = (sSC: StockSalesCosts): DadosNegocioEstoqueVendasCustosApiModel => ({
classificacaoMes: sSC.monthRating,
comissaoVendas: Number(sSC.salesCommission),
documento: sSC.document && this.documentApiAdapter.mapDomainToApiModel(sSC.document),
mesAnoReferencia: sSC.monthYearReference,
})
}
export class BDUpdateStockSalesCosts implements ApiAdapter<UpdateBDStockSalesCosts['Input'], AtualizarEstoqueVendasCustosDadosNegocioRequest> {
private stockSalesCostsApiMapper: BDStockSalesCostsApiAdapter
constructor() {
this.stockSalesCostsApiMapper = new BDStockSalesCostsApiAdapter()
}
public mapDomainToApiModel = (input: UpdateBDStockSalesCosts['Input']): AtualizarEstoqueVendasCustosDadosNegocioRequest => ({
projetoId: input.projectId,
dadosNegocioEstoqueVendasCustosApiModel: this.stockSalesCostsApiMapper.mapDomainToApiModel(input.stockSalesCosts),
})
}
import { BDIdentification, BDProductService, Document } from '@agiliza/api/domain'
import {
BDIdentification,
BDProductService,
Document,
StockSalesCosts,
UpdateBDAddress
} from '@agiliza/api/domain'
import {
DadosNegocioEnderecoApiModel,
DadosNegocioEstoqueVendasCustosApiModel,
DadosNegocioIdentificacaoApiModel,
DadosNegocioProdutoServicoApiModel,
DocumentoApiModel
} from '@microcredito/client'
import { DomainAdapter } from '../shared'
import { AddressMapper } from './customerData'
export class ProjectDocumentMapper implements DomainAdapter<DocumentoApiModel, Document> {
public mapTipoDocumentoApiToDomain = (tipo: DocumentoApiModel['tipoDocumento']): Document['type'] => ({
......@@ -56,3 +65,31 @@ export class BDProductsServicesMapper implements DomainAdapter<DadosNegocioProdu
variableCosts: pS.custosVariaveis ? this.mapPriceAmountToDomain(pS.custosVariaveis) : { amount: '', price: '' },
})
}
export class BDUpdateAddressMapper implements DomainAdapter<DadosNegocioEnderecoApiModel, UpdateBDAddress['Output']> {
private bdAddressMapper: AddressMapper
constructor() {
this.bdAddressMapper = new AddressMapper()
}
public mapApiModelToDomain = (bdAdr: DadosNegocioEnderecoApiModel): UpdateBDAddress['Output'] => ({
proof: bdAdr.comprovante || '',
referencePoint: bdAdr.pontoReferencia,
...this.bdAddressMapper.mapApiModelToDomain(
bdAdr.endereco || { bairro: '', cep: '', estado: '', logradouro: '', municipio: '', numero: '', complemento: '' }
),
})
}
export class BDUpdateStockSalesCostsMapper implements DomainAdapter<DadosNegocioEstoqueVendasCustosApiModel, StockSalesCosts> {
private documentMapper: ProjectDocumentMapper
constructor() {
this.documentMapper = new ProjectDocumentMapper()
}
public mapApiModelToDomain = (sSC: DadosNegocioEstoqueVendasCustosApiModel): StockSalesCosts => ({
document: sSC.documento && this.documentMapper.mapApiModelToDomain(sSC.documento),
monthRating: sSC.classificacaoMes || '',
monthYearReference: sSC.mesAnoReferencia || '',
salesCommission: sSC.comissaoVendas?.toString() || '',
})
}
import { ProposalDataContext } from '@agiliza/api/domain'
import {
ClassificacaoMesApiModel,
EnquadramentoApiModel,
EscolaridadeApiModel,
EstadoCivilApiModel,
GeneroApiModel,
LocalApiModel,
OPLiquidadaApiModel,
RegistroEscrituraApiModel,
SetorAtividadeApiModel,
TipoDocumentoApiModel,
TipoMoradiaApiModel,
TipoReferenciaApiModel
} from '@microcredito/client'
import { DomainAdapter, IdDescriptionMapper } from '../shared'
import { CodeDescriptionMapper, DomainAdapter, IdDescriptionMapper } from '../shared'
export interface DadosPropostaContexto {
enquadramentos: EnquadramentoApiModel[]
......@@ -19,13 +24,20 @@ export interface DadosPropostaContexto {
tiposReferencia: TipoReferenciaApiModel[]
registrosEscritura: RegistroEscrituraApiModel[]
tiposMoradia: TipoMoradiaApiModel[]
setoresAtividade: SetorAtividadeApiModel[]
opsLiquidadas: OPLiquidadaApiModel[]
locais: LocalApiModel[]
tiposDocumento: TipoDocumentoApiModel[]
classificacoesMes: ClassificacaoMesApiModel[]
}
export class ContextMapper implements DomainAdapter<DadosPropostaContexto, ProposalDataContext> {
private idDescriptionMapper: IdDescriptionMapper
private codeDescriptionMapper: CodeDescriptionMapper
constructor() {
this.idDescriptionMapper = new IdDescriptionMapper()
this.codeDescriptionMapper = new CodeDescriptionMapper()
}
public mapApiModelToDomain = (dP: DadosPropostaContexto): ProposalDataContext => ({
frameworks: dP.enquadramentos.map(this.idDescriptionMapper.mapApiModelToDomain),
......@@ -35,5 +47,10 @@ export class ContextMapper implements DomainAdapter<DadosPropostaContexto, Propo
referenceTypes: dP.tiposReferencia.map(this.idDescriptionMapper.mapApiModelToDomain),
homeTypes: dP.tiposMoradia.map(this.idDescriptionMapper.mapApiModelToDomain),
deedRecords: dP.registrosEscritura.map(this.idDescriptionMapper.mapApiModelToDomain),
activitySectors: dP.setoresAtividade.map(this.idDescriptionMapper.mapApiModelToDomain),
settledOPs: dP.opsLiquidadas.map(this.idDescriptionMapper.mapApiModelToDomain),
locals: dP.locais.map(this.idDescriptionMapper.mapApiModelToDomain),
documentTypes: dP.tiposDocumento.map(this.codeDescriptionMapper.mapApiModelToDomain),
monthRatings: dP.classificacoesMes.map(this.idDescriptionMapper.mapApiModelToDomain),
})
}
import { IdDescricao } from '@agiliza/api/domain'
import { CodigoDescricao, IdDescricao } from '@agiliza/api/domain'
import { Entity } from '@agiliza/utils/method'
export interface DomainAdapter<A, B> {
......@@ -15,3 +15,10 @@ export class IdDescriptionMapper implements DomainAdapter<IdDescricao, IdDescrip
description: iD.descricao || '',
})
}
export class CodeDescriptionMapper implements DomainAdapter<CodigoDescricao, IdDescription> {
public mapApiModelToDomain = (iD: Partial<CodigoDescricao>): IdDescription => ({
id: iD.codigo || '',
description: iD.descricao || '',
})
}
import {
AddBDProductService,
GetBDProductsServices,
UpdateBDProductService
UpdateBDAddress,
UpdateBDIdentification,
UpdateBDProductService,
UpdateBDStockSalesCosts
} from '@agiliza/api/domain'
import { ErrorMappers } from '@agiliza/api/mappers'
import { ClienteApi, Configuration } from '@microcredito/client'
......@@ -13,6 +16,9 @@ export interface PDBusinessDataRepository {
getProductsServices(input: GetBDProductsServices['Input']): Promise<GetBDProductsServices['Output']>
addProductService(input: AddBDProductService['Input']): Promise<AddBDProductService['Output']>
updateProductService(input: UpdateBDProductService['Input']): Promise<UpdateBDProductService['Output']>
updateIdentification(input: UpdateBDIdentification['Input']): Promise<UpdateBDIdentification['Output']>
updateAddress(input: UpdateBDAddress['Input']): Promise<UpdateBDAddress['Output']>
updateStockSalesCosts(input: UpdateBDStockSalesCosts['Input']): Promise<UpdateBDStockSalesCosts['Output']>
}
export class PDBusinessDataRepositoryImpl implements PDBusinessDataRepository {
......@@ -21,12 +27,25 @@ export class PDBusinessDataRepositoryImpl implements PDBusinessDataRepository {
private bdGetServicesProductsMapper: ProposalDataMappers.BDProductsServicesMapper
private bdAddProductServiceApiMapper: ProposalDataApiMappers.BDAddProductServiceApiMapper
private bdUpdateProductServiceApiMapper: ProposalDataApiMappers.BDUpdateProductServiceApiMapper
private bdUpdateAddressApiMapper: ProposalDataApiMappers.BDUpdateAddressApiMapper
private bdUpdateIdentificationApiMapper: ProposalDataApiMappers.BDUpdateIdentificationApiMapper
private bdUpdateAddressMapper: ProposalDataMappers.BDUpdateAddressMapper
private bdIdentificationMapper: ProposalDataMappers.BDIdentificationMapper
private bdUpdateStockSalesCostsApiMapper: ProposalDataApiMappers.BDUpdateStockSalesCosts
private bdUpdateStockSalesCostsMapper: ProposalDataMappers.BDUpdateStockSalesCostsMapper
constructor(userAgent: string, accessToken: string) {
this.errorAdapter = new ErrorMappers.ResponseErrorAdapter()
this.bdGetServicesProductsMapper = new ProposalDataMappers.BDProductsServicesMapper()
this.bdAddProductServiceApiMapper = new ProposalDataApiMappers.BDAddProductServiceApiMapper()
this.bdUpdateProductServiceApiMapper = new ProposalDataApiMappers.BDUpdateProductServiceApiMapper()
this.bdUpdateAddressApiMapper = new ProposalDataApiMappers.BDUpdateAddressApiMapper()
this.bdUpdateAddressMapper = new ProposalDataMappers.BDUpdateAddressMapper()
this.bdUpdateIdentificationApiMapper = new ProposalDataApiMappers.BDUpdateIdentificationApiMapper()
this.bdIdentificationMapper = new ProposalDataMappers.BDIdentificationMapper()
this.bdUpdateStockSalesCostsApiMapper = new ProposalDataApiMappers.BDUpdateStockSalesCosts()
this.bdUpdateStockSalesCostsMapper = new ProposalDataMappers.BDUpdateStockSalesCostsMapper()
this.api = new ClienteApi(
new Configuration({
basePath: API_URL,
......@@ -67,6 +86,37 @@ export class PDBusinessDataRepositoryImpl implements PDBusinessDataRepository {
throw result
}
}
public updateIdentification = async (input: UpdateBDIdentification['Input']): Promise<UpdateBDIdentification['Output']> => {
try {
console.log(this.bdUpdateIdentificationApiMapper.mapDomainToApiModel(input))
const response = await this.api.atualizarIdentificacaoDadosNegocio(this.bdUpdateIdentificationApiMapper.mapDomainToApiModel(input))
return this.bdIdentificationMapper.mapApiModelToDomain(response)
} catch (e) {
const result = await this.errorAdapter.mapApiModelToDomain(e)
throw result
}
}
public updateAddress = async (input: UpdateBDAddress['Input']): Promise<UpdateBDAddress['Output']> => {
try {
const response = await this.api.atualizarEnderecoDadosNegocio(this.bdUpdateAddressApiMapper.mapDomainToApiModel(input))
return this.bdUpdateAddressMapper.mapApiModelToDomain(response)
} catch (e) {
const result = await this.errorAdapter.mapApiModelToDomain(e)
throw result
}
}
public updateStockSalesCosts = async (input: UpdateBDStockSalesCosts['Input']): Promise<UpdateBDStockSalesCosts['Output']> => {
try {
const response = await this.api.atualizarEstoqueVendasCustosDadosNegocio(this.bdUpdateStockSalesCostsApiMapper.mapDomainToApiModel(input))
return this.bdUpdateStockSalesCostsMapper.mapApiModelToDomain(response)
} catch (e) {
const result = await this.errorAdapter.mapApiModelToDomain(e)
throw result
}
}
}
export class PDBusinessDataRepositoryImplFactory {
......
......@@ -39,6 +39,11 @@ export class ProposalDataContextRepositoryImpl implements ProposalDataContextRep
tiposReferencia: await this.api.obterTiposReferencia(),
tiposMoradia: await this.api.obterTiposMoradia(),
registrosEscritura: await this.api.obterRegistrosEscritura(),
setoresAtividade: await this.api.obterSetoresAtividade(),
opsLiquidadas: await this.api.obterOpsLiquidadas(),
locais: await this.api.obterLocais(),
tiposDocumento: await this.api.obterTiposDocumento(),
classificacoesMes: await this.api.obterClassificacoesMes(),
}
return this.contextMapper.mapApiModelToDomain(contexto)
} catch (e) {
......
......@@ -22,7 +22,7 @@ const ImageUpload = (props: Props) => {
const { classes, className, buttonClassName, image, onChangeImage, label, imageStyle } = props
return (
<div className={className}>
<div className={cn(className, classes.container)}>
<Button variant="text" component="label" className={cn(classes.photoBtn, buttonClassName)} classes={{ label: classes.photoLabelBtn }}>
{image ? (
<div className={classes.card} style={imageStyle}>
......
......@@ -4,6 +4,7 @@ import { createStyles } from '@material-ui/styles'
// eslint-disable-next-line
export default (theme: Theme) => {
return createStyles({
container: { width: '100%', textAlign: 'center', marginTop: theme.spacing(1), marginBottom: theme.spacing(1) },
photoBtn: { width: '100%' },
photoLabelBtn: { display: 'flex', flexDirection: 'column', height: '280px', alignItems: 'center', flexGrow: 1 },
card: { width: '100%', maxWidth: '100%', height: '100%', textAlign: 'center' },
......
......@@ -44,7 +44,7 @@ const Address = (props: Props) => {
<>
<TextField variant="outlined" label="CEP" value={maskCEP(cep)} onChange={handleChange('cep')} inputProps={{ maxLength: 9 }} />
<TextField variant="outlined" label="Rua / Avenida" value={street} onChange={handleChange('street')} />
<TextField variant="outlined" label="Número" value={number} onChange={handleChange('number')} />
<TextField variant="outlined" label="Número" type="tel" value={number} onChange={handleChange('number')} />
<TextField variant="outlined" label="Complemento" value={complement} onChange={handleChange('complement')} />
<SelectField
id="state-select"
......
import React from 'react'
import { Document, ProposalDataContext } from '@agiliza/api/domain'
import ImageUpload from '@agiliza/components/organisms/ImageUpload'
import { SelectField } from '@curio/components'
interface Props {
onChangeImage: React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>['onChange']
onChangeDocumentType: (vl: string) => void
context: ProposalDataContext
document?: Document
}
const Document = (props: Props) => {
const { context, document, onChangeDocumentType, onChangeImage } = props
return (
<>
<SelectField
id="document-type-select-field"
label="Tipo de documento"
value={document?.type.id || ''}
onChange={onChangeDocumentType}
items={context.documentTypes.map((dT) => ({ label: dT.description, value: dT.id }))}
variant="outlined"
shrink={false}
/>
<ImageUpload label="Foto" image={document?.url || ''} onChangeImage={onChangeImage} />
</>
)
}
export default Document
export { default } from './Document'
export * from './Document'
import React from 'react'
import { City, State } from '@agiliza/api/domain/authentication'
import { getErrorProps, useErrorValidator } from '@agiliza/utils/hooks/errorValidation'
import { useErrorValidator } from '@agiliza/utils/hooks/errorValidation'
import { ActionType } from '@agiliza/utils/hooks/state'
import { maskCPFCNPJ, maskPhone } from '@agiliza/utils/masks'
import { maskPhone } from '@agiliza/utils/masks'
import CPFCNPJField from '@agiliza/views/ProposalData/components/atoms/CPFCNPJField'
import { TextField, TextFieldProps } from '@material-ui/core'
import { withStyles, WithStyles } from '@material-ui/core/styles'
......@@ -25,7 +26,7 @@ const FirstAccess = (props: Props) => {
const { cpf, name, email, phone, ...addressState } = state
const { errorState, actions: errorActions } = useErrorValidator(initState)
const { actions: errorActions } = useErrorValidator(initState)
const handleChange =
(key: keyof FirstAccessState): TextFieldProps['onChange'] =>
......@@ -39,15 +40,7 @@ const FirstAccess = (props: Props) => {
return (
<form className={classes.form}>
<TextField
variant="outlined"
label="CPF"
value={maskCPFCNPJ(cpf)}
onChange={handleChange('cpf')}
inputProps={{ maxLength: 14 }}
disabled
{...getErrorProps(errorState.cpf)}
/>
<CPFCNPJField value={cpf} onChange={handleChange('cpf')} onlyCPF disabled />
<TextField variant="outlined" label="Nome" value={name} onChange={handleChange('name')} />
<TextField variant="outlined" label="Email" value={email} onChange={handleChange('email')} />
<TextField variant="outlined" label="Telefone" value={maskPhone(phone)} onChange={handleChange('phone')} inputProps={{ maxLength: 15 }} />
......
......@@ -4,3 +4,7 @@ export * from './Login'
export * from './Address'
export * from './FirstAccess'
export * from './RGTemplate'
import DocumentTemplate from './Document'
export { DocumentTemplate }
......@@ -17,6 +17,11 @@ export const initialState: Store = {
referenceTypes: { byId: {}, allIds: [] },
homeTypes: { byId: {}, allIds: [] },
deedRecords: { byId: {}, allIds: [] },
activitySectors: { byId: {}, allIds: [] },
settledOPs: { byId: {}, allIds: [] },
locals: { byId: {}, allIds: [] },
documentTypes: { byId: {}, allIds: [] },
monthRatings: { byId: {}, allIds: [] },
}
export default createSlice({
......
......@@ -44,6 +44,7 @@ export default createSlice({
state.proposalId = action.payload
},
[customerDataTypes.addIndentification.fulfilled]: (state, action: PayloadAction<Identification>) => {
console.log(action)
state.personId = action.payload.id
},
[customerDataTypes.getReferences.fulfilled]: (state, action: PayloadAction<GetCDReferences['Output']>) => {
......
......@@ -15,6 +15,11 @@ const contextSchemas: Record<keyof ProposalDataContext, any> = {
referenceTypes: new schema.Array(new schema.Entity('referenceTypes')),
homeTypes: new schema.Array(new schema.Entity('homeTypes')),
deedRecords: new schema.Array(new schema.Entity('deedRecords')),
activitySectors: new schema.Array(new schema.Entity('activitySectors')),
settledOPs: new schema.Array(new schema.Entity('settledOPs')),
locals: new schema.Array(new schema.Entity('locals')),
documentTypes: new schema.Array(new schema.Entity('documentTypes')),
monthRatings: new schema.Array(new schema.Entity('monthRatings')),
}
export const normalizeContext = (context: ProposalDataContext) => {
......
import {
AddBDProductService,
GetBDProductsServices,
UpdateBDProductService
UpdateBDAddress,
UpdateBDIdentification,
UpdateBDProductService,
UpdateBDStockSalesCosts
} from '@agiliza/api/domain'
import { PDBusinessDataRepositoryImplFactory } from '@agiliza/api/useCases'
import { appPlatform } from '@agiliza/constants/platform'
......@@ -54,6 +57,39 @@ export const actions = {
return thunkApi.rejectWithValue(e)
}
}),
updateIdentification: createAsyncThunk(`${prefix}/updateIdentification`, async (input: WithSuccess<UpdateBDIdentification['Input']>, thunkApi) => {
const useCase = PDBusinessDataRepositoryImplFactory.create(appPlatform)
try {
const response = await useCase.updateIdentification(input)
input.onSuccess && input.onSuccess()
return response
} catch (e) {
return thunkApi.rejectWithValue(e)
}
}),
updateAddress: createAsyncThunk(`${prefix}/updateAddress`, async (input: WithSuccess<UpdateBDAddress['Input']>, thunkApi) => {
const useCase = PDBusinessDataRepositoryImplFactory.create(appPlatform)
try {
const response = await useCase.updateAddress(input)
input.onSuccess && input.onSuccess()
return response
} catch (e) {
return thunkApi.rejectWithValue(e)
}
}),
updateStockSalesCosts: createAsyncThunk(
`${prefix}/updateStockSalesCosts`,
async (input: WithSuccess<UpdateBDStockSalesCosts['Input']>, thunkApi) => {
const useCase = PDBusinessDataRepositoryImplFactory.create(appPlatform)
try {
const response = await useCase.updateStockSalesCosts(input)
input.onSuccess && input.onSuccess()
return response
} catch (e) {
return thunkApi.rejectWithValue(e)
}
}
),
} as const
export const types = getTypesThunkActions(actions)
......
......@@ -11,7 +11,7 @@ export type Formatter = (txt: string) => string
export type FormatterState<S> = { [k in keyof S]?: Formatter | Formatter[] }
export type UpdatePayload<S> = {
[k in keyof S]: S[k]
[k in keyof S]: Partial<S[k]>
}
type FormState<S> = {
......
......@@ -23,6 +23,19 @@ export const maskCPFCNPJ = (str?: string) => {
return filteredString
}
export const maskCNPJ = (text: string) => {
if (!text) return ''
const filteredText = extractNumbers(text)
const length = filteredText.length
if (length < 3) return filteredText
if (length < 6) return filteredText.replace(/(\d\d)/, '$1.')
if (length < 9) return filteredText.replace(/(\d\d)(\d\d\d)/, '$1.$2.')
if (length < 13) return filteredText.replace(/(\d\d)(\d\d\d)(\d\d\d)/, '$1.$2.$3/')
if (length < 15) return filteredText.replace(/(\d\d)(\d\d\d)(\d\d\d)(\d\d\d\d)/, '$1.$2.$3/$4-')
return text
}
export const maskCEP = (str?: string) => {
if (!str) return ''
const filteredString = extractNumbers(str)
......
import React from 'react'
import { maskCNPJ, maskCPFCNPJ } from '@agiliza/utils/masks'
import { TextField, TextFieldProps } from '@material-ui/core'
type ExtendedProps = Record<string, unknown> & Pick<TextFieldProps, 'value' | 'onChange' | 'disabled'>
interface Props extends ExtendedProps {
onlyCPF?: boolean
onlyCPNJ?: boolean
label?: string
}
const CPFCNPJField = (props: Props) => {
const { onlyCPF, onlyCPNJ, label = 'CPF', value, ...textFieldProps } = props
const getLabel = () => (onlyCPF ? 'CPF' : onlyCPNJ ? 'CNPJ' : 'CPF / CNPJ')
return (
<TextField
type="tel"
variant="outlined"
inputProps={{ maxLength: onlyCPF ? 14 : 18 }}
label={getLabel()}
value={onlyCPF ? maskCPFCNPJ((value as string) || '') : maskCNPJ((value as string) || '')}
{...textFieldProps}
/>
)
}
export default CPFCNPJField
export { default } from './CPFCNPJField'
export * from './CPFCNPJField'
import React from 'react'
import { useFormState } from '@agiliza/utils/hooks/state'
import { ActionType } from '@agiliza/utils/hooks/state'
import { withStyles, WithStyles } from '@material-ui/core/styles'
import { connected, ConnectedProps } from './connect'
import Form from './Form'
import { initialState } from './state'
import { BDAddressState } from './state'
import styles from './styles'
type ExtendedProps = WithStyles<typeof styles>
type ExtendedProps = WithStyles<typeof styles> & ConnectedProps
interface Props extends ExtendedProps {}
interface Props extends ExtendedProps {
state: BDAddressState
actions: ActionType<BDAddressState>
}
const Address = (props: Props) => {
const { classes } = props
const formState = useFormState('addressData', initialState)
const { classes, context, state, actions } = props
return (
<div className={classes.contentContainer}>
<div className={classes.content}>
<Form {...formState} />
<Form state={state} actions={actions} context={context} />
</div>
</div>
)
}
export default withStyles(styles)(Address)
export default connected(withStyles(styles)(Address))
import React from 'react'
import { AuthenticationContext } from '@agiliza/api/domain'
import ImageUpload from '@agiliza/components/organisms/ImageUpload'
import AddressTemplate from '@agiliza/components/templates/Address'
import { ActionType } from '@agiliza/utils/hooks/state'
import Address from '@agiliza/views/ProposalData/components/templates/Address'
import { getBase64FromFile } from '@agiliza/utils/method'
import { TextField, TextFieldProps } from '@material-ui/core'
import { withStyles, WithStyles } from '@material-ui/core/styles'
......@@ -13,12 +16,13 @@ type ExtendedProps = WithStyles<typeof styles>
interface Props extends ExtendedProps {
state: BDAddressState
actions: ActionType<BDAddressState>
context: AuthenticationContext
}
const Form = (props: Props) => {
const { classes, state: _state, actions } = props
const { classes, state: _state, actions, context } = props
const { cep, number, street, city, complement, district, state, referencePoint } = _state
const { cep, number, street, city, complement, district, state, referencePoint, proof } = _state
const handleChangeText =
(key: keyof BDAddressState): TextFieldProps['onChange'] =>
......@@ -26,9 +30,23 @@ const Form = (props: Props) => {
actions.update({ [key]: evt.target.value })
}
const handleChangeProof: React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>['onChange'] = async (evt) => {
const file = evt.target.files && evt.target.files[0]
if (file) {
const b64: string = await getBase64FromFile(file)
actions.update({ proof: b64 })
}
}
return (
<form className={classes.form}>
<Address state={{ cep, number, street, city, complement, district, state }} onChange={(addrs) => actions.update(addrs)} />
<ImageUpload label="Comprovante de residência" image={proof} onChangeImage={handleChangeProof} />
<AddressTemplate
states={context.states}
cities={context.cities}
state={{ cep, number, street, city, complement, district, state }}
onChange={(addrs) => actions.update(addrs)}
/>
<TextField variant="outlined" label="Ponto de referência" value={referencePoint} onChange={handleChangeText('referencePoint')} />
</form>
)
......
import { connect } from 'react-redux'
import { AuthenticationContext } from '@agiliza/api/domain'
import { StoreState } from '@agiliza/redux'
import * as entAuthentication from '@agiliza/redux/entities/authentication'
export interface ConnectedProps {
context: AuthenticationContext
}
type StateProps = Pick<ConnectedProps, 'context'>
// type DispatchProps = Pick<ConnectedProps, 'getContext'>
const mapStateToProps = (state: StoreState): StateProps => ({
context: entAuthentication.selectors.getContextEntities(state.entities.authentication),
})
// const mapDispatchToProps = (dispatch: Dispatch): DispatchProps =>
// bindActionCreators(
// {
// },
// dispatch
// )
export const connected = connect(mapStateToProps)
export { default } from './Address'
export * from './Address'
export * from './state'
import { file } from '@agiliza/__mocks__/files'
import { BDAddress } from '@agiliza/api/domain'
type ExtendedState = BDAddress
export interface BDAddressState extends ExtendedState {}
export const initialState: BDAddressState = {
export const initialState: BDAddressState =
process.env.NODE_ENV === 'development'
? {
id: '',
proof: file,
cep: '29100100',
city: '16',
complement: 'TEST',
district: 'TEST',
number: '123',
state: '1',
street: 'TEST',
referencePoint: 'TEST',
}
: {
id: '',
proof: '',
cep: '',
city: '',
......@@ -14,4 +30,4 @@ export const initialState: BDAddressState = {
state: '',
street: '',
referencePoint: '',
}
}
import React from 'react'
import { ProposalDataContext } from '@agiliza/api/domain'
import DocumentTemplate from '@agiliza/components/templates/Document'
import { ActionType } from '@agiliza/utils/hooks/state'
import { maskCPFCNPJ } from '@agiliza/utils/masks'
import { DatePicker } from '@curio/components'
import { getBase64FromFile } from '@agiliza/utils/method'
import CPFCNPJField from '@agiliza/views/ProposalData/components/atoms/CPFCNPJField'
import { DatePicker, SelectField, SelectFieldProps } from '@curio/components'
import { TextField, TextFieldProps } from '@material-ui/core'
import { withStyles, WithStyles } from '@material-ui/core/styles'
......@@ -14,12 +17,26 @@ type ExtendedProps = WithStyles<typeof styles>
interface Props extends ExtendedProps {
state: BDIdentificationState
actions: ActionType<BDIdentificationState>
context: ProposalDataContext
}
const Form = (props: Props) => {
const { classes, state, actions } = props
const { classes, state, actions, context } = props
const { cnpj, openingDate } = state
const {
cnpj,
openingDate,
stateRegistration,
cityRegistration,
fantasyName,
commercialRegistration,
activitySector,
settledOP,
local,
codeCNAE,
mainActivity,
document,
} = state
const handleChangeText =
(key: keyof BDIdentificationState): TextFieldProps['onChange'] =>
......@@ -31,24 +48,75 @@ const Form = (props: Props) => {
actions.update({ [type]: date })
}
const handleChangeSelect =
(key: keyof BDIdentificationState): SelectFieldProps['onChange'] =>
(vl) => {
actions.update({ [key]: vl })
}
const handleChangeProof: React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>['onChange'] = async (evt) => {
const file = evt.target.files && evt.target.files[0]
if (file) {
const b64: string = await getBase64FromFile(file)
actions.update({ document: { url: b64 } })
}
}
const handleChangeDocumentType = (value: string) => {
const documentType = context.documentTypes.find((dT) => dT.id === value)
if (documentType) actions.update({ document: { type: documentType } })
}
return (
<form className={classes.form}>
<TextField
variant="outlined"
type="tel"
label="CNPJ"
value={maskCPFCNPJ(cnpj)}
onChange={handleChangeText('cnpj')}
inputProps={{ maxLength: 18 }}
/>
<DocumentTemplate document={document} context={context} onChangeImage={handleChangeProof} onChangeDocumentType={handleChangeDocumentType} />
<CPFCNPJField value={cnpj} onChange={handleChangeText('cnpj')} onlyCPNJ />
<DatePicker
id="admission-date"
label="Data de admissão"
label="Data da abertura"
value={openingDate}
onChange={handleChangeDate('openingDate')}
format="dd/MM/yyyy"
className={classes.datePicker}
/>
<TextField variant="outlined" label="Inscrição estadual" value={stateRegistration} onChange={handleChangeText('stateRegistration')} />
<TextField variant="outlined" label="Inscrição municipal" value={cityRegistration} onChange={handleChangeText('cityRegistration')} />
<TextField variant="outlined" label="Nome fantasia" value={fantasyName} onChange={handleChangeText('fantasyName')} />
<TextField
variant="outlined"
label="Inscrição comercial"
value={commercialRegistration}
onChange={handleChangeText('commercialRegistration')}
/>
<SelectField
id="activity-sector-select-field"
label="Setor de atividade"
value={activitySector}
onChange={handleChangeSelect('activitySector')}
items={context.activitySectors.map((aS) => ({ label: aS.description, value: aS.id }))}
variant="outlined"
shrink={false}
/>
<SelectField
id="settled-op-select-field"
label="Op. liquidadas (NC)"
value={settledOP}
onChange={handleChangeSelect('settledOP')}
items={context.settledOPs.map((sOP) => ({ label: sOP.description, value: sOP.id }))}
variant="outlined"
shrink={false}
/>
<SelectField
id="settled-op-select-field"
label="Local"
value={local}
onChange={handleChangeSelect('local')}
items={context.locals.map((aS) => ({ label: aS.description, value: aS.id }))}
variant="outlined"
shrink={false}
/>
<TextField variant="outlined" type="tel" label="Código CNAE" value={codeCNAE} onChange={handleChangeText('codeCNAE')} />
<TextField variant="outlined" label="Atividade principal" value={mainActivity} onChange={handleChangeText('mainActivity')} />
</form>
)
}
......
import React from 'react'
import { useFormState } from '@agiliza/utils/hooks/state'
import { ActionType } from '@agiliza/utils/hooks/state'
import { withStyles, WithStyles } from '@material-ui/core/styles'
import { connected, ConnectedProps } from './connect'
import Form from './Form'
import { initialState } from './state'
import { BDIdentificationState } from './state'
import styles from './styles'
type ExtendedProps = WithStyles<typeof styles>
type ExtendedProps = WithStyles<typeof styles> & ConnectedProps
interface Props extends ExtendedProps {}
interface Props extends ExtendedProps {
state: BDIdentificationState
actions: ActionType<BDIdentificationState>
}
const Identification = (props: Props) => {
const { classes } = props
const formState = useFormState('identificationForm', initialState)
const { classes, context, state, actions } = props
return (
<div className={classes.contentContainer}>
<div className={classes.content}>
<Form {...formState} />
<Form state={state} actions={actions} context={context} />
</div>
</div>
)
}
export default withStyles(styles)(Identification)
export default connected(withStyles(styles)(Identification))
import { connect } from 'react-redux'
import { ProposalDataContext } from '@agiliza/api/domain'
import { StoreState } from '@agiliza/redux'
import * as entProposalDataContext from '@agiliza/redux/entities/proposalData/context'
export interface ConnectedProps {
context: ProposalDataContext
}
type StateProps = Pick<ConnectedProps, 'context'>
// type DispatchProps = Pick<ConnectedProps, 'addIndentification'>
const mapStateToProps = (state: StoreState): StateProps => ({
context: entProposalDataContext.selectors.getContext(state.entities.proposalData.context),
})
// const mapDispatchToProps = (dispatch: Dispatch): DispatchProps =>
// bindActionCreators(
// {
// },
// dispatch
// )
export const connected = connect(mapStateToProps)
export { default } from './Identification'
export * from './Identification'
export * from './state'
import { file } from '@agiliza/__mocks__/files'
import { BDIdentification } from '@agiliza/api/domain'
type ExtendedState = BDIdentification
export interface BDIdentificationState extends ExtendedState {
mainActivity: ''
mainActivity: string
}
export const initialState: BDIdentificationState = {
export const initialState: BDIdentificationState =
process.env.NODE_ENV === 'development'
? {
cnpj: '81.867.778/0001-02',
activitySector: '1',
cityRegistration: '123456',
codeCNAE: '123456',
companyName: 'TEST',
document: { extraInformations: 'TEST', id: '1', url: file, type: { id: '1', description: '' } },
fantasyName: 'TEST',
local: '1',
settledOP: '1',
stateRegistration: '123456',
commercialRegistration: '123456',
mainActivity: 'TEST',
openingDate: new Date('2010-10-10'),
}
: {
cnpj: '',
activitySector: '',
cityRegistration: '',
codeCNAE: '',
companyName: '',
document: { extraInformations: '', id: '', url: undefined, type: { id: undefined, description: '' } },
document: { extraInformations: '', id: '', url: '', type: { id: '', description: '' } },
fantasyName: '',
local: '',
settledOP: '',
......@@ -20,4 +38,4 @@ export const initialState: BDIdentificationState = {
commercialRegistration: '',
mainActivity: '',
openingDate: null,
}
}
import React, { useEffect } from 'react'
import { BDProductService } from '@agiliza/api/domain'
import ButtonWithProgress from '@agiliza/components/atoms/ButtonWithProgress'
import { useFormState } from '@agiliza/utils/hooks/state'
import {
Button,
......@@ -22,10 +23,11 @@ interface Props extends ExtendedProps {
onClose: () => void
productService?: BDProductService
onSave(rfc: BDProductService, add: boolean): () => void
fetching: boolean
}
const Dialog = (props: Props) => {
const { classes, open, onClose, onSave, productService } = props
const { classes, fetching, open, onClose, onSave, productService } = props
const formState = useFormState('VehicleForm', initialState)
......@@ -48,7 +50,9 @@ const Dialog = (props: Props) => {
</DialogContent>
<DialogActions>
<Button onClick={onClose}>Cancelar</Button>
<Button onClick={onSave(mapStateToProductService(), !productService)}>Salvar</Button>
<ButtonWithProgress variant="text" fetching={fetching} onClick={onSave(mapStateToProductService(), !productService)}>
Salvar
</ButtonWithProgress>
</DialogActions>
</MUIDialog>
)
......
......@@ -19,6 +19,5 @@ export default (theme: Theme) => {
},
switchCardPhotoContainer: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-evenly' },
datePicker: { marginBottom: '0px !important' },
label: { marginBottom: theme.spacing(2) },
})
}
......@@ -20,25 +20,33 @@ interface Props extends ExtendedProps {
}
const ProductsServices = (props: Props) => {
const { classes, projectId, productsServices } = props
const { classes, fetching, projectId, productsServices } = props
const [selectedProductService, setSelectedProductService] = useState<BDProductService | undefined>()
const [open, setOpen] = useState(false)
const handleClickListItem = (vehicle: BDProductService) => () => {
setSelectedProductService(vehicle)
const handleClickListItem = (productService: BDProductService) => () => {
setOpen(true)
setSelectedProductService(productService)
}
const handleClickAdd = () => {
setOpen(true)
setSelectedProductService(undefined)
}
const handleClickClose = () => {
setOpen(false)
setSelectedProductService(undefined)
}
const handleSave = (productService: BDProductService, add: boolean) => () => {
if (add) props.addProductService({ projectId, productService, onSuccess: () => setOpen(false) })
else props.updateProductService({ projectId, productServiceId: productService.id, productService, onSuccess: () => setOpen(false) })
const onSuccess = () => {
setOpen(false)
setSelectedProductService(productService)
}
if (add) props.addProductService({ projectId, productService, onSuccess })
else props.updateProductService({ projectId, productServiceId: productService.id, productService, onSuccess })
}
return (
......@@ -62,7 +70,7 @@ const ProductsServices = (props: Props) => {
<Avatar className={classes.avatarBtnContainer} onClick={handleClickAdd}>
<AddIcon />
</Avatar>
<Dialog open={open} onClose={() => setOpen(false)} productService={selectedProductService} onSave={handleSave} />
<Dialog fetching={fetching} open={open} onClose={handleClickClose} productService={selectedProductService} onSave={handleSave} />
</>
)
}
......
......@@ -6,7 +6,6 @@ import { StoreState } from '@agiliza/redux'
import * as entProposalDataContext from '@agiliza/redux/entities/proposalData/context'
import * as entProposalData from '@agiliza/redux/entities/proposalData/proposal'
import * as ucProposalData from '@agiliza/redux/useCases/proposalData/businessData'
import * as ucProposalDataContext from '@agiliza/redux/useCases/proposalData/context'
export interface ConnectedProps {
fetching: boolean
......@@ -21,7 +20,7 @@ type StateProps = Pick<ConnectedProps, 'fetching' | 'context' | 'productsService
type DispatchProps = Pick<ConnectedProps, 'getProductsServices' | 'addProductService' | 'updateProductService'>
const mapStateToProps = (state: StoreState): StateProps => ({
fetching: ucProposalDataContext.selectors.isFetching(state.ui.login),
fetching: ucProposalData.selectors.isFetching(state.useCases.proposalData.businessData),
context: entProposalDataContext.selectors.getContext(state.entities.proposalData.context),
productsServices: entProposalData.selectors.getProductsServices(state.entities.proposalData.proposal),
})
......
import React from 'react'
import { BDProductService, ProposalDataContext } from '@agiliza/api/domain'
import { DocumentTemplate } from '@agiliza/components/templates'
import { formatCurrency } from '@agiliza/utils/formatters'
import { ActionType } from '@agiliza/utils/hooks/state'
import { maskMonthYear } from '@agiliza/utils/masks'
import { TextField, TextFieldProps } from '@material-ui/core'
import { getBase64FromFile } from '@agiliza/utils/method'
import { SelectField, SelectFieldProps } from '@curio/components'
import { TextField, TextFieldProps, Typography } from '@material-ui/core'
import { withStyles, WithStyles } from '@material-ui/core/styles'
import { BDStockSalesCostsState } from '../state'
......@@ -13,12 +18,14 @@ type ExtendedProps = WithStyles<typeof styles>
interface Props extends ExtendedProps {
state: BDStockSalesCostsState
actions: ActionType<BDStockSalesCostsState>
context: ProposalDataContext
productsServices: BDProductService[]
}
const Form = (props: Props) => {
const { classes, state, actions } = props
const { classes, state, actions, context, productsServices } = props
const { monthYearReference, salesCommission } = state
const { monthYearReference, salesCommission, document, monthRating } = state
const handleChangeText =
(key: keyof BDStockSalesCostsState): TextFieldProps['onChange'] =>
......@@ -26,8 +33,42 @@ const Form = (props: Props) => {
actions.update({ [key]: evt.target.value })
}
const handleChangeImage: React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>['onChange'] = async (evt) => {
const file = evt.target.files && evt.target.files[0]
if (file) {
const b64: string = await getBase64FromFile(file)
actions.update({ document: { url: b64 } })
}
}
const handleChangeDocumentType = (value: string) => {
const documentType = context.documentTypes.find((dT) => dT.id === value)
if (documentType) actions.update({ document: { type: documentType } })
}
const handleChangeSelect =
(key: keyof BDStockSalesCostsState): SelectFieldProps['onChange'] =>
(vl) => {
actions.update({ [key]: vl })
}
const getTotals = (key: keyof Pick<BDProductService, 'monthlySales' | 'stock' | 'variableCosts'>) => {
let total = 0
productsServices?.forEach((pS) => (total += Number(pS[key].amount) * Number(pS[key].price)))
return total
}
const getTotalCommission = (comm: string) => {
return (getTotals('monthlySales') * Number(comm)) / 100
}
return (
<form className={classes.form}>
<DocumentTemplate context={context} document={document} onChangeImage={handleChangeImage} onChangeDocumentType={handleChangeDocumentType} />
{/* <Typography className={classes.label}>
Preencha as informações abaixo, e na tela seguinte informe os produtos/serviços e os respectivos dados referente a estoque, vendas mensais e
custos variáveis.
</Typography> */}
<TextField
variant="outlined"
label="Mês/Ano referência"
......@@ -36,13 +77,28 @@ const Form = (props: Props) => {
inputProps={{ maxLength: 7 }}
type="tel"
/>
<TextField variant="outlined" label="Comissão vendas (%)" value={salesCommission} onChange={handleChangeText('salesCommission')} />
<SelectField
id="month-rating-select-field"
label="Classificação do mês"
value={monthRating}
onChange={handleChangeSelect('monthRating')}
items={context.monthRatings.map((mR) => ({ label: mR.description, value: mR.id }))}
variant="outlined"
shrink={false}
/>
<Typography className={classes.label}>
Após o preenchimento das informações citadas acima, os totais abaixo serão preenchidos automaticamente.
</Typography>
<TextField variant="outlined" disabled label="Total geral estoque" value={formatCurrency(getTotals('stock').toFixed(2)) || ''} />
<TextField variant="outlined" disabled label="Total geral vendas" value={formatCurrency(getTotals('monthlySales').toFixed(2)) || ''} />
<TextField
variant="outlined"
label="Comissão vendas (%)"
value={salesCommission}
onChange={handleChangeText('salesCommission')}
inputProps={{ maxLength: 7 }}
disabled
label="Total geral vendas"
value={formatCurrency(getTotalCommission(salesCommission).toFixed(2)) || ''}
/>
<TextField variant="outlined" disabled label="Total geral custos var." value={formatCurrency(getTotals('variableCosts').toFixed(2)) || ''} />
</form>
)
}
......
......@@ -19,5 +19,6 @@ export default (theme: Theme) => {
},
switchCardPhotoContainer: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-evenly' },
datePicker: { marginBottom: '0px !important' },
label: { ...sharedStyles(theme).label, textAlign: 'center' },
})
}
import React from 'react'
import { useFormState } from '@agiliza/utils/hooks/state'
import { ActionType } from '@agiliza/utils/hooks/state'
import { withStyles, WithStyles } from '@material-ui/core/styles'
import { connected, ConnectedProps } from './connect'
import Form from './Form'
import { initialState } from './state'
import { BDStockSalesCostsState } from './state'
import styles from './styles'
type ExtendedProps = WithStyles<typeof styles>
type ExtendedProps = WithStyles<typeof styles> & ConnectedProps
interface Props extends ExtendedProps {}
interface Props extends ExtendedProps {
state: BDStockSalesCostsState
actions: ActionType<BDStockSalesCostsState>
}
const StockSalesCosts = (props: Props) => {
const { classes } = props
const formState = useFormState('stockSalesCostsForm', initialState)
const { classes, context, productsServices, state, actions } = props
return (
<div className={classes.contentContainer}>
<div className={classes.content}>
<Form {...formState} />
<Form state={state} actions={actions} context={context} productsServices={productsServices} />
</div>
</div>
)
}
export default withStyles(styles)(StockSalesCosts)
export default connected(withStyles(styles)(StockSalesCosts))
import { connect } from 'react-redux'
import { BDProductService, ProposalDataContext } from '@agiliza/api/domain'
import { StoreState } from '@agiliza/redux'
import * as entProposalDataContext from '@agiliza/redux/entities/proposalData/context'
import * as entProposalData from '@agiliza/redux/entities/proposalData/proposal'
export interface ConnectedProps {
context: ProposalDataContext
productsServices: BDProductService[]
}
type StateProps = Pick<ConnectedProps, 'context' | 'productsServices'>
// type DispatchProps = Pick<ConnectedProps, 'addIndentification'>
const mapStateToProps = (state: StoreState): StateProps => ({
context: entProposalDataContext.selectors.getContext(state.entities.proposalData.context),
productsServices: entProposalData.selectors.getProductsServices(state.entities.proposalData.proposal),
})
// const mapDispatchToProps = (dispatch: Dispatch): DispatchProps =>
// bindActionCreators(
// {
// },
// dispatch
// )
export const connected = connect(mapStateToProps)
export { default } from './StockSalesCosts'
export * from './StockSalesCosts'
export * from './state'
......@@ -13,4 +13,5 @@ export default (theme: Theme) =>
tabs: { borderRight: `1px solid ${theme.palette.divider}` },
tabWrapper: { flexDirection: 'row' },
tabLabelIcon: { marginBottom: '0px !important', marginRight: theme.spacing(1) },
label: { marginBottom: theme.spacing(2) },
})
......@@ -38,7 +38,7 @@ const Form = (props: Props) => {
return (
<form className={classes.form}>
<ImageUpload label="Comprovante de residência" image={proof} onChangeImage={handleChangeProof} className={classes.imageUpload} />
<ImageUpload label="Comprovante de residência" image={proof} onChangeImage={handleChangeProof} />
<Address state={state} onChange={handleChangeAddress} states={states} cities={cities} />
</form>
)
......
......@@ -64,7 +64,7 @@ const Form = (props: Props) => {
<Switch label="Possui imóveis?" value={hasProperty} onChange={(vl) => actions.update({ hasProperty: vl })} required />
{hasProperty ? (
<>
<ImageUpload label="Escritura" image={deed} onChangeImage={handleChangeProof} className={classes.imageUpload} />
<ImageUpload label="Escritura" image={deed} onChangeImage={handleChangeProof} />
<SelectField
id="type-select-field"
label="Tipo"
......
......@@ -3,7 +3,7 @@ import React from 'react'
import { BanestesAccount, DataType, ProposalDataContext } from '@agiliza/api/domain'
import AccountInputsPhoto from '@agiliza/components/templates/AccountInputsPhoto'
import { ActionType } from '@agiliza/utils/hooks/state'
import { maskCPFCNPJ } from '@agiliza/utils/masks'
import CPFCNPJField from '@agiliza/views/ProposalData/components/atoms/CPFCNPJField'
import { SelectField, SelectFieldProps } from '@curio/components'
import { FormControlLabel, Switch, TextField, TextFieldProps } from '@material-ui/core'
import { withStyles, WithStyles } from '@material-ui/core/styles'
......@@ -64,7 +64,7 @@ const Form = (props: Props) => {
variant="outlined"
shrink={false}
/>
<TextField variant="outlined" label="CPF" value={maskCPFCNPJ(cpfcnpj)} onChange={handleChangeText('cpfcnpj')} inputProps={{ maxLength: 14 }} />
<CPFCNPJField value={cpfcnpj} onChange={handleChangeText('cpfcnpj')} onlyCPF />
<TextField variant="outlined" label="Nome / Razão social" value={name || ''} onChange={handleChangeText('name')} />
<SelectField
id="gender-select-field"
......@@ -77,7 +77,7 @@ const Form = (props: Props) => {
/>
<div className={classes.switchCardPhotoContainer}>
<FormControlLabel
label="Possui conta no Banestes?"
label="Possui conta na entidade?"
control={
<Switch
checked={hasAccount}
......
......@@ -18,6 +18,7 @@ interface Props extends ExtendedProps {
const Identification = (props: Props) => {
const { classes, context, state, actions } = props
return (
<div className={classes.contentContainer}>
<div className={classes.content}>
......
import React, { useEffect } from 'react'
import { ProposalDataContext, Reference } from '@agiliza/api/domain'
import ButtonWithProgress from '@agiliza/components/atoms/ButtonWithProgress'
import { ActionType } from '@agiliza/utils/hooks/state'
import {
Button,
......@@ -25,10 +26,11 @@ interface Props extends ExtendedProps {
reference?: Reference
onSave(rfc: Reference, add: boolean): () => void
context: ProposalDataContext
fetching: boolean
}
const Dialog = (props: Props) => {
const { classes, open, onClose, onSave, reference, context, state, actions } = props
const { classes, fetching, open, onClose, onSave, reference, context, state, actions } = props
useEffect(() => {
if (reference) actions.update(reference)
......@@ -47,7 +49,9 @@ const Dialog = (props: Props) => {
</DialogContent>
<DialogActions>
<Button onClick={onClose}>Cancelar</Button>
<Button onClick={onSave(mapStateToReference(), !reference)}>Salvar</Button>
<ButtonWithProgress variant="text" fetching={fetching} onClick={onSave(mapStateToReference(), !reference)}>
Salvar
</ButtonWithProgress>
</DialogActions>
</MUIDialog>
)
......
......@@ -40,20 +40,20 @@ const Form = (props: Props) => {
}
const handleChangeSelect =
(key: keyof Pick<CDReferenceState, 'photo'>): SelectFieldProps['onChange'] =>
(key: keyof Pick<CDReferenceState, 'type'>): SelectFieldProps['onChange'] =>
(value) => {
actions.update({ [key]: value })
}
return (
<form className={classes.form}>
<ImageUpload label="Foto da referência" image={photo} onChangeImage={handleChangePhoto} className={classes.imageUpload} />
<ImageUpload label="Foto da referência" image={photo} onChangeImage={handleChangePhoto} />
<SelectField
id="type-select"
variant="outlined"
label="Tipo"
value={type}
onChange={handleChangeSelect('photo')}
onChange={handleChangeSelect('type')}
items={context.referenceTypes.map((st) => ({ label: st.description, value: st.id }))}
shrink={false}
// className={classes.selectField}
......
......@@ -21,7 +21,9 @@ interface Props extends ExtendedProps {
}
const References = (props: Props) => {
const { classes, context, state, actions, references, projectId, personId } = props
const { classes, fetching, context, state, actions, references, projectId, personId } = props
console.log(personId)
const [selectedReference, setSelectedReference] = useState<Reference | undefined>()
......@@ -32,22 +34,30 @@ const References = (props: Props) => {
}, [])
const handleClickListItem = (reference: Reference) => () => {
setSelectedReference(reference)
setOpen(true)
setSelectedReference(reference)
}
const handleClickAdd = () => {
setOpen(true)
setSelectedReference(undefined)
}
const handleClickClose = () => {
setOpen(false)
setSelectedReference(undefined)
}
const handleSave = (reference: Reference, add: boolean) => () => {
const onSuccess = () => {
setOpen(false)
setSelectedReference(reference)
}
if (add)
props.addReference({
projectId,
personId,
reference,
onSuccess: () => setOpen(false),
onSuccess,
})
else
props.updateReference({
......@@ -55,7 +65,7 @@ const References = (props: Props) => {
personId,
referenceId: reference.id,
reference,
onSuccess: () => setOpen(false),
onSuccess,
})
}
......@@ -81,8 +91,9 @@ const References = (props: Props) => {
<AddIcon />
</Avatar>
<Dialog
fetching={fetching}
open={open}
onClose={() => setOpen(false)}
onClose={handleClickClose}
reference={selectedReference}
onSave={handleSave}
context={context}
......
......@@ -5,7 +5,6 @@ import { ProposalDataContext, Reference } from '@agiliza/api/domain'
import { StoreState } from '@agiliza/redux'
import * as entProposalDataContext from '@agiliza/redux/entities/proposalData/context'
import * as entProposalData from '@agiliza/redux/entities/proposalData/proposal'
import * as ucProposalDataContext from '@agiliza/redux/useCases/proposalData/context'
import * as ucProposalData from '@agiliza/redux/useCases/proposalData/customerData'
export interface ConnectedProps {
......@@ -21,7 +20,7 @@ type StateProps = Pick<ConnectedProps, 'fetching' | 'context' | 'references'>
type DispatchProps = Pick<ConnectedProps, 'getReferences' | 'addReference' | 'updateReference'>
const mapStateToProps = (state: StoreState): StateProps => ({
fetching: ucProposalDataContext.selectors.isFetching(state.ui.login),
fetching: ucProposalData.selectors.isFetching(state.useCases.proposalData.customerData),
context: entProposalDataContext.selectors.getContext(state.entities.proposalData.context),
references: entProposalData.selectors.getReferences(state.entities.proposalData.proposal),
})
......
......@@ -5,8 +5,9 @@ import ImageUpload from '@agiliza/components/organisms/ImageUpload'
import Address, { AddressState } from '@agiliza/components/templates/Address'
import { formatCurrency } from '@agiliza/utils/formatters'
import { ActionType } from '@agiliza/utils/hooks/state'
import { maskCPFCNPJ, maskPhone } from '@agiliza/utils/masks'
import { maskPhone } from '@agiliza/utils/masks'
import { getBase64FromFile } from '@agiliza/utils/method'
import CPFCNPJField from '@agiliza/views/ProposalData/components/atoms/CPFCNPJField'
import { DatePicker } from '@curio/components'
import { TextField, TextFieldProps } from '@material-ui/core'
import { withStyles, WithStyles } from '@material-ui/core/styles'
......@@ -52,7 +53,7 @@ const Form = (props: Props) => {
return (
<form className={classes.form}>
<TextField variant="outlined" label="Razão social" value={companyName} onChange={handleChangeText('companyName')} />
<TextField variant="outlined" label="CNPJ" value={maskCPFCNPJ(cnpj)} onChange={handleChangeText('cnpj')} inputProps={{ maxLength: 18 }} />
<CPFCNPJField value={cnpj} onChange={handleChangeText('cnpj')} onlyCPNJ />
<DatePicker
id="admission-date"
label="Data de admissão"
......@@ -61,7 +62,7 @@ const Form = (props: Props) => {
format="dd/MM/yyyy"
className={classes.datePicker}
/>
<ImageUpload className={classes.imageUpload} label="Comprovante" image={proofAddress} onChangeImage={handleChangeProof} />
<ImageUpload label="Comprovante" image={proofAddress} onChangeImage={handleChangeProof} />
<TextField variant="outlined" label="Telefone" value={maskPhone(mobile)} onChange={handleChangeText('mobile')} />
<TextField variant="outlined" label="Renda líquida" value={formatCurrency(netIncome)} onChange={handleChangeText('netIncome')} />
<Address state={address} onChange={handleChangeAddress} states={context.states} cities={context.cities} />
......
......@@ -4,8 +4,9 @@ import { Workplace } from '@agiliza/api/domain'
import ImageUpload from '@agiliza/components/organisms/ImageUpload'
import { formatCurrency } from '@agiliza/utils/formatters'
import { ActionType } from '@agiliza/utils/hooks/state'
import { maskCPFCNPJ, maskLandline, maskPhone } from '@agiliza/utils/masks'
import { maskLandline, maskPhone } from '@agiliza/utils/masks'
import { getBase64FromFile } from '@agiliza/utils/method'
import CPFCNPJField from '@agiliza/views/ProposalData/components/atoms/CPFCNPJField'
import { DatePicker } from '@curio/components'
import { TextField, TextFieldProps, Typography } from '@material-ui/core'
import { withStyles, WithStyles } from '@material-ui/core/styles'
......@@ -59,14 +60,8 @@ const Form = (props: Props) => {
Local de trabalho
</Typography>
<TextField variant="outlined" label="Razão social" value={workplace?.workplaceName || ''} onChange={handleChangeWorkplace('workplaceName')} />
<ImageUpload label="Comprovante" image={workplace?.proof || ''} onChangeImage={handleChangePhoto} className={classes.imageUpload} />
<TextField
variant="outlined"
label="CNPJ"
value={maskCPFCNPJ(workplace?.cnpj || '')}
onChange={handleChangeWorkplace('cnpj')}
inputProps={{ maxLength: 18 }}
/>
<ImageUpload label="Comprovante" image={workplace?.proof || ''} onChangeImage={handleChangePhoto} />
<CPFCNPJField value={workplace?.cnpj || ''} onChange={handleChangeWorkplace('cnpj')} onlyCPNJ />
<DatePicker
id="admission-date"
label="Data de admissão"
......
......@@ -4,8 +4,8 @@ import { ProposalDataContext } from '@agiliza/api/domain'
import ImageUpload from '@agiliza/components/organisms/ImageUpload'
import RGTemplate from '@agiliza/components/templates/RGTemplate'
import { ActionType } from '@agiliza/utils/hooks/state'
import { maskCPFCNPJ } from '@agiliza/utils/masks'
import { extractNumbers, getBase64FromFile } from '@agiliza/utils/method'
import CPFCNPJField from '@agiliza/views/ProposalData/components/atoms/CPFCNPJField'
import { DatePicker, SelectField, SelectFieldProps, Switch } from '@curio/components'
import { TextField, TextFieldProps } from '@material-ui/core'
import { withStyles, WithStyles } from '@material-ui/core/styles'
......@@ -70,8 +70,8 @@ const Form = (props: Props) => {
return (
<form className={classes.form}>
<TextField variant="outlined" label="CPF" value={maskCPFCNPJ(cpf)} onChange={handleChangeText('cpf')} inputProps={{ maxLength: 14 }} />
<ImageUpload label="Certidão de casamento" image={marriageCertificate} onChangeImage={handleChangeProof} className={classes.imageUpload} />
<CPFCNPJField value={cpf} onChange={handleChangeText('cpf')} onlyCPF />
<ImageUpload label="Certidão de casamento" image={marriageCertificate} onChangeImage={handleChangeProof} />
<TextField variant="outlined" label="Nome" value={name} onChange={handleChangeText('name')} />
<RGTemplate rg={rg} onChange={handleChangeRG} />
<DatePicker
......
import React, { useEffect } from 'react'
import { Vehicle } from '@agiliza/api/domain'
import ButtonWithProgress from '@agiliza/components/atoms/ButtonWithProgress'
import { useFormState } from '@agiliza/utils/hooks/state'
import {
Button,
......@@ -22,10 +23,11 @@ interface Props extends ExtendedProps {
onClose: () => void
vehicle?: Vehicle
onSave(rfc: Vehicle, add: boolean): () => void
fetching: boolean
}
const Dialog = (props: Props) => {
const { classes, open, onClose, onSave, vehicle } = props
const { classes, fetching, open, onClose, onSave, vehicle } = props
const formState = useFormState('VehicleForm', initialState)
......@@ -48,7 +50,9 @@ const Dialog = (props: Props) => {
</DialogContent>
<DialogActions>
<Button onClick={onClose}>Cancelar</Button>
<Button onClick={onSave(mapStateToVehicle(), !vehicle)}>Salvar</Button>
<ButtonWithProgress variant="text" fetching={fetching} onClick={onSave(mapStateToVehicle(), !vehicle)}>
Salvar
</ButtonWithProgress>
</DialogActions>
</MUIDialog>
)
......
......@@ -21,15 +21,15 @@ interface Props extends ExtendedProps {
}
const Vehicles = (props: Props) => {
const { classes, projectId, personId, vehicles } = props
const { classes, fetching, projectId, personId, vehicles } = props
const [selectedVehicle, setSelectedVehicle] = useState<Vehicle | undefined>()
const [open, setOpen] = useState(false)
const handleClickListItem = (vehicle: Vehicle) => () => {
setSelectedVehicle(vehicle)
setOpen(true)
setSelectedVehicle(vehicle)
}
const handleClickAdd = () => {
......@@ -37,13 +37,22 @@ const Vehicles = (props: Props) => {
setSelectedVehicle(undefined)
}
const handleClickClose = () => {
setOpen(false)
setSelectedVehicle(undefined)
}
const handleSave = (vehicle: Vehicle, add: boolean) => () => {
const onSuccess = () => {
setOpen(false)
setSelectedVehicle(vehicle)
}
if (add)
props.addVehicle({
projectId,
personId,
vehicle,
onSuccess: () => setOpen(false),
onSuccess,
})
else
props.updateVehicle({
......@@ -51,7 +60,7 @@ const Vehicles = (props: Props) => {
personId,
vehicleId: vehicle.id,
vehicle,
onSuccess: () => setOpen(false),
onSuccess,
})
}
......@@ -76,7 +85,7 @@ const Vehicles = (props: Props) => {
<Avatar className={classes.avatarBtnContainer} onClick={handleClickAdd}>
<AddIcon />
</Avatar>
<Dialog open={open} onClose={() => setOpen(false)} vehicle={selectedVehicle} onSave={handleSave} />
<Dialog fetching={fetching} open={open} onClose={handleClickClose} vehicle={selectedVehicle} onSave={handleSave} />
</>
)
}
......
......@@ -5,7 +5,6 @@ import { ProposalDataContext, Vehicle } from '@agiliza/api/domain'
import { StoreState } from '@agiliza/redux'
import * as entProposalDataContext from '@agiliza/redux/entities/proposalData/context'
import * as entProposalData from '@agiliza/redux/entities/proposalData/proposal'
import * as ucProposalDataContext from '@agiliza/redux/useCases/proposalData/context'
import * as ucProposalData from '@agiliza/redux/useCases/proposalData/customerData'
export interface ConnectedProps {
......@@ -21,7 +20,7 @@ type StateProps = Pick<ConnectedProps, 'fetching' | 'context' | 'vehicles'>
type DispatchProps = Pick<ConnectedProps, 'getVehicles' | 'addVehicle' | 'updateVehicle'>
const mapStateToProps = (state: StoreState): StateProps => ({
fetching: ucProposalDataContext.selectors.isFetching(state.ui.login),
fetching: ucProposalData.selectors.isFetching(state.useCases.proposalData.customerData),
context: entProposalDataContext.selectors.getContext(state.entities.proposalData.context),
vehicles: entProposalData.selectors.getVehicles(state.entities.proposalData.proposal),
})
......
import { file } from '@agiliza/__mocks__/files'
import { Vehicle } from '@agiliza/api/domain'
type ExtendedState = Vehicle
export interface CDVehicleState extends ExtendedState {}
export const initialState: CDVehicleState = {
export const initialState: CDVehicleState =
process.env.NODE_ENV === 'development'
? {
id: '',
brand: 'TEST',
document: file,
hasInsurance: true,
hasOnus: true,
licensePlate: 'AAA9999',
marketValue: '25000',
model: 'TEST',
year: '2010',
}
: {
id: '',
brand: '',
document: '',
......@@ -14,4 +28,4 @@ export const initialState: CDVehicleState = {
marketValue: '',
model: '',
year: '',
}
}
......@@ -4,7 +4,7 @@ import { frameworks, genders } from '@agiliza/__mocks__/proposalData'
import { BanestesAccount, DataType } from '@agiliza/api/domain'
import AccountInputsPhoto from '@agiliza/components/templates/AccountInputsPhoto'
import { ActionType } from '@agiliza/utils/hooks/state'
import { maskCPFCNPJ } from '@agiliza/utils/masks'
import CPFCNPJField from '@agiliza/views/ProposalData/components/atoms/CPFCNPJField'
import { SelectField, SelectFieldProps } from '@curio/components'
import { FormControlLabel, Switch, TextField, TextFieldProps } from '@material-ui/core'
import { withStyles, WithStyles } from '@material-ui/core/styles'
......@@ -64,13 +64,7 @@ const Customer = (props: Props) => {
variant="outlined"
shrink={false}
/>
<TextField
variant="outlined"
label="CPF / CNPJ"
value={maskCPFCNPJ(cpfcnpj)}
onChange={handleChangeText('cpfcnpj')}
inputProps={{ maxLength: 18 }}
/>
<CPFCNPJField value={cpfcnpj} onChange={handleChangeText('cpfcnpj')} />
<TextField variant="outlined" label="Nome / Razão social" value={name || ''} onChange={handleChangeText('name')} />
<SelectField
id="gender-select-field"
......
......@@ -22,12 +22,16 @@ import {
ZoomOutMap as ZoomOutMapIcon
} from '@material-ui/icons'
import BDAddress from './BusinessData/Address'
import BDIdentification from './BusinessData/Identification'
import BDAddress, { initialState as bdAddressInitState } from './BusinessData/Address'
import BDIdentification, {
initialState as bdIdentificationInitState
} from './BusinessData/Identification'
import ProductsServices, {
initialState as bdProductServiceInitState
} from './BusinessData/ProductsServices'
import StockSalesCosts from './BusinessData/StockSalesCosts'
import StockSalesCosts, {
initialState as bdStockSalesCostsInitState
} from './BusinessData/StockSalesCosts'
import { connected, ConnectedProps } from './connect'
import Address, { initialState as cdAddressInitState } from './CustomerData/Address'
import Home, { initialState as cdHomeInitState } from './CustomerData/Home'
......@@ -55,8 +59,8 @@ type ExtendedProps = WithStyles<typeof styles> & RouteComponentProps & Connected
interface Props extends ExtendedProps {}
const ProposalData = (props: Props) => {
const { classes, fetching, proposalId, personId } = props
const [activeStep, setActiveStep] = useState(12)
const { classes, history, fetching, proposalId, personId } = props
const [activeStep, setActiveStep] = useState(0)
useEffect(() => {
props.fetchContext()
......@@ -66,12 +70,15 @@ const ProposalData = (props: Props) => {
const cdIdentification = useFormState('cdIdentificationState', cdIdentInitState)
const cdPersonalData = useFormState('cdPersonalDataState', cdPersonalDataInitState)
const cdAddress = useFormState('cdAddressState', cdAddressInitState)
const cdSourceIncome = useFormState('cdAddressState', cdSourceIncomeInitState)
const cdSpouseData = useFormState('cdAddressState', cdSpouseDataInitState)
const cdReference = useFormState('cdSpoudeAddDataState', cdReferenceInitState)
const cdSourceIncome = useFormState('cdSourceIncome', cdSourceIncomeInitState)
const cdSpouseData = useFormState('cdSpouseData', cdSpouseDataInitState)
const cdReference = useFormState('cdReference', cdReferenceInitState)
const cdHomeState = useFormState('cdHomeState', cdHomeInitState)
const cdVehicleState = useFormState('cdVehicleState', cdVehicleInitState)
const bdIdentificationState = useFormState('bdIdentificationState', bdIdentificationInitState)
const bdAddressState = useFormState('bdAddressState', bdAddressInitState)
const bdStockSalesCostsState = useFormState('bdStockSalesCostsState', bdStockSalesCostsInitState)
const bdProductServiceState = useFormState('bdProductServiceState', bdProductServiceInitState)
const customerDataItems = useMemo(
......@@ -107,16 +114,24 @@ const ProposalData = (props: Props) => {
const businessDataItems = useMemo(
() => [
{ label: 'Identificação', icon: <AccountBoxIcon />, component: <BDIdentification /> },
{ label: 'Endereço', icon: <ApartmentIcon />, component: <BDAddress /> },
{ label: 'Estoque, Vendas e Custos', icon: <AttachMoneyIcon />, component: <StockSalesCosts /> },
{
label: 'Identificação',
icon: <AccountBoxIcon />,
component: <BDIdentification state={bdIdentificationState.state} actions={bdIdentificationState.actions} />,
},
{ label: 'Endereço', icon: <ApartmentIcon />, component: <BDAddress state={bdAddressState.state} actions={bdAddressState.actions} /> },
{
label: 'Produto',
icon: <InsertDriveFileIcon />,
component: <ProductsServices projectId={proposalId} state={bdProductServiceState.state} actions={bdProductServiceState.actions} />,
},
{
label: 'Estoque, Vendas e Custos',
icon: <AttachMoneyIcon />,
component: <StockSalesCosts state={bdStockSalesCostsState.state} actions={bdStockSalesCostsState.actions} />,
},
],
[bdProductServiceState]
[bdIdentificationState, bdAddressState, bdStockSalesCostsState, bdProductServiceState]
)
const proposalDataItems = useMemo(() => [...customerDataItems, ...businessDataItems], [customerDataItems, businessDataItems])
......@@ -143,7 +158,7 @@ const ProposalData = (props: Props) => {
})
break
case 2:
props.updateAddress({
props.updateCDAddress({
...projectPersonIds,
address: cdAddress.state,
onSuccess: () => setActiveStep((prevActiveStep) => prevActiveStep + 1),
......@@ -177,6 +192,30 @@ const ProposalData = (props: Props) => {
onSuccess: () => setActiveStep((prevActiveStep) => prevActiveStep + 1),
})
break
case 9:
props.updateIdentification({
projectId: proposalId,
identification: bdIdentificationState.state,
onSuccess: () => setActiveStep((prevActiveStep) => prevActiveStep + 1),
})
break
case 10:
props.updateBDAddress({
projectId: proposalId,
address: bdAddressState.state,
onSuccess: () => setActiveStep((prevActiveStep) => prevActiveStep + 1),
})
break
case 12:
props.updateStockSalesCosts({
projectId: proposalId,
stockSalesCosts: bdStockSalesCostsState.state,
onSuccess: () => {
props.reset()
history.push('/')
},
})
break
default:
setActiveStep((prevActiveStep) => prevActiveStep + 1)
}
......@@ -212,7 +251,7 @@ const ProposalData = (props: Props) => {
activeStep={activeStep}
style={{ width: '100%' }}
nextButton={
<Button size="large" onClick={handleNext} disabled={activeStep === steps - 1} className={classes.stepperBtn}>
<ButtonWithProgress fetching={fetching} variant="text" size="large" onClick={handleNext} className={classes.stepperBtn}>
{activeStep === steps - 1 ? (
'Finalizar'
) : (
......@@ -221,20 +260,13 @@ const ProposalData = (props: Props) => {
<KeyboardArrowRightIcon />
</>
)}
</Button>
</ButtonWithProgress>
}
backButton={
<ButtonWithProgress
fetching={fetching}
size="large"
variant="text"
onClick={handleBack}
disabled={activeStep === 0}
className={classes.stepperBtn}
>
<Button size="large" onClick={handleBack} disabled={activeStep === 0} className={classes.stepperBtn}>
<KeyboardArrowLeftIcon />
Anterior
</ButtonWithProgress>
</Button>
}
/>
{/* </Stepper> */}
......
......@@ -4,38 +4,56 @@ import { bindActionCreators, Dispatch } from 'redux'
import { StoreState } from '@agiliza/redux'
import * as entProposal from '@agiliza/redux/entities/proposalData/proposal'
import * as ucAuthentication from '@agiliza/redux/useCases/authentication'
import * as ucProposalDataBD from '@agiliza/redux/useCases/proposalData/businessData'
import * as ucProposalDataContext from '@agiliza/redux/useCases/proposalData/context'
import * as ucProposalDataCD from '@agiliza/redux/useCases/proposalData/customerData'
import { createSelector } from '@reduxjs/toolkit'
export interface ConnectedProps {
fetching: boolean
proposalId: string
personId: string
reset: () => void
fetchContext: typeof ucProposalDataContext.actions.fetchContext
getContextAddress: typeof ucAuthentication.actions.getContext
addIndentification: typeof ucProposalDataCD.actions.addIndentification
updatePersonalData: typeof ucProposalDataCD.actions.updatePersonalData
updateAddress: typeof ucProposalDataCD.actions.updateAddress
updateCDAddress: typeof ucProposalDataCD.actions.updateAddress
updateSourceIncome: typeof ucProposalDataCD.actions.updateSourceIncome
updateSpouseData: typeof ucProposalDataCD.actions.updateSpouseData
updateHome: typeof ucProposalDataCD.actions.updateHome
updateIdentification: typeof ucProposalDataBD.actions.updateIdentification
updateBDAddress: typeof ucProposalDataBD.actions.updateAddress
updateStockSalesCosts: typeof ucProposalDataBD.actions.updateStockSalesCosts
}
type StateProps = Pick<ConnectedProps, 'fetching' | 'proposalId' | 'personId'>
type DispatchProps = Pick<
ConnectedProps,
| 'reset'
| 'addIndentification'
| 'fetchContext'
| 'updatePersonalData'
| 'updateAddress'
| 'updateCDAddress'
| 'getContextAddress'
| 'updateSourceIncome'
| 'updateSpouseData'
| 'updateHome'
| 'updateIdentification'
| 'updateBDAddress'
| 'updateStockSalesCosts'
>
const isFetching = createSelector(
(state: StoreState) => ucProposalDataContext.selectors.isFetching(state.ui.login),
(state: StoreState) => ucAuthentication.selectors.isFetching(state.useCases.authentication),
(state: StoreState) => ucProposalDataCD.selectors.isFetching(state.useCases.proposalData.customerData),
(state: StoreState) => ucProposalDataBD.selectors.isFetching(state.useCases.proposalData.businessData),
(...conditions) => conditions.some((c) => c)
)
const mapStateToProps = (state: StoreState): StateProps => ({
fetching: ucProposalDataContext.selectors.isFetching(state.ui.login),
fetching: isFetching(state),
proposalId: entProposal.selectors.getProposalId(state.entities.proposalData.proposal),
personId: entProposal.selectors.getPersonlId(state.entities.proposalData.proposal),
})
......@@ -43,14 +61,18 @@ const mapStateToProps = (state: StoreState): StateProps => ({
const mapDispatchToProps = (dispatch: Dispatch): DispatchProps =>
bindActionCreators(
{
reset: () => ({ type: 'RESET_STORE' }),
addIndentification: ucProposalDataCD.actions.addIndentification,
fetchContext: ucProposalDataContext.actions.fetchContext,
updatePersonalData: ucProposalDataCD.actions.updatePersonalData,
updateAddress: ucProposalDataCD.actions.updateAddress,
updateCDAddress: ucProposalDataCD.actions.updateAddress,
getContextAddress: ucAuthentication.actions.getContext,
updateSourceIncome: ucProposalDataCD.actions.updateSourceIncome,
updateSpouseData: ucProposalDataCD.actions.updateSpouseData,
updateHome: ucProposalDataCD.actions.updateHome,
updateBDAddress: ucProposalDataBD.actions.updateAddress,
updateIdentification: ucProposalDataBD.actions.updateIdentification,
updateStockSalesCosts: ucProposalDataBD.actions.updateStockSalesCosts,
},
dispatch
)
......
......@@ -30,5 +30,4 @@ export default (theme: Theme) =>
width: '30%',
height: '100%',
},
imageUpload: { width: '100%', textAlign: 'center', marginTop: theme.spacing(1), marginBottom: theme.spacing(1) },
})
import React, { useEffect, useState } from 'react'
import { RouteComponentProps, useHistory } from 'react-router'
import { destinations } from '@agiliza/__mocks__/creditLines'
import { SimulationCategory } from '@agiliza/api/domain'
import { extractCurrency, extractNumbers } from '@agiliza/utils/extractors'
import { formatCurrency } from '@agiliza/utils/formatters'
import { SelectField } from '@curio/components'
import {
Button,
CircularProgress,
......@@ -41,6 +43,7 @@ const CreditLinesList = (props: Props) => {
const [amount, setAmount] = useState('0')
const [paymentMonths, setPaymentMonths] = useState(0)
const [graceMonths, setGraceMonths] = useState(0)
const [destination, setDestination] = useState('')
const parentPath = match.path.substring(0, match.path.lastIndexOf('/'))
const handleSimulate = () => {
......@@ -64,7 +67,7 @@ const CreditLinesList = (props: Props) => {
<div className={classes.contentContainer}>
<div className={classes.content}>
<Typography variant="h5" className={classes.title}>
Escolha a melhor linha de crédito para você e clique em simular!
Escolha a melhor opção para sua empresa e clique em simular!
</Typography>
<Autocomplete<SimulationCategory>
id="credit-lines"
......@@ -72,7 +75,7 @@ const CreditLinesList = (props: Props) => {
options={simulationCategories}
getOptionLabel={(option) => option.description}
getOptionSelected={(opt, val) => opt.id === selectedSimulCategory?.id}
noOptionsText="Nenhuma linha encontrada"
noOptionsText="Nenhum motivo encontrado..."
value={selectedSimulCategory}
onChange={(_, opt) => {
setSelectedSimulCategory(opt || null)
......@@ -104,7 +107,7 @@ const CreditLinesList = (props: Props) => {
<TextField
{...params}
id="select-patient-id"
label="Linha de crédito"
label="Qual o motivo do financiamento?"
variant="outlined"
InputProps={{
ref: params.InputProps.ref,
......@@ -122,7 +125,7 @@ const CreditLinesList = (props: Props) => {
/>
<TextField
className={classes.description}
label="Descrição da linha de crédito"
label="Descrição"
value={selectedSimulCategory?.fullDescription || ''}
rows={5}
multiline
......@@ -134,6 +137,16 @@ const CreditLinesList = (props: Props) => {
variant="outlined"
unselectable="on"
/>
<SelectField
id="destination-select"
variant="outlined"
label="Qual a destinação do capital?"
value={destination}
onChange={(vl) => setDestination(vl)}
items={destinations.map((st) => ({ label: st.description, value: st.id }))}
shrink={false}
className={classes.destinationsSelect}
/>
<SliderField
className={classes.sliderField}
title="De quanto você precisa?"
......
......@@ -13,4 +13,5 @@ export default (theme: Theme) =>
description: { margin: theme.spacing(2), width: '100%' },
sliderField: { textAlign: 'center', width: '100%', marginBottom: theme.spacing(3) },
btnContainer: { width: '100%', textAlign: 'right', marginBottom: theme.spacing(2) },
destinationsSelect: { marginBottom: theme.spacing(2) },
})
......@@ -1264,10 +1264,10 @@
prop-types "^15.7.2"
react-is "^16.8.0 || ^17.0.0"
"@microcredito/client@^0.7.14":
version "0.7.14"
resolved "https://nexus.dev.evologica.com.br/repository/npm/@microcredito/client/-/client-0.7.14.tgz#066eb548f6ed10bb8a194ae4511c86f2344f45b6"
integrity sha1-Bm61SPbtELuKGUrkURyG8jRPRbY=
"@microcredito/client@^0.7.16":
version "0.7.16"
resolved "https://nexus.dev.evologica.com.br/repository/npm/@microcredito/client/-/client-0.7.16.tgz#a8a771014a5610a2e20871e40f226c233a154b6a"
integrity sha1-qKdxAUpWEKLiCHHkDyJsIzoVS2o=
"@nodelib/fs.scandir@2.1.4":
version "2.1.4"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment