refactor: update packages to React 19, Vite 8 and Tailwind 4 and modernize configs
This commit is contained in:
1
dist/assets/js/form-vendor-vQotxSmE.js
vendored
1
dist/assets/js/form-vendor-vQotxSmE.js
vendored
File diff suppressed because one or more lines are too long
32
dist/assets/js/react-vendor-CqRd3GwO.js
vendored
32
dist/assets/js/react-vendor-CqRd3GwO.js
vendored
File diff suppressed because one or more lines are too long
12
dist/assets/js/router-vendor-D4by-_6Z.js
vendored
12
dist/assets/js/router-vendor-D4by-_6Z.js
vendored
File diff suppressed because one or more lines are too long
1
dist/assets/js/zod-7IfHMaWP.js
vendored
1
dist/assets/js/zod-7IfHMaWP.js
vendored
@@ -1 +0,0 @@
|
|||||||
import{a as p,b as y,c as v}from"./form-vendor-vQotxSmE.js";function g(r,s,o){function e(t,c){var u;Object.defineProperty(t,"_zod",{value:t._zod??{},enumerable:!1}),(u=t._zod).traits??(u.traits=new Set),t._zod.traits.add(r),s(t,c);for(const f in n.prototype)f in t||Object.defineProperty(t,f,{value:n.prototype[f].bind(t)});t._zod.constr=n,t._zod.def=c}const a=o?.Parent??Object;class i extends a{}Object.defineProperty(i,"name",{value:r});function n(t){var c;const u=o?.Parent?new i:this;e(u,t),(c=u._zod).deferred??(c.deferred=[]);for(const f of u._zod.deferred)f();return u}return Object.defineProperty(n,"init",{value:e}),Object.defineProperty(n,Symbol.hasInstance,{value:t=>o?.Parent&&t instanceof o.Parent?!0:t?._zod?.traits?.has(r)}),Object.defineProperty(n,"name",{value:r}),n}class j extends Error{constructor(){super("Encountered Promise during synchronous parse. Use .parseAsync() instead.")}}const z={};function m(r){return z}function w(r,s){return typeof s=="bigint"?s.toString():s}const b=Error.captureStackTrace?Error.captureStackTrace:(...r)=>{};function d(r){return typeof r=="string"?r:r?.message}function E(r,s,o){const e={...r,path:r.path??[]};if(!r.message){const a=d(r.inst?._zod.def?.error?.(r))??d(s?.error?.(r))??d(o.customError?.(r))??d(o.localeError?.(r))??"Invalid input";e.message=a}return delete e.inst,delete e.continue,s?.reportInput||delete e.input,e}const P=(r,s)=>{r.name="$ZodError",Object.defineProperty(r,"_zod",{value:r._zod,enumerable:!1}),Object.defineProperty(r,"issues",{value:s,enumerable:!1}),Object.defineProperty(r,"message",{get(){return JSON.stringify(s,w,2)},enumerable:!0}),Object.defineProperty(r,"toString",{value:()=>r.message,enumerable:!1})},O=g("$ZodError",P),_=g("$ZodError",P,{Parent:Error}),S=r=>(s,o,e,a)=>{const i=e?Object.assign(e,{async:!1}):{async:!1},n=s._zod.run({value:o,issues:[]},i);if(n instanceof Promise)throw new j;if(n.issues.length){const t=new(a?.Err??r)(n.issues.map(c=>E(c,i,m())));throw b(t,a?.callee),t}return n.value},A=S(_),Z=r=>async(s,o,e,a)=>{const i=e?Object.assign(e,{async:!0}):{async:!0};let n=s._zod.run({value:o,issues:[]},i);if(n instanceof Promise&&(n=await n),n.issues.length){const t=new(a?.Err??r)(n.issues.map(c=>E(c,i,m())));throw b(t,a?.callee),t}return n.value},N=Z(_);function h(r,s){try{var o=r()}catch(e){return s(e)}return o&&o.then?o.then(void 0,s):o}function I(r,s){for(var o={};r.length;){var e=r[0],a=e.code,i=e.message,n=e.path.join(".");if(!o[n])if("unionErrors"in e){var t=e.unionErrors[0].errors[0];o[n]={message:t.message,type:t.code}}else o[n]={message:i,type:a};if("unionErrors"in e&&e.unionErrors.forEach(function(f){return f.errors.forEach(function(l){return r.push(l)})}),s){var c=o[n].types,u=c&&c[e.code];o[n]=v(n,s,o,a,u?[].concat(u,e.message):e.message)}r.shift()}return o}function U(r,s){for(var o={};r.length;){var e=r[0],a=e.code,i=e.message,n=e.path.join(".");if(!o[n])if(e.code==="invalid_union"&&e.errors.length>0){var t=e.errors[0][0];o[n]={message:t.message,type:t.code}}else o[n]={message:i,type:a};if(e.code==="invalid_union"&&e.errors.forEach(function(f){return f.forEach(function(l){return r.push(l)})}),s){var c=o[n].types,u=c&&c[e.code];o[n]=v(n,s,o,a,u?[].concat(u,e.message):e.message)}r.shift()}return o}function k(r,s,o){if(o===void 0&&(o={}),(function(e){return"_def"in e&&typeof e._def=="object"&&"typeName"in e._def})(r))return function(e,a,i){try{return Promise.resolve(h(function(){return Promise.resolve(r[o.mode==="sync"?"parse":"parseAsync"](e,s)).then(function(n){return i.shouldUseNativeValidation&&p({},i),{errors:{},values:o.raw?Object.assign({},e):n}})},function(n){if((function(t){return Array.isArray(t?.issues)})(n))return{values:{},errors:y(I(n.errors,!i.shouldUseNativeValidation&&i.criteriaMode==="all"),i)};throw n}))}catch(n){return Promise.reject(n)}};if((function(e){return"_zod"in e&&typeof e._zod=="object"})(r))return function(e,a,i){try{return Promise.resolve(h(function(){return Promise.resolve((o.mode==="sync"?A:N)(r,e,s)).then(function(n){return i.shouldUseNativeValidation&&p({},i),{errors:{},values:o.raw?Object.assign({},e):n}})},function(n){if((function(t){return t instanceof O})(n))return{values:{},errors:y(U(n.issues,!i.shouldUseNativeValidation&&i.criteriaMode==="all"),i)};throw n}))}catch(n){return Promise.reject(n)}};throw new Error("Invalid input: not a Zod schema")}export{k as a};
|
|
||||||
1
dist/assets/png/tracksteel-logo-CJR9ckUT.png
vendored
1
dist/assets/png/tracksteel-logo-CJR9ckUT.png
vendored
File diff suppressed because one or more lines are too long
18
dist/index.html
vendored
18
dist/index.html
vendored
@@ -8,14 +8,16 @@
|
|||||||
<meta name="theme-color" content="#2563eb" />
|
<meta name="theme-color" content="#2563eb" />
|
||||||
<link rel="manifest" href="/manifest.json" />
|
<link rel="manifest" href="/manifest.json" />
|
||||||
<title>RDO Mobile - Relatório Diário de Obra</title>
|
<title>RDO Mobile - Relatório Diário de Obra</title>
|
||||||
<script type="module" crossorigin src="/assets/js/index-DXLajEHZ.js"></script>
|
<script type="module" crossorigin src="/assets/index-BFMh0Owy.js"></script>
|
||||||
<link rel="modulepreload" crossorigin href="/assets/js/react-vendor-CqRd3GwO.js">
|
<link rel="modulepreload" crossorigin href="/assets/react-DtrESx-C.js">
|
||||||
<link rel="modulepreload" crossorigin href="/assets/js/router-vendor-D4by-_6Z.js">
|
<link rel="modulepreload" crossorigin href="/assets/preload-helper-DSXbuxSR.js">
|
||||||
<link rel="modulepreload" crossorigin href="/assets/js/query-vendor-Dc_G4OIP.js">
|
<link rel="modulepreload" crossorigin href="/assets/supabase-L170XLdN.js">
|
||||||
<link rel="modulepreload" crossorigin href="/assets/js/ui-vendor-DHNIDV-1.js">
|
<link rel="modulepreload" crossorigin href="/assets/createLucideIcon-BLxppFDo.js">
|
||||||
<link rel="modulepreload" crossorigin href="/assets/js/supabase-vendor-By1yMVW6.js">
|
<link rel="modulepreload" crossorigin href="/assets/jsx-runtime-DNOlzffn.js">
|
||||||
<link rel="modulepreload" crossorigin href="/assets/js/state-vendor-DK3LaRDK.js">
|
<link rel="modulepreload" crossorigin href="/assets/react-eH9hKoTL.js">
|
||||||
<link rel="stylesheet" crossorigin href="/assets/css/index-CYCdtjzd.css">
|
<link rel="modulepreload" crossorigin href="/assets/useUserStore-Btl1TeSc.js">
|
||||||
|
<link rel="modulepreload" crossorigin href="/assets/useAuth-Bw9Uh8UY.js">
|
||||||
|
<link rel="stylesheet" crossorigin href="/assets/index-B3UgNpvV.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|||||||
4900
package-lock.json
generated
4900
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
83
package.json
83
package.json
@@ -16,54 +16,53 @@
|
|||||||
"auto-sync": "node scripts/auto-sync.js"
|
"auto-sync": "node scripts/auto-sync.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@capacitor/core": "^6.0.0",
|
"@capacitor/core": "^8.2.0",
|
||||||
"@capacitor/ios": "^6.0.0",
|
"@capacitor/ios": "^8.2.0",
|
||||||
"@hookform/resolvers": "^5.2.1",
|
"@hookform/resolvers": "^5.2.2",
|
||||||
"@radix-ui/react-dialog": "^1.0.5",
|
"@radix-ui/react-dialog": "^1.1.15",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.0.6",
|
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
||||||
"@radix-ui/react-select": "^2.0.0",
|
"@radix-ui/react-select": "^2.2.6",
|
||||||
"@radix-ui/react-toast": "^1.1.5",
|
"@radix-ui/react-toast": "^1.2.15",
|
||||||
"@supabase/supabase-js": "^2.39.0",
|
"@supabase/supabase-js": "^2.99.3",
|
||||||
"@tanstack/react-query": "^5.89.0",
|
"@tailwindcss/vite": "^4.2.2",
|
||||||
"@tanstack/react-query-devtools": "^5.89.0",
|
"@tanstack/react-query": "^5.95.0",
|
||||||
"@vitejs/plugin-react": "^4.4.1",
|
"@tanstack/react-query-devtools": "^5.95.0",
|
||||||
"autoprefixer": "^10.4.21",
|
"@vitejs/plugin-react": "^6.0.1",
|
||||||
"chokidar": "^4.0.3",
|
"chokidar": "^5.0.0",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"dexie": "^4.2.1",
|
"dexie": "^4.3.0",
|
||||||
"dexie-react-hooks": "^4.2.0",
|
"dexie-react-hooks": "^4.2.0",
|
||||||
"framer-motion": "^10.18.0",
|
"framer-motion": "^12.38.0",
|
||||||
"lucide-react": "^0.511.0",
|
"lucide-react": "^0.577.0",
|
||||||
"phosphor-react": "^1.4.1",
|
"phosphor-react": "^1.4.1",
|
||||||
"postcss": "^8.5.3",
|
|
||||||
"qrcode.react": "^4.2.0",
|
"qrcode.react": "^4.2.0",
|
||||||
"react": "^18.3.1",
|
"react": "^19.2.4",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^19.2.4",
|
||||||
"react-hook-form": "^7.48.2",
|
"react-hook-form": "^7.72.0",
|
||||||
"react-router-dom": "^7.3.0",
|
"react-router-dom": "^7.13.1",
|
||||||
"sonner": "^2.0.7",
|
"sonner": "^2.0.7",
|
||||||
"tailwind-merge": "^3.0.2",
|
"tailwind-merge": "^3.5.0",
|
||||||
"tailwindcss": "^3.4.17",
|
"tailwindcss": "^4.2.2",
|
||||||
"typescript": "~5.8.3",
|
"typescript": "~5.9.3",
|
||||||
"vite": "^6.3.5",
|
"vite": "^8.0.1",
|
||||||
"vite-tsconfig-paths": "^5.1.4",
|
"vite-tsconfig-paths": "^6.1.1",
|
||||||
"zod": "^3.22.4",
|
"zod": "^4.3.6",
|
||||||
"zustand": "^5.0.3"
|
"zustand": "^5.0.12"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@capacitor/cli": "^6.0.0",
|
"@capacitor/cli": "^8.2.0",
|
||||||
"@eslint/js": "^9.25.0",
|
"@eslint/js": "^10.0.1",
|
||||||
"@types/node": "^22.15.30",
|
"@types/node": "^25.5.0",
|
||||||
"@types/react": "^18.3.3",
|
"@types/react": "^19.2.14",
|
||||||
"@types/react-dom": "^18.3.0",
|
"@types/react-dom": "^19.2.3",
|
||||||
"@typescript-eslint/eslint-plugin": "^7.15.0",
|
"@typescript-eslint/eslint-plugin": "^8.57.1",
|
||||||
"@typescript-eslint/parser": "^7.15.0",
|
"@typescript-eslint/parser": "^8.57.1",
|
||||||
"babel-plugin-react-dev-locator": "^1.0.0",
|
"babel-plugin-react-dev-locator": "^1.0.6",
|
||||||
"baseline-browser-mapping": "^2.10.0",
|
"baseline-browser-mapping": "^2.10.10",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^10.1.0",
|
||||||
"eslint-plugin-react-hooks": "^4.6.2",
|
"eslint-plugin-react-hooks": "^7.0.1",
|
||||||
"eslint-plugin-react-refresh": "^0.4.7",
|
"eslint-plugin-react-refresh": "^0.5.2",
|
||||||
"globals": "^16.0.0",
|
"globals": "^17.4.0",
|
||||||
"typescript-eslint": "^8.30.1"
|
"typescript-eslint": "^8.57.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
/** WARNING: DON'T EDIT THIS FILE */
|
|
||||||
/** WARNING: DON'T EDIT THIS FILE */
|
|
||||||
/** WARNING: DON'T EDIT THIS FILE */
|
|
||||||
|
|
||||||
export default {
|
|
||||||
plugins: {
|
|
||||||
tailwindcss: {},
|
|
||||||
autoprefixer: {},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
245
setup_rdo_schema_final.sql
Normal file
245
setup_rdo_schema_final.sql
Normal file
@@ -0,0 +1,245 @@
|
|||||||
|
-- ============================================================================
|
||||||
|
-- SCRIPT DE MIGRAÇÃO: CONFIGURAÇÃO DO ESQUEMA 'rdo'
|
||||||
|
-- ============================================================================
|
||||||
|
-- Este script cria o esquema 'rdo', tabelas e permissões necessárias
|
||||||
|
-- para alinhar o banco de dados com a configuração do app.
|
||||||
|
-- ============================================================================
|
||||||
|
|
||||||
|
-- 1. CRIAR ESQUEMA
|
||||||
|
-- ============================================================================
|
||||||
|
CREATE SCHEMA IF NOT EXISTS rdo;
|
||||||
|
|
||||||
|
-- 2. GARANTIR EXTENSÕES
|
||||||
|
-- ============================================================================
|
||||||
|
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
||||||
|
|
||||||
|
-- 3. CRIAR TABELAS NO ESQUEMA 'rdo'
|
||||||
|
-- ============================================================================
|
||||||
|
|
||||||
|
-- Tabela: Organizacoes
|
||||||
|
CREATE TABLE IF NOT EXISTS rdo.organizacoes (
|
||||||
|
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
|
||||||
|
nome TEXT NOT NULL,
|
||||||
|
slug TEXT UNIQUE NOT NULL,
|
||||||
|
razao_social TEXT,
|
||||||
|
cnpj TEXT,
|
||||||
|
status TEXT DEFAULT 'ativa' CHECK (status IN ('ativa', 'inativa', 'suspensa')),
|
||||||
|
plano TEXT DEFAULT 'trial' CHECK (plano IN ('trial', 'basico', 'profissional', 'enterprise')),
|
||||||
|
max_usuarios INTEGER DEFAULT 5,
|
||||||
|
max_obras INTEGER DEFAULT 10,
|
||||||
|
max_rdos_mes INTEGER DEFAULT 100,
|
||||||
|
max_storage_mb INTEGER DEFAULT 1024,
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Tabela: Usuarios
|
||||||
|
CREATE TABLE IF NOT EXISTS rdo.usuarios (
|
||||||
|
id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE,
|
||||||
|
organizacao_id UUID REFERENCES rdo.organizacoes(id) ON DELETE SET NULL,
|
||||||
|
email TEXT NOT NULL,
|
||||||
|
nome TEXT NOT NULL,
|
||||||
|
telefone TEXT,
|
||||||
|
cargo TEXT,
|
||||||
|
role TEXT DEFAULT 'usuario' CHECK (role IN ('dev', 'admin', 'engenheiro', 'mestre_obra', 'usuario')),
|
||||||
|
ativo BOOLEAN DEFAULT true,
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Tabela: Obras
|
||||||
|
CREATE TABLE IF NOT EXISTS rdo.obras (
|
||||||
|
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
|
||||||
|
organizacao_id UUID NOT NULL REFERENCES rdo.organizacoes(id) ON DELETE CASCADE,
|
||||||
|
nome TEXT NOT NULL,
|
||||||
|
descricao TEXT,
|
||||||
|
endereco TEXT,
|
||||||
|
cep TEXT,
|
||||||
|
cidade TEXT,
|
||||||
|
estado TEXT,
|
||||||
|
responsavel_id UUID REFERENCES rdo.usuarios(id) ON DELETE SET NULL,
|
||||||
|
data_inicio DATE,
|
||||||
|
data_prevista_fim DATE,
|
||||||
|
data_conclusao DATE,
|
||||||
|
progresso_geral NUMERIC(5,2) DEFAULT 0,
|
||||||
|
status TEXT DEFAULT 'ativa' CHECK (status IN ('ativa', 'pausada', 'concluida', 'cancelada')),
|
||||||
|
configuracoes JSONB DEFAULT '{}'::jsonb,
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Tabela: RDOs
|
||||||
|
CREATE TABLE IF NOT EXISTS rdo.rdos (
|
||||||
|
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
|
||||||
|
organizacao_id UUID REFERENCES rdo.organizacoes(id) ON DELETE CASCADE,
|
||||||
|
obra_id UUID NOT NULL REFERENCES rdo.obras(id) ON DELETE CASCADE,
|
||||||
|
criado_por UUID NOT NULL REFERENCES rdo.usuarios(id),
|
||||||
|
data_relatorio DATE NOT NULL,
|
||||||
|
condicoes_climaticas TEXT NOT NULL,
|
||||||
|
observacoes_gerais TEXT,
|
||||||
|
status TEXT DEFAULT 'rascunho' CHECK (status IN ('rascunho', 'enviado', 'aprovado', 'rejeitado')),
|
||||||
|
aprovado_por UUID REFERENCES rdo.usuarios(id),
|
||||||
|
aprovado_em TIMESTAMPTZ,
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Tabela: RDO Atividades
|
||||||
|
CREATE TABLE IF NOT EXISTS rdo.rdo_atividades (
|
||||||
|
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
|
||||||
|
rdo_id UUID NOT NULL REFERENCES rdo.rdos(id) ON DELETE CASCADE,
|
||||||
|
tipo_atividade TEXT NOT NULL,
|
||||||
|
descricao TEXT NOT NULL,
|
||||||
|
localizacao TEXT,
|
||||||
|
percentual_concluido NUMERIC(5,2) DEFAULT 0,
|
||||||
|
ordem INTEGER DEFAULT 0,
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Tabela: RDO Mão de Obra
|
||||||
|
CREATE TABLE IF NOT EXISTS rdo.rdo_mao_obra (
|
||||||
|
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
|
||||||
|
rdo_id UUID NOT NULL REFERENCES rdo.rdos(id) ON DELETE CASCADE,
|
||||||
|
funcao TEXT NOT NULL,
|
||||||
|
quantidade INTEGER DEFAULT 0,
|
||||||
|
horas_trabalhadas NUMERIC(5,2) DEFAULT 0,
|
||||||
|
observacoes TEXT,
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Tabela: RDO Equipamentos
|
||||||
|
CREATE TABLE IF NOT EXISTS rdo.rdo_equipamentos (
|
||||||
|
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
|
||||||
|
rdo_id UUID NOT NULL REFERENCES rdo.rdos(id) ON DELETE CASCADE,
|
||||||
|
nome_equipamento TEXT NOT NULL,
|
||||||
|
tipo TEXT,
|
||||||
|
horas_utilizadas NUMERIC(5,2) DEFAULT 0,
|
||||||
|
combustivel_gasto NUMERIC(10,2) DEFAULT 0,
|
||||||
|
observacoes TEXT,
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Tabela: RDO Ocorrencias
|
||||||
|
CREATE TABLE IF NOT EXISTS rdo.rdo_ocorrencias (
|
||||||
|
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
|
||||||
|
rdo_id UUID NOT NULL REFERENCES rdo.rdos(id) ON DELETE CASCADE,
|
||||||
|
tipo_ocorrencia TEXT NOT NULL,
|
||||||
|
descricao TEXT NOT NULL,
|
||||||
|
gravidade TEXT CHECK (gravidade IN ('baixa', 'media', 'alta', 'critica')),
|
||||||
|
acao_tomada TEXT,
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Tabela: RDO Anexos
|
||||||
|
CREATE TABLE IF NOT EXISTS rdo.rdo_anexos (
|
||||||
|
id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
|
||||||
|
rdo_id UUID NOT NULL REFERENCES rdo.rdos(id) ON DELETE CASCADE,
|
||||||
|
nome_arquivo TEXT NOT NULL,
|
||||||
|
tipo_arquivo TEXT,
|
||||||
|
url_storage TEXT NOT NULL,
|
||||||
|
tamanho_bytes BIGINT,
|
||||||
|
descricao TEXT,
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 4. HABILITAR RLS NO NOVO ESQUEMA
|
||||||
|
-- ============================================================================
|
||||||
|
ALTER TABLE rdo.organizacoes ENABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE rdo.usuarios ENABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE rdo.obras ENABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE rdo.rdos ENABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE rdo.rdo_atividades ENABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE rdo.rdo_mao_obra ENABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE rdo.rdo_equipamentos ENABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE rdo.rdo_ocorrencias ENABLE ROW LEVEL SECURITY;
|
||||||
|
ALTER TABLE rdo.rdo_anexos ENABLE ROW LEVEL SECURITY;
|
||||||
|
|
||||||
|
-- 5. CRIAR POLÍTICAS PERMISSIVAS (INICIAL) PARA AUTHENTICATED
|
||||||
|
-- ============================================================================
|
||||||
|
CREATE POLICY "auth_all_rdo_usuarios" ON rdo.usuarios FOR ALL USING (auth.uid() IS NOT NULL) WITH CHECK (auth.uid() IS NOT NULL);
|
||||||
|
CREATE POLICY "auth_all_rdo_orgs" ON rdo.organizacoes FOR ALL USING (auth.uid() IS NOT NULL) WITH CHECK (auth.uid() IS NOT NULL);
|
||||||
|
CREATE POLICY "auth_all_rdo_obras" ON rdo.obras FOR ALL USING (auth.uid() IS NOT NULL) WITH CHECK (auth.uid() IS NOT NULL);
|
||||||
|
CREATE POLICY "auth_all_rdo_rdos" ON rdo.rdos FOR ALL USING (auth.uid() IS NOT NULL) WITH CHECK (auth.uid() IS NOT NULL);
|
||||||
|
CREATE POLICY "auth_all_rdo_ativ" ON rdo.rdo_atividades FOR ALL USING (auth.uid() IS NOT NULL) WITH CHECK (auth.uid() IS NOT NULL);
|
||||||
|
CREATE POLICY "auth_all_rdo_mao" ON rdo.rdo_mao_obra FOR ALL USING (auth.uid() IS NOT NULL) WITH CHECK (auth.uid() IS NOT NULL);
|
||||||
|
CREATE POLICY "auth_all_rdo_equip" ON rdo.rdo_equipamentos FOR ALL USING (auth.uid() IS NOT NULL) WITH CHECK (auth.uid() IS NOT NULL);
|
||||||
|
CREATE POLICY "auth_all_rdo_ocor" ON rdo.rdo_ocorrencias FOR ALL USING (auth.uid() IS NOT NULL) WITH CHECK (auth.uid() IS NOT NULL);
|
||||||
|
CREATE POLICY "auth_all_rdo_anex" ON rdo.rdo_anexos FOR ALL USING (auth.uid() IS NOT NULL) WITH CHECK (auth.uid() IS NOT NULL);
|
||||||
|
|
||||||
|
-- 6. PERMISSÕES DE SCHEMA
|
||||||
|
-- ============================================================================
|
||||||
|
GRANT USAGE ON SCHEMA rdo TO authenticated, anon;
|
||||||
|
GRANT ALL ON ALL TABLES IN SCHEMA rdo TO authenticated;
|
||||||
|
GRANT ALL ON ALL SEQUENCES IN SCHEMA rdo TO authenticated;
|
||||||
|
GRANT ALL ON ALL FUNCTIONS IN SCHEMA rdo TO authenticated;
|
||||||
|
|
||||||
|
-- 7. CORRIGIR TRIGGER PARA O NOVO ESQUEMA
|
||||||
|
-- ============================================================================
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION rdo.handle_new_user()
|
||||||
|
RETURNS TRIGGER
|
||||||
|
SECURITY DEFINER
|
||||||
|
SET search_path = rdo, public
|
||||||
|
AS $$
|
||||||
|
DECLARE
|
||||||
|
user_name TEXT;
|
||||||
|
BEGIN
|
||||||
|
-- Extrair nome
|
||||||
|
user_name := COALESCE(
|
||||||
|
NEW.raw_user_meta_data->>'nome',
|
||||||
|
NEW.raw_user_meta_data->>'name',
|
||||||
|
NEW.raw_user_meta_data->>'full_name',
|
||||||
|
split_part(NEW.email, '@', 1)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Inserir em rdo.usuarios
|
||||||
|
INSERT INTO rdo.usuarios (
|
||||||
|
id,
|
||||||
|
email,
|
||||||
|
nome,
|
||||||
|
role,
|
||||||
|
ativo
|
||||||
|
) VALUES (
|
||||||
|
NEW.id,
|
||||||
|
NEW.email,
|
||||||
|
user_name,
|
||||||
|
'usuario',
|
||||||
|
true
|
||||||
|
)
|
||||||
|
ON CONFLICT (id) DO UPDATE SET
|
||||||
|
email = EXCLUDED.email,
|
||||||
|
nome = COALESCE(EXCLUDED.nome, rdo.usuarios.nome),
|
||||||
|
updated_at = NOW();
|
||||||
|
|
||||||
|
RETURN NEW;
|
||||||
|
END;
|
||||||
|
$$ LANGUAGE plpgsql;
|
||||||
|
|
||||||
|
-- Remover trigger antigo se existir em auth.users
|
||||||
|
DROP TRIGGER IF EXISTS on_auth_user_created ON auth.users;
|
||||||
|
|
||||||
|
-- Criar novo trigger apontando para a função no esquema rdo
|
||||||
|
CREATE TRIGGER on_auth_user_created
|
||||||
|
AFTER INSERT ON auth.users
|
||||||
|
FOR EACH ROW
|
||||||
|
EXECUTE FUNCTION rdo.handle_new_user();
|
||||||
|
|
||||||
|
-- 8. DADOS INICIAIS (SEED)
|
||||||
|
-- ============================================================================
|
||||||
|
|
||||||
|
-- Criar organização padrão se não houver nenhuma
|
||||||
|
INSERT INTO rdo.organizacoes (nome, slug, status, plano)
|
||||||
|
VALUES ('Baldon Engemetal', 'baldon-engemetal', 'ativa', 'profissional')
|
||||||
|
ON CONFLICT (slug) DO NOTHING;
|
||||||
|
|
||||||
|
-- Garantir que o admin atual seja um usuário no esquema rdo (se ele já existir no Auth)
|
||||||
|
INSERT INTO rdo.usuarios (id, email, nome, role, ativo)
|
||||||
|
SELECT id, email, 'Admin TrackSteel', 'dev', true
|
||||||
|
FROM auth.users
|
||||||
|
WHERE email = 'admtracksteel@gmail.com'
|
||||||
|
ON CONFLICT (id) DO UPDATE SET role = 'dev', ativo = true;
|
||||||
|
|
||||||
|
-- Associar admin à organização Baldon
|
||||||
|
UPDATE rdo.usuarios
|
||||||
|
SET organizacao_id = (SELECT id FROM rdo.organizacoes WHERE slug = 'baldon-engemetal' LIMIT 1)
|
||||||
|
WHERE email = 'admtracksteel@gmail.com';
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useEffect, useRef } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { useQueryClient } from '@tanstack/react-query';
|
import { useQueryClient } from '@tanstack/react-query';
|
||||||
import { supabase } from '../lib/supabase';
|
import { supabase } from '../lib/supabase';
|
||||||
import { queryKeys, invalidateQueries } from '../lib/queryClient';
|
import { queryKeys, invalidateQueries } from '../lib/queryClient';
|
||||||
@@ -7,11 +7,11 @@ import type { RealtimeChannel } from '@supabase/supabase-js';
|
|||||||
// Hook para sincronização em tempo real de usuários
|
// Hook para sincronização em tempo real de usuários
|
||||||
export const useUsersRealtime = () => {
|
export const useUsersRealtime = () => {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const channelRef = useRef<RealtimeChannel | null>(null);
|
const [channel, setChannel] = useState<RealtimeChannel | null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Criar canal de subscription
|
// Criar canal de subscription
|
||||||
channelRef.current = supabase
|
const newChannel = supabase
|
||||||
.channel('usuarios-changes')
|
.channel('usuarios-changes')
|
||||||
.on(
|
.on(
|
||||||
'postgres_changes',
|
'postgres_changes',
|
||||||
@@ -36,24 +36,26 @@ export const useUsersRealtime = () => {
|
|||||||
)
|
)
|
||||||
.subscribe();
|
.subscribe();
|
||||||
|
|
||||||
|
setChannel(newChannel);
|
||||||
|
|
||||||
// Cleanup na desmontagem
|
// Cleanup na desmontagem
|
||||||
return () => {
|
return () => {
|
||||||
if (channelRef.current) {
|
if (newChannel) {
|
||||||
supabase.removeChannel(channelRef.current);
|
supabase.removeChannel(newChannel);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, [queryClient]);
|
}, [queryClient]);
|
||||||
|
|
||||||
return channelRef.current;
|
return channel;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Hook para sincronização em tempo real de obras
|
// Hook para sincronização em tempo real de obras
|
||||||
export const useObrasRealtimeSync = () => {
|
export const useObrasRealtimeSync = () => {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const channelRef = useRef<RealtimeChannel | null>(null);
|
const [channel, setChannel] = useState<RealtimeChannel | null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
channelRef.current = supabase
|
const newChannel = supabase
|
||||||
.channel('obras-changes')
|
.channel('obras-changes')
|
||||||
.on(
|
.on(
|
||||||
'postgres_changes',
|
'postgres_changes',
|
||||||
@@ -81,23 +83,25 @@ export const useObrasRealtimeSync = () => {
|
|||||||
)
|
)
|
||||||
.subscribe();
|
.subscribe();
|
||||||
|
|
||||||
|
setChannel(newChannel);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
if (channelRef.current) {
|
if (newChannel) {
|
||||||
supabase.removeChannel(channelRef.current);
|
supabase.removeChannel(newChannel);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, [queryClient]);
|
}, [queryClient]);
|
||||||
|
|
||||||
return channelRef.current;
|
return channel;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Hook para sincronização em tempo real de RDOs
|
// Hook para sincronização em tempo real de RDOs
|
||||||
export const useRdosRealtimeSync = (obraId?: string) => {
|
export const useRdosRealtimeSync = (obraId?: string) => {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const channelRef = useRef<RealtimeChannel | null>(null);
|
const [channel, setChannel] = useState<RealtimeChannel | null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
channelRef.current = supabase
|
const newChannel = supabase
|
||||||
.channel('rdos-changes')
|
.channel('rdos-changes')
|
||||||
.on(
|
.on(
|
||||||
'postgres_changes',
|
'postgres_changes',
|
||||||
@@ -139,14 +143,16 @@ export const useRdosRealtimeSync = (obraId?: string) => {
|
|||||||
)
|
)
|
||||||
.subscribe();
|
.subscribe();
|
||||||
|
|
||||||
|
setChannel(newChannel);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
if (channelRef.current) {
|
if (newChannel) {
|
||||||
supabase.removeChannel(channelRef.current);
|
supabase.removeChannel(newChannel);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, [queryClient, obraId]);
|
}, [queryClient, obraId]);
|
||||||
|
|
||||||
return channelRef.current;
|
return channel;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Hook principal para sincronização completa
|
// Hook principal para sincronização completa
|
||||||
|
|||||||
@@ -1,6 +1,21 @@
|
|||||||
@tailwind base;
|
@import "tailwindcss";
|
||||||
@tailwind components;
|
|
||||||
@tailwind utilities;
|
@theme {
|
||||||
|
--breakpoint-xs: 475px;
|
||||||
|
--max-width-screen-xs: 475px;
|
||||||
|
|
||||||
|
--container-padding: 1rem;
|
||||||
|
--container-center: true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@layer base {
|
||||||
|
:root {
|
||||||
|
--container-sm: 1.5rem;
|
||||||
|
--container-lg: 2rem;
|
||||||
|
--container-xl: 2.5rem;
|
||||||
|
--container-2xl: 3rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ export class OfflineManager {
|
|||||||
filter?: (item: T) => boolean
|
filter?: (item: T) => boolean
|
||||||
): Promise<T[]> {
|
): Promise<T[]> {
|
||||||
try {
|
try {
|
||||||
let query = offlineDb[table].where('_deleted').notEqual(1);
|
const query = offlineDb[table].where('_deleted').notEqual(1);
|
||||||
const data = await query.toArray();
|
const data = await query.toArray();
|
||||||
|
|
||||||
if (filter) {
|
if (filter) {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export const SyncLogsPage: React.FC = () => {
|
|||||||
setStats(syncStats);
|
setStats(syncStats);
|
||||||
};
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
const handleResolveConflict = (conflictId: string) => {
|
const handleResolveConflict = (conflictId: string) => {
|
||||||
// Aqui você implementaria a lógica de resolução manual
|
// Aqui você implementaria a lógica de resolução manual
|
||||||
// Por enquanto, apenas remove o conflito
|
// Por enquanto, apenas remove o conflito
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ export class SyncService {
|
|||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'INSERT': {
|
case 'INSERT': {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
const { error: insertError } = await supabase
|
const { error: insertError } = await supabase
|
||||||
.from(table)
|
.from(table)
|
||||||
.insert(data as any);
|
.insert(data as any);
|
||||||
@@ -173,7 +173,7 @@ export class SyncService {
|
|||||||
await this.checkAndResolveConflict(table, data);
|
await this.checkAndResolveConflict(table, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
const { error: updateError } = await supabase
|
const { error: updateError } = await supabase
|
||||||
.from(table)
|
.from(table)
|
||||||
.update(data as any)
|
.update(data as any)
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
/** @type {import('tailwindcss').Config} */
|
|
||||||
|
|
||||||
export default {
|
|
||||||
darkMode: "class",
|
|
||||||
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
|
|
||||||
theme: {
|
|
||||||
container: {
|
|
||||||
center: true,
|
|
||||||
padding: {
|
|
||||||
DEFAULT: '1rem',
|
|
||||||
sm: '1.5rem',
|
|
||||||
lg: '2rem',
|
|
||||||
xl: '2.5rem',
|
|
||||||
'2xl': '3rem',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
screens: {
|
|
||||||
'xs': '475px',
|
|
||||||
'sm': '640px',
|
|
||||||
'md': '768px',
|
|
||||||
'lg': '1024px',
|
|
||||||
'xl': '1280px',
|
|
||||||
'2xl': '1536px',
|
|
||||||
},
|
|
||||||
extend: {
|
|
||||||
maxWidth: {
|
|
||||||
'screen-xs': '475px',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: [],
|
|
||||||
};
|
|
||||||
@@ -1,66 +1,22 @@
|
|||||||
import { defineConfig } from 'vite'
|
import { defineConfig } from 'vite'
|
||||||
import react from '@vitejs/plugin-react'
|
import react from '@vitejs/plugin-react'
|
||||||
import tsconfigPaths from "vite-tsconfig-paths";
|
import tailwindcss from '@tailwindcss/vite'
|
||||||
|
|
||||||
// https://vite.dev/config/
|
// https://vite.dev/config/
|
||||||
export default defineConfig(({ command, mode }) => {
|
export default defineConfig({
|
||||||
const isDev = command === 'serve';
|
|
||||||
const isProd = mode === 'production';
|
|
||||||
|
|
||||||
return {
|
|
||||||
// Base path otimizado para Netlify
|
// Base path otimizado para Netlify
|
||||||
base: '/',
|
base: '/',
|
||||||
|
|
||||||
// Otimizações de build para Netlify
|
// Otimizações de build para Netlify
|
||||||
build: {
|
build: {
|
||||||
sourcemap: false, // Desabilitar sourcemaps em produção para reduzir tamanho
|
minify: true,
|
||||||
target: 'es2020',
|
|
||||||
minify: 'esbuild',
|
|
||||||
cssMinify: true,
|
|
||||||
assetsInlineLimit: 4096, // Inline assets menores que 4KB
|
|
||||||
emptyOutDir: true,
|
emptyOutDir: true,
|
||||||
|
|
||||||
// Configurações avançadas de chunk splitting
|
|
||||||
rollupOptions: {
|
|
||||||
output: {
|
|
||||||
// Nomes de arquivo com hash para cache busting
|
|
||||||
chunkFileNames: 'assets/js/[name]-[hash].js',
|
|
||||||
entryFileNames: 'assets/js/[name]-[hash].js',
|
|
||||||
assetFileNames: 'assets/[ext]/[name]-[hash].[ext]',
|
|
||||||
|
|
||||||
// Estratégia de splitting otimizada
|
|
||||||
manualChunks: {
|
|
||||||
// Vendor chunks para melhor cache
|
|
||||||
'react-vendor': ['react', 'react-dom'],
|
|
||||||
'router-vendor': ['react-router-dom'],
|
|
||||||
'query-vendor': ['@tanstack/react-query', '@tanstack/react-query-devtools'],
|
|
||||||
'supabase-vendor': ['@supabase/supabase-js'],
|
|
||||||
'ui-vendor': ['lucide-react', 'framer-motion', 'sonner'],
|
|
||||||
'form-vendor': ['react-hook-form', '@hookform/resolvers', 'zod'],
|
|
||||||
'state-vendor': ['zustand', 'dexie']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Configurações de compressão otimizadas para Netlify
|
|
||||||
reportCompressedSize: false,
|
|
||||||
chunkSizeWarningLimit: 1000,
|
|
||||||
|
|
||||||
// Otimizações específicas para deploy
|
|
||||||
modulePreload: {
|
|
||||||
polyfill: false // Reduz o bundle size
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Otimizações de desenvolvimento
|
// Otimizações de desenvolvimento
|
||||||
server: {
|
server: {
|
||||||
hmr: {
|
host: true,
|
||||||
overlay: false // Reduz ruído visual durante desenvolvimento
|
port: 5173,
|
||||||
},
|
|
||||||
// Configurações de performance
|
|
||||||
fs: {
|
|
||||||
strict: false
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Configurações de preview otimizadas
|
// Configurações de preview otimizadas
|
||||||
@@ -103,18 +59,6 @@ export default defineConfig(({ command, mode }) => {
|
|||||||
|
|
||||||
plugins: [
|
plugins: [
|
||||||
react(),
|
react(),
|
||||||
tsconfigPaths(),
|
tailwindcss(),
|
||||||
],
|
],
|
||||||
|
|
||||||
// Configuração para ignorar erros de TypeScript no build
|
|
||||||
esbuild: {
|
|
||||||
logOverride: { 'this-is-undefined-in-esm': 'silent' },
|
|
||||||
...(isProd && {
|
|
||||||
drop: ['console', 'debugger'],
|
|
||||||
minifyIdentifiers: true,
|
|
||||||
minifySyntax: true,
|
|
||||||
minifyWhitespace: true,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user