42 changed files with 1383 additions and 546 deletions
@ -0,0 +1,48 @@ |
|||||
|
package api |
||||
|
|
||||
|
import ( |
||||
|
"encoding/json" |
||||
|
"fmt" |
||||
|
"io" |
||||
|
"regexp" |
||||
|
) |
||||
|
|
||||
|
func (s *Session) GetInvoice(identifier string) (map[string]interface{}, error) { |
||||
|
var endpoint string |
||||
|
|
||||
|
isInvoiceNumber, _ := regexp.MatchString(`^[A-Za-z]`, identifier) |
||||
|
|
||||
|
if isInvoiceNumber { |
||||
|
endpoint = fmt.Sprintf("/invoice?invoiceNumber=%s", identifier) |
||||
|
} else { |
||||
|
endpoint = fmt.Sprintf("/invoice/%s", identifier) |
||||
|
} |
||||
|
|
||||
|
resp, err := s.DoRequest("GET", endpoint, nil) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
defer resp.Body.Close() |
||||
|
|
||||
|
body, _ := io.ReadAll(resp.Body) |
||||
|
if resp.StatusCode != 200 { |
||||
|
return nil, fmt.Errorf("failed to get invoice info: %s, response: %s", resp.Status, string(body)) |
||||
|
} |
||||
|
|
||||
|
var result map[string]interface{} |
||||
|
if err := json.Unmarshal(body, &result); err != nil { |
||||
|
return nil, fmt.Errorf("error unmarshalling response: %v", err) |
||||
|
} |
||||
|
|
||||
|
if data, ok := result["data"].(map[string]interface{}); ok { |
||||
|
if invoices, ok := data["invoices"].([]interface{}); ok && len(invoices) > 0 { |
||||
|
if invoice, ok := invoices[0].(map[string]interface{}); ok { |
||||
|
return invoice, nil |
||||
|
} |
||||
|
} else { |
||||
|
return data, nil |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return nil, fmt.Errorf("no invoice found in the response") |
||||
|
} |
||||
@ -0,0 +1,63 @@ |
|||||
|
package api |
||||
|
|
||||
|
import ( |
||||
|
"encoding/json" |
||||
|
"fmt" |
||||
|
"io" |
||||
|
) |
||||
|
|
||||
|
func (s *Session) GetAttachmentsForJob(jobID string) (map[string]interface{}, error) { |
||||
|
resp, err := s.DoRequest("GET", fmt.Sprintf("/job/%s/paperwork", jobID), nil) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
defer resp.Body.Close() |
||||
|
|
||||
|
body, _ := io.ReadAll(resp.Body) |
||||
|
if resp.StatusCode != 200 { |
||||
|
return nil, fmt.Errorf("failed to get attachments: %s, response: %s", resp.Status, string(body)) |
||||
|
} |
||||
|
|
||||
|
var result map[string]interface{} |
||||
|
if err := json.Unmarshal(body, &result); err != nil { |
||||
|
return nil, fmt.Errorf("error unmarshalling response: %v", err) |
||||
|
} |
||||
|
return result, nil |
||||
|
} |
||||
|
|
||||
|
func (s *Session) DeleteAttachment(attachmentID string) error { |
||||
|
resp, err := s.DoRequest("DELETE", fmt.Sprintf("/attachment/%s", attachmentID), nil) |
||||
|
if err != nil { |
||||
|
return err |
||||
|
} |
||||
|
defer resp.Body.Close() |
||||
|
|
||||
|
if resp.StatusCode != 200 && resp.StatusCode != 204 { |
||||
|
body, _ := io.ReadAll(resp.Body) |
||||
|
return fmt.Errorf("failed to delete attachment: %s, response: %s", resp.Status, string(body)) |
||||
|
} |
||||
|
|
||||
|
return nil |
||||
|
} |
||||
|
|
||||
|
func (s *Session) GetDeficiencyInfoForJob(jobID string) ([]map[string]interface{}, error) { |
||||
|
resp, err := s.DoRequest("GET", fmt.Sprintf("/deficiency/%s", jobID), nil) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
defer resp.Body.Close() |
||||
|
|
||||
|
body, _ := io.ReadAll(resp.Body) |
||||
|
if resp.StatusCode != 200 { |
||||
|
return nil, fmt.Errorf("failed to get deficiency info: %s, response: %s", resp.Status, string(body)) |
||||
|
} |
||||
|
|
||||
|
var result struct { |
||||
|
Data []map[string]interface{} `json:"data"` |
||||
|
} |
||||
|
if err := json.Unmarshal(body, &result); err != nil { |
||||
|
return nil, fmt.Errorf("error unmarshalling response: %v", err) |
||||
|
} |
||||
|
|
||||
|
return result.Data, nil |
||||
|
} |
||||
@ -0,0 +1,46 @@ |
|||||
|
package api |
||||
|
|
||||
|
import ( |
||||
|
"sync" |
||||
|
"time" |
||||
|
) |
||||
|
|
||||
|
type SessionStore struct { |
||||
|
sessions map[string]*Session |
||||
|
mu sync.RWMutex |
||||
|
} |
||||
|
|
||||
|
func NewSessionStore() *SessionStore { |
||||
|
return &SessionStore{ |
||||
|
sessions: make(map[string]*Session), |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func (store *SessionStore) Set(sessionID string, session *Session) { |
||||
|
store.mu.Lock() |
||||
|
defer store.mu.Unlock() |
||||
|
store.sessions[sessionID] = session |
||||
|
} |
||||
|
|
||||
|
func (store *SessionStore) Get(sessionID string) (*Session, bool) { |
||||
|
store.mu.RLock() |
||||
|
defer store.mu.RUnlock() |
||||
|
session, ok := store.sessions[sessionID] |
||||
|
return session, ok |
||||
|
} |
||||
|
|
||||
|
func (store *SessionStore) Delete(sessionID string) { |
||||
|
store.mu.Lock() |
||||
|
defer store.mu.Unlock() |
||||
|
delete(store.sessions, sessionID) |
||||
|
} |
||||
|
|
||||
|
func (store *SessionStore) CleanupSessions() { |
||||
|
store.mu.Lock() |
||||
|
defer store.mu.Unlock() |
||||
|
for id, session := range store.sessions { |
||||
|
if time.Since(session.LastAccessed) > 24*time.Hour { |
||||
|
delete(store.sessions, id) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,24 +1,48 @@ |
|||||
package handlers |
package cli |
||||
|
|
||||
import ( |
import ( |
||||
"html/template" |
"marmic/servicetrade-toolbox/internal/api" |
||||
"net/http" |
"marmic/servicetrade-toolbox/internal/ui" |
||||
|
"marmic/servicetrade-toolbox/internal/utils" |
||||
) |
) |
||||
|
|
||||
func AdminHandler(w http.ResponseWriter, r *http.Request) { |
func HandleAdmin(session *api.Session) { |
||||
if r.Header.Get("HX-Request") == "true" { |
for { |
||||
// This is an HTMX request, return only the jobs partial
|
ui.ClearScreen() |
||||
tmpl := template.Must(template.ParseFiles("templates/partials/jobs.html")) |
ui.DisplayMenu([]string{ |
||||
jobs := r.Cookies() // Replace with actual data fetching
|
"User Management", |
||||
tmpl.Execute(w, jobs) |
"System Settings", |
||||
} else { |
"Back to Main Menu", |
||||
// This is a full page request
|
}, "Admin Menu") |
||||
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/partials/admin.html")) |
|
||||
jobs := []string{"Job 1", "Job 2", "Job 3"} // Replace with actual data fetching
|
|
||||
|
|
||||
tmpl.Execute(w, map[string]interface{}{ |
choice, err := utils.GetUserChoice(3) |
||||
"Title": "Jobs", |
if err != nil { |
||||
"Jobs": jobs, |
ui.DisplayError("Invalid input:", err) |
||||
}) |
utils.PressEnterToContinue() |
||||
|
continue |
||||
} |
} |
||||
|
|
||||
|
switch choice { |
||||
|
case 1: |
||||
|
userManagement(session) |
||||
|
case 2: |
||||
|
systemSettings(session) |
||||
|
case 3: |
||||
|
return |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func userManagement(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
ui.DisplayMessage("User Management") |
||||
|
// TODO: Implement user management logic
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func systemSettings(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
ui.DisplayMessage("System Settings") |
||||
|
// TODO: Implement system settings logic
|
||||
|
utils.PressEnterToContinue() |
||||
} |
} |
||||
|
|||||
@ -1,11 +1,67 @@ |
|||||
package handlers |
package cli |
||||
|
|
||||
import ( |
import ( |
||||
"html/template" |
"fmt" |
||||
"net/http" |
"marmic/servicetrade-toolbox/internal/api" |
||||
|
"marmic/servicetrade-toolbox/internal/ui" |
||||
|
"marmic/servicetrade-toolbox/internal/utils" |
||||
) |
) |
||||
|
|
||||
func AssetsHandler(w http.ResponseWriter, r *http.Request) { |
func HandleAssets(session *api.Session) { |
||||
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/assets.html")) |
for { |
||||
tmpl.Execute(w, nil) |
ui.ClearScreen() |
||||
|
fmt.Println("Assets Menu:") |
||||
|
fmt.Println("1. List Assets") |
||||
|
fmt.Println("2. Add Asset") |
||||
|
fmt.Println("3. Edit Asset") |
||||
|
fmt.Println("4. Delete Asset") |
||||
|
fmt.Println("5. Back to Main Menu") |
||||
|
|
||||
|
choice, err := utils.GetUserChoice(5) |
||||
|
if err != nil { |
||||
|
ui.DisplayError("Invalid input:", err) |
||||
|
utils.PressEnterToContinue() |
||||
|
continue |
||||
|
} |
||||
|
switch choice { |
||||
|
case 1: |
||||
|
listAssets(session) |
||||
|
case 2: |
||||
|
addAsset(session) |
||||
|
case 3: |
||||
|
editAsset(session) |
||||
|
case 4: |
||||
|
deleteAsset(session) |
||||
|
case 5: |
||||
|
return |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func listAssets(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Listing assets...") |
||||
|
// TODO: Implement asset listing logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func addAsset(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Adding a new asset...") |
||||
|
// TODO: Implement asset creation logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func editAsset(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Editing an asset...") |
||||
|
// TODO: Implement asset editing logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func deleteAsset(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Deleting an asset...") |
||||
|
// TODO: Implement asset deletion logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
} |
} |
||||
|
|||||
@ -1,11 +1,67 @@ |
|||||
package handlers |
package cli |
||||
|
|
||||
import ( |
import ( |
||||
"html/template" |
"fmt" |
||||
"net/http" |
"marmic/servicetrade-toolbox/internal/api" |
||||
|
"marmic/servicetrade-toolbox/internal/ui" |
||||
|
"marmic/servicetrade-toolbox/internal/utils" |
||||
) |
) |
||||
|
|
||||
func CompaniesHandler(w http.ResponseWriter, r *http.Request) { |
func HandleCompanies(session *api.Session) { |
||||
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/companies.html")) |
for { |
||||
tmpl.Execute(w, nil) |
ui.ClearScreen() |
||||
|
fmt.Println("Companies Menu:") |
||||
|
fmt.Println("1. List Companies") |
||||
|
fmt.Println("2. Add Company") |
||||
|
fmt.Println("3. Edit Company") |
||||
|
fmt.Println("4. Delete Company") |
||||
|
fmt.Println("5. Back to Main Menu") |
||||
|
|
||||
|
choice, err := utils.GetUserChoice(5) |
||||
|
if err != nil { |
||||
|
ui.DisplayError("Invalid input:", err) |
||||
|
utils.PressEnterToContinue() |
||||
|
continue |
||||
|
} |
||||
|
switch choice { |
||||
|
case 1: |
||||
|
listCompanies(session) |
||||
|
case 2: |
||||
|
addCompany(session) |
||||
|
case 3: |
||||
|
editCompany(session) |
||||
|
case 4: |
||||
|
deleteCompany(session) |
||||
|
case 5: |
||||
|
return |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func listCompanies(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Listing companies...") |
||||
|
// TODO: Implement company listing logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func addCompany(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Adding a new company...") |
||||
|
// TODO: Implement company creation logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func editCompany(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Editing a company...") |
||||
|
// TODO: Implement company editing logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func deleteCompany(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Deleting a company...") |
||||
|
// TODO: Implement company deletion logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
} |
} |
||||
|
|||||
@ -1,11 +1,67 @@ |
|||||
package handlers |
package cli |
||||
|
|
||||
import ( |
import ( |
||||
"html/template" |
"fmt" |
||||
"net/http" |
"marmic/servicetrade-toolbox/internal/api" |
||||
|
"marmic/servicetrade-toolbox/internal/ui" |
||||
|
"marmic/servicetrade-toolbox/internal/utils" |
||||
) |
) |
||||
|
|
||||
func ContactsHandler(w http.ResponseWriter, r *http.Request) { |
func HandleContacts(session *api.Session) { |
||||
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/contacts.html")) |
for { |
||||
tmpl.Execute(w, nil) |
ui.ClearScreen() |
||||
|
fmt.Println("Contacts Menu:") |
||||
|
fmt.Println("1. List Contacts") |
||||
|
fmt.Println("2. Add Contact") |
||||
|
fmt.Println("3. Edit Contact") |
||||
|
fmt.Println("4. Delete Contact") |
||||
|
fmt.Println("5. Back to Main Menu") |
||||
|
|
||||
|
choice, err := utils.GetUserChoice(5) |
||||
|
if err != nil { |
||||
|
ui.DisplayError("Invalid input:", err) |
||||
|
utils.PressEnterToContinue() |
||||
|
continue |
||||
|
} |
||||
|
switch choice { |
||||
|
case 1: |
||||
|
listContacts(session) |
||||
|
case 2: |
||||
|
addContact(session) |
||||
|
case 3: |
||||
|
editContact(session) |
||||
|
case 4: |
||||
|
deleteContact(session) |
||||
|
case 5: |
||||
|
return |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func listContacts(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Listing contacts...") |
||||
|
// TODO: Implement contact listing logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func addContact(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Adding a new contact...") |
||||
|
// TODO: Implement contact creation logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func editContact(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Editing a contact...") |
||||
|
// TODO: Implement contact editing logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func deleteContact(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Deleting a contact...") |
||||
|
// TODO: Implement contact deletion logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
} |
} |
||||
|
|||||
@ -1,11 +1,67 @@ |
|||||
package handlers |
package cli |
||||
|
|
||||
import ( |
import ( |
||||
"html/template" |
"fmt" |
||||
"net/http" |
"marmic/servicetrade-toolbox/internal/api" |
||||
|
"marmic/servicetrade-toolbox/internal/ui" |
||||
|
"marmic/servicetrade-toolbox/internal/utils" |
||||
) |
) |
||||
|
|
||||
func ContractsHandler(w http.ResponseWriter, r *http.Request) { |
func HandleContracts(session *api.Session) { |
||||
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/contracts.html")) |
for { |
||||
tmpl.Execute(w, nil) |
ui.ClearScreen() |
||||
|
fmt.Println("Contracts Menu:") |
||||
|
fmt.Println("1. List Contracts") |
||||
|
fmt.Println("2. Add Contract") |
||||
|
fmt.Println("3. Edit Contract") |
||||
|
fmt.Println("4. Delete Contract") |
||||
|
fmt.Println("5. Back to Main Menu") |
||||
|
|
||||
|
choice, err := utils.GetUserChoice(5) |
||||
|
if err != nil { |
||||
|
ui.DisplayError("Invalid input:", err) |
||||
|
utils.PressEnterToContinue() |
||||
|
continue |
||||
|
} |
||||
|
switch choice { |
||||
|
case 1: |
||||
|
listContracts(session) |
||||
|
case 2: |
||||
|
addContract(session) |
||||
|
case 3: |
||||
|
editContract(session) |
||||
|
case 4: |
||||
|
deleteContract(session) |
||||
|
case 5: |
||||
|
return |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func listContracts(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Listing contracts...") |
||||
|
// TODO: Implement contract listing logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func addContract(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Adding a new contract...") |
||||
|
// TODO: Implement contract creation logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func editContract(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Editing a contract...") |
||||
|
// TODO: Implement contract editing logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func deleteContract(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Deleting a contract...") |
||||
|
// TODO: Implement contract deletion logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
} |
} |
||||
|
|||||
@ -1,34 +0,0 @@ |
|||||
package handlers |
|
||||
|
|
||||
import ( |
|
||||
"html/template" |
|
||||
"log" |
|
||||
"net/http" |
|
||||
) |
|
||||
|
|
||||
func DashboardHandler(w http.ResponseWriter, r *http.Request) { |
|
||||
tmpl, err := template.ParseFiles( |
|
||||
"templates/layout.html", |
|
||||
"templates/dashboard.html", |
|
||||
"templates/partials/invoice_search.html", |
|
||||
"templates/partials/invoice_search_results.html", |
|
||||
) |
|
||||
if err != nil { |
|
||||
log.Printf("Template parsing error: %v", err) |
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError) |
|
||||
return |
|
||||
} |
|
||||
|
|
||||
data := struct{}{} // Empty struct as data
|
|
||||
|
|
||||
if r.Header.Get("HX-Request") == "true" { |
|
||||
err = tmpl.ExecuteTemplate(w, "content", data) |
|
||||
} else { |
|
||||
err = tmpl.ExecuteTemplate(w, "layout.html", data) |
|
||||
} |
|
||||
if err != nil { |
|
||||
log.Printf("Template execution error: %v", err) |
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError) |
|
||||
return |
|
||||
} |
|
||||
} |
|
||||
@ -1,11 +1,57 @@ |
|||||
package handlers |
package cli |
||||
|
|
||||
import ( |
import ( |
||||
"html/template" |
"fmt" |
||||
"net/http" |
"marmic/servicetrade-toolbox/internal/api" |
||||
|
"marmic/servicetrade-toolbox/internal/ui" |
||||
|
"marmic/servicetrade-toolbox/internal/utils" |
||||
) |
) |
||||
|
|
||||
func GenericHandler(w http.ResponseWriter, r *http.Request) { |
func HandleGenericTools(session *api.Session) { |
||||
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/generic.html")) |
for { |
||||
tmpl.Execute(w, nil) |
ui.ClearScreen() |
||||
|
fmt.Println("Generic Tools Menu:") |
||||
|
fmt.Println("1. Tool 1") |
||||
|
fmt.Println("2. Tool 2") |
||||
|
fmt.Println("3. Tool 3") |
||||
|
fmt.Println("4. Back to Main Menu") |
||||
|
|
||||
|
choice, err := utils.GetUserChoice(4) |
||||
|
if err != nil { |
||||
|
ui.DisplayError("Invalid input:", err) |
||||
|
utils.PressEnterToContinue() |
||||
|
continue |
||||
|
} |
||||
|
switch choice { |
||||
|
case 1: |
||||
|
runTool1(session) |
||||
|
case 2: |
||||
|
runTool2(session) |
||||
|
case 3: |
||||
|
runTool3(session) |
||||
|
case 4: |
||||
|
return |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func runTool1(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Running Tool 1...") |
||||
|
// TODO: Implement Tool 1 logic
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func runTool2(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Running Tool 2...") |
||||
|
// TODO: Implement Tool 2 logic
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func runTool3(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Running Tool 3...") |
||||
|
// TODO: Implement Tool 3 logic
|
||||
|
utils.PressEnterToContinue() |
||||
} |
} |
||||
|
|||||
@ -1,57 +1,70 @@ |
|||||
package handlers |
package cli |
||||
|
|
||||
import ( |
import ( |
||||
"html/template" |
"fmt" |
||||
"log" |
|
||||
"marmic/servicetrade-toolbox/internal/api" |
"marmic/servicetrade-toolbox/internal/api" |
||||
"net/http" |
"marmic/servicetrade-toolbox/internal/ui" |
||||
"strings" |
"marmic/servicetrade-toolbox/internal/utils" |
||||
) |
) |
||||
|
|
||||
func InvoicesHandler(w http.ResponseWriter, r *http.Request) { |
func HandleInvoices(session *api.Session) { |
||||
session, ok := r.Context().Value("session").(*api.Session) |
for { |
||||
if !ok { |
ui.ClearScreen() |
||||
http.Error(w, "Unauthorized", http.StatusUnauthorized) |
fmt.Println("Invoices Menu:") |
||||
return |
fmt.Println("1. Search Invoice") |
||||
} |
fmt.Println("2. List Recent Invoices") |
||||
|
fmt.Println("3. Create Invoice") |
||||
|
fmt.Println("4. Back to Main Menu") |
||||
|
|
||||
// Handle the search request
|
choice, err := utils.GetUserChoice(4) |
||||
if r.Method == "GET" && r.URL.Query().Get("search") != "" { |
if err != nil { |
||||
handleInvoiceSearch(w, r, session) |
ui.DisplayError("Invalid input:", err) |
||||
|
utils.PressEnterToContinue() |
||||
|
continue |
||||
|
} |
||||
|
switch choice { |
||||
|
case 1: |
||||
|
searchInvoice(session) |
||||
|
case 2: |
||||
|
listRecentInvoices(session) |
||||
|
case 3: |
||||
|
createInvoice(session) |
||||
|
case 4: |
||||
return |
return |
||||
} |
} |
||||
|
|
||||
// Handle the initial page load
|
|
||||
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/invoices.html")) |
|
||||
err := tmpl.Execute(w, nil) |
|
||||
if err != nil { |
|
||||
log.Printf("Error executing template: %v", err) |
|
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError) |
|
||||
} |
} |
||||
} |
} |
||||
|
|
||||
func handleInvoiceSearch(w http.ResponseWriter, r *http.Request, session *api.Session) { |
func searchInvoice(session *api.Session) { |
||||
searchTerm := strings.TrimSpace(r.URL.Query().Get("search")) |
ui.ClearScreen() |
||||
|
fmt.Println("Search Invoice:") |
||||
if searchTerm == "" { |
identifier := utils.PromptForInput("Enter Invoice Number or ID: ") |
||||
log.Println("Empty search term, returning empty response") |
|
||||
w.WriteHeader(http.StatusOK) |
|
||||
return |
|
||||
} |
|
||||
|
|
||||
invoice, err := session.GetInvoice(searchTerm) |
invoice, err := session.GetInvoice(identifier) |
||||
if err != nil { |
if err != nil { |
||||
log.Printf("Error fetching invoice: %v", err) |
fmt.Printf("Error fetching invoice: %v\n", err) |
||||
w.WriteHeader(http.StatusInternalServerError) |
utils.PressEnterToContinue() |
||||
tmpl := template.Must(template.ParseFiles("templates/partials/invoice_search_results.html")) |
|
||||
tmpl.ExecuteTemplate(w, "invoice_search_results", map[string]interface{}{"Error": err.Error()}) |
|
||||
return |
return |
||||
} |
} |
||||
|
|
||||
tmpl := template.Must(template.ParseFiles("templates/partials/invoice_search_results.html")) |
fmt.Println("Invoice Details:") |
||||
err = tmpl.ExecuteTemplate(w, "invoice_search_results", invoice) |
fmt.Printf("Invoice Number: %v\n", invoice["invoiceNumber"]) |
||||
if err != nil { |
fmt.Printf("Total Price: $%v\n", invoice["totalPrice"]) |
||||
log.Printf("Error executing template: %v", err) |
fmt.Printf("Status: %v\n", invoice["status"]) |
||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError) |
|
||||
} |
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func listRecentInvoices(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Listing recent invoices...") |
||||
|
// TODO: Implement recent invoices listing logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func createInvoice(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Creating a new invoice...") |
||||
|
// TODO: Implement invoice creation logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
} |
} |
||||
|
|||||
@ -1,26 +1,116 @@ |
|||||
package handlers |
package cli |
||||
|
|
||||
import ( |
import ( |
||||
"html/template" |
"fmt" |
||||
"net/http" |
"marmic/servicetrade-toolbox/internal/api" |
||||
|
"marmic/servicetrade-toolbox/internal/ui" |
||||
|
"marmic/servicetrade-toolbox/internal/utils" |
||||
) |
) |
||||
|
|
||||
func JobsHandler(w http.ResponseWriter, r *http.Request) { |
func HandleJobs(session *api.Session) { |
||||
jobs := []string{"Job 1", "Job 2", "Job 3"} // Replace with actual data fetching
|
for { |
||||
|
ui.DisplayMenu([]string{ |
||||
if r.Header.Get("HX-Request") == "true" { |
"Search Job by ID", |
||||
// This is an HTMX request, return the jobs content wrapped in the content template
|
"List Recent Jobs", |
||||
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/partials/jobs.html")) |
"Create New Job", |
||||
tmpl.ExecuteTemplate(w, "content", map[string]interface{}{ |
"Manage Job Attachments", |
||||
"Title": "Jobs", |
"View Deficiencies", |
||||
"Jobs": jobs, |
"Back to Main Menu", |
||||
}) |
}, "Jobs Menu") |
||||
} else { |
|
||||
// This is a full page request
|
choice, err := utils.GetUserChoice(6) |
||||
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/partials/jobs.html")) |
if err != nil { |
||||
tmpl.Execute(w, map[string]interface{}{ |
ui.DisplayError("Invalid input:", err) |
||||
"Title": "Jobs", |
utils.PressEnterToContinue() |
||||
"Jobs": jobs, |
continue |
||||
}) |
} |
||||
|
|
||||
|
switch choice { |
||||
|
case 1: |
||||
|
searchJobByID(session) |
||||
|
case 2: |
||||
|
listRecentJobs(session) |
||||
|
case 3: |
||||
|
createNewJob(session) |
||||
|
case 4: |
||||
|
manageJobAttachments(session) |
||||
|
case 5: |
||||
|
viewDeficiencyById(session) |
||||
|
case 6: |
||||
|
return |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func searchJobByID(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
ui.DisplayMessage("Search Job by ID:") |
||||
|
jobID := utils.PromptForInput("Enter Job ID: ") |
||||
|
|
||||
|
// TODO: Implement job search logic using the API
|
||||
|
ui.DisplayMessage(fmt.Sprintf("Searching for job with ID: %s", jobID)) |
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func listRecentJobs(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
ui.DisplayMessage("Listing recent jobs...") |
||||
|
// TODO: Implement recent jobs listing logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func createNewJob(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
ui.DisplayMessage("Creating a new job...") |
||||
|
// TODO: Implement job creation logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func manageJobAttachments(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
jobID := utils.PromptForInput("Enter Job ID: ") |
||||
|
|
||||
|
attachments, err := session.GetAttachmentsForJob(jobID) |
||||
|
if err != nil { |
||||
|
ui.DisplayError("Failed to retrieve attachments:", err) |
||||
|
utils.PressEnterToContinue() |
||||
|
return |
||||
} |
} |
||||
|
|
||||
|
ui.DisplayMessage(fmt.Sprintf("Attachments for Job %s:", jobID)) |
||||
|
if dataMap, ok := attachments["data"].(map[string]interface{}); ok { |
||||
|
if attachmentsList, ok := dataMap["attachments"].([]interface{}); ok { |
||||
|
for i, attachment := range attachmentsList { |
||||
|
if att, ok := attachment.(map[string]interface{}); ok { |
||||
|
ui.DisplayMessage(fmt.Sprintf("%d. %s", i+1, att["fileName"])) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// TODO: Implement attachment deletion logic
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func viewDeficiencyById(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
deficiencyID := utils.PromptForInput("Enter Deficiency ID: ") |
||||
|
|
||||
|
ui.DisplayMessage(fmt.Sprintf("Fetching information for Deficiency %s...", deficiencyID)) |
||||
|
|
||||
|
deficiencies, err := session.GetDeficiencyInfoForJob(deficiencyID) |
||||
|
if err != nil { |
||||
|
ui.DisplayError("Failed to retrieve deficiency information:", err) |
||||
|
utils.PressEnterToContinue() |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
for _, deficiency := range deficiencies { |
||||
|
ui.DisplayMessage(fmt.Sprintf("ID: %v", deficiency["id"])) |
||||
|
ui.DisplayMessage(fmt.Sprintf("Description: %v", deficiency["description"])) |
||||
|
ui.DisplayMessage(fmt.Sprintf("Status: %v", deficiency["status"])) |
||||
|
ui.DisplayMessage("---") |
||||
|
} |
||||
|
|
||||
|
utils.PressEnterToContinue() |
||||
} |
} |
||||
|
|||||
@ -1,11 +1,67 @@ |
|||||
package handlers |
package cli |
||||
|
|
||||
import ( |
import ( |
||||
"html/template" |
"fmt" |
||||
"net/http" |
"marmic/servicetrade-toolbox/internal/api" |
||||
|
"marmic/servicetrade-toolbox/internal/ui" |
||||
|
"marmic/servicetrade-toolbox/internal/utils" |
||||
) |
) |
||||
|
|
||||
func LocationsHandler(w http.ResponseWriter, r *http.Request) { |
func HandleLocations(session *api.Session) { |
||||
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/locations.html")) |
for { |
||||
tmpl.Execute(w, nil) |
ui.ClearScreen() |
||||
|
fmt.Println("Locations Menu:") |
||||
|
fmt.Println("1. List Locations") |
||||
|
fmt.Println("2. Add Location") |
||||
|
fmt.Println("3. Edit Location") |
||||
|
fmt.Println("4. Delete Location") |
||||
|
fmt.Println("5. Back to Main Menu") |
||||
|
|
||||
|
choice, err := utils.GetUserChoice(5) |
||||
|
if err != nil { |
||||
|
ui.DisplayError("Invalid input:", err) |
||||
|
utils.PressEnterToContinue() |
||||
|
continue |
||||
|
} |
||||
|
switch choice { |
||||
|
case 1: |
||||
|
listLocations(session) |
||||
|
case 2: |
||||
|
addLocation(session) |
||||
|
case 3: |
||||
|
editLocation(session) |
||||
|
case 4: |
||||
|
deleteLocation(session) |
||||
|
case 5: |
||||
|
return |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func listLocations(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Listing locations...") |
||||
|
// TODO: Implement location listing logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func addLocation(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Adding a new location...") |
||||
|
// TODO: Implement location creation logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func editLocation(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Editing a location...") |
||||
|
// TODO: Implement location editing logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func deleteLocation(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Deleting a location...") |
||||
|
// TODO: Implement location deletion logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
} |
} |
||||
|
|||||
@ -1,11 +1,57 @@ |
|||||
package handlers |
package cli |
||||
|
|
||||
import ( |
import ( |
||||
"html/template" |
"fmt" |
||||
"net/http" |
"marmic/servicetrade-toolbox/internal/api" |
||||
|
"marmic/servicetrade-toolbox/internal/ui" |
||||
|
"marmic/servicetrade-toolbox/internal/utils" |
||||
) |
) |
||||
|
|
||||
func NotificationsHandler(w http.ResponseWriter, r *http.Request) { |
func HandleNotifications(session *api.Session) { |
||||
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/notifications.html")) |
for { |
||||
tmpl.Execute(w, nil) |
ui.ClearScreen() |
||||
|
fmt.Println("Notifications Menu:") |
||||
|
fmt.Println("1. View Notifications") |
||||
|
fmt.Println("2. Mark Notification as Read") |
||||
|
fmt.Println("3. Delete Notification") |
||||
|
fmt.Println("4. Back to Main Menu") |
||||
|
|
||||
|
choice, err := utils.GetUserChoice(4) |
||||
|
if err != nil { |
||||
|
ui.DisplayError("Invalid input:", err) |
||||
|
utils.PressEnterToContinue() |
||||
|
continue |
||||
|
} |
||||
|
switch choice { |
||||
|
case 1: |
||||
|
viewNotifications(session) |
||||
|
case 2: |
||||
|
markNotificationAsRead(session) |
||||
|
case 3: |
||||
|
deleteNotification(session) |
||||
|
case 4: |
||||
|
return |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func viewNotifications(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Viewing notifications...") |
||||
|
// TODO: Implement notification viewing logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func markNotificationAsRead(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Marking notification as read...") |
||||
|
// TODO: Implement marking notification as read logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func deleteNotification(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Deleting notification...") |
||||
|
// TODO: Implement notification deletion logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
} |
} |
||||
|
|||||
@ -1,11 +1,67 @@ |
|||||
package handlers |
package cli |
||||
|
|
||||
import ( |
import ( |
||||
"html/template" |
"fmt" |
||||
"net/http" |
"marmic/servicetrade-toolbox/internal/api" |
||||
|
"marmic/servicetrade-toolbox/internal/ui" |
||||
|
"marmic/servicetrade-toolbox/internal/utils" |
||||
) |
) |
||||
|
|
||||
func QuotesHandler(w http.ResponseWriter, r *http.Request) { |
func HandleQuotes(session *api.Session) { |
||||
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/quotes.html")) |
for { |
||||
tmpl.Execute(w, nil) |
ui.ClearScreen() |
||||
|
fmt.Println("Quotes Menu:") |
||||
|
fmt.Println("1. List Quotes") |
||||
|
fmt.Println("2. Create Quote") |
||||
|
fmt.Println("3. Edit Quote") |
||||
|
fmt.Println("4. Delete Quote") |
||||
|
fmt.Println("5. Back to Main Menu") |
||||
|
|
||||
|
choice, err := utils.GetUserChoice(5) |
||||
|
if err != nil { |
||||
|
ui.DisplayError("Invalid input:", err) |
||||
|
utils.PressEnterToContinue() |
||||
|
continue |
||||
|
} |
||||
|
switch choice { |
||||
|
case 1: |
||||
|
listQuotes(session) |
||||
|
case 2: |
||||
|
createQuote(session) |
||||
|
case 3: |
||||
|
editQuote(session) |
||||
|
case 4: |
||||
|
deleteQuote(session) |
||||
|
case 5: |
||||
|
return |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func listQuotes(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Listing quotes...") |
||||
|
// TODO: Implement quote listing logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func createQuote(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Creating a new quote...") |
||||
|
// TODO: Implement quote creation logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func editQuote(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Editing a quote...") |
||||
|
// TODO: Implement quote editing logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func deleteQuote(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Deleting a quote...") |
||||
|
// TODO: Implement quote deletion logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
} |
} |
||||
|
|||||
@ -1,11 +1,67 @@ |
|||||
package handlers |
package cli |
||||
|
|
||||
import ( |
import ( |
||||
"html/template" |
"fmt" |
||||
"net/http" |
"marmic/servicetrade-toolbox/internal/api" |
||||
|
"marmic/servicetrade-toolbox/internal/ui" |
||||
|
"marmic/servicetrade-toolbox/internal/utils" |
||||
) |
) |
||||
|
|
||||
func ServicesHandler(w http.ResponseWriter, r *http.Request) { |
func HandleServices(session *api.Session) { |
||||
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/services.html")) |
for { |
||||
tmpl.Execute(w, nil) |
ui.ClearScreen() |
||||
|
fmt.Println("Services Menu:") |
||||
|
fmt.Println("1. List Services") |
||||
|
fmt.Println("2. Add Service") |
||||
|
fmt.Println("3. Edit Service") |
||||
|
fmt.Println("4. Delete Service") |
||||
|
fmt.Println("5. Back to Main Menu") |
||||
|
|
||||
|
choice, err := utils.GetUserChoice(5) |
||||
|
if err != nil { |
||||
|
ui.DisplayError("Invalid input:", err) |
||||
|
utils.PressEnterToContinue() |
||||
|
continue |
||||
|
} |
||||
|
switch choice { |
||||
|
case 1: |
||||
|
listServices(session) |
||||
|
case 2: |
||||
|
addService(session) |
||||
|
case 3: |
||||
|
editService(session) |
||||
|
case 4: |
||||
|
deleteService(session) |
||||
|
case 5: |
||||
|
return |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func listServices(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Listing services...") |
||||
|
// TODO: Implement service listing logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func addService(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Adding a new service...") |
||||
|
// TODO: Implement service creation logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func editService(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Editing a service...") |
||||
|
// TODO: Implement service editing logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func deleteService(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Deleting a service...") |
||||
|
// TODO: Implement service deletion logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
} |
} |
||||
|
|||||
@ -1,11 +1,67 @@ |
|||||
package handlers |
package cli |
||||
|
|
||||
import ( |
import ( |
||||
"html/template" |
"fmt" |
||||
"net/http" |
"marmic/servicetrade-toolbox/internal/api" |
||||
|
"marmic/servicetrade-toolbox/internal/ui" |
||||
|
"marmic/servicetrade-toolbox/internal/utils" |
||||
) |
) |
||||
|
|
||||
func TagsHandler(w http.ResponseWriter, r *http.Request) { |
func HandleTags(session *api.Session) { |
||||
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/tags.html")) |
for { |
||||
tmpl.Execute(w, nil) |
ui.ClearScreen() |
||||
|
fmt.Println("Tags Menu:") |
||||
|
fmt.Println("1. List Tags") |
||||
|
fmt.Println("2. Add Tag") |
||||
|
fmt.Println("3. Edit Tag") |
||||
|
fmt.Println("4. Delete Tag") |
||||
|
fmt.Println("5. Back to Main Menu") |
||||
|
|
||||
|
choice, err := utils.GetUserChoice(5) |
||||
|
if err != nil { |
||||
|
ui.DisplayError("Invalid input:", err) |
||||
|
utils.PressEnterToContinue() |
||||
|
continue |
||||
|
} |
||||
|
switch choice { |
||||
|
case 1: |
||||
|
listTags(session) |
||||
|
case 2: |
||||
|
addTag(session) |
||||
|
case 3: |
||||
|
editTag(session) |
||||
|
case 4: |
||||
|
deleteTag(session) |
||||
|
case 5: |
||||
|
return |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func listTags(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Listing tags...") |
||||
|
// TODO: Implement tag listing logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func addTag(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Adding a new tag...") |
||||
|
// TODO: Implement tag creation logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func editTag(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Editing a tag...") |
||||
|
// TODO: Implement tag editing logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func deleteTag(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Deleting a tag...") |
||||
|
// TODO: Implement tag deletion logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
} |
} |
||||
|
|||||
@ -1,11 +1,67 @@ |
|||||
package handlers |
package cli |
||||
|
|
||||
import ( |
import ( |
||||
"html/template" |
"fmt" |
||||
"net/http" |
"marmic/servicetrade-toolbox/internal/api" |
||||
|
"marmic/servicetrade-toolbox/internal/ui" |
||||
|
"marmic/servicetrade-toolbox/internal/utils" |
||||
) |
) |
||||
|
|
||||
func UsersHandler(w http.ResponseWriter, r *http.Request) { |
func HandleUsers(session *api.Session) { |
||||
tmpl := template.Must(template.ParseFiles("templates/layout.html", "templates/users.html")) |
for { |
||||
tmpl.Execute(w, nil) |
ui.ClearScreen() |
||||
|
fmt.Println("Users Menu:") |
||||
|
fmt.Println("1. List Users") |
||||
|
fmt.Println("2. Add User") |
||||
|
fmt.Println("3. Edit User") |
||||
|
fmt.Println("4. Delete User") |
||||
|
fmt.Println("5. Back to Main Menu") |
||||
|
|
||||
|
choice, err := utils.GetUserChoice(5) |
||||
|
if err != nil { |
||||
|
ui.DisplayError("Invalid input:", err) |
||||
|
utils.PressEnterToContinue() |
||||
|
continue |
||||
|
} |
||||
|
switch choice { |
||||
|
case 1: |
||||
|
listUsers(session) |
||||
|
case 2: |
||||
|
addUser(session) |
||||
|
case 3: |
||||
|
editUser(session) |
||||
|
case 4: |
||||
|
deleteUser(session) |
||||
|
case 5: |
||||
|
return |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func listUsers(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Listing users...") |
||||
|
// TODO: Implement user listing logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func addUser(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Adding a new user...") |
||||
|
// TODO: Implement user creation logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func editUser(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Editing a user...") |
||||
|
// TODO: Implement user editing logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
|
} |
||||
|
|
||||
|
func deleteUser(session *api.Session) { |
||||
|
ui.ClearScreen() |
||||
|
fmt.Println("Deleting a user...") |
||||
|
// TODO: Implement user deletion logic using the API
|
||||
|
utils.PressEnterToContinue() |
||||
} |
} |
||||
|
|||||
@ -0,0 +1,36 @@ |
|||||
|
package middleware |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
"marmic/servicetrade-toolbox/internal/api" |
||||
|
"net/http" |
||||
|
) |
||||
|
|
||||
|
var SessionStore = api.NewSessionStore() |
||||
|
|
||||
|
func AuthMiddleware(next http.Handler) http.Handler { |
||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
||||
|
cookie, err := r.Cookie("PHPSESSID") |
||||
|
if err != nil { |
||||
|
http.Redirect(w, r, "/login", http.StatusSeeOther) |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
sessionID := cookie.Value |
||||
|
session, exists := SessionStore.Get(sessionID) |
||||
|
if !exists { |
||||
|
session = api.NewSession() |
||||
|
session.Cookie = "PHPSESSID=" + sessionID |
||||
|
|
||||
|
if err := session.ValidateSession(); err != nil { |
||||
|
http.Redirect(w, r, "/login", http.StatusSeeOther) |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
SessionStore.Set(sessionID, session) |
||||
|
} |
||||
|
|
||||
|
ctx := context.WithValue(r.Context(), "session", session) |
||||
|
next.ServeHTTP(w, r.WithContext(ctx)) |
||||
|
}) |
||||
|
} |
||||
@ -0,0 +1,37 @@ |
|||||
|
package ui |
||||
|
|
||||
|
import ( |
||||
|
"fmt" |
||||
|
|
||||
|
"github.com/inancgumus/screen" |
||||
|
) |
||||
|
|
||||
|
func ClearScreen() { |
||||
|
screen.Clear() |
||||
|
screen.MoveTopLeft() |
||||
|
} |
||||
|
|
||||
|
func DisplayStartScreen() { |
||||
|
ClearScreen() |
||||
|
fmt.Println("========================================") |
||||
|
fmt.Println(" Welcome to ServiceTrade CLI") |
||||
|
fmt.Println("========================================") |
||||
|
fmt.Println("Please log in with your ServiceTrade credentials to continue.") |
||||
|
fmt.Println() |
||||
|
} |
||||
|
|
||||
|
func DisplayMessage(message string) { |
||||
|
fmt.Println(message) |
||||
|
} |
||||
|
|
||||
|
func DisplayError(prefix string, err error) { |
||||
|
fmt.Printf("%s %v\n", prefix, err) |
||||
|
} |
||||
|
|
||||
|
func DisplayMenu(items []string, title string) { |
||||
|
ClearScreen() |
||||
|
fmt.Printf("\n%s:\n", title) |
||||
|
for i, item := range items { |
||||
|
fmt.Printf("%d. %s\n", i+1, item) |
||||
|
} |
||||
|
} |
||||
@ -1,79 +0,0 @@ |
|||||
package ui |
|
||||
|
|
||||
import ( |
|
||||
"bufio" |
|
||||
"fmt" |
|
||||
"os" |
|
||||
"strconv" |
|
||||
"strings" |
|
||||
|
|
||||
"github.com/inancgumus/screen" |
|
||||
) |
|
||||
|
|
||||
func ClearScreen() { |
|
||||
screen.Clear() |
|
||||
screen.MoveTopLeft() |
|
||||
} |
|
||||
|
|
||||
func DisplayStartScreen() { |
|
||||
ClearScreen() |
|
||||
fmt.Println("========================================") |
|
||||
fmt.Println(" Welcome to ServiceTrade CLI") |
|
||||
fmt.Println("========================================") |
|
||||
fmt.Println("Please log in with your ServiceTrade credentials to continue.") |
|
||||
fmt.Println() |
|
||||
} |
|
||||
|
|
||||
func PromptCredentials() (string, string, error) { |
|
||||
reader := bufio.NewReader(os.Stdin) |
|
||||
|
|
||||
fmt.Print("Enter your email: ") |
|
||||
email, _ := reader.ReadString('\n') |
|
||||
email = strings.TrimSpace(email) |
|
||||
|
|
||||
fmt.Print("Enter your password: ") |
|
||||
password, _ := reader.ReadString('\n') |
|
||||
password = strings.TrimSpace(password) |
|
||||
|
|
||||
return email, password, nil |
|
||||
} |
|
||||
|
|
||||
func DisplayMessage(message string) { |
|
||||
fmt.Println(message) |
|
||||
} |
|
||||
|
|
||||
func DisplayError(prefix string, err error) { |
|
||||
fmt.Printf("%s %v\n", prefix, err) |
|
||||
} |
|
||||
|
|
||||
func PressEnterToContinue() { |
|
||||
fmt.Println("Press Enter to continue...") |
|
||||
bufio.NewReader(os.Stdin).ReadBytes('\n') |
|
||||
} |
|
||||
|
|
||||
func DisplayMenu(items []string, title string) { |
|
||||
ClearScreen() |
|
||||
fmt.Printf("\n%s:\n", title) |
|
||||
for i, item := range items { |
|
||||
fmt.Printf("%d. %s\n", i+1, item) |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
func GetUserChoice(max int) (int, error) { |
|
||||
reader := bufio.NewReader(os.Stdin) |
|
||||
fmt.Printf("\nEnter your choice (1-%d): ", max) |
|
||||
input, _ := reader.ReadString('\n') |
|
||||
input = strings.TrimSpace(input) |
|
||||
choice, err := strconv.Atoi(input) |
|
||||
if err != nil || choice < 1 || choice > max { |
|
||||
return 0, fmt.Errorf("invalid input") |
|
||||
} |
|
||||
return choice, nil |
|
||||
} |
|
||||
|
|
||||
func PromptForInput(prompt string) string { |
|
||||
reader := bufio.NewReader(os.Stdin) |
|
||||
fmt.Print(prompt) |
|
||||
input, _ := reader.ReadString('\n') |
|
||||
return strings.TrimSpace(input) |
|
||||
} |
|
||||
Loading…
Reference in new issue