Add notification settings, account deletion, photo reporting, and pending-user photos

Addresses user bug reports: settings pages needed real notification
preferences and account deletion, admin needed a way to flag a specific
photo independent of deleting it, and the pending-approval users list
needed to surface applicant photos for review.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-26 18:08:57 +03:30
parent c8e6f80c51
commit 2c6d4bfbd2
12 changed files with 188 additions and 17 deletions
+40 -3
View File
@@ -52,9 +52,29 @@ func (s *AdminService) GetUser(id uint) (*models.User, error) {
return s.userRepo.FindByID(id)
}
// ListPendingUsers کاربرانی که آنبوردینگ رو تکمیل کردن و منتظر بررسی‌اند
func (s *AdminService) ListPendingUsers() ([]models.User, error) {
return s.userRepo.ListPendingApproval()
// ListPendingUsers کاربرانی که آنبوردینگ رو تکمیل کردن و منتظر بررسی‌اند، به
// همراه عکس‌هاشون (batch گرفته می‌شه، نه یک کوئری جدا به‌ازای هر کاربر) تا
// ادمین بدون کلیک روی هرکدوم بتونه یه نگاه سریع به عکس‌ها بندازه.
func (s *AdminService) ListPendingUsers() ([]models.User, map[uint][]string, error) {
users, err := s.userRepo.ListPendingApproval()
if err != nil {
return nil, nil, err
}
ids := make([]uint, len(users))
for i, u := range users {
ids[i] = u.ID
}
photos, err := s.photoRepo.ListByUserIDs(ids)
if err != nil {
return nil, nil, err
}
photosByUser := make(map[uint][]string, len(ids))
for _, p := range photos {
photosByUser[p.UserID] = append(photosByUser[p.UserID], p.URL)
}
return users, photosByUser, nil
}
// ApproveUser کاربر رو تایید می‌کنه تا بتونه وارد صفحه‌ی دوستیابی بشه
@@ -205,6 +225,23 @@ func (s *AdminService) ReportUser(id uint, reason string) (*models.Report, error
return report, nil
}
// ReportPhoto یک عکس مشخص رو گزارش می‌کنه (روی صاحب عکس هم توی سابقه‌ی
// گزارش‌ها ثبت می‌شه، با ارجاع به همون عکس).
func (s *AdminService) ReportPhoto(photoID uint, reason string) (*models.Report, error) {
if reason == "" {
return nil, ErrReportReasonEmpty
}
photo, err := s.photoRepo.FindByID(photoID)
if err != nil {
return nil, err
}
report := &models.Report{UserID: photo.UserID, PhotoID: &photo.ID, Reason: reason}
if err := s.reportRepo.Create(report); err != nil {
return nil, err
}
return report, nil
}
// ListReports سابقه‌ی گزارش‌های ثبت‌شده روی یک کاربر رو برمی‌گردونه.
func (s *AdminService) ListReports(userID uint) ([]models.Report, error) {
return s.reportRepo.ListByUser(userID)
+22
View File
@@ -141,3 +141,25 @@ func (s *ProfileService) CheckIn(user *models.User) (*dto.CheckInResult, error)
return &dto.CheckInResult{StreakCount: newStreak, IsNewToday: true}, nil
}
// UpdateNotificationSettings ترجیحات اعلان کاربر رو ذخیره می‌کنه.
func (s *ProfileService) UpdateNotificationSettings(user *models.User, req dto.UpdateNotificationSettingsRequest) error {
if err := s.userRepo.UpdateFields(user, map[string]interface{}{
"notify_matches": req.NotifyMatches,
"notify_messages": req.NotifyMessages,
"notify_likes": req.NotifyLikes,
}); err != nil {
return err
}
user.NotifyMatches = req.NotifyMatches
user.NotifyMessages = req.NotifyMessages
user.NotifyLikes = req.NotifyLikes
return nil
}
// DeleteAccount حساب کاربر رو غیرفعال می‌کنه (soft) نه پاک‌سازی کامل رکورد؛
// چون مچ‌ها/پیام‌های طرف مقابل نباید یهو پاره بشن. کاربر غیرفعال دیگه اصلاً
// نمی‌تونه لاگین کنه (چک IsActive توی AuthRequired و AuthService).
func (s *ProfileService) DeleteAccount(user *models.User) error {
return s.userRepo.UpdateFields(user, map[string]interface{}{"is_active": false})
}