package volunteer import ( "database/sql" "errors" "fmt" "time" ) type Volunteer struct { ID int64 `json:"id"` Name string `json:"name"` Email string `json:"email"` Role string `json:"role"` Active bool `json:"active"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } type CreateInput struct { Name string `json:"name"` Email string `json:"email"` Password string `json:"password"` Role string `json:"role"` } type UpdateInput struct { Name *string `json:"name"` Email *string `json:"email"` Role *string `json:"role"` Active *bool `json:"active"` } type Store struct { db *sql.DB } func NewStore(db *sql.DB) *Store { return &Store{db: db} } func (s *Store) Create(name, email, hashedPassword, role string) (*Volunteer, error) { res, err := s.db.Exec( `INSERT INTO volunteers (name, email, password, role) VALUES (?, ?, ?, ?)`, name, email, hashedPassword, role, ) if err != nil { return nil, fmt.Errorf("insert volunteer: %w", err) } id, _ := res.LastInsertId() return s.GetByID(id) } func (s *Store) GetByID(id int64) (*Volunteer, error) { v := &Volunteer{} var createdAt, updatedAt string err := s.db.QueryRow( `SELECT id, name, email, role, active, created_at, updated_at FROM volunteers WHERE id = ?`, id, ).Scan(&v.ID, &v.Name, &v.Email, &v.Role, &v.Active, &createdAt, &updatedAt) if errors.Is(err, sql.ErrNoRows) { return nil, nil } if err != nil { return nil, fmt.Errorf("get volunteer: %w", err) } v.CreatedAt, _ = time.Parse("2006-01-02 15:04:05", createdAt) v.UpdatedAt, _ = time.Parse("2006-01-02 15:04:05", updatedAt) return v, nil } func (s *Store) List(activeOnly bool) ([]Volunteer, error) { query := `SELECT id, name, email, role, active, created_at, updated_at FROM volunteers` if activeOnly { query += ` WHERE active = 1` } query += ` ORDER BY name` rows, err := s.db.Query(query) if err != nil { return nil, fmt.Errorf("list volunteers: %w", err) } defer rows.Close() var volunteers []Volunteer for rows.Next() { var v Volunteer var createdAt, updatedAt string if err := rows.Scan(&v.ID, &v.Name, &v.Email, &v.Role, &v.Active, &createdAt, &updatedAt); err != nil { return nil, err } v.CreatedAt, _ = time.Parse("2006-01-02 15:04:05", createdAt) v.UpdatedAt, _ = time.Parse("2006-01-02 15:04:05", updatedAt) volunteers = append(volunteers, v) } return volunteers, rows.Err() } func (s *Store) Update(id int64, in UpdateInput) (*Volunteer, error) { v, err := s.GetByID(id) if err != nil || v == nil { return v, err } if in.Name != nil { v.Name = *in.Name } if in.Email != nil { v.Email = *in.Email } if in.Role != nil { v.Role = *in.Role } if in.Active != nil { v.Active = *in.Active } activeInt := 0 if v.Active { activeInt = 1 } _, err = s.db.Exec( `UPDATE volunteers SET name=?, email=?, role=?, active=?, updated_at=datetime('now') WHERE id=?`, v.Name, v.Email, v.Role, activeInt, id, ) if err != nil { return nil, fmt.Errorf("update volunteer: %w", err) } return s.GetByID(id) }