33 changed files with 353 additions and 1587 deletions
@ -1,95 +0,0 @@ |
|||
package main |
|||
|
|||
import ( |
|||
"fmt" |
|||
"marmic/servicetrade-toolbox/internal/api" |
|||
"marmic/servicetrade-toolbox/internal/handlers/cli" |
|||
"marmic/servicetrade-toolbox/internal/ui" |
|||
"marmic/servicetrade-toolbox/internal/utils" |
|||
"os" |
|||
) |
|||
|
|||
func main() { |
|||
ui.DisplayStartScreen() |
|||
|
|||
email, password, err := utils.PromptCredentials() |
|||
if err != nil { |
|||
ui.DisplayError("Error getting credentials:", err) |
|||
os.Exit(1) |
|||
} |
|||
|
|||
session := api.NewSession() |
|||
err = session.Login(email, password) |
|||
if err != nil { |
|||
ui.DisplayError("Authentication failed:", err) |
|||
os.Exit(1) |
|||
} |
|||
|
|||
fmt.Println("Login successful!") |
|||
|
|||
for { |
|||
ui.ClearScreen() |
|||
fmt.Println("Main Menu:") |
|||
fmt.Println("1. Jobs") |
|||
fmt.Println("2. Invoices") |
|||
fmt.Println("3. Companies") |
|||
fmt.Println("4. Assets") |
|||
fmt.Println("5. Contacts") |
|||
fmt.Println("6. Contracts") |
|||
fmt.Println("7. Generic Tools") |
|||
fmt.Println("8. Locations") |
|||
fmt.Println("9. Notifications") |
|||
fmt.Println("10. Quotes") |
|||
fmt.Println("11. Services") |
|||
fmt.Println("12. Tags") |
|||
fmt.Println("13. Users") |
|||
fmt.Println("14. Admin") |
|||
fmt.Println("15. Logout") |
|||
|
|||
choice, err := utils.GetUserChoice(15) |
|||
if err != nil { |
|||
ui.DisplayError("Invalid input:", err) |
|||
utils.PressEnterToContinue() |
|||
continue |
|||
} |
|||
switch choice { |
|||
case 1: |
|||
cli.HandleJobs(session) |
|||
case 2: |
|||
cli.HandleInvoices(session) |
|||
case 3: |
|||
cli.HandleCompanies(session) |
|||
case 4: |
|||
cli.HandleAssets(session) |
|||
case 5: |
|||
cli.HandleContacts(session) |
|||
case 6: |
|||
cli.HandleContracts(session) |
|||
case 7: |
|||
cli.HandleGenericTools(session) |
|||
case 8: |
|||
cli.HandleLocations(session) |
|||
case 9: |
|||
cli.HandleNotifications(session) |
|||
case 10: |
|||
cli.HandleQuotes(session) |
|||
case 11: |
|||
cli.HandleServices(session) |
|||
case 12: |
|||
cli.HandleTags(session) |
|||
case 13: |
|||
cli.HandleUsers(session) |
|||
case 14: |
|||
cli.HandleAdmin(session) |
|||
case 15: |
|||
err := session.Logout() |
|||
if err != nil { |
|||
ui.DisplayError("Error during logout: ", err) |
|||
} else { |
|||
fmt.Println("Logout successful.") |
|||
} |
|||
fmt.Println("Exiting ServiceTrade CLI Toolbox. Goodbye!") |
|||
return |
|||
} |
|||
} |
|||
} |
|||
@ -1,82 +0,0 @@ |
|||
package auth |
|||
|
|||
import ( |
|||
"bytes" |
|||
"encoding/json" |
|||
"fmt" |
|||
"io" |
|||
"net/http" |
|||
"strings" |
|||
) |
|||
|
|||
type Session struct { |
|||
Client *http.Client |
|||
Cookie string |
|||
} |
|||
|
|||
func NewSession() *Session { |
|||
return &Session{Client: &http.Client{}} |
|||
} |
|||
|
|||
func (s *Session) Login(email, password string) error { |
|||
url := "https://api.servicetrade.com/api/auth" |
|||
payload := map[string]string{ |
|||
"username": email, |
|||
"password": password, |
|||
} |
|||
payloadBytes, _ := json.Marshal(payload) |
|||
|
|||
req, err := http.NewRequest("POST", url, bytes.NewBuffer(payloadBytes)) |
|||
if err != nil { |
|||
return fmt.Errorf("error creating request: %v", err) |
|||
} |
|||
req.Header.Set("Content-Type", "application/json") |
|||
|
|||
resp, err := s.Client.Do(req) |
|||
if err != nil { |
|||
return fmt.Errorf("error sending request: %v", err) |
|||
} |
|||
defer resp.Body.Close() |
|||
|
|||
body, _ := io.ReadAll(resp.Body) |
|||
|
|||
if resp.StatusCode != 200 { |
|||
return fmt.Errorf("failed to authenticate: %s, response: %s", resp.Status, string(body)) |
|||
} |
|||
|
|||
for _, cookie := range resp.Cookies() { |
|||
if strings.Contains(cookie.Name, "PHPSESSID") { |
|||
s.Cookie = cookie.String() |
|||
return nil |
|||
} |
|||
} |
|||
|
|||
return fmt.Errorf("failed to retrieve session cookie; authentication may have failed") |
|||
} |
|||
|
|||
func (s *Session) Logout() error { |
|||
if s.Cookie == "" { |
|||
return fmt.Errorf("no active session to end") |
|||
} |
|||
|
|||
url := "https://api.servicetrade.com/api/auth" |
|||
req, err := http.NewRequest("DELETE", url, nil) |
|||
if err != nil { |
|||
return fmt.Errorf("failed to create DELETE request to end session: %v", err) |
|||
} |
|||
req.Header.Set("Cookie", s.Cookie) |
|||
|
|||
resp, err := s.Client.Do(req) |
|||
if err != nil { |
|||
return fmt.Errorf("failed to send DELETE request to end session: %v", err) |
|||
} |
|||
defer resp.Body.Close() |
|||
|
|||
if resp.StatusCode != 200 && resp.StatusCode != 204 { |
|||
body, _ := io.ReadAll(resp.Body) |
|||
return fmt.Errorf("failed to end session: %s, response: %s", resp.Status, string(body)) |
|||
} |
|||
|
|||
s.Cookie = "" |
|||
return nil |
|||
} |
|||
@ -1,48 +0,0 @@ |
|||
package cli |
|||
|
|||
import ( |
|||
"marmic/servicetrade-toolbox/internal/api" |
|||
"marmic/servicetrade-toolbox/internal/ui" |
|||
"marmic/servicetrade-toolbox/internal/utils" |
|||
) |
|||
|
|||
func HandleAdmin(session *api.Session) { |
|||
for { |
|||
ui.ClearScreen() |
|||
ui.DisplayMenu([]string{ |
|||
"User Management", |
|||
"System Settings", |
|||
"Back to Main Menu", |
|||
}, "Admin Menu") |
|||
|
|||
choice, err := utils.GetUserChoice(3) |
|||
if err != nil { |
|||
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,67 +0,0 @@ |
|||
package cli |
|||
|
|||
import ( |
|||
"fmt" |
|||
"marmic/servicetrade-toolbox/internal/api" |
|||
"marmic/servicetrade-toolbox/internal/ui" |
|||
"marmic/servicetrade-toolbox/internal/utils" |
|||
) |
|||
|
|||
func HandleAssets(session *api.Session) { |
|||
for { |
|||
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,67 +0,0 @@ |
|||
package cli |
|||
|
|||
import ( |
|||
"fmt" |
|||
"marmic/servicetrade-toolbox/internal/api" |
|||
"marmic/servicetrade-toolbox/internal/ui" |
|||
"marmic/servicetrade-toolbox/internal/utils" |
|||
) |
|||
|
|||
func HandleCompanies(session *api.Session) { |
|||
for { |
|||
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,67 +0,0 @@ |
|||
package cli |
|||
|
|||
import ( |
|||
"fmt" |
|||
"marmic/servicetrade-toolbox/internal/api" |
|||
"marmic/servicetrade-toolbox/internal/ui" |
|||
"marmic/servicetrade-toolbox/internal/utils" |
|||
) |
|||
|
|||
func HandleContacts(session *api.Session) { |
|||
for { |
|||
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,67 +0,0 @@ |
|||
package cli |
|||
|
|||
import ( |
|||
"fmt" |
|||
"marmic/servicetrade-toolbox/internal/api" |
|||
"marmic/servicetrade-toolbox/internal/ui" |
|||
"marmic/servicetrade-toolbox/internal/utils" |
|||
) |
|||
|
|||
func HandleContracts(session *api.Session) { |
|||
for { |
|||
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,57 +0,0 @@ |
|||
package cli |
|||
|
|||
import ( |
|||
"fmt" |
|||
"marmic/servicetrade-toolbox/internal/api" |
|||
"marmic/servicetrade-toolbox/internal/ui" |
|||
"marmic/servicetrade-toolbox/internal/utils" |
|||
) |
|||
|
|||
func HandleGenericTools(session *api.Session) { |
|||
for { |
|||
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,70 +0,0 @@ |
|||
package cli |
|||
|
|||
import ( |
|||
"fmt" |
|||
"marmic/servicetrade-toolbox/internal/api" |
|||
"marmic/servicetrade-toolbox/internal/ui" |
|||
"marmic/servicetrade-toolbox/internal/utils" |
|||
) |
|||
|
|||
func HandleInvoices(session *api.Session) { |
|||
for { |
|||
ui.ClearScreen() |
|||
fmt.Println("Invoices Menu:") |
|||
fmt.Println("1. Search Invoice") |
|||
fmt.Println("2. List Recent Invoices") |
|||
fmt.Println("3. Create Invoice") |
|||
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: |
|||
searchInvoice(session) |
|||
case 2: |
|||
listRecentInvoices(session) |
|||
case 3: |
|||
createInvoice(session) |
|||
case 4: |
|||
return |
|||
} |
|||
} |
|||
} |
|||
|
|||
func searchInvoice(session *api.Session) { |
|||
ui.ClearScreen() |
|||
fmt.Println("Search Invoice:") |
|||
identifier := utils.PromptForInput("Enter Invoice Number or ID: ") |
|||
|
|||
invoice, err := session.GetInvoice(identifier) |
|||
if err != nil { |
|||
fmt.Printf("Error fetching invoice: %v\n", err) |
|||
utils.PressEnterToContinue() |
|||
return |
|||
} |
|||
|
|||
fmt.Println("Invoice Details:") |
|||
fmt.Printf("Invoice Number: %v\n", invoice["invoiceNumber"]) |
|||
fmt.Printf("Total Price: $%v\n", invoice["totalPrice"]) |
|||
fmt.Printf("Status: %v\n", invoice["status"]) |
|||
|
|||
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,116 +0,0 @@ |
|||
package cli |
|||
|
|||
import ( |
|||
"fmt" |
|||
"marmic/servicetrade-toolbox/internal/api" |
|||
"marmic/servicetrade-toolbox/internal/ui" |
|||
"marmic/servicetrade-toolbox/internal/utils" |
|||
) |
|||
|
|||
func HandleJobs(session *api.Session) { |
|||
for { |
|||
ui.DisplayMenu([]string{ |
|||
"Search Job by ID", |
|||
"List Recent Jobs", |
|||
"Create New Job", |
|||
"Manage Job Attachments", |
|||
"View Deficiencies", |
|||
"Back to Main Menu", |
|||
}, "Jobs Menu") |
|||
|
|||
choice, err := utils.GetUserChoice(6) |
|||
if err != nil { |
|||
ui.DisplayError("Invalid input:", err) |
|||
utils.PressEnterToContinue() |
|||
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,67 +0,0 @@ |
|||
package cli |
|||
|
|||
import ( |
|||
"fmt" |
|||
"marmic/servicetrade-toolbox/internal/api" |
|||
"marmic/servicetrade-toolbox/internal/ui" |
|||
"marmic/servicetrade-toolbox/internal/utils" |
|||
) |
|||
|
|||
func HandleLocations(session *api.Session) { |
|||
for { |
|||
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,104 +0,0 @@ |
|||
package cli |
|||
|
|||
import ( |
|||
"html/template" |
|||
"log" |
|||
"marmic/servicetrade-toolbox/internal/api" |
|||
"marmic/servicetrade-toolbox/internal/middleware" |
|||
"net/http" |
|||
"strings" |
|||
) |
|||
|
|||
func LoginHandler(w http.ResponseWriter, r *http.Request) { |
|||
if r.Method == "GET" { |
|||
tmpl := template.Must(template.ParseFiles("templates/login.html")) |
|||
tmpl.Execute(w, nil) |
|||
return |
|||
} |
|||
|
|||
if r.Method == "POST" { |
|||
email := r.FormValue("email") |
|||
password := r.FormValue("password") |
|||
|
|||
session := api.NewSession() |
|||
err := session.Login(email, password) |
|||
if err != nil { |
|||
if r.Header.Get("HX-Request") == "true" { |
|||
w.Write([]byte("<div class='error'>Login failed: " + err.Error() + "</div>")) |
|||
} else { |
|||
http.Error(w, "Login failed", http.StatusUnauthorized) |
|||
} |
|||
return |
|||
} |
|||
|
|||
cookieParts := strings.Split(session.Cookie, ";") |
|||
sessionID := strings.TrimPrefix(cookieParts[0], "PHPSESSID=") |
|||
|
|||
middleware.SessionStore.Set(sessionID, session) |
|||
|
|||
http.SetCookie(w, &http.Cookie{ |
|||
Name: "PHPSESSID", |
|||
Value: sessionID, |
|||
Path: "/", |
|||
HttpOnly: true, |
|||
Secure: r.TLS != nil, |
|||
SameSite: http.SameSiteLaxMode, |
|||
}) |
|||
|
|||
if r.Header.Get("HX-Request") == "true" { |
|||
w.Header().Set("HX-Redirect", "/") |
|||
w.WriteHeader(http.StatusOK) |
|||
w.Write([]byte("Login successful")) |
|||
} else { |
|||
http.Redirect(w, r, "/", http.StatusSeeOther) |
|||
} |
|||
} |
|||
} |
|||
|
|||
func LogoutHandler(w http.ResponseWriter, r *http.Request) { |
|||
cookie, err := r.Cookie("PHPSESSID") |
|||
if err != nil { |
|||
log.Printf("No session cookie found: %v", err) |
|||
redirectToLogin(w, r) |
|||
return |
|||
} |
|||
|
|||
sessionID := cookie.Value |
|||
session, exists := middleware.SessionStore.Get(sessionID) |
|||
if !exists { |
|||
log.Println("No session found in store") |
|||
redirectToLogin(w, r) |
|||
return |
|||
} |
|||
|
|||
err = session.Logout() |
|||
if err != nil { |
|||
log.Printf("Logout failed: %v", err) |
|||
http.Error(w, "Logout failed", http.StatusInternalServerError) |
|||
return |
|||
} |
|||
|
|||
middleware.SessionStore.Delete(sessionID) |
|||
|
|||
http.SetCookie(w, &http.Cookie{ |
|||
Name: "PHPSESSID", |
|||
Value: "", |
|||
Path: "/", |
|||
MaxAge: -1, |
|||
HttpOnly: true, |
|||
Secure: r.TLS != nil, |
|||
SameSite: http.SameSiteLaxMode, |
|||
}) |
|||
|
|||
log.Println("Logout successful, redirecting to login page") |
|||
redirectToLogin(w, r) |
|||
} |
|||
|
|||
func redirectToLogin(w http.ResponseWriter, r *http.Request) { |
|||
if r.Header.Get("HX-Request") != "" { |
|||
w.Header().Set("HX-Redirect", "/login") |
|||
w.WriteHeader(http.StatusOK) |
|||
} else { |
|||
http.Redirect(w, r, "/login", http.StatusSeeOther) |
|||
} |
|||
} |
|||
@ -1,57 +0,0 @@ |
|||
package cli |
|||
|
|||
import ( |
|||
"fmt" |
|||
"marmic/servicetrade-toolbox/internal/api" |
|||
"marmic/servicetrade-toolbox/internal/ui" |
|||
"marmic/servicetrade-toolbox/internal/utils" |
|||
) |
|||
|
|||
func HandleNotifications(session *api.Session) { |
|||
for { |
|||
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,67 +0,0 @@ |
|||
package cli |
|||
|
|||
import ( |
|||
"fmt" |
|||
"marmic/servicetrade-toolbox/internal/api" |
|||
"marmic/servicetrade-toolbox/internal/ui" |
|||
"marmic/servicetrade-toolbox/internal/utils" |
|||
) |
|||
|
|||
func HandleQuotes(session *api.Session) { |
|||
for { |
|||
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,67 +0,0 @@ |
|||
package cli |
|||
|
|||
import ( |
|||
"fmt" |
|||
"marmic/servicetrade-toolbox/internal/api" |
|||
"marmic/servicetrade-toolbox/internal/ui" |
|||
"marmic/servicetrade-toolbox/internal/utils" |
|||
) |
|||
|
|||
func HandleServices(session *api.Session) { |
|||
for { |
|||
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,67 +0,0 @@ |
|||
package cli |
|||
|
|||
import ( |
|||
"fmt" |
|||
"marmic/servicetrade-toolbox/internal/api" |
|||
"marmic/servicetrade-toolbox/internal/ui" |
|||
"marmic/servicetrade-toolbox/internal/utils" |
|||
) |
|||
|
|||
func HandleTags(session *api.Session) { |
|||
for { |
|||
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,67 +0,0 @@ |
|||
package cli |
|||
|
|||
import ( |
|||
"fmt" |
|||
"marmic/servicetrade-toolbox/internal/api" |
|||
"marmic/servicetrade-toolbox/internal/ui" |
|||
"marmic/servicetrade-toolbox/internal/utils" |
|||
) |
|||
|
|||
func HandleUsers(session *api.Session) { |
|||
for { |
|||
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() |
|||
} |
|||
@ -1,37 +0,0 @@ |
|||
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) |
|||
} |
|||
} |
|||
Loading…
Reference in new issue