feat: enhance call and point registration features with sensor data integration
- Updated the CallWindow component to include connection quality states and reconnection attempts, improving user experience during calls. - Enhanced the ChatWindow to allow starting audio and video calls in a new window, providing users with more flexibility. - Integrated accelerometer and gyroscope data collection in the RegistroPonto component, enabling validation of point registration authenticity. - Improved error handling and user feedback for sensor permissions and data validation, ensuring a smoother registration process. - Updated backend logic to validate sensor data and adjust confidence scores for point registration, enhancing security against spoofing.
This commit is contained in:
@@ -108,9 +108,14 @@
|
||||
}
|
||||
|
||||
// Verificar permissões de localização e webcam
|
||||
async function verificarPermissoes(): Promise<{ localizacao: boolean; webcam: boolean }> {
|
||||
async function verificarPermissoes(): Promise<{
|
||||
localizacao: boolean;
|
||||
webcam: boolean;
|
||||
permissoesNecessarias: string[];
|
||||
}> {
|
||||
let localizacaoAutorizada = false;
|
||||
let webcamAutorizada = false;
|
||||
const permissoesNecessarias: string[] = [];
|
||||
|
||||
// Verificar permissão de geolocalização
|
||||
if (navigator.geolocation) {
|
||||
@@ -126,8 +131,11 @@
|
||||
localizacaoAutorizada = true;
|
||||
resolve();
|
||||
},
|
||||
() => {
|
||||
(error) => {
|
||||
clearTimeout(timeoutId);
|
||||
if (error.code === error.PERMISSION_DENIED) {
|
||||
permissoesNecessarias.push('localização');
|
||||
}
|
||||
reject(new Error('Permissão de localização negada'));
|
||||
},
|
||||
{ timeout: 5000, maximumAge: 0, enableHighAccuracy: false }
|
||||
@@ -147,10 +155,11 @@
|
||||
stream.getTracks().forEach(track => track.stop());
|
||||
} catch (error) {
|
||||
console.warn('Permissão de webcam não concedida:', error);
|
||||
permissoesNecessarias.push('câmera');
|
||||
}
|
||||
}
|
||||
|
||||
return { localizacao: localizacaoAutorizada, webcam: webcamAutorizada };
|
||||
return { localizacao: localizacaoAutorizada, webcam: webcamAutorizada, permissoesNecessarias };
|
||||
}
|
||||
|
||||
async function registrarPonto() {
|
||||
@@ -176,7 +185,8 @@
|
||||
const permissoes = await verificarPermissoes();
|
||||
if (!permissoes.localizacao || !permissoes.webcam) {
|
||||
mensagemErroModal = 'Permissões necessárias';
|
||||
detalhesErroModal = 'Para registrar o ponto, é necessário autorizar o compartilhamento de localização e a captura de foto.';
|
||||
const permissoesLista = permissoes.permissoesNecessarias.join(', ');
|
||||
detalhesErroModal = `Para registrar o ponto, é necessário autorizar o compartilhamento de localização e a captura de foto.\n\nPermissões negadas: ${permissoesLista || 'localização e/ou câmera'}`;
|
||||
mostrarModalErro = true;
|
||||
return;
|
||||
}
|
||||
@@ -188,6 +198,8 @@
|
||||
try {
|
||||
// Coletar informações do dispositivo
|
||||
const informacoesDispositivo = await obterInformacoesDispositivo();
|
||||
// Nota: A permissão de sensor não é impeditiva - apenas câmera e localização são obrigatórias
|
||||
|
||||
coletandoInfo = false;
|
||||
|
||||
// Obter tempo sincronizado e aplicar GMT offset (igual ao relógio)
|
||||
@@ -278,30 +290,80 @@
|
||||
}, 1000);
|
||||
} catch (error) {
|
||||
console.error('Erro ao registrar ponto:', error);
|
||||
const mensagemErro = error instanceof Error ? error.message : 'Erro ao registrar ponto';
|
||||
let mensagemErro = 'Erro desconhecido ao registrar ponto';
|
||||
let detalhesErro = 'Tente novamente em alguns instantes.';
|
||||
|
||||
// Verificar se é erro de registro duplicado
|
||||
if (
|
||||
mensagemErro.includes('Já existe um registro neste minuto') ||
|
||||
mensagemErro.includes('já existe um registro')
|
||||
) {
|
||||
mensagemErroModal = 'Registro de ponto duplicado';
|
||||
const tipoLabelErro = config
|
||||
? getTipoRegistroLabel(proximoTipo, {
|
||||
nomeEntrada: config.nomeEntrada,
|
||||
nomeSaidaAlmoco: config.nomeSaidaAlmoco,
|
||||
nomeRetornoAlmoco: config.nomeRetornoAlmoco,
|
||||
nomeSaida: config.nomeSaida,
|
||||
})
|
||||
: getTipoRegistroLabel(proximoTipo);
|
||||
detalhesErroModal = `Não é possível registrar o ponto no mesmo minuto.\n\nVocê já possui um registro de ${tipoLabelErro} para este minuto.\n\nPor favor, aguarde pelo menos 1 minuto antes de tentar registrar novamente.`;
|
||||
mostrarModalErro = true;
|
||||
} else {
|
||||
// Outros erros também mostram no modal
|
||||
mensagemErroModal = 'Erro ao registrar ponto';
|
||||
detalhesErroModal = mensagemErro;
|
||||
mostrarModalErro = true;
|
||||
if (error instanceof Error) {
|
||||
const erroMessage = error.message || '';
|
||||
|
||||
// Erro de registro duplicado
|
||||
if (
|
||||
erroMessage.includes('Já existe um registro neste minuto') ||
|
||||
erroMessage.includes('já existe um registro')
|
||||
) {
|
||||
mensagemErro = 'Registro de ponto duplicado';
|
||||
const tipoLabelErro = config
|
||||
? getTipoRegistroLabel(proximoTipo, {
|
||||
nomeEntrada: config.nomeEntrada,
|
||||
nomeSaidaAlmoco: config.nomeSaidaAlmoco,
|
||||
nomeRetornoAlmoco: config.nomeRetornoAlmoco,
|
||||
nomeSaida: config.nomeSaida,
|
||||
})
|
||||
: getTipoRegistroLabel(proximoTipo);
|
||||
detalhesErro = `Não é possível registrar o ponto no mesmo minuto.\n\nVocê já possui um registro de ${tipoLabelErro} para este minuto.\n\nPor favor, aguarde pelo menos 1 minuto antes de tentar registrar novamente.`;
|
||||
}
|
||||
// Erro de validação de argumentos
|
||||
else if (
|
||||
erroMessage.includes('ArgumentValidationError') ||
|
||||
erroMessage.includes('Object contains extra field') ||
|
||||
erroMessage.includes('validation')
|
||||
) {
|
||||
mensagemErro = 'Erro na validação dos dados';
|
||||
detalhesErro = 'Ocorreu um erro ao validar as informações do dispositivo.\n\nPor favor, tente novamente ou recarregue a página.';
|
||||
}
|
||||
// Erro de autenticação
|
||||
else if (
|
||||
erroMessage.includes('não autenticado') ||
|
||||
erroMessage.includes('autenticado') ||
|
||||
erroMessage.includes('auth')
|
||||
) {
|
||||
mensagemErro = 'Erro de autenticação';
|
||||
detalhesErro = 'Sua sessão pode ter expirado. Por favor, faça login novamente.';
|
||||
}
|
||||
// Erro de permissão/validação de localização
|
||||
else if (
|
||||
erroMessage.includes('localização') ||
|
||||
erroMessage.includes('Localização') ||
|
||||
erroMessage.includes('location')
|
||||
) {
|
||||
mensagemErro = 'Erro na validação de localização';
|
||||
detalhesErro = 'Não foi possível validar sua localização.\n\nPor favor, verifique se você autorizou o compartilhamento de localização e tente novamente.';
|
||||
}
|
||||
// Erro genérico do servidor
|
||||
else if (erroMessage.includes('Server Error') || erroMessage.includes('Server')) {
|
||||
mensagemErro = 'Erro no servidor';
|
||||
detalhesErro = 'Ocorreu um erro no servidor ao processar seu registro.\n\nPor favor, tente novamente em alguns instantes.';
|
||||
}
|
||||
// Outros erros - mostrar mensagem simplificada
|
||||
else {
|
||||
mensagemErro = 'Erro ao registrar ponto';
|
||||
// Se a mensagem de erro for muito técnica, mostrar mensagem genérica
|
||||
if (
|
||||
erroMessage.includes('Error:') ||
|
||||
erroMessage.includes('TypeError') ||
|
||||
erroMessage.includes('ReferenceError') ||
|
||||
erroMessage.length > 200
|
||||
) {
|
||||
detalhesErro = 'Ocorreu um erro ao processar o registro.\n\nPor favor, tente novamente ou recarregue a página.';
|
||||
} else {
|
||||
detalhesErro = erroMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mensagemErroModal = mensagemErro;
|
||||
detalhesErroModal = detalhesErro;
|
||||
mostrarModalErro = true;
|
||||
} finally {
|
||||
registrando = false;
|
||||
coletandoInfo = false;
|
||||
|
||||
Reference in New Issue
Block a user