/ plan.go
plan.go
  1  package main
  2  
  3  import (
  4  	"encoding/json"
  5  	"log"
  6  	"strconv"
  7  
  8  	"github.com/google/uuid"
  9  	"github.com/maxence-charriere/go-app/v10/pkg/app"
 10  	shell "github.com/stateless-minds/go-ipfs-api"
 11  )
 12  
 13  const dbPlan = "plan"
 14  
 15  // plan is a component that holds cyber-gubi. A component is a
 16  // customizable, independent, and reusable UI element. It is created by
 17  // embedding app.Compo into a struct.
 18  type plan struct {
 19  	app.Compo
 20  	sh           *shell.Shell
 21  	loggedIn     bool
 22  	userID       string
 23  	businessName string
 24  	price        int
 25  	plan         Plan
 26  }
 27  
 28  type Plan struct {
 29  	ID        string `mapstructure:"_id" json:"_id" validate:"uuid_rfc4122"`               // Unique identifier for the transaction
 30  	Name      string `mapstructure:"name" json:"name" validate:"uuid_rfc4122"`             // Business name
 31  	Price     int    `mapstructure:"price" json:"price" validate:"uuid_rfc4122"`           // Monthly recurring price
 32  	CreatedBy string `mapstructure:"created_by" json:"created_by" validate:"uuid_rfc4122"` // User ID of business who created it
 33  }
 34  
 35  func (p *plan) OnMount(ctx app.Context) {
 36  	sh := shell.NewShell("localhost:5001")
 37  	p.sh = sh
 38  
 39  	ctx.GetState("loggedIn", &p.loggedIn)
 40  	if !p.loggedIn {
 41  		ctx.Navigate("/auth")
 42  	}
 43  
 44  	ctx.GetState("userID", &p.userID)
 45  
 46  	ctx.ObserveState("plan", &p.plan)
 47  
 48  	ctx.ObserveState("businessName", &p.businessName)
 49  }
 50  
 51  func (p *plan) createPlan(ctx app.Context, e app.Event) {
 52  	e.PreventDefault()
 53  	valid := app.Window().GetElementByID("plan-form").Call("reportValidity").Bool()
 54  	if valid {
 55  		p.storePLan(ctx)
 56  	}
 57  }
 58  
 59  func (p *plan) storePLan(ctx app.Context) {
 60  	ctx.Async(func() {
 61  		var plan Plan
 62  		if (p.plan == Plan{}) {
 63  			plan = Plan{
 64  				ID:        uuid.NewString(),
 65  				Name:      p.businessName,
 66  				Price:     p.price * 100,
 67  				CreatedBy: p.userID,
 68  			}
 69  		} else {
 70  			plan = Plan{
 71  				ID:        p.plan.ID,
 72  				Name:      p.businessName,
 73  				Price:     p.price * 100,
 74  				CreatedBy: p.plan.CreatedBy,
 75  			}
 76  		}
 77  
 78  		planJSON, err := json.Marshal(plan)
 79  		if err != nil {
 80  			log.Fatal(err)
 81  		}
 82  
 83  		err = p.sh.OrbitDocsPut(dbPlan, planJSON)
 84  		if err != nil {
 85  			log.Fatal(err)
 86  		}
 87  
 88  		ctx.Dispatch(func(ctx app.Context) {
 89  			if (p.plan == Plan{}) {
 90  				ctx.Notifications().New(app.Notification{
 91  					Title: "Success",
 92  					Body:  "Plan created successfully!",
 93  				})
 94  			} else {
 95  				ctx.Notifications().New(app.Notification{
 96  					Title: "Success",
 97  					Body:  "Plan updated successfully!",
 98  				})
 99  			}
100  			ctx.Navigate("/wallet")
101  		})
102  	})
103  }
104  
105  // The Render method is where the component appearance is defined. Here, a
106  // create plan form is displayed.
107  func (p *plan) Render() app.UI {
108  	return app.Div().Class("container").Body(
109  		app.Div().Class("mobile").Body(
110  			app.Div().Class("header").Body(
111  				newNav(),
112  				app.Div().Class("header-summary").Body(
113  					app.Span().Class("logo").Text("cyber-gubi"),
114  					app.Div().Class("summary-text").Body(
115  						app.Span().Text("Plan"),
116  					),
117  				),
118  			),
119  			app.Div().ID("content").Body(
120  				app.Div().Class("card").Body(
121  					app.Div().Class("upper-row").Body(
122  						app.Div().Class("card-item").Body(
123  							app.If(p.plan == Plan{}, func() app.UI {
124  								return app.Span().Class("span-header").Text("Create Plan")
125  							}).Else(func() app.UI {
126  								return app.Span().Class("span-header").Text("Update Plan")
127  							}),
128  							app.Form().ID("plan-form").Body(
129  								app.Div().ID("plan").Body(
130  									app.If(p.plan == Plan{}, func() app.UI {
131  										return app.Div().Body(
132  											app.Input().ID("plan-price").Class("product").Type("number").Min(1).Name("plan-price").Placeholder("Monthly amount").Required(true).OnChange(p.ValueTo(&p.price)),
133  										)
134  									}).Else(func() app.UI {
135  										return app.Div().Body(
136  											app.Input().ID("plan-price").Class("product").Type("number").Min(1).Name("plan-price").Placeholder(strconv.Itoa(p.plan.Price / 100)).Required(true).OnChange(p.ValueTo(&p.price)),
137  										)
138  									}),
139  								),
140  								app.Div().Class("drawer drawer-pay").Body(
141  									app.Div().Class("menu-btn").Body(
142  										app.Button().Class("submit").Type("submit").Text("Submit").OnClick(p.createPlan),
143  									),
144  								),
145  							),
146  						),
147  					),
148  				),
149  			),
150  		),
151  	)
152  }