package services import ( "errors" "fmt" "regexp" "strings" "gauth-central/internal/database" "gauth-central/internal/models" "gorm.io/gorm" ) type AboutService struct{} func NewAboutService() *AboutService { return &AboutService{} } // CreateAbout creates a new about entry. func (s *AboutService) CreateAbout( title string, image string, imageSub string, cv string, birthday string, city string, study string, website string, phone string, age string, interests string, degree string, x string, mail string, done *int, projectDone string, userH *int, hapyUser string, great *int, greatReviews string, team *int, supportTeam string, isActive bool, counterActive bool, ) (*models.About, error) { slug := s.generateUniqueSlug(slugifyAbout(title), "") about := models.About{ Title: title, Image: image, ImageSub: imageSub, CV: cv, Birthday: birthday, City: city, Study: study, Website: website, Phone: phone, Age: age, Interests: interests, Degree: degree, X: x, Mail: mail, Done: done, ProjectDone: projectDone, UserH: userH, HapyUser: hapyUser, Great: great, GreatReviews: greatReviews, Team: team, SupportTeam: supportTeam, Slug: slug, IsActive: isActive, CounterActive: counterActive, } if err := database.DB.Create(&about).Error; err != nil { return nil, err } return s.GetAboutByID(about.ID.String()) } // GetAllAbout retrieves all about entries. Use onlyActive to filter public data. func (s *AboutService) GetAllAbout(onlyActive bool) ([]models.About, error) { var abouts []models.About query := database.DB.Order("created_at desc") if onlyActive { query = query.Where("is_active = ?", true) } if err := query.Find(&abouts).Error; err != nil { return nil, err } return abouts, nil } // GetFirstActiveAbout returns the newest active about entry. func (s *AboutService) GetFirstActiveAbout() (*models.About, error) { var about models.About if err := database.DB.Where("is_active = ?", true).Order("created_at desc").First(&about).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, errors.New("about not found") } return nil, err } return &about, nil } // GetAboutByID retrieves an about entry by ID. func (s *AboutService) GetAboutByID(id string) (*models.About, error) { var about models.About if err := database.DB.Where("id = ?", id).First(&about).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, errors.New("about not found") } return nil, err } return &about, nil } // GetAboutBySlug retrieves an about entry by slug. Use onlyActive to limit public access. func (s *AboutService) GetAboutBySlug(slug string, onlyActive bool) (*models.About, error) { var about models.About query := database.DB.Where("slug = ?", slug) if onlyActive { query = query.Where("is_active = ?", true) } if err := query.First(&about).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, errors.New("about not found") } return nil, err } return &about, nil } // UpdateAbout updates an existing about entry. func (s *AboutService) UpdateAbout( id string, title *string, image *string, imageSub *string, cv *string, birthday *string, city *string, study *string, website *string, phone *string, age *string, interests *string, degree *string, x *string, mail *string, done *int, projectDone *string, userH *int, hapyUser *string, great *int, greatReviews *string, team *int, supportTeam *string, slug *string, isActive *bool, counterActive *bool, ) (*models.About, error) { about, err := s.GetAboutByID(id) if err != nil { return nil, err } updates := map[string]interface{}{} if title != nil { updates["title"] = *title } if image != nil { updates["image"] = *image } if imageSub != nil { updates["image_sub"] = *imageSub } if cv != nil { updates["cv"] = *cv } if birthday != nil { updates["birthday"] = *birthday } if city != nil { updates["city"] = *city } if study != nil { updates["study"] = *study } if website != nil { updates["website"] = *website } if phone != nil { updates["phone"] = *phone } if age != nil { updates["age"] = *age } if interests != nil { updates["interests"] = *interests } if degree != nil { updates["degree"] = *degree } if x != nil { updates["x"] = *x } if mail != nil { updates["mail"] = *mail } if done != nil { updates["done"] = *done } if projectDone != nil { updates["project_done"] = *projectDone } if userH != nil { updates["user_h"] = *userH } if hapyUser != nil { updates["hapy_user"] = *hapyUser } if great != nil { updates["great"] = *great } if greatReviews != nil { updates["great_reviews"] = *greatReviews } if team != nil { updates["team"] = *team } if supportTeam != nil { updates["support_team"] = *supportTeam } if slug != nil { clean := slugifyAbout(*slug) if clean == "" { return nil, errors.New("slug cannot be empty") } if s.slugExists(clean, id) { return nil, errors.New("slug already exists") } updates["slug"] = clean } if isActive != nil { updates["is_active"] = *isActive } if counterActive != nil { updates["counter_active"] = *counterActive } if len(updates) > 0 { if err := database.DB.Model(about).Updates(updates).Error; err != nil { return nil, err } } return s.GetAboutByID(id) } // DeleteAbout deletes an about entry by ID. func (s *AboutService) DeleteAbout(id string) error { result := database.DB.Delete(&models.About{}, "id = ?", id) if result.Error != nil { return result.Error } if result.RowsAffected == 0 { return errors.New("about not found") } return nil } func (s *AboutService) generateUniqueSlug(baseSlug string, excludeID string) string { slug := baseSlug counter := 1 for s.slugExists(slug, excludeID) { slug = fmt.Sprintf("%s-%d", baseSlug, counter) counter++ } return slug } func (s *AboutService) slugExists(slug string, excludeID string) bool { var count int64 query := database.DB.Model(&models.About{}).Where("slug = ?", slug) if excludeID != "" { query = query.Where("id <> ?", excludeID) } query.Count(&count) return count > 0 } func slugifyAbout(input string) string { clean := strings.TrimSpace(input) if clean == "" { return "" } replacer := strings.NewReplacer( "ı", "i", "İ", "i", "ş", "s", "Ş", "s", "ğ", "g", "Ğ", "g", "ç", "c", "Ç", "c", "ö", "o", "Ö", "o", "ü", "u", "Ü", "u", ) clean = strings.ToLower(replacer.Replace(clean)) re := regexp.MustCompile(`[^a-z0-9]+`) clean = re.ReplaceAllString(clean, "-") clean = strings.Trim(clean, "-") if clean == "" { return "about" } return clean }