Padrão #6
openRim - Interação entre opções após a ação do usuário
0%
Description
Aqui vou citar as outras ações a mais caso o usuário selecione uma das 7 opções listadas na tarefa anterior:
Ausência Renal Direita / Nefrectomia Direita (aqui também vale o contrário para o lado esquerdo)
- Bloquear e desmarcar:
Medidas Rim Direito / Nefropatia parenquimatosa Rim Direito / Cisto Rim Direito / Cistos Bilaterais / Dilatação do sistema coletor Rim Direito / cálculo obstrutivo rim direito / múltiplos cálculos obstrutivos bilaterais - Bloquear a possibilidade de escolher "direito", "rim direito" ou "RD" de:
"direita" em rim pélvico (dentro de anomalias congênitas) / "RD" em nefrectomia parcial (dentro de cirurgias prévias) / "RD" em nódulo sólido / "RD" em Angiomiolipoma / "RD" em Cisto complexo / "RD" em todos os Cálculos não obstrutivos / "rim direito" em microcálculos calicinais
Rins em Ferradura
- Bloquear e desmarcar: Medidas Rim Direito e Esquerdo / Nefropatia parenquimatosa (Direito ou Esquerdo) / Cirurgias prévias (todo o campo)
Ectopia renal cruzada direita ou esquerda
- Bloquear e desmarcar todos os campos, exceto dilatação do sistema coletor RD e RE (pode bloquear também cálculo obstrutivo)
Files
Updated by jean sodré 6 months ago
- Status changed from em execução to teste
Exemplo de lógica aplicada:
$scope.criarExclusaoMutuaComMemoria({
campos: [
'dados.rins.ausenciaRD',
'dados.rins.ausenciaRE',
'dados.rins.cistoRimDireitoQtd',
'dados.rins.nefropatiaRD',
'dados.rins.cistosBilateraisAtivo',
'dados.rins.dilatacaoDireitoGrau',
'dados.rins.ureteralDireito',
'dados.rins.calculoObstrutivoDireito',
'dados.rins.multiplosCalculos',
'dados.rins.cistoRimEsquerdoQtd',
'dados.rins.nefropatiaRE',
'dados.rins.dilatacaoEsquerdoGrau',
'dados.rins.ureteralEsquerdo',
'dados.rins.calculoObstrutivoEsquerdo'
],
gruposCompativeis: [
// Grupo 1: Ausência Lado Direito - compatível com elementos do lado esquerdo
['dados.rins.ausenciaRE', 'dados.rins.cistoRimDireitoQtd', 'dados.rins.nefropatiaRD', 'dados.rins.cistosBilateraisAtivo',
'dados.rins.dilatacaoDireitoGrau', 'dados.rins.ureteralDireito', 'dados.rins.calculoObstrutivoDireito'
],
// Grupo 2: Ausência Lado Esquerdo - compatível com elementos do lado direito
['dados.rins.ausenciaRD', 'dados.rins.cistoRimEsquerdoQtd', 'dados.rins.nefropatiaRE', 'dados.rins.cistosBilateraisAtivo',
'dados.rins.dilatacaoEsquerdoGrau', 'dados.rins.ureteralEsquerdo', 'dados.rins.calculoObstrutivoEsquerdo' ],
// Grupo 3: Elementos do lado esquerdo compatíveis entre si
['dados.rins.cistoRimEsquerdoQtd', 'dados.rins.nefropatiaRE', 'dados.rins.cistosBilateraisAtivo',
'dados.rins.dilatacaoEsquerdoGrau', 'dados.rins.ureteralEsquerdo', 'dados.rins.calculoObstrutivoEsquerdo',
'dados.rins.calculoObstrutivoDireito', 'dados.rins.multiplosCalculos' ],
// Grupo 4: Elementos do lado direito compatíveis entre si
['dados.rins.cistoRimDireitoQtd', 'dados.rins.nefropatiaRD', 'dados.rins.cistosBilateraisAtivo',
'dados.rins.dilatacaoDireitoGrau', 'dados.rins.ureteralDireito', 'dados.rins.calculoObstrutivoDireito',
'dados.rins.multiplosCalculos'
]
],
camposPrioritarios: [
'dados.rins.ausenciaRD',
'dados.rins.ausenciaRE'
]
});
Updated by jean sodré 6 months ago · Edited
Função criada para salvar em memória e facilitar a configuração desabilitar/habilitar campos
$scope.criarExclusaoMutuaComMemoria = function(config) {
let processandoExclusao = false;
let memoriaEstados = {}; // Guarda o estado anterior dos campos
// Função para obter valor aninhado
function getNestedValue(obj, path) {
return path.split('.').reduce((current, key) => {
return current && current[key] !== undefined ? current[key] : null;
}, obj);
}
// Função para definir valor aninhado
function setNestedValue(obj, path, value) {
const keys = path.split('.');
const lastKey = keys.pop();
const target = keys.reduce((current, key) => {
if (!current[key]) current[key] = {};
return current[key];
}, obj);
target[lastKey] = value;
}
// Função para detectar o tipo de valor e definir o valor "vazio"
function getValorVazio(valor) {
if (typeof valor === 'boolean') return false;
if (typeof valor === 'number') return 0;
if (typeof valor === 'string') return '';
return null;
}
// 🎯 NOVA FUNÇÃO: Verifica se um campo está ativo considerando valores específicos
function campoEstaAtivo(path, valorEspecifico = null) {
const valor = getNestedValue($scope, path);
// Se foi especificado um valor específico, verifica se o campo tem esse valor
if (valorEspecifico !== null) {
return valor === valorEspecifico;
}
// Lógica original para outros tipos
if (typeof valor === 'boolean') return valor === true;
if (typeof valor === 'number') return valor !== 0;
if (typeof valor === 'string') return valor !== '';
return false;
}
// 🎯 NOVA FUNÇÃO: Verifica se um campo tem configuração de valor específico
function temValorEspecifico(campoConfig) {
return typeof campoConfig === 'object' && campoConfig.campo && campoConfig.valor;
}
// 🎯 NOVA FUNÇÃO: Extrai o nome do campo de uma configuração
function getNomeCampo(campoConfig) {
return temValorEspecifico(campoConfig) ? campoConfig.campo : campoConfig;
}
// 🎯 NOVA FUNÇÃO: Extrai o valor específico de uma configuração
function getValorEspecifico(campoConfig) {
return temValorEspecifico(campoConfig) ? campoConfig.valor : null;
}
// 🎯 FUNÇÃO: Salva estado atual dos campos na memória
function salvarEstadoNaMemoria(campoReferencia, camposParaSalvar) {
if (!memoriaEstados[campoReferencia]) {
memoriaEstados[campoReferencia] = {};
}
camposParaSalvar.forEach(campoConfig => {
const nomeCampo = getNomeCampo(campoConfig);
const valor = getNestedValue($scope, nomeCampo);
if (campoEstaAtivo(nomeCampo)) {
memoriaEstados[campoReferencia][nomeCampo] = valor;
console.log(`💾 Salvando estado de '${nomeCampo}':`, valor);
}
});
}
// 🎯 FUNÇÃO: Restaura estado dos campos da memória
function restaurarEstadoDaMemoria(campoReferencia) {
if (memoriaEstados[campoReferencia]) {
console.log(`🔄 Restaurando estados para '${campoReferencia}':`, memoriaEstados[campoReferencia]);
Object.keys(memoriaEstados[campoReferencia]).forEach(campo => {
const valorSalvo = memoriaEstados[campoReferencia][campo];
setNestedValue($scope, campo, valorSalvo);
console.log(`✅ Restaurado '${campo}' para:`, valorSalvo);
});
// Limpa a memória após restaurar
delete memoriaEstados[campoReferencia];
}
}
// 🎯 FUNÇÃO: Limpa memória de um campo
function limparMemoriaDoCampo(campoReferencia) {
if (memoriaEstados[campoReferencia]) {
console.log(`🗑️ Limpando memória de '${campoReferencia}'`);
delete memoriaEstados[campoReferencia];
}
}
// 🎯 NOVA FUNÇÃO: Limpa um campo considerando configurações especiais
function limparCampo(campoConfig) {
const nomeCampo = getNomeCampo(campoConfig);
// Se tem configuração de limpeza específica
if (temValorEspecifico(campoConfig) && campoConfig.limparPara !== undefined) {
setNestedValue($scope, nomeCampo, campoConfig.limparPara);
console.log(`🧹 Limpando '${nomeCampo}' para valor específico:`, campoConfig.limparPara);
} else {
// Lógica original
const valor = getNestedValue($scope, nomeCampo);
const valorVazio = getValorVazio(valor);
setNestedValue($scope, nomeCampo, valorVazio);
console.log(`🧹 Limpando '${nomeCampo}' para valor vazio:`, valorVazio);
}
}
// 🎯 NOVA FUNÇÃO: Verifica se dois campos são compatíveis
function saoCompativeis(campoConfig1, campoConfig2) {
const nomeCampo1 = getNomeCampo(campoConfig1);
const nomeCampo2 = getNomeCampo(campoConfig2);
if (config.gruposCompativeis) {
return config.gruposCompativeis.some(grupo => {
const temCampo1 = grupo.some(item => getNomeCampo(item) === nomeCampo1);
const temCampo2 = grupo.some(item => getNomeCampo(item) === nomeCampo2);
return temCampo1 && temCampo2;
});
}
return false;
}
// 🎯 NOVA FUNÇÃO: Verifica se é um campo prioritário
function ehCampoPrioritario(campoConfig) {
const nomeCampo = getNomeCampo(campoConfig);
return config.camposPrioritarios && config.camposPrioritarios.some(item =>
getNomeCampo(item) === nomeCampo
);
}
// 🎯 NOVA FUNÇÃO: Obtém campos incompatíveis
function getCamposIncompativeis(campoReferencia, todosCampos) {
return todosCampos.filter(campoConfig => {
const nomeCampo = getNomeCampo(campoConfig);
const nomeReferencia = getNomeCampo(campoReferencia);
return nomeCampo !== nomeReferencia && !saoCompativeis(campoReferencia, campoConfig);
});
}
// 🎯 NOVA FUNÇÃO: Normaliza a lista de campos para incluir apenas nomes únicos para o watchGroup
function getNomesCamposParaWatch() {
const nomes = new Set();
config.campos.forEach(campoConfig => {
nomes.add(getNomeCampo(campoConfig));
});
return Array.from(nomes);
}
// Cria o $watchGroup automaticamente
const nomesParaWatch = getNomesCamposParaWatch();
$scope.$watchGroup(nomesParaWatch, function(newValues, oldValues) {
// Evita loop infinito
if (processandoExclusao) return;
// Evita execução na primeira vez
if (newValues === oldValues) return;
// Encontra qual campo foi alterado
let campoAlterado = null;
let valorAnterior = null;
let valorAtual = null;
for (let i = 0; i < nomesParaWatch.length; i++) {
if (newValues[i] !== oldValues[i]) {
const nomeCampo = nomesParaWatch[i];
valorAnterior = oldValues[i];
valorAtual = newValues[i];
// Encontra a configuração completa do campo alterado
campoAlterado = config.campos.find(campoConfig =>
getNomeCampo(campoConfig) === nomeCampo
);
break;
}
}
if (campoAlterado) {
processandoExclusao = true;
const nomeCampoAlterado = getNomeCampo(campoAlterado);
const valorEspecifico = getValorEspecifico(campoAlterado);
console.log('Campo alterado:', nomeCampoAlterado, 'de', valorAnterior, 'para', valorAtual);
if (valorEspecifico) {
console.log('Valor específico monitorado:', valorEspecifico);
}
// Obtém os campos incompatíveis com o campo alterado
const camposIncompativeis = getCamposIncompativeis(campoAlterado, config.campos);
// 🎯 LÓGICA PRINCIPAL: Se campo foi ATIVADO (considerando valor específico)
if (campoEstaAtivo(nomeCampoAlterado, valorEspecifico)) {
console.log(`✅ Campo '${nomeCampoAlterado}' foi ativado`);
// 🎯 Se é um campo prioritário
if (ehCampoPrioritario(campoAlterado)) {
console.log(`🎯 Campo '${nomeCampoAlterado}' é prioritário - salvando estados`);
// Salva o estado dos campos que serão limpos
salvarEstadoNaMemoria(nomeCampoAlterado, camposIncompativeis);
}
// Limpa os campos incompatíveis que estão ativos
camposIncompativeis.forEach(campoConfig => {
const nomeCampo = getNomeCampo(campoConfig);
const valorEspecificoIncompativel = getValorEspecifico(campoConfig);
if (campoEstaAtivo(nomeCampo, valorEspecificoIncompativel)) {
console.log(`🧹 Limpando campo incompatível: '${nomeCampo}'`);
limparCampo(campoConfig);
}
});
// Limpa memória de outros campos prioritários que podem ter conflito
if (config.camposPrioritarios) {
config.camposPrioritarios.forEach(campoPrioritario => {
const nomePrioritario = getNomeCampo(campoPrioritario);
if (nomePrioritario !== nomeCampoAlterado) {
limparMemoriaDoCampo(nomePrioritario);
}
});
}
}
// 🎯 LÓGICA PRINCIPAL: Se campo foi DESATIVADO
else {
console.log(`❌ Campo '${nomeCampoAlterado}' foi desativado`);
// 🎯 Se é um campo prioritário que foi desativado
if (ehCampoPrioritario(campoAlterado)) {
console.log(`🔄 Campo '${nomeCampoAlterado}' é prioritário - restaurando estados`);
// Restaura o estado anterior dos campos
restaurarEstadoDaMemoria(nomeCampoAlterado);
}
}
setTimeout(() => {
processandoExclusao = false;
}, 100);
}
});
console.log('Exclusão mútua com memória criada para:', config.campos.map(c => getNomeCampo(c)));
console.log('Grupos compatíveis:', config.gruposCompativeis);
console.log('Campos prioritários:', config.camposPrioritarios);
};
Updated by Henrique Novaes 6 months ago
Após revisão:
- Ausência RD selecionada pelo usuário:
- falta bloquear o campo "Nefropatia parenquimatosa RD"
- Quando seleciono "Nefropatia parenquimatosa RE" está desmarcando automaticamente o "Ausência RD" (o certo é o usuário poder utilizar essa opção)
- Nefrectomia total ainda está habilitado = o certo é bloquear as duas opções (lado direito e lado esquerdo)
- As opções de lado direito de "nefrectomia parcial", "rim pélvico", "nódulo sólido", "angiomiolipoma", "cisto complexo", "cálculos não obstrutivos" e "microcálculos calicinais" permanecem passíveis de serem selecionadas (o certo é estarem bloqueadas já que não temos rim direito)
OBS: no caso dos microcálculos calicinais, tem uma opção "bilaterais" na caixa de seleção que também é bloqueada nesses casos de ausência RD/RE e nefrectomia total RD/RE
-
Ausência RE selecionada pelo usuário:
Mesma situação do ausência RD, porém do lado esquerdo agora -
Nefrectomia RD/RE selecionada pelo usuário
Popover com problema, não consegui testar -
Rins em Ferradura
Bloqueou os campos certos, porém está bloqueando os "Cistos Rim Direito" e "Cistos Rim Esquerdo" quando são descritos isoladamente (o certo é não bloquear esses campos). O restante está correto -
Ectopia Renal Cruzada
Correto
Updated by Henrique Novaes 6 months ago
- File clipboard-202507080042-gnrqc.png clipboard-202507080042-gnrqc.png added
- Status changed from teste to teste reprovado
- "Ausência RD" selecionada pelo usuário
- Está bloqueando todo o campo de cirurgias prévias (como comentado anteriormente na outra tarefa, o objetivo é bloquear apenas "nefrectomia total")
- Ao mudar o numero de "cistos", desmarca sozinho de maneira errada o "ausência RD". Da mesma forma outras alternativas como "nefropatia parenquimatosa RE" e "microcálculos calicinais" também se desmarcam sozinhas ao tentar mudar algo na caixa de seleção deles, mas não interferem diretamente no "ausência RD".
- precisamos também bloquear as opções do lado direito das seguintes: "nefrectomia parcial", "rim pélvico", "nódulo sólido", "angiomiolipoma", "cisto complexo", "cálculos não obstrutivos" e "microcálculos calicinais" (o certo é estarem bloqueadas já que não temos rim direito). Segue um exemplo:
- "Ausência RE" selecionada pelo usuário
- Aqui consegui marcar outras opções sem problemas, o que falta mesmo é bloquear a possibilidade de marcar o lado esquerdo das mesmas opções acima ("nefrectomia parcial", "rim pélvico", "nódulo sólido", "angiomiolipoma", "cisto complexo", "cálculos não obstrutivos" e "microcálculos calicinais")
- "Nefrectomia total direita" selecionada pelo usuário
- Precisamos bloquear os campos de "ausência RD", "ausência RE", "cistos Rim direito", "Cistos bilaterais", "Dilatação sistema coletor direito", "Cistos bilaterais" e "múltiplos cálculos não obstrutivos bilaterais"
- precisamos também bloquear as opções do lado direito das seguintes: "nefrectomia parcial", "rim pélvico", "nódulo sólido", "angiomiolipoma", "cisto complexo", "cálculos não obstrutivos" e "microcálculos calicinais" (o certo é estarem bloqueadas já que não temos rim direito).
- "Nefrectomia total esquerda" selecionada pelo usuário
- Precisamos bloquear os campos de "ausência RD", "ausência RE", "cistos Rim esquerdo", "Cistos bilaterais", "Dilatação sistema coletor esquerdo", "Cistos bilaterais" e "múltiplos cálculos não obstrutivos bilaterais"
- precisamos também bloquear as opções do lado esquerdo das seguintes: "nefrectomia parcial", "rim pélvico", "nódulo sólido", "angiomiolipoma", "cisto complexo", "cálculos não obstrutivos" e "microcálculos calicinais" (o certo é estarem bloqueadas já que não temos rim esquerdo).
Notei também que estamos tendo problemas ao selecionar alguma opção das caixas de seleção de algumas opções:
- Nefropatia parenquimatosa RD/RE: desmarca sozinho ao clicar na caixa de seleção
-
- ureteral: desmarca sozinho ao clicar na caixa de seleção
- Microcálculos calicinais: desmarca sozinho ao clicar na caixa de seleção
Updated by jean sodré 6 months ago
- File Captura de Tela 2025-07-09 às 20.56.26.png Captura de Tela 2025-07-09 às 20.56.26.png added
- Status changed from teste reprovado to teste
Sobre o pedido 3 e o pedido 4 "bloquear nefrectomia parcial", eu não não apliquei porque é um radio, então o usuário só vai poder escolher ou um ou outro mesmo... Mas depois me confirma como prefere

Updated by Henrique Novaes 6 months ago
- Status changed from teste to teste reprovado
Comentei com mais precisão na tarefa #2