package store // import ( // "context" // "fmt" // "strings" // "time" // "github.com/google/uuid" // "git.warky.dev/wdevs/amcs/internal/generatedmodels" // ext "git.warky.dev/wdevs/amcs/internal/types" // ) // func (db *DB) AddFamilyMember(ctx context.Context, m ext.FamilyMember) (ext.FamilyMember, error) { // row := db.pool.QueryRow(ctx, ` // insert into family_members (name, relationship, birth_date, notes) // values ($1, $2, $3, $4) // returning id, created_at // `, m.Name, nullStr(m.Relationship), m.BirthDate, nullStr(m.Notes)) // created := m // var model generatedmodels.ModelPublicFamilyMembers // if err := row.Scan(&model.ID, &model.CreatedAt); err != nil { // return ext.FamilyMember{}, fmt.Errorf("insert family member: %w", err) // } // created.ID = model.ID.UUID() // created.CreatedAt = model.CreatedAt.Time() // return created, nil // } // func (db *DB) ListFamilyMembers(ctx context.Context) ([]ext.FamilyMember, error) { // rows, err := db.pool.Query(ctx, `select id, name, relationship, birth_date, notes, created_at from family_members order by name`) // if err != nil { // return nil, fmt.Errorf("list family members: %w", err) // } // defer rows.Close() // var members []ext.FamilyMember // for rows.Next() { // var model generatedmodels.ModelPublicFamilyMembers // if err := rows.Scan(&model.ID, &model.Name, &model.Relationship, &model.BirthDate, &model.Notes, &model.CreatedAt); err != nil { // return nil, fmt.Errorf("scan family member: %w", err) // } // members = append(members, familyMemberFromModel(model)) // } // return members, rows.Err() // } // func (db *DB) AddActivity(ctx context.Context, a ext.Activity) (ext.Activity, error) { // row := db.pool.QueryRow(ctx, ` // insert into activities (family_member_id, title, activity_type, day_of_week, start_time, end_time, start_date, end_date, location, notes) // values ($1, $2, $3, $4, $5::time, $6::time, $7, $8, $9, $10) // returning id, created_at // `, a.FamilyMemberID, a.Title, nullStr(a.ActivityType), nullStr(a.DayOfWeek), // nullStr(a.StartTime), nullStr(a.EndTime), a.StartDate, a.EndDate, // nullStr(a.Location), nullStr(a.Notes)) // created := a // var model generatedmodels.ModelPublicActivities // if err := row.Scan(&model.ID, &model.CreatedAt); err != nil { // return ext.Activity{}, fmt.Errorf("insert activity: %w", err) // } // created.ID = model.ID.UUID() // created.CreatedAt = model.CreatedAt.Time() // return created, nil // } // func (db *DB) GetWeekSchedule(ctx context.Context, weekStart time.Time) ([]ext.Activity, error) { // weekEnd := weekStart.AddDate(0, 0, 7) // rows, err := db.pool.Query(ctx, ` // select a.id, a.family_member_id, fm.name, a.title, a.activity_type, // a.day_of_week, a.start_time::text, a.end_time::text, // a.start_date, a.end_date, a.location, a.notes, a.created_at // from activities a // left join family_members fm on fm.id = a.family_member_id // where (a.start_date >= $1 and a.start_date < $2) // or (a.day_of_week is not null and (a.end_date is null or a.end_date >= $1)) // order by a.start_date, a.start_time // `, weekStart, weekEnd) // if err != nil { // return nil, fmt.Errorf("get week schedule: %w", err) // } // defer rows.Close() // return scanActivities(rows) // } // func (db *DB) SearchActivities(ctx context.Context, query, activityType string, memberID *uuid.UUID) ([]ext.Activity, error) { // args := []any{} // conditions := []string{} // if q := strings.TrimSpace(query); q != "" { // args = append(args, "%"+q+"%") // conditions = append(conditions, fmt.Sprintf("(a.title ILIKE $%d OR a.notes ILIKE $%d)", len(args), len(args))) // } // if t := strings.TrimSpace(activityType); t != "" { // args = append(args, t) // conditions = append(conditions, fmt.Sprintf("a.activity_type = $%d", len(args))) // } // if memberID != nil { // args = append(args, *memberID) // conditions = append(conditions, fmt.Sprintf("a.family_member_id = $%d", len(args))) // } // q := ` // select a.id, a.family_member_id, fm.name, a.title, a.activity_type, // a.day_of_week, a.start_time::text, a.end_time::text, // a.start_date, a.end_date, a.location, a.notes, a.created_at // from activities a // left join family_members fm on fm.id = a.family_member_id // ` // if len(conditions) > 0 { // q += " where " + strings.Join(conditions, " and ") // } // q += " order by a.start_date, a.start_time" // rows, err := db.pool.Query(ctx, q, args...) // if err != nil { // return nil, fmt.Errorf("search activities: %w", err) // } // defer rows.Close() // return scanActivities(rows) // } // func (db *DB) AddImportantDate(ctx context.Context, d ext.ImportantDate) (ext.ImportantDate, error) { // row := db.pool.QueryRow(ctx, ` // insert into important_dates (family_member_id, title, date_value, recurring_yearly, reminder_days_before, notes) // values ($1, $2, $3, $4, $5, $6) // returning id, created_at // `, d.FamilyMemberID, d.Title, d.DateValue, d.RecurringYearly, d.ReminderDaysBefore, nullStr(d.Notes)) // created := d // var model generatedmodels.ModelPublicImportantDates // if err := row.Scan(&model.ID, &model.CreatedAt); err != nil { // return ext.ImportantDate{}, fmt.Errorf("insert important date: %w", err) // } // created.ID = model.ID.UUID() // created.CreatedAt = model.CreatedAt.Time() // return created, nil // } // func (db *DB) GetUpcomingDates(ctx context.Context, daysAhead int) ([]ext.ImportantDate, error) { // if daysAhead <= 0 { // daysAhead = 30 // } // now := time.Now() // cutoff := now.AddDate(0, 0, daysAhead) // // For yearly recurring events, check if this year's occurrence falls in range // rows, err := db.pool.Query(ctx, ` // select d.id, d.family_member_id, fm.name, d.title, d.date_value, // d.recurring_yearly, d.reminder_days_before, d.notes, d.created_at // from important_dates d // left join family_members fm on fm.id = d.family_member_id // where ( // (d.recurring_yearly = false and d.date_value between $1 and $2) // or // (d.recurring_yearly = true and // make_date(extract(year from now())::int, extract(month from d.date_value)::int, extract(day from d.date_value)::int) // between $1 and $2) // ) // order by d.date_value // `, now, cutoff) // if err != nil { // return nil, fmt.Errorf("get upcoming dates: %w", err) // } // defer rows.Close() // var dates []ext.ImportantDate // for rows.Next() { // var model generatedmodels.ModelPublicImportantDates // var memberName *string // if err := rows.Scan(&model.ID, &model.FamilyMemberID, &memberName, &model.Title, &model.DateValue, // &model.RecurringYearly, &model.ReminderDaysBefore, &model.Notes, &model.CreatedAt); err != nil { // return nil, fmt.Errorf("scan important date: %w", err) // } // dates = append(dates, importantDateFromModel(model, strVal(memberName))) // } // return dates, rows.Err() // } // func scanActivities(rows interface { // Next() bool // Scan(...any) error // Err() error // Close() // }) ([]ext.Activity, error) { // defer rows.Close() // var activities []ext.Activity // for rows.Next() { // var model generatedmodels.ModelPublicActivities // var memberName *string // if err := rows.Scan( // &model.ID, &model.FamilyMemberID, &memberName, &model.Title, &model.ActivityType, // &model.DayOfWeek, &model.StartTime, &model.EndTime, // &model.StartDate, &model.EndDate, &model.Location, &model.Notes, &model.CreatedAt, // ); err != nil { // return nil, fmt.Errorf("scan activity: %w", err) // } // activities = append(activities, activityFromModel(model, strVal(memberName))) // } // return activities, rows.Err() // }