diff --git a/backend/internal/domain/models.go b/backend/internal/domain/models.go index e92f1db..08895ca 100644 --- a/backend/internal/domain/models.go +++ b/backend/internal/domain/models.go @@ -15,10 +15,15 @@ type Tenant struct { LicenseNumber string `db:"license_number" json:"license_number"` IsVerified bool `db:"is_verified" json:"is_verified"` // Location - Latitude float64 `db:"latitude" json:"latitude"` - Longitude float64 `db:"longitude" json:"longitude"` - City string `db:"city" json:"city"` - State string `db:"state" json:"state"` + Latitude float64 `db:"latitude" json:"latitude"` + Longitude float64 `db:"longitude" json:"longitude"` + City string `db:"city" json:"city"` + State string `db:"state" json:"state"` + // Contact & Hours + Phone string `db:"phone" json:"phone"` + OperatingHours string `db:"operating_hours" json:"operating_hours"` // e.g. "Seg-Sex: 08:00-18:00, Sab: 08:00-12:00" + Is24Hours bool `db:"is_24_hours" json:"is_24_hours"` + // Timestamps CreatedAt time.Time `db:"created_at" json:"created_at"` UpdatedAt time.Time `db:"updated_at" json:"updated_at"` } diff --git a/backend/internal/repository/postgres/migrations/0005_tenants_operating_hours.sql b/backend/internal/repository/postgres/migrations/0005_tenants_operating_hours.sql new file mode 100644 index 0000000..2585f85 --- /dev/null +++ b/backend/internal/repository/postgres/migrations/0005_tenants_operating_hours.sql @@ -0,0 +1,9 @@ +-- +goose Up +ALTER TABLE companies ADD COLUMN phone TEXT NOT NULL DEFAULT ''; +ALTER TABLE companies ADD COLUMN operating_hours TEXT NOT NULL DEFAULT ''; +ALTER TABLE companies ADD COLUMN is_24_hours BOOLEAN NOT NULL DEFAULT false; + +-- +goose Down +ALTER TABLE companies DROP COLUMN phone; +ALTER TABLE companies DROP COLUMN operating_hours; +ALTER TABLE companies DROP COLUMN is_24_hours; diff --git a/backend/internal/repository/postgres/postgres.go b/backend/internal/repository/postgres/postgres.go index d52b98b..9d3f927 100644 --- a/backend/internal/repository/postgres/postgres.go +++ b/backend/internal/repository/postgres/postgres.go @@ -29,8 +29,8 @@ func (r *Repository) CreateCompany(ctx context.Context, company *domain.Company) company.CreatedAt = now company.UpdatedAt = now - query := `INSERT INTO companies (id, cnpj, corporate_name, category, license_number, is_verified, latitude, longitude, city, state, created_at, updated_at) -VALUES (:id, :cnpj, :corporate_name, :category, :license_number, :is_verified, :latitude, :longitude, :city, :state, :created_at, :updated_at)` + query := `INSERT INTO companies (id, cnpj, corporate_name, category, license_number, is_verified, latitude, longitude, city, state, phone, operating_hours, is_24_hours, created_at, updated_at) +VALUES (:id, :cnpj, :corporate_name, :category, :license_number, :is_verified, :latitude, :longitude, :city, :state, :phone, :operating_hours, :is_24_hours, :created_at, :updated_at)` _, err := r.db.NamedExecContext(ctx, query, company) return err @@ -72,7 +72,7 @@ func (r *Repository) ListCompanies(ctx context.Context, filter domain.CompanyFil filter.Limit = 20 } args = append(args, filter.Limit, filter.Offset) - listQuery := fmt.Sprintf("SELECT id, cnpj, corporate_name, category, license_number, is_verified, latitude, longitude, city, state, created_at, updated_at %s%s ORDER BY created_at DESC LIMIT $%d OFFSET $%d", baseQuery, where, len(args)-1, len(args)) + listQuery := fmt.Sprintf("SELECT id, cnpj, corporate_name, category, license_number, is_verified, latitude, longitude, city, state, phone, operating_hours, is_24_hours, created_at, updated_at %s%s ORDER BY created_at DESC LIMIT $%d OFFSET $%d", baseQuery, where, len(args)-1, len(args)) var companies []domain.Company if err := r.db.SelectContext(ctx, &companies, listQuery, args...); err != nil { @@ -83,7 +83,7 @@ func (r *Repository) ListCompanies(ctx context.Context, filter domain.CompanyFil func (r *Repository) GetCompany(ctx context.Context, id uuid.UUID) (*domain.Company, error) { var company domain.Company - query := `SELECT id, cnpj, corporate_name, category, license_number, is_verified, latitude, longitude, city, state, created_at, updated_at FROM companies WHERE id = $1` + query := `SELECT id, cnpj, corporate_name, category, license_number, is_verified, latitude, longitude, city, state, phone, operating_hours, is_24_hours, created_at, updated_at FROM companies WHERE id = $1` if err := r.db.GetContext(ctx, &company, query, id); err != nil { return nil, err } @@ -94,7 +94,7 @@ func (r *Repository) UpdateCompany(ctx context.Context, company *domain.Company) company.UpdatedAt = time.Now().UTC() query := `UPDATE companies -SET cnpj = :cnpj, corporate_name = :corporate_name, category = :category, license_number = :license_number, is_verified = :is_verified, latitude = :latitude, longitude = :longitude, city = :city, state = :state, updated_at = :updated_at +SET cnpj = :cnpj, corporate_name = :corporate_name, category = :category, license_number = :license_number, is_verified = :is_verified, latitude = :latitude, longitude = :longitude, city = :city, state = :state, phone = :phone, operating_hours = :operating_hours, is_24_hours = :is_24_hours, updated_at = :updated_at WHERE id = :id` res, err := r.db.NamedExecContext(ctx, query, company) diff --git a/marketplace/src/pages/Company.tsx b/marketplace/src/pages/Company.tsx index e093b7e..e9847f8 100644 --- a/marketplace/src/pages/Company.tsx +++ b/marketplace/src/pages/Company.tsx @@ -13,6 +13,9 @@ interface Company { state: string latitude: number longitude: number + phone: string + operating_hours: string + is_24_hours: boolean created_at: string updated_at: string } @@ -180,8 +183,43 @@ export function CompanyPage() { const [shippingEditing, setShippingEditing] = useState(false) const [form, setForm] = useState({ corporate_name: '', - license_number: '' + license_number: '', + phone: '', + operating_hours: '', + is_24_hours: false, + city: '', + state: '' }) + // User editing state + const [editingUser, setEditingUser] = useState(null) + const [userForm, setUserForm] = useState({ name: '', email: '', role: '' }) + + const handleDeleteUser = async (userId: string) => { + if (!confirm('Tem certeza que deseja excluir este usuário?')) return + try { + await apiClient.delete(`/v1/users/${userId}`) + if (company) void loadUsers(company.id) + } catch (err) { + console.error('Erro ao excluir usuário:', err) + setUsersError('Erro ao excluir usuário') + } + } + + const handleSaveUser = async () => { + if (!editingUser) return + try { + await apiClient.patch(`/v1/users/${editingUser.id}`, { + name: userForm.name, + email: userForm.email, + role: userForm.role + }) + setEditingUser(null) + if (company) void loadUsers(company.id) + } catch (err) { + console.error('Erro ao salvar usuário:', err) + setUsersError('Erro ao salvar usuário') + } + } useEffect(() => { loadCompany() @@ -194,7 +232,12 @@ export function CompanyPage() { setCompany(data) setForm({ corporate_name: data.corporate_name, - license_number: data.license_number + license_number: data.license_number, + phone: data.phone || '', + operating_hours: data.operating_hours || '', + is_24_hours: data.is_24_hours || false, + city: data.city, + state: data.state }) setError(null) void loadUsers(data.id) @@ -457,29 +500,99 @@ export function CompanyPage() { {company && activeTab === 'overview' && editing && (
-
- - setForm({ ...form, corporate_name: e.target.value })} - className="w-full rounded border border-gray-200 px-3 py-2" - /> +
+
+ + setForm({ ...form, corporate_name: e.target.value })} + className="w-full rounded border border-gray-200 px-3 py-2" + /> +
+
+ + setForm({ ...form, license_number: e.target.value })} + className="w-full rounded border border-gray-200 px-3 py-2" + /> +
+
+ + setForm({ ...form, phone: e.target.value })} + className="w-full rounded border border-gray-200 px-3 py-2" + placeholder="(00) 00000-0000" + /> +
+
+
+ + setForm({ ...form, city: e.target.value })} + className="w-full rounded border border-gray-200 px-3 py-2" + /> +
+
+ + setForm({ ...form, state: e.target.value })} + className="w-full rounded border border-gray-200 px-3 py-2" + maxLength={2} + placeholder="GO" + /> +
+
-
- - setForm({ ...form, license_number: e.target.value })} - className="w-full rounded border border-gray-200 px-3 py-2" - /> + +
+

Horário de Funcionamento

+
+ + {!form.is_24_hours && ( +
+ +