diff --git a/cmd/main.go b/cmd/main.go index bf3e16d..c98a1d7 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -27,6 +27,10 @@ func main() { return c.Redirect(http.StatusMovedPermanently, "/landing_page/") }) + app.GET("/pie_chart", func(c echo.Context) error { + return c.Redirect(http.StatusMovedPermanently, "/pie_chart/") + }) + uStore, err := db.NewUserStore(dbName) if err != nil { app.Logger.Fatalf("failed to create store: %s", err) @@ -54,6 +58,15 @@ func main() { lphs := handlers.NewLandingPageHandler(lps) handlers.SetupRoutesLandingPage(app, lphs) + LpchartStore, err := db.NewPieChartStore(dbName) + if err != nil { + app.Logger.Fatalf("failed to create store: %s", err) + } + + lpchart := services.NewServicesPiechart(services.Piechart{}, LpchartStore) + lphsx := handlers.NewPiechartHandler(lpchart) + handlers.SetupRoutesPieChart(app, lphsx) + app.Logger.Fatal(app.Start(":5000")) } diff --git a/db/chart.store.go b/db/chart.store.go new file mode 100644 index 0000000..904c8e3 --- /dev/null +++ b/db/chart.store.go @@ -0,0 +1,26 @@ +package db + +import ( + "database/sql" + + _ "github.com/glebarez/go-sqlite" +) + +type PieChartStore struct { + Db *sql.DB +} + +func NewPieChartStore(dbName string) (PieChartStore, error) { + Db, err := getConnection(dbName) + if err != nil { + return PieChartStore{}, err + } + + if err := createMigrations(dbName, Db); err != nil { + return PieChartStore{}, err + } + + return PieChartStore{ + Db, + }, nil +} diff --git a/handlers/chart.handlers.go b/handlers/chart.handlers.go new file mode 100644 index 0000000..3a0e382 --- /dev/null +++ b/handlers/chart.handlers.go @@ -0,0 +1,68 @@ +package handlers + +import ( + "crypto/md5" + "encoding/hex" + "encoding/json" + "fmt" + "strings" + "time" + + "github.com/a-h/templ" + "github.com/emarifer/go-templ-project-structure/services" + "github.com/emarifer/go-templ-project-structure/views/piechart" + "github.com/emarifer/go-templ-project-structure/views/xsample" + + "github.com/labstack/echo/v4" +) + +type PiechartService interface { + GetPieChart(string, int) (string, services.Piechart, error) +} + +func NewPiechartHandler(us PiechartService) *PiechartHandler { + return &PiechartHandler{ + PiechartService: us, + } +} + +type PiechartHandler struct { + PiechartService PiechartService +} + +func (uh *PiechartHandler) Hello(c echo.Context) error { + helo := xsample.ShowHelo("Hello World", xsample.HelloWorld("Hello World"), xsample.CssHelo(), xsample.JsHelo()) + return uh.View(c, helo) +} + +func (uh *PiechartHandler) ShowPieChart(c echo.Context) error { + // helo := piechart.MainPieChart("main_001") + var code = "mcu006" + title, udata, err := uh.PiechartService.GetPieChart(code, 1) + if err != nil { + // fmt.Println(err) + return err + } + + jsonData, err := json.MarshalIndent(udata, "", " ") + if err != nil { + fmt.Println("Error:", err) + return err + } + + // randomID := md5.Sum([]byte(title + time.Now().String())) + seed := title + time.Now().String() + hash := md5.Sum([]byte(seed)) + randomID := hex.EncodeToString(hash[:]) + randomID = strings.ReplaceAll(randomID, "-", "") + + // randomID := hex.EncodeToString(md5.Sum([]byte(title + time.Now().String()))) + helo := piechart.ShowPieChart("Chart", piechart.MainPieChart(randomID, string(jsonData)), piechart.CssPieChart(), piechart.JsPieChart()) + return uh.View(c, helo) +} + +func (uh *PiechartHandler) View(c echo.Context, cmp templ.Component) error { + c.Response().Header().Set(echo.HeaderContentType, echo.MIMETextHTML) + + return cmp.Render(c.Request().Context(), c.Response().Writer) +} diff --git a/handlers/landingpage.handlers.go b/handlers/landingpage.handlers.go index f96eafc..84e332a 100644 --- a/handlers/landingpage.handlers.go +++ b/handlers/landingpage.handlers.go @@ -5,7 +5,7 @@ import ( "github.com/a-h/templ" "github.com/emarifer/go-templ-project-structure/services" - landingpage "github.com/emarifer/go-templ-project-structure/views/LandingPage" + landingpage "github.com/emarifer/go-templ-project-structure/views/landingpage" "github.com/labstack/echo/v4" ) diff --git a/handlers/routes.go b/handlers/routes.go index 5196bcf..7a1b452 100644 --- a/handlers/routes.go +++ b/handlers/routes.go @@ -19,6 +19,10 @@ func SetupRoutesLandingPage(app *echo.Echo, h *LandingPageHandler) { Lp := app.Group("/landing_page") Lp.GET("/", h.ShowLandingPage) } +func SetupRoutesPieChart(app *echo.Echo, h *PiechartHandler) { + Lp := app.Group("/pie_chart") + Lp.GET("/", h.ShowPieChart) +} func SetupRoutesProject(app *echo.Echo) { } diff --git a/services/chart.services.go b/services/chart.services.go new file mode 100644 index 0000000..2c0b74b --- /dev/null +++ b/services/chart.services.go @@ -0,0 +1,342 @@ +package services + +import ( + "fmt" + + "github.com/emarifer/go-templ-project-structure/db" +) + +func NewServicesPiechart(u Piechart, uStore db.PieChartStore) *ServicesPiechart { + + return &ServicesPiechart{ + Piechart: u, + PieChartStore: uStore, + } +} + +// type Option struct { +// Title struct { +// Text string +// Left string +// } +// Tooltip struct { +// Trigger string +// } +// Legend struct { +// Top string +// Left string +// Orient string +// } +// Series []Series +// } + +type SeriesData struct { + Value int `json:"value"` + Name string `json:"name"` +} + +type Series struct { + Label struct { + Position string `json:"position"` + Formatter string `json:"formatter"` + } `json:"label"` + Name string `json:"name"` + Type string `json:"type"` + Radius []string `json:"radius"` + ItemStyle struct { + BorderRadius int `json:"borderRadius"` + BorderColor string `json:"borderColor"` + BorderWidth int `json:"borderWidth"` + } `json:"itemStyle"` + Data []SeriesData `json:"data"` + Emphasis struct { + ItemStyle struct { + ShadowBlur int `json:"shadowBlur"` + ShadowOffsetX int `json:"shadowOffsetX"` + ShadowColor string `json:"shadowColor"` + } `json:"itemStyle"` + } `json:"emphasis"` +} + +type Barchart struct { + Title struct { + Text string `json:"text"` + } `json:"title"` + Dataset struct { + Source [][]interface{} `json:"source"` + } `json:"dataset"` + Grid struct { + ContainLabel bool `json:"containLabel"` + } `json:"grid"` + XAxis struct { + Name string `json:"name"` + } `json:"xAxis"` + YAxis struct { + Type string `json:"type"` + } `json:"yAxis"` + VisualMap struct { + Orient string `json:"orient"` + Left string `json:"left"` + Min int `json:"min"` + Max int `json:"max"` + Show bool `json:"show"` + Dimension int `json:"dimension"` + InRange struct { + Color []string `json:"color"` + } `json:"inRange"` + } `json:"visualMap"` + Series []struct { + Label struct { + Position string `json:"position"` + Show bool `json:"show"` + Formatter string `json:"formatter"` + } `json:"label"` + Type string `json:"type"` + Encode struct { + X string `json:"x"` + Y string `json:"y"` + } `json:"encode"` + } `json:"series"` +} + +type Piechart struct { + // ID int `json:"id"` + // Xsamplename string `json:"Xsamplename"` + // Email string `json:"email"` + // CreatedAt time.Time `json:"created_at,omitempty"` + + Title struct { + Text string `json:"text"` + Left string `json:"left"` + } `json:"title"` + Tooltip struct { + Trigger string `json:"trigger"` + } `json:"tooltip"` + Legend struct { + Top string `json:"top"` + Left string `json:"left"` + Orient string `json:"orient"` + } `json:"legend"` + Series []Series `json:"series"` +} + +type ServicesPiechart struct { + Piechart Piechart + PieChartStore db.PieChartStore +} + +// func (su *ServicesPiechart) GetAllXsamples() ([]Piechart, error) { +// query := `SELECT id, Xsamplename, email, created_at FROM Xsamples ORDER BY created_at DESC` + +// rows, err := su.PieChartStore.Db.Query(query) +// if err != nil { +// return []Piechart{}, err +// } +// // We close the resource +// defer rows.Close() + +// Xsamples := []Piechart{} +// for rows.Next() { +// rows.Scan( +// &su.Piechart.ID, +// &su.Piechart.Xsamplename, +// &su.Piechart.Email, +// &su.Piechart.CreatedAt, +// ) + +// Xsamples = append(Xsamples, su.Piechart) +// } + +// return Xsamples, nil +// } + +// func (su *ServicesPiechart) GetXsampleById(id int) (Piechart, error) { + +// query := `SELECT id, Xsamplename, email, created_at FROM Xsamples +// WHERE id = ?` + +// stmt, err := su.PieChartStore.Db.Prepare(query) +// if err != nil { +// return Piechart{}, err +// } + +// defer stmt.Close() + +// su.Piechart.ID = id +// err = stmt.QueryRow( +// su.Piechart.ID, +// ).Scan( +// &su.Piechart.ID, +// &su.Piechart.Xsamplename, +// &su.Piechart.Email, +// &su.Piechart.CreatedAt, +// ) +// if err != nil { +// return Piechart{}, err +// } + +// return su.Piechart, nil +// } + +// Peserta MCU -- MCU001 +func GetPieChartMcu001(code string, id int) (string, Piechart, error) { + var title = "Status Index Masa Tubuh (BMI)" + option := Piechart{ + Title: struct { + Text string `json:"text"` + Left string `json:"left"` + }{ + Text: title, + Left: "center", + }, + Tooltip: struct { + Trigger string `json:"trigger"` + }{ + Trigger: "item", + }, + Legend: struct { + Top string `json:"top"` + Left string `json:"left"` + Orient string `json:"orient"` + }{ + Top: "bottom", + Left: "center", + Orient: "vertical", + }, + Series: []Series{ + { + Label: struct { + Position string `json:"position"` + Formatter string `json:"formatter"` + }{ + Position: "inner", + Formatter: "{d}%", + }, + Name: "Access From", + Type: "pie", + Radius: []string{"20%", "50%"}, + ItemStyle: struct { + BorderRadius int `json:"borderRadius"` + BorderColor string `json:"borderColor"` + BorderWidth int `json:"borderWidth"` + }{ + BorderRadius: 10, + BorderColor: "#fff", + BorderWidth: 2, + }, + Data: []SeriesData{ + {Value: 506, Name: "Sudah MCU : 506 Peserta"}, + {Value: 54, Name: "Belum MCU : 54 Peserta"}, + }, + Emphasis: struct { + ItemStyle struct { + ShadowBlur int `json:"shadowBlur"` + ShadowOffsetX int `json:"shadowOffsetX"` + ShadowColor string `json:"shadowColor"` + } `json:"itemStyle"` + }{ + ItemStyle: struct { + ShadowBlur int `json:"shadowBlur"` + ShadowOffsetX int `json:"shadowOffsetX"` + ShadowColor string `json:"shadowColor"` + }{ + ShadowBlur: 10, + ShadowOffsetX: 0, + ShadowColor: "rgba(0, 0, 0, 0.5)", + }, + }, + }, + }, + } + return title, option, nil +} + +// Kepersertaan MCU Berdasarkan Jenis Kelamin -- MCU002 + +// Status Index Masa Tubuh (BMI) -- MCU006 +func GetPieChartMcu006(code string, id int) (string, Piechart, error) { + var title = "Status Index Masa Tubuh (BMI)" + option := Piechart{ + Title: struct { + Text string `json:"text"` + Left string `json:"left"` + }{ + Text: title, + Left: "center", + }, + Tooltip: struct { + Trigger string `json:"trigger"` + }{ + Trigger: "item", + }, + Legend: struct { + Top string `json:"top"` + Left string `json:"left"` + Orient string `json:"orient"` + }{ + Top: "bottom", + Left: "center", + Orient: "vertical", + }, + Series: []Series{ + { + Label: struct { + Position string `json:"position"` + Formatter string `json:"formatter"` + }{ + Position: "inner", + Formatter: "{d}%", + }, + Name: "Access From", + Type: "pie", + Radius: []string{"20%", "50%"}, + ItemStyle: struct { + BorderRadius int `json:"borderRadius"` + BorderColor string `json:"borderColor"` + BorderWidth int `json:"borderWidth"` + }{ + BorderRadius: 10, + BorderColor: "#fff", + BorderWidth: 2, + }, + Data: []SeriesData{ + {Value: 19, Name: "Underweight : 19 Peserta"}, + {Value: 104, Name: "Normal : 104 Peserta"}, + {Value: 230, Name: "Obese 1 : 230 Peserta"}, + {Value: 99, Name: "Obese 2 : 99 Peserta"}, + }, + Emphasis: struct { + ItemStyle struct { + ShadowBlur int `json:"shadowBlur"` + ShadowOffsetX int `json:"shadowOffsetX"` + ShadowColor string `json:"shadowColor"` + } `json:"itemStyle"` + }{ + ItemStyle: struct { + ShadowBlur int `json:"shadowBlur"` + ShadowOffsetX int `json:"shadowOffsetX"` + ShadowColor string `json:"shadowColor"` + }{ + ShadowBlur: 10, + ShadowOffsetX: 0, + ShadowColor: "rgba(0, 0, 0, 0.5)", + }, + }, + }, + }, + } + + return title, option, nil +} + +func (su *ServicesPiechart) GetPieChart(code string, id int) (string, Piechart, error) { + if code == "mcu001" { + return GetPieChartMcu001(code, id) + } + + if code == "mcu006" { + return GetPieChartMcu006(code, id) + } + + return "", Piechart{}, fmt.Errorf("code " + code + " not found") +} diff --git a/views/component/chart/chart.templ b/views/component/chart/chart.templ new file mode 100644 index 0000000..2776c4e --- /dev/null +++ b/views/component/chart/chart.templ @@ -0,0 +1,30 @@ +package chart + +templ ShowChart(idDiv string, udata string) { +
+ @GenerateChart(idDiv, udata) +} + +script GenerateChart(idDiv string, udata string) { + htmx.onLoad(function(elt) { + console.log("elt ",elt) + var element = document.getElementById(idDiv); + console.log("element ",element) + if (element) { + element.style.height = "400px"; + element.style.width = "100%"; + } + + var myChart = {}; + var option = {}; + + // var myChart_001 = echarts.init(document.getElementById(idDiv)); + myChart[idDiv] = echarts.init(element); + + // var option_001 = JSON.parse(udata); + option[idDiv] = JSON.parse(udata); + console.log("option ", option) + // myChart_001.setOption(option_001); + myChart[idDiv].setOption(option[idDiv]); + }); +} \ No newline at end of file diff --git a/views/component/chart/chart_templ.go b/views/component/chart/chart_templ.go new file mode 100644 index 0000000..8c688c0 --- /dev/null +++ b/views/component/chart/chart_templ.go @@ -0,0 +1,82 @@ +// Code generated by templ - DO NOT EDIT. + +// templ: version: v0.2.663 +package chart + +//lint:file-ignore SA4006 This context is only used if a nested component is present. + +import "github.com/a-h/templ" +import "context" +import "io" +import "bytes" + +func ShowChart(idDiv string, udata string) templ.Component { + return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) + if !templ_7745c5c3_IsBuffer { + templ_7745c5c3_Buffer = templ.GetBuffer() + defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var1 := templ.GetChildren(ctx) + if templ_7745c5c3_Var1 == nil { + templ_7745c5c3_Var1 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = GenerateChart(idDiv, udata).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if !templ_7745c5c3_IsBuffer { + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) + } + return templ_7745c5c3_Err + }) +} + +func GenerateChart(idDiv string, udata string) templ.ComponentScript { + return templ.ComponentScript{ + Name: `__templ_GenerateChart_4c73`, + Function: `function __templ_GenerateChart_4c73(idDiv, udata){htmx.onLoad(function(elt) { + console.log("elt ",elt) + var element = document.getElementById(idDiv); + console.log("element ",element) + if (element) { + element.style.height = "400px"; + element.style.width = "100%"; + } + + var myChart = {}; + var option = {}; + + // var myChart_001 = echarts.init(document.getElementById(idDiv)); + myChart[idDiv] = echarts.init(element); + + // var option_001 = JSON.parse(udata); + option[idDiv] = JSON.parse(udata); + console.log("option ", option) + // myChart_001.setOption(option_001); + myChart[idDiv].setOption(option[idDiv]); + }); +}`, + Call: templ.SafeScript(`__templ_GenerateChart_4c73`, idDiv, udata), + CallInline: templ.SafeScriptInline(`__templ_GenerateChart_4c73`, idDiv, udata), + } +} diff --git a/views/layout/playground_layout.templ b/views/layout/playground_layout.templ index 831444e..b5c96bb 100644 --- a/views/layout/playground_layout.templ +++ b/views/layout/playground_layout.templ @@ -92,6 +92,8 @@ templ PlaygroundLayout(title string, css templ.Component, js templ.Component) { id="kt_body" class="header-fixed header-mobile-fixed subheader-enabled subheader-fixed subheader-mobile-fixed aside-enabled aside-fixed aside-minimize-hoverable page-loading" > + // htmx + { children... } @@ -166,12 +168,7 @@ templ PlaygroundLayout(title string, css templ.Component, js templ.Component) { - + @js ") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/views/mcu/peserta/bagian.txt b/views/mcu/peserta/bagian.txt new file mode 100644 index 0000000..e69de29 diff --git a/views/piechart/piechart.templ b/views/piechart/piechart.templ new file mode 100644 index 0000000..0330396 --- /dev/null +++ b/views/piechart/piechart.templ @@ -0,0 +1,59 @@ +package piechart + +import ( + "github.com/emarifer/go-templ-project-structure/views/layout" + chart "github.com/emarifer/go-templ-project-structure/views/component/chart" +) + +templ MainPieChart(idDiv string, udata string) { + +Data Kepesertaan MCU
+Data Kepesertaan MCU