refactor(TServicoPedido): Refatoração da tela, otimizando e separando as responsabilidades
This commit is contained in:
parent
790dbe2df3
commit
32937c9501
16 changed files with 655 additions and 672 deletions
18
README.md
18
README.md
|
|
@ -5,3 +5,21 @@ NEXT_PUBLIC_ORIUS_APP_STATE=GO
|
|||
NEXT_PUBLIC_ORIUS_APP_API_URL=<http://localhost:8000/>
|
||||
NEXT_PUBLIC_ORIUS_APP_API_PREFIX=api/v1/
|
||||
NEXT_PUBLIC_ORIUS_APP_API_CONTENT_TYPE=application/json
|
||||
|
||||
## Modo Debug
|
||||
|
||||
Abra Run → Add Configuration… → Attach to Node.js
|
||||
|
||||
Configure:
|
||||
|
||||
{
|
||||
"name": "Attach Next.js (9230)",
|
||||
"type": "node",
|
||||
"request": "attach",
|
||||
"port": 9230,
|
||||
"restart": true,
|
||||
"smartStep": true,
|
||||
"skipFiles": ["<node_internals>/**"]
|
||||
}
|
||||
|
||||
npm run dev:debug
|
||||
|
|
|
|||
|
|
@ -12,9 +12,6 @@ const nextConfig = {
|
|||
eslint: { ignoreDuringBuilds: true },
|
||||
typescript: { ignoreBuildErrors: true },
|
||||
|
||||
// Removido o experimental.runtime (incompatível no Next 15)
|
||||
// O runtime agora é definido por rota ou via middleware (Edge/Node.js),
|
||||
// mas por padrão, tudo roda em Node.js quando "output: standalone" está ativo.
|
||||
};
|
||||
|
||||
module.exports = nextConfig;
|
||||
|
|
|
|||
206
package-lock.json
generated
206
package-lock.json
generated
|
|
@ -63,6 +63,7 @@
|
|||
"@types/react-dom": "^19",
|
||||
"@typescript-eslint/eslint-plugin": "^8.46.1",
|
||||
"@typescript-eslint/parser": "^8.46.1",
|
||||
"cross-env": "^10.1.0",
|
||||
"eslint": "^9.38.0",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-import-resolver-typescript": "^4.4.4",
|
||||
|
|
@ -400,6 +401,13 @@
|
|||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@epic-web/invariant": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@epic-web/invariant/-/invariant-1.0.0.tgz",
|
||||
"integrity": "sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@eslint-community/eslint-utils": {
|
||||
"version": "4.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz",
|
||||
|
|
@ -4254,6 +4262,24 @@
|
|||
"react": ">= 16.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cross-env": {
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cross-env/-/cross-env-10.1.0.tgz",
|
||||
"integrity": "sha512-GsYosgnACZTADcmEyJctkJIoqAhHjttw7RsFrVoJNXbsWWqaq6Ym+7kZjq6mS45O0jij6vtiReppKQEtqWy6Dw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@epic-web/invariant": "^1.0.0",
|
||||
"cross-spawn": "^7.0.6"
|
||||
},
|
||||
"bin": {
|
||||
"cross-env": "dist/bin/cross-env.js",
|
||||
"cross-env-shell": "dist/bin/cross-env-shell.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
}
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||
|
|
@ -4273,6 +4299,7 @@
|
|||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
||||
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
|
||||
"devOptional": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/d3-array": {
|
||||
|
|
@ -4396,127 +4423,6 @@
|
|||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/d3-array": {
|
||||
"version": "3.2.4",
|
||||
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz",
|
||||
"integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"internmap": "1 - 2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/d3-color": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz",
|
||||
"integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/d3-ease": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz",
|
||||
"integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==",
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/d3-format": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz",
|
||||
"integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/d3-interpolate": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
|
||||
"integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"d3-color": "1 - 3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/d3-path": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz",
|
||||
"integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/d3-scale": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz",
|
||||
"integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"d3-array": "2.10.0 - 3",
|
||||
"d3-format": "1 - 3",
|
||||
"d3-interpolate": "1.2.0 - 3",
|
||||
"d3-time": "2.1.1 - 3",
|
||||
"d3-time-format": "2 - 4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/d3-shape": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz",
|
||||
"integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"d3-path": "^3.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/d3-time": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz",
|
||||
"integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"d3-array": "2 - 3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/d3-time-format": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz",
|
||||
"integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"d3-time": "1 - 3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/d3-timer": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz",
|
||||
"integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/damerau-levenshtein": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
|
||||
|
|
@ -4612,12 +4518,6 @@
|
|||
"integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/decimal.js-light": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz",
|
||||
"integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/deep-is": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
|
||||
|
|
@ -4690,16 +4590,6 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dom-helpers": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
|
||||
"integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.8.7",
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/dunder-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||
|
|
@ -5615,15 +5505,6 @@
|
|||
"dev": true,
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/fast-equals": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.3.2.tgz",
|
||||
"integrity": "sha512-6rxyATwPCkaFIL3JLqw8qXqMpIZ942pTX/tbQFkRsDGblS8tNGtlUauA/+mt6RUfqn/4MoEr+WDkYoIQbibWuQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-glob": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
|
||||
|
|
@ -6187,15 +6068,6 @@
|
|||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/internmap": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz",
|
||||
"integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/is-array-buffer": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
|
||||
|
|
@ -7082,12 +6954,6 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.includes": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
|
||||
|
|
@ -8009,21 +7875,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-smooth": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.4.tgz",
|
||||
"integrity": "sha512-gnGKTpYwqL0Iii09gHobNolvX4Kiq4PKx6eWBCYYix+8cdw+cGo3do906l1NBPKkSWx1DghC1dlWG9L2uGd61Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-equals": "^5.0.1",
|
||||
"prop-types": "^15.8.1",
|
||||
"react-transition-group": "^4.4.5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-style-singleton": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz",
|
||||
|
|
@ -9000,9 +8851,6 @@
|
|||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.9.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
|
||||
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
||||
"version": "5.9.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
|
||||
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@
|
|||
"version": "25.9.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev --turbopack",
|
||||
"dev": "next dev",
|
||||
"dev:debug": "cross-env NEXT_USE_TURBOPACK=0 NODE_OPTIONS=\"--inspect=9230\" next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
|
|
@ -65,6 +66,7 @@
|
|||
"@types/react-dom": "^19",
|
||||
"@typescript-eslint/eslint-plugin": "^8.46.1",
|
||||
"@typescript-eslint/parser": "^8.46.1",
|
||||
"cross-env": "^10.1.0",
|
||||
"eslint": "^9.38.0",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-import-resolver-typescript": "^4.4.4",
|
||||
|
|
|
|||
|
|
@ -2,48 +2,15 @@
|
|||
|
||||
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: {},
|
||||
};
|
||||
|
||||
if (data?.pessoa?.pessoa_id) {
|
||||
item.subview = {
|
||||
servico: data.servico_tipo,
|
||||
pessoa: data.pessoa,
|
||||
};
|
||||
}
|
||||
|
||||
return item;
|
||||
return response;
|
||||
}
|
||||
|
||||
export const GCalculoServicoService = withClientErrorHandler(executeGCalculoServicoService);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import HandleSelectTServicoTipoInterface from './HandleSelectTServicoTipoInterface';
|
||||
|
||||
export default function HandleSelectTServicoTipoAction({
|
||||
export default function handleServicoTipoPessoaSelection({
|
||||
servico,
|
||||
emolumento,
|
||||
onOpenPessoaForm,
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
|
||||
export default function TServicoPedidoItemLocalPrepare(data, response) {
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
if (data?.pessoa?.pessoa_id) {
|
||||
item.subview = {
|
||||
servico: data.servico_tipo,
|
||||
pessoa: data.pessoa,
|
||||
};
|
||||
}
|
||||
|
||||
return item
|
||||
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import TServicoItemPedidoAddInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoAddInterface';
|
||||
|
||||
export default function TServicoPedidoItemPreparePayload(data: TServicoItemPedidoAddInterface) {
|
||||
|
||||
data.qtd = 1;
|
||||
data.valor_documento = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import { Minus, Plus } from 'lucide-react';
|
||||
import React, { memo } from 'react';
|
||||
import { useWatch } from 'react-hook-form';
|
||||
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
|
|
@ -17,12 +18,13 @@ import TPessoaTableFormSubview from '@/packages/administrativo/components/TPesso
|
|||
import TServicoItemPedidoFormTableInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoFormTableInterface';
|
||||
import GetCapitalize from '@/shared/actions/text/GetCapitalize';
|
||||
|
||||
function TServicoItemPedidoFormTableComponent({
|
||||
data,
|
||||
form,
|
||||
params,
|
||||
}: TServicoItemPedidoFormTableInterface) {
|
||||
console.log(data);
|
||||
function TServicoItemPedidoFormTableComponent({ form, params, handleChangeQtd }: TServicoItemPedidoFormTableInterface) {
|
||||
|
||||
const { control } = form;
|
||||
|
||||
// Sempre “ouve” o campo itens do formulário
|
||||
const data = useWatch({ control, name: 'itens' }) || [];
|
||||
|
||||
return (
|
||||
<div className="rounded-md border">
|
||||
<Table>
|
||||
|
|
@ -37,66 +39,71 @@ function TServicoItemPedidoFormTableComponent({
|
|||
<TableHead className="text-center">Qtd.</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
|
||||
<TableBody>
|
||||
{data?.length ? (
|
||||
data.map((item, index) => {
|
||||
return (
|
||||
<React.Fragment key={`fragment-${index}`}>
|
||||
{/* Linha principal */}
|
||||
<TableRow key={`row-${index}`} className="cursor-pointer hover:bg-gray-50">
|
||||
<TableCell>
|
||||
<div className="flex items-center gap-3">
|
||||
<div>
|
||||
<div className="font-semibold text-gray-900 capitalize">
|
||||
{GetCapitalize(item.descricao)}
|
||||
</div>
|
||||
<div className="text-sm text-gray-500">{GetCapitalize(item.tabela)}</div>
|
||||
{data.length ? (
|
||||
data.map((item, index) => (
|
||||
<React.Fragment key={`fragment-${index}`}>
|
||||
<TableRow className="cursor-pointer hover:bg-gray-50">
|
||||
<TableCell>
|
||||
<div className="flex items-center gap-3">
|
||||
<div>
|
||||
<div className="font-semibold text-gray-900 capitalize">
|
||||
{GetCapitalize(item.descricao)}
|
||||
</div>
|
||||
<div className="text-sm text-gray-500">{GetCapitalize(item.tabela)}</div>
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell>R$ {item.emolumento ?? '---'}</TableCell>
|
||||
<TableCell>R$ {item.taxa_judiciaria ?? '---'}</TableCell>
|
||||
<TableCell>R$ {item.fundesp ?? '---'}</TableCell>
|
||||
<TableCell>R$ {item.valor_iss ?? '---'}</TableCell>
|
||||
<TableCell>R$ {item.valor ?? '---'}</TableCell>
|
||||
<TableCell>
|
||||
<div className="flex items-center justify-center gap-1">
|
||||
<Button
|
||||
type="button"
|
||||
size="icon"
|
||||
variant="outline"
|
||||
className="h-8 w-8 rounded-lg border bg-white"
|
||||
>
|
||||
<Minus className="h-4 w-4" />
|
||||
</Button>
|
||||
<Input type="number" className="h-8 w-12 px-1 text-center" />
|
||||
<Button
|
||||
type="button"
|
||||
size="icon"
|
||||
variant="outline"
|
||||
className="h-8 w-8 rounded-lg border bg-white"
|
||||
>
|
||||
<Plus className="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell>R$ {item.emolumento ?? '---'}</TableCell>
|
||||
<TableCell>R$ {item.taxa_judiciaria ?? '---'}</TableCell>
|
||||
<TableCell>R$ {item.fundesp ?? '---'}</TableCell>
|
||||
<TableCell>R$ {item.valor_iss ?? '---'}</TableCell>
|
||||
<TableCell>R$ {item.valor ?? '---'}</TableCell>
|
||||
<TableCell>
|
||||
<div className="flex items-center justify-center gap-1">
|
||||
<Button
|
||||
type="button"
|
||||
size="icon"
|
||||
variant="outline"
|
||||
className="h-8 w-8 rounded-lg border bg-white"
|
||||
onClick={() => handleChangeQtd(index, -1)}
|
||||
>
|
||||
<Minus className="h-4 w-4" />
|
||||
</Button>
|
||||
<Input
|
||||
type="number"
|
||||
className="h-8 w-12 px-1 text-center"
|
||||
value={item.qtd ?? 1}
|
||||
readOnly
|
||||
/>
|
||||
<Button
|
||||
type="button"
|
||||
size="icon"
|
||||
variant="outline"
|
||||
className="h-8 w-8 rounded-lg border bg-white"
|
||||
onClick={() => handleChangeQtd(index, 1)}
|
||||
>
|
||||
<Plus className="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
|
||||
{item.subview && (
|
||||
<TableRow className="bg-gray-50">
|
||||
<TableCell colSpan={7} className="p-4">
|
||||
<TPessoaTableFormSubview
|
||||
item_index={Number(item.index)}
|
||||
data={item.subview}
|
||||
params={params}
|
||||
form={form}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
{/* SubView */}
|
||||
{item.subview && (
|
||||
<TableRow className="bg-gray-50">
|
||||
<TableCell colSpan={7} className="p-4">
|
||||
<TPessoaTableFormSubview
|
||||
item_index={Number(item.index)}
|
||||
data={item.subview}
|
||||
params={params}
|
||||
form={form}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
</React.Fragment>
|
||||
);
|
||||
})
|
||||
)}
|
||||
</React.Fragment>
|
||||
))
|
||||
) : (
|
||||
<TableRow>
|
||||
<TableCell colSpan={7} className="py-4 text-center">
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
'use client';
|
||||
|
||||
import { CreditCard, Package, UserSquare2 } from 'lucide-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
|
||||
import { CreditCardIcon, PackageIcon, UserSquare2Icon } from 'lucide-react';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
|
|
@ -21,295 +21,23 @@ import GEmolumentoServicoSelect from '@/packages/administrativo/components/GEmol
|
|||
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 useTServicoPedidoFormControllerHook from '@/packages/servicos/hooks/TServicoPedido/useTServicoPedidoFormControllerHook';
|
||||
import { TServicoPedidoFormInterface } from '@/packages/servicos/interfaces/TServicoPedido/TServicoPedidoFormInterface';
|
||||
import TServicoPedidoInterface from '@/packages/servicos/interfaces/TServicoPedido/TServicoPedidoInterface';
|
||||
import { TServicoPedidoFormValues } from '@/packages/servicos/schemas/TServicoPedido/TServicoPedidoFormSchema';
|
||||
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,
|
||||
StepSection
|
||||
} from '@/shared/components/step/stepNavigator';
|
||||
import TipoPagamentoSelect from '@/shared/components/tipoPagamento/TipoPagamentoSelect';
|
||||
import { SituacoesEnum } from '@/shared/enums/SituacoesEnum';
|
||||
|
||||
export default function TServicoPedidoForm({ servico_pedido_id }: TServicoPedidoFormInterface) {
|
||||
const router = useRouter();
|
||||
const form = useTServicoPedidoFormHook({});
|
||||
const { setValue, reset, watch } = form;
|
||||
|
||||
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<StepNavigatorRef>(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: TServicoPedidoFormValues) => {
|
||||
// Ativa o botão de loading
|
||||
setIsSaving(true);
|
||||
|
||||
// Converte o tipo do formulário (Zod) para o tipo da API (Interface)
|
||||
const payload: TServicoPedidoInterface = {
|
||||
...data,
|
||||
situacao: data.situacao as unknown as SituacoesEnum,
|
||||
};
|
||||
|
||||
const response = await saveTServicoPedido(payload);
|
||||
|
||||
setIsSaving(false);
|
||||
|
||||
// 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(() => {
|
||||
// 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]);
|
||||
const tServicoPedidoController = useTServicoPedidoFormControllerHook(servico_pedido_id)
|
||||
const { form } = tServicoPedidoController
|
||||
|
||||
// Memoriza os dados para não renderizar novamente
|
||||
const sections: StepSection[] = useMemo(
|
||||
|
|
@ -317,21 +45,21 @@ export default function TServicoPedidoForm({ servico_pedido_id }: TServicoPedido
|
|||
{
|
||||
key: 'pedido',
|
||||
id: 'selectPedido',
|
||||
icon: <Package className="h-4 w-4" />,
|
||||
icon: <PackageIcon className="h-4 w-4" />,
|
||||
title: 'Pedido',
|
||||
description: 'Dados gerais do pedido.',
|
||||
},
|
||||
{
|
||||
key: 'servicoPedidoItem',
|
||||
id: 'selectServicoPedidoItem',
|
||||
icon: <UserSquare2 className="h-4 w-4" />,
|
||||
icon: <UserSquare2Icon className="h-4 w-4" />,
|
||||
title: 'Itens',
|
||||
description: 'Itens/serviços do pedido.',
|
||||
},
|
||||
{
|
||||
key: 'payment',
|
||||
id: 'selectPayment',
|
||||
icon: <CreditCard className="h-4 w-4" />,
|
||||
icon: <CreditCardIcon className="h-4 w-4" />,
|
||||
title: 'Pagamento',
|
||||
description: 'Forma e dados de pagamento.',
|
||||
},
|
||||
|
|
@ -496,15 +224,16 @@ export default function TServicoPedidoForm({ servico_pedido_id }: TServicoPedido
|
|||
<LoadingButton
|
||||
text={`+ Adicionar`}
|
||||
textLoading="Adicionando..."
|
||||
onClick={handleSelectServicoTipo}
|
||||
loading={isAdding}
|
||||
onClick={tServicoPedidoController.handleSelectServicoTipo}
|
||||
loading={tServicoPedidoController.isAdding}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-12">
|
||||
<TServicoItemPedidoFormTable
|
||||
form={form}
|
||||
params={TServicoPedidoParams}
|
||||
data={TServicoItemPedidoLocal}
|
||||
params={tServicoPedidoController.TServicoPedidoParams}
|
||||
data={tServicoPedidoController.TServicoItemPedidoLocal}
|
||||
handleChangeQtd={tServicoPedidoController.handleChangeQtd}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -563,20 +292,23 @@ export default function TServicoPedidoForm({ servico_pedido_id }: TServicoPedido
|
|||
<FormField
|
||||
control={form.control}
|
||||
name="valor_pedido"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Valor do Pedido</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
type="number"
|
||||
onChange={(e) => field.onChange(parseNumberInput(e))}
|
||||
readOnly={true}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
render={({ field }) => {
|
||||
const valorPedido = form.watch('valor_pedido');
|
||||
return (
|
||||
<FormItem>
|
||||
<FormLabel>Valor do Pedido</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
type="number"
|
||||
value={valorPedido ?? 0}
|
||||
readOnly
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-12 md:col-span-4">
|
||||
|
|
@ -590,7 +322,7 @@ export default function TServicoPedidoForm({ servico_pedido_id }: TServicoPedido
|
|||
<Input
|
||||
{...field}
|
||||
type="number"
|
||||
onChange={(e) => field.onChange(parseNumberInput(e))}
|
||||
onChange={(e) => field.onChange(Number(e.target.value))}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
|
|
@ -623,7 +355,7 @@ export default function TServicoPedidoForm({ servico_pedido_id }: TServicoPedido
|
|||
<Card className="card-border">
|
||||
<CardContent>
|
||||
<StepNavigator
|
||||
ref={ref}
|
||||
ref={tServicoPedidoController.ref}
|
||||
sections={sections}
|
||||
defaultActive="pedido"
|
||||
scrollOffset={16}
|
||||
|
|
@ -639,9 +371,9 @@ export default function TServicoPedidoForm({ servico_pedido_id }: TServicoPedido
|
|||
<div className="flex items-center space-x-2">
|
||||
<Switch
|
||||
id="permanecer_formulario"
|
||||
checked={shouldKeepFormOpen}
|
||||
checked={tServicoPedidoController.shouldKeepFormOpen}
|
||||
onCheckedChange={(checked) => {
|
||||
setShouldKeepFormOpen(checked);
|
||||
tServicoPedidoController.setShouldKeepFormOpen(checked);
|
||||
}}
|
||||
/>
|
||||
<Label htmlFor="permanecer_formulario">Permanecer no formulário</Label>
|
||||
|
|
@ -650,15 +382,15 @@ export default function TServicoPedidoForm({ servico_pedido_id }: TServicoPedido
|
|||
className="w-full"
|
||||
variant="outline"
|
||||
type="button"
|
||||
onClick={handleOpenCancelDialog}
|
||||
onClick={tServicoPedidoController.handleOpenCancelDialog}
|
||||
>
|
||||
Cancelar
|
||||
</Button>
|
||||
<LoadingButton
|
||||
text="Salvar"
|
||||
textLoading="Salvando..."
|
||||
onClick={handleOpenSaveConfirm}
|
||||
loading={isSaving}
|
||||
onClick={tServicoPedidoController.handleOpenSaveConfirm}
|
||||
loading={tServicoPedidoController.isSaving}
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
|
@ -668,41 +400,41 @@ export default function TServicoPedidoForm({ servico_pedido_id }: TServicoPedido
|
|||
</form>
|
||||
|
||||
{/* Cofirmação de envio de dados */}
|
||||
{isSaveConfirmOpen && (
|
||||
{tServicoPedidoController.isSaveConfirmOpen && (
|
||||
<ConfirmDialog
|
||||
isOpen={isSaveConfirmOpen}
|
||||
isOpen={tServicoPedidoController.isSaveConfirmOpen}
|
||||
title="Confirmar pedido"
|
||||
description="Atenção"
|
||||
message="Deseja confirmar o pedido?"
|
||||
confirmText="Sim, confirmar"
|
||||
cancelText="Cancelar"
|
||||
onConfirm={handleSubmitWithConfirmation}
|
||||
onCancel={handleCloseSaveConfirm}
|
||||
onConfirm={tServicoPedidoController.handleSubmitWithConfirmation}
|
||||
onCancel={tServicoPedidoController.handleCloseSaveConfirm}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Confirma o cancelamento do pedido */}
|
||||
{isCancelDialogOpen && (
|
||||
{tServicoPedidoController.isCancelDialogOpen && (
|
||||
<ConfirmDialog
|
||||
isOpen={isCancelDialogOpen}
|
||||
isOpen={tServicoPedidoController.isCancelDialogOpen}
|
||||
title="Cancelamento de pedido"
|
||||
description="Atenção"
|
||||
message="Deseja cancelar o pedido? Os dados não serão salvos!"
|
||||
confirmText="Sim, cancelar"
|
||||
cancelText="Fechar"
|
||||
onConfirm={handleConfirmCancel}
|
||||
onCancel={handleCloseCancelDialog}
|
||||
onConfirm={tServicoPedidoController.handleConfirmCancel}
|
||||
onCancel={tServicoPedidoController.handleCloseCancelDialog}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Modal TPessoa */}
|
||||
{isPessoaFormOpen && (
|
||||
{tServicoPedidoController.isPessoaFormOpen && (
|
||||
<TPessoaTableFormDialog
|
||||
isOpen={isPessoaFormOpen}
|
||||
tipoPessoa={selectedPessoaTipo}
|
||||
onClose={handleClosePessoaForm}
|
||||
onSave={handleAddItemWithPessoa}
|
||||
buttonIsLoading={isSaving}
|
||||
isOpen={tServicoPedidoController.isPessoaFormOpen}
|
||||
tipoPessoa={tServicoPedidoController.selectedPessoaTipo}
|
||||
onClose={tServicoPedidoController.handleClosePessoaForm}
|
||||
onSave={tServicoPedidoController.handleAddItemWithPessoa}
|
||||
buttonIsLoading={tServicoPedidoController.isSaving}
|
||||
/>
|
||||
)}
|
||||
</Form>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,16 @@
|
|||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { FieldValues, Path, PathValue, UseFormSetValue } from 'react-hook-form';
|
||||
|
||||
import { GCalculoServicoService } from '@/packages/administrativo/services/GCalculo/GCalculoServicoService';
|
||||
import TServicoPedidoItemLocalPrepare from '@/packages/servicos/actions/TServicoPedidoItem/TServicoPedidoItemLocalPrepare';
|
||||
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<TFormValues extends FieldValues>(
|
||||
setValue?: UseFormSetValue<TFormValues>,
|
||||
) {
|
||||
|
|
@ -17,8 +19,9 @@ export function useTServicoItemPedidoCalculoHook<TFormValues extends FieldValues
|
|||
const [TServicoItemPedido, setTServicoItemPedido] = useState<
|
||||
TServicoItemPedidoCalculoResponseInterface[]
|
||||
>([]);
|
||||
const [shouldSync, setShouldSync] = useState(false);
|
||||
|
||||
const addTServicoItemPedido = async (data: TServicoItemPedidoAddInterface) => {
|
||||
const calculoTServicoItemPedido = async (data: TServicoItemPedidoAddInterface) => {
|
||||
const payload = TServicoPedidoItemPreparePayload(data);
|
||||
|
||||
if (payload.status) {
|
||||
|
|
@ -26,39 +29,41 @@ export function useTServicoItemPedidoCalculoHook<TFormValues extends FieldValues
|
|||
return;
|
||||
}
|
||||
|
||||
const response = await GCalculoServicoService(payload, data);
|
||||
const response = await GCalculoServicoService(payload);
|
||||
|
||||
if (response.status) {
|
||||
if (response.status != 200) {
|
||||
setResponse(response);
|
||||
return;
|
||||
}
|
||||
|
||||
setTServicoItemPedido((prev) => {
|
||||
const safePrev = Array.isArray(prev) ? prev : [];
|
||||
const itemLocal = TServicoPedidoItemLocalPrepare(data, response);
|
||||
|
||||
const novoItem = response;
|
||||
if (!itemLocal) return;
|
||||
|
||||
if (!novoItem) return safePrev;
|
||||
// Atualiza apenas o estado local
|
||||
setTServicoItemPedido((prev) => [...prev, itemLocal]);
|
||||
|
||||
const novoArray = [...safePrev, novoItem];
|
||||
// Marca para sincronizar com o formulário
|
||||
setShouldSync(true);
|
||||
|
||||
if (setValue) {
|
||||
setValue(
|
||||
'itens' as Path<TFormValues>,
|
||||
novoArray as unknown as PathValue<TFormValues, Path<TFormValues>>,
|
||||
{ shouldDirty: true },
|
||||
);
|
||||
}
|
||||
|
||||
return novoArray;
|
||||
});
|
||||
|
||||
return response;
|
||||
return itemLocal;
|
||||
};
|
||||
|
||||
// Efeito seguro para sincronizar com o react-hook-form após o render
|
||||
useEffect(() => {
|
||||
if (setValue && shouldSync) {
|
||||
setValue(
|
||||
'itens' as Path<TFormValues>,
|
||||
TServicoItemPedido as unknown as PathValue<TFormValues, Path<TFormValues>>,
|
||||
{ shouldDirty: true },
|
||||
);
|
||||
setShouldSync(false);
|
||||
}
|
||||
}, [setValue, shouldSync, TServicoItemPedido]);
|
||||
|
||||
return {
|
||||
TServicoItemPedido,
|
||||
setTServicoItemPedido,
|
||||
addTServicoItemPedido,
|
||||
calculoTServicoItemPedido,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,47 +0,0 @@
|
|||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import { FieldValues, Path, PathValue, UseFormSetValue } from 'react-hook-form';
|
||||
|
||||
import TServicoItemPedidoCalculoResponseInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoCalculoResponseInterface';
|
||||
|
||||
export function useTServicoItemPedidoLocalAddHook<TFormValues extends FieldValues>(
|
||||
setValue?: UseFormSetValue<TFormValues>,
|
||||
) {
|
||||
const [TServicoItemPedidoLocal, setLocalTServicoItemPedido] = useState<
|
||||
TServicoItemPedidoCalculoResponseInterface[]
|
||||
>([]);
|
||||
|
||||
const localAddTServicoItemPedido = (item: TServicoItemPedidoCalculoResponseInterface) => {
|
||||
setLocalTServicoItemPedido((prev) => {
|
||||
const updated = [...prev, item];
|
||||
|
||||
if (setValue) {
|
||||
setValue(
|
||||
'itens' as Path<TFormValues>,
|
||||
updated as unknown as PathValue<TFormValues, Path<TFormValues>>,
|
||||
);
|
||||
}
|
||||
|
||||
return updated;
|
||||
});
|
||||
};
|
||||
|
||||
const localClearTServicoItemPedido = () => {
|
||||
setLocalTServicoItemPedido([]);
|
||||
|
||||
if (setValue) {
|
||||
setValue(
|
||||
'itens' as Path<TFormValues>,
|
||||
[] as unknown as PathValue<TFormValues, Path<TFormValues>>,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
TServicoItemPedidoLocal,
|
||||
localAddTServicoItemPedido,
|
||||
setLocalTServicoItemPedido,
|
||||
localClearTServicoItemPedido,
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
'use client';
|
||||
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { FieldValues, Path, PathValue, UseFormSetValue } from 'react-hook-form';
|
||||
|
||||
import TServicoItemPedidoCalculoResponseInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoCalculoResponseInterface';
|
||||
|
||||
export function useTServicoItemPedidoLocalHandleHook<TFormValues extends FieldValues>(
|
||||
setValue?: UseFormSetValue<TFormValues>,
|
||||
) {
|
||||
const [TServicoItemPedidoLocal, setLocalTServicoItemPedido] = useState<
|
||||
TServicoItemPedidoCalculoResponseInterface[]
|
||||
>([]);
|
||||
|
||||
// Estado auxiliar para indicar que o form deve ser atualizado
|
||||
const [shouldSync, setShouldSync] = useState(false);
|
||||
|
||||
// Adiciona item localmente (apenas atualiza o state)
|
||||
const localAddTServicoItemPedido = (item: TServicoItemPedidoCalculoResponseInterface) => {
|
||||
setLocalTServicoItemPedido((prev) => [...prev, item]);
|
||||
setShouldSync(true);
|
||||
};
|
||||
|
||||
// Remove item por índice
|
||||
const localRemoveTServicoItemPedido = useCallback((index: number) => {
|
||||
setLocalTServicoItemPedido((prev) => prev.filter((_, i) => i !== index));
|
||||
setShouldSync(true);
|
||||
}, []);
|
||||
|
||||
// Limpa os itens
|
||||
const localClearTServicoItemPedido = () => {
|
||||
setLocalTServicoItemPedido([]);
|
||||
setShouldSync(true);
|
||||
};
|
||||
|
||||
// Efeito responsável por sincronizar o formulário depois da atualização
|
||||
useEffect(() => {
|
||||
if (setValue && shouldSync) {
|
||||
setValue(
|
||||
'itens' as Path<TFormValues>,
|
||||
TServicoItemPedidoLocal as unknown as PathValue<TFormValues, Path<TFormValues>>,
|
||||
{ shouldDirty: true },
|
||||
);
|
||||
setShouldSync(false);
|
||||
}
|
||||
}, [setValue, shouldSync, TServicoItemPedidoLocal]);
|
||||
|
||||
return {
|
||||
TServicoItemPedidoLocal,
|
||||
localAddTServicoItemPedido,
|
||||
localRemoveTServicoItemPedido,
|
||||
setLocalTServicoItemPedido,
|
||||
localClearTServicoItemPedido,
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,363 @@
|
|||
'use client';
|
||||
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
|
||||
import TPessoaInterface from '@/packages/administrativo/interfaces/TPessoa/TPessoaInterface';
|
||||
import { useTServicoItemPedidoCalculoHook } from '@/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoCalculoHook';
|
||||
import { useTServicoItemPedidoIndexHook } from '@/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoIndexHook';
|
||||
import { useTServicoItemPedidoLocalHandleHook } from '@/packages/servicos/hooks/TServicoItemPedido/useTServicoItemPedidoLocalHandleHook';
|
||||
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 TServicoPedidoInterface from '@/packages/servicos/interfaces/TServicoPedido/TServicoPedidoInterface';
|
||||
import { TServicoPedidoFormValues } from '@/packages/servicos/schemas/TServicoPedido/TServicoPedidoFormSchema';
|
||||
import { useResponse } from '@/shared/components/response/ResponseContext';
|
||||
import { StepNavigatorRef } from '@/shared/components/step/stepNavigator';
|
||||
import { SituacoesEnum } from '@/shared/enums/SituacoesEnum';
|
||||
import { TipoPessoaEnum } from '@/shared/enums/TipoPessoaEnum';
|
||||
|
||||
export default function useTServicoPedidoFormControllerHook(servico_pedido_id?: number) {
|
||||
|
||||
const router = useRouter();
|
||||
const form = useTServicoPedidoFormHook({});
|
||||
const { setValue, reset, watch } = form;
|
||||
|
||||
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<StepNavigatorRef>(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, localRemoveTServicoItemPedido, setLocalTServicoItemPedido } = useTServicoItemPedidoLocalHandleHook(setValue);
|
||||
const { calculoTServicoItemPedido } = 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: TServicoPedidoFormValues) => {
|
||||
// Ativa o botão de loading
|
||||
setIsSaving(true);
|
||||
|
||||
// Converte o tipo do formulário (Zod) para o tipo da API (Interface)
|
||||
const payload: TServicoPedidoInterface = {
|
||||
...data,
|
||||
situacao: data.situacao as unknown as SituacoesEnum,
|
||||
};
|
||||
|
||||
const response = await saveTServicoPedido(payload);
|
||||
|
||||
// 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) => {
|
||||
handleAddItem(selectedTPessoa)
|
||||
}, [selectedEmolumento, selectedServicoTipo]);
|
||||
|
||||
// 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);
|
||||
}, []);
|
||||
|
||||
const handleRemoveLocalItem = useCallback(async (index: number) => {
|
||||
|
||||
localRemoveTServicoItemPedido(index)
|
||||
|
||||
}, []);
|
||||
|
||||
// Controle de itens
|
||||
const handleAddItem = useCallback(async (selectedTPessoa?: TPessoaInterface) => {
|
||||
|
||||
setIsAdding(true);
|
||||
|
||||
// Prepara e valida os dados de item do pedido
|
||||
const payload = {
|
||||
servico_tipo: selectedServicoTipo,
|
||||
emolumento: selectedEmolumento,
|
||||
};
|
||||
|
||||
// Se existir pessoa, adiciona ao payload
|
||||
if (selectedTPessoa) {
|
||||
payload.pessoa = selectedTPessoa;
|
||||
}
|
||||
|
||||
// Obtem o resultado da adição do item
|
||||
const item = await calculoTServicoItemPedido(payload);
|
||||
|
||||
// Verifica se foi realizado o calculo
|
||||
if (!item) {
|
||||
setResponse({
|
||||
status: 422,
|
||||
detail: 'Não foi localizado item para o serviço',
|
||||
})
|
||||
setIsAdding(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Define índice e adiciona localmente
|
||||
const index = TServicoItemPedidoLocal.length;
|
||||
|
||||
// Guarda o indice
|
||||
item.index = index
|
||||
|
||||
// Adiciona o item calculo localmente
|
||||
localAddTServicoItemPedido(item)
|
||||
|
||||
// Define os itens
|
||||
form.setValue(`itens.${index}`, item);
|
||||
|
||||
setIsAdding(false);
|
||||
|
||||
}, [calculoTServicoItemPedido, 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 tipoPessoa = [TipoPessoaEnum.FISICA, TipoPessoaEnum.JURIDICA]
|
||||
|
||||
// Verifica se o emolumento e o tipo de serviço foram selecionados
|
||||
if (!selectedServicoTipo || !selectedEmolumento) {
|
||||
setResponse({
|
||||
status: 422,
|
||||
detail: 'Serviço e emolumento devem ser selecionados',
|
||||
})
|
||||
return;
|
||||
}
|
||||
|
||||
// Verifica se deve selecionar pessoas
|
||||
switch (tipoPessoa.includes(selectedServicoTipo.tipo_pessoa)) {
|
||||
|
||||
// Habilita o formulário
|
||||
case true:
|
||||
|
||||
handleOpenPessoaForm(selectedServicoTipo.tipo_pessoa);
|
||||
break;
|
||||
|
||||
// Adiciona direto
|
||||
default:
|
||||
|
||||
handleAddItem();
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}, [selectedServicoTipo, selectedEmolumento, handleOpenPessoaForm, handleAddItem]);
|
||||
|
||||
const calcularTotais = useCallback(() => {
|
||||
const itens = form.getValues('itens') || [];
|
||||
|
||||
if (!itens.length) {
|
||||
setValue('valor_pedido', 0, { shouldDirty: true });
|
||||
setValue('valor_pago', 0, { shouldDirty: true });
|
||||
return;
|
||||
}
|
||||
|
||||
const total = itens.reduce((acc, item) => acc + Number(item.valor ?? 0), 0);
|
||||
|
||||
// Atualiza sempre o valor do pedido
|
||||
setValue('valor_pedido', total, { shouldDirty: true });
|
||||
|
||||
// Atualiza o valor pago apenas se estiver vazio, null, undefined ou 0
|
||||
const valorPagoAtual = Number(form.getValues('valor_pago')) || 0;
|
||||
if (!valorPagoAtual) {
|
||||
setValue('valor_pago', total, { shouldDirty: true });
|
||||
}
|
||||
}, [form, setValue]);
|
||||
|
||||
// Incremente ou decrementa a quantidade
|
||||
const handleChangeQtd = useCallback(
|
||||
(index: number, delta: number) => {
|
||||
const currentItens = form.getValues('itens') || [];
|
||||
const currentItem = currentItens[index];
|
||||
if (!currentItem) return;
|
||||
|
||||
const currentQtd = Number(currentItem.qtd ?? 1);
|
||||
const newQtd = currentQtd + delta;
|
||||
|
||||
// Se quantidade for 0 ou menor, remove o item
|
||||
if (newQtd <= 0) {
|
||||
const filteredItens = currentItens.filter((_, i) => i !== index);
|
||||
form.setValue('itens', filteredItens, { shouldDirty: true });
|
||||
localRemoveTServicoItemPedido(index);
|
||||
calcularTotais();
|
||||
return;
|
||||
}
|
||||
|
||||
const multiplier = newQtd / currentQtd;
|
||||
|
||||
const updatedItem = {
|
||||
...currentItem,
|
||||
qtd: newQtd,
|
||||
emolumento: (Number(currentItem.emolumento) * multiplier).toFixed(2),
|
||||
taxa_judiciaria: (Number(currentItem.taxa_judiciaria) * multiplier).toFixed(2),
|
||||
fundesp: (Number(currentItem.fundesp) * multiplier).toFixed(2),
|
||||
valor_iss: (Number(currentItem.valor_iss) * multiplier).toFixed(2),
|
||||
valor: (Number(currentItem.valor) * multiplier).toFixed(2),
|
||||
};
|
||||
|
||||
const updatedItens = [...currentItens];
|
||||
updatedItens[index] = updatedItem;
|
||||
|
||||
form.setValue('itens', updatedItens, { shouldDirty: true });
|
||||
calcularTotais();
|
||||
},
|
||||
[form, localRemoveTServicoItemPedido, calcularTotais],
|
||||
);
|
||||
|
||||
// Dispara a busca do pedido
|
||||
useEffect(() => {
|
||||
// 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]);
|
||||
|
||||
return {
|
||||
form,
|
||||
ref,
|
||||
isSaving,
|
||||
isAdding,
|
||||
isPessoaFormOpen,
|
||||
isSaveConfirmOpen,
|
||||
isCancelDialogOpen,
|
||||
shouldKeepFormOpen,
|
||||
selectedPessoaTipo,
|
||||
TServicoItemPedidoLocal,
|
||||
TServicoPedidoParams,
|
||||
|
||||
// setters diretos
|
||||
setIsSaveConfirmOpen,
|
||||
setIsCancelDialogOpen,
|
||||
setShouldKeepFormOpen,
|
||||
|
||||
// handlers principais
|
||||
handleSavePedido,
|
||||
handleSelectServicoTipo,
|
||||
handleSubmitWithConfirmation,
|
||||
handleCloseSaveConfirm,
|
||||
handleOpenCancelDialog,
|
||||
handleConfirmCancel,
|
||||
handleCloseCancelDialog,
|
||||
handleClosePessoaForm,
|
||||
handleAddItemWithPessoa,
|
||||
handleOpenSaveConfirm,
|
||||
handleChangeQtd
|
||||
};
|
||||
}
|
||||
|
|
@ -1,12 +1,13 @@
|
|||
import { UseFormReturn } from 'react-hook-form';
|
||||
|
||||
import TServicoItemPedidoAddResponseInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoCalculoResponseInterface';
|
||||
import { TServicoPedidoFormValues } from '@/packages/servicos/schemas/TServicoPedido/TServicoPedidoFormSchema';
|
||||
import GConfigInterface from '@/shared/interfaces/GConfigInterface';
|
||||
|
||||
import { TServicoPedidoFormValues } from '../../schemas/TServicoPedido/TServicoPedidoFormSchema';
|
||||
|
||||
export default interface TServicoItemPedidoFormTableInterface {
|
||||
data: TServicoItemPedidoAddResponseInterface[];
|
||||
form: UseFormReturn<TServicoPedidoFormValues>;
|
||||
params: GConfigInterface[];
|
||||
handleChangeQtd: any;
|
||||
}
|
||||
|
|
|
|||
4
src/shared/enums/TipoPessoaEnum.ts
Normal file
4
src/shared/enums/TipoPessoaEnum.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
export const TipoPessoaEnum = {
|
||||
FISICA: "F",
|
||||
JURIDICA: "J"
|
||||
} as const
|
||||
Loading…
Add table
Reference in a new issue