package store import ( "context" "database/sql" ) func (s *Store) Projects(ctx context.Context, featuredOnly bool) ([]Project, error) { query := `select id, slug, title, location, year, category, description, cover_image, featured, created_at from projects` if featuredOnly { query += ` where featured = 1` } query += ` order by created_at desc, id desc` rows, err := s.db.QueryContext(ctx, query) if err != nil { return nil, err } defer rows.Close() var projects []Project for rows.Next() { var p Project var featured int if err := rows.Scan(&p.ID, &p.Slug, &p.Title, &p.Location, &p.Year, &p.Category, &p.Description, &p.CoverImage, &featured, &p.CreatedAt); err != nil { return nil, err } p.Featured = featured == 1 projects = append(projects, p) } return projects, rows.Err() } func (s *Store) ProjectBySlug(ctx context.Context, slug string) (Project, error) { var p Project var featured int err := s.db.QueryRowContext(ctx, `select id, slug, title, location, year, category, description, cover_image, featured, created_at from projects where slug = ?`, slug). Scan(&p.ID, &p.Slug, &p.Title, &p.Location, &p.Year, &p.Category, &p.Description, &p.CoverImage, &featured, &p.CreatedAt) if err != nil { return p, err } p.Featured = featured == 1 p.Images, err = s.ProjectImages(ctx, p.ID) return p, err } func (s *Store) ProjectImages(ctx context.Context, projectID int64) ([]ProjectImage, error) { rows, err := s.db.QueryContext(ctx, `select id, project_id, path, caption, position from project_images where project_id = ? order by position asc, id asc`, projectID) if err != nil { return nil, err } defer rows.Close() var images []ProjectImage for rows.Next() { var img ProjectImage if err := rows.Scan(&img.ID, &img.ProjectID, &img.Path, &img.Caption, &img.Position); err != nil { return nil, err } images = append(images, img) } return images, rows.Err() } func (s *Store) ProjectImagesByProject(ctx context.Context) (map[int64][]ProjectImage, error) { rows, err := s.db.QueryContext(ctx, `select id, project_id, path, caption, position from project_images order by project_id asc, position asc, id asc`) if err != nil { return nil, err } defer rows.Close() images := make(map[int64][]ProjectImage) for rows.Next() { var img ProjectImage if err := rows.Scan(&img.ID, &img.ProjectID, &img.Path, &img.Caption, &img.Position); err != nil { return nil, err } images[img.ProjectID] = append(images[img.ProjectID], img) } return images, rows.Err() } func (s *Store) ProjectImageForSlug(ctx context.Context, slug string, imageID int64) (Project, ProjectImage, error) { p, err := s.ProjectBySlug(ctx, slug) if err != nil { return Project{}, ProjectImage{}, err } for _, img := range p.Images { if img.ID == imageID { return p, img, nil } } return Project{}, ProjectImage{}, sql.ErrNoRows } func (s *Store) CreateProject(ctx context.Context, p Project) (int64, error) { res, err := s.db.ExecContext(ctx, `insert into projects (slug, title, location, year, category, description, cover_image, featured) values (?, ?, ?, ?, ?, ?, ?, ?)`, p.Slug, p.Title, p.Location, p.Year, p.Category, p.Description, p.CoverImage, boolInt(p.Featured)) if err != nil { return 0, err } return res.LastInsertId() } func (s *Store) UpdateProject(ctx context.Context, p Project) error { _, err := s.db.ExecContext(ctx, `update projects set slug=?, title=?, location=?, year=?, category=?, description=?, cover_image=?, featured=? where id=?`, p.Slug, p.Title, p.Location, p.Year, p.Category, p.Description, p.CoverImage, boolInt(p.Featured), p.ID) return err } func (s *Store) DeleteProject(ctx context.Context, id int64) error { _, err := s.db.ExecContext(ctx, `delete from projects where id = ?`, id) return err } func (s *Store) AddProjectImage(ctx context.Context, projectID int64, path, caption string) error { var pos int _ = s.db.QueryRowContext(ctx, `select coalesce(max(position), -1) + 1 from project_images where project_id = ?`, projectID).Scan(&pos) _, err := s.db.ExecContext(ctx, `insert into project_images (project_id, path, caption, position) values (?, ?, ?, ?)`, projectID, path, caption, pos) return err } func (s *Store) DeleteProjectImage(ctx context.Context, id int64) error { _, err := s.db.ExecContext(ctx, `delete from project_images where id = ?`, id) return err }