Commit b069d199 authored by Rafael's avatar Rafael

Adiciona mais conexões com o serviço.

parent 06b6c363
{ {
"API_URL": "http://172.16.17.3:8080", "API_URL": "http://172.16.17.3:8080",
"APP_NAME_BROKER": "@microcredito-dev/agente", "APP_NAME_BROKER": "@agiliza-dev/agente",
"APP_NAME_CUSTOMER": "@microcredito-dev/cliente", "APP_NAME_CUSTOMER": "@agiliza-dev/cliente",
"SESSION_KEY_BROKER": "@microcredito-dev/agente", "SESSION_KEY_BROKER": "@agiliza-dev/agente",
"SESSION_KEY_CUSTOMER": "@microcredito-dev/cliente" "SESSION_KEY_CUSTOMER": "@agiliza-dev/cliente"
} }
{ {
"API_URL": "http://192.168.0.34:8080", "API_URL": "http://172.16.17.3:8080",
"APP_NAME_BROKER": "@microcredito-dev/agente", "APP_NAME_BROKER": "@agiliza-dev/agente",
"APP_NAME_CUSTOMER": "@microcredito-dev/cliente", "APP_NAME_CUSTOMER": "@agiliza-dev/cliente",
"SESSION_KEY_BROKER": "@microcredito-dev/agente", "SESSION_KEY_BROKER": "@agiliza-dev/agente",
"SESSION_KEY_CUSTOMER": "@microcredito-dev/cliente" "SESSION_KEY_CUSTOMER": "@agiliza-dev/cliente"
} }
{ {
"API_URL": "https://microcredito.dev.evologica.com.br", "API_URL": "http://172.16.17.3:8080",
"APP_NAME_BROKER": "@microcredito/agente", "APP_NAME_BROKER": "@agiliza-dev/agente",
"APP_NAME_CUSTOMER": "@microcredito/cliente", "APP_NAME_CUSTOMER": "@agiliza-dev/cliente",
"SESSION_KEY_BROKER": "@microcredito/agente", "SESSION_KEY_BROKER": "@agiliza-dev/agente",
"SESSION_KEY_CUSTOMER": "@microcredito/cliente" "SESSION_KEY_CUSTOMER": "@agiliza-dev/cliente"
} }
{ {
"API_URL": "https://microcredito.test.evologica.com.br", "API_URL": "http://172.16.17.3:8080",
"APP_NAME_BROKER": "@microcredito-staging/agente", "APP_NAME_BROKER": "@agiliza-dev/agente",
"APP_NAME_CUSTOMER": "@microcredito-staging/cliente", "APP_NAME_CUSTOMER": "@agiliza-dev/cliente",
"SESSION_KEY_BROKER": "@microcredito-staging/agente", "SESSION_KEY_BROKER": "@agiliza-dev/agente",
"SESSION_KEY_CUSTOMER": "@microcredito-staging/cliente" "SESSION_KEY_CUSTOMER": "@agiliza-dev/cliente"
} }
...@@ -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.11", "@microcredito/client": "^0.7.13",
"@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",
......
{ {
"API_URL": "http://172.16.17.3:8080", "API_URL": "http://172.16.17.3:8080",
"APP_NAME_BROKER": "@microcredito-dev/agente", "APP_NAME_BROKER": "@agiliza-dev/agente",
"APP_NAME_CUSTOMER": "@microcredito-dev/cliente", "APP_NAME_CUSTOMER": "@agiliza-dev/cliente",
"SESSION_KEY_BROKER": "@microcredito-dev/agente", "SESSION_KEY_BROKER": "@agiliza-dev/agente",
"SESSION_KEY_CUSTOMER": "@microcredito-dev/cliente" "SESSION_KEY_CUSTOMER": "@agiliza-dev/cliente"
} }
\ No newline at end of file
import { Entity } from '@agiliza/utils/method'
export * from './proposalData' export * from './proposalData'
export * from './context' export * from './context'
export * from './error' export * from './error'
...@@ -15,3 +17,19 @@ export interface Customer { ...@@ -15,3 +17,19 @@ export interface Customer {
address?: Partial<Address> address?: Partial<Address>
profilePicture?: string profilePicture?: string
} }
export interface IdDescricao {
id: string
descricao: string
}
export interface DocumentType extends Entity {
description: string
}
export interface Document {
id: string
type: DocumentType
extraInformations: string
url: string
}
...@@ -19,3 +19,13 @@ export interface UpdateBDIdentificationArgs { ...@@ -19,3 +19,13 @@ export interface UpdateBDIdentificationArgs {
projectId: string projectId: string
identification: BDIdentification identification: BDIdentification
} }
interface InputUpdateBDIdentification {
projectId: string
identification: BDIdentification
}
export interface UpdateBDIdentification {
Input: InputUpdateBDIdentification
Output: BDIdentification
}
import { Entity } from '@agiliza/utils/method'
export interface Framework extends Entity {
description: string
}
export interface Gender extends Entity {
description: string
}
export interface ProposalDataContext {
frameworks: Framework[]
genders: Gender[]
}
export interface FetchContext {
Input: void
Output: ProposalDataContext
}
export * from './involvedPeople' export * from './involvedPeople'
export * from './businessData' export * from './businessData'
export * from './context'
export interface Address { export interface Address {
id: string id: string
......
...@@ -16,8 +16,8 @@ export interface GetSubProducts { ...@@ -16,8 +16,8 @@ export interface GetSubProducts {
interface InputGetSubProducts { interface InputGetSubProducts {
creditValue: number creditValue: number
idModality: string categoryId: string
idGracePeriod: string gracePeriodId: string
installmentsNumber: number installmentsNumber: number
} }
...@@ -28,3 +28,20 @@ export interface InstallmentOption extends Entity { ...@@ -28,3 +28,20 @@ export interface InstallmentOption extends Entity {
installmentValue?: number installmentValue?: number
netValue?: number netValue?: number
} }
interface InputCreateProposal {
creditValue: number
gracePeriodId: number
categoryId: string
installmentsNumber: number
subproductId: string
}
interface OutputCreateProposal {
proposalId: string
}
export interface CreateProposal {
Input: InputCreateProposal
Output: OutputCreateProposal
}
import * as AuthenticationApiMappers from './authentication' import * as AuthenticationApiMappers from './authentication'
import * as ProposalDataApiMappers from './proposalData'
import * as SessionApiAdapters from './session' import * as SessionApiAdapters from './session'
import * as SimulationApiMappers from './simulation' import * as SimulationApiMappers from './simulation'
export { SessionApiAdapters, SimulationApiMappers, AuthenticationApiMappers } export { SessionApiAdapters, SimulationApiMappers, AuthenticationApiMappers, ProposalDataApiMappers }
import { BusinessData, CreateProposal, Document, UpdateBDIdentification } from '@agiliza/api/domain'
import { extractNumbers } from '@agiliza/utils/extractors'
import { DadosNegocioIdentificacaoApiModel, DocumentoApiModel } from '@microcredito/client'
import { AtualizarIdentificacaoDadosNegocioRequest } from '@microcredito/client/dist/apis/AgenteApi'
import { CriarPropostaRequest } from '@microcredito/client/dist/apis/ClienteApi'
import { ApiAdapter } from '../shared'
export class DocumentApiMapper implements ApiAdapter<Document, DocumentoApiModel> {
private mapDocumentTypeToApi = (docType: Document['type']): DocumentoApiModel['tipoDocumento'] => ({
codigo: docType.id,
descricao: docType.description,
})
public mapDomainToApiModel = (doc: Document): DocumentoApiModel => ({
id: doc.id,
imagem: doc.url,
tipoDocumento: this.mapDocumentTypeToApi(doc.type),
informacoesComplementares: doc.extraInformations,
})
}
export class BDIdentificationApiMapper implements ApiAdapter<BusinessData['identification'], DadosNegocioIdentificacaoApiModel> {
private documentAdapter: DocumentApiMapper
constructor() {
this.documentAdapter = new DocumentApiMapper()
}
public mapDomainToApiModel = (ident: BusinessData['identification']): DadosNegocioIdentificacaoApiModel => ({
cnpj: extractNumbers(ident?.cnpj),
codigoCNAE: ident?.codeCNAE,
dataAbertura: ident?.openingDate !== null ? ident?.openingDate : undefined,
documento: ident?.document ? this.documentAdapter.mapDomainToApiModel(ident?.document) : undefined,
inscricaoComercial: ident?.commercialRegistration,
inscricaoEstadual: ident?.stateRegistration,
inscricaoMunicipal: ident?.cityRegistration,
local: ident?.local,
nomeFantasia: ident?.fantasyName,
opLiquidada: ident?.settledOP,
razaoSocial: ident?.companyName,
setorAtividade: ident?.activitySector,
})
}
export class BDUpdateIdentificationApiMapper implements ApiAdapter<UpdateBDIdentification['Input'], AtualizarIdentificacaoDadosNegocioRequest> {
private identificationApiMapper: BDIdentificationApiMapper
constructor() {
this.identificationApiMapper = new BDIdentificationApiMapper()
}
public mapDomainToApiModel = (input: UpdateBDIdentification['Input']): AtualizarIdentificacaoDadosNegocioRequest => ({
projetoId: input.projectId,
dadosNegocioIdentificacaoApiModel: this.identificationApiMapper.mapDomainToApiModel(input.identification),
})
}
export class CreateProposalApiMapper implements ApiAdapter<CreateProposal['Input'], CriarPropostaRequest> {
public mapDomainToApiModel = (input: CreateProposal['Input']): CriarPropostaRequest => ({
criarPropostaRequestApiModel: {
carencia: input.gracePeriodId,
categoriaSimulacao: input.categoryId,
quantidadeParcelas: input.installmentsNumber,
valorInteresse: input.creditValue,
subprodutoId: input.subproductId,
},
})
}
...@@ -6,8 +6,8 @@ import { ApiAdapter } from '../shared' ...@@ -6,8 +6,8 @@ import { ApiAdapter } from '../shared'
export class GetSubProductsApiMapper implements ApiAdapter<GetSubProducts['Input'], SimularCreditoRequestApiModel> { export class GetSubProductsApiMapper implements ApiAdapter<GetSubProducts['Input'], SimularCreditoRequestApiModel> {
public mapDomainToApiModel = (input: GetSubProducts['Input']): SimularCreditoRequestApiModel => ({ public mapDomainToApiModel = (input: GetSubProducts['Input']): SimularCreditoRequestApiModel => ({
valorCredito: input.creditValue, valorCredito: input.creditValue,
codigoCarencia: input.idGracePeriod, codigoCarencia: input.gracePeriodId,
codigoModalidade: input.idModality, codigoModalidade: input.categoryId,
numeroParcelas: input.installmentsNumber, numeroParcelas: input.installmentsNumber,
}) })
} }
...@@ -2,7 +2,10 @@ import * as AuthenticationMappers from './authentication' ...@@ -2,7 +2,10 @@ import * as AuthenticationMappers from './authentication'
import * as ContextMappers from './context' import * as ContextMappers from './context'
import * as CustomerMappers from './customer' import * as CustomerMappers from './customer'
import * as ErrorMappers from './error' import * as ErrorMappers from './error'
import * as ProposalDataMappers from './proposalData'
import * as SessionAdapters from './session' import * as SessionAdapters from './session'
import * as SimulationMappers from './simulation' import * as SimulationMappers from './simulation'
export { ContextMappers, ErrorMappers, SessionAdapters, SimulationMappers, AuthenticationMappers, CustomerMappers } export { ContextMappers, ErrorMappers, SessionAdapters, SimulationMappers, AuthenticationMappers, CustomerMappers, ProposalDataMappers }
export * from './shared'
import { BDIdentification, Document } from '@agiliza/api/domain'
import { DadosNegocioIdentificacaoApiModel, DocumentoApiModel } from '@microcredito/client'
import { DomainAdapter } from '../shared'
export class ProjectDocumentMapper implements DomainAdapter<DocumentoApiModel, Document> {
public mapTipoDocumentoApiToDomain = (tipo: DocumentoApiModel['tipoDocumento']): Document['type'] => ({
id: tipo.codigo,
description: tipo.descricao,
})
public mapApiModelToDomain = (apimodel: DocumentoApiModel): Document => ({
id: apimodel.id,
url: apimodel.imagem,
type: this.mapTipoDocumentoApiToDomain(apimodel.tipoDocumento),
extraInformations: apimodel.informacoesComplementares || '',
})
}
export class BDIdentificationMapper implements DomainAdapter<DadosNegocioIdentificacaoApiModel, BDIdentification> {
private documentAdapter: ProjectDocumentMapper
constructor() {
this.documentAdapter = new ProjectDocumentMapper()
}
public mapApiModelToDomain = (dnIdent: DadosNegocioIdentificacaoApiModel): BDIdentification => ({
activitySector: dnIdent.setorAtividade || '',
cityRegistration: dnIdent.inscricaoMunicipal || '',
cnpj: dnIdent.cnpj || '',
codeCNAE: dnIdent.codigoCNAE || '',
commercialRegistration: dnIdent.inscricaoComercial || '',
companyName: dnIdent.razaoSocial || '',
fantasyName: dnIdent.nomeFantasia || '',
local: dnIdent.local || '',
openingDate: dnIdent.dataAbertura || null,
settledOP: dnIdent.opLiquidada || '',
stateRegistration: dnIdent.inscricaoEstadual || '',
document: dnIdent.documento ? this.documentAdapter.mapApiModelToDomain(dnIdent.documento) : undefined,
})
}
import { ProposalDataContext } from '@agiliza/api/domain'
import { EnquadramentoApiModel, GeneroApiModel } from '@microcredito/client'
import { DomainAdapter, IdDescriptionMapper } from '../shared'
export interface DadosPropostaContexto {
enquadramentos: EnquadramentoApiModel[]
generos: GeneroApiModel[]
}
export class ContextMapper implements DomainAdapter<DadosPropostaContexto, ProposalDataContext> {
private idDescriptionMapper: IdDescriptionMapper
constructor() {
this.idDescriptionMapper = new IdDescriptionMapper()
}
public mapApiModelToDomain = (dP: DadosPropostaContexto): ProposalDataContext => ({
frameworks: dP.enquadramentos.map(this.idDescriptionMapper.mapApiModelToDomain),
genders: dP.generos.map(this.idDescriptionMapper.mapApiModelToDomain),
})
}
export * from './businessData'
export * from './context'
import { IdDescricao } from '@agiliza/api/domain'
import { Entity } from '@agiliza/utils/method'
export interface DomainAdapter<A, B> { export interface DomainAdapter<A, B> {
mapApiModelToDomain(apiModel: A): B mapApiModelToDomain(apiModel: A): B
} }
interface IdDescription extends Entity {
description: string
}
export class IdDescriptionMapper implements DomainAdapter<IdDescricao, IdDescription> {
public mapApiModelToDomain = (iD: IdDescricao): IdDescription => ({
id: iD.id,
description: iD.descricao,
})
}
export * from './session' export * from './session'
export * from './simulation' export * from './simulation'
export * from './authentication' export * from './authentication'
export * from './proposalData'
import { mapUserAgentToString, SESSION_KEY, UserAgent } from '../shared'
export interface PDBusinessDataRepository {}
export class PDBusinessDataRepositoryImpl implements PDBusinessDataRepository {
// private api: ClienteApi
// private errorAdapter: ErrorMappers.ResponseErrorAdapter
constructor(userAgent: string, accessToken: string) {
// this.errorAdapter = new ErrorMappers.ResponseErrorAdapter()
// this.api = new ClienteApi(
// new Configuration({
// basePath: API_URL,
// accessToken,
// headers: {
// 'User-Agent': userAgent,
// },
// })
// )
}
}
export class PDBusinessDataRepositoryImplFactory {
static create(userAgent: UserAgent) {
const accessToken = localStorage.getItem(SESSION_KEY) || ''
const repository = new PDBusinessDataRepositoryImpl(mapUserAgentToString(userAgent), accessToken)
return repository
}
}
import { FetchContext } from '@agiliza/api/domain'
import { Configuration, DominioApi } from '@microcredito/client'
import { ErrorMappers, ProposalDataMappers } from '../../mappers'
import { DadosPropostaContexto } from '../../mappers/domain/proposalData/context'
import { API_URL, mapUserAgentToString, SESSION_KEY, UserAgent } from '../shared'
export interface ProposalDataContextRepository {
fetchContext(): Promise<FetchContext['Output']>
}
export class ProposalDataContextRepositoryImpl implements ProposalDataContextRepository {
private api: DominioApi
private errorAdapter: ErrorMappers.ResponseErrorAdapter
private contextMapper: ProposalDataMappers.ContextMapper
constructor(userAgent: string, accessToken: string) {
this.errorAdapter = new ErrorMappers.ResponseErrorAdapter()
this.contextMapper = new ProposalDataMappers.ContextMapper()
this.api = new DominioApi(
new Configuration({
basePath: API_URL,
accessToken,
headers: {
'User-Agent': userAgent,
},
})
)
}
public fetchContext = async (): Promise<FetchContext['Output']> => {
try {
const contexto: DadosPropostaContexto = { enquadramentos: await this.api.obterEnquadramentos(), generos: await this.api.obterGeneros() }
return this.contextMapper.mapApiModelToDomain(contexto)
} catch (e) {
const result = await this.errorAdapter.mapApiModelToDomain(e)
throw result
}
}
}
export class ProposalDataContextRepositoryImplFactory {
static create(userAgent: UserAgent) {
const accessToken = localStorage.getItem(SESSION_KEY) || ''
const repository = new ProposalDataContextRepositoryImpl(mapUserAgentToString(userAgent), accessToken)
return repository
}
}
import { CreateProposal, UpdateBDIdentification } from '@agiliza/api/domain'
import { ClienteApi, Configuration } from '@microcredito/client'
import { ErrorMappers, ProposalDataApiMappers, ProposalDataMappers } from '../../mappers'
import { API_URL, mapUserAgentToString, SESSION_KEY, UserAgent } from '../shared'
export interface PDCustomerDataDataRepository {
createProposal(input: CreateProposal['Input']): Promise<CreateProposal['Output']>
updateIdentification(input: UpdateBDIdentification['Input']): Promise<UpdateBDIdentification['Output']>
}
export class PDCustomerDataRepositoryImpl implements PDCustomerDataDataRepository {
private api: ClienteApi
private errorAdapter: ErrorMappers.ResponseErrorAdapter
private updateIdentificationApiMapper: ProposalDataApiMappers.BDUpdateIdentificationApiMapper
private identificationMapper: ProposalDataMappers.BDIdentificationMapper
private createProposalApiMapper: ProposalDataApiMappers.CreateProposalApiMapper
constructor(userAgent: string, accessToken: string) {
this.errorAdapter = new ErrorMappers.ResponseErrorAdapter()
this.updateIdentificationApiMapper = new ProposalDataApiMappers.BDUpdateIdentificationApiMapper()
this.identificationMapper = new ProposalDataMappers.BDIdentificationMapper()
this.createProposalApiMapper = new ProposalDataApiMappers.CreateProposalApiMapper()
this.api = new ClienteApi(
new Configuration({
basePath: API_URL,
accessToken,
headers: {
'User-Agent': userAgent,
},
})
)
}
public updateIdentification = async (input: UpdateBDIdentification['Input']): Promise<UpdateBDIdentification['Output']> => {
try {
const response = await this.api.atualizarIdentificacaoDadosNegocio(this.updateIdentificationApiMapper.mapDomainToApiModel(input))
return this.identificationMapper.mapApiModelToDomain(response)
} catch (e) {
const result = await this.errorAdapter.mapApiModelToDomain(e)
throw result
}
}
public createProposal = async (input: CreateProposal['Input']): Promise<CreateProposal['Output']> => {
try {
const response = await this.api.criarProposta(this.createProposalApiMapper.mapDomainToApiModel(input))
return { proposalId: response.propostaId || '' }
} catch (e) {
const result = await this.errorAdapter.mapApiModelToDomain(e)
throw result
}
}
}
export class PDCustomerDataRepositoryImplFactory {
static create(userAgent: UserAgent) {
const accessToken = localStorage.getItem(SESSION_KEY) || ''
const repository = new PDCustomerDataRepositoryImpl(mapUserAgentToString(userAgent), accessToken)
return repository
}
}
export * from './context'
export * from './businessData'
...@@ -5,80 +5,6 @@ import { Customer } from '../domain' ...@@ -5,80 +5,6 @@ import { Customer } from '../domain'
import { CustomerMappers, SessionAdapters, SessionApiAdapters as Adapters } from '../mappers' import { CustomerMappers, SessionAdapters, SessionApiAdapters as Adapters } from '../mappers'
import { API_URL, mapUserAgentToString, SESSION_KEY, UserAgent } from './shared' import { API_URL, mapUserAgentToString, SESSION_KEY, UserAgent } from './shared'
// import { getSessionManager } from '@agiliza/curio'
// import { createMenuAPI } from '../dynamo'
// // import { createMenuAPI } from '../dynamo'
// // import { SolicitarRedefinicao, VerificarCodigo, RedefinirSenha } from '../interfaces/Login'
// // const ucRecuperarSenha = {
// // id: '3522',
// // SOLICITAR_REDEFINICAO: 'RM_SOLICITAR_REDEFINICAO',
// // VERIFICAR_CODIGO: 'RM_VERIFICAR_CODIGO',
// // DEFIINIR_SENHA: 'RM_DEFINIR_SENHA'
// // }
// interface LoginParams {
// username: string
// password: string
// }
// export const initialize = async () => {
// await getSessionManager()
// }
// export const login = async ({ username, password }: LoginParams) => {
// const sessionManager = await getSessionManager()
// return sessionManager.openMainUseCase(username, password)
// }
// export const logout = async () => {
// const sessionManager = await getSessionManager()
// sessionManager?.session?.abort()
// }
// export const { fetchMenu } = createMenuAPI()
// export const solicitarRedefinicao = async (funcionario: SolicitarRedefinicao) => {
// const mainUseCase = await sessionManager.anonymousConnection()
// const uc = await mainUseCase.openUseCase(ucRecuperarSenha.id)
// const response = await uc.sendRequest(ucRecuperarSenha.SOLICITAR_REDEFINICAO, {
// Funcionario: funcionario
// })
// await uc.abort()
// return response.Funcionario as Funcionario
// }
// const enviarCodigoSenha = async (envCodigo: VerificarCodigo) => {
// const { _codigoAcesso, _OID } = envCodigo
// const mainUseCase = await sessionManager.anonymousConnection()
// const uc = await mainUseCase.openUseCase(ucRecuperarSenha.id)
// const response = await uc.sendRequest(ucRecuperarSenha.VERIFICAR_CODIGO, {
// Funcionario: { _codigoAcesso, _OID }
// })
// await uc.abort()
// return response.Funcionario as Funcionario
// }
// const redefinirSenha = async (redefSenha: RedefinirSenha) => {
// const { _OID, _senha, _codigoAcesso } = redefSenha
// const mainUseCase = await sessionManager.anonymousConnection()
// const uc = await mainUseCase.openUseCase(ucRecuperarSenha.id)
// const response = await uc.sendRequest(ucRecuperarSenha.DEFIINIR_SENHA, {
// Funcionario: { _senha, _OID, _codigoAcesso }
// })
// await uc.abort()
// return response.Funcionario as Funcionario
// }
// export const useCaseRecuperarSenha = {
// solicitarRedefinicao,
// enviarCodigoSenha,
// redefinirSenha
// }
export interface SessionRepository { export interface SessionRepository {
login(username: string, password: string): Promise<Customer> login(username: string, password: string): Promise<Customer>
logout(): void logout(): void
...@@ -110,6 +36,7 @@ export class SessionRepositoryImpl implements SessionRepository { ...@@ -110,6 +36,7 @@ export class SessionRepositoryImpl implements SessionRepository {
try { try {
const params = this.loginApiAdapter.mapDomainToApiModel({ username: extractNumbers(username), password }) const params = this.loginApiAdapter.mapDomainToApiModel({ username: extractNumbers(username), password })
const accessToken = await this.api.login(params) const accessToken = await this.api.login(params)
localStorage.setItem(SESSION_KEY, accessToken.token)
const clienteApi = new ClienteApi( const clienteApi = new ClienteApi(
new Configuration({ new Configuration({
basePath: API_URL, basePath: API_URL,
...@@ -131,7 +58,7 @@ export class SessionRepositoryImpl implements SessionRepository { ...@@ -131,7 +58,7 @@ export class SessionRepositoryImpl implements SessionRepository {
localStorage.removeItem(SESSION_KEY) localStorage.removeItem(SESSION_KEY)
} }
public connect = () => { public connect = () => {
const sessionKey = localStorage.getItem(SESSION_KEY) const sessionKey = localStorage.getItem(SESSION_KEY) || 'a'
if (sessionKey) return if (sessionKey) return
else throw new Error() else throw new Error()
// return await new Promise<void>((res, rej) => { // return await new Promise<void>((res, rej) => {
......
...@@ -3,9 +3,7 @@ import React, { useState } from 'react' ...@@ -3,9 +3,7 @@ import React, { useState } from 'react'
import { Collapse, CollapseProps, Fade } from '@material-ui/core' import { Collapse, CollapseProps, Fade } from '@material-ui/core'
import MuiAppBar, { AppBarProps as MuiAppBarProps } from '@material-ui/core/AppBar' import MuiAppBar, { AppBarProps as MuiAppBarProps } from '@material-ui/core/AppBar'
import IconButton from '@material-ui/core/IconButton'
import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' import { createStyles, makeStyles, Theme } from '@material-ui/core/styles'
import { Menu as DrawerIcon } from '@material-ui/icons'
import { Toolbar, ToolbarProps } from './Toolbar' import { Toolbar, ToolbarProps } from './Toolbar'
...@@ -43,15 +41,15 @@ const AppBar = ({ className, position = 'static', actions, title, children, onNa ...@@ -43,15 +41,15 @@ const AppBar = ({ className, position = 'static', actions, title, children, onNa
setFadeIn(isAppearing) setFadeIn(isAppearing)
} }
const nav = onNavClick ? ( // const nav = onNavClick ? (
<IconButton color="inherit" onClick={onNavClick}> // <IconButton color="inherit" onClick={onNavClick}>
<DrawerIcon /> // <DrawerIcon />
</IconButton> // </IconButton>
) : null // ) : null
return ( return (
<> <>
<MuiAppBar className={cn(classes.appBar, className)} position={position} style={style}> <MuiAppBar className={cn(classes.appBar, className)} position={position} style={style}>
<Toolbar title={title} actions={actions} nav={nav} /> <Toolbar title={title} actions={actions} /*nav={nav}*/ />
{children && ( {children && (
<Collapse appear enter in onEntered={onCollapse} timeout={400}> <Collapse appear enter in onEntered={onCollapse} timeout={400}>
<div> <div>
......
...@@ -12,6 +12,7 @@ import DateFnsUtils from '@date-io/date-fns' ...@@ -12,6 +12,7 @@ import DateFnsUtils from '@date-io/date-fns'
import { MuiThemeProvider } from '@material-ui/core/styles' import { MuiThemeProvider } from '@material-ui/core/styles'
import { MuiPickersUtilsProvider } from '@material-ui/pickers' import { MuiPickersUtilsProvider } from '@material-ui/pickers'
import { SESSION_KEY } from './api/useCases/shared'
import ErrorDialog from './components/molecules/ErrorDialog' import ErrorDialog from './components/molecules/ErrorDialog'
import { store } from './redux' import { store } from './redux'
import { theme } from './theme' import { theme } from './theme'
...@@ -37,6 +38,8 @@ const Adm = (props: Props) => { ...@@ -37,6 +38,8 @@ const Adm = (props: Props) => {
) )
} }
localStorage.removeItem(SESSION_KEY) // Don't store any access token
if (isValidBrowser) { if (isValidBrowser) {
render(<Adm />, root) render(<Adm />, root)
} else { } else {
......
...@@ -2,6 +2,10 @@ import authentication, { ...@@ -2,6 +2,10 @@ import authentication, {
initialState as authenticationInitState, initialState as authenticationInitState,
Store as AuthenticationState Store as AuthenticationState
} from './authentication' } from './authentication'
import proposalData, {
initialState as proposalDataInitState,
State as ProposalDataState
} from './proposalData'
import simulation, { import simulation, {
initialState as simulationInitState, initialState as simulationInitState,
State as SimulationState State as SimulationState
...@@ -12,18 +16,21 @@ export interface EntitiesState { ...@@ -12,18 +16,21 @@ export interface EntitiesState {
system: System system: System
simulation: SimulationState simulation: SimulationState
authentication: AuthenticationState authentication: AuthenticationState
proposalData: ProposalDataState
} }
export const initialState: EntitiesState = { export const initialState: EntitiesState = {
simulation: simulationInitState, simulation: simulationInitState,
system: systemInitState, system: systemInitState,
authentication: authenticationInitState, authentication: authenticationInitState,
proposalData: proposalDataInitState,
} }
const reducers = { const reducers = {
simulation, simulation,
system, system,
authentication, authentication,
proposalData,
} }
export default reducers export default reducers
import { getActionTypes } from '@agiliza/utils/method'
import * as selectors from './selectors'
import slice from './slice'
export * from './slice'
const actions = slice.actions
const reducer = slice.reducer
const types = getActionTypes(slice.actions)
export { actions, types, selectors }
export default reducer
import { ProposalDataContext } from '@agiliza/api/domain'
import { entries, values } from '@agiliza/utils/method'
import { createSelector } from '@reduxjs/toolkit'
import { Store } from './slice'
export const getAllIds = (key: keyof Store) => (state: Store) => {
return state[key].allIds
}
export const getById = (key: keyof Store) => (state: Store) => {
return state[key].byId
}
export const getFrameworks = createSelector(getById('frameworks'), getAllIds('frameworks'), (byId, allIds) => allIds.map((id) => byId[id]))
export const getContext = (state: Store) =>
entries(state).reduce((entities, [k, v]) => {
return { ...entities, [k]: values(v.byId) }
}, {} as ProposalDataContext)
import { ProposalDataContext } from '@agiliza/api/domain'
import { types as fetchTypes } from '@agiliza/redux/useCases/proposalData/context'
import { entries, keys, WithEntityStore } from '@agiliza/utils/method'
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import { normalizeContext, PROPOSAL_DATA_PREFIX } from '../shared'
export interface Store extends WithEntityStore<ProposalDataContext> {
// frameworks: EntityStore<Framework>
}
export const initialState: Store = {
frameworks: { byId: {}, allIds: [] },
genders: { byId: {}, allIds: [] },
}
export default createSlice({
name: `${PROPOSAL_DATA_PREFIX}/context`,
initialState,
reducers: {},
extraReducers: {
[fetchTypes.fetchContext.fulfilled]: (state, action: PayloadAction<ProposalDataContext>) => {
const normalized = normalizeContext(action.payload)
entries(normalized).forEach(([k, v]) => {
state[k].byId = v
state[k].allIds = keys(v)
})
},
},
})
import { combineReducers } from 'redux'
import context, { initialState as contextInitState, Store as ContextStore } from './context'
export interface State {
context: ContextStore
}
export const initialState: State = {
context: contextInitState,
}
export default combineReducers({
context,
})
import { normalize, schema } from 'normalizr'
import { ProposalDataContext } from '@agiliza/api/domain'
import { WithNormalizedEntity } from '@agiliza/utils/method'
export const PROPOSAL_DATA_PREFIX = 'entities/proposalData'
export type NormalizedContext = WithNormalizedEntity<ProposalDataContext>
const contextSchemas = new schema.Object({
frameworks: new schema.Array(new schema.Entity('frameworks')),
genders: new schema.Array(new schema.Entity('genders')),
})
export const normalizeContext = (context: ProposalDataContext) => {
const { entities } = normalize(context, contextSchemas)
const normalizedEntities = entities as unknown as NormalizedContext
return normalizedEntities
}
...@@ -5,27 +5,21 @@ import { ...@@ -5,27 +5,21 @@ import {
} from './drawer' } from './drawer'
import { initialState as errorInitialState, reducer as error, State as ErrorState } from './error' import { initialState as errorInitialState, reducer as error, State as ErrorState } from './error'
import login, { initialState as loginInitialState, State as LoginState } from './login' import login, { initialState as loginInitialState, State as LoginState } from './login'
// import { import simulation, {
// initialState as profileInitialState, initialState as simulationInitialState,
// reducer as profile, State as SimulationState
// State as ProfileState } from './simulation'
// } from './profile'
import { import {
initialState as systemInitialState, initialState as systemInitialState,
reducer as system, reducer as system,
State as SystemState State as SystemState
} from './system' } from './system'
// import { initialState as userInitialState, reducer as user, State as UserState } from './user'
// export * from './login'
export interface UIState { export interface UIState {
login: LoginState login: LoginState
error: ErrorState error: ErrorState
drawer: DrawerState drawer: DrawerState
// user: UserState simulation: SimulationState
// profile: ProfileState
system: SystemState system: SystemState
} }
...@@ -33,18 +27,16 @@ const reducers = { ...@@ -33,18 +27,16 @@ const reducers = {
login, login,
error, error,
drawer, drawer,
// user,
// profile,
system, system,
simulation,
} }
export const initialState: UIState = { export const initialState: UIState = {
login: loginInitialState, login: loginInitialState,
error: errorInitialState, error: errorInitialState,
drawer: drawerInitialState, drawer: drawerInitialState,
// user: userInitialState,
// profile: profileInitialState,
system: systemInitialState, system: systemInitialState,
simulation: simulationInitialState,
} }
export default reducers export default reducers
import * as selectors from './selectors'
import slice from './slice'
export * from './slice'
const actions = slice.actions
export { selectors, actions }
export default slice.reducer
import { State } from './slice'
export const getData = (state: State) => state.data
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
const prefix = 'ui/simulation'
export interface State {
data?: { simulationCategoryId: string; amount: string; paymentMonths: number; graceMonths: number }
}
export const initialState: State = {}
const simulation = createSlice({
name: prefix,
initialState,
reducers: {
setData: (state, action: PayloadAction<State['data']>) => {
state.data = action.payload
},
},
})
export default simulation
...@@ -2,6 +2,10 @@ import authentication, { ...@@ -2,6 +2,10 @@ import authentication, {
initialState as authenticationInitialState, initialState as authenticationInitialState,
State as AuthenticationState State as AuthenticationState
} from './authentication' } from './authentication'
import proposalData, {
initialState as proposalDataInitialState,
State as ProposalDataState
} from './proposalData'
import simulation, { import simulation, {
initialState as simulationInitialState, initialState as simulationInitialState,
State as SimulationState State as SimulationState
...@@ -10,16 +14,19 @@ import simulation, { ...@@ -10,16 +14,19 @@ import simulation, {
export interface UseCasesState { export interface UseCasesState {
simulation: SimulationState simulation: SimulationState
authentication: AuthenticationState authentication: AuthenticationState
proposalData: ProposalDataState
} }
const reducers = { const reducers = {
simulation, simulation,
authentication, authentication,
proposalData,
} }
export const initialState: UseCasesState = { export const initialState: UseCasesState = {
simulation: simulationInitialState, simulation: simulationInitialState,
authentication: authenticationInitialState, authentication: authenticationInitialState,
proposalData: proposalDataInitialState,
} }
export default reducers export default reducers
import * as selectors from './selectors'
import slice from './slice'
export * from './slice'
export { selectors }
export default slice.reducer
import { State } from './slice'
export const isFetching = (state: State) => state.fetching
import { createAsyncReducers, getTypesThunkActions, values } from '@agiliza/utils/method'
import { createSlice } from '@reduxjs/toolkit'
const prefix = 'useCases/businessData'
export interface State {
fetching: boolean
}
export const initialState: State = {
fetching: false,
}
export const actions = {} as const
export const types = getTypesThunkActions(actions)
const login = createSlice({
name: prefix,
initialState,
reducers: {},
extraReducers: {
...values(types).reduce((reducers, type) => ({ ...reducers, ...createAsyncReducers(type) }), {}),
},
})
export default login
import * as selectors from './selectors'
import slice from './slice'
export * from './slice'
export { selectors }
export default slice.reducer
import { State } from './slice'
export const isFetching = (state: State) => state.fetching
import { ProposalDataContextRepositoryImplFactory } from '@agiliza/api/useCases'
import { appPlatform } from '@agiliza/constants/platform'
import { createAsyncReducers, getTypesThunkActions, values } from '@agiliza/utils/method'
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'
const prefix = 'useCases/proposalData'
export interface State {
fetching: boolean
}
export const initialState: State = {
fetching: false,
}
export const actions = {
fetchContext: createAsyncThunk(`${prefix}/fetchContext`, async (_, thunkApi) => {
const useCase = ProposalDataContextRepositoryImplFactory.create(appPlatform)
try {
return await useCase.fetchContext()
} catch (e) {
return thunkApi.rejectWithValue(e)
}
}),
} as const
export const types = getTypesThunkActions(actions)
const login = createSlice({
name: prefix,
initialState,
reducers: {},
extraReducers: {
...values(types).reduce((reducers, type) => ({ ...reducers, ...createAsyncReducers(type) }), {}),
},
})
export default login
import * as selectors from './selectors'
import slice from './slice'
export * from './slice'
export { selectors }
export default slice.reducer
import { State } from './slice'
export const isFetching = (state: State) => state.fetching
import { CreateProposal } from '@agiliza/api/domain'
import {
PDCustomerDataRepositoryImplFactory
} from '@agiliza/api/useCases/proposalData/customerData'
import { appPlatform } from '@agiliza/constants/platform'
import {
createAsyncReducers,
getTypesThunkActions,
values,
WithSuccess
} from '@agiliza/utils/method'
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'
const prefix = 'useCases/customerData'
export interface State {
fetching: boolean
}
export const initialState: State = {
fetching: false,
}
export const actions = {
createProposal: createAsyncThunk(`${prefix}/createProposal`, async (input: WithSuccess<CreateProposal['Input']>, thunkApi) => {
const useCase = PDCustomerDataRepositoryImplFactory.create(appPlatform)
try {
const proposalId = await useCase.createProposal(input)
input.onSuccess && input.onSuccess()
return proposalId
} catch (e) {
return thunkApi.rejectWithValue(e)
}
}),
updateIndentification: createAsyncThunk(`${prefix}/updateIndentification`, async (input: WithSuccess<CreateProposal['Input']>, thunkApi) => {
const useCase = PDCustomerDataRepositoryImplFactory.create(appPlatform)
try {
const proposalId = await useCase.createProposal(input)
input.onSuccess && input.onSuccess()
return proposalId
} catch (e) {
return thunkApi.rejectWithValue(e)
}
}),
} as const
export const types = getTypesThunkActions(actions)
const login = createSlice({
name: prefix,
initialState,
reducers: {},
extraReducers: {
...values(types).reduce((reducers, type) => ({ ...reducers, ...createAsyncReducers(type) }), {}),
},
})
export default login
import { combineReducers } from 'redux'
import businessData, {
initialState as businessDataInitialState,
State as BusinessDataState
} from './businessData'
import context, { initialState as contextInitialState, State as ContextState } from './context'
import customerData, {
initialState as customerDataInitialState,
State as CustomerDataState
} from './customerData'
export interface State {
context: ContextState
businessData: BusinessDataState
customerData: CustomerDataState
}
export const initialState: State = {
context: contextInitialState,
businessData: businessDataInitialState,
customerData: customerDataInitialState,
}
export default combineReducers({ context, businessData, customerData })
...@@ -109,6 +109,14 @@ export interface EntityStore<T> { ...@@ -109,6 +109,14 @@ export interface EntityStore<T> {
allIds: string[] allIds: string[]
} }
export type WithNormalizedEntity<T extends Record<string, any>> = {
[k in keyof T]: T[k] extends Array<any> ? NormalizedEntity<T[k][0]> : unknown
}
export type WithEntityStore<T> = {
[K in keyof T]: T[K] extends Array<any> ? EntityStore<T[K][0]> : unknown
}
export function syncById<T extends Entity, State extends EntityStore<T>>(state: State, entities: NormalizedEntity<T> = {}): NormalizedEntity<T> { export function syncById<T extends Entity, State extends EntityStore<T>>(state: State, entities: NormalizedEntity<T> = {}): NormalizedEntity<T> {
return deepmerge<NormalizedEntity<T>>(state.byId, entities, { return deepmerge<NormalizedEntity<T>>(state.byId, entities, {
arrayMerge: <Type>(dest: Type[], src: Type[]) => src, arrayMerge: <Type>(dest: Type[], src: Type[]) => src,
......
...@@ -3,11 +3,7 @@ import React from 'react' ...@@ -3,11 +3,7 @@ import React from 'react'
import ItemWithIcon from '@agiliza/components/atoms/ItemWithIcon' import ItemWithIcon from '@agiliza/components/atoms/ItemWithIcon'
import List from '@material-ui/core/List' import List from '@material-ui/core/List'
import { import { AttachMoney as AttachMoneyIcon, ExitToApp } from '@material-ui/icons'
AttachMoney as AttachMoneyIcon,
Description as DescriptionIcon,
ExitToApp
} from '@material-ui/icons'
import withStyles from '@material-ui/styles/withStyles' import withStyles from '@material-ui/styles/withStyles'
import { styles } from './styles' import { styles } from './styles'
...@@ -28,7 +24,7 @@ export const PATHS = { ...@@ -28,7 +24,7 @@ export const PATHS = {
export const drawerListItems: ListItem[] = [ export const drawerListItems: ListItem[] = [
{ label: 'Linhas de Crédito', path: PATHS.creditLines, Icon: AttachMoneyIcon }, { label: 'Linhas de Crédito', path: PATHS.creditLines, Icon: AttachMoneyIcon },
{ label: 'Dados da Proposta', path: PATHS.proposalData, Icon: DescriptionIcon }, // { label: 'Dados da Proposta', path: PATHS.proposalData, Icon: DescriptionIcon },
] ]
export const mapPathToTitle = (path: string) => { export const mapPathToTitle = (path: string) => {
......
import React, { lazy, Suspense, useEffect } from 'react' import React, { lazy, Suspense, useEffect } from 'react'
import { Redirect, Route, RouteComponentProps, Switch, useLocation } from 'react-router' import { Redirect, Route, RouteComponentProps, Switch, useHistory } from 'react-router'
import AppBar from '@agiliza/components/molecules/AppBar' import AppBar from '@agiliza/components/molecules/AppBar'
import CircularProgress from '@agiliza/components/molecules/CircularProgress' import CircularProgress from '@agiliza/components/molecules/CircularProgress'
import Drawer from '@agiliza/components/molecules/Drawer' import NotFound from '@agiliza/components/templates/NotFound'
import { actions as drawerActions } from '@agiliza/redux/ui/drawer' import { actions as drawerActions } from '@agiliza/redux/ui/drawer'
import { actions as loginActions } from '@agiliza/redux/ui/login' import { actions as loginActions } from '@agiliza/redux/ui/login'
import { ProposalDataRouteState } from '@agiliza/views/ProposalData/pages/ProposalData'
import { Typography } from '@material-ui/core'
import { withStyles, WithStyles } from '@material-ui/core/styles' import { withStyles, WithStyles } from '@material-ui/core/styles'
import connect, { ConnectedProps } from './connect' import connect, { ConnectedProps } from './connect'
import DrawerItems, { mapPathToTitle, PATHS } from './DrawerItems' import { PATHS } from './DrawerItems'
import styles from './styles' import styles from './styles'
const SimulationCreditLines = lazy(() => import('@agiliza/views/SimulationCreditLines/pages/router')) const SimulationCreditLines = lazy(() => import('@agiliza/views/SimulationCreditLines/pages/router'))
...@@ -24,9 +26,9 @@ interface Props extends BaseProps { ...@@ -24,9 +26,9 @@ interface Props extends BaseProps {
} }
const Main = (props: Props) => { const Main = (props: Props) => {
const { classes, drawerOpen, toggleDrawer, logout, fetchMenu, ...routeProps } = props const { classes, toggleDrawer, fetchMenu } = props
const { pathname } = useLocation() const history = useHistory()
useEffect(() => { useEffect(() => {
fetchMenu() fetchMenu()
...@@ -34,12 +36,26 @@ const Main = (props: Props) => { ...@@ -34,12 +36,26 @@ const Main = (props: Props) => {
return ( return (
<div className={classes.pageContainer}> <div className={classes.pageContainer}>
<AppBar onNavClick={toggleDrawer} title={<div className={classes.title}>{mapPathToTitle(pathname)}</div>} /> <AppBar
<Drawer drawerOpen={drawerOpen} toggleDrawer={toggleDrawer} logout={logout} Items={DrawerItems} {...routeProps} /> onNavClick={toggleDrawer}
title={
<a onClick={() => history.push('/')} className={classes.titleAnchor}>
<Typography className={classes.appTitle}>Agiliza</Typography>
</a>
}
/>
{/* <Drawer drawerOpen={drawerOpen} toggleDrawer={toggleDrawer} logout={logout} Items={DrawerItems} {...routeProps} /> */}
<Suspense fallback={<CircularProgress />}> <Suspense fallback={<CircularProgress />}>
<Switch> <Switch>
<Route path={PATHS.creditLines} render={(rProps) => <SimulationCreditLines {...rProps} />} /> <Route path={PATHS.creditLines} render={(rProps) => <SimulationCreditLines {...rProps} />} />
<Route path={PATHS.proposalData} render={(rProps) => <ProposalData {...rProps} />} /> <Route
path={PATHS.proposalData}
render={(rProps) => {
const { location } = rProps as RouteComponentProps<any, any, ProposalDataRouteState>
if (location.state?.subproductId) return <ProposalData {...rProps} />
else return <NotFound {...rProps} />
}}
/>
<Redirect from="/" to={PATHS.creditLines} /> <Redirect from="/" to={PATHS.creditLines} />
</Switch> </Switch>
</Suspense> </Suspense>
......
...@@ -14,5 +14,7 @@ export default (theme: Theme) => { ...@@ -14,5 +14,7 @@ export default (theme: Theme) => {
paddingBottom: 0, paddingBottom: 0,
justifyContent: 'flex-start', justifyContent: 'flex-start',
}, },
appTitle: { flexGrow: 1, fontSize: '100%', textTransform: 'uppercase' },
titleAnchor: { cursor: 'pointer' },
}) })
} }
import React from 'react' import React from 'react'
import { withStyles, WithStyles } from '@material-ui/core/styles' import { withStyles, WithStyles } from '@material-ui/core/styles'
import {
AccountBox as AccountBoxIcon,
CheckBox as CheckBoxIcon,
ContactMail as ContactMailIcon,
DriveEta as DriveEtaIcon,
Forum as ForumIcon,
Home as HomeIcon,
List as ListIcon,
LocalAtm as LocalAtmIcon,
ZoomOutMap as ZoomOutMapIcon
} from '@material-ui/icons'
import Address from './Address'
import Home from './Home'
import Identification from './Identification'
import PersonalData from './PersonalData'
import References from './References'
import SourceIncome from './SourceIncome'
import SpouseAdditionalData from './SpouseAdditionalData'
import SpouseData from './SpouseData'
import styles from './styles' import styles from './styles'
import Vehicles from './Vehicles'
export const personalDataItems = [
{ label: 'Identificação', icon: <AccountBoxIcon />, component: <Identification /> },
{ label: 'Dados Pessoais', icon: <ListIcon />, component: <PersonalData /> },
{ label: 'Endereço', icon: <ContactMailIcon />, component: <Address /> },
{ label: 'Fonte de renda', icon: <LocalAtmIcon />, component: <SourceIncome /> },
{ label: 'Cônjuge - Ident.', icon: <ForumIcon />, component: <SpouseData /> },
{ label: 'Cônjuge +', icon: <ZoomOutMapIcon />, component: <SpouseAdditionalData /> },
{ label: 'Referências', icon: <CheckBoxIcon />, component: <References /> },
{ label: 'Moradia', icon: <HomeIcon />, component: <Home /> },
{ label: 'Veículos', icon: <DriveEtaIcon />, component: <Vehicles /> },
]
type ExtendedProps = WithStyles<typeof styles> type ExtendedProps = WithStyles<typeof styles>
...@@ -43,8 +11,8 @@ interface Props extends ExtendedProps { ...@@ -43,8 +11,8 @@ interface Props extends ExtendedProps {
} }
const CustomerData = (props: Props) => { const CustomerData = (props: Props) => {
const { classes, activeStep } = props const { classes } = props
return <div className={classes.stepContentContainer}>{personalDataItems[activeStep].component}</div> return <div className={classes.stepContentContainer}>{}</div>
} }
export default withStyles(styles)(CustomerData) export default withStyles(styles)(CustomerData)
import React from 'react' import React from 'react'
import { frameworks, genders } from '@agiliza/__mocks__/proposalData' import { BanestesAccount, DataType, ProposalDataContext } 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 { maskCPFCNPJ } from '@agiliza/utils/masks'
...@@ -9,28 +8,29 @@ import { SelectField, SelectFieldProps } from '@curio/components' ...@@ -9,28 +8,29 @@ 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'
import { IPIdentificationState } from '../state' import { CDIdentificationState } from '../state'
import styles from './styles' import styles from './styles'
type ExtendedProps = WithStyles<typeof styles> type ExtendedProps = WithStyles<typeof styles>
interface Props extends ExtendedProps { interface Props extends ExtendedProps {
state: IPIdentificationState state: CDIdentificationState
actions: ActionType<IPIdentificationState> actions: ActionType<CDIdentificationState>
context: ProposalDataContext
} }
const Form = (props: Props) => { const Form = (props: Props) => {
const { classes, state, actions } = props const { classes, state, actions, context } = props
const { cpfcnpj, dataType, name, gender, hasAccount, account } = state const { cpfcnpj, dataType, name, gender, hasAccount, account } = state
const handleChangeText = const handleChangeText =
(key: keyof IPIdentificationState): TextFieldProps['onChange'] => (key: keyof CDIdentificationState): TextFieldProps['onChange'] =>
(evt) => { (evt) => {
actions.update({ [key]: evt.target.value }) actions.update({ [key]: evt.target.value })
} }
const handleChangeSelect = const handleChangeSelect =
(key: keyof IPIdentificationState): SelectFieldProps['onChange'] => (key: keyof CDIdentificationState): SelectFieldProps['onChange'] =>
(vl) => { (vl) => {
actions.update({ [key]: vl }) actions.update({ [key]: vl })
} }
...@@ -60,7 +60,7 @@ const Form = (props: Props) => { ...@@ -60,7 +60,7 @@ const Form = (props: Props) => {
label="Enquadramento" label="Enquadramento"
value={dataType?.framework} value={dataType?.framework}
onChange={handleChangeDataType('framework')} onChange={handleChangeDataType('framework')}
items={frameworks.map((fw) => ({ label: fw.name, value: fw.id }))} items={context.frameworks.map((fw) => ({ label: fw.description, value: fw.id }))}
variant="outlined" variant="outlined"
shrink={false} shrink={false}
/> />
...@@ -77,7 +77,7 @@ const Form = (props: Props) => { ...@@ -77,7 +77,7 @@ const Form = (props: Props) => {
label="Sexo" label="Sexo"
value={gender} value={gender}
onChange={handleChangeSelect('gender')} onChange={handleChangeSelect('gender')}
items={genders.map((fw) => ({ label: fw.name, value: fw.id }))} items={context.genders.map((fw) => ({ label: fw.description, value: fw.id }))}
variant="outlined" variant="outlined"
shrink={false} shrink={false}
/> />
......
import React from 'react' import React, { useEffect } 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 { CDIdentificationState } 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: CDIdentificationState
actions: ActionType<any>
}
const Identification = (props: Props) => { const Identification = (props: Props) => {
const { classes } = props const { classes, context, state, actions } = props
const formState = useFormState('identificationForm', initialState) useEffect(() => {
props.fetchContext()
}, [])
return ( return (
<div className={classes.contentContainer}> <div className={classes.contentContainer}>
<div className={classes.content}> <div className={classes.content}>
<Form {...formState} /> <Form context={context} state={state} actions={actions} />
</div> </div>
</div> </div>
) )
} }
export default withStyles(styles)(Identification) export default connected(withStyles(styles)(Identification))
import { connect } from 'react-redux'
import { bindActionCreators, Dispatch } from 'redux'
import { ProposalDataContext } from '@agiliza/api/domain'
import { StoreState } from '@agiliza/redux'
import * as entProposalDataContext from '@agiliza/redux/entities/proposalData/context'
import * as ucProposalDataContext from '@agiliza/redux/useCases/proposalData/context'
import * as ucProposalDataCD from '@agiliza/redux/useCases/proposalData/customerData'
export interface ConnectedProps {
fetching: boolean
context: ProposalDataContext
fetchContext: typeof ucProposalDataContext.actions.fetchContext
updateIndentification: typeof ucProposalDataCD.actions.updateIndentification
}
type StateProps = Pick<ConnectedProps, 'fetching' | 'context'>
type DispatchProps = Pick<ConnectedProps, 'fetchContext' | 'updateIndentification'>
const mapStateToProps = (state: StoreState): StateProps => ({
fetching: ucProposalDataContext.selectors.isFetching(state.ui.login),
context: entProposalDataContext.selectors.getContext(state.entities.proposalData.context),
})
const mapDispatchToProps = (dispatch: Dispatch): DispatchProps =>
bindActionCreators(
{
fetchContext: ucProposalDataContext.actions.fetchContext,
updateIndentification: ucProposalDataCD.actions.updateIndentification,
},
dispatch
)
export const connected = connect(mapStateToProps, mapDispatchToProps)
export { default } from './Identification' export { default } from './Identification'
export * from './Identification' export * from './Identification'
export * from './state'
...@@ -2,11 +2,11 @@ import { InvolvedPerson } from '@agiliza/api/domain' ...@@ -2,11 +2,11 @@ import { InvolvedPerson } from '@agiliza/api/domain'
type ExtendedState = Omit<InvolvedPerson['identification'], 'type'> type ExtendedState = Omit<InvolvedPerson['identification'], 'type'>
export interface IPIdentificationState extends ExtendedState { export interface CDIdentificationState extends ExtendedState {
hasAccount: boolean hasAccount: boolean
} }
export const initialState: IPIdentificationState = { export const initialState: CDIdentificationState = {
id: '', id: '',
name: '', name: '',
cpfcnpj: '', cpfcnpj: '',
......
import React, { useMemo, useState } from 'react' import React, { useMemo, useState } from 'react'
import { RouteComponentProps } from 'react-router' import { RouteComponentProps } from 'react-router'
import { PATHS } from '@agiliza/views/Main/DrawerItems' import { useFormState } from '@agiliza/utils/hooks/state'
import { Button, MobileStepper, Typography } from '@material-ui/core' import { Button, MobileStepper, Typography } from '@material-ui/core'
import { withStyles, WithStyles } from '@material-ui/core/styles' import { withStyles, WithStyles } from '@material-ui/core/styles'
import { import {
AccountBox as AccountBoxIcon,
CheckBox as CheckBoxIcon,
ContactMail as ContactMailIcon,
DriveEta as DriveEtaIcon,
Forum as ForumIcon,
Home as HomeIcon,
KeyboardArrowLeft as KeyboardArrowLeftIcon, KeyboardArrowLeft as KeyboardArrowLeftIcon,
KeyboardArrowRight as KeyboardArrowRightIcon KeyboardArrowRight as KeyboardArrowRightIcon,
List as ListIcon,
LocalAtm as LocalAtmIcon,
ZoomOutMap as ZoomOutMapIcon
} from '@material-ui/icons' } from '@material-ui/icons'
import { businessDataItems } from './BusinessData' import { businessDataItems } from './BusinessData'
import { personalDataItems } from './CustomerData' import { connected, ConnectedProps } from './connect'
import Address from './CustomerData/Address'
import Home from './CustomerData/Home'
import Identification, { initialState as cdIdentInitState } from './CustomerData/Identification'
import PersonalData from './CustomerData/PersonalData'
import References from './CustomerData/References'
import SourceIncome from './CustomerData/SourceIncome'
import SpouseAdditionalData from './CustomerData/SpouseAdditionalData'
import SpouseData from './CustomerData/SpouseData'
import Vehicles from './CustomerData/Vehicles'
import styles from './shared-styles' import styles from './shared-styles'
export const PROPOSAL_DATA_PATHS = { export const PROPOSAL_DATA_PATHS = {
selectOption: PATHS.proposalData + '/selecionarOpcao', selectOption: '/selecionarOpcao',
involvedPeople: PATHS.proposalData + '/pessoasEnvolvidas', involvedPeople: '/pessoasEnvolvidas',
businessData: PATHS.proposalData + '/dadosNegocio', businessData: '/dadosNegocio',
} }
const proposalDataItems = [...personalDataItems, ...businessDataItems] export interface ProposalDataRouteState {
subproductId: string
}
type ExtendedProps = WithStyles<typeof styles> & RouteComponentProps type ExtendedProps = WithStyles<typeof styles> & RouteComponentProps & ConnectedProps
interface Props extends ExtendedProps {} interface Props extends ExtendedProps {}
...@@ -29,7 +49,31 @@ const ProposalData = (props: Props) => { ...@@ -29,7 +49,31 @@ const ProposalData = (props: Props) => {
const { classes } = props const { classes } = props
const [activeStep, setActiveStep] = useState(0) const [activeStep, setActiveStep] = useState(0)
const cdIdentification = useFormState('proposalDataState', cdIdentInitState)
const customerDataItems = useMemo(
() => [
{
label: 'Identificação',
icon: <AccountBoxIcon />,
component: <Identification state={cdIdentification.state} actions={cdIdentification.actions} />,
},
{ label: 'Dados Pessoais', icon: <ListIcon />, component: <PersonalData /> },
{ label: 'Endereço', icon: <ContactMailIcon />, component: <Address /> },
{ label: 'Fonte de renda', icon: <LocalAtmIcon />, component: <SourceIncome /> },
{ label: 'Cônjuge - Ident.', icon: <ForumIcon />, component: <SpouseData /> },
{ label: 'Cônjuge +', icon: <ZoomOutMapIcon />, component: <SpouseAdditionalData /> },
{ label: 'Referências', icon: <CheckBoxIcon />, component: <References /> },
{ label: 'Moradia', icon: <HomeIcon />, component: <Home /> },
{ label: 'Veículos', icon: <DriveEtaIcon />, component: <Vehicles /> },
],
[cdIdentification]
)
const proposalDataItems = useMemo(() => [...customerDataItems, ...businessDataItems], [customerDataItems, businessDataItems])
const steps = useMemo(() => proposalDataItems.length, [proposalDataItems]) const steps = useMemo(() => proposalDataItems.length, [proposalDataItems])
// const location = useLocation<ProposalDataRouteState>()
const handleNext = () => { const handleNext = () => {
// if (activeStep === steps - 1) history.push({ pathname: PATHS.creditLines }) // if (activeStep === steps - 1) history.push({ pathname: PATHS.creditLines })
...@@ -41,7 +85,7 @@ const ProposalData = (props: Props) => { ...@@ -41,7 +85,7 @@ const ProposalData = (props: Props) => {
} }
const mapActiveStepToTitle = () => { const mapActiveStepToTitle = () => {
if (activeStep < personalDataItems.length) return 'Dados do cliente' if (activeStep < customerDataItems.length) return 'Dados do cliente'
if (activeStep < proposalDataItems.length) return 'Dados de negócio' if (activeStep < proposalDataItems.length) return 'Dados de negócio'
} }
...@@ -90,4 +134,4 @@ const ProposalData = (props: Props) => { ...@@ -90,4 +134,4 @@ const ProposalData = (props: Props) => {
) )
} }
export default withStyles(styles)(ProposalData) export default connected(withStyles(styles)(ProposalData))
import { connect } from 'react-redux'
import { StoreState } from '@agiliza/redux'
import * as ucProposalDataContext from '@agiliza/redux/useCases/proposalData/context'
export interface ConnectedProps {
fetching: boolean
}
type StateProps = Pick<ConnectedProps, 'fetching'>
// type DispatchProps = Record<string, any>
const mapStateToProps = (state: StoreState): StateProps => ({
fetching: ucProposalDataContext.selectors.isFetching(state.ui.login),
})
// const mapDispatchToProps = (dispatch: Dispatch): DispatchProps => bindActionCreators({}, dispatch)
export const connected = connect(mapStateToProps)
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import { RouteComponentProps } from 'react-router' import { RouteComponentProps, useHistory } from 'react-router'
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'
...@@ -17,7 +17,7 @@ import { withStyles, WithStyles } from '@material-ui/core/styles' ...@@ -17,7 +17,7 @@ import { withStyles, WithStyles } from '@material-ui/core/styles'
import { Refresh as RefreshIcon } from '@material-ui/icons' import { Refresh as RefreshIcon } from '@material-ui/icons'
import { Autocomplete } from '@material-ui/lab' import { Autocomplete } from '@material-ui/lab'
import { CREDIT_LINES_PATHS } from '../router' import { CREDIT_LINES_PATHS, SimulationRouteState } from '../router'
import { connected, ConnectedProps } from './connect' import { connected, ConnectedProps } from './connect'
import SliderField from './SliderField' import SliderField from './SliderField'
import styles from './styles' import styles from './styles'
...@@ -29,12 +29,14 @@ interface Props extends ExtendedProps { ...@@ -29,12 +29,14 @@ interface Props extends ExtendedProps {
} }
const CreditLinesList = (props: Props) => { const CreditLinesList = (props: Props) => {
const { classes, fetching, history, match, simulationCategories } = props const { classes, fetching, match, simulationCategories } = props
useEffect(() => { useEffect(() => {
props.fetchSimulationCategories() props.fetchSimulationCategories()
}, []) }, [])
const history = useHistory<SimulationRouteState>()
const [selectedSimulCategory, setSelectedSimulCategory] = useState<SimulationCategory | null>(null) const [selectedSimulCategory, setSelectedSimulCategory] = useState<SimulationCategory | null>(null)
const [amount, setAmount] = useState('0') const [amount, setAmount] = useState('0')
const [paymentMonths, setPaymentMonths] = useState(0) const [paymentMonths, setPaymentMonths] = useState(0)
...@@ -44,13 +46,15 @@ const CreditLinesList = (props: Props) => { ...@@ -44,13 +46,15 @@ const CreditLinesList = (props: Props) => {
const handleSimulate = () => { const handleSimulate = () => {
if (selectedSimulCategory) if (selectedSimulCategory)
props.getSubproducts({ props.getSubproducts({
idModality: selectedSimulCategory.id, categoryId: selectedSimulCategory.id,
creditValue: Number(amount), creditValue: Number(amount),
idGracePeriod: graceMonths.toString(), gracePeriodId: graceMonths.toString(),
installmentsNumber: paymentMonths, installmentsNumber: paymentMonths,
onSuccess: (subPdcs) => { onSuccess: (subPdcs) => {
if (subPdcs && subPdcs.length > 0) history.push({ pathname: parentPath + CREDIT_LINES_PATHS.simulation }) if (subPdcs && subPdcs.length > 0) {
else props.setErrorMessage('Nenhum subproduto encontrado. Tente novamente com outros valores...') props.setData({ simulationCategoryId: selectedSimulCategory.id, amount, paymentMonths, graceMonths })
history.push({ pathname: parentPath + CREDIT_LINES_PATHS.simulation, state: { hasSubproducts: true } })
} else props.setErrorMessage('Nenhum subproduto encontrado. Tente novamente com outros valores...')
}, },
}) })
} }
...@@ -81,7 +85,9 @@ const CreditLinesList = (props: Props) => { ...@@ -81,7 +85,9 @@ const CreditLinesList = (props: Props) => {
const isValid = React.isValidElement(params.InputProps.endAdornment) const isValid = React.isValidElement(params.InputProps.endAdornment)
const fetchingEndAdornment = ( const fetchingEndAdornment = (
<InputAdornment position="end" style={{ flex: '1', display: 'flex', justifyContent: 'flex-end' }}> <InputAdornment position="end" style={{ flex: '1', display: 'flex', justifyContent: 'flex-end' }}>
<IconButton>
<CircularProgress size={20} /> <CircularProgress size={20} />
</IconButton>
</InputAdornment> </InputAdornment>
) )
const validEndAdornment = React.cloneElement(params.InputProps.endAdornment as React.ReactElement, { const validEndAdornment = React.cloneElement(params.InputProps.endAdornment as React.ReactElement, {
...@@ -190,24 +196,24 @@ const CreditLinesList = (props: Props) => { ...@@ -190,24 +196,24 @@ const CreditLinesList = (props: Props) => {
/> />
<SliderField <SliderField
className={classes.sliderField} className={classes.sliderField}
title="Quantos dias de carência?" title="Quantos meses de carência?"
sliderProps={{ sliderProps={{
min: 0, min: 0,
max: selectedSimulCategory?.maxGraceMonths || 12, max: selectedSimulCategory?.maxGraceMonths || 12,
marks: selectedSimulCategory marks: selectedSimulCategory
? [ ? [
{ value: 0, label: `${0} dias` }, { value: 0, label: `${0} meses` },
{ value: selectedSimulCategory?.maxGraceMonths, label: `${selectedSimulCategory?.maxGraceMonths} dias` }, { value: selectedSimulCategory?.maxGraceMonths, label: `${selectedSimulCategory?.maxGraceMonths} meses` },
] ]
: [ : [
{ value: 0, label: '0 dias' }, { value: 0, label: '0 meses' },
{ value: 12, label: '' }, { value: 12, label: '' },
], ],
value: Number(graceMonths), value: Number(graceMonths),
onChange: (_, value) => setGraceMonths(value as number), onChange: (_, value) => setGraceMonths(value as number),
}} }}
valueField={graceMonths.toString()} valueField={graceMonths.toString()}
suffix={`dia${graceMonths > 1 ? 's' : ''}`} suffix={`m${paymentMonths > 1 ? 'e' : 'ê'}s${paymentMonths > 1 ? 'es' : ''}`}
disabled={!selectedSimulCategory} disabled={!selectedSimulCategory}
onChangeField={(evt) => setGraceMonths(Number(extractNumbers(evt.target.value)))} onChangeField={(evt) => setGraceMonths(Number(extractNumbers(evt.target.value)))}
onBlurField={(evt) => { onBlurField={(evt) => {
......
...@@ -4,6 +4,7 @@ import { SimulationCategory } from '@agiliza/api/domain' ...@@ -4,6 +4,7 @@ import { SimulationCategory } from '@agiliza/api/domain'
import { StoreState } from '@agiliza/redux' import { StoreState } from '@agiliza/redux'
import * as entSimulationContext from '@agiliza/redux/entities/simulation/context' import * as entSimulationContext from '@agiliza/redux/entities/simulation/context'
import { actions as errorActions } from '@agiliza/redux/ui/error' import { actions as errorActions } from '@agiliza/redux/ui/error'
import * as uiSimulation from '@agiliza/redux/ui/simulation'
import * as ucSimulation from '@agiliza/redux/useCases/simulation' import * as ucSimulation from '@agiliza/redux/useCases/simulation'
import { bindActionCreators, Dispatch } from '@reduxjs/toolkit' import { bindActionCreators, Dispatch } from '@reduxjs/toolkit'
...@@ -13,10 +14,11 @@ export interface ConnectedProps { ...@@ -13,10 +14,11 @@ export interface ConnectedProps {
fetchSimulationCategories: typeof ucSimulation.actions.fetchSimulationCategories fetchSimulationCategories: typeof ucSimulation.actions.fetchSimulationCategories
getSubproducts: typeof ucSimulation.actions.getSubproducts getSubproducts: typeof ucSimulation.actions.getSubproducts
setErrorMessage: typeof errorActions.setErrorMessage setErrorMessage: typeof errorActions.setErrorMessage
setData: typeof uiSimulation.actions.setData
} }
type StateProps = Pick<ConnectedProps, 'fetching' | 'simulationCategories'> type StateProps = Pick<ConnectedProps, 'fetching' | 'simulationCategories'>
type DispatchProps = Pick<ConnectedProps, 'fetchSimulationCategories' | 'getSubproducts' | 'setErrorMessage'> type DispatchProps = Pick<ConnectedProps, 'fetchSimulationCategories' | 'getSubproducts' | 'setErrorMessage' | 'setData'>
const mapStateToProps = (state: StoreState): StateProps => ({ const mapStateToProps = (state: StoreState): StateProps => ({
fetching: ucSimulation.selectors.isFetching(state.useCases.simulation), fetching: ucSimulation.selectors.isFetching(state.useCases.simulation),
...@@ -29,6 +31,7 @@ const mapDispatchToProps = (dispatch: Dispatch): DispatchProps => ...@@ -29,6 +31,7 @@ const mapDispatchToProps = (dispatch: Dispatch): DispatchProps =>
fetchSimulationCategories: ucSimulation.actions.fetchSimulationCategories, fetchSimulationCategories: ucSimulation.actions.fetchSimulationCategories,
getSubproducts: ucSimulation.actions.getSubproducts, getSubproducts: ucSimulation.actions.getSubproducts,
setErrorMessage: errorActions.setErrorMessage, setErrorMessage: errorActions.setErrorMessage,
setData: uiSimulation.actions.setData,
}, },
dispatch dispatch
) )
......
import React, { useEffect, useState } from 'react' import React, { useState } from 'react'
import { SubProduct } from '@agiliza/api/domain' import { SubProduct } from '@agiliza/api/domain'
import { formatCurrency } from '@agiliza/utils/formatters' import { formatCurrency } from '@agiliza/utils/formatters'
...@@ -14,19 +14,16 @@ import styles from './styles' ...@@ -14,19 +14,16 @@ import styles from './styles'
type ExtendedProps = WithStyles<typeof styles> & ConnectedProps type ExtendedProps = WithStyles<typeof styles> & ConnectedProps
interface Props extends ExtendedProps { interface Props extends ExtendedProps {
onChangeCanGoForward: (vl: boolean) => void subproduct?: SubProduct
onChangeSubproduct: (subprd?: SubProduct) => void
} }
const CreditLinesInfo = (props: Props) => { const CreditLinesInfo = (props: Props) => {
const { classes, onChangeCanGoForward, subproducts } = props const { classes, subproducts, subproduct, onChangeSubproduct } = props
const [selectedSP, setSelectedSP] = useState<SubProduct | undefined>() // const [selectedSP, setSelectedSP] = useState<SubProduct | undefined>()
const [open, setOpen] = useState(false) const [open, setOpen] = useState(false)
useEffect(() => {
onChangeCanGoForward(!!selectedSP)
}, [selectedSP])
return ( return (
<div className={classes.contentContainer}> <div className={classes.contentContainer}>
<div className={classes.content}> <div className={classes.content}>
...@@ -35,24 +32,24 @@ const CreditLinesInfo = (props: Props) => { ...@@ -35,24 +32,24 @@ const CreditLinesInfo = (props: Props) => {
className={classes.selectField} className={classes.selectField}
label="Opções de Subproduto" label="Opções de Subproduto"
items={subproducts.map((sp) => ({ label: sp.description || '', value: sp.id }))} items={subproducts.map((sp) => ({ label: sp.description || '', value: sp.id }))}
value={selectedSP?.id || ''} value={subproduct?.id || ''}
onChange={(value) => { onChange={(value) => {
const subprd = subproducts.find((sp) => sp.id === value) const subprd = subproducts.find((sp) => sp.id === value)
setSelectedSP(subprd) onChangeSubproduct(subprd)
}} }}
shrink={false} shrink={false}
/> />
<Grid container className={classes.gridContainer}> <Grid container className={classes.gridContainer}>
<GridLine label="Número de parcelas" value={selectedSP?.maxAmountInstallment || ''} /> <GridLine label="Número de parcelas" value={subproduct?.maxAmountInstallment || ''} />
{/* <GridLine label="Valor das parcelas" value={formatCurrency(selectedSP?.amount.toFixed(2))} /> */} {/* <GridLine label="Valor das parcelas" value={formatCurrency(subproduct?.amount.toFixed(2))} /> */}
<GridLine label="Taxa de juros" value={selectedSP?.fee ? `${selectedSP?.fee} %` : ''} /> <GridLine label="Taxa de juros" value={subproduct?.fee ? `${subproduct?.fee} %` : ''} />
<GridLine label="Custo efetivo total (CET)" value={selectedSP?.IOF !== undefined ? `${selectedSP?.IOF} %` : ''} /> <GridLine label="Custo efetivo total (CET)" value={subproduct?.IOF !== undefined ? `${subproduct?.IOF} %` : ''} />
<GridLine label="Taxa abertura crédito (TAC)" value={formatCurrency(selectedSP?.TAC?.toFixed(2))} /> <GridLine label="Taxa abertura crédito (TAC)" value={formatCurrency(subproduct?.TAC?.toFixed(2))} />
</Grid> </Grid>
<Button variant="text" onClick={() => setOpen(true)} disabled={!selectedSP}> <Button variant="text" onClick={() => setOpen(true)} disabled={!subproduct}>
Exibir opções de parcelamento Exibir opções de parcelamento
</Button> </Button>
<InstallmentsDialog open={open} onClose={() => setOpen(false)} installmentOptions={selectedSP?.installementOptions} /> <InstallmentsDialog open={open} onClose={() => setOpen(false)} installmentOptions={subproduct?.installementOptions} />
</div> </div>
</div> </div>
) )
......
import React, { useMemo, useState } from 'react' import React, { useMemo, useState } from 'react'
import { RouteComponentProps } from 'react-router' import { RouteComponentProps } from 'react-router'
import { SubProduct } from '@agiliza/api/domain'
import { extractNumbers } from '@agiliza/utils/method'
import { PATHS } from '@agiliza/views/Main/DrawerItems' import { PATHS } from '@agiliza/views/Main/DrawerItems'
import { Button, Step, StepLabel, Stepper } from '@material-ui/core' import { Button, Step, StepLabel, Stepper } from '@material-ui/core'
import { withStyles, WithStyles } from '@material-ui/core/styles' import { withStyles, WithStyles } from '@material-ui/core/styles'
...@@ -9,37 +11,51 @@ import { ...@@ -9,37 +11,51 @@ import {
KeyboardArrowRight as KeyboardArrowRightIcon KeyboardArrowRight as KeyboardArrowRightIcon
} from '@material-ui/icons' } from '@material-ui/icons'
import { connected, ConnectedProps } from './connect'
import CreditLinesInfo from './CreditLinesInfo' import CreditLinesInfo from './CreditLinesInfo'
import styles from './styles' import styles from './styles'
import UserForm from './UserForm' import UserForm from './UserForm'
type ExtendedProps = WithStyles<typeof styles> & RouteComponentProps type ExtendedProps = WithStyles<typeof styles> & RouteComponentProps & ConnectedProps
interface Props extends ExtendedProps {} interface Props extends ExtendedProps {}
const Simulation = (props: Props) => { const Simulation = (props: Props) => {
const { classes, ...routerProps } = props const { classes, customer, simulationData, ...routerProps } = props
const { history } = routerProps const { history } = routerProps
// const theme = useTheme() // const theme = useTheme()
const [activeStep, setActiveStep] = useState(0) const [activeStep, setActiveStep] = useState(0)
const [canGoForward, setCanGoForward] = useState(true) // const [canGoForward, setCanGoForward] = useState(true)
const handleChangeCanGoForward = (value: boolean) => { const [subproduct, setSubproduct] = useState<SubProduct | undefined>()
setCanGoForward(value)
const handleChangeSubproduct = (sp?: SubProduct) => {
setSubproduct(sp)
} }
const renderStep = (step: number) => { const renderStep = (step: number) => {
switch (step) { switch (step) {
case 0: case 0:
return <CreditLinesInfo onChangeCanGoForward={handleChangeCanGoForward} /> return <CreditLinesInfo subproduct={subproduct} onChangeSubproduct={handleChangeSubproduct} />
case 1: case 1:
return <UserForm onChangeCanGoForward={handleChangeCanGoForward} /> return <UserForm />
} }
} }
const handleNext = () => { const handleNext = () => {
if (activeStep === steps - 1) history.push({ pathname: PATHS.creditLines }) if (activeStep === steps - 1) {
else setActiveStep((prevActiveStep) => prevActiveStep + 1) if (simulationData && subproduct) {
const { simulationCategoryId, amount, graceMonths, paymentMonths } = simulationData
props.createProposal({
categoryId: simulationCategoryId,
creditValue: Number(extractNumbers(amount)),
gracePeriodId: graceMonths,
installmentsNumber: paymentMonths,
subproductId: subproduct.id,
onSuccess: () => history.push({ pathname: PATHS.proposalData, state: { subproductId: subproduct?.id } }),
})
}
} else setActiveStep((prevActiveStep) => prevActiveStep + 1)
} }
const handleBack = () => { const handleBack = () => {
...@@ -48,6 +64,15 @@ const Simulation = (props: Props) => { ...@@ -48,6 +64,15 @@ const Simulation = (props: Props) => {
const steps = useMemo(() => 2, []) const steps = useMemo(() => 2, [])
const canGoForward = useMemo(() => {
switch (activeStep) {
case 0:
return !!subproduct
case 1:
return !!customer
}
}, [activeStep, subproduct, customer])
return ( return (
<div className={classes.pageContent}> <div className={classes.pageContent}>
<div className={classes.stepContentContainer}>{renderStep(activeStep)}</div> <div className={classes.stepContentContainer}>{renderStep(activeStep)}</div>
...@@ -98,4 +123,4 @@ const Simulation = (props: Props) => { ...@@ -98,4 +123,4 @@ const Simulation = (props: Props) => {
) )
} }
export default withStyles(styles)(Simulation) export default connected(withStyles(styles)(Simulation))
import React, { useEffect, useState } from 'react' import React, { useState } from 'react'
import ButtonWithProgress from '@agiliza/components/atoms/ButtonWithProgress' import ButtonWithProgress from '@agiliza/components/atoms/ButtonWithProgress'
import LoginTemplate from '@agiliza/components/templates/Login' import LoginTemplate from '@agiliza/components/templates/Login'
...@@ -27,22 +27,16 @@ interface State { ...@@ -27,22 +27,16 @@ interface State {
type ExtendedProps = WithStyles<typeof styles> & ConnectedProps type ExtendedProps = WithStyles<typeof styles> & ConnectedProps
interface Props extends ExtendedProps { interface Props extends ExtendedProps {}
onChangeCanGoForward: (vl: boolean) => void
}
const UserForm = (props: Props) => { const UserForm = (props: Props) => {
const { classes, fetching, onChangeCanGoForward, customer } = props const { classes, fetching, customer } = props
const [state, setState] = useState<State>({ username: '', password: '' }) const [state, setState] = useState<State>({ username: '', password: '' })
const { username, password } = state const { username, password } = state
const [open, setOpen] = useState(false) const [open, setOpen] = useState(false)
// const { errorState, validState: isValidState, actions } = useErrorValidator({ username: '', password: '' }) // const { errorState, validState: isValidState, actions } = useErrorValidator({ username: '', password: '' })
useEffect(() => {
onChangeCanGoForward(false)
}, [])
// useEffect(() => { // useEffect(() => {
// onChangeCanGoForward(isValidState) // onChangeCanGoForward(isValidState)
// }, [isValidState]) // }, [isValidState])
...@@ -68,9 +62,6 @@ const UserForm = (props: Props) => { ...@@ -68,9 +62,6 @@ const UserForm = (props: Props) => {
props.login({ props.login({
username: extractNumbers(username), username: extractNumbers(username),
password, password,
onSuccess: () => {
onChangeCanGoForward(true)
},
}) })
} }
> >
......
import { connect } from 'react-redux'
import { bindActionCreators, Dispatch } from 'redux'
import { Customer } from '@agiliza/api/domain'
import { StoreState } from '@agiliza/redux'
import * as session from '@agiliza/redux/session'
import * as uiSimulation from '@agiliza/redux/ui/simulation'
import * as ucProposalDataCD from '@agiliza/redux/useCases/proposalData/customerData'
export interface ConnectedProps {
customer?: Customer
simulationData: uiSimulation.State['data']
createProposal: typeof ucProposalDataCD.actions.createProposal
}
type StateProps = Pick<ConnectedProps, 'customer' | 'simulationData'>
type DispatchProps = Pick<ConnectedProps, 'createProposal'>
const mapStateToProps = (state: StoreState): StateProps => ({
customer: session.selectors.getCustomer(state.session),
simulationData: uiSimulation.selectors.getData(state.ui.simulation),
})
const mapDispatchToProps = (dispatch: Dispatch): DispatchProps =>
bindActionCreators(
{
createProposal: ucProposalDataCD.actions.createProposal,
},
dispatch
)
export const connected = connect(mapStateToProps, mapDispatchToProps)
...@@ -14,6 +14,10 @@ export const CREDIT_LINES_PATHS = { ...@@ -14,6 +14,10 @@ export const CREDIT_LINES_PATHS = {
simulation: '/simulador', simulation: '/simulador',
} }
export interface SimulationRouteState {
hasSubproducts: boolean
}
type ExtendedProps = WithStyles<typeof styles> & RouteComponentProps type ExtendedProps = WithStyles<typeof styles> & RouteComponentProps
interface Props extends ExtendedProps {} interface Props extends ExtendedProps {}
...@@ -29,10 +33,9 @@ const CreditLinesRouter = (props: Props) => { ...@@ -29,10 +33,9 @@ const CreditLinesRouter = (props: Props) => {
exact exact
path={match.path + CREDIT_LINES_PATHS.simulation} path={match.path + CREDIT_LINES_PATHS.simulation}
render={(rProps) => { render={(rProps) => {
return <Simulation {...rProps} /> const { location } = rProps as RouteComponentProps<any, any, SimulationRouteState>
// const { location } = rProps as RouteComponentProps<any, any, { id: string }> if (location.state?.hasSubproducts) return <Simulation {...rProps} />
// if (location.state?.id) return <Simulation {...rProps} /> else return <Redirect from={match.path + CREDIT_LINES_PATHS.simulation} to="/" />
// else return <NotFound {...rProps} />
}} }}
/> />
<Redirect from={match.path} to={match.path + CREDIT_LINES_PATHS.creditLinesList} /> <Redirect from={match.path} to={match.path + CREDIT_LINES_PATHS.creditLinesList} />
......
...@@ -4,7 +4,6 @@ import { connect } from 'react-redux' ...@@ -4,7 +4,6 @@ import { connect } from 'react-redux'
import { Route, Router, Switch } from 'react-router' import { Route, Router, Switch } from 'react-router'
import { bindActionCreators, Dispatch } from 'redux' import { bindActionCreators, Dispatch } from 'redux'
import AuthRoute from '@agiliza/components/atoms/AuthRoute'
import CircularProgress from '@agiliza/components/molecules/CircularProgress' import CircularProgress from '@agiliza/components/molecules/CircularProgress'
import { StoreState } from '@agiliza/redux' import { StoreState } from '@agiliza/redux'
import { isAuthenticated, isAuthenticating, isInitializing } from '@agiliza/redux/session/selectors' import { isAuthenticated, isAuthenticating, isInitializing } from '@agiliza/redux/session/selectors'
...@@ -13,7 +12,6 @@ import { isDrawerOpen } from '@agiliza/redux/ui/drawer/selectors' ...@@ -13,7 +12,6 @@ import { isDrawerOpen } from '@agiliza/redux/ui/drawer/selectors'
import { getError } from '@agiliza/redux/ui/error/selectors' import { getError } from '@agiliza/redux/ui/error/selectors'
import { actions as loginActions } from '@agiliza/redux/ui/login' import { actions as loginActions } from '@agiliza/redux/ui/login'
const Login = lazy(() => import('./Login'))
const Main = lazy(() => import('./Main')) const Main = lazy(() => import('./Main'))
const history = createHashHistory() const history = createHashHistory()
...@@ -38,8 +36,9 @@ const Views = (props: Props) => { ...@@ -38,8 +36,9 @@ const Views = (props: Props) => {
<Router history={history}> <Router history={history}>
<Suspense fallback={<CircularProgress />}> <Suspense fallback={<CircularProgress />}>
<Switch> <Switch>
<Route path="/login" render={(renderProps) => <Login {...renderProps} />} /> {/* <Route path="/login" render={(renderProps) => <Login {...renderProps} />} /> */}
<AuthRoute path="/" component={Main} /> <Route path="/" component={Main} />
{/* <AuthRoute path="/" component={Main} /> */}
</Switch> </Switch>
</Suspense> </Suspense>
</Router> </Router>
......
...@@ -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.11": "@microcredito/client@^0.7.13":
version "0.7.11" version "0.7.13"
resolved "https://nexus.dev.evologica.com.br/repository/npm/@microcredito/client/-/client-0.7.11.tgz#6601c681c6452c71d18e82f9ddca8bddeedf44a7" resolved "https://nexus.dev.evologica.com.br/repository/npm/@microcredito/client/-/client-0.7.13.tgz#ab47d224d9e5a373df69375afd086d6db7dee77b"
integrity sha1-ZgHGgcZFLHHRjoL53cqL3e7fRKc= integrity sha1-q0fSJNnlo3PfaTda/Qhtbbfe53s=
"@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