diff --git a/package-lock.json b/package-lock.json index 9c71c6f..901bbba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,10 +19,11 @@ "@radix-ui/react-label": "^2.1.7", "@radix-ui/react-popover": "^1.1.15", "@radix-ui/react-progress": "^1.1.7", + "@radix-ui/react-radio-group": "^1.3.8", "@radix-ui/react-scroll-area": "^1.2.10", "@radix-ui/react-select": "^2.2.6", - "@radix-ui/react-separator": "^1.1.7", - "@radix-ui/react-slot": "^1.2.3", + "@radix-ui/react-separator": "^1.1.8", + "@radix-ui/react-slot": "^1.2.4", "@radix-ui/react-switch": "^1.2.6", "@radix-ui/react-tabs": "^1.1.13", "@radix-ui/react-tooltip": "^1.2.8", @@ -123,6 +124,7 @@ "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", @@ -1434,6 +1436,24 @@ } } }, + "node_modules/@radix-ui/react-alert-dialog/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-arrow": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz", @@ -1570,6 +1590,24 @@ } } }, + "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-compose-refs": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", @@ -1636,6 +1674,24 @@ } } }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-direction": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz", @@ -1828,6 +1884,24 @@ } } }, + "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-popover": { "version": "1.1.15", "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.15.tgz", @@ -1865,6 +1939,24 @@ } } }, + "node_modules/@radix-ui/react-popover/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-popper": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz", @@ -1968,6 +2060,24 @@ } } }, + "node_modules/@radix-ui/react-primitive/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-progress": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.7.tgz", @@ -1992,6 +2102,38 @@ } } }, + "node_modules/@radix-ui/react-radio-group": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.3.8.tgz", + "integrity": "sha512-VBKYIYImA5zsxACdisNQ3BjCBfmbGH3kQlnFVqlWU4tXwjy7cGX8ta80BcrO+WJXIn5iBylEH3K6ZTlee//lgQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-roving-focus": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.11.tgz", @@ -2097,13 +2239,54 @@ } } }, - "node_modules/@radix-ui/react-separator": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.7.tgz", - "integrity": "sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA==", + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.1.3" + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-separator": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.8.tgz", + "integrity": "sha512-sDvqVY4itsKwwSMEe0jtKgfTh+72Sy3gPmQpjqcQneqQ4PFmr/1I0YA+2/puilhggCe2gJcx5EBAYFkWkdpa5g==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-primitive": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz", + "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.4" }, "peerDependencies": { "@types/react": "*", @@ -2121,9 +2304,9 @@ } }, "node_modules/@radix-ui/react-slot": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", - "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz", + "integrity": "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==", "license": "MIT", "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" @@ -2231,6 +2414,24 @@ } } }, + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-use-callback-ref": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", @@ -2939,6 +3140,7 @@ "integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==", "devOptional": true, "license": "MIT", + "peer": true, "dependencies": { "csstype": "^3.0.2" } @@ -2949,6 +3151,7 @@ "integrity": "sha512-9KQPoO6mZCi7jcIStSnlOWn2nEF3mNmyr3rIAsGnAbQKYbRLyqmeSc39EVgtxXVia+LMT8j3knZLAZAh+xLmrw==", "devOptional": true, "license": "MIT", + "peer": true, "peerDependencies": { "@types/react": "^19.2.0" } @@ -2965,6 +3168,7 @@ "integrity": "sha512-rUsLh8PXmBjdiPY+Emjz9NX2yHvhS11v0SR6xNJkm5GM1MO9ea/1GoDKlHHZGrOJclL/cZ2i/vRUYVtjRhrHVQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.46.1", @@ -2995,6 +3199,7 @@ "integrity": "sha512-6JSSaBZmsKvEkbRUkf7Zj7dru/8ZCrJxAqArcLaVMee5907JdtEbKGsZ7zNiIm/UAkpGUkaSMZEXShnN2D1HZA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.46.1", "@typescript-eslint/types": "8.46.1", @@ -3469,6 +3674,7 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -3821,6 +4027,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.8.9", "caniuse-lite": "^1.0.30001746", @@ -4625,6 +4832,7 @@ "integrity": "sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -4685,6 +4893,7 @@ "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", "dev": true, "license": "MIT", + "peer": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -4811,6 +5020,7 @@ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", @@ -6965,6 +7175,7 @@ "resolved": "https://registry.npmjs.org/next/-/next-15.5.5.tgz", "integrity": "sha512-OQVdBPtpBfq7HxFN0kOVb7rXXOSIkt5lTzDJDGRBcOyVvNRIWFauMqi1gIHd1pszq1542vMOGY0HP4CaiALfkA==", "license": "MIT", + "peer": true, "dependencies": { "@next/env": "15.5.5", "@swc/helpers": "0.5.15", @@ -7361,6 +7572,7 @@ "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "dev": true, "license": "MIT", + "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -7518,6 +7730,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -7527,6 +7740,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==", "license": "MIT", + "peer": true, "dependencies": { "scheduler": "^0.26.0" }, @@ -7539,6 +7753,7 @@ "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.65.0.tgz", "integrity": "sha512-xtOzDz063WcXvGWaHgLNrNzlsdFgtUWcb32E6WFaGTd7kPZG3EeDusjdZfUsPwKCKVXy1ZlntifaHZ4l8pAsmw==", "license": "MIT", + "peer": true, "engines": { "node": ">=18.0.0" }, @@ -7554,7 +7769,8 @@ "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/react-masked-text": { "version": "1.0.5", @@ -7567,6 +7783,7 @@ "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", "license": "MIT", + "peer": true, "dependencies": { "@types/use-sync-external-store": "^0.0.6", "use-sync-external-store": "^1.4.0" @@ -7685,7 +7902,8 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/redux-thunk": { "version": "3.1.0", @@ -8445,6 +8663,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -8456,7 +8675,8 @@ "version": "8.1.2", "resolved": "https://registry.npmjs.org/tinymce/-/tinymce-8.1.2.tgz", "integrity": "sha512-KITxHEEHRlxC5xOnxA123eAJ67NgsWxNphtItWt9TRu07DiTZrWIqJeIKRX9euE51/l3kJO4WQiqoBXKTJJGsA==", - "license": "GPL-2.0-or-later" + "license": "GPL-2.0-or-later", + "peer": true }, "node_modules/to-regex-range": { "version": "5.0.1", @@ -8610,6 +8830,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -8675,6 +8896,7 @@ "dev": true, "hasInstallScript": true, "license": "MIT", + "peer": true, "dependencies": { "napi-postinstall": "^0.3.0" }, @@ -8961,6 +9183,7 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.12.tgz", "integrity": "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==", "license": "MIT", + "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/package.json b/package.json index 1fe27a2..b918299 100644 --- a/package.json +++ b/package.json @@ -21,10 +21,11 @@ "@radix-ui/react-label": "^2.1.7", "@radix-ui/react-popover": "^1.1.15", "@radix-ui/react-progress": "^1.1.7", + "@radix-ui/react-radio-group": "^1.3.8", "@radix-ui/react-scroll-area": "^1.2.10", "@radix-ui/react-select": "^2.2.6", - "@radix-ui/react-separator": "^1.1.7", - "@radix-ui/react-slot": "^1.2.3", + "@radix-ui/react-separator": "^1.1.8", + "@radix-ui/react-slot": "^1.2.4", "@radix-ui/react-switch": "^1.2.6", "@radix-ui/react-tabs": "^1.1.13", "@radix-ui/react-tooltip": "^1.2.8", diff --git a/public/sounds/success.mp3 b/public/sounds/success.mp3 new file mode 100644 index 0000000..0241778 Binary files /dev/null and b/public/sounds/success.mp3 differ diff --git a/src/app/(protected)/(administrativo)/(g_usuario)/usuarios/formulario/page.tsx b/src/app/(protected)/(administrativo)/(g_usuario)/usuarios/formulario/page.tsx index 5c54cba..2721d7a 100644 --- a/src/app/(protected)/(administrativo)/(g_usuario)/usuarios/formulario/page.tsx +++ b/src/app/(protected)/(administrativo)/(g_usuario)/usuarios/formulario/page.tsx @@ -3,13 +3,10 @@ import { zodResolver } from '@hookform/resolvers/zod'; import { useForm } from 'react-hook-form'; import { z } from 'zod'; -import { Input } from '@/components/ui/input'; -import { GUsuarioSchema } from '../../../../../../packages/administrativo/schemas/GUsuario/GUsuarioSchema'; + import { Button } from '@/components/ui/button'; - import { Card, CardContent } from '@/components/ui/card'; - import { Form, FormControl, @@ -18,8 +15,10 @@ import { FormLabel, FormMessage, } from '@/components/ui/form'; +import { Input } from '@/components/ui/input'; import { useGUsuarioSaveHook } from '../../../../../../packages/administrativo/hooks/GUsuario/useGUsuarioSaveHook'; +import { GUsuarioSchema } from '../../../../../../packages/administrativo/schemas/GUsuario/GUsuarioSchema'; type FormValues = z.infer; diff --git a/src/app/(protected)/(administrativo)/(g_usuario)/usuarios/page.tsx b/src/app/(protected)/(administrativo)/(g_usuario)/usuarios/page.tsx index 3f1d234..07463dd 100644 --- a/src/app/(protected)/(administrativo)/(g_usuario)/usuarios/page.tsx +++ b/src/app/(protected)/(administrativo)/(g_usuario)/usuarios/page.tsx @@ -1,7 +1,10 @@ 'use client'; -import { Card, CardContent } from '@/components/ui/card'; +import Link from 'next/link'; +import { useEffect } from 'react'; +import { Button } from '@/components/ui/button'; +import { Card, CardContent } from '@/components/ui/card'; import { Table, TableBody, @@ -10,14 +13,14 @@ import { TableHeader, TableRow, } from '@/components/ui/table'; - -import Usuario from '../../../../../packages/administrativo/interfaces/GUsuario/GUsuarioInterface'; -import { Button } from '@/components/ui/button'; -import Link from 'next/link'; -import { useGUsuarioIndexHook } from '../../../../../packages/administrativo/hooks/GUsuario/useGUsuarioIndexHook'; -import { useEffect } from 'react'; import Loading from '@/shared/components/loading/loading'; +import { useGUsuarioIndexHook } from '../../../../../packages/administrativo/hooks/GUsuario/useGUsuarioIndexHook'; +import Usuario from '../../../../../packages/administrativo/interfaces/GUsuario/GUsuarioInterface'; + + + + export default function UsuarioPage() { const { usuarios, fetchUsuarios } = useGUsuarioIndexHook(); diff --git a/src/app/(protected)/(cadastros)/cadastros/(t_servico_tipo)/servicos-tipo/page.tsx b/src/app/(protected)/(cadastros)/cadastros/(t_servico_tipo)/servicos-tipo/page.tsx index 5215447..c976323 100644 --- a/src/app/(protected)/(cadastros)/cadastros/(t_servico_tipo)/servicos-tipo/page.tsx +++ b/src/app/(protected)/(cadastros)/cadastros/(t_servico_tipo)/servicos-tipo/page.tsx @@ -1,26 +1,26 @@ 'use client'; -import { useEffect, useState, useCallback } from 'react'; import { Card, CardContent } from '@/components/ui/card'; +import { useCallback, useEffect, useState } from 'react'; import Loading from '@/shared/components/loading/loading'; // Componentes específicos para TServicoTipo -import TServicoTipoTable from '../../_components/t_servico_tipo/TServicoTipoTable'; import TServicoTipoForm from '../../_components/t_servico_tipo/TServicoTipoForm'; +import TServicoTipoTable from '../../_components/t_servico_tipo/TServicoTipoTable'; // Hooks específicos para TServicoTipo -import { useTServicoTipoReadHook } from '../../_hooks/t_servico_tipo/useTServicoTipoReadHook'; -import { useTServicoTipoSaveHook } from '../../_hooks/t_servico_tipo/useTServicoTipoSaveHook'; -import { useTServicoTipoRemoveHook } from '../../_hooks/t_servico_tipo/useTServicoTipoRemoveHook'; -import { useTServicoTipoEditHook } from '../../_hooks/t_servico_tipo/useTServicoTipoEditHook'; +import { useTServicoTipoEditHook } from '../../../../../../packages/administrativo/hooks/TServicoTipo/useTServicoTipoEditHook'; +import { useTServicoTipoReadHook } from '../../../../../../packages/administrativo/hooks/TServicoTipo/useTServicoTipoReadHook'; +import { useTServicoTipoRemoveHook } from '../../../../../../packages/administrativo/hooks/TServicoTipo/useTServicoTipoRemoveHook'; +import { useTServicoTipoSaveHook } from '../../../../../../packages/administrativo/hooks/TServicoTipo/useTServicoTipoSaveHook'; import ConfirmDialog from '@/shared/components/confirmDialog/ConfirmDialog'; import { useConfirmDialog } from '@/shared/components/confirmDialog/useConfirmDialog'; // Interface específica para TServicoTipo -import TServicoTipoInterface from '../../_interfaces/TServicoTipoInterface'; import Header from '@/shared/components/structure/Header'; +import TServicoTipoInterface from '../../_interfaces/TServicoTipoInterface'; export default function TServicoTipoPage() { // Hooks para leitura, salvamento e remoção diff --git a/src/app/(protected)/(cadastros)/cadastros/_components/t_servico_tipo/TServicoTipoForm.tsx b/src/app/(protected)/(cadastros)/cadastros/_components/t_servico_tipo/TServicoTipoForm.tsx index 37ac514..e9da655 100644 --- a/src/app/(protected)/(cadastros)/cadastros/_components/t_servico_tipo/TServicoTipoForm.tsx +++ b/src/app/(protected)/(cadastros)/cadastros/_components/t_servico_tipo/TServicoTipoForm.tsx @@ -1,11 +1,7 @@ 'use client'; -import React from 'react'; -import z from 'zod'; -import { useForm } from 'react-hook-form'; -import { zodResolver } from '@hookform/resolvers/zod'; -import { useState } from 'react'; import { Button } from '@/components/ui/button'; +import { Checkbox } from '@/components/ui/checkbox'; import { Dialog, DialogClose, @@ -15,8 +11,6 @@ import { DialogHeader, DialogTitle, } from '@/components/ui/dialog'; -import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; -import { CirclePlus, DollarSign, Settings, SquarePen, Trash } from 'lucide-react'; import { Form, FormControl, @@ -26,13 +20,10 @@ import { FormMessage, } from '@/components/ui/form'; import { Input } from '@/components/ui/input'; -import { Checkbox } from '@/components/ui/checkbox'; import { Select, SelectContent, - SelectItem, - SelectTrigger, - SelectValue, + SelectItem } from '@/components/ui/select'; import { Table, @@ -42,23 +33,28 @@ import { TableHeader, TableRow, } from '@/components/ui/table'; +import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { CirclePlus, DollarSign, Settings, SquarePen, Trash } from 'lucide-react'; +import React, { useState } from 'react'; +import { useForm } from 'react-hook-form'; -import { TServicoTipoSchema, TServicoTipoFormValues } from '../../_schemas/TServicoTipoSchema'; -import { useEffect } from 'react'; -import GMarcacaoTipoSelect from '@/packages/administrativo/components/GMarcacaoTipo/GMarcacaoTipoSelect'; -import GEmolumentoSelect from '@/packages/administrativo/components/GEmolumento/GEmolumentoSelect'; import { useGEmolumentoItemReadHook } from '@/app/(protected)/(cadastros)/cadastros/_hooks/g_emolumento_item/useGEmolumentoItemReadHook'; +import { useTServicoEtiquetaReadHook } from '@/app/(protected)/(cadastros)/cadastros/_hooks/t_servico_etiqueta/useTServicoEtiquetaReadHook'; +import { useTServicoEtiquetaRemoveHook } from '@/app/(protected)/(cadastros)/cadastros/_hooks/t_servico_etiqueta/useTServicoEtiquetaRemoveHook'; +import { useTServicoEtiquetaSaveHook } from '@/app/(protected)/(cadastros)/cadastros/_hooks/t_servico_etiqueta/useTServicoEtiquetaSaveHook'; import { GEmolumentoItemReadInterface } from '@/app/(protected)/(cadastros)/cadastros/_interfaces/GEmolumentoItemReadInterface'; -import CategoriaServicoSelect from '@/shared/components/categoriaServicoSelect/CategoriaServicoSelect'; import CCaixaServicoSelect from '@/packages/administrativo/components/CCaixaServico/CCaixaServicoSelect'; -import { TServicoTipoSaveData } from '../../_data/TServicoTipo/TServicoTipoSaveData'; +import GEmolumentoSelect from '@/packages/administrativo/components/GEmolumento/GEmolumentoSelect'; +import GMarcacaoTipoSelect from '@/packages/administrativo/components/GMarcacaoTipo/GMarcacaoTipoSelect'; import TTBReconhecimentoTipoSelect from '@/packages/administrativo/components/TTBReconhecimentoTipo/TTBReconhecimentoTipoSelect'; +import CategoriaServicoSelect from '@/shared/components/categoriaServicoSelect/CategoriaServicoSelect'; import { ConfirmacaoCheckBox } from '@/shared/components/confirmacao/ConfirmacaoCheckBox'; import ConfirmacaoSelect from '@/shared/components/confirmacao/ConfirmacaoSelect'; import { TipoPessoaSelect } from '@/shared/components/tipoPessoa/tipoPessoaSelect'; -import { useTServicoEtiquetaReadHook } from '@/app/(protected)/(cadastros)/cadastros/_hooks/t_servico_etiqueta/useTServicoEtiquetaReadHook'; -import { useTServicoEtiquetaSaveHook } from '@/app/(protected)/(cadastros)/cadastros/_hooks/t_servico_etiqueta/useTServicoEtiquetaSaveHook'; -import { useTServicoEtiquetaRemoveHook } from '@/app/(protected)/(cadastros)/cadastros/_hooks/t_servico_etiqueta/useTServicoEtiquetaRemoveHook'; +import { useEffect } from 'react'; +import { TServicoTipoSaveData } from '../../../../../../packages/administrativo/data/TServicoTipo/TServicoTipoSaveData'; +import { TServicoTipoFormValues, TServicoTipoSchema } from '../../_schemas/TServicoTipoSchema'; // Propriedades esperadas pelo componente interface Props { diff --git a/src/app/(protected)/(cadastros)/cadastros/_data/GEmolumento/GEmolumentoIndexData.ts b/src/app/(protected)/(cadastros)/cadastros/_data/GEmolumento/GEmolumentoIndexData.ts index 422fb54..ceb79ab 100644 --- a/src/app/(protected)/(cadastros)/cadastros/_data/GEmolumento/GEmolumentoIndexData.ts +++ b/src/app/(protected)/(cadastros)/cadastros/_data/GEmolumento/GEmolumentoIndexData.ts @@ -6,20 +6,19 @@ import API from '@/shared/services/api/Api'; // Importa o enum que define os métodos HTTP disponíveis (GET, POST, PUT, DELETE, etc.) import { Methods } from '@/shared/services/api/enums/ApiMethodEnum'; + import { GEmolumentoReadInterface } from '../../_interfaces/GEmolumentoReadInterface'; // Função assíncrona responsável por executar a requisição para listar os tipos de marcação async function executeGEmolumentoIndexData(data: GEmolumentoReadInterface) { + // Cria uma nova instância da classe API para enviar a requisição const api = new API(); - // Concatena o endpoint com a query string (caso existam parâmetros) - const endpoint = `administrativo/g_emolumento/${data.sistema_id}`; - // Envia uma requisição GET para o endpoint 'administrativo/g_marcacao_tipo/' return await api.send({ method: Methods.GET, - endpoint: endpoint, + endpoint: `administrativo/g_emolumento/sistema/${data.sistema_id}?${new URLSearchParams(data.urlParams).toString()}`, }); } diff --git a/src/app/(protected)/(cadastros)/cadastros/_hooks/g_emolumento/useGEmolumentoReadHook.ts b/src/app/(protected)/(cadastros)/cadastros/_hooks/g_emolumento/useGEmolumentoReadHook.ts index b18cc96..924bf9c 100644 --- a/src/app/(protected)/(cadastros)/cadastros/_hooks/g_emolumento/useGEmolumentoReadHook.ts +++ b/src/app/(protected)/(cadastros)/cadastros/_hooks/g_emolumento/useGEmolumentoReadHook.ts @@ -1,15 +1,16 @@ // Importa o hook responsável por gerenciar e exibir respostas globais (sucesso, erro, etc.) +import { useMemo, useState } from 'react'; + import { useResponse } from '@/shared/components/response/ResponseContext'; // Importa hooks do React para gerenciamento de estado e memorização de valores -import { useMemo, useState } from 'react'; // Importa a interface que define a estrutura dos dados de "GEmolumento" +import { GEmolumentoInterface } from '../../_interfaces/GEmolumentoInterface'; import { GEmolumentoReadInterface } from '../../_interfaces/GEmolumentoReadInterface'; // Importa o serviço responsável por buscar os dados de "GEmolumento" na API import { GEmolumentoIndexService } from '../../_services/g_emolumento/GEmolumentoIndexService'; -import { GEmolumentoInterface } from '../../_interfaces/GEmolumentoInterface'; // Hook personalizado para leitura (consulta) dos emolumentos export const useGEmolumentoReadHook = () => { diff --git a/src/app/(protected)/(cadastros)/cadastros/_hooks/g_emolumento_item/useGEmolumentoItemReadHook.ts b/src/app/(protected)/(cadastros)/cadastros/_hooks/g_emolumento_item/useGEmolumentoItemReadHook.ts index 000908a..1fa5dd1 100644 --- a/src/app/(protected)/(cadastros)/cadastros/_hooks/g_emolumento_item/useGEmolumentoItemReadHook.ts +++ b/src/app/(protected)/(cadastros)/cadastros/_hooks/g_emolumento_item/useGEmolumentoItemReadHook.ts @@ -1,15 +1,16 @@ // Importa o hook responsável por gerenciar e exibir respostas globais (sucesso, erro, etc.) +import { useMemo, useState } from 'react'; + import { useResponse } from '@/shared/components/response/ResponseContext'; // Importa hooks do React para gerenciamento de estado e memorização de valores -import { useMemo, useState } from 'react'; // Importa a interface que define a estrutura dos dados de "gEmolumentoItem" +import { GEmolumentoItemInterface } from '../../_interfaces/GEmolumentoItemInterface'; import { GEmolumentoItemReadInterface } from '../../_interfaces/GEmolumentoItemReadInterface'; // Importa o serviço responsável por buscar os dados de "GEmolumentoItem" na API import { GEmolumentoItemValorService } from '../../_services/g_emolumento_item/GEmolumentoItemValorService'; -import { GEmolumentoItemInterface } from '../../_interfaces/GEmolumentoItemInterface'; // Hook personalizado para leitura (consulta) dos emolumentos export const useGEmolumentoItemReadHook = () => { diff --git a/src/app/(protected)/(cadastros)/cadastros/_interfaces/GEmolumentoReadInterface.ts b/src/app/(protected)/(cadastros)/cadastros/_interfaces/GEmolumentoReadInterface.ts index 111562f..b853138 100644 --- a/src/app/(protected)/(cadastros)/cadastros/_interfaces/GEmolumentoReadInterface.ts +++ b/src/app/(protected)/(cadastros)/cadastros/_interfaces/GEmolumentoReadInterface.ts @@ -1,3 +1,4 @@ export interface GEmolumentoReadInterface { sistema_id?: number; + urlParams?: object } diff --git a/src/app/(protected)/(cadastros)/cadastros/_interfaces/TServicoTipoInterface.ts b/src/app/(protected)/(cadastros)/cadastros/_interfaces/TServicoTipoInterface.ts index a7e6e7c..a7d793c 100644 --- a/src/app/(protected)/(cadastros)/cadastros/_interfaces/TServicoTipoInterface.ts +++ b/src/app/(protected)/(cadastros)/cadastros/_interfaces/TServicoTipoInterface.ts @@ -2,6 +2,7 @@ export default interface TServicoTipoInterface { servico_tipo_id?: number; // SERVICO_TIPO_ID NUMERIC(10,2) NOT NULL (PK) descricao: string; // DESCRICAO VARCHAR(60) valor?: number; // VALOR NUMERIC(14,3) + tipo_item?: string; requer_autorizacao?: string; // REQUER_AUTORIZACAO VARCHAR(1) requer_biometria?: string; // REQUER_BIOMETRIA VARCHAR(1) tipo_pessoa?: string; // TIPO_PESSOA VARCHAR(1) diff --git a/src/app/(protected)/(cadastros)/cadastros/_services/g_emolumento/GEmolumentoIndexService.ts b/src/app/(protected)/(cadastros)/cadastros/_services/g_emolumento/GEmolumentoIndexService.ts index 4d46361..8d90167 100644 --- a/src/app/(protected)/(cadastros)/cadastros/_services/g_emolumento/GEmolumentoIndexService.ts +++ b/src/app/(protected)/(cadastros)/cadastros/_services/g_emolumento/GEmolumentoIndexService.ts @@ -7,6 +7,7 @@ import { GEmolumentoReadInterface } from '../../_interfaces/GEmolumentoReadInter // Função assíncrona responsável por executar o serviço de listagem de tipos de marcação async function executeGEmolumentoIndexService(data: GEmolumentoReadInterface) { + // Chama a função que realiza a requisição à API e aguarda a resposta const response = await GEmolumentoIndexData(data); diff --git a/src/app/(protected)/layout.tsx b/src/app/(protected)/layout.tsx index c6fea82..9943bc3 100644 --- a/src/app/(protected)/layout.tsx +++ b/src/app/(protected)/layout.tsx @@ -2,8 +2,8 @@ import type { Metadata } from 'next'; import { Geist, Geist_Mono } from 'next/font/google'; import '../globals.css'; -import { ResponseProvider } from '../../shared/components/response/ResponseContext'; import { AppSidebar } from '@/components/app-sidebar'; +import { ThemeProvider } from '@/components/theme-provider'; import { Breadcrumb, BreadcrumbItem, @@ -15,7 +15,10 @@ import { import { Separator } from '@/components/ui/separator'; import { SidebarInset, SidebarProvider, SidebarTrigger } from '@/components/ui/sidebar'; import { Toaster } from '@/components/ui/sonner'; + import Response from '../../shared/components/response/response'; +import { ResponseProvider } from '../../shared/components/response/ResponseContext'; + const geistSans = Geist({ variable: '--font-geist-sans', @@ -35,46 +38,48 @@ export const metadata: Metadata = { }, }; -export default function RootLayout({ - children, -}: Readonly<{ - children: React.ReactNode; -}>) { +export default function RootLayout({ children }: { children: React.ReactNode }) { return ( - + - - - -
-
- - - - - - Building Your Application - - - - Data Fetching - - - -
-
- -
- {children} - - -
-
-
-
+ + + + + +
+
+ + + + + + + Building Your Application + + + + + Data Fetching + + + +
+
+ + +
+ {children} + + +
+
+
+
+
); diff --git a/src/app/(protected)/servicos/balcao/detalhes/[servicoPedidoId]/page.tsx b/src/app/(protected)/servicos/balcao/detalhes/[servicoPedidoId]/page.tsx new file mode 100644 index 0000000..a69a920 --- /dev/null +++ b/src/app/(protected)/servicos/balcao/detalhes/[servicoPedidoId]/page.tsx @@ -0,0 +1,16 @@ +'use client' + +import { useParams } from "next/navigation"; + +import TServicoPedidoDetails from "@/packages/servicos/components/TServicoPedido/TServicoPedidoDetails"; + +export default function TServicoPedidoDetailsPage() { + + const params = useParams(); + + return ( + + ) +} \ No newline at end of file diff --git a/src/app/(protected)/servicos/balcao/pedido/[servicoPedidoId]/page.tsx b/src/app/(protected)/servicos/balcao/pedido/[servicoPedidoId]/page.tsx new file mode 100644 index 0000000..d830198 --- /dev/null +++ b/src/app/(protected)/servicos/balcao/pedido/[servicoPedidoId]/page.tsx @@ -0,0 +1,16 @@ +'use client' + +import { useParams } from "next/navigation"; + +import TServicoPedidoForm from "@/packages/servicos/components/TServicoPedido/TServicoPedidoForm"; + +export default function TServicoPedidoPage() { + + const params = useParams(); + + return ( + + ) +} \ No newline at end of file diff --git a/src/app/(protected)/servicos/balcao/pedido/page.tsx b/src/app/(protected)/servicos/balcao/pedido/page.tsx index 12d4839..ceb16b2 100644 --- a/src/app/(protected)/servicos/balcao/pedido/page.tsx +++ b/src/app/(protected)/servicos/balcao/pedido/page.tsx @@ -1,90 +1,7 @@ -import { Card, CardContent } from "@/components/ui/card"; -import TServicoItemPedidoResumo from "@/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoResumo"; +import TServicoPedidoForm from "@/packages/servicos/components/TServicoPedido/TServicoPedidoForm" -const itens = [ - { - id: 1, - descricao: "Reconhecimento de Firma", - valor: 12.50, - }, - { - id: 2, - descricao: "Autenticação de Cópia", - valor: 6.00, - }, - { - id: 3, - descricao: "Procuração Pública", - valor: 98.75, - }, - { - id: 4, - descricao: "Certidão de Escritura", - valor: 42.30, - }, - { - id: 5, - descricao: "Registro de Documento", - valor: 73.10, - }, -] - - -export default function PedidoPage() { +export default function TServicoPedidoPage() { return ( -
-
-
- - -
-
- - - - - -
-
- - - - - -
-
- - - - - -
-
- - - - - -
-
- - - - - -
-
-
-
-
-
- -
-
-
+ ) } \ No newline at end of file diff --git a/src/app/globals.css b/src/app/globals.css index 988ebfb..14d7db0 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -3,60 +3,179 @@ @custom-variant dark (&:is(.dark *)); +:root { + --background: oklch(0.9911 0 0); + --foreground: oklch(0.2988 0.0123 222.4429); + --card: oklch(1.0000 0 0); + --card-foreground: oklch(0.2988 0.0123 222.4429); + --popover: oklch(0.9881 0 0); + --popover-foreground: oklch(0.2988 0.0123 222.4429); + --primary: oklch(0.7210 0.1873 47.5640); + --primary-foreground: oklch(1.0000 0 0); + --secondary: oklch(0.2988 0.0123 222.4429); + --secondary-foreground: oklch(1.0000 0 0); + --muted: oklch(0.9700 0 0); + --muted-foreground: oklch(0.5560 0 0); + --accent: oklch(0.9551 0 0); + --accent-foreground: oklch(0.2988 0.0123 222.4429); + --destructive: oklch(0.5770 0.2450 27.3250); + --destructive-foreground: oklch(1 0 0); + --border: oklch(0.9220 0 0); + --input: oklch(0.9220 0 0); + --ring: oklch(0.7080 0 0); + --chart-1: oklch(0.8100 0.1000 252); + --chart-2: oklch(0.6200 0.1900 260); + --chart-3: oklch(0.5500 0.2200 263); + --chart-4: oklch(0.4900 0.2200 264); + --chart-5: oklch(0.4200 0.1800 266); + --sidebar: oklch(1.0000 0 0); + --sidebar-foreground: oklch(0.2988 0.0123 222.4429); + --sidebar-primary: oklch(0.2364 0.0083 240.2365); + --sidebar-primary-foreground: oklch(0.9850 0 0); + --sidebar-accent: oklch(0.9700 0 0); + --sidebar-accent-foreground: oklch(0.2050 0 0); + --sidebar-border: oklch(0.9220 0 0); + --sidebar-ring: oklch(0.7080 0 0); + --font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + --font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif; + --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + --radius: 0.625rem; + --shadow-x: 0; + --shadow-y: 1px; + --shadow-blur: 3px; + --shadow-spread: 0px; + --shadow-opacity: 0.1; + --shadow-color: oklch(0 0 0); + --shadow-2xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05); + --shadow-xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05); + --shadow-sm: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 1px 2px -1px hsl(0 0% 0% / 0.10); + --shadow: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 1px 2px -1px hsl(0 0% 0% / 0.10); + --shadow-md: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 2px 4px -1px hsl(0 0% 0% / 0.10); + --shadow-lg: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 4px 6px -1px hsl(0 0% 0% / 0.10); + --shadow-xl: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 8px 10px -1px hsl(0 0% 0% / 0.10); + --shadow-2xl: 0 1px 3px 0px hsl(0 0% 0% / 0.25); + --tracking-normal: 0em; + --spacing: 0.25rem; + --shadow-offset-x: 0; + --shadow-offset-y: 1px; + --letter-spacing: 0em; +} + +.dark { + --background: oklch(0.1934 0.0062 236.9149); + --foreground: oklch(0.9881 0 0); + --card: oklch(0.2364 0.0083 240.2365); + --card-foreground: oklch(0.9881 0 0); + --popover: oklch(0.2988 0.0123 222.4429); + --popover-foreground: oklch(0.9881 0 0); + --primary: oklch(0.7210 0.1873 47.5640); + --primary-foreground: oklch(0.2988 0.0123 222.4429); + --secondary: oklch(0.2988 0.0123 222.4429); + --secondary-foreground: oklch(1.0000 0 0); + --muted: oklch(0.2690 0 0); + --muted-foreground: oklch(0.7080 0 0); + --accent: oklch(0.2988 0.0123 222.4429); + --accent-foreground: oklch(1.0000 0 0); + --destructive: oklch(0.7040 0.1910 22.2160); + --destructive-foreground: oklch(0.9850 0 0); + --border: oklch(0.2750 0 0); + --input: oklch(0.3250 0 0); + --ring: oklch(0.5560 0 0); + --chart-1: oklch(0.8100 0.1000 252); + --chart-2: oklch(0.6200 0.1900 260); + --chart-3: oklch(0.5500 0.2200 263); + --chart-4: oklch(0.4900 0.2200 264); + --chart-5: oklch(0.4200 0.1800 266); + --sidebar: oklch(0.2364 0.0083 240.2365); + --sidebar-foreground: oklch(0.9881 0 0); + --sidebar-primary: oklch(0.4880 0.2430 264.3760); + --sidebar-primary-foreground: oklch(0.9850 0 0); + --sidebar-accent: oklch(0.2690 0 0); + --sidebar-accent-foreground: oklch(0.9850 0 0); + --sidebar-border: oklch(0.2750 0 0); + --sidebar-ring: oklch(0.4390 0 0); + --font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + --font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif; + --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + --radius: 0.625rem; + --shadow-x: 0; + --shadow-y: 1px; + --shadow-blur: 3px; + --shadow-spread: 0px; + --shadow-opacity: 0.1; + --shadow-color: oklch(0 0 0); + --shadow-2xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05); + --shadow-xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05); + --shadow-sm: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 1px 2px -1px hsl(0 0% 0% / 0.10); + --shadow: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 1px 2px -1px hsl(0 0% 0% / 0.10); + --shadow-md: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 2px 4px -1px hsl(0 0% 0% / 0.10); + --shadow-lg: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 4px 6px -1px hsl(0 0% 0% / 0.10); + --shadow-xl: 0 1px 3px 0px hsl(0 0% 0% / 0.10), 0 8px 10px -1px hsl(0 0% 0% / 0.10); + --shadow-2xl: 0 1px 3px 0px hsl(0 0% 0% / 0.25); + --shadow-offset-x: 0; + --shadow-offset-y: 1px; + --letter-spacing: 0em; + --spacing: 0.25rem; +} + @theme inline { --color-background: var(--background); --color-foreground: var(--foreground); - --font-sans: Inter, sans-serif; - --font-mono: JetBrains Mono, monospace; - --color-sidebar-ring: var(--sidebar-ring); - --color-sidebar-border: var(--sidebar-border); - --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); - --color-sidebar-accent: var(--sidebar-accent); - --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); - --color-sidebar-primary: var(--sidebar-primary); - --color-sidebar-foreground: var(--sidebar-foreground); - --color-sidebar: var(--sidebar); - --color-chart-5: var(--chart-5); - --color-chart-4: var(--chart-4); - --color-chart-3: var(--chart-3); - --color-chart-2: var(--chart-2); - --color-chart-1: var(--chart-1); - --color-ring: var(--ring); - --color-input: var(--input); - --color-border: var(--border); - --color-destructive: var(--destructive); - --color-accent-foreground: var(--accent-foreground); - --color-accent: var(--accent); - --color-muted-foreground: var(--muted-foreground); - --color-muted: var(--muted); - --color-secondary-foreground: var(--secondary-foreground); - --color-secondary: var(--secondary); - --color-primary-foreground: var(--primary-foreground); - --color-primary: var(--primary); - --color-popover-foreground: var(--popover-foreground); - --color-popover: var(--popover); - --color-card-foreground: var(--card-foreground); --color-card: var(--card); + --color-card-foreground: var(--card-foreground); + --color-popover: var(--popover); + --color-popover-foreground: var(--popover-foreground); + --color-primary: var(--primary); + --color-primary-foreground: var(--primary-foreground); + --color-secondary: var(--secondary); + --color-secondary-foreground: var(--secondary-foreground); + --color-muted: var(--muted); + --color-muted-foreground: var(--muted-foreground); + --color-accent: var(--accent); + --color-accent-foreground: var(--accent-foreground); + --color-destructive: var(--destructive); + --color-destructive-foreground: var(--destructive-foreground); + --color-border: var(--border); + --color-input: var(--input); + --color-ring: var(--ring); + --color-chart-1: var(--chart-1); + --color-chart-2: var(--chart-2); + --color-chart-3: var(--chart-3); + --color-chart-4: var(--chart-4); + --color-chart-5: var(--chart-5); + --color-sidebar: var(--sidebar); + --color-sidebar-foreground: var(--sidebar-foreground); + --color-sidebar-primary: var(--sidebar-primary); + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); + --color-sidebar-accent: var(--sidebar-accent); + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); + --color-sidebar-border: var(--sidebar-border); + --color-sidebar-ring: var(--sidebar-ring); + + --font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + --font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif; + --radius-sm: calc(var(--radius) - 4px); --radius-md: calc(var(--radius) - 2px); --radius-lg: var(--radius); --radius-xl: calc(var(--radius) + 4px); - --font-serif: Source Serif 4, serif; - --radius: 0.375rem; + + --shadow-2xs: var(--shadow-2xs); + --shadow-xs: var(--shadow-xs); + --shadow-sm: var(--shadow-sm); + --shadow: var(--shadow); + --shadow-md: var(--shadow-md); + --shadow-lg: var(--shadow-lg); + --shadow-xl: var(--shadow-xl); + --shadow-2xl: var(--shadow-2xl); + --radius: 0.625rem; --tracking-tighter: calc(var(--tracking-normal) - 0.05em); --tracking-tight: calc(var(--tracking-normal) - 0.025em); --tracking-wide: calc(var(--tracking-normal) + 0.025em); --tracking-wider: calc(var(--tracking-normal) + 0.05em); --tracking-widest: calc(var(--tracking-normal) + 0.1em); --tracking-normal: var(--tracking-normal); - --shadow-2xl: var(--shadow-2xl); - --shadow-xl: var(--shadow-xl); - --shadow-lg: var(--shadow-lg); - --shadow-md: var(--shadow-md); - --shadow: var(--shadow); - --shadow-sm: var(--shadow-sm); - --shadow-xs: var(--shadow-xs); - --shadow-2xs: var(--shadow-2xs); --spacing: var(--spacing); --letter-spacing: var(--letter-spacing); --shadow-offset-y: var(--shadow-offset-y); @@ -65,118 +184,6 @@ --shadow-blur: var(--shadow-blur); --shadow-opacity: var(--shadow-opacity); --color-shadow-color: var(--shadow-color); - --color-destructive-foreground: var(--destructive-foreground); -} - -:root { - --radius: 0.375rem; - --background: oklch(1 0 0); - --foreground: oklch(0.2686 0 0); - --card: oklch(1 0 0); - --card-foreground: oklch(0.2686 0 0); - --popover: oklch(1 0 0); - --popover-foreground: oklch(0.2686 0 0); - --primary: oklch(0.7686 0.1647 70.0804); - --primary-foreground: oklch(0 0 0); - --secondary: oklch(0.967 0.0029 264.5419); - --secondary-foreground: oklch(0.4461 0.0263 256.8018); - --muted: oklch(0.9846 0.0017 247.8389); - --muted-foreground: oklch(0.551 0.0234 264.3637); - --accent: oklch(0.9869 0.0214 95.2774); - --accent-foreground: oklch(0.4732 0.1247 46.2007); - --destructive: oklch(0.6368 0.2078 25.3313); - --border: oklch(0.9276 0.0058 264.5313); - --input: oklch(0.9276 0.0058 264.5313); - --ring: oklch(0.7686 0.1647 70.0804); - --chart-1: oklch(0.7686 0.1647 70.0804); - --chart-2: oklch(0.6658 0.1574 58.3183); - --chart-3: oklch(0.5553 0.1455 48.9975); - --chart-4: oklch(0.4732 0.1247 46.2007); - --chart-5: oklch(0.4137 0.1054 45.9038); - --sidebar: oklch(0.9846 0.0017 247.8389); - --sidebar-foreground: oklch(0.2686 0 0); - --sidebar-primary: oklch(0.7686 0.1647 70.0804); - --sidebar-primary-foreground: oklch(1 0 0); - --sidebar-accent: oklch(0.9869 0.0214 95.2774); - --sidebar-accent-foreground: oklch(0.4732 0.1247 46.2007); - --sidebar-border: oklch(0.9276 0.0058 264.5313); - --sidebar-ring: oklch(0.7686 0.1647 70.0804); - --destructive-foreground: oklch(1 0 0); - --font-sans: Inter, sans-serif; - --font-serif: Source Serif 4, serif; - --font-mono: JetBrains Mono, monospace; - --shadow-color: hsl(0 0% 0%); - --shadow-opacity: 0.1; - --shadow-blur: 8px; - --shadow-spread: -1px; - --shadow-offset-x: 0px; - --shadow-offset-y: 4px; - --letter-spacing: 0em; - --spacing: 0.25rem; - --shadow-2xs: 0px 4px 8px -1px hsl(0 0% 0% / 0.05); - --shadow-xs: 0px 4px 8px -1px hsl(0 0% 0% / 0.05); - --shadow-sm: 0px 4px 8px -1px hsl(0 0% 0% / 0.1), 0px 1px 2px -2px hsl(0 0% 0% / 0.1); - --shadow: 0px 4px 8px -1px hsl(0 0% 0% / 0.1), 0px 1px 2px -2px hsl(0 0% 0% / 0.1); - --shadow-md: 0px 4px 8px -1px hsl(0 0% 0% / 0.1), 0px 2px 4px -2px hsl(0 0% 0% / 0.1); - --shadow-lg: 0px 4px 8px -1px hsl(0 0% 0% / 0.1), 0px 4px 6px -2px hsl(0 0% 0% / 0.1); - --shadow-xl: 0px 4px 8px -1px hsl(0 0% 0% / 0.1), 0px 8px 10px -2px hsl(0 0% 0% / 0.1); - --shadow-2xl: 0px 4px 8px -1px hsl(0 0% 0% / 0.25); - --tracking-normal: 0em; -} - -.dark { - --background: oklch(0.2046 0 0); - --foreground: oklch(0.9219 0 0); - --card: oklch(0.2686 0 0); - --card-foreground: oklch(0.9219 0 0); - --popover: oklch(0.2686 0 0); - --popover-foreground: oklch(0.9219 0 0); - --primary: oklch(0.7686 0.1647 70.0804); - --primary-foreground: oklch(0 0 0); - --secondary: oklch(0.2686 0 0); - --secondary-foreground: oklch(0.9219 0 0); - --muted: oklch(0.2686 0 0); - --muted-foreground: oklch(0.7155 0 0); - --accent: oklch(0.4732 0.1247 46.2007); - --accent-foreground: oklch(0.9243 0.1151 95.7459); - --destructive: oklch(0.6368 0.2078 25.3313); - --border: oklch(0.3715 0 0); - --input: oklch(0.3715 0 0); - --ring: oklch(0.7686 0.1647 70.0804); - --chart-1: oklch(0.8369 0.1644 84.4286); - --chart-2: oklch(0.6658 0.1574 58.3183); - --chart-3: oklch(0.4732 0.1247 46.2007); - --chart-4: oklch(0.5553 0.1455 48.9975); - --chart-5: oklch(0.4732 0.1247 46.2007); - --sidebar: oklch(0.1684 0 0); - --sidebar-foreground: oklch(0.9219 0 0); - --sidebar-primary: oklch(0.7686 0.1647 70.0804); - --sidebar-primary-foreground: oklch(1 0 0); - --sidebar-accent: oklch(0.4732 0.1247 46.2007); - --sidebar-accent-foreground: oklch(0.9243 0.1151 95.7459); - --sidebar-border: oklch(0.3715 0 0); - --sidebar-ring: oklch(0.7686 0.1647 70.0804); - --destructive-foreground: oklch(1 0 0); - --radius: 0.375rem; - --font-sans: Inter, sans-serif; - --font-serif: Source Serif 4, serif; - --font-mono: JetBrains Mono, monospace; - --shadow-color: hsl(0 0% 0%); - --shadow-opacity: 0.1; - --shadow-blur: 8px; - --shadow-spread: -1px; - --shadow-offset-x: 0px; - --shadow-offset-y: 4px; - --letter-spacing: 0em; - --spacing: 0.25rem; - --shadow-2xs: 0px 4px 8px -1px hsl(0 0% 0% / 0.05); - --shadow-xs: 0px 4px 8px -1px hsl(0 0% 0% / 0.05); - --shadow-sm: 0px 4px 8px -1px hsl(0 0% 0% / 0.1), 0px 1px 2px -2px hsl(0 0% 0% / 0.1); - --shadow: 0px 4px 8px -1px hsl(0 0% 0% / 0.1), 0px 1px 2px -2px hsl(0 0% 0% / 0.1); - --shadow-md: 0px 4px 8px -1px hsl(0 0% 0% / 0.1), 0px 2px 4px -2px hsl(0 0% 0% / 0.1); - --shadow-lg: 0px 4px 8px -1px hsl(0 0% 0% / 0.1), 0px 4px 6px -2px hsl(0 0% 0% / 0.1); - --shadow-xl: 0px 4px 8px -1px hsl(0 0% 0% / 0.1), 0px 8px 10px -2px hsl(0 0% 0% / 0.1); - --shadow-2xl: 0px 4px 8px -1px hsl(0 0% 0% / 0.25); } @layer base { @@ -190,4 +197,4 @@ .bg-brand { background-color: #1a292f; } -} +} \ No newline at end of file diff --git a/src/components/app-sidebar.tsx b/src/components/app-sidebar.tsx index 6e27ad0..ff3e156 100644 --- a/src/components/app-sidebar.tsx +++ b/src/components/app-sidebar.tsx @@ -5,6 +5,7 @@ import { Frame, GalleryVerticalEnd, HouseIcon, + SquareMousePointer, SquareTerminal, UsersIcon } from 'lucide-react'; @@ -47,7 +48,7 @@ const data = { { title: 'Servicos', url: '#', - icon: UsersIcon, + icon: SquareMousePointer, isActive: false, items: [ { @@ -177,6 +178,34 @@ const data = { title: 'Atos/Partes Tipos', url: '/administrativo/atos/partes-tipos', }, + { + title: "Valores de Serviços", + url: "/administrativo/valores-de-servicos", + }, + { + title: "Gramatica", + url: "/administrativo/gramatica", + }, + { + title: "Cartório", + url: "/administrativo/cartorio", + }, + { + title: "Financeiro/Periodo", + url: "/administrativo/financeiro/periodos", + }, + { + title: "Financeiro/Emolumentos", + url: "/administrativo/financeiro/emolumentos", + }, + { + title: "Selos/Grupos", + url: "/administrativo/selos/grupos", + }, + { + title: "Financeiro/Cálculo Rápido", + url: "/administrativo/financeiro/calculo-rapido", + } ], }, ], diff --git a/src/components/nav-user.tsx b/src/components/nav-user.tsx index 43ea768..3ba16be 100644 --- a/src/components/nav-user.tsx +++ b/src/components/nav-user.tsx @@ -1,6 +1,15 @@ 'use client'; -import { ChevronsUpDown, LogOut, Sparkles } from 'lucide-react'; +import { + ChevronsUpDown, + LogOut, + Moon, + Sparkles, + Sun, +} from 'lucide-react'; +import { useTheme } from 'next-themes'; +import { useCallback, useState } from 'react'; + import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'; import { DropdownMenu, @@ -17,11 +26,9 @@ import { SidebarMenuItem, useSidebar, } from '@/components/ui/sidebar'; - -import GUsuarioAuthenticatedInterface from '@/shared/interfaces/GUsuarioAuthenticatedInterface'; -import ConfirmDialog from '@/shared/components/confirmDialog/ConfirmDialog'; import { useGUsuarioLogoutHook } from '@/packages/administrativo/hooks/GUsuario/useGUsuarioLogoutHook'; -import { use, useCallback, useState } from 'react'; +import ConfirmDialog from '@/shared/components/confirmDialog/ConfirmDialog'; +import GUsuarioAuthenticatedInterface from '@/shared/interfaces/GUsuarioAuthenticatedInterface'; export function NavUser({ user }: { user: GUsuarioAuthenticatedInterface }) { // Hook para encerrar sessão @@ -32,19 +39,26 @@ export function NavUser({ user }: { user: GUsuarioAuthenticatedInterface }) { const { isMobile } = useSidebar(); - // Manipulação de formulário de confirmação - const handleConfirmOpen = useCallback(async () => { + // Tema (claro/escuro) - next-themes + const { theme, setTheme } = useTheme(); + const isDark = theme === 'dark'; + + const handleConfirmOpen = useCallback(() => { setIsConfirmOpen(true); }, []); - const handleLogoutConfirm = useCallback(async () => { + const handleLogoutConfirm = useCallback(() => { logoutUsuario(); - }, []); + }, [logoutUsuario]); - const handleLogoutCancel = useCallback(async () => { + const handleLogoutCancel = useCallback(() => { setIsConfirmOpen(false); }, []); + const handleToggleTheme = useCallback(() => { + setTheme(isDark ? 'light' : 'dark'); + }, [isDark, setTheme]); + if (!user) { return 'Carregando...'; } @@ -61,13 +75,13 @@ export function NavUser({ user }: { user: GUsuarioAuthenticatedInterface }) { > - - {user.sigla} + + {user.sigla} +
{user.nome} - {user.email}
@@ -85,13 +99,13 @@ export function NavUser({ user }: { user: GUsuarioAuthenticatedInterface }) {
- - {user.sigla} + + {user.sigla} +
{user.nome} - {user.email}
@@ -100,16 +114,32 @@ export function NavUser({ user }: { user: GUsuarioAuthenticatedInterface }) { + {/* Alternância de tema */} + + {isDark ? ( + + ) : ( + + )} + {isDark ? 'Modo claro' : 'Modo escuro'} + + - + Configurações - handleConfirmOpen()}> - + + Log out @@ -122,11 +152,11 @@ export function NavUser({ user }: { user: GUsuarioAuthenticatedInterface }) { isOpen={isConfirmOpen} title="Log-out" description="Atenção" - message={`Deseja realmente encerrar a sessão ? Dados não salvos serão perdidos`} + message="Deseja realmente encerrar a sessão? Dados não salvos serão perdidos." confirmText="Sim, sair" cancelText="Cancelar" - onConfirm={() => handleLogoutConfirm()} - onCancel={() => handleLogoutCancel()} + onConfirm={handleLogoutConfirm} + onCancel={handleLogoutCancel} /> ); diff --git a/src/components/theme-provider.tsx b/src/components/theme-provider.tsx new file mode 100644 index 0000000..58eee5b --- /dev/null +++ b/src/components/theme-provider.tsx @@ -0,0 +1,17 @@ +"use client"; + +import { ThemeProvider as NextThemesProvider } from "next-themes"; +import * as React from "react"; + +export function ThemeProvider({ children }: { children: React.ReactNode }) { + return ( + + {children} + + ); +} diff --git a/src/components/ui/button-group.tsx b/src/components/ui/button-group.tsx new file mode 100644 index 0000000..8600af0 --- /dev/null +++ b/src/components/ui/button-group.tsx @@ -0,0 +1,83 @@ +import { Slot } from "@radix-ui/react-slot" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" +import { Separator } from "@/components/ui/separator" + +const buttonGroupVariants = cva( + "flex w-fit items-stretch [&>*]:focus-visible:z-10 [&>*]:focus-visible:relative [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md has-[>[data-slot=button-group]]:gap-2", + { + variants: { + orientation: { + horizontal: + "[&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none", + vertical: + "flex-col [&>*:not(:first-child)]:rounded-t-none [&>*:not(:first-child)]:border-t-0 [&>*:not(:last-child)]:rounded-b-none", + }, + }, + defaultVariants: { + orientation: "horizontal", + }, + } +) + +function ButtonGroup({ + className, + orientation, + ...props +}: React.ComponentProps<"div"> & VariantProps) { + return ( +
+ ) +} + +function ButtonGroupText({ + className, + asChild = false, + ...props +}: React.ComponentProps<"div"> & { + asChild?: boolean +}) { + const Comp = asChild ? Slot : "div" + + return ( + + ) +} + +function ButtonGroupSeparator({ + className, + orientation = "vertical", + ...props +}: React.ComponentProps) { + return ( + + ) +} + +export { + ButtonGroup, + ButtonGroupSeparator, + ButtonGroupText, + buttonGroupVariants, +} diff --git a/src/components/ui/item.tsx b/src/components/ui/item.tsx new file mode 100644 index 0000000..d97de21 --- /dev/null +++ b/src/components/ui/item.tsx @@ -0,0 +1,193 @@ +import * as React from "react" +import { Slot } from "@radix-ui/react-slot" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" +import { Separator } from "@/components/ui/separator" + +function ItemGroup({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function ItemSeparator({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +const itemVariants = cva( + "group/item flex items-center border border-transparent text-sm rounded-md transition-colors [a]:hover:bg-accent/50 [a]:transition-colors duration-100 flex-wrap outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]", + { + variants: { + variant: { + default: "bg-transparent", + outline: "border-border", + muted: "bg-muted/50", + }, + size: { + default: "p-4 gap-4 ", + sm: "py-3 px-4 gap-2.5", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + } +) + +function Item({ + className, + variant = "default", + size = "default", + asChild = false, + ...props +}: React.ComponentProps<"div"> & + VariantProps & { asChild?: boolean }) { + const Comp = asChild ? Slot : "div" + return ( + + ) +} + +const itemMediaVariants = cva( + "flex shrink-0 items-center justify-center gap-2 group-has-[[data-slot=item-description]]/item:self-start [&_svg]:pointer-events-none group-has-[[data-slot=item-description]]/item:translate-y-0.5", + { + variants: { + variant: { + default: "bg-transparent", + icon: "size-8 border rounded-sm bg-muted [&_svg:not([class*='size-'])]:size-4", + image: + "size-10 rounded-sm overflow-hidden [&_img]:size-full [&_img]:object-cover", + }, + }, + defaultVariants: { + variant: "default", + }, + } +) + +function ItemMedia({ + className, + variant = "default", + ...props +}: React.ComponentProps<"div"> & VariantProps) { + return ( +
+ ) +} + +function ItemContent({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function ItemTitle({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function ItemDescription({ className, ...props }: React.ComponentProps<"p">) { + return ( +

a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4", + className + )} + {...props} + /> + ) +} + +function ItemActions({ className, ...props }: React.ComponentProps<"div">) { + return ( +

+ ) +} + +function ItemHeader({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function ItemFooter({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +export { + Item, + ItemMedia, + ItemContent, + ItemActions, + ItemGroup, + ItemSeparator, + ItemTitle, + ItemDescription, + ItemHeader, + ItemFooter, +} diff --git a/src/components/ui/separator.tsx b/src/components/ui/separator.tsx index 4e528b9..275381c 100644 --- a/src/components/ui/separator.tsx +++ b/src/components/ui/separator.tsx @@ -1,13 +1,13 @@ -'use client'; +"use client" -import * as React from 'react'; -import * as SeparatorPrimitive from '@radix-ui/react-separator'; +import * as React from "react" +import * as SeparatorPrimitive from "@radix-ui/react-separator" -import { cn } from '@/lib/utils'; +import { cn } from "@/lib/utils" function Separator({ className, - orientation = 'horizontal', + orientation = "horizontal", decorative = true, ...props }: React.ComponentProps) { @@ -17,12 +17,12 @@ function Separator({ decorative={decorative} orientation={orientation} className={cn( - 'bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px', - className, + "bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px", + className )} {...props} /> - ); + ) } -export { Separator }; +export { Separator } diff --git a/src/components/ui/sidebar.tsx b/src/components/ui/sidebar.tsx index d3d8082..79449af 100644 --- a/src/components/ui/sidebar.tsx +++ b/src/components/ui/sidebar.tsx @@ -1,12 +1,10 @@ 'use client'; -import * as React from 'react'; import { Slot } from '@radix-ui/react-slot'; import { cva, VariantProps } from 'class-variance-authority'; import { PanelLeftIcon } from 'lucide-react'; +import * as React from 'react'; -import { useIsMobile } from '@/hooks/use-mobile'; -import { cn } from '@/lib/utils'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Separator } from '@/components/ui/separator'; @@ -19,6 +17,8 @@ import { } from '@/components/ui/sheet'; import { Skeleton } from '@/components/ui/skeleton'; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'; +import { useIsMobile } from '@/hooks/use-mobile'; +import { cn } from '@/lib/utils'; const SIDEBAR_COOKIE_NAME = 'sidebar_state'; const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7; @@ -548,7 +548,7 @@ function SidebarMenuAction({ 'peer-data-[size=lg]/menu-button:top-2.5', 'group-data-[collapsible=icon]:hidden', showOnHover && - 'peer-data-[active=true]/menu-button:text-sidebar-accent-foreground group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 md:opacity-0', + 'peer-data-[active=true]/menu-button:text-sidebar-accent-foreground group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 md:opacity-0', className, )} {...props} @@ -690,5 +690,6 @@ export { SidebarRail, SidebarSeparator, SidebarTrigger, - useSidebar, + useSidebar }; + diff --git a/src/packages/administrativo/components/GEmolumento/GEmolumentoSelect.tsx b/src/packages/administrativo/components/GEmolumento/GEmolumentoSelect.tsx index 7c7a4cf..a5ebcd4 100644 --- a/src/packages/administrativo/components/GEmolumento/GEmolumentoSelect.tsx +++ b/src/packages/administrativo/components/GEmolumento/GEmolumentoSelect.tsx @@ -3,6 +3,20 @@ import { CheckIcon, ChevronsUpDownIcon } from 'lucide-react'; import React from 'react'; +import { useGEmolumentoReadHook } from '@/app/(protected)/(cadastros)/cadastros/_hooks/g_emolumento/useGEmolumentoReadHook'; +import { GEmolumentoReadInterface } from '@/app/(protected)/(cadastros)/cadastros/_interfaces/GEmolumentoReadInterface'; +import { Button } from '@/components/ui/button'; +import { + Command, + CommandEmpty, + CommandGroup, + CommandInput, + CommandItem, + CommandList, + +import { CheckIcon, ChevronsUpDownIcon } from 'lucide-react'; +import React from 'react'; + import { useGEmolumentoReadHook } from '@/app/(protected)/(cadastros)/cadastros/_hooks/g_emolumento/useGEmolumentoReadHook'; import { GEmolumentoReadInterface } from '@/app/(protected)/(cadastros)/cadastros/_interfaces/GEmolumentoReadInterface'; import { Button } from '@/components/ui/button'; @@ -154,4 +168,28 @@ export default function GEmolumentoSelect({ ); + // Fecha o popover + setOpen(false); +}} + > + {/* Ícone de seleção (check) */ } + < CheckIcon +className = { + cn( + 'mr-2 h-4 w-4', + String(field.value?.key ?? field.value) === String(item.emolumento_id) + ? 'opacity-100' + : 'opacity-0', + )} + /> +{/* Nome formatado do emolumento */ } +{ GetCapitalize(item.descricao) } + + ))} + + + + + + ); } diff --git a/src/packages/administrativo/components/GEmolumento/GEmolumentoServicoSelect.tsx b/src/packages/administrativo/components/GEmolumento/GEmolumentoServicoSelect.tsx new file mode 100644 index 0000000..bf7a479 --- /dev/null +++ b/src/packages/administrativo/components/GEmolumento/GEmolumentoServicoSelect.tsx @@ -0,0 +1,151 @@ +'use client'; + +import { CheckIcon, ChevronsUpDownIcon } from 'lucide-react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; + +import { useGEmolumentoReadHook } from '@/app/(protected)/(cadastros)/cadastros/_hooks/g_emolumento/useGEmolumentoReadHook'; +import { GEmolumentoReadInterface } from '@/app/(protected)/(cadastros)/cadastros/_interfaces/GEmolumentoReadInterface'; +import { Button } from '@/components/ui/button'; +import { + Command, + CommandEmpty, + CommandGroup, + CommandInput, + CommandItem, + CommandList, +} from '@/components/ui/command'; +import { FormControl } from '@/components/ui/form'; +import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'; +import { cn } from '@/lib/utils'; +import GetCapitalize from '@/shared/actions/text/GetCapitalize'; + +// Tipagem das props do componente +interface GEmolumentoSelectProps { + sistema_id: number; + field: any; + onSelectChange?: (emolumento: { emolumento_id: number; descricao: string }) => void; + className?: string; +} + +// Componente principal do select de emolumentos +export default function GEmolumentoServicoSelect({ + sistema_id, + field, + onSelectChange, + className, +}: GEmolumentoSelectProps) { + const [open, setOpen] = useState(false); + const [isLoading, setIsLoading] = useState(false); + + // Define parâmetros de leitura para o hook que busca os emolumentos + const gEmolumentoReadParams: GEmolumentoReadInterface = { sistema_id, urlParams: { situacao: 'A' } }; + const { gEmolumento = [], fetchGEmolumento } = useGEmolumentoReadHook(); + + /** + * Efeito para buscar os dados apenas uma vez. + */ + const loadData = useCallback(async () => { + if (gEmolumento.length) return; + setIsLoading(true); + await fetchGEmolumento(gEmolumentoReadParams); + setIsLoading(false); + }, [gEmolumento.length, fetchGEmolumento, gEmolumentoReadParams]); + + useEffect(() => { + loadData(); + }, [loadData]); + + /** + * Memoriza o item selecionado para evitar reprocessamentos. + */ + const selected = useMemo( + () => + gEmolumento.find( + (item) => String(item.emolumento_id) === String(field?.value?.id ?? ''), + ), + [gEmolumento, field?.value], + ); + + /** + * Manipulador de seleção com verificação segura. + */ + const handleSelect = useCallback( + (item: any) => { + if (!field?.onChange) return; + + const selectedValue = { + emolumento_id: Number(item.emolumento_id), + descricao: item.descricao, + sistema_id: item.sistema_id, + }; + + field.onChange(selectedValue); + + if (onSelectChange) onSelectChange(selectedValue); + + setOpen(false); + }, + [field, onSelectChange], + ); + + return ( + + + + + + + + + + + + + {isLoading ? 'Carregando...' : 'Nenhum resultado encontrado.'} + + + {gEmolumento.map((item) => ( + handleSelect(item)} + > + + {GetCapitalize(item.descricao ?? '')} + + ))} + + + + + + ); +} diff --git a/src/packages/administrativo/components/GGramatica/GGramaticaForm.tsx b/src/packages/administrativo/components/GGramatica/GGramaticaForm.tsx index 25bfa17..b9710c3 100644 --- a/src/packages/administrativo/components/GGramatica/GGramaticaForm.tsx +++ b/src/packages/administrativo/components/GGramatica/GGramaticaForm.tsx @@ -1,6 +1,6 @@ 'use client'; -import React, { useEffect } from 'react'; +import { useEffect } from 'react'; import { Button } from '@/components/ui/button'; import { diff --git a/src/packages/administrativo/components/GGramatica/GGramaticaIndex.tsx b/src/packages/administrativo/components/GGramatica/GGramaticaIndex.tsx index be6e005..e4be82b 100644 --- a/src/packages/administrativo/components/GGramatica/GGramaticaIndex.tsx +++ b/src/packages/administrativo/components/GGramatica/GGramaticaIndex.tsx @@ -1,6 +1,6 @@ 'use client'; -import { useEffect, useState, useCallback } from 'react'; +import { useCallback, useEffect, useState } from 'react'; import { useGGramaticaDeleteHook } from '@/packages/administrativo/hooks/GGramatica/useGGramaticaDeleteHook'; diff --git a/src/packages/administrativo/components/GGramatica/GGramaticaTable.tsx b/src/packages/administrativo/components/GGramatica/GGramaticaTable.tsx index 648ccaf..58295e9 100644 --- a/src/packages/administrativo/components/GGramatica/GGramaticaTable.tsx +++ b/src/packages/administrativo/components/GGramatica/GGramaticaTable.tsx @@ -2,8 +2,8 @@ import { DataTable } from '@/shared/components/dataTable/DataTable'; -import GGramaticaColumns from './GGramaticaColumns'; import GGramaticaTableInterface from '../../interfaces/GGramatica/GGramaticaTableInterface'; +import GGramaticaColumns from './GGramaticaColumns'; /** * Componente principal da tabela de Naturezas diff --git a/src/packages/administrativo/components/GUsuario/GUsuarioSelect.tsx b/src/packages/administrativo/components/GUsuario/GUsuarioSelect.tsx new file mode 100644 index 0000000..ee5d466 --- /dev/null +++ b/src/packages/administrativo/components/GUsuario/GUsuarioSelect.tsx @@ -0,0 +1,125 @@ +'use client'; + +import { CheckIcon, ChevronsUpDownIcon } from 'lucide-react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; + +import { Button } from '@/components/ui/button'; +import { + Command, + CommandEmpty, + CommandGroup, + CommandInput, + CommandItem, + CommandList, +} from '@/components/ui/command'; +import { FormControl } from '@/components/ui/form'; +import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'; +import { cn } from '@/lib/utils'; +import { useGUsuarioIndexHook } from '@/packages/administrativo/hooks/GUsuario/useGUsuarioIndexHook'; +import GUsuarioSelectInterface from '@/packages/administrativo/interfaces/GUsuario/GUsuarioSelectInterface'; +import GetCapitalize from '@/shared/actions/text/GetCapitalize'; + +import GUsuarioIndexInterface from '../../interfaces/GUsuario/GusuarioIndexInterface'; + +export default function GUsuarioSelect({ field }: GUsuarioSelectInterface) { + const [open, setOpen] = useState(false); + const [isLoading, setIsLoading] = useState(false); + const { usuarios, fetchUsuarios } = useGUsuarioIndexHook(); + + /** + * Efeito para buscar os dados apenas uma vez. + * useCallback evita recriação desnecessária da função. + */ + const loadData = useCallback(async () => { + + const urlParams = { + assina: 'S', + situacao: 'A' + } + + const GUsuarioIndex: GUsuarioIndexInterface = { + urlParams: urlParams + } + + if (usuarios?.length) return; + setIsLoading(true); + await fetchUsuarios(GUsuarioIndex); + setIsLoading(false); + }, [usuarios?.length, fetchUsuarios]); + + useEffect(() => { + loadData(); + }, [loadData]); + + /** + * Memoriza o bairro selecionado para evitar reprocessamentos. + */ + const selected = useMemo( + () => usuarios?.find((b) => String(b.usuario_id) === String(field?.value ?? '')), + [usuarios, field?.value], + ); + + /** + * Manipulador de seleção com verificação segura. + */ + const handleSelect = useCallback( + (bairroId: string | number) => { + if (!field?.onChange) return; + field.onChange(bairroId); + setOpen(false); + }, + [field], + ); + + return ( + + + + + + + + + + + + {isLoading ? 'Carregando...' : 'Nenhum resultado encontrado.'} + + + {usuarios?.map((item) => ( + handleSelect(item.usuario_id)} + > + + {GetCapitalize(item.nome_completo ?? '')} + + ))} + + + + + + ); +} diff --git a/src/packages/administrativo/components/TPessoa/TPessoaJuridica/TPessoaJuridicaForm.tsx b/src/packages/administrativo/components/TPessoa/TPessoaJuridica/TPessoaJuridicaForm.tsx index 93d9eb8..487f696 100644 --- a/src/packages/administrativo/components/TPessoa/TPessoaJuridica/TPessoaJuridicaForm.tsx +++ b/src/packages/administrativo/components/TPessoa/TPessoaJuridica/TPessoaJuridicaForm.tsx @@ -1,7 +1,7 @@ 'use client'; import { HouseIcon, IdCardIcon, UserIcon } from 'lucide-react'; -import React, { useEffect } from 'react'; +import { useEffect } from 'react'; import { Button } from '@/components/ui/button'; import { diff --git a/src/packages/administrativo/components/TPessoa/TPessoaTableFormColumnsDialog.tsx b/src/packages/administrativo/components/TPessoa/TPessoaTableFormColumnsDialog.tsx new file mode 100644 index 0000000..0c13af2 --- /dev/null +++ b/src/packages/administrativo/components/TPessoa/TPessoaTableFormColumnsDialog.tsx @@ -0,0 +1,161 @@ +import { ColumnDef } from '@tanstack/react-table'; +import { ArrowUpDownIcon } from 'lucide-react'; + +import { Button } from '@/components/ui/button'; +import { Checkbox } from '@/components/ui/checkbox'; +import { FormatCPF } from '@/shared/actions/CPF/FormatCPF'; +import { FormatDateTime } from '@/shared/actions/dateTime/FormatDateTime'; +import { FormatPhone } from '@/shared/actions/phone/FormatPhone'; +import GetNameInitials from '@/shared/actions/text/GetNameInitials'; +import empty from '@/shared/actions/validations/empty'; + +import TPessoaInterface from '../../interfaces/TPessoa/TPessoaInterface'; + +/** + * Função para criar a definição das colunas da tabela + */ +export function TPessoaTableFormColumnsDialog(setSelectedTPessoa: React.Dispatch>): ColumnDef[] { + return [ + { + id: 'select', + header: '', + cell: ({ row, table }) => ( + { + // Limpa todas as seleções antes de selecionar uma nova + table.resetRowSelection(); + row.toggleSelected(!!value); + setSelectedTPessoa(value ? row.original : null); + }} + aria-label="Select row" + /> + ), + enableSorting: false, + enableHiding: false, + }, + // ID + { + accessorKey: 'pessoa_id', + header: ({ column }) => ( + + ), + cell: ({ row }) => Number(row.getValue('pessoa_id')), + enableSorting: false, + }, + + // Nome / Email / Foto + { + id: 'nome_completo', + accessorFn: (row) => row, + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const pessoa = row.original; + + return ( +
+ {/* Foto ou Iniciais */} +
+ {pessoa.foto ? ( + {pessoa.nome + ) : ( + + {GetNameInitials(pessoa.nome)} + + )} +
+ + {/* Nome e Email */} +
+
{pessoa.nome || '-'}
+
+ {empty(pessoa.email) ? 'Email não informado' : pessoa.email} +
+
+
+ ); + }, + sortingFn: (a, b) => + (a.original.nome?.toLowerCase() || '').localeCompare(b.original.nome?.toLowerCase() || ''), + }, + + // CPF + { + accessorKey: 'cpf_cnpj', + header: ({ column }) => ( + + ), + cell: ({ row }) => FormatCPF(row.getValue('cpf_cnpj')), + }, + + // Telefone + { + accessorKey: 'telefone', + header: ({ column }) => ( + + ), + cell: ({ row }) => FormatPhone(row.getValue('telefone')), + }, + + // Cidade / UF + { + id: 'cidade_uf', + accessorFn: (row) => `${row.cidade}/${row.uf}`, + header: ({ column }) => ( + + ), + cell: ({ row }) => {row.getValue('cidade_uf') || '-'}, + sortingFn: (a, b) => + `${a.original.cidade}/${a.original.uf}` + .toLowerCase() + .localeCompare(`${b.original.cidade}/${b.original.uf}`.toLowerCase()), + }, + + // Data de cadastro + { + accessorKey: 'data_cadastro', + header: ({ column }) => ( + + ), + cell: ({ row }) => FormatDateTime(row.getValue('data_cadastro')), + sortingFn: 'datetime', + }, + + ]; +} diff --git a/src/packages/administrativo/components/TPessoa/TPessoaTableFormDialog.tsx b/src/packages/administrativo/components/TPessoa/TPessoaTableFormDialog.tsx new file mode 100644 index 0000000..a318a2f --- /dev/null +++ b/src/packages/administrativo/components/TPessoa/TPessoaTableFormDialog.tsx @@ -0,0 +1,128 @@ +'use client'; + +import { useEffect, useState } from 'react'; + +import { Button } from '@/components/ui/button'; +import { + Dialog, + DialogClose, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle +} from '@/components/ui/dialog'; +import { useTPessoaFisicaIndexHook } from '@/packages/administrativo/hooks/TPessoa/TPessoaFisica/useTPessoaFisicaIndexHook'; +import { useTPessoaJuridicaIndexHook } from '@/packages/administrativo/hooks/TPessoa/TPessoaJuridica/useTPessoaJuridicaIndexHook'; +import TPessoaInterface from '@/packages/administrativo/interfaces/TPessoa/TPessoaInterface'; +import TPessoaTableFormInterface from '@/packages/administrativo/interfaces/TPessoa/TPessoaTableFormInterface'; +import { DataTable } from '@/shared/components/dataTable/DataTable'; +import LoadingButton from '@/shared/components/loadingButton/LoadingButton'; + +import { TPessoaTableFormColumnsDialog } from './TPessoaTableFormColumnsDialog'; + +export default function TPessoaTableFormDialog({ + isOpen, + tipoPessoa, + onClose, + onSave, + buttonIsLoading, +}: TPessoaTableFormInterface) { + + const { tPessoaFisica, fetchTPessoaFisica } = useTPessoaFisicaIndexHook(); + const { tPessoaJuridica, fetchTPessoaJuridica } = useTPessoaJuridicaIndexHook(); + const [pessoas, setPessoas] = useState() + const [selectedTPessoa, setSelectedTPessoa] = useState(null); + + // Executa o Hook de Acordo com o tipo de pessoa informado + const loadData = async (tipoPessoa: string) => { + + switch (tipoPessoa) { + + case "F": + + await fetchTPessoaFisica(); + break; + + case "J": + + await fetchTPessoaJuridica(); + break; + + } + + }; + + // Atualiza a variavel de pessoa quando tiver alteração na variavel de pessoas fisicas + useEffect(() => { + + setPessoas(tPessoaFisica) + + }, [tPessoaFisica]) + + // Atualiza a variavel de pessoa quando tiver alteração na variavel de pessoas juridicas + useEffect(() => { + + setPessoas(tPessoaJuridica) + + }, [tPessoaJuridica]) + + // Executa o hook correspondente ao tipo de pessoa, sempre que o tipo pessoa mudar + useEffect(() => { + + // Verifica se o tipo pessoa esta preenchido + if (tipoPessoa) { + + // Dispara o carregamento de informações + loadData(tipoPessoa); + + } + + }, [tipoPessoa]); + + const columns = TPessoaTableFormColumnsDialog(setSelectedTPessoa); + + return ( + { + if (!open) onClose(null, false); + }} + > + + + Pessoa + Busque a pessoa desejada + +
+ +
+ {/* Rodapé do Dialog */} + + + + + { onSave(selectedTPessoa); onClose(null, false); }} + /> + +
+
+ ); +} diff --git a/src/packages/administrativo/components/TPessoa/TPessoaTableFormSubview.tsx b/src/packages/administrativo/components/TPessoa/TPessoaTableFormSubview.tsx new file mode 100644 index 0000000..367b213 --- /dev/null +++ b/src/packages/administrativo/components/TPessoa/TPessoaTableFormSubview.tsx @@ -0,0 +1,129 @@ +import { FingerprintIcon, WebcamIcon } from 'lucide-react'; +import { + memo, + useCallback, + useMemo, + useState +} from 'react'; + +import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'; +import { Button } from '@/components/ui/button'; +import { + Item, + ItemActions, + ItemContent, + ItemDescription, + ItemMedia, + ItemTitle +} from '@/components/ui/item'; +import TPessoaCartaoForm from '@/packages/servicos/components/TPessoaCartao/TPessoaCartaoForm'; +import GetNameInitials from '@/shared/actions/text/GetNameInitials'; +import WebCamDialog from '@/shared/components/webcam/WebCamDialog'; +import { useFingerTechCaptureHook } from '@/shared/hooks/FingerTech/useFingerTechCaptureHook'; + +import TPessoaTableFormSubviewInterface from '../../interfaces/TPessoa/TPessoaTableFormSubviewInterface'; + +function TPessoaTableFormSubview({ + item_index, + data, + params, + form, +}: TPessoaTableFormSubviewInterface) { + + const [isWebCamOpenDialog, setIsWebCamOpenDialog] = useState(false) + const { base64, captureFingerTech } = useFingerTechCaptureHook(); + + // Chama o leitor biométrico + const handleBiometria = useCallback(() => { + + console.log(captureFingerTech()) + + }, []) + + // Define a classe do botão de biometria com base no status, sem estado extra + const biometriaButtonClass = useMemo(() => { + switch (1) { + case 0: + // Amarelo (aviso) + return 'bg-amber-100 text-amber-700 border border-amber-300 hover:bg-amber-200 hover:text-amber-800'; + case 1: + // Verde discreto + return 'bg-green-100 text-green-700 border border-green-300 hover:bg-green-200 hover:text-green-800'; + case 2: + // Vermelho (erro) + return 'bg-red-100 text-red-700 border border-red-300 hover:bg-red-200 hover:text-red-800'; + default: + return ''; + } + }, []); + + return ( +
+ + + + + + {GetNameInitials(data.pessoa?.nome)} + + + + + + {data.pessoa?.cpf_cnpj} - {data.pessoa?.nome} + + + {data.pessoa?.email || 'Email não informado'} + + {params + .filter((param) => Number(param.valor) === data.servico.servico_tipo_id) + .map((param) => ( + + ))} + + + + {data.servico.requer_biometria === 'S' && ( + + )} + {data.servico.requer_biometria && ( + + )} + + + {isWebCamOpenDialog && ( + { setIsWebCamOpenDialog(false) }} + onSave={() => { }} + key={item_index} + /> + )} +
+ ); +} + +// Memo para evitar re-renderizações desnecessárias da subview +export default memo(TPessoaTableFormSubview); \ No newline at end of file diff --git a/src/packages/administrativo/components/TPessoaRepresentante/TPessoaRepresentanteForm.tsx b/src/packages/administrativo/components/TPessoaRepresentante/TPessoaRepresentanteForm.tsx index a8ddf69..9bb39c6 100644 --- a/src/packages/administrativo/components/TPessoaRepresentante/TPessoaRepresentanteForm.tsx +++ b/src/packages/administrativo/components/TPessoaRepresentante/TPessoaRepresentanteForm.tsx @@ -1,6 +1,6 @@ 'use client'; -import React, { useEffect, useState } from 'react'; +import { useEffect, useState } from 'react'; import { Button } from '@/components/ui/button'; import { @@ -17,11 +17,11 @@ import { ResetFormIfData } from '@/shared/actions/form/ResetFormIfData'; import { DataTable } from '@/shared/components/dataTable/DataTable'; import LoadingButton from '@/shared/components/loadingButton/LoadingButton'; -import TPessoasRepresentanteFormColumns from './TPessoasRepresentanteFormColumns'; import { useTPessoaFisicaIndexHook } from '../../hooks/TPessoa/TPessoaFisica/useTPessoaFisicaIndexHook'; import { useTPessoaRepresentanteFormHook } from '../../hooks/TPessoaRepresentante/useTPessoaRepresentanteFormHook'; import TPessoaRepresentanteInterface from '../../interfaces/TPessoaRepresentante/TPessoaRepresentanteInterface'; import TPessoaRepresentanteFormInterface from '../../interfaces/TPessoaRepresentante/TPessoaRepresentnateFormInterface'; +import TPessoasRepresentanteFormColumns from './TPessoasRepresentanteFormColumns'; export default function TPessoaRepresentanteForm({ isOpen, diff --git a/src/packages/administrativo/components/TServicoTipo/TServicoTipoSelect.tsx b/src/packages/administrativo/components/TServicoTipo/TServicoTipoSelect.tsx new file mode 100644 index 0000000..232b308 --- /dev/null +++ b/src/packages/administrativo/components/TServicoTipo/TServicoTipoSelect.tsx @@ -0,0 +1,138 @@ +'use client'; + +import { CheckIcon, ChevronsUpDownIcon } from 'lucide-react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; + +import { Button } from '@/components/ui/button'; +import { + Command, + CommandEmpty, + CommandGroup, + CommandInput, + CommandItem, + CommandList, +} from '@/components/ui/command'; +import { FormControl } from '@/components/ui/form'; +import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'; +import { cn } from '@/lib/utils'; +import { useTServicoTipoReadHook } from '@/packages/administrativo/hooks/TServicoTipo/useTServicoTipoReadHook'; +import TServicoTipoSelectInterface from '@/packages/administrativo/interfaces/TServicoTipo/TServicoTipoSelectInterface'; +import GetCapitalize from '@/shared/actions/text/GetCapitalize'; + +import TServicoTipoIndexInteface from '../../interfaces/TServicoTipo/TServicoTipoIndexInteface'; + +export default function TServicoTipoSelect({ field }: TServicoTipoSelectInterface) { + const [open, setOpen] = useState(false); + const [isLoading, setIsLoading] = useState(false); + const { tServicoTipo = [], fetchTServicoTipo } = useTServicoTipoReadHook(); + + /** + * Efeito para buscar os dados apenas uma vez. + */ + const loadData = useCallback(async () => { + + const TServicoTipoIndex: TServicoTipoIndexInteface = { + urlParams: { + situacao: 'A' + } + } + + if (tServicoTipo.length) return; + setIsLoading(true); + await fetchTServicoTipo(TServicoTipoIndex); + setIsLoading(false); + }, [tServicoTipo.length, fetchTServicoTipo]); + + useEffect(() => { + loadData(); + }, [loadData]); + + /** + * Item selecionado (comparando por ID) + */ + const selected = useMemo( + () => + tServicoTipo.find( + (item) => String(item.servico_tipo_id) === String(field?.value?.servico_tipo_id ?? ''), + ), + [tServicoTipo, field?.value], + ); + + /** + * Manipulador de seleção + */ + const handleSelect = useCallback( + (item: any) => { + if (!field?.onChange) return; + + const selectedValue = { + servico_tipo_id: Number(item.servico_tipo_id), + descricao: item.descricao, + tipo_item: item.tipo_item, + tipo_pessoa: item.tipo_pessoa, + requer_biometria: item.requer_biometria, + requer_cpf: item.requer_cpf, + servico_caixa_id: item.servico_caixa_id, + selar: item.selar, + }; + + field.onChange(selectedValue); + setOpen(false); + }, + [field], + ); + + return ( + + + + + + + + + + + + + {isLoading ? 'Carregando...' : 'Nenhum resultado encontrado.'} + + + {tServicoTipo.map((item) => ( + handleSelect(item)} + > + + {GetCapitalize(item.descricao ?? '')} + + ))} + + + + + + ); +} diff --git a/src/packages/administrativo/data/GCalculo/GCalculoServicoData.ts b/src/packages/administrativo/data/GCalculo/GCalculoServicoData.ts new file mode 100644 index 0000000..fe803f7 --- /dev/null +++ b/src/packages/administrativo/data/GCalculo/GCalculoServicoData.ts @@ -0,0 +1,17 @@ +import GCalculoInterface from '@/packages/administrativo/interfaces/GCalculo/GCalculoInterface'; +import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; +import API from '@/shared/services/api/Api'; +import { Methods } from '@/shared/services/api/enums/ApiMethodEnum'; +import ApiResponseInterface from '@/shared/services/api/interfaces/ApiResponseInterface'; + + +async function executeGCalculoCalcularData(data: GCalculoInterface): Promise { + const api = new API(); + return api.send({ + method: Methods.POST, + endpoint: `administrativo/g_calculo/servico/`, + body: data, + }); +} + +export const GCalculoServico = withClientErrorHandler(executeGCalculoCalcularData); diff --git a/src/packages/administrativo/data/GUsuario/GUsuarioIndexData.ts b/src/packages/administrativo/data/GUsuario/GUsuarioIndexData.ts index 1d0ceba..d5d1b99 100644 --- a/src/packages/administrativo/data/GUsuario/GUsuarioIndexData.ts +++ b/src/packages/administrativo/data/GUsuario/GUsuarioIndexData.ts @@ -3,13 +3,17 @@ import API from '@/shared/services/api/Api'; import { Methods } from '@/shared/services/api/enums/ApiMethodEnum'; -export default async function GUsuarioIndexData() { +import GUsuarioIndexInterface from '../../interfaces/GUsuario/GusuarioIndexInterface'; + +export default async function GUsuarioIndexData(data: GUsuarioIndexInterface) { const api = new API(); const response = await api.send({ method: Methods.GET, - endpoint: `administrativo/g_usuario/`, + endpoint: `administrativo/g_usuario?${new URLSearchParams(data.urlParams).toString()}`, }); + console.log(response) + return response; } diff --git a/src/app/(protected)/(cadastros)/cadastros/_data/TServicoTipo/TServicoTipoEditData.ts b/src/packages/administrativo/data/TServicoTipo/TServicoTipoEditData.ts similarity index 89% rename from src/app/(protected)/(cadastros)/cadastros/_data/TServicoTipo/TServicoTipoEditData.ts rename to src/packages/administrativo/data/TServicoTipo/TServicoTipoEditData.ts index ab2d56d..d08b582 100644 --- a/src/app/(protected)/(cadastros)/cadastros/_data/TServicoTipo/TServicoTipoEditData.ts +++ b/src/packages/administrativo/data/TServicoTipo/TServicoTipoEditData.ts @@ -5,7 +5,7 @@ import API from '@/shared/services/api/Api'; // import { Methods } from '@/shared/services/api/enums/ApiMethodEnum'; // // Importa a interface tipada que define a estrutura dos dados do tipo de serviço -import TServicoTipoInterface from '../../_interfaces/TServicoTipoInterface'; // Alterado de GCidadeInterface +import TServicoTipoInterface from '../../../../app/(protected)/(cadastros)/cadastros/_interfaces/TServicoTipoInterface'; // Alterado de GCidadeInterface // Importa função que encapsula chamadas assíncronas e trata erros automaticamente import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; // diff --git a/src/app/(protected)/(cadastros)/cadastros/_data/TServicoTipo/TServicoTipoIndexData.ts b/src/packages/administrativo/data/TServicoTipo/TServicoTipoIndexData.ts similarity index 72% rename from src/app/(protected)/(cadastros)/cadastros/_data/TServicoTipo/TServicoTipoIndexData.ts rename to src/packages/administrativo/data/TServicoTipo/TServicoTipoIndexData.ts index 7003e6e..3aadff7 100644 --- a/src/app/(protected)/(cadastros)/cadastros/_data/TServicoTipo/TServicoTipoIndexData.ts +++ b/src/packages/administrativo/data/TServicoTipo/TServicoTipoIndexData.ts @@ -1,21 +1,23 @@ // Importa o serviço de API que será utilizado para realizar requisições HTTP -import API from '@/shared/services/api/Api'; // +import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; +import API from '@/shared/services/api/Api'; // Importa o enum que contém os métodos HTTP disponíveis (GET, POST, PUT, DELETE) import { Methods } from '@/shared/services/api/enums/ApiMethodEnum'; // +import TServicoTipoIndexInteface from '../../interfaces/TServicoTipo/TServicoTipoIndexInteface'; + // Importa função que encapsula chamadas assíncronas e trata erros automaticamente -import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; // // Função assíncrona que implementa a lógica de buscar todos os tipos de serviço (GET) -async function executeTServicoTipoIndexData() { +async function executeTServicoTipoIndexData(data: TServicoTipoIndexInteface) { // Instancia o cliente da API para enviar a requisição const api = new API(); // // Executa a requisição para a API com o método apropriado e o endpoint da tabela t_servico_tipo return await api.send({ method: Methods.GET, // GET listar todos os itens - endpoint: `administrativo/t_servico_tipo/`, // Endpoint atualizado + endpoint: `administrativo/t_servico_tipo/?${new URLSearchParams(data.urlParams).toString()}`, }); } diff --git a/src/app/(protected)/(cadastros)/cadastros/_data/TServicoTipo/TServicoTipoRemoveData.ts b/src/packages/administrativo/data/TServicoTipo/TServicoTipoRemoveData.ts similarity index 89% rename from src/app/(protected)/(cadastros)/cadastros/_data/TServicoTipo/TServicoTipoRemoveData.ts rename to src/packages/administrativo/data/TServicoTipo/TServicoTipoRemoveData.ts index aa5c6c3..92778de 100644 --- a/src/app/(protected)/(cadastros)/cadastros/_data/TServicoTipo/TServicoTipoRemoveData.ts +++ b/src/packages/administrativo/data/TServicoTipo/TServicoTipoRemoveData.ts @@ -5,7 +5,7 @@ import API from '@/shared/services/api/Api'; // import { Methods } from '@/shared/services/api/enums/ApiMethodEnum'; // // Importa a interface tipada que define a estrutura dos dados do tipo de serviço -import TServicoTipoInterface from '../../_interfaces/TServicoTipoInterface'; // Alterado de GCidadeInterface +import TServicoTipoInterface from '../../../../app/(protected)/(cadastros)/cadastros/_interfaces/TServicoTipoInterface'; // Alterado de GCidadeInterface // Importa função que encapsula chamadas assíncronas e trata erros automaticamente import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; // diff --git a/src/app/(protected)/(cadastros)/cadastros/_data/TServicoTipo/TServicoTipoSaveData.ts b/src/packages/administrativo/data/TServicoTipo/TServicoTipoSaveData.ts similarity index 91% rename from src/app/(protected)/(cadastros)/cadastros/_data/TServicoTipo/TServicoTipoSaveData.ts rename to src/packages/administrativo/data/TServicoTipo/TServicoTipoSaveData.ts index 53f6d83..b00b40a 100644 --- a/src/app/(protected)/(cadastros)/cadastros/_data/TServicoTipo/TServicoTipoSaveData.ts +++ b/src/packages/administrativo/data/TServicoTipo/TServicoTipoSaveData.ts @@ -2,13 +2,12 @@ import API from '@/shared/services/api/Api'; // // Importa o esquema de validação de dados para tipos de serviço -import { TServicoTipoFormValues } from '../../_schemas/TServicoTipoSchema'; +import { TServicoTipoFormValues } from '../../../../app/(protected)/(cadastros)/cadastros/_schemas/TServicoTipoSchema'; // Importa o enum que contém os métodos HTTP disponíveis (GET, POST, PUT, DELETE) import { Methods } from '@/shared/services/api/enums/ApiMethodEnum'; // // Importa a interface tipada que define a estrutura dos dados do tipo de serviço -import TServicoTipoInterface from '../../_interfaces/TServicoTipoInterface'; // Interface alterada // Importa função que encapsula chamadas assíncronas e trata erros automaticamente import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; // diff --git a/src/packages/administrativo/hooks/GUsuario/useGUsuarioIndexHook.ts b/src/packages/administrativo/hooks/GUsuario/useGUsuarioIndexHook.ts index f081677..1cb7b36 100644 --- a/src/packages/administrativo/hooks/GUsuario/useGUsuarioIndexHook.ts +++ b/src/packages/administrativo/hooks/GUsuario/useGUsuarioIndexHook.ts @@ -2,18 +2,21 @@ import { useState } from 'react'; +import Usuario from '@/packages/administrativo/interfaces/GUsuario/GUsuarioInterface'; import { useResponse } from '@/shared/components/response/ResponseContext'; -import Usuario from '../../interfaces/GUsuario/GUsuarioInterface'; +import GUsuarioIndexInterface from '../../interfaces/GUsuario/GusuarioIndexInterface'; import GUsuarioIndex from '../../services/GUsuario/GUsuarioIndex'; + export const useGUsuarioIndexHook = () => { const { setResponse } = useResponse(); const [usuarios, setUsuarios] = useState(null); - const fetchUsuarios = async () => { - const response = await GUsuarioIndex(); + const fetchUsuarios = async (data: GUsuarioIndexInterface) => { + + const response = await GUsuarioIndex(data); setUsuarios(response.data); diff --git a/src/packages/administrativo/hooks/TPessoa/TPessoaFisica/useTPessoaFisicaIndexHook.ts b/src/packages/administrativo/hooks/TPessoa/TPessoaFisica/useTPessoaFisicaIndexHook.ts index feb748a..43d6c9b 100644 --- a/src/packages/administrativo/hooks/TPessoa/TPessoaFisica/useTPessoaFisicaIndexHook.ts +++ b/src/packages/administrativo/hooks/TPessoa/TPessoaFisica/useTPessoaFisicaIndexHook.ts @@ -15,6 +15,8 @@ export const useTPessoaFisicaIndexHook = () => { setTPessoa(response.data); setResponse(response); + + return response.data }; return { tPessoaFisica, fetchTPessoaFisica }; diff --git a/src/app/(protected)/(cadastros)/cadastros/_hooks/t_servico_tipo/useTServicoTipoEditHook.ts b/src/packages/administrativo/hooks/TServicoTipo/useTServicoTipoEditHook.ts similarity index 81% rename from src/app/(protected)/(cadastros)/cadastros/_hooks/t_servico_tipo/useTServicoTipoEditHook.ts rename to src/packages/administrativo/hooks/TServicoTipo/useTServicoTipoEditHook.ts index b0094f8..70deeab 100644 --- a/src/app/(protected)/(cadastros)/cadastros/_hooks/t_servico_tipo/useTServicoTipoEditHook.ts +++ b/src/packages/administrativo/hooks/TServicoTipo/useTServicoTipoEditHook.ts @@ -1,10 +1,10 @@ import { useResponse } from '@/shared/components/response/ResponseContext'; // Contexto global para gerenciar respostas da API // Interface tipada do tipo de serviço -import TServicoTipoInterface from '../../_interfaces/TServicoTipoInterface'; +import TServicoTipoInterface from '../../../../app/(protected)/(cadastros)/cadastros/_interfaces/TServicoTipoInterface'; // Função que Edit o tipo de serviço via API -import { TServicoTipoEditData } from '../../_data/TServicoTipo/TServicoTipoEditData'; +import { TServicoTipoEditData } from '../../data/TServicoTipo/TServicoTipoEditData'; // Hook customizado para remoção de tipos de serviço export const useTServicoTipoEditHook = () => { diff --git a/src/app/(protected)/(cadastros)/cadastros/_hooks/t_servico_tipo/useTServicoTipoReadHook.ts b/src/packages/administrativo/hooks/TServicoTipo/useTServicoTipoReadHook.ts similarity index 72% rename from src/app/(protected)/(cadastros)/cadastros/_hooks/t_servico_tipo/useTServicoTipoReadHook.ts rename to src/packages/administrativo/hooks/TServicoTipo/useTServicoTipoReadHook.ts index b827959..a50af75 100644 --- a/src/app/(protected)/(cadastros)/cadastros/_hooks/t_servico_tipo/useTServicoTipoReadHook.ts +++ b/src/packages/administrativo/hooks/TServicoTipo/useTServicoTipoReadHook.ts @@ -1,14 +1,17 @@ -import { useResponse } from '@/shared/components/response/ResponseContext'; // Contexto global para gerenciar respostas da API import { useState } from 'react'; +import { useResponse } from '@/shared/components/response/ResponseContext'; // Contexto global para gerenciar respostas da API + // Serviço que busca a lista de tipos de serviço (TServicoTipoIndexService) -import { TServicoTipoIndexService } from '../../_services/t_servico_tipo/TServicoTipoIndexService'; +import TServicoTipoInterface from '../../../../app/(protected)/(cadastros)/cadastros/_interfaces/TServicoTipoInterface'; +import TServicoTipoIndexInteface from '../../interfaces/TServicoTipo/TServicoTipoIndexInteface'; +import { TServicoTipoIndexService } from '../../services/TServicoTipo/TServicoTipoIndexService'; // Interface tipada do tipo de serviço -import TServicoTipoInterface from '../../_interfaces/TServicoTipoInterface'; // Hook customizado para leitura de dados de tipos de serviço export const useTServicoTipoReadHook = () => { + // Hook do contexto de resposta para feedback global (alertas, mensagens etc.) const { setResponse } = useResponse(); @@ -16,9 +19,9 @@ export const useTServicoTipoReadHook = () => { const [tServicoTipo, setTServicoTipo] = useState([]); // Função assíncrona que busca os dados dos tipos de serviço - const fetchTServicoTipo = async () => { + const fetchTServicoTipo = async (data: TServicoTipoIndexInteface) => { // Chama o serviço responsável por consultar a API - const response = await TServicoTipoIndexService(); + const response = await TServicoTipoIndexService(data); // Atualiza o estado local com os dados retornados setTServicoTipo(response.data); diff --git a/src/app/(protected)/(cadastros)/cadastros/_hooks/t_servico_tipo/useTServicoTipoRemoveHook.ts b/src/packages/administrativo/hooks/TServicoTipo/useTServicoTipoRemoveHook.ts similarity index 81% rename from src/app/(protected)/(cadastros)/cadastros/_hooks/t_servico_tipo/useTServicoTipoRemoveHook.ts rename to src/packages/administrativo/hooks/TServicoTipo/useTServicoTipoRemoveHook.ts index e0f8d5d..25fe956 100644 --- a/src/app/(protected)/(cadastros)/cadastros/_hooks/t_servico_tipo/useTServicoTipoRemoveHook.ts +++ b/src/packages/administrativo/hooks/TServicoTipo/useTServicoTipoRemoveHook.ts @@ -1,10 +1,10 @@ import { useResponse } from '@/shared/components/response/ResponseContext'; // Contexto global para gerenciar respostas da API // Interface tipada do tipo de serviço -import TServicoTipoInterface from '../../_interfaces/TServicoTipoInterface'; +import TServicoTipoInterface from '../../../../app/(protected)/(cadastros)/cadastros/_interfaces/TServicoTipoInterface'; // Função que remove o tipo de serviço via API -import { TServicoTipoRemoveData } from '../../_data/TServicoTipo/TServicoTipoRemoveData'; +import { TServicoTipoRemoveData } from '../../data/TServicoTipo/TServicoTipoRemoveData'; // Hook customizado para remoção de tipos de serviço export const useTServicoTipoRemoveHook = () => { diff --git a/src/app/(protected)/(cadastros)/cadastros/_hooks/t_servico_tipo/useTServicoTipoSaveHook.ts b/src/packages/administrativo/hooks/TServicoTipo/useTServicoTipoSaveHook.ts similarity index 82% rename from src/app/(protected)/(cadastros)/cadastros/_hooks/t_servico_tipo/useTServicoTipoSaveHook.ts rename to src/packages/administrativo/hooks/TServicoTipo/useTServicoTipoSaveHook.ts index 964d127..0ba369f 100644 --- a/src/app/(protected)/(cadastros)/cadastros/_hooks/t_servico_tipo/useTServicoTipoSaveHook.ts +++ b/src/packages/administrativo/hooks/TServicoTipo/useTServicoTipoSaveHook.ts @@ -1,11 +1,11 @@ -import { useState } from 'react'; import { useResponse } from '@/shared/components/response/ResponseContext'; +import { useState } from 'react'; // Interface tipada do tipo de serviço -import TServicoTipoInterface from '../../_interfaces/TServicoTipoInterface'; +import TServicoTipoInterface from '../../../../app/(protected)/(cadastros)/cadastros/_interfaces/TServicoTipoInterface'; // Serviço que salva os dados do tipo de serviço -import { TServicoTipoSaveService } from '../../_services/t_servico_tipo/TServicoTipoSaveService'; +import { TServicoTipoSaveService } from '../../services/TServicoTipo/TServicoTipoSaveService'; export const useTServicoTipoSaveHook = () => { const { setResponse } = useResponse(); diff --git a/src/packages/administrativo/interfaces/GCalculo/GCalculoServicoInterface.ts b/src/packages/administrativo/interfaces/GCalculo/GCalculoServicoInterface.ts new file mode 100644 index 0000000..19ecb7b --- /dev/null +++ b/src/packages/administrativo/interfaces/GCalculo/GCalculoServicoInterface.ts @@ -0,0 +1,4 @@ +export default interface GCalculoServicoInterface { + valor_documento?: number; + emolumento_id?: number; +} diff --git a/src/packages/administrativo/interfaces/GUsuario/GUsuarioIndexInterface.ts b/src/packages/administrativo/interfaces/GUsuario/GUsuarioIndexInterface.ts new file mode 100644 index 0000000..dabc97d --- /dev/null +++ b/src/packages/administrativo/interfaces/GUsuario/GUsuarioIndexInterface.ts @@ -0,0 +1,3 @@ +export default interface GUsuarioIndexInterface { + urlParams: object +} \ No newline at end of file diff --git a/src/packages/administrativo/interfaces/GUsuario/GUsuarioSelectInterface.ts b/src/packages/administrativo/interfaces/GUsuario/GUsuarioSelectInterface.ts new file mode 100644 index 0000000..bd695f8 --- /dev/null +++ b/src/packages/administrativo/interfaces/GUsuario/GUsuarioSelectInterface.ts @@ -0,0 +1,6 @@ +export default interface GTBairroSelectInterface { + field?: { + value?: number | string; + onChange?: (value: string | number) => void; + }; +} diff --git a/src/packages/administrativo/interfaces/TPessoa/TPessoaTableDetailSubviewInterface.ts b/src/packages/administrativo/interfaces/TPessoa/TPessoaTableDetailSubviewInterface.ts new file mode 100644 index 0000000..b5dcd75 --- /dev/null +++ b/src/packages/administrativo/interfaces/TPessoa/TPessoaTableDetailSubviewInterface.ts @@ -0,0 +1,7 @@ +export default interface TPessoaTableFormSubviewInterface { + params: any; + servico: any; + selectedTPessoa: any; + form: any; + index: number +} \ No newline at end of file diff --git a/src/packages/administrativo/interfaces/TPessoa/TPessoaTableFormInterface.ts b/src/packages/administrativo/interfaces/TPessoa/TPessoaTableFormInterface.ts new file mode 100644 index 0000000..e542ae5 --- /dev/null +++ b/src/packages/administrativo/interfaces/TPessoa/TPessoaTableFormInterface.ts @@ -0,0 +1,8 @@ + +export default interface TPessoaTableFormInterface { + isOpen: boolean; + tipoPessoa: string; + onClose: (item: null, isFormStatus: boolean) => void; + onSave: (data: any) => void; + buttonIsLoading: boolean; +} diff --git a/src/packages/administrativo/interfaces/TPessoa/TPessoaTableFormSubviewInterface.ts b/src/packages/administrativo/interfaces/TPessoa/TPessoaTableFormSubviewInterface.ts new file mode 100644 index 0000000..7c44173 --- /dev/null +++ b/src/packages/administrativo/interfaces/TPessoa/TPessoaTableFormSubviewInterface.ts @@ -0,0 +1,11 @@ +import { UseFormReturn } from "react-hook-form"; + +import { TServicoPedidoFormValues } from "@/packages/servicos/schemas/TServicoPedido/TServicoPedidoFormSchema"; +import GConfigInterface from "@/shared/interfaces/GConfigInterface"; + +export default interface TPessoaTableFormSubviewInterface { + item_index: number, + data: any, + params: GConfigInterface[], + form: UseFormReturn; +} \ No newline at end of file diff --git a/src/packages/administrativo/interfaces/TServicoTipo/TServicoTipoIndexInteface.ts b/src/packages/administrativo/interfaces/TServicoTipo/TServicoTipoIndexInteface.ts new file mode 100644 index 0000000..ab18dc8 --- /dev/null +++ b/src/packages/administrativo/interfaces/TServicoTipo/TServicoTipoIndexInteface.ts @@ -0,0 +1,3 @@ +export default interface TServicoTipoIndexInteface { + urlParams: object +} \ No newline at end of file diff --git a/src/packages/administrativo/interfaces/TServicoTipo/TServicoTipoSelectInterface.ts b/src/packages/administrativo/interfaces/TServicoTipo/TServicoTipoSelectInterface.ts new file mode 100644 index 0000000..42d5533 --- /dev/null +++ b/src/packages/administrativo/interfaces/TServicoTipo/TServicoTipoSelectInterface.ts @@ -0,0 +1,6 @@ +export default interface TServicoTipoSelectInterface { + field?: { + value?: number | string; + onChange?: (value: string | number) => void; + }; +} diff --git a/src/packages/administrativo/services/GCalculo/GCalculoServicoService.ts b/src/packages/administrativo/services/GCalculo/GCalculoServicoService.ts new file mode 100644 index 0000000..02d6395 --- /dev/null +++ b/src/packages/administrativo/services/GCalculo/GCalculoServicoService.ts @@ -0,0 +1,46 @@ +import { GCalculoServico } from "@/packages/administrativo/data/GCalculo/GCalculoServicoData"; +import GCalculoServicoInterface from "@/packages/administrativo/interfaces/GCalculo/GCalculoServicoInterface"; +import TServicoItemPedidoAddInterface from "@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoAddInterface"; +import { withClientErrorHandler } from "@/shared/actions/withClientErrorHandler/withClientErrorHandler"; + + +async function executeGCalculoServicoService(payload: GCalculoServicoInterface, data: TServicoItemPedidoAddInterface) { + + const response = await GCalculoServico(payload); + + if (response.status == 404 || response.status == 400) { + + return { + + 'status': response.status, + 'message': 'Erro ao processar dados' + + }; + + } + + const item = { + emolumento_id: response.data.emolumento_id, + emolumento_item_id: response.data.emolumento_item_id ?? null, + servico_tipo_id: data.servico_tipo.servico_tipo_id ?? 0, + tipo_item: data.servico_tipo.tipo_item ?? "", + descricao: data.servico_tipo.descricao ?? "", + tabela: data.servico_tipo?.descricao ?? "", + situacao: "F", + qtd: 1, + valor: response.data.valor_total ?? 0, + emolumento: response.data.valor_emolumento ?? 0, + fundesp: response.data.valor_fundos ?? 0, + taxa_judiciaria: response.data.taxa_judiciaria ?? 0, + valor_iss: response.data.valor_iss ?? 0, + pessoa_id: data?.pessoa?.pessoa_id ?? null, + subview: { + servico: data.servico_tipo, + pessoa: data.pessoa, + } + }; + + return item; +} + +export const GCalculoServicoService = withClientErrorHandler(executeGCalculoServicoService); \ No newline at end of file diff --git a/src/packages/administrativo/services/GUsuario/GUsuarioIndex.ts b/src/packages/administrativo/services/GUsuario/GUsuarioIndex.ts index ac2d962..bde697b 100644 --- a/src/packages/administrativo/services/GUsuario/GUsuarioIndex.ts +++ b/src/packages/administrativo/services/GUsuario/GUsuarioIndex.ts @@ -1,9 +1,10 @@ 'use server'; import GUsuarioIndexData from '../../data/GUsuario/GUsuarioIndexData'; +import GUsuarioIndexInterface from '../../interfaces/GUsuario/GusuarioIndexInterface'; -export default async function GUsuarioIndex() { - const response = await GUsuarioIndexData(); +export default async function GUsuarioIndex(data: GUsuarioIndexInterface) { + const response = await GUsuarioIndexData(data); return response; } diff --git a/src/app/(protected)/(cadastros)/cadastros/_services/t_servico_tipo/TServicoTipoEditService.ts b/src/packages/administrativo/services/TServicoTipo/TServicoTipoEditService.ts similarity index 79% rename from src/app/(protected)/(cadastros)/cadastros/_services/t_servico_tipo/TServicoTipoEditService.ts rename to src/packages/administrativo/services/TServicoTipo/TServicoTipoEditService.ts index 9e0ab2e..99e6bee 100644 --- a/src/app/(protected)/(cadastros)/cadastros/_services/t_servico_tipo/TServicoTipoEditService.ts +++ b/src/packages/administrativo/services/TServicoTipo/TServicoTipoEditService.ts @@ -1,10 +1,10 @@ import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; // Função que envolve qualquer ação assíncrona para capturar e tratar erros do cliente -import { TServicoTipoEditData } from '../../_data/TServicoTipo/TServicoTipoEditData'; +import { TServicoTipoEditData } from '../../data/TServicoTipo/TServicoTipoEditData'; // Função que remove os dados do tipo de serviço via API -import TServicoTipoInterface from '../../_interfaces/TServicoTipoInterface'; +import TServicoTipoInterface from '../../../../app/(protected)/(cadastros)/cadastros/_interfaces/TServicoTipoInterface'; // Interface tipada do tipo de serviço // Função assíncrona que executa a remoção de um tipo de serviço diff --git a/src/app/(protected)/(cadastros)/cadastros/_services/t_servico_tipo/TServicoTipoIndexService.ts b/src/packages/administrativo/services/TServicoTipo/TServicoTipoIndexService.ts similarity index 68% rename from src/app/(protected)/(cadastros)/cadastros/_services/t_servico_tipo/TServicoTipoIndexService.ts rename to src/packages/administrativo/services/TServicoTipo/TServicoTipoIndexService.ts index d8654ca..ed7dcc8 100644 --- a/src/app/(protected)/(cadastros)/cadastros/_services/t_servico_tipo/TServicoTipoIndexService.ts +++ b/src/packages/administrativo/services/TServicoTipo/TServicoTipoIndexService.ts @@ -1,13 +1,14 @@ import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; // Função que envolve qualquer ação assíncrona para capturar e tratar erros do cliente -import { TServicoTipoIndexData } from '../../_data/TServicoTipo/TServicoTipoIndexData'; +import { TServicoTipoIndexData } from '../../data/TServicoTipo/TServicoTipoIndexData'; +import TServicoTipoIndexInteface from '../../interfaces/TServicoTipo/TServicoTipoIndexInteface'; // Função que retorna os dados da lista de tipos de serviço (chamada à API ou mock) // Função assíncrona que executa a chamada para buscar os dados dos tipos de serviço -async function executeTServicoTipoIndexService() { +async function executeTServicoTipoIndexService(data: TServicoTipoIndexInteface) { // Chama a função que retorna os dados dos tipos de serviço - const response = await TServicoTipoIndexData(); + const response = await TServicoTipoIndexData(data); // Retorna a resposta para o chamador return response; diff --git a/src/app/(protected)/(cadastros)/cadastros/_services/t_servico_tipo/TServicoTipoRemoveService.ts b/src/packages/administrativo/services/TServicoTipo/TServicoTipoRemoveService.ts similarity index 79% rename from src/app/(protected)/(cadastros)/cadastros/_services/t_servico_tipo/TServicoTipoRemoveService.ts rename to src/packages/administrativo/services/TServicoTipo/TServicoTipoRemoveService.ts index 4376393..0fe26e2 100644 --- a/src/app/(protected)/(cadastros)/cadastros/_services/t_servico_tipo/TServicoTipoRemoveService.ts +++ b/src/packages/administrativo/services/TServicoTipo/TServicoTipoRemoveService.ts @@ -1,10 +1,10 @@ import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; // Função que envolve qualquer ação assíncrona para capturar e tratar erros do cliente -import { TServicoTipoRemoveData } from '../../_data/TServicoTipo/TServicoTipoRemoveData'; +import { TServicoTipoRemoveData } from '../../data/TServicoTipo/TServicoTipoRemoveData'; // Função que remove os dados do tipo de serviço via API -import TServicoTipoInterface from '../../_interfaces/TServicoTipoInterface'; +import TServicoTipoInterface from '../../../../app/(protected)/(cadastros)/cadastros/_interfaces/TServicoTipoInterface'; // Interface tipada do tipo de serviço // Função assíncrona que executa a remoção de um tipo de serviço diff --git a/src/app/(protected)/(cadastros)/cadastros/_services/t_servico_tipo/TServicoTipoSaveService.ts b/src/packages/administrativo/services/TServicoTipo/TServicoTipoSaveService.ts similarity index 80% rename from src/app/(protected)/(cadastros)/cadastros/_services/t_servico_tipo/TServicoTipoSaveService.ts rename to src/packages/administrativo/services/TServicoTipo/TServicoTipoSaveService.ts index 770d824..966d210 100644 --- a/src/app/(protected)/(cadastros)/cadastros/_services/t_servico_tipo/TServicoTipoSaveService.ts +++ b/src/packages/administrativo/services/TServicoTipo/TServicoTipoSaveService.ts @@ -2,10 +2,10 @@ import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; // Função que salva os dados do tipo de serviço via API (ou mock) -import { TServicoTipoSaveData } from '../../_data/TServicoTipo/TServicoTipoSaveData'; +import { TServicoTipoSaveData } from '../../data/TServicoTipo/TServicoTipoSaveData'; // Interface tipada do tipo de serviço -import TServicoTipoInterface from '../../_interfaces/TServicoTipoInterface'; +import TServicoTipoInterface from '../../../../app/(protected)/(cadastros)/cadastros/_interfaces/TServicoTipoInterface'; // Função assíncrona que executa o salvamento de um tipo de serviço async function executeTServicoTipoSaveService(data: TServicoTipoInterface) { diff --git a/src/packages/servicos/actions/TServicoPedido/HandleAddItemAction.ts b/src/packages/servicos/actions/TServicoPedido/HandleAddItemAction.ts new file mode 100644 index 0000000..c642bca --- /dev/null +++ b/src/packages/servicos/actions/TServicoPedido/HandleAddItemAction.ts @@ -0,0 +1,15 @@ + +interface HandleAddItemInterface { + servicoSelecionado: any; + emolumentoSelecionado: any; +} + +export default async function HandleAddItemAction({ servicoSelecionado, emolumentoSelecionado }: HandleAddItemInterface) { + + if (!servicoSelecionado || !emolumentoSelecionado) return false; + + return { + servico_tipo: servicoSelecionado, + emolumento: emolumentoSelecionado, + }; +} \ No newline at end of file diff --git a/src/packages/servicos/actions/TServicoPedido/HandleSelectTServicoTipoAction.ts b/src/packages/servicos/actions/TServicoPedido/HandleSelectTServicoTipoAction.ts new file mode 100644 index 0000000..c569337 --- /dev/null +++ b/src/packages/servicos/actions/TServicoPedido/HandleSelectTServicoTipoAction.ts @@ -0,0 +1,24 @@ + + +export default function HandleSelectTServicoTipoAction({ servico, emolumento, onOpenPessoaForm, onAddItem }: HandleSelectTServicoTipoInterface) { + + if (!servico || !emolumento) { + + return { + 'status': 422, + 'detail': 'Serviço e emolumento devem ser selecionados' + }; + + }; + + if (servico?.tipo_pessoa) { + + onOpenPessoaForm(servico.tipo_pessoa); + + } else { + + onAddItem(); + + } + +} \ No newline at end of file diff --git a/src/packages/servicos/actions/TServicoPedido/HandleSelectTServicoTipoInterface.ts b/src/packages/servicos/actions/TServicoPedido/HandleSelectTServicoTipoInterface.ts new file mode 100644 index 0000000..c7e626f --- /dev/null +++ b/src/packages/servicos/actions/TServicoPedido/HandleSelectTServicoTipoInterface.ts @@ -0,0 +1,8 @@ +export default interface HandleSelectTServicoTipoInterface { + + servico: any; + emolumento: any; + onOpenPessoaForm: (tipoPessoa: string) => void, + onAddItem: () => void + +} \ No newline at end of file diff --git a/src/packages/servicos/actions/TServicoPedidoItem/TServicoPedidoItemPreparePayload.ts b/src/packages/servicos/actions/TServicoPedidoItem/TServicoPedidoItemPreparePayload.ts new file mode 100644 index 0000000..34d6361 --- /dev/null +++ b/src/packages/servicos/actions/TServicoPedidoItem/TServicoPedidoItemPreparePayload.ts @@ -0,0 +1,31 @@ +import TServicoItemPedidoAddInterface from "@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoAddInterface"; + +export default function TServicoPedidoItemPreparePayload(data: TServicoItemPedidoAddInterface) { + + data.qtd = 1 + data.valor_documento = 0 + + // Verifica dados obrigatórios de serviço e emolumento + if (!data?.emolumento?.emolumento_id || !data?.servico_tipo?.servico_tipo_id) { + return { + status: 400, + message: 'Dados informados inválidos: serviço ou emolumento não informado.' + }; + } + + // Valida sistema_id (padrão 2, mas ainda assim precisa ser válido) + if (!data?.emolumento.sistema_id || data.servico_tipo.servico_tipo_id <= 0) { + return { + status: 400, + message: 'Sistema inválido ou não informado.' + }; + } + + return { + sistema_id: data.emolumento.sistema_id, + valor_documento: data.valor_documento, + quantidade: data.qtd, + emolumento_id: data.emolumento.emolumento_id, + }; + +} diff --git a/src/packages/servicos/components/TPessoaCartao/TPessoaCartaoForm.tsx b/src/packages/servicos/components/TPessoaCartao/TPessoaCartaoForm.tsx new file mode 100644 index 0000000..a08ca8c --- /dev/null +++ b/src/packages/servicos/components/TPessoaCartao/TPessoaCartaoForm.tsx @@ -0,0 +1,88 @@ +import { useState } from "react"; + +import { FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { Switch } from "@/components/ui/switch"; +import TPessoaCartaoFormInterface from "@/packages/servicos/interfaces/TPessoaCartao/TPessoaCartaoFormInterface"; +import { parseNumberInput } from "@/shared/actions/form/parseNumberInput"; +import ConfirmacaoSelect from "@/shared/components/confirmacao/ConfirmacaoSelect"; + + +export default function TPessoaCartaoForm({ index, form }: TPessoaCartaoFormInterface) { + + const [cartaoAutomatico, setCartaoAutomatico] = useState(true); + + return ( +
+
+ { + setCartaoAutomatico(checked); + form.setValue(`itens.${index}.cartao_automatico`, checked); + }} + /> + +
+ {!cartaoAutomatico && ( +
+ {/* Gerar selo */} +
+ ( + + Gerar Selo + + + + )} + /> +
+ {/* Nº Cartão */} +
+ ( + + Nº cartão + + field.onChange(parseNumberInput(e))} + defaultValue={field.value ?? ""} + /> + + + + )} + /> +
+ {/* Data de Abertura */} +
+ ( + + Data de Abertura + + + + + + )} + /> +
+
+ )} +
+ ) +} \ No newline at end of file diff --git a/src/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoColumns.tsx b/src/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoColumns.tsx deleted file mode 100644 index b48305c..0000000 --- a/src/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoColumns.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import { ColumnDef } from '@tanstack/react-table'; -import { EllipsisIcon, PencilIcon, Trash2Icon } from 'lucide-react'; - -import { Button } from '@/components/ui/button'; -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuGroup, - DropdownMenuItem, - DropdownMenuSeparator, - DropdownMenuTrigger, -} from '@/components/ui/dropdown-menu'; -import GetCapitalize from '@/shared/actions/text/GetCapitalize'; -import { SortableHeader } from '@/shared/components/dataTable/SortableHeader'; - -import TServicoItemPedidoInterface from '../../interfaces/TServicoItemPedido/TServicoItemPedidoIntefarce'; - -export default function TServicoItemPedidoColumns( - onEdit: (item: TServicoItemPedidoInterface, isEditingFormStatus: boolean) => void, - onDelete: (item: TServicoItemPedidoInterface, isEditingFormStatus: boolean) => void, -): ColumnDef[] { - return [ - // ID - { - accessorKey: 'gramatica_id', - header: ({ column }) => SortableHeader('ID', column), - cell: ({ row }) => Number(row.getValue('gramatica_id')), - enableSorting: true, - }, - - // Descrição - { - accessorKey: 'palavra', - header: ({ column }) => SortableHeader('Palavra', column), - cell: ({ row }) => GetCapitalize(String(row.getValue('palavra') || '')), - }, - - // Ações - { - id: 'actions', - header: 'Ações', - cell: ({ row }) => { - const natureza = row.original; - - return ( - - - - - - - - onEdit(natureza, true)}> - - Editar - - - - - onDelete(natureza, true)} - > - - Remover - - - - - ); - }, - enableSorting: false, - enableHiding: false, - }, - ]; -} diff --git a/src/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoForm.tsx b/src/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoForm.tsx deleted file mode 100644 index d943bbc..0000000 --- a/src/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoForm.tsx +++ /dev/null @@ -1,110 +0,0 @@ -'use client'; - -import { useEffect } from 'react'; - -import { Button } from '@/components/ui/button'; -import { - Dialog, - DialogClose, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, -} from '@/components/ui/dialog'; -import { - Form, - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, -} from '@/components/ui/form'; -import { Input } from '@/components/ui/input'; -import { ResetFormIfData } from '@/shared/actions/form/ResetFormIfData'; -import LoadingButton from '@/shared/components/loadingButton/LoadingButton'; - -import { useTServicoItemPedidoFormHook } from '../../hooks/TServicoItemPedido/useTServicoItemPedidoFormHook'; -import { TServicoItemPedidoFormInterface } from '../../interfaces/TServicoItemPedido/TServicoItemPedidoFormInterface'; - -/** - * Formulário de cadastro/edição de Natureza - * Baseado nos campos da tabela G_NATUREZA - */ -export default function TServicoItemPedidoForm({ - isOpen, - data, - onClose, - onSave, - buttonIsLoading, -}: TServicoItemPedidoFormInterface) { - const form = useTServicoItemPedidoFormHook({}); - - // Atualiza o formulário quando recebe dados para edição - useEffect(() => { - ResetFormIfData(form, data); - }, [data, form]); - - function onError(error: any) { - console.log('Erro no formulário:', error); - } - - return ( - { - if (!open) onClose(null, false); - }} - > - - - Formulário de Gramática - - Formulário de Gramática - - - {/* Formulário principal */} -
- - {/* GRID MOBILE FIRST */} -
- {/* Palavra */} -
- ( - - Palavra - - - - - - )} - /> -
-
- {/* Rodapé */} - - - - - - -
- -
-
- ); -} diff --git a/src/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoFormTable.tsx b/src/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoFormTable.tsx new file mode 100644 index 0000000..859465e --- /dev/null +++ b/src/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoFormTable.tsx @@ -0,0 +1,116 @@ +'use client'; + +import { Minus, Plus } from 'lucide-react'; +import React, { memo } from 'react'; + +import { Button } from '@/components/ui/button'; +import { Input } from '@/components/ui/input'; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow +} from '@/components/ui/table'; +import TPessoaTableFormSubview from '@/packages/administrativo/components/TPessoa/TPessoaTableFormSubview'; +import TServicoItemPedidoFormTableInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoFormTableInterface'; +import GetCapitalize from '@/shared/actions/text/GetCapitalize'; + +function TServicoItemPedidoFormTableComponent({ + data, + form, + params +}: TServicoItemPedidoFormTableInterface) { + return ( +
+ + + + + Serviço / Tabela + + + Emolumento + + + Tx. Judiciária + + + Fundesp 21% + + + ISS 5% + + + Total + + Qtd. + + + + {data?.length ? ( + data.map((item, index) => { + return ( + + {/* Linha principal */} + + +
+
+
+ {GetCapitalize(item.descricao)} +
+
+ {GetCapitalize(item.tabela)} +
+
+
+
+ R$ {item.emolumento ?? '---'} + R$ {item.taxa_judiciaria ?? '---'} + R$ {item.fundesp ?? '---'} + R$ {item.valor_iss ?? '---'} + R$ {item.valor ?? '---'} + +
+ + + +
+
+
+ {/* SubView */} + {item.subview && ( + + + + + + )} +
+ ); + }) + ) : ( + + + Nenhum item encontrado. + + + )} +
+
+
+ ); +} + +export const TServicoItemPedidoFormTable = memo(TServicoItemPedidoFormTableComponent); \ No newline at end of file diff --git a/src/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoIndex.tsx b/src/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoIndex.tsx deleted file mode 100644 index 97eb904..0000000 --- a/src/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoIndex.tsx +++ /dev/null @@ -1,161 +0,0 @@ -'use client'; - -import { useCallback, useEffect, useState } from 'react'; - - -import { useTServicoItemPedidoDeleteHook } from '@/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoDeleteHook'; -import { useTServicoItemPedidoIndexHook } from '@/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoIndexHook'; -import { useTServicoItemPedidoSaveHook } from '@/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoSaveHook'; -import TServicoItemPedidoInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoIntefarce'; -import ConfirmDialog from '@/shared/components/confirmDialog/ConfirmDialog'; -import { useConfirmDialog } from '@/shared/components/confirmDialog/useConfirmDialog'; -import Loading from '@/shared/components/loading/loading'; -import Header from '@/shared/components/structure/Header'; - -import TServicoItemPedidoForm from './TServicoItemPedidoForm'; -import TServicoItemPedidoTable from './TServicoItemPedidoTable'; - -export default function TServicoItemPedidoIndex() { - - // Controle de estado do botão - const [buttonIsLoading, setButtonIsLoading] = useState(false); - - // Hooks para leitura e salvamento - const { TServicoItemPedido, indexTServicoItemPedido } = useTServicoItemPedidoIndexHook(); - const { saveTServicoItemPedido } = useTServicoItemPedidoSaveHook(); - const { deleteTServicoItemPedido } = useTServicoItemPedidoDeleteHook(); - - // Estados - const [selectedData, setSelectedData] = useState(null); - const [isFormOpen, setIsFormOpen] = useState(false); - - // Estado para saber qual item será deletado - const [itemToDelete, setItemToDelete] = useState(null); - - /** - * Hook do modal de confirmação - */ - const { isOpen: isConfirmOpen, openDialog: openConfirmDialog, handleCancel } = useConfirmDialog(); - - /** - * Abre o formulário no modo de edição ou criação - */ - const handleOpenForm = useCallback((data: TServicoItemPedidoInterface | null) => { - setSelectedData(data); - setIsFormOpen(true); - }, []); - - /** - * Fecha o formulário e limpa o andamento selecionado - */ - const handleCloseForm = useCallback(() => { - setSelectedData(null); - setIsFormOpen(false); - }, []); - - /** - * Salva os dados do formulário - */ - const handleSave = useCallback( - async (formData: TServicoItemPedidoInterface) => { - // Coloca o botão em estado de loading - setButtonIsLoading(true); - - // Aguarda salvar o registro - await saveTServicoItemPedido(formData); - - // Remove o botão em estado de loading - setButtonIsLoading(false); - - // Atualiza a lista de dados - indexTServicoItemPedido(); - }, - [saveTServicoItemPedido, indexTServicoItemPedido, handleCloseForm], - ); - - /** - * Quando o usuário clica em "remover" na tabela - */ - const handleConfirmDelete = useCallback( - (item: TServicoItemPedidoInterface) => { - // Define o item atual para remoção - setItemToDelete(item); - // Abre o modal de confirmação - openConfirmDialog(); - }, - [openConfirmDialog], - ); - - /** - * Executa a exclusão de fato quando o usuário confirma - */ - const handleDelete = useCallback(async () => { - // Protege contra null - if (!itemToDelete) return; - - // Executa o Hook de remoção - await deleteTServicoItemPedido(itemToDelete); - - // Atualiza a lista - await indexTServicoItemPedido(); - - // Limpa o item selecionado - setItemToDelete(null); - - // Fecha o modal - handleCancel(); - }, [itemToDelete, indexTServicoItemPedido, handleCancel]); - - /** - * Busca inicial dos dados - */ - useEffect(() => { - indexTServicoItemPedido(); - }, []); - - /** - * Tela de loading enquanto carrega os dados - */ - if (TServicoItemPedido?.length == 0) { - return ; - } - - return ( -
- {/* Cabeçalho */} -
{ - handleOpenForm(null); - }} - /> - {/* Tabela de andamentos */} - - {/* Modal de confirmação */} - {isConfirmOpen && ( - - )} - {/* Formulário de criação/edição */} - {isFormOpen && ( - - )} -
- ); -} diff --git a/src/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoList.tsx b/src/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoList.tsx new file mode 100644 index 0000000..ea8ed69 --- /dev/null +++ b/src/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoList.tsx @@ -0,0 +1,209 @@ +'use client'; + + +import { BookmarkX, IdCardIcon, MoreHorizontalIcon, RotateCcwIcon, TicketIcon } from 'lucide-react'; +import { useCallback, useEffect, useState } from 'react'; + +import { Button } from '@/components/ui/button'; +import { ButtonGroup } from '@/components/ui/button-group'; +import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; +import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger } from '@/components/ui/dropdown-menu'; +import { useTServicoItemPedidoCancelarHook } from '@/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoCancelarHook'; +import TServicoItemPedidoInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoIntefarce'; +import TServicoItemPedidoListInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoListInterface'; +import FormatMoney from '@/shared/actions/money/FormatMoney'; +import { useResponse } from '@/shared/components/response/ResponseContext'; +import { ServicosPedidosSituacoesBadge } from '@/shared/components/servicosPedidosSituacoes/ServicosPedidosSituacoesBadge'; + +import { useTServicoItemPedidoAtivarHook } from '../../hooks/TServicoItemPedido/useTServicoItemPedidoAtivarHook'; + +export default function TServicoItemPedidoList({ items, openConfirmDialog }: TServicoItemPedidoListInterface) { + + const { setResponse } = useResponse(); + const { cancelarTServicoItemPedido } = useTServicoItemPedidoCancelarHook() + const { ativarTServicoItemPedido } = useTServicoItemPedidoAtivarHook() + + const [localItems, setLocalItems] = useState(items || []) + + useEffect(() => { + + setLocalItems(items || []) + + }, [items]) + + const handleSituacaoTServicoItemPedido = useCallback(async (item: any) => { + + const servicoItemPedido: TServicoItemPedidoInterface = { + + servico_itempedido_id: item.servico_itempedido_id + + } + + let response: any = null + + switch (item.situacao) { + + case 'C': + + response = await ativarTServicoItemPedido(servicoItemPedido) + break + + case 'F': + + response = await cancelarTServicoItemPedido(servicoItemPedido) + break + + default: + + setResponse({ + status: 422, + error: 'Situação', + detail: 'Situação não tratada' + }) + break + + } + + if (response) { + + setLocalItems((prev) => + + prev.map((i) => + + i.servico_itempedido_id === item.servico_itempedido_id ? { ...i, situacao: response.situacao } : i + + ) + ) + } + + }, [cancelarTServicoItemPedido, setLocalItems]) + + return ( + + + + Itens: {localItems?.length} + + + + + {/* Altura máxima + scroll vertical */} +
+ + {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}?` + const confirmButton = isCancelado ? 'Sim, ativar item' : 'Sim, estornar item' + const actionIcon = isCancelado ? : + + return ( +
+ + {/* Descrição */} +
+ +

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

+ +
+ + # {item.servico_itempedido_id} + +
+ +
+ + {/* Valores (grid compacto) */} +
+ +
+
Emolumento
+
{FormatMoney(item.emolumento)}
+
+ +
+
Tx. Judiciária
+
{FormatMoney(item.taxa_judiciaria)}
+
+ +
+
ISS
+
{FormatMoney(item.valor_iss)}
+
+ +
+
Fundesp
+
{FormatMoney(item.fundesp)}
+
+ +
+
Total
+
{FormatMoney(item.valor)}
+
+ +
+ + + + + + + + + + + + Imprimir Etiqueta + + + + + + Imprimir Cartão + + + + + + openConfirmDialog({ + title: confirmTitle, + description: 'Confirmação necessária', + message: confirmMessage, + confirmText: confirmButton, + cancelText: 'Cancelar', + onConfirm: () => { + handleSituacaoTServicoItemPedido(item) + }, + }) + } + > + {actionIcon} {actionLabel} + + + + + + +
+
+ +
+ ) + })} +
+
+
+ ); +} diff --git a/src/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoTable.tsx b/src/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoTable.tsx deleted file mode 100644 index 3b5fecb..0000000 --- a/src/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoTable.tsx +++ /dev/null @@ -1,23 +0,0 @@ -'use client'; - -import { DataTable } from '@/shared/components/dataTable/DataTable'; - -import TServicoItemPedidoColumns from './TServicoItemPedidoColumns'; -import TServicoItemPedidoTableInterface from '../../interfaces/TServicoItemPedido/TServicoItemPedidoTableInterface'; - -/** - * Componente principal da tabela de Naturezas - */ -export default function TServicoItemPedidoTable({ data, onEdit, onDelete }: TServicoItemPedidoTableInterface) { - const columns = TServicoItemPedidoColumns(onEdit, onDelete); - return ( -
- -
- ); -} diff --git a/src/packages/servicos/components/TServicoPedido/TServicoPedidoColumns.tsx b/src/packages/servicos/components/TServicoPedido/TServicoPedidoColumns.tsx index 7dc34b7..e5d0966 100644 --- a/src/packages/servicos/components/TServicoPedido/TServicoPedidoColumns.tsx +++ b/src/packages/servicos/components/TServicoPedido/TServicoPedidoColumns.tsx @@ -1,5 +1,6 @@ import { ColumnDef } from '@tanstack/react-table'; -import { EllipsisIcon, PencilIcon, Trash2Icon } from 'lucide-react'; +import { EllipsisIcon, EyeIcon, PencilIcon, Trash2Icon } from 'lucide-react'; +import Link from 'next/link'; import { Button } from '@/components/ui/button'; import { @@ -10,8 +11,13 @@ import { DropdownMenuSeparator, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu'; +import { FormatCPF } from '@/shared/actions/CPF/FormatCPF'; +import { FormatDateTime } from '@/shared/actions/dateTime/FormatDateTime'; import GetCapitalize from '@/shared/actions/text/GetCapitalize'; +import GetNameInitials from '@/shared/actions/text/GetNameInitials'; +import empty from '@/shared/actions/validations/empty'; import { SortableHeader } from '@/shared/components/dataTable/SortableHeader'; +import { ServicosPedidosSituacoesBadge } from '@/shared/components/servicosPedidosSituacoes/ServicosPedidosSituacoesBadge'; import TServicoPedidoInterface from '../../interfaces/TServicoPedido/TServicoPedidoInterface'; @@ -22,17 +28,75 @@ export default function TServicoPedidoColumns( return [ // ID { - accessorKey: 'gramatica_id', + accessorKey: 'servico_pedido_id', header: ({ column }) => SortableHeader('ID', column), - cell: ({ row }) => Number(row.getValue('gramatica_id')), + cell: ({ row }) => Number(row.getValue('servico_pedido_id')), enableSorting: true, }, - // Descrição + // Data Pedido { - accessorKey: 'palavra', - header: ({ column }) => SortableHeader('Palavra', column), - cell: ({ row }) => GetCapitalize(String(row.getValue('palavra') || '')), + accessorKey: 'data_pedido', + header: ({ column }) => SortableHeader('Data', column), + cell: ({ row }) => FormatDateTime(row.getValue('data_pedido')), + }, + + // Apresentante + { + accessorKey: 'apresentante', + header: ({ column }) => SortableHeader('Apresentante', column), + cell: ({ row }) => { + const data = row.original; + return ( +
+ {/* Foto ou Iniciais */} +
+ + {GetNameInitials(data.apresentante)} + +
+
+
{data.apresentante || '-'}
+
+ {empty(data.cpfcnpj_apresentante) ? '---' : FormatCPF(data.cpfcnpj_apresentante)} +
+
+
+ ); + }, + sortingFn: (a, b) => + (a.original.apresentante?.toLowerCase() || '').localeCompare(b.original.apresentante?.toLowerCase() || ''), + }, + + // Situação + { + accessorKey: 'situacao', + header: ({ column }) => SortableHeader('Situação', column), + cell: ({ row }) => { + return ( + + ) + }, + }, + + // Valor Pedido + { + accessorKey: 'valor_pedido', + header: ({ column }) => SortableHeader('Total', column), + cell: ({ row }) => { + return ( +
+ R$ {row.getValue('valor_pedido') || '---'} +
+ ); + }, + }, + + // Usuário + { + accessorKey: 'login', + header: ({ column }) => SortableHeader('Operador', column), + cell: ({ row }) => GetCapitalize(String(row.getValue('login') || '')), }, // Ações @@ -40,8 +104,7 @@ export default function TServicoPedidoColumns( id: 'actions', header: 'Ações', cell: ({ row }) => { - const natureza = row.original; - + const servicoPedido = row.original; return ( @@ -49,20 +112,23 @@ export default function TServicoPedidoColumns( - - onEdit(natureza, true)}> - - Editar + + + + Detalhes + - - - onDelete(natureza, true)} - > + + + + Editar + + + + onDelete(servicoPedido, true)}> Remover diff --git a/src/packages/servicos/components/TServicoPedido/TServicoPedidoDetails.tsx b/src/packages/servicos/components/TServicoPedido/TServicoPedidoDetails.tsx new file mode 100644 index 0000000..792308d --- /dev/null +++ b/src/packages/servicos/components/TServicoPedido/TServicoPedidoDetails.tsx @@ -0,0 +1,268 @@ +'use client'; + + +import { BookmarkX, CalendarIcon, ReceiptText, RotateCcwIcon } from 'lucide-react'; +import { useCallback, useEffect, useState } from 'react'; + +import { Button } from '@/components/ui/button'; +import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; +import { Separator } from '@/components/ui/separator'; +import TServicoItemPedidoList from '@/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoList'; +import TServicoPedidoDetailsPagamento from '@/packages/servicos/components/TServicoPedido/TServicoPedidoDetailsPagamento'; +import { useTServicoItemPedidoIndexHook } from '@/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoIndexHook'; +import { useTServicoPedidoShowHook } from '@/packages/servicos/hooks/TServicoPedido/useTServicoPedidoShowHook'; +import TServicoPedidoInterface from '@/packages/servicos/interfaces/TServicoPedido/TServicoPedidoInterface'; +import { FormatCPF } from '@/shared/actions/CPF/FormatCPF'; +import { FormatDateTime } from '@/shared/actions/dateTime/FormatDateTime'; +import GetCapitalize from '@/shared/actions/text/GetCapitalize'; +import GetNameInitials from '@/shared/actions/text/GetNameInitials'; +import ConfirmDialog from '@/shared/components/confirmDialog/ConfirmDialog'; +import { useResponse } from '@/shared/components/response/ResponseContext'; + +import { useTServicoPedidoAtivarHook } from '../../hooks/TServicoPedido/useTServicoPedidoAtivarHook'; +import { useTServicoPedidoCancelarHook } from '../../hooks/TServicoPedido/useTServicoPedidoCancelarHook'; + +export default function TServicoPedidoDetails({ servico_pedido_id }: TServicoPedidoInterface) { + + const { setResponse } = useResponse(); + const { ativarTServicoPedido } = useTServicoPedidoAtivarHook() + const { cancelarTServicoPedido } = useTServicoPedidoCancelarHook() + + const { TServicoItemPedido, indexTServicoItemPedido } = useTServicoItemPedidoIndexHook() + const { TServicoPedido, setTServicoPedido, showTServicoPedido } = useTServicoPedidoShowHook() + + const handleSituacaoTServicoPedido = useCallback(async (pedido: any) => { + + const servicoPedido: TServicoPedidoInterface = { + + servico_pedido_id: pedido.servico_pedido_id + + } + + let response: any = null + + switch (pedido.situacao) { + + case 'C': + + response = await ativarTServicoPedido(servicoPedido) + break + + case 'F': + + response = await cancelarTServicoPedido(servicoPedido) + break + + default: + + setResponse({ + status: 422, + error: 'Situação', + detail: 'Situação não tratada' + }) + break + + } + + if (response) { + + pedido.situacao = response.situacao + + setTServicoPedido(pedido) + + } + + }, [cancelarTServicoPedido]) + + const [confirmDialog, setConfirmDialog] = useState({ + isOpen: false, + title: '', + description: '', + message: '', + confirmText: 'Confirmar', + cancelText: 'Cancelar', + onConfirm: () => { }, + onCancel: () => { }, + }) + + // 🔹 Função utilitária para abrir o dialog dinamicamente + const openConfirmDialog = ({ + title, + description, + message, + confirmText = 'Confirmar', + cancelText = 'Cancelar', + onConfirm, + onCancel, + }) => { + setConfirmDialog({ + isOpen: true, + title, + description, + message, + confirmText, + cancelText, + onConfirm: () => { + onConfirm?.() + setConfirmDialog((prev) => ({ ...prev, isOpen: false })) + }, + onCancel: () => { + onCancel?.() + setConfirmDialog((prev) => ({ ...prev, isOpen: false })) + }, + }) + } + + const TServicoPedidoShowData = useCallback(async () => { + const servicoPedido: TServicoPedidoInterface = { + servico_pedido_id: servico_pedido_id + } + const response = await showTServicoPedido(servicoPedido) + if (response.servico_pedido_id) { + TServicoPedidoItemIndexData(response.servico_pedido_id) + } + }) + + const TServicoPedidoItemIndexData = useCallback(async (servico_pedido_id: number) => { + const servicoPedido: TServicoPedidoInterface = { + servico_pedido_id: servico_pedido_id + } + await indexTServicoItemPedido(servicoPedido) + }) + + const handleCancelServicoPedidoOpenDialog = useCallback((state: boolean) => { + setIsCancelServicoPedidoDialogOpen(state) + }, []) + + useEffect(() => { + TServicoPedidoShowData() + }, []) + + const isCancelado = TServicoPedido?.situacao === 'C' + const actionLabel = isCancelado ? 'Ativar Pedido' : 'Estornar Pedido' + const actionIcon = isCancelado ? : + + return ( +
+

+ Pedido: #{TServicoPedido?.servico_pedido_id} +

+ {/* Main */} +
+
+ {/* Left column */} +
+ + +
+ {/* Right column (sidebar) */} +
+ + + + Apresentante + + + + {/* Header com avatar e link */} +
+ {/* Foto ou Iniciais */} +
+ + {GetNameInitials(TServicoPedido?.apresentante)} + +
+
+
+ {GetCapitalize(TServicoPedido?.apresentante)} +
+
+ {FormatCPF(String(TServicoPedido?.cpfcnpj_apresentante))} +
+
+
+ +
+ + + {FormatDateTime(TServicoPedido?.data_pedido)} + +
+
+
+ + + + Operador + + + +
+ {/* Foto ou Iniciais */} +
+ + {GetNameInitials(TServicoPedido?.login)} + +
+
+
+ {GetCapitalize(TServicoPedido?.login)} +
+
+ {GetCapitalize(TServicoPedido?.funcao)} +
+
+
+
+
+ + + + Controles + + + + + + + +
+
+
+ {/* Confirma o cancelamento do pedido */} + +
+ ) +} \ No newline at end of file diff --git a/src/packages/servicos/components/TServicoPedido/TServicoPedidoDetailsPagamento.tsx b/src/packages/servicos/components/TServicoPedido/TServicoPedidoDetailsPagamento.tsx new file mode 100644 index 0000000..de7f70a --- /dev/null +++ b/src/packages/servicos/components/TServicoPedido/TServicoPedidoDetailsPagamento.tsx @@ -0,0 +1,85 @@ +'use client'; + +import * as React from 'react'; + +import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; +import { Separator } from '@/components/ui/separator'; +import FormatMoney from '@/shared/actions/money/FormatMoney'; +import { ServicosPedidosSituacoesBadge } from '@/shared/components/servicosPedidosSituacoes/ServicosPedidosSituacoesBadge'; + +import TServicoPedidoDetailsPagamentoInterface from '../../interfaces/TServicoPedido/TServicoPedidoDetailsPagamentoInterface'; + +export default function TServicoPedidoDetailsPagamento({ + situacao, + items, +}: TServicoPedidoDetailsPagamentoInterface) { + + // Somas por tipo de valor + const { emolumento, taxa_judiciaria, valor_iss, fundesp } = React.useMemo(() => { + + return (items ?? []).reduce( + + (acc, item) => { + + if (item.situacao === 'F') { + + acc.emolumento += item.emolumento; + acc.taxa_judiciaria += item.taxa_judiciaria; + acc.valor_iss += item.valor_iss; + acc.fundesp += item.fundesp; + + } + + return acc; + + }, + { emolumento: 0, taxa_judiciaria: 0, valor_iss: 0, fundesp: 0 } + + ); + + }, [items]); + + // Total exibido = soma dos quatro componentes + const total = emolumento + taxa_judiciaria + valor_iss + fundesp; + + return ( + + + + Pagamento + + + +
+
+ Emolumento + {FormatMoney(emolumento)} +
+ +
+ Tx. Judiciária + {FormatMoney(taxa_judiciaria)} +
+ +
+ ISS + {FormatMoney(valor_iss)} +
+ +
+ Fundesp + {FormatMoney(fundesp)} +
+ + + +
+ Total + {FormatMoney(total)} +
+ +
+
+
+ ); +} diff --git a/src/packages/servicos/components/TServicoPedido/TServicoPedidoForm.tsx b/src/packages/servicos/components/TServicoPedido/TServicoPedidoForm.tsx index ea3e993..2cc3b78 100644 --- a/src/packages/servicos/components/TServicoPedido/TServicoPedidoForm.tsx +++ b/src/packages/servicos/components/TServicoPedido/TServicoPedidoForm.tsx @@ -1,110 +1,726 @@ 'use client'; -import { useEffect } from 'react'; +import { CreditCard, Package, UserSquare2 } from 'lucide-react'; +import { useRouter } from 'next/navigation'; +import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { Button } from '@/components/ui/button'; import { - Dialog, - DialogClose, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, -} from '@/components/ui/dialog'; + Card, + CardContent, + CardHeader, + CardTitle +} from '@/components/ui/card'; import { Form, FormControl, FormField, FormItem, FormLabel, - FormMessage, + FormMessage } from '@/components/ui/form'; import { Input } from '@/components/ui/input'; -import { ResetFormIfData } from '@/shared/actions/form/ResetFormIfData'; +import { Label } from '@/components/ui/label'; +import { Switch } from '@/components/ui/switch'; +import GEmolumentoServicoSelect from '@/packages/administrativo/components/GEmolumento/GEmolumentoServicoSelect'; +import GUsuarioSelect from '@/packages/administrativo/components/GUsuario/GUsuarioSelect'; +import TPessoaTableFormDialog from '@/packages/administrativo/components/TPessoa/TPessoaTableFormDialog'; +import TServicoTipoSelect from '@/packages/administrativo/components/TServicoTipo/TServicoTipoSelect'; +import TPessoaInterface from '@/packages/administrativo/interfaces/TPessoa/TPessoaInterface'; +import HandleSelectTServicoTipoAction from '@/packages/servicos/actions/TServicoPedido/HandleSelectTServicoTipoAction'; +import { TServicoItemPedidoFormTable } from '@/packages/servicos/components/TServicoItemPedido/TServicoItemPedidoFormTable'; +import { useTServicoItemPedidoCalculoHook } from '@/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoCalculoHook'; +import { useTServicoItemPedidoIndexHook } from '@/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoIndexHook'; +import { useTServicoItemPedidoLocalAddHook } from '@/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoLocalAddHook'; +import { useTServicoPedidoFormHook } from '@/packages/servicos/hooks/TServicoPedido/useTServicoPedidoFormHook'; +import { useTServicoPedidoLoadParamsHook } from '@/packages/servicos/hooks/TServicoPedido/useTServicoPedidoLoadParamsHook'; +import { useTServicoPedidoSaveHook } from '@/packages/servicos/hooks/TServicoPedido/useTServicoPedidoSaveHook'; +import { useTServicoPedidoShowHook } from '@/packages/servicos/hooks/TServicoPedido/useTServicoPedidoShowHook'; +import TServicoItemPedidoAddInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoAddInterface'; +import { TServicoPedidoFormInterface } from '@/packages/servicos/interfaces/TServicoPedido/TServicoPedidoFormInterface'; +import TServicoPedidoInterface from '@/packages/servicos/interfaces/TServicoPedido/TServicoPedidoInterface'; +import { FormatCPFCNPJForm } from '@/shared/actions/CPF/FormatCPFCNPJForm'; +import { UnmaskCPFCNPJForm } from '@/shared/actions/CPF/UnmaskCPFCNPJForm'; +import { parseNumberInput } from '@/shared/actions/form/parseNumberInput'; +import ConfirmDialog from '@/shared/components/confirmDialog/ConfirmDialog'; import LoadingButton from '@/shared/components/loadingButton/LoadingButton'; +import { useResponse } from '@/shared/components/response/ResponseContext'; +import { + StepNavigator, + StepNavigatorRef, + StepSection +} from '@/shared/components/step/stepNavigator'; +import TipoPagamentoSelect from '@/shared/components/tipoPagamento/TipoPagamentoSelect'; -import { useTServicoPedidoFormHook } from '../../hooks/TServicoPedido/useTServicoPedidoFormHook'; -import { TServicoPedidoFormInterface } from '../../interfaces/TServicoPedido/TServicoPedidoFormInterface'; -/** - * Formulário de cadastro/edição de Natureza - * Baseado nos campos da tabela G_NATUREZA - */ -export default function TServicoPedidoForm({ - isOpen, - data, - onClose, - onSave, - buttonIsLoading, -}: TServicoPedidoFormInterface) { + +export default function TServicoPedidoForm({ servico_pedido_id }: TServicoPedidoFormInterface) { + + const router = useRouter(); const form = useTServicoPedidoFormHook({}); + const { setValue, reset, watch } = form; - // Atualiza o formulário quando recebe dados para edição + const [isSaving, setIsSaving] = useState(false); + const [isAdding, setIsAdding] = useState(false); + const [isPessoaFormOpen, setIsPessoaFormOpen] = useState(false); + const [isSaveConfirmOpen, setIsSaveConfirmOpen] = useState(false); + const [isCancelDialogOpen, setIsCancelDialogOpen] = useState(false) + const [selectedPessoaTipo, setSelectedPessoaTipo] = useState(''); + const [shouldKeepFormOpen, setShouldKeepFormOpen] = useState(false) + + const ref = useRef(null); + + // Controles de formulário + const handleClosePessoaForm = useCallback(() => setIsPessoaFormOpen(false), []); + const handleOpenSaveConfirm = useCallback(() => setIsSaveConfirmOpen(true), []); + const handleCloseSaveConfirm = useCallback(() => setIsSaveConfirmOpen(false), []); + + // Hooks + // const playSuccess = useSoundHook("/sounds/success.mp3"); + const { setResponse } = useResponse() + const { saveTServicoPedido } = useTServicoPedidoSaveHook(); + const { showTServicoPedido } = useTServicoPedidoShowHook(); + const { TServicoItemPedidoLocal, localAddTServicoItemPedido, setLocalTServicoItemPedido } = useTServicoItemPedidoLocalAddHook(setValue); + const { addTServicoItemPedido } = useTServicoItemPedidoCalculoHook(setValue); + const { indexTServicoItemPedido } = useTServicoItemPedidoIndexHook(); + const { TServicoPedidoParams, loadParamsTServicoPedido } = + useTServicoPedidoLoadParamsHook(); + + // Acompanha as alterações, nos campos definidos + const selectedServicoTipo = watch('servico_tipo'); + const selectedEmolumento = watch('emolumento'); + + const handleFormError = useCallback((errors: any) => { + console.group("Erros de validação do formulário"); + console.log("Campos com erro:", errors); + console.groupEnd(); + }, []); + + // Envia a requisição para a API + const handleSavePedido = useCallback(async (data: TServicoPedidoInterface) => { + + // Ativa o botão de loading + setIsSaving(true); + + // Guarda a resposta da APi + const response = await saveTServicoPedido(data); + + // Desativa o botão de loading + setIsSaving(false); + + // Verifica se devo redirecionar a pagina + if (response?.servico_pedido_id > 0) { + + // Toca o som do sistema + // playSuccess() + + } + + // Verifica se devo redirecionar a pagina + if (response?.servico_pedido_id > 0 && !shouldKeepFormOpen) { + + router.replace(`/servicos/balcao/detalhes/${response.servico_pedido_id}`); + + } + + }, [saveTServicoPedido, shouldKeepFormOpen]); + + // Modal de confirmação de serviço + const handleSubmitWithConfirmation = useCallback(() => { + + // Envia o formulário + form.handleSubmit(handleSavePedido, handleFormError)(); + + }, [form, handleSavePedido, handleFormError]); + + // Busca os itens do Pedido + const fetchPedidoItens = useCallback(async (id: number) => { + + const pedidoItens = { + servico_pedido_id: id + } + + // Busca os itens do pedido + const response = await indexTServicoItemPedido(pedidoItens); + + // Verifica se os dados foram localizados + if (response?.data?.length) { + + // Atualiza os dados dos itens locais + setLocalTServicoItemPedido(response.data); + + // Atualiza os itens do formulário + setValue('itens', response.data); + + } + }, [indexTServicoItemPedido, setValue, setLocalTServicoItemPedido]); + + // Busca o pedido Principal + const fetchPedido = useCallback(async () => { + + // Busca o pedido principal + const response = await showTServicoPedido({ servico_pedido_id }); + + // Verifica se o pedido foi localizado + if (response?.servico_pedido_id) { + + // Atualiza os dados do formulário + reset(response); + + // Carrega os itens do pedido + fetchPedidoItens(response.servico_pedido_id); + + } + + }, [servico_pedido_id, showTServicoPedido, reset, fetchPedidoItens]); + + const handleAddItemWithPessoa = useCallback(async (selectedTPessoa: TPessoaInterface) => { + + // Habilita o loading + setIsAdding(true) + + // Constroi um novo item + const newItem = await addTServicoItemPedido({ + servico_tipo: selectedServicoTipo, + emolumento: selectedEmolumento, + pessoa: selectedTPessoa + }); + + // Verifica se existe um novo item + if (!newItem) return; + + // Obtem o indice atual + const index = TServicoItemPedidoLocal.length; + + // Define a posição do item + newItem.index = index + + // Atualiza o estado + localAddTServicoItemPedido(newItem); + + // Atualiza os itens do formulário + form.setValue(`itens.${index}`, newItem); + + // Desabilita o loading + setIsAdding(false) + + }, [ + addTServicoItemPedido, + selectedServicoTipo, + selectedEmolumento, + TServicoItemPedidoLocal.length, + localAddTServicoItemPedido, + form, + ]); + + // Controla o formulário de cancelamento de pedido + const handleOpenCancelDialog = useCallback( + + async () => { + + // Fecha a confirmação + setIsCancelDialogOpen(true) + + }, [] + + ) + + // Controle de redirecionamento + const handleConfirmCancel = useCallback( + + async () => { + + // Redireciona o usuário + router.replace(`/servicos/balcao/`); + + }, [] + + ) + + // Controle do formulário de cancelamento do Pedido + const handleCloseCancelDialog = useCallback( + + async () => { + + // Fecha o formulário + setIsCancelDialogOpen(false) + + }, [] + + ) + + // Controle de itens + const handleAddItemBasic = useCallback(async () => { + + setIsAdding(true) + + // Prepara e valida os dados de item do pedido + const payload: TServicoItemPedidoAddInterface = { + servico_tipo: selectedServicoTipo, + emolumento: selectedEmolumento + } + + // Verifica se os dados foram criados corretamente + if (!payload) return; + + // Obtem o resultado da adição do item + const newItem = await addTServicoItemPedido(payload); + + // Se tiver um novo item, adiciona o mesmo na tela + if (newItem) localAddTServicoItemPedido(newItem); + + setIsAdding(false) + + }, [addTServicoItemPedido, selectedServicoTipo, selectedEmolumento, localAddTServicoItemPedido]); + + // Habilita o formulário de pessoas + const handleOpenPessoaForm = useCallback((tipoPessoa: string) => { + + setSelectedPessoaTipo(tipoPessoa); + setIsPessoaFormOpen(true); + + }, []); + + // Adiciona o item a tabela e verifica se deve ou não montar a subview da linha da tabela + const handleSelectServicoTipo = useCallback(() => { + + const response = HandleSelectTServicoTipoAction({ + servico: selectedServicoTipo, + emolumento: selectedEmolumento, + onOpenPessoaForm: handleOpenPessoaForm, + onAddItem: handleAddItemBasic + }) + + // Verifica se existem erros + if (response?.status) { + setResponse(response) + } + + }, [selectedServicoTipo, selectedEmolumento, handleOpenPessoaForm, handleAddItemBasic]); + + // Cálculo automático dos totais + const calcularTotais = useCallback(() => { + if (!TServicoItemPedidoLocal || !TServicoItemPedidoLocal.length) { + setValue("valor_pedido", 0); + setValue("valor_pago", 0); + return; + } + + const total = TServicoItemPedidoLocal.reduce((acc, item) => { + const valor = Number(item.valor ?? 0); + return acc + valor; + }, 0); + + setValue("valor_pedido", total, { shouldDirty: true }); + + // opcional: manter valor pago igual ao pedido + const valorPagoAtual = watch("valor_pago"); + if (!valorPagoAtual || valorPagoAtual === 0) { + setValue("valor_pago", total, { shouldDirty: true }); + } + }, [TServicoItemPedidoLocal, setValue, watch]); + + // Dispara a busca do pedido useEffect(() => { - ResetFormIfData(form, data); - }, [data, form]); - function onError(error: any) { - console.log('Erro no formulário:', error); - } + // Se existir pedido_id, busca o pedido + if (servico_pedido_id) fetchPedido(); + + }, [servico_pedido_id, fetchPedido]); + + // Dispara a busca de itens + useEffect(() => { + + // Dispara a busca dos itens + setValue('itens', TServicoItemPedidoLocal, { shouldDirty: true }); + + }, [TServicoItemPedidoLocal, setValue]); + + // Dispara a busca de parâmetros + useEffect(() => { + + loadParamsTServicoPedido(); + + }, []); + + // Monitora mudanças na lista de itens + useEffect(() => { + calcularTotais(); + }, [TServicoItemPedidoLocal, calcularTotais]); + + // Memoriza os dados para não renderizar novamente + const sections: StepSection[] = useMemo(() => [ + { + key: 'pedido', + id: 'selectPedido', + icon: , + title: 'Pedido', + description: 'Dados gerais do pedido.' + }, + { + key: 'servicoPedidoItem', + id: 'selectServicoPedidoItem', + icon: , + title: 'Itens', + description: 'Itens/serviços do pedido.' + }, + { + key: 'payment', + id: 'selectPayment', + icon: , + title: 'Pagamento', + description: 'Forma e dados de pagamento.' + } + ], []); return ( - { - if (!open) onClose(null, false); - }} - > - - - Formulário de Gramática - - Formulário de Gramática - - - {/* Formulário principal */} -
- - {/* GRID MOBILE FIRST */} -
- {/* Palavra */} -
- ( - - Palavra - - +

Pedido

+ + +
+ + {/* Seção1 */} +
+
+ + + +

Pedido

+
+ + +
+ {/* Escrevente */} +
+ ( + + Escrevente/Tabelião + + + + )} /> - - - - )} - /> +
+ {/* Apresentante */} +
+ ( + + Apresentante + + + + )} + /> +
+ {/* CPF */} +
+ ( + + CPF/CNPJ + + { + const raw = UnmaskCPFCNPJForm(e.target.value); + field.onChange(raw); + }} + maxLength={14} + /> + + + + )} + /> +
+ {/* Pessoa Selo */} +
+ ( + + Pessoa Selo + + + + )} + /> +
+ {/* Pessoa CPF */} +
+ ( + + CPF/CNPJ + + { + const raw = UnmaskCPFCNPJForm(e.target.value); + field.onChange(raw); + }} + maxLength={14} + /> + + + + )} + /> +
+ +
+
+
+ + {/* Seção 2 */} + + +

Itens

+
+ +
+
+ ( + + Serviços + + + + )} + /> +
+
+ ( + + Emolumentos + + + + )} + /> +
+
+ +
+
+ +
+
+
+
+ + {/* Seção 3 */} + + +

Pagamento

+
+ +
+
+ ( + + Requerente + + + + )} + /> +
+
+ ( + + CPF/CNPJ + + { + const raw = UnmaskCPFCNPJForm(e.target.value); + field.onChange(raw); + }} + maxLength={14} + /> + + + )} + /> +
+
+ ( + + Valor do Pedido + + field.onChange(parseNumberInput(e))} + readOnly={true} + /> + + + + )} + /> +
+
+ ( + + Valor Pago + + field.onChange(parseNumberInput(e))} /> + + + + )} + /> +
+
+ ( + + Forma Pagamento + + + + )} + /> +
+
+
+
-
- {/* Rodapé */} - - - - - - - - - -
+ + + {/* Sidebar */} + +
+ + + {/* Cofirmação de envio de dados */} + {isSaveConfirmOpen && ( + + )} + + {/* Confirma o cancelamento do pedido */} + {isCancelDialogOpen && ( + + )} + + {/* Modal TPessoa */} + {isPessoaFormOpen && ( + + )} + + +
); } diff --git a/src/packages/servicos/components/TServicoPedido/TServicoPedidoIndex.tsx b/src/packages/servicos/components/TServicoPedido/TServicoPedidoIndex.tsx index dedf0e0..3615c71 100644 --- a/src/packages/servicos/components/TServicoPedido/TServicoPedidoIndex.tsx +++ b/src/packages/servicos/components/TServicoPedido/TServicoPedidoIndex.tsx @@ -109,7 +109,7 @@ export default function TServicoPedidoIndex() { * Busca inicial dos dados */ useEffect(() => { - // indexTServicoPedido(); + indexTServicoPedido(); }, []); return ( @@ -119,12 +119,13 @@ export default function TServicoPedidoIndex() { title={'Pedidos'} description={'Pedidos de Autenticação/Reconhecimento'} buttonText={'Novo pedido'} - buttonAction={() => { - handleOpenForm(null); - }} + href='/servicos/balcao/pedido' /> {/* Tabela de andamentos */} - + {/* Modal de confirmação */} {isConfirmOpen && ( - + + + + +
); } diff --git a/src/packages/servicos/data/TServicoItemPedido/TServicoItemPedidoAtivarData.ts b/src/packages/servicos/data/TServicoItemPedido/TServicoItemPedidoAtivarData.ts new file mode 100644 index 0000000..b451321 --- /dev/null +++ b/src/packages/servicos/data/TServicoItemPedido/TServicoItemPedidoAtivarData.ts @@ -0,0 +1,22 @@ +import TServicoItemPedidoInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoIntefarce'; +import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; +import API from '@/shared/services/api/Api'; +import { Methods } from '@/shared/services/api/enums/ApiMethodEnum'; +import ApiResponseInterface from '@/shared/services/api/interfaces/ApiResponseInterface'; + + +async function executeTServicoItemPedidoAtivarData(data: TServicoItemPedidoInterface): Promise { + + const api = new API(); + + return api.send({ + + method: Methods.PUT, + endpoint: `servicos/balcao/t_servico_itempedido/${data.servico_itempedido_id}/ativar`, + body: data, + + }); + +} + +export const TServicoItemPedidoAtivarData = withClientErrorHandler(executeTServicoItemPedidoAtivarData); diff --git a/src/packages/servicos/data/TServicoItemPedido/TServicoItemPedidoCancelarData.ts b/src/packages/servicos/data/TServicoItemPedido/TServicoItemPedidoCancelarData.ts new file mode 100644 index 0000000..51cdda2 --- /dev/null +++ b/src/packages/servicos/data/TServicoItemPedido/TServicoItemPedidoCancelarData.ts @@ -0,0 +1,22 @@ +import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; +import API from '@/shared/services/api/Api'; +import { Methods } from '@/shared/services/api/enums/ApiMethodEnum'; +import ApiResponseInterface from '@/shared/services/api/interfaces/ApiResponseInterface'; + +import TServicoItemPedidoInterface from '../../interfaces/TServicoItemPedido/TServicoItemPedidoIntefarce'; + +async function executeTServicoItemPedidoCancelarData(data: TServicoItemPedidoInterface): Promise { + + const api = new API(); + + return api.send({ + + method: Methods.PUT, + endpoint: `servicos/balcao/t_servico_itempedido/${data.servico_itempedido_id}/cancelar`, + body: data, + + }); + +} + +export const TServicoItemPedidoCancelarData = withClientErrorHandler(executeTServicoItemPedidoCancelarData); diff --git a/src/packages/servicos/data/TServicoItemPedido/TServicoItemPedidoIndexData.ts b/src/packages/servicos/data/TServicoItemPedido/TServicoItemPedidoIndexData.ts index db1e311..26ee8b0 100644 --- a/src/packages/servicos/data/TServicoItemPedido/TServicoItemPedidoIndexData.ts +++ b/src/packages/servicos/data/TServicoItemPedido/TServicoItemPedidoIndexData.ts @@ -1,15 +1,16 @@ +import TServicoItemPedidoInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoIntefarce'; import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; import API from '@/shared/services/api/Api'; import { Methods } from '@/shared/services/api/enums/ApiMethodEnum'; import ApiResponseInterface from '@/shared/services/api/interfaces/ApiResponseInterface'; -async function executeTServicoItemPedidoIndexData(): Promise { - const api = new API(); +async function executeTServicoItemPedidoIndexData(data: TServicoItemPedidoInterface): Promise { + const api = new API(); return api.send({ method: Methods.GET, - endpoint: `servicos/t_servico_itempedido/`, + endpoint: `servicos/balcao/t_servico_itempedido/pedido/${data.servico_pedido_id}`, }); } -export const TServicoItemPedidoIndexData = withClientErrorHandler(executeTServicoItemPedidoIndexData); +export const TServicoItemPedidoIndexData = withClientErrorHandler(executeTServicoItemPedidoIndexData); \ No newline at end of file diff --git a/src/packages/servicos/data/TServicoItemPedido/TServicoItemPedidoShowData.ts b/src/packages/servicos/data/TServicoItemPedido/TServicoItemPedidoShowData.ts new file mode 100644 index 0000000..1282797 --- /dev/null +++ b/src/packages/servicos/data/TServicoItemPedido/TServicoItemPedidoShowData.ts @@ -0,0 +1,16 @@ +import TServicoItemPedidoInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoIntefarce'; +import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; +import API from '@/shared/services/api/Api'; +import { Methods } from '@/shared/services/api/enums/ApiMethodEnum'; +import ApiResponseInterface from '@/shared/services/api/interfaces/ApiResponseInterface'; + + +async function executeTServicoItemPedidoShowData(data: TServicoItemPedidoInterface): Promise { + const api = new API(); + return api.send({ + method: Methods.GET, + endpoint: `servicos/balcao/t_servico_itempedido/pedido/${data.servico_pedido_id}`, + }); +} + +export const TServicoItemPedidoShowData = withClientErrorHandler(executeTServicoItemPedidoShowData); diff --git a/src/packages/servicos/data/TServicoPedido/TServicoPedidoAtivarData.ts b/src/packages/servicos/data/TServicoPedido/TServicoPedidoAtivarData.ts new file mode 100644 index 0000000..541ef37 --- /dev/null +++ b/src/packages/servicos/data/TServicoPedido/TServicoPedidoAtivarData.ts @@ -0,0 +1,19 @@ +import TServicoPedidoInterface from '@/packages/servicos/interfaces/TServicoPedido/TServicoPedidoInterface'; +import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; +import API from '@/shared/services/api/Api'; +import { Methods } from '@/shared/services/api/enums/ApiMethodEnum'; +import ApiResponseInterface from '@/shared/services/api/interfaces/ApiResponseInterface'; + + +async function executeTServicoPedidoAtivarData(data: TServicoPedidoInterface): Promise { + + const api = new API(); + + return api.send({ + method: Methods.PUT, + endpoint: `servicos/balcao/t_servico_pedido/${data.servico_pedido_id}/ativar`, + body: data, + }); +} + +export const TServicoPedidoAtivarData = withClientErrorHandler(executeTServicoPedidoAtivarData); diff --git a/src/packages/servicos/data/TServicoPedido/TServicoPedidoCancelarData.ts b/src/packages/servicos/data/TServicoPedido/TServicoPedidoCancelarData.ts new file mode 100644 index 0000000..e0f10ce --- /dev/null +++ b/src/packages/servicos/data/TServicoPedido/TServicoPedidoCancelarData.ts @@ -0,0 +1,19 @@ +import TServicoPedidoInterface from '@/packages/servicos/interfaces/TServicoPedido/TServicoPedidoInterface'; +import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; +import API from '@/shared/services/api/Api'; +import { Methods } from '@/shared/services/api/enums/ApiMethodEnum'; +import ApiResponseInterface from '@/shared/services/api/interfaces/ApiResponseInterface'; + + +async function executeTServicoPedidoCancelarData(data: TServicoPedidoInterface): Promise { + + const api = new API(); + + return api.send({ + method: Methods.PUT, + endpoint: `servicos/balcao/t_servico_pedido/${data.servico_pedido_id}/cancelar`, + body: data, + }); +} + +export const TServicoPedidoCancelarData = withClientErrorHandler(executeTServicoPedidoCancelarData); diff --git a/src/packages/servicos/data/TServicoPedido/TServicoPedidoDeleteData.ts b/src/packages/servicos/data/TServicoPedido/TServicoPedidoDeleteData.ts index 226517a..f6f9cb3 100644 --- a/src/packages/servicos/data/TServicoPedido/TServicoPedidoDeleteData.ts +++ b/src/packages/servicos/data/TServicoPedido/TServicoPedidoDeleteData.ts @@ -10,7 +10,7 @@ async function executeTServicoPedidoDeleteData(data: TServicoPedidoInterface): P return api.send({ method: Methods.DELETE, - endpoint: `servico/t_servico_pedido/${data.servico_pedido_id}`, + endpoint: `servicos/balcao/t_servico_pedido/${data.servico_pedido_id}`, }); } diff --git a/src/packages/servicos/data/TServicoPedido/TServicoPedidoIndexData.ts b/src/packages/servicos/data/TServicoPedido/TServicoPedidoIndexData.ts index 5cfa3e9..fe48526 100644 --- a/src/packages/servicos/data/TServicoPedido/TServicoPedidoIndexData.ts +++ b/src/packages/servicos/data/TServicoPedido/TServicoPedidoIndexData.ts @@ -8,7 +8,7 @@ async function executeTServicoPedidoIndexData(): Promise { return api.send({ method: Methods.GET, - endpoint: `servico/t_servico_pedido/`, + endpoint: `servicos/balcao/t_servico_pedido/`, }); } diff --git a/src/packages/servicos/data/TServicoPedido/TServicoPedidoLoadParamsData.ts b/src/packages/servicos/data/TServicoPedido/TServicoPedidoLoadParamsData.ts new file mode 100644 index 0000000..aeb1824 --- /dev/null +++ b/src/packages/servicos/data/TServicoPedido/TServicoPedidoLoadParamsData.ts @@ -0,0 +1,15 @@ +import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; +import API from '@/shared/services/api/Api'; +import { Methods } from '@/shared/services/api/enums/ApiMethodEnum'; +import ApiResponseInterface from '@/shared/services/api/interfaces/ApiResponseInterface'; + +async function executeTServicoPedidoLoadParamsData(): Promise { + const api = new API(); + + return api.send({ + method: Methods.GET, + endpoint: `servicos/balcao/t_servico_pedido/load-params`, + }); +} + +export const TServicoPedidoLoadParamsData = withClientErrorHandler(executeTServicoPedidoLoadParamsData); diff --git a/src/packages/servicos/data/TServicoPedido/TServicoPedidoSaveData.ts b/src/packages/servicos/data/TServicoPedido/TServicoPedidoSaveData.ts index f3eed76..2123ed6 100644 --- a/src/packages/servicos/data/TServicoPedido/TServicoPedidoSaveData.ts +++ b/src/packages/servicos/data/TServicoPedido/TServicoPedidoSaveData.ts @@ -15,7 +15,7 @@ async function executeTServicoPedidoSaveData(data: TServicoPedidoInterface): Pro // Executa a requisição para a API com o método apropriado e envia os dados no corpo return api.send({ method: isUpdate ? Methods.PUT : Methods.POST, // PUT se atualizar, POST se criar - endpoint: `servico/t_servico_pedido/${data.servico_pedido_id || ''}`, // endpoint dinâmico + endpoint: `servicos/balcao/t_servico_pedido/${data.servico_pedido_id || ''}`, // endpoint dinâmico body: data, // payload enviado para a API }); } diff --git a/src/packages/servicos/data/TServicoPedido/TServicoPedidoShowData.ts b/src/packages/servicos/data/TServicoPedido/TServicoPedidoShowData.ts new file mode 100644 index 0000000..cd2e8d7 --- /dev/null +++ b/src/packages/servicos/data/TServicoPedido/TServicoPedidoShowData.ts @@ -0,0 +1,16 @@ +import TServicoPedidoInterface from '@/packages/servicos/interfaces/TServicoPedido/TServicoPedidoInterface'; +import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; +import API from '@/shared/services/api/Api'; +import { Methods } from '@/shared/services/api/enums/ApiMethodEnum'; +import ApiResponseInterface from '@/shared/services/api/interfaces/ApiResponseInterface'; + + +async function executeTServicoPedidoShowData(data: TServicoPedidoInterface): Promise { + const api = new API(); + return api.send({ + method: Methods.GET, + endpoint: `servicos/balcao/t_servico_pedido/${data.servico_pedido_id}`, + }); +} + +export const TServicoPedidoShowData = withClientErrorHandler(executeTServicoPedidoShowData); diff --git a/src/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoAtivarHook.ts b/src/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoAtivarHook.ts new file mode 100644 index 0000000..5b1b05a --- /dev/null +++ b/src/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoAtivarHook.ts @@ -0,0 +1,33 @@ +'use client'; + +import { useState } from 'react'; + +import TServicoItemPedidoInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoIntefarce'; +import { TServicoItemPedidoAtivarService } from '@/packages/servicos/services/TServicoItemPedido/TServicoItemPedidoAtivarService'; +import { useResponse } from '@/shared/components/response/ResponseContext'; + + +export const useTServicoItemPedidoAtivarHook = () => { + + const { setResponse } = useResponse(); + + const [TServicoItemPedido, setTServicoItemPedido] = useState(null); + + const [isOpen, setIsOpen] = useState(false); + + const ativarTServicoItemPedido = async (data: TServicoItemPedidoInterface) => { + + const response = await TServicoItemPedidoAtivarService(data); + + setTServicoItemPedido(response.data); + + setResponse(response); + + setIsOpen(false); + + return response.data; + + }; + + return { TServicoItemPedido, ativarTServicoItemPedido, isOpen, setIsOpen }; +}; \ No newline at end of file diff --git a/src/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoCalculoHook.ts b/src/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoCalculoHook.ts new file mode 100644 index 0000000..7a1646b --- /dev/null +++ b/src/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoCalculoHook.ts @@ -0,0 +1,85 @@ +'use client'; + +import { useState } from 'react'; +import { FieldValues, UseFormSetValue } from 'react-hook-form'; + + +import { GCalculoServicoService } from '@/packages/administrativo/services/GCalculo/GCalculoServicoService'; +import TServicoPedidoItemPreparePayload from '@/packages/servicos/actions/TServicoPedidoItem/TServicoPedidoItemPreparePayload'; +import TServicoItemPedidoAddInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoAddInterface'; +import TServicoItemPedidoCalculoResponseInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoCalculoResponseInterface'; +import { useResponse } from '@/shared/components/response/ResponseContext'; + + + +export function useTServicoItemPedidoCalculoHook(setValue?: UseFormSetValue) { + + const { setResponse } = useResponse(); + + const [TServicoItemPedido, setTServicoItemPedido] = useState([]); + + const addTServicoItemPedido = async (data: TServicoItemPedidoAddInterface) => { + + // Trata os dados do payload + const payload = TServicoPedidoItemPreparePayload(data); + + if (payload.status) { + + setResponse(payload) + + return; + + } + + // Realiza a busca do item + const response = await GCalculoServicoService(payload, data); + + // Verifico se tenho código de resposta + if (response.status) { + + // Exibo a resposta em tela + setResponse(response) + + return; + + } + + // Verifica se tem status de erro + if (response.status) { + + return { + + 'status': response.status, + 'message': 'Erro ao processar dados' + + }; + + } + + // Atualiza o estado com fallback seguro + setTServicoItemPedido((prev) => { + + const safePrev = Array.isArray(prev) ? prev : []; + const novoArray = [...safePrev, response]; + + if (setValue) { + + // Protege contra sobrescrita incorreta do formulário + setValue('itens', novoArray, { shouldDirty: true }); + + } + + return novoArray; + + }); + + return response; + + }; + + return { + TServicoItemPedido, + setTServicoItemPedido, + addTServicoItemPedido, + }; +}; diff --git a/src/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoCancelarHook.ts b/src/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoCancelarHook.ts new file mode 100644 index 0000000..e0f3f64 --- /dev/null +++ b/src/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoCancelarHook.ts @@ -0,0 +1,32 @@ +'use client'; + +import { useState } from 'react'; + +import TServicoItemPedidoInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoIntefarce'; +import { TServicoItemPedidoCancelarService } from '@/packages/servicos/services/TServicoItemPedido/TServicoItemPedidoCancelarService'; +import { useResponse } from '@/shared/components/response/ResponseContext'; + +export const useTServicoItemPedidoCancelarHook = () => { + + const { setResponse } = useResponse(); + + const [TServicoItemPedido, setTServicoItemPedido] = useState(null); + + const [isOpen, setIsOpen] = useState(false); + + const cancelarTServicoItemPedido = async (data: TServicoItemPedidoInterface) => { + + const response = await TServicoItemPedidoCancelarService(data); + + setTServicoItemPedido(response.data); + + setResponse(response); + + setIsOpen(false); + + return response.data; + + }; + + return { TServicoItemPedido, cancelarTServicoItemPedido, isOpen, setIsOpen }; +}; \ No newline at end of file diff --git a/src/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoIndexHook.ts b/src/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoIndexHook.ts index 002c56d..79d74b6 100644 --- a/src/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoIndexHook.ts +++ b/src/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoIndexHook.ts @@ -2,23 +2,29 @@ import { useState } from 'react'; +import TServicoItemPedidoIndexResponseInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoCalculoResponseInterface'; +import TServicoItemPedidoInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoIntefarce'; +import { TServicoItemPedidoIndexService } from '@/packages/servicos/services/TServicoItemPedido/TServicoItemPedidoIndexService'; import { useResponse } from '@/shared/components/response/ResponseContext'; -import TServicoItemPedidoInterface from '../../interfaces/TServicoItemPedido/TServicoItemPedidoIntefarce'; -import { TServicoItemPedidoIndexService } from '../../services/TServicoItemPedido/TServicoItemPedidoIndexService'; - export const useTServicoItemPedidoIndexHook = () => { + const { setResponse } = useResponse(); - const [TServicoItemPedido, setTServicoItemPedido] = useState([]); + const [TServicoItemPedido, setTServicoItemPedido] = useState([]); + + const indexTServicoItemPedido = async (data: TServicoItemPedidoInterface) => { + + const response = await TServicoItemPedidoIndexService(data); - const indexTServicoItemPedido = async () => { - const response = await TServicoItemPedidoIndexService(); - // Armazena os dados consultados setTServicoItemPedido(response.data); - // Define a resposta (toast, modal, feedback, etc.) + setResponse(response); + + // Retorno imediato dos valores + return response + }; return { diff --git a/src/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoLocalAddHook.ts b/src/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoLocalAddHook.ts new file mode 100644 index 0000000..cad206b --- /dev/null +++ b/src/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoLocalAddHook.ts @@ -0,0 +1,41 @@ +'use client'; + +import { useState } from 'react'; +import { FieldValues, UseFormSetValue } from 'react-hook-form'; + +import { default as TServicoItemPedidoAddResponseInterface, default as TServicoItemPedidoIndexResponseInterface } from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoCalculoResponseInterface'; + + +export function useTServicoItemPedidoLocalAddHook(setValue?: UseFormSetValue) { + + const [TServicoItemPedidoLocal, setLocalTServicoItemPedido] = useState([]); + + const localAddTServicoItemPedido = (item: TServicoItemPedidoAddResponseInterface) => { + + setLocalTServicoItemPedido((prev) => { + + const updated = [...prev, item]; + + if (setValue) setValue("itens", updated); + + return updated; + + }); + + }; + + const localClearTServicoItemPedido = () => { + + setLocalTServicoItemPedido([]); + + if (setValue) setValue("itens", []); + + }; + + return { + TServicoItemPedidoLocal, + localAddTServicoItemPedido, + setLocalTServicoItemPedido, + localClearTServicoItemPedido, + }; +}; diff --git a/src/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoShowHook.ts b/src/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoShowHook.ts new file mode 100644 index 0000000..d065be8 --- /dev/null +++ b/src/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoShowHook.ts @@ -0,0 +1,28 @@ +import { useState } from 'react'; + +import TServicoItemPedidoInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoIntefarce'; +import { TServicoItemPedidoShowService } from '@/packages/servicos/services/TServicoItemPedido/TServicoItemPedidoShowService'; +import { useResponse } from '@/shared/components/response/ResponseContext'; + + + +export const useTServicoItemPedidoShowHook = () => { + + const { setResponse } = useResponse(); + + const [TServicoItemPedido, setTServicoItemPedido] = useState(); + + const showTServicoItemPedido = async (data: TServicoItemPedidoInterface) => { + + const response = await TServicoItemPedidoShowService(data); + + setTServicoItemPedido(response.data); + + setResponse(response); + + return response.data + + }; + + return { TServicoItemPedido, showTServicoItemPedido }; +}; diff --git a/src/packages/servicos/hooks/TServicoPedido/useTServicoPedidoAtivarHook.ts b/src/packages/servicos/hooks/TServicoPedido/useTServicoPedidoAtivarHook.ts new file mode 100644 index 0000000..5bbfe0d --- /dev/null +++ b/src/packages/servicos/hooks/TServicoPedido/useTServicoPedidoAtivarHook.ts @@ -0,0 +1,37 @@ +'use client'; + +import { useState } from 'react'; + +import TServicoPedidoInterface from '@/packages/servicos/interfaces/TServicoPedido/TServicoPedidoInterface'; +import { TServicoPedidoAtivarService } from '@/packages/servicos/services/TServicoPedido/TServicoPedidoAtivarService'; +import { useResponse } from '@/shared/components/response/ResponseContext'; + +export const useTServicoPedidoAtivarHook = () => { + + const { setResponse } = useResponse(); + + const [TServicoPedido, setTServicoPedido] = useState(null); + + // controla se o formulário está aberto ou fechado + const [isOpen, setIsOpen] = useState(false); + + const ativarTServicoPedido = async (data: TServicoPedidoInterface) => { + + const response = await TServicoPedidoAtivarService(data); + + // Armazena os dados da resposta + setTServicoPedido(response.data); + + // Define os dados da resposta (toast, modal, etc.) + setResponse(response); + + // Fecha o formulário automaticamente após salvar + setIsOpen(false); + + // Retorna os valores de forma imediata + return response.data; + + }; + + return { TServicoPedido, ativarTServicoPedido, isOpen, setIsOpen }; +}; diff --git a/src/packages/servicos/hooks/TServicoPedido/useTServicoPedidoCancelarHook.ts b/src/packages/servicos/hooks/TServicoPedido/useTServicoPedidoCancelarHook.ts new file mode 100644 index 0000000..b0e1cc2 --- /dev/null +++ b/src/packages/servicos/hooks/TServicoPedido/useTServicoPedidoCancelarHook.ts @@ -0,0 +1,37 @@ +'use client'; + +import { useState } from 'react'; + +import TServicoPedidoInterface from '@/packages/servicos/interfaces/TServicoPedido/TServicoPedidoInterface'; +import { TServicoPedidoCancelarService } from '@/packages/servicos/services/TServicoPedido/TServicoPedidoCancelarService'; +import { useResponse } from '@/shared/components/response/ResponseContext'; + +export const useTServicoPedidoCancelarHook = () => { + + const { setResponse } = useResponse(); + + const [TServicoPedido, setTServicoPedido] = useState(null); + + // controla se o formulário está aberto ou fechado + const [isOpen, setIsOpen] = useState(false); + + const cancelarTServicoPedido = async (data: TServicoPedidoInterface) => { + + const response = await TServicoPedidoCancelarService(data); + + // Armazena os dados da resposta + setTServicoPedido(response.data); + + // Define os dados da resposta (toast, modal, etc.) + setResponse(response); + + // Fecha o formulário automaticamente após salvar + setIsOpen(false); + + // Retorna os valores de forma imediata + return response.data; + + }; + + return { TServicoPedido, cancelarTServicoPedido, isOpen, setIsOpen }; +}; diff --git a/src/packages/servicos/hooks/TServicoPedido/useTServicoPedidoFormHook.ts b/src/packages/servicos/hooks/TServicoPedido/useTServicoPedidoFormHook.ts index 697c882..39edf22 100644 --- a/src/packages/servicos/hooks/TServicoPedido/useTServicoPedidoFormHook.ts +++ b/src/packages/servicos/hooks/TServicoPedido/useTServicoPedidoFormHook.ts @@ -1,13 +1,26 @@ import { zodResolver } from '@hookform/resolvers/zod'; import { useForm } from 'react-hook-form'; -import { TServicoPedidoFormValues, TServicoPedidoSchema } from '../../schemas/TServicoPedido/TServicoPedidoSchema'; +import { TServicoPedidoFormSchema, TServicoPedidoFormValues } from '@/packages/servicos/schemas/TServicoPedido/TServicoPedidoFormSchema'; export function useTServicoPedidoFormHook(defaults?: Partial) { return useForm({ - resolver: zodResolver(TServicoPedidoSchema), + resolver: zodResolver(TServicoPedidoFormSchema), defaultValues: { - servico_pedido_id: 0, + escrevente_id: 0, + apresentante: "", + cpfcnpj_apresentante: "", + selo_pessoa_nome: "", + selo_pessoa_cpfcnpj: "", + servico_tipo: null, + emolumento: null, + itens: [], + pagador_nome: "", + pagador_cpfcnpj: "", + valor_pedido: 0, + valor_pago: 0, + situacao: "F", + tipo_pagamento: null, ...defaults, }, }); diff --git a/src/packages/servicos/hooks/TServicoPedido/useTServicoPedidoLoadParamsHook.ts b/src/packages/servicos/hooks/TServicoPedido/useTServicoPedidoLoadParamsHook.ts new file mode 100644 index 0000000..9cbede3 --- /dev/null +++ b/src/packages/servicos/hooks/TServicoPedido/useTServicoPedidoLoadParamsHook.ts @@ -0,0 +1,22 @@ +'use client'; + +import { useState } from 'react'; + + +import GConfigInterface from '@/shared/interfaces/GConfigInterface'; + +import { TServicoPedidoLoadParamsService } from '../../services/TServicoPedido/TServicoPedidoLoadParamsService'; + +export const useTServicoPedidoLoadParamsHook = () => { + const [TServicoPedidoParams, setTServicoPedidoParams] = useState([]); + + const loadParamsTServicoPedido = async () => { + const response = await TServicoPedidoLoadParamsService(); + setTServicoPedidoParams(response.data); + }; + + return { + TServicoPedidoParams, + loadParamsTServicoPedido, + }; +}; diff --git a/src/packages/servicos/hooks/TServicoPedido/useTServicoPedidoSaveHook.ts b/src/packages/servicos/hooks/TServicoPedido/useTServicoPedidoSaveHook.ts index 8883f3b..e72dd90 100644 --- a/src/packages/servicos/hooks/TServicoPedido/useTServicoPedidoSaveHook.ts +++ b/src/packages/servicos/hooks/TServicoPedido/useTServicoPedidoSaveHook.ts @@ -2,12 +2,12 @@ import { useState } from 'react'; +import TServicoPedidoInterface from '@/packages/servicos/interfaces/TServicoPedido/TServicoPedidoInterface'; +import { TServicoPedidoSaveService } from '@/packages/servicos/services/TServicoPedido/TServicoPedidoSaveService'; import { useResponse } from '@/shared/components/response/ResponseContext'; -import TServicoPedidoInterface from '../../interfaces/TServicoPedido/TServicoPedidoInterface'; -import { TServicoPedidoSaveService } from '../../services/TServicoPedido/TServicoPedidoSaveService'; - export const useTServicoPedidoSaveHook = () => { + const { setResponse } = useResponse(); const [TServicoPedido, setTServicoPedido] = useState(null); @@ -16,6 +16,7 @@ export const useTServicoPedidoSaveHook = () => { const [isOpen, setIsOpen] = useState(false); const saveTServicoPedido = async (data: TServicoPedidoInterface) => { + const response = await TServicoPedidoSaveService(data); // Armazena os dados da resposta @@ -29,6 +30,7 @@ export const useTServicoPedidoSaveHook = () => { // Retorna os valores de forma imediata return response.data; + }; return { TServicoPedido, saveTServicoPedido, isOpen, setIsOpen }; diff --git a/src/packages/servicos/hooks/TServicoPedido/useTServicoPedidoShowHook.ts b/src/packages/servicos/hooks/TServicoPedido/useTServicoPedidoShowHook.ts new file mode 100644 index 0000000..6d097b3 --- /dev/null +++ b/src/packages/servicos/hooks/TServicoPedido/useTServicoPedidoShowHook.ts @@ -0,0 +1,29 @@ +import { useState } from 'react'; + + +import TServicoPedidoInterface from '@/packages/servicos/interfaces/TServicoPedido/TServicoPedidoInterface'; +import { TServicoPedidoShowService } from '@/packages/servicos/services/TServicoPedido/TServicoPedidoShowService'; +import { useResponse } from '@/shared/components/response/ResponseContext'; + + +export const useTServicoPedidoShowHook = () => { + + const { setResponse } = useResponse(); + + const [TServicoPedido, setTServicoPedido] = useState(); + + const showTServicoPedido = async (data: TServicoPedidoInterface) => { + + const response = await TServicoPedidoShowService(data); + + setTServicoPedido(response.data); + + setResponse(response); + + return response.data + + }; + + return { TServicoPedido, setTServicoPedido, showTServicoPedido }; + +}; diff --git a/src/packages/servicos/interfaces/TPessoaCartao/TPessoaCartaoFormInterface.ts b/src/packages/servicos/interfaces/TPessoaCartao/TPessoaCartaoFormInterface.ts new file mode 100644 index 0000000..4fda09d --- /dev/null +++ b/src/packages/servicos/interfaces/TPessoaCartao/TPessoaCartaoFormInterface.ts @@ -0,0 +1,8 @@ +import { UseFormReturn } from "react-hook-form"; + +import { TServicoPedidoFormValues } from "@/packages/servicos/schemas/TServicoPedido/TServicoPedidoFormSchema"; + +export default interface TPessoaCartaoFormInterface { + index: number; + form: UseFormReturn; +} \ No newline at end of file diff --git a/src/packages/servicos/interfaces/TServico/TServicoInterface.ts b/src/packages/servicos/interfaces/TServico/TServicoInterface.ts new file mode 100644 index 0000000..a52ef70 --- /dev/null +++ b/src/packages/servicos/interfaces/TServico/TServicoInterface.ts @@ -0,0 +1,4 @@ +export default interface TServicoInterface { + servico_pedido_id: number; + escrevente_id: number; +} diff --git a/src/packages/servicos/interfaces/TServico/TServicoItemPedidoSubviewInterface.ts b/src/packages/servicos/interfaces/TServico/TServicoItemPedidoSubviewInterface.ts new file mode 100644 index 0000000..bacbf7f --- /dev/null +++ b/src/packages/servicos/interfaces/TServico/TServicoItemPedidoSubviewInterface.ts @@ -0,0 +1,7 @@ +import TServicoTipoInterface from "@/app/(protected)/(cadastros)/cadastros/_interfaces/TServicoTipoInterface"; +import TPessoaInterface from "@/packages/administrativo/interfaces/TPessoa/TPessoaInterface"; + +export default interface TServicoItemPedidoSubviewInterface { + servico: TServicoTipoInterface; + pessoa: TPessoaInterface; +} diff --git a/src/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoAddInterface.ts b/src/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoAddInterface.ts new file mode 100644 index 0000000..45367db --- /dev/null +++ b/src/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoAddInterface.ts @@ -0,0 +1,28 @@ +import TServicoTipoInterface from "@/app/(protected)/(cadastros)/cadastros/_interfaces/TServicoTipoInterface"; +import GEmolumentoInterface from "@/packages/administrativo/interfaces/GEmolumento/GEmolumentoInterface"; +import TPessoaInterface from "@/packages/administrativo/interfaces/TPessoa/TPessoaInterface"; + +export default interface TServicoItemPedidoAddInterface { + /** + * Índice local na lista de itens (usado no front) + */ + index?: number; + + qtd?: number; + valor_documento?: number; + + /** + * Emolumento selecionado + */ + emolumento: GEmolumentoInterface; + + /** + * Serviço/tipo de serviço selecionado + */ + servico_tipo: TServicoTipoInterface; + + /** + * Pessoa vinculada ao item (quando aplicável) + */ + pessoa?: TPessoaInterface; +} diff --git a/src/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoCalculoResponseInterface.ts b/src/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoCalculoResponseInterface.ts new file mode 100644 index 0000000..3ccd7b1 --- /dev/null +++ b/src/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoCalculoResponseInterface.ts @@ -0,0 +1,29 @@ +import TServicoItemPedidoSubviewInterface from "../TServico/TServicoItemPedidoSubviewInterface"; + +export default interface TServicoItemPedidoCalculoResponseInterface { + index?: number; + + emolumento_id: number; + emolumento_item_id: number; + servico_tipo_id: number; + + tipo_item: string; + descricao: string; + tabela: string; + situacao: string; + + qtd: number; + valor: number; + + emolumento: number; + fundesp: number; + taxa_judiciaria: number; + valor_iss: number; + + pessoa_id?: number; + + /** + * Subview com serviço + pessoa (usado na linha expandida) + */ + subview?: TServicoItemPedidoSubviewInterface; +} diff --git a/src/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoFormInterface.ts b/src/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoFormInterface.ts deleted file mode 100644 index e418f33..0000000 --- a/src/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoFormInterface.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { TServicoItemPedidoFormValues } from '../../schemas/TServicoItemPedido/TServicoItemPedidoSchema'; - -export interface TServicoItemPedidoFormInterface { - isOpen: boolean; - data: TServicoItemPedidoFormValues | null; - onClose: (item: null, isFormStatus: boolean) => void; - onSave: (data: TServicoItemPedidoFormValues) => void; - buttonIsLoading: boolean; -} diff --git a/src/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoFormTableInterface.ts b/src/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoFormTableInterface.ts new file mode 100644 index 0000000..a4d96f1 --- /dev/null +++ b/src/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoFormTableInterface.ts @@ -0,0 +1,13 @@ +import { UseFormReturn } from "react-hook-form"; + +import TServicoItemPedidoAddResponseInterface from "@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoCalculoResponseInterface"; +import GConfigInterface from "@/shared/interfaces/GConfigInterface"; + +import { TServicoPedidoFormValues } from "../../schemas/TServicoPedido/TServicoPedidoFormSchema"; + + +export default interface TServicoItemPedidoFormTableInterface { + data: TServicoItemPedidoAddResponseInterface[]; + form: UseFormReturn; + params: GConfigInterface[]; +} \ No newline at end of file diff --git a/src/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoIntefarce.ts b/src/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoIntefarce.ts index d4dec7c..3622224 100644 --- a/src/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoIntefarce.ts +++ b/src/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoIntefarce.ts @@ -1,66 +1,91 @@ +import TServicoItemPedidoSubviewInterface from "../TServico/TServicoItemPedidoSubviewInterface"; + export default interface TServicoItemPedidoInterface { - servico_itempedido_id?: number - servico_pedido_id?: number - servico_tipo_id?: number - valor?: number - qtd?: number - pessoa_id?: number - impressao_etiqueta?: string - situacao?: string - etiqueta_numero?: number - pessoa_auxiliar_id?: number - pessoa_sp_abono_rep?: string - tipo_item?: string - imprimir?: string - observacao?: string - impressao_direta?: string - selo_livro_id?: number - emolumento?: number - fundesp?: number - taxa_judiciaria?: number - desconto?: number - desc_complementar?: string - valor_manual?: string - valor_documento?: number - outra_taxa1?: number - emolumento_item_id?: number - certidao_impressa?: string - certidao_ato_id?: number - emolumento_id?: number - certidao_previsao?: string | Date - certidao_ato_antigo?: string - certidao_data_emissao?: string | Date - certidao_texto?: string | null // BLOB -> texto longo ou base64 - ato_antigo_tipo?: string - valor_iss?: number - id_ato_isentado?: number - motivo_isencao?: string - pessoas_etiquetas?: number - abonador?: string - servico_cartao?: string - valor_informacoes_centrais?: number - situacao_diferido?: string - sigla_numero?: string - motivo_diferido?: string - nome_juridico?: string - etiqueta_apenas_frente?: string - indexacao_id?: number - certidao_data_lavratura?: string | Date - nfse_id?: number - qtd_pagina_certidao?: number - placa?: string - dut?: string - etiqueta_unica?: string - fundo_abonador?: string - instrumento_publico?: string - data_lavratura_abono?: string | Date - valor_base_calculo?: number - valor_avaliacao?: number - ato_abonado?: number - transferencia_veiculo?: string - usar_a4?: string - cpf_abono_rep?: string - vrcext?: number - valor_fundo_selo?: number - averbacao?: string + servico_itempedido_id?: number; + servico_pedido_id?: number; + servico_tipo_id?: number; + + valor?: number; + qtd?: number; + pessoa_id?: number; + + impressao_etiqueta?: string; + situacao?: string; + etiqueta_numero?: number; + pessoa_auxiliar_id?: number; + pessoa_sp_abono_rep?: string; + tipo_item?: string; + imprimir?: string; + observacao?: string; + impressao_direta?: string; + + // 🔹 Valores financeiros e emolumentos + selo_livro_id?: number; + emolumento?: number; + fundesp?: number; + taxa_judiciaria?: number; + desconto?: number; + desc_complementar?: string; + valor_manual?: string; + valor_documento?: number; + outra_taxa1?: number; + emolumento_item_id?: number; + emolumento_id?: number; + valor_iss?: number; + valor_informacoes_centrais?: number; + id_ato_isentado?: number; + motivo_isencao?: string; + valor_base_calculo?: number; + valor_avaliacao?: number; + vrcext?: number; + valor_fundo_selo?: number; + + // 🔹 Certidão + certidao_impressa?: string; + certidao_ato_id?: number; + certidao_previsao?: string | Date; + certidao_ato_antigo?: string; + certidao_data_emissao?: string | Date; + certidao_texto?: string | null; + ato_antigo_tipo?: string; + pessoas_etiquetas?: number; + qtd_pagina_certidao?: number; + + // 🔹 Situações / Diferimento / Notas + situacao_diferido?: string; + motivo_diferido?: string; + averbacao?: string; + + // 🔹 Dados auxiliares + abonador?: string; + servico_cartao?: string; + nome_juridico?: string; + etiqueta_apenas_frente?: string; + indexacao_id?: number; + certidao_data_lavratura?: string | Date; + nfse_id?: number; + placa?: string; + dut?: string; + etiqueta_unica?: string; + fundo_abonador?: string; + instrumento_publico?: string; + data_lavratura_abono?: string | Date; + ato_abonado?: number; + transferencia_veiculo?: string; + usar_a4?: string; + cpf_abono_rep?: string; + + // 🔹 Campos usados na UI + descricao?: string; + tabela?: string; + + /** + * Índice local na lista (usado no front para map e controle) + */ + index?: number; + + /** + * Subview: serviço + pessoa vinculada ao item + */ + subview?: TServicoItemPedidoSubviewInterface; } diff --git a/src/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoListInterface.ts b/src/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoListInterface.ts new file mode 100644 index 0000000..ae1fbab --- /dev/null +++ b/src/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoListInterface.ts @@ -0,0 +1,6 @@ +import TServicoItemPedidoIndexResponseInterface from "./TServicoItemPedidoCalculoResponseInterface"; + +export default interface TServicoItemPedidoListInterface { + items: TServicoItemPedidoIndexResponseInterface[]; + openConfirmDialog: any +} \ No newline at end of file diff --git a/src/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoTableInterface.ts b/src/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoTableInterface.ts index abff7e9..50453f6 100644 --- a/src/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoTableInterface.ts +++ b/src/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoTableInterface.ts @@ -2,6 +2,4 @@ import TServicoItemPedidoInterface from "./TServicoItemPedidoIntefarce"; export default interface TServicoItemPedidoTableInterface { data?: TServicoItemPedidoInterface[]; - onEdit: (item: TServicoItemPedidoInterface, isEditingFormStatus: boolean) => void; - onDelete: (item: TServicoItemPedidoInterface, isEditingFormStatus: boolean) => void; } diff --git a/src/packages/servicos/interfaces/TServicoPedido/TServicoPedidoDetailsInterface.ts b/src/packages/servicos/interfaces/TServicoPedido/TServicoPedidoDetailsInterface.ts new file mode 100644 index 0000000..f9753b2 --- /dev/null +++ b/src/packages/servicos/interfaces/TServicoPedido/TServicoPedidoDetailsInterface.ts @@ -0,0 +1,3 @@ +export default interface TServicoPedidoDetailsInterface { + servico_pedido_id: number +} \ No newline at end of file diff --git a/src/packages/servicos/interfaces/TServicoPedido/TServicoPedidoDetailsPagamentoInterface.ts b/src/packages/servicos/interfaces/TServicoPedido/TServicoPedidoDetailsPagamentoInterface.ts new file mode 100644 index 0000000..4630c0c --- /dev/null +++ b/src/packages/servicos/interfaces/TServicoPedido/TServicoPedidoDetailsPagamentoInterface.ts @@ -0,0 +1,8 @@ +import TServicoItemPedidoIndexResponseInterface from "../TServicoItemPedido/TServicoItemPedidoCalculoResponseInterface"; + +export default interface TServicoPedidoDetailsPagamentoInterface { + + situacao: string, + items: TServicoItemPedidoIndexResponseInterface[] + +} \ No newline at end of file diff --git a/src/packages/servicos/interfaces/TServicoPedido/TServicoPedidoFormInterface.ts b/src/packages/servicos/interfaces/TServicoPedido/TServicoPedidoFormInterface.ts index cd375ef..eea5c91 100644 --- a/src/packages/servicos/interfaces/TServicoPedido/TServicoPedidoFormInterface.ts +++ b/src/packages/servicos/interfaces/TServicoPedido/TServicoPedidoFormInterface.ts @@ -1,9 +1,7 @@ -import { TServicoPedidoFormValues } from '../../schemas/TServicoPedido/TServicoPedidoSchema'; - export interface TServicoPedidoFormInterface { - isOpen: boolean; - data: TServicoPedidoFormValues | null; - onClose: (item: null, isFormStatus: boolean) => void; - onSave: (data: TServicoPedidoFormValues) => void; - buttonIsLoading: boolean; -} + /** + * ID opcional do pedido, usado para modo edição + * - Se não informado, o formulário funciona em modo "novo pedido" + */ + servico_pedido_id?: number; +} \ No newline at end of file diff --git a/src/packages/servicos/interfaces/TServicoPedido/TServicoPedidoInterface.ts b/src/packages/servicos/interfaces/TServicoPedido/TServicoPedidoInterface.ts index c2e3d06..ff67371 100644 --- a/src/packages/servicos/interfaces/TServicoPedido/TServicoPedidoInterface.ts +++ b/src/packages/servicos/interfaces/TServicoPedido/TServicoPedidoInterface.ts @@ -1,7 +1,22 @@ +import TServicoTipoInterface from "@/app/(protected)/(cadastros)/cadastros/_interfaces/TServicoTipoInterface"; +import GEmolumentoInterface from "@/packages/administrativo/interfaces/GEmolumento/GEmolumentoInterface"; +import TServicoItemPedidoAddResponseInterface from "@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoCalculoResponseInterface"; + export default interface TServicoPedidoInterface { + /** + * Chave primária do pedido + */ servico_pedido_id?: number; + + /** + * Valores financeiros do pedido + */ valor_pedido?: number; valor_pago?: number; + + /** + * Dados de controle + */ usuario_id?: number; data_pedido?: string; mensalista_livrocaixa_id?: number; @@ -9,7 +24,39 @@ export default interface TServicoPedidoInterface { escrevente_id?: number; situacao?: string; estornado?: string; - apresentante?: string; nfse_id?: number; + + /** + * Apresentante / Pessoa selo + */ + apresentante?: string; cpfcnpj_apresentante?: string; -} \ No newline at end of file + selo_pessoa_nome?: string; + selo_pessoa_cpfcnpj?: string; + + /** + * Meta-informações de usuário/funcão (quando retornado pela API) + */ + login?: string; + funcao?: string; + + /** + * Serviço e emolumento selecionados no front. + * - No backend, provavelmente só IDs são gravados, + * mas no front trabalhamos com o objeto completo. + */ + servico_tipo: TServicoTipoInterface; + emolumento: GEmolumentoInterface; + + /** + * Itens do pedido (array tipado, e não mais []) + */ + itens?: TServicoItemPedidoAddResponseInterface[]; + + /** + * Dados de pagamento + */ + pagador_nome?: string; + pagador_cpfcnpj?: string; + tipo_pagamento?: number; +} diff --git a/src/packages/servicos/schemas/TServicoItemPedido/TServicoItemPedidoSchema.ts b/src/packages/servicos/schemas/TServicoItemPedido/TServicoItemPedidoSchema.ts index 89bfc54..4b53246 100644 --- a/src/packages/servicos/schemas/TServicoItemPedido/TServicoItemPedidoSchema.ts +++ b/src/packages/servicos/schemas/TServicoItemPedido/TServicoItemPedidoSchema.ts @@ -65,6 +65,9 @@ export const TServicoItemPedidoSchema = z.object({ vrcext: z.number().optional(), valor_fundo_selo: z.number().optional(), averbacao: z.string().optional(), + cartao_numero: z.union([z.number(), z.null()]), + cartao_data: z.string().optional(), + cartao_selar: z.string().optional() }) export type TServicoItemPedidoFormValues = z.infer diff --git a/src/packages/servicos/schemas/TServicoPedido/TServicoPedidoFormSchema.ts b/src/packages/servicos/schemas/TServicoPedido/TServicoPedidoFormSchema.ts new file mode 100644 index 0000000..3a9e490 --- /dev/null +++ b/src/packages/servicos/schemas/TServicoPedido/TServicoPedidoFormSchema.ts @@ -0,0 +1,67 @@ +import z from "zod"; + +export const TServicoPedidoFormSchema = z.object({ + + servico_pedido_id: z + .number() + .optional(), + + escrevente_id: z + .number() + .int() + .positive("Escrevente é obrigatório."), + + apresentante: z + .string() + .min(1, "Apresentante é obrigatório."), + + cpfcnpj_apresentante: z + .string() + .min(1, "CPF/CNPJ do apresentante é obrigatório."), + + selo_pessoa_nome: z + .string() + .min(1, "Nome da pessoa do selo é obrigatório."), + + selo_pessoa_cpfcnpj: z + .string() + .min(1, "CPF/CNPJ da pessoa do selo é obrigatório."), + + servico_tipo: z + .any() + .refine((v) => !!v, "Selecione um serviço."), + + emolumento: z + .any() + .refine((v) => !!v, "Selecione um emolumento."), + + itens: z + .array(z.any()) + .min(1, "Adicione ao menos um item ao pedido."), + + pagador_nome: z + .string() + .min(1, "Nome do requerente é obrigatório."), + + pagador_cpfcnpj: z + .string() + .min(1, "CPF/CNPJ do requerente é obrigatório."), + + valor_pedido: z + .number() + .nonnegative("Valor do pedido inválido."), + + valor_pago: z + .number() + .nonnegative("Valor pago inválido."), + + tipo_pagamento: z + .any() + .refine((v) => !!v, "Selecione a forma de pagamento."), + + situacao: z + .string() + .min(1, "Campo situação deve ser informado"), +}); + +export type TServicoPedidoFormValues = z.infer; \ No newline at end of file diff --git a/src/packages/servicos/schemas/TServicoPedido/TServicoPedidoSchema.ts b/src/packages/servicos/schemas/TServicoPedido/TServicoPedidoSchema.ts index 8fffc16..3f68c1d 100644 --- a/src/packages/servicos/schemas/TServicoPedido/TServicoPedidoSchema.ts +++ b/src/packages/servicos/schemas/TServicoPedido/TServicoPedidoSchema.ts @@ -1,19 +1,30 @@ import z from "zod"; -export const TServicoPedidoSchema = z.object({ - servico_pedido_id: z.number().optional, - valor_pedido: z.number().optional, - valor_pago: z.number().optional, - usuario_id: z.number().optional, - data_pedido: z.string().optional, - mensalista_livrocaixa_id: z.number().optional, - observacao: z.string().optional, - escrevente_id: z.number().optional, - situacao: z.string().optional, - estornado: z.string().optional, - apresentante: z.string().optional, - nfse_id: z.number().optional, - cpfcnpj_apresentante: z.string().optional, -}); +import { TServicoItemPedidoSchema } from "../TServicoItemPedido/TServicoItemPedidoSchema"; -export type TServicoPedidoFormValues = z.infer; \ No newline at end of file + +export const TServicoPedidoSchema = z.object({ + servico_pedido_id: z.number().optional(), + valor_pedido: z.number().optional(), + valor_pago: z.number().optional(), + usuario_id: z.number().optional(), + data_pedido: z.union([z.string(), z.null()]), + mensalista_livrocaixa_id: z.union([z.number(), z.null()]), + observacao: z.union([z.string(), z.null()]), + escrevente_id: z.number(), + situacao: z.string().optional(), + estornado: z.union([z.string(), z.null()]), + nfse_id: z.union([z.number(), z.null()]), + apresentante: z.string(), + cpfcnpj_apresentante: z.string().optional(), + selo_pessoa_nome: z.string().min(1), + selo_pessoa_cpfcnpj: z.string().min(1), + login: z.string().optional(), + funcao: z.union([z.string(), z.null()]), + itens: z.array(TServicoItemPedidoSchema).default([]), + servico_tipo: z.object().optional(), + emolumento: z.object().optional(), + pagador_nome: z.string().min(1), + pagador_cpfcnpj: z.string().min(1), + tipo_pagamento: z.number(), +}); \ No newline at end of file diff --git a/src/packages/servicos/services/TServicoItemPedido/TServicoItemPedidoAtivarService.ts b/src/packages/servicos/services/TServicoItemPedido/TServicoItemPedidoAtivarService.ts new file mode 100644 index 0000000..c5f0775 --- /dev/null +++ b/src/packages/servicos/services/TServicoItemPedido/TServicoItemPedidoAtivarService.ts @@ -0,0 +1,14 @@ +import { TServicoItemPedidoAtivarData } from '@/packages/servicos/data/TServicoItemPedido/TServicoItemPedidoAtivarData'; +import TServicoItemPedidoInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoIntefarce'; +import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; + + +async function executeTServicoItemPedidoAtivarService(data: TServicoItemPedidoInterface) { + + const response = await TServicoItemPedidoAtivarData(data); + + return response; + +} + +export const TServicoItemPedidoAtivarService = withClientErrorHandler(executeTServicoItemPedidoAtivarService); diff --git a/src/packages/servicos/services/TServicoItemPedido/TServicoItemPedidoCancelarService.ts b/src/packages/servicos/services/TServicoItemPedido/TServicoItemPedidoCancelarService.ts new file mode 100644 index 0000000..687831b --- /dev/null +++ b/src/packages/servicos/services/TServicoItemPedido/TServicoItemPedidoCancelarService.ts @@ -0,0 +1,14 @@ +import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; + +import { TServicoItemPedidoCancelarData } from '../../data/TServicoItemPedido/TServicoItemPedidoCancelarData'; +import TServicoItemPedidoInterface from '../../interfaces/TServicoItemPedido/TServicoItemPedidoIntefarce'; + +async function executeTServicoItemPedidoCancelarService(data: TServicoItemPedidoInterface) { + + const response = await TServicoItemPedidoCancelarData(data); + + return response; + +} + +export const TServicoItemPedidoCancelarService = withClientErrorHandler(executeTServicoItemPedidoCancelarService); diff --git a/src/packages/servicos/services/TServicoItemPedido/TServicoItemPedidoIndexService.ts b/src/packages/servicos/services/TServicoItemPedido/TServicoItemPedidoIndexService.ts index 37403fd..9c1c69d 100644 --- a/src/packages/servicos/services/TServicoItemPedido/TServicoItemPedidoIndexService.ts +++ b/src/packages/servicos/services/TServicoItemPedido/TServicoItemPedidoIndexService.ts @@ -1,9 +1,10 @@ + +import { TServicoItemPedidoIndexData } from '@/packages/servicos/data/TServicoItemPedido/TServicoItemPedidoIndexData'; +import TServicoItemPedidoInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoIntefarce'; import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; -import { TServicoItemPedidoIndexData } from '../../data/TServicoItemPedido/TServicoItemPedidoIndexData'; - -export default async function executeTServicoItemPedidoIndexService() { - const response = await TServicoItemPedidoIndexData(); +export default async function executeTServicoItemPedidoIndexService(data: TServicoItemPedidoInterface) { + const response = await TServicoItemPedidoIndexData(data); return response; } diff --git a/src/packages/servicos/services/TServicoItemPedido/TServicoItemPedidoShowService.ts b/src/packages/servicos/services/TServicoItemPedido/TServicoItemPedidoShowService.ts new file mode 100644 index 0000000..878a690 --- /dev/null +++ b/src/packages/servicos/services/TServicoItemPedido/TServicoItemPedidoShowService.ts @@ -0,0 +1,17 @@ + +import { TServicoItemPedidoShowData } from '@/packages/servicos/data/TServicoItemPedido/TServicoItemPedidoShowData'; +import TServicoItemPedidoInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoIntefarce'; +import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; + + + + +async function executeTServicoItemPedidoShowService(data: TServicoItemPedidoInterface) { + + const response = await TServicoItemPedidoShowData(data); + + return response; + +} + +export const TServicoItemPedidoShowService = withClientErrorHandler(executeTServicoItemPedidoShowService); diff --git a/src/packages/servicos/services/TServicoPedido/TServicoPedidoAtivarService.ts b/src/packages/servicos/services/TServicoPedido/TServicoPedidoAtivarService.ts new file mode 100644 index 0000000..fc694f7 --- /dev/null +++ b/src/packages/servicos/services/TServicoPedido/TServicoPedidoAtivarService.ts @@ -0,0 +1,11 @@ +import { TServicoPedidoAtivarData } from '@/packages/servicos/data/TServicoPedido/TServicoPedidoAtivarData'; +import TServicoPedidoInterface from '@/packages/servicos/interfaces/TServicoPedido/TServicoPedidoInterface'; +import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; + + +async function executeTServicoPedidoAtivarService(data: TServicoPedidoInterface) { + const response = await TServicoPedidoAtivarData(data); + return response; +} + +export const TServicoPedidoAtivarService = withClientErrorHandler(executeTServicoPedidoAtivarService); \ No newline at end of file diff --git a/src/packages/servicos/services/TServicoPedido/TServicoPedidoCancelarService.ts b/src/packages/servicos/services/TServicoPedido/TServicoPedidoCancelarService.ts new file mode 100644 index 0000000..462b3c7 --- /dev/null +++ b/src/packages/servicos/services/TServicoPedido/TServicoPedidoCancelarService.ts @@ -0,0 +1,10 @@ +import { TServicoPedidoCancelarData } from '@/packages/servicos/data/TServicoPedido/TServicoPedidoCancelarData'; +import TServicoPedidoInterface from '@/packages/servicos/interfaces/TServicoPedido/TServicoPedidoInterface'; +import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; + +async function executeTServicoPedidoCancelarService(data: TServicoPedidoInterface) { + const response = await TServicoPedidoCancelarData(data); + return response; +} + +export const TServicoPedidoCancelarService = withClientErrorHandler(executeTServicoPedidoCancelarService); diff --git a/src/packages/servicos/services/TServicoPedido/TServicoPedidoLoadParamsService.ts b/src/packages/servicos/services/TServicoPedido/TServicoPedidoLoadParamsService.ts new file mode 100644 index 0000000..f5c414c --- /dev/null +++ b/src/packages/servicos/services/TServicoPedido/TServicoPedidoLoadParamsService.ts @@ -0,0 +1,10 @@ +import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; + +import { TServicoPedidoLoadParamsData } from '../../data/TServicoPedido/TServicoPedidoLoadParamsData'; + +export default async function executeTServicoPedidoLoadParamsService() { + const response = await TServicoPedidoLoadParamsData(); + return response; +} + +export const TServicoPedidoLoadParamsService = withClientErrorHandler(executeTServicoPedidoLoadParamsService); diff --git a/src/packages/servicos/services/TServicoPedido/TServicoPedidoShowService.ts b/src/packages/servicos/services/TServicoPedido/TServicoPedidoShowService.ts new file mode 100644 index 0000000..df4d660 --- /dev/null +++ b/src/packages/servicos/services/TServicoPedido/TServicoPedidoShowService.ts @@ -0,0 +1,12 @@ + + +import { TServicoPedidoShowData } from '@/packages/servicos/data/TServicoPedido/TServicoPedidoShowData'; +import TServicoPedidoInterface from '@/packages/servicos/interfaces/TServicoPedido/TServicoPedidoInterface'; +import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; + +async function executeTServicoPedidoShowService(data: TServicoPedidoInterface) { + const response = await TServicoPedidoShowData(data); + return response; +} + +export const TServicoPedidoShowService = withClientErrorHandler(executeTServicoPedidoShowService); diff --git a/src/shared/actions/CPF/FormatCPFCNPJForm.ts b/src/shared/actions/CPF/FormatCPFCNPJForm.ts new file mode 100644 index 0000000..1fa91e1 --- /dev/null +++ b/src/shared/actions/CPF/FormatCPFCNPJForm.ts @@ -0,0 +1,25 @@ +import { UnmaskCPFCNPJForm } from "./UnmaskCPFCNPJForm"; + +export function isCpf(value: string): boolean { + return UnmaskCPFCNPJForm(value).length <= 11; +} + +export function FormatCPFCNPJForm(value: string = ''): string { + const digits = UnmaskCPFCNPJForm(value); + + // CPF — 11 dígitos + if (digits.length <= 11) { + return digits + .replace(/^(\d{3})(\d)/, "$1.$2") + .replace(/^(\d{3})\.(\d{3})(\d)/, "$1.$2.$3") + .replace(/^(\d{3})\.(\d{3})\.(\d{3})(\d{1,2})$/, "$1.$2.$3-$4"); + } + + // CNPJ — 14 dígitos + return digits + .slice(0, 14) + .replace(/^(\d{2})(\d)/, "$1.$2") + .replace(/^(\d{2})\.(\d{3})(\d)/, "$1.$2.$3") + .replace(/^(\d{2})\.(\d{3})\.(\d{3})(\d)/, "$1.$2.$3/$4") + .replace(/^(\d{2})\.(\d{3})\.(\d{3})\/(\d{4})(\d{1,2})$/, "$1.$2.$3/$4-$5"); +} diff --git a/src/shared/actions/CPF/UnmaskCPFCNPJForm.ts b/src/shared/actions/CPF/UnmaskCPFCNPJForm.ts new file mode 100644 index 0000000..462ca38 --- /dev/null +++ b/src/shared/actions/CPF/UnmaskCPFCNPJForm.ts @@ -0,0 +1,3 @@ +export function UnmaskCPFCNPJForm(value: string = ""): string { + return value.replace(/\D/g, "").slice(0, 11); +} diff --git a/src/shared/actions/data/ToMoney.ts b/src/shared/actions/data/ToMoney.ts new file mode 100644 index 0000000..95a5c24 --- /dev/null +++ b/src/shared/actions/data/ToMoney.ts @@ -0,0 +1,6 @@ +// Helper: garante número com 2 casas decimais +export const toMoney = (v: unknown): number => { + const n = Number(v ?? 0); + // evita problemas de ponto flutuante + return Math.round((n + Number.EPSILON) * 100) / 100; +}; diff --git a/src/shared/actions/money/FormatMoney.ts b/src/shared/actions/money/FormatMoney.ts new file mode 100644 index 0000000..9ad7fce --- /dev/null +++ b/src/shared/actions/money/FormatMoney.ts @@ -0,0 +1,5 @@ +export default function FormatMoney(data) { + + return new Intl.NumberFormat('pt-BR', { style: 'currency', currency: 'BRL' }).format(Number(data || 0)); + +} \ No newline at end of file diff --git a/src/shared/components/dataTable/DataTable.tsx b/src/shared/components/dataTable/DataTable.tsx index f99c703..6b82471 100644 --- a/src/shared/components/dataTable/DataTable.tsx +++ b/src/shared/components/dataTable/DataTable.tsx @@ -2,16 +2,16 @@ import { ColumnDef, + ColumnFiltersState, flexRender, getCoreRowModel, getFilteredRowModel, getPaginationRowModel, getSortedRowModel, - useReactTable, - SortingState, - ColumnFiltersState, - VisibilityState, RowSelectionState, + SortingState, + useReactTable, + VisibilityState, } from '@tanstack/react-table'; import { ChevronLeftIcon, ChevronRightIcon, EyeIcon } from 'lucide-react'; import React from 'react'; @@ -35,7 +35,19 @@ import { import DataTableInterface from './interfaces/DataTableInterface'; -export function DataTable({ +/** + * DataTable genérico com suporte a subvisões dinâmicas (subtabelas ou detalhes). + * O conteúdo extra pode ser definido dinamicamente por linha, em `row.original.subview`. + * + * Exemplo de item: + * { + * id: 1, + * descricao: 'Item principal', + * valor: 100, + * subview: , + * } + */ +export function DataTable React.ReactNode) }>({ data, columns, filterColumn, @@ -44,7 +56,6 @@ export function DataTable({ onDelete, onRowClick, }: DataTableInterface) { - // Garante que data sempre seja array const safeData = Array.isArray(data) ? data : []; // Estados internos da tabela @@ -53,40 +64,43 @@ export function DataTable({ const [columnVisibility, setColumnVisibility] = React.useState({}); const [rowSelection, setRowSelection] = React.useState({}); - // Configuração da tabela + // Cria a tabela const table = useReactTable({ data: safeData, columns: [ ...columns, ...(onEdit || onDelete ? [ - { - id: 'actions', - header: 'Ações', - cell: ({ row }: any) => ( -
- {onEdit && ( - - )} - {onDelete && ( - - )} -
- ), - } as ColumnDef, - ] + { + id: 'actions', + header: 'Ações', + cell: ({ row }: any) => ( +
+ {onEdit && ( + + )} + {onDelete && ( + + )} +
+ ), + } as ColumnDef, + ] : []), ], - state: { - sorting, - columnFilters, - columnVisibility, - rowSelection, - }, + state: { sorting, columnFilters, columnVisibility, rowSelection }, onSortingChange: setSorting, onColumnFiltersChange: setColumnFilters, onColumnVisibilityChange: setColumnVisibility, @@ -99,16 +113,22 @@ export function DataTable({ return (
- {/* Filtros e colunas */} + {/* 🔍 Filtros e colunas */}
{filterColumn && ( table.getColumn(filterColumn)?.setFilterValue(e.target.value)} + value={ + (table.getColumn(filterColumn)?.getFilterValue() as string) ?? '' + } + onChange={(e) => + table.getColumn(filterColumn)?.setFilterValue(e.target.value) + } className="w-full" /> )} + + {/* Menu de colunas visíveis */}
- {/* Tabela */} + + {/* 🧱 Tabela principal */}
+ {/* Cabeçalho */} {table.getHeaderGroups().map((headerGroup) => ( @@ -143,41 +165,57 @@ export function DataTable({ {header.isPlaceholder ? null - : flexRender(header.column.columnDef.header, header.getContext())} + : flexRender( + header.column.columnDef.header, + header.getContext(), + )} ))} ))} + + {/* Corpo */} {table.getRowModel().rows?.length ? ( - table.getRowModel().rows.map((row) => ( - onRowClick?.(row.original)} - > - {row.getVisibleCells().map((cell) => ( - - {flexRender(cell.column.columnDef.cell, cell.getContext())} - - ))} - - )) + table.getRowModel().rows.map((row) => { + return ( + onRowClick?.(row.original)} + > + {row.getVisibleCells().map((cell) => ( + + {flexRender( + cell.column.columnDef.cell, + cell.getContext(), + )} + + ))} + + ); + }) ) : ( - + Nenhum resultado encontrado. )} +
- {/* Paginação */} + + {/* 📄 Paginação */}
- Página {table.getState().pagination.pageIndex + 1} de {table.getPageCount()} + Página {table.getState().pagination.pageIndex + 1} de{' '} + {table.getPageCount()}
+ + + + + + + Nenhum resultado encontrado. + + {options.map((item) => ( + { + field.onChange(item.value); + setOpen(false); + }} + > + + {item.label} + + ))} + + + + + + ); +} diff --git a/src/shared/components/step/stepNavigator.tsx b/src/shared/components/step/stepNavigator.tsx new file mode 100644 index 0000000..a6f55d1 --- /dev/null +++ b/src/shared/components/step/stepNavigator.tsx @@ -0,0 +1,256 @@ +'use client'; + +import * as React from 'react'; + +import { cn } from '@/lib/utils'; // ajuste o caminho conforme seu projeto + +/** ========================= + * Constantes (com defaults) + * ========================= */ +const DEFAULT_SCROLL_OFFSET = 16; +const DEFAULT_SPY_LOCK_MS = 600; + +/** =========== + * Tipos + * =========== */ +export type StepKey = string; + +export type StepSection = { + /** chave lógica do step (ex.: 'pedido') */ + key: StepKey; + /** id do elemento alvo no DOM (ex.: 'selectPedido') */ + id: string; + /** ícone (lucide ou outro) */ + icon: React.ReactNode; + /** título do step */ + title: string; + /** descrição curta do step */ + description?: string; +}; + +export type StepNavigatorProps = { + /** Lista de seções em ordem */ + sections: StepSection[]; + /** Ativo controlado externamente */ + active?: StepKey; + /** Ativo padrão (modo não-controlado) */ + defaultActive?: StepKey; + /** Callback ao mudar de seção (por scroll ou clique) */ + onChange?: (key: StepKey) => void; + + /** Offset do topo ao calcular posicionamento (ex.: header fixo) */ + scrollOffset?: number; + /** Tempo de bloqueio do spy após scroll programático */ + spyLockMs?: number; + + /** Classe extra no container */ + className?: string; + /** Se `false`, desabilita o scroll-spy */ + enableScrollSpy?: boolean; +}; + +/** ================= + * Hook: useScrollSpy + * ================= */ +function useScrollSpy(opts: { + sections: StepSection[]; + active: StepKey | undefined; + setActive: (key: StepKey) => void; + scrollOffset: number; + enable: boolean; + lockMs: number; +}) { + const { sections, active, setActive, scrollOffset, enable, lockMs } = opts; + + // bloqueio do spy durante rolagem programática + const spyLockedRef = React.useRef(false); + const spyTimerRef = React.useRef(null); + + const lockSpy = React.useCallback(() => { + spyLockedRef.current = true; + if (spyTimerRef.current) window.clearTimeout(spyTimerRef.current); + spyTimerRef.current = window.setTimeout(() => { + spyLockedRef.current = false; + }, lockMs) as unknown as number; + }, [lockMs]); + + const scrollToId = React.useCallback( + (id: string) => { + const el = document.getElementById(id); + if (!el) return; + lockSpy(); + const y = el.getBoundingClientRect().top + window.scrollY - scrollOffset; + window.scrollTo({ top: y, behavior: 'smooth' }); + }, + [lockSpy, scrollOffset] + ); + + React.useEffect(() => { + if (!enable) return; + + const handler = () => { + if (spyLockedRef.current) return; + + let current: StepKey | undefined = undefined; + let best = Number.POSITIVE_INFINITY; + + for (const { key, id } of sections) { + const el = document.getElementById(id); + if (!el) continue; + const dist = Math.abs(el.getBoundingClientRect().top - scrollOffset - 8); + if (dist < best) { + best = dist; + current = key; + } + } + + if (current && current !== active) { + setActive(current); + } + }; + + handler(); // avalia logo ao montar + window.addEventListener('scroll', handler, { passive: true }); + return () => window.removeEventListener('scroll', handler); + }, [enable, sections, active, scrollOffset, setActive]); + + return { scrollToId, lockSpy }; +} + +/** ================== + * Subcomponente: StepLink + * ================== */ +function StepLink({ + active, + onClick, + icon, + title, + description, +}: { + active?: boolean; + onClick?: () => void; + icon: React.ReactNode; + title: string; + description?: string; +}) { + return ( + + ); +} + +/** =================== + * Componente principal + * =================== */ +export type StepNavigatorRef = { + /** Rola até a seção pela key ou id */ + scrollTo: (target: StepKey | { id: string }) => void; +}; + +export const StepNavigator = React.forwardRef( + ( + { + sections, + active: activeProp, + defaultActive, + onChange, + scrollOffset = DEFAULT_SCROLL_OFFSET, + spyLockMs = DEFAULT_SPY_LOCK_MS, + className, + enableScrollSpy = true, + }, + ref + ) => { + // estado controlado/ não-controlado + const [activeState, setActiveState] = React.useState( + activeProp ?? defaultActive ?? sections[0]?.key + ); + + // sincroniza quando for controlado + React.useEffect(() => { + if (activeProp !== undefined) setActiveState(activeProp); + }, [activeProp]); + + const setActive = React.useCallback( + (key: StepKey) => { + if (activeProp === undefined) { + setActiveState(key); + } + onChange?.(key); + }, + [activeProp, onChange] + ); + + const { scrollToId, lockSpy } = useScrollSpy({ + sections, + active: activeState, + setActive, + scrollOffset, + enable: enableScrollSpy, + lockMs: spyLockMs, + }); + + const scrollTo = React.useCallback( + (target: StepKey | { id: string }) => { + const id = + typeof target === 'string' + ? sections.find((s) => s.key === target)?.id + : target.id; + if (!id) return; + scrollToId(id); + }, + [sections, scrollToId] + ); + + React.useImperativeHandle(ref, () => ({ scrollTo }), [scrollTo]); + + return ( + + ); + } +); +StepNavigator.displayName = 'StepNavigator'; \ No newline at end of file diff --git a/src/shared/components/structure/Header.tsx b/src/shared/components/structure/Header.tsx index d7c0763..b462cbe 100644 --- a/src/shared/components/structure/Header.tsx +++ b/src/shared/components/structure/Header.tsx @@ -1,4 +1,7 @@ +'use client'; + import { PlusIcon } from 'lucide-react'; +import Link from 'next/link'; import { Button } from '@/components/ui/button'; @@ -6,21 +9,40 @@ interface HeaderProps { title: string; description: string; buttonText: string; - buttonAction: (...args: any[]) => void; + href?: `/${string}`; + buttonAction?: () => void; + className?: string; } -export default function Header({ title, description, buttonText, buttonAction }: HeaderProps) { +export default function Header({ + title, + description, + buttonText, + href, + buttonAction, + className, +}: HeaderProps) { return ( -
+

{title}

{description}

- + + {href ? ( + + ) : ( + + )}
); diff --git a/src/shared/components/tipoPagamento/TipoPagamentoSelect.tsx b/src/shared/components/tipoPagamento/TipoPagamentoSelect.tsx new file mode 100644 index 0000000..a5757f4 --- /dev/null +++ b/src/shared/components/tipoPagamento/TipoPagamentoSelect.tsx @@ -0,0 +1,85 @@ +import { CheckIcon, ChevronsUpDownIcon } from 'lucide-react'; +import React from 'react'; + +import { Button } from '@/components/ui/button'; +import { + Command, + CommandEmpty, + CommandGroup, + CommandInput, + CommandItem, + CommandList, +} from '@/components/ui/command'; +import { FormControl } from '@/components/ui/form'; +import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'; +import { cn } from '@/lib/utils'; +import { TipoPagamentoEnum } from '@/shared/enums/TipoPagamentoEnum'; + +type TipoPagamentoSelectProps = { + field: { + value?: number | null; + onChange: (value: number) => void; + }; +}; + +export default function TipoPagamentoSelect({ field }: TipoPagamentoSelectProps) { + const [open, setOpen] = React.useState(false); + + // Cria as opções a partir do enum + const options = Object.entries(TipoPagamentoEnum).map(([key, label]) => ({ + value: Number(key), + label, + })); + + // Label exibida atualmente + const selectedLabel = + field.value !== undefined && field.value !== null + ? options.find((item) => item.value === Number(field.value))?.label + : 'Selecione...'; + + return ( + + + + + + + + + + + Nenhum resultado encontrado. + + {options.map((item) => ( + { + field.onChange(item.value); // envia número + setOpen(false); + }} + > + + {item.label} + + ))} + + + + + + ); +} diff --git a/src/shared/components/webcam/WebCamDialog.tsx b/src/shared/components/webcam/WebCamDialog.tsx new file mode 100644 index 0000000..fa61c07 --- /dev/null +++ b/src/shared/components/webcam/WebCamDialog.tsx @@ -0,0 +1,72 @@ +'use client'; + +import { DialogClose } from '@radix-ui/react-dialog'; +import { useState } from 'react'; + +import { Button } from '@/components/ui/button'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle +} from '@/components/ui/dialog'; +import LoadingButton from '@/shared/components/loadingButton/LoadingButton'; +import WebcamCapture from '@/shared/components/webcam/webcam'; +import WebCamDialogInterface from '@/shared/interfaces/WebCamDialogInterface'; + + +export default function WebCamDialog({ + isOpen, + onClose, + onSave, +}: WebCamDialogInterface) { + + const [base64, setBase64] = useState('') + + const handleBase64 = async (data: string) => { + + setBase64(data) + + } + + return ( + { + if (!open) onClose(null, false); + }} + > + + + + Webcam + + + Captura de foto + + + + {/* Rodapé */} + + + + + { onSave(base64) }} + /> + + + + ); +} diff --git a/src/shared/components/webcam/webcam.tsx b/src/shared/components/webcam/webcam.tsx new file mode 100644 index 0000000..b11615b --- /dev/null +++ b/src/shared/components/webcam/webcam.tsx @@ -0,0 +1,228 @@ +'use client'; + +import React, { useCallback, useEffect, useRef, useState } from 'react'; + +import { Button } from '@/components/ui/button'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select'; + +type WebcamCaptureProps = { + width?: number; + height?: number; + /** Recebe a base64 (sem o prefixo data:image/png;base64,) e o dataURL completo */ + onCapture?: (base64: string, dataUrl: string) => void; + /** Opcional: nome do input hidden para enviar em forms */ + hiddenInputName?: string; +}; + +const WebcamCapture: React.FC = ({ + width = 320, + height = 240, + onCapture, + hiddenInputName, +}) => { + + const videoRef = useRef(null); + const streamRef = useRef(null); + + const [isStreaming, setIsStreaming] = useState(false); + const [photoDataUrl, setPhotoDataUrl] = useState(null); + const [photoBase64, setPhotoBase64] = useState(null); + + const [devices, setDevices] = useState([]); + const [selectedDeviceId, setSelectedDeviceId] = useState(''); + + // Carregar lista de webcams + useEffect(() => { + const loadDevices = async () => { + if (!navigator.mediaDevices?.enumerateDevices) return; + + try { + const allDevices = await navigator.mediaDevices.enumerateDevices(); + const videoDevices = allDevices.filter( + (device) => device.kind === 'videoinput' + ); + setDevices(videoDevices); + + // Se ainda não há câmera selecionada, seleciona a primeira + if (videoDevices.length > 0 && !selectedDeviceId) { + setSelectedDeviceId(videoDevices[0].deviceId); + } + } catch (error) { + console.error('Erro ao listar dispositivos de mídia:', error); + } + }; + + loadDevices(); + + // Atualiza lista se dispositivo for plugado/removido + navigator.mediaDevices?.addEventListener('devicechange', loadDevices); + + return () => { + navigator.mediaDevices?.removeEventListener('devicechange', loadDevices); + }; + }, [selectedDeviceId]); + + const stopWebcam = useCallback(() => { + if (streamRef.current) { + streamRef.current.getTracks().forEach((track) => track.stop()); + streamRef.current = null; + } + setIsStreaming(false); + }, []); + + const startWebcam = useCallback(async () => { + try { + // Para evitar streams múltiplos + if (streamRef.current) { + streamRef.current.getTracks().forEach((track) => track.stop()); + streamRef.current = null; + } + + const constraints: MediaStreamConstraints = { + video: selectedDeviceId + ? { deviceId: { exact: selectedDeviceId } } + : true, + }; + + const stream = await navigator.mediaDevices.getUserMedia( + constraints as MediaStreamConstraints + ); + streamRef.current = stream; + + if (videoRef.current) { + videoRef.current.srcObject = stream; + } + + setIsStreaming(true); + } catch (error) { + console.error('Erro ao acessar webcam:', error); + alert('Não foi possível acessar a webcam.'); + } + }, [selectedDeviceId]); + + const handleCapture = useCallback(() => { + if (!videoRef.current || !isStreaming) { + alert('Webcam não está ligada.'); + return; + } + + const video = videoRef.current; + + const canvas = document.createElement('canvas'); + canvas.width = video.videoWidth || width; + canvas.height = video.videoHeight || height; + + const ctx = canvas.getContext('2d'); + if (!ctx) { + alert('Não foi possível capturar a imagem.'); + return; + } + + ctx.drawImage(video, 0, 0, canvas.width, canvas.height); + + const dataUrl = canvas.toDataURL('image/png'); // data:image/png;base64,.... + const base64Only = dataUrl.split(',')[1]; + + setPhotoDataUrl(dataUrl); + setPhotoBase64(base64Only); + + if (onCapture) { + onCapture(base64Only, dataUrl); + } + + }, [isStreaming, onCapture, width, height]); + + // Cleanup ao desmontar + useEffect(() => { + return () => { + if (streamRef.current) { + streamRef.current.getTracks().forEach((track) => track.stop()); + } + }; + }, []); + + return ( +
+
+ + + + + + + +
+ +
+ ); +}; + +export default WebcamCapture; diff --git a/src/shared/data/fingertech/FingerTechCaptureData.ts b/src/shared/data/fingertech/FingerTechCaptureData.ts new file mode 100644 index 0000000..cc50617 --- /dev/null +++ b/src/shared/data/fingertech/FingerTechCaptureData.ts @@ -0,0 +1,22 @@ +import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; + +/********************************************* +* Nome: Capture +* Descrição: Chama o método "Capture" da aplicação desktop, +* responsável por chamar a tela de captura de digital para apenas um único dedo. +* Este método é recomendável quando você deseja capturar a impressão digital de um único dedo e +* não existe a necessidade de identificar qual dedo da mão esta digital pertence. +* Retorno: Template (String) ou Null +*********************************************/ +async function executeFingerTechCaptureData() { + + const response = await fetch(`http://localhost:9000/api/public/v1/captura/Capturar/1`, + { + method: 'GET' + }, + ); + + return await response.text() +} + +export const FingerTechCaptureData = withClientErrorHandler(executeFingerTechCaptureData); diff --git a/src/shared/data/fingertech/FingerTechEnrollData.ts b/src/shared/data/fingertech/FingerTechEnrollData.ts new file mode 100644 index 0000000..c54361d --- /dev/null +++ b/src/shared/data/fingertech/FingerTechEnrollData.ts @@ -0,0 +1,25 @@ +import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; + +/********************************************* +* Nome: Enroll +* Descrição: Chama o método "Enroll" da aplicação desktop, +* responsável por chamar a tela de captura de impressão digital para mais de um dedo. +* Este método é recomendável quando você deseja capturar a impressão digital de mais de um dedo e +* quando é necessário identificar a qual dedo esta digital pertence. +* Quando houver a captura de mais de uma impressão digital, elas serão armazenadas de maneira +* codificada no mesmo "Template" (String), mas durante a comparação qualquer dedo poderá ser +* comparado. +* Retorno: Template (String) ou "" (Vazio) +*********************************************/ +async function executeFingerTechEnrollData() { + + const response = await fetch(`http://localhost:9000/api/public/v1/captura/Enroll/1`, + { + method: 'GET' + }, + ); + + return await response.text() +} + +export const FingerTechEnrollData = withClientErrorHandler(executeFingerTechEnrollData); diff --git a/src/shared/data/fingertech/FingerTechMatchData.ts b/src/shared/data/fingertech/FingerTechMatchData.ts new file mode 100644 index 0000000..0450850 --- /dev/null +++ b/src/shared/data/fingertech/FingerTechMatchData.ts @@ -0,0 +1,23 @@ +import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; + +/********************************************* +* Nome: Match +* Descrição: Chama o método "VerifyMatch" da aplicação desktop, +* responsável por chamar a tela de captura de digital para apenas um único dedo e realizar a +* comparação com um outro template (impressão digital) já cadastrada. +* Este método é recomendável quando você deseja você comparação de 1:1 (Um para Um). +* Retorno: Template (String) ou Null +*********************************************/ +async function executeFingerTechMatchData() { + + // 'http://localhost:9000/api/public/v1/captura/Comparar?Digital=' + digital, + const response = await fetch(`http://localhost:9000/api/public/v1/captura/Capturar/1`, + { + method: 'GET' + }, + ); + + return await response.text() +} + +export const FingerTechMatchData = withClientErrorHandler(executeFingerTechMatchData); diff --git a/src/shared/enums/ServicosPedidosSituacoesEnum.ts b/src/shared/enums/ServicosPedidosSituacoesEnum.ts new file mode 100644 index 0000000..0ebc674 --- /dev/null +++ b/src/shared/enums/ServicosPedidosSituacoesEnum.ts @@ -0,0 +1,5 @@ +export enum ServicosPedidosSituacoesEnum { + A = 'Aberto', + F = 'Fechado', + C = 'Cancelado', +} diff --git a/src/shared/enums/TipoPagamentoEnum.ts b/src/shared/enums/TipoPagamentoEnum.ts new file mode 100644 index 0000000..a6f3a8e --- /dev/null +++ b/src/shared/enums/TipoPagamentoEnum.ts @@ -0,0 +1,6 @@ +export const TipoPagamentoEnum = { + 1: 'Dinheiro', + 2: 'Cartão de Crédito', + 3: 'Cartão de Débito', + 4: 'Pix', +} as const; diff --git a/src/shared/hooks/FingerTech/useFingerTechCaptureHook.ts b/src/shared/hooks/FingerTech/useFingerTechCaptureHook.ts new file mode 100644 index 0000000..956f504 --- /dev/null +++ b/src/shared/hooks/FingerTech/useFingerTechCaptureHook.ts @@ -0,0 +1,25 @@ +'use client'; + +import { useState } from 'react'; + +import { FingerTechCaptureService } from '@/shared/services/FingerTech/FingerTechCaptureService'; + +export const useFingerTechCaptureHook = () => { + + const [base64, setBase64] = useState(''); + + const captureFingerTech = async () => { + + const response = await FingerTechCaptureService(); + + setBase64(response); + + return response + + }; + + return { + base64, + captureFingerTech, + }; +}; diff --git a/src/shared/hooks/FingerTech/useFingerTechEnrollHook.ts b/src/shared/hooks/FingerTech/useFingerTechEnrollHook.ts new file mode 100644 index 0000000..74afb2e --- /dev/null +++ b/src/shared/hooks/FingerTech/useFingerTechEnrollHook.ts @@ -0,0 +1,25 @@ +'use client'; + +import { useState } from 'react'; + +import { FingerTechEnrollService } from '@/shared/services/FingerTech/FingerTechEnrollService'; + +export const useFingerTechEnrollHook = () => { + + const [base64, setBase64] = useState(''); + + const enrollFingerTech = async () => { + + const response = await FingerTechEnrollService(); + + setBase64(response); + + return response + + }; + + return { + base64, + enrollFingerTech, + }; +}; diff --git a/src/shared/hooks/FingerTech/useFingerTechMatchHook.ts b/src/shared/hooks/FingerTech/useFingerTechMatchHook.ts new file mode 100644 index 0000000..85734e1 --- /dev/null +++ b/src/shared/hooks/FingerTech/useFingerTechMatchHook.ts @@ -0,0 +1,25 @@ +'use client'; + +import { useState } from 'react'; + +import { FingerTechMatchService } from '@/shared/services/FingerTech/FingerTechMatchService'; + +export const useFingerTechMatchHook = () => { + + const [base64, setBase64] = useState(''); + + const matchFingerTech = async () => { + + const response = await FingerTechMatchService(); + + setBase64(response); + + return response + + }; + + return { + base64, + matchFingerTech, + }; +}; diff --git a/src/shared/hooks/sound/useSoundHook.ts b/src/shared/hooks/sound/useSoundHook.ts new file mode 100644 index 0000000..45a2c71 --- /dev/null +++ b/src/shared/hooks/sound/useSoundHook.ts @@ -0,0 +1,18 @@ +'use client' + +import { useCallback, useRef } from "react"; + +export function useSoundHook(soundPath: string) { + + const audioRef = useRef(null); + + if (!audioRef.current) { + audioRef.current = new Audio(soundPath); + } + + const play = useCallback(() => { + audioRef.current?.play().catch(() => { }); + }, []); + + return play; +} diff --git a/src/shared/hooks/useRunOnceByKey.ts b/src/shared/hooks/useRunOnceByKey.ts new file mode 100644 index 0000000..d70665f --- /dev/null +++ b/src/shared/hooks/useRunOnceByKey.ts @@ -0,0 +1,18 @@ +import { useCallback, useRef } from "react"; + +export default function useRunOnceByKey() { + const done = useRef(new Set()); + + const run = useCallback(async (key: string, tasks: Array<() => Promise>, opts?: { signal?: AbortSignal }) => { + if (done.current.has(key)) return; + done.current.add(key); + + await Promise.allSettled(tasks.map(fn => fn())); + }, []); + + const resetKey = useCallback((key: string) => { + done.current.delete(key); + }, []); + + return { run, resetKey }; +} \ No newline at end of file diff --git a/src/shared/interfaces/GConfigInterface.ts b/src/shared/interfaces/GConfigInterface.ts new file mode 100644 index 0000000..b176765 --- /dev/null +++ b/src/shared/interfaces/GConfigInterface.ts @@ -0,0 +1,13 @@ +export default interface GConfigInterface { + config_id?: number; + config_grupo_id?: number; + config_padrao_id?: number; + secao?: string; + nome?: string; + valor?: string; + descricao?: string; + texto?: string; + terminal?: string; + tipo_valor?: string; + atualizado?: string; +} \ No newline at end of file diff --git a/src/shared/interfaces/WebCamDialogInterface.ts b/src/shared/interfaces/WebCamDialogInterface.ts new file mode 100644 index 0000000..55924fa --- /dev/null +++ b/src/shared/interfaces/WebCamDialogInterface.ts @@ -0,0 +1,5 @@ +export default interface WebCamDialogInterface { + isOpen: boolean; + onClose: (item: null, isFormStatus: boolean) => void; + onSave: (data: string) => void; +} \ No newline at end of file diff --git a/src/shared/services/FingerTech/FingerTechCaptureService.ts b/src/shared/services/FingerTech/FingerTechCaptureService.ts new file mode 100644 index 0000000..ef97f8b --- /dev/null +++ b/src/shared/services/FingerTech/FingerTechCaptureService.ts @@ -0,0 +1,9 @@ +import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; +import { FingerTechCaptureData } from '@/shared/data/fingertech/FingerTechCaptureData'; + +export default async function executeFingerTechCaputreService() { + const response = await FingerTechCaptureData(); + return response; +} + +export const FingerTechCaptureService = withClientErrorHandler(executeFingerTechCaputreService); diff --git a/src/shared/services/FingerTech/FingerTechEnrollService.ts b/src/shared/services/FingerTech/FingerTechEnrollService.ts new file mode 100644 index 0000000..7316166 --- /dev/null +++ b/src/shared/services/FingerTech/FingerTechEnrollService.ts @@ -0,0 +1,9 @@ +import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; +import { FingerTechEnrollData } from '@/shared/data/fingertech/FingerTechEnrollData'; + +export default async function executeFingerTechCEnrollService() { + const response = await FingerTechEnrollData(); + return response; +} + +export const FingerTechEnrollService = withClientErrorHandler(executeFingerTechCEnrollService); diff --git a/src/shared/services/FingerTech/FingerTechMatchService.ts b/src/shared/services/FingerTech/FingerTechMatchService.ts new file mode 100644 index 0000000..b52ddc7 --- /dev/null +++ b/src/shared/services/FingerTech/FingerTechMatchService.ts @@ -0,0 +1,9 @@ +import { withClientErrorHandler } from '@/shared/actions/withClientErrorHandler/withClientErrorHandler'; +import { FingerTechMatchData } from '@/shared/data/fingertech/FingerTechMatchData'; + +export default async function executeFingerTechMatchService() { + const response = await FingerTechMatchData(); + return response; +} + +export const FingerTechMatchService = withClientErrorHandler(executeFingerTechMatchService);