feat: sistema GastroBar PDV completo

- Backend: Fastify + Prisma/SQLite com autenticacao JWT
- CRUD completo: usuarios, categorias, produtos, comandas
- Sistema de comandas com itens, status, pagamento
- Controle de estoque (entrada/saida automatica)
- Relatorios e dashboard com KPIs
- Notificacoes sonoras na cozinha
- Frontend: SPA vanilla TS com tema dark glassmorphism
- Mobile-first com bottom-sheet e cards compactos
- Busca de comandas por periodo
- Modal de detalhes com secao editavel colapsavel
This commit is contained in:
2026-07-21 12:47:15 -03:00
commit 402ac776ac
55 changed files with 7403 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
import { z } from 'zod';
export const loginSchema = z.object({
email: z.string().email(),
senha: z.string().min(6),
});
export type LoginInput = z.infer<typeof loginSchema>;
export const changePasswordSchema = z.object({
senhaAtual: z.string().min(6),
novaSenha: z.string().min(6),
});
export type ChangePasswordInput = z.infer<typeof changePasswordSchema>;

View File

@@ -0,0 +1,7 @@
import { z } from 'zod';
export const categorySchema = z.object({
nome: z.string().min(2),
});
export type CategoryInput = z.infer<typeof categorySchema>;

View File

@@ -0,0 +1,37 @@
import { z } from 'zod';
export const createOrderSchema = z.object({
identificador: z.string().min(1),
nomeCliente: z.string().optional(),
});
export const addItemOrderSchema = z.object({
produtoId: z.string().uuid(),
quantidade: z.number().int().positive(),
observacao: z.string().optional(),
});
export const updateItemStatusSchema = z.object({
status: z.enum(['PENDENTE', 'PREPARANDO', 'PRONTO', 'ENTREGUE']),
});
export const updateOrderSchema = z.object({
identificador: z.string().min(1).optional(),
nomeCliente: z.string().optional(),
status: z.enum(['ABERTA', 'FECHADA', 'PAGA', 'CANCELADA']).optional(),
desconto: z.number().min(0).optional(),
acrescimo: z.number().min(0).optional(),
taxaServico: z.boolean().optional(),
motivoCancelamento: z.string().optional(),
});
export const payOrderSchema = z.object({
formaPagamento: z.enum(['DINHEIRO', 'CARTAO_CREDITO', 'CARTAO_DEBITO', 'PIX']),
});
export type CreateOrderInput = z.infer<typeof createOrderSchema>;
export type AddItemOrderInput = z.infer<typeof addItemOrderSchema>;
export type UpdateItemStatusInput = z.infer<typeof updateItemStatusSchema>;
export type UpdateOrderInput = z.infer<typeof updateOrderSchema>;
export type PayOrderInput = z.infer<typeof payOrderSchema>;

View File

@@ -0,0 +1,16 @@
import { z } from 'zod';
export const productSchema = z.object({
nome: z.string().min(2),
descricao: z.string().optional(),
fotoUrl: z.string().url().optional(),
preco: z.number().positive(),
custo: z.number().positive().optional(),
estoqueAtual: z.number().int().nonnegative().default(0),
estoqueMinimo: z.number().int().nonnegative().default(0),
itemCozinha: z.boolean(),
ativo: z.boolean().default(true),
categoriaId: z.string().uuid(),
});
export type ProductInput = z.infer<typeof productSchema>;

View File

@@ -0,0 +1,25 @@
import { z } from 'zod';
export const userSchema = z.object({
nome: z.string().min(2),
email: z.string().email(),
senha: z.string().min(6),
role: z.enum(['ADMIN', 'CAIXA', 'GARCOM', 'COZINHA', 'BARMAN']),
ativo: z.boolean().default(true),
});
export const updateUserSchema = z.object({
nome: z.string().min(2).optional(),
email: z.string().email().optional(),
role: z.enum(['ADMIN', 'CAIXA', 'GARCOM', 'COZINHA', 'BARMAN']).optional(),
ativo: z.boolean().optional(),
});
export type UserInput = z.infer<typeof userSchema>;
export type UpdateUserInput = z.infer<typeof updateUserSchema>;
export const resetPasswordSchema = z.object({
novaSenha: z.string().min(6),
});
export type ResetPasswordInput = z.infer<typeof resetPasswordSchema>;