feat(ui): add content editor components for skills and thoughts
Some checks failed
CI / build-and-test (push) Failing after -31m24s
Some checks failed
CI / build-and-test (push) Failing after -31m24s
* Implement ContentEditorField for inline editing of content * Create ContentEditorModal for editing content in a modal * Introduce FormerShell for managing forms related to skills and thoughts * Enhance SkillsPage and ThoughtsPage with new components for better content management
This commit is contained in:
@@ -1,280 +1,280 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
// import (
|
||||
// "context"
|
||||
// "encoding/json"
|
||||
// "fmt"
|
||||
// "strings"
|
||||
// "time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
// "github.com/google/uuid"
|
||||
|
||||
"git.warky.dev/wdevs/amcs/internal/generatedmodels"
|
||||
ext "git.warky.dev/wdevs/amcs/internal/types"
|
||||
)
|
||||
// "git.warky.dev/wdevs/amcs/internal/generatedmodels"
|
||||
// ext "git.warky.dev/wdevs/amcs/internal/types"
|
||||
// )
|
||||
|
||||
func (db *DB) AddRecipe(ctx context.Context, r ext.Recipe) (ext.Recipe, error) {
|
||||
ingredients, err := json.Marshal(r.Ingredients)
|
||||
if err != nil {
|
||||
return ext.Recipe{}, fmt.Errorf("marshal ingredients: %w", err)
|
||||
}
|
||||
instructions, err := json.Marshal(r.Instructions)
|
||||
if err != nil {
|
||||
return ext.Recipe{}, fmt.Errorf("marshal instructions: %w", err)
|
||||
}
|
||||
if r.Tags == nil {
|
||||
r.Tags = []string{}
|
||||
}
|
||||
// func (db *DB) AddRecipe(ctx context.Context, r ext.Recipe) (ext.Recipe, error) {
|
||||
// ingredients, err := json.Marshal(r.Ingredients)
|
||||
// if err != nil {
|
||||
// return ext.Recipe{}, fmt.Errorf("marshal ingredients: %w", err)
|
||||
// }
|
||||
// instructions, err := json.Marshal(r.Instructions)
|
||||
// if err != nil {
|
||||
// return ext.Recipe{}, fmt.Errorf("marshal instructions: %w", err)
|
||||
// }
|
||||
// if r.Tags == nil {
|
||||
// r.Tags = []string{}
|
||||
// }
|
||||
|
||||
row := db.pool.QueryRow(ctx, `
|
||||
insert into recipes (name, cuisine, prep_time_minutes, cook_time_minutes, servings, ingredients, instructions, tags, rating, notes)
|
||||
values ($1, $2, $3, $4, $5, $6::jsonb, $7::jsonb, $8, $9, $10)
|
||||
returning id, created_at, updated_at
|
||||
`, r.Name, nullStr(r.Cuisine), r.PrepTimeMinutes, r.CookTimeMinutes, r.Servings,
|
||||
ingredients, instructions, r.Tags, r.Rating, nullStr(r.Notes))
|
||||
// row := db.pool.QueryRow(ctx, `
|
||||
// insert into recipes (name, cuisine, prep_time_minutes, cook_time_minutes, servings, ingredients, instructions, tags, rating, notes)
|
||||
// values ($1, $2, $3, $4, $5, $6::jsonb, $7::jsonb, $8, $9, $10)
|
||||
// returning id, created_at, updated_at
|
||||
// `, r.Name, nullStr(r.Cuisine), r.PrepTimeMinutes, r.CookTimeMinutes, r.Servings,
|
||||
// ingredients, instructions, r.Tags, r.Rating, nullStr(r.Notes))
|
||||
|
||||
created := r
|
||||
var model generatedmodels.ModelPublicRecipes
|
||||
if err := row.Scan(&model.ID, &model.CreatedAt, &model.UpdatedAt); err != nil {
|
||||
return ext.Recipe{}, fmt.Errorf("insert recipe: %w", err)
|
||||
}
|
||||
created.ID = model.ID.UUID()
|
||||
created.CreatedAt = model.CreatedAt.Time()
|
||||
created.UpdatedAt = model.UpdatedAt.Time()
|
||||
return created, nil
|
||||
}
|
||||
// created := r
|
||||
// var model generatedmodels.ModelPublicRecipes
|
||||
// if err := row.Scan(&model.ID, &model.CreatedAt, &model.UpdatedAt); err != nil {
|
||||
// return ext.Recipe{}, fmt.Errorf("insert recipe: %w", err)
|
||||
// }
|
||||
// created.ID = model.ID.UUID()
|
||||
// created.CreatedAt = model.CreatedAt.Time()
|
||||
// created.UpdatedAt = model.UpdatedAt.Time()
|
||||
// return created, nil
|
||||
// }
|
||||
|
||||
func (db *DB) SearchRecipes(ctx context.Context, query, cuisine string, tags []string, ingredient string) ([]ext.Recipe, error) {
|
||||
args := []any{}
|
||||
conditions := []string{}
|
||||
// func (db *DB) SearchRecipes(ctx context.Context, query, cuisine string, tags []string, ingredient string) ([]ext.Recipe, error) {
|
||||
// args := []any{}
|
||||
// conditions := []string{}
|
||||
|
||||
if q := strings.TrimSpace(query); q != "" {
|
||||
args = append(args, "%"+q+"%")
|
||||
conditions = append(conditions, fmt.Sprintf("name ILIKE $%d", len(args)))
|
||||
}
|
||||
if c := strings.TrimSpace(cuisine); c != "" {
|
||||
args = append(args, c)
|
||||
conditions = append(conditions, fmt.Sprintf("cuisine = $%d", len(args)))
|
||||
}
|
||||
if len(tags) > 0 {
|
||||
args = append(args, tags)
|
||||
conditions = append(conditions, fmt.Sprintf("tags @> $%d", len(args)))
|
||||
}
|
||||
if ing := strings.TrimSpace(ingredient); ing != "" {
|
||||
args = append(args, "%"+ing+"%")
|
||||
conditions = append(conditions, fmt.Sprintf("ingredients::text ILIKE $%d", len(args)))
|
||||
}
|
||||
// if q := strings.TrimSpace(query); q != "" {
|
||||
// args = append(args, "%"+q+"%")
|
||||
// conditions = append(conditions, fmt.Sprintf("name ILIKE $%d", len(args)))
|
||||
// }
|
||||
// if c := strings.TrimSpace(cuisine); c != "" {
|
||||
// args = append(args, c)
|
||||
// conditions = append(conditions, fmt.Sprintf("cuisine = $%d", len(args)))
|
||||
// }
|
||||
// if len(tags) > 0 {
|
||||
// args = append(args, tags)
|
||||
// conditions = append(conditions, fmt.Sprintf("tags @> $%d", len(args)))
|
||||
// }
|
||||
// if ing := strings.TrimSpace(ingredient); ing != "" {
|
||||
// args = append(args, "%"+ing+"%")
|
||||
// conditions = append(conditions, fmt.Sprintf("ingredients::text ILIKE $%d", len(args)))
|
||||
// }
|
||||
|
||||
q := `select id, name, cuisine, prep_time_minutes, cook_time_minutes, servings, ingredients, instructions, tags::text[], rating, notes, created_at, updated_at from recipes`
|
||||
if len(conditions) > 0 {
|
||||
q += " where " + strings.Join(conditions, " and ")
|
||||
}
|
||||
q += " order by name"
|
||||
// q := `select id, name, cuisine, prep_time_minutes, cook_time_minutes, servings, ingredients, instructions, tags::text[], rating, notes, created_at, updated_at from recipes`
|
||||
// if len(conditions) > 0 {
|
||||
// q += " where " + strings.Join(conditions, " and ")
|
||||
// }
|
||||
// q += " order by name"
|
||||
|
||||
rows, err := db.pool.Query(ctx, q, args...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("search recipes: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
// rows, err := db.pool.Query(ctx, q, args...)
|
||||
// if err != nil {
|
||||
// return nil, fmt.Errorf("search recipes: %w", err)
|
||||
// }
|
||||
// defer rows.Close()
|
||||
|
||||
var recipes []ext.Recipe
|
||||
for rows.Next() {
|
||||
r, err := scanRecipeRow(rows)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
recipes = append(recipes, r)
|
||||
}
|
||||
return recipes, rows.Err()
|
||||
}
|
||||
// var recipes []ext.Recipe
|
||||
// for rows.Next() {
|
||||
// r, err := scanRecipeRow(rows)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// recipes = append(recipes, r)
|
||||
// }
|
||||
// return recipes, rows.Err()
|
||||
// }
|
||||
|
||||
func (db *DB) GetRecipe(ctx context.Context, id uuid.UUID) (ext.Recipe, error) {
|
||||
row := db.pool.QueryRow(ctx, `
|
||||
select id, name, cuisine, prep_time_minutes, cook_time_minutes, servings, ingredients, instructions, tags::text[], rating, notes, created_at, updated_at
|
||||
from recipes where id = $1
|
||||
`, id)
|
||||
// func (db *DB) GetRecipe(ctx context.Context, id uuid.UUID) (ext.Recipe, error) {
|
||||
// row := db.pool.QueryRow(ctx, `
|
||||
// select id, name, cuisine, prep_time_minutes, cook_time_minutes, servings, ingredients, instructions, tags::text[], rating, notes, created_at, updated_at
|
||||
// from recipes where id = $1
|
||||
// `, id)
|
||||
|
||||
var model generatedmodels.ModelPublicRecipes
|
||||
var tags []string
|
||||
if err := row.Scan(&model.ID, &model.Name, &model.Cuisine, &model.PrepTimeMinutes, &model.CookTimeMinutes, &model.Servings,
|
||||
&model.Ingredients, &model.Instructions, &tags, &model.Rating, &model.Notes, &model.CreatedAt, &model.UpdatedAt); err != nil {
|
||||
return ext.Recipe{}, fmt.Errorf("get recipe: %w", err)
|
||||
}
|
||||
if tags == nil {
|
||||
tags = []string{}
|
||||
}
|
||||
return recipeFromModel(model, tags), nil
|
||||
}
|
||||
// var model generatedmodels.ModelPublicRecipes
|
||||
// var tags []string
|
||||
// if err := row.Scan(&model.ID, &model.Name, &model.Cuisine, &model.PrepTimeMinutes, &model.CookTimeMinutes, &model.Servings,
|
||||
// &model.Ingredients, &model.Instructions, &tags, &model.Rating, &model.Notes, &model.CreatedAt, &model.UpdatedAt); err != nil {
|
||||
// return ext.Recipe{}, fmt.Errorf("get recipe: %w", err)
|
||||
// }
|
||||
// if tags == nil {
|
||||
// tags = []string{}
|
||||
// }
|
||||
// return recipeFromModel(model, tags), nil
|
||||
// }
|
||||
|
||||
func (db *DB) UpdateRecipe(ctx context.Context, id uuid.UUID, r ext.Recipe) (ext.Recipe, error) {
|
||||
ingredients, err := json.Marshal(r.Ingredients)
|
||||
if err != nil {
|
||||
return ext.Recipe{}, fmt.Errorf("marshal ingredients: %w", err)
|
||||
}
|
||||
instructions, err := json.Marshal(r.Instructions)
|
||||
if err != nil {
|
||||
return ext.Recipe{}, fmt.Errorf("marshal instructions: %w", err)
|
||||
}
|
||||
if r.Tags == nil {
|
||||
r.Tags = []string{}
|
||||
}
|
||||
// func (db *DB) UpdateRecipe(ctx context.Context, id uuid.UUID, r ext.Recipe) (ext.Recipe, error) {
|
||||
// ingredients, err := json.Marshal(r.Ingredients)
|
||||
// if err != nil {
|
||||
// return ext.Recipe{}, fmt.Errorf("marshal ingredients: %w", err)
|
||||
// }
|
||||
// instructions, err := json.Marshal(r.Instructions)
|
||||
// if err != nil {
|
||||
// return ext.Recipe{}, fmt.Errorf("marshal instructions: %w", err)
|
||||
// }
|
||||
// if r.Tags == nil {
|
||||
// r.Tags = []string{}
|
||||
// }
|
||||
|
||||
_, err = db.pool.Exec(ctx, `
|
||||
update recipes set
|
||||
name = $2, cuisine = $3, prep_time_minutes = $4, cook_time_minutes = $5,
|
||||
servings = $6, ingredients = $7::jsonb, instructions = $8::jsonb,
|
||||
tags = $9, rating = $10, notes = $11
|
||||
where id = $1
|
||||
`, id, r.Name, nullStr(r.Cuisine), r.PrepTimeMinutes, r.CookTimeMinutes, r.Servings,
|
||||
ingredients, instructions, r.Tags, r.Rating, nullStr(r.Notes))
|
||||
if err != nil {
|
||||
return ext.Recipe{}, fmt.Errorf("update recipe: %w", err)
|
||||
}
|
||||
return db.GetRecipe(ctx, id)
|
||||
}
|
||||
// _, err = db.pool.Exec(ctx, `
|
||||
// update recipes set
|
||||
// name = $2, cuisine = $3, prep_time_minutes = $4, cook_time_minutes = $5,
|
||||
// servings = $6, ingredients = $7::jsonb, instructions = $8::jsonb,
|
||||
// tags = $9, rating = $10, notes = $11
|
||||
// where id = $1
|
||||
// `, id, r.Name, nullStr(r.Cuisine), r.PrepTimeMinutes, r.CookTimeMinutes, r.Servings,
|
||||
// ingredients, instructions, r.Tags, r.Rating, nullStr(r.Notes))
|
||||
// if err != nil {
|
||||
// return ext.Recipe{}, fmt.Errorf("update recipe: %w", err)
|
||||
// }
|
||||
// return db.GetRecipe(ctx, id)
|
||||
// }
|
||||
|
||||
func (db *DB) CreateMealPlan(ctx context.Context, weekStart time.Time, entries []ext.MealPlanInput) ([]ext.MealPlanEntry, error) {
|
||||
if _, err := db.pool.Exec(ctx, `delete from meal_plans where week_start = $1`, weekStart); err != nil {
|
||||
return nil, fmt.Errorf("clear meal plan: %w", err)
|
||||
}
|
||||
// func (db *DB) CreateMealPlan(ctx context.Context, weekStart time.Time, entries []ext.MealPlanInput) ([]ext.MealPlanEntry, error) {
|
||||
// if _, err := db.pool.Exec(ctx, `delete from meal_plans where week_start = $1`, weekStart); err != nil {
|
||||
// return nil, fmt.Errorf("clear meal plan: %w", err)
|
||||
// }
|
||||
|
||||
var results []ext.MealPlanEntry
|
||||
for _, e := range entries {
|
||||
row := db.pool.QueryRow(ctx, `
|
||||
insert into meal_plans (week_start, day_of_week, meal_type, recipe_id, custom_meal, servings, notes)
|
||||
values ($1, $2, $3, $4, $5, $6, $7)
|
||||
returning id, created_at
|
||||
`, weekStart, e.DayOfWeek, e.MealType, e.RecipeID, nullStr(e.CustomMeal), e.Servings, nullStr(e.Notes))
|
||||
// var results []ext.MealPlanEntry
|
||||
// for _, e := range entries {
|
||||
// row := db.pool.QueryRow(ctx, `
|
||||
// insert into meal_plans (week_start, day_of_week, meal_type, recipe_id, custom_meal, servings, notes)
|
||||
// values ($1, $2, $3, $4, $5, $6, $7)
|
||||
// returning id, created_at
|
||||
// `, weekStart, e.DayOfWeek, e.MealType, e.RecipeID, nullStr(e.CustomMeal), e.Servings, nullStr(e.Notes))
|
||||
|
||||
entry := ext.MealPlanEntry{
|
||||
WeekStart: weekStart,
|
||||
DayOfWeek: e.DayOfWeek,
|
||||
MealType: e.MealType,
|
||||
RecipeID: e.RecipeID,
|
||||
CustomMeal: e.CustomMeal,
|
||||
Servings: e.Servings,
|
||||
Notes: e.Notes,
|
||||
}
|
||||
var model generatedmodels.ModelPublicMealPlans
|
||||
if err := row.Scan(&model.ID, &model.CreatedAt); err != nil {
|
||||
return nil, fmt.Errorf("insert meal plan entry: %w", err)
|
||||
}
|
||||
entry.ID = model.ID.UUID()
|
||||
entry.CreatedAt = model.CreatedAt.Time()
|
||||
results = append(results, entry)
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
// entry := ext.MealPlanEntry{
|
||||
// WeekStart: weekStart,
|
||||
// DayOfWeek: e.DayOfWeek,
|
||||
// MealType: e.MealType,
|
||||
// RecipeID: e.RecipeID,
|
||||
// CustomMeal: e.CustomMeal,
|
||||
// Servings: e.Servings,
|
||||
// Notes: e.Notes,
|
||||
// }
|
||||
// var model generatedmodels.ModelPublicMealPlans
|
||||
// if err := row.Scan(&model.ID, &model.CreatedAt); err != nil {
|
||||
// return nil, fmt.Errorf("insert meal plan entry: %w", err)
|
||||
// }
|
||||
// entry.ID = model.ID.UUID()
|
||||
// entry.CreatedAt = model.CreatedAt.Time()
|
||||
// results = append(results, entry)
|
||||
// }
|
||||
// return results, nil
|
||||
// }
|
||||
|
||||
func (db *DB) GetMealPlan(ctx context.Context, weekStart time.Time) ([]ext.MealPlanEntry, error) {
|
||||
rows, err := db.pool.Query(ctx, `
|
||||
select mp.id, mp.week_start, mp.day_of_week, mp.meal_type, mp.recipe_id, r.name, mp.custom_meal, mp.servings, mp.notes, mp.created_at
|
||||
from meal_plans mp
|
||||
left join recipes r on r.id = mp.recipe_id
|
||||
where mp.week_start = $1
|
||||
order by
|
||||
case mp.day_of_week
|
||||
when 'monday' then 1 when 'tuesday' then 2 when 'wednesday' then 3
|
||||
when 'thursday' then 4 when 'friday' then 5 when 'saturday' then 6
|
||||
when 'sunday' then 7 else 8
|
||||
end,
|
||||
case mp.meal_type
|
||||
when 'breakfast' then 1 when 'lunch' then 2 when 'dinner' then 3
|
||||
when 'snack' then 4 else 5
|
||||
end
|
||||
`, weekStart)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get meal plan: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
// func (db *DB) GetMealPlan(ctx context.Context, weekStart time.Time) ([]ext.MealPlanEntry, error) {
|
||||
// rows, err := db.pool.Query(ctx, `
|
||||
// select mp.id, mp.week_start, mp.day_of_week, mp.meal_type, mp.recipe_id, r.name, mp.custom_meal, mp.servings, mp.notes, mp.created_at
|
||||
// from meal_plans mp
|
||||
// left join recipes r on r.id = mp.recipe_id
|
||||
// where mp.week_start = $1
|
||||
// order by
|
||||
// case mp.day_of_week
|
||||
// when 'monday' then 1 when 'tuesday' then 2 when 'wednesday' then 3
|
||||
// when 'thursday' then 4 when 'friday' then 5 when 'saturday' then 6
|
||||
// when 'sunday' then 7 else 8
|
||||
// end,
|
||||
// case mp.meal_type
|
||||
// when 'breakfast' then 1 when 'lunch' then 2 when 'dinner' then 3
|
||||
// when 'snack' then 4 else 5
|
||||
// end
|
||||
// `, weekStart)
|
||||
// if err != nil {
|
||||
// return nil, fmt.Errorf("get meal plan: %w", err)
|
||||
// }
|
||||
// defer rows.Close()
|
||||
|
||||
var entries []ext.MealPlanEntry
|
||||
for rows.Next() {
|
||||
var model generatedmodels.ModelPublicMealPlans
|
||||
var recipeName *string
|
||||
if err := rows.Scan(&model.ID, &model.WeekStart, &model.DayOfWeek, &model.MealType, &model.RecipeID, &recipeName, &model.CustomMeal, &model.Servings, &model.Notes, &model.CreatedAt); err != nil {
|
||||
return nil, fmt.Errorf("scan meal plan entry: %w", err)
|
||||
}
|
||||
entries = append(entries, mealPlanEntryFromModel(model, strVal(recipeName)))
|
||||
}
|
||||
return entries, rows.Err()
|
||||
}
|
||||
// var entries []ext.MealPlanEntry
|
||||
// for rows.Next() {
|
||||
// var model generatedmodels.ModelPublicMealPlans
|
||||
// var recipeName *string
|
||||
// if err := rows.Scan(&model.ID, &model.WeekStart, &model.DayOfWeek, &model.MealType, &model.RecipeID, &recipeName, &model.CustomMeal, &model.Servings, &model.Notes, &model.CreatedAt); err != nil {
|
||||
// return nil, fmt.Errorf("scan meal plan entry: %w", err)
|
||||
// }
|
||||
// entries = append(entries, mealPlanEntryFromModel(model, strVal(recipeName)))
|
||||
// }
|
||||
// return entries, rows.Err()
|
||||
// }
|
||||
|
||||
func (db *DB) GenerateShoppingList(ctx context.Context, weekStart time.Time) (ext.ShoppingList, error) {
|
||||
entries, err := db.GetMealPlan(ctx, weekStart)
|
||||
if err != nil {
|
||||
return ext.ShoppingList{}, err
|
||||
}
|
||||
// func (db *DB) GenerateShoppingList(ctx context.Context, weekStart time.Time) (ext.ShoppingList, error) {
|
||||
// entries, err := db.GetMealPlan(ctx, weekStart)
|
||||
// if err != nil {
|
||||
// return ext.ShoppingList{}, err
|
||||
// }
|
||||
|
||||
recipeIDs := map[uuid.UUID]bool{}
|
||||
for _, e := range entries {
|
||||
if e.RecipeID != nil {
|
||||
recipeIDs[*e.RecipeID] = true
|
||||
}
|
||||
}
|
||||
// recipeIDs := map[uuid.UUID]bool{}
|
||||
// for _, e := range entries {
|
||||
// if e.RecipeID != nil {
|
||||
// recipeIDs[*e.RecipeID] = true
|
||||
// }
|
||||
// }
|
||||
|
||||
aggregated := map[string]*ext.ShoppingItem{}
|
||||
for id := range recipeIDs {
|
||||
recipe, err := db.GetRecipe(ctx, id)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
for _, ing := range recipe.Ingredients {
|
||||
key := strings.ToLower(ing.Name)
|
||||
if existing, ok := aggregated[key]; ok {
|
||||
if ing.Quantity != "" {
|
||||
existing.Quantity += "+" + ing.Quantity
|
||||
}
|
||||
} else {
|
||||
recipeIDCopy := id
|
||||
aggregated[key] = &ext.ShoppingItem{
|
||||
Name: ing.Name,
|
||||
Quantity: ing.Quantity,
|
||||
Unit: ing.Unit,
|
||||
Purchased: false,
|
||||
RecipeID: &recipeIDCopy,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// aggregated := map[string]*ext.ShoppingItem{}
|
||||
// for id := range recipeIDs {
|
||||
// recipe, err := db.GetRecipe(ctx, id)
|
||||
// if err != nil {
|
||||
// continue
|
||||
// }
|
||||
// for _, ing := range recipe.Ingredients {
|
||||
// key := strings.ToLower(ing.Name)
|
||||
// if existing, ok := aggregated[key]; ok {
|
||||
// if ing.Quantity != "" {
|
||||
// existing.Quantity += "+" + ing.Quantity
|
||||
// }
|
||||
// } else {
|
||||
// recipeIDCopy := id
|
||||
// aggregated[key] = &ext.ShoppingItem{
|
||||
// Name: ing.Name,
|
||||
// Quantity: ing.Quantity,
|
||||
// Unit: ing.Unit,
|
||||
// Purchased: false,
|
||||
// RecipeID: &recipeIDCopy,
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
items := make([]ext.ShoppingItem, 0, len(aggregated))
|
||||
for _, item := range aggregated {
|
||||
items = append(items, *item)
|
||||
}
|
||||
// items := make([]ext.ShoppingItem, 0, len(aggregated))
|
||||
// for _, item := range aggregated {
|
||||
// items = append(items, *item)
|
||||
// }
|
||||
|
||||
itemsJSON, err := json.Marshal(items)
|
||||
if err != nil {
|
||||
return ext.ShoppingList{}, fmt.Errorf("marshal shopping items: %w", err)
|
||||
}
|
||||
// itemsJSON, err := json.Marshal(items)
|
||||
// if err != nil {
|
||||
// return ext.ShoppingList{}, fmt.Errorf("marshal shopping items: %w", err)
|
||||
// }
|
||||
|
||||
row := db.pool.QueryRow(ctx, `
|
||||
insert into shopping_lists (week_start, items)
|
||||
values ($1, $2::jsonb)
|
||||
on conflict (week_start) do update set items = excluded.items, updated_at = now()
|
||||
returning id, created_at, updated_at
|
||||
`, weekStart, itemsJSON)
|
||||
// row := db.pool.QueryRow(ctx, `
|
||||
// insert into shopping_lists (week_start, items)
|
||||
// values ($1, $2::jsonb)
|
||||
// on conflict (week_start) do update set items = excluded.items, updated_at = now()
|
||||
// returning id, created_at, updated_at
|
||||
// `, weekStart, itemsJSON)
|
||||
|
||||
var model generatedmodels.ModelPublicShoppingLists
|
||||
list := ext.ShoppingList{WeekStart: weekStart, Items: items}
|
||||
if err := row.Scan(&model.ID, &model.CreatedAt, &model.UpdatedAt); err != nil {
|
||||
return ext.ShoppingList{}, fmt.Errorf("upsert shopping list: %w", err)
|
||||
}
|
||||
list.ID = model.ID.UUID()
|
||||
list.CreatedAt = model.CreatedAt.Time()
|
||||
list.UpdatedAt = model.UpdatedAt.Time()
|
||||
return list, nil
|
||||
}
|
||||
// var model generatedmodels.ModelPublicShoppingLists
|
||||
// list := ext.ShoppingList{WeekStart: weekStart, Items: items}
|
||||
// if err := row.Scan(&model.ID, &model.CreatedAt, &model.UpdatedAt); err != nil {
|
||||
// return ext.ShoppingList{}, fmt.Errorf("upsert shopping list: %w", err)
|
||||
// }
|
||||
// list.ID = model.ID.UUID()
|
||||
// list.CreatedAt = model.CreatedAt.Time()
|
||||
// list.UpdatedAt = model.UpdatedAt.Time()
|
||||
// return list, nil
|
||||
// }
|
||||
|
||||
func scanRecipeRow(rows interface{ Scan(...any) error }) (ext.Recipe, error) {
|
||||
var model generatedmodels.ModelPublicRecipes
|
||||
var tags []string
|
||||
if err := rows.Scan(&model.ID, &model.Name, &model.Cuisine, &model.PrepTimeMinutes, &model.CookTimeMinutes, &model.Servings,
|
||||
&model.Ingredients, &model.Instructions, &tags, &model.Rating, &model.Notes, &model.CreatedAt, &model.UpdatedAt); err != nil {
|
||||
return ext.Recipe{}, fmt.Errorf("scan recipe: %w", err)
|
||||
}
|
||||
if tags == nil {
|
||||
tags = []string{}
|
||||
}
|
||||
return recipeFromModel(model, tags), nil
|
||||
}
|
||||
// func scanRecipeRow(rows interface{ Scan(...any) error }) (ext.Recipe, error) {
|
||||
// var model generatedmodels.ModelPublicRecipes
|
||||
// var tags []string
|
||||
// if err := rows.Scan(&model.ID, &model.Name, &model.Cuisine, &model.PrepTimeMinutes, &model.CookTimeMinutes, &model.Servings,
|
||||
// &model.Ingredients, &model.Instructions, &tags, &model.Rating, &model.Notes, &model.CreatedAt, &model.UpdatedAt); err != nil {
|
||||
// return ext.Recipe{}, fmt.Errorf("scan recipe: %w", err)
|
||||
// }
|
||||
// if tags == nil {
|
||||
// tags = []string{}
|
||||
// }
|
||||
// return recipeFromModel(model, tags), nil
|
||||
// }
|
||||
|
||||
Reference in New Issue
Block a user