Add filtering support to GET /api/v1/habits endpoint
Implemented comprehensive filtering capabilities for the habits list endpoint: - Filter by type (BOOLEAN, COUNTER, VALUE) - Filter by frequency (DAILY, WEEKLY, MONTHLY) - Filter by archived status - Text search in habit name and description - All filters can be combined - Filters work with pagination Technical changes: - Added FilterParams to GetUserHabitsQuery - Created HabitFilter struct in repository interface - Implemented dynamic SQL query building in SQLite repository - Updated HTTP handler to parse filter query parameters - Added comprehensive tests for repository and handler filtering - Updated all test mocks with new filter methods
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"apocapoc-api/internal/domain/repositories"
|
||||
"apocapoc-api/internal/shared/pagination"
|
||||
"context"
|
||||
"testing"
|
||||
@@ -238,3 +239,11 @@ func (m *mockHabitRepo) FindActiveByUserIDWithPagination(ctx context.Context, us
|
||||
func (m *mockHabitRepo) CountActiveByUserID(ctx context.Context, userID string) (int, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (m *mockHabitRepo) FindByUserIDFiltered(ctx context.Context, userID string, filter repositories.HabitFilter, paginationParams *pagination.Params) ([]*entities.Habit, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *mockHabitRepo) CountByUserIDFiltered(ctx context.Context, userID string, filter repositories.HabitFilter) (int, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"apocapoc-api/internal/domain/repositories"
|
||||
"apocapoc-api/internal/shared/pagination"
|
||||
"context"
|
||||
"testing"
|
||||
@@ -141,3 +142,11 @@ func (m *mockDeleteUserRepo) FindActiveByUserIDWithPagination(ctx context.Contex
|
||||
func (m *mockDeleteUserRepo) CountActiveByUserID(ctx context.Context, userID string) (int, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (m *mockDeleteUserRepo) FindByUserIDFiltered(ctx context.Context, userID string, filter repositories.HabitFilter, paginationParams *pagination.Params) ([]*entities.Habit, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *mockDeleteUserRepo) CountByUserIDFiltered(ctx context.Context, userID string, filter repositories.HabitFilter) (int, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"apocapoc-api/internal/domain/repositories"
|
||||
"apocapoc-api/internal/shared/pagination"
|
||||
"context"
|
||||
"testing"
|
||||
@@ -554,3 +555,19 @@ func (m *mockHabitRepoForMark) FindActiveByUserIDWithPagination(ctx context.Cont
|
||||
func (m *mockHabitRepoForMark) CountActiveByUserID(ctx context.Context, userID string) (int, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (m *mockEntryRepo) FindByUserIDFiltered(ctx context.Context, userID string, filter repositories.HabitFilter, paginationParams *pagination.Params) ([]*entities.Habit, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *mockEntryRepo) CountByUserIDFiltered(ctx context.Context, userID string, filter repositories.HabitFilter) (int, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (m *mockHabitRepoForMark) FindByUserIDFiltered(ctx context.Context, userID string, filter repositories.HabitFilter, paginationParams *pagination.Params) ([]*entities.Habit, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *mockHabitRepoForMark) CountByUserIDFiltered(ctx context.Context, userID string, filter repositories.HabitFilter) (int, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"apocapoc-api/internal/domain/repositories"
|
||||
"apocapoc-api/internal/shared/pagination"
|
||||
"context"
|
||||
"errors"
|
||||
@@ -304,3 +305,11 @@ func (m *mockUserRepo) FindActiveByUserIDWithPagination(ctx context.Context, use
|
||||
func (m *mockUserRepo) CountActiveByUserID(ctx context.Context, userID string) (int, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (m *mockUserRepo) FindByUserIDFiltered(ctx context.Context, userID string, filter repositories.HabitFilter, paginationParams *pagination.Params) ([]*entities.Habit, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *mockUserRepo) CountByUserIDFiltered(ctx context.Context, userID string, filter repositories.HabitFilter) (int, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"apocapoc-api/internal/domain/repositories"
|
||||
"apocapoc-api/internal/shared/pagination"
|
||||
"context"
|
||||
"testing"
|
||||
@@ -351,3 +352,19 @@ func (m *mockRequestResetUserRepo) FindActiveByUserIDWithPagination(ctx context.
|
||||
func (m *mockRequestResetUserRepo) CountActiveByUserID(ctx context.Context, userID string) (int, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (m *mockRequestResetTokenRepo) FindByUserIDFiltered(ctx context.Context, userID string, filter repositories.HabitFilter, paginationParams *pagination.Params) ([]*entities.Habit, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *mockRequestResetTokenRepo) CountByUserIDFiltered(ctx context.Context, userID string, filter repositories.HabitFilter) (int, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (m *mockRequestResetUserRepo) FindByUserIDFiltered(ctx context.Context, userID string, filter repositories.HabitFilter, paginationParams *pagination.Params) ([]*entities.Habit, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *mockRequestResetUserRepo) CountByUserIDFiltered(ctx context.Context, userID string, filter repositories.HabitFilter) (int, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"apocapoc-api/internal/domain/repositories"
|
||||
"apocapoc-api/internal/shared/pagination"
|
||||
"context"
|
||||
"testing"
|
||||
@@ -396,3 +397,19 @@ func (m *mockResetPasswordUserRepo) FindActiveByUserIDWithPagination(ctx context
|
||||
func (m *mockResetPasswordUserRepo) CountActiveByUserID(ctx context.Context, userID string) (int, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (m *mockPasswordResetTokenRepo) FindByUserIDFiltered(ctx context.Context, userID string, filter repositories.HabitFilter, paginationParams *pagination.Params) ([]*entities.Habit, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *mockPasswordResetTokenRepo) CountByUserIDFiltered(ctx context.Context, userID string, filter repositories.HabitFilter) (int, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (m *mockResetPasswordUserRepo) FindByUserIDFiltered(ctx context.Context, userID string, filter repositories.HabitFilter, paginationParams *pagination.Params) ([]*entities.Habit, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *mockResetPasswordUserRepo) CountByUserIDFiltered(ctx context.Context, userID string, filter repositories.HabitFilter) (int, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"apocapoc-api/internal/domain/repositories"
|
||||
"apocapoc-api/internal/shared/pagination"
|
||||
"context"
|
||||
"testing"
|
||||
@@ -195,3 +196,11 @@ func (m *mockRefreshTokenRepo) FindActiveByUserIDWithPagination(ctx context.Cont
|
||||
func (m *mockRefreshTokenRepo) CountActiveByUserID(ctx context.Context, userID string) (int, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (m *mockRefreshTokenRepo) FindByUserIDFiltered(ctx context.Context, userID string, filter repositories.HabitFilter, paginationParams *pagination.Params) ([]*entities.Habit, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *mockRefreshTokenRepo) CountByUserIDFiltered(ctx context.Context, userID string, filter repositories.HabitFilter) (int, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"apocapoc-api/internal/domain/repositories"
|
||||
"apocapoc-api/internal/shared/pagination"
|
||||
"context"
|
||||
"testing"
|
||||
@@ -146,3 +147,11 @@ func (m *mockEntryRepoForUnmark) FindActiveByUserIDWithPagination(ctx context.Co
|
||||
func (m *mockEntryRepoForUnmark) CountActiveByUserID(ctx context.Context, userID string) (int, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (m *mockEntryRepoForUnmark) FindByUserIDFiltered(ctx context.Context, userID string, filter repositories.HabitFilter, paginationParams *pagination.Params) ([]*entities.Habit, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *mockEntryRepoForUnmark) CountByUserIDFiltered(ctx context.Context, userID string, filter repositories.HabitFilter) (int, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"apocapoc-api/internal/domain/repositories"
|
||||
"apocapoc-api/internal/shared/pagination"
|
||||
"context"
|
||||
"testing"
|
||||
@@ -345,3 +346,11 @@ func (m *mockVerifyEmailUserRepo) FindActiveByUserIDWithPagination(ctx context.C
|
||||
func (m *mockVerifyEmailUserRepo) CountActiveByUserID(ctx context.Context, userID string) (int, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (m *mockVerifyEmailUserRepo) FindByUserIDFiltered(ctx context.Context, userID string, filter repositories.HabitFilter, paginationParams *pagination.Params) ([]*entities.Habit, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *mockVerifyEmailUserRepo) CountByUserIDFiltered(ctx context.Context, userID string, filter repositories.HabitFilter) (int, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user