diff --git a/backend-old/internal/domain/models.go b/backend-old/internal/domain/models.go index 293d018..58df818 100644 --- a/backend-old/internal/domain/models.go +++ b/backend-old/internal/domain/models.go @@ -54,6 +54,9 @@ type User struct { Email string `db:"email" json:"email"` EmailVerified bool `db:"email_verified" json:"email_verified"` PasswordHash string `db:"password_hash" json:"-"` + Superadmin bool `db:"superadmin" json:"superadmin"` + NomeSocial string `db:"nome_social" json:"nome_social"` + CPF string `db:"cpf" json:"cpf"` CreatedAt time.Time `db:"created_at" json:"created_at"` UpdatedAt time.Time `db:"updated_at" json:"updated_at"` } diff --git a/backend-old/internal/http/handler/dto.go b/backend-old/internal/http/handler/dto.go index 9f8f24e..b7464d1 100644 --- a/backend-old/internal/http/handler/dto.go +++ b/backend-old/internal/http/handler/dto.go @@ -16,12 +16,15 @@ import ( // --- Request DTOs --- type createUserRequest struct { - CompanyID uuid.UUID `json:"company_id"` - Role string `json:"role"` - Name string `json:"name"` - Username string `json:"username"` - Email string `json:"email"` - Password string `json:"password"` + CompanyID uuid.UUID `json:"company_id"` + Role string `json:"role"` + Name string `json:"name"` + Username string `json:"username"` + Email string `json:"email"` + Password string `json:"password"` + Superadmin bool `json:"superadmin"` + NomeSocial string `json:"nome-social"` + CPF string `json:"cpf"` } type registerAuthRequest struct { diff --git a/backend-old/internal/http/handler/handler_test.go b/backend-old/internal/http/handler/handler_test.go index 402b6bc..713d337 100644 --- a/backend-old/internal/http/handler/handler_test.go +++ b/backend-old/internal/http/handler/handler_test.go @@ -170,6 +170,10 @@ func (m *MockRepository) CreateInventoryItem(ctx context.Context, item *domain.I return nil } +func (m *MockRepository) UpdateInventoryItem(ctx context.Context, item *domain.InventoryItem) error { + return nil +} + func (m *MockRepository) ListInventory(ctx context.Context, filter domain.InventoryFilter) ([]domain.InventoryItem, int64, error) { return []domain.InventoryItem{}, 0, nil } diff --git a/backend-old/internal/http/handler/product_handler.go b/backend-old/internal/http/handler/product_handler.go index 9542e00..9b0993b 100644 --- a/backend-old/internal/http/handler/product_handler.go +++ b/backend-old/internal/http/handler/product_handler.go @@ -431,14 +431,59 @@ func (h *Handler) GetProductByEAN(w http.ResponseWriter, r *http.Request) { } type registerInventoryRequest struct { - ProductID string `json:"product_id"` - SellerID string `json:"seller_id"` - SalePriceCents int64 `json:"sale_price_cents"` - OriginalPriceCents int64 `json:"original_price_cents"` // Added to fix backend error - FinalPriceCents int64 `json:"final_price_cents"` // Optional explicit field - StockQuantity int64 `json:"stock_quantity"` - ExpiresAt string `json:"expires_at"` // ISO8601 - Observations string `json:"observations"` + ProductID string `json:"product_id"` + SellerID string `json:"seller_id"` + SalePriceCents int64 `json:"sale_price_cents"` + StockQuantity int64 `json:"stock_quantity"` + ExpiresAt string `json:"expires_at"` // ISO8601 + Observations string `json:"observations"` +} + +type updateInventoryRequest struct { + StockQuantity int64 `json:"qtdade_estoque"` + SalePrice float64 `json:"preco_venda"` +} + +// UpdateInventoryItem updates price and stock for an existing inventory item. +func (h *Handler) UpdateInventoryItem(w http.ResponseWriter, r *http.Request) { + // Parse ID from path + idStr := r.PathValue("id") + if idStr == "" { + parts := splitPath(r.URL.Path) + if len(parts) > 0 { + idStr = parts[len(parts)-1] + } + } + if idStr == "" { + writeError(w, http.StatusBadRequest, errors.New("id is required")) + return + } + itemID, err := uuid.FromString(idStr) + if err != nil { + writeError(w, http.StatusBadRequest, errors.New("invalid id format")) + return + } + + var req updateInventoryRequest + if err := decodeJSON(r.Context(), r, &req); err != nil { + writeError(w, http.StatusBadRequest, err) + return + } + + claims, ok := middleware.GetClaims(r.Context()) + if !ok || claims.CompanyID == nil { + writeError(w, http.StatusUnauthorized, errors.New("unauthorized")) + return + } + + priceCents := int64(req.SalePrice * 100) + err = h.svc.UpdateInventoryItem(r.Context(), itemID, *claims.CompanyID, priceCents, req.StockQuantity) + if err != nil { + writeError(w, http.StatusInternalServerError, err) + return + } + + writeJSON(w, http.StatusOK, map[string]string{"status": "updated"}) } // CreateInventoryItem godoc @@ -479,11 +524,8 @@ func (h *Handler) CreateInventoryItem(w http.ResponseWriter, r *http.Request) { } } - // Logic: Use FinalPriceCents if provided, else SalePriceCents + // Logic: Use SalePriceCents finalPrice := req.SalePriceCents - if req.FinalPriceCents > 0 { - finalPrice = req.FinalPriceCents - } item := &domain.InventoryItem{ ProductID: prodID, diff --git a/backend-old/internal/http/handler/user_handler.go b/backend-old/internal/http/handler/user_handler.go index a6a060f..3f80c9c 100644 --- a/backend-old/internal/http/handler/user_handler.go +++ b/backend-old/internal/http/handler/user_handler.go @@ -45,12 +45,23 @@ func (h *Handler) CreateUser(w http.ResponseWriter, r *http.Request) { } } + // Only Superadmin can create another Superadmin + if req.Superadmin { + if !strings.EqualFold(requester.Role, "super_admin") && !strings.EqualFold(requester.Role, "superadmin") { // Allow both variations just in case + writeError(w, http.StatusForbidden, errors.New("only superadmins can create superadmins")) + return + } + } + user := &domain.User{ - CompanyID: req.CompanyID, - Role: req.Role, - Name: req.Name, - Username: req.Username, - Email: req.Email, + CompanyID: req.CompanyID, + Role: req.Role, + Name: req.Name, + Username: req.Username, + Email: req.Email, + Superadmin: req.Superadmin, + NomeSocial: req.NomeSocial, + CPF: req.CPF, } if err := h.svc.CreateUser(r.Context(), user, req.Password); err != nil { diff --git a/backend-old/internal/repository/postgres/migrations/0014_add_superadmin_fields.sql b/backend-old/internal/repository/postgres/migrations/0014_add_superadmin_fields.sql new file mode 100644 index 0000000..8f18ca6 --- /dev/null +++ b/backend-old/internal/repository/postgres/migrations/0014_add_superadmin_fields.sql @@ -0,0 +1,3 @@ +ALTER TABLE users ADD COLUMN IF NOT EXISTS superadmin BOOLEAN NOT NULL DEFAULT FALSE; +ALTER TABLE users ADD COLUMN IF NOT EXISTS nome_social TEXT; +ALTER TABLE users ADD COLUMN IF NOT EXISTS cpf TEXT; diff --git a/backend-old/internal/repository/postgres/postgres.go b/backend-old/internal/repository/postgres/postgres.go index 3e7d263..baf2413 100644 --- a/backend-old/internal/repository/postgres/postgres.go +++ b/backend-old/internal/repository/postgres/postgres.go @@ -854,8 +854,8 @@ func (r *Repository) CreateUser(ctx context.Context, user *domain.User) error { user.CreatedAt = now user.UpdatedAt = now - query := `INSERT INTO users (id, company_id, role, name, username, email, email_verified, password_hash, created_at, updated_at) -VALUES (:id, :company_id, :role, :name, :username, :email, :email_verified, :password_hash, :created_at, :updated_at)` + query := `INSERT INTO users (id, company_id, role, name, username, email, email_verified, password_hash, superadmin, nome_social, cpf, created_at, updated_at) +VALUES (:id, :company_id, :role, :name, :username, :email, :email_verified, :password_hash, :superadmin, :nome_social, :cpf, :created_at, :updated_at)` _, err := r.db.NamedExecContext(ctx, query, user) return err @@ -1383,97 +1383,9 @@ func (r *Repository) CreateInventoryItem(ctx context.Context, item *domain.Inven return err } -// ReplaceCart clears the cart and adds new items in a transaction. -func (r *Repository) ReplaceCart(ctx context.Context, buyerID uuid.UUID, items []domain.CartItem) error { - tx, err := r.db.BeginTxx(ctx, nil) - if err != nil { - return err - } - defer tx.Rollback() - - // 1. Clear Cart - if _, err := tx.ExecContext(ctx, "DELETE FROM cart_items WHERE buyer_id = $1", buyerID); err != nil { - return err - } - - // 2. Add Items - query := `INSERT INTO cart_items (id, buyer_id, product_id, quantity, unit_cents, batch, expires_at, created_at, updated_at) -VALUES (:id, :buyer_id, :product_id, :quantity, :unit_cents, :batch, :expires_at, :created_at, :updated_at)` - - for _, item := range items { - // Ensure IDs - if item.ID == uuid.Nil { - item.ID = uuid.Must(uuid.NewV7()) - } - item.CreatedAt = time.Now().UTC() - item.UpdatedAt = time.Now().UTC() - - if _, err := tx.NamedExecContext(ctx, query, item); err != nil { - return err - } - } - - return tx.Commit() -} - -// UpdateOrderItems replaces order items and updates total, handling stock accordingly. -func (r *Repository) UpdateOrderItems(ctx context.Context, orderID uuid.UUID, items []domain.OrderItem, totalCents int64) error { - tx, err := r.db.BeginTxx(ctx, nil) - if err != nil { - return err - } - defer tx.Rollback() - - // 1. Fetch existing items to restore stock - var oldItems []domain.OrderItem - if err := tx.SelectContext(ctx, &oldItems, "SELECT product_id, quantity FROM order_items WHERE order_id = $1", orderID); err != nil { - return err - } - - // 2. Restore stock for old items - for _, item := range oldItems { - if _, err := tx.ExecContext(ctx, "UPDATE products SET stock = stock + $1, updated_at = $2 WHERE id = $3", item.Quantity, time.Now().UTC(), item.ProductID); err != nil { - return err - } - } - - // 3. Delete existing items - if _, err := tx.ExecContext(ctx, "DELETE FROM order_items WHERE order_id = $1", orderID); err != nil { - return err - } - - // 4. Insert new items and consume stock - itemQuery := `INSERT INTO order_items (id, order_id, product_id, quantity, unit_cents, batch, expires_at) -VALUES (:id, :order_id, :product_id, :quantity, :unit_cents, :batch, :expires_at)` - - now := time.Now().UTC() - for _, item := range items { - if item.ID == uuid.Nil { - item.ID = uuid.Must(uuid.NewV7()) - } - item.OrderID = orderID - if _, err := tx.NamedExecContext(ctx, itemQuery, item); err != nil { - return err - } - - // Reduce stock - res, err := tx.ExecContext(ctx, `UPDATE products SET stock = stock - $1, updated_at = $2 WHERE id = $3 AND stock >= $1`, item.Quantity, now, item.ProductID) - if err != nil { - return err - } - rows, err := res.RowsAffected() - if err != nil { - return err - } - if rows == 0 { - return fmt.Errorf("insufficient stock for product %s", item.ProductID) - } - } - - // 5. Update Order Total - if _, err := tx.ExecContext(ctx, "UPDATE orders SET total_cents = $1, updated_at = $2 WHERE id = $3", totalCents, now, orderID); err != nil { - return err - } - - return tx.Commit() +func (r *Repository) UpdateInventoryItem(ctx context.Context, item *domain.InventoryItem) error { + query := `UPDATE inventory_items SET sale_price_cents = :sale_price_cents, stock_quantity = :stock_quantity, updated_at = :updated_at WHERE id = :id AND seller_id = :seller_id` + item.UpdatedAt = time.Now().UTC() + _, err := r.db.NamedExecContext(ctx, query, item) + return err } diff --git a/backend-old/internal/server/server.go b/backend-old/internal/server/server.go index 970e8d2..aa862df 100644 --- a/backend-old/internal/server/server.go +++ b/backend-old/internal/server/server.go @@ -109,8 +109,8 @@ func New(cfg config.Config) (*Server, error) { mux.Handle("GET /api/v1/inventory", chain(http.HandlerFunc(h.ListInventory), middleware.Logger, middleware.Gzip, auth)) mux.Handle("POST /api/v1/inventory", chain(http.HandlerFunc(h.CreateInventoryItem), middleware.Logger, middleware.Gzip, auth)) mux.Handle("POST /api/v1/produtos-venda", chain(http.HandlerFunc(h.CreateInventoryItem), middleware.Logger, middleware.Gzip, auth)) // Alias - mux.Handle("PUT /api/v1/produtos-venda/{id}", chain(http.HandlerFunc(h.UpdateInventoryItem), middleware.Logger, middleware.Gzip, auth)) // Correct Handler mux.Handle("GET /api/v1/produtos-venda", chain(http.HandlerFunc(h.ListInventory), middleware.Logger, middleware.Gzip, auth)) // Alias for list + mux.Handle("PUT /api/v1/produtos-venda/{id}", chain(http.HandlerFunc(h.UpdateInventoryItem), middleware.Logger, middleware.Gzip, auth)) // Update inventory mux.Handle("POST /api/v1/inventory/adjust", chain(http.HandlerFunc(h.AdjustInventory), middleware.Logger, middleware.Gzip, auth)) mux.Handle("POST /api/v1/orders", chain(http.HandlerFunc(h.CreateOrder), middleware.Logger, middleware.Gzip, auth)) diff --git a/backend-old/internal/usecase/product_service.go b/backend-old/internal/usecase/product_service.go index 8cb356c..9163983 100644 --- a/backend-old/internal/usecase/product_service.go +++ b/backend-old/internal/usecase/product_service.go @@ -129,10 +129,14 @@ func (s *Service) RegisterInventoryItem(ctx context.Context, item *domain.Invent return s.repo.CreateInventoryItem(ctx, item) } -func (s *Service) GetInventoryItem(ctx context.Context, id uuid.UUID) (*domain.InventoryItem, error) { - return s.repo.GetInventoryItem(ctx, id) -} - -func (s *Service) UpdateInventoryItem(ctx context.Context, item *domain.InventoryItem) error { +func (s *Service) UpdateInventoryItem(ctx context.Context, itemID uuid.UUID, sellerID uuid.UUID, priceCents int64, stockQuantity int64) error { + // We construct a partial item just for update + item := &domain.InventoryItem{ + ID: itemID, + SellerID: sellerID, + SalePriceCents: priceCents, + StockQuantity: stockQuantity, + } + // Future improvement: check if item exists and belongs to seller first, strict validation return s.repo.UpdateInventoryItem(ctx, item) } diff --git a/backend-old/internal/usecase/usecase.go b/backend-old/internal/usecase/usecase.go index 111045a..b56e86e 100644 --- a/backend-old/internal/usecase/usecase.go +++ b/backend-old/internal/usecase/usecase.go @@ -36,7 +36,6 @@ type Repository interface { AdjustInventory(ctx context.Context, productID uuid.UUID, delta int64, reason string) (*domain.InventoryItem, error) ListInventory(ctx context.Context, filter domain.InventoryFilter) ([]domain.InventoryItem, int64, error) CreateInventoryItem(ctx context.Context, item *domain.InventoryItem) error - GetInventoryItem(ctx context.Context, id uuid.UUID) (*domain.InventoryItem, error) UpdateInventoryItem(ctx context.Context, item *domain.InventoryItem) error CreateOrder(ctx context.Context, order *domain.Order) error diff --git a/backend-old/internal/usecase/usecase_test.go b/backend-old/internal/usecase/usecase_test.go index a7ab474..adfd1e6 100644 --- a/backend-old/internal/usecase/usecase_test.go +++ b/backend-old/internal/usecase/usecase_test.go @@ -183,6 +183,9 @@ func (m *MockRepository) AdjustInventory(ctx context.Context, productID uuid.UUI func (m *MockRepository) CreateInventoryItem(ctx context.Context, item *domain.InventoryItem) error { return nil } +func (m *MockRepository) UpdateInventoryItem(ctx context.Context, item *domain.InventoryItem) error { + return nil +} func (m *MockRepository) ListInventory(ctx context.Context, filter domain.InventoryFilter) ([]domain.InventoryItem, int64, error) { return nil, 0, nil } diff --git a/saveinmed-frontend/src/app/dashboard/components/CadastroSuperadminModal.tsx b/saveinmed-frontend/src/app/dashboard/components/CadastroSuperadminModal.tsx index 0d0a0ae..6f33fc6 100644 --- a/saveinmed-frontend/src/app/dashboard/components/CadastroSuperadminModal.tsx +++ b/saveinmed-frontend/src/app/dashboard/components/CadastroSuperadminModal.tsx @@ -1,12 +1,13 @@ "use client"; import { useState } from "react"; -import { X, AlertCircle, CheckCircle, Loader } from "lucide-react"; +import { X, AlertCircle, CheckCircle, Loader, Eye, EyeOff } from "lucide-react"; interface CadastroSuperadminModalProps { isOpen: boolean; onClose: () => void; onSuccess?: () => void; + currentCompanyId?: string; } // Funções de máscara @@ -31,10 +32,14 @@ export default function CadastroSuperadminModal({ isOpen, onClose, onSuccess, + currentCompanyId, }: CadastroSuperadminModalProps) { const [loading, setLoading] = useState(false); const [error, setError] = useState(""); const [success, setSuccess] = useState(false); + + const [showPassword, setShowPassword] = useState(false); + const [showConfirmPassword, setShowConfirmPassword] = useState(false); const [formData, setFormData] = useState({ nome: "", @@ -117,24 +122,22 @@ export default function CadastroSuperadminModal({ const telefoneLimpo = formData.telefone.replace(/\D/g, ""); const payload = { - identificador: formData.email, - nome: formData.nome, + name: formData.nome, + username: formData.email, email: formData.email, - telefone: telefoneLimpo || null, - senha: formData.senha, + password: formData.senha, cpf: cpfLimpo, - ativo: true, superadmin: true, - nivel: "admin", - "registro-completo": true, + role: "superadmin", "nome-social": formData.nomeSocial || null, + company_id: currentCompanyId || "00000000-0000-0000-0000-000000000000", // Fallback if no company provided, though might fail if foreign key invalid }; // Obter token do localStorage para enviar autorização const token = localStorage.getItem('access_token'); const response = await fetch( - `${process.env.NEXT_PUBLIC_BFF_API_URL}/usuarios`, + `${process.env.NEXT_PUBLIC_BFF_API_URL}/users`, { method: "POST", headers: { @@ -168,6 +171,7 @@ export default function CadastroSuperadminModal({ const errorData = await response.json().catch(() => ({})); setError( errorData.message || + errorData.error || `Erro ao criar superadmin (${response.status})` ); } @@ -308,15 +312,28 @@ export default function CadastroSuperadminModal({ - +
+ + +
{/* Confirmar Senha */} @@ -324,15 +341,28 @@ export default function CadastroSuperadminModal({ - +
+ + +
{/* Botões */} diff --git a/saveinmed-frontend/src/app/dashboard/page.tsx b/saveinmed-frontend/src/app/dashboard/page.tsx index 25ec7b3..bffb99c 100644 --- a/saveinmed-frontend/src/app/dashboard/page.tsx +++ b/saveinmed-frontend/src/app/dashboard/page.tsx @@ -825,6 +825,7 @@ const Dashboard = () => { onSuccess={() => { setShowCadastroSuperadminModal(false); }} + currentCompanyId={userData?.company_id || empresaId} /> ); diff --git a/saveinmed-frontend/src/app/usuarios-pendentes/page.tsx b/saveinmed-frontend/src/app/usuarios-pendentes/page.tsx index 700111a..808b6ed 100644 --- a/saveinmed-frontend/src/app/usuarios-pendentes/page.tsx +++ b/saveinmed-frontend/src/app/usuarios-pendentes/page.tsx @@ -4,14 +4,29 @@ import { useEffect, useState } from "react"; import { EmpresaBff, empresaApiService } from "@/services/empresaApiService"; import { useRouter } from "next/navigation"; import Header from "@/components/Header"; -import { CheckCircleIcon, XCircleIcon, BuildingOfficeIcon } from "@heroicons/react/24/outline"; +import { + CheckCircleIcon, + XCircleIcon, + BuildingOfficeIcon, + MagnifyingGlassIcon, + ArrowPathIcon, + UserGroupIcon, + CalendarIcon, + EnvelopeIcon, + PhoneIcon, + IdentificationIcon, + ClockIcon +} from "@heroicons/react/24/outline"; export default function UsuariosPendentesPage() { const router = useRouter(); const [empresas, setEmpresas] = useState([]); + const [filteredEmpresas, setFilteredEmpresas] = useState([]); const [loading, setLoading] = useState(true); const [userData, setUserData] = useState(null); const [error, setError] = useState(""); + const [search, setSearch] = useState(""); + const [approvingId, setApprovingId] = useState(null); const fetchUserData = async () => { try { @@ -48,6 +63,7 @@ export default function UsuariosPendentesPage() { try { const data = await empresaApiService.listar({ is_verified: false }); setEmpresas(data); + setFilteredEmpresas(data); } catch (err) { console.error(err); setError("Erro ao carregar usuários pendentes."); @@ -61,8 +77,25 @@ export default function UsuariosPendentesPage() { fetchPendentes(); }, []); + useEffect(() => { + if (!search.trim()) { + setFilteredEmpresas(empresas); + return; + } + const term = search.toLowerCase(); + const filtered = empresas.filter(e => + (e.razao_social || "").toLowerCase().includes(term) || + (e.nome_fantasia || "").toLowerCase().includes(term) || + (e.cnpj || "").includes(term) || + (e.email || "").toLowerCase().includes(term) + ); + setFilteredEmpresas(filtered); + }, [search, empresas]); + const handleAprovar = async (companyId: string) => { if (!confirm("Tem certeza que deseja aprovar este cadastro?")) return; + + setApprovingId(companyId); try { const sucesso = await empresaApiService.atualizar(companyId, { @@ -70,17 +103,25 @@ export default function UsuariosPendentesPage() { } as any); if (sucesso) { + // Remove from list without full reload for better UX + setEmpresas(prev => prev.filter(e => e.id !== companyId)); alert("Cadastro aprovado com sucesso!"); - fetchPendentes(); } else { alert("Erro ao aprovar cadastro."); } } catch (err) { console.error(err); alert("Erro ao processar aprovação."); + } finally { + setApprovingId(null); } }; + const formatarData = (dataString?: string) => { + if (!dataString) return "N/A"; + return new Date(dataString).toLocaleDateString('pt-BR'); + }; + if (!userData && loading) { return (
@@ -103,6 +144,38 @@ export default function UsuariosPendentesPage() {
+ {/* Filtros e Busca */} +
+
+
+ +
+
+ +
+ setSearch(e.target.value)} + className="block w-full pl-10 pr-3 py-2 border border-gray-300 rounded-md leading-5 bg-white placeholder-gray-500 focus:outline-none focus:placeholder-gray-400 focus:ring-1 focus:ring-blue-500 focus:border-blue-500" + placeholder="Razão Social, CNPJ ou Email..." + /> +
+
+ +
+
+ {error && (
@@ -114,59 +187,158 @@ export default function UsuariosPendentesPage() {
)} - {loading ? ( -
-
-

Carregando solicitações...

+ {/* Stats Cards */} +
+
+
+
+
+ +
+
+
+
Total Pendentes
+
{empresas.length}
+
+
+
+
- ) : empresas.length === 0 ? ( -
- -

Nenhum cadastro pendente

-

Todas as solicitações foram processadas.

+
+
+
+
+ +
+
+
+
Data Hoje
+
{new Date().toLocaleDateString('pt-BR')}
+
+
+
+
- ) : ( -
- {empresas.map((empresa) => ( -
-
-
-
-
-

- {empresa.razao_social || empresa.nome_fantasia || "Sem Nome"} -

- - Pendente - -
- -
-

CNPJ: {empresa.cnpj}

-

Email: {empresa.email}

-

Telefone: {empresa.telefone}

-

ID: {empresa.id}

-
-
+ {/* Placeholder for more stats if needed */} +
-
- -
+ {/* Lista */} +
+
+

+ Solicitações ({filteredEmpresas.length}) +

+ + {loading ? ( +
+
+

Carregando solicitações...

-
-
- ))} -
- )} + ) : filteredEmpresas.length === 0 ? ( +
+ +

Nenhum cadastro encontrado

+

+ {search ? "Nenhum resultado para sua busca." : "Todas as solicitações foram processadas."} +

+
+ ) : ( +
+ {filteredEmpresas.map((empresa) => ( +
+
+
+
+
+
+

+ {empresa.razao_social || empresa.nome_fantasia || "Sem Nome"} +

+ + Pendente + +
+

+ ID: {empresa.id} +

+
+ +
+ +
+
+ +
+
+ +
+

CNPJ

+

{empresa.cnpj}

+
+
+
+ +
+

Email

+

{empresa.email}

+
+
+
+ +
+

Telefone

+

{empresa.telefone || "N/A"}

+
+
+
+ +
+

Data Cadastro

+

{formatarData(empresa.created_at)}

+
+
+
+
+ +
+ +
+
+
+ ))} +
+ )} +
+
); diff --git a/saveinmed-frontend/src/services/empresaApiService.ts b/saveinmed-frontend/src/services/empresaApiService.ts index 28407fd..1b721fc 100644 --- a/saveinmed-frontend/src/services/empresaApiService.ts +++ b/saveinmed-frontend/src/services/empresaApiService.ts @@ -21,6 +21,8 @@ export interface EmpresaBff { estado: string; latitude?: string; longitude?: string; + created_at?: string; + category?: string; } export const empresaApiService = { @@ -97,6 +99,9 @@ export const empresaApiService = { ...item, razao_social: item.corporate_name || item.razao_social, // Fallback nome_fantasia: item.trade_name || item.nome_fantasia || "", + telefone: item.phone || item.telefone || "N/A", + created_at: item.created_at, + category: item.category, })); } catch (error) { console.error('❌ Erro ao listar empresas:', error);