Some checks failed
CI / build-and-test (push) Failing after -31m25s
* Update project creation and retrieval to use generated models * Modify skill addition and listing to utilize generated models * Refactor thought handling to incorporate generated models * Adjust tool annotations to align with new model structure * Update API calls in the UI to use new ResolveSpec-based endpoints * Enhance stats retrieval logic to aggregate thought metadata
207 lines
7.1 KiB
Go
207 lines
7.1 KiB
Go
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()
|
|
}
|