feat: Add 'atas' (minutes/records) management feature, and implement various improvements across UI, backend logic, and authentication.
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import { v } from 'convex/values';
|
||||
import { api, internal } from './_generated/api';
|
||||
import type { Id } from './_generated/dataModel';
|
||||
import { action, internalMutation, internalQuery, mutation, query } from './_generated/server';
|
||||
import { getCurrentUserFunction } from './auth';
|
||||
import type { Id } from './_generated/dataModel';
|
||||
import { api, internal } from './_generated/api';
|
||||
|
||||
/**
|
||||
* Tipo de retorno da configuração do relógio
|
||||
@@ -24,14 +24,13 @@ export const obterConfiguracao = query({
|
||||
args: {},
|
||||
handler: async (ctx): Promise<ConfiguracaoRelogioRetorno> => {
|
||||
// Buscar todas as configurações e pegar a mais recente (por atualizadoEm)
|
||||
const configs = await ctx.db
|
||||
.query('configuracaoRelogio')
|
||||
.collect();
|
||||
|
||||
const configs = await ctx.db.query('configuracaoRelogio').collect();
|
||||
|
||||
// Pegar a configuração mais recente (ordenar por atualizadoEm desc)
|
||||
const config = configs.length > 0
|
||||
? configs.sort((a, b) => (b.atualizadoEm || 0) - (a.atualizadoEm || 0))[0]
|
||||
: null;
|
||||
const config =
|
||||
configs.length > 0
|
||||
? configs.sort((a, b) => (b.atualizadoEm || 0) - (a.atualizadoEm || 0))[0]
|
||||
: null;
|
||||
|
||||
if (!config) {
|
||||
// Retornar configuração padrão (GMT-3 para Brasília)
|
||||
@@ -42,7 +41,7 @@ export const obterConfiguracao = query({
|
||||
fallbackParaPC: true,
|
||||
ultimaSincronizacao: null,
|
||||
offsetSegundos: null,
|
||||
gmtOffset: -3, // GMT-3 para Brasília
|
||||
gmtOffset: -3 // GMT-3 para Brasília
|
||||
};
|
||||
}
|
||||
|
||||
@@ -50,9 +49,9 @@ export const obterConfiguracao = query({
|
||||
...config,
|
||||
ultimaSincronizacao: config.ultimaSincronizacao ?? null, // Converter undefined para null
|
||||
offsetSegundos: config.offsetSegundos ?? null, // Converter undefined para null
|
||||
gmtOffset: config.gmtOffset ?? -3, // Padrão GMT-3 para Brasília se não configurado
|
||||
gmtOffset: config.gmtOffset ?? -3 // Padrão GMT-3 para Brasília se não configurado
|
||||
};
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -62,14 +61,13 @@ export const obterConfiguracaoInternal = internalQuery({
|
||||
args: {},
|
||||
handler: async (ctx): Promise<ConfiguracaoRelogioRetorno> => {
|
||||
// Buscar todas as configurações e pegar a mais recente (por atualizadoEm)
|
||||
const configs = await ctx.db
|
||||
.query('configuracaoRelogio')
|
||||
.collect();
|
||||
|
||||
const configs = await ctx.db.query('configuracaoRelogio').collect();
|
||||
|
||||
// Pegar a configuração mais recente (ordenar por atualizadoEm desc)
|
||||
const config = configs.length > 0
|
||||
? configs.sort((a, b) => (b.atualizadoEm || 0) - (a.atualizadoEm || 0))[0]
|
||||
: null;
|
||||
const config =
|
||||
configs.length > 0
|
||||
? configs.sort((a, b) => (b.atualizadoEm || 0) - (a.atualizadoEm || 0))[0]
|
||||
: null;
|
||||
|
||||
if (!config) {
|
||||
// Retornar configuração padrão (GMT-3 para Brasília)
|
||||
@@ -80,7 +78,7 @@ export const obterConfiguracaoInternal = internalQuery({
|
||||
fallbackParaPC: true,
|
||||
ultimaSincronizacao: null,
|
||||
offsetSegundos: null,
|
||||
gmtOffset: -3, // GMT-3 para Brasília
|
||||
gmtOffset: -3 // GMT-3 para Brasília
|
||||
};
|
||||
}
|
||||
|
||||
@@ -88,9 +86,9 @@ export const obterConfiguracaoInternal = internalQuery({
|
||||
...config,
|
||||
ultimaSincronizacao: config.ultimaSincronizacao ?? null, // Converter undefined para null
|
||||
offsetSegundos: config.offsetSegundos ?? null, // Converter undefined para null
|
||||
gmtOffset: config.gmtOffset ?? -3, // Padrão GMT-3 para Brasília se não configurado
|
||||
gmtOffset: config.gmtOffset ?? -3 // Padrão GMT-3 para Brasília se não configurado
|
||||
};
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -102,7 +100,7 @@ export const salvarConfiguracao = mutation({
|
||||
portaNTP: v.optional(v.number()),
|
||||
usarServidorExterno: v.boolean(),
|
||||
fallbackParaPC: v.boolean(),
|
||||
gmtOffset: v.optional(v.number()),
|
||||
gmtOffset: v.optional(v.number())
|
||||
},
|
||||
handler: async (ctx, args) => {
|
||||
const usuario = await getCurrentUserFunction(ctx);
|
||||
@@ -123,13 +121,12 @@ export const salvarConfiguracao = mutation({
|
||||
}
|
||||
|
||||
// Buscar configuração existente (pegar a mais recente)
|
||||
const configs = await ctx.db
|
||||
.query('configuracaoRelogio')
|
||||
.collect();
|
||||
|
||||
const configExistente = configs.length > 0
|
||||
? configs.sort((a, b) => (b.atualizadoEm || 0) - (a.atualizadoEm || 0))[0]
|
||||
: null;
|
||||
const configs = await ctx.db.query('configuracaoRelogio').collect();
|
||||
|
||||
const configExistente =
|
||||
configs.length > 0
|
||||
? configs.sort((a, b) => (b.atualizadoEm || 0) - (a.atualizadoEm || 0))[0]
|
||||
: null;
|
||||
|
||||
if (configExistente) {
|
||||
// Atualizar configuração existente
|
||||
@@ -140,7 +137,7 @@ export const salvarConfiguracao = mutation({
|
||||
fallbackParaPC: args.fallbackParaPC,
|
||||
gmtOffset: args.gmtOffset ?? -3, // Padrão GMT-3 para Brasília
|
||||
atualizadoPor: usuario._id as Id<'usuarios'>,
|
||||
atualizadoEm: Date.now(),
|
||||
atualizadoEm: Date.now()
|
||||
});
|
||||
return { configId: configExistente._id };
|
||||
} else {
|
||||
@@ -152,11 +149,11 @@ export const salvarConfiguracao = mutation({
|
||||
fallbackParaPC: args.fallbackParaPC,
|
||||
gmtOffset: args.gmtOffset ?? -3, // Padrão GMT-3 para Brasília
|
||||
atualizadoPor: usuario._id as Id<'usuarios'>,
|
||||
atualizadoEm: Date.now(),
|
||||
atualizadoEm: Date.now()
|
||||
});
|
||||
return { configId };
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -167,9 +164,9 @@ export const obterTempoServidor = query({
|
||||
handler: async () => {
|
||||
return {
|
||||
timestamp: Date.now(),
|
||||
data: new Date().toISOString(),
|
||||
data: new Date().toISOString()
|
||||
};
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -191,14 +188,17 @@ export const sincronizarTempo = action({
|
||||
args: {},
|
||||
handler: async (ctx): Promise<SincronizacaoRetorno> => {
|
||||
// Buscar configuração usando query interna para evitar referência circular
|
||||
const config: ConfiguracaoRelogioRetorno = await ctx.runQuery(internal.configuracaoRelogio.obterConfiguracaoInternal, {});
|
||||
const config: ConfiguracaoRelogioRetorno = await ctx.runQuery(
|
||||
internal.configuracaoRelogio.obterConfiguracaoInternal,
|
||||
{}
|
||||
);
|
||||
|
||||
if (!config.usarServidorExterno) {
|
||||
return {
|
||||
sucesso: true,
|
||||
timestamp: Date.now(),
|
||||
usandoServidorExterno: false,
|
||||
offsetSegundos: 0,
|
||||
offsetSegundos: 0
|
||||
};
|
||||
}
|
||||
|
||||
@@ -208,7 +208,7 @@ export const sincronizarTempo = action({
|
||||
try {
|
||||
const servidorNTP = config.servidorNTP || 'pool.ntp.org';
|
||||
let serverTime: number;
|
||||
|
||||
|
||||
// Se o servidor configurado for uma URL HTTP/HTTPS, tentar usar diretamente
|
||||
if (servidorNTP.startsWith('http://') || servidorNTP.startsWith('https://')) {
|
||||
try {
|
||||
@@ -216,7 +216,11 @@ export const sincronizarTempo = action({
|
||||
if (!response.ok) {
|
||||
throw new Error('Falha ao obter tempo do servidor configurado');
|
||||
}
|
||||
const data = (await response.json()) as { unixtime?: number; unixTime?: number; unixtimestamp?: number };
|
||||
const data = (await response.json()) as {
|
||||
unixtime?: number;
|
||||
unixTime?: number;
|
||||
unixtimestamp?: number;
|
||||
};
|
||||
// Tentar diferentes formatos de resposta
|
||||
if (data.unixtime) {
|
||||
serverTime = data.unixtime * 1000; // Converter segundos para milissegundos
|
||||
@@ -261,7 +265,7 @@ export const sincronizarTempo = action({
|
||||
if (configExistente) {
|
||||
await ctx.runMutation(internal.configuracaoRelogio.atualizarSincronizacao, {
|
||||
configId: configExistente._id,
|
||||
offsetSegundos,
|
||||
offsetSegundos
|
||||
});
|
||||
}
|
||||
|
||||
@@ -269,7 +273,7 @@ export const sincronizarTempo = action({
|
||||
sucesso: true,
|
||||
timestamp: serverTime, // Retorna UTC (sem GMT offset aplicado)
|
||||
usandoServidorExterno: true,
|
||||
offsetSegundos,
|
||||
offsetSegundos
|
||||
};
|
||||
} catch (error) {
|
||||
// Sempre usar fallback como última opção, mesmo se desabilitado
|
||||
@@ -277,18 +281,18 @@ export const sincronizarTempo = action({
|
||||
const aviso: string = config.fallbackParaPC
|
||||
? 'Falha ao sincronizar com servidor externo, usando relógio do PC'
|
||||
: 'Falha ao sincronizar com servidor externo. Fallback desabilitado, mas usando relógio do PC como última opção.';
|
||||
|
||||
|
||||
console.warn('Erro ao sincronizar tempo com servidor externo:', error);
|
||||
|
||||
|
||||
return {
|
||||
sucesso: true,
|
||||
timestamp: Date.now(),
|
||||
usandoServidorExterno: false,
|
||||
offsetSegundos: 0,
|
||||
aviso,
|
||||
aviso
|
||||
};
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -298,7 +302,7 @@ export const listarConfiguracoes = internalQuery({
|
||||
args: {},
|
||||
handler: async (ctx) => {
|
||||
return await ctx.db.query('configuracaoRelogio').collect();
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -307,13 +311,12 @@ export const listarConfiguracoes = internalQuery({
|
||||
export const atualizarSincronizacao = internalMutation({
|
||||
args: {
|
||||
configId: v.id('configuracaoRelogio'),
|
||||
offsetSegundos: v.number(),
|
||||
offsetSegundos: v.number()
|
||||
},
|
||||
handler: async (ctx, args) => {
|
||||
await ctx.db.patch(args.configId, {
|
||||
ultimaSincronizacao: Date.now(),
|
||||
offsetSegundos: args.offsetSegundos,
|
||||
offsetSegundos: args.offsetSegundos
|
||||
});
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user