Commit 284bf3e6 authored by Rafael's avatar Rafael

Adiciona telas de dados de proposta.

parent ed044d10
...@@ -90,7 +90,7 @@ ...@@ -90,7 +90,7 @@
"@material-ui/icons": "^4.11.2", "@material-ui/icons": "^4.11.2",
"@material-ui/lab": "4.0.0-alpha.58", "@material-ui/lab": "4.0.0-alpha.58",
"@material-ui/pickers": "^3.3.10", "@material-ui/pickers": "^3.3.10",
"@microcredito/client": "^0.7.14", "@microcredito/client": "^0.7.16",
"@reduxjs/toolkit": "^1.2.5", "@reduxjs/toolkit": "^1.2.5",
"@types/react-swipeable-views": "^0.13.1", "@types/react-swipeable-views": "^0.13.1",
"@types/react-swipeable-views-utils": "^0.13.3", "@types/react-swipeable-views-utils": "^0.13.3",
......
...@@ -42,3 +42,34 @@ export const creditLinesData: Record<string, CreditLineData> = Array.from(Array( ...@@ -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 { ...@@ -23,6 +23,11 @@ export interface IdDescricao {
descricao: string descricao: string
} }
export interface CodigoDescricao {
codigo: string
descricao: string
}
export interface DocumentType extends Entity { export interface DocumentType extends Entity {
description: string 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 proof: string
referencePoint?: string referencePoint?: string
} }
export interface UpdateBDAddressArgs { interface InputUpdateBDAddress {
projectId: string projectId: string
address: BDAddress address: BDAddress
} }
export interface UpdateBDAddress {
Input: InputUpdateBDAddress
Output: BDAddress
}
import type { Document } from '../../../domain/project' import { Document } from '../..'
export interface BDIdentification { export interface BDIdentification {
cnpj: string cnpj: string
document: Document document?: Document
openingDate: Date | null openingDate: Date | null
companyName: string companyName: string
stateRegistration: string stateRegistration: string
......
...@@ -6,3 +6,13 @@ export interface StockSalesCosts { ...@@ -6,3 +6,13 @@ export interface StockSalesCosts {
salesCommission: string salesCommission: string
monthRating: 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 { ...@@ -28,6 +28,26 @@ export interface HomeType extends Entity {
description: string 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 { export interface ProposalDataContext {
frameworks: Framework[] frameworks: Framework[]
genders: Gender[] genders: Gender[]
...@@ -36,6 +56,11 @@ export interface ProposalDataContext { ...@@ -36,6 +56,11 @@ export interface ProposalDataContext {
referenceTypes: ReferenceType[] referenceTypes: ReferenceType[]
homeTypes: HomeType[] homeTypes: HomeType[]
deedRecords: DeedRecord[] deedRecords: DeedRecord[]
activitySectors: ActivitySector[]
settledOPs: SettledOP[]
locals: Local[]
documentTypes: DocumentType[]
monthRatings: MonthRating[]
} }
export interface FetchContext { export interface FetchContext {
......
import { import {
AddBDProductService, AddBDProductService,
BDAddress,
BDProductService, BDProductService,
BusinessData, BusinessData,
CreateProposal, CreateProposal,
Document, Document,
StockSalesCosts,
UpdateBDAddress,
UpdateBDIdentification, UpdateBDIdentification,
UpdateBDProductService UpdateBDProductService,
UpdateBDStockSalesCosts
} from '@agiliza/api/domain' } from '@agiliza/api/domain'
import { extractNumbers } from '@agiliza/utils/extractors' import { extractNumbers } from '@agiliza/utils/extractors'
import { import {
DadosNegocioEnderecoApiModel,
DadosNegocioEstoqueVendasCustosApiModel,
DadosNegocioIdentificacaoApiModel, DadosNegocioIdentificacaoApiModel,
DadosNegocioProdutoServicoApiModel, DadosNegocioProdutoServicoApiModel,
DocumentoApiModel DocumentoApiModel
} from '@microcredito/client' } from '@microcredito/client'
import { import {
AtualizaProdutoServicoDadosNegocioRequest, AtualizaProdutoServicoDadosNegocioRequest,
AtualizarEnderecoDadosNegocioRequest,
AtualizarEstoqueVendasCustosDadosNegocioRequest,
AtualizarIdentificacaoDadosNegocioRequest, AtualizarIdentificacaoDadosNegocioRequest,
CriarProdutoServicoDadosNegocioRequest CriarProdutoServicoDadosNegocioRequest
} from '@microcredito/client/dist/apis/AgenteApi' } from '@microcredito/client/dist/apis/AgenteApi'
import { CriarPropostaRequest } from '@microcredito/client/dist/apis/ClienteApi' import { CriarPropostaRequest } from '@microcredito/client/dist/apis/ClienteApi'
import { ApiAdapter } from '../shared' import { ApiAdapter } from '../shared'
import { AddressApiMapper } from './customerData'
export class DocumentApiMapper implements ApiAdapter<Document, DocumentoApiModel> { export class DocumentApiMapper implements ApiAdapter<Document, DocumentoApiModel> {
private mapDocumentTypeToApi = (docType: Document['type']): DocumentoApiModel['tipoDocumento'] => ({ private mapDocumentTypeToApi = (docType: Document['type']): DocumentoApiModel['tipoDocumento'] => ({
...@@ -31,7 +40,7 @@ export class DocumentApiMapper implements ApiAdapter<Document, DocumentoApiModel ...@@ -31,7 +40,7 @@ export class DocumentApiMapper implements ApiAdapter<Document, DocumentoApiModel
public mapDomainToApiModel = (doc: Document): DocumentoApiModel => ({ public mapDomainToApiModel = (doc: Document): DocumentoApiModel => ({
id: doc.id, id: doc.id,
imagem: doc.url, imagem: doc.url,
tipoDocumento: this.mapDocumentTypeToApi(doc.type), tipoDocumento: doc.type ? this.mapDocumentTypeToApi(doc.type) : { codigo: '', descricao: '' },
informacoesComplementares: doc.extraInformations, informacoesComplementares: doc.extraInformations,
}) })
} }
...@@ -45,7 +54,7 @@ export class BDIdentificationApiMapper implements ApiAdapter<BusinessData['ident ...@@ -45,7 +54,7 @@ export class BDIdentificationApiMapper implements ApiAdapter<BusinessData['ident
cnpj: extractNumbers(ident?.cnpj), cnpj: extractNumbers(ident?.cnpj),
codigoCNAE: ident?.codeCNAE, codigoCNAE: ident?.codeCNAE,
dataAbertura: ident?.openingDate !== null ? ident?.openingDate : undefined, 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, inscricaoComercial: ident?.commercialRegistration,
inscricaoEstadual: ident?.stateRegistration, inscricaoEstadual: ident?.stateRegistration,
inscricaoMunicipal: ident?.cityRegistration, inscricaoMunicipal: ident?.cityRegistration,
...@@ -117,3 +126,50 @@ export class BDUpdateProductServiceApiMapper implements ApiAdapter<UpdateBDProdu ...@@ -117,3 +126,50 @@ export class BDUpdateProductServiceApiMapper implements ApiAdapter<UpdateBDProdu
dadosNegocioProdutoServicoApiModel: this.bdProductServiceApiMapper.mapDomainToApiModel(input.productService), 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 { import {
BDIdentification,
BDProductService,
Document,
StockSalesCosts,
UpdateBDAddress
} from '@agiliza/api/domain'
import {
DadosNegocioEnderecoApiModel,
DadosNegocioEstoqueVendasCustosApiModel,
DadosNegocioIdentificacaoApiModel, DadosNegocioIdentificacaoApiModel,
DadosNegocioProdutoServicoApiModel, DadosNegocioProdutoServicoApiModel,
DocumentoApiModel DocumentoApiModel
} from '@microcredito/client' } from '@microcredito/client'
import { DomainAdapter } from '../shared' import { DomainAdapter } from '../shared'
import { AddressMapper } from './customerData'
export class ProjectDocumentMapper implements DomainAdapter<DocumentoApiModel, Document> { export class ProjectDocumentMapper implements DomainAdapter<DocumentoApiModel, Document> {
public mapTipoDocumentoApiToDomain = (tipo: DocumentoApiModel['tipoDocumento']): Document['type'] => ({ public mapTipoDocumentoApiToDomain = (tipo: DocumentoApiModel['tipoDocumento']): Document['type'] => ({
...@@ -56,3 +65,31 @@ export class BDProductsServicesMapper implements DomainAdapter<DadosNegocioProdu ...@@ -56,3 +65,31 @@ export class BDProductsServicesMapper implements DomainAdapter<DadosNegocioProdu
variableCosts: pS.custosVariaveis ? this.mapPriceAmountToDomain(pS.custosVariaveis) : { amount: '', price: '' }, 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 { ProposalDataContext } from '@agiliza/api/domain'
import { import {
ClassificacaoMesApiModel,
EnquadramentoApiModel, EnquadramentoApiModel,
EscolaridadeApiModel, EscolaridadeApiModel,
EstadoCivilApiModel, EstadoCivilApiModel,
GeneroApiModel, GeneroApiModel,
LocalApiModel,
OPLiquidadaApiModel,
RegistroEscrituraApiModel, RegistroEscrituraApiModel,
SetorAtividadeApiModel,
TipoDocumentoApiModel,
TipoMoradiaApiModel, TipoMoradiaApiModel,
TipoReferenciaApiModel TipoReferenciaApiModel
} from '@microcredito/client' } from '@microcredito/client'
import { DomainAdapter, IdDescriptionMapper } from '../shared' import { CodeDescriptionMapper, DomainAdapter, IdDescriptionMapper } from '../shared'
export interface DadosPropostaContexto { export interface DadosPropostaContexto {
enquadramentos: EnquadramentoApiModel[] enquadramentos: EnquadramentoApiModel[]
...@@ -19,13 +24,20 @@ export interface DadosPropostaContexto { ...@@ -19,13 +24,20 @@ export interface DadosPropostaContexto {
tiposReferencia: TipoReferenciaApiModel[] tiposReferencia: TipoReferenciaApiModel[]
registrosEscritura: RegistroEscrituraApiModel[] registrosEscritura: RegistroEscrituraApiModel[]
tiposMoradia: TipoMoradiaApiModel[] tiposMoradia: TipoMoradiaApiModel[]
setoresAtividade: SetorAtividadeApiModel[]
opsLiquidadas: OPLiquidadaApiModel[]
locais: LocalApiModel[]
tiposDocumento: TipoDocumentoApiModel[]
classificacoesMes: ClassificacaoMesApiModel[]
} }
export class ContextMapper implements DomainAdapter<DadosPropostaContexto, ProposalDataContext> { export class ContextMapper implements DomainAdapter<DadosPropostaContexto, ProposalDataContext> {
private idDescriptionMapper: IdDescriptionMapper private idDescriptionMapper: IdDescriptionMapper
private codeDescriptionMapper: CodeDescriptionMapper
constructor() { constructor() {
this.idDescriptionMapper = new IdDescriptionMapper() this.idDescriptionMapper = new IdDescriptionMapper()
this.codeDescriptionMapper = new CodeDescriptionMapper()
} }
public mapApiModelToDomain = (dP: DadosPropostaContexto): ProposalDataContext => ({ public mapApiModelToDomain = (dP: DadosPropostaContexto): ProposalDataContext => ({
frameworks: dP.enquadramentos.map(this.idDescriptionMapper.mapApiModelToDomain), frameworks: dP.enquadramentos.map(this.idDescriptionMapper.mapApiModelToDomain),
...@@ -35,5 +47,10 @@ export class ContextMapper implements DomainAdapter<DadosPropostaContexto, Propo ...@@ -35,5 +47,10 @@ export class ContextMapper implements DomainAdapter<DadosPropostaContexto, Propo
referenceTypes: dP.tiposReferencia.map(this.idDescriptionMapper.mapApiModelToDomain), referenceTypes: dP.tiposReferencia.map(this.idDescriptionMapper.mapApiModelToDomain),
homeTypes: dP.tiposMoradia.map(this.idDescriptionMapper.mapApiModelToDomain), homeTypes: dP.tiposMoradia.map(this.idDescriptionMapper.mapApiModelToDomain),
deedRecords: dP.registrosEscritura.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' import { Entity } from '@agiliza/utils/method'
export interface DomainAdapter<A, B> { export interface DomainAdapter<A, B> {
...@@ -15,3 +15,10 @@ export class IdDescriptionMapper implements DomainAdapter<IdDescricao, IdDescrip ...@@ -15,3 +15,10 @@ export class IdDescriptionMapper implements DomainAdapter<IdDescricao, IdDescrip
description: iD.descricao || '', description: iD.descricao || '',
}) })
} }
export class CodeDescriptionMapper implements DomainAdapter<CodigoDescricao, IdDescription> {
public mapApiModelToDomain = (iD: Partial<CodigoDescricao>): IdDescription => ({
id: iD.codigo || '',
description: iD.descricao || '',
})
}
import { import {
AddBDProductService, AddBDProductService,
GetBDProductsServices, GetBDProductsServices,
UpdateBDProductService UpdateBDAddress,
UpdateBDIdentification,
UpdateBDProductService,
UpdateBDStockSalesCosts
} from '@agiliza/api/domain' } from '@agiliza/api/domain'
import { ErrorMappers } from '@agiliza/api/mappers' import { ErrorMappers } from '@agiliza/api/mappers'
import { ClienteApi, Configuration } from '@microcredito/client' import { ClienteApi, Configuration } from '@microcredito/client'
...@@ -13,6 +16,9 @@ export interface PDBusinessDataRepository { ...@@ -13,6 +16,9 @@ export interface PDBusinessDataRepository {
getProductsServices(input: GetBDProductsServices['Input']): Promise<GetBDProductsServices['Output']> getProductsServices(input: GetBDProductsServices['Input']): Promise<GetBDProductsServices['Output']>
addProductService(input: AddBDProductService['Input']): Promise<AddBDProductService['Output']> addProductService(input: AddBDProductService['Input']): Promise<AddBDProductService['Output']>
updateProductService(input: UpdateBDProductService['Input']): Promise<UpdateBDProductService['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 { export class PDBusinessDataRepositoryImpl implements PDBusinessDataRepository {
...@@ -21,12 +27,25 @@ export class PDBusinessDataRepositoryImpl implements PDBusinessDataRepository { ...@@ -21,12 +27,25 @@ export class PDBusinessDataRepositoryImpl implements PDBusinessDataRepository {
private bdGetServicesProductsMapper: ProposalDataMappers.BDProductsServicesMapper private bdGetServicesProductsMapper: ProposalDataMappers.BDProductsServicesMapper
private bdAddProductServiceApiMapper: ProposalDataApiMappers.BDAddProductServiceApiMapper private bdAddProductServiceApiMapper: ProposalDataApiMappers.BDAddProductServiceApiMapper
private bdUpdateProductServiceApiMapper: ProposalDataApiMappers.BDUpdateProductServiceApiMapper 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) { constructor(userAgent: string, accessToken: string) {
this.errorAdapter = new ErrorMappers.ResponseErrorAdapter() this.errorAdapter = new ErrorMappers.ResponseErrorAdapter()
this.bdGetServicesProductsMapper = new ProposalDataMappers.BDProductsServicesMapper() this.bdGetServicesProductsMapper = new ProposalDataMappers.BDProductsServicesMapper()
this.bdAddProductServiceApiMapper = new ProposalDataApiMappers.BDAddProductServiceApiMapper() this.bdAddProductServiceApiMapper = new ProposalDataApiMappers.BDAddProductServiceApiMapper()
this.bdUpdateProductServiceApiMapper = new ProposalDataApiMappers.BDUpdateProductServiceApiMapper() 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( this.api = new ClienteApi(
new Configuration({ new Configuration({
basePath: API_URL, basePath: API_URL,
...@@ -67,6 +86,37 @@ export class PDBusinessDataRepositoryImpl implements PDBusinessDataRepository { ...@@ -67,6 +86,37 @@ export class PDBusinessDataRepositoryImpl implements PDBusinessDataRepository {
throw result 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 { export class PDBusinessDataRepositoryImplFactory {
......
...@@ -39,6 +39,11 @@ export class ProposalDataContextRepositoryImpl implements ProposalDataContextRep ...@@ -39,6 +39,11 @@ export class ProposalDataContextRepositoryImpl implements ProposalDataContextRep
tiposReferencia: await this.api.obterTiposReferencia(), tiposReferencia: await this.api.obterTiposReferencia(),
tiposMoradia: await this.api.obterTiposMoradia(), tiposMoradia: await this.api.obterTiposMoradia(),
registrosEscritura: await this.api.obterRegistrosEscritura(), 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) return this.contextMapper.mapApiModelToDomain(contexto)
} catch (e) { } catch (e) {
......
...@@ -22,7 +22,7 @@ const ImageUpload = (props: Props) => { ...@@ -22,7 +22,7 @@ const ImageUpload = (props: Props) => {
const { classes, className, buttonClassName, image, onChangeImage, label, imageStyle } = props const { classes, className, buttonClassName, image, onChangeImage, label, imageStyle } = props
return ( return (
<div className={className}> <div className={cn(className, classes.container)}>
<Button variant="text" component="label" className={cn(classes.photoBtn, buttonClassName)} classes={{ label: classes.photoLabelBtn }}> <Button variant="text" component="label" className={cn(classes.photoBtn, buttonClassName)} classes={{ label: classes.photoLabelBtn }}>
{image ? ( {image ? (
<div className={classes.card} style={imageStyle}> <div className={classes.card} style={imageStyle}>
......
...@@ -4,6 +4,7 @@ import { createStyles } from '@material-ui/styles' ...@@ -4,6 +4,7 @@ import { createStyles } from '@material-ui/styles'
// eslint-disable-next-line // eslint-disable-next-line
export default (theme: Theme) => { export default (theme: Theme) => {
return createStyles({ return createStyles({
container: { width: '100%', textAlign: 'center', marginTop: theme.spacing(1), marginBottom: theme.spacing(1) },
photoBtn: { width: '100%' }, photoBtn: { width: '100%' },
photoLabelBtn: { display: 'flex', flexDirection: 'column', height: '280px', alignItems: 'center', flexGrow: 1 }, photoLabelBtn: { display: 'flex', flexDirection: 'column', height: '280px', alignItems: 'center', flexGrow: 1 },
card: { width: '100%', maxWidth: '100%', height: '100%', textAlign: 'center' }, card: { width: '100%', maxWidth: '100%', height: '100%', textAlign: 'center' },
......
...@@ -44,7 +44,7 @@ const Address = (props: Props) => { ...@@ -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="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="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')} /> <TextField variant="outlined" label="Complemento" value={complement} onChange={handleChange('complement')} />
<SelectField <SelectField
id="state-select" 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 React from 'react'
import { City, State } from '@agiliza/api/domain/authentication' 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 { 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 { TextField, TextFieldProps } from '@material-ui/core'
import { withStyles, WithStyles } from '@material-ui/core/styles' import { withStyles, WithStyles } from '@material-ui/core/styles'
...@@ -25,7 +26,7 @@ const FirstAccess = (props: Props) => { ...@@ -25,7 +26,7 @@ const FirstAccess = (props: Props) => {
const { cpf, name, email, phone, ...addressState } = state const { cpf, name, email, phone, ...addressState } = state
const { errorState, actions: errorActions } = useErrorValidator(initState) const { actions: errorActions } = useErrorValidator(initState)
const handleChange = const handleChange =
(key: keyof FirstAccessState): TextFieldProps['onChange'] => (key: keyof FirstAccessState): TextFieldProps['onChange'] =>
...@@ -39,15 +40,7 @@ const FirstAccess = (props: Props) => { ...@@ -39,15 +40,7 @@ const FirstAccess = (props: Props) => {
return ( return (
<form className={classes.form}> <form className={classes.form}>
<TextField <CPFCNPJField value={cpf} onChange={handleChange('cpf')} onlyCPF disabled />
variant="outlined"
label="CPF"
value={maskCPFCNPJ(cpf)}
onChange={handleChange('cpf')}
inputProps={{ maxLength: 14 }}
disabled
{...getErrorProps(errorState.cpf)}
/>
<TextField variant="outlined" label="Nome" value={name} onChange={handleChange('name')} /> <TextField variant="outlined" label="Nome" value={name} onChange={handleChange('name')} />
<TextField variant="outlined" label="Email" value={email} onChange={handleChange('email')} /> <TextField variant="outlined" label="Email" value={email} onChange={handleChange('email')} />
<TextField variant="outlined" label="Telefone" value={maskPhone(phone)} onChange={handleChange('phone')} inputProps={{ maxLength: 15 }} /> <TextField variant="outlined" label="Telefone" value={maskPhone(phone)} onChange={handleChange('phone')} inputProps={{ maxLength: 15 }} />
......
...@@ -4,3 +4,7 @@ export * from './Login' ...@@ -4,3 +4,7 @@ export * from './Login'
export * from './Address' export * from './Address'
export * from './FirstAccess' export * from './FirstAccess'
export * from './RGTemplate' export * from './RGTemplate'
import DocumentTemplate from './Document'
export { DocumentTemplate }
...@@ -17,6 +17,11 @@ export const initialState: Store = { ...@@ -17,6 +17,11 @@ export const initialState: Store = {
referenceTypes: { byId: {}, allIds: [] }, referenceTypes: { byId: {}, allIds: [] },
homeTypes: { byId: {}, allIds: [] }, homeTypes: { byId: {}, allIds: [] },
deedRecords: { byId: {}, allIds: [] }, deedRecords: { byId: {}, allIds: [] },
activitySectors: { byId: {}, allIds: [] },
settledOPs: { byId: {}, allIds: [] },
locals: { byId: {}, allIds: [] },
documentTypes: { byId: {}, allIds: [] },
monthRatings: { byId: {}, allIds: [] },
} }
export default createSlice({ export default createSlice({
......
...@@ -44,6 +44,7 @@ export default createSlice({ ...@@ -44,6 +44,7 @@ export default createSlice({
state.proposalId = action.payload state.proposalId = action.payload
}, },
[customerDataTypes.addIndentification.fulfilled]: (state, action: PayloadAction<Identification>) => { [customerDataTypes.addIndentification.fulfilled]: (state, action: PayloadAction<Identification>) => {
console.log(action)
state.personId = action.payload.id state.personId = action.payload.id
}, },
[customerDataTypes.getReferences.fulfilled]: (state, action: PayloadAction<GetCDReferences['Output']>) => { [customerDataTypes.getReferences.fulfilled]: (state, action: PayloadAction<GetCDReferences['Output']>) => {
......
...@@ -15,6 +15,11 @@ const contextSchemas: Record<keyof ProposalDataContext, any> = { ...@@ -15,6 +15,11 @@ const contextSchemas: Record<keyof ProposalDataContext, any> = {
referenceTypes: new schema.Array(new schema.Entity('referenceTypes')), referenceTypes: new schema.Array(new schema.Entity('referenceTypes')),
homeTypes: new schema.Array(new schema.Entity('homeTypes')), homeTypes: new schema.Array(new schema.Entity('homeTypes')),
deedRecords: new schema.Array(new schema.Entity('deedRecords')), 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) => { export const normalizeContext = (context: ProposalDataContext) => {
......
import { import {
AddBDProductService, AddBDProductService,
GetBDProductsServices, GetBDProductsServices,
UpdateBDProductService UpdateBDAddress,
UpdateBDIdentification,
UpdateBDProductService,
UpdateBDStockSalesCosts
} from '@agiliza/api/domain' } from '@agiliza/api/domain'
import { PDBusinessDataRepositoryImplFactory } from '@agiliza/api/useCases' import { PDBusinessDataRepositoryImplFactory } from '@agiliza/api/useCases'
import { appPlatform } from '@agiliza/constants/platform' import { appPlatform } from '@agiliza/constants/platform'
...@@ -54,6 +57,39 @@ export const actions = { ...@@ -54,6 +57,39 @@ export const actions = {
return thunkApi.rejectWithValue(e) 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 } as const
export const types = getTypesThunkActions(actions) export const types = getTypesThunkActions(actions)
......
...@@ -11,7 +11,7 @@ export type Formatter = (txt: string) => string ...@@ -11,7 +11,7 @@ export type Formatter = (txt: string) => string
export type FormatterState<S> = { [k in keyof S]?: Formatter | Formatter[] } export type FormatterState<S> = { [k in keyof S]?: Formatter | Formatter[] }
export type UpdatePayload<S> = { export type UpdatePayload<S> = {
[k in keyof S]: S[k] [k in keyof S]: Partial<S[k]>
} }
type FormState<S> = { type FormState<S> = {
......
...@@ -23,6 +23,19 @@ export const maskCPFCNPJ = (str?: string) => { ...@@ -23,6 +23,19 @@ export const maskCPFCNPJ = (str?: string) => {
return filteredString 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) => { export const maskCEP = (str?: string) => {
if (!str) return '' if (!str) return ''
const filteredString = extractNumbers(str) 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 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 { withStyles, WithStyles } from '@material-ui/core/styles'
import { connected, ConnectedProps } from './connect'
import Form from './Form' import Form from './Form'
import { initialState } from './state' import { BDAddressState } from './state'
import styles from './styles' 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 Address = (props: Props) => {
const { classes } = props const { classes, context, state, actions } = props
const formState = useFormState('addressData', initialState)
return ( return (
<div className={classes.contentContainer}> <div className={classes.contentContainer}>
<div className={classes.content}> <div className={classes.content}>
<Form {...formState} /> <Form state={state} actions={actions} context={context} />
</div> </div>
</div> </div>
) )
} }
export default withStyles(styles)(Address) export default connected(withStyles(styles)(Address))
import React from 'react' 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 { 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 { TextField, TextFieldProps } from '@material-ui/core'
import { withStyles, WithStyles } from '@material-ui/core/styles' import { withStyles, WithStyles } from '@material-ui/core/styles'
...@@ -13,12 +16,13 @@ type ExtendedProps = WithStyles<typeof styles> ...@@ -13,12 +16,13 @@ type ExtendedProps = WithStyles<typeof styles>
interface Props extends ExtendedProps { interface Props extends ExtendedProps {
state: BDAddressState state: BDAddressState
actions: ActionType<BDAddressState> actions: ActionType<BDAddressState>
context: AuthenticationContext
} }
const Form = (props: Props) => { 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 = const handleChangeText =
(key: keyof BDAddressState): TextFieldProps['onChange'] => (key: keyof BDAddressState): TextFieldProps['onChange'] =>
...@@ -26,9 +30,23 @@ const Form = (props: Props) => { ...@@ -26,9 +30,23 @@ const Form = (props: Props) => {
actions.update({ [key]: evt.target.value }) 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 ( return (
<form className={classes.form}> <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')} /> <TextField variant="outlined" label="Ponto de referência" value={referencePoint} onChange={handleChangeText('referencePoint')} />
</form> </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 { default } from './Address'
export * from './Address' export * from './Address'
export * from './state'
import { file } from '@agiliza/__mocks__/files'
import { BDAddress } from '@agiliza/api/domain' import { BDAddress } from '@agiliza/api/domain'
type ExtendedState = BDAddress type ExtendedState = BDAddress
export interface BDAddressState extends ExtendedState {} 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: '', proof: '',
cep: '', cep: '',
city: '', city: '',
...@@ -14,4 +30,4 @@ export const initialState: BDAddressState = { ...@@ -14,4 +30,4 @@ export const initialState: BDAddressState = {
state: '', state: '',
street: '', street: '',
referencePoint: '', referencePoint: '',
} }
import React from 'react' 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 { ActionType } from '@agiliza/utils/hooks/state'
import { maskCPFCNPJ } from '@agiliza/utils/masks' import { getBase64FromFile } from '@agiliza/utils/method'
import { DatePicker } from '@curio/components' import CPFCNPJField from '@agiliza/views/ProposalData/components/atoms/CPFCNPJField'
import { DatePicker, SelectField, SelectFieldProps } from '@curio/components'
import { TextField, TextFieldProps } from '@material-ui/core' import { TextField, TextFieldProps } from '@material-ui/core'
import { withStyles, WithStyles } from '@material-ui/core/styles' import { withStyles, WithStyles } from '@material-ui/core/styles'
...@@ -14,12 +17,26 @@ type ExtendedProps = WithStyles<typeof styles> ...@@ -14,12 +17,26 @@ type ExtendedProps = WithStyles<typeof styles>
interface Props extends ExtendedProps { interface Props extends ExtendedProps {
state: BDIdentificationState state: BDIdentificationState
actions: ActionType<BDIdentificationState> actions: ActionType<BDIdentificationState>
context: ProposalDataContext
} }
const Form = (props: Props) => { 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 = const handleChangeText =
(key: keyof BDIdentificationState): TextFieldProps['onChange'] => (key: keyof BDIdentificationState): TextFieldProps['onChange'] =>
...@@ -31,24 +48,75 @@ const Form = (props: Props) => { ...@@ -31,24 +48,75 @@ const Form = (props: Props) => {
actions.update({ [type]: date }) 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 ( return (
<form className={classes.form}> <form className={classes.form}>
<TextField <DocumentTemplate document={document} context={context} onChangeImage={handleChangeProof} onChangeDocumentType={handleChangeDocumentType} />
variant="outlined" <CPFCNPJField value={cnpj} onChange={handleChangeText('cnpj')} onlyCPNJ />
type="tel"
label="CNPJ"
value={maskCPFCNPJ(cnpj)}
onChange={handleChangeText('cnpj')}
inputProps={{ maxLength: 18 }}
/>
<DatePicker <DatePicker
id="admission-date" id="admission-date"
label="Data de admissão" label="Data da abertura"
value={openingDate} value={openingDate}
onChange={handleChangeDate('openingDate')} onChange={handleChangeDate('openingDate')}
format="dd/MM/yyyy" format="dd/MM/yyyy"
className={classes.datePicker} 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> </form>
) )
} }
......
import React from 'react' 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 { withStyles, WithStyles } from '@material-ui/core/styles'
import { connected, ConnectedProps } from './connect'
import Form from './Form' import Form from './Form'
import { initialState } from './state' import { BDIdentificationState } from './state'
import styles from './styles' 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 Identification = (props: Props) => {
const { classes } = props const { classes, context, state, actions } = props
const formState = useFormState('identificationForm', initialState)
return ( return (
<div className={classes.contentContainer}> <div className={classes.contentContainer}>
<div className={classes.content}> <div className={classes.content}>
<Form {...formState} /> <Form state={state} actions={actions} context={context} />
</div> </div>
</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 { default } from './Identification'
export * from './Identification' export * from './Identification'
export * from './state'
import { file } from '@agiliza/__mocks__/files'
import { BDIdentification } from '@agiliza/api/domain' import { BDIdentification } from '@agiliza/api/domain'
type ExtendedState = BDIdentification type ExtendedState = BDIdentification
export interface BDIdentificationState extends ExtendedState { 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: '', cnpj: '',
activitySector: '', activitySector: '',
cityRegistration: '', cityRegistration: '',
codeCNAE: '', codeCNAE: '',
companyName: '', companyName: '',
document: { extraInformations: '', id: '', url: undefined, type: { id: undefined, description: '' } }, document: { extraInformations: '', id: '', url: '', type: { id: '', description: '' } },
fantasyName: '', fantasyName: '',
local: '', local: '',
settledOP: '', settledOP: '',
...@@ -20,4 +38,4 @@ export const initialState: BDIdentificationState = { ...@@ -20,4 +38,4 @@ export const initialState: BDIdentificationState = {
commercialRegistration: '', commercialRegistration: '',
mainActivity: '', mainActivity: '',
openingDate: null, openingDate: null,
} }
import React, { useEffect } from 'react' import React, { useEffect } from 'react'
import { BDProductService } from '@agiliza/api/domain' import { BDProductService } from '@agiliza/api/domain'
import ButtonWithProgress from '@agiliza/components/atoms/ButtonWithProgress'
import { useFormState } from '@agiliza/utils/hooks/state' import { useFormState } from '@agiliza/utils/hooks/state'
import { import {
Button, Button,
...@@ -22,10 +23,11 @@ interface Props extends ExtendedProps { ...@@ -22,10 +23,11 @@ interface Props extends ExtendedProps {
onClose: () => void onClose: () => void
productService?: BDProductService productService?: BDProductService
onSave(rfc: BDProductService, add: boolean): () => void onSave(rfc: BDProductService, add: boolean): () => void
fetching: boolean
} }
const Dialog = (props: Props) => { const Dialog = (props: Props) => {
const { classes, open, onClose, onSave, productService } = props const { classes, fetching, open, onClose, onSave, productService } = props
const formState = useFormState('VehicleForm', initialState) const formState = useFormState('VehicleForm', initialState)
...@@ -48,7 +50,9 @@ const Dialog = (props: Props) => { ...@@ -48,7 +50,9 @@ const Dialog = (props: Props) => {
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={onClose}>Cancelar</Button> <Button onClick={onClose}>Cancelar</Button>
<Button onClick={onSave(mapStateToProductService(), !productService)}>Salvar</Button> <ButtonWithProgress variant="text" fetching={fetching} onClick={onSave(mapStateToProductService(), !productService)}>
Salvar
</ButtonWithProgress>
</DialogActions> </DialogActions>
</MUIDialog> </MUIDialog>
) )
......
...@@ -19,6 +19,5 @@ export default (theme: Theme) => { ...@@ -19,6 +19,5 @@ export default (theme: Theme) => {
}, },
switchCardPhotoContainer: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-evenly' }, switchCardPhotoContainer: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-evenly' },
datePicker: { marginBottom: '0px !important' }, datePicker: { marginBottom: '0px !important' },
label: { marginBottom: theme.spacing(2) },
}) })
} }
...@@ -20,25 +20,33 @@ interface Props extends ExtendedProps { ...@@ -20,25 +20,33 @@ interface Props extends ExtendedProps {
} }
const ProductsServices = (props: Props) => { const ProductsServices = (props: Props) => {
const { classes, projectId, productsServices } = props const { classes, fetching, projectId, productsServices } = props
const [selectedProductService, setSelectedProductService] = useState<BDProductService | undefined>() const [selectedProductService, setSelectedProductService] = useState<BDProductService | undefined>()
const [open, setOpen] = useState(false) const [open, setOpen] = useState(false)
const handleClickListItem = (vehicle: BDProductService) => () => { const handleClickListItem = (productService: BDProductService) => () => {
setSelectedProductService(vehicle)
setOpen(true) setOpen(true)
setSelectedProductService(productService)
} }
const handleClickAdd = () => { const handleClickAdd = () => {
setOpen(true) setOpen(true)
setSelectedProductService(undefined) setSelectedProductService(undefined)
} }
const handleClickClose = () => {
setOpen(false)
setSelectedProductService(undefined)
}
const handleSave = (productService: BDProductService, add: boolean) => () => { const handleSave = (productService: BDProductService, add: boolean) => () => {
if (add) props.addProductService({ projectId, productService, onSuccess: () => setOpen(false) }) const onSuccess = () => {
else props.updateProductService({ projectId, productServiceId: productService.id, productService, onSuccess: () => setOpen(false) }) setOpen(false)
setSelectedProductService(productService)
}
if (add) props.addProductService({ projectId, productService, onSuccess })
else props.updateProductService({ projectId, productServiceId: productService.id, productService, onSuccess })
} }
return ( return (
...@@ -62,7 +70,7 @@ const ProductsServices = (props: Props) => { ...@@ -62,7 +70,7 @@ const ProductsServices = (props: Props) => {
<Avatar className={classes.avatarBtnContainer} onClick={handleClickAdd}> <Avatar className={classes.avatarBtnContainer} onClick={handleClickAdd}>
<AddIcon /> <AddIcon />
</Avatar> </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' ...@@ -6,7 +6,6 @@ import { StoreState } from '@agiliza/redux'
import * as entProposalDataContext from '@agiliza/redux/entities/proposalData/context' import * as entProposalDataContext from '@agiliza/redux/entities/proposalData/context'
import * as entProposalData from '@agiliza/redux/entities/proposalData/proposal' import * as entProposalData from '@agiliza/redux/entities/proposalData/proposal'
import * as ucProposalData from '@agiliza/redux/useCases/proposalData/businessData' import * as ucProposalData from '@agiliza/redux/useCases/proposalData/businessData'
import * as ucProposalDataContext from '@agiliza/redux/useCases/proposalData/context'
export interface ConnectedProps { export interface ConnectedProps {
fetching: boolean fetching: boolean
...@@ -21,7 +20,7 @@ type StateProps = Pick<ConnectedProps, 'fetching' | 'context' | 'productsService ...@@ -21,7 +20,7 @@ type StateProps = Pick<ConnectedProps, 'fetching' | 'context' | 'productsService
type DispatchProps = Pick<ConnectedProps, 'getProductsServices' | 'addProductService' | 'updateProductService'> type DispatchProps = Pick<ConnectedProps, 'getProductsServices' | 'addProductService' | 'updateProductService'>
const mapStateToProps = (state: StoreState): StateProps => ({ 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), context: entProposalDataContext.selectors.getContext(state.entities.proposalData.context),
productsServices: entProposalData.selectors.getProductsServices(state.entities.proposalData.proposal), productsServices: entProposalData.selectors.getProductsServices(state.entities.proposalData.proposal),
}) })
......
import React from 'react' 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 { ActionType } from '@agiliza/utils/hooks/state'
import { maskMonthYear } from '@agiliza/utils/masks' 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 { withStyles, WithStyles } from '@material-ui/core/styles'
import { BDStockSalesCostsState } from '../state' import { BDStockSalesCostsState } from '../state'
...@@ -13,12 +18,14 @@ type ExtendedProps = WithStyles<typeof styles> ...@@ -13,12 +18,14 @@ type ExtendedProps = WithStyles<typeof styles>
interface Props extends ExtendedProps { interface Props extends ExtendedProps {
state: BDStockSalesCostsState state: BDStockSalesCostsState
actions: ActionType<BDStockSalesCostsState> actions: ActionType<BDStockSalesCostsState>
context: ProposalDataContext
productsServices: BDProductService[]
} }
const Form = (props: Props) => { 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 = const handleChangeText =
(key: keyof BDStockSalesCostsState): TextFieldProps['onChange'] => (key: keyof BDStockSalesCostsState): TextFieldProps['onChange'] =>
...@@ -26,8 +33,42 @@ const Form = (props: Props) => { ...@@ -26,8 +33,42 @@ const Form = (props: Props) => {
actions.update({ [key]: evt.target.value }) 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 ( return (
<form className={classes.form}> <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 <TextField
variant="outlined" variant="outlined"
label="Mês/Ano referência" label="Mês/Ano referência"
...@@ -36,13 +77,28 @@ const Form = (props: Props) => { ...@@ -36,13 +77,28 @@ const Form = (props: Props) => {
inputProps={{ maxLength: 7 }} inputProps={{ maxLength: 7 }}
type="tel" 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 <TextField
variant="outlined" variant="outlined"
label="Comissão vendas (%)" disabled
value={salesCommission} label="Total geral vendas"
onChange={handleChangeText('salesCommission')} value={formatCurrency(getTotalCommission(salesCommission).toFixed(2)) || ''}
inputProps={{ maxLength: 7 }}
/> />
<TextField variant="outlined" disabled label="Total geral custos var." value={formatCurrency(getTotals('variableCosts').toFixed(2)) || ''} />
</form> </form>
) )
} }
......
...@@ -19,5 +19,6 @@ export default (theme: Theme) => { ...@@ -19,5 +19,6 @@ export default (theme: Theme) => {
}, },
switchCardPhotoContainer: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-evenly' }, switchCardPhotoContainer: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-evenly' },
datePicker: { marginBottom: '0px !important' }, datePicker: { marginBottom: '0px !important' },
label: { ...sharedStyles(theme).label, textAlign: 'center' },
}) })
} }
import React from 'react' 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 { withStyles, WithStyles } from '@material-ui/core/styles'
import { connected, ConnectedProps } from './connect'
import Form from './Form' import Form from './Form'
import { initialState } from './state' import { BDStockSalesCostsState } from './state'
import styles from './styles' 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 StockSalesCosts = (props: Props) => {
const { classes } = props const { classes, context, productsServices, state, actions } = props
const formState = useFormState('stockSalesCostsForm', initialState)
return ( return (
<div className={classes.contentContainer}> <div className={classes.contentContainer}>
<div className={classes.content}> <div className={classes.content}>
<Form {...formState} /> <Form state={state} actions={actions} context={context} productsServices={productsServices} />
</div> </div>
</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 { default } from './StockSalesCosts'
export * from './StockSalesCosts' export * from './StockSalesCosts'
export * from './state'
...@@ -13,4 +13,5 @@ export default (theme: Theme) => ...@@ -13,4 +13,5 @@ export default (theme: Theme) =>
tabs: { borderRight: `1px solid ${theme.palette.divider}` }, tabs: { borderRight: `1px solid ${theme.palette.divider}` },
tabWrapper: { flexDirection: 'row' }, tabWrapper: { flexDirection: 'row' },
tabLabelIcon: { marginBottom: '0px !important', marginRight: theme.spacing(1) }, tabLabelIcon: { marginBottom: '0px !important', marginRight: theme.spacing(1) },
label: { marginBottom: theme.spacing(2) },
}) })
...@@ -38,7 +38,7 @@ const Form = (props: Props) => { ...@@ -38,7 +38,7 @@ const Form = (props: Props) => {
return ( return (
<form className={classes.form}> <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} /> <Address state={state} onChange={handleChangeAddress} states={states} cities={cities} />
</form> </form>
) )
......
...@@ -64,7 +64,7 @@ const Form = (props: Props) => { ...@@ -64,7 +64,7 @@ const Form = (props: Props) => {
<Switch label="Possui imóveis?" value={hasProperty} onChange={(vl) => actions.update({ hasProperty: vl })} required /> <Switch label="Possui imóveis?" value={hasProperty} onChange={(vl) => actions.update({ hasProperty: vl })} required />
{hasProperty ? ( {hasProperty ? (
<> <>
<ImageUpload label="Escritura" image={deed} onChangeImage={handleChangeProof} className={classes.imageUpload} /> <ImageUpload label="Escritura" image={deed} onChangeImage={handleChangeProof} />
<SelectField <SelectField
id="type-select-field" id="type-select-field"
label="Tipo" label="Tipo"
......
...@@ -3,7 +3,7 @@ import React from 'react' ...@@ -3,7 +3,7 @@ import React from 'react'
import { BanestesAccount, DataType, ProposalDataContext } from '@agiliza/api/domain' import { BanestesAccount, DataType, ProposalDataContext } from '@agiliza/api/domain'
import AccountInputsPhoto from '@agiliza/components/templates/AccountInputsPhoto' import AccountInputsPhoto from '@agiliza/components/templates/AccountInputsPhoto'
import { ActionType } from '@agiliza/utils/hooks/state' 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 { SelectField, SelectFieldProps } from '@curio/components'
import { FormControlLabel, Switch, TextField, TextFieldProps } from '@material-ui/core' import { FormControlLabel, Switch, TextField, TextFieldProps } from '@material-ui/core'
import { withStyles, WithStyles } from '@material-ui/core/styles' import { withStyles, WithStyles } from '@material-ui/core/styles'
...@@ -64,7 +64,7 @@ const Form = (props: Props) => { ...@@ -64,7 +64,7 @@ const Form = (props: Props) => {
variant="outlined" variant="outlined"
shrink={false} 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')} /> <TextField variant="outlined" label="Nome / Razão social" value={name || ''} onChange={handleChangeText('name')} />
<SelectField <SelectField
id="gender-select-field" id="gender-select-field"
...@@ -77,7 +77,7 @@ const Form = (props: Props) => { ...@@ -77,7 +77,7 @@ const Form = (props: Props) => {
/> />
<div className={classes.switchCardPhotoContainer}> <div className={classes.switchCardPhotoContainer}>
<FormControlLabel <FormControlLabel
label="Possui conta no Banestes?" label="Possui conta na entidade?"
control={ control={
<Switch <Switch
checked={hasAccount} checked={hasAccount}
......
...@@ -18,6 +18,7 @@ interface Props extends ExtendedProps { ...@@ -18,6 +18,7 @@ interface Props extends ExtendedProps {
const Identification = (props: Props) => { const Identification = (props: Props) => {
const { classes, context, state, actions } = props const { classes, context, state, actions } = props
return ( return (
<div className={classes.contentContainer}> <div className={classes.contentContainer}>
<div className={classes.content}> <div className={classes.content}>
......
import React, { useEffect } from 'react' import React, { useEffect } from 'react'
import { ProposalDataContext, Reference } from '@agiliza/api/domain' import { ProposalDataContext, Reference } from '@agiliza/api/domain'
import ButtonWithProgress from '@agiliza/components/atoms/ButtonWithProgress'
import { ActionType } from '@agiliza/utils/hooks/state' import { ActionType } from '@agiliza/utils/hooks/state'
import { import {
Button, Button,
...@@ -25,10 +26,11 @@ interface Props extends ExtendedProps { ...@@ -25,10 +26,11 @@ interface Props extends ExtendedProps {
reference?: Reference reference?: Reference
onSave(rfc: Reference, add: boolean): () => void onSave(rfc: Reference, add: boolean): () => void
context: ProposalDataContext context: ProposalDataContext
fetching: boolean
} }
const Dialog = (props: Props) => { 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(() => { useEffect(() => {
if (reference) actions.update(reference) if (reference) actions.update(reference)
...@@ -47,7 +49,9 @@ const Dialog = (props: Props) => { ...@@ -47,7 +49,9 @@ const Dialog = (props: Props) => {
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={onClose}>Cancelar</Button> <Button onClick={onClose}>Cancelar</Button>
<Button onClick={onSave(mapStateToReference(), !reference)}>Salvar</Button> <ButtonWithProgress variant="text" fetching={fetching} onClick={onSave(mapStateToReference(), !reference)}>
Salvar
</ButtonWithProgress>
</DialogActions> </DialogActions>
</MUIDialog> </MUIDialog>
) )
......
...@@ -40,20 +40,20 @@ const Form = (props: Props) => { ...@@ -40,20 +40,20 @@ const Form = (props: Props) => {
} }
const handleChangeSelect = const handleChangeSelect =
(key: keyof Pick<CDReferenceState, 'photo'>): SelectFieldProps['onChange'] => (key: keyof Pick<CDReferenceState, 'type'>): SelectFieldProps['onChange'] =>
(value) => { (value) => {
actions.update({ [key]: value }) actions.update({ [key]: value })
} }
return ( return (
<form className={classes.form}> <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 <SelectField
id="type-select" id="type-select"
variant="outlined" variant="outlined"
label="Tipo" label="Tipo"
value={type} value={type}
onChange={handleChangeSelect('photo')} onChange={handleChangeSelect('type')}
items={context.referenceTypes.map((st) => ({ label: st.description, value: st.id }))} items={context.referenceTypes.map((st) => ({ label: st.description, value: st.id }))}
shrink={false} shrink={false}
// className={classes.selectField} // className={classes.selectField}
......
...@@ -21,7 +21,9 @@ interface Props extends ExtendedProps { ...@@ -21,7 +21,9 @@ interface Props extends ExtendedProps {
} }
const References = (props: Props) => { 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>() const [selectedReference, setSelectedReference] = useState<Reference | undefined>()
...@@ -32,22 +34,30 @@ const References = (props: Props) => { ...@@ -32,22 +34,30 @@ const References = (props: Props) => {
}, []) }, [])
const handleClickListItem = (reference: Reference) => () => { const handleClickListItem = (reference: Reference) => () => {
setSelectedReference(reference)
setOpen(true) setOpen(true)
setSelectedReference(reference)
} }
const handleClickAdd = () => { const handleClickAdd = () => {
setOpen(true) setOpen(true)
setSelectedReference(undefined) setSelectedReference(undefined)
} }
const handleClickClose = () => {
setOpen(false)
setSelectedReference(undefined)
}
const handleSave = (reference: Reference, add: boolean) => () => { const handleSave = (reference: Reference, add: boolean) => () => {
const onSuccess = () => {
setOpen(false)
setSelectedReference(reference)
}
if (add) if (add)
props.addReference({ props.addReference({
projectId, projectId,
personId, personId,
reference, reference,
onSuccess: () => setOpen(false), onSuccess,
}) })
else else
props.updateReference({ props.updateReference({
...@@ -55,7 +65,7 @@ const References = (props: Props) => { ...@@ -55,7 +65,7 @@ const References = (props: Props) => {
personId, personId,
referenceId: reference.id, referenceId: reference.id,
reference, reference,
onSuccess: () => setOpen(false), onSuccess,
}) })
} }
...@@ -81,8 +91,9 @@ const References = (props: Props) => { ...@@ -81,8 +91,9 @@ const References = (props: Props) => {
<AddIcon /> <AddIcon />
</Avatar> </Avatar>
<Dialog <Dialog
fetching={fetching}
open={open} open={open}
onClose={() => setOpen(false)} onClose={handleClickClose}
reference={selectedReference} reference={selectedReference}
onSave={handleSave} onSave={handleSave}
context={context} context={context}
......
...@@ -5,7 +5,6 @@ import { ProposalDataContext, Reference } from '@agiliza/api/domain' ...@@ -5,7 +5,6 @@ import { ProposalDataContext, Reference } from '@agiliza/api/domain'
import { StoreState } from '@agiliza/redux' import { StoreState } from '@agiliza/redux'
import * as entProposalDataContext from '@agiliza/redux/entities/proposalData/context' import * as entProposalDataContext from '@agiliza/redux/entities/proposalData/context'
import * as entProposalData from '@agiliza/redux/entities/proposalData/proposal' 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' import * as ucProposalData from '@agiliza/redux/useCases/proposalData/customerData'
export interface ConnectedProps { export interface ConnectedProps {
...@@ -21,7 +20,7 @@ type StateProps = Pick<ConnectedProps, 'fetching' | 'context' | 'references'> ...@@ -21,7 +20,7 @@ type StateProps = Pick<ConnectedProps, 'fetching' | 'context' | 'references'>
type DispatchProps = Pick<ConnectedProps, 'getReferences' | 'addReference' | 'updateReference'> type DispatchProps = Pick<ConnectedProps, 'getReferences' | 'addReference' | 'updateReference'>
const mapStateToProps = (state: StoreState): StateProps => ({ 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), context: entProposalDataContext.selectors.getContext(state.entities.proposalData.context),
references: entProposalData.selectors.getReferences(state.entities.proposalData.proposal), references: entProposalData.selectors.getReferences(state.entities.proposalData.proposal),
}) })
......
...@@ -5,8 +5,9 @@ import ImageUpload from '@agiliza/components/organisms/ImageUpload' ...@@ -5,8 +5,9 @@ import ImageUpload from '@agiliza/components/organisms/ImageUpload'
import Address, { AddressState } from '@agiliza/components/templates/Address' import Address, { AddressState } from '@agiliza/components/templates/Address'
import { formatCurrency } from '@agiliza/utils/formatters' import { formatCurrency } from '@agiliza/utils/formatters'
import { ActionType } from '@agiliza/utils/hooks/state' 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 { getBase64FromFile } from '@agiliza/utils/method'
import CPFCNPJField from '@agiliza/views/ProposalData/components/atoms/CPFCNPJField'
import { DatePicker } from '@curio/components' import { DatePicker } from '@curio/components'
import { TextField, TextFieldProps } from '@material-ui/core' import { TextField, TextFieldProps } from '@material-ui/core'
import { withStyles, WithStyles } from '@material-ui/core/styles' import { withStyles, WithStyles } from '@material-ui/core/styles'
...@@ -52,7 +53,7 @@ const Form = (props: Props) => { ...@@ -52,7 +53,7 @@ const Form = (props: Props) => {
return ( return (
<form className={classes.form}> <form className={classes.form}>
<TextField variant="outlined" label="Razão social" value={companyName} onChange={handleChangeText('companyName')} /> <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 <DatePicker
id="admission-date" id="admission-date"
label="Data de admissão" label="Data de admissão"
...@@ -61,7 +62,7 @@ const Form = (props: Props) => { ...@@ -61,7 +62,7 @@ const Form = (props: Props) => {
format="dd/MM/yyyy" format="dd/MM/yyyy"
className={classes.datePicker} 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="Telefone" value={maskPhone(mobile)} onChange={handleChangeText('mobile')} />
<TextField variant="outlined" label="Renda líquida" value={formatCurrency(netIncome)} onChange={handleChangeText('netIncome')} /> <TextField variant="outlined" label="Renda líquida" value={formatCurrency(netIncome)} onChange={handleChangeText('netIncome')} />
<Address state={address} onChange={handleChangeAddress} states={context.states} cities={context.cities} /> <Address state={address} onChange={handleChangeAddress} states={context.states} cities={context.cities} />
......
...@@ -4,8 +4,9 @@ import { Workplace } from '@agiliza/api/domain' ...@@ -4,8 +4,9 @@ import { Workplace } from '@agiliza/api/domain'
import ImageUpload from '@agiliza/components/organisms/ImageUpload' import ImageUpload from '@agiliza/components/organisms/ImageUpload'
import { formatCurrency } from '@agiliza/utils/formatters' import { formatCurrency } from '@agiliza/utils/formatters'
import { ActionType } from '@agiliza/utils/hooks/state' 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 { getBase64FromFile } from '@agiliza/utils/method'
import CPFCNPJField from '@agiliza/views/ProposalData/components/atoms/CPFCNPJField'
import { DatePicker } from '@curio/components' import { DatePicker } from '@curio/components'
import { TextField, TextFieldProps, Typography } from '@material-ui/core' import { TextField, TextFieldProps, Typography } from '@material-ui/core'
import { withStyles, WithStyles } from '@material-ui/core/styles' import { withStyles, WithStyles } from '@material-ui/core/styles'
...@@ -59,14 +60,8 @@ const Form = (props: Props) => { ...@@ -59,14 +60,8 @@ const Form = (props: Props) => {
Local de trabalho Local de trabalho
</Typography> </Typography>
<TextField variant="outlined" label="Razão social" value={workplace?.workplaceName || ''} onChange={handleChangeWorkplace('workplaceName')} /> <TextField variant="outlined" label="Razão social" value={workplace?.workplaceName || ''} onChange={handleChangeWorkplace('workplaceName')} />
<ImageUpload label="Comprovante" image={workplace?.proof || ''} onChangeImage={handleChangePhoto} className={classes.imageUpload} /> <ImageUpload label="Comprovante" image={workplace?.proof || ''} onChangeImage={handleChangePhoto} />
<TextField <CPFCNPJField value={workplace?.cnpj || ''} onChange={handleChangeWorkplace('cnpj')} onlyCPNJ />
variant="outlined"
label="CNPJ"
value={maskCPFCNPJ(workplace?.cnpj || '')}
onChange={handleChangeWorkplace('cnpj')}
inputProps={{ maxLength: 18 }}
/>
<DatePicker <DatePicker
id="admission-date" id="admission-date"
label="Data de admissão" label="Data de admissão"
......
...@@ -4,8 +4,8 @@ import { ProposalDataContext } from '@agiliza/api/domain' ...@@ -4,8 +4,8 @@ import { ProposalDataContext } from '@agiliza/api/domain'
import ImageUpload from '@agiliza/components/organisms/ImageUpload' import ImageUpload from '@agiliza/components/organisms/ImageUpload'
import RGTemplate from '@agiliza/components/templates/RGTemplate' import RGTemplate from '@agiliza/components/templates/RGTemplate'
import { ActionType } from '@agiliza/utils/hooks/state' import { ActionType } from '@agiliza/utils/hooks/state'
import { maskCPFCNPJ } from '@agiliza/utils/masks'
import { extractNumbers, getBase64FromFile } from '@agiliza/utils/method' 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 { DatePicker, SelectField, SelectFieldProps, Switch } from '@curio/components'
import { TextField, TextFieldProps } from '@material-ui/core' import { TextField, TextFieldProps } from '@material-ui/core'
import { withStyles, WithStyles } from '@material-ui/core/styles' import { withStyles, WithStyles } from '@material-ui/core/styles'
...@@ -70,8 +70,8 @@ const Form = (props: Props) => { ...@@ -70,8 +70,8 @@ const Form = (props: Props) => {
return ( return (
<form className={classes.form}> <form className={classes.form}>
<TextField variant="outlined" label="CPF" value={maskCPFCNPJ(cpf)} onChange={handleChangeText('cpf')} inputProps={{ maxLength: 14 }} /> <CPFCNPJField value={cpf} onChange={handleChangeText('cpf')} onlyCPF />
<ImageUpload label="Certidão de casamento" image={marriageCertificate} onChangeImage={handleChangeProof} className={classes.imageUpload} /> <ImageUpload label="Certidão de casamento" image={marriageCertificate} onChangeImage={handleChangeProof} />
<TextField variant="outlined" label="Nome" value={name} onChange={handleChangeText('name')} /> <TextField variant="outlined" label="Nome" value={name} onChange={handleChangeText('name')} />
<RGTemplate rg={rg} onChange={handleChangeRG} /> <RGTemplate rg={rg} onChange={handleChangeRG} />
<DatePicker <DatePicker
......
import React, { useEffect } from 'react' import React, { useEffect } from 'react'
import { Vehicle } from '@agiliza/api/domain' import { Vehicle } from '@agiliza/api/domain'
import ButtonWithProgress from '@agiliza/components/atoms/ButtonWithProgress'
import { useFormState } from '@agiliza/utils/hooks/state' import { useFormState } from '@agiliza/utils/hooks/state'
import { import {
Button, Button,
...@@ -22,10 +23,11 @@ interface Props extends ExtendedProps { ...@@ -22,10 +23,11 @@ interface Props extends ExtendedProps {
onClose: () => void onClose: () => void
vehicle?: Vehicle vehicle?: Vehicle
onSave(rfc: Vehicle, add: boolean): () => void onSave(rfc: Vehicle, add: boolean): () => void
fetching: boolean
} }
const Dialog = (props: Props) => { const Dialog = (props: Props) => {
const { classes, open, onClose, onSave, vehicle } = props const { classes, fetching, open, onClose, onSave, vehicle } = props
const formState = useFormState('VehicleForm', initialState) const formState = useFormState('VehicleForm', initialState)
...@@ -48,7 +50,9 @@ const Dialog = (props: Props) => { ...@@ -48,7 +50,9 @@ const Dialog = (props: Props) => {
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={onClose}>Cancelar</Button> <Button onClick={onClose}>Cancelar</Button>
<Button onClick={onSave(mapStateToVehicle(), !vehicle)}>Salvar</Button> <ButtonWithProgress variant="text" fetching={fetching} onClick={onSave(mapStateToVehicle(), !vehicle)}>
Salvar
</ButtonWithProgress>
</DialogActions> </DialogActions>
</MUIDialog> </MUIDialog>
) )
......
...@@ -21,15 +21,15 @@ interface Props extends ExtendedProps { ...@@ -21,15 +21,15 @@ interface Props extends ExtendedProps {
} }
const Vehicles = (props: Props) => { const Vehicles = (props: Props) => {
const { classes, projectId, personId, vehicles } = props const { classes, fetching, projectId, personId, vehicles } = props
const [selectedVehicle, setSelectedVehicle] = useState<Vehicle | undefined>() const [selectedVehicle, setSelectedVehicle] = useState<Vehicle | undefined>()
const [open, setOpen] = useState(false) const [open, setOpen] = useState(false)
const handleClickListItem = (vehicle: Vehicle) => () => { const handleClickListItem = (vehicle: Vehicle) => () => {
setSelectedVehicle(vehicle)
setOpen(true) setOpen(true)
setSelectedVehicle(vehicle)
} }
const handleClickAdd = () => { const handleClickAdd = () => {
...@@ -37,13 +37,22 @@ const Vehicles = (props: Props) => { ...@@ -37,13 +37,22 @@ const Vehicles = (props: Props) => {
setSelectedVehicle(undefined) setSelectedVehicle(undefined)
} }
const handleClickClose = () => {
setOpen(false)
setSelectedVehicle(undefined)
}
const handleSave = (vehicle: Vehicle, add: boolean) => () => { const handleSave = (vehicle: Vehicle, add: boolean) => () => {
const onSuccess = () => {
setOpen(false)
setSelectedVehicle(vehicle)
}
if (add) if (add)
props.addVehicle({ props.addVehicle({
projectId, projectId,
personId, personId,
vehicle, vehicle,
onSuccess: () => setOpen(false), onSuccess,
}) })
else else
props.updateVehicle({ props.updateVehicle({
...@@ -51,7 +60,7 @@ const Vehicles = (props: Props) => { ...@@ -51,7 +60,7 @@ const Vehicles = (props: Props) => {
personId, personId,
vehicleId: vehicle.id, vehicleId: vehicle.id,
vehicle, vehicle,
onSuccess: () => setOpen(false), onSuccess,
}) })
} }
...@@ -76,7 +85,7 @@ const Vehicles = (props: Props) => { ...@@ -76,7 +85,7 @@ const Vehicles = (props: Props) => {
<Avatar className={classes.avatarBtnContainer} onClick={handleClickAdd}> <Avatar className={classes.avatarBtnContainer} onClick={handleClickAdd}>
<AddIcon /> <AddIcon />
</Avatar> </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' ...@@ -5,7 +5,6 @@ import { ProposalDataContext, Vehicle } from '@agiliza/api/domain'
import { StoreState } from '@agiliza/redux' import { StoreState } from '@agiliza/redux'
import * as entProposalDataContext from '@agiliza/redux/entities/proposalData/context' import * as entProposalDataContext from '@agiliza/redux/entities/proposalData/context'
import * as entProposalData from '@agiliza/redux/entities/proposalData/proposal' 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' import * as ucProposalData from '@agiliza/redux/useCases/proposalData/customerData'
export interface ConnectedProps { export interface ConnectedProps {
...@@ -21,7 +20,7 @@ type StateProps = Pick<ConnectedProps, 'fetching' | 'context' | 'vehicles'> ...@@ -21,7 +20,7 @@ type StateProps = Pick<ConnectedProps, 'fetching' | 'context' | 'vehicles'>
type DispatchProps = Pick<ConnectedProps, 'getVehicles' | 'addVehicle' | 'updateVehicle'> type DispatchProps = Pick<ConnectedProps, 'getVehicles' | 'addVehicle' | 'updateVehicle'>
const mapStateToProps = (state: StoreState): StateProps => ({ 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), context: entProposalDataContext.selectors.getContext(state.entities.proposalData.context),
vehicles: entProposalData.selectors.getVehicles(state.entities.proposalData.proposal), vehicles: entProposalData.selectors.getVehicles(state.entities.proposalData.proposal),
}) })
......
import { file } from '@agiliza/__mocks__/files'
import { Vehicle } from '@agiliza/api/domain' import { Vehicle } from '@agiliza/api/domain'
type ExtendedState = Vehicle type ExtendedState = Vehicle
export interface CDVehicleState extends ExtendedState {} 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: '', id: '',
brand: '', brand: '',
document: '', document: '',
...@@ -14,4 +28,4 @@ export const initialState: CDVehicleState = { ...@@ -14,4 +28,4 @@ export const initialState: CDVehicleState = {
marketValue: '', marketValue: '',
model: '', model: '',
year: '', year: '',
} }
...@@ -4,7 +4,7 @@ import { frameworks, genders } from '@agiliza/__mocks__/proposalData' ...@@ -4,7 +4,7 @@ import { frameworks, genders } from '@agiliza/__mocks__/proposalData'
import { BanestesAccount, DataType } from '@agiliza/api/domain' import { BanestesAccount, DataType } from '@agiliza/api/domain'
import AccountInputsPhoto from '@agiliza/components/templates/AccountInputsPhoto' import AccountInputsPhoto from '@agiliza/components/templates/AccountInputsPhoto'
import { ActionType } from '@agiliza/utils/hooks/state' 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 { SelectField, SelectFieldProps } from '@curio/components'
import { FormControlLabel, Switch, TextField, TextFieldProps } from '@material-ui/core' import { FormControlLabel, Switch, TextField, TextFieldProps } from '@material-ui/core'
import { withStyles, WithStyles } from '@material-ui/core/styles' import { withStyles, WithStyles } from '@material-ui/core/styles'
...@@ -64,13 +64,7 @@ const Customer = (props: Props) => { ...@@ -64,13 +64,7 @@ const Customer = (props: Props) => {
variant="outlined" variant="outlined"
shrink={false} shrink={false}
/> />
<TextField <CPFCNPJField value={cpfcnpj} onChange={handleChangeText('cpfcnpj')} />
variant="outlined"
label="CPF / CNPJ"
value={maskCPFCNPJ(cpfcnpj)}
onChange={handleChangeText('cpfcnpj')}
inputProps={{ maxLength: 18 }}
/>
<TextField variant="outlined" label="Nome / Razão social" value={name || ''} onChange={handleChangeText('name')} /> <TextField variant="outlined" label="Nome / Razão social" value={name || ''} onChange={handleChangeText('name')} />
<SelectField <SelectField
id="gender-select-field" id="gender-select-field"
......
...@@ -22,12 +22,16 @@ import { ...@@ -22,12 +22,16 @@ import {
ZoomOutMap as ZoomOutMapIcon ZoomOutMap as ZoomOutMapIcon
} from '@material-ui/icons' } from '@material-ui/icons'
import BDAddress from './BusinessData/Address' import BDAddress, { initialState as bdAddressInitState } from './BusinessData/Address'
import BDIdentification from './BusinessData/Identification' import BDIdentification, {
initialState as bdIdentificationInitState
} from './BusinessData/Identification'
import ProductsServices, { import ProductsServices, {
initialState as bdProductServiceInitState initialState as bdProductServiceInitState
} from './BusinessData/ProductsServices' } from './BusinessData/ProductsServices'
import StockSalesCosts from './BusinessData/StockSalesCosts' import StockSalesCosts, {
initialState as bdStockSalesCostsInitState
} from './BusinessData/StockSalesCosts'
import { connected, ConnectedProps } from './connect' import { connected, ConnectedProps } from './connect'
import Address, { initialState as cdAddressInitState } from './CustomerData/Address' import Address, { initialState as cdAddressInitState } from './CustomerData/Address'
import Home, { initialState as cdHomeInitState } from './CustomerData/Home' import Home, { initialState as cdHomeInitState } from './CustomerData/Home'
...@@ -55,8 +59,8 @@ type ExtendedProps = WithStyles<typeof styles> & RouteComponentProps & Connected ...@@ -55,8 +59,8 @@ type ExtendedProps = WithStyles<typeof styles> & RouteComponentProps & Connected
interface Props extends ExtendedProps {} interface Props extends ExtendedProps {}
const ProposalData = (props: Props) => { const ProposalData = (props: Props) => {
const { classes, fetching, proposalId, personId } = props const { classes, history, fetching, proposalId, personId } = props
const [activeStep, setActiveStep] = useState(12) const [activeStep, setActiveStep] = useState(0)
useEffect(() => { useEffect(() => {
props.fetchContext() props.fetchContext()
...@@ -66,12 +70,15 @@ const ProposalData = (props: Props) => { ...@@ -66,12 +70,15 @@ const ProposalData = (props: Props) => {
const cdIdentification = useFormState('cdIdentificationState', cdIdentInitState) const cdIdentification = useFormState('cdIdentificationState', cdIdentInitState)
const cdPersonalData = useFormState('cdPersonalDataState', cdPersonalDataInitState) const cdPersonalData = useFormState('cdPersonalDataState', cdPersonalDataInitState)
const cdAddress = useFormState('cdAddressState', cdAddressInitState) const cdAddress = useFormState('cdAddressState', cdAddressInitState)
const cdSourceIncome = useFormState('cdAddressState', cdSourceIncomeInitState) const cdSourceIncome = useFormState('cdSourceIncome', cdSourceIncomeInitState)
const cdSpouseData = useFormState('cdAddressState', cdSpouseDataInitState) const cdSpouseData = useFormState('cdSpouseData', cdSpouseDataInitState)
const cdReference = useFormState('cdSpoudeAddDataState', cdReferenceInitState) const cdReference = useFormState('cdReference', cdReferenceInitState)
const cdHomeState = useFormState('cdHomeState', cdHomeInitState) const cdHomeState = useFormState('cdHomeState', cdHomeInitState)
const cdVehicleState = useFormState('cdVehicleState', cdVehicleInitState) 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 bdProductServiceState = useFormState('bdProductServiceState', bdProductServiceInitState)
const customerDataItems = useMemo( const customerDataItems = useMemo(
...@@ -107,16 +114,24 @@ const ProposalData = (props: Props) => { ...@@ -107,16 +114,24 @@ const ProposalData = (props: Props) => {
const businessDataItems = useMemo( const businessDataItems = useMemo(
() => [ () => [
{ label: 'Identificação', icon: <AccountBoxIcon />, component: <BDIdentification /> }, {
{ label: 'Endereço', icon: <ApartmentIcon />, component: <BDAddress /> }, label: 'Identificação',
{ label: 'Estoque, Vendas e Custos', icon: <AttachMoneyIcon />, component: <StockSalesCosts /> }, 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', label: 'Produto',
icon: <InsertDriveFileIcon />, icon: <InsertDriveFileIcon />,
component: <ProductsServices projectId={proposalId} state={bdProductServiceState.state} actions={bdProductServiceState.actions} />, 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]) const proposalDataItems = useMemo(() => [...customerDataItems, ...businessDataItems], [customerDataItems, businessDataItems])
...@@ -143,7 +158,7 @@ const ProposalData = (props: Props) => { ...@@ -143,7 +158,7 @@ const ProposalData = (props: Props) => {
}) })
break break
case 2: case 2:
props.updateAddress({ props.updateCDAddress({
...projectPersonIds, ...projectPersonIds,
address: cdAddress.state, address: cdAddress.state,
onSuccess: () => setActiveStep((prevActiveStep) => prevActiveStep + 1), onSuccess: () => setActiveStep((prevActiveStep) => prevActiveStep + 1),
...@@ -177,6 +192,30 @@ const ProposalData = (props: Props) => { ...@@ -177,6 +192,30 @@ const ProposalData = (props: Props) => {
onSuccess: () => setActiveStep((prevActiveStep) => prevActiveStep + 1), onSuccess: () => setActiveStep((prevActiveStep) => prevActiveStep + 1),
}) })
break 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: default:
setActiveStep((prevActiveStep) => prevActiveStep + 1) setActiveStep((prevActiveStep) => prevActiveStep + 1)
} }
...@@ -212,7 +251,7 @@ const ProposalData = (props: Props) => { ...@@ -212,7 +251,7 @@ const ProposalData = (props: Props) => {
activeStep={activeStep} activeStep={activeStep}
style={{ width: '100%' }} style={{ width: '100%' }}
nextButton={ 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 ? ( {activeStep === steps - 1 ? (
'Finalizar' 'Finalizar'
) : ( ) : (
...@@ -221,20 +260,13 @@ const ProposalData = (props: Props) => { ...@@ -221,20 +260,13 @@ const ProposalData = (props: Props) => {
<KeyboardArrowRightIcon /> <KeyboardArrowRightIcon />
</> </>
)} )}
</Button> </ButtonWithProgress>
} }
backButton={ backButton={
<ButtonWithProgress <Button size="large" onClick={handleBack} disabled={activeStep === 0} className={classes.stepperBtn}>
fetching={fetching}
size="large"
variant="text"
onClick={handleBack}
disabled={activeStep === 0}
className={classes.stepperBtn}
>
<KeyboardArrowLeftIcon /> <KeyboardArrowLeftIcon />
Anterior Anterior
</ButtonWithProgress> </Button>
} }
/> />
{/* </Stepper> */} {/* </Stepper> */}
......
...@@ -4,38 +4,56 @@ import { bindActionCreators, Dispatch } from 'redux' ...@@ -4,38 +4,56 @@ import { bindActionCreators, Dispatch } from 'redux'
import { StoreState } from '@agiliza/redux' import { StoreState } from '@agiliza/redux'
import * as entProposal from '@agiliza/redux/entities/proposalData/proposal' import * as entProposal from '@agiliza/redux/entities/proposalData/proposal'
import * as ucAuthentication from '@agiliza/redux/useCases/authentication' 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 ucProposalDataContext from '@agiliza/redux/useCases/proposalData/context'
import * as ucProposalDataCD from '@agiliza/redux/useCases/proposalData/customerData' import * as ucProposalDataCD from '@agiliza/redux/useCases/proposalData/customerData'
import { createSelector } from '@reduxjs/toolkit'
export interface ConnectedProps { export interface ConnectedProps {
fetching: boolean fetching: boolean
proposalId: string proposalId: string
personId: string personId: string
reset: () => void
fetchContext: typeof ucProposalDataContext.actions.fetchContext fetchContext: typeof ucProposalDataContext.actions.fetchContext
getContextAddress: typeof ucAuthentication.actions.getContext getContextAddress: typeof ucAuthentication.actions.getContext
addIndentification: typeof ucProposalDataCD.actions.addIndentification addIndentification: typeof ucProposalDataCD.actions.addIndentification
updatePersonalData: typeof ucProposalDataCD.actions.updatePersonalData updatePersonalData: typeof ucProposalDataCD.actions.updatePersonalData
updateAddress: typeof ucProposalDataCD.actions.updateAddress updateCDAddress: typeof ucProposalDataCD.actions.updateAddress
updateSourceIncome: typeof ucProposalDataCD.actions.updateSourceIncome updateSourceIncome: typeof ucProposalDataCD.actions.updateSourceIncome
updateSpouseData: typeof ucProposalDataCD.actions.updateSpouseData updateSpouseData: typeof ucProposalDataCD.actions.updateSpouseData
updateHome: typeof ucProposalDataCD.actions.updateHome 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 StateProps = Pick<ConnectedProps, 'fetching' | 'proposalId' | 'personId'>
type DispatchProps = Pick< type DispatchProps = Pick<
ConnectedProps, ConnectedProps,
| 'reset'
| 'addIndentification' | 'addIndentification'
| 'fetchContext' | 'fetchContext'
| 'updatePersonalData' | 'updatePersonalData'
| 'updateAddress' | 'updateCDAddress'
| 'getContextAddress' | 'getContextAddress'
| 'updateSourceIncome' | 'updateSourceIncome'
| 'updateSpouseData' | 'updateSpouseData'
| 'updateHome' | '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 => ({ const mapStateToProps = (state: StoreState): StateProps => ({
fetching: ucProposalDataContext.selectors.isFetching(state.ui.login), fetching: isFetching(state),
proposalId: entProposal.selectors.getProposalId(state.entities.proposalData.proposal), proposalId: entProposal.selectors.getProposalId(state.entities.proposalData.proposal),
personId: entProposal.selectors.getPersonlId(state.entities.proposalData.proposal), personId: entProposal.selectors.getPersonlId(state.entities.proposalData.proposal),
}) })
...@@ -43,14 +61,18 @@ const mapStateToProps = (state: StoreState): StateProps => ({ ...@@ -43,14 +61,18 @@ const mapStateToProps = (state: StoreState): StateProps => ({
const mapDispatchToProps = (dispatch: Dispatch): DispatchProps => const mapDispatchToProps = (dispatch: Dispatch): DispatchProps =>
bindActionCreators( bindActionCreators(
{ {
reset: () => ({ type: 'RESET_STORE' }),
addIndentification: ucProposalDataCD.actions.addIndentification, addIndentification: ucProposalDataCD.actions.addIndentification,
fetchContext: ucProposalDataContext.actions.fetchContext, fetchContext: ucProposalDataContext.actions.fetchContext,
updatePersonalData: ucProposalDataCD.actions.updatePersonalData, updatePersonalData: ucProposalDataCD.actions.updatePersonalData,
updateAddress: ucProposalDataCD.actions.updateAddress, updateCDAddress: ucProposalDataCD.actions.updateAddress,
getContextAddress: ucAuthentication.actions.getContext, getContextAddress: ucAuthentication.actions.getContext,
updateSourceIncome: ucProposalDataCD.actions.updateSourceIncome, updateSourceIncome: ucProposalDataCD.actions.updateSourceIncome,
updateSpouseData: ucProposalDataCD.actions.updateSpouseData, updateSpouseData: ucProposalDataCD.actions.updateSpouseData,
updateHome: ucProposalDataCD.actions.updateHome, updateHome: ucProposalDataCD.actions.updateHome,
updateBDAddress: ucProposalDataBD.actions.updateAddress,
updateIdentification: ucProposalDataBD.actions.updateIdentification,
updateStockSalesCosts: ucProposalDataBD.actions.updateStockSalesCosts,
}, },
dispatch dispatch
) )
......
...@@ -30,5 +30,4 @@ export default (theme: Theme) => ...@@ -30,5 +30,4 @@ export default (theme: Theme) =>
width: '30%', width: '30%',
height: '100%', height: '100%',
}, },
imageUpload: { width: '100%', textAlign: 'center', marginTop: theme.spacing(1), marginBottom: theme.spacing(1) },
}) })
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import { RouteComponentProps, useHistory } from 'react-router' import { RouteComponentProps, useHistory } from 'react-router'
import { destinations } from '@agiliza/__mocks__/creditLines'
import { SimulationCategory } from '@agiliza/api/domain' import { SimulationCategory } from '@agiliza/api/domain'
import { extractCurrency, extractNumbers } from '@agiliza/utils/extractors' import { extractCurrency, extractNumbers } from '@agiliza/utils/extractors'
import { formatCurrency } from '@agiliza/utils/formatters' import { formatCurrency } from '@agiliza/utils/formatters'
import { SelectField } from '@curio/components'
import { import {
Button, Button,
CircularProgress, CircularProgress,
...@@ -41,6 +43,7 @@ const CreditLinesList = (props: Props) => { ...@@ -41,6 +43,7 @@ const CreditLinesList = (props: Props) => {
const [amount, setAmount] = useState('0') const [amount, setAmount] = useState('0')
const [paymentMonths, setPaymentMonths] = useState(0) const [paymentMonths, setPaymentMonths] = useState(0)
const [graceMonths, setGraceMonths] = useState(0) const [graceMonths, setGraceMonths] = useState(0)
const [destination, setDestination] = useState('')
const parentPath = match.path.substring(0, match.path.lastIndexOf('/')) const parentPath = match.path.substring(0, match.path.lastIndexOf('/'))
const handleSimulate = () => { const handleSimulate = () => {
...@@ -64,7 +67,7 @@ const CreditLinesList = (props: Props) => { ...@@ -64,7 +67,7 @@ const CreditLinesList = (props: Props) => {
<div className={classes.contentContainer}> <div className={classes.contentContainer}>
<div className={classes.content}> <div className={classes.content}>
<Typography variant="h5" className={classes.title}> <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> </Typography>
<Autocomplete<SimulationCategory> <Autocomplete<SimulationCategory>
id="credit-lines" id="credit-lines"
...@@ -72,7 +75,7 @@ const CreditLinesList = (props: Props) => { ...@@ -72,7 +75,7 @@ const CreditLinesList = (props: Props) => {
options={simulationCategories} options={simulationCategories}
getOptionLabel={(option) => option.description} getOptionLabel={(option) => option.description}
getOptionSelected={(opt, val) => opt.id === selectedSimulCategory?.id} getOptionSelected={(opt, val) => opt.id === selectedSimulCategory?.id}
noOptionsText="Nenhuma linha encontrada" noOptionsText="Nenhum motivo encontrado..."
value={selectedSimulCategory} value={selectedSimulCategory}
onChange={(_, opt) => { onChange={(_, opt) => {
setSelectedSimulCategory(opt || null) setSelectedSimulCategory(opt || null)
...@@ -104,7 +107,7 @@ const CreditLinesList = (props: Props) => { ...@@ -104,7 +107,7 @@ const CreditLinesList = (props: Props) => {
<TextField <TextField
{...params} {...params}
id="select-patient-id" id="select-patient-id"
label="Linha de crédito" label="Qual o motivo do financiamento?"
variant="outlined" variant="outlined"
InputProps={{ InputProps={{
ref: params.InputProps.ref, ref: params.InputProps.ref,
...@@ -122,7 +125,7 @@ const CreditLinesList = (props: Props) => { ...@@ -122,7 +125,7 @@ const CreditLinesList = (props: Props) => {
/> />
<TextField <TextField
className={classes.description} className={classes.description}
label="Descrição da linha de crédito" label="Descrição"
value={selectedSimulCategory?.fullDescription || ''} value={selectedSimulCategory?.fullDescription || ''}
rows={5} rows={5}
multiline multiline
...@@ -134,6 +137,16 @@ const CreditLinesList = (props: Props) => { ...@@ -134,6 +137,16 @@ const CreditLinesList = (props: Props) => {
variant="outlined" variant="outlined"
unselectable="on" 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 <SliderField
className={classes.sliderField} className={classes.sliderField}
title="De quanto você precisa?" title="De quanto você precisa?"
......
...@@ -13,4 +13,5 @@ export default (theme: Theme) => ...@@ -13,4 +13,5 @@ export default (theme: Theme) =>
description: { margin: theme.spacing(2), width: '100%' }, description: { margin: theme.spacing(2), width: '100%' },
sliderField: { textAlign: 'center', width: '100%', marginBottom: theme.spacing(3) }, sliderField: { textAlign: 'center', width: '100%', marginBottom: theme.spacing(3) },
btnContainer: { width: '100%', textAlign: 'right', marginBottom: theme.spacing(2) }, btnContainer: { width: '100%', textAlign: 'right', marginBottom: theme.spacing(2) },
destinationsSelect: { marginBottom: theme.spacing(2) },
}) })
...@@ -1264,10 +1264,10 @@ ...@@ -1264,10 +1264,10 @@
prop-types "^15.7.2" prop-types "^15.7.2"
react-is "^16.8.0 || ^17.0.0" react-is "^16.8.0 || ^17.0.0"
"@microcredito/client@^0.7.14": "@microcredito/client@^0.7.16":
version "0.7.14" version "0.7.16"
resolved "https://nexus.dev.evologica.com.br/repository/npm/@microcredito/client/-/client-0.7.14.tgz#066eb548f6ed10bb8a194ae4511c86f2344f45b6" resolved "https://nexus.dev.evologica.com.br/repository/npm/@microcredito/client/-/client-0.7.16.tgz#a8a771014a5610a2e20871e40f226c233a154b6a"
integrity sha1-Bm61SPbtELuKGUrkURyG8jRPRbY= integrity sha1-qKdxAUpWEKLiCHHkDyJsIzoVS2o=
"@nodelib/fs.scandir@2.1.4": "@nodelib/fs.scandir@2.1.4":
version "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