Initial working shopping cart thing.

master
Zed A. Shaw 3 weeks ago
parent e011a8c333
commit 1c46f3dc38
  1. 1
      data/crud.go
  2. 21
      data/models.go
  3. 10
      features/init.go
  4. 13
      migrations/20260112190943_shopping_init.sql
  5. 13
      migrations/20260112195518_shopping_cart.sql
  6. 16
      static/style.css

@ -28,6 +28,7 @@ func Shutdown() {
} }
func SelectJson[T any](c *fiber.Ctx, err error, sql string, args ...interface{}) error { func SelectJson[T any](c *fiber.Ctx, err error, sql string, args ...interface{}) error {
// BUG: add a precondition that aborts if array of interfaces to avoid "unsupported $1 array of interfaces"
var result []T var result []T
if err != nil { goto fail } if err != nil { goto fail }

@ -25,9 +25,30 @@ type NullExample struct {
HasMaybe null.Int `db:"replying_to" validate:"omitempty,numeric"` HasMaybe null.Int `db:"replying_to" validate:"omitempty,numeric"`
} }
type Product struct {
Id int `db:"id" validate:"numeric"`
Title string `db:"title" validate:"required"`
Description string `db:"description" validate:"required"`
Price float64 `db:"price" validate:"required"`
Slug string `db:"slug" validate:"required"`
}
type CartItem struct {
Id int `db:"id" validate:"numeric"`
UserId int `db:"user_id" validate:"numeric,required"`
ProductId int `db:"product_id" validate:"required"`
Quantity int `db:"quantity" validate:"numeric"`
}
type Cart struct {
Items []CartItem
}
func Models() map[string]reflect.Type { func Models() map[string]reflect.Type {
return map[string]reflect.Type{ return map[string]reflect.Type{
"user": reflect.TypeFor[User](), "user": reflect.TypeFor[User](),
"product": reflect.TypeFor[Product](),
"cart_item": reflect.TypeFor[CartItem](),
"null_example": reflect.TypeFor[NullExample](), "null_example": reflect.TypeFor[NullExample](),
} }
} }

@ -2,11 +2,13 @@ package features
import ( import (
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
email "MY/webapp/features/email" "MY/webapp/features/email"
paypal "MY/webapp/features/paypal" "MY/webapp/features/paypal"
"MY/webapp/features/shopping"
) )
func Setup(app *fiber.App) { func Setup(app *fiber.App) {
email.Setup(app) features_email.Setup(app)
paypal.Setup(app) features_paypal.Setup(app)
features_shopping.Setup(app)
} }

@ -0,0 +1,13 @@
-- +goose Up
-- +goose StatementBegin
CREATE TABLE Product (id INTEGER PRIMARY KEY,
title TEXT,
description TEXT,
price float,
slug TEXT UNIQUE);
-- +goose StatementEnd
-- +goose Down
-- +goose StatementBegin
DROP TABLE Product;
-- +goose StatementEnd

@ -0,0 +1,13 @@
-- +goose Up
-- +goose StatementBegin
CREATE TABLE Cart (
id INTEGER PRIMARY KEY,
user_id INTEGER NOT NULL,
product_id INTEGER NOT NULL,
quantity INTEGER);
-- +goose StatementEnd
-- +goose Down
-- +goose StatementBegin
DROP TABLE Cart;
-- +goose StatementEnd

@ -476,6 +476,9 @@
.bg-gray-700 { .bg-gray-700 {
background-color: var(--color-gray-700); background-color: var(--color-gray-700);
} }
.bg-gray-800 {
background-color: var(--color-gray-800);
}
.bg-green-400\! { .bg-green-400\! {
background-color: var(--color-green-400) !important; background-color: var(--color-green-400) !important;
} }
@ -485,6 +488,9 @@
.\!p-4 { .\!p-4 {
padding: calc(var(--spacing) * 4) !important; padding: calc(var(--spacing) * 4) !important;
} }
.\!p-30 {
padding: calc(var(--spacing) * 30) !important;
}
.p-0\! { .p-0\! {
padding: calc(var(--spacing) * 0) !important; padding: calc(var(--spacing) * 0) !important;
} }
@ -500,6 +506,12 @@
.p-6 { .p-6 {
padding: calc(var(--spacing) * 6); padding: calc(var(--spacing) * 6);
} }
.p-10 {
padding: calc(var(--spacing) * 10);
}
.p-30 {
padding: calc(var(--spacing) * 30);
}
.pt-4 { .pt-4 {
padding-top: calc(var(--spacing) * 4); padding-top: calc(var(--spacing) * 4);
} }
@ -537,6 +549,10 @@
font-size: var(--text-2xl); font-size: var(--text-2xl);
line-height: var(--tw-leading, var(--text-2xl--line-height)); line-height: var(--tw-leading, var(--text-2xl--line-height));
} }
.text-lg {
font-size: var(--text-lg);
line-height: var(--tw-leading, var(--text-lg--line-height));
}
.text-sm { .text-sm {
font-size: var(--text-sm); font-size: var(--text-sm);
line-height: var(--tw-leading, var(--text-sm--line-height)); line-height: var(--tw-leading, var(--text-sm--line-height));

Loading…
Cancel
Save