backup: Backup de código
This commit is contained in:
parent
79f2092882
commit
e50818e52a
45 changed files with 1518 additions and 443 deletions
33
package-lock.json
generated
33
package-lock.json
generated
|
|
@ -19,6 +19,7 @@
|
|||
"@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",
|
||||
|
|
@ -1992,6 +1993,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",
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
"@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",
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
<TServicoPedidoDetails
|
||||
servico_pedido_id={Number(params.servicoPedidoId)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
@ -69,116 +69,166 @@
|
|||
}
|
||||
|
||||
: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);
|
||||
--background: #f8fafc;
|
||||
--foreground: #1e293b;
|
||||
--card: #ffffff;
|
||||
--card-foreground: #1e293b;
|
||||
--popover: #ffffff;
|
||||
--popover-foreground: #1e293b;
|
||||
--primary: #1a292f;
|
||||
--primary-foreground: #ffffff;
|
||||
--secondary: #e5e7eb;
|
||||
--secondary-foreground: #162227;
|
||||
--muted: #f3f4f6;
|
||||
--muted-foreground: #6b7280;
|
||||
--accent: #e0e7ff;
|
||||
--accent-foreground: #2b454f;
|
||||
--destructive: #ef4444;
|
||||
--destructive-foreground: #ffffff;
|
||||
--border: #d1d5db;
|
||||
--input: #d1d5db;
|
||||
--ring: #2b454f;
|
||||
--chart-1: #f26f28;
|
||||
--chart-2: #f26418;
|
||||
--chart-3: #e75a0d;
|
||||
--chart-4: #c14b0b;
|
||||
--chart-5: #9a3c09;
|
||||
--sidebar: #f3f4f6;
|
||||
--sidebar-foreground: #1e293b;
|
||||
--sidebar-primary: #2b454f;
|
||||
--sidebar-primary-foreground: #ffffff;
|
||||
--sidebar-accent: #1a292f;
|
||||
--sidebar-accent-foreground: #374151;
|
||||
--sidebar-border: #ffffff;
|
||||
--sidebar-ring: #2b454f;
|
||||
--font-sans: Inter, sans-serif;
|
||||
--font-serif: Source Serif 4, serif;
|
||||
--font-serif: Merriweather, serif;
|
||||
--font-mono: JetBrains Mono, monospace;
|
||||
--shadow-color: hsl(0 0% 0%);
|
||||
--shadow-opacity: 0.1;
|
||||
--radius: 0.5rem;
|
||||
--shadow-x: 0px;
|
||||
--shadow-y: 4px;
|
||||
--shadow-blur: 8px;
|
||||
--shadow-spread: -1px;
|
||||
--shadow-offset-x: 0px;
|
||||
--shadow-offset-y: 4px;
|
||||
--letter-spacing: 0em;
|
||||
--spacing: 0.25rem;
|
||||
--shadow-opacity: 0.1;
|
||||
--shadow-color: hsl(0 0% 0%);
|
||||
--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-sm: 0px 4px 8px -1px hsl(0 0% 0% / 0.10), 0px 1px 2px -2px hsl(0 0% 0% / 0.10);
|
||||
--shadow: 0px 4px 8px -1px hsl(0 0% 0% / 0.10), 0px 1px 2px -2px hsl(0 0% 0% / 0.10);
|
||||
--shadow-md: 0px 4px 8px -1px hsl(0 0% 0% / 0.10), 0px 2px 4px -2px hsl(0 0% 0% / 0.10);
|
||||
--shadow-lg: 0px 4px 8px -1px hsl(0 0% 0% / 0.10), 0px 4px 6px -2px hsl(0 0% 0% / 0.10);
|
||||
--shadow-xl: 0px 4px 8px -1px hsl(0 0% 0% / 0.10), 0px 8px 10px -2px hsl(0 0% 0% / 0.10);
|
||||
--shadow-2xl: 0px 4px 8px -1px hsl(0 0% 0% / 0.25);
|
||||
--tracking-normal: 0em;
|
||||
--spacing: 0.25rem;
|
||||
}
|
||||
|
||||
.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;
|
||||
--background: #0f172a;
|
||||
--foreground: #e2e8f0;
|
||||
--card: #1e293b;
|
||||
--card-foreground: #e2e8f0;
|
||||
--popover: #1e293b;
|
||||
--popover-foreground: #e2e8f0;
|
||||
--primary: #818cf8;
|
||||
--primary-foreground: #0f172a;
|
||||
--secondary: #2d3748;
|
||||
--secondary-foreground: #d1d5db;
|
||||
--muted: #152032;
|
||||
--muted-foreground: #9ca3af;
|
||||
--accent: #374151;
|
||||
--accent-foreground: #d1d5db;
|
||||
--destructive: #ef4444;
|
||||
--destructive-foreground: #0f172a;
|
||||
--border: #4b5563;
|
||||
--input: #4b5563;
|
||||
--ring: #818cf8;
|
||||
--chart-1: #818cf8;
|
||||
--chart-2: #6366f1;
|
||||
--chart-3: #4f46e5;
|
||||
--chart-4: #4338ca;
|
||||
--chart-5: #3730a3;
|
||||
--sidebar: #1e293b;
|
||||
--sidebar-foreground: #e2e8f0;
|
||||
--sidebar-primary: #818cf8;
|
||||
--sidebar-primary-foreground: #0f172a;
|
||||
--sidebar-accent: #374151;
|
||||
--sidebar-accent-foreground: #d1d5db;
|
||||
--sidebar-border: #4b5563;
|
||||
--sidebar-ring: #818cf8;
|
||||
--font-sans: Inter, sans-serif;
|
||||
--font-serif: Source Serif 4, serif;
|
||||
--font-serif: Merriweather, serif;
|
||||
--font-mono: JetBrains Mono, monospace;
|
||||
--shadow-color: hsl(0 0% 0%);
|
||||
--shadow-opacity: 0.1;
|
||||
--radius: 0.5rem;
|
||||
--shadow-x: 0px;
|
||||
--shadow-y: 4px;
|
||||
--shadow-blur: 8px;
|
||||
--shadow-spread: -1px;
|
||||
--shadow-offset-x: 0px;
|
||||
--shadow-offset-y: 4px;
|
||||
--letter-spacing: 0em;
|
||||
--spacing: 0.25rem;
|
||||
--shadow-opacity: 0.1;
|
||||
--shadow-color: hsl(0 0% 0%);
|
||||
--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-sm: 0px 4px 8px -1px hsl(0 0% 0% / 0.10), 0px 1px 2px -2px hsl(0 0% 0% / 0.10);
|
||||
--shadow: 0px 4px 8px -1px hsl(0 0% 0% / 0.10), 0px 1px 2px -2px hsl(0 0% 0% / 0.10);
|
||||
--shadow-md: 0px 4px 8px -1px hsl(0 0% 0% / 0.10), 0px 2px 4px -2px hsl(0 0% 0% / 0.10);
|
||||
--shadow-lg: 0px 4px 8px -1px hsl(0 0% 0% / 0.10), 0px 4px 6px -2px hsl(0 0% 0% / 0.10);
|
||||
--shadow-xl: 0px 4px 8px -1px hsl(0 0% 0% / 0.10), 0px 8px 10px -2px hsl(0 0% 0% / 0.10);
|
||||
--shadow-2xl: 0px 4px 8px -1px hsl(0 0% 0% / 0.25);
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
--color-background: var(--background);
|
||||
--color-foreground: var(--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: var(--font-sans);
|
||||
--font-mono: var(--font-mono);
|
||||
--font-serif: var(--font-serif);
|
||||
|
||||
--radius-sm: calc(var(--radius) - 4px);
|
||||
--radius-md: calc(var(--radius) - 2px);
|
||||
--radius-lg: var(--radius);
|
||||
--radius-xl: calc(var(--radius) + 4px);
|
||||
|
||||
--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);
|
||||
}
|
||||
|
||||
@layer base {
|
||||
* {
|
||||
@apply border-border outline-ring/50;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,114 @@
|
|||
'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';
|
||||
|
||||
|
||||
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.
|
||||
* useCallback evita recriação desnecessária da função.
|
||||
*/
|
||||
const loadData = useCallback(async () => {
|
||||
if (tServicoTipo.length) return;
|
||||
setIsLoading(true);
|
||||
await fetchTServicoTipo();
|
||||
setIsLoading(false);
|
||||
}, [tServicoTipo.length, fetchTServicoTipo]);
|
||||
|
||||
useEffect(() => {
|
||||
loadData();
|
||||
}, [loadData]);
|
||||
|
||||
/**
|
||||
* Memoriza o bairro selecionado para evitar reprocessamentos.
|
||||
*/
|
||||
const selected = useMemo(
|
||||
() => tServicoTipo.find((b) => String(b.servico_tipo_id) === String(field?.value ?? '')),
|
||||
[tServicoTipo, 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 (
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<FormControl className="w-full">
|
||||
<Button
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
aria-expanded={open}
|
||||
disabled={isLoading}
|
||||
className="justify-between"
|
||||
>
|
||||
{isLoading
|
||||
? 'Carregando...'
|
||||
: selected
|
||||
? GetCapitalize(selected.descricao)
|
||||
: 'Selecione...'}
|
||||
<ChevronsUpDownIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</FormControl>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-full p-0">
|
||||
<Command>
|
||||
<CommandInput placeholder="Buscar bairro..." disabled={isLoading} />
|
||||
<CommandList>
|
||||
<CommandEmpty>
|
||||
{isLoading ? 'Carregando...' : 'Nenhum resultado encontrado.'}
|
||||
</CommandEmpty>
|
||||
<CommandGroup>
|
||||
{tServicoTipo.map((item) => (
|
||||
<CommandItem
|
||||
key={item.servico_tipo_id}
|
||||
value={item.descricao?.toLowerCase() ?? ''}
|
||||
onSelect={() => handleSelect(Number(item.servico_tipo_id))}
|
||||
>
|
||||
<CheckIcon
|
||||
className={cn(
|
||||
'mr-2 h-4 w-4',
|
||||
String(field?.value ?? '') === String(item.servico_tipo_id)
|
||||
? 'opacity-100'
|
||||
: 'opacity-0',
|
||||
)}
|
||||
/>
|
||||
{GetCapitalize(item.descricao ?? '')}
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
|
|
@ -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'; //
|
||||
|
|
@ -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'; //
|
||||
|
|
@ -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'; //
|
||||
|
|
@ -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 = () => {
|
||||
|
|
@ -2,10 +2,10 @@ import { useResponse } from '@/shared/components/response/ResponseContext'; // C
|
|||
import { useState } from 'react';
|
||||
|
||||
// Serviço que busca a lista de tipos de serviço (TServicoTipoIndexService)
|
||||
import { TServicoTipoIndexService } from '../../_services/t_servico_tipo/TServicoTipoIndexService';
|
||||
import { TServicoTipoIndexService } from '../../services/TServicoTipo/TServicoTipoIndexService';
|
||||
|
||||
// Interface tipada do tipo de serviço
|
||||
import TServicoTipoInterface from '../../_interfaces/TServicoTipoInterface';
|
||||
import TServicoTipoInterface from '../../../../app/(protected)/(cadastros)/cadastros/_interfaces/TServicoTipoInterface';
|
||||
|
||||
// Hook customizado para leitura de dados de tipos de serviço
|
||||
export const useTServicoTipoReadHook = () => {
|
||||
|
|
@ -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 = () => {
|
||||
|
|
@ -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();
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
export default interface TServicoTipoSelectInterface {
|
||||
field?: {
|
||||
value?: number | string;
|
||||
onChange?: (value: string | number) => void;
|
||||
};
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
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';
|
||||
// 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
|
||||
|
|
@ -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
|
||||
|
|
@ -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) {
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
import { ColumnDef } from '@tanstack/react-table';
|
||||
import { Minus, Plus } from 'lucide-react';
|
||||
|
||||
import { Button } from '@/components/ui/button';
|
||||
import TServicoItemPedidoInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoIntefarce';
|
||||
import GetCapitalize from '@/shared/actions/text/GetCapitalize';
|
||||
import { SortableHeader } from '@/shared/components/dataTable/SortableHeader';
|
||||
|
||||
/** Permite atualizar a linha externamente, caso o DataTable forneça meta.updateData */
|
||||
type TableMeta = {
|
||||
updateData?: (rowIndex: number, columnId: string, value: unknown) => void;
|
||||
};
|
||||
|
||||
export default function TServicoItemPedidoFormColumns(
|
||||
onEdit: (item: TServicoItemPedidoInterface, isEditingFormStatus: boolean) => void,
|
||||
onDelete: (item: TServicoItemPedidoInterface, isEditingFormStatus: boolean) => void,
|
||||
): ColumnDef<TServicoItemPedidoInterface>[] {
|
||||
return [
|
||||
// servico
|
||||
{
|
||||
accessorKey: 'servico',
|
||||
header: ({ column }) => SortableHeader('Serviço / Tabela', column),
|
||||
cell: ({ row }) => {
|
||||
const data = row.original;
|
||||
return (
|
||||
<div className="flex items-center gap-3">
|
||||
<div>
|
||||
<div className="font-semibold text-gray-900 capitalize">
|
||||
{GetCapitalize(data.servico)}
|
||||
</div>
|
||||
<div className="text-sm text-gray-500">
|
||||
{GetCapitalize(data.tabela)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
sortingFn: (a, b) =>
|
||||
(a.original.servico?.toLowerCase() || '').localeCompare(
|
||||
b.original.servico?.toLowerCase() || '',
|
||||
),
|
||||
},
|
||||
|
||||
// emolumento
|
||||
{
|
||||
accessorKey: 'emolumento',
|
||||
header: ({ column }) => SortableHeader('Emolumento', column),
|
||||
cell: ({ row }) => <div>R$ {row.getValue('emolumento') || '---'}</div>,
|
||||
},
|
||||
|
||||
// taxa_judiciaria
|
||||
{
|
||||
accessorKey: 'taxa_judiciaria',
|
||||
header: ({ column }) => SortableHeader('Tx. Judiciária', column),
|
||||
cell: ({ row }) => <div>R$ {row.getValue('taxa_judiciaria') || '---'}</div>,
|
||||
},
|
||||
|
||||
// fundesp
|
||||
{
|
||||
accessorKey: 'fundesp',
|
||||
header: ({ column }) => SortableHeader('Fundesp 21%', column),
|
||||
cell: ({ row }) => <div>R$ {row.getValue('fundesp') || '---'}</div>,
|
||||
},
|
||||
|
||||
// valor_iss
|
||||
{
|
||||
accessorKey: 'valor_iss',
|
||||
header: ({ column }) => SortableHeader('ISS 5%', column),
|
||||
cell: ({ row }) => <div>R$ {row.getValue('valor_iss') || '---'}</div>,
|
||||
},
|
||||
|
||||
// total
|
||||
{
|
||||
accessorKey: 'valor',
|
||||
header: ({ column }) => SortableHeader('Total', column),
|
||||
cell: ({ row }) => <div>R$ {row.getValue('valor') || '---'}</div>,
|
||||
},
|
||||
|
||||
// quantidade (componente solicitado)
|
||||
{
|
||||
accessorKey: 'quantidade',
|
||||
header: ({ column }) => SortableHeader('Qtd.', column),
|
||||
enableSorting: false,
|
||||
size: 160,
|
||||
cell: ({ row, table }) => {
|
||||
const value = Number(row.getValue('quantidade') ?? 1);
|
||||
const min = 0;
|
||||
const max = 999;
|
||||
|
||||
const updateData = (table.options.meta as TableMeta | undefined)?.updateData;
|
||||
|
||||
const setNext = (next: number) => {
|
||||
if (updateData) updateData(row.index, 'quantidade', next);
|
||||
};
|
||||
|
||||
const dec = () => setNext(Math.max(min, value - 1));
|
||||
const inc = () => setNext(Math.min(max, value + 1));
|
||||
|
||||
return (
|
||||
<div className="flex items-center">
|
||||
<Button
|
||||
type="button"
|
||||
size="icon"
|
||||
variant="outline"
|
||||
onClick={dec}
|
||||
disabled={value <= min}
|
||||
aria-label="Diminuir quantidade"
|
||||
className="bg-white border border-gray-300 dark:bg-gray-700 dark:border-gray-700 ring-primary dark:ring-white hover:border-primary dark:hover:border-white hover:ring-1 hover:text-primary dark:hover:text-white dark:hover:bg-transparent text-gray-600 dark:text-gray-100 h-8 rounded-lg w-8 inline-flex items-center justify-center text-base button-press-feedback"
|
||||
>
|
||||
<Minus className="h-4 w-4" />
|
||||
</Button>
|
||||
|
||||
<div className="w-10 text-center">
|
||||
<span>{value}</span>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
type="button"
|
||||
size="icon"
|
||||
variant="outline"
|
||||
onClick={inc}
|
||||
disabled={value >= max}
|
||||
aria-label="Aumentar quantidade"
|
||||
className="bg-white border border-gray-300 dark:bg-gray-700 dark:border-gray-700 ring-primary dark:ring-white hover:border-primary dark:hover:border-white hover:ring-1 hover:text-primary dark:hover:text-white dark:hover:bg-transparent text-gray-600 dark:text-gray-100 h-8 rounded-lg w-8 inline-flex items-center justify-center text-base button-press-feedback"
|
||||
>
|
||||
<Plus className="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
'use client';
|
||||
|
||||
import TServicoItemPedidoTableInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoTableInterface';
|
||||
import { DataTable } from '@/shared/components/dataTable/DataTable';
|
||||
|
||||
import TServicoItemPedidoFormColumns from './TServicoItemPedidoFormColumns';
|
||||
|
||||
|
||||
/**
|
||||
* Componente principal da tabela de Naturezas
|
||||
*/
|
||||
export default function TServicoItemPedidoFormTable({ data, onEdit, onDelete }: TServicoItemPedidoTableInterface) {
|
||||
const columns = TServicoItemPedidoFormColumns(onEdit, onDelete);
|
||||
return (
|
||||
<div>
|
||||
<DataTable
|
||||
data={data}
|
||||
columns={columns}
|
||||
filterColumn="servico"
|
||||
filterPlaceholder="Buscar por serviço..."
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
'use client';
|
||||
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import TServicoItemPedidoListInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoListInterface';
|
||||
|
||||
export default function TServicoItemPedidoList({ items }: TServicoItemPedidoListInterface) {
|
||||
const money = (v: unknown) =>
|
||||
new Intl.NumberFormat('pt-BR', { style: 'currency', currency: 'BRL' }).format(Number(v || 0));
|
||||
|
||||
return (
|
||||
<Card className="card-border">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-2xl font-semibold">Itens: {items?.length}</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{/* Altura máxima + scroll vertical */}
|
||||
<div className="space-y-4 max-h-[60vh] overflow-y-auto pr-1">
|
||||
{items.map((item) => (
|
||||
<div
|
||||
key={item.servico_itempedido_id}
|
||||
className="bg-cart-item border-cart-border flex items-start gap-4 rounded-lg border p-4"
|
||||
>
|
||||
{/* Descrição */}
|
||||
<div className="min-w-0 flex-1">
|
||||
<h3 className="text-foreground line-clamp-2 text-sm lg:text-base font-bold">
|
||||
{item.descricao}
|
||||
</h3>
|
||||
<h6 className="text-foreground line-clamp-2 text-sm lg:text-base">
|
||||
# {item.servico_itempedido_id}
|
||||
</h6>
|
||||
</div>
|
||||
{/* Valores (grid compacto) */}
|
||||
<div className="grid grid-cols-5 gap-3 min-w-[520px] text-right">
|
||||
<div>
|
||||
<div className="text-xs text-muted-foreground">Emolumento</div>
|
||||
<div className="font-semibold">{money(item.emolumento)}</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="text-xs text-muted-foreground">Tx. Judiciária</div>
|
||||
<div className="font-semibold">{money(item.taxa_judiciaria)}</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="text-xs text-muted-foreground">ISS</div>
|
||||
<div className="font-semibold">{money(item.valor_iss)}</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="text-xs text-muted-foreground">Fundesp</div>
|
||||
<div className="font-semibold">{money(item.fundesp)}</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className="text-xs text-muted-foreground">Total</div>
|
||||
<div className="font-semibold">{money(item.valor)}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
|
@ -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 {
|
||||
|
|
@ -103,7 +104,7 @@ export default function TServicoPedidoColumns(
|
|||
id: 'actions',
|
||||
header: 'Ações',
|
||||
cell: ({ row }) => {
|
||||
const natureza = row.original;
|
||||
const servicoPedido = row.original;
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
|
|
@ -113,15 +114,19 @@ export default function TServicoPedidoColumns(
|
|||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent side="left" align="start">
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuItem onSelect={() => onEdit(natureza, true)}>
|
||||
<DropdownMenuItem asChild>
|
||||
<Link href={`/servicos/balcao/detalhes/${row.getValue('servico_pedido_id')}`}>
|
||||
<EyeIcon className="mr-2 h-4 w-4" />
|
||||
Detalhes
|
||||
</Link>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem onSelect={() => onEdit(servicoPedido, true)}>
|
||||
<PencilIcon className="mr-2 h-4 w-4" />
|
||||
Editar
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem
|
||||
className="text-red-600"
|
||||
onSelect={() => onDelete(natureza, true)}
|
||||
>
|
||||
<DropdownMenuItem onSelect={() => onDelete(servicoPedido, true)}>
|
||||
<Trash2Icon className="mr-2 h-4 w-4" />
|
||||
Remover
|
||||
</DropdownMenuItem>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,157 @@
|
|||
'use client';
|
||||
|
||||
|
||||
import { CalendarIcon, ClockIcon, Pencil } from 'lucide-react';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { Separator } from '@/components/ui/separator';
|
||||
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 { useTServicoItemPedidoIndexHook } from '../../hooks/TServicoItemPedido/useTServicoItemPedidoIndexHook';
|
||||
import { useTServicoPedidoShowHook } from '../../hooks/TServicoPedido/useTServicoPedidoShowHook';
|
||||
import TServicoItemPedidoList from '../TServicoItemPedido/TServicoItemPedidoList';
|
||||
import TServicoPedidoDetailsPagamento from './TServicoPedidoDetailsPagamento';
|
||||
|
||||
|
||||
|
||||
export default function TServicoPedidoDetails({ servico_pedido_id }: TServicoPedidoInterface) {
|
||||
|
||||
const { TServicoItemPedido, indexTServicoItemPedido } = useTServicoItemPedidoIndexHook()
|
||||
const { TServicoPedido, showTServicoPedido } = useTServicoPedidoShowHook()
|
||||
|
||||
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)
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
TServicoPedidoShowData()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="relative h-full flex flex-col px-2 sm:px-4 py-2 sm:py-4 md:px-6 container mx-auto">
|
||||
<div className="container mx-auto flex items-center justify-between mb-4">
|
||||
<h3 className="text-2xl font-semibold">
|
||||
Pedido: #{TServicoPedido?.servico_pedido_id}
|
||||
</h3>
|
||||
<div className="flex items-center gap-2 print:hidden">
|
||||
<Button>
|
||||
<Pencil className="mr-2 h-4 w-4" />
|
||||
Edit
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
{/* Main */}
|
||||
<div className="container mx-auto h-full">
|
||||
<div className="flex flex-col lg:flex-row gap-4">
|
||||
{/* Left column */}
|
||||
<div className="flex flex-col flex-auto gap-4">
|
||||
<TServicoItemPedidoList
|
||||
items={TServicoItemPedido}
|
||||
/>
|
||||
<TServicoPedidoDetailsPagamento
|
||||
situacao={TServicoPedido?.situacao}
|
||||
items={TServicoItemPedido}
|
||||
/>
|
||||
</div>
|
||||
{/* Right column (sidebar) */}
|
||||
<div className="lg:w-[320px] xl:w-[420px] flex flex-col gap-4">
|
||||
<Card role="presentation" className="card-border">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-2xl font-semibold">
|
||||
Apresentante
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{/* Header com avatar e link */}
|
||||
<div className="flex items-center gap-2">
|
||||
{/* Foto ou Iniciais */}
|
||||
<div className="flex h-10 w-10 items-center justify-center overflow-hidden rounded-full bg-gray-200">
|
||||
<span className="text-sm font-medium text-gray-700">
|
||||
{GetNameInitials(TServicoPedido?.apresentante)}
|
||||
</span>
|
||||
</div>
|
||||
<div className="min-w-0">
|
||||
<div className="font-bold truncate">
|
||||
{GetCapitalize(TServicoPedido?.apresentante)}
|
||||
</div>
|
||||
<div className="font-light truncate">
|
||||
{FormatCPF(String(TServicoPedido?.cpfcnpj_apresentante))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Separator className="my-5" />
|
||||
<div className="mb-4 flex items-center gap-2">
|
||||
<CalendarIcon className="opacity-70" />
|
||||
<span className="truncate">
|
||||
{FormatDateTime(TServicoPedido?.data_pedido)}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<ClockIcon className="opacity-70" />
|
||||
<span className="truncate">
|
||||
14:50:31
|
||||
</span>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card role="presentation" className="card-border">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-2xl font-semibold">
|
||||
Operador
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="flex items-center gap-2">
|
||||
{/* Foto ou Iniciais */}
|
||||
<div className="flex h-10 w-10 items-center justify-center overflow-hidden rounded-full bg-gray-200">
|
||||
<span className="text-sm font-medium text-gray-700">
|
||||
{GetNameInitials(TServicoPedido?.login)}
|
||||
</span>
|
||||
</div>
|
||||
<div className="min-w-0">
|
||||
<div className="font-bold truncate">
|
||||
{GetCapitalize(TServicoPedido?.login)}
|
||||
</div>
|
||||
<div className="font-light truncate">
|
||||
{GetCapitalize(TServicoPedido?.funcao)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<Card className="card-border">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-2xl font-semibold">
|
||||
Impressões
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="flex flex-col gap-2">
|
||||
<Button className="w-full" variant="outline">Recibo</Button>
|
||||
<Button className="w-full">Etiqueta</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
'use client';
|
||||
|
||||
import * as React from 'react';
|
||||
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { Separator } from '@/components/ui/separator';
|
||||
import { ServicosPedidosSituacoesBadge } from '@/shared/components/servicosPedidosSituacoes/ServicosPedidosSituacoesBadge';
|
||||
|
||||
import TServicoPedidoDetailsPagamentoInterface from '../../interfaces/TServicoPedido/TServicoPedidoDetailsPagamentoInterface';
|
||||
|
||||
export default function TServicoPedidoDetailsPagamento({
|
||||
situacao,
|
||||
items,
|
||||
}: TServicoPedidoDetailsPagamentoInterface) {
|
||||
|
||||
// Formatação monetária (BRL)
|
||||
const fmt = React.useMemo(
|
||||
() => new Intl.NumberFormat('pt-BR', { style: 'currency', currency: 'BRL' }),
|
||||
[]
|
||||
);
|
||||
|
||||
// Helper para evitar NaN/undefined
|
||||
const safe = (n: number | undefined | null) =>
|
||||
typeof n === 'number' && Number.isFinite(n) ? n : 0;
|
||||
|
||||
// Somas por tipo de valor
|
||||
const { emolumento, taxa_judiciaria, valor_iss, fundesp } = React.useMemo(() => {
|
||||
return (items ?? []).reduce(
|
||||
(acc, item) => {
|
||||
acc.emolumento += safe(item.emolumento);
|
||||
acc.taxa_judiciaria += safe(item.taxa_judiciaria);
|
||||
acc.valor_iss += safe(item.valor_iss);
|
||||
acc.fundesp += safe(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 (
|
||||
<Card className="card-border">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-2xl font-semibold">
|
||||
Pagamento <ServicosPedidosSituacoesBadge situacao={situacao} />
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
|
||||
<CardContent>
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-muted-foreground">Emolumento</span>
|
||||
<span className="font-medium">{fmt.format(emolumento)}</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-muted-foreground">Tx. Judiciária</span>
|
||||
<span className="font-medium">{fmt.format(taxa_judiciaria)}</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-muted-foreground">ISS</span>
|
||||
<span className="font-medium">{fmt.format(valor_iss)}</span>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-muted-foreground">Fundesp</span>
|
||||
<span className="font-medium">{fmt.format(fundesp)}</span>
|
||||
</div>
|
||||
|
||||
<Separator className="border-cart-border" />
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-muted-foreground font-semibold">Total</span>
|
||||
<span className="font-semibold">{fmt.format(total)}</span>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
|
@ -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 { 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) {
|
||||
const form = useTServicoPedidoFormHook({});
|
||||
|
||||
// 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 (
|
||||
<Dialog
|
||||
open={isOpen}
|
||||
onOpenChange={(open) => {
|
||||
if (!open) onClose(null, false);
|
||||
}}
|
||||
>
|
||||
<DialogContent className="w-full max-w-full p-6 sm:max-w-3xl md:max-w-2xl lg:max-w-2xl">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="text-lg sm:text-xl">Formulário de Gramática</DialogTitle>
|
||||
<DialogDescription className="text-muted-foreground text-sm">
|
||||
Formulário de Gramática
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
{/* Formulário principal */}
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSave, onError)} className="space-y-6">
|
||||
{/* GRID MOBILE FIRST */}
|
||||
<div className="grid w-full grid-cols-12 gap-4">
|
||||
{/* Palavra */}
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-12">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="apresentante"
|
||||
render={({ field }) => (
|
||||
<FormItem className="col-span-1 sm:col-span-2">
|
||||
<FormLabel>Palavra</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
type="text"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{/* Rodapé */}
|
||||
<DialogFooter className="mt-6 flex flex-col justify-end gap-2 sm:flex-row">
|
||||
<DialogClose asChild>
|
||||
<Button variant="outline" type="button">
|
||||
Cancelar
|
||||
</Button>
|
||||
</DialogClose>
|
||||
<LoadingButton
|
||||
text="Salvar"
|
||||
textLoading="Salvando..."
|
||||
type="submit"
|
||||
loading={buttonIsLoading}
|
||||
/>
|
||||
</DialogFooter>
|
||||
</form>
|
||||
</Form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
import { CreditCard, Package, UserSquare2 } from 'lucide-react';
|
||||
import * as React from 'react';
|
||||
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import {
|
||||
Form,
|
||||
|
|
@ -15,8 +16,12 @@ import {
|
|||
import { Input } from '@/components/ui/input';
|
||||
import { cn } from '@/lib/utils';
|
||||
import GUsuarioSelect from '@/packages/administrativo/components/GUsuario/GUsuarioSelect';
|
||||
import TServicoTipoSelect from '@/packages/administrativo/components/TServicoTipo/TServicoTipoSelect';
|
||||
import { useTServicoPedidoFormHook } from '@/packages/servicos/hooks/TServicoPedido/useTServicoPedidoFormHook';
|
||||
import { ResetFormIfData } from '@/shared/actions/form/ResetFormIfData';
|
||||
import TipoPagamentoSelect from '@/shared/components/tipoPagamento/TipoPagamentoSelect';
|
||||
|
||||
import TServicoItemPedidoFormTable from '../TServicoItemPedido/TServicoItemPedidoFormTable';
|
||||
|
||||
type StepKey = 'pedido' | 'servicoPedidoItem' | 'payment';
|
||||
|
||||
|
|
@ -96,186 +101,420 @@ export default function TServicoPedidoForm() {
|
|||
ResetFormIfData(form, data);
|
||||
}, [data, form]);
|
||||
|
||||
const dataItens = [
|
||||
{
|
||||
'emolumento': 4.99,
|
||||
'fundesp': 1.21,
|
||||
'taxa_judiciaria': 0,
|
||||
'valor_iss': 0.25,
|
||||
'valor': 6.45,
|
||||
'servico': 'Autenticação Original',
|
||||
'tabela': 'Autenticação por página'
|
||||
},
|
||||
{
|
||||
'emolumento': 3.50,
|
||||
'fundesp': 0.85,
|
||||
'taxa_judiciaria': 0,
|
||||
'valor_iss': 0.18,
|
||||
'valor': 4.53,
|
||||
'servico': 'Autenticação de Cópia',
|
||||
'tabela': 'Autenticação por página'
|
||||
},
|
||||
{
|
||||
'emolumento': 5.90,
|
||||
'fundesp': 1.20,
|
||||
'taxa_judiciaria': 0,
|
||||
'valor_iss': 0.30,
|
||||
'valor': 7.40,
|
||||
'servico': 'Reconhecimento de Firma (Semelhança)',
|
||||
'tabela': 'Reconhecimento de firma'
|
||||
},
|
||||
{
|
||||
'emolumento': 8.50,
|
||||
'fundesp': 1.75,
|
||||
'taxa_judiciaria': 0,
|
||||
'valor_iss': 0.43,
|
||||
'valor': 10.68,
|
||||
'servico': 'Reconhecimento de Firma (Autenticidade)',
|
||||
'tabela': 'Reconhecimento de firma'
|
||||
},
|
||||
{
|
||||
'emolumento': 12.00,
|
||||
'fundesp': 2.50,
|
||||
'taxa_judiciaria': 0,
|
||||
'valor_iss': 0.60,
|
||||
'valor': 15.10,
|
||||
'servico': 'Abertura de Firma',
|
||||
'tabela': 'Ficha de assinatura'
|
||||
},
|
||||
{
|
||||
'emolumento': 18.00,
|
||||
'fundesp': 3.60,
|
||||
'taxa_judiciaria': 0,
|
||||
'valor_iss': 0.90,
|
||||
'valor': 22.50,
|
||||
'servico': 'Procuração Particular',
|
||||
'tabela': 'Procuração por folha'
|
||||
},
|
||||
{
|
||||
'emolumento': 35.00,
|
||||
'fundesp': 7.00,
|
||||
'taxa_judiciaria': 0,
|
||||
'valor_iss': 1.75,
|
||||
'valor': 43.75,
|
||||
'servico': 'Procuração Pública',
|
||||
'tabela': 'Procuração (tabela geral)'
|
||||
},
|
||||
{
|
||||
'emolumento': 20.00,
|
||||
'fundesp': 4.00,
|
||||
'taxa_judiciaria': 0,
|
||||
'valor_iss': 1.00,
|
||||
'valor': 25.00,
|
||||
'servico': 'Certidão Simples',
|
||||
'tabela': 'Certidões'
|
||||
},
|
||||
{
|
||||
'emolumento': 45.00,
|
||||
'fundesp': 9.00,
|
||||
'taxa_judiciaria': 0,
|
||||
'valor_iss': 2.25,
|
||||
'valor': 56.25,
|
||||
'servico': 'Certidão em Inteiro Teor',
|
||||
'tabela': 'Certidões'
|
||||
},
|
||||
{
|
||||
'emolumento': 80.00,
|
||||
'fundesp': 16.00,
|
||||
'taxa_judiciaria': 0,
|
||||
'valor_iss': 4.00,
|
||||
'valor': 100.00,
|
||||
'servico': 'Ata Notarial',
|
||||
'tabela': 'Ata por página'
|
||||
},
|
||||
{
|
||||
'emolumento': 7.50,
|
||||
'fundesp': 1.50,
|
||||
'taxa_judiciaria': 0,
|
||||
'valor_iss': 0.38,
|
||||
'valor': 9.38,
|
||||
'servico': 'Testemunha em Documento',
|
||||
'tabela': 'Outras declarações'
|
||||
},
|
||||
{
|
||||
'emolumento': 6.20,
|
||||
'fundesp': 1.24,
|
||||
'taxa_judiciaria': 0,
|
||||
'valor_iss': 0.31,
|
||||
'valor': 7.75,
|
||||
'servico': 'Autenticação de Documento Eletrônico',
|
||||
'tabela': 'Autenticação digital'
|
||||
},
|
||||
{
|
||||
'emolumento': 25.00,
|
||||
'fundesp': 5.00,
|
||||
'taxa_judiciaria': 0,
|
||||
'valor_iss': 1.25,
|
||||
'valor': 31.25,
|
||||
'servico': 'Reconhecimento de Sinal Público',
|
||||
'tabela': 'Sinal público'
|
||||
},
|
||||
{
|
||||
'emolumento': 10.00,
|
||||
'fundesp': 2.00,
|
||||
'taxa_judiciaria': 0,
|
||||
'valor_iss': 0.50,
|
||||
'valor': 12.50,
|
||||
'servico': 'Certificação de Cópia Digital',
|
||||
'tabela': 'Certificação digital'
|
||||
},
|
||||
{
|
||||
'emolumento': 9.90,
|
||||
'fundesp': 1.98,
|
||||
'taxa_judiciaria': 0,
|
||||
'valor_iss': 0.50,
|
||||
'valor': 12.38,
|
||||
'servico': 'Arquivamento de Documento',
|
||||
'tabela': 'Arquivamento'
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
return (
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSubmit, onError)}>
|
||||
<div className="flex gap-4">
|
||||
{/* Sidebar - Sticky */}
|
||||
<aside className="hidden w-[360px] lg:block">
|
||||
<div className="sticky top-4 z-10 max-h-[calc(100vh-2rem)] overflow-auto">
|
||||
<Card role="presentation" className="card-border">
|
||||
<CardContent>
|
||||
<nav className="flex flex-col gap-2">
|
||||
<StepLink
|
||||
active={active === 'pedido'}
|
||||
onClick={() => {
|
||||
setActive('pedido');
|
||||
scrollToSection('selectPedido');
|
||||
}}
|
||||
icon={<Package className="h-4 w-4" />}
|
||||
title="Pedido"
|
||||
description="Dados gerais do pedido."
|
||||
/>
|
||||
<StepLink
|
||||
active={active === 'servicoPedidoItem'}
|
||||
onClick={() => {
|
||||
setActive('servicoPedidoItem');
|
||||
scrollToSection('selectServicoPedidoItem');
|
||||
}}
|
||||
icon={<UserSquare2 className="h-4 w-4" />}
|
||||
title="Itens"
|
||||
description="Itens/serviços do pedido."
|
||||
/>
|
||||
<StepLink
|
||||
active={active === 'payment'}
|
||||
onClick={() => {
|
||||
setActive('payment');
|
||||
scrollToSection('selectPayment');
|
||||
}}
|
||||
icon={<CreditCard className="h-4 w-4" />}
|
||||
title="Pagamento"
|
||||
description="Forma e dados de pagamento."
|
||||
/>
|
||||
</nav>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</aside>
|
||||
{/* Conteúdo */}
|
||||
<main className="flex-1">
|
||||
<div className="flex flex-col gap-4">
|
||||
{/* Seção: Pedido */}
|
||||
<Card role="presentation" id="selectPedido" className="scroll-mt-6">
|
||||
<CardHeader>
|
||||
<CardTitle className="mb-2">Pedido</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<div className="grid w-full grid-cols-12 gap-4">
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-12">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="apresentante"
|
||||
render={({ field }) => (
|
||||
<FormItem className="col-span-1 sm:col-span-2">
|
||||
<FormLabel>Escrevente/Tabelião</FormLabel>
|
||||
<GUsuarioSelect field={field} />
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
<div>
|
||||
<h3 className='text-4xl font-bold mb-4'>
|
||||
Pedido
|
||||
</h3>
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSubmit, onError)}>
|
||||
<div className="flex gap-4">
|
||||
{/* Sidebar - Sticky */}
|
||||
<aside className="hidden w-[360px] lg:block">
|
||||
<div className="sticky top-4 z-10 max-h-[calc(100vh-2rem)] overflow-auto">
|
||||
<Card role="presentation" className="card-border">
|
||||
<CardContent>
|
||||
<nav className="flex flex-col gap-2">
|
||||
<StepLink
|
||||
active={active === 'pedido'}
|
||||
onClick={() => {
|
||||
setActive('pedido');
|
||||
scrollToSection('selectPedido');
|
||||
}}
|
||||
icon={<Package className="h-4 w-4" />}
|
||||
title="Pedido"
|
||||
description="Dados gerais do pedido."
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-8">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="apresentante"
|
||||
render={({ field }) => (
|
||||
<FormItem className="col-span-1 sm:col-span-2">
|
||||
<FormLabel>Apresentante</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
type="text"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
<StepLink
|
||||
active={active === 'servicoPedidoItem'}
|
||||
onClick={() => {
|
||||
setActive('servicoPedidoItem');
|
||||
scrollToSection('selectServicoPedidoItem');
|
||||
}}
|
||||
icon={<UserSquare2 className="h-4 w-4" />}
|
||||
title="Itens"
|
||||
description="Itens/serviços do pedido."
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-4">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="cpfcnpj_apresentante"
|
||||
render={({ field }) => (
|
||||
<FormItem className="col-span-1 sm:col-span-2">
|
||||
<FormLabel>CPF</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
type="text"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
<StepLink
|
||||
active={active === 'payment'}
|
||||
onClick={() => {
|
||||
setActive('payment');
|
||||
scrollToSection('selectPayment');
|
||||
}}
|
||||
icon={<CreditCard className="h-4 w-4" />}
|
||||
title="Pagamento"
|
||||
description="Forma e dados de pagamento."
|
||||
/>
|
||||
</nav>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</aside>
|
||||
{/* Conteúdo */}
|
||||
<main className="flex-1">
|
||||
<div className="flex flex-col gap-4">
|
||||
{/* Seção: Pedido */}
|
||||
<Card role="presentation" id="selectPedido" className="scroll-mt-6">
|
||||
<CardHeader>
|
||||
<CardTitle className="mb-2">
|
||||
<h4 className='text-3xl'>
|
||||
Pedido
|
||||
</h4>
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<div className="grid w-full grid-cols-12 gap-4">
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-12">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="apresentante"
|
||||
render={({ field }) => (
|
||||
<FormItem className="col-span-1 sm:col-span-2">
|
||||
<FormLabel className='font-semibold'>Escrevente/Tabelião</FormLabel>
|
||||
<GUsuarioSelect field={field} />
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-8">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="apresentante"
|
||||
render={({ field }) => (
|
||||
<FormItem className="col-span-1 sm:col-span-2">
|
||||
<FormLabel>Apresentante</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
type="text"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-4">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="cpfcnpj_apresentante"
|
||||
render={({ field }) => (
|
||||
<FormItem className="col-span-1 sm:col-span-2">
|
||||
<FormLabel>CPF</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
type="text"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-8">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="selo_pessoa_nome"
|
||||
render={({ field }) => (
|
||||
<FormItem className="col-span-1 sm:col-span-2">
|
||||
<FormLabel>Pessoa presente no selo</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
type="text"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-4">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="selo_pessoa_cpfcnpj"
|
||||
render={({ field }) => (
|
||||
<FormItem className="col-span-1 sm:col-span-2">
|
||||
<FormLabel>CPF</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
type="text"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-8">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="selo_pessoa_nome"
|
||||
render={({ field }) => (
|
||||
<FormItem className="col-span-1 sm:col-span-2">
|
||||
<FormLabel>Pessoa presente no selo</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
type="text"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
{/* Seção: Itens */}
|
||||
<Card role="presentation" id="selectServicoPedidoItem" className="scroll-mt-6">
|
||||
<CardHeader>
|
||||
<CardTitle>
|
||||
<h4 className='text-3xl'>
|
||||
Itens
|
||||
</h4>
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<div className="grid w-full grid-cols-12 gap-4">
|
||||
<div className="col-span-12 sm:col-span-12 md:col-span-12">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="apresentante"
|
||||
render={({ field }) => (
|
||||
<FormItem className="col-span-1 sm:col-span-2">
|
||||
<FormLabel>Serviços</FormLabel>
|
||||
<TServicoTipoSelect field={field} />
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-12 sm:col-span-12 md:col-span-12">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="apresentante"
|
||||
render={({ field }) => (
|
||||
<FormItem className="col-span-1 sm:col-span-2">
|
||||
<FormLabel>Emolumentos</FormLabel>
|
||||
<TServicoTipoSelect field={field} />
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-12 sm:col-span-12 md:col-span-12">
|
||||
<TServicoItemPedidoFormTable
|
||||
data={dataItens}
|
||||
onEdit={() => { }}
|
||||
onDelete={() => { }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-4">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="selo_pessoa_cpfcnpj"
|
||||
render={({ field }) => (
|
||||
<FormItem className="col-span-1 sm:col-span-2">
|
||||
<FormLabel>CPF</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
type="text"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
{/* Seção: Pagamento */}
|
||||
<Card role="presentation" id="selectPayment" className="scroll-mt-6">
|
||||
<CardHeader>
|
||||
<CardTitle className="mb-2">
|
||||
<h4 className='text-3xl'>
|
||||
Pagamento
|
||||
</h4>
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<div className="grid w-full grid-cols-12 gap-4">
|
||||
<div className="col-span-12 sm:col-span-12 md:col-span-8">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="apresentante"
|
||||
render={({ field }) => (
|
||||
<FormItem className="col-span-1 sm:col-span-2">
|
||||
<FormLabel>Requerente</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
type="text"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-12 sm:col-span-12 md:col-span-4">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="apresentante"
|
||||
render={({ field }) => (
|
||||
<FormItem className="col-span-1 sm:col-span-2">
|
||||
<FormLabel>CPF/CNPJ Requerente</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
{...field}
|
||||
type="text"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-12 sm:col-span-12 md:col-span-12">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="apresentante"
|
||||
render={({ field }) => (
|
||||
<FormItem className="col-span-1 sm:col-span-2">
|
||||
<FormLabel>Forma Pagamento</FormLabel>
|
||||
<TipoPagamentoSelect field={field} />
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-span-12 sm:col-span-12 md:col-span-12 flex justify-end items-center gap-4">
|
||||
<Button type="button" variant="outline">
|
||||
Cancelar
|
||||
</Button>
|
||||
<Button type="submit">
|
||||
Confirmar
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Seção: Itens */}
|
||||
<Card role="presentation" id="selectServicoPedidoItem" className="scroll-mt-6">
|
||||
<CardHeader>
|
||||
<CardTitle className="mb-2">Itens</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<div className="grid w-full grid-cols-12 gap-4">
|
||||
<div className="col-span-12 sm:col-span-6 md:col-span-12">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="apresentante"
|
||||
render={({ field }) => (
|
||||
<FormItem className="col-span-1 sm:col-span-2">
|
||||
<FormLabel>Escrevente/Tabelião</FormLabel>
|
||||
<GUsuarioSelect field={field} />
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Seção: Pagamento */}
|
||||
<Card role="presentation" id="selectPayment" className="scroll-mt-6">
|
||||
<CardHeader>
|
||||
<CardTitle className="mb-2">Pagamento</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">...</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<ApiResponseInterface> {
|
||||
const api = new API();
|
||||
|
||||
async function executeTServicoItemPedidoIndexData(data: TServicoItemPedidoInterface): Promise<ApiResponseInterface> {
|
||||
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);
|
||||
|
|
@ -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<ApiResponseInterface> {
|
||||
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);
|
||||
|
|
@ -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<ApiResponseInterface> {
|
||||
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);
|
||||
|
|
@ -2,23 +2,29 @@
|
|||
|
||||
import { useState } from 'react';
|
||||
|
||||
import TServicoItemPedidoIndexResponseInterface from '@/packages/servicos/interfaces/TServicoItemPedido/TServicoItemPedidoIndexResponseInterface';
|
||||
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<TServicoItemPedidoInterface[]>([]);
|
||||
const [TServicoItemPedido, setTServicoItemPedido] = useState<TServicoItemPedidoIndexResponseInterface[]>([]);
|
||||
|
||||
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 {
|
||||
|
|
|
|||
|
|
@ -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<TServicoItemPedidoInterface>();
|
||||
|
||||
const showTServicoItemPedido = async (data: TServicoItemPedidoInterface) => {
|
||||
|
||||
const response = await TServicoItemPedidoShowService(data);
|
||||
|
||||
setTServicoItemPedido(response.data);
|
||||
|
||||
setResponse(response);
|
||||
|
||||
return response.data
|
||||
|
||||
};
|
||||
|
||||
return { TServicoItemPedido, showTServicoItemPedido };
|
||||
};
|
||||
|
|
@ -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<TServicoPedidoInterface>(null);
|
||||
|
||||
const showTServicoPedido = async (data: TServicoPedidoInterface) => {
|
||||
|
||||
const response = await TServicoPedidoShowService(data);
|
||||
|
||||
setTServicoPedido(response.data);
|
||||
|
||||
setResponse(response);
|
||||
|
||||
return response.data
|
||||
|
||||
};
|
||||
|
||||
return { TServicoPedido, showTServicoPedido };
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
export default interface TServicoItemPedidoIndexResponseInterface {
|
||||
servico_itempedido_id: number,
|
||||
emolumento: number,
|
||||
taxa_judiciaria: number,
|
||||
valor_iss: number,
|
||||
fundesp: number,
|
||||
valor: number,
|
||||
descricao: string,
|
||||
emolumento_descricao: string,
|
||||
situacao: string
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
import TServicoItemPedidoIndexResponseInterface from "./TServicoItemPedidoIndexResponseInterface";
|
||||
|
||||
export default interface TServicoItemPedidoListInterface {
|
||||
items: TServicoItemPedidoIndexResponseInterface[];
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
export default interface TServicoPedidoDetailsInterface {
|
||||
servico_pedido_id: number
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
import TServicoItemPedidoIndexResponseInterface from "../TServicoItemPedido/TServicoItemPedidoIndexResponseInterface";
|
||||
|
||||
export default interface TServicoPedidoDetailsPagamentoInterface {
|
||||
|
||||
situacao: string,
|
||||
items: TServicoItemPedidoIndexResponseInterface[]
|
||||
|
||||
}
|
||||
|
|
@ -14,4 +14,6 @@ export default interface TServicoPedidoInterface {
|
|||
cpfcnpj_apresentante?: string;
|
||||
selo_pessoa_nome?: string;
|
||||
selo_pessoa_cpfcnpj?: string;
|
||||
login?: string;
|
||||
funcao?: string;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
@ -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);
|
||||
85
src/shared/components/tipoPagamento/TipoPagamentoSelect.tsx
Normal file
85
src/shared/components/tipoPagamento/TipoPagamentoSelect.tsx
Normal file
|
|
@ -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 (
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<FormControl className="w-full">
|
||||
<Button
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
aria-expanded={open}
|
||||
className="justify-between"
|
||||
>
|
||||
{selectedLabel}
|
||||
<ChevronsUpDownIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</FormControl>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-full p-0">
|
||||
<Command>
|
||||
<CommandInput placeholder="Buscar tipo de parte..." />
|
||||
<CommandList>
|
||||
<CommandEmpty>Nenhum resultado encontrado.</CommandEmpty>
|
||||
<CommandGroup>
|
||||
{options.map((item) => (
|
||||
<CommandItem
|
||||
key={item.value}
|
||||
value={item.label.toLowerCase()}
|
||||
onSelect={() => {
|
||||
field.onChange(item.value); // envia número
|
||||
setOpen(false);
|
||||
}}
|
||||
>
|
||||
<CheckIcon
|
||||
className={cn(
|
||||
'mr-2 h-4 w-4',
|
||||
Number(field.value) === item.value ? 'opacity-100' : 'opacity-0',
|
||||
)}
|
||||
/>
|
||||
{item.label}
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
6
src/shared/enums/TipoPagamentoEnum.ts
Normal file
6
src/shared/enums/TipoPagamentoEnum.ts
Normal file
|
|
@ -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;
|
||||
18
src/shared/hooks/useRunOnceByKey.ts
Normal file
18
src/shared/hooks/useRunOnceByKey.ts
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
import { useCallback, useRef } from "react";
|
||||
|
||||
export default function useRunOnceByKey() {
|
||||
const done = useRef(new Set<string>());
|
||||
|
||||
const run = useCallback(async (key: string, tasks: Array<() => Promise<unknown>>, 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 };
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue