From 5ef46780a59ae066b444d1e2c6bd01aa3dad65b6 Mon Sep 17 00:00:00 2001 From: Keven Date: Mon, 22 Dec 2025 18:03:49 -0300 Subject: [PATCH] =?UTF-8?q?feat(Certidao):=20Adiciona=20recursos=20para=20?= =?UTF-8?q?manipular=20certid=C3=B5es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 33 ++ package-lock.json | 290 ++++++++++++++++++ package.json | 5 +- public/modelo.docx | Bin 0 -> 54650 bytes src/middleware.ts | 16 +- .../GGramatica/useGGramaticaIndexHook.ts | 2 +- .../GGramatica/GGramaticaIndexService.ts | 3 +- .../TServicoItemPedidoCertidaoForm.tsx | 65 ++++ .../TServicoItemPedidoEtiquetaForm.tsx | 64 ++++ .../TServicoItemPedidoList.tsx | 71 ++++- .../TServicoPedido/TServicoPedidoDetails.tsx | 6 + .../TServicoItemPedidoCertidaoEditData.ts | 20 ++ .../useTServicoItemPedidoCertidaoEditHook.ts | 35 +++ .../useTServicoPedidoDetailsControllerHook.ts | 1 + .../useTServicoPedidoShowHook.ts | 2 + .../TServicoItemPedidoCertidaFormInterface.ts | 5 + ...TServicoItemPedidoEtiquetaFormInterface.ts | 5 + .../TServicoItemPedidoCertidaoEditService.ts | 18 ++ .../TServicoItemPedidoIndexService.ts | 2 + .../TServicoPedidoShowService.ts | 2 + src/shared/actions/file/GetFileExtension.ts | 21 ++ .../editor/onlyoffice/OnlyOfficeEditor.tsx | 48 +++ .../editor/onlyoffice/actions/GetServerUrl.ts | 20 ++ .../data/OnlyOfficeEditorPrepareData.ts | 18 ++ .../data/OnlyOfficeEditorServiceUpData.ts | 40 +++ .../hooks/usePrepareOnlyOfficeEditorHook.ts | 53 ++++ .../interface/OnlyOfficeInterface.ts | 4 + .../OnlyOfficeEditorPrepareService.ts | 11 + src/shared/services/api/Api.ts | 2 +- 29 files changed, 841 insertions(+), 21 deletions(-) create mode 100644 public/modelo.docx create mode 100644 src/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoCertidaoForm.tsx create mode 100644 src/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoEtiquetaForm.tsx create mode 100644 src/packages/servicos/data/TServicoItemPedido/TServicoItemPedidoCertidaoEditData.ts create mode 100644 src/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoCertidaoEditHook.ts create mode 100644 src/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoCertidaFormInterface.ts create mode 100644 src/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoEtiquetaFormInterface.ts create mode 100644 src/packages/servicos/services/TServicoItemPedido/TServicoItemPedidoCertidaoEditService.ts create mode 100644 src/shared/actions/file/GetFileExtension.ts create mode 100644 src/shared/components/editor/onlyoffice/OnlyOfficeEditor.tsx create mode 100644 src/shared/components/editor/onlyoffice/actions/GetServerUrl.ts create mode 100644 src/shared/components/editor/onlyoffice/data/OnlyOfficeEditorPrepareData.ts create mode 100644 src/shared/components/editor/onlyoffice/data/OnlyOfficeEditorServiceUpData.ts create mode 100644 src/shared/components/editor/onlyoffice/hooks/usePrepareOnlyOfficeEditorHook.ts create mode 100644 src/shared/components/editor/onlyoffice/interface/OnlyOfficeInterface.ts create mode 100644 src/shared/components/editor/onlyoffice/services/OnlyOfficeEditorPrepareService.ts diff --git a/README.md b/README.md index 593ff60..1e08bbf 100644 --- a/README.md +++ b/README.md @@ -23,3 +23,36 @@ Configure: } npm run dev:debug + +## onlyoffice + +docker run -i -t -d -p 8081:80 --restart=always -e JWT_ENABLED=false onlyoffice/documentserver + +## next em rede + +``` +npx next dev -H 0.0.0.0 +``` + +``` +"scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "dev:lan": "next dev -H 0.0.0.0" <-- Adicione esta linha +}, +``` + +Como acessar no outro dispositivo +Descubra seu IP Local: + +No Windows (seu caso), abra um terminal (CMD ou PowerShell) e digite: + +Bash + +ipconfig +Procure por Endereço IPv4 (geralmente começa com 192.168.x.x ou 10.0.x.x). + +Acesse no navegador: No celular ou outro computador, digite: http://SEU_IP_AQUI:3000 + +Exemplo: diff --git a/package-lock.json b/package-lock.json index 356caec..4689e00 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,9 +7,11 @@ "": { "name": "saas", "version": "25.9.1", + "hasInstallScript": true, "dependencies": { "@faker-js/faker": "^10.0.0", "@hookform/resolvers": "^5.2.1", + "@onlyoffice/document-editor-react": "^2.1.1", "@radix-ui/react-alert-dialog": "^1.1.15", "@radix-ui/react-avatar": "^1.1.10", "@radix-ui/react-checkbox": "^1.3.3", @@ -75,6 +77,7 @@ "eslint-plugin-unused-imports": "^4.2.0", "prettier": "^3.6.2", "prettier-plugin-tailwindcss": "^0.6.14", + "shx": "^0.4.0", "tailwindcss": "^4", "tw-animate-css": "^1.3.7", "typescript": "5.9.3", @@ -1391,6 +1394,19 @@ "node": ">= 8" } }, + "node_modules/@onlyoffice/document-editor-react": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@onlyoffice/document-editor-react/-/document-editor-react-2.1.1.tgz", + "integrity": "sha512-b0SnFPmT+OEyJons18PPHpwtFABVCI4nr3gPtAAImar1PhN9tNc9703Yo5KPYsHhIgVq+FqHSWgunI9GJnKa5w==", + "license": "Apache-2.0", + "dependencies": { + "lodash": "4.17.21" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17 || ^18 || ^19", + "react-dom": "^16.9.0 || ^17 || ^18 || ^19" + } + }, "node_modules/@pkgr/core": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", @@ -4628,6 +4644,16 @@ "dev": true, "license": "MIT" }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, "node_modules/enhanced-resolve": { "version": "5.18.3", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", @@ -5485,6 +5511,98 @@ "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", "license": "MIT" }, + "node_modules/execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/execa/node_modules/cross-spawn": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz", + "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/execa/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/execa/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/execa/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, "node_modules/faker-js": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/faker-js/-/faker-js-1.0.0.tgz", @@ -5775,6 +5893,19 @@ "node": ">= 0.4" } }, + "node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/get-symbol-description": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", @@ -6068,6 +6199,16 @@ "node": ">=12" } }, + "node_modules/interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/is-array-buffer": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", @@ -6373,6 +6514,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-string": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", @@ -6954,6 +7105,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, "node_modules/lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", @@ -7287,6 +7444,13 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true, + "license": "MIT" + }, "node_modules/node-releases": { "version": "2.0.25", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.25.tgz", @@ -7294,6 +7458,29 @@ "dev": true, "license": "MIT" }, + "node_modules/npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -7416,6 +7603,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -7452,6 +7649,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -7720,6 +7927,17 @@ "react-is": "^16.13.1" } }, + "node_modules/pump": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -7924,6 +8142,18 @@ "react-is": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, + "node_modules/rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", + "dev": true, + "dependencies": { + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/redux": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", @@ -8274,6 +8504,42 @@ "node": ">=8" } }, + "node_modules/shelljs": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.9.2.tgz", + "integrity": "sha512-S3I64fEiKgTZzKCC46zT/Ib9meqofLrQVbpSswtjFfAVDW+AZ54WTnAM/3/yENoxz/V1Cy6u3kiiEbQ4DNphvw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "execa": "^1.0.0", + "fast-glob": "^3.3.2", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + }, + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/shx": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/shx/-/shx-0.4.0.tgz", + "integrity": "sha512-Z0KixSIlGPpijKgcH6oCMCbltPImvaKy0sGH8AkLRXw1KyzpKtaCTizP2xen+hNDqVF4xxgvA0KXSb9o4Q6hnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.8", + "shelljs": "^0.9.2" + }, + "bin": { + "shx": "lib/cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/side-channel": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", @@ -8350,6 +8616,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, "node_modules/sonner": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/sonner/-/sonner-2.0.7.tgz", @@ -8516,6 +8789,16 @@ "node": ">=4" } }, + "node_modules/strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -9181,6 +9464,13 @@ "node": ">=0.10.0" } }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, "node_modules/yallist": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", diff --git a/package.json b/package.json index c86c680..cf4ab2a 100644 --- a/package.json +++ b/package.json @@ -8,11 +8,13 @@ "dev:debug": "cross-env NEXT_USE_TURBOPACK=0 NODE_OPTIONS=\"--inspect=9230\" next dev", "build": "next build", "start": "next start", - "lint": "next lint" + "lint": "next lint", + "postinstall": "shx mkdir -p public/libs && shx cp -r node_modules/tinymce public/libs/tinymce" }, "dependencies": { "@faker-js/faker": "^10.0.0", "@hookform/resolvers": "^5.2.1", + "@onlyoffice/document-editor-react": "^2.1.1", "@radix-ui/react-alert-dialog": "^1.1.15", "@radix-ui/react-avatar": "^1.1.10", "@radix-ui/react-checkbox": "^1.3.3", @@ -78,6 +80,7 @@ "eslint-plugin-unused-imports": "^4.2.0", "prettier": "^3.6.2", "prettier-plugin-tailwindcss": "^0.6.14", + "shx": "^0.4.0", "tailwindcss": "^4", "tw-animate-css": "^1.3.7", "typescript": "5.9.3", diff --git a/public/modelo.docx b/public/modelo.docx new file mode 100644 index 0000000000000000000000000000000000000000..e816699373953a89ddd3ab840b0d59b02a826dc5 GIT binary patch literal 54650 zcmd421yo(zk}kY)cXxuj2X`lUa0~A4?iSo#g9Hc;!QF!dcXtWy4sUZ#pY!gyeQ)3H z*WKg)slgiTJ=gr|tD04-YOOUpL>o+8NsbM@(!Tto5CM zA012??eq;T^-YZ#S(upE84Z7@LGScNgM^<~)YwGd*~*ESSj-Jb?{_8!<~Ah6|Hk)C z7axhfot>4rp}rH4D5Hyw(cfvIw>2>_H#9b~HFUNHn#f>lWh`%CVQlC`!uXFBSlAhx z{+$MM>odr0(E2yS8Gti?qwZ*CZs$k~^v*xy^)~d+4gU`&+S&YL zd)~hPC+4_XoBW-w-(BEF|26`gBoB-X2XiB1Vqyh-2PZjwYv4LCy4pGzF`8Q0Iy&k* zxHJCg@&B0kzh1F7SUU$>Lt{rrVDMR6G5m@Ahps=|_Rm>40RzyO@wX%MTX_GSb^l_m z{w{=mgZbAw|6s>xY-40&>tyWs-&XwZJn;wee}Rmnle^Xb29@7&{|iJ+fXS|`Z(wEo zKkt@5q5n0VKV#{?8x;R;ZT>{I);G8L*F^q|7FS~fC1WQiV5t8u1kB%n{}(7Z{;%=* z1Npx|#>Cdv>3=Dm{)GP5bpF3iqdy$?Kc75*ApdJ0{7o?Z&(ruD@PEzZ&xHS<=kX`> ze}={XA0qRQn(#mGia(J5Lr(xNdkPM=c8-j|n)=_SVEoqi85tYV1M9z?v4fMj@t-Zy zKdkkCDmS!s_wStUqZJp!) zV-HQt`|)pk!vDu!`Y(MY3IAU~iKUGANF1b$m`R9#@1g&7qyBpjB>Hb{^zZ%pUvx13 z^$Z}gzJsZ;6CcTMZQ-BQ@b^abAJbv^&(rzKeZyaQSQ|U(8|gdg18*n(vW)+i(Z3H9 z#(&}<*8e=CzncG#9P|&O`5$olBX59RHsfCc;m^Q>{_Q4ip$MwN6%PQ=Tmb-3fPwe# z+OtHpDx~T~(lFSohKACjzpwC+)@<$w-MtuI6h}4tn)fYj3 z{u|>Q_BJG}roKF}2JeMDD&*(tY{!rSs(Zs@BkQU903B%(uAYsw%jdqe=Z&_*s-`or zlGZ&f@#@yTAX92BkAyuf%AU5O7A-pHCR0ZV_s#oRC={#bjoS{-x$j9BP2F%fGV2gO zU0DzBXW8IQe}1H{`r5rCG?A2C3Hlx}BH2OOf;Tyts!gd~=UZYFi+9HT5ULQs)zaQ} zG_c%_`}WAnf`XTmOSOGibB=kxA3Ba z06R$~MyeM{@jJDqO2WzLcY>~T_uc;QsTfm-7A~0Eo!B|KWGT{gZ;&157Ctnr)40}p zzaVxVb3cfeW{l5LPT^FtZ2W>BY-LDUbGJZJQqA4+&9 zrEN&h+*#|1>9x`W|J5s*LB*ch-l;ISh!D9$!k-Th3l64KaJmeE?1h}DpqgU;gDu9wUe{f(y*kU$3 zfZ6~-nC|IS&&fMnQ@1l4&Dzr<4VFnoeDDZ<$-d|Y%%Q2H&W|fJljuoo5**T|cycaG zUjr%YHbM2hl*$Kl=0uRP?$3Z+4!Nc>VkLYM3k?&LYDiux=nH{oNtC= zL9HYYE)vZCA|UMfg6O%zWsz|-BNe)#{3Sa!`9hz&H^5@dTmbC!|~-YiqrnPM@(Sr9C@{ib8lj4!aNQ(?(e?w{`C0C)F;eRi5A1 z@H$gK@KPm2?vRgmq*{2MlCOEd1m_S*&T?H@n6}_xBWsy+dPwI3(n2W=u0FZG7EB$x z>J53~7viBtR7Z54-V2J+A%C%xa1&-m#Kpz0 zNrF$MB^ZC)orHt%0#(%v_f}eENW$C4F6KKIMRu5tXaAgnu+JzY57_tf1eCT12>^_z z_7Xlzf6}wATJXZ5xnZd(B*!B1hQR|U1c#o}M~fi&A4us!1Uo+=9x=U)H|!zWShe!D zY3I*w*QTxW-_ki1Poq-cxbLU?ep$7=;~aY6$H8&Glb(MV8SyVlqk&?Beln*$Onsy_ zvgjsU>NjJnSiH6_Rb1PdwdtWcU94B3*WxJ&sb-h{p#(X{^4RmKW9hMi6+8X-(~J78 zb*>zBZNyn2ggkw#orvV25BfR>`+1Q-cZYL6KV0L-4+MAs6M(v2w=sS0THn|YQxniT zP$pNkW{4YlZaDsVtK2-m9TL&~vcCL6Y)lX-mMo>@;@i64p@B^TYF;Ecna074P<42HJ8 z_&wo$_eBr{?3I;o01wgj5_2+Tt`5YzCSS#5VS|cD-MM zlV~vvO^X!YN3v*gT7wv@(h?x*vlE{zzdM`*yuz)+Ss*PA0V-@tI^+SR$+S@(5JH^T z_+Yu%nk!|_t!muM`EWGG`HfS>=%w$s%)POcIWR>to8nk8d|tc=bV2$Lk?(dCi(5f< zlB?-N`UDI8WD##uria3`QCaixHU_o&vWH~H(0jxS>$Ujug;R0odbw* zssy7_4cb#XFW23w)Jbfc?`nn7Ag#%^Gf6ifuxB%e2RADT@%w0zf(p_O`_dI@kB`vx zk_8vLNn2oSP6MKLB%9$PkHPwgVC1X#HXc2+V)VXG6r;}z`UwwenpxQw+4+Z-d|&en zi2%u3>zM9rPLVu2tT@wU4bYRW$emXs3^RBYi~pGwS94~ka?9uk%eWoYY7<(^pIg)( zt?HoIJq!jq@cw&jD<3fAur$c&0BK)3{9*iHrG%OVi6KIfZwjb4wOcFWm04A3A~*$P(UdZ|rAr{bULdm4v_M1W zYctQ=1Sd96A0P&l%BA;L=H_g&ob*;kfSxY$&S(4&V?sseWq z!CQWm7*U4Bge&;a!00Dg)E!^!O(_%!nqMAkIB(9|j>-n&v3=QBBsehQyn~>f@5L2I zm;$mTxFXm9dgVLMmY$**CZD%K=?e9|#tTQ>s0jwU$g2~D{I)8zn1Uv%x7`G#^HllS$81tOZ%bMlQWf8!H>SeaRTlr`G&(lxv zMaja-yZH3s;OpGOkI@@SRhGRC8;q1ch#NLQqSXcO1eQpIRpUp=>AeP-qR<2S{ev|Z z7|>P|@lvxvNDuuoiA^bDyk0R_`CmWkRl-3(_6>xM4TP(lBk$ml3b^(fohwo46j z7l0=_nDWQ7w$4?BAqg+_Rw&hYLjRvr(@_aM1&BWn?AMVt(K&mSN0q7Q+C2yr?9T_| zL5bv0zp)&2lOorb7wtzTJ`lnYL46tB6VyrpRVUP&yDV3u+!b=ITw>8OIYnCOSv?%> z+FTQOUE6!zc@VM9@pWlOEIc___z;7#lisw|)L;aWg6cmn39fL`WZ3UstHDcNzrtjLRf^+0VXER{e=SBWTw$zdBs2Y(6l#UlS z{iurd=oa#v?s#=wY8Bvf=%b7NlG+*C3Y(2;gjT@yN<#HX?+8qB=CrTl^)hB;1@ zlW}9ZVN_)d;;~G#gdSg`iatC)Y3&gp*`yWmf=y9IGOZv+CVH_%uOTzcIo$Xo{|Z3n z0Uw;@@{4(?@?_H+*j1ccKHWi(bd40pb%d4K3%AT*+k$g+D?sDE$FEHhQt%f(5$`11 zhL@#;fIZsW58E;Ewd35+s!X|2>AA+&o)}2|! zb|L0GX7bMB36|$685b$9GTKVkOGFy#9U zll~_mWK^TJr@n(z@Z4vEg&%mtC%6MgNp1?OxsH@f%;9y*p&d3v@~U~dBvD@UK7jYq zI@+14Lpdy-lmI#wg;TBPlT9M5*KtGoT5H4*?@PUW;j9t|?Qo`pIQ~9rOyf)S^f>EN zdLMfT=w62fD%_D%$3RWdJ1N4wXNnJ5 zk627=AjIDwyfLg~1gTA~uX}7beGp-{kebtf(o-ws9#XpDvcF*UgCN~qas9{f@9mxCv9>XL7HoC=^ZWn>{7>3}CoQ$In8S5^(74|71RxBy4QB zfV}$-dITG~s-j2dXH_vW21Y;E`>Dtc>#3?^%{GOKDqE*oN@>c1kB=1V ziiBy~{;^WRn!J>s`uAwuY7F`kjB4Hcqr0B^`y>X!$7AI^-Md|xHJ+@#$dJ4g)m`?D zu}TTgX4xBMQhDnm`K^8V4u@Zk7Z{z%li7$TW9F&}WkTeg1XyFlvN*D^iAl2Fo4!BcG%K;Wa#)*M}jOAhKIw$3E{VOw~+N zoez$sj2{?mSo(9A4#I9(po8Itv{j`-OD{jA*&oUg&f|fiq|&OQFR{=J6(||@W14U{ zEF}?&Nr-Um(MnCPwMGUgFuZi*T*E{#`I1Rh6a{2_8IxE}`$lPcS?=ucjBQzw%>L0o zYMrv=P8o^~f>pL9Gt~}29mEl(=crgJZW?pL@Wm%b-O$vbedBW`jDTP0^kV#tA&hNB zCKv1vgimF-N6?E-90utWkKxiog5&Q|EX5}`(X3$w1oU$Ts4q+1A5wNVL)-Di^pDc= z5dl@Hee%;&@WY_pee!5&?|V{eK|q6FHg$EvW=X!jclZ^!OR-kNX) zt+Uo2;_^<$3b>k@^oS&0@E{^7NK(0-h|CxHsX=1(U^{=B(Y%W zhdBXQ_nsC7DUZpe4N<7u>Tper0|24}4JoCl_XAi;`5fx9Vj%;Q9lA!d2}Wuwby?kQ zm+?dLcK}OxC5Ea^({oZt+KG*?JYMkV&acF2LKV31EV1=M9plo0sk^jzNvP;3cD6>$ z^|7b#P4hKBA`!e##l$g0A*o`(6TbnSO~&-yo|76k5{FyR>w{I*+c4Jr2{DdKQKoGP z8UKxJRrFJ8!RLnex~3GM*fU*d-yXzfj4%(0x3%yTR0waKwNl!vBsY5>#D#{jyQp~k zRNSV&2xE69!oKYms*^>+mw5T@gR0-co-yg+FTmc=?|M4 zq~{A4=2yXMV326!t4<^bs=5qVF4YR02ZBH$hnY98YZyl-57g9Ed*c138hyl1QLU1S z;x9yk!`?f^xo`>7bi(ZkbT3YGA@qQ-5k8JX?@#Ivn+hlzV3c5}AvQ&HzjE zSw;rrTC&al$4)ZFwjEkIovtP_K`kr2G&9eDge_^hM6(E}B)eMa>=nvdZ7b$y_|N#&Fc5axV1KcbBF`h0Y{Hia*H*~OmSb_^!5od_># zSaC4Eq!eG^gK4FCI4bZDHsP(WI(o{X9ps4|*;1{FYr^G0Lco^R3kwsBM+Z6$>!ZZ8 z;bw;2LGZof)ig*w(A>RlelU>JB3$(lSFLmwUQh!wAymQ>waSQL+~0gzf_B3EMOzK2 zu59hKF+}|N8FhA(((9T6i9NdKT2Jkpy<2@1-#mZ`#!}}8UD!=@a+J5K(E%&l zJ1uTD;h$j1IwBt#55$_1QI zrxe-{iRFJ>F4wVuC}=lb*~y1~{X*nno-_jTrP(jMowEBe5_{|1HX0j`qM?5~+W%If zH-^l&xpKJPJ>aCXxmW|m<0oUC!$i?bfJau}{TxWY7jt=1ak%!*5Q=P-Bi^-vcjYRz zs*7cmL6Krb_p;})b**}3y;k2%#Dk4}WdL{RiGK*;Bn7S7haH+py7han^N9%%Kf7}n zQ@Sn<0(RZ_PL@wSb$AeSD~+G z!1=4)tcEXGj)O%66w@*x4$a~<`O0ZGNrs2c*yFH&#r9mm^|^WG%2M#&oi3(ykrkA~ z*S(Uf2f=P=`C#5vh7zmZaIN!Tgm#p{^Hx|$LMT}iTk8p%DSvW#)kYOBvH3H&ZK=uT zvZ|DVairU;M`@Stz>&-CF zHKHxGHQxJJZ0T&jsncVD#-R{Av9Imp&nMXJESSR{esoaSz0$ghAx*K(k=f`;3=pqW zi(8|j#R&}){^i>5v0f%+3FcN4E)#pw6b-O`&BfPN^J4Hf^FeT{Iva(peq#@LpBL?A za}axiD%su~*;bi=#Z-q@Cd%Qe;nTEeU;ErVMa1xOP(1UV=wtoTPf+@DcY=fv1geAe zmWNH(b8-gl?1$U?3uoW`?(SXm=5Io+DHYQttfsix->52Fa?OO}L1d&*Ml(N>O(sHa zOnJ(vY=&tkS1F*$ZfIdQQq|NWvK9W+x~yMwUo=kGq4=%#Bm0lk}R!%GraQp-+}al8r@3FU$;@+oef8 z%#ST;?LX|rbY2W9q&%_xM9<^xEx=A2f>|lBefQO;AXP9zJy1uv>K|X6xmcUrt6PpR+j}Omnz?7NHjSL#lgmT#+kVSDA5uX zR(7TOGb|$JfRMWM)C%VhLh|Aj;&rGcq7c#ZbofwK$gGjzUDX9TZr=)inR#|6N>Lvf zlSrcX#wdk&9p4X?Nj|Q{MkZ{-tbmcyvE*lqV*Ki3X;=A{E)Xz^5l{xQ*D5!E)lazs z<5}rxMCiwBoz~{X{(Tfio#*^fda;dRcOWq6(k}r813hi_qhH}q)=FW3f6$faH)=E# z$FFDK=amr^aDwJ(Ac&iO!5O{#X*BW7u9uU{MP7gN&QQ$1v!O;YrH=fkk#5&)@qu=e zLz@wHp-z4-8tN6SQ_2VAmS9n&;Fc~vi3s_M_R=A|xE110UVRy}4yN;#ZpsjTMbpXXH zAAs$c0EL^kN>B1T-xx-ro=k&_S*zINq0Z77Sn(|s|6iqNk;fauQ~?FW>IPtgp~`#? z37=J|Q{ZNXAXU|Rzt2s}72=t7HCdy7Ln=-?kD?(E!Ei7o1*w>zS}InCZQ;SQvvzv5 z3^WG|CP!aCg|D3QWur4;Ji3GT9$bx%5!u)R-FTFYOk&(5ioOEB=)95;a99U~AZ{i} zj?L<>st=~)Gb3)*x;7%r1#7|=w)AIvhF!!MPc%rY+DUVzg`B5WUj?4|LH^PgG`@0< zdZ;qZK64cF?WhpmiGOJqzT|mL0?3~y0d}kj+>nBKCN=yL_cB-&UznyWDykCo2bC%s!BC{OjA*Xb~7N6Og z#npVv@Z`?EZ3wf%eCin`3LSo`h!B%J?zXI{olB|B2m~1s;62C)9DD5-cpcL~aiWE` zGkLT@@>#OtRE!BI?MrHmjn~f@7x+V_KqCSERl;q4)gQkU38OI5KBA5H)Uxiebm+D4 zkBGw3pY!wXqM?Y`v*Qq(6^%7SKG-;85eePTx5BXN-hUZ0{yebS<({utQIwC!^)2#C zdRLgWp{b>mX}{b8v8IZC@$!zjti|9$$vS)dwOrasSWNsqS6FxIJ{kf>Sbu~aH!sm= z4fs=R#Vvc#7P057?>*EylChm#SLFVNFmoopxr|a7<7=-1f4m<4{Vg4Kb0+o>2mnwE z`8RLr{&^Gu6H%Oe1N3%hTGxbuAXn1}zi zU`Uq1qi4O->+)4*{nu_sNnW7CCsHFijRCrk#LRP5!}A>-uBFnL_r%0l7y(1`ita9s z-ZKTT4xPDPqJT5t9?1S7WUHa3ltPy7%BW;SK1_Z32|GGidJNm~9WOLWdyZPf!i(&0 z&!~3D*$AAM*&(VR^qBjR&{qd8%g_y#$Km^`;LioL1kt_GzLD4?>c_+c$fZ&W8Sys( zAxtKXM{?Bt*&xCu#U_9j+~b|0qaqmr_X1j}=$V})jDdm&W0!&S9hre7}UTbriy$G9Lp zhRv)VGFF99jLr7K_$H|RtbXBTjVY{h3XGCDb@h|uRoVWmNvJrNccWQ_#i%-6uwiB% zsHVz^GS2)UwTGiczQVtRfK&k|;27?e$yU-J{84NOSxn(dv)9_CaEW!WT07>$ z;7PieXURTV6;G=ZrrJdbJ6qSeleCF#DXHZ^Y^jqGany%Nl(&gnQkSI*F82OF%Rl4; zKa`jGlqqE9oGa;!d&U$R%^g1MI3u>-?mzMBw*e!l!(YhtyE zy2>oijk(;79DI$OZJjzj)6r#}rX<9x|Cef%a+m85#doy_WQQfJ7yRmWSh-Lk;fP0L zmE)wGE$}y>?@v7rkWcpIVKoBarsve3-L{B|MUabf{_1PKZw+1}Kwmcjlk9JN{WrUD z-m+}@_bl_l@=Q`q!l3+!S2v_H{T+#^%PqgZ;-d6>3Wk4Z8Ix$CaA zHc!tPntg9MLet_*t2{^~Mr9s$8o%@d%pi{w`C6d{cVwB!yS5^ywNCubT9~5O!Y@f7 zn6yr~pt393mUd(1E66Ltz^5jP8p)oBpd@9wG0ei;O5CAh*jiA-3S zcgM!@EW|>xwX3>R+cQLA9zt`qnr`Oev8NEXG?ziTB69!2T*tlN!7j*9ynpPa(@~5g zWR@t4J7Y0b&J#)_Ki80ObZA^CiUDz{1aa}zu=nA#Iu=$+nK=1*Ir59~21;Ei4$IQ6 z-}WMpb5_@6w;EEKLp|cj$9B9+NhG>>8%Blxpb~<|yC$9iNkW>Z_4_(;uHltb62y{G zk2nt-lFfd5^7JL=zJslh!iR7_8c7d^N&aTV=XWO+yMtr(a{z0>IvwW@ViE1&GqU!5xl5Y^AEW&L*IL}uI?7~9&(=BsBH@862dy};r_bz-s4`;sbByA z8|>d)VE@>|_LgRKs!I+_?8wg;2sx$us0+tc$)>0+775kykq7Np2xMxg;sDHA0Qs

qou1>wZE`Al@jmNnj5#t08F#d)vSxDQFyZZ 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\~MfQ4!yA zDIOtCACsxm&JZ+YHddc^~w{@9W-UPhhk&SoVtojAb z3=0KkR*e7cRnL!1?KD&-sjHT%yqHerdeLujk#~tv&Bi`P#KJ-x>RbBlf;hdnbm@mP ze#?Qy*DaFXJ`^h9<%^a=CDG&VQ!^qRmA8@H(M4Db^41%iGQ=-qwj+2CpE~);O-7EMJwxgaSIcy_bUT z*hRrwg}GfeZS6O{B8&3eADr!1g>CE7)jwZ1EmOd4O|_eaVG?Aj4NO?)+7mCgDfqZfPh+vpO?w+GlN(H@@+{`?#vI@@28Pw!%QW4&FDX{lPOloo`hm8LsDC zk0!4fw@>-|78xJ3n2j2(CY)B9xP5)Eck4(p`TdZ0{*a(~`jfbuIR22I$$jREzLP+i z+ZQoCX&+CeDkFxfZxk{khpM$@b(SkI%c?b410dhsJK0po~vGC)|54gWRW&b?9o z`~iZ&84z_N04Di&(fJ{tId=%@QblZ7ttm5@joCnTx?QhRGVVP z+&oJ1i#J? z#B9ktEg!#p!8FDhc~X&-FqPFXArmSZ&6)O8hrR4rA**QA2yBLzPKPIZL9qUi2>oPp z=uiao*B<;k@A2QI?RT2i|1R$1@6pr$n=bpm7+WcL&cbC0^w$^wn~3+1@SQD8ZB5yK ze&>XeHV?JuqZc@EZxb0PRLn;?h^39Rr$X7(h)PE39g>Lp!fn)reD(YIXk+2I5;VOT zWU=(WEjjV)laQ}H8ddQJXCu%bkSh&?Pxr||`1d$XCJZSyuA^4;TEo{IASFpv?ughTqTU%!ki&NhoXJqoWRrANg;{?OIh)wkIv_;ab-JV zLM}G?!a_QISlElmt-KIpk(`18LppsjbYkLmAvHKfek8oC9nVe$nyDaq7hFq%cWB9- zT)Pry&k3cd*<6vfMHRE~eF$crSCV@Y5`6qn8=AwaSr33{u56+N?&AO4)gV$45e#^z(Nq)MYmm!QWXh*i{n=aIP3TcsyA)dYfHTA%JZ$DxDX zTj`Wg-xRN(lcz>LG4U`Fc=s9gtJ*}OHWRbl0lU$0JqjHMP8iWJm1c%xsa~ML4`5dt zoAGT8cD%lfjg-=NdY3N5h0eG)OxM(O8}XZjl~*Lv*(vYi69r=)7W*T(&5sb3NnVX&~HLR2zG!Pmu+o%Riet4sjd*vi)-^sVbU50X^ z3=oS3B;^9AMJO#pUR5kPKAwHn!p-L{-!5)gRy4>kLX@30;zMcY+E&C2PP*|Nsc}JM zcD8_(x%4wL7t=9SaVu|@R4aJzG)Dne?b9=UKxn`IBzuYEdh^Gn<=lfYt>|>;^B6s$ z7S!bE>LNSIL$dXUA#FQjFV7(ZS6LpxE=R&0q@P+4qJ4W{G{v)s&O>*>f>9i5U!OZp zHp|}MZbp6fo!hNhlXO|$fz-Ow#Q}bq75RBPwuXVy4?PBcb|Vt@?$H?5?T98BTEm!j z;KT?6U^Q`paR>qx7{$LRtlAYOK?Q-JU-y6h_V;fuBwyM&1L$Xc4G()$Ctc`By(_?n zm!YfzNJ75=jo)4hz}sIJ)Su_mKOK>O9(le9slpAwt36--MO1})0)SQE)dN63e;V!u*H(U+8*w{U4Rq zdqDvIM#Q`RV=Vvl{|yv(*WY{0D>?-@EApV+Z9RnT5C7j8V|U&4bPOkh#6TbvfP94c zm+<4c{^9QIVPpD}*?rgf_X*vvp74*@bC zuF_qC_n%6we^vUuFZ^wP`u8!3y8b1m-@C_XCgLy#Ik9zUzJ$qWhijio9{-(Q99`~R!Ze=!R0LjL}Yh%oT3(0?@??}Etw)M*L% z7oGpsxcqCsqwc+{@;?}$&>8Qa0UiB|)PHlN-o5wuQ?k78ZgjsSfA3TOaiIM*%FX`2 zm;AkZ{YOdqU+w route.path === path); const authToken = request.cookies.get('access_token'); @@ -25,6 +33,8 @@ export function middleware(request: NextRequest) { // 3. Autenticado em rota pública com flag "redirect" → vai para raiz if (authToken && publicRoute && publicRoute.whenAuthenticated === 'redirect') { + // OBS: Se ROOT_PATH for '/login', isso pode gerar um loop infinito para usuários logados. + // O ideal seria redirecionar para '/' (dashboard), mas mantive seu código original. return NextResponse.redirect(new URL(ROOT_PATH, request.url)); } @@ -52,7 +62,7 @@ export function middleware(request: NextRequest) { export const config: MiddlewareConfig = { matcher: [ - // ignora APIs, arquivos estáticos e metadados - '/((?!api|_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt|images).*)', + // ignora APIs, arquivos estáticos, metadados E ARQUIVOS .DOCX + '/((?!api|_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt|images|.*\\.docx$).*)', ], -}; +}; \ No newline at end of file diff --git a/src/packages/administrativo/hooks/GGramatica/useGGramaticaIndexHook.ts b/src/packages/administrativo/hooks/GGramatica/useGGramaticaIndexHook.ts index e1b900d..74b8fda 100644 --- a/src/packages/administrativo/hooks/GGramatica/useGGramaticaIndexHook.ts +++ b/src/packages/administrativo/hooks/GGramatica/useGGramaticaIndexHook.ts @@ -2,10 +2,10 @@ import { useState } from 'react'; -import { useResponse } from '@/shared/components/response/ResponseContext'; import GGramaticaInterface from '@/packages/administrativo/interfaces/GGramatica/GGramaticaInterface'; import { GGramaticaIndexService } from '@/packages/administrativo/services/GGramatica/GGramaticaIndexService'; +import { useResponse } from '@/shared/components/response/ResponseContext'; export const useGGramaticaIndexHook = () => { const { setResponse } = useResponse(); diff --git a/src/packages/administrativo/services/GGramatica/GGramaticaIndexService.ts b/src/packages/administrativo/services/GGramatica/GGramaticaIndexService.ts index 7a9fde6..7bda48e 100644 --- a/src/packages/administrativo/services/GGramatica/GGramaticaIndexService.ts +++ b/src/packages/administrativo/services/GGramatica/GGramaticaIndexService.ts @@ -1,12 +1,11 @@ 'use server'; +import { GGramaticaIndexData } from '@/packages/administrativo/data/GGramatica/GGramaticaIndexData'; import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; -import { GGramaticaIndexData } from '@/packages/administrativo/data/GGramatica/GGramaticaIndexData'; export default async function executeGGramaticaIndexService() { const response = await GGramaticaIndexData(); - return response; } diff --git a/src/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoCertidaoForm.tsx b/src/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoCertidaoForm.tsx new file mode 100644 index 0000000..1788c85 --- /dev/null +++ b/src/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoCertidaoForm.tsx @@ -0,0 +1,65 @@ +"use client"; + +import { useMemo } from "react"; + +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; +import TServicoItemPedidoCertidaFormInterface from "@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoCertidaFormInterface"; +import GetFileExtension from "@/shared/actions/file/GetFileExtension"; +import OnlyOfficeEditor from "@/shared/components/editor/onlyoffice/OnlyOfficeEditor"; + +export default function TServicoItemPedidoCertidaForm({ + isOpen, + selectedItem, + onClose, +}: TServicoItemPedidoCertidaFormInterface) { + + const config = useMemo(() => { + + return { + documentType: "word", + document: { + + fileType: GetFileExtension(selectedItem?.certidao_texto,), + title: selectedItem?.certidao_texto, + name: selectedItem?.certidao_texto, + key: `etiqueta_${selectedItem?.servico_itempedido_id}_${new Date().getTime()}`, + }, + editorConfig: { + mode: "edit", + lang: "pt-BR", + callbackUrl: "https://seu-backend.com/api/onlyoffice/callback", + }, + }; + + }, [selectedItem]); + + return ( +

!open && onClose(false)}> + + + Editor de Certidão + +
+ {/* Mostra um loading enquanto os dados não chegam */} + {!config && ( +
+ Carregando documento... +
+ )} + {/* Só renderiza o Editor se o config estiver pronto */} + {isOpen && config && ( + + )} +
+
+
+ ); +} \ No newline at end of file diff --git a/src/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoEtiquetaForm.tsx b/src/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoEtiquetaForm.tsx new file mode 100644 index 0000000..c28d132 --- /dev/null +++ b/src/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoEtiquetaForm.tsx @@ -0,0 +1,64 @@ +"use client"; + +import { useMemo } from "react"; + +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; +import TServicoItemPedidoEtiquetaFormInterface from "@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoEtiquetaFormInterface"; +import GetFileExtension from "@/shared/actions/file/GetFileExtension"; +import OnlyOfficeEditor from "@/shared/components/editor/onlyoffice/OnlyOfficeEditor"; + +export default function TServicoItemPedidoEtiquetaForm({ + isOpen, + selectedItem, + onClose, +}: TServicoItemPedidoEtiquetaFormInterface) { + + const config = useMemo(() => { + + return { + documentType: "word", + document: { + + fileType: GetFileExtension(selectedItem?.etiqueta_texto,), + title: selectedItem?.etiqueta_texto, + name: selectedItem?.etiqueta_texto, + key: `etiqueta_${selectedItem?.servico_itempedido_id}_${new Date().getTime()}`, + }, + editorConfig: { + mode: "edit", + lang: "pt-BR", + }, + }; + + }, [selectedItem]); + + return ( + !open && onClose(false)}> + + + Editor de Etiqueta + +
+ {/* Mostra um loading enquanto os dados não chegam */} + {!config && ( +
+ Carregando documento... +
+ )} + {/* Só renderiza o Editor se o config estiver pronto */} + {isOpen && config && ( + + )} +
+
+
+ ); +} \ No newline at end of file diff --git a/src/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoList.tsx b/src/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoList.tsx index 3ecc8ab..2f0b790 100644 --- a/src/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoList.tsx +++ b/src/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoList.tsx @@ -7,6 +7,7 @@ import { RotateCcwIcon, TicketIcon, } from 'lucide-react'; +import { useState } from 'react'; import { Button } from '@/components/ui/button'; import { ButtonGroup } from '@/components/ui/button-group'; @@ -25,8 +26,15 @@ import FormatMoney from '@/shared/actions/money/FormatMoney'; import { ServicosPedidosSituacoesBadge } from '@/shared/components/servicosPedidosSituacoes/ServicosPedidosSituacoesBadge'; import { ServicosPedidosSituacoesEnum } from '@/shared/enums/ServicosPedidosSituacoesEnum'; +import TServicoItemPedidoCertidaForm from './TServicoItemPedidoCertidaoForm'; +import TServicoItemPedidoEtiquetaForm from './TServicoItemPedidoEtiquetaForm'; + + export default function TServicoItemPedidoList({ items, openConfirmDialog }: TServicoItemPedidoListInterface) { + const [isOpenTServicoItemPedidoCertidaForm, setIsOpenTServicoItemPedidoCertidaForm] = useState(false) + const [isOpenTServicoItemPedidoEtiquetaForm, setIsOpenTServicoItemPedidoEtiquetaForm] = useState(false) + const [selectedItem, setSelectedItem] = useState() const { localItems, handleSituacaoTServicoItemPedido } = useTServicoItemPedidoListControllerHook(items); return ( @@ -43,7 +51,6 @@ export default function TServicoItemPedidoList({ items, openConfirmDialog }: TSe {localItems.map((item) => { const isCancelado = item.situacao === 'C'; - const actionLabel = isCancelado ? 'Ativar Item' : 'Estornar Item'; const confirmTitle = isCancelado ? 'Ativação de Item' : 'Estorno de Item'; const confirmMessage = isCancelado ? `Deseja realmente ativar o item #${item.servico_itempedido_id}?` : `Deseja realmente estornar o item #${item.servico_itempedido_id}?`; @@ -59,10 +66,7 @@ export default function TServicoItemPedidoList({ items, openConfirmDialog }: TSe {/* Descrição */}

- {item.descricao} de {item.nome} –{' '} - + {item.descricao} de {item.nome} –

@@ -111,14 +115,41 @@ export default function TServicoItemPedidoList({ items, openConfirmDialog }: TSe - - - Imprimir Etiqueta - - - Imprimir Cartão - - + {item.etiqueta_modelo_id && ( + <> + + { + setSelectedItem(item); + setIsOpenTServicoItemPedidoEtiquetaForm(true); + }} + > + Imprimir Etiqueta + + + Imprimir Cartão + + + + )} + + {item.tipo_item == 'C' && ( + <> + + { + setSelectedItem(item); + setIsOpenTServicoItemPedidoCertidaForm(true); + }} + > + Editar Certidão + + + Imprimir Certidão + + + + )} @@ -149,6 +180,20 @@ export default function TServicoItemPedidoList({ items, openConfirmDialog }: TSe ); })}
+ {isOpenTServicoItemPedidoCertidaForm && ( + + )} + {isOpenTServicoItemPedidoEtiquetaForm && ( + + )} ); diff --git a/src/packages/servicos/components/TServicoPedido/TServicoPedidoDetails.tsx b/src/packages/servicos/components/TServicoPedido/TServicoPedidoDetails.tsx index d04ab2d..71edf4d 100644 --- a/src/packages/servicos/components/TServicoPedido/TServicoPedidoDetails.tsx +++ b/src/packages/servicos/components/TServicoPedido/TServicoPedidoDetails.tsx @@ -28,13 +28,19 @@ export default function TServicoPedidoDetails({ } = useTServicoPedidoDetailsControllerHook(servico_pedido_id); return ( +
+

+ Pedido: #{TServicoPedido?.servico_pedido_id} +

+
+ {/* Coluna esquerda */}
{ + const api = new API(); + console.log('executeTServicoItemPedidoCertidaoEditData', 1) + return api.send({ + method: Methods.GET, + endpoint: `servicos/pedidos/t_servico_itempedido/${data.servico_itempedido_id}/certidao/editar`, + }); +} + +export const TServicoItemPedidoCertidaoEditData = withClientErrorHandler( + executeTServicoItemPedidoCertidaoEditData, +); diff --git a/src/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoCertidaoEditHook.ts b/src/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoCertidaoEditHook.ts new file mode 100644 index 0000000..ac34a34 --- /dev/null +++ b/src/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoCertidaoEditHook.ts @@ -0,0 +1,35 @@ +'use client'; + +import { useState } from 'react'; + +import TServicoItemPedidoIndexResponseInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoCalculoResponseInterface'; +import TServicoItemPedidoInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoIntefarce'; +import { TServicoItemPedidoCertidaoEditService } from '@/packages/servicos/services/TServicoItemPedido/TServicoItemPedidoCertidaoEditService'; +import { useResponse } from '@/shared/components/response/ResponseContext'; + + +export const useTServicoItemPedidoCertidaoEditHook = () => { + + const { setResponse } = useResponse(); + + const [TServicoItemPedido, setTServicoItemPedido] = useState([]); + + const certidaoEditTServicoItemPedido = async (data: TServicoItemPedidoInterface) => { + + console.log('useTServicoItemPedidoCertidaoEditHook', 1) + + const response = await TServicoItemPedidoCertidaoEditService(data); + + setTServicoItemPedido(response.data); + + setResponse(response); + + // Retorno imediato dos valores + return response; + }; + + return { + TServicoItemPedido, + certidaoEditTServicoItemPedido, + }; +}; diff --git a/src/packages/servicos/hooks/TServicoPedido/useTServicoPedidoDetailsControllerHook.ts b/src/packages/servicos/hooks/TServicoPedido/useTServicoPedidoDetailsControllerHook.ts index ccba08a..d072d7c 100644 --- a/src/packages/servicos/hooks/TServicoPedido/useTServicoPedidoDetailsControllerHook.ts +++ b/src/packages/servicos/hooks/TServicoPedido/useTServicoPedidoDetailsControllerHook.ts @@ -33,6 +33,7 @@ export function useTServicoPedidoDetailsControllerHook( TServicoPedido, setTServicoPedido, } = useTServicoPedidoShowHook(); + const { indexTServicoItemPedido, TServicoItemPedido } = useTServicoItemPedidoIndexHook(); diff --git a/src/packages/servicos/hooks/TServicoPedido/useTServicoPedidoShowHook.ts b/src/packages/servicos/hooks/TServicoPedido/useTServicoPedidoShowHook.ts index 3b30621..51a7493 100644 --- a/src/packages/servicos/hooks/TServicoPedido/useTServicoPedidoShowHook.ts +++ b/src/packages/servicos/hooks/TServicoPedido/useTServicoPedidoShowHook.ts @@ -1,3 +1,5 @@ +'use client'; + import { useState } from 'react'; import TServicoPedidoInterface from '@/packages/servicos/interfaces/TServicoPedido/TServicoPedidoInterface'; diff --git a/src/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoCertidaFormInterface.ts b/src/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoCertidaFormInterface.ts new file mode 100644 index 0000000..b7de0e2 --- /dev/null +++ b/src/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoCertidaFormInterface.ts @@ -0,0 +1,5 @@ +export default interface TServicoItemPedidoCertidaFormInterface { + isOpen: boolean, + selectedItem: any; + onClose: any; +} \ No newline at end of file diff --git a/src/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoEtiquetaFormInterface.ts b/src/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoEtiquetaFormInterface.ts new file mode 100644 index 0000000..5b0c3ee --- /dev/null +++ b/src/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoEtiquetaFormInterface.ts @@ -0,0 +1,5 @@ +export default interface TServicoItemPedidoEtiquetaFormInterface { + isOpen: boolean, + selectedItem: any; + onClose: any; +} \ No newline at end of file diff --git a/src/packages/servicos/services/TServicoItemPedido/TServicoItemPedidoCertidaoEditService.ts b/src/packages/servicos/services/TServicoItemPedido/TServicoItemPedidoCertidaoEditService.ts new file mode 100644 index 0000000..f7bb1e1 --- /dev/null +++ b/src/packages/servicos/services/TServicoItemPedido/TServicoItemPedidoCertidaoEditService.ts @@ -0,0 +1,18 @@ +'use server'; + +import { TServicoItemPedidoCertidaoEditData } from '@/packages/servicos/data/TServicoItemPedido/TServicoItemPedidoCertidaoEditData'; +import TServicoItemPedidoInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoIntefarce'; +import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; + + +export default async function executeTServicoItemPedidoCertidaoEditService( + data: TServicoItemPedidoInterface, +) { + console.log('executeTServicoItemPedidoCertidaoEditService', 1) + const response = await TServicoItemPedidoCertidaoEditData(data); + return response; +} + +export const TServicoItemPedidoCertidaoEditService = withClientErrorHandler( + executeTServicoItemPedidoCertidaoEditService, +); diff --git a/src/packages/servicos/services/TServicoItemPedido/TServicoItemPedidoIndexService.ts b/src/packages/servicos/services/TServicoItemPedido/TServicoItemPedidoIndexService.ts index 4bf6774..c9d20f6 100644 --- a/src/packages/servicos/services/TServicoItemPedido/TServicoItemPedidoIndexService.ts +++ b/src/packages/servicos/services/TServicoItemPedido/TServicoItemPedidoIndexService.ts @@ -1,3 +1,5 @@ +'use server'; + import { TServicoItemPedidoIndexData } from '@/packages/servicos/data/TServicoItemPedido/TServicoItemPedidoIndexData'; import TServicoItemPedidoInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoIntefarce'; import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; diff --git a/src/packages/servicos/services/TServicoPedido/TServicoPedidoShowService.ts b/src/packages/servicos/services/TServicoPedido/TServicoPedidoShowService.ts index 493ee3e..b9278b8 100644 --- a/src/packages/servicos/services/TServicoPedido/TServicoPedidoShowService.ts +++ b/src/packages/servicos/services/TServicoPedido/TServicoPedidoShowService.ts @@ -1,3 +1,5 @@ +'use server' + import { TServicoPedidoShowData } from '@/packages/servicos/data/TServicoPedido/TServicoPedidoShowData'; import TServicoPedidoInterface from '@/packages/servicos/interfaces/TServicoPedido/TServicoPedidoInterface'; import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; diff --git a/src/shared/actions/file/GetFileExtension.ts b/src/shared/actions/file/GetFileExtension.ts new file mode 100644 index 0000000..ef28fb8 --- /dev/null +++ b/src/shared/actions/file/GetFileExtension.ts @@ -0,0 +1,21 @@ +/** + * Obtém a extensão do arquivo a partir do nome ou caminho. + * + * @param filename - Nome do arquivo ou caminho completo + * @returns A extensão do arquivo (ex: 'png', 'pdf') ou string vazia se não houver + */ +export default function GetFileExtension(filename?: string): string { + if (!filename) return ''; + + // Encontra a posição do último ponto na string + const lastDotIndex = filename.lastIndexOf('.'); + + // Se não houver ponto, retorna vazio. + // Opcional: verifica se o ponto não é o primeiro caractere (arquivos como .gitignore) + if (lastDotIndex === -1) { + return ''; + } + + // Retorna tudo após o último ponto e converte para minúsculas + return filename.substring(lastDotIndex + 1).toLowerCase(); +} \ No newline at end of file diff --git a/src/shared/components/editor/onlyoffice/OnlyOfficeEditor.tsx b/src/shared/components/editor/onlyoffice/OnlyOfficeEditor.tsx new file mode 100644 index 0000000..91632f3 --- /dev/null +++ b/src/shared/components/editor/onlyoffice/OnlyOfficeEditor.tsx @@ -0,0 +1,48 @@ +import { DocumentEditor } from "@onlyoffice/document-editor-react"; +import { useEffect, useState } from "react"; + +import GetServerUrl from "./actions/GetServerUrl"; +import { usePrepareOnlyOfficeEditorHook } from "./hooks/usePrepareOnlyOfficeEditorHook"; +import OnlyOfficeInteface from "./interface/OnlyOfficeInterface"; + +export default function OnlyOfficeEditor({ id, config }: OnlyOfficeInteface) { + + const { prepareOnlyOfficeEditorHook } = usePrepareOnlyOfficeEditorHook(); + const [serverUrl, setServerUrl] = useState(null); + + useEffect(() => { + + // 1. Criamos a função async interna + const executePrepare = async () => { + + // Se prepareOnlyOfficeEditorHook já é async, basta aguardar + const response = await prepareOnlyOfficeEditorHook(); + + // Define a url que deve ser carregado o editor + setServerUrl(GetServerUrl(response.data, 1)) + + // Atualiza o caminho do documento + config.document.url = GetServerUrl(response.data, 2) + '/temp/' + config.document.name + + console.log('config', config) + + }; + + // 2. Chamamos ela imediatamente + executePrepare() + + }, [id, config]); + + return ( + <> + {serverUrl && ( + + )} + + ); +} \ No newline at end of file diff --git a/src/shared/components/editor/onlyoffice/actions/GetServerUrl.ts b/src/shared/components/editor/onlyoffice/actions/GetServerUrl.ts new file mode 100644 index 0000000..ad9df53 --- /dev/null +++ b/src/shared/components/editor/onlyoffice/actions/GetServerUrl.ts @@ -0,0 +1,20 @@ +export default function GetServerUrl(data, port) { + + let _port = null + + switch (Number(port)) { + + case 1: + + _port = data.port_only_office + break; + + case 2: + + _port = data.port_api + break; + } + + return `http://${data.ip}:${_port}`; + +} \ No newline at end of file diff --git a/src/shared/components/editor/onlyoffice/data/OnlyOfficeEditorPrepareData.ts b/src/shared/components/editor/onlyoffice/data/OnlyOfficeEditorPrepareData.ts new file mode 100644 index 0000000..dc463ff --- /dev/null +++ b/src/shared/components/editor/onlyoffice/data/OnlyOfficeEditorPrepareData.ts @@ -0,0 +1,18 @@ +import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; +import ApiResponseInterface from '@/shared/services/api/interfaces/ApiResponseInterface'; + +async function executeOnlyOfficeEditorPrepareData(): Promise { + + return { + status: 200, + message: "Dados carregados com sucesso", + data: { + ip: process.env.NEXT_PUBLIC_ORIUS_ONLYOFFICE_IP, + port_only_office: process.env.NEXT_PUBLIC_ORIUS_ONLYOFFICE_PORT, + port_api: process.env.NEXT_PUBLIC_ORIUS_APP_API_PORT, + } + } + +} + +export const OnlyOfficeEditorPrepareData = withClientErrorHandler(executeOnlyOfficeEditorPrepareData); diff --git a/src/shared/components/editor/onlyoffice/data/OnlyOfficeEditorServiceUpData.ts b/src/shared/components/editor/onlyoffice/data/OnlyOfficeEditorServiceUpData.ts new file mode 100644 index 0000000..5041f71 --- /dev/null +++ b/src/shared/components/editor/onlyoffice/data/OnlyOfficeEditorServiceUpData.ts @@ -0,0 +1,40 @@ +import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; +import ApiResponseInterface from '@/shared/services/api/interfaces/ApiResponseInterface'; + +// Adicionei url como parâmetro para tornar a função reutilizável e testável +async function executeOnlyOfficeEditorServiceUpData(url: string): Promise { + + const timeoutMs = 2000; // Defina o tempo limite desejado + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), timeoutMs); + + try { + + const response = await fetch(url, { + method: 'HEAD', + signal: controller.signal + }); + + // O fetch nativo não lança erro em 404 ou 500, então verificamos manualmente. + if (!response.ok) { + throw new Error(`Serviço indisponível. Status: ${response.status}`); + } + + return { + status: 200, + message: "Editor inicializado com sucesso", + data: { + online: true, + status: response.status + } + }; + + } finally { + + // Isso garante que o timer seja limpo, quer a requisição funcione ou falhe (erro propagado) + clearTimeout(timeoutId); + + } +} + +export const OnlyOfficeEditorServiceUpData = withClientErrorHandler(executeOnlyOfficeEditorServiceUpData); \ No newline at end of file diff --git a/src/shared/components/editor/onlyoffice/hooks/usePrepareOnlyOfficeEditorHook.ts b/src/shared/components/editor/onlyoffice/hooks/usePrepareOnlyOfficeEditorHook.ts new file mode 100644 index 0000000..ace44ab --- /dev/null +++ b/src/shared/components/editor/onlyoffice/hooks/usePrepareOnlyOfficeEditorHook.ts @@ -0,0 +1,53 @@ +'use client'; + +import { useState } from 'react'; +import { object } from 'zod'; + +import GGramaticaInterface from '@/packages/administrativo/interfaces/GGramatica/GGramaticaInterface'; +import { useResponse } from '@/shared/components/response/ResponseContext'; + +import { OnlyOfficeEditorServiceUpData } from '../data/OnlyOfficeEditorServiceUpData'; +import { OnlyOfficeEditorPrepareService } from '../services/OnlyOfficeEditorPrepareService'; + +export const usePrepareOnlyOfficeEditorHook = () => { + + const { setResponse } = useResponse(); + + const [onlyOfficeEditor, setOnlyOfficeEditor] = useState([]); + const [serviceUpData, setServiceUpData] = useState(object); + + const prepareOnlyOfficeEditorHook = async () => { + + // Busca as confgiurações do editor + const response = await OnlyOfficeEditorPrepareService(); + + // Define a url do editor + const urlServer = `http://${response.data.ip}:${response.data.port_only_office}` + + // Busca as confgiurações do editor + const responseServiceUp = await OnlyOfficeEditorServiceUpData(urlServer); + + if (responseServiceUp.status != 200) { + setResponse({ + status: responseServiceUp.status, + detail: 'Não foi possivel conectar ao editor', + message: 'Não foi possivel conectar ao editor' + }) + } + + // Armazena os dados consultados + setOnlyOfficeEditor(response.data); + + // Define a resposta (toast, modal, feedback, etc.) + setResponse(response); + + // Retorna os dados imediatamente + return response; + + }; + + return { + onlyOfficeEditor, + prepareOnlyOfficeEditorHook, + }; +}; diff --git a/src/shared/components/editor/onlyoffice/interface/OnlyOfficeInterface.ts b/src/shared/components/editor/onlyoffice/interface/OnlyOfficeInterface.ts new file mode 100644 index 0000000..bb4e30d --- /dev/null +++ b/src/shared/components/editor/onlyoffice/interface/OnlyOfficeInterface.ts @@ -0,0 +1,4 @@ +export default interface OnlyOfficeInteface { + id: string; + config: object; +} \ No newline at end of file diff --git a/src/shared/components/editor/onlyoffice/services/OnlyOfficeEditorPrepareService.ts b/src/shared/components/editor/onlyoffice/services/OnlyOfficeEditorPrepareService.ts new file mode 100644 index 0000000..e5d7897 --- /dev/null +++ b/src/shared/components/editor/onlyoffice/services/OnlyOfficeEditorPrepareService.ts @@ -0,0 +1,11 @@ +'use server'; + +import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; +import { OnlyOfficeEditorPrepareData } from '@/shared/components/editor/onlyoffice/data/OnlyOfficeEditorPrepareData'; + +export default async function executeOnlyOfficeEditorPrepareService() { + const response = await OnlyOfficeEditorPrepareData(); + return response; +} + +export const OnlyOfficeEditorPrepareService = withClientErrorHandler(executeOnlyOfficeEditorPrepareService); \ No newline at end of file diff --git a/src/shared/services/api/Api.ts b/src/shared/services/api/Api.ts index f2cbd56..b80d19a 100644 --- a/src/shared/services/api/Api.ts +++ b/src/shared/services/api/Api.ts @@ -17,7 +17,7 @@ export default class API { try { // Verifica se todos os dados estão corretos - this.ApiSchema.url = process.env.NEXT_PUBLIC_ORIUS_APP_API_URL; + this.ApiSchema.url = process.env.NEXT_PUBLIC_ORIUS_APP_API_URL + ':' + process.env.NEXT_PUBLIC_ORIUS_APP_API_PORT + '/'; this.ApiSchema.prefix = process.env.NEXT_PUBLIC_ORIUS_APP_API_PREFIX; this.ApiSchema.endpoint = _data.endpoint; this.ApiSchema.contentType = process.env.NEXT_PUBLIC_ORIUS_APP_API_CONTENT_TYPE;