﻿B4J=true
Group=Handlers
ModulesStructureVersion=1
Type=Class
Version=10.3
@EndOfDesignText@
' Categories Handler class
' Version 6.00beta
Sub Class_Globals
	Private DB As MiniORM
	Private App As EndsMeet
	Private KVS As KeyValueStore
	Private Method As String
	Private Request As ServletRequest
	Private Response As ServletResponse
End Sub

Public Sub Initialize
	App = Main.App
	KVS = Main.KVS
	DB.Initialize(Main.DBType, Null)
End Sub

Sub Handle (req As ServletRequest, resp As ServletResponse)
	Request = req
	Response = resp
	Method = req.Method
	Log($"${Request.Method}: ${Request.RequestURI}"$)
	Dim path As String = req.RequestURI
	If path = "/categories" Then
		RenderPage
	Else If path = "/api/categories/table" Then
		HandleTable
	Else If path = "/api/categories/add" Then
		HandleAddModal
	Else If path.StartsWith("/api/categories/edit/") Then
		HandleEditModal
	Else If path.StartsWith("/api/categories/delete/") Then
		HandleDeleteModal
	Else
		HandleCategories
	End If
End Sub

Private Sub RenderPage
	If KVS.ContainsKey("/categories") = False Then
		Dim main1 As MainView
		main1.Initialize
		main1.LoadContent(ContentContainer)
		main1.LoadModal(ModalContainer)
		main1.LoadToast(ToastContainer)
	
		Dim page1 As Tag = main1.Render
		Dim doc As Document
		doc.Initialize
		doc.AppendDocType
		doc.Append(page1.build)

		' Store for reuse
		KVS.Put("/categories", App.ReplaceMap(doc.ToString, App.ctx))
	End If
	App.WriteHtml(Response, KVS.Get("/categories"))
End Sub

Private Sub ContentContainer As Tag
	Dim content1 As Tag = Div.cls("row mt-3 text-center align-items-center justify-content-center")
	Dim col1 As Tag = Div.cls("col-md-12 col-lg-6").up(content1)
	Dim form1 As Tag = Form.cls("form mb-3").action("").up(col1)
	Dim row1 As Tag = Div.cls("row").up(form1)
	Dim col2 As Tag = Div.cls("col-md-6 col-lg-6 text-start").up(row1)
	H3.text("CATEGORY LIST").up(col2)
	Dim div1 As Tag = Div.cls("col-md-6 col-lg-6").up(row1)
	Dim div2 As Tag = Div.cls("text-end mt-2").up(div1)
	
	Dim anchor1 As Tag = Anchor.up(div2)
	anchor1.hrefOf("$SERVER_URL$")
	anchor1.cls("btn btn-primary me-2")
	anchor1.add(Icon.cls("bi bi-house me-2"))
	anchor1.text("Home")

	Dim button2 As Tag = Button.up(div2)
	button2.cls("btn btn-success ml-2")
	button2.hxGet("/api/categories/add")
	button2.hxTarget("#modal-content")
	button2.hxTrigger("click")
	button2.data("bs-toggle", "modal")
	button2.data("bs-target", "#modal-container")
	button2.add(Icon.cls("bi bi-plus-lg me-2"))
	button2.text("Add Category")

	Dim container1 As Tag = Div.up(col1)
	container1.id("categories-container")
	container1.hxGet("/api/categories/table")
	container1.hxTrigger("load")
	container1.text("Loading...")

	Return content1
End Sub

Private Sub ModalContainer As Tag
	Dim modal1 As Tag = Div.id("modal-container")
	modal1.cls("modal fade")
	modal1.attr("tabindex", "-1")
	modal1.aria("hidden", "true")
	Dim modalDialog As Tag = Div.up(modal1).cls("modal-dialog modal-dialog-centered")
	Div.cls("modal-content").id("modal-content").up(modalDialog)
	Return modal1
End Sub

Private Sub ToastContainer As Tag
	Dim div1 As Tag = Div.cls("position-fixed end-0 p-3")
	div1.sty("z-index: 2000")
	div1.sty("bottom: 0%")
	Dim toast1 As Tag = Div.id("toast-container").up(div1)
	toast1.cls("toast align-items-center text-bg-success border-0")
	toast1.attr("role", "alert")
	Dim div2 As Tag = Div.cls("d-flex").up(toast1)
	Dim div3 As Tag = Div.cls("toast-body").id("toast-body").up(div2)
	div3.text("Operation successful!")
	Dim button1 As Tag = Button.typeOf("button").up(div2)
	button1.cls("btn-close btn-close-white me-2 m-auto")
	button1.data("bs-dismiss", "toast")
	Return div1
End Sub

' Return table HTML
Private Sub HandleTable
	'Dim s As String = GenerateCategoriesTable.Build
	'File.WriteString(File.DirApp, "table.html", s)
	App.WriteHtml(Response, GenerateCategoriesTable.Build)
End Sub

' Add modal
Private Sub HandleAddModal
	Dim form1 As Tag = Form.init
	form1.hxPost("/api/categories")
	form1.hxTarget("#modal-messages")
	form1.hxSwap("innerHTML")
	
	Dim modalHeader As Tag = Div.cls("modal-header").up(form1)
	H5.cls("modal-title").text("Add Category").up(modalHeader)
	Button.typeOf("button").cls("btn-close").data("bs-dismiss", "modal").up(modalHeader)

	Dim modalBody As Tag = Div.cls("modal-body").up(form1)
	Div.id("modal-messages").up(modalBody)'.hxSwapOob("true")
	
	Dim group1 As Tag = modalBody.add(Div.cls("form-group"))
	Label.forId("name").text("Name ").up(group1).add(Span.cls("text-danger").text("*"))
	Input.typeOf("text").up(group1).id("name").name("name").cls("form-control").attr3("required")

	Dim modalFooter As Tag = Div.cls("modal-footer").up(form1)
	Button.typeOf("submit").cls("btn btn-success px-3").text("Create").up(modalFooter)
	Button.typeOf("button").cls("btn btn-secondary px-3").data("bs-dismiss", "modal").text("Cancel").up(modalFooter)

	App.WriteHtml(Response, form1.Build)
End Sub

' Edit modal
Private Sub HandleEditModal
	Dim id As String = Request.RequestURI.SubString("/api/categories/edit/".Length)
	Dim form1 As Tag = Form.init
	form1.hxPut($"/api/categories"$)
	form1.hxTarget("#modal-messages")
	form1.hxSwap("innerHTML")
		
	DB.SQL = Main.DBOpen
	DB.Table = "tbl_categories"
	DB.Columns = Array("id", "category_name AS name")
	DB.WhereParam("id = ?", id)
	DB.Query
	If DB.Found Then
		Dim name As String = DB.First.Get("name")

		Dim modalHeader As Tag = Div.cls("modal-header").up(form1)
		H5.cls("modal-title").text("Edit Category").up(modalHeader)
		Button.typeOf("button").cls("btn-close").data("bs-dismiss", "modal").up(modalHeader)
		
		Dim modalBody As Tag = Div.cls("modal-body").up(form1)
		Div.id("modal-messages").up(modalBody)
		Input.typeOf("hidden").up(modalBody).name("id").valueOf(id)
		
		Dim group1 As Tag = Div.cls("form-group").up(modalBody)
		Label.forId("name").text("Name ").up(group1).add(Span.cls("text-danger").text("*"))
		Input.typeOf("text").cls("form-control").id("name").name("name").valueOf(name).attr3("required").up(group1)

		Dim modalFooter As Tag = Div.cls("modal-footer").up(form1)
		Button.typeOf("submit").cls("btn btn-primary px-3").text("Update").up(modalFooter)
		Button.typeOf("button").cls("btn btn-secondary px-3").data("bs-dismiss", "modal").text("Cancel").up(modalFooter)
	End If
	DB.Close

	App.WriteHtml(Response, form1.Build)
End Sub

' Delete modal
Private Sub HandleDeleteModal
	Dim id As String = Request.RequestURI.SubString("/api/categories/delete/".Length)
	Dim form1 As Tag = Form.init
	form1.hxDelete($"/api/categories"$)
	form1.hxTarget("#modal-messages")
	form1.hxSwap("innerHTML")

	DB.SQL = Main.DBOpen
	DB.Table = "tbl_categories"
	DB.Columns = Array("id", "category_name AS name")
	DB.WhereParam("id = ?", id)
	DB.Query
	If DB.Found Then
		Dim name As String = DB.First.Get("name")

		Dim modalHeader As Tag = Div.cls("modal-header").up(form1)
		H5.cls("modal-title").text("Delete Category").up(modalHeader)
		Button.typeOf("button").cls("btn-close").data("bs-dismiss", "modal").up(modalHeader)
		
		Dim modalBody As Tag = Div.cls("modal-body").up(form1)
		Div.id("modal-messages").up(modalBody)
		Input.typeOf("hidden").name("id").valueOf(id).up(modalBody)
		Paragraph.text($"Delete ${name}?"$).up(modalBody)

		Dim modalFooter As Tag = Div.cls("modal-footer").up(form1)
		Button.typeOf("submit").cls("btn btn-danger px-3").text("Delete").up(modalFooter)
		Button.typeOf("button").cls("btn btn-secondary px-3").data("bs-dismiss", "modal").text("Cancel").up(modalFooter)
	End If
	DB.Close

	App.WriteHtml(Response, form1.Build)
End Sub

' Handle CRUD operations
Private Sub HandleCategories
	Select Method
		Case "POST"
			' Create
			Dim name As String = Request.GetParameter("name")
			If name = "" Or name.Trim.Length < 2 Then
				ShowAlert("Category name must be at least 2 characters long.", "warning")
				Return
			End If
			Try
				DB.SQL = Main.DBOpen
				DB.Table = "tbl_categories"
				DB.Where = Array("category_name = ?")
				DB.Parameters = Array(name)
				DB.Query
				If DB.Found Then
					DB.Close
					ShowAlert("Category already exists!", "warning")
					Return
				End If
			Catch
				Log(LastException)
				ShowAlert($"Database error: ${LastException.Message}"$, "danger")
			End Try

			' Insert new row
			Try
				DB.Reset
				DB.Columns = Array("category_name", "created_date")
				DB.Parameters = Array(name, Main.CurrentDateTime)
				DB.Save
				DB.Close
				ShowToast("Category", "created", "Category created successfully!", "success")
			Catch
				ShowAlert($"Database error: ${LastException.Message}"$, "danger")
			End Try
		Case "PUT"
			' Update
			Dim id As Int = Request.GetParameter("id")
			Dim name As String = Request.GetParameter("name")
			DB.SQL = Main.DBOpen
			DB.Table = "tbl_categories"
			
			DB.Find(id)
			If DB.Found = False Then
				ShowAlert("Category not found!", "warning")
				DB.Close
				Return
			End If

			DB.Reset
			DB.Where = Array("category_name = ?", "id <> ?")
			DB.Parameters = Array(name, id)
			DB.Query
			If DB.Found Then
				ShowAlert("Category already exists!", "warning")
				DB.Close
				Return
			End If
			
			' Update row
			Try
				DB.Reset
				DB.Columns = Array("category_name", "modified_date")
				DB.Parameters = Array(name, Main.CurrentDateTime)
				DB.Id = id
				DB.Save
				DB.Close
				ShowToast("Category", "updated", "Category updated successfully!", "info")
			Catch
				ShowAlert($"Database error: ${LastException.Message}"$, "danger")
			End Try
		Case "DELETE"
			' Delete
			Dim id As Int = Request.GetParameter("id")
			DB.SQL = Main.DBOpen
			DB.Table = "tbl_categories"
			
			DB.Find(id)
			If DB.Found = False Then
				ShowAlert("Category not found!", "warning")
				DB.Close
				Return
			End If
			
			DB.Table = "tbl_products"
			DB.WhereParam("category_id = ?", id)
			DB.Query
			If DB.Found Then
				ShowAlert("Cannot delete category with associated products!", "warning")
				DB.Close
				Return
			End If

			' Delete row
			Try
				DB.Table = "tbl_categories"
				DB.Id = id
				DB.Delete
				DB.Close
				ShowToast("Category", "deleted", "Category deleted successfully!", "danger")
			Catch
				ShowAlert($"Database error: ${LastException.Message}"$, "danger")
			End Try
	End Select
End Sub

Private Sub GenerateCategoriesTable As Tag
	'KVS.Remove("/categories/table")
	'KVS.Remove("/categories/table/row")
	'Avoid using KVS for small components
	'If KVS.ContainsKey("/categories/table") Then
	'	Dim table1 As Tag = Html.Parse(KVS.Get("/categories/table"))
	'	Dim tbody1 As Tag = table1.Child(1)
	'Else
		Dim table1 As Tag = HtmlTable.cls("table table-bordered table-hover rounded small")
		Dim thead1 As Tag = Thead.cls("table-light").up(table1)
		thead1.add(Th.sty("text-align: right; width: 50px").text("#"))
		thead1.add(Th.text("Name"))
		thead1.add(Th.sty("text-align: center; width: 120px").text("Actions"))
		Dim tbody1 As Tag = Tbody.init.up(table1)
		
	'	' Store for reuse
	'	KVS.Put("/categories/table", table1.Build)
	'End If

	'Avoid using KVS for small components
	'If KVS.ContainsKey("/categories/table/row") = False Then
	'	Dim tr1 As Tag = Tr.init
	'	Td.cls("align-middle").sty("text-align: right").up(tr1)
	'	Td.cls("align-middle").up(tr1)
	'	Dim td1 As Tag = Td.cls("align-middle text-center px-1 py-1").up(tr1)
	'	
	'	Dim anchor1 As Tag = Anchor.cls("edit text-primary mx-2").up(td1)
	'	anchor1.hxGet("")
	'	anchor1.hxTarget("#modal-content")
	'	anchor1.hxTrigger("click")
	'	anchor1.data("bs-toggle", "modal")
	'	anchor1.data("bs-target", "#modal-container")
	'	anchor1.add(Icon.cls("bi bi-pencil"))
	'	anchor1.attr("title", "Edit")
	'	
	'	Dim anchor2 As Tag = Anchor.cls("delete text-danger mx-2").up(td1)
	'	anchor2.hxGet("")
	'	anchor2.hxTarget("#modal-content")
	'	anchor2.hxTrigger("click")
	'	anchor2.data("bs-toggle", "modal")
	'	anchor2.data("bs-target", "#modal-container")
	'	anchor2.add(Icon.cls("bi bi-trash3"))
	'	anchor2.attr("title", "Delete")
	'	
	'	' Store for reuse
	'	KVS.Put("/categories/table/row", tr1.Build)
	'End If
	
	DB.SQL = Main.DBOpen
	DB.Table = "tbl_categories"
	DB.Columns = Array("id", "category_name AS name")
	DB.OrderBy = CreateMap("id": "")
	DB.Query
	For Each row As Map In DB.Results
		Dim id As Int = row.Get("id")
		Dim name As String = row.Get("name")
		
		'Avoid using KVS for small components
		'Dim tr1 As Tag = Html.Parse(KVS.Get("/categories/table/row"))
		
		'Dim td1 As Tag = tr1.Child(0)
		'td1.text(id)
		
		'Dim td2 As Tag = tr1.Child(1)
		'td2.text(name)
		
		'Dim td3 As Tag = tr1.Child(2)
		
		'Dim anchor1 As Tag = td3.Child(0)
		'anchor1.hxGet($"/api/categories/edit/${id}"$)
		
		'Dim anchor2 As Tag = td3.Child(1)
		'anchor2.hxGet($"/api/categories/delete/${id}"$)

		Dim tr1 As Tag = Tr.init
		
		Dim td1 As Tag = Td.cls("align-middle").sty("text-align: right").up(tr1)
		td1.text(id)
		
		Dim td2 As Tag = Td.cls("align-middle").up(tr1)
		td2.text(name)
		
		Dim td3 As Tag = Td.cls("align-middle text-center px-1 py-1").up(tr1)
		
		Dim anchor1 As Tag = Anchor.cls("edit text-primary mx-2").up(td3)
		anchor1.hxGet($"/api/categories/edit/${id}"$)
		anchor1.hxTarget("#modal-content")
		anchor1.hxTrigger("click")
		anchor1.data("bs-toggle", "modal")
		anchor1.data("bs-target", "#modal-container")
		anchor1.add(Icon.cls("bi bi-pencil"))
		anchor1.attr("title", "Edit")
		
		Dim anchor2 As Tag = Anchor.cls("delete text-danger mx-2").up(td3)
		anchor2.hxGet($"/api/categories/delete/${id}"$)
		anchor2.hxTarget("#modal-content")
		anchor2.hxTrigger("click")
		anchor2.data("bs-toggle", "modal")
		anchor2.data("bs-target", "#modal-container")
		anchor2.add(Icon.cls("bi bi-trash3"))
		anchor2.attr("title", "Delete")

		tbody1.add(tr1)
	Next
	DB.Close
	Return table1
End Sub

Private Sub ShowAlert (message As String, status As String)
	Dim div1 As Tag = Div.cls("alert alert-" & status).text(message)
	App.WriteHtml(Response, div1.Build)
End Sub

Private Sub ShowToast (entity As String, action As String, message As String, status As String)
	Dim div1 As Tag = Div.id("categories-container")
	div1.hxSwapOob("true")
	div1.add(GenerateCategoriesTable)

	Dim script1 As MiniJs
	script1.Initialize
	script1.AddCustomEventDispatch("entity:changed", _
	CreateMap( _
	"entity": entity, _
	"action": action, _
	"message": message, _
	"status": status))

	App.WriteHtml(Response, div1.Build & CRLF & script1.Generate)
End Sub