package repository import ( "context" "database/sql" "bugulma/backend/internal/domain" "gorm.io/gorm" ) // TimelineRepository implements domain.TimelineRepository with GORM type TimelineRepository struct { *BaseRepository[domain.TimelineItem] } // NewTimelineRepository creates a new GORM-based timeline repository func NewTimelineRepository(db *gorm.DB) *TimelineRepository { return &TimelineRepository{ BaseRepository: NewBaseRepository[domain.TimelineItem](db), } } // getLocalizedValue retrieves a localized value from the localizations table // Returns empty string if not found (will fallback to default) func (r *TimelineRepository) getLocalizedValue(entityType, entityID, field, locale string) string { if locale == "en" || locale == "tt" { // Only localize if not default (assuming default is Russian) locRepo := NewLocalizationRepository(r.DB()) loc, err := locRepo.GetByEntityAndField(context.Background(), entityType, entityID, field, locale) if err != nil || loc == nil { return "" // Not found, will fallback to default } return loc.Value } return "" // Default locale, no localization needed } // GetAll retrieves all timeline items with optional filtering func (r *TimelineRepository) GetAll(locale string, heritageOnly bool) ([]domain.TimelineItem, error) { // Default to Russian if locale is empty or invalid if locale == "" { locale = "ru" } if locale != "ru" && locale != "en" && locale != "tt" { locale = "ru" } var items []domain.TimelineItem query := r.DB() // Filter by heritage flag if requested if heritageOnly { query = query.Where("heritage IS TRUE") } if err := query.Order(`"order" ASC`).Find(&items).Error; err != nil { return nil, err } // Apply localization if not Russian if locale != "ru" { for i := range items { item := &items[i] if localizedTitle := r.getLocalizedValue("timeline_item", item.ID, "title", locale); localizedTitle != "" { item.Title = localizedTitle } if localizedContent := r.getLocalizedValue("timeline_item", item.ID, "content", locale); localizedContent != "" { item.Content = localizedContent } } } return items, nil } // GetByID retrieves a timeline item by ID func (r *TimelineRepository) GetByID(ctx context.Context, id string) (*domain.TimelineItem, error) { return r.BaseRepository.GetByID(ctx, id) } // GetHeritageItems retrieves only timeline items marked for heritage display func (r *TimelineRepository) GetHeritageItems(locale string) ([]domain.TimelineItem, error) { return r.GetAll(locale, true) } // Create creates a new timeline item func (r *TimelineRepository) Create(ctx context.Context, item *domain.TimelineItem) error { return r.BaseRepository.Create(ctx, item) } // Update updates a timeline item func (r *TimelineRepository) Update(ctx context.Context, item *domain.TimelineItem) error { return r.BaseRepository.Update(ctx, item) } // Delete deletes a timeline item by ID func (r *TimelineRepository) Delete(ctx context.Context, id string) error { return r.BaseRepository.Delete(ctx, id) } // GetByHeritageFlag retrieves timeline items by heritage flag func (r *TimelineRepository) GetByHeritageFlag(ctx context.Context, isHeritage bool) ([]domain.TimelineItem, error) { var items []domain.TimelineItem query := r.DB().WithContext(ctx) if isHeritage { query = query.Where(&domain.TimelineItem{Heritage: sql.NullBool{Bool: true, Valid: true}}) } else { // For false, we need to find items where heritage is either false or null query = query.Where("heritage IS NULL OR heritage = false") } if err := query.Order(`"order" ASC`).Find(&items).Error; err != nil { return nil, err } return items, nil }